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