void ComputeFiniteStrain::computeQpStrain() { // inverse of _Fhat RankTwoTensor invFhat(_Fhat[_qp].inverse()); // A = I - _Fhat^-1 RankTwoTensor A(RankTwoTensor::initIdentity); A -= invFhat; // Cinv - I = A A^T - A - A^T; RankTwoTensor Cinv_I = A * A.transpose() - A - A.transpose(); // strain rate D from Taylor expansion, Chat = (-1/2(Chat^-1 - I) + 1/4*(Chat^-1 - I)^2 + ... RankTwoTensor total_strain_increment = -Cinv_I * 0.5 + Cinv_I * Cinv_I * 0.25; _strain_increment[_qp] = total_strain_increment; if (_no_thermal_eigenstrains) //Deprecated; use ComputeThermalExpansionEigenStrains instead { if (_t_step >= 2) _step_one = false; if (_step_one) _strain_increment[_qp].addIa(-_thermal_expansion_coeff * (_T[_qp] - _T0)); else _strain_increment[_qp].addIa(-_thermal_expansion_coeff * (_T[_qp] - _T_old[_qp])); } // Remove the Eigen strain increment _strain_increment[_qp] -= _stress_free_strain_increment[_qp]; RankTwoTensor D = _strain_increment[_qp] / _dt; _strain_rate[_qp] = D; const Real a[3] = { invFhat(1,2) - invFhat(2,1), invFhat(2,0) - invFhat(0,2), invFhat(0,1) - invFhat(1,0) }; Real q = (a[0]*a[0] + a[1]*a[1] + a[2]*a[2]) / 4.0; Real trFhatinv_1 = invFhat.trace() - 1.0; const Real p = trFhatinv_1 * trFhatinv_1 / 4.0; // cos theta_a const Real C1 = std::sqrt(p + 3.0*p*p*(1.0 - (p + q))/((p+q)*(p+q)) - 2.0*p*p*p*(1-(p+q))/((p+q)*(p+q)*(p+q))); Real C2; if (q > 0.01) // (1-cos theta_a)/4q C2 = (1.0 - C1) / (4.0 * q); else //alternate form for small q C2 = 0.125 + q * 0.03125 * (p*p - 12 * (p-1)) / (p*p) + q*q * (p - 2.0) * (p*p - 10.0 * p + 32.0) / (p*p*p) + q*q*q * (1104.0 - 992.0 * p + 376.0 * p*p - 72 * p*p*p + 5.0 * p*p*p*p) / (512.0*p*p*p*p); const Real C3 = 0.5 * std::sqrt((p * q * (3.0 - q) + p*p*p + q*q) / ((p + q) * (p + q) * (p + q))); //sin theta_a/(2 sqrt(q)) // Calculate incremental rotation. Note that this value is the transpose of that from Rashid, 93, so we transpose it before storing RankTwoTensor R_incr; R_incr.addIa(C1); for (unsigned int i = 0; i < 3; ++i) for (unsigned int j = 0; j < 3; ++j) R_incr(i,j) += C2 * a[i] * a[j]; R_incr(0,1) += C3 * a[2]; R_incr(0,2) -= C3 * a[1]; R_incr(1,0) -= C3 * a[2]; R_incr(1,2) += C3 * a[0]; R_incr(2,0) += C3 * a[1]; R_incr(2,1) -= C3 * a[0]; _rotation_increment[_qp] = R_incr.transpose(); //Update strain in intermediate configuration _mechanical_strain[_qp] = _mechanical_strain_old[_qp] + _strain_increment[_qp]; _total_strain[_qp] = _total_strain_old[_qp] + total_strain_increment; //Rotate strain to current configuration _mechanical_strain[_qp] = _rotation_increment[_qp] * _mechanical_strain[_qp] * _rotation_increment[_qp].transpose(); _total_strain[_qp] = _rotation_increment[_qp] * _total_strain[_qp] * _rotation_increment[_qp].transpose(); }
void FiniteStrainMaterial::computeQpStrain(const RankTwoTensor & Fhat) { //Cinv - I = A A^T - A - A^T; RankTwoTensor A; //A = I - Fhatinv A.addIa(1.0); A -= Fhat.inverse(); RankTwoTensor Cinv_I = A*A.transpose() - A - A.transpose(); //strain rate D from Taylor expansion, Chat = (-1/2(Chat^-1 - I) + 1/4*(Chat^-1 - I)^2 + ... _strain_increment[_qp] = -Cinv_I*0.5 + Cinv_I*Cinv_I*0.25; /*RankTwoTensor Chat = Fhat.transpose()*Fhat; RankTwoTensor A = Chat; A.addIa(-1.0); RankTwoTensor B = Chat*0.25; B.addIa(-0.75); _strain_increment[_qp] = -B*A;*/ RankTwoTensor D = _strain_increment[_qp]/_t_step; _strain_rate[_qp] = D; //Calculate rotation R_incr RankTwoTensor invFhat(Fhat.inverse()); std::vector<Real> a(3); a[0] = invFhat(1,2) - invFhat(2,1); a[1] = invFhat(2,0) - invFhat(0,2); a[2] = invFhat(0,1) - invFhat(1,0); Real q = (a[0]*a[0] + a[1]*a[1] + a[2]*a[2])/4.0; Real trFhatinv_1 = invFhat.trace() - 1.0; Real p = trFhatinv_1*trFhatinv_1/4.0; // Real y = 1.0/((q + p)*(q + p)*(q + p)); /*Real C1 = std::sqrt(p * (1 + (p*(q+q+(q+p))) * (1-(q+p)) * y)); Real C2 = 0.125 + q * 0.03125 * (p*p - 12*(p-1)) / (p*p); Real C3 = 0.5 * std::sqrt( (p*q*(3-q) + p*p*p + q*q)*y ); */ Real C1 = std::sqrt(p + 3.0*p*p*(1.0 - (p + q))/((p+q)*(p+q)) - 2.0*p*p*p*(1-(p+q))/((p+q)*(p+q)*(p+q))); //cos theta_a Real C2 = 0.0; if (q > 0.01) C2 = (1.0 - C1)/(4.0*q); // (1-cos theta_a)/4q else //alternate form for small q C2 = 0.125 + q*0.03125*(p*p - 12*(p-1))/(p*p) + q*q*(p - 2.0)*(p*p - 10.0*p + 32.0)/(p*p*p) + q*q*q*(1104.0 - 992.0*p + 376.0*p*p - 72*p*p*p + 5.0*p*p*p*p)/(512.0*p*p*p*p); Real C3 = 0.5*std::sqrt((p*q*(3.0 - q) + p*p*p + q*q)/((p + q)*(p + q)*(p + q))); //sin theta_a/(2 sqrt(q)) //Calculate incremental rotation. Note that this value is the transpose of that from Rashid, 93, so we transpose it before storing RankTwoTensor R_incr; R_incr.addIa(C1); for (unsigned int i=0; i<3; ++i) for (unsigned int j = 0; j < 3; ++j) R_incr(i,j) += C2*a[i]*a[j]; R_incr(0,1) += C3*a[2]; R_incr(0,2) -= C3*a[1]; R_incr(1,0) -= C3*a[2]; R_incr(1,2) += C3*a[0]; R_incr(2,0) += C3*a[1]; R_incr(2,1) -= C3*a[0]; _rotation_increment[_qp] = R_incr.transpose(); }
void ComputeFiniteStrain::computeQpIncrements(RankTwoTensor & total_strain_increment, RankTwoTensor & rotation_increment) { switch (_decomposition_method) { case DecompMethod::TaylorExpansion: { // inverse of _Fhat RankTwoTensor invFhat(_Fhat[_qp].inverse()); // A = I - _Fhat^-1 RankTwoTensor A(RankTwoTensor::initIdentity); A -= invFhat; // Cinv - I = A A^T - A - A^T; RankTwoTensor Cinv_I = A * A.transpose() - A - A.transpose(); // strain rate D from Taylor expansion, Chat = (-1/2(Chat^-1 - I) + 1/4*(Chat^-1 - I)^2 + ... total_strain_increment = -Cinv_I * 0.5 + Cinv_I * Cinv_I * 0.25; const Real a[3] = { invFhat(1, 2) - invFhat(2, 1), invFhat(2, 0) - invFhat(0, 2), invFhat(0, 1) - invFhat(1, 0) }; Real q = (a[0] * a[0] + a[1] * a[1] + a[2] * a[2]) / 4.0; Real trFhatinv_1 = invFhat.trace() - 1.0; const Real p = trFhatinv_1 * trFhatinv_1 / 4.0; // cos theta_a const Real C1 = std::sqrt(p + 3.0 * std::pow(p, 2.0) * (1.0 - (p + q)) / std::pow(p + q, 2.0) - 2.0 * std::pow(p, 3.0) * (1.0 - (p + q)) / std::pow(p + q, 3.0)); Real C2; if (q > 0.01) // (1-cos theta_a)/4q C2 = (1.0 - C1) / (4.0 * q); else //alternate form for small q C2 = 0.125 + q * 0.03125 * (std::pow(p, 2.0) - 12.0 * (p - 1.0)) / std::pow(p, 2.0) + std::pow(q, 2.0) * (p - 2.0) * (std::pow(p, 2.0) - 10.0 * p + 32.0) / std::pow(p, 3.0) + std::pow(q, 3.0) * (1104.0 - 992.0 * p + 376.0 * std::pow(p, 2.0) - 72.0 * std::pow(p, 3.0) + 5.0 * std::pow(p, 4.0)) / (512.0 * std::pow(p, 4.0)); const Real C3 = 0.5 * std::sqrt((p * q * (3.0 - q) + std::pow(p, 3.0) + std::pow(q, 2.0)) / std::pow(p + q, 3.0)); //sin theta_a/(2 sqrt(q)) // Calculate incremental rotation. Note that this value is the transpose of that from Rashid, 93, so we transpose it before storing RankTwoTensor R_incr; R_incr.addIa(C1); for (unsigned int i = 0; i < 3; ++i) for (unsigned int j = 0; j < 3; ++j) R_incr(i,j) += C2 * a[i] * a[j]; R_incr(0,1) += C3 * a[2]; R_incr(0,2) -= C3 * a[1]; R_incr(1,0) -= C3 * a[2]; R_incr(1,2) += C3 * a[0]; R_incr(2,0) += C3 * a[1]; R_incr(2,1) -= C3 * a[0]; rotation_increment = R_incr.transpose(); break; } case DecompMethod::EigenSolution: { std::vector<Real> e_value(3); RankTwoTensor e_vector, N1, N2, N3; RankTwoTensor Chat = _Fhat[_qp].transpose() * _Fhat[_qp]; Chat.symmetricEigenvaluesEigenvectors(e_value, e_vector); const Real lambda1 = std::sqrt(e_value[0]); const Real lambda2 = std::sqrt(e_value[1]); const Real lambda3 = std::sqrt(e_value[2]); N1.vectorOuterProduct(e_vector.column(0), e_vector.column(0)); N2.vectorOuterProduct(e_vector.column(1), e_vector.column(1)); N3.vectorOuterProduct(e_vector.column(2), e_vector.column(2)); RankTwoTensor Uhat = N1 * lambda1 + N2 * lambda2 + N3 * lambda3; RankTwoTensor invUhat(Uhat.inverse()); rotation_increment = _Fhat[_qp] * invUhat; total_strain_increment = N1 * std::log(lambda1) + N2 * std::log(lambda2) + N3 * std::log(lambda3); break; } default: mooseError("ComputeFiniteStrain Error: Pass valid decomposition type: TaylorExpansion or EigenSolution."); } }