Mercurial > repos > public > sbplib
comparison +scheme/Schrodinger2d.m @ 912:1cdf5ead2a16 feature/utux2D
Refactor interface method for Schrodinger2d
author | Martin Almquist <malmquist@stanford.edu> |
---|---|
date | Sun, 25 Nov 2018 19:46:39 -0800 |
parents | b9c98661ff5d |
children | 46f5dc61d90b |
comparison
equal
deleted
inserted
replaced
911:f7306f03f77a | 912:1cdf5ead2a16 |
---|---|
31 e_w, e_e, e_s, e_n | 31 e_w, e_e, e_s, e_n |
32 d_w, d_e, d_s, d_n | 32 d_w, d_e, d_s, d_n |
33 | 33 |
34 H_boundary % Boundary inner products | 34 H_boundary % Boundary inner products |
35 | 35 |
36 interpolation_type % MC or AWW | |
37 | |
38 end | 36 end |
39 | 37 |
40 methods | 38 methods |
41 | 39 |
42 function obj = Schrodinger2d(g ,order, a, opSet, interpolation_type) | 40 function obj = Schrodinger2d(g ,order, a, opSet) |
43 default_arg('interpolation_type','AWW'); | |
44 default_arg('opSet',{@sbp.D2Variable, @sbp.D2Variable}); | 41 default_arg('opSet',{@sbp.D2Variable, @sbp.D2Variable}); |
45 default_arg('a',1); | 42 default_arg('a',1); |
46 dim = 2; | 43 dim = 2; |
47 | 44 |
48 assert(isa(g, 'grid.Cartesian')) | 45 assert(isa(g, 'grid.Cartesian')) |
148 obj.e_n = obj.e_r{2}; | 145 obj.e_n = obj.e_r{2}; |
149 obj.d_w = obj.d1_l{1}; | 146 obj.d_w = obj.d1_l{1}; |
150 obj.d_e = obj.d1_r{1}; | 147 obj.d_e = obj.d1_r{1}; |
151 obj.d_s = obj.d1_l{2}; | 148 obj.d_s = obj.d1_l{2}; |
152 obj.d_n = obj.d1_r{2}; | 149 obj.d_n = obj.d1_r{2}; |
153 obj.interpolation_type = interpolation_type; | |
154 | 150 |
155 end | 151 end |
156 | 152 |
157 | 153 |
158 % Closure functions return the operators applied to the own domain to close the boundary | 154 % Closure functions return the operators applied to the own domain to close the boundary |
200 otherwise | 196 otherwise |
201 error('No such boundary condition: type = %s',type); | 197 error('No such boundary condition: type = %s',type); |
202 end | 198 end |
203 end | 199 end |
204 | 200 |
201 % opts Struct that specifies the interface coupling. | |
202 % Fields: | |
203 % -- interpolation: struct of interpolation operators (empty for conforming grids) | |
205 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary,opts) | 204 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary,opts) |
205 if isempty(opts) | |
206 [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary); | |
207 else | |
208 assertType(opts, 'struct'); | |
209 if isfield(opts, 'I_local2neighbor') | |
210 [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,opts); | |
211 else | |
212 [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,opts); | |
213 end | |
214 end | |
215 end | |
216 | |
217 function [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,opts) | |
206 % u denotes the solution in the own domain | 218 % u denotes the solution in the own domain |
207 % v denotes the solution in the neighbour domain | 219 % v denotes the solution in the neighbour domain |
208 % Get neighbour boundary operator | 220 |
209 | 221 % Get boundary operators |
210 [coord_nei, n_nei] = get_boundary_number(obj, neighbour_boundary); | 222 [e_neighbour, d_neighbour] = neighbour_scheme.get_boundary_ops(neighbour_boundary); |
211 [coord, n] = get_boundary_number(obj, boundary); | 223 [e, d, H_gamma] = obj.get_boundary_ops(boundary); |
212 switch n_nei | |
213 case 1 | |
214 % North or east boundary | |
215 e_neighbour = neighbour_scheme.e_r; | |
216 d_neighbour = neighbour_scheme.d1_r; | |
217 case -1 | |
218 % South or west boundary | |
219 e_neighbour = neighbour_scheme.e_l; | |
220 d_neighbour = neighbour_scheme.d1_l; | |
221 end | |
222 | |
223 e_neighbour = e_neighbour{coord_nei}; | |
224 d_neighbour = d_neighbour{coord_nei}; | |
225 H_gamma = obj.H_boundary{coord}; | |
226 Hi = obj.Hi; | 224 Hi = obj.Hi; |
227 a = obj.a; | 225 a = obj.a; |
228 | 226 |
229 switch coord_nei | 227 % Get outward unit normal component |
230 case 1 | 228 [~, n] = obj.get_boundary_number(boundary); |
231 m_neighbour = neighbour_scheme.m(2); | |
232 case 2 | |
233 m_neighbour = neighbour_scheme.m(1); | |
234 end | |
235 | |
236 switch coord | |
237 case 1 | |
238 m = obj.m(2); | |
239 case 2 | |
240 m = obj.m(1); | |
241 end | |
242 | |
243 switch n | |
244 case 1 | |
245 % North or east boundary | |
246 e = obj.e_r; | |
247 d = obj.d1_r; | |
248 case -1 | |
249 % South or west boundary | |
250 e = obj.e_l; | |
251 d = obj.d1_l; | |
252 end | |
253 e = e{coord}; | |
254 d = d{coord}; | |
255 | 229 |
256 Hi = obj.Hi; | 230 Hi = obj.Hi; |
257 sigma = -n*1i*a/2; | 231 sigma = -n*1i*a/2; |
258 tau = -n*(1i*a)'/2; | 232 tau = -n*(1i*a)'/2; |
259 | 233 |
260 grid_ratio = m/m_neighbour; | |
261 if grid_ratio ~= 1 | |
262 | |
263 [ms, index] = sort([m, m_neighbour]); | |
264 orders = [obj.order, neighbour_scheme.order]; | |
265 orders = orders(index); | |
266 | |
267 switch obj.interpolation_type | |
268 case 'MC' | |
269 interpOpSet = sbp.InterpMC(ms(1),ms(2),orders(1),orders(2)); | |
270 if grid_ratio < 1 | |
271 I_neighbour2local_e = interpOpSet.IF2C; | |
272 I_neighbour2local_d = interpOpSet.IF2C; | |
273 I_local2neighbour_e = interpOpSet.IC2F; | |
274 I_local2neighbour_d = interpOpSet.IC2F; | |
275 elseif grid_ratio > 1 | |
276 I_neighbour2local_e = interpOpSet.IC2F; | |
277 I_neighbour2local_d = interpOpSet.IC2F; | |
278 I_local2neighbour_e = interpOpSet.IF2C; | |
279 I_local2neighbour_d = interpOpSet.IF2C; | |
280 end | |
281 case 'AWW' | |
282 %String 'C2F' indicates that ICF2 is more accurate. | |
283 interpOpSetF2C = sbp.InterpAWW(ms(1),ms(2),orders(1),orders(2),'F2C'); | |
284 interpOpSetC2F = sbp.InterpAWW(ms(1),ms(2),orders(1),orders(2),'C2F'); | |
285 if grid_ratio < 1 | |
286 % Local is coarser than neighbour | |
287 I_neighbour2local_e = interpOpSetF2C.IF2C; | |
288 I_neighbour2local_d = interpOpSetC2F.IF2C; | |
289 I_local2neighbour_e = interpOpSetC2F.IC2F; | |
290 I_local2neighbour_d = interpOpSetF2C.IC2F; | |
291 elseif grid_ratio > 1 | |
292 % Local is finer than neighbour | |
293 I_neighbour2local_e = interpOpSetC2F.IC2F; | |
294 I_neighbour2local_d = interpOpSetF2C.IC2F; | |
295 I_local2neighbour_e = interpOpSetF2C.IF2C; | |
296 I_local2neighbour_d = interpOpSetC2F.IF2C; | |
297 end | |
298 otherwise | |
299 error(['Interpolation type ' obj.interpolation_type ... | |
300 ' is not available.' ]); | |
301 end | |
302 | |
303 else | |
304 % No interpolation required | |
305 I_neighbour2local_e = speye(m,m); | |
306 I_neighbour2local_d = speye(m,m); | |
307 I_local2neighbour_e = speye(m,m); | |
308 I_local2neighbour_d = speye(m,m); | |
309 end | |
310 | |
311 closure = tau*Hi*d*H_gamma*e' + sigma*Hi*e*H_gamma*d'; | 234 closure = tau*Hi*d*H_gamma*e' + sigma*Hi*e*H_gamma*d'; |
312 penalty = -tau*Hi*d*H_gamma*I_neighbour2local_e*e_neighbour' ... | 235 penalty = -tau*Hi*d*H_gamma*e_neighbour' ... |
313 -sigma*Hi*e*H_gamma*I_neighbour2local_d*d_neighbour'; | 236 -sigma*Hi*e*H_gamma*d_neighbour'; |
237 | |
238 end | |
239 | |
240 function [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,opts) | |
241 % u denotes the solution in the own domain | |
242 % v denotes the solution in the neighbour domain | |
243 | |
244 % Get boundary operators | |
245 [e_neighbour, d_neighbour] = neighbour_scheme.get_boundary_ops(neighbour_boundary); | |
246 [e, d, H_gamma] = obj.get_boundary_ops(boundary); | |
247 Hi = obj.Hi; | |
248 a = obj.a; | |
249 | |
250 % Get outward unit normal component | |
251 [~, n] = obj.get_boundary_number(boundary); | |
252 | |
253 % Get interpolation operators from opts | |
254 I_u2v_good = opts.I_local2neighbor.good; | |
255 I_u2v_bad = opts.I_local2neighbor.bad; | |
256 I_v2u_good = opts.I_neighbor2local.good; | |
257 I_v2u_bad = opts.I_neighbor2local.bad; | |
258 | |
259 sigma = -n*1i*a/2; | |
260 tau = -n*(1i*a)'/2; | |
261 | |
262 closure = tau*Hi*d*H_gamma*e' + sigma*Hi*e*H_gamma*d'; | |
263 penalty = -tau*Hi*d*H_gamma*I_v2u_good*e_neighbour' ... | |
264 -sigma*Hi*e*H_gamma*I_v2u_bad*d_neighbour'; | |
314 | 265 |
315 end | 266 end |
316 | 267 |
317 % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. | 268 % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. |
318 function [j, nj] = get_boundary_number(obj, boundary) | 269 function [j, nj] = get_boundary_number(obj, boundary) |
332 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | 283 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} |
333 nj = 1; | 284 nj = 1; |
334 end | 285 end |
335 end | 286 end |
336 | 287 |
337 % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. | 288 % Returns the boundary ops and sign for the boundary specified by the string boundary. |
338 function [return_op] = get_boundary_operator(obj, op, boundary) | 289 % The right boundary is considered the positive boundary |
290 function [e, d, H_b] = get_boundary_ops(obj, boundary) | |
339 | 291 |
340 switch boundary | 292 switch boundary |
341 case {'w','W','west','West', 'e', 'E', 'east', 'East'} | 293 case 'w' |
342 j = 1; | 294 e = obj.e_w; |
343 case {'s','S','south','South', 'n', 'N', 'north', 'North'} | 295 d = obj.d_w; |
344 j = 2; | 296 H_b = obj.H_boundary{1}; |
297 case 'e' | |
298 e = obj.e_e; | |
299 d = obj.d_e; | |
300 H_b = obj.H_boundary{1}; | |
301 case 's' | |
302 e = obj.e_s; | |
303 d = obj.d_s; | |
304 H_b = obj.H_boundary{2}; | |
305 case 'n' | |
306 e = obj.e_n; | |
307 d = obj.d_n; | |
308 H_b = obj.H_boundary{2}; | |
345 otherwise | 309 otherwise |
346 error('No such boundary: boundary = %s',boundary); | 310 error('No such boundary: boundary = %s',boundary); |
347 end | 311 end |
348 | |
349 switch op | |
350 case 'e' | |
351 switch boundary | |
352 case {'w','W','west','West','s','S','south','South'} | |
353 return_op = obj.e_l{j}; | |
354 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | |
355 return_op = obj.e_r{j}; | |
356 end | |
357 case 'd' | |
358 switch boundary | |
359 case {'w','W','west','West','s','S','south','South'} | |
360 return_op = obj.d1_l{j}; | |
361 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | |
362 return_op = obj.d1_r{j}; | |
363 end | |
364 otherwise | |
365 error(['No such operator: operator = ' op]); | |
366 end | |
367 | |
368 end | 312 end |
369 | 313 |
370 function N = size(obj) | 314 function N = size(obj) |
371 N = prod(obj.m); | 315 N = prod(obj.m); |
372 end | 316 end |