Mercurial > repos > public > sbplib
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'}); |