Mercurial > repos > public > sbplib
comparison +scheme/LaplaceCurvilinear.m @ 922:1d91c2a8aada feature/utux2D
Refactor LaplCurv.interfaceNonConf. Add method for interpolation operator generation in LaplCurv
author | Martin Almquist <malmquist@stanford.edu> |
---|---|
date | Sun, 02 Dec 2018 17:10:07 -0800 |
parents | 19c05eefc8c6 |
children | 8f8f5ff23ead |
comparison
equal
deleted
inserted
replaced
921:19c05eefc8c6 | 922:1d91c2a8aada |
---|---|
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 if isempty(opts) |
282 [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary); | 282 [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary); |
283 else | 283 else |
284 assertType(opts, 'struct'); | 284 assertType(opts, 'struct'); |
285 if isfield(opts, 'I_local2neighbor') | 285 if isfield(opts, 'interpolation') |
286 [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,opts); | 286 [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,opts); |
287 else | 287 else |
288 [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,opts); | 288 [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,opts); |
289 end | 289 end |
290 end | 290 end |
327 | 327 |
328 % TODO: Make this work for curvilinear grids | 328 % TODO: Make this work for curvilinear grids |
329 warning('LaplaceCurvilinear: Non-conforming grid interpolation only works for Cartesian grids.'); | 329 warning('LaplaceCurvilinear: Non-conforming grid interpolation only works for Cartesian grids.'); |
330 | 330 |
331 default_field(opts, 'tuning', 1.2); | 331 default_field(opts, 'tuning', 1.2); |
332 default_field(opts, 'interpolation', 'OP'); | |
332 tuning = opts.tuning; | 333 tuning = opts.tuning; |
333 | 334 |
334 % u denotes the solution in the own domain | 335 % u denotes the solution in the own domain |
335 % v denotes the solution in the neighbour domain | 336 % v denotes the solution in the neighbour domain |
336 I_u2v_good = opts.I_local2neighbor.good; | 337 [e_u, d_u, gamm_u, H_b_u, I_u, ~, X_u] = obj.get_boundary_ops(boundary); |
337 I_u2v_bad = opts.I_local2neighbor.bad; | 338 [e_v, d_v, gamm_v, H_b_v, I_v, ~, X_v] = neighbour_scheme.get_boundary_ops(neighbour_boundary); |
338 I_v2u_good = opts.I_neighbor2local.good; | 339 |
339 I_v2u_bad = opts.I_neighbor2local.bad; | 340 % Extract the coordinate that varies along the interface |
340 | 341 switch boundary |
341 [e_u, d_u, gamm_u, H_b_u, I_u] = obj.get_boundary_ops(boundary); | 342 case {'e','w'} |
342 [e_v, d_v, gamm_v, H_b_v, I_v] = neighbour_scheme.get_boundary_ops(neighbour_boundary); | 343 x_u = X_u(:,2); |
344 case {'s', 'n'} | |
345 x_u = X_u(:,1); | |
346 end | |
347 | |
348 switch neighbour_boundary | |
349 case {'e','w'} | |
350 x_v = X_v(:,2); | |
351 case {'s', 'n'} | |
352 x_v = X_v(:,1); | |
353 end | |
354 | |
343 Hi = obj.Hi; | 355 Hi = obj.Hi; |
344 a = obj.a; | 356 a = obj.a; |
345 | 357 |
346 u = obj; | 358 u = obj; |
347 v = neighbour_scheme; | 359 v = neighbour_scheme; |
356 | 368 |
357 tau_u = tuning * spdiag(tau_u); | 369 tau_u = tuning * spdiag(tau_u); |
358 tau_v = tuning * spdiag(tau_v); | 370 tau_v = tuning * spdiag(tau_v); |
359 beta_u = tau_v; | 371 beta_u = tau_v; |
360 | 372 |
373 % Build interpolation operators | |
374 [I_u2v_good, I_u2v_bad, I_v2u_good, I_v2u_bad] = ... | |
375 obj.InterpolationOperators(x_u, x_v, obj.order, opts.interpolation); | |
376 | |
361 closure = a*Hi*e_u*tau_u*H_b_u*e_u' + ... | 377 closure = a*Hi*e_u*tau_u*H_b_u*e_u' + ... |
362 a*Hi*e_u*H_b_u*I_v2u_bad*beta_u*I_u2v_good*e_u' + ... | 378 a*Hi*e_u*H_b_u*I_v2u_bad*beta_u*I_u2v_good*e_u' + ... |
363 a*1/2*Hi*d_u*H_b_u*e_u' + ... | 379 a*1/2*Hi*d_u*H_b_u*e_u' + ... |
364 -a*1/2*Hi*e_u*H_b_u*d_u'; | 380 -a*1/2*Hi*e_u*H_b_u*d_u'; |
365 | 381 |
373 | 389 |
374 % Returns the boundary ops and sign for the boundary specified by the string boundary. | 390 % Returns the boundary ops and sign for the boundary specified by the string boundary. |
375 % The right boundary is considered the positive boundary | 391 % The right boundary is considered the positive boundary |
376 % | 392 % |
377 % I -- the indices of the boundary points in the grid matrix | 393 % I -- the indices of the boundary points in the grid matrix |
378 function [e, d, gamm, H_b, I] = get_boundary_ops(obj, boundary) | 394 % X -- coordinates along the boundary; |
395 function [e, d, gamm, H_b, I, X, X_logic] = get_boundary_ops(obj, boundary) | |
379 | 396 |
380 % gridMatrix = zeros(obj.m(2),obj.m(1)); | 397 % gridMatrix = zeros(obj.m(2),obj.m(1)); |
381 % gridMatrix(:) = 1:numel(gridMatrix); | 398 % gridMatrix(:) = 1:numel(gridMatrix); |
382 | 399 |
383 ind = grid.funcToMatrix(obj.grid, 1:prod(obj.m)); | 400 ind = grid.funcToMatrix(obj.grid, 1:prod(obj.m)); |
405 I = ind(:,end)'; | 422 I = ind(:,end)'; |
406 otherwise | 423 otherwise |
407 error('No such boundary: boundary = %s',boundary); | 424 error('No such boundary: boundary = %s',boundary); |
408 end | 425 end |
409 | 426 |
427 X = obj.grid.getBoundary(boundary); | |
428 if isa(obg.grid, 'grid.Curvilinear')) | |
429 X_logic = obj.grid.logic.getBoundary(boundary); | |
430 else | |
431 % Cartesian physical coordinates are also logical coordinates | |
432 X_logic = X; | |
433 end | |
434 | |
410 switch boundary | 435 switch boundary |
411 case {'w','e'} | 436 case {'w','e'} |
412 gamm = obj.gamm_u; | 437 gamm = obj.gamm_u; |
413 case {'s','n'} | 438 case {'s','n'} |
414 gamm = obj.gamm_v; | 439 gamm = obj.gamm_v; |
415 end | 440 end |
441 | |
442 end | |
443 | |
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 | |
416 end | 499 end |
417 | 500 |
418 function N = size(obj) | 501 function N = size(obj) |
419 N = prod(obj.m); | 502 N = prod(obj.m); |
420 end | 503 end |