Mercurial > repos > public > sbplib
comparison +scheme/Elastic2dVariable.m @ 890:c70131daaa6e feature/d1_staggered
Merge with feature/poroelastic.
author | Martin Almquist <malmquist@stanford.edu> |
---|---|
date | Wed, 21 Nov 2018 18:29:29 -0800 |
parents | 14fee299ada2 |
children | e30aaa4a3e09 386ef449df51 |
comparison
equal
deleted
inserted
replaced
885:18e10217dca9 | 890:c70131daaa6e |
---|---|
1 classdef Elastic2dVariable < scheme.Scheme | 1 classdef Elastic2dVariable < scheme.Scheme |
2 | 2 |
3 % Discretizes the elastic wave equation: | 3 % Discretizes the elastic wave equation: |
4 % rho u_{i,tt} = di lambda dj u_j + dj mu di u_j + dj mu dj u_i | 4 % rho u_{i,tt} = di lambda dj u_j + dj mu di u_j + dj mu dj u_i |
5 % opSet should be cell array of opSets, one per dimension. This | 5 % opSet should be cell array of opSets, one per dimension. This |
6 % is useful if we have periodic BC in one direction. | 6 % is useful if we have periodic BC in one direction. |
7 | 7 |
8 properties | 8 properties |
9 m % Number of points in each direction, possibly a vector | 9 m % Number of points in each direction, possibly a vector |
28 | 28 |
29 % Traction operators used for BC | 29 % Traction operators used for BC |
30 T_l, T_r | 30 T_l, T_r |
31 tau_l, tau_r | 31 tau_l, tau_r |
32 | 32 |
33 H, Hi % Inner products | 33 H, Hi, H_1D % Inner products |
34 phi % Borrowing constant for (d1 - e^T*D1) from R | |
35 gamma % Borrowing constant for d1 from M | |
36 H11 % First element of H | |
37 e_l, e_r | 34 e_l, e_r |
38 d1_l, d1_r % Normal derivatives at the boundary | 35 d1_l, d1_r % Normal derivatives at the boundary |
39 E % E{i}^T picks out component i | 36 E % E{i}^T picks out component i |
40 | 37 |
41 H_boundary % Boundary inner products | 38 H_boundary % Boundary inner products |
42 | 39 |
43 % Kroneckered norms and coefficients | 40 % Kroneckered norms and coefficients |
44 RHOi_kron | 41 RHOi_kron |
45 Hi_kron | 42 Hi_kron |
43 | |
44 % Borrowing constants of the form gamma*h, where gamma is a dimensionless constant. | |
45 theta_R % Borrowing (d1- D1)^2 from R | |
46 theta_H % First entry in norm matrix | |
47 theta_M % Borrowing d1^2 from M. | |
48 | |
49 % Structures used for adjoint optimization | |
50 B | |
46 end | 51 end |
47 | 52 |
48 methods | 53 methods |
49 | 54 |
50 function obj = Elastic2dVariable(g ,order, lambda_fun, mu_fun, rho_fun, opSet) | 55 % The coefficients can either be function handles or grid functions |
56 function obj = Elastic2dVariable(g ,order, lambda, mu, rho, opSet) | |
51 default_arg('opSet',{@sbp.D2Variable, @sbp.D2Variable}); | 57 default_arg('opSet',{@sbp.D2Variable, @sbp.D2Variable}); |
52 default_arg('lambda_fun', @(x,y) 0*x+1); | 58 default_arg('lambda', @(x,y) 0*x+1); |
53 default_arg('mu_fun', @(x,y) 0*x+1); | 59 default_arg('mu', @(x,y) 0*x+1); |
54 default_arg('rho_fun', @(x,y) 0*x+1); | 60 default_arg('rho', @(x,y) 0*x+1); |
55 dim = 2; | 61 dim = 2; |
56 | 62 |
57 assert(isa(g, 'grid.Cartesian')) | 63 assert(isa(g, 'grid.Cartesian')) |
58 | 64 |
59 lambda = grid.evalOn(g, lambda_fun); | 65 if isa(lambda, 'function_handle') |
60 mu = grid.evalOn(g, mu_fun); | 66 lambda = grid.evalOn(g, lambda); |
61 rho = grid.evalOn(g, rho_fun); | 67 end |
68 if isa(mu, 'function_handle') | |
69 mu = grid.evalOn(g, mu); | |
70 end | |
71 if isa(rho, 'function_handle') | |
72 rho = grid.evalOn(g, rho); | |
73 end | |
74 | |
62 m = g.size(); | 75 m = g.size(); |
63 m_tot = g.N(); | 76 m_tot = g.N(); |
64 | 77 |
65 h = g.scaling(); | 78 h = g.scaling(); |
66 lim = g.lim; | 79 lim = g.lim; |
80 if isempty(lim) | |
81 x = g.x; | |
82 lim = cell(length(x),1); | |
83 for i = 1:length(x) | |
84 lim{i} = {min(x{i}), max(x{i})}; | |
85 end | |
86 end | |
67 | 87 |
68 % 1D operators | 88 % 1D operators |
69 ops = cell(dim,1); | 89 ops = cell(dim,1); |
70 for i = 1:dim | 90 for i = 1:dim |
71 ops{i} = opSet{i}(m(i), lim{i}, order); | 91 ops{i} = opSet{i}(m(i), lim{i}, order); |
72 end | 92 end |
73 | 93 |
74 % Borrowing constants | 94 % Borrowing constants |
75 for i = 1:dim | 95 for i = 1:dim |
76 beta = ops{i}.borrowing.R.delta_D; | 96 obj.theta_R{i} = h(i)*ops{i}.borrowing.R.delta_D; |
77 obj.H11{i} = ops{i}.borrowing.H11; | 97 obj.theta_H{i} = h(i)*ops{i}.borrowing.H11; |
78 obj.phi{i} = beta/obj.H11{i}; | 98 obj.theta_M{i} = h(i)*ops{i}.borrowing.M.d1; |
79 obj.gamma{i} = ops{i}.borrowing.M.d1; | |
80 end | 99 end |
81 | 100 |
82 I = cell(dim,1); | 101 I = cell(dim,1); |
83 D1 = cell(dim,1); | 102 D1 = cell(dim,1); |
84 D2 = cell(dim,1); | 103 D2 = cell(dim,1); |
162 obj.H = kron(H{1},H{2}); | 181 obj.H = kron(H{1},H{2}); |
163 obj.Hi = inv(obj.H); | 182 obj.Hi = inv(obj.H); |
164 obj.H_boundary = cell(dim,1); | 183 obj.H_boundary = cell(dim,1); |
165 obj.H_boundary{1} = H{2}; | 184 obj.H_boundary{1} = H{2}; |
166 obj.H_boundary{2} = H{1}; | 185 obj.H_boundary{2} = H{1}; |
186 obj.H_1D = {H{1}, H{2}}; | |
167 | 187 |
168 % E{i}^T picks out component i. | 188 % E{i}^T picks out component i. |
169 E = cell(dim,1); | 189 E = cell(dim,1); |
170 I = speye(m_tot,m_tot); | 190 I = speye(m_tot,m_tot); |
171 for i = 1:dim | 191 for i = 1:dim |
192 D2_mu{j}*E{i}' ... | 212 D2_mu{j}*E{i}' ... |
193 ); | 213 ); |
194 end | 214 end |
195 end | 215 end |
196 obj.D = D; | 216 obj.D = D; |
197 %=========================================% | 217 %=========================================%' |
198 | 218 |
199 % Numerical traction operators for BC. | 219 % Numerical traction operators for BC. |
200 % Because d1 =/= e0^T*D1, the numerical tractions are different | 220 % Because d1 =/= e0^T*D1, the numerical tractions are different |
201 % at every boundary. | 221 % at every boundary. |
202 T_l = cell(dim,1); | 222 T_l = cell(dim,1); |
221 % Loop over components | 241 % Loop over components |
222 for i = 1:dim | 242 for i = 1:dim |
223 tau_l{j}{i} = sparse(m_tot,dim*m_tot); | 243 tau_l{j}{i} = sparse(m_tot,dim*m_tot); |
224 tau_r{j}{i} = sparse(m_tot,dim*m_tot); | 244 tau_r{j}{i} = sparse(m_tot,dim*m_tot); |
225 for k = 1:dim | 245 for k = 1:dim |
226 T_l{j}{i,k} = ... | 246 T_l{j}{i,k} = ... |
227 -d(i,j)*LAMBDA*(d(i,k)*e_l{k}*d1_l{k}' + db(i,k)*D1{k})... | 247 -d(i,j)*LAMBDA*(d(i,k)*e_l{k}*d1_l{k}' + db(i,k)*D1{k})... |
228 -d(j,k)*MU*(d(i,j)*e_l{i}*d1_l{i}' + db(i,j)*D1{i})... | 248 -d(j,k)*MU*(d(i,j)*e_l{i}*d1_l{i}' + db(i,j)*D1{i})... |
229 -d(i,k)*MU*e_l{j}*d1_l{j}'; | 249 -d(i,k)*MU*e_l{j}*d1_l{j}'; |
230 | 250 |
231 T_r{j}{i,k} = ... | 251 T_r{j}{i,k} = ... |
232 d(i,j)*LAMBDA*(d(i,k)*e_r{k}*d1_r{k}' + db(i,k)*D1{k})... | 252 d(i,j)*LAMBDA*(d(i,k)*e_r{k}*d1_r{k}' + db(i,k)*D1{k})... |
233 +d(j,k)*MU*(d(i,j)*e_r{i}*d1_r{i}' + db(i,j)*D1{i})... | 253 +d(j,k)*MU*(d(i,j)*e_r{i}*d1_r{i}' + db(i,j)*D1{i})... |
234 +d(i,k)*MU*e_r{j}*d1_r{j}'; | 254 +d(i,k)*MU*e_r{j}*d1_r{j}'; |
235 | 255 |
236 tau_l{j}{i} = tau_l{j}{i} + T_l{j}{i,k}*E{k}'; | 256 tau_l{j}{i} = tau_l{j}{i} + T_l{j}{i,k}*E{k}'; |
237 tau_r{j}{i} = tau_r{j}{i} + T_r{j}{i,k}*E{k}'; | 257 tau_r{j}{i} = tau_r{j}{i} + T_r{j}{i,k}*E{k}'; |
238 end | 258 end |
254 obj.h = h; | 274 obj.h = h; |
255 obj.order = order; | 275 obj.order = order; |
256 obj.grid = g; | 276 obj.grid = g; |
257 obj.dim = dim; | 277 obj.dim = dim; |
258 | 278 |
279 % Used for adjoint optimization | |
280 obj.B = cell(1,dim); | |
281 for i = 1:dim | |
282 obj.B{i} = zeros(m(i),m(i),m(i)); | |
283 for k = 1:m(i) | |
284 c = sparse(m(i),1); | |
285 c(k) = 1; | |
286 [~, obj.B{i}(:,:,k)] = ops{i}.D2(c); | |
287 end | |
288 end | |
289 | |
259 end | 290 end |
260 | 291 |
261 | 292 |
262 % Closure functions return the operators applied to the own domain to close the boundary | 293 % Closure functions return the operators applied to the own domain to close the boundary |
263 % Penalty functions return the operators to force the solution. In the case of an interface it returns the operator applied to the other doamin. | 294 % Penalty functions return the operators to force the solution. In the case of an interface it returns the operator applied to the other doamin. |
264 % boundary is a string specifying the boundary e.g. 'l','r' or 'e','w','n','s'. | 295 % boundary is a string specifying the boundary e.g. 'l','r' or 'e','w','n','s'. |
265 % type is a cell array of strings specifying the type of boundary condition for each component. | 296 % bc is a cell array of component and bc type, e.g. {1, 'd'} for Dirichlet condition |
297 % on the first component. | |
266 % data is a function returning the data that should be applied at the boundary. | 298 % data is a function returning the data that should be applied at the boundary. |
267 % neighbour_scheme is an instance of Scheme that should be interfaced to. | 299 % neighbour_scheme is an instance of Scheme that should be interfaced to. |
268 % neighbour_boundary is a string specifying which boundary to interface to. | 300 % neighbour_boundary is a string specifying which boundary to interface to. |
269 function [closure, penalty] = boundary_condition(obj, boundary, type, parameter) | 301 function [closure, penalty] = boundary_condition(obj, boundary, bc, tuning) |
270 default_arg('type',{'free','free'}); | 302 default_arg('tuning', 1.2); |
271 default_arg('parameter', []); | 303 |
304 assert( iscell(bc), 'The BC type must be a 2x1 cell array' ); | |
305 comp = bc{1}; | |
306 type = bc{2}; | |
272 | 307 |
273 % j is the coordinate direction of the boundary | 308 % j is the coordinate direction of the boundary |
274 % nj: outward unit normal component. | 309 j = obj.get_boundary_number(boundary); |
275 % nj = -1 for west, south, bottom boundaries | 310 [e, T, tau, H_gamma] = obj.get_boundary_operator({'e','T','tau','H'}, boundary); |
276 % nj = 1 for east, north, top boundaries | |
277 [j, nj] = obj.get_boundary_number(boundary); | |
278 switch nj | |
279 case 1 | |
280 e = obj.e_r; | |
281 d = obj.d1_r; | |
282 tau = obj.tau_r{j}; | |
283 T = obj.T_r{j}; | |
284 case -1 | |
285 e = obj.e_l; | |
286 d = obj.d1_l; | |
287 tau = obj.tau_l{j}; | |
288 T = obj.T_l{j}; | |
289 end | |
290 | 311 |
291 E = obj.E; | 312 E = obj.E; |
292 Hi = obj.Hi; | 313 Hi = obj.Hi; |
293 H_gamma = obj.H_boundary{j}; | |
294 LAMBDA = obj.LAMBDA; | 314 LAMBDA = obj.LAMBDA; |
295 MU = obj.MU; | 315 MU = obj.MU; |
296 RHOi = obj.RHOi; | 316 RHOi = obj.RHOi; |
297 | 317 |
298 dim = obj.dim; | 318 dim = obj.dim; |
299 m_tot = obj.grid.N(); | 319 m_tot = obj.grid.N(); |
300 | 320 |
301 RHOi_kron = obj.RHOi_kron; | |
302 Hi_kron = obj.Hi_kron; | |
303 | |
304 % Preallocate | 321 % Preallocate |
305 closure = sparse(dim*m_tot, dim*m_tot); | 322 closure = sparse(dim*m_tot, dim*m_tot); |
306 penalty = cell(dim,1); | 323 penalty = sparse(dim*m_tot, m_tot/obj.m(j)); |
307 for k = 1:dim | 324 |
308 penalty{k} = sparse(dim*m_tot, m_tot/obj.m(j)); | 325 k = comp; |
309 end | 326 switch type |
310 | 327 |
311 % Loop over components that we (potentially) have different BC on | 328 % Dirichlet boundary condition |
312 for k = 1:dim | 329 case {'D','d','dirichlet','Dirichlet'} |
313 switch type{k} | 330 |
314 | 331 theta_R = obj.theta_R{j}; |
315 % Dirichlet boundary condition | 332 theta_H = obj.theta_H{j}; |
316 case {'D','d','dirichlet','Dirichlet'} | 333 theta_M = obj.theta_M{j}; |
317 | 334 |
318 tuning = 1.2; | 335 a_lambda = dim/theta_H + 1/theta_R; |
319 phi = obj.phi{j}; | 336 a_mu_i = 2/theta_M; |
320 h = obj.h(j); | 337 a_mu_ij = 2/theta_H + 1/theta_R; |
321 h11 = obj.H11{j}*h; | 338 |
322 gamma = obj.gamma{j}; | 339 d = @kroneckerDelta; % Kronecker delta |
323 | 340 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta |
324 a_lambda = dim/h11 + 1/(h11*phi); | 341 alpha = @(i,j) tuning*( d(i,j)* a_lambda*LAMBDA ... |
325 a_mu_i = 2/(gamma*h); | 342 + d(i,j)* a_mu_i*MU ... |
326 a_mu_ij = 2/h11 + 1/(h11*phi); | 343 + db(i,j)*a_mu_ij*MU ); |
327 | 344 |
328 d = @kroneckerDelta; % Kronecker delta | 345 % Loop over components that Dirichlet penalties end up on |
329 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta | 346 for i = 1:dim |
330 alpha = @(i,j) tuning*( d(i,j)* a_lambda*LAMBDA ... | 347 C = T{k,i}; |
331 + d(i,j)* a_mu_i*MU ... | 348 A = -d(i,k)*alpha(i,j); |
332 + db(i,j)*a_mu_ij*MU ); | 349 B = A + C; |
333 | 350 closure = closure + E{i}*RHOi*Hi*B'*e*H_gamma*(e'*E{k}' ); |
334 % Loop over components that Dirichlet penalties end up on | 351 penalty = penalty - E{i}*RHOi*Hi*B'*e*H_gamma; |
335 for i = 1:dim | 352 end |
336 C = T{k,i}; | 353 |
337 A = -d(i,k)*alpha(i,j); | 354 % Free boundary condition |
338 B = A + C; | 355 case {'F','f','Free','free','traction','Traction','t','T'} |
339 closure = closure + E{i}*RHOi*Hi*B'*e{j}*H_gamma*(e{j}'*E{k}' ); | 356 closure = closure - E{k}*RHOi*Hi*e*H_gamma* (e'*tau{k} ); |
340 penalty{k} = penalty{k} - E{i}*RHOi*Hi*B'*e{j}*H_gamma; | 357 penalty = penalty + E{k}*RHOi*Hi*e*H_gamma; |
341 end | 358 |
342 | 359 % Unknown boundary condition |
343 % Free boundary condition | 360 otherwise |
344 case {'F','f','Free','free','traction','Traction','t','T'} | 361 error('No such boundary condition: type = %s',type); |
345 closure = closure - E{k}*RHOi*Hi*e{j}*H_gamma* (e{j}'*tau{k} ); | |
346 penalty{k} = penalty{k} + E{k}*RHOi*Hi*e{j}*H_gamma; | |
347 | |
348 % Unknown boundary condition | |
349 otherwise | |
350 error('No such boundary condition: type = %s',type); | |
351 end | |
352 end | 362 end |
353 end | 363 end |
354 | 364 |
355 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary) | 365 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary) |
356 % u denotes the solution in the own domain | 366 % u denotes the solution in the own domain |
357 % v denotes the solution in the neighbour domain | 367 % v denotes the solution in the neighbour domain |
368 % Operators without subscripts are from the own domain. | |
358 tuning = 1.2; | 369 tuning = 1.2; |
359 % tuning = 20.2; | 370 |
360 error('Interface not implemented'); | 371 % j is the coordinate direction of the boundary |
372 j = obj.get_boundary_number(boundary); | |
373 j_v = neighbour_scheme.get_boundary_number(neighbour_boundary); | |
374 | |
375 % Get boundary operators | |
376 [e, T, tau, H_gamma] = obj.get_boundary_operator({'e','T','tau','H'}, boundary); | |
377 [e_v, tau_v] = neighbour_scheme.get_boundary_operator({'e','tau'}, neighbour_boundary); | |
378 | |
379 % Operators and quantities that correspond to the own domain only | |
380 Hi = obj.Hi; | |
381 RHOi = obj.RHOi; | |
382 dim = obj.dim; | |
383 | |
384 %--- Other operators ---- | |
385 m_tot_u = obj.grid.N(); | |
386 E = obj.E; | |
387 LAMBDA_u = obj.LAMBDA; | |
388 MU_u = obj.MU; | |
389 lambda_u = e'*LAMBDA_u*e; | |
390 mu_u = e'*MU_u*e; | |
391 | |
392 m_tot_v = neighbour_scheme.grid.N(); | |
393 E_v = neighbour_scheme.E; | |
394 LAMBDA_v = neighbour_scheme.LAMBDA; | |
395 MU_v = neighbour_scheme.MU; | |
396 lambda_v = e_v'*LAMBDA_v*e_v; | |
397 mu_v = e_v'*MU_v*e_v; | |
398 %------------------------- | |
399 | |
400 % Borrowing constants | |
401 theta_R_u = obj.theta_R{j}; | |
402 theta_H_u = obj.theta_H{j}; | |
403 theta_M_u = obj.theta_M{j}; | |
404 | |
405 theta_R_v = neighbour_scheme.theta_R{j_v}; | |
406 theta_H_v = neighbour_scheme.theta_H{j_v}; | |
407 theta_M_v = neighbour_scheme.theta_M{j_v}; | |
408 | |
409 function [alpha_ii, alpha_ij] = computeAlpha(th_R, th_H, th_M, lambda, mu) | |
410 alpha_ii = dim*lambda/(4*th_H) + lambda/(4*th_R) + mu/(2*th_M); | |
411 alpha_ij = mu/(2*th_H) + mu/(4*th_R); | |
412 end | |
413 | |
414 [alpha_ii_u, alpha_ij_u] = computeAlpha(theta_R_u, theta_H_u, theta_M_u, lambda_u, mu_u); | |
415 [alpha_ii_v, alpha_ij_v] = computeAlpha(theta_R_v, theta_H_v, theta_M_v, lambda_v, mu_v); | |
416 sigma_ii = tuning*(alpha_ii_u + alpha_ii_v); | |
417 sigma_ij = tuning*(alpha_ij_u + alpha_ij_v); | |
418 | |
419 d = @kroneckerDelta; % Kronecker delta | |
420 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta | |
421 sigma = @(i,j) tuning*(d(i,j)*sigma_ii + db(i,j)*sigma_ij); | |
422 | |
423 % Preallocate | |
424 closure = sparse(dim*m_tot_u, dim*m_tot_u); | |
425 penalty = sparse(dim*m_tot_u, dim*m_tot_v); | |
426 | |
427 % Loop over components that penalties end up on | |
428 for i = 1:dim | |
429 closure = closure - E{i}*RHOi*Hi*e*sigma(i,j)*H_gamma*e'*E{i}'; | |
430 penalty = penalty + E{i}*RHOi*Hi*e*sigma(i,j)*H_gamma*e_v'*E_v{i}'; | |
431 | |
432 closure = closure - 1/2*E{i}*RHOi*Hi*e*H_gamma*e'*tau{i}; | |
433 penalty = penalty - 1/2*E{i}*RHOi*Hi*e*H_gamma*e_v'*tau_v{i}; | |
434 | |
435 % Loop over components that we have interface conditions on | |
436 for k = 1:dim | |
437 closure = closure + 1/2*E{i}*RHOi*Hi*T{k,i}'*e*H_gamma*e'*E{k}'; | |
438 penalty = penalty - 1/2*E{i}*RHOi*Hi*T{k,i}'*e*H_gamma*e_v'*E_v{k}'; | |
439 end | |
440 end | |
361 end | 441 end |
362 | 442 |
363 % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. | 443 % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. |
364 function [j, nj] = get_boundary_number(obj, boundary) | 444 function [j, nj] = get_boundary_number(obj, boundary) |
365 | 445 |
378 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | 458 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} |
379 nj = 1; | 459 nj = 1; |
380 end | 460 end |
381 end | 461 end |
382 | 462 |
383 % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. | 463 % Returns the boundary operator op for the boundary specified by the string boundary. |
384 function [return_op] = get_boundary_operator(obj, op, boundary) | 464 % op: may be a cell array of strings |
465 function [varargout] = get_boundary_operator(obj, op, boundary) | |
385 | 466 |
386 switch boundary | 467 switch boundary |
387 case {'w','W','west','West', 'e', 'E', 'east', 'East'} | 468 case {'w','W','west','West', 'e', 'E', 'east', 'East'} |
388 j = 1; | 469 j = 1; |
389 case {'s','S','south','South', 'n', 'N', 'north', 'North'} | 470 case {'s','S','south','South', 'n', 'N', 'north', 'North'} |
390 j = 2; | 471 j = 2; |
391 otherwise | 472 otherwise |
392 error('No such boundary: boundary = %s',boundary); | 473 error('No such boundary: boundary = %s',boundary); |
393 end | 474 end |
394 | 475 |
395 switch op | 476 if ~iscell(op) |
396 case 'e' | 477 op = {op}; |
397 switch boundary | 478 end |
398 case {'w','W','west','West','s','S','south','South'} | 479 |
399 return_op = obj.e_l{j}; | 480 for i = 1:length(op) |
400 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | 481 switch op{i} |
401 return_op = obj.e_r{j}; | 482 case 'e' |
402 end | 483 switch boundary |
403 case 'd' | 484 case {'w','W','west','West','s','S','south','South'} |
404 switch boundary | 485 varargout{i} = obj.e_l{j}; |
405 case {'w','W','west','West','s','S','south','South'} | 486 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} |
406 return_op = obj.d1_l{j}; | 487 varargout{i} = obj.e_r{j}; |
407 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | 488 end |
408 return_op = obj.d1_r{j}; | 489 case 'd' |
409 end | 490 switch boundary |
410 otherwise | 491 case {'w','W','west','West','s','S','south','South'} |
411 error(['No such operator: operatr = ' op]); | 492 varargout{i} = obj.d1_l{j}; |
493 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | |
494 varargout{i} = obj.d1_r{j}; | |
495 end | |
496 case 'H' | |
497 varargout{i} = obj.H_boundary{j}; | |
498 case 'T' | |
499 switch boundary | |
500 case {'w','W','west','West','s','S','south','South'} | |
501 varargout{i} = obj.T_l{j}; | |
502 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | |
503 varargout{i} = obj.T_r{j}; | |
504 end | |
505 case 'tau' | |
506 switch boundary | |
507 case {'w','W','west','West','s','S','south','South'} | |
508 varargout{i} = obj.tau_l{j}; | |
509 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | |
510 varargout{i} = obj.tau_r{j}; | |
511 end | |
512 case 'alpha' | |
513 % alpha = alpha(i,j) is the penalty strength for displacement BC. | |
514 tuning = 1.2; | |
515 LAMBDA = obj.LAMBDA; | |
516 MU = obj.MU; | |
517 | |
518 phi = obj.phi{j}; | |
519 h = obj.h(j); | |
520 h11 = obj.H11{j}*h; | |
521 gamma = obj.gamma{j}; | |
522 dim = obj.dim; | |
523 | |
524 a_lambda = dim/h11 + 1/(h11*phi); | |
525 a_mu_i = 2/(gamma*h); | |
526 a_mu_ij = 2/h11 + 1/(h11*phi); | |
527 | |
528 d = @kroneckerDelta; % Kronecker delta | |
529 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta | |
530 alpha = @(i,k) d(i,k)*tuning*( d(i,j)* a_lambda*LAMBDA ... | |
531 + d(i,j)* a_mu_i*MU ... | |
532 + db(i,j)*a_mu_ij*MU ); | |
533 varargout{i} = alpha; | |
534 otherwise | |
535 error(['No such operator: operator = ' op{i}]); | |
536 end | |
412 end | 537 end |
413 | 538 |
414 end | 539 end |
415 | 540 |
416 function N = size(obj) | 541 function N = size(obj) |
417 N = prod(obj.m); | 542 N = obj.dim*prod(obj.m); |
418 end | 543 end |
419 end | 544 end |
420 end | 545 end |