https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SolidMechanicsPlasticDruckerPragerHyperbolic.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
11#include "RankFourTensor.h"
12#include "libmesh/utility.h"
13
15registerMooseObjectRenamed("SolidMechanicsApp",
16 TensorMechanicsPlasticDruckerPragerHyperbolic,
17 "01/01/2025 00:00",
19
22{
24 params.addParam<bool>("use_custom_returnMap",
25 true,
26 "Whether to use the custom returnMap "
27 "algorithm. Set to true if you are using "
28 "isotropic elasticity.");
29 params.addParam<bool>("use_custom_cto",
30 true,
31 "Whether to use the custom consistent tangent "
32 "operator computations. Set to true if you are "
33 "using isotropic elasticity.");
34 params.addClassDescription("J2 plasticity, associative, with hardening");
35 params.addRangeCheckedParam<Real>("smoother",
36 0.0,
37 "smoother>=0",
38 "The cone vertex at J2=0 is smoothed. The maximum mean "
39 "stress possible, which is Cohesion*Cot(friction_angle) for "
40 "smoother=0, becomes (Cohesion - "
41 "smoother/3)*Cot(friction_angle). This is a non-hardening "
42 "parameter");
43 params.addRangeCheckedParam<unsigned>(
44 "max_iterations",
45 40,
46 "max_iterations>0",
47 "Maximum iterations to use in the custom return map function");
49 "Non-associative Drucker Prager plasticity with hyperbolic smoothing of the cone tip.");
50 return params;
51}
52
54 const InputParameters & parameters)
56 _smoother2(Utility::pow<2>(getParam<Real>("smoother"))),
57 _use_custom_returnMap(getParam<bool>("use_custom_returnMap")),
58 _use_custom_cto(getParam<bool>("use_custom_cto")),
59 _max_iters(getParam<unsigned>("max_iterations"))
60{
61}
62
63Real
65 Real intnl) const
66{
67 Real aaa;
68 Real bbb;
69 bothAB(intnl, aaa, bbb);
70 return std::sqrt(stress.secondInvariant() + _smoother2) + stress.trace() * bbb - aaa;
71}
72
75{
76 return 0.5 * stress.dsecondInvariant() / std::sqrt(stress.secondInvariant() + _smoother2) +
77 stress.dtrace() * bbb;
78}
79
82 Real /*intnl*/) const
83{
84 RankFourTensor dr_dstress;
85 dr_dstress = 0.5 * stress.d2secondInvariant() / std::sqrt(stress.secondInvariant() + _smoother2);
86 dr_dstress += -0.5 * 0.5 * stress.dsecondInvariant().outerProduct(stress.dsecondInvariant()) /
87 std::pow(stress.secondInvariant() + _smoother2, 1.5);
88 return dr_dstress;
89}
90
91std::string
93{
94 return "DruckerPragerHyperbolic";
95}
96
97bool
99 Real intnl_old,
100 const RankFourTensor & E_ijkl,
101 Real ep_plastic_tolerance,
102 RankTwoTensor & returned_stress,
103 Real & returned_intnl,
104 std::vector<Real> & dpm,
105 RankTwoTensor & delta_dp,
106 std::vector<Real> & yf,
107 bool & trial_stress_inadmissible) const
108{
110 return SolidMechanicsPlasticModel::returnMap(trial_stress,
111 intnl_old,
112 E_ijkl,
113 ep_plastic_tolerance,
114 returned_stress,
115 returned_intnl,
116 dpm,
117 delta_dp,
118 yf,
119 trial_stress_inadmissible);
120
121 yf.resize(1);
122
123 yf[0] = yieldFunction(trial_stress, intnl_old);
124
125 if (yf[0] < _f_tol)
126 {
127 // the trial_stress is admissible
128 trial_stress_inadmissible = false;
129 return true;
130 }
131
132 trial_stress_inadmissible = true;
133 const Real mu = E_ijkl(0, 1, 0, 1);
134 const Real lambda = E_ijkl(0, 0, 0, 0) - 2.0 * mu;
135 const Real bulky = 3.0 * lambda + 2.0 * mu;
136 const Real Tr_trial = trial_stress.trace();
137 const Real J2trial = trial_stress.secondInvariant();
138
139 // Perform a Newton-Raphson to find dpm when
140 // residual = (1 + dpm*mu/ll)sqrt(ll^2 - s^2) - sqrt(J2trial) = 0, with s=smoother
141 // with ll = sqrt(J2 + s^2) = aaa - bbb*Tr(stress) = aaa - bbb(Tr_trial - p*3*bulky*bbb_flow)
142 Real aaa;
143 Real daaa;
144 Real bbb;
145 Real dbbb;
146 Real bbb_flow;
147 Real dbbb_flow;
148 Real ll;
149 Real dll;
150 Real residual;
151 Real jac;
152 dpm[0] = 0;
153 unsigned int iter = 0;
154 do
155 {
156 bothAB(intnl_old + dpm[0], aaa, bbb);
157 dbothAB(intnl_old + dpm[0], daaa, dbbb);
158 onlyB(intnl_old + dpm[0], dilation, bbb_flow);
159 donlyB(intnl_old + dpm[0], dilation, dbbb_flow);
160 ll = aaa - bbb * (Tr_trial - dpm[0] * bulky * 3 * bbb_flow);
161 dll = daaa - dbbb * (Tr_trial - dpm[0] * bulky * 3 * bbb_flow) +
162 bbb * bulky * 3 * (bbb_flow + dpm[0] * dbbb_flow);
163 residual = bbb * (Tr_trial - dpm[0] * bulky * 3 * bbb_flow) - aaa +
164 std::sqrt(J2trial / Utility::pow<2>(1 + dpm[0] * mu / ll) + _smoother2);
165 jac = dbbb * (Tr_trial - dpm[0] * bulky * 3 * bbb_flow) -
166 bbb * bulky * 3 * (bbb_flow + dpm[0] * dbbb_flow) - daaa +
167 0.5 * J2trial * (-2.0) * (mu / ll - dpm[0] * mu * dll / ll / ll) /
168 Utility::pow<3>(1 + dpm[0] * mu / ll) /
169 std::sqrt(J2trial / Utility::pow<2>(1.0 + dpm[0] * mu / ll) + _smoother2);
170 dpm[0] += -residual / jac;
171 if (iter > _max_iters) // not converging
172 return false;
173 iter++;
174 } while (residual * residual > _f_tol * _f_tol);
175
176 // set the returned values
177 yf[0] = 0;
178 returned_intnl = intnl_old + dpm[0];
179
180 bothAB(returned_intnl, aaa, bbb);
181 onlyB(returned_intnl, dilation, bbb_flow);
182 ll = aaa - bbb * (Tr_trial - dpm[0] * bulky * 3.0 * bbb_flow);
183 returned_stress =
184 trial_stress.deviatoric() / (1.0 + dpm[0] * mu / ll); // this is the deviatoric part only
185
186 RankTwoTensor rij = 0.5 * returned_stress.deviatoric() /
187 ll; // this is the derivatoric part the flow potential only
188
189 // form the returned stress and the full flow potential
190 const Real returned_trace_over_3 = (aaa - ll) / bbb / 3.0;
191 for (unsigned i = 0; i < 3; ++i)
192 {
193 returned_stress(i, i) += returned_trace_over_3;
194 rij(i, i) += bbb_flow;
195 }
196
197 delta_dp = rij * dpm[0];
198
199 return true;
200}
201
204 const RankTwoTensor & trial_stress,
205 Real intnl_old,
206 const RankTwoTensor & stress,
207 Real intnl,
208 const RankFourTensor & E_ijkl,
209 const std::vector<Real> & cumulative_pm) const
210{
211 if (!_use_custom_cto)
213 trial_stress, intnl_old, stress, intnl, E_ijkl, cumulative_pm);
214
215 const Real mu = E_ijkl(0, 1, 0, 1);
216 const Real la = E_ijkl(0, 0, 0, 0) - 2.0 * mu;
217 const Real bulky = 3.0 * la + 2.0 * mu;
218 Real bbb;
219 onlyB(intnl, friction, bbb);
220 Real bbb_flow;
221 onlyB(intnl, dilation, bbb_flow);
222 Real dbbb_flow;
223 donlyB(intnl, dilation, dbbb_flow);
224 const Real bbb_flow_mod = bbb_flow + cumulative_pm[0] * dbbb_flow;
225 const Real J2 = stress.secondInvariant();
226 const RankTwoTensor sij = stress.deviatoric();
227 const Real sq = std::sqrt(J2 + _smoother2);
228
229 const Real one_over_h =
230 1.0 / (-dyieldFunction_dintnl(stress, intnl) + mu * J2 / Utility::pow<2>(sq) +
231 3.0 * bbb * bbb_flow_mod * bulky); // correct up to hard
232
233 const RankTwoTensor df_dsig_timesE =
234 mu * sij / sq + bulky * bbb * RankTwoTensor(RankTwoTensor::initIdentity); // correct
235 const RankTwoTensor rmod_timesE =
236 mu * sij / sq +
237 bulky * bbb_flow_mod * RankTwoTensor(RankTwoTensor::initIdentity); // correct up to hard
238
239 const RankFourTensor coeff_ep =
240 E_ijkl - one_over_h * rmod_timesE.outerProduct(df_dsig_timesE); // correct
241
242 const RankFourTensor dr_dsig_timesE = -0.5 * mu * sij.outerProduct(sij) / Utility::pow<3>(sq) +
243 mu * stress.d2secondInvariant() / sq; // correct
244 const RankTwoTensor df_dsig_E_dr_dsig =
245 0.5 * mu * _smoother2 * sij / Utility::pow<4>(sq); // correct
246
247 const RankFourTensor coeff_si =
249 cumulative_pm[0] *
250 (dr_dsig_timesE - one_over_h * rmod_timesE.outerProduct(df_dsig_E_dr_dsig));
251
252 RankFourTensor s_inv;
253 try
254 {
255 s_inv = coeff_si.invSymm();
256 }
257 catch (MooseException & e)
258 {
259 return coeff_ep; // when coeff_si is singular return the "linear" tangent operator
260 }
261
262 return s_inv * coeff_ep;
263}
264
265bool
270
271bool
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
const double mu
registerMooseObjectRenamed("SolidMechanicsApp", TensorMechanicsPlasticDruckerPragerHyperbolic, "01/01/2025 00:00", SolidMechanicsPlasticDruckerPragerHyperbolic)
registerMooseObject("SolidMechanicsApp", SolidMechanicsPlasticDruckerPragerHyperbolic)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
RankFourTensorTempl< T > invSymm() const
RankFourTensorTempl< T > outerProduct(const RankTwoTensorTempl< T > &b) const
T secondInvariant() const
RankTwoTensorTempl< T > dsecondInvariant() const
RankTwoTensorTempl< T > dtrace() const
RankTwoTensorTempl< T > deviatoric() const
RankFourTensorTempl< T > d2secondInvariant() const
Rate-independent non-associative Drucker Prager with hardening/softening.
const bool _use_custom_cto
Whether to use the custom consistent tangent operator calculation.
virtual RankTwoTensor df_dsig(const RankTwoTensor &stress, Real bbb) const override
Function that's used in dyieldFunction_dstress and flowPotential.
virtual bool useCustomReturnMap() const override
Returns false. You will want to override this in your derived class if you write a custom returnMap f...
RankFourTensor dflowPotential_dstress(const RankTwoTensor &stress, Real intnl) const override
The derivative of the flow potential with respect to stress.
virtual bool 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 override
Performs a custom return-map.
const unsigned _max_iters
max iters for custom return map loop
const Real _smoother2
smoothing parameter for the cone's tip
virtual bool useCustomCTO() const override
Returns false. You will want to override this in your derived class if you write a custom consistent ...
virtual RankFourTensor consistentTangentOperator(const RankTwoTensor &trial_stress, Real intnl_old, const RankTwoTensor &stress, Real intnl, const RankFourTensor &E_ijkl, const std::vector< Real > &cumulative_pm) const override
Calculates a custom consistent tangent operator.
Real yieldFunction(const RankTwoTensor &stress, Real intnl) const override
The following functions are what you should override when building single-plasticity models.
const bool _use_custom_returnMap
whether to use the custom returnMap function
Rate-independent non-associative Drucker Prager with hardening/softening.
void onlyB(Real intnl, int fd, Real &bbb) const
Calculate bbb or bbb_flow.
void dbothAB(Real intnl, Real &daaa, Real &dbbb) const
Calculates d(aaa)/d(intnl) and d(bbb)/d(intnl) as a function of the internal parameter intnl.
void bothAB(Real intnl, Real &aaa, Real &bbb) const
Calculates aaa and bbb as a function of the internal parameter intnl.
void donlyB(Real intnl, int fd, Real &dbbb) const
Calculate d(bbb)/d(intnl) or d(bbb_flow)/d(intnl)
virtual Real dyieldFunction_dintnl(const RankTwoTensor &stress, Real intnl) const override
The derivative of yield function with respect to the internal parameter.
virtual RankFourTensor consistentTangentOperator(const RankTwoTensor &trial_stress, Real intnl_old, const RankTwoTensor &stress, Real intnl, const RankFourTensor &E_ijkl, const std::vector< Real > &cumulative_pm) const
Calculates a custom consistent tangent operator.
virtual bool 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
Performs a custom return-map.
const Real _f_tol
Tolerance on yield function.