diff +scheme/Elastic2dCurvilinearAnisotropic.m @ 1295:cb053fabbedc feature/poroelastic

Add displacement BC on normal tangential components, but it is only provably stable if traction bc are used for the other component.
author Martin Almquist <malmquist@stanford.edu>
date Thu, 02 Jul 2020 20:05:50 -0700
parents fe712a1fca3f
children a0d615bde7f8
line wrap: on
line diff
--- a/+scheme/Elastic2dCurvilinearAnisotropic.m	Thu Jul 02 15:00:21 2020 -0700
+++ b/+scheme/Elastic2dCurvilinearAnisotropic.m	Thu Jul 02 20:05:50 2020 -0700
@@ -36,6 +36,7 @@
         tau1_w, tau1_e, tau1_s, tau1_n  % Return scalar field
         tau2_w, tau2_e, tau2_s, tau2_n  % Return scalar field
         tau_n_w, tau_n_e, tau_n_s, tau_n_n % Return scalar field
+        tau_t_w, tau_t_e, tau_t_s, tau_t_n % Return scalar field
 
         % Inner products
         H
@@ -320,16 +321,16 @@
             obj.et_s = (obj.tangent_s{1}*obj.e1_s' + obj.tangent_s{2}*obj.e2_s')';
             obj.et_n = (obj.tangent_n{1}*obj.e1_n' + obj.tangent_n{2}*obj.e2_n')';
 
-            % obj.tau_n_w = (obj.en_w'*obj.e_w*obj.tau_w')';
-            % obj.tau_n_e = (obj.en_e'*obj.e_e*obj.tau_e')';
-            % obj.tau_n_s = (obj.en_s'*obj.e_s*obj.tau_s')';
-            % obj.tau_n_n = (obj.en_n'*obj.e_n*obj.tau_n')';
-
             obj.tau_n_w = (obj.n_w{1}*obj.tau1_w' + obj.n_w{2}*obj.tau2_w')';
             obj.tau_n_e = (obj.n_e{1}*obj.tau1_e' + obj.n_e{2}*obj.tau2_e')';
             obj.tau_n_s = (obj.n_s{1}*obj.tau1_s' + obj.n_s{2}*obj.tau2_s')';
             obj.tau_n_n = (obj.n_n{1}*obj.tau1_n' + obj.n_n{2}*obj.tau2_n')';
 
+            obj.tau_t_w = (obj.tangent_w{1}*obj.tau1_w' + obj.tangent_w{2}*obj.tau2_w')';
+            obj.tau_t_e = (obj.tangent_e{1}*obj.tau1_e' + obj.tangent_e{2}*obj.tau2_e')';
+            obj.tau_t_s = (obj.tangent_s{1}*obj.tau1_s' + obj.tangent_s{2}*obj.tau2_s')';
+            obj.tau_t_n = (obj.tangent_n{1}*obj.tau1_n' + obj.tangent_n{2}*obj.tau2_n')';
+
             % Stress operators
             sigma = cell(dim, dim);
             D1 = {obj.Dx, obj.Dy};
@@ -398,17 +399,17 @@
                 end
                 e1 = obj.getBoundaryOperator('e1', boundary);
 
-                bc = {1, type};
-                [c1, p1] = obj.refObj.boundary_condition(boundary, bc, tuning);
-                bc = {2, type};
-                c2 = obj.refObj.boundary_condition(boundary, bc, tuning);
+                bc1 = {1, type};
+                [c1, p1] = obj.refObj.boundary_condition(boundary, bc1, tuning);
+                bc2 = {2, type};
+                c2 = obj.refObj.boundary_condition(boundary, bc2, tuning);
 
                 switch type
                 case {'F','f','Free','free','traction','Traction','t','T'}
                     closure = en*en'*(c1+c2);
                     penalty = en*e1'*p1;
                 case {'D','d','dirichlet','Dirichlet','displacement','Displacement'}
-                    error('Not implemented');
+                    [closure, penalty] = obj.displacementBCNormalTangential(boundary, bc, tuning);
                 end
 
             end
@@ -423,8 +424,8 @@
             end
         end
 
-        function [closure, penalty] = displacementBCNormalTangential(boundary, bc, tuning)
-            error('not implemented');
+        function [closure, penalty] = displacementBCNormalTangential(obj, boundary, bc, tuning)
+            disp('WARNING: displacementBCNormalTangential is only guaranteed to work for displaacement BC on one component and traction on the other');
             u = obj;
 
             component = bc{1};
@@ -432,60 +433,55 @@
 
             switch component
             case 'n'
-                en_u       = u.getBoundaryOperator('en', boundary);
-                tau_n_u     = u.getBoundaryOperator('tau_n', boundary);
+                en      = u.getBoundaryOperator('en', boundary);
+                tau_n   = u.getBoundaryOperator('tau_n', boundary);
+                N       = u.getNormal(boundary);
             case 't'
-                en_u       = u.getBoundaryOperator('et', boundary);
-                tau_n_u     = u.getBoundaryOperator('tau_t', boundary);
+                en      = u.getBoundaryOperator('et', boundary);
+                tau_n   = u.getBoundaryOperator('tau_t', boundary);
+                N       = u.getTangent(boundary);
             end
 
             % Operators
-            e_u       = u.getBoundaryOperatorForScalarField('e', boundary);
-            h11_u     = u.getBorrowing(boundary);
-            n_u      = u.getNormal(boundary);
+            e       = u.getBoundaryOperatorForScalarField('e', boundary);
+            h11     = u.getBorrowing(boundary);
+            n      = u.getNormal(boundary);
 
-            C_u = u.C;
-            Ji_u = u.Ji;
-            s_u = spdiag(u.(['s_' boundary]));
-            m_tot_u = u.grid.N();
+            C = u.C;
+            Ji = u.Ji;
+            s = spdiag(u.(['s_' boundary]));
+            m_tot = u.grid.N();
 
             Hi      = u.E{1}*inv(u.H)*u.E{1}' + u.E{2}*inv(u.H)*u.E{2}';
             RHOi    = u.E{1}*inv(u.RHO)*u.E{1}' + u.E{2}*inv(u.RHO)*u.E{2}';
 
-            % Shared operators
             H_gamma         = u.getBoundaryQuadratureForScalarField(boundary);
             dim             = u.dim;
 
             % Preallocate
             [~, m_int] = size(H_gamma);
-            closure = sparse(dim*m_tot_u, dim*m_tot_u);
-            penalty = sparse(dim*m_tot_u, dim*m_tot_v);
+            closure = sparse(dim*m_tot, dim*m_tot);
+            penalty = sparse(dim*m_tot, m_int);
 
-            % Continuity of normal displacement, term 1: The symmetric term
-            Z_u = sparse(m_int, m_int);
-            Z_v = sparse(m_int, m_int);
+            % Term 1: The symmetric term
+            Z = sparse(m_int, m_int);
             for i = 1:dim
                 for j = 1:dim
                     for l = 1:dim
                         for k = 1:dim
-                            Z_u = Z_u + n_u{i}*n_u{j}*e_u'*Ji_u*C_u{l,i,k,j}*e_u*n_u{k}*n_u{l};
-                            Z_v = Z_v + n_v{i}*n_v{j}*e_v'*Ji_v*C_v{l,i,k,j}*e_v*n_v{k}*n_v{l};
+                            Z = Z + n{i}*N{j}*e'*Ji*C{i,j,k,l}*e*n{k}*N{l};
                         end
                     end
                 end
             end
 
-            Z = -tuning*dim*( 1/(4*h11_u)*s_u*Z_u + 1/(4*h11_v)*s_v*Z_v );
-            closure = closure + en_u*H_gamma*Z*en_u';
-            penalty = penalty + en_u*H_gamma*Z*en_v';
+            Z = -tuning*dim*1/h11*s*Z;
+            closure = closure + en*H_gamma*Z*en';
+            penalty = penalty - en*H_gamma*Z;
 
-            % Continuity of normal displacement, term 2: The symmetrizing term
-            closure = closure + 1/2*tau_n_u*H_gamma*en_u';
-            penalty = penalty + 1/2*tau_n_u*H_gamma*en_v';
-
-            % Continuity of normal traction
-            closure = closure - 1/2*en_u*H_gamma*tau_n_u';
-            penalty = penalty - 1/2*en_u*H_gamma*tau_n_v';
+            % Term 2: The symmetrizing term
+            closure = closure + tau_n*H_gamma*en';
+            penalty = penalty - tau_n*H_gamma;
 
             % Multiply all normal component terms by inverse of density x quadraure
             closure = RHOi*Hi*closure;
@@ -565,8 +561,8 @@
                 for j = 1:dim
                     for l = 1:dim
                         for k = 1:dim
-                            Z_u = Z_u + n_u{i}*n_u{j}*e_u'*Ji_u*C_u{l,i,k,j}*e_u*n_u{k}*n_u{l};
-                            Z_v = Z_v + n_v{i}*n_v{j}*e_v'*Ji_v*C_v{l,i,k,j}*e_v*n_v{k}*n_v{l};
+                            Z_u = Z_u + n_u{i}*n_u{j}*e_u'*Ji_u*C_u{i,j,k,l}*e_u*n_u{k}*n_u{l};
+                            Z_v = Z_v + n_v{i}*n_v{j}*e_v'*Ji_v*C_v{i,j,k,l}*e_v*n_v{k}*n_v{l};
                         end
                     end
                 end
@@ -615,11 +611,19 @@
             n = obj.(['n_' boundary]);
         end
 
+        % Returns the unit tangent vector for the boundary specified by the string boundary.
+        % t is a cell of diagonal matrices for each normal component, t{1} = t_1, t{2} = t_2.
+        function t = getTangent(obj, boundary)
+            assertIsMember(boundary, {'w', 'e', 's', 'n'})
+
+            t = obj.(['tangent_' boundary]);
+        end
+
         % Returns the boundary operator op for the boundary specified by the string boundary.
         % op -- string
         function o = getBoundaryOperator(obj, op, boundary)
             assertIsMember(boundary, {'w', 'e', 's', 'n'})
-            assertIsMember(op, {'e', 'e1', 'e2', 'tau', 'tau1', 'tau2', 'en', 'et', 'tau_n'})
+            assertIsMember(op, {'e', 'e1', 'e2', 'tau', 'tau1', 'tau2', 'en', 'et', 'tau_n', 'tau_t'})
 
             o = obj.([op, '_', boundary]);