18 TensorMechanicsPlasticTensileMulti,
29 "A SolidMechanicsHardening UserObject that defines hardening of the tensile strength");
31 "Yield surface is shifted by this amount to avoid problems with " 32 "defining derivatives when eigenvalues are equal. If this is " 33 "larger than f_tol, a warning will be issued. Default = f_tol.");
34 params.
addParam<
unsigned int>(
"max_iterations",
36 "Maximum number of Newton-Raphson iterations " 37 "allowed in the custom return-map algorithm. " 38 " For highly nonlinear hardening this may " 39 "need to be higher than 10.");
40 params.
addParam<
bool>(
"use_custom_returnMap",
42 "Whether to use the custom returnMap " 43 "algorithm. Set to true if you are using " 44 "isotropic elasticity.");
45 params.
addParam<
bool>(
"use_custom_cto",
47 "Whether to use the custom consistent tangent " 48 "operator computations. Set to true if you are " 49 "using isotropic elasticity.");
57 _max_iters(getParam<unsigned
int>(
"max_iterations")),
58 _shift(parameters.isParamValid(
"shift") ? getParam<
Real>(
"shift") : _f_tol),
59 _use_custom_returnMap(getParam<bool>(
"use_custom_returnMap")),
60 _use_custom_cto(getParam<bool>(
"use_custom_cto"))
63 mooseError(
"Value of 'shift' in SolidMechanicsPlasticTensileMulti must not be negative\n");
65 _console <<
"WARNING: value of 'shift' in SolidMechanicsPlasticTensileMulti is probably set " 69 mooseError(
"SolidMechanicsPlasticTensileMulti is only defined for LIBMESH_DIM=3");
82 std::vector<Real> &
f)
const 84 std::vector<Real> eigvals;
89 f[0] = eigvals[0] +
_shift - str;
90 f[1] = eigvals[1] - str;
91 f[2] = eigvals[2] -
_shift - str;
96 const RankTwoTensor & stress, Real , std::vector<RankTwoTensor> & df_dstress)
const 98 std::vector<Real> eigvals;
101 if (eigvals[0] > eigvals[1] - 0.1 *
_shift || eigvals[1] > eigvals[2] - 0.1 *
_shift)
103 Real small_perturbation;
105 while (eigvals[0] > eigvals[1] - 0.1 *
_shift || eigvals[1] > eigvals[2] - 0.1 *
_shift)
107 for (
unsigned i = 0; i < 3; ++i)
108 for (
unsigned j = 0;
j <= i; ++
j)
111 shifted_stress(i,
j) += small_perturbation;
112 shifted_stress(
j, i) += small_perturbation;
122 std::vector<Real> & df_dintnl)
const 130 std::vector<RankTwoTensor> & r)
const 138 const RankTwoTensor & stress, Real , std::vector<RankFourTensor> & dr_dstress)
const 145 const RankTwoTensor & , Real , std::vector<RankTwoTensor> & dr_dintnl)
const 167 std::vector<bool> & act,
170 act.assign(3,
false);
174 returned_stress = stress;
179 std::vector<Real> dpm(3);
181 std::vector<Real> yf(3);
182 bool trial_stress_inadmissible;
192 trial_stress_inadmissible);
194 for (
unsigned i = 0; i < 3; ++i)
195 act[i] = (dpm[i] > 0);
200 const std::vector<Real> &
b)
const 202 return a[0] *
b[0] +
a[1] *
b[1] +
a[2] *
b[2];
207 const std::vector<Real> &
b,
208 const std::vector<Real> &
c)
const 210 return a[0] * (
b[1] *
c[2] -
b[2] *
c[1]) -
a[1] * (
b[0] *
c[2] -
b[2] *
c[0]) +
211 a[2] * (
b[0] *
c[1] -
b[1] *
c[0]);
217 return "TensileMulti";
224 Real ep_plastic_tolerance,
226 Real & returned_intnl,
227 std::vector<Real> & dpm,
229 std::vector<Real> & yf,
230 bool & trial_stress_inadmissible)
const 236 ep_plastic_tolerance,
242 trial_stress_inadmissible);
247 ep_plastic_tolerance,
253 trial_stress_inadmissible);
260 Real ep_plastic_tolerance,
262 Real & returned_intnl,
263 std::vector<Real> & dpm,
265 std::vector<Real> & yf,
266 bool & trial_stress_inadmissible)
const 268 mooseAssert(dpm.size() == 3,
269 "SolidMechanicsPlasticTensileMulti size of dpm should be 3 but it is " << dpm.size());
271 std::vector<Real> eigvals;
280 yf[0] = eigvals[0] - str;
281 yf[1] = eigvals[1] - str;
282 yf[2] = eigvals[2] - str;
287 trial_stress_inadmissible =
false;
291 trial_stress_inadmissible =
true;
293 returned_stress.
zero();
316 std::vector<RealVectorValue> n(3);
317 n[0](0) = E_ijkl(0, 0, 0, 0);
318 n[0](1) = E_ijkl(1, 1, 0, 0);
319 n[0](2) = E_ijkl(2, 2, 0, 0);
320 n[1](0) = E_ijkl(0, 0, 1, 1);
321 n[1](1) = E_ijkl(1, 1, 1, 1);
322 n[1](2) = E_ijkl(2, 2, 1, 1);
323 n[2](0) = E_ijkl(0, 0, 2, 2);
324 n[2](1) = E_ijkl(1, 1, 2, 2);
325 n[2](2) = E_ijkl(2, 2, 2, 2);
337 const unsigned int number_of_return_paths = 3;
338 std::vector<int> trial_order(number_of_return_paths);
342 trial_order[0] =
tip;
343 trial_order[1] =
edge;
344 trial_order[2] =
plane;
348 trial_order[0] =
edge;
349 trial_order[1] =
tip;
350 trial_order[2] =
plane;
354 trial_order[0] =
plane;
355 trial_order[1] =
edge;
356 trial_order[2] =
tip;
360 bool nr_converged =
false;
361 for (trial = 0; trial < number_of_return_paths; ++trial)
363 switch (trial_order[trial])
366 nr_converged =
returnTip(eigvals, n, dpm, returned_stress, intnl_old, 0);
369 nr_converged =
returnEdge(eigvals, n, dpm, returned_stress, intnl_old, 0);
372 nr_converged =
returnPlane(eigvals, n, dpm, returned_stress, intnl_old, 0);
378 if (nr_converged &&
KuhnTuckerOK(returned_stress, dpm, str, ep_plastic_tolerance))
382 if (trial == number_of_return_paths)
384 Moose::err <<
"Trial stress = \n";
385 trial_stress.
print(Moose::err);
386 Moose::err <<
"Internal parameter = " << intnl_old << std::endl;
387 mooseError(
"SolidMechanicsPlasticTensileMulti: FAILURE! You probably need to implement a " 391 yf[0] = eigvals[0] - str;
392 yf[1] = eigvals[1] - str;
393 yf[2] = eigvals[2] - str;
399 returned_intnl = intnl_old;
400 for (
unsigned i = 0; i < 3; ++i)
402 yf[i] = returned_stress(i, i) - str;
403 delta_dp(i, i) = dpm[i];
404 returned_intnl += dpm[i];
406 returned_stress = eigvecs * returned_stress * (eigvecs.
transpose());
407 delta_dp = eigvecs * delta_dp * (eigvecs.
transpose());
413 const std::vector<RealVectorValue> & n,
414 std::vector<Real> & dpm,
417 Real initial_guess)
const 437 Real x = initial_guess;
438 const Real denom = (n[0](0) - n[0](1)) * (n[0](0) + 2 * n[0](1));
451 const Real eig = eigvals[0] + eigvals[1] + eigvals[2];
452 const Real bul = (n[0](0) + 2 * n[0](1));
460 Real residual = bul *
x - eig + 3 * str;
462 unsigned int iter = 0;
466 x += -residual / jacobian;
470 residual = bul *
x - eig + 3 * str;
478 dpm[0] = (n[0](0) * (eigvals[0] - str) + n[0](1) * (eigvals[0] - eigvals[1] - eigvals[2] + str)) /
480 dpm[1] = (n[0](0) * (eigvals[1] - str) + n[0](1) * (eigvals[1] - eigvals[2] - eigvals[0] + str)) /
482 dpm[2] = (n[0](0) * (eigvals[2] - str) + n[0](1) * (eigvals[2] - eigvals[0] - eigvals[1] + str)) /
484 returned_stress(0, 0) = returned_stress(1, 1) = returned_stress(2, 2) = str;
490 const std::vector<RealVectorValue> & n,
491 std::vector<Real> & dpm,
494 Real initial_guess)
const 518 Real x = initial_guess;
519 const Real denom = n[0](0) + n[0](1);
532 const Real eig = eigvals[1] + eigvals[2];
533 Real residual = denom *
x - eig + 2 * str;
535 unsigned int iter = 0;
539 x += -residual / jacobian;
543 residual = denom *
x - eig + 2 * str;
549 dpm[1] = ((eigvals[1] * n[0](0) - eigvals[2] * n[0](1)) / (n[0](0) - n[0](1)) - str) / denom;
550 dpm[2] = ((eigvals[2] * n[0](0) - eigvals[1] * n[0](1)) / (n[0](0) - n[0](1)) - str) / denom;
552 returned_stress(0, 0) = eigvals[0] - n[0](1) * (dpm[1] + dpm[2]);
553 returned_stress(1, 1) = returned_stress(2, 2) = str;
559 const std::vector<RealVectorValue> & n,
560 std::vector<Real> & dpm,
563 Real initial_guess)
const 581 dpm[2] = initial_guess;
584 unsigned int iter = 0;
588 dpm[2] += -residual / jacobian;
591 residual = n[2](2) * dpm[2] - eigvals[2] +
tensile_strength(intnl_old + dpm[2]);
597 returned_stress(0, 0) = eigvals[0] - dpm[2] * n[2](0);
598 returned_stress(1, 1) = eigvals[1] - dpm[2] * n[2](1);
599 returned_stress(2, 2) = eigvals[2] - dpm[2] * n[2](2);
605 const std::vector<Real> & dpm,
607 Real ep_plastic_tolerance)
const 609 for (
unsigned i = 0; i < 3; ++i)
611 returned_diagonal_stress(i, i) - str, dpm[i], ep_plastic_tolerance))
623 const std::vector<Real> & cumulative_pm)
const 627 trial_stress, intnl_old, stress, intnl, E_ijkl, cumulative_pm);
629 mooseAssert(cumulative_pm.size() == 3,
630 "SolidMechanicsPlasticTensileMulti size of cumulative_pm should be 3 but it is " 631 << cumulative_pm.size());
633 if (cumulative_pm[2] <= 0)
637 std::vector<Real> eigvals;
643 std::vector<Real> trial_eigvals;
677 const Real la = E_ijkl(0, 0, 1, 1);
678 const Real mu = 0.5 * (E_ijkl(0, 0, 0, 0) - la);
680 if (cumulative_pm[1] <= 0)
683 const Real denom = hard + la + 2 *
mu;
684 const Real al = la * la / denom;
685 const Real be = la * (la + 2 *
mu) / denom;
686 const Real ga = hard * (la + 2 *
mu) / denom;
687 std::vector<Real> comps(9);
688 comps[0] = comps[4] = la + 2 *
mu - al;
689 comps[1] = comps[3] = la - al;
690 comps[2] = comps[5] = comps[6] = comps[7] = la - be;
694 else if (cumulative_pm[0] <= 0)
697 const Real denom = 2 * hard + 2 * la + 2 *
mu;
698 const Real al = hard * 2 * la / denom;
699 const Real be = hard * (2 * la + 2 *
mu) / denom;
700 std::vector<Real> comps(9);
701 comps[0] = la + 2 *
mu - 2 * la * la / denom;
702 comps[1] = comps[2] = al;
703 comps[3] = comps[6] = al;
704 comps[4] = comps[5] = comps[7] = comps[8] = be;
710 const Real denom = 3 * hard + 3 * la + 2 *
mu;
711 std::vector<Real> comps(2);
712 comps[0] = hard * (3 * la + 2 *
mu) / denom;
717 cto.
rotate(trial_eigvecs);
736 for (
unsigned k = 0;
k < 3; ++
k)
737 for (
unsigned b = 0;
b < 3; ++
b)
741 for (
unsigned m = 0; m < 3; ++m)
742 for (
unsigned n = 0; n < 3; ++n)
743 for (
unsigned i = 0; i < 3; ++i)
744 drdsig(i,
k, m, n) += trial_eigvecs(m,
b) * trial_eigvecs(n,
k) * trial_eigvecs(i,
b) /
745 (trial_eigvals[
k] - trial_eigvals[
b]);
755 for (
unsigned i = 0; i < 3; ++i)
756 for (
unsigned j = 0;
j < 3; ++
j)
757 for (
unsigned a = 0;
a < 3; ++
a)
758 for (
unsigned k = 0;
k < 3; ++
k)
759 for (
unsigned m = 0; m < 3; ++m)
760 ans(i,
j,
a,
a) += (drdsig(i,
k, m, m) * trial_eigvecs(
j,
k) +
761 trial_eigvecs(i,
k) * drdsig(
j,
k, m, m)) *
764 for (
unsigned i = 0; i < 3; ++i)
765 for (
unsigned j = 0;
j < 3; ++
j)
766 for (
unsigned a = 0;
a < 3; ++
a)
767 for (
unsigned b = 0;
b < 3; ++
b)
768 for (
unsigned k = 0;
k < 3; ++
k)
770 ans(i,
j,
a,
b) += (drdsig(i,
k,
a,
b) * trial_eigvecs(
j,
k) +
771 trial_eigvecs(i,
k) * drdsig(
j,
k,
a,
b)) *
773 ans(i,
j,
a,
b) += (drdsig(i,
k,
b,
a) * trial_eigvecs(
j,
k) +
774 trial_eigvecs(i,
k) * drdsig(
j,
k,
b,
a)) *
virtual void yieldFunctionV(const RankTwoTensor &stress, Real intnl, std::vector< Real > &f) const override
Calculates the yield functions.
void symmetricEigenvalues(std::vector< Real > &eigvals) 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 ...
void dsymmetricEigenvalues(std::vector< Real > &eigvals, std::vector< RankTwoTensorTempl< Real >> &deigvals) const
void print(std::ostream &stm=Moose::out) const
void seed(std::size_t i, unsigned int seed)
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 void dyieldFunction_dstressV(const RankTwoTensor &stress, Real intnl, std::vector< RankTwoTensor > &df_dstress) const override
The derivative of yield functions with respect to stress.
virtual std::string modelName() const =0
void fillFromInputVector(const std::vector< T > &input, FillMethod fill_method)
Real dot(const std::vector< Real > &a, const std::vector< Real > &b) const
dot product of two 3-dimensional vectors
bool KuhnTuckerSingleSurface(Real yf, Real dpm, Real dpm_tol) const
Returns true if the Kuhn-Tucker conditions for the single surface are satisfied.
virtual Real value(Real intnl) const
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.
bool returnPlane(const std::vector< Real > &eigvals, const std::vector< RealVectorValue > &n, std::vector< Real > &dpm, RankTwoTensor &returned_stress, Real intnl_old, Real initial_guess) const
Tries to return-map to the Tensile plane The return value is true if the internal Newton-Raphson proc...
registerMooseObjectRenamed("SolidMechanicsApp", TensorMechanicsPlasticTensileMulti, "01/01/2025 00:00", SolidMechanicsPlasticTensileMulti)
static InputParameters validParams()
const bool _use_custom_returnMap
Whether to use the custom return-map algorithm.
const std::vector< double > x
virtual std::string modelName() const override
Real f(Real x)
Test function for Brents method.
bool KuhnTuckerOK(const RankTwoTensor &returned_diagonal_stress, const std::vector< Real > &dpm, Real str, Real ep_plastic_tolerance) const
Returns true if the Kuhn-Tucker conditions are satisfied.
static const std::string mu
FiniteStrainTensileMulti implements rate-independent associative tensile failure with hardening/softe...
void d2symmetricEigenvalues(std::vector< RankFourTensorTempl< Real >> &deriv) const
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.
virtual bool doReturnMap(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
Just like returnMap, but a protected interface that definitely uses the algorithm, since returnMap itself does not use the algorithm if _use_returnMap=false.
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.
const SolidMechanicsHardeningModel & _strength
bool returnTip(const std::vector< Real > &eigvals, const std::vector< RealVectorValue > &n, std::vector< Real > &dpm, RankTwoTensor &returned_stress, Real intnl_old, Real initial_guess) const
Tries to return-map to the Tensile tip.
virtual void flowPotentialV(const RankTwoTensor &stress, Real intnl, std::vector< RankTwoTensor > &r) const override
The flow potentials.
void rotate(const TypeTensor< T > &R)
virtual bool useCustomReturnMap() const override
Returns false. You will want to override this in your derived class if you write a custom returnMap f...
virtual void dflowPotential_dstressV(const RankTwoTensor &stress, Real intnl, std::vector< RankFourTensor > &dr_dstress) const override
The derivative of the flow potential with respect to stress.
const Real _f_tol
Tolerance on yield function.
SolidMechanicsPlasticTensileMulti(const InputParameters ¶meters)
virtual Real derivative(Real intnl) const
RankTwoTensorTempl< Real > transpose() const
Hardening Model base class.
virtual void dyieldFunction_dintnlV(const RankTwoTensor &stress, Real intnl, std::vector< Real > &df_dintnl) const override
The derivative of yield functions with respect to the internal parameter.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const bool _use_custom_cto
Whether to use the custom consistent tangent operator calculation.
void symmetricEigenvaluesEigenvectors(std::vector< Real > &eigvals, RankTwoTensorTempl< Real > &eigvecs) const
const Real _shift
yield function is shifted by this amount to avoid problems with stress-derivatives at equal eigenvalu...
virtual void dflowPotential_dintnlV(const RankTwoTensor &stress, Real intnl, std::vector< RankTwoTensor > &dr_dintnl) const override
The derivative of the flow potential with respect to the internal parameter.
bool returnEdge(const std::vector< Real > &eigvals, const std::vector< RealVectorValue > &n, std::vector< Real > &dpm, RankTwoTensor &returned_stress, Real intnl_old, Real initial_guess) const
Tries to return-map to the Tensile edge.
registerMooseObject("SolidMechanicsApp", SolidMechanicsPlasticTensileMulti)
void mooseError(Args &&... args) const
Real triple(const std::vector< Real > &a, const std::vector< Real > &b, const std::vector< Real > &c) const
triple product of three 3-dimensional vectors
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
virtual unsigned int numberSurfaces() const override
The number of yield surfaces for this plasticity model.
static InputParameters validParams()
const ConsoleStream _console
virtual Real tensile_strength(const Real internal_param) const
tensile strength as a function of residual value, rate, and internal_param
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.
Plastic Model base class The virtual functions written below must be over-ridden in derived classes t...
virtual bool useCustomCTO() const override
Returns false. You will want to override this in your derived class if you write a custom consistent ...
static const std::string k
void ErrorVector unsigned int
const unsigned int _max_iters
maximum iterations allowed in the custom return-map algorithm