11 #include "RankFourTensor.h"
12 #include "libmesh/utility.h"
22 params.addRequiredParam<UserObjectName>(
24 "A TensorMechanicsHardening UserObject that defines hardening of the cohesion. "
25 "Physically the cohesion should not be negative.");
26 params.addRequiredParam<UserObjectName>(
28 "A TensorMechanicsHardening UserObject that defines hardening of the "
29 "friction angle (in radians). Physically the friction angle should be "
30 "between 0 and 90deg.");
31 params.addRequiredParam<UserObjectName>(
33 "A TensorMechanicsHardening UserObject that defines hardening of the "
34 "dilation angle (in radians). Usually the dilation angle is not greater "
35 "than the friction angle, and it is between 0 and 90deg.");
36 params.addRangeCheckedParam<Real>(
39 "mc_edge_smoother>=0 & mc_edge_smoother<=30",
40 "Smoothing parameter: the edges of the cone are smoothed by the given amount.");
41 MooseEnum tip_scheme(
"hyperbolic cap",
"hyperbolic");
42 params.addParam<MooseEnum>(
43 "tip_scheme", tip_scheme,
"Scheme by which the pyramid's tip will be smoothed.");
44 params.addRequiredRangeCheckedParam<Real>(
"mc_tip_smoother",
46 "Smoothing parameter: the cone vertex at mean = "
47 "cohesion*cot(friction_angle), will be smoothed by "
48 "the given amount. Typical value is 0.1*cohesion");
49 params.addParam<Real>(
52 "For the 'cap' tip_scheme, smoothing is performed in the stress_mean > cap_start region");
53 params.addRangeCheckedParam<Real>(
"cap_rate",
56 "For the 'cap' tip_scheme, this controls how quickly the cap "
57 "degenerates to a hemisphere: small values mean a slow "
58 "degeneration to a hemisphere (and zero means the 'cap' will "
59 "be totally inactive). Typical value is 1/tensile_strength");
60 params.addParam<Real>(
"mc_lode_cutoff",
61 "If the second invariant of stress is less than this "
62 "amount, the Lode angle is assumed to be zero. This is "
63 "to gaurd against precision-loss problems, and this "
64 "parameter should be set small. Default = "
65 "0.00001*((yield_Function_tolerance)^2)");
66 params.addClassDescription(
"Non-associative Mohr-Coulomb plasticity with hardening/softening");
72 const InputParameters & parameters)
77 _tip_scheme(getParam<MooseEnum>(
"tip_scheme")),
78 _small_smoother2(Utility::
pow<2>(getParam<Real>(
"mc_tip_smoother"))),
79 _cap_start(getParam<Real>(
"cap_start")),
80 _cap_rate(getParam<Real>(
"cap_rate")),
81 _tt(getParam<Real>(
"mc_edge_smoother") *
libMesh::pi / 180.0),
82 _costt(std::cos(_tt)),
83 _sintt(std::sin(_tt)),
84 _cos3tt(std::cos(3 * _tt)),
85 _sin3tt(std::sin(3 * _tt)),
86 _cos6tt(std::cos(6 * _tt)),
87 _sin6tt(std::sin(6 * _tt)),
88 _lode_cutoff(parameters.isParamValid(
"mc_lode_cutoff") ? getParam<Real>(
"mc_lode_cutoff")
89 : 1.0E-5 * Utility::
pow<2>(_f_tol))
93 mooseError(
"mc_lode_cutoff must not be negative");
97 if (
phi(0) < 0 ||
psi(0) < 0 ||
phi(0) > libMesh::pi / 2.0 ||
psi(0) > libMesh::pi / 2.0)
98 mooseError(
"Mohr-Coulomb friction and dilation angles must lie in [0, Pi/2]");
100 mooseError(
"Mohr-Coulomb friction angle must not be less than Mohr-Coulomb dilation angle");
102 mooseError(
"Mohr-Coulomb cohesion must not be negative");
107 Real sin_angle = std::sin(std::max(
phi(0),
psi(0)));
108 sin_angle = std::max(sin_angle, std::sin(std::max(
phi(1E6),
psi(1E6))));
109 Real rhs = std::sqrt(3) * (35 * std::sin(
_tt) + 14 * std::sin(5 *
_tt) - 5 * std::sin(7 *
_tt)) /
110 16 / Utility::pow<5>(std::cos(
_tt)) / (11 - 10 * std::cos(2 *
_tt));
111 if (rhs <= sin_angle)
112 mooseError(
"Mohr-Coulomb edge smoothing angle is too small and a non-convex yield surface will "
113 "result. Please choose a larger value");
119 Real mean_stress = stress.trace() / 3.0;
120 Real sinphi = std::sin(
phi(intnl));
121 Real cosphi = std::cos(
phi(intnl));
123 if (std::abs(sin3Lode) <=
_sin3tt)
126 std::vector<Real> eigvals;
127 stress.symmetricEigenvalues(eigvals);
128 return mean_stress * sinphi +
129 std::sqrt(
smooth(stress) +
130 0.25 * Utility::pow<2>(eigvals[2] - eigvals[0] +
131 (eigvals[2] + eigvals[0] - 2 * mean_stress) * sinphi)) -
138 abbo(sin3Lode, sinphi, aaa, bbb, ccc);
139 Real kk = aaa + bbb * sin3Lode + ccc * Utility::pow<2>(sin3Lode);
140 Real sibar2 = stress.secondInvariant();
141 return mean_stress * sinphi + std::sqrt(
smooth(stress) + sibar2 * Utility::pow<2>(kk)) -
149 Real mean_stress = stress.trace() / 3.0;
152 if (std::abs(sin3Lode) <=
_sin3tt)
155 std::vector<Real> eigvals;
156 std::vector<RankTwoTensor> deigvals;
157 stress.dsymmetricEigenvalues(eigvals, deigvals);
158 Real tmp = eigvals[2] - eigvals[0] + (eigvals[2] + eigvals[0] - 2.0 * mean_stress) * sin_angle;
160 deigvals[2] - deigvals[0] + (deigvals[2] + deigvals[0] - 2.0 * dmean_stress) * sin_angle;
161 Real denom = std::sqrt(
smooth(stress) + 0.25 * Utility::pow<2>(tmp));
162 return dmean_stress * sin_angle +
163 (0.5 *
dsmooth(stress) * dmean_stress + 0.25 * tmp * dtmp) / denom;
169 abbo(sin3Lode, sin_angle, aaa, bbb, ccc);
170 Real kk = aaa + bbb * sin3Lode + ccc * Utility::pow<2>(sin3Lode);
172 Real sibar2 = stress.secondInvariant();
174 Real denom = std::sqrt(
smooth(stress) + sibar2 * Utility::pow<2>(kk));
175 return dmean_stress * sin_angle + (0.5 *
dsmooth(stress) * dmean_stress +
176 0.5 * dsibar2 * Utility::pow<2>(kk) + sibar2 * kk * dkk) /
185 Real sinphi = std::sin(
phi(intnl));
186 return df_dsig(stress, sinphi);
193 Real sin_angle = std::sin(
phi(intnl));
194 Real cos_angle = std::cos(
phi(intnl));
195 Real dsin_angle = cos_angle *
dphi(intnl);
196 Real dcos_angle = -sin_angle *
dphi(intnl);
198 Real mean_stress = stress.trace() / 3.0;
200 if (std::abs(sin3Lode) <=
_sin3tt)
203 std::vector<Real> eigvals;
204 stress.symmetricEigenvalues(eigvals);
205 Real tmp = eigvals[2] - eigvals[0] + (eigvals[2] + eigvals[0] - 2 * mean_stress) * sin_angle;
206 Real dtmp = (eigvals[2] + eigvals[0] - 2 * mean_stress) * dsin_angle;
207 Real denom = std::sqrt(
smooth(stress) + 0.25 * Utility::pow<2>(tmp));
208 return mean_stress * dsin_angle + 0.25 * tmp * dtmp / denom -
dcohesion(intnl) * cos_angle -
215 abbo(sin3Lode, sin_angle, aaa, bbb, ccc);
216 Real daaa, dbbb, dccc;
217 dabbo(sin3Lode, sin_angle, daaa, dbbb, dccc);
218 Real kk = aaa + bbb * sin3Lode + ccc * Utility::pow<2>(sin3Lode);
219 Real dkk = (daaa + dbbb * sin3Lode + dccc * Utility::pow<2>(sin3Lode)) * dsin_angle;
220 Real sibar2 = stress.secondInvariant();
221 Real denom = std::sqrt(
smooth(stress) + sibar2 * Utility::pow<2>(kk));
222 return mean_stress * dsin_angle + sibar2 * kk * dkk / denom -
dcohesion(intnl) * cos_angle -
230 Real sinpsi = std::sin(
psi(intnl));
231 return df_dsig(stress, sinpsi);
239 Real sin_angle = std::sin(
psi(intnl));
240 Real mean_stress = stress.trace() / 3.0;
243 if (std::abs(sin3Lode) <=
_sin3tt)
246 std::vector<Real> eigvals;
247 std::vector<RankTwoTensor> deigvals;
248 std::vector<RankFourTensor> d2eigvals;
249 stress.dsymmetricEigenvalues(eigvals, deigvals);
250 stress.d2symmetricEigenvalues(d2eigvals);
252 Real tmp = eigvals[2] - eigvals[0] + (eigvals[2] + eigvals[0] - 2.0 * mean_stress) * sin_angle;
254 deigvals[2] - deigvals[0] + (deigvals[2] + deigvals[0] - 2.0 * dmean_stress) * sin_angle;
255 Real denom = std::sqrt(
smooth(stress) + 0.25 * Utility::pow<2>(tmp));
256 Real denom3 = Utility::pow<3>(denom);
257 Real d2smooth_over_denom =
d2smooth(stress) / denom;
260 dr_dstress = 0.25 * tmp *
261 (d2eigvals[2] - d2eigvals[0] + (d2eigvals[2] + d2eigvals[0]) * sin_angle) / denom;
263 for (
unsigned i = 0; i < 3; ++i)
264 for (
unsigned j = 0; j < 3; ++j)
265 for (
unsigned k = 0; k < 3; ++k)
266 for (
unsigned l = 0; l < 3; ++l)
268 dr_dstress(i, j, k, l) +=
269 0.5 * d2smooth_over_denom * dmean_stress(i, j) * dmean_stress(k, l);
270 dr_dstress(i, j, k, l) += 0.25 * dtmp(i, j) * dtmp(k, l) / denom;
271 dr_dstress(i, j, k, l) -= 0.25 * numer(i, j) * numer(k, l) / denom3;
278 abbo(sin3Lode, sin_angle, aaa, bbb, ccc);
280 Real kk = aaa + bbb * sin3Lode + ccc * Utility::pow<2>(sin3Lode);
283 for (
unsigned i = 0; i < 3; ++i)
284 for (
unsigned j = 0; j < 3; ++j)
285 for (
unsigned k = 0; k < 3; ++k)
286 for (
unsigned l = 0; l < 3; ++l)
287 d2kk(i, j, k, l) += 2 * ccc * dsin3Lode(i, j) * dsin3Lode(k, l);
289 Real sibar2 = stress.secondInvariant();
293 Real denom = std::sqrt(
smooth(stress) + sibar2 * Utility::pow<2>(kk));
294 Real denom3 = Utility::pow<3>(denom);
295 Real d2smooth_over_denom =
d2smooth(stress) / denom;
297 0.5 *
dsmooth(stress) * dmean_stress + 0.5 * dsibar2 * kk * kk + sibar2 * kk * dkk;
299 dr_dstress = (0.5 * d2sibar2 * Utility::pow<2>(kk) + sibar2 * kk * d2kk) / denom;
300 for (
unsigned i = 0; i < 3; ++i)
301 for (
unsigned j = 0; j < 3; ++j)
302 for (
unsigned k = 0; k < 3; ++k)
303 for (
unsigned l = 0; l < 3; ++l)
305 dr_dstress(i, j, k, l) +=
306 0.5 * d2smooth_over_denom * dmean_stress(i, j) * dmean_stress(k, l);
307 dr_dstress(i, j, k, l) +=
308 (dsibar2(i, j) * dkk(k, l) * kk + dkk(i, j) * dsibar2(k, l) * kk +
309 sibar2 * dkk(i, j) * dkk(k, l)) /
311 dr_dstress(i, j, k, l) -= numer_full(i, j) * numer_full(k, l) / denom3;
321 Real sin_angle = std::sin(
psi(intnl));
322 Real dsin_angle = std::cos(
psi(intnl)) *
dpsi(intnl);
324 Real mean_stress = stress.trace() / 3.0;
328 if (std::abs(sin3Lode) <=
_sin3tt)
331 std::vector<Real> eigvals;
332 std::vector<RankTwoTensor> deigvals;
333 stress.dsymmetricEigenvalues(eigvals, deigvals);
334 Real tmp = eigvals[2] - eigvals[0] + (eigvals[2] + eigvals[0] - 2.0 * mean_stress) * sin_angle;
335 Real dtmp_dintnl = (eigvals[2] + eigvals[0] - 2 * mean_stress) * dsin_angle;
337 deigvals[2] - deigvals[0] + (deigvals[2] + deigvals[0] - 2.0 * dmean_stress) * sin_angle;
339 (deigvals[2] + deigvals[0] - 2.0 * dmean_stress) * dsin_angle;
340 Real denom = std::sqrt(
smooth(stress) + 0.25 * Utility::pow<2>(tmp));
341 return dmean_stress * dsin_angle + 0.25 * dtmp_dintnl * dtmp_dstress / denom +
342 0.25 * tmp * d2tmp_dstress_dintnl / denom -
343 0.5 * (
dsmooth(stress) * dmean_stress + 0.5 * tmp * dtmp_dstress) * 0.25 * tmp *
344 dtmp_dintnl / Utility::pow<3>(denom);
350 abbo(sin3Lode, sin_angle, aaa, bbb, ccc);
351 Real kk = aaa + bbb * sin3Lode + ccc * Utility::pow<2>(sin3Lode);
353 Real daaa, dbbb, dccc;
354 dabbo(sin3Lode, sin_angle, daaa, dbbb, dccc);
355 Real dkk_dintnl = (daaa + dbbb * sin3Lode + dccc * Utility::pow<2>(sin3Lode)) * dsin_angle;
358 (dbbb + 2 * dccc * sin3Lode) * stress.dsin3Lode(
_lode_cutoff) * dsin_angle;
360 Real sibar2 = stress.secondInvariant();
362 Real denom = std::sqrt(
smooth(stress) + sibar2 * Utility::pow<2>(kk));
364 return dmean_stress * dsin_angle +
365 (dsibar2 * kk * dkk_dintnl + sibar2 * dkk_dintnl * dkk_dstress +
366 sibar2 * kk * d2kk_dstress_dintnl) /
368 (0.5 *
dsmooth(stress) * dmean_stress + 0.5 * dsibar2 * Utility::pow<2>(kk) +
369 sibar2 * kk * dkk_dstress) *
370 sibar2 * kk * dkk_dintnl / Utility::pow<3>(denom);
412 const Real sin3lode,
const Real sin_angle, Real & aaa, Real & bbb, Real & ccc)
const
414 Real tmp1 = (sin3lode >= 0 ?
_costt - sin_angle *
_sintt / std::sqrt(3.0)
416 Real tmp2 = (sin3lode >= 0 ?
_sintt + sin_angle *
_costt / std::sqrt(3.0)
420 ccc += (sin3lode >= 0 ? -3 *
_sin3tt * tmp2 : 3 *
_sin3tt * tmp2);
421 ccc /= 18 * Utility::pow<3>(
_cos3tt);
425 bbb /= 18 * Utility::pow<3>(
_cos3tt);
427 aaa = (sin3lode >= 0 ? -sin_angle *
_sintt / std::sqrt(3.0) - bbb *
_sin3tt
434 const Real sin3lode,
const Real , Real & daaa, Real & dbbb, Real & dccc)
const
436 Real dtmp1 = (sin3lode >= 0 ? -
_sintt / std::sqrt(3.0) :
_sintt / std::sqrt(3.0));
437 Real dtmp2 =
_costt / std::sqrt(3.0);
440 dccc += (sin3lode >= 0 ? -3 *
_sin3tt * dtmp2 : 3 *
_sin3tt * dtmp2);
441 dccc /= 18 * Utility::pow<3>(
_cos3tt);
445 dbbb /= 18 * Utility::pow<3>(
_cos3tt);
447 daaa = (sin3lode >= 0 ? -
_sintt / std::sqrt(3.0) - dbbb *
_sin3tt
449 daaa += -dccc * Utility::pow<2>(
_sin3tt);
462 smoother2 += Utility::pow<2>(p);
481 dsmoother2 += 2 * p * dp_dx;
489 Real d2smoother2 = 0;
503 d2smoother2 += 2 * Utility::pow<2>(dp_dx) + 2 * p * d2p_dx2;
511 return "MohrCoulomb";