Mercurial > repos > public > sbplib
comparison +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 |
comparison
equal
deleted
inserted
replaced
942:35701c85e356 | 943:21394c78c72e |
---|---|
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 % Inner products |
34 | |
34 phi % Borrowing constant for (d1 - e^T*D1) from R | 35 phi % Borrowing constant for (d1 - e^T*D1) from R |
35 gamma % Borrowing constant for d1 from M | 36 gamma % Borrowing constant for d1 from M |
36 H11 % First element of H | 37 H11 % First element of H |
38 | |
39 % Borrowing from H, M, and R | |
40 thH | |
41 thM | |
42 thR | |
43 | |
37 e_l, e_r | 44 e_l, e_r |
38 d1_l, d1_r % Normal derivatives at the boundary | 45 d1_l, d1_r % Normal derivatives at the boundary |
39 E % E{i}^T picks out component i | 46 E % E{i}^T picks out component i |
40 | 47 |
41 H_boundary % Boundary inner products | 48 H_boundary % Boundary inner products |
62 m = g.size(); | 69 m = g.size(); |
63 m_tot = g.N(); | 70 m_tot = g.N(); |
64 | 71 |
65 h = g.scaling(); | 72 h = g.scaling(); |
66 lim = g.lim; | 73 lim = g.lim; |
74 if isempty(lim) | |
75 x = g.x; | |
76 lim = cell(length(x),1); | |
77 for i = 1:length(x) | |
78 lim{i} = {min(x{i}), max(x{i})}; | |
79 end | |
80 end | |
67 | 81 |
68 % 1D operators | 82 % 1D operators |
69 ops = cell(dim,1); | 83 ops = cell(dim,1); |
70 for i = 1:dim | 84 for i = 1:dim |
71 ops{i} = opSet{i}(m(i), lim{i}, order); | 85 ops{i} = opSet{i}(m(i), lim{i}, order); |
75 for i = 1:dim | 89 for i = 1:dim |
76 beta = ops{i}.borrowing.R.delta_D; | 90 beta = ops{i}.borrowing.R.delta_D; |
77 obj.H11{i} = ops{i}.borrowing.H11; | 91 obj.H11{i} = ops{i}.borrowing.H11; |
78 obj.phi{i} = beta/obj.H11{i}; | 92 obj.phi{i} = beta/obj.H11{i}; |
79 obj.gamma{i} = ops{i}.borrowing.M.d1; | 93 obj.gamma{i} = ops{i}.borrowing.M.d1; |
94 | |
95 % Better names | |
96 obj.thR{i} = ops{i}.borrowing.R.delta_D; | |
97 obj.thM{i} = ops{i}.borrowing.M.d1; | |
98 obj.thH{i} = ops{i}.borrowing.H11; | |
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); |
260 | 279 |
261 | 280 |
262 % Closure functions return the operators applied to the own domain to close the boundary | 281 % 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. | 282 % 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'. | 283 % 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. | 284 % bc is a cell array of component and bc type, e.g. {1, 'd'} for Dirichlet condition |
285 % on the first component. | |
266 % data is a function returning the data that should be applied at the boundary. | 286 % 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. | 287 % neighbour_scheme is an instance of Scheme that should be interfaced to. |
268 % neighbour_boundary is a string specifying which boundary to interface to. | 288 % neighbour_boundary is a string specifying which boundary to interface to. |
269 function [closure, penalty] = boundary_condition(obj, boundary, type, parameter) | 289 function [closure, penalty] = boundary_condition(obj, boundary, bc, tuning) |
270 default_arg('type',{'free','free'}); | 290 default_arg('tuning', 1.2); |
271 default_arg('parameter', []); | 291 |
292 assert( iscell(bc), 'The BC type must be a 2x1 cell array' ); | |
293 comp = bc{1}; | |
294 type = bc{2}; | |
272 | 295 |
273 % j is the coordinate direction of the boundary | 296 % j is the coordinate direction of the boundary |
274 % nj: outward unit normal component. | 297 j = obj.get_boundary_number(boundary); |
275 % nj = -1 for west, south, bottom boundaries | 298 [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 | 299 |
291 E = obj.E; | 300 E = obj.E; |
292 Hi = obj.Hi; | 301 Hi = obj.Hi; |
293 H_gamma = obj.H_boundary{j}; | |
294 LAMBDA = obj.LAMBDA; | 302 LAMBDA = obj.LAMBDA; |
295 MU = obj.MU; | 303 MU = obj.MU; |
296 RHOi = obj.RHOi; | 304 RHOi = obj.RHOi; |
297 | 305 |
298 dim = obj.dim; | 306 dim = obj.dim; |
299 m_tot = obj.grid.N(); | 307 m_tot = obj.grid.N(); |
300 | 308 |
301 RHOi_kron = obj.RHOi_kron; | |
302 Hi_kron = obj.Hi_kron; | |
303 | |
304 % Preallocate | 309 % Preallocate |
305 closure = sparse(dim*m_tot, dim*m_tot); | 310 closure = sparse(dim*m_tot, dim*m_tot); |
306 penalty = cell(dim,1); | 311 penalty = sparse(dim*m_tot, m_tot/obj.m(j)); |
307 for k = 1:dim | 312 |
308 penalty{k} = sparse(dim*m_tot, m_tot/obj.m(j)); | 313 k = comp; |
309 end | 314 switch type |
310 | 315 |
311 % Loop over components that we (potentially) have different BC on | 316 % Dirichlet boundary condition |
312 for k = 1:dim | 317 case {'D','d','dirichlet','Dirichlet'} |
313 switch type{k} | 318 |
314 | 319 phi = obj.phi{j}; |
315 % Dirichlet boundary condition | 320 h = obj.h(j); |
316 case {'D','d','dirichlet','Dirichlet'} | 321 h11 = obj.H11{j}*h; |
317 | 322 gamma = obj.gamma{j}; |
318 tuning = 1.2; | 323 |
319 phi = obj.phi{j}; | 324 a_lambda = dim/h11 + 1/(h11*phi); |
320 h = obj.h(j); | 325 a_mu_i = 2/(gamma*h); |
321 h11 = obj.H11{j}*h; | 326 a_mu_ij = 2/h11 + 1/(h11*phi); |
322 gamma = obj.gamma{j}; | 327 |
323 | 328 d = @kroneckerDelta; % Kronecker delta |
324 a_lambda = dim/h11 + 1/(h11*phi); | 329 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta |
325 a_mu_i = 2/(gamma*h); | 330 alpha = @(i,j) tuning*( d(i,j)* a_lambda*LAMBDA ... |
326 a_mu_ij = 2/h11 + 1/(h11*phi); | 331 + d(i,j)* a_mu_i*MU ... |
327 | 332 + db(i,j)*a_mu_ij*MU ); |
328 d = @kroneckerDelta; % Kronecker delta | 333 |
329 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta | 334 % Loop over components that Dirichlet penalties end up on |
330 alpha = @(i,j) tuning*( d(i,j)* a_lambda*LAMBDA ... | 335 for i = 1:dim |
331 + d(i,j)* a_mu_i*MU ... | 336 C = T{k,i}; |
332 + db(i,j)*a_mu_ij*MU ); | 337 A = -d(i,k)*alpha(i,j); |
333 | 338 B = A + C; |
334 % Loop over components that Dirichlet penalties end up on | 339 closure = closure + E{i}*RHOi*Hi*B'*e*H_gamma*(e'*E{k}' ); |
335 for i = 1:dim | 340 penalty = penalty - E{i}*RHOi*Hi*B'*e*H_gamma; |
336 C = T{k,i}; | |
337 A = -d(i,k)*alpha(i,j); | |
338 B = A + C; | |
339 closure = closure + E{i}*RHOi*Hi*B'*e{j}*H_gamma*(e{j}'*E{k}' ); | |
340 penalty{k} = penalty{k} - E{i}*RHOi*Hi*B'*e{j}*H_gamma; | |
341 end | |
342 | |
343 % Free boundary condition | |
344 case {'F','f','Free','free','traction','Traction','t','T'} | |
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 | 341 end |
342 | |
343 % Free boundary condition | |
344 case {'F','f','Free','free','traction','Traction','t','T'} | |
345 closure = closure - E{k}*RHOi*Hi*e*H_gamma* (e'*tau{k} ); | |
346 penalty = penalty + E{k}*RHOi*Hi*e*H_gamma; | |
347 | |
348 % Unknown boundary condition | |
349 otherwise | |
350 error('No such boundary condition: type = %s',type); | |
352 end | 351 end |
353 end | 352 end |
354 | 353 |
355 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary,opts) | 354 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary) |
356 % u denotes the solution in the own domain | 355 % u denotes the solution in the own domain |
357 % v denotes the solution in the neighbour domain | 356 % v denotes the solution in the neighbour domain |
357 % Operators without subscripts are from the own domain. | |
358 tuning = 1.2; | 358 tuning = 1.2; |
359 % tuning = 20.2; | 359 |
360 error('Interface not implemented'); | 360 % j is the coordinate direction of the boundary |
361 j = obj.get_boundary_number(boundary); | |
362 j_v = neighbour_scheme.get_boundary_number(neighbour_boundary); | |
363 | |
364 % Get boundary operators | |
365 [e, T, tau, H_gamma] = obj.get_boundary_operator({'e','T','tau','H'}, boundary); | |
366 [e_v, tau_v] = neighbour_scheme.get_boundary_operator({'e','tau'}, neighbour_boundary); | |
367 | |
368 % Operators and quantities that correspond to the own domain only | |
369 Hi = obj.Hi; | |
370 RHOi = obj.RHOi; | |
371 dim = obj.dim; | |
372 | |
373 %--- Other operators ---- | |
374 m_tot_u = obj.grid.N(); | |
375 E = obj.E; | |
376 LAMBDA_u = obj.LAMBDA; | |
377 MU_u = obj.MU; | |
378 lambda_u = e'*LAMBDA_u*e; | |
379 mu_u = e'*MU_u*e; | |
380 | |
381 m_tot_v = neighbour_scheme.grid.N(); | |
382 E_v = neighbour_scheme.E; | |
383 LAMBDA_v = neighbour_scheme.LAMBDA; | |
384 MU_v = neighbour_scheme.MU; | |
385 lambda_v = e_v'*LAMBDA_v*e_v; | |
386 mu_v = e_v'*MU_v*e_v; | |
387 %------------------------- | |
388 | |
389 % Borrowing constants | |
390 h_u = obj.h(j); | |
391 thR_u = obj.thR{j}*h_u; | |
392 thM_u = obj.thM{j}*h_u; | |
393 thH_u = obj.thH{j}*h_u; | |
394 | |
395 h_v = neighbour_scheme.h(j_v); | |
396 thR_v = neighbour_scheme.thR{j_v}*h_v; | |
397 thH_v = neighbour_scheme.thH{j_v}*h_v; | |
398 thM_v = neighbour_scheme.thM{j_v}*h_v; | |
399 | |
400 % alpha = penalty strength for normal component, beta for tangential | |
401 alpha_u = dim*lambda_u/(4*thH_u) + lambda_u/(4*thR_u) + mu_u/(2*thM_u); | |
402 alpha_v = dim*lambda_v/(4*thH_v) + lambda_v/(4*thR_v) + mu_v/(2*thM_v); | |
403 beta_u = mu_u/(2*thH_u) + mu_u/(4*thR_u); | |
404 beta_v = mu_v/(2*thH_v) + mu_v/(4*thR_v); | |
405 alpha = alpha_u + alpha_v; | |
406 beta = beta_u + beta_v; | |
407 | |
408 d = @kroneckerDelta; % Kronecker delta | |
409 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta | |
410 strength = @(i,j) tuning*(d(i,j)*alpha + db(i,j)*beta); | |
411 | |
412 % Preallocate | |
413 closure = sparse(dim*m_tot_u, dim*m_tot_u); | |
414 penalty = sparse(dim*m_tot_u, dim*m_tot_v); | |
415 | |
416 % Loop over components that penalties end up on | |
417 for i = 1:dim | |
418 closure = closure - E{i}*RHOi*Hi*e*strength(i,j)*H_gamma*e'*E{i}'; | |
419 penalty = penalty + E{i}*RHOi*Hi*e*strength(i,j)*H_gamma*e_v'*E_v{i}'; | |
420 | |
421 closure = closure - 1/2*E{i}*RHOi*Hi*e*H_gamma*e'*tau{i}; | |
422 penalty = penalty - 1/2*E{i}*RHOi*Hi*e*H_gamma*e_v'*tau_v{i}; | |
423 | |
424 % Loop over components that we have interface conditions on | |
425 for k = 1:dim | |
426 closure = closure + 1/2*E{i}*RHOi*Hi*T{k,i}'*e*H_gamma*e'*E{k}'; | |
427 penalty = penalty - 1/2*E{i}*RHOi*Hi*T{k,i}'*e*H_gamma*e_v'*E_v{k}'; | |
428 end | |
429 end | |
361 end | 430 end |
362 | 431 |
363 % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. | 432 % 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) | 433 function [j, nj] = get_boundary_number(obj, boundary) |
365 | 434 |
378 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | 447 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} |
379 nj = 1; | 448 nj = 1; |
380 end | 449 end |
381 end | 450 end |
382 | 451 |
383 % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. | 452 % Returns the boundary operator op for the boundary specified by the string boundary. |
384 function [return_op] = get_boundary_operator(obj, op, boundary) | 453 % op: may be a cell array of strings |
454 function [varargout] = get_boundary_operator(obj, op, boundary) | |
385 | 455 |
386 switch boundary | 456 switch boundary |
387 case {'w','W','west','West', 'e', 'E', 'east', 'East'} | 457 case {'w','W','west','West', 'e', 'E', 'east', 'East'} |
388 j = 1; | 458 j = 1; |
389 case {'s','S','south','South', 'n', 'N', 'north', 'North'} | 459 case {'s','S','south','South', 'n', 'N', 'north', 'North'} |
390 j = 2; | 460 j = 2; |
391 otherwise | 461 otherwise |
392 error('No such boundary: boundary = %s',boundary); | 462 error('No such boundary: boundary = %s',boundary); |
393 end | 463 end |
394 | 464 |
395 switch op | 465 if ~iscell(op) |
396 case 'e' | 466 op = {op}; |
397 switch boundary | 467 end |
398 case {'w','W','west','West','s','S','south','South'} | 468 |
399 return_op = obj.e_l{j}; | 469 for i = 1:length(op) |
400 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | 470 switch op{i} |
401 return_op = obj.e_r{j}; | 471 case 'e' |
402 end | 472 switch boundary |
403 case 'd' | 473 case {'w','W','west','West','s','S','south','South'} |
404 switch boundary | 474 varargout{i} = obj.e_l{j}; |
405 case {'w','W','west','West','s','S','south','South'} | 475 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} |
406 return_op = obj.d1_l{j}; | 476 varargout{i} = obj.e_r{j}; |
407 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | 477 end |
408 return_op = obj.d1_r{j}; | 478 case 'd' |
409 end | 479 switch boundary |
410 otherwise | 480 case {'w','W','west','West','s','S','south','South'} |
411 error(['No such operator: operatr = ' op]); | 481 varargout{i} = obj.d1_l{j}; |
482 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | |
483 varargout{i} = obj.d1_r{j}; | |
484 end | |
485 case 'H' | |
486 varargout{i} = obj.H_boundary{j}; | |
487 case 'T' | |
488 switch boundary | |
489 case {'w','W','west','West','s','S','south','South'} | |
490 varargout{i} = obj.T_l{j}; | |
491 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | |
492 varargout{i} = obj.T_r{j}; | |
493 end | |
494 case 'tau' | |
495 switch boundary | |
496 case {'w','W','west','West','s','S','south','South'} | |
497 varargout{i} = obj.tau_l{j}; | |
498 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | |
499 varargout{i} = obj.tau_r{j}; | |
500 end | |
501 otherwise | |
502 error(['No such operator: operator = ' op{i}]); | |
503 end | |
412 end | 504 end |
413 | 505 |
414 end | 506 end |
415 | 507 |
416 function N = size(obj) | 508 function N = size(obj) |
417 N = prod(obj.m); | 509 N = obj.dim*prod(obj.m); |
418 end | 510 end |
419 end | 511 end |
420 end | 512 end |