https://mooseframework.inl.gov
SolidMechanicsPlasticTensile.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  TensorMechanicsPlasticTensile,
17  "01/01/2025 00:00",
19 
22 {
24  params.addRequiredParam<UserObjectName>(
25  "tensile_strength",
26  "A SolidMechanicsHardening UserObject that defines hardening of the tensile strength");
27  params.addRangeCheckedParam<Real>(
28  "tensile_edge_smoother",
29  25.0,
30  "tensile_edge_smoother>=0 & tensile_edge_smoother<=30",
31  "Smoothing parameter: the edges of the cone are smoothed by the given amount.");
32  MooseEnum tip_scheme("hyperbolic cap", "hyperbolic");
33  params.addParam<MooseEnum>(
34  "tip_scheme", tip_scheme, "Scheme by which the pyramid's tip will be smoothed.");
35  params.addRequiredRangeCheckedParam<Real>("tensile_tip_smoother",
36  "tensile_tip_smoother>=0",
37  "For the 'hyperbolic' tip_scheme, the pyramid vertex "
38  "will be smoothed by the given amount. For the 'cap' "
39  "tip_scheme, additional smoothing will occur. Typical "
40  "value is 0.1*tensile_strength");
41  params.addParam<Real>(
42  "cap_start",
43  0.0,
44  "For the 'cap' tip_scheme, smoothing is performed in the stress_mean > cap_start region");
45  params.addRangeCheckedParam<Real>("cap_rate",
46  0.0,
47  "cap_rate>=0",
48  "For the 'cap' tip_scheme, this controls how quickly the cap "
49  "degenerates to a hemisphere: small values mean a slow "
50  "degeneration to a hemisphere (and zero means the 'cap' will "
51  "be totally inactive). Typical value is 1/tensile_strength");
52  params.addParam<Real>("tensile_lode_cutoff",
53  "If the second invariant of stress is less than "
54  "this amount, the Lode angle is assumed to be zero. "
55  "This is to guard against precision-loss problems, "
56  "and this parameter should be set small. Default = "
57  "0.00001*((yield_Function_tolerance)^2)");
58  params.addClassDescription(
59  "Associative tensile plasticity with hardening/softening, and tensile_strength = 1");
60 
61  return params;
62 }
63 
65  : SolidMechanicsPlasticModel(parameters),
66  _strength(getUserObject<SolidMechanicsHardeningModel>("tensile_strength")),
67  _tip_scheme(getParam<MooseEnum>("tip_scheme")),
68  _small_smoother2(Utility::pow<2>(getParam<Real>("tensile_tip_smoother"))),
69  _cap_start(getParam<Real>("cap_start")),
70  _cap_rate(getParam<Real>("cap_rate")),
71  _tt(getParam<Real>("tensile_edge_smoother") * libMesh::pi / 180.0),
72  _sin3tt(std::sin(3.0 * _tt)),
73  _lode_cutoff(parameters.isParamValid("tensile_lode_cutoff")
74  ? getParam<Real>("tensile_lode_cutoff")
75  : 1.0e-5 * Utility::pow<2>(_f_tol))
76 
77 {
78  if (_lode_cutoff < 0)
79  mooseError("tensile_lode_cutoff must not be negative");
80  _ccc = (-std::cos(3.0 * _tt) * (std::cos(_tt) - std::sin(_tt) / std::sqrt(3.0)) -
81  3.0 * _sin3tt * (std::sin(_tt) + std::cos(_tt) / std::sqrt(3.0))) /
82  (18.0 * Utility::pow<3>(std::cos(3.0 * _tt)));
83  _bbb = (std::sin(6.0 * _tt) * (std::cos(_tt) - std::sin(_tt) / std::sqrt(3.0)) -
84  6.0 * std::cos(6.0 * _tt) * (std::sin(_tt) + std::cos(_tt) / std::sqrt(3.0))) /
85  (18.0 * Utility::pow<3>(std::cos(3.0 * _tt)));
86  _aaa = -std::sin(_tt) / std::sqrt(3.0) - _bbb * _sin3tt - _ccc * Utility::pow<2>(_sin3tt) +
87  std::cos(_tt);
88 }
89 
90 Real
92 {
93  Real mean_stress = stress.trace() / 3.0;
94  Real sin3Lode = stress.sin3Lode(_lode_cutoff, 0);
95  if (sin3Lode <= _sin3tt)
96  {
97  // the non-edge-smoothed version
98  std::vector<Real> eigvals;
99  stress.symmetricEigenvalues(eigvals);
100  return mean_stress + std::sqrt(smooth(stress) + Utility::pow<2>(eigvals[2] - mean_stress)) -
101  tensile_strength(intnl);
102  }
103  else
104  {
105  // the edge-smoothed version
106  Real kk = _aaa + _bbb * sin3Lode + _ccc * Utility::pow<2>(sin3Lode);
107  Real sibar2 = stress.secondInvariant();
108  return mean_stress + std::sqrt(smooth(stress) + sibar2 * Utility::pow<2>(kk)) -
109  tensile_strength(intnl);
110  }
111 }
112 
115  Real /*intnl*/) const
116 {
117  Real mean_stress = stress.trace() / 3.0;
118  RankTwoTensor dmean_stress = stress.dtrace() / 3.0;
119  Real sin3Lode = stress.sin3Lode(_lode_cutoff, 0);
120  if (sin3Lode <= _sin3tt)
121  {
122  // the non-edge-smoothed version
123  std::vector<Real> eigvals;
124  std::vector<RankTwoTensor> deigvals;
125  stress.dsymmetricEigenvalues(eigvals, deigvals);
126  Real denom = std::sqrt(smooth(stress) + Utility::pow<2>(eigvals[2] - mean_stress));
127  return dmean_stress + (0.5 * dsmooth(stress) * dmean_stress +
128  (eigvals[2] - mean_stress) * (deigvals[2] - dmean_stress)) /
129  denom;
130  }
131  else
132  {
133  // the edge-smoothed version
134  Real kk = _aaa + _bbb * sin3Lode + _ccc * Utility::pow<2>(sin3Lode);
135  RankTwoTensor dkk = (_bbb + 2.0 * _ccc * sin3Lode) * stress.dsin3Lode(_lode_cutoff);
136  Real sibar2 = stress.secondInvariant();
137  RankTwoTensor dsibar2 = stress.dsecondInvariant();
138  Real denom = std::sqrt(smooth(stress) + sibar2 * Utility::pow<2>(kk));
139  return dmean_stress + (0.5 * dsmooth(stress) * dmean_stress +
140  0.5 * dsibar2 * Utility::pow<2>(kk) + sibar2 * kk * dkk) /
141  denom;
142  }
143 }
144 
145 Real
147  Real intnl) const
148 {
149  return -dtensile_strength(intnl);
150 }
151 
154 {
155  // This plasticity is associative so
156  return dyieldFunction_dstress(stress, intnl);
157 }
158 
161  Real /*intnl*/) const
162 {
163  Real mean_stress = stress.trace() / 3.0;
164  RankTwoTensor dmean_stress = stress.dtrace() / 3.0;
165  Real sin3Lode = stress.sin3Lode(_lode_cutoff, 0);
166  if (sin3Lode <= _sin3tt)
167  {
168  // the non-edge-smoothed version
169  std::vector<Real> eigvals;
170  std::vector<RankTwoTensor> deigvals;
171  std::vector<RankFourTensor> d2eigvals;
172  stress.dsymmetricEigenvalues(eigvals, deigvals);
173  stress.d2symmetricEigenvalues(d2eigvals);
174 
175  Real denom = std::sqrt(smooth(stress) + Utility::pow<2>(eigvals[2] - mean_stress));
176  Real denom3 = Utility::pow<3>(denom);
177  RankTwoTensor numer_part = deigvals[2] - dmean_stress;
178  RankTwoTensor numer_full =
179  0.5 * dsmooth(stress) * dmean_stress + (eigvals[2] - mean_stress) * numer_part;
180  Real d2smooth_over_denom = d2smooth(stress) / denom;
181 
182  RankFourTensor dr_dstress = (eigvals[2] - mean_stress) * d2eigvals[2] / denom;
183  for (unsigned i = 0; i < 3; ++i)
184  for (unsigned j = 0; j < 3; ++j)
185  for (unsigned k = 0; k < 3; ++k)
186  for (unsigned l = 0; l < 3; ++l)
187  {
188  dr_dstress(i, j, k, l) +=
189  0.5 * d2smooth_over_denom * dmean_stress(i, j) * dmean_stress(k, l);
190  dr_dstress(i, j, k, l) += numer_part(i, j) * numer_part(k, l) / denom;
191  dr_dstress(i, j, k, l) -= numer_full(i, j) * numer_full(k, l) / denom3;
192  }
193  return dr_dstress;
194  }
195  else
196  {
197  // the edge-smoothed version
198  RankTwoTensor dsin3Lode = stress.dsin3Lode(_lode_cutoff);
199  Real kk = _aaa + _bbb * sin3Lode + _ccc * Utility::pow<2>(sin3Lode);
200  RankTwoTensor dkk = (_bbb + 2.0 * _ccc * sin3Lode) * dsin3Lode;
201  RankFourTensor d2kk = (_bbb + 2.0 * _ccc * sin3Lode) * stress.d2sin3Lode(_lode_cutoff);
202  for (unsigned i = 0; i < 3; ++i)
203  for (unsigned j = 0; j < 3; ++j)
204  for (unsigned k = 0; k < 3; ++k)
205  for (unsigned l = 0; l < 3; ++l)
206  d2kk(i, j, k, l) += 2.0 * _ccc * dsin3Lode(i, j) * dsin3Lode(k, l);
207 
208  Real sibar2 = stress.secondInvariant();
209  RankTwoTensor dsibar2 = stress.dsecondInvariant();
210  RankFourTensor d2sibar2 = stress.d2secondInvariant();
211 
212  Real denom = std::sqrt(smooth(stress) + sibar2 * Utility::pow<2>(kk));
213  Real denom3 = Utility::pow<3>(denom);
214  Real d2smooth_over_denom = d2smooth(stress) / denom;
215  RankTwoTensor numer_full =
216  0.5 * dsmooth(stress) * dmean_stress + 0.5 * dsibar2 * kk * kk + sibar2 * kk * dkk;
217 
218  RankFourTensor dr_dstress = (0.5 * d2sibar2 * Utility::pow<2>(kk) + sibar2 * kk * d2kk) / denom;
219  for (unsigned i = 0; i < 3; ++i)
220  for (unsigned j = 0; j < 3; ++j)
221  for (unsigned k = 0; k < 3; ++k)
222  for (unsigned l = 0; l < 3; ++l)
223  {
224  dr_dstress(i, j, k, l) +=
225  0.5 * d2smooth_over_denom * dmean_stress(i, j) * dmean_stress(k, l);
226  dr_dstress(i, j, k, l) +=
227  (dsibar2(i, j) * dkk(k, l) * kk + dkk(i, j) * dsibar2(k, l) * kk +
228  sibar2 * dkk(i, j) * dkk(k, l)) /
229  denom;
230  dr_dstress(i, j, k, l) -= numer_full(i, j) * numer_full(k, l) / denom3;
231  }
232  return dr_dstress;
233  }
234 }
235 
238  Real /*intnl*/) const
239 {
240  return RankTwoTensor();
241 }
242 
243 Real
244 SolidMechanicsPlasticTensile::tensile_strength(const Real internal_param) const
245 {
246  return _strength.value(internal_param);
247 }
248 
249 Real
250 SolidMechanicsPlasticTensile::dtensile_strength(const Real internal_param) const
251 {
252  return _strength.derivative(internal_param);
253 }
254 
255 Real
257 {
258  Real smoother2 = _small_smoother2;
259  if (_tip_scheme == "cap")
260  {
261  Real x = stress.trace() / 3.0 - _cap_start;
262  Real p = 0;
263  if (x > 0)
264  p = x * (1 - std::exp(-_cap_rate * x));
265  smoother2 += Utility::pow<2>(p);
266  }
267  return smoother2;
268 }
269 
270 Real
272 {
273  Real dsmoother2 = 0;
274  if (_tip_scheme == "cap")
275  {
276  Real x = stress.trace() / 3.0 - _cap_start;
277  Real p = 0;
278  Real dp_dx = 0;
279  if (x > 0)
280  {
281  p = x * (1 - std::exp(-_cap_rate * x));
282  dp_dx = (1 - std::exp(-_cap_rate * x)) + x * _cap_rate * std::exp(-_cap_rate * x);
283  }
284  dsmoother2 += 2.0 * p * dp_dx;
285  }
286  return dsmoother2;
287 }
288 
289 Real
291 {
292  Real d2smoother2 = 0;
293  if (_tip_scheme == "cap")
294  {
295  Real x = stress.trace() / 3.0 - _cap_start;
296  Real p = 0;
297  Real dp_dx = 0;
298  Real d2p_dx2 = 0;
299  if (x > 0)
300  {
301  p = x * (1 - std::exp(-_cap_rate * x));
302  dp_dx = (1 - std::exp(-_cap_rate * x)) + x * _cap_rate * std::exp(-_cap_rate * x);
303  d2p_dx2 = 2.0 * _cap_rate * std::exp(-_cap_rate * x) -
304  x * Utility::pow<2>(_cap_rate) * std::exp(-_cap_rate * x);
305  }
306  d2smoother2 += 2.0 * Utility::pow<2>(dp_dx) + 2.0 * p * d2p_dx2;
307  }
308  return d2smoother2;
309 }
310 
311 std::string
313 {
314  return "Tensile";
315 }
Real yieldFunction(const RankTwoTensor &stress, Real intnl) const override
The following functions are what you should override when building single-plasticity models...
RankTwoTensorTempl< Real > dsecondInvariant() const
RankFourTensorTempl< Real > d2secondInvariant() const
registerMooseObject("SolidMechanicsApp", SolidMechanicsPlasticTensile)
void addRequiredRangeCheckedParam(const std::string &name, const std::string &parsed_function, const std::string &doc_string)
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sin(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tan
void symmetricEigenvalues(std::vector< Real > &eigvals) const
FiniteStrainTensile implements rate-independent associative tensile failure with hardening/softening ...
Real sin3Lode(const Real &r0, const Real &r0_value) const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, 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.
void dsymmetricEigenvalues(std::vector< Real > &eigvals, std::vector< RankTwoTensorTempl< Real >> &deigvals) const
Real dyieldFunction_dintnl(const RankTwoTensor &stress, Real intnl) const override
The derivative of yield function with respect to the internal parameter.
MooseEnum _tip_scheme
The yield function is modified to f = s_m + sqrt(a + s_bar^2 K^2) - tensile_strength where "a" depend...
RankTwoTensorTempl< Real > dtrace() const
virtual Real dtensile_strength(const Real internal_param) const
d(tensile strength)/d(internal_param) as a function of residual value, rate, and internal_param ...
Real _bbb
Abbo et al&#39;s B parameter.
RankTwoTensor dyieldFunction_dstress(const RankTwoTensor &stress, Real intnl) const override
The derivative of yield function with respect to stress.
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
Real _sin3tt
sin(3*_tt) - useful for making comparisons with Lode angle
virtual Real value(Real intnl) const
void addRequiredParam(const std::string &name, const std::string &doc_string)
SolidMechanicsPlasticTensile(const InputParameters &parameters)
RankTwoTensorTempl< Real > dsin3Lode(const Real &r0) const
virtual Real tensile_strength(const Real internal_param) const
tensile strength as a function of residual value, rate, and internal_param
Real _small_smoother2
Square of tip smoothing parameter to smooth the cone at mean_stress = T.
static InputParameters validParams()
Real _cap_rate
dictates how quickly the &#39;cap&#39; degenerates to a hemisphere - see doco for _tip_scheme ...
const std::vector< double > x
Real _lode_cutoff
if secondInvariant < _lode_cutoff then set Lode angle to zero. This is to guard against precision-los...
void d2symmetricEigenvalues(std::vector< RankFourTensorTempl< Real >> &deriv) const
RankTwoTensor flowPotential(const RankTwoTensor &stress, Real intnl) const override
The flow potential.
RankFourTensorTempl< Real > d2sin3Lode(const Real &r0) const
const SolidMechanicsHardeningModel & _strength
Real _tt
edge smoothing parameter, in radians
Real _aaa
Abbo et al&#39;s A parameter.
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
virtual Real derivative(Real intnl) const
virtual Real d2smooth(const RankTwoTensor &stress) const
returns the d^2a/dstress_mean^2 - see doco for _tip_scheme
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
RankTwoTensor dflowPotential_dintnl(const RankTwoTensor &stress, Real intnl) const override
The derivative of the flow potential with respect to the internal parameter.
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")
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
Real _ccc
Abbo et al&#39;s C parameter.
virtual Real smooth(const RankTwoTensor &stress) const
returns the &#39;a&#39; parameter - see doco for _tip_scheme
Plastic Model base class The virtual functions written below must be over-ridden in derived classes t...
registerMooseObjectRenamed("SolidMechanicsApp", TensorMechanicsPlasticTensile, "01/01/2025 00:00", SolidMechanicsPlasticTensile)
static const std::string k
Definition: NS.h:130
Real _cap_start
smoothing parameter dictating when the &#39;cap&#39; will start - see doco for _tip_scheme ...
virtual std::string modelName() const override
const Real pi
virtual Real dsmooth(const RankTwoTensor &stress) const
returns the da/dstress_mean - see doco for _tip_scheme