Mercurial > repos > public > sbplib
comparison +scheme/Elastic2dCurvilinear.m @ 1052:cb4bfd0d81ea feature/getBoundaryOp
Elastic2dCurv: Rename get_boundary_op and add getBoundaryQuadrature
author | Martin Almquist <malmquist@stanford.edu> |
---|---|
date | Wed, 23 Jan 2019 16:57:50 -0800 |
parents | 1f6b2fb69225 |
children | 60c875c18de3 |
comparison
equal
deleted
inserted
replaced
1051:84200bbae101 | 1052:cb4bfd0d81ea |
---|---|
1 classdef Elastic2dCurvilinear < scheme.Scheme | 1 classdef Elastic2dCurvilinear < scheme.Scheme |
2 | 2 |
3 % Discretizes the elastic wave equation in curvilinear coordinates. | 3 % Discretizes the elastic wave equation in curvilinear coordinates. |
4 % | 4 % |
5 % Untransformed equation: | 5 % Untransformed equation: |
6 % rho u_{i,tt} = di lambda dj u_j + dj mu di u_j + dj mu dj u_i | 6 % rho u_{i,tt} = di lambda dj u_j + dj mu di u_j + dj mu dj u_i |
7 % | 7 % |
8 % Transformed equation: | 8 % Transformed equation: |
9 % J*rho u_{i,tt} = dk J b_ik lambda b_jl dl u_j | 9 % J*rho u_{i,tt} = dk J b_ik lambda b_jl dl u_j |
10 % + dk J b_jk mu b_il dl u_j | 10 % + dk J b_jk mu b_il dl u_j |
11 % + dk J b_jk mu b_jl dl u_i | 11 % + dk J b_jk mu b_jl dl u_i |
12 % opSet should be cell array of opSets, one per dimension. This | 12 % opSet should be cell array of opSets, one per dimension. This |
13 % is useful if we have periodic BC in one direction. | 13 % is useful if we have periodic BC in one direction. |
14 | 14 |
15 properties | 15 properties |
16 m % Number of points in each direction, possibly a vector | 16 m % Number of points in each direction, possibly a vector |
47 gamma % Borrowing constant for d1 from M | 47 gamma % Borrowing constant for d1 from M |
48 H11 % First element of H | 48 H11 % First element of H |
49 e_l, e_r | 49 e_l, e_r |
50 d1_l, d1_r % Normal derivatives at the boundary | 50 d1_l, d1_r % Normal derivatives at the boundary |
51 E % E{i}^T picks out component i | 51 E % E{i}^T picks out component i |
52 | 52 |
53 H_boundary_l, H_boundary_r % Boundary inner products | 53 H_boundary_l, H_boundary_r % Boundary inner products |
54 | 54 |
55 % Kroneckered norms and coefficients | 55 % Kroneckered norms and coefficients |
56 RHOi_kron | 56 RHOi_kron |
57 Ji_kron, J_kron | 57 Ji_kron, J_kron |
143 xmax = max(ops{1}.x); | 143 xmax = max(ops{1}.x); |
144 ymax = max(ops{2}.x); | 144 ymax = max(ops{2}.x); |
145 opSetMetric{1} = sbp.D2Variable(m(1), {0, xmax}, order); | 145 opSetMetric{1} = sbp.D2Variable(m(1), {0, xmax}, order); |
146 opSetMetric{2} = sbp.D2Variable(m(2), {0, ymax}, order); | 146 opSetMetric{2} = sbp.D2Variable(m(2), {0, ymax}, order); |
147 D1Metric{1} = kron(opSetMetric{1}.D1, I{2}); | 147 D1Metric{1} = kron(opSetMetric{1}.D1, I{2}); |
148 D1Metric{2} = kron(I{1}, opSetMetric{2}.D1); | 148 D1Metric{2} = kron(I{1}, opSetMetric{2}.D1); |
149 | 149 |
150 x_xi = D1Metric{1}*x; | 150 x_xi = D1Metric{1}*x; |
151 x_eta = D1Metric{2}*x; | 151 x_eta = D1Metric{2}*x; |
152 y_xi = D1Metric{1}*y; | 152 y_xi = D1Metric{1}*y; |
153 y_eta = D1Metric{2}*y; | 153 y_eta = D1Metric{2}*y; |
325 T_l{j}{i,k} = sparse(m_tot,m_tot); | 325 T_l{j}{i,k} = sparse(m_tot,m_tot); |
326 T_r{j}{i,k} = sparse(m_tot,m_tot); | 326 T_r{j}{i,k} = sparse(m_tot,m_tot); |
327 | 327 |
328 for m = 1:dim | 328 for m = 1:dim |
329 for l = 1:dim | 329 for l = 1:dim |
330 T_l{j}{i,k} = T_l{j}{i,k} + ... | 330 T_l{j}{i,k} = T_l{j}{i,k} + ... |
331 -d(k,l)* J*b{i,j}*b{k,m}*LAMBDA*(d(m,j)*e_l{m}*d1_l{m}' + db(m,j)*D1{m}) ... | 331 -d(k,l)* J*b{i,j}*b{k,m}*LAMBDA*(d(m,j)*e_l{m}*d1_l{m}' + db(m,j)*D1{m}) ... |
332 -d(k,l)* J*b{k,j}*b{i,m}*MU*(d(m,j)*e_l{m}*d1_l{m}' + db(m,j)*D1{m}) ... | 332 -d(k,l)* J*b{k,j}*b{i,m}*MU*(d(m,j)*e_l{m}*d1_l{m}' + db(m,j)*D1{m}) ... |
333 -d(i,k)* J*b{l,j}*b{l,m}*MU*(d(m,j)*e_l{m}*d1_l{m}' + db(m,j)*D1{m}); | 333 -d(i,k)* J*b{l,j}*b{l,m}*MU*(d(m,j)*e_l{m}*d1_l{m}' + db(m,j)*D1{m}); |
334 | 334 |
335 T_r{j}{i,k} = T_r{j}{i,k} + ... | 335 T_r{j}{i,k} = T_r{j}{i,k} + ... |
336 d(k,l)* J*b{i,j}*b{k,m}*LAMBDA*(d(m,j)*e_r{m}*d1_r{m}' + db(m,j)*D1{m}) + ... | 336 d(k,l)* J*b{i,j}*b{k,m}*LAMBDA*(d(m,j)*e_r{m}*d1_r{m}' + db(m,j)*D1{m}) + ... |
337 d(k,l)* J*b{k,j}*b{i,m}*MU*(d(m,j)*e_r{m}*d1_r{m}' + db(m,j)*D1{m}) + ... | 337 d(k,l)* J*b{k,j}*b{i,m}*MU*(d(m,j)*e_r{m}*d1_r{m}' + db(m,j)*D1{m}) + ... |
338 d(i,k)* J*b{l,j}*b{l,m}*MU*(d(m,j)*e_r{m}*d1_r{m}' + db(m,j)*D1{m}); | 338 d(i,k)* J*b{l,j}*b{l,m}*MU*(d(m,j)*e_r{m}*d1_r{m}' + db(m,j)*D1{m}); |
339 end | 339 end |
340 end | 340 end |
341 | 341 |
342 T_l{j}{i,k} = inv(beta{j})*T_l{j}{i,k}; | 342 T_l{j}{i,k} = inv(beta{j})*T_l{j}{i,k}; |
343 T_r{j}{i,k} = inv(beta{j})*T_r{j}{i,k}; | 343 T_r{j}{i,k} = inv(beta{j})*T_r{j}{i,k}; |
344 | 344 |
345 tau_l{j}{i} = tau_l{j}{i} + T_l{j}{i,k}*E{k}'; | 345 tau_l{j}{i} = tau_l{j}{i} + T_l{j}{i,k}*E{k}'; |
346 tau_r{j}{i} = tau_r{j}{i} + T_r{j}{i,k}*E{k}'; | 346 tau_r{j}{i} = tau_r{j}{i} + T_r{j}{i,k}*E{k}'; |
347 end | 347 end |
348 | 348 |
385 comp = bc{1}; | 385 comp = bc{1}; |
386 type = bc{2}; | 386 type = bc{2}; |
387 | 387 |
388 % j is the coordinate direction of the boundary | 388 % j is the coordinate direction of the boundary |
389 j = obj.get_boundary_number(boundary); | 389 j = obj.get_boundary_number(boundary); |
390 [e, T, tau, H_gamma] = obj.get_boundary_operator({'e','T','tau','H'}, boundary); | 390 [e, T, tau, H_gamma] = obj.getBoundaryOperator({'e','T','tau','H'}, boundary); |
391 | 391 |
392 E = obj.E; | 392 E = obj.E; |
393 Hi = obj.Hi; | 393 Hi = obj.Hi; |
394 LAMBDA = obj.LAMBDA; | 394 LAMBDA = obj.LAMBDA; |
395 MU = obj.MU; | 395 MU = obj.MU; |
421 | 421 |
422 d = @kroneckerDelta; % Kronecker delta | 422 d = @kroneckerDelta; % Kronecker delta |
423 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta | 423 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta |
424 alpha = @(i,j) tuning*( d(i,j)* a_lambda*LAMBDA ... | 424 alpha = @(i,j) tuning*( d(i,j)* a_lambda*LAMBDA ... |
425 + d(i,j)* a_mu_i*MU ... | 425 + d(i,j)* a_mu_i*MU ... |
426 + db(i,j)*a_mu_ij*MU ); | 426 + db(i,j)*a_mu_ij*MU ); |
427 | 427 |
428 % Loop over components that Dirichlet penalties end up on | 428 % Loop over components that Dirichlet penalties end up on |
429 for i = 1:dim | 429 for i = 1:dim |
430 C = T{k,i}; | 430 C = T{k,i}; |
431 A = -d(i,k)*alpha(i,j); | 431 A = -d(i,k)*alpha(i,j); |
432 B = A + C; | 432 B = A + C; |
433 closure = closure + E{i}*RHOi*Hi*Ji*B'*e*H_gamma*(e'*E{k}' ); | 433 closure = closure + E{i}*RHOi*Hi*Ji*B'*e*H_gamma*(e'*E{k}' ); |
434 penalty = penalty - E{i}*RHOi*Hi*Ji*B'*e*H_gamma; | 434 penalty = penalty - E{i}*RHOi*Hi*Ji*B'*e*H_gamma; |
435 end | 435 end |
436 | 436 |
437 % Free boundary condition | 437 % Free boundary condition |
438 case {'F','f','Free','free','traction','Traction','t','T'} | 438 case {'F','f','Free','free','traction','Traction','t','T'} |
439 closure = closure - E{k}*RHOi*Ji*Hi*e*H_gamma* (e'*tau{k} ); | 439 closure = closure - E{k}*RHOi*Ji*Hi*e*H_gamma* (e'*tau{k} ); |
440 penalty = penalty + E{k}*RHOi*Ji*Hi*e*H_gamma; | 440 penalty = penalty + E{k}*RHOi*Ji*Hi*e*H_gamma; |
441 | 441 |
442 % Unknown boundary condition | 442 % Unknown boundary condition |
443 otherwise | 443 otherwise |
444 error('No such boundary condition: type = %s',type); | 444 error('No such boundary condition: type = %s',type); |
455 % j is the coordinate direction of the boundary | 455 % j is the coordinate direction of the boundary |
456 j = obj.get_boundary_number(boundary); | 456 j = obj.get_boundary_number(boundary); |
457 j_v = neighbour_scheme.get_boundary_number(neighbour_boundary); | 457 j_v = neighbour_scheme.get_boundary_number(neighbour_boundary); |
458 | 458 |
459 % Get boundary operators | 459 % Get boundary operators |
460 [e, T, tau, H_gamma] = obj.get_boundary_operator({'e','T','tau','H'}, boundary); | 460 [e, T, tau, H_gamma] = obj.getBoundaryOperator({'e','T','tau','H'}, boundary); |
461 [e_v, tau_v] = neighbour_scheme.get_boundary_operator({'e','tau'}, neighbour_boundary); | 461 [e_v, tau_v] = neighbour_scheme.getBoundaryOperator({'e','tau'}, neighbour_boundary); |
462 | 462 |
463 % Operators and quantities that correspond to the own domain only | 463 % Operators and quantities that correspond to the own domain only |
464 Hi = obj.Hi; | 464 Hi = obj.Hi; |
465 RHOi = obj.RHOi; | 465 RHOi = obj.RHOi; |
466 dim = obj.dim; | 466 dim = obj.dim; |
467 | 467 |
468 %--- Other operators ---- | 468 %--- Other operators ---- |
469 m_tot_u = obj.grid.N(); | 469 m_tot_u = obj.grid.N(); |
470 E = obj.E; | 470 E = obj.E; |
471 LAMBDA_u = obj.LAMBDA; | 471 LAMBDA_u = obj.LAMBDA; |
472 MU_u = obj.MU; | 472 MU_u = obj.MU; |
478 LAMBDA_v = neighbour_scheme.LAMBDA; | 478 LAMBDA_v = neighbour_scheme.LAMBDA; |
479 MU_v = neighbour_scheme.MU; | 479 MU_v = neighbour_scheme.MU; |
480 lambda_v = e_v'*LAMBDA_v*e_v; | 480 lambda_v = e_v'*LAMBDA_v*e_v; |
481 mu_v = e_v'*MU_v*e_v; | 481 mu_v = e_v'*MU_v*e_v; |
482 %------------------------- | 482 %------------------------- |
483 | 483 |
484 % Borrowing constants | 484 % Borrowing constants |
485 phi_u = obj.phi{j}; | 485 phi_u = obj.phi{j}; |
486 h_u = obj.h(j); | 486 h_u = obj.h(j); |
487 h11_u = obj.H11{j}*h_u; | 487 h11_u = obj.H11{j}*h_u; |
488 gamma_u = obj.gamma{j}; | 488 gamma_u = obj.gamma{j}; |
491 h_v = neighbour_scheme.h(j_v); | 491 h_v = neighbour_scheme.h(j_v); |
492 h11_v = neighbour_scheme.H11{j_v}*h_v; | 492 h11_v = neighbour_scheme.H11{j_v}*h_v; |
493 gamma_v = neighbour_scheme.gamma{j_v}; | 493 gamma_v = neighbour_scheme.gamma{j_v}; |
494 | 494 |
495 % E > sum_i 1/(2*alpha_ij)*(tau_i)^2 | 495 % E > sum_i 1/(2*alpha_ij)*(tau_i)^2 |
496 function [alpha_ii, alpha_ij] = computeAlpha(phi,h,h11,gamma,lambda,mu) | 496 function [alpha_ii, alpha_ij] = computeAlpha(phi,h,h11,gamma,lambda,mu) |
497 th1 = h11/(2*dim); | 497 th1 = h11/(2*dim); |
498 th2 = h11*phi/2; | 498 th2 = h11*phi/2; |
499 th3 = h*gamma; | 499 th3 = h*gamma; |
500 a1 = ( (th1 + th2)*th3*lambda + 4*th1*th2*mu ) / (2*th1*th2*th3); | 500 a1 = ( (th1 + th2)*th3*lambda + 4*th1*th2*mu ) / (2*th1*th2*th3); |
501 a2 = ( 16*(th1 + th2)*lambda*mu ) / (th1*th2*th3); | 501 a2 = ( 16*(th1 + th2)*lambda*mu ) / (th1*th2*th3); |
503 | 503 |
504 alpha_ij = mu*(2/h11 + 1/(phi*h11)); | 504 alpha_ij = mu*(2/h11 + 1/(phi*h11)); |
505 end | 505 end |
506 | 506 |
507 [alpha_ii_u, alpha_ij_u] = computeAlpha(phi_u,h_u,h11_u,gamma_u,lambda_u,mu_u); | 507 [alpha_ii_u, alpha_ij_u] = computeAlpha(phi_u,h_u,h11_u,gamma_u,lambda_u,mu_u); |
508 [alpha_ii_v, alpha_ij_v] = computeAlpha(phi_v,h_v,h11_v,gamma_v,lambda_v,mu_v); | 508 [alpha_ii_v, alpha_ij_v] = computeAlpha(phi_v,h_v,h11_v,gamma_v,lambda_v,mu_v); |
509 sigma_ii = tuning*(alpha_ii_u + alpha_ii_v)/4; | 509 sigma_ii = tuning*(alpha_ii_u + alpha_ii_v)/4; |
510 sigma_ij = tuning*(alpha_ij_u + alpha_ij_v)/4; | 510 sigma_ij = tuning*(alpha_ij_u + alpha_ij_v)/4; |
511 | 511 |
512 d = @kroneckerDelta; % Kronecker delta | 512 d = @kroneckerDelta; % Kronecker delta |
513 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta | 513 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta |
525 closure = closure - 1/2*E{i}*RHOi*Hi*e*H_gamma*e'*tau{i}; | 525 closure = closure - 1/2*E{i}*RHOi*Hi*e*H_gamma*e'*tau{i}; |
526 penalty = penalty - 1/2*E{i}*RHOi*Hi*e*H_gamma*e_v'*tau_v{i}; | 526 penalty = penalty - 1/2*E{i}*RHOi*Hi*e*H_gamma*e_v'*tau_v{i}; |
527 | 527 |
528 % Loop over components that we have interface conditions on | 528 % Loop over components that we have interface conditions on |
529 for k = 1:dim | 529 for k = 1:dim |
530 closure = closure + 1/2*E{i}*RHOi*Hi*T{k,i}'*e*H_gamma*e'*E{k}'; | 530 closure = closure + 1/2*E{i}*RHOi*Hi*T{k,i}'*e*H_gamma*e'*E{k}'; |
531 penalty = penalty - 1/2*E{i}*RHOi*Hi*T{k,i}'*e*H_gamma*e_v'*E_v{k}'; | 531 penalty = penalty - 1/2*E{i}*RHOi*Hi*T{k,i}'*e*H_gamma*e_v'*E_v{k}'; |
532 end | 532 end |
533 end | 533 end |
534 end | 534 end |
535 | 535 |
536 % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. | 536 % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. |
537 function [j, nj] = get_boundary_number(obj, boundary) | 537 function [j, nj] = get_boundary_number(obj, boundary) |
553 end | 553 end |
554 end | 554 end |
555 | 555 |
556 % Returns the boundary operator op for the boundary specified by the string boundary. | 556 % Returns the boundary operator op for the boundary specified by the string boundary. |
557 % op: may be a cell array of strings | 557 % op: may be a cell array of strings |
558 function [varargout] = get_boundary_operator(obj, op, boundary) | 558 function [varargout] = getBoundaryOperator(obj, op, boundary) |
559 | 559 |
560 switch boundary | 560 switch boundary |
561 case {'w','W','west','West', 'e', 'E', 'east', 'East'} | 561 case {'w','W','west','West', 'e', 'E', 'east', 'East'} |
562 j = 1; | 562 j = 1; |
563 case {'s','S','south','South', 'n', 'N', 'north', 'North'} | 563 case {'s','S','south','South', 'n', 'N', 'north', 'North'} |
585 varargout{i} = obj.d1_l{j}; | 585 varargout{i} = obj.d1_l{j}; |
586 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | 586 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} |
587 varargout{i} = obj.d1_r{j}; | 587 varargout{i} = obj.d1_r{j}; |
588 end | 588 end |
589 case 'H' | 589 case 'H' |
590 switch boundary | 590 switch boundary |
591 case {'w','W','west','West','s','S','south','South'} | 591 case {'w','W','west','West','s','S','south','South'} |
592 varargout{i} = obj.H_boundary_l{j}; | 592 varargout{i} = obj.H_boundary_l{j}; |
593 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | 593 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} |
594 varargout{i} = obj.H_boundary_r{j}; | 594 varargout{i} = obj.H_boundary_r{j}; |
595 end | 595 end |
604 switch boundary | 604 switch boundary |
605 case {'w','W','west','West','s','S','south','South'} | 605 case {'w','W','west','West','s','S','south','South'} |
606 varargout{i} = obj.tau_l{j}; | 606 varargout{i} = obj.tau_l{j}; |
607 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | 607 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} |
608 varargout{i} = obj.tau_r{j}; | 608 varargout{i} = obj.tau_r{j}; |
609 end | 609 end |
610 otherwise | 610 otherwise |
611 error(['No such operator: operator = ' op{i}]); | 611 error(['No such operator: operator = ' op{i}]); |
612 end | 612 end |
613 end | 613 end |
614 | 614 |
615 end | |
616 | |
617 % Returns square boundary quadrature matrix, of dimension | |
618 % corresponding to the number of boundary points | |
619 % | |
620 % boundary -- string | |
621 function H = getBoundaryQuadrature(obj, boundary) | |
622 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
623 | |
624 switch boundary | |
625 case {'w'} | |
626 H = H_boundary_l{1}; | |
627 case 'e' | |
628 H = H_boundary_r{1}; | |
629 case 's' | |
630 H = H_boundary_l{2}; | |
631 case 'n' | |
632 H = H_boundary_r{2}; | |
633 end | |
634 I_dim = speye(obj.dim, obj.dim); | |
635 H = kron(H, I_dim); | |
615 end | 636 end |
616 | 637 |
617 function N = size(obj) | 638 function N = size(obj) |
618 N = obj.dim*prod(obj.m); | 639 N = obj.dim*prod(obj.m); |
619 end | 640 end |