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 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)); strain_increment.yz() = 0; strain_increment.zx() = 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; }
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; }
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 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 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; }
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) ); }
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 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 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; }
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 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); }
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; }
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; }
Real MaterialTensorAux::getTensorQuantity(const SymmTensor & tensor, const MTA_ENUM quantity, const MooseEnum & quantity_moose_enum, const int index, const Point * curr_point, const Point * p1, const Point * p2) { Real value(0); if (quantity == MTA_COMPONENT) { value = tensor.component(index); } else if ( quantity == MTA_VONMISES ) { value = std::sqrt(0.5*( std::pow(tensor.xx() - tensor.yy(), 2) + std::pow(tensor.yy() - tensor.zz(), 2) + std::pow(tensor.zz() - tensor.xx(), 2) + 6 * ( std::pow(tensor.xy(), 2) + std::pow(tensor.yz(), 2) + std::pow(tensor.zx(), 2)))); } else if ( quantity == MTA_PLASTICSTRAINMAG ) { value = std::sqrt(2.0/3.0 * tensor.doubleContraction(tensor)); } else if ( quantity == MTA_HYDROSTATIC ) { value = tensor.trace()/3.0; } else if ( quantity == MTA_HOOP ) { // This is the location of the stress. A vector from the cylindrical axis to this point will define the x' axis. Point p0( *curr_point ); // The vector p1 + t*(p2-p1) defines the cylindrical axis. The point along this // axis closest to p0 is found by the following for t: const Point p2p1( *p2 - *p1 ); const Point p2p0( *p2 - p0 ); const Point p1p0( *p1 - p0 ); const Real t( -(p1p0*p2p1)/p2p1.size_sq() ); // The nearest point on the cylindrical axis to p0 is p. const Point p( *p1 + t * p2p1 ); Point xp( p0 - p ); xp /= xp.size(); Point yp( p2p1/p2p1.size() ); Point zp( xp.cross( yp )); // // The following works but does more than we need // // // Rotation matrix R // ColumnMajorMatrix R(3,3); // // Fill with direction cosines // R(0,0) = xp(0); // R(1,0) = xp(1); // R(2,0) = xp(2); // R(0,1) = yp(0); // R(1,1) = yp(1); // R(2,1) = yp(2); // R(0,2) = zp(0); // R(1,2) = zp(1); // R(2,2) = zp(2); // // Rotate // ColumnMajorMatrix tensor( _tensor[_qp].columnMajorMatrix() ); // ColumnMajorMatrix tensorp( R.transpose() * ( tensor * R )); // // Hoop stress is the zz stress // value = tensorp(2,2); // // Instead, tensorp(2,2) = R^T(2,:)*tensor*R(:,2) // const Real zp0( zp(0) ); const Real zp1( zp(1) ); const Real zp2( zp(2) ); value = (zp0*tensor(0,0)+zp1*tensor(1,0)+zp2*tensor(2,0))*zp0 + (zp0*tensor(0,1)+zp1*tensor(1,1)+zp2*tensor(2,1))*zp1 + (zp0*tensor(0,2)+zp1*tensor(1,2)+zp2*tensor(2,2))*zp2; } else if ( quantity == MTA_RADIAL ) { // This is the location of the stress. A vector from the cylindrical axis to this point will define the x' axis // which is the radial direction in which we want the stress. Point p0( *curr_point ); // The vector p1 + t*(p2-p1) defines the cylindrical axis. The point along this // axis closest to p0 is found by the following for t: const Point p2p1( *p2 - *p1 ); const Point p2p0( *p2 - p0 ); const Point p1p0( *p1 - p0 ); const Real t( -(p1p0*p2p1)/p2p1.size_sq() ); // The nearest point on the cylindrical axis to p0 is p. const Point p( *p1 + t * p2p1 ); Point xp( p0 - p ); xp /= xp.size(); const Real xp0( xp(0) ); const Real xp1( xp(1) ); const Real xp2( xp(2) ); value = (xp0*tensor(0,0)+xp1*tensor(1,0)+xp2*tensor(2,0))*xp0 + (xp0*tensor(0,1)+xp1*tensor(1,1)+xp2*tensor(2,1))*xp1 + (xp0*tensor(0,2)+xp1*tensor(1,2)+xp2*tensor(2,2))*xp2; } else if ( quantity == MTA_AXIAL ) { // The vector p2p1=(p2-p1) defines the axis, which is the direction in which we want the stress. Point p2p1( *p2 - *p1 ); p2p1 /= p2p1.size(); const Real axis0( p2p1(0) ); const Real axis1( p2p1(1) ); const Real axis2( p2p1(2) ); value = (axis0*tensor(0,0)+axis1*tensor(1,0)+axis2*tensor(2,0))*axis0 + (axis0*tensor(0,1)+axis1*tensor(1,1)+axis2*tensor(2,1))*axis1 + (axis0*tensor(0,2)+axis1*tensor(1,2)+axis2*tensor(2,2))*axis2; } else if ( quantity == MTA_MAXPRINCIPAL ) { value = principalValue( tensor, 0 ); } else if ( quantity == MTA_MEDPRINCIPAL ) { value = principalValue( tensor, 1 ); } else if ( quantity == MTA_MINPRINCIPAL ) { value = principalValue( tensor, 2 ); } else if ( quantity == MTA_FIRSTINVARIANT ) { value = tensor.trace(); } else if ( quantity == MTA_SECONDINVARIANT ) { value = tensor.xx()*tensor.yy() + tensor.yy()*tensor.zz() + tensor.zz()*tensor.xx() - tensor.xy()*tensor.xy() - tensor.yz()*tensor.yz() - tensor.zx()*tensor.zx(); } else if ( quantity == MTA_THIRDINVARIANT ) { value = tensor.xx()*tensor.yy()*tensor.zz() - tensor.xx()*tensor.yz()*tensor.yz() + tensor.xy()*tensor.zx()*tensor.yz() - tensor.xy()*tensor.xy()*tensor.zz() + tensor.zx()*tensor.xy()*tensor.yz() - tensor.zx()*tensor.zx()*tensor.yy(); } else if ( quantity == MTA_TRIAXIALITY ) { Real hydrostatic = tensor.trace()/3.0; Real von_mises = std::sqrt(0.5*( std::pow(tensor.xx() - tensor.yy(), 2) + std::pow(tensor.yy() - tensor.zz(), 2) + std::pow(tensor.zz() - tensor.xx(), 2) + 6 * ( std::pow(tensor.xy(), 2) + std::pow(tensor.yz(), 2) + std::pow(tensor.zx(), 2)))); value = std::abs(hydrostatic / von_mises); } else if ( quantity == MTA_VOLUMETRICSTRAIN ) { value = tensor.trace() + tensor.xx()*tensor.yy() + tensor.yy()*tensor.zz() + tensor.zz()*tensor.xx() + tensor.xx()*tensor.yy()*tensor.zz(); } else { mooseError("Unknown quantity in MaterialTensorAux: " + quantity_moose_enum.operator std::string()); } return value; }
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); if (_have_strain_zz) strain_increment.zz() = _strain_zz[qp]; else if (_have_scalar_strain_zz && _scalar_strain_zz.size()>0) strain_increment.zz() = _scalar_strain_zz[0]; else 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)); } if (_volumetric_locking_correction) { // volumetric locking correction Real volumetric_strain = 0.0; Real volume = 0.0; Real dim = 3.0; for (unsigned int qp_loop = 0; qp_loop < _solid_model.qrule()->n_points(); ++qp_loop) { if (_have_strain_zz) volumetric_strain += (_grad_disp_x[qp_loop](0) + _grad_disp_y[qp_loop](1) + _strain_zz[qp_loop]) / dim * _solid_model.JxW(qp_loop); else if (_have_scalar_strain_zz && _scalar_strain_zz.size() > 0) volumetric_strain += (_grad_disp_x[qp_loop](0) + _grad_disp_y[qp_loop](1) + _scalar_strain_zz[0]) / dim * _solid_model.JxW(qp_loop); else volumetric_strain += (_grad_disp_x[qp_loop](0) + _grad_disp_y[qp_loop](1)) / dim * _solid_model.JxW(qp_loop); volume += _solid_model.JxW(qp_loop); if (_large_strain) { volumetric_strain += 0.5 * (_grad_disp_x[qp_loop](0) * _grad_disp_x[qp_loop](0) + _grad_disp_y[qp_loop](0) * _grad_disp_y[qp_loop](0)) / dim * _solid_model.JxW(qp_loop); volumetric_strain += 0.5 * (_grad_disp_x[qp_loop](1) * _grad_disp_x[qp_loop](1) + _grad_disp_y[qp_loop](1) * _grad_disp_y[qp_loop](1)) / dim * _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 / dim; strain_increment.yy() += volumetric_strain - trace / dim; strain_increment.zz() += volumetric_strain - trace / dim; } total_strain_new = strain_increment; strain_increment -= total_strain_old; }
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; }
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; }