def Hessian(self, StrainTensors, elem=0, gcounter=0): mu = self.mu k1 = self.k1 k2 = self.k2 I = StrainTensors['I'] J = StrainTensors['J'][gcounter] b = StrainTensors['b'][gcounter] F = StrainTensors['F'][gcounter] if self.ndim == 3: trb = trace(b) elif self.ndim == 2: trb = trace(b) + 1 # ISOCHORIC PART H_Voigt = 2.*mu*J**(-5./3.) * (1./9.*trb*einsum('ij,kl',I,I) - \ 1./3.*einsum('ij,kl',I,b) - 1./3.*einsum('ij,kl',b,I) + \ 1./6.*trb*(einsum('il,jk',I,I) + einsum('ik,jl',I,I)) ) # VOLUMETRIC PART if self.is_nearly_incompressible: H_Voigt += self.pressure * ( einsum('ij,kl', I, I) - (einsum('ik,jl', I, I) + einsum('il,jk', I, I))) else: H_Voigt += self.kappa * ( (2. * J - 1.) * einsum('ij,kl', I, I) - (J - 1.) * (einsum('ik,jl', I, I) + einsum('il,jk', I, I))) # Anisotropic contibution nfibres = self.anisotropic_orientations.shape[1] for i_fibre in range(nfibres): N = self.anisotropic_orientations[elem][i_fibre][:, None] FN = np.dot(F, N)[:, 0] innerFN = einsum('i,i', FN, FN) outerFN = einsum('i,j', FN, FN) expo = np.exp(k2 * (innerFN - 1.)**2) H_Voigt += 4. * k1 / J * (1. + 2. * k2 * (innerFN - 1.)**2) * expo * einsum( 'ij,kl', outerFN, outerFN) H_Voigt = Voigt(H_Voigt, 1) return H_Voigt
def Hessian(self, StrainTensors, elem=0, gcounter=0): """Hessian split into isochoroic and volumetric parts""" I = StrainTensors['I'] b = StrainTensors['b'][gcounter] J = StrainTensors['J'][gcounter] mu = self.mu # ISOCHORIC H_Voigt = 2*mu*J**(-5./3.)*(1./9.*trace(b)*einsum('ij,kl',I,I) - \ 1./3.*(einsum('ij,kl',b,I) + einsum('ij,kl',I,b)) +\ 1./6.*trace(b)*(einsum('ik,jl',I,I) + einsum('il,jk',I,I)) ) # VOLUMETRIC CHANGES if self.is_nearly_incompressible: H_Voigt += self.pressure*(einsum('ij,kl',I,I) - (einsum('ik,jl',I,I) + einsum('il,jk',I,I))) else: H_Voigt += self.kappa*((2.*J-1.)*einsum('ij,kl',I,I) - (J-1.)*(einsum('ik,jl',I,I) + einsum('il,jk',I,I))) H_Voigt = Voigt(H_Voigt,1) self.H_VoigtSize = H_Voigt.shape[0] return H_Voigt
def CauchyStress(self, StrainTensors, elem=0, gcounter=0): mu = self.mu k1 = self.k1 k2 = self.k2 I = StrainTensors['I'] J = StrainTensors['J'][gcounter] b = StrainTensors['b'][gcounter] F = StrainTensors['F'][gcounter] if self.ndim == 3: trb = trace(b) elif self.ndim == 2: trb = trace(b) + 1 # ISOCHORIC PART stress = mu * J**(-5. / 3.) * (b - 1. / 3. * trb * I) # VOLUMETRIC PART if self.is_nearly_incompressible: stress += self.pressure * I else: stress += self.kappa * (J - 1.) * I # Anisotropic contibution nfibres = self.anisotropic_orientations.shape[1] for i_fibre in range(nfibres): N = self.anisotropic_orientations[elem, i_fibre, :, None] FN = np.dot(F, N)[:, 0] innerFN = einsum('i,i', FN, FN) outerFN = einsum('i,j', FN, FN) expo = np.exp(k2 * (innerFN - 1.)**2) stress += 2. * k1 / J * (innerFN - 1.) * expo * outerFN return stress
def CauchyStress(self,StrainTensors,elem=0,gcounter=0): I = StrainTensors['I'] J = StrainTensors['J'][gcounter] b = StrainTensors['b'][gcounter] mu = self.mu # ISOCHORIC PART stress = mu*J**(-5./3.)*(b - 1./3.*trace(b)*I) # VOLUMETRIC PART if self.is_nearly_incompressible: stress += self.pressure*I else: stress += self.kappa*(J-1.)*I return stress
def Hessian(self, StrainTensors, elem=0, gcounter=0): #print(np.finfo(np.float64).eps) I = StrainTensors['I'] J = StrainTensors['J'][gcounter] F = StrainTensors['F'][gcounter] # Directional vector for element Normal = self.anisotropic_orientations[elem][0][:, None] Normal = np.dot(I, Normal)[:, 0] Tangential = self.anisotropic_orientations[elem][1][:, None] Tangential = np.dot(I, Tangential)[:, 0] Axial = self.anisotropic_orientations[elem][2][:, None] Axial = np.dot(I, Axial)[:, 0] Rotation = np.eye(3, 3, dtype=np.float64) for i in range(3): Rotation[0, i] = Normal[i] Rotation[1, i] = Tangential[i] Rotation[2, i] = Axial[i] # Growth tensor (same for all constituent) outerNormal = einsum('i,j', Normal, Normal) outerTangential = I - outerNormal F_g = self.StateVariables[gcounter][20] * outerNormal + outerTangential # Remodeling tensor for elastin F_r = I + (self.StateVariables[gcounter][0:9].reshape(3, 3) - I) * self.factor_increment F_r = np.dot(Rotation.T, np.dot(F_r, Rotation)) # Elastin Growth and Remodeling tensor F_gr = np.dot(F_r, F_g) F_gr_inv = np.linalg.inv(F_gr) # ELASTIN F_e = np.dot(F, F_gr_inv) J_e = np.linalg.det(F_e) b_e = np.dot(F_e, F_e.T) if self.ndim == 3: trb = trace(b_e) elif self.ndim == 2: trb = trace(b_e) + 1. H_Voigt = 2.*self.mu*J_e**(-2./3.)*(1./9.*trb*einsum('ij,kl',I,I) - \ 1./3.*(einsum('ij,kl',I,b_e) + einsum('ij,kl',b_e,I)) + \ 1./6.*trb*(einsum('ik,jl',I,I) + einsum('il,jk',I,I)) )*self.StateVariables[gcounter][14]/J if self.is_nearly_incompressible: H_Voigt += self.pressure*J_e*(einsum('ij,kl',I,I) - \ (einsum('ik,jl',I,I) + einsum('il,jk',I,I)))*self.StateVariables[gcounter][14]/J else: H_Voigt += self.kappa*J_e*((2.*J_e-1.)*einsum('ij,kl',I,I) - \ (J_e-1.)*(einsum('ik,jl',I,I) + einsum('il,jk',I,I)))*self.StateVariables[gcounter][14]/J #SMC AND COLLAGEN FIBRES for fibre_i in [1, 2, 3, 4, 5]: # Fibre direction N = self.anisotropic_orientations[elem][fibre_i][:, None] N = np.dot(I, N)[:, 0] FN = np.dot(F, N) # Remodeling stretch in fibre direction lambda_r = 1. + (self.StateVariables[gcounter][fibre_i + 8] - 1.) * self.factor_increment # TOTAL deformation innerFN = einsum('i,i', FN, FN) outerFN = einsum('i,j', FN, FN) # ELASTIC deformation innerFN_e = innerFN / lambda_r**2 outerFN_e = outerFN / lambda_r**2 if fibre_i is 1: k1 = self.k1m * self.StateVariables[gcounter][15] / J k2 = self.k2m # Anisotropic Stiffness for this key H_Voigt += 4. * k1 * (1. + 2. * k2 * (innerFN_e - 1.)**2) * np.exp( k2 * (innerFN_e - 1.)**2) * einsum( 'ij,kl', outerFN_e, outerFN_e) # Active stress for SMC s_act = self.maxi_active_stress * self.StateVariables[ gcounter][15] / J stretch_m = self.maxi_active_stretch stretch_0 = self.zero_active_stretch stretch_a = self.active_stretch H_Voigt += -2.*(s_act/(self.rho0*innerFN**2))*\ (1.-((stretch_m-stretch_a)/(stretch_m-stretch_0))**2)*einsum('ij,kl',outerFN,outerFN) elif fibre_i is not 1: k1 = self.k1c if (innerFN_e - 1.0) >= 0.0 else 0.075 * self.k1c k1 = k1 * self.StateVariables[gcounter][14 + fibre_i] / J k2 = self.k2c # Anisotropic Stiffness for this key H_Voigt += 4. * k1 * (1. + 2. * k2 * (innerFN_e - 1.)**2) * np.exp( k2 * (innerFN_e - 1.)**2) * einsum( 'ij,kl', outerFN_e, outerFN_e) H_Voigt = Voigt(H_Voigt, 1) return H_Voigt