RankTwoTensor TensorMechanicsPlasticMeanCapTC::df_dsig(const RankTwoTensor & stress, Real intnl) const { const Real tr = stress.trace(); const Real t_str = tensile_strength(intnl); if (tr >= t_str) return stress.dtrace(); const Real c_str = compressive_strength(intnl); if (tr <= c_str) return -stress.dtrace(); return - std::cos(M_PI * (tr - c_str) / (t_str - c_str)) * stress.dtrace(); }
RankTwoTensor TensorMechanicsPlasticTensile::dyieldFunction_dstress(const RankTwoTensor & stress, Real /*intnl*/) const { Real mean_stress = stress.trace() / 3.0; RankTwoTensor dmean_stress = stress.dtrace() / 3.0; Real sin3Lode = stress.sin3Lode(_lode_cutoff, 0); if (sin3Lode <= _sin3tt) { // the non-edge-smoothed version std::vector<Real> eigvals; std::vector<RankTwoTensor> deigvals; stress.dsymmetricEigenvalues(eigvals, deigvals); Real denom = std::sqrt(smooth(stress) + Utility::pow<2>(eigvals[2] - mean_stress)); return dmean_stress + (0.5 * dsmooth(stress) * dmean_stress + (eigvals[2] - mean_stress) * (deigvals[2] - dmean_stress)) / denom; } else { // the edge-smoothed version Real kk = _aaa + _bbb * sin3Lode + _ccc * Utility::pow<2>(sin3Lode); RankTwoTensor dkk = (_bbb + 2.0 * _ccc * sin3Lode) * stress.dsin3Lode(_lode_cutoff); Real sibar2 = stress.secondInvariant(); RankTwoTensor dsibar2 = stress.dsecondInvariant(); Real denom = std::sqrt(smooth(stress) + sibar2 * Utility::pow<2>(kk)); return dmean_stress + (0.5 * dsmooth(stress) * dmean_stress + 0.5 * dsibar2 * Utility::pow<2>(kk) + sibar2 * kk * dkk) / denom; } }
RankTwoTensor TensorMechanicsPlasticDruckerPrager::dflowPotential_dintnl(const RankTwoTensor & stress, Real intnl) const { Real dbbb; donlyB(intnl, dilation, dbbb); return stress.dtrace() * dbbb; }
RankFourTensor TensorMechanicsPlasticTensile::dflowPotential_dstress(const RankTwoTensor & stress, const Real & intnl) const { Real mean_stress = stress.trace()/3.0; RankTwoTensor dmean_stress = stress.dtrace()/3.0; Real sin3Lode = stress.sin3Lode(_lode_cutoff, 0); if (sin3Lode <= _sin3tt) { // the non-edge-smoothed version std::vector<Real> eigvals; std::vector<RankTwoTensor> deigvals; std::vector<RankFourTensor> d2eigvals; stress.dsymmetricEigenvalues(eigvals, deigvals); stress.d2symmetricEigenvalues(d2eigvals); Real denom = std::sqrt(_small_smoother2 + std::pow(eigvals[2] - mean_stress, 2)); RankFourTensor dr_dstress = (eigvals[2] - mean_stress)*d2eigvals[2]/denom; for (unsigned i = 0 ; i < 3 ; ++i) for (unsigned j = 0 ; j < 3 ; ++j) for (unsigned k = 0 ; k < 3 ; ++k) for (unsigned l = 0 ; l < 3 ; ++l) dr_dstress(i, j, k, l) += (1 - std::pow((eigvals[2] - mean_stress)/denom, 2))*(deigvals[2](i, j) - dmean_stress(i, j))*(deigvals[2](k, l) - dmean_stress(k, l))/denom; return dr_dstress; } else { // the edge-smoothed version RankTwoTensor dsin3Lode = stress.dsin3Lode(_lode_cutoff); Real kk = _aaa + _bbb*sin3Lode + _ccc*std::pow(sin3Lode, 2); RankTwoTensor dkk = (_bbb + 2*_ccc*sin3Lode)*dsin3Lode; RankFourTensor d2kk = (_bbb + 2*_ccc*sin3Lode)*stress.d2sin3Lode(_lode_cutoff); for (unsigned i = 0 ; i < 3 ; ++i) for (unsigned j = 0 ; j < 3 ; ++j) for (unsigned k = 0 ; k < 3 ; ++k) for (unsigned l = 0 ; l < 3 ; ++l) d2kk(i, j, k, l) += 2*_ccc*dsin3Lode(i, j)*dsin3Lode(k, l); Real sibar2 = stress.secondInvariant(); RankTwoTensor dsibar2 = stress.dsecondInvariant(); RankFourTensor d2sibar2 = stress.d2secondInvariant(); Real denom = std::sqrt(_small_smoother2 + sibar2*std::pow(kk, 2)); RankFourTensor dr_dstress = (0.5*d2sibar2*std::pow(kk, 2) + sibar2*kk*d2kk)/denom; for (unsigned i = 0 ; i < 3 ; ++i) for (unsigned j = 0 ; j < 3 ; ++j) for (unsigned k = 0 ; k < 3 ; ++k) for (unsigned l = 0 ; l < 3 ; ++l) { dr_dstress(i, j, k, l) += (dsibar2(i, j)*dkk(k, l)*kk + dkk(i, j)*dsibar2(k, l)*kk + sibar2*dkk(i, j)*dkk(k, l))/denom; dr_dstress(i, j, k, l) -= (0.5*dsibar2(i, j)*std::pow(kk, 2) + sibar2*kk*dkk(i, j))*(0.5*dsibar2(k, l)*std::pow(kk, 2) + sibar2*kk*dkk(k, l))/std::pow(denom, 3); } return dr_dstress; } }
RankFourTensor TensorMechanicsPlasticMeanCapTC::dflowPotential_dstress(const RankTwoTensor & stress, Real intnl) const { const Real tr = stress.trace(); const Real t_str = tensile_strength(intnl); if (tr >= t_str) return RankFourTensor(); const Real c_str = compressive_strength(intnl); if (tr <= c_str) return RankFourTensor(); return M_PI / (t_str - c_str) * std::sin(M_PI * (tr - c_str) / (t_str - c_str)) * stress.dtrace().outerProduct(stress.dtrace()); }
RankTwoTensor TensorMechanicsPlasticMeanCapTC::dflowPotential_dintnl(const RankTwoTensor & stress, Real intnl) const { const Real tr = stress.trace(); const Real t_str = tensile_strength(intnl); if (tr >= t_str) return RankTwoTensor(); const Real c_str = compressive_strength(intnl); if (tr <= c_str) return RankTwoTensor(); const Real dt = dtensile_strength(intnl); const Real dc = dcompressive_strength(intnl); return std::sin(M_PI * (tr - c_str) / (t_str - c_str)) * stress.dtrace() * M_PI / std::pow(t_str - c_str, 2) * ((tr - t_str) * dc - (tr - c_str) * dt); }
RankFourTensor TensorMechanicsPlasticTensile::dflowPotential_dstress(const RankTwoTensor & stress, Real /*intnl*/) const { Real mean_stress = stress.trace() / 3.0; RankTwoTensor dmean_stress = stress.dtrace() / 3.0; Real sin3Lode = stress.sin3Lode(_lode_cutoff, 0); if (sin3Lode <= _sin3tt) { // the non-edge-smoothed version std::vector<Real> eigvals; std::vector<RankTwoTensor> deigvals; std::vector<RankFourTensor> d2eigvals; stress.dsymmetricEigenvalues(eigvals, deigvals); stress.d2symmetricEigenvalues(d2eigvals); Real denom = std::sqrt(smooth(stress) + Utility::pow<2>(eigvals[2] - mean_stress)); Real denom3 = Utility::pow<3>(denom); RankTwoTensor numer_part = deigvals[2] - dmean_stress; RankTwoTensor numer_full = 0.5 * dsmooth(stress) * dmean_stress + (eigvals[2] - mean_stress) * numer_part; Real d2smooth_over_denom = d2smooth(stress) / denom; RankFourTensor dr_dstress = (eigvals[2] - mean_stress) * d2eigvals[2] / denom; for (unsigned i = 0; i < 3; ++i) for (unsigned j = 0; j < 3; ++j) for (unsigned k = 0; k < 3; ++k) for (unsigned l = 0; l < 3; ++l) { dr_dstress(i, j, k, l) += 0.5 * d2smooth_over_denom * dmean_stress(i, j) * dmean_stress(k, l); dr_dstress(i, j, k, l) += numer_part(i, j) * numer_part(k, l) / denom; dr_dstress(i, j, k, l) -= numer_full(i, j) * numer_full(k, l) / denom3; } return dr_dstress; } else { // the edge-smoothed version RankTwoTensor dsin3Lode = stress.dsin3Lode(_lode_cutoff); Real kk = _aaa + _bbb * sin3Lode + _ccc * Utility::pow<2>(sin3Lode); RankTwoTensor dkk = (_bbb + 2.0 * _ccc * sin3Lode) * dsin3Lode; RankFourTensor d2kk = (_bbb + 2.0 * _ccc * sin3Lode) * stress.d2sin3Lode(_lode_cutoff); for (unsigned i = 0; i < 3; ++i) for (unsigned j = 0; j < 3; ++j) for (unsigned k = 0; k < 3; ++k) for (unsigned l = 0; l < 3; ++l) d2kk(i, j, k, l) += 2.0 * _ccc * dsin3Lode(i, j) * dsin3Lode(k, l); Real sibar2 = stress.secondInvariant(); RankTwoTensor dsibar2 = stress.dsecondInvariant(); RankFourTensor d2sibar2 = stress.d2secondInvariant(); Real denom = std::sqrt(smooth(stress) + sibar2 * Utility::pow<2>(kk)); Real denom3 = Utility::pow<3>(denom); Real d2smooth_over_denom = d2smooth(stress) / denom; RankTwoTensor numer_full = 0.5 * dsmooth(stress) * dmean_stress + 0.5 * dsibar2 * kk * kk + sibar2 * kk * dkk; RankFourTensor dr_dstress = (0.5 * d2sibar2 * Utility::pow<2>(kk) + sibar2 * kk * d2kk) / denom; for (unsigned i = 0; i < 3; ++i) for (unsigned j = 0; j < 3; ++j) for (unsigned k = 0; k < 3; ++k) for (unsigned l = 0; l < 3; ++l) { dr_dstress(i, j, k, l) += 0.5 * d2smooth_over_denom * dmean_stress(i, j) * dmean_stress(k, l); dr_dstress(i, j, k, l) += (dsibar2(i, j) * dkk(k, l) * kk + dkk(i, j) * dsibar2(k, l) * kk + sibar2 * dkk(i, j) * dkk(k, l)) / denom; dr_dstress(i, j, k, l) -= numer_full(i, j) * numer_full(k, l) / denom3; } return dr_dstress; } }
RankTwoTensor TensorMechanicsPlasticDruckerPrager::df_dsig(const RankTwoTensor & stress, Real bbb) const { return 0.5 * stress.dsecondInvariant() / std::sqrt(stress.secondInvariant()) + stress.dtrace() * bbb; }
bool TensorMechanicsPlasticMeanCapTC::returnMap(const RankTwoTensor & trial_stress, Real intnl_old, const RankFourTensor & E_ijkl, Real ep_plastic_tolerance, RankTwoTensor & returned_stress, Real & returned_intnl, std::vector<Real> & dpm, RankTwoTensor & delta_dp, std::vector<Real> & yf, bool & trial_stress_inadmissible) const { if (!(_use_custom_returnMap)) return TensorMechanicsPlasticModel::returnMap(trial_stress, intnl_old, E_ijkl, ep_plastic_tolerance, returned_stress, returned_intnl, dpm, delta_dp, yf, trial_stress_inadmissible); yf.resize(1); Real yf_orig = yieldFunction(trial_stress, intnl_old); yf[0] = yf_orig; if (yf_orig < _f_tol) { // the trial_stress is admissible trial_stress_inadmissible = false; return true; } trial_stress_inadmissible = true; // In the following we want to solve // trial_stress - stress = E_ijkl * dpm * r ...... (1) // and either // stress.trace() = tensile_strength(intnl) ...... (2a) // intnl = intnl_old + dpm ...... (3a) // or // stress.trace() = compressive_strength(intnl) ... (2b) // intnl = intnl_old - dpm ...... (3b) // The former (2a and 3a) are chosen if // trial_stress.trace() > tensile_strength(intnl_old) // while the latter (2b and 3b) are chosen if // trial_stress.trace() < compressive_strength(intnl_old) // The variables we want to solve for are stress, dpm // and intnl. We do this using a Newton approach, starting // with stress=trial_stress and intnl=intnl_old and dpm=0 const bool tensile_failure = (trial_stress.trace() >= tensile_strength(intnl_old)); const Real dirn = (tensile_failure ? 1.0 : -1.0); RankTwoTensor n; // flow direction, which is E_ijkl * r for (unsigned i = 0; i < 3; ++i) for (unsigned j = 0; j < 3; ++j) for (unsigned k = 0; k < 3; ++k) n(i, j) += dirn * E_ijkl(i, j, k, k); const Real n_trace = n.trace(); // Perform a Newton-Raphson to find dpm when // residual = trial_stress.trace() - tensile_strength(intnl) - dpm * n.trace() [for tensile_failure=true] // or // residual = trial_stress.trace() - compressive_strength(intnl) - dpm * n.trace() [for tensile_failure=false] Real trial_trace = trial_stress.trace(); Real residual; Real jac; dpm[0] = 0; unsigned int iter = 0; do { if (tensile_failure) { residual = trial_trace - tensile_strength(intnl_old + dpm[0]) - dpm[0] * n_trace; jac = -dtensile_strength(intnl_old + dpm[0]) - n_trace; } else { residual = trial_trace - compressive_strength(intnl_old - dpm[0]) - dpm[0] * n_trace; jac = -dcompressive_strength(intnl_old - dpm[0]) - n_trace; } dpm[0] += -residual/jac; if (iter > _max_iters) // not converging return false; iter++; } while (residual*residual > _f_tol*_f_tol); // set the returned values yf[0] = 0; returned_intnl = intnl_old + dirn * dpm[0]; returned_stress = trial_stress - dpm[0] * n; delta_dp = dpm[0] * dirn * returned_stress.dtrace(); return true; }