Mercurial > repos > public > sbplib
diff +scheme/Elastic2dVariable.m @ 943:21394c78c72e feature/utux2D
Merge with default
author | Martin Almquist <malmquist@stanford.edu> |
---|---|
date | Tue, 04 Dec 2018 15:24:36 -0800 |
parents | b9c98661ff5d b374a8aa9246 |
children | a4ad90b37998 a2fcc4cf2298 |
line wrap: on
line diff
--- a/+scheme/Elastic2dVariable.m Tue Dec 04 14:54:28 2018 -0800 +++ b/+scheme/Elastic2dVariable.m Tue Dec 04 15:24:36 2018 -0800 @@ -31,9 +31,16 @@ tau_l, tau_r H, Hi % Inner products + phi % Borrowing constant for (d1 - e^T*D1) from R gamma % Borrowing constant for d1 from M H11 % First element of H + + % Borrowing from H, M, and R + thH + thM + thR + e_l, e_r d1_l, d1_r % Normal derivatives at the boundary E % E{i}^T picks out component i @@ -64,6 +71,13 @@ h = g.scaling(); lim = g.lim; + if isempty(lim) + x = g.x; + lim = cell(length(x),1); + for i = 1:length(x) + lim{i} = {min(x{i}), max(x{i})}; + end + end % 1D operators ops = cell(dim,1); @@ -77,6 +91,11 @@ obj.H11{i} = ops{i}.borrowing.H11; obj.phi{i} = beta/obj.H11{i}; obj.gamma{i} = ops{i}.borrowing.M.d1; + + % Better names + obj.thR{i} = ops{i}.borrowing.R.delta_D; + obj.thM{i} = ops{i}.borrowing.M.d1; + obj.thH{i} = ops{i}.borrowing.H11; end I = cell(dim,1); @@ -262,35 +281,24 @@ % Closure functions return the operators applied to the own domain to close the boundary % Penalty functions return the operators to force the solution. In the case of an interface it returns the operator applied to the other doamin. % boundary is a string specifying the boundary e.g. 'l','r' or 'e','w','n','s'. - % type is a cell array of strings specifying the type of boundary condition for each component. + % bc is a cell array of component and bc type, e.g. {1, 'd'} for Dirichlet condition + % on the first component. % data is a function returning the data that should be applied at the boundary. % 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, parameter) - default_arg('type',{'free','free'}); - default_arg('parameter', []); + function [closure, penalty] = boundary_condition(obj, boundary, bc, tuning) + default_arg('tuning', 1.2); + + assert( iscell(bc), 'The BC type must be a 2x1 cell array' ); + comp = bc{1}; + type = bc{2}; % j is the coordinate direction of the boundary - % nj: outward unit normal component. - % nj = -1 for west, south, bottom boundaries - % nj = 1 for east, north, top boundaries - [j, nj] = obj.get_boundary_number(boundary); - switch nj - case 1 - e = obj.e_r; - d = obj.d1_r; - tau = obj.tau_r{j}; - T = obj.T_r{j}; - case -1 - e = obj.e_l; - d = obj.d1_l; - tau = obj.tau_l{j}; - T = obj.T_l{j}; - end + j = obj.get_boundary_number(boundary); + [e, T, tau, H_gamma] = obj.get_boundary_operator({'e','T','tau','H'}, boundary); E = obj.E; Hi = obj.Hi; - H_gamma = obj.H_boundary{j}; LAMBDA = obj.LAMBDA; MU = obj.MU; RHOi = obj.RHOi; @@ -298,66 +306,127 @@ dim = obj.dim; m_tot = obj.grid.N(); - RHOi_kron = obj.RHOi_kron; - Hi_kron = obj.Hi_kron; - % Preallocate closure = sparse(dim*m_tot, dim*m_tot); - penalty = cell(dim,1); - for k = 1:dim - penalty{k} = sparse(dim*m_tot, m_tot/obj.m(j)); - end + penalty = sparse(dim*m_tot, m_tot/obj.m(j)); - % Loop over components that we (potentially) have different BC on - for k = 1:dim - switch type{k} + k = comp; + switch type + + % Dirichlet boundary condition + case {'D','d','dirichlet','Dirichlet'} - % Dirichlet boundary condition - case {'D','d','dirichlet','Dirichlet'} + phi = obj.phi{j}; + h = obj.h(j); + h11 = obj.H11{j}*h; + gamma = obj.gamma{j}; - tuning = 1.2; - phi = obj.phi{j}; - h = obj.h(j); - h11 = obj.H11{j}*h; - gamma = obj.gamma{j}; - - a_lambda = dim/h11 + 1/(h11*phi); - a_mu_i = 2/(gamma*h); - a_mu_ij = 2/h11 + 1/(h11*phi); + a_lambda = dim/h11 + 1/(h11*phi); + a_mu_i = 2/(gamma*h); + a_mu_ij = 2/h11 + 1/(h11*phi); - d = @kroneckerDelta; % Kronecker delta - db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta - alpha = @(i,j) tuning*( d(i,j)* a_lambda*LAMBDA ... - + d(i,j)* a_mu_i*MU ... - + db(i,j)*a_mu_ij*MU ); + d = @kroneckerDelta; % Kronecker delta + db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta + alpha = @(i,j) tuning*( d(i,j)* a_lambda*LAMBDA ... + + d(i,j)* a_mu_i*MU ... + + db(i,j)*a_mu_ij*MU ); - % Loop over components that Dirichlet penalties end up on - for i = 1:dim - C = T{k,i}; - A = -d(i,k)*alpha(i,j); - B = A + C; - closure = closure + E{i}*RHOi*Hi*B'*e{j}*H_gamma*(e{j}'*E{k}' ); - penalty{k} = penalty{k} - E{i}*RHOi*Hi*B'*e{j}*H_gamma; - end + % Loop over components that Dirichlet penalties end up on + for i = 1:dim + C = T{k,i}; + A = -d(i,k)*alpha(i,j); + B = A + C; + closure = closure + E{i}*RHOi*Hi*B'*e*H_gamma*(e'*E{k}' ); + penalty = penalty - E{i}*RHOi*Hi*B'*e*H_gamma; + end - % Free boundary condition - case {'F','f','Free','free','traction','Traction','t','T'} - closure = closure - E{k}*RHOi*Hi*e{j}*H_gamma* (e{j}'*tau{k} ); - penalty{k} = penalty{k} + E{k}*RHOi*Hi*e{j}*H_gamma; + % Free boundary condition + case {'F','f','Free','free','traction','Traction','t','T'} + closure = closure - E{k}*RHOi*Hi*e*H_gamma* (e'*tau{k} ); + penalty = penalty + E{k}*RHOi*Hi*e*H_gamma; - % Unknown boundary condition - otherwise - error('No such boundary condition: type = %s',type); - end + % Unknown boundary condition + otherwise + error('No such boundary condition: type = %s',type); end end - function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary,opts) + function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary) % u denotes the solution in the own domain % v denotes the solution in the neighbour domain + % Operators without subscripts are from the own domain. tuning = 1.2; - % tuning = 20.2; - error('Interface not implemented'); + + % j is the coordinate direction of the boundary + j = obj.get_boundary_number(boundary); + j_v = neighbour_scheme.get_boundary_number(neighbour_boundary); + + % Get boundary operators + [e, T, tau, H_gamma] = obj.get_boundary_operator({'e','T','tau','H'}, boundary); + [e_v, tau_v] = neighbour_scheme.get_boundary_operator({'e','tau'}, neighbour_boundary); + + % Operators and quantities that correspond to the own domain only + Hi = obj.Hi; + RHOi = obj.RHOi; + dim = obj.dim; + + %--- Other operators ---- + m_tot_u = obj.grid.N(); + E = obj.E; + LAMBDA_u = obj.LAMBDA; + MU_u = obj.MU; + lambda_u = e'*LAMBDA_u*e; + mu_u = e'*MU_u*e; + + m_tot_v = neighbour_scheme.grid.N(); + E_v = neighbour_scheme.E; + LAMBDA_v = neighbour_scheme.LAMBDA; + MU_v = neighbour_scheme.MU; + lambda_v = e_v'*LAMBDA_v*e_v; + mu_v = e_v'*MU_v*e_v; + %------------------------- + + % Borrowing constants + h_u = obj.h(j); + thR_u = obj.thR{j}*h_u; + thM_u = obj.thM{j}*h_u; + thH_u = obj.thH{j}*h_u; + + h_v = neighbour_scheme.h(j_v); + thR_v = neighbour_scheme.thR{j_v}*h_v; + thH_v = neighbour_scheme.thH{j_v}*h_v; + thM_v = neighbour_scheme.thM{j_v}*h_v; + + % alpha = penalty strength for normal component, beta for tangential + alpha_u = dim*lambda_u/(4*thH_u) + lambda_u/(4*thR_u) + mu_u/(2*thM_u); + alpha_v = dim*lambda_v/(4*thH_v) + lambda_v/(4*thR_v) + mu_v/(2*thM_v); + beta_u = mu_u/(2*thH_u) + mu_u/(4*thR_u); + beta_v = mu_v/(2*thH_v) + mu_v/(4*thR_v); + alpha = alpha_u + alpha_v; + beta = beta_u + beta_v; + + d = @kroneckerDelta; % Kronecker delta + db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta + strength = @(i,j) tuning*(d(i,j)*alpha + db(i,j)*beta); + + % Preallocate + closure = sparse(dim*m_tot_u, dim*m_tot_u); + penalty = sparse(dim*m_tot_u, dim*m_tot_v); + + % Loop over components that penalties end up on + for i = 1:dim + closure = closure - E{i}*RHOi*Hi*e*strength(i,j)*H_gamma*e'*E{i}'; + penalty = penalty + E{i}*RHOi*Hi*e*strength(i,j)*H_gamma*e_v'*E_v{i}'; + + closure = closure - 1/2*E{i}*RHOi*Hi*e*H_gamma*e'*tau{i}; + penalty = penalty - 1/2*E{i}*RHOi*Hi*e*H_gamma*e_v'*tau_v{i}; + + % Loop over components that we have interface conditions on + for k = 1:dim + closure = closure + 1/2*E{i}*RHOi*Hi*T{k,i}'*e*H_gamma*e'*E{k}'; + penalty = penalty - 1/2*E{i}*RHOi*Hi*T{k,i}'*e*H_gamma*e_v'*E_v{k}'; + end + end end % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. @@ -380,8 +449,9 @@ 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 operator op for the boundary specified by the string boundary. + % op: may be a cell array of strings + function [varargout] = get_boundary_operator(obj, op, boundary) switch boundary case {'w','W','west','West', 'e', 'E', 'east', 'East'} @@ -392,29 +462,51 @@ 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: operatr = ' op]); + if ~iscell(op) + op = {op}; + end + + for i = 1:length(op) + switch op{i} + case 'e' + switch boundary + case {'w','W','west','West','s','S','south','South'} + varargout{i} = obj.e_l{j}; + case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} + varargout{i} = obj.e_r{j}; + end + case 'd' + switch boundary + case {'w','W','west','West','s','S','south','South'} + varargout{i} = obj.d1_l{j}; + case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} + varargout{i} = obj.d1_r{j}; + end + case 'H' + varargout{i} = obj.H_boundary{j}; + case 'T' + switch boundary + case {'w','W','west','West','s','S','south','South'} + varargout{i} = obj.T_l{j}; + case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} + varargout{i} = obj.T_r{j}; + end + case 'tau' + switch boundary + case {'w','W','west','West','s','S','south','South'} + varargout{i} = obj.tau_l{j}; + case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} + varargout{i} = obj.tau_r{j}; + end + otherwise + error(['No such operator: operator = ' op{i}]); + end end end function N = size(obj) - N = prod(obj.m); + N = obj.dim*prod(obj.m); end end end