comparison +scheme/Elastic2dVariableAnisotropicIncompatible.m @ 1346:464e6f65c2c6 feature/poroelastic

Refactor computation of borrowing from C. Update to correct number of boundary points for borrowing from R.
author Martin Almquist <martin.almquist@it.uu.se>
date Tue, 30 Apr 2024 14:18:47 +0200
parents 14f44e81e1e3
children ac54767ae1fb
comparison
equal deleted inserted replaced
1345:14f44e81e1e3 1346:464e6f65c2c6
48 48
49 % Borrowing constants of the form gamma*h, where gamma is a dimensionless constant. 49 % Borrowing constants of the form gamma*h, where gamma is a dimensionless constant.
50 h11 % First entry in norm matrix 50 h11 % First entry in norm matrix
51 theta_R % Borrowing from R 51 theta_R % Borrowing from R
52 52
53 nBP % Number of boundary points, related to borrowing. 53 nBP_R % Number of boundary points in R, related to borrowing from R.
54 e_shifted_scalar_w, e_shifted_scalar_e, e_shifted_scalar_s, e_shifted_scalar_n; % Act on scalar field, return scalar field 54 e_shifted_scalar_w, e_shifted_scalar_e, e_shifted_scalar_s, e_shifted_scalar_n; % Act on scalar field, return scalar field
55 55
56 end 56 end
57 57
58 methods 58 methods
122 122
123 switch order 123 switch order
124 case 2 124 case 2
125 width = 3; 125 width = 3;
126 nBP = 2; 126 nBP = 2;
127 nBP_R = 2;
127 case 4 128 case 4
128 width = 5; 129 width = 5;
129 nBP = 6; 130 nBP = 6;
131 nBP_R = 4;
130 case 6 132 case 6
131 width = 7; 133 width = 7;
132 nBP = 9; 134 nBP = 9;
135 nBP_R = 7;
133 end 136 end
134 137
135 I = cell(dim,1); 138 I = cell(dim,1);
136 D1 = cell(dim,1); 139 D1 = cell(dim,1);
137 D2 = cell(dim,1); 140 D2 = cell(dim,1);
185 e_e = kron(e_scalar_e, I_dim); 188 e_e = kron(e_scalar_e, I_dim);
186 e_s = kron(e_scalar_s, I_dim); 189 e_s = kron(e_scalar_s, I_dim);
187 e_n = kron(e_scalar_n, I_dim); 190 e_n = kron(e_scalar_n, I_dim);
188 191
189 % Boundary restriction, shifted up to nBP-1 points 192 % Boundary restriction, shifted up to nBP-1 points
190 e_shifted_scalar_w = cell(nBP, 1); 193 e_shifted_scalar_w = cell(nBP_R, 1);
191 e_shifted_scalar_e = cell(nBP, 1); 194 e_shifted_scalar_e = cell(nBP_R, 1);
192 e_shifted_scalar_s = cell(nBP, 1); 195 e_shifted_scalar_s = cell(nBP_R, 1);
193 e_shifted_scalar_n = cell(nBP, 1); 196 e_shifted_scalar_n = cell(nBP_R, 1);
194 for i = 1:nBP-1 197 for i = 1:nBP_R-1
195 e_0_nBP = {0*e_0{1}, 0*e_0{2}}; 198 e_0_nBP = {0*e_0{1}, 0*e_0{2}};
196 e_m_nBP = {0*e_m{1}, 0*e_m{2}}; 199 e_m_nBP = {0*e_m{1}, 0*e_m{2}};
197 e_0_nBP{1}(i) = 1; 200 e_0_nBP{1}(i) = 1;
198 e_0_nBP{2}(i) = 1; 201 e_0_nBP{2}(i) = 1;
199 e_m_nBP{1}(end+1-i) = 1; 202 e_m_nBP{1}(end+1-i) = 1;
405 obj.m = m; 408 obj.m = m;
406 obj.h = h; 409 obj.h = h;
407 obj.order = order; 410 obj.order = order;
408 obj.grid = g; 411 obj.grid = g;
409 obj.dim = dim; 412 obj.dim = dim;
410 obj.nBP = nBP; 413 obj.nBP_R = nBP_R;
411 414
412 end 415 end
413 416
414 417
415 % Closure functions return the operators applied to the own domain to close the boundary 418 % Closure functions return the operators applied to the own domain to close the boundary
427 % bc = {comp, 'd', dComps}, 430 % bc = {comp, 'd', dComps},
428 % where 431 % where
429 % dComps = vector of components with displacement BC. Default: 1:dim. 432 % dComps = vector of components with displacement BC. Default: 1:dim.
430 % In this way, we can specify one BC at a time even though the SATs depend on all BC. 433 % In this way, we can specify one BC at a time even though the SATs depend on all BC.
431 function [closure, penalty] = boundary_condition(obj, boundary, bc, tuning) 434 function [closure, penalty] = boundary_condition(obj, boundary, bc, tuning)
432 default_arg('tuning', 1.0); 435 default_arg('tuning', 1.2);
433 436
434 assert( iscell(bc), 'The BC type must be a 2x1 or 3x1 cell array' ); 437 assert( iscell(bc), 'The BC type must be a 2x1 or 3x1 cell array' );
435 comp = bc{1}; 438 comp = bc{1};
436 type = bc{2}; 439 type = bc{2};
437 if ischar(comp) 440 if ischar(comp)
438 comp = obj.getComponent(comp, boundary); 441 comp = obj.getComponent(comp, boundary);
439 end 442 end
440 443
441 e = obj.getBoundaryOperatorForScalarField('e', boundary); 444 e = obj.getBoundaryOperatorForScalarField('e', boundary);
442 e_sh = obj.getBoundaryOperatorForScalarField('e_shifted', boundary);
443 tau = obj.getBoundaryOperator(['tau' num2str(comp)], boundary); 445 tau = obj.getBoundaryOperator(['tau' num2str(comp)], boundary);
444 T = obj.getBoundaryTractionOperator(boundary); 446 T = obj.getBoundaryTractionOperator(boundary);
445 [h11, th_R] = obj.getBorrowing(boundary); 447 [h11, th_R] = obj.getBorrowing(boundary);
446 H_gamma = obj.getBoundaryQuadratureForScalarField(boundary); 448 H_gamma = obj.getBoundaryQuadratureForScalarField(boundary);
447 nu = obj.getNormal(boundary); 449 nu = obj.getNormal(boundary);
485 penalty = penalty - E{i}*RHOi*Hi*X'*e*H_gamma; 487 penalty = penalty - E{i}*RHOi*Hi*X'*e*H_gamma;
486 end 488 end
487 489
488 % Symmetric part only required on components with displacement BC. 490 % Symmetric part only required on components with displacement BC.
489 % (Otherwise it's not symmetric.) 491 % (Otherwise it's not symmetric.)
490 492 beta_vec = obj.computeBorrowingFromC(boundary);
491 % 1. Compute beta such that C_bJbL_boundary - \beta*C_bJbL_i >= 0, i = 0, 1, ..., nBP.
492 [~, N] = size(e);
493 beta_vec = ones(N, 1);
494 b = obj.getComponent('normal', boundary);
495 C_boundary = cell(dim, dim, dim, dim);
496 for i = 1:dim
497 for j = 1:dim
498 for k = 1:dim
499 for l = 1:dim
500 C_boundary{i,j,k,l} = e'*C{i,j,k,l}*e ;
501 end
502 end
503 end
504 end
505
506 % Loop over shift inward from boundary
507 for m = 1:obj.nBP-1
508 C_shifted = cell(dim, dim, dim, dim);
509 for i = 1:dim
510 for j = 1:dim
511 for k = 1:dim
512 for l = 1:dim
513 C_shifted{i,j,k,l} = e_sh{m}'*C{i,j,k,l}*e_sh{m};
514 end
515 end
516 end
517 end
518
519 % Loop along boundary
520 for i = 1:N
521 C_boundary_mat = [C_boundary{b,1,b,1}(i,i), C_boundary{b,1,b,2}(i,i); ...
522 C_boundary{b,2,b,1}(i,i), C_boundary{b,2,b,2}(i,i)];
523
524 C_shifted_mat = [C_shifted{b,1,b,1}(i,i), C_shifted{b,1,b,2}(i,i); ...
525 C_shifted{b,2,b,1}(i,i), C_shifted{b,2,b,2}(i,i)];
526
527 beta = obj.computeBorrowingFromC(C_boundary_mat, C_shifted_mat);
528 beta_vec(i) = min(beta_vec(i), beta);
529 end
530 end
531 if min(beta_vec) < 1e-10
532 disp('WARNING! No borrowing from C seems to be possible.')
533 disp(['min(beta) = ' num2str(min(beta_vec))])
534 end
535 beta_inv = e*spdiag(1./beta_vec)*e'; 493 beta_inv = e*spdiag(1./beta_vec)*e';
536 494
537 % Compensate at corners 495 % Compensate at corners
496 [~, N] = size(e);
538 corner_weight = ones(N, 1); 497 corner_weight = ones(N, 1);
539 corner_weight(1) = 2; 498 corner_weight(1) = 2;
540 corner_weight(end) = 2; 499 corner_weight(end) = 2;
541 corner_weight = e*spdiag(corner_weight)*e'; 500 corner_weight = e*spdiag(corner_weight)*e';
542 501
548 for l = 1:dim 507 for l = 1:dim
549 for k = 1:dim 508 for k = 1:dim
550 Z = Z + nu(l)*C{l,i,k,j}*nu(k); 509 Z = Z + nu(l)*C{l,i,k,j}*nu(k);
551 end 510 end
552 end 511 end
553 Z = -1.2*tuning*(corner_weight/h11 + beta_inv/th_R)*Z; 512 Z = -tuning*(corner_weight/h11 + beta_inv/th_R)*Z;
554 X = Z; 513 X = Z;
555 closure = closure + E{i}*RHOi*Hi*X'*e*H_gamma*(e'*E{j}' ); 514 closure = closure + E{i}*RHOi*Hi*X'*e*H_gamma*(e'*E{j}' );
556 penalty = penalty - E{i}*RHOi*Hi*X'*e*H_gamma; 515 penalty = penalty - E{i}*RHOi*Hi*X'*e*H_gamma;
557 end 516 end
558 517
703 function [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,type) 662 function [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,type)
704 error('Non-conforming interfaces not implemented yet.'); 663 error('Non-conforming interfaces not implemented yet.');
705 end 664 end
706 665
707 % Computes the largest beta such that C_b - beta*C_s >= 0, using bisection. 666 % Computes the largest beta such that C_b - beta*C_s >= 0, using bisection.
708 function beta = computeBorrowingFromC(obj, C_b, C_s) 667 function beta = borrowingBisection(obj, C_b, C_s)
709 tol = 1e-8; 668 tol = 1e-8;
710 beta_min = 0; 669 beta_min = 0;
711 beta_max = 1; 670 beta_max = 1;
712 beta = 0.5; 671 beta = 0.5;
713 err = (beta_max - beta_min)/2; 672 err = (beta_max - beta_min)/2;
723 end 682 end
724 err = err/2; 683 err = err/2;
725 end 684 end
726 end 685 end
727 686
687 % Computes largest beta such that C_bJbL_boundary - \beta*C_bJbL_i >= 0, i = 0, 1, ..., nBP.
688 function beta = computeBorrowingFromC(obj, boundary)
689
690 e = obj.getBoundaryOperatorForScalarField('e', boundary);
691 e_sh = obj.getBoundaryOperatorForScalarField('e_shifted', boundary);
692 dim = obj.dim;
693
694 [~, N] = size(e);
695 beta = ones(N, 1);
696 b = obj.getComponent('normal', boundary);
697 C_boundary = cell(dim, dim, dim, dim);
698 for i = 1:dim
699 for j = 1:dim
700 for k = 1:dim
701 for l = 1:dim
702 C_boundary{i,j,k,l} = e'*obj.C{i,j,k,l}*e ;
703 end
704 end
705 end
706 end
707
708 % Loop over shift inward from boundary
709 for m = 1:obj.nBP_R-1
710 C_shifted = cell(dim, dim, dim, dim);
711 for i = 1:dim
712 for j = 1:dim
713 for k = 1:dim
714 for l = 1:dim
715 C_shifted{i,j,k,l} = e_sh{m}'*obj.C{i,j,k,l}*e_sh{m};
716 end
717 end
718 end
719 end
720
721 % Loop along boundary
722 for i = 1:N
723 C_boundary_mat = [C_boundary{b,1,b,1}(i,i), C_boundary{b,1,b,2}(i,i); ...
724 C_boundary{b,2,b,1}(i,i), C_boundary{b,2,b,2}(i,i)];
725
726 C_shifted_mat = [C_shifted{b,1,b,1}(i,i), C_shifted{b,1,b,2}(i,i); ...
727 C_shifted{b,2,b,1}(i,i), C_shifted{b,2,b,2}(i,i)];
728
729 beta_i = obj.borrowingBisection(C_boundary_mat, C_shifted_mat);
730 beta(i) = min(beta(i), beta_i);
731 end
732 end
733 if min(beta) < 1e-10
734 disp('WARNING! No borrowing from C seems to be possible.')
735 disp(['min(beta) = ' num2str(min(beta))])
736 end
737 end
738
728 % Returns the component number that is the tangential/normal component 739 % Returns the component number that is the tangential/normal component
729 % at the specified boundary 740 % at the specified boundary
730 function comp = getComponent(obj, comp_str, boundary) 741 function comp = getComponent(obj, comp_str, boundary)
731 assertIsMember(comp_str, {'normal', 'tangential'}); 742 assertIsMember(comp_str, {'normal', 'tangential'});
732 assertIsMember(boundary, {'w', 'e', 's', 'n'}); 743 assertIsMember(boundary, {'w', 'e', 's', 'n'});