https://mooseframework.inl.gov
SolidMechanicsPlasticWeakPlaneShear.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 
15 registerMooseObjectRenamed("SolidMechanicsApp",
16  TensorMechanicsPlasticWeakPlaneShear,
17  "01/01/2025 00:00",
19 
22 {
24  params.addRequiredParam<UserObjectName>(
25  "cohesion",
26  "A SolidMechanicsHardening UserObject that defines hardening of the cohesion. "
27  "Physically the cohesion should not be negative.");
28  params.addRequiredParam<UserObjectName>("tan_friction_angle",
29  "A SolidMechanicsHardening UserObject that defines "
30  "hardening of tan(friction angle). Physically the "
31  "friction angle should be between 0 and 90deg.");
32  params.addRequiredParam<UserObjectName>(
33  "tan_dilation_angle",
34  "A SolidMechanicsHardening UserObject that defines hardening of the "
35  "tan(dilation angle). Usually the dilation angle is not greater than "
36  "the friction angle, and it is between 0 and 90deg.");
37  MooseEnum tip_scheme("hyperbolic cap", "hyperbolic");
38  params.addParam<MooseEnum>(
39  "tip_scheme", tip_scheme, "Scheme by which the cone's tip will be smoothed.");
41  "smoother",
42  "smoother>=0",
43  "For the 'hyperbolic' tip_scheme, the cone vertex at shear-stress "
44  "= 0 will be smoothed by the given amount. For the 'cap' "
45  "tip_scheme, additional smoothing will occur. Typical value is "
46  "0.1*cohesion");
47  params.addParam<Real>(
48  "cap_start",
49  0.0,
50  "For the 'cap' tip_scheme, smoothing is performed in the stress_zz > cap_start region");
51  params.addRangeCheckedParam<Real>("cap_rate",
52  0.0,
53  "cap_rate>=0",
54  "For the 'cap' tip_scheme, this controls how quickly the cap "
55  "degenerates to a hemisphere: small values mean a slow "
56  "degeneration to a hemisphere (and zero means the 'cap' will "
57  "be totally inactive). Typical value is 1/cohesion");
58  params.addClassDescription("Non-associative finite-strain weak-plane shear perfect plasticity. "
59  "Here cohesion = 1, tan(phi) = 1 = tan(psi)");
60 
61  return params;
62 }
63 
65  const InputParameters & parameters)
66  : SolidMechanicsPlasticModel(parameters),
67  _cohesion(getUserObject<SolidMechanicsHardeningModel>("cohesion")),
68  _tan_phi(getUserObject<SolidMechanicsHardeningModel>("tan_friction_angle")),
69  _tan_psi(getUserObject<SolidMechanicsHardeningModel>("tan_dilation_angle")),
70  _tip_scheme(getParam<MooseEnum>("tip_scheme")),
71  _small_smoother2(Utility::pow<2>(getParam<Real>("smoother"))),
72  _cap_start(getParam<Real>("cap_start")),
73  _cap_rate(getParam<Real>("cap_rate"))
74 {
75  // With arbitary UserObjects, it is impossible to check everything, and
76  // I think this is the best I can do
77  if (tan_phi(0) < 0 || tan_psi(0) < 0)
78  mooseError("Weak-Plane-Shear friction and dilation angles must lie in [0, Pi/2]");
79  if (tan_phi(0) < tan_psi(0))
80  mooseError(
81  "Weak-Plane-Shear friction angle must not be less than Weak-Plane-Shear dilation angle");
82  if (cohesion(0) < 0)
83  mooseError("Weak-Plane-Shear cohesion must not be negative");
84 }
85 
86 Real
88 {
89  // note that i explicitly symmeterise in preparation for Cosserat
90  return std::sqrt(Utility::pow<2>((stress(0, 2) + stress(2, 0)) / 2.0) +
91  Utility::pow<2>((stress(1, 2) + stress(2, 1)) / 2.0) + smooth(stress)) +
92  stress(2, 2) * tan_phi(intnl) - cohesion(intnl);
93 }
94 
97  Real _tan_phi_or_psi) const
98 {
99  RankTwoTensor deriv; // the constructor zeroes this
100 
101  Real tau = std::sqrt(Utility::pow<2>((stress(0, 2) + stress(2, 0)) / 2.0) +
102  Utility::pow<2>((stress(1, 2) + stress(2, 1)) / 2.0) + smooth(stress));
103  // note that i explicitly symmeterise in preparation for Cosserat
104  if (tau == 0.0)
105  {
106  // the derivative is not defined here, but i want to set it nonzero
107  // because otherwise the return direction might be too crazy
108  deriv(0, 2) = deriv(2, 0) = 0.5;
109  deriv(1, 2) = deriv(2, 1) = 0.5;
110  }
111  else
112  {
113  deriv(0, 2) = deriv(2, 0) = 0.25 * (stress(0, 2) + stress(2, 0)) / tau;
114  deriv(1, 2) = deriv(2, 1) = 0.25 * (stress(1, 2) + stress(2, 1)) / tau;
115  deriv(2, 2) = 0.5 * dsmooth(stress) / tau;
116  }
117  deriv(2, 2) += _tan_phi_or_psi;
118  return deriv;
119 }
120 
123  Real intnl) const
124 {
125  return df_dsig(stress, tan_phi(intnl));
126 }
127 
128 Real
130  Real intnl) const
131 {
132  return stress(2, 2) * dtan_phi(intnl) - dcohesion(intnl);
133 }
134 
137 {
138  return df_dsig(stress, tan_psi(intnl));
139 }
140 
143  Real /*intnl*/) const
144 {
145  RankFourTensor dr_dstress;
146  Real tau = std::sqrt(Utility::pow<2>((stress(0, 2) + stress(2, 0)) / 2.0) +
147  Utility::pow<2>((stress(1, 2) + stress(2, 1)) / 2.0) + smooth(stress));
148  if (tau == 0.0)
149  return dr_dstress;
150 
151  // note that i explicitly symmeterise
152  RankTwoTensor dtau;
153  dtau(0, 2) = dtau(2, 0) = 0.25 * (stress(0, 2) + stress(2, 0)) / tau;
154  dtau(1, 2) = dtau(2, 1) = 0.25 * (stress(1, 2) + stress(2, 1)) / tau;
155  dtau(2, 2) = 0.5 * dsmooth(stress) / tau;
156 
157  for (unsigned i = 0; i < 3; ++i)
158  for (unsigned j = 0; j < 3; ++j)
159  for (unsigned k = 0; k < 3; ++k)
160  for (unsigned l = 0; l < 3; ++l)
161  dr_dstress(i, j, k, l) = -dtau(i, j) * dtau(k, l) / tau;
162 
163  // note that i explicitly symmeterise
164  dr_dstress(0, 2, 0, 2) += 0.25 / tau;
165  dr_dstress(0, 2, 2, 0) += 0.25 / tau;
166  dr_dstress(2, 0, 0, 2) += 0.25 / tau;
167  dr_dstress(2, 0, 2, 0) += 0.25 / tau;
168  dr_dstress(1, 2, 1, 2) += 0.25 / tau;
169  dr_dstress(1, 2, 2, 1) += 0.25 / tau;
170  dr_dstress(2, 1, 1, 2) += 0.25 / tau;
171  dr_dstress(2, 1, 2, 1) += 0.25 / tau;
172  dr_dstress(2, 2, 2, 2) += 0.5 * d2smooth(stress) / tau;
173 
174  return dr_dstress;
175 }
176 
179  Real intnl) const
180 {
181  RankTwoTensor dr_dintnl;
182  dr_dintnl(2, 2) = dtan_psi(intnl);
183  return dr_dintnl;
184 }
185 
186 Real
187 SolidMechanicsPlasticWeakPlaneShear::cohesion(const Real internal_param) const
188 {
189  return _cohesion.value(internal_param);
190 }
191 
192 Real
193 SolidMechanicsPlasticWeakPlaneShear::dcohesion(const Real internal_param) const
194 {
195  return _cohesion.derivative(internal_param);
196 }
197 
198 Real
199 SolidMechanicsPlasticWeakPlaneShear::tan_phi(const Real internal_param) const
200 {
201  return _tan_phi.value(internal_param);
202 }
203 
204 Real
205 SolidMechanicsPlasticWeakPlaneShear::dtan_phi(const Real internal_param) const
206 {
207  return _tan_phi.derivative(internal_param);
208 }
209 
210 Real
211 SolidMechanicsPlasticWeakPlaneShear::tan_psi(const Real internal_param) const
212 {
213  return _tan_psi.value(internal_param);
214 }
215 
216 Real
217 SolidMechanicsPlasticWeakPlaneShear::dtan_psi(const Real internal_param) const
218 {
219  return _tan_psi.derivative(internal_param);
220 }
221 
222 Real
224 {
225  Real smoother2 = _small_smoother2;
226  if (_tip_scheme == "cap")
227  {
228  Real x = stress(2, 2) - _cap_start;
229  Real p = 0;
230  if (x > 0)
231  p = x * (1 - std::exp(-_cap_rate * x));
232  smoother2 += Utility::pow<2>(p);
233  }
234  return smoother2;
235 }
236 
237 Real
239 {
240  Real dsmoother2 = 0;
241  if (_tip_scheme == "cap")
242  {
243  Real x = stress(2, 2) - _cap_start;
244  Real p = 0;
245  Real dp_dx = 0;
246  if (x > 0)
247  {
248  const Real exp_cap_rate_x = std::exp(-_cap_rate * x);
249  p = x * (1 - exp_cap_rate_x);
250  dp_dx = (1 - exp_cap_rate_x) + x * _cap_rate * exp_cap_rate_x;
251  }
252  dsmoother2 += 2 * p * dp_dx;
253  }
254  return dsmoother2;
255 }
256 
257 Real
259 {
260  Real d2smoother2 = 0;
261  if (_tip_scheme == "cap")
262  {
263  Real x = stress(2, 2) - _cap_start;
264  Real p = 0;
265  Real dp_dx = 0;
266  Real d2p_dx2 = 0;
267  if (x > 0)
268  {
269  const Real exp_cap_rate_x = std::exp(-_cap_rate * x);
270  p = x * (1.0 - exp_cap_rate_x);
271  dp_dx = (1.0 - exp_cap_rate_x) + x * _cap_rate * exp_cap_rate_x;
272  d2p_dx2 = 2.0 * _cap_rate * exp_cap_rate_x - x * Utility::pow<2>(_cap_rate) * exp_cap_rate_x;
273  }
274  d2smoother2 += 2.0 * Utility::pow<2>(dp_dx) + 2.0 * p * d2p_dx2;
275  }
276  return d2smoother2;
277 }
278 
279 void
281  const RankTwoTensor & stress,
282  Real intnl,
283  const RankFourTensor & Eijkl,
284  std::vector<bool> & act,
285  RankTwoTensor & returned_stress) const
286 {
287  act.assign(1, false);
288  returned_stress = stress;
289 
290  if (f[0] <= _f_tol)
291  return;
292 
293  // in the following i will derive returned_stress for the case smoother=0
294 
295  Real tanpsi = tan_psi(intnl);
296  Real tanphi = tan_phi(intnl);
297 
298  // norm is the normal to the yield surface
299  // with f having psi (dilation angle) instead of phi:
300  // norm(0) = df/dsig(2,0) = df/dsig(0,2)
301  // norm(1) = df/dsig(2,1) = df/dsig(1,2)
302  // norm(2) = df/dsig(2,2)
303  std::vector<Real> norm(3, 0.0);
304  const Real tau = std::sqrt(Utility::pow<2>((stress(0, 2) + stress(2, 0)) / 2.0) +
305  Utility::pow<2>((stress(1, 2) + stress(2, 1)) / 2.0));
306  if (tau > 0.0)
307  {
308  norm[0] = 0.25 * (stress(0, 2) + stress(2, 0)) / tau;
309  norm[1] = 0.25 * (stress(1, 2) + stress(2, 1)) / tau;
310  }
311  else
312  {
313  returned_stress(2, 2) = cohesion(intnl) / tanphi;
314  act[0] = true;
315  return;
316  }
317  norm[2] = tanpsi;
318 
319  // to get the flow directions, we have to multiply norm by Eijkl.
320  // I assume that E(0,2,0,2) = E(1,2,1,2), and E(2,2,0,2) = 0 = E(0,2,1,2), etc
321  // with the usual symmetry. This makes finding the returned_stress
322  // much easier.
323  // returned_stress = stress - alpha*n
324  // where alpha is chosen so that f = 0
325  Real alpha = f[0] / (Eijkl(0, 2, 0, 2) + Eijkl(2, 2, 2, 2) * tanpsi * tanphi);
326 
327  if (1 - alpha * Eijkl(0, 2, 0, 2) / tau >= 0)
328  {
329  // returning to the "surface" of the cone
330  returned_stress(2, 2) = stress(2, 2) - alpha * Eijkl(2, 2, 2, 2) * norm[2];
331  returned_stress(0, 2) = returned_stress(2, 0) =
332  stress(0, 2) - alpha * 2.0 * Eijkl(0, 2, 0, 2) * norm[0];
333  returned_stress(1, 2) = returned_stress(2, 1) =
334  stress(1, 2) - alpha * 2.0 * Eijkl(1, 2, 1, 2) * norm[1];
335  }
336  else
337  {
338  // returning to the "tip" of the cone
339  returned_stress(2, 2) = cohesion(intnl) / tanphi;
340  returned_stress(0, 2) = returned_stress(2, 0) = returned_stress(1, 2) = returned_stress(2, 1) =
341  0.0;
342  }
343  returned_stress(0, 0) =
344  stress(0, 0) - Eijkl(0, 0, 2, 2) * (stress(2, 2) - returned_stress(2, 2)) / Eijkl(2, 2, 2, 2);
345  returned_stress(1, 1) =
346  stress(1, 1) - Eijkl(1, 1, 2, 2) * (stress(2, 2) - returned_stress(2, 2)) / Eijkl(2, 2, 2, 2);
347 
348  act[0] = true;
349 }
350 
351 std::string
353 {
354  return "WeakPlaneShear";
355 }
virtual Real tan_phi(const Real internal_param) const
tan_phi as a function of internal parameter
virtual void activeConstraints(const std::vector< Real > &f, const RankTwoTensor &stress, Real intnl, const RankFourTensor &Eijkl, std::vector< bool > &act, RankTwoTensor &returned_stress) const override
The active yield surfaces, given a vector of yield functions.
Real _cap_rate
dictates how quickly the &#39;cap&#39; degenerates to a hemisphere - see doco for _tip_scheme ...
Real _small_smoother2
smoothing parameter for the cone&#39;s tip - see doco for _tip_scheme
void addRequiredRangeCheckedParam(const std::string &name, const std::string &parsed_function, const std::string &doc_string)
const SolidMechanicsHardeningModel & _tan_psi
Hardening model for tan(psi)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const SolidMechanicsHardeningModel & _cohesion
Hardening model for cohesion.
virtual Real dtan_psi(const Real internal_param) const
d(tan_psi)/d(internal_param);
const SolidMechanicsHardeningModel & _tan_phi
Hardening model for tan(phi)
virtual Real tan_psi(const Real internal_param) const
tan_psi as a function of internal parameter
Real yieldFunction(const RankTwoTensor &stress, Real intnl) const override
The following functions are what you should override when building single-plasticity models...
RankTwoTensor flowPotential(const RankTwoTensor &stress, Real intnl) const override
The flow potential.
virtual Real d2smooth(const RankTwoTensor &stress) const
returns the d^2a/dstress(2,2)^2 - see doco for _tip_scheme
virtual Real value(Real intnl) const
RankTwoTensor df_dsig(const RankTwoTensor &stress, Real _tan_phi_or_psi) const
Function that&#39;s used in dyieldFunction_dstress and flowPotential.
void addRequiredParam(const std::string &name, const std::string &doc_string)
RankFourTensor dflowPotential_dstress(const RankTwoTensor &stress, Real intnl) const override
The derivative of the flow potential with respect to stress.
virtual Real cohesion(const Real internal_param) const
cohesion as a function of internal parameter
static InputParameters validParams()
SolidMechanicsPlasticWeakPlaneShear(const InputParameters &parameters)
Real deriv(unsigned n, unsigned alpha, unsigned beta, Real x)
const std::vector< double > x
Real f(Real x)
Test function for Brents method.
virtual std::string modelName() const override
auto norm(const T &a) -> decltype(std::abs(a))
Real _cap_start
smoothing parameter dictating when the &#39;cap&#39; will start - see doco for _tip_scheme ...
virtual Real dsmooth(const RankTwoTensor &stress) const
returns the da/dstress(2,2) - see doco for _tip_scheme
const Real _f_tol
Tolerance on yield function.
RankTwoTensor dflowPotential_dintnl(const RankTwoTensor &stress, Real intnl) const override
The derivative of the flow potential with respect to the internal parameter.
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
virtual Real derivative(Real intnl) const
RankTwoTensor dyieldFunction_dstress(const RankTwoTensor &stress, Real intnl) const override
The derivative of yield function with respect to stress.
virtual Real dtan_phi(const Real internal_param) const
d(tan_phi)/d(internal_param);
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string alpha
Definition: NS.h:134
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
Real dyieldFunction_dintnl(const RankTwoTensor &stress, Real intnl) const override
The derivative of yield function with respect to the internal parameter.
registerMooseObjectRenamed("SolidMechanicsApp", TensorMechanicsPlasticWeakPlaneShear, "01/01/2025 00:00", SolidMechanicsPlasticWeakPlaneShear)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
virtual Real dcohesion(const Real internal_param) const
d(cohesion)/d(internal_param)
Plastic Model base class The virtual functions written below must be over-ridden in derived classes t...
virtual Real smooth(const RankTwoTensor &stress) const
returns the &#39;a&#39; parameter - see doco for _tip_scheme
static const std::string k
Definition: NS.h:130
MooseEnum _tip_scheme
The yield function is modified to f = sqrt(s_xz^2 + s_yz^2 + a) + s_zz*_tan_phi - _cohesion where "a"...
registerMooseObject("SolidMechanicsApp", SolidMechanicsPlasticWeakPlaneShear)
Rate-independent associative weak-plane tensile failure with hardening/softening. ...