Mercurial > repos > public > sbplib
comparison +scheme/LaplaceCurvilinear.m @ 927:4291731570bb feature/utux2D
Rename AWW OP. Make Interpolation operator classes take grid points as arguments. Remove LaplCurv.interpolationOperators. Introduce default struct in LaplCurv.interface.
author | Martin Almquist <malmquist@stanford.edu> |
---|---|
date | Mon, 03 Dec 2018 14:53:52 -0800 |
parents | 8f8f5ff23ead |
children | 1c61d8fa9903 |
comparison
equal
deleted
inserted
replaced
926:60a3bc79835a | 927:4291731570bb |
---|---|
276 % opts Struct that specifies the interface coupling. | 276 % opts Struct that specifies the interface coupling. |
277 % Fields: | 277 % Fields: |
278 % -- tuning: penalty strength, defaults to 1.2 | 278 % -- tuning: penalty strength, defaults to 1.2 |
279 % -- interpolation: struct of interpolation operators (empty for conforming grids) | 279 % -- interpolation: struct of interpolation operators (empty for conforming grids) |
280 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary,opts) | 280 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary,opts) |
281 if isempty(opts) | 281 |
282 defaultType.tuning = 1.2; | |
283 defaultType.interpolation = 'none'; | |
284 default_struct('opts', defaultType); | |
285 | |
286 switch opts.interpolation | |
287 case {'none', ''} | |
282 [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary); | 288 [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary); |
283 else | 289 case {'op','OP'} |
284 assertType(opts, 'struct'); | 290 [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,opts); |
285 if isfield(opts, 'interpolation') | 291 otherwise |
286 [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,opts); | 292 error('Unknown type of interpolation: %s ', type.interpolation); |
287 else | |
288 [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,opts); | |
289 end | |
290 end | 293 end |
291 end | 294 end |
292 | 295 |
293 function [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,opts) | 296 function [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,opts) |
294 | 297 |
326 function [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,opts) | 329 function [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,opts) |
327 | 330 |
328 % TODO: Make this work for curvilinear grids | 331 % TODO: Make this work for curvilinear grids |
329 warning('LaplaceCurvilinear: Non-conforming grid interpolation only works for Cartesian grids.'); | 332 warning('LaplaceCurvilinear: Non-conforming grid interpolation only works for Cartesian grids.'); |
330 | 333 |
331 default_field(opts, 'tuning', 1.2); | 334 % User can request special interpolation operators by specifying type.interpOpSet |
332 default_field(opts, 'interpolation', 'OP'); | 335 default_field(opts, 'interpOpSet', @sbp.InterpOpsOP); |
336 interpOpSet = opts.interpOpSet; | |
333 tuning = opts.tuning; | 337 tuning = opts.tuning; |
338 | |
334 | 339 |
335 % u denotes the solution in the own domain | 340 % u denotes the solution in the own domain |
336 % v denotes the solution in the neighbour domain | 341 % v denotes the solution in the neighbour domain |
337 [e_u, d_u, gamm_u, H_b_u, I_u, ~, X_u] = obj.get_boundary_ops(boundary); | 342 [e_u, d_u, gamm_u, H_b_u, I_u, ~, X_u] = obj.get_boundary_ops(boundary); |
338 [e_v, d_v, gamm_v, H_b_v, I_v, ~, X_v] = neighbour_scheme.get_boundary_ops(neighbour_boundary); | 343 [e_v, d_v, gamm_v, H_b_v, I_v, ~, X_v] = neighbour_scheme.get_boundary_ops(neighbour_boundary); |
369 tau_u = tuning * spdiag(tau_u); | 374 tau_u = tuning * spdiag(tau_u); |
370 tau_v = tuning * spdiag(tau_v); | 375 tau_v = tuning * spdiag(tau_v); |
371 beta_u = tau_v; | 376 beta_u = tau_v; |
372 | 377 |
373 % Build interpolation operators | 378 % Build interpolation operators |
374 [I_u2v_good, I_u2v_bad, I_v2u_good, I_v2u_bad] = ... | 379 intOps = interpOpSet(x_u, x_v, obj.order, neighbour_scheme.order); |
375 obj.interpolationOperators(x_u, x_v, obj.order, opts.interpolation); | 380 Iu2v = intOps.Iu2v; |
381 Iv2u = intOps.Iv2u; | |
376 | 382 |
377 closure = a*Hi*e_u*tau_u*H_b_u*e_u' + ... | 383 closure = a*Hi*e_u*tau_u*H_b_u*e_u' + ... |
378 a*Hi*e_u*H_b_u*I_v2u_bad*beta_u*I_u2v_good*e_u' + ... | 384 a*Hi*e_u*H_b_u*Iv2u.bad*beta_u*Iu2v.good*e_u' + ... |
379 a*1/2*Hi*d_u*H_b_u*e_u' + ... | 385 a*1/2*Hi*d_u*H_b_u*e_u' + ... |
380 -a*1/2*Hi*e_u*H_b_u*d_u'; | 386 -a*1/2*Hi*e_u*H_b_u*d_u'; |
381 | 387 |
382 penalty = -a*Hi*e_u*tau_u*H_b_u*I_v2u_good*e_v' + ... | 388 penalty = -a*Hi*e_u*tau_u*H_b_u*Iv2u.good*e_v' + ... |
383 -a*Hi*e_u*H_b_u*I_v2u_bad*beta_u*e_v' + ... | 389 -a*Hi*e_u*H_b_u*Iv2u.bad*beta_u*e_v' + ... |
384 -a*1/2*Hi*d_u*H_b_u*I_v2u_good*e_v' + ... | 390 -a*1/2*Hi*d_u*H_b_u*Iv2u.good*e_v' + ... |
385 -a*1/2*Hi*e_u*H_b_u*I_v2u_bad*d_v'; | 391 -a*1/2*Hi*e_u*H_b_u*Iv2u.bad*d_v'; |
386 | |
387 | 392 |
388 end | 393 end |
389 | 394 |
390 % Returns the boundary ops and sign for the boundary specified by the string boundary. | 395 % Returns the boundary ops and sign for the boundary specified by the string boundary. |
391 % The right boundary is considered the positive boundary | 396 % The right boundary is considered the positive boundary |
439 gamm = obj.gamm_v; | 444 gamm = obj.gamm_v; |
440 end | 445 end |
441 | 446 |
442 end | 447 end |
443 | 448 |
444 % x_u, x_v -- vectors of the coordinate that varies along the boundary | |
445 % interpOpSet -- string, e.g 'MC' or 'OP'. | |
446 % TODO: Allow for general x_u, x_v. Currently only works for 2:1 ratio. | |
447 function [I_u2v_good, I_u2v_bad, I_v2u_good, I_v2u_bad] = interpolationOperators(obj, x_u, x_v, order, interpOpSet) | |
448 default_arg(interpOpSet, 'OP'); | |
449 | |
450 m_u = length(x_u) - 1; | |
451 m_v = length(x_v) - 1; | |
452 | |
453 if m_u == m_v | |
454 % Matching grids, no interpolation required (presumably) | |
455 error('LaplaceCurvilinear.interpolationOperators: m_u equals m_v, this interface should not need interpolation.') | |
456 elseif m_u/m_v == 2 | |
457 % Block u is finer | |
458 | |
459 switch interpOpSet | |
460 case 'MC' | |
461 interpOps = sbp.InterpMC(m_v+1, m_u+1, order, order); | |
462 I_u2v_good = interpOps.IF2C; | |
463 I_u2v_bad = interpOps.IF2C; | |
464 I_v2u_good = interpOps.IC2F; | |
465 I_v2u_bad = interpOps.IC2F; | |
466 | |
467 case {'OP', 'AWW'} | |
468 interpOpsF2C = sbp.InterpAWW(m_v+1, m_u+1, order, order, 'F2C'); | |
469 interpOpsC2F = sbp.InterpAWW(m_v+1, m_u+1, order, order, 'C2F'); | |
470 I_u2v_good = interpOpsF2C.IF2C; | |
471 I_u2v_bad = interpOpsC2F.IF2C; | |
472 I_v2u_good = interpOpsC2F.IC2F; | |
473 I_v2u_bad = interpOpsF2C.IC2F; | |
474 end | |
475 | |
476 elseif m_v/m_u == 2 | |
477 % Block v is finer | |
478 | |
479 switch interpOpSet | |
480 case 'MC' | |
481 interpOps = sbp.InterpMC(m_u+1, m_v+1, order, order); | |
482 I_u2v_good = interpOps.IC2F; | |
483 I_u2v_bad = interpOps.IC2F; | |
484 I_v2u_good = interpOps.IF2C; | |
485 I_v2u_bad = interpOps.IF2C; | |
486 | |
487 case {'OP', 'AWW'} | |
488 interpOpsF2C = sbp.InterpAWW(m_u+1, m_v+1, order, order, 'F2C'); | |
489 interpOpsC2F = sbp.InterpAWW(m_u+1, m_v+1, order, order, 'C2F'); | |
490 I_u2v_good = interpOpsC2F.IC2F; | |
491 I_u2v_bad = interpOpsF2C.IC2F; | |
492 I_v2u_good = interpOpsF2C.IF2C; | |
493 I_v2u_bad = interpOpsC2F.IF2C; | |
494 end | |
495 else | |
496 error(sprintf('Interpolation operators for grid ratio %f have not yet been constructed', m_u/m_v)); | |
497 end | |
498 | |
499 end | |
500 | |
501 function N = size(obj) | 449 function N = size(obj) |
502 N = prod(obj.m); | 450 N = prod(obj.m); |
503 end | 451 end |
504 end | 452 end |
505 end | 453 end |