https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
15registerMooseObjectRenamed("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)");
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
90Real
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
145Real
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
243Real
245{
246 return _strength.value(internal_param);
247}
248
249Real
251{
252 return _strength.derivative(internal_param);
253}
254
255Real
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
270Real
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
289Real
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
311std::string
313{
314 return "Tensile";
315}
const std::vector< double > x
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
const Real p
registerMooseObject("SolidMechanicsApp", SolidMechanicsPlasticTensile)
registerMooseObjectRenamed("SolidMechanicsApp", TensorMechanicsPlasticTensile, "01/01/2025 00:00", SolidMechanicsPlasticTensile)
void addRequiredRangeCheckedParam(const std::string &name, const std::string &parsed_function, const std::string &doc_string)
void addRequiredParam(const std::string &name, const std::string &doc_string)
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)
void mooseError(Args &&... args) const
RankTwoTensorTempl< T > dsin3Lode(const T &r0) const
void dsymmetricEigenvalues(std::vector< T > &eigvals, std::vector< RankTwoTensorTempl< T > > &deigvals) const
T secondInvariant() const
void d2symmetricEigenvalues(std::vector< RankFourTensorTempl< T > > &deriv) const
T sin3Lode(const T &r0, const T &r0_value) const
void symmetricEigenvalues(std::vector< T > &eigvals) const
RankTwoTensorTempl< T > dsecondInvariant() const
RankTwoTensorTempl< T > dtrace() const
RankFourTensorTempl< T > d2secondInvariant() const
RankFourTensorTempl< T > d2sin3Lode(const T &r0) const
virtual Real derivative(Real intnl) const
virtual Real value(Real intnl) const
Plastic Model base class The virtual functions written below must be over-ridden in derived classes t...
static InputParameters validParams()
FiniteStrainTensile implements rate-independent associative tensile failure with hardening/softening ...
Real dyieldFunction_dintnl(const RankTwoTensor &stress, Real intnl) const override
The derivative of yield function with respect to the internal parameter.
Real _lode_cutoff
if secondInvariant < _lode_cutoff then set Lode angle to zero. This is to guard against precision-los...
Real _aaa
Abbo et al's A parameter.
Real _small_smoother2
Square of tip smoothing parameter to smooth the cone at mean_stress = T.
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
virtual Real dsmooth(const RankTwoTensor &stress) const
returns the da/dstress_mean - see doco for _tip_scheme
Real _sin3tt
sin(3*_tt) - useful for making comparisons with Lode angle
virtual Real d2smooth(const RankTwoTensor &stress) const
returns the d^2a/dstress_mean^2 - see doco for _tip_scheme
Real yieldFunction(const RankTwoTensor &stress, Real intnl) const override
The following functions are what you should override when building single-plasticity models.
MooseEnum _tip_scheme
The yield function is modified to f = s_m + sqrt(a + s_bar^2 K^2) - tensile_strength where "a" depend...
SolidMechanicsPlasticTensile(const InputParameters &parameters)
RankFourTensor dflowPotential_dstress(const RankTwoTensor &stress, Real intnl) const override
The derivative of the flow potential with respect to stress.
Real _cap_start
smoothing parameter dictating when the 'cap' will start - see doco for _tip_scheme
virtual Real smooth(const RankTwoTensor &stress) const
returns the 'a' parameter - see doco for _tip_scheme
Real _bbb
Abbo et al's B parameter.
Real _ccc
Abbo et al's C parameter.
RankTwoTensor dflowPotential_dintnl(const RankTwoTensor &stress, Real intnl) const override
The derivative of the flow potential with respect to the internal parameter.
Real _tt
edge smoothing parameter, in radians
RankTwoTensor flowPotential(const RankTwoTensor &stress, Real intnl) const override
The flow potential.
const SolidMechanicsHardeningModel & _strength
RankTwoTensor dyieldFunction_dstress(const RankTwoTensor &stress, Real intnl) const override
The derivative of yield function with respect to stress.
virtual std::string modelName() const override
virtual Real tensile_strength(const Real internal_param) const
tensile strength as a function of residual value, rate, and internal_param
Real _cap_rate
dictates how quickly the 'cap' degenerates to a hemisphere - see doco for _tip_scheme
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...