void AxisymmetricRZ::computeStrain( const unsigned qp, const SymmTensor & total_strain_old, SymmTensor & total_strain_new, SymmTensor & strain_increment ) { strain_increment.xx() = _grad_disp_r[qp](0); strain_increment.yy() = _grad_disp_z[qp](1); strain_increment.zz() = (_solid_model.q_point(qp)(0) != 0.0 ? _disp_r[qp]/_solid_model.q_point(qp)(0) : 0.0); strain_increment.xy() = 0.5*(_grad_disp_r[qp](1) + _grad_disp_z[qp](0)); if (_large_strain) { strain_increment.xx() += 0.5*(_grad_disp_r[qp](0)*_grad_disp_r[qp](0) + _grad_disp_z[qp](0)*_grad_disp_z[qp](0)); strain_increment.yy() += 0.5*(_grad_disp_r[qp](1)*_grad_disp_r[qp](1) + _grad_disp_z[qp](1)*_grad_disp_z[qp](1)); strain_increment.zz() += 0.5*(strain_increment.zz()*strain_increment.zz()); strain_increment.xy() += 0.5*(_grad_disp_r[qp](0)*_grad_disp_r[qp](1) + _grad_disp_z[qp](0)*_grad_disp_z[qp](1)); } total_strain_new = strain_increment; strain_increment -= total_strain_old; }
bool ConstitutiveModel::applyThermalStrain(unsigned qp, SymmTensor & strain_increment, SymmTensor & d_strain_dT) { if (_has_temp && _t_step != 0) { Real inc_thermal_strain; Real d_thermal_strain_d_temp; Real old_temp; if (_t_step == 1 && _has_stress_free_temp) old_temp = _stress_free_temp; else old_temp = _temperature_old[qp]; Real current_temp = _temperature[qp]; Real delta_t = current_temp - old_temp; Real alpha = _alpha; if (_alpha_function) { Point p; Real alpha_current_temp = _alpha_function->value(current_temp,p); Real alpha_old_temp = _alpha_function->value(old_temp,p); if (_mean_alpha_function) { Real small(1e-6); Real numerator = alpha_current_temp * (current_temp - _ref_temp) - alpha_old_temp * (old_temp - _ref_temp); Real denominator = 1.0 + alpha_old_temp * (old_temp - _ref_temp); if (denominator < small) mooseError("Denominator too small in thermal strain calculation"); inc_thermal_strain = numerator / denominator; d_thermal_strain_d_temp = alpha_current_temp * (current_temp - _ref_temp); } else { inc_thermal_strain = delta_t * 0.5 * (alpha_current_temp + alpha_old_temp); d_thermal_strain_d_temp = alpha_current_temp; } } else { inc_thermal_strain = delta_t * alpha; d_thermal_strain_d_temp = alpha; } strain_increment.addDiag(-inc_thermal_strain); d_strain_dT.addDiag(-d_thermal_strain_d_temp); } bool modified = true; return modified; }
Real volumetricStrain(const SymmTensor & symm_strain) { Real value = symm_strain.trace(); value += symm_strain.xx() * symm_strain.yy() + symm_strain.yy() * symm_strain.zz() + symm_strain.zz() * symm_strain.xx() + symm_strain.xx() * symm_strain.yy() * symm_strain.zz(); return value; }
Real StressDivergence::computeQpJacobian() { Real sum_C3x3 = _Jacobian_mult[_qp].sum_3x3(); RealGradient sum_C3x1 = _Jacobian_mult[_qp].sum_3x1(); Real jacobian = 0.0; // B^T_i * C * B_j jacobian += _Jacobian_mult[_qp].stiffness( _component, _component, _grad_test[_i][_qp], _grad_phi[_j][_qp]); // B^T_i * C *B_j if (_volumetric_locking_correction) { // jacobian = Bbar^T_i * C * Bbar_j where Bbar = B + Bvol // jacobian = B^T_i * C * B_j + Bvol^T_i * C * Bvol_j + Bvol^T_i * C * B_j + B^T_i * C * Bvol_j // Bvol^T_i * C * Bvol_j jacobian += sum_C3x3 * (_avg_grad_test[_i][_component] - _grad_test[_i][_qp](_component)) * (_avg_grad_phi[_j][_component] - _grad_phi[_j][_qp](_component)) / 9.0; // B^T_i * C * Bvol_j jacobian += sum_C3x1(_component) * _grad_test[_i][_qp](_component) * (_avg_grad_phi[_j][_component] - _grad_phi[_j][_qp](_component)) / 3.0; // Bvol^T_i * C * B_j SymmTensor phi; if (_component == 0) { phi.xx() = _grad_phi[_j][_qp](0); phi.xy() = _grad_phi[_j][_qp](1); phi.xz() = _grad_phi[_j][_qp](2); } else if (_component == 1) { phi.yy() = _grad_phi[_j][_qp](1); phi.xy() = _grad_phi[_j][_qp](0); phi.yz() = _grad_phi[_j][_qp](2); } else if (_component == 2) { phi.zz() = _grad_phi[_j][_qp](2); phi.xz() = _grad_phi[_j][_qp](0); phi.yz() = _grad_phi[_j][_qp](1); } SymmTensor tmp(_Jacobian_mult[_qp] * phi); jacobian += (tmp.xx() + tmp.yy() + tmp.zz()) * (_avg_grad_test[_i][_component] - _grad_test[_i][_qp](_component)) / 3.0; } if (_dt > 0) return jacobian * (1 + _alpha + _zeta / _dt); else return jacobian; }
void PlaneStrain::computeStrain( const unsigned qp, const SymmTensor & total_strain_old, SymmTensor & total_strain_new, SymmTensor & strain_increment ) { strain_increment.xx() = _grad_disp_x[qp](0); strain_increment.yy() = _grad_disp_y[qp](1); strain_increment.zz() = 0; strain_increment.xy() = 0.5*(_grad_disp_x[qp](1) + _grad_disp_y[qp](0)); strain_increment.yz() = 0; strain_increment.zx() = 0; if (_large_strain) { strain_increment.xx() += 0.5*(_grad_disp_x[qp](0)*_grad_disp_x[qp](0) + _grad_disp_y[qp](0)*_grad_disp_y[qp](0)); strain_increment.yy() += 0.5*(_grad_disp_x[qp](1)*_grad_disp_x[qp](1) + _grad_disp_y[qp](1)*_grad_disp_y[qp](1)); strain_increment.xy() += 0.5*(_grad_disp_x[qp](0)*_grad_disp_x[qp](1) + _grad_disp_y[qp](0)*_grad_disp_y[qp](1)); } total_strain_new = strain_increment; strain_increment -= total_strain_old; }
Real vonMisesStress(const SymmTensor & symm_stress) { Real value = std::pow(symm_stress.xx() - symm_stress.yy(), 2) + std::pow(symm_stress.yy() - symm_stress.zz(), 2) + std::pow(symm_stress.zz() - symm_stress.xx(), 2) + 6 * (std::pow(symm_stress.xy(), 2) + std::pow(symm_stress.yz(), 2) + std::pow(symm_stress.zx(), 2)); return std::sqrt(value / 2.0); }
Real StressDivergenceRSpherical::computeQpOffDiagJacobian(unsigned int jvar) { if ( _temp_coupled && jvar == _temp_var ) { SymmTensor test; test.xx() = _grad_test[_i][_qp](0); test.yy() = _test[_i][_qp] / _q_point[_qp](0); test.zz() = test.yy(); return _d_stress_dT[_qp].doubleContraction(test) * _phi[_j][_qp]; } return 0; }
bool PoroElasticity::formPermeabilityTensor (SymmTensor& K, const Vectors&, const FiniteElement&, const Vec3& X) const { const PoroMaterial* pmat = dynamic_cast<const PoroMaterial*>(material); if (!pmat) return false; Vec3 permeability = pmat->getPermeability(X); K.zero(); for (size_t i = 1; i <= K.dim(); i++) K(i,i) = permeability(i); return true; }
Real MaterialTensorAux::principalValue( const SymmTensor & tensor, unsigned int index ) { ColumnMajorMatrix eval(3,1); ColumnMajorMatrix evec(3,3); tensor.columnMajorMatrix().eigen(eval, evec); // Eigen computes low to high. We want high first. int i = -index + 2; return eval(i); }
Real calcPrincipleValues(const SymmTensor & symm_tensor, unsigned int index, RealVectorValue & direction) { ColumnMajorMatrix eval(3,1); ColumnMajorMatrix evec(3,3); symm_tensor.columnMajorMatrix().eigen(eval, evec); // Eigen computes low to high. We want high first. direction(0) = evec(0,index); direction(1) = evec(1,index); direction(2) = evec(2,index); return eval(index); }
Real StressDivergenceRZ::computeQpOffDiagJacobian(unsigned int jvar) { if ( _rdisp_coupled && jvar == _rdisp_var ) { return calculateJacobian( _component, 0 ); } else if ( _zdisp_coupled && jvar == _zdisp_var ) { return calculateJacobian( _component, 1 ); } else if ( _temp_coupled && jvar == _temp_var ) { SymmTensor test; if (_component == 0) { test.xx() = _grad_test[_i][_qp](0); test.xy() = 0.5*_grad_test[_i][_qp](1); test.zz() = _test[_i][_qp] / _q_point[_qp](0); } else { test.xy() = 0.5*_grad_test[_i][_qp](0); test.yy() = _grad_test[_i][_qp](1); } return _d_stress_dT[_qp].doubleContraction(test) * _phi[_j][_qp]; } return 0; }
void Nonlinear::computeStrainIncrement( const ColumnMajorMatrix & Fhat, SymmTensor & strain_increment ) { // // A calculation of the strain at the mid-interval is probably more // accurate (second vs. first order). This would require the // incremental deformation gradient at the mid-step, which we // currently don't have. We would then have to calculate the // rotation for the whole step. // // // We are looking for: // log( Uhat ) // = log( sqrt( Fhat^T*Fhat ) ) // = log( sqrt( Chat ) ) // A Taylor series expansion gives: // ( Chat - 0.25 * Chat^T*Chat - 0.75 * I ) // = ( - 0.25 * Chat^T*Chat + Chat - 0.75 * I ) // = ( (0.25*Chat - 0.75*I) * (Chat - I) ) // = ( B * A ) // B // = 0.25*Chat - 0.75*I // = 0.25*(Chat - I) - 0.5*I // = 0.25*A - 0.5*I // const Real Uxx = Fhat(0,0); const Real Uxy = Fhat(0,1); const Real Uxz = Fhat(0,2); const Real Uyx = Fhat(1,0); const Real Uyy = Fhat(1,1); const Real Uyz = Fhat(1,2); const Real Uzx = Fhat(2,0); const Real Uzy = Fhat(2,1); const Real Uzz = Fhat(2,2); const Real Axx = Uxx*Uxx + Uyx*Uyx + Uzx*Uzx - 1.0; const Real Axy = Uxx*Uxy + Uyx*Uyy + Uzx*Uzy; const Real Axz = Uxx*Uxz + Uyx*Uyz + Uzx*Uzz; const Real Ayy = Uxy*Uxy + Uyy*Uyy + Uzy*Uzy - 1.0; const Real Ayz = Uxy*Uxz + Uyy*Uyz + Uzy*Uzz; const Real Azz = Uxz*Uxz + Uyz*Uyz + Uzz*Uzz - 1.0; const Real Bxx = 0.25 * Axx - 0.5; const Real Bxy = 0.25 * Axy; const Real Bxz = 0.25 * Axz; const Real Byy = 0.25 * Ayy - 0.5; const Real Byz = 0.25 * Ayz; const Real Bzz = 0.25 * Azz - 0.5; strain_increment.xx( -(Bxx*Axx + Bxy*Axy + Bxz*Axz) ); strain_increment.xy( -(Bxx*Axy + Bxy*Ayy + Bxz*Ayz) ); strain_increment.zx( -(Bxx*Axz + Bxy*Ayz + Bxz*Azz) ); strain_increment.yy( -(Bxy*Axy + Byy*Ayy + Byz*Ayz) ); strain_increment.yz( -(Bxy*Axz + Byy*Ayz + Byz*Azz) ); strain_increment.zz( -(Bxz*Axz + Byz*Ayz + Bzz*Azz) ); }
ColumnMajorMatrix CrackFrontDefinition::rotateToCrackFrontCoords(const SymmTensor tensor, const unsigned int node_index) const { ColumnMajorMatrix tensor_CMM; tensor_CMM(0,0) = tensor.xx(); tensor_CMM(0,1) = tensor.xy(); tensor_CMM(0,2) = tensor.xz(); tensor_CMM(1,0) = tensor.xy(); tensor_CMM(1,1) = tensor.yy(); tensor_CMM(1,2) = tensor.yz(); tensor_CMM(2,0) = tensor.xz(); tensor_CMM(2,1) = tensor.yz(); tensor_CMM(2,2) = tensor.zz(); ColumnMajorMatrix tmp = _rot_matrix[node_index] * tensor_CMM; ColumnMajorMatrix rotT = _rot_matrix[node_index].transpose(); ColumnMajorMatrix rotated_tensor = tmp * rotT; return rotated_tensor; }
void CardiacHolzapfel2009Material::computeQpStressProperties(const SymmTensor &C, const SymmTensor & /*E*/) { const SymmTensor CC(square(C)); // invariants (We will not need all of them. However, defining them avoids to forget any.) const Real I1(C.trace()); /*const Real I2(0.5*(I1*I1-CC.trace()));*/ /*const Real I3(_J[_qp]); */ const Real I4f(_Ef[_qp]*(C*_Ef[_qp])); const Real I4s(_Es[_qp]*(C*_Es[_qp])); /*const Real I4n(_En[_qp]*(C*_En[_qp])); */ /*const Real I5f(_Ef[_qp]*(CC*_Ef[_qp]));*/ /*const Real I5s(_Es[_qp]*(CC*_Es[_qp]));*/ /*const Real I5n(_En[_qp]*(CC*_En[_qp]));*/ const Real I8fs(_Ef[_qp]*(C*_Es[_qp])); /*const Real I8fn(_Ef[_qp]*(C*_En[_qp]));*/ /*const Real I8sn(_Es[_qp]*(C*_En[_qp]));*/ // the following will be needed in the stress as well as in the energy and stress_derivative const Real i_term( _p[A1 ]*std::exp(_p[B1 ]*(I1 -3) ) ); const Real f_term( 2*_p[Af ]*std::exp(_p[Bf ]*(I4f-1)*(I4f-1)) ); const Real s_term( 2*_p[As ]*std::exp(_p[Bs ]*(I4s-1)*(I4s-1)) ); const Real fs_term( _p[Afs]*std::exp(_p[Bfs]* I8fs * I8fs ) ); // elastic energy contribution _W[_qp] = i_term /(2*_p[B1 ]) + ( f_term - 2*_p[Af ])/(2*_p[Bf ]) + ( s_term - 2*_p[As ])/(2*_p[Bs ]) + (fs_term - 2*_p[Afs])/(2*_p[Bfs]); // tensors for constructing stress and stress_derivative const SymmTensor EfEf(kron(_Ef[_qp])); const SymmTensor EsEs(kron(_Es[_qp])); const SymmTensor EfEs(kronSym(_Ef[_qp],_Es[_qp])); // stress _stress[_qp] = scaledID(i_term) + EfEf*(I4f-1)*f_term + EsEs*(I4s-1)*s_term + EfEs*I8fs*fs_term; // stress derivative /* fancy lambda function syntax makes things much easier here */ _stress_derivative[_qp].fill_from_minor_iter( [&](const unsigned int M, const unsigned int N, const unsigned int P, const unsigned int Q) -> Real { return _p[B1 ] * i_term * _id(M,N) * _id(P,Q) + (1 + (I4f-1)*(I4f-1)*2*_p[Bf ]) * f_term * EfEf(M,N) * EfEf(P,Q) + (1 + (I4f-1)*(I4f-1)*2*_p[Bf ]) * s_term * EsEs(M,N) * EsEs(P,Q) + (1 + I8fs *2*_p[Bfs]) * fs_term * EfEs(M,N) * EfEs(P,Q); } ); }
bool Elasticity::kinematics (const Vector& eV, const Vector& N, const Matrix& dNdX, double r, Matrix& B, Tensor&, SymmTensor& eps) const { // Evaluate the strain-displacement matrix, B if (axiSymmetry) { if (!this->formBmatrix(B,N,dNdX,r)) return false; } else { if (!this->formBmatrix(B,dNdX)) return false; } if (eV.empty() || eps.dim() == 0) return true; // Evaluate the strains return B.multiply(eV,eps); // eps = B*eV }
Real component(const SymmTensor & symm_tensor, unsigned int index, RealVectorValue & direction) { direction.zero(); if (index < 3) direction(index) = 1.0; else if (index == 3)//xy { direction(0) = std::sqrt(0.5); direction(1) = direction(0); } else if (index == 4)//yz { direction(1) = std::sqrt(0.5); direction(2) = direction(1); } else if (index == 5)//zx { direction(0) = std::sqrt(0.5); direction(2) = direction(0); } return symm_tensor.component(index); }
void ReturnMappingModel::computeStress(const Elem & /*current_elem*/, const SymmElasticityTensor & elasticityTensor, const SymmTensor & stress_old, SymmTensor & strain_increment, SymmTensor & stress_new, SymmTensor & inelastic_strain_increment) { // compute deviatoric trial stress SymmTensor dev_trial_stress(stress_new); dev_trial_stress.addDiag(-dev_trial_stress.trace() / 3.0); // compute effective trial stress Real dts_squared = dev_trial_stress.doubleContraction(dev_trial_stress); Real effective_trial_stress = std::sqrt(1.5 * dts_squared); // compute effective strain increment SymmTensor dev_strain_increment(strain_increment); dev_strain_increment.addDiag(-strain_increment.trace() / 3.0); _effective_strain_increment = dev_strain_increment.doubleContraction(dev_strain_increment); _effective_strain_increment = std::sqrt(2.0 / 3.0 * _effective_strain_increment); const SymmIsotropicElasticityTensor * iso_e_t = dynamic_cast<const SymmIsotropicElasticityTensor *>(&elasticityTensor); if (!iso_e_t) mooseError("Models derived from ReturnMappingModel require a SymmIsotropicElasticityTensor"); _three_shear_modulus = 3.0 * iso_e_t->shearModulus(); computeStressInitialize(effective_trial_stress, elasticityTensor); Real scalar; returnMappingSolve(effective_trial_stress, scalar, _console); // compute inelastic and elastic strain increments if (_legacy_return_mapping) { if (effective_trial_stress < 0.01) effective_trial_stress = 0.01; inelastic_strain_increment = dev_trial_stress; inelastic_strain_increment *= (1.5 * scalar / effective_trial_stress); } else { if (scalar != 0.0) inelastic_strain_increment = dev_trial_stress * (1.5 * scalar / effective_trial_stress); else inelastic_strain_increment = 0.0; } strain_increment -= inelastic_strain_increment; _effective_inelastic_strain[_qp] = _effective_inelastic_strain_old[_qp] + scalar; // compute stress increment stress_new = elasticityTensor * strain_increment; // update stress stress_new += stress_old; computeStressFinalize(inelastic_strain_increment); }
void SymmIsotropicElasticityTensor::multiply( const SymmTensor & x, SymmTensor & b ) const { const Real xx = x.xx(); const Real yy = x.yy(); const Real zz = x.zz(); const Real xy = x.xy(); const Real yz = x.yz(); const Real zx = x.zx(); b.xx() = _val[ 0]*xx + _val[ 1]*yy + _val[ 2]*zz; b.yy() = _val[ 1]*xx + _val[ 6]*yy + _val[ 7]*zz; b.zz() = _val[ 2]*xx + _val[ 7]*yy + _val[11]*zz; b.xy() = 2*_val[15]*xy; b.yz() = 2*_val[18]*yz; b.zx() = 2*_val[20]*zx; }
bool FractureElasticityVoigt::evalStress (double lambda, double mu, double Gc, const SymmTensor& epsil, double* Phi, SymmTensor* sigma, Matrix* dSdE, bool postProc, bool printElm) const { PROFILE3("FractureEl::evalStress"); unsigned short int a = 0, b = 0; // Define a Lambda-function to set up the isotropic constitutive matrix auto&& setIsotropic = [this,a,b](Matrix& C, double lambda, double mu) mutable { for (a = 1; a <= C.rows(); a++) if (a > nsd) C(a,a) = mu; else { C(a,a) = 2.0*mu; for (b = 1; b <= nsd; b++) C(a,b) += lambda; } }; // Define some material constants double trEps = epsil.trace(); double C0 = trEps >= -epsZ ? Gc*lambda : lambda; double Cp = Gc*mu; if (trEps >= -epsZ && trEps <= epsZ) { // No strains, stress free configuration Phi[0] = 0.0; if (postProc) Phi[1] = Phi[2] = Phi[3] = 0.0; if (sigma) *sigma = 0.0; if (dSdE) setIsotropic(*dSdE,C0,Cp); return true; } // Calculate principal strains and the associated directions Vec3 eps; std::vector<SymmTensor> M(nsd,SymmTensor(nsd)); { PROFILE4("Tensor::principal"); if (!epsil.principal(eps,M.data())) return false; } // Split the strain tensor into positive and negative parts SymmTensor ePos(nsd), eNeg(nsd); for (a = 0; a < nsd; a++) if (eps[a] > 0.0) ePos += eps[a]*M[a]; else if (eps[a] < 0.0) eNeg += eps[a]*M[a]; if (sigma) { // Evaluate the stress tensor *sigma = C0*trEps; *sigma += 2.0*mu*(Gc*ePos + eNeg); } // Evaluate the tensile energy Phi[0] = mu*(ePos*ePos).trace(); if (trEps > 0.0) Phi[0] += 0.5*lambda*trEps*trEps; if (postProc) { // Evaluate the compressive energy Phi[1] = mu*(eNeg*eNeg).trace(); if (trEps < 0.0) Phi[1] += 0.5*lambda*trEps*trEps; // Evaluate the total strain energy Phi[2] = Gc*Phi[0] + Phi[1]; // Evaluate the bulk energy Phi[3] = Gc*(Phi[0] + Phi[1]); } else if (sigmaC > 0.0) // Evaluate the crack driving function Phi[0] = this->MieheCrit56(eps,lambda,mu); #if INT_DEBUG > 4 std::cout <<"eps_p = "<< eps <<"\n"; for (a = 0; a < nsd; a++) std::cout <<"M("<< 1+a <<") =\n"<< M[a]; std::cout <<"ePos =\n"<< ePos <<"eNeg =\n"<< eNeg; if (sigma) std::cout <<"sigma =\n"<< *sigma; std::cout <<"Phi = "<< Phi[0]; if (postProc) std::cout <<" "<< Phi[1] <<" "<< Phi[2] <<" "<< Phi[3]; std::cout << std::endl; #else if (printElm) { std::cout <<"g(c) = "<< Gc <<"\nepsilon =\n"<< epsil <<"eps_p = "<< eps <<"\nePos =\n"<< ePos <<"eNeg =\n"<< eNeg; if (sigma) std::cout <<"sigma =\n"<< *sigma; std::cout <<"Phi = "<< Phi[0]; if (postProc) std::cout <<" "<< Phi[1] <<" "<< Phi[2] <<" "<< Phi[3]; std::cout << std::endl; } #endif if (!dSdE) return true; else if (eps[0] == eps[nsd-1]) { // Hydrostatic pressure setIsotropic(*dSdE, C0, eps.x > 0.0 ? Cp : mu); return true; } typedef unsigned short int s_ind; // Convenience type definition // Define a Lambda-function to calculate (lower triangle of) the matrix Qa auto&& getQ = [this](Matrix& Q, const SymmTensor& Ma, double C) { if (C == 0.0) return; auto&& Mult = [Ma](s_ind i, s_ind j, s_ind k, s_ind l) { return Ma(i,j)*Ma(k,l); }; s_ind i, j, k, l, is, js; // Normal stresses and strains for (i = 1; i <= nsd; i++) for (j = 1; j <= i; j++) Q(i,j) += C*Mult(i,i,j,j); is = nsd+1; for (i = 1; i < nsd; i++) for (j = i+1; j <= nsd; j++, is++) { // Shear stress coupled to normal strain for (k = 1; k <= nsd; k++) Q(is,k) += C*Mult(i,j,k,k); // Shear stress coupled to shear strain js = nsd+1; for (k = 1; k < nsd; k++) for (l = k+1; js <= is; l++, js++) Q(is,js) += C*Mult(i,j,k,l); } }; // Define a Lambda-function to calculate (lower triangle of) the matrix Gab auto&& getG = [this](Matrix& G, const SymmTensor& Ma, const SymmTensor& Mb, double C) { if (C == 0.0) return; auto&& Mult = [Ma,Mb](s_ind i, s_ind j, s_ind k, s_ind l) { return Ma(i,k)*Mb(j,l) + Ma(i,l)*Mb(j,k) + Mb(i,k)*Ma(j,l) + Mb(i,l)*Ma(j,k); }; s_ind i, j, k, l, is, js; // Normal stresses and strains for (i = 1; i <= nsd; i++) for (j = 1; j <= i; j++) G(i,j) += C*Mult(i,i,j,j); is = nsd+1; for (i = 1; i < nsd; i++) for (j = i+1; j <= nsd; j++, is++) { // Shear stress coupled to normal strain for (k = 1; k <= nsd; k++) G(is,k) += C*Mult(i,j,k,k); // Shear stress coupled to shear strain js = nsd+1; for (k = 1; k < nsd; k++) for (l = k+1; js <= is; l++, js++) G(is,js) += C*Mult(i,j,k,l); } }; // Evaluate the stress tangent assuming Voigt notation and symmetry for (a = 1; a <= nsd; a++) for (b = 1; b <= a; b++) (*dSdE)(a,b) = C0; for (a = 0; a < nsd; a++) { double C1 = eps[a] >= 0.0 ? Cp : mu; getQ(*dSdE, M[a], 2.0*C1); if (eps[a] != 0.0) for (b = 0; b < nsd; b++) if (a != b && eps[a] != eps[b]) getG(*dSdE,M[a],M[b],C1/(1.0-eps[b]/eps[a])); } // Account for symmetry for (b = 2; b <= dSdE->rows(); b++) for (a = 1; a < b; a++) (*dSdE)(a,b) = (*dSdE)(b,a); return true; }
Real StressDivergence::computeQpOffDiagJacobian(unsigned int jvar) { unsigned int coupled_component = 0; bool active = false; if (_xdisp_coupled && jvar == _xdisp_var) { coupled_component = 0; active = true; } else if (_ydisp_coupled && jvar == _ydisp_var) { coupled_component = 1; active = true; } else if (_zdisp_coupled && jvar == _zdisp_var) { coupled_component = 2; active = true; } if (active) { Real sum_C3x3 = _Jacobian_mult[_qp].sum_3x3(); RealGradient sum_C3x1 = _Jacobian_mult[_qp].sum_3x1(); Real jacobian = 0.0; jacobian += _Jacobian_mult[_qp].stiffness( _component, coupled_component, _grad_test[_i][_qp], _grad_phi[_j][_qp]); // B^T_i * C *B_j if (_volumetric_locking_correction) { // jacobian = Bbar^T_i * C * Bbar_j where Bbar = B + Bvol // jacobian = B^T_i * C * B_j + Bvol^T_i * C * Bvol_j + Bvol^T_i * C * B_j + B^T_i * C * // Bvol_j // Bvol^T_i * C * Bvol_j jacobian += sum_C3x3 * (_avg_grad_test[_i][_component] - _grad_test[_i][_qp](_component)) * (_avg_grad_phi[_j][coupled_component] - _grad_phi[_j][_qp](coupled_component)) / 9.0; // B^T_i * C * Bvol_j jacobian += sum_C3x1(_component) * _grad_test[_i][_qp](_component) * (_avg_grad_phi[_j][coupled_component] - _grad_phi[_j][_qp](coupled_component)) / 3.0; // Bvol^T_i * C * B_i SymmTensor phi; if (coupled_component == 0) { phi.xx() = _grad_phi[_j][_qp](0); phi.xy() = _grad_phi[_j][_qp](1); phi.xz() = _grad_phi[_j][_qp](2); } else if (coupled_component == 1) { phi.yy() = _grad_phi[_j][_qp](1); phi.xy() = _grad_phi[_j][_qp](0); phi.yz() = _grad_phi[_j][_qp](2); } else if (coupled_component == 2) { phi.zz() = _grad_phi[_j][_qp](2); phi.xz() = _grad_phi[_j][_qp](0); phi.yz() = _grad_phi[_j][_qp](1); } SymmTensor tmp(_Jacobian_mult[_qp] * phi); jacobian += (tmp.xx() + tmp.yy() + tmp.zz()) * (_avg_grad_test[_i][_component] - _grad_test[_i][_qp](_component)) / 3.0; } if (_dt > 0) return jacobian * (1 + _alpha + _zeta / _dt); else return jacobian; } if (_temp_coupled && jvar == _temp_var) return _d_stress_dT[_qp].rowDot(_component, _grad_test[_i][_qp]) * _phi[_j][_qp]; return 0; }
Real equivalentPlasticStrain(const SymmTensor & symm_strain) { return std::sqrt(2.0 / 3.0 * symm_strain.doubleContraction(symm_strain)); }
void PLC_LSH::computeLSH( const SymmTensor & strain_increment, SymmTensor & plastic_strain_increment, SymmTensor & stress_new ) { // compute deviatoric trial stress SymmTensor dev_trial_stress(stress_new); dev_trial_stress.addDiag( -stress_new.trace()/3 ); // effective trial stress Real dts_squared = dev_trial_stress.doubleContraction(dev_trial_stress); Real effective_trial_stress = std::sqrt(1.5 * dts_squared); // determine if yield condition is satisfied Real yield_condition = effective_trial_stress - _hardening_variable_old[_qp] - _yield_stress; _hardening_variable[_qp] = _hardening_variable_old[_qp]; _plastic_strain[_qp] = _plastic_strain_old[_qp]; if (yield_condition > 0) // then use newton iteration to determine effective plastic strain increment { unsigned int it = 0; Real plastic_residual = 0; Real norm_plas_residual = 10; Real first_norm_plas_residual = 10; Real scalar_plastic_strain_increment = 0; while (it < _max_its && norm_plas_residual > _absolute_tolerance && (norm_plas_residual/first_norm_plas_residual) > _relative_tolerance) { plastic_residual = effective_trial_stress - (3. * _shear_modulus * scalar_plastic_strain_increment) - _hardening_variable[_qp] - _yield_stress; norm_plas_residual = std::abs(plastic_residual); if (it == 0) { first_norm_plas_residual = norm_plas_residual; } scalar_plastic_strain_increment += plastic_residual / (3. * _shear_modulus + _hardening_constant); _hardening_variable[_qp] = _hardening_variable_old[_qp] + (_hardening_constant * scalar_plastic_strain_increment); if (_output_iteration_info == true) { _console << "pls_it=" << it << " trl_strs=" << effective_trial_stress << " del_p=" << scalar_plastic_strain_increment << " harden=" << _hardening_variable[_qp] << " rel_res=" << norm_plas_residual/first_norm_plas_residual << " rel_tol=" << _relative_tolerance << " abs_res=" << norm_plas_residual << " abs_tol=" << _absolute_tolerance << std::endl; } ++it; } if (it == _max_its && norm_plas_residual > _absolute_tolerance && (norm_plas_residual/first_norm_plas_residual) > _relative_tolerance) { mooseError("Max sub-newton iteration hit during plasticity increment solve!"); } if (effective_trial_stress < 0.01) { effective_trial_stress = 0.01; } plastic_strain_increment = dev_trial_stress; plastic_strain_increment *= (1.5*scalar_plastic_strain_increment/effective_trial_stress); SymmTensor elastic_strain_increment(strain_increment); elastic_strain_increment -= plastic_strain_increment; // compute stress increment stress_new = *elasticityTensor() * elastic_strain_increment; // update stress and plastic strain stress_new += _stress_old; _plastic_strain[_qp] += plastic_strain_increment; } // end of if statement }
Real hydrostatic(const SymmTensor & symm_tensor) { return symm_tensor.trace() / 3.0; }
Real firstInvariant(const SymmTensor & symm_tensor) { return symm_tensor.trace(); }
Real thirdInvariant(const SymmTensor & symm_tensor) { Real val = 0.0; val = symm_tensor.xx() * symm_tensor.yy() * symm_tensor.zz() - symm_tensor.xx() * symm_tensor.yz() * symm_tensor.yz() + symm_tensor.xy() * symm_tensor.yz() * symm_tensor.zx() - symm_tensor.xy() * symm_tensor.xy() * symm_tensor.zz() + symm_tensor.zx() * symm_tensor.xy() * symm_tensor.yz() - symm_tensor.zx() * symm_tensor.yy() * symm_tensor.zx(); return val; }
Real secondInvariant(const SymmTensor & symm_tensor) { Real value = symm_tensor.xx() * symm_tensor.yy() + symm_tensor.yy() * symm_tensor.zz() + symm_tensor.zz() * symm_tensor.xx() - symm_tensor.xy() * symm_tensor.xy() - symm_tensor.yz() * symm_tensor.yz() - symm_tensor.zx() * symm_tensor.zx(); return value; }
void Element::unrotateSymmetricTensor( const ColumnMajorMatrix & R, const SymmTensor & T, SymmTensor & result ) { // Rt T R // 00 10 20 00 01 02 00 01 02 // 01 11 21 * 10 11 12 * 10 11 12 // 02 12 22 20 21 22 20 21 22 // const Real T00 = R(0,0)*T.xx() + R(1,0)*T.xy() + R(2,0)*T.zx(); const Real T01 = R(0,0)*T.xy() + R(1,0)*T.yy() + R(2,0)*T.yz(); const Real T02 = R(0,0)*T.zx() + R(1,0)*T.yz() + R(2,0)*T.zz(); const Real T10 = R(0,1)*T.xx() + R(1,1)*T.xy() + R(2,1)*T.zx(); const Real T11 = R(0,1)*T.xy() + R(1,1)*T.yy() + R(2,1)*T.yz(); const Real T12 = R(0,1)*T.zx() + R(1,1)*T.yz() + R(2,1)*T.zz(); const Real T20 = R(0,2)*T.xx() + R(1,2)*T.xy() + R(2,2)*T.zx(); const Real T21 = R(0,2)*T.xy() + R(1,2)*T.yy() + R(2,2)*T.yz(); const Real T22 = R(0,2)*T.zx() + R(1,2)*T.yz() + R(2,2)*T.zz(); result.xx( T00 * R(0,0) + T01 * R(1,0) + T02 * R(2,0) ); result.yy( T10 * R(0,1) + T11 * R(1,1) + T12 * R(2,1) ); result.zz( T20 * R(0,2) + T21 * R(1,2) + T22 * R(2,2) ); result.xy( T00 * R(0,1) + T01 * R(1,1) + T02 * R(2,1) ); result.yz( T10 * R(0,2) + T11 * R(1,2) + T12 * R(2,2) ); result.zx( T00 * R(0,2) + T01 * R(1,2) + T02 * R(2,2) ); }
void SymmElasticityTensor::multiply(const SymmTensor & x, SymmTensor & b) const { const Real xx = x.xx(); const Real yy = x.yy(); const Real zz = x.zz(); const Real xy = x.xy(); const Real yz = x.yz(); const Real zx = x.zx(); b.xx() = _val[0] * xx + _val[1] * yy + _val[2] * zz + 2 * (_val[3] * xy + _val[4] * yz + _val[5] * zx); b.yy() = _val[1] * xx + _val[6] * yy + _val[7] * zz + 2 * (_val[8] * xy + _val[9] * yz + _val[10] * zx); b.zz() = _val[2] * xx + _val[7] * yy + _val[11] * zz + 2 * (_val[12] * xy + _val[13] * yz + _val[14] * zx); b.xy() = _val[3] * xx + _val[8] * yy + _val[12] * zz + 2 * (_val[15] * xy + _val[16] * yz + _val[17] * zx); b.yz() = _val[4] * xx + _val[9] * yy + _val[13] * zz + 2 * (_val[16] * xy + _val[18] * yz + _val[19] * zx); b.zx() = _val[5] * xx + _val[10] * yy + _val[14] * zz + 2 * (_val[17] * xy + _val[19] * yz + _val[20] * zx); }
void Linear::computeStrain( const unsigned qp, const SymmTensor & total_strain_old, SymmTensor & total_strain_new, SymmTensor & strain_increment ) { strain_increment.xx( _grad_disp_x[qp](0) ); strain_increment.yy( _grad_disp_y[qp](1) ); strain_increment.zz( _grad_disp_z[qp](2) ); strain_increment.xy( 0.5*(_grad_disp_x[qp](1)+_grad_disp_y[qp](0)) ); strain_increment.yz( 0.5*(_grad_disp_y[qp](2)+_grad_disp_z[qp](1)) ); strain_increment.zx( 0.5*(_grad_disp_z[qp](0)+_grad_disp_x[qp](2)) ); if (_large_strain) { strain_increment.xx() += 0.5*(_grad_disp_x[qp](0)*_grad_disp_x[qp](0) + _grad_disp_y[qp](0)*_grad_disp_y[qp](0) + _grad_disp_z[qp](0)*_grad_disp_z[qp](0)); strain_increment.yy() += 0.5*(_grad_disp_x[qp](1)*_grad_disp_x[qp](1) + _grad_disp_y[qp](1)*_grad_disp_y[qp](1) + _grad_disp_z[qp](1)*_grad_disp_z[qp](1)); strain_increment.zz() += 0.5*(_grad_disp_x[qp](2)*_grad_disp_x[qp](2) + _grad_disp_y[qp](2)*_grad_disp_y[qp](2) + _grad_disp_z[qp](2)*_grad_disp_z[qp](2)); strain_increment.xy() += 0.5*(_grad_disp_x[qp](0)*_grad_disp_x[qp](1) + _grad_disp_y[qp](0)*_grad_disp_y[qp](1) + _grad_disp_z[qp](0)*_grad_disp_z[qp](1)); strain_increment.yz() += 0.5*(_grad_disp_x[qp](1)*_grad_disp_x[qp](2) + _grad_disp_y[qp](1)*_grad_disp_y[qp](2) + _grad_disp_z[qp](1)*_grad_disp_z[qp](2)); strain_increment.zx() += 0.5*(_grad_disp_x[qp](2)*_grad_disp_x[qp](0) + _grad_disp_y[qp](2)*_grad_disp_y[qp](0) + _grad_disp_z[qp](2)*_grad_disp_z[qp](0)); } if (_volumetric_locking_correction) { // volumetric locking correction - averaging the volumertic strain over the element Real volumetric_strain = 0.0; Real volume = 0.0; for (unsigned int qp_loop = 0; qp_loop < _solid_model.qrule()->n_points(); ++qp_loop) { volumetric_strain += (_grad_disp_x[qp_loop](0) + _grad_disp_y[qp_loop](1) + _grad_disp_z[qp_loop](2)) / 3.0 * _solid_model.JxW(qp_loop); volume += _solid_model.JxW(qp_loop); if (_large_strain) { volumetric_strain += 0.5 * (_grad_disp_x[qp](0) * _grad_disp_x[qp](0) + _grad_disp_y[qp](0) * _grad_disp_y[qp](0) + _grad_disp_z[qp](0) * _grad_disp_z[qp](0)) / 3.0 * _solid_model.JxW(qp_loop); volumetric_strain += 0.5 * (_grad_disp_x[qp](1) * _grad_disp_x[qp](1) + _grad_disp_y[qp](1) * _grad_disp_y[qp](1) + _grad_disp_z[qp](1) * _grad_disp_z[qp](1)) / 3.0 * _solid_model.JxW(qp_loop); volumetric_strain += 0.5 * (_grad_disp_x[qp](2) * _grad_disp_x[qp](2) + _grad_disp_y[qp](2) * _grad_disp_y[qp](2) + _grad_disp_z[qp](2) * _grad_disp_z[qp](2)) / 3.0 * _solid_model.JxW(qp_loop); } } volumetric_strain /= volume; // average volumetric strain // strain increment at _qp Real trace = strain_increment.trace(); strain_increment.xx() += volumetric_strain - trace / 3.0; strain_increment.yy() += volumetric_strain - trace / 3.0; strain_increment.zz() += volumetric_strain - trace / 3.0; } total_strain_new = strain_increment; strain_increment -= total_strain_old; }
Real component(const SymmTensor & symm_tensor, unsigned int index) { return symm_tensor.component(index); }