Mercurial > repos > public > sbplib
changeset 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 | f7306f03f77a |
children | 95cd70f4b07d |
files | +scheme/Schrodinger2d.m |
diffstat | 1 files changed, 67 insertions(+), 123 deletions(-) [+] |
line wrap: on
line diff
--- a/+scheme/Schrodinger2d.m Sat Nov 24 15:43:34 2018 -0800 +++ b/+scheme/Schrodinger2d.m Sun Nov 25 19:46:39 2018 -0800 @@ -33,14 +33,11 @@ H_boundary % Boundary inner products - interpolation_type % MC or AWW - end methods - function obj = Schrodinger2d(g ,order, a, opSet, interpolation_type) - default_arg('interpolation_type','AWW'); + function obj = Schrodinger2d(g ,order, a, opSet) default_arg('opSet',{@sbp.D2Variable, @sbp.D2Variable}); default_arg('a',1); dim = 2; @@ -150,7 +147,6 @@ obj.d_e = obj.d1_r{1}; obj.d_s = obj.d1_l{2}; obj.d_n = obj.d1_r{2}; - obj.interpolation_type = interpolation_type; end @@ -202,115 +198,70 @@ end end + % opts Struct that specifies the interface coupling. + % Fields: + % -- interpolation: struct of interpolation operators (empty for conforming grids) function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary,opts) + if isempty(opts) + [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary); + else + assertType(opts, 'struct'); + if isfield(opts, 'I_local2neighbor') + [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,opts); + else + [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,opts); + end + end + end + + function [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,opts) % u denotes the solution in the own domain % v denotes the solution in the neighbour domain - % Get neighbour boundary operator - [coord_nei, n_nei] = get_boundary_number(obj, neighbour_boundary); - [coord, n] = get_boundary_number(obj, boundary); - switch n_nei - case 1 - % North or east boundary - e_neighbour = neighbour_scheme.e_r; - d_neighbour = neighbour_scheme.d1_r; - case -1 - % South or west boundary - e_neighbour = neighbour_scheme.e_l; - d_neighbour = neighbour_scheme.d1_l; - end - - e_neighbour = e_neighbour{coord_nei}; - d_neighbour = d_neighbour{coord_nei}; - H_gamma = obj.H_boundary{coord}; + % Get boundary operators + [e_neighbour, d_neighbour] = neighbour_scheme.get_boundary_ops(neighbour_boundary); + [e, d, H_gamma] = obj.get_boundary_ops(boundary); Hi = obj.Hi; a = obj.a; - switch coord_nei - case 1 - m_neighbour = neighbour_scheme.m(2); - case 2 - m_neighbour = neighbour_scheme.m(1); - end - - switch coord - case 1 - m = obj.m(2); - case 2 - m = obj.m(1); - end - - switch n - case 1 - % North or east boundary - e = obj.e_r; - d = obj.d1_r; - case -1 - % South or west boundary - e = obj.e_l; - d = obj.d1_l; - end - e = e{coord}; - d = d{coord}; + % Get outward unit normal component + [~, n] = obj.get_boundary_number(boundary); Hi = obj.Hi; sigma = -n*1i*a/2; tau = -n*(1i*a)'/2; - grid_ratio = m/m_neighbour; - if grid_ratio ~= 1 + closure = tau*Hi*d*H_gamma*e' + sigma*Hi*e*H_gamma*d'; + penalty = -tau*Hi*d*H_gamma*e_neighbour' ... + -sigma*Hi*e*H_gamma*d_neighbour'; - [ms, index] = sort([m, m_neighbour]); - orders = [obj.order, neighbour_scheme.order]; - orders = orders(index); + end + + function [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,opts) + % u denotes the solution in the own domain + % v denotes the solution in the neighbour domain - switch obj.interpolation_type - case 'MC' - interpOpSet = sbp.InterpMC(ms(1),ms(2),orders(1),orders(2)); - if grid_ratio < 1 - I_neighbour2local_e = interpOpSet.IF2C; - I_neighbour2local_d = interpOpSet.IF2C; - I_local2neighbour_e = interpOpSet.IC2F; - I_local2neighbour_d = interpOpSet.IC2F; - elseif grid_ratio > 1 - I_neighbour2local_e = interpOpSet.IC2F; - I_neighbour2local_d = interpOpSet.IC2F; - I_local2neighbour_e = interpOpSet.IF2C; - I_local2neighbour_d = interpOpSet.IF2C; - end - case 'AWW' - %String 'C2F' indicates that ICF2 is more accurate. - interpOpSetF2C = sbp.InterpAWW(ms(1),ms(2),orders(1),orders(2),'F2C'); - interpOpSetC2F = sbp.InterpAWW(ms(1),ms(2),orders(1),orders(2),'C2F'); - if grid_ratio < 1 - % Local is coarser than neighbour - I_neighbour2local_e = interpOpSetF2C.IF2C; - I_neighbour2local_d = interpOpSetC2F.IF2C; - I_local2neighbour_e = interpOpSetC2F.IC2F; - I_local2neighbour_d = interpOpSetF2C.IC2F; - elseif grid_ratio > 1 - % Local is finer than neighbour - I_neighbour2local_e = interpOpSetC2F.IC2F; - I_neighbour2local_d = interpOpSetF2C.IC2F; - I_local2neighbour_e = interpOpSetF2C.IF2C; - I_local2neighbour_d = interpOpSetC2F.IF2C; - end - otherwise - error(['Interpolation type ' obj.interpolation_type ... - ' is not available.' ]); - end + % Get boundary operators + [e_neighbour, d_neighbour] = neighbour_scheme.get_boundary_ops(neighbour_boundary); + [e, d, H_gamma] = obj.get_boundary_ops(boundary); + Hi = obj.Hi; + a = obj.a; + + % Get outward unit normal component + [~, n] = obj.get_boundary_number(boundary); - else - % No interpolation required - I_neighbour2local_e = speye(m,m); - I_neighbour2local_d = speye(m,m); - I_local2neighbour_e = speye(m,m); - I_local2neighbour_d = speye(m,m); - end + % Get interpolation operators from opts + I_u2v_good = opts.I_local2neighbor.good; + I_u2v_bad = opts.I_local2neighbor.bad; + I_v2u_good = opts.I_neighbor2local.good; + I_v2u_bad = opts.I_neighbor2local.bad; + + sigma = -n*1i*a/2; + tau = -n*(1i*a)'/2; closure = tau*Hi*d*H_gamma*e' + sigma*Hi*e*H_gamma*d'; - penalty = -tau*Hi*d*H_gamma*I_neighbour2local_e*e_neighbour' ... - -sigma*Hi*e*H_gamma*I_neighbour2local_d*d_neighbour'; + penalty = -tau*Hi*d*H_gamma*I_v2u_good*e_neighbour' ... + -sigma*Hi*e*H_gamma*I_v2u_bad*d_neighbour'; end @@ -334,37 +285,30 @@ end end - % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. - function [return_op] = get_boundary_operator(obj, op, boundary) + % Returns the boundary ops and sign for the boundary specified by the string boundary. + % The right boundary is considered the positive boundary + function [e, d, H_b] = get_boundary_ops(obj, boundary) switch boundary - case {'w','W','west','West', 'e', 'E', 'east', 'East'} - j = 1; - case {'s','S','south','South', 'n', 'N', 'north', 'North'} - j = 2; + case 'w' + e = obj.e_w; + d = obj.d_w; + H_b = obj.H_boundary{1}; + case 'e' + e = obj.e_e; + d = obj.d_e; + H_b = obj.H_boundary{1}; + case 's' + e = obj.e_s; + d = obj.d_s; + H_b = obj.H_boundary{2}; + case 'n' + e = obj.e_n; + d = obj.d_n; + H_b = obj.H_boundary{2}; otherwise error('No such boundary: boundary = %s',boundary); end - - switch op - case 'e' - switch boundary - case {'w','W','west','West','s','S','south','South'} - return_op = obj.e_l{j}; - case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} - return_op = obj.e_r{j}; - end - case 'd' - switch boundary - case {'w','W','west','West','s','S','south','South'} - return_op = obj.d1_l{j}; - case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} - return_op = obj.d1_r{j}; - end - otherwise - error(['No such operator: operator = ' op]); - end - end function N = size(obj)