Mercurial > repos > public > sbplib
changeset 885:18e10217dca9 feature/d1_staggered
Generalize Staggered1DAcoustics to handle variable coefficients defined by both function handles and vectors.
author | Martin Almquist <malmquist@stanford.edu> |
---|---|
date | Sun, 04 Nov 2018 12:36:30 -0800 |
parents | 675e571e6f4a |
children | c70131daaa6e |
files | +scheme/Staggered1DAcousticsVariable.m |
diffstat | 1 files changed, 67 insertions(+), 35 deletions(-) [+] |
line wrap: on
line diff
--- a/+scheme/Staggered1DAcousticsVariable.m Tue Jun 19 14:25:43 2018 -0700 +++ b/+scheme/Staggered1DAcousticsVariable.m Sun Nov 04 12:36:30 2018 -0800 @@ -2,10 +2,10 @@ properties m % Number of points of primal grid in each direction, possibly a vector h % Grid spacing - + % Grids grid % Total grid object - grid_primal + grid_primal grid_dual order % Order accuracy for the approximation @@ -39,15 +39,15 @@ methods - % Scheme for A*u_t + B u_x = 0, + % Scheme for A*u_t + B u_x = 0, % u = [p, v]; % A: Diagonal and A > 0, % A = [a1, 0; % 0, a2] - % + % % B = B^T and with diagonal entries = 0. - % B = [0 b - % b 0] + % B = [0 b + % b 0] % Here we store p on the primal grid and v on the dual % A and B are cell matrices of function handles function obj = Staggered1DAcousticsVariable(g, order, A, B) @@ -69,16 +69,48 @@ x_primal = obj.grid_primal.points(); x_dual = obj.grid_dual.points(); + % If coefficients are function handles, evaluate them + if isa(A{1,1}, 'function_handle') + A{1,1} = A{1,1}(x_primal); + A{1,2} = A{1,2}(x_dual); + A{2,1} = A{2,1}(x_primal); + A{2,2} = A{2,2}(x_dual); + end + + if isa(B{1,1}, 'function_handle') + B{1,1} = B{1,1}(x_primal); + B{1,2} = B{1,2}(x_primal); + B{2,1} = B{2,1}(x_dual); + B{2,2} = B{2,2}(x_dual); + end + + % If coefficents are vectors, turn them into diagonal matrices + [m, n] = size(A{1,1}); + if m==1 || n == 1 + A{1,1} = spdiag(A{1,1}, 0); + A{2,1} = spdiag(A{2,1}, 0); + A{1,2} = spdiag(A{1,2}, 0); + A{2,2} = spdiag(A{2,2}, 0); + end + + [m, n] = size(B{1,1}); + if m==1 || n == 1 + B{1,1} = spdiag(B{1,1}, 0); + B{2,1} = spdiag(B{2,1}, 0); + B{1,2} = spdiag(B{1,2}, 0); + B{2,2} = spdiag(B{2,2}, 0); + end + % Boundary matrices - obj.A_l = [A{1,1}(xl), A{1,2}(xl);.... - A{2,1}(xl), A{2,2}(xl)]; - obj.A_r = [A{1,1}(xr), A{1,2}(xr);.... - A{2,1}(xr), A{2,2}(xr)]; - obj.B_l = [B{1,1}(xl), B{1,2}(xl);.... - B{2,1}(xl), B{2,2}(xl)]; - obj.B_r = [B{1,1}(xr), B{1,2}(xr);.... - B{2,1}(xr), B{2,2}(xr)]; - + obj.A_l = full([A{1,1}(1,1), A{1,2}(1,1);.... + A{2,1}(1,1), A{2,2}(1,1)]); + obj.A_r = full([A{1,1}(end,end), A{1,2}(end,end);.... + A{2,1}(end,end), A{2,2}(end,end)]); + obj.B_l = full([B{1,1}(1,1), B{1,2}(1,1);.... + B{2,1}(1,1), B{2,2}(1,1)]); + obj.B_r = full([B{1,1}(end,end), B{1,2}(end,end);.... + B{2,1}(end,end), B{2,2}(end,end)]); + % Get operators ops = sbp.D1StaggeredUpwind(obj.m, xlim, order); obj.h = ops.h; @@ -88,14 +120,14 @@ H_dual = ops.H_dual; obj.H = blockmatrix.toMatrix( {H_primal, []; [], H_dual } ); obj.Hi = inv(obj.H); - + D1_primal = ops.D1_primal; D1_dual = ops.D1_dual; - A11_B12 = spdiag(-1./A{1,1}(x_primal).*B{1,2}(x_primal), 0); - A22_B21 = spdiag(-1./A{2,2}(x_dual).*B{2,1}(x_dual), 0); + A11_B12 = -A{1,1}\B{1,2}; + A22_B21 = -A{2,2}\B{2,1}; D = {[], A11_B12*D1_primal;... A22_B21*D1_dual, []}; - obj.D = blockmatrix.toMatrix(D); + obj.D = blockmatrix.toMatrix(D); obj.D1_primal = D1_primal; obj.D1_dual = D1_dual; @@ -104,9 +136,9 @@ e_primal_r = ops.e_primal_r; e_dual_l = ops.e_dual_l; e_dual_r = ops.e_dual_r; - e_l = {e_primal_l, [];... + e_l = {e_primal_l, [];... [] , e_dual_l}; - e_r = {e_primal_r, [];... + e_r = {e_primal_r, [];... [] , e_dual_r}; obj.e_l = blockmatrix.toMatrix(e_l); obj.e_r = blockmatrix.toMatrix(e_r); @@ -126,7 +158,7 @@ % neighbour_scheme is an instance of Scheme that should be interfaced to. % neighbour_boundary is a string specifying which boundary to interface to. function [closure, penalty] = boundary_condition(obj, boundary, type) - + default_arg('type','p'); % type = 'p' => boundary condition for p @@ -202,25 +234,25 @@ sigma = sparse(sigma); L = sparse(L); Tin = sparse(Tin); - + switch boundary case 'l' - tau = -1*obj.e_l * inv(A) * inv(T)' * sigma * inv(L*Tin); + tau = -1*obj.e_l * inv(A) * inv(T)' * sigma * inv(L*Tin); closure = obj.Hi*tau*L*obj.e_l'; case 'r' - tau = 1*obj.e_r * inv(A) * inv(T)' * sigma * inv(L*Tin); + tau = 1*obj.e_r * inv(A) * inv(T)' * sigma * inv(L*Tin); closure = obj.Hi*tau*L*obj.e_r'; end - + penalty = -obj.Hi*tau; - + end - + % Uses the hat variable method for the interface coupling, % see hypsyst_varcoeff.pdf in the hypsyst repository. - % Notation: u for left side of interface, v for right side. + % Notation: u for left side of interface, v for right side. function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary) % Get boundary matrices @@ -249,7 +281,7 @@ C_u = inv(A_u)*B_u; C_v = inv(A_v)*B_v; - % Diagonalize C + % Diagonalize C [T_u, ~] = eig(C_u); Lambda_u = inv(T_u)*C_u*T_u; lambda_u = diag(Lambda_u); @@ -279,18 +311,18 @@ % Create S_tilde and T_tilde Stilde = [Sp_u; Sm_v]; Ttilde = inv(Stilde); - Ttilde_p = Ttilde(:,1); + Ttilde_p = Ttilde(:,1); Ttilde_m = Ttilde(:,2); % Solve for penalty parameters theta_1,2 LHS = Ttilde_m*Sm_v*Tm_u; RHS = B_u*Tm_u; - th_u = RHS./LHS; + th_u = RHS./LHS; TH_u = diag(th_u); LHS = Ttilde_p*Sp_u*Tp_v; RHS = -B_v*Tp_v; - th_v = RHS./LHS; + th_v = RHS./LHS; TH_v = diag(th_v); % Construct penalty matrices @@ -313,9 +345,9 @@ closure = closure_u; penalty = penalty_u; end - + end - + function N = size(obj) N = 2*obj.m+1; end