https://mooseframework.inl.gov
Classes | Functions
LagrangianObjectiveRates Namespace Reference

Objective-stress-rate updates as stateless free functions. More...

Classes

struct  Inputs
 Per-qp quantities a rate reads. More...
 
struct  Outputs
 Per-qp outputs a rate produces. More...
 

Functions

Outputs truesdell (const Inputs &in, bool need_jacobian)
 sigma_{n+1} = J(dL)^{-1} (sigma_n + Deltasigma). Truesdell rate. More...
 
Outputs jaumann (const Inputs &in, bool need_jacobian)
 sigma_{n+1} = J(dW)^{-1} (sigma_n + Deltasigma). Jaumann rate. More...
 
Outputs greenNaghdi (const Inputs &in, bool need_jacobian)
 sigma_{n+1} = J(dO)^{-1} (sigma_n + Deltasigma), with dO built from the polar rotation increment. More...
 
Outputs rashid (const Inputs &in, bool need_jacobian)
 sigma_{n+1} = r_hat (sigma_n + Deltasigma) r_hat^T, r_hat = exp(Deltaw). More...
 
Outputs compute (const MooseEnum &rate, const Inputs &in, bool need_jacobian)
 Dispatch to the rate selected by the objective_rate enum (truesdell / jaumann / green_naghdi / rashid). More...
 

Detailed Description

Objective-stress-rate updates as stateless free functions.

Each rate integrates the constitutive small-stress increment into the cumulative Cauchy stress using its objective-rate advection and, when requested, returns the consistent tangent d(sigma_cauchy)/d(dL) plus the eigenstrain sensitivity. The rates are pure functions of an explicit Inputs bundle – no coupling to the material that gathers them – so they can be unit tested in isolation and dispatched by a switch (composition, not a class hierarchy).

Function Documentation

◆ compute()

Outputs LagrangianObjectiveRates::compute ( const MooseEnum rate,
const Inputs in,
bool  need_jacobian 
)

Dispatch to the rate selected by the objective_rate enum (truesdell / jaumann / green_naghdi / rashid).

Errors on an unknown value.

Definition at line 290 of file LagrangianObjectiveRate.C.

Referenced by calculate(), ComputeLagrangianObjectiveStress::computeQpCauchyStress(), KKSPhaseConcentrationMultiPhaseMaterial::computeQpProperties(), KKSPhaseConcentrationMaterial::computeQpProperties(), and TEST().

291 {
292  const std::string s = rate;
293  if (s == "truesdell")
294  return truesdell(in, need_jacobian);
295  if (s == "jaumann")
296  return jaumann(in, need_jacobian);
297  if (s == "green_naghdi")
298  return greenNaghdi(in, need_jacobian);
299  if (s == "rashid")
300  return rashid(in, need_jacobian);
301  mooseError("Unknown objective_rate value: ", s);
302 }
void mooseError(Args &&... args)
Outputs greenNaghdi(const Inputs &in, bool need_jacobian)
sigma_{n+1} = J(dO)^{-1} (sigma_n + Deltasigma), with dO built from the polar rotation increment...
Outputs jaumann(const Inputs &in, bool need_jacobian)
sigma_{n+1} = J(dW)^{-1} (sigma_n + Deltasigma). Jaumann rate.
Outputs truesdell(const Inputs &in, bool need_jacobian)
sigma_{n+1} = J(dL)^{-1} (sigma_n + Deltasigma). Truesdell rate.
Outputs rashid(const Inputs &in, bool need_jacobian)
sigma_{n+1} = r_hat (sigma_n + Deltasigma) r_hat^T, r_hat = exp(Deltaw).

◆ greenNaghdi()

Outputs LagrangianObjectiveRates::greenNaghdi ( const Inputs in,
bool  need_jacobian 
)

sigma_{n+1} = J(dO)^{-1} (sigma_n + Deltasigma), with dO built from the polar rotation increment.

Definition at line 197 of file LagrangianObjectiveRate.C.

Referenced by compute(), and TEST().

198 {
199  usingTensorIndices(i, j, k, l, m);
200 
202  const RankTwoTensor dR = in.rotation * in.rotation_old.transpose() - I;
203  const RankTwoTensor dO = dR * in.inv_df;
204 
205  Outputs out;
206  if (!need_jacobian)
207  {
208  out.cauchy_stress = advectStressSolve(in.cauchy_stress_old + in.dS, dO);
209  return out;
210  }
211 
212  auto [S, Jinv] = advectStress(in.cauchy_stress_old + in.dS, dO);
213  out.cauchy_stress = S;
214  out.dcauchy_stress_d_eigenstrain = -Jinv * in.small_jacobian;
215 
216  const RankFourTensor & d_R_d_F = in.d_rotation_d_F;
217  const RankFourTensor d_F_d_dL = in.d_dL_d_F.inverse();
218  const RankTwoTensor T = in.rotation_old.transpose() * in.inv_df;
219 
220  const RankFourTensor d_invdf_d_F = -in.inv_df.times<i, k, l, j>(in.inv_def_grad);
221  const RankFourTensor d_invdf_d_dL = d_invdf_d_F * d_F_d_dL;
222  const RankFourTensor d_dO_d_invdf = dR.times<i, k, j, l>(I);
223 
224  const RankFourTensor d_dO_d_dL =
225  T.times<m, j, i, m, k, l>(d_R_d_F * d_F_d_dL) + d_dO_d_invdf * d_invdf_d_dL;
226  const RankFourTensor U = stressAdvectionDerivative(S) * d_dO_d_dL;
227  out.cauchy_jacobian = cauchyJacobian(Jinv, in.small_jacobian, U);
228  return out;
229 }
RankFourTensorTempl< T > inverse() const
const double T
static RankTwoTensorTempl Identity()
static const std::string S
Definition: NS.h:167
RankTwoTensorTempl< Real > transpose() const
RankFourTensorTempl< Real > times(const RankTwoTensorTempl< Real > &b) const
OStreamProxy out
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
static const std::string k
Definition: NS.h:134

◆ jaumann()

Outputs LagrangianObjectiveRates::jaumann ( const Inputs in,
bool  need_jacobian 
)

sigma_{n+1} = J(dW)^{-1} (sigma_n + Deltasigma). Jaumann rate.

Definition at line 174 of file LagrangianObjectiveRate.C.

Referenced by compute(), and TEST().

175 {
176  Outputs out;
177  if (!need_jacobian)
178  {
179  out.cauchy_stress = advectStressSolve(in.cauchy_stress_old + in.dS, in.dW);
180  return out;
181  }
182 
183  auto [S, Jinv] = advectStress(in.cauchy_stress_old + in.dS, in.dW);
184  out.cauchy_stress = S;
185  out.dcauchy_stress_d_eigenstrain = -Jinv * in.small_jacobian;
186 
187  const RankFourTensor d_dW_d_dL = in.d_dW_d_F * in.d_dL_d_F.inverse();
188  const RankFourTensor U = stressAdvectionDerivative(S) * d_dW_d_dL;
189  out.cauchy_jacobian = cauchyJacobian(Jinv, in.small_jacobian, U);
190  return out;
191 }
RankFourTensorTempl< T > inverse() const
static const std::string S
Definition: NS.h:167
OStreamProxy out

◆ rashid()

Outputs LagrangianObjectiveRates::rashid ( const Inputs in,
bool  need_jacobian 
)

sigma_{n+1} = r_hat (sigma_n + Deltasigma) r_hat^T, r_hat = exp(Deltaw).

See rashid_project/plan_outline.pdf Sec.3.2.

Definition at line 235 of file LagrangianObjectiveRate.C.

Referenced by compute(), and TEST().

236 {
237  usingTensorIndices(i_, j_, k_, l_, m_, n_);
238 
239  // r_hat = exp(Deltaw). Skip its R4 derivative when we don't need the Jacobian.
240  RankFourTensor d_rhat_d_dW;
241  const RankTwoTensor rhat = rotationFromVorticity(in.dW, need_jacobian ? &d_rhat_d_dW : nullptr);
242  const RankTwoTensor rhatT = rhat.transpose();
243 
244  // sigma_{n+1} = r_hat (sigma_n + Deltasigma) r_hat^T (eq. 22)
245  const RankTwoTensor S_inner = in.cauchy_stress_old + in.dS;
246  Outputs out;
247  out.cauchy_stress = rhat * S_inner * rhatT;
248 
249  if (!need_jacobian)
250  return out;
251 
252  // J^{-1}_{ijkl} = r_hat_ik r_hat_jl (eq. 24), the rank-4 (r_hat (x) r_hat) sandwich. Used for
253  // the eigenstrain Jacobian and as the "outer" operator for the constitutive piece. We name the
254  // dummy "middle pair" k, l here (output indices i, j, k, l) -- when chained via
255  // RankFourTensor::operator*, the k, l contract against small_jacobian's first pair, as desired.
256  const RankFourTensor J_inv = rhat.times<i_, k_, j_, l_>(rhat);
257 
258  // dsigma/d(eigenstrain) = -J^{-1} : small_jacobian.
259  // (mechanical_strain = total_strain - eigenstrain, hence the minus.)
260  out.dcauchy_stress_d_eigenstrain = -(J_inv * in.small_jacobian);
261 
262  // Chain rule pieces for dsigma/d(dL):
263  // d(Deltaw)/d(dL) = d(dW)/dF * inverse(d(dL)/dF)
264  // d(Deltad)/d(dL) = I^(4) - d(Deltaw)/d(dL) (Deltad + Deltaw = dL by construction).
265  // d(r_hat)/d(dL) = d(r_hat)/d(Deltaw) * d(Deltaw)/d(dL).
266  const RankFourTensor d_F_d_dL = in.d_dL_d_F.inverse();
267  const RankFourTensor d_dW_d_dL = in.d_dW_d_F * d_F_d_dL;
268  const RankFourTensor d_dD_d_dL = RankFourTensor::IdentityFour() - d_dW_d_dL;
269  const RankFourTensor d_rhat_d_dL = d_rhat_d_dW * d_dW_d_dL;
270 
271  // Rotation pieces of dsigma/d(dL):
272  // T1_{ijkl} = (d_rhat_d_dL)_{imkl} * (S r_hat^T)_{mj}
273  // T2_{ijkl} = (r_hat S)_{im} * (d_rhat_d_dL)_{jmkl}
274  const RankTwoTensor SR = S_inner * rhatT; // S r_hat^T (shape (m, j))
275  const RankTwoTensor RS = rhat * S_inner; // r_hat S (shape (i, m))
276  const RankFourTensor T1 = SR.times<m_, j_, i_, m_, k_, l_>(d_rhat_d_dL);
277  const RankFourTensor T2 = RS.times<i_, m_, j_, m_, k_, l_>(d_rhat_d_dL);
278 
279  // Constitutive piece: J^{-1} : (small_jacobian * d(Deltad)/d(dL)).
280  const RankFourTensor T3 = J_inv * (in.small_jacobian * d_dD_d_dL);
281 
282  out.cauchy_jacobian = T1 + T2 + T3;
283  return out;
284 }
RankFourTensorTempl< T > inverse() const
static RankFourTensorTempl< Real > IdentityFour()
RankTwoTensorTempl< Real > transpose() const
RankFourTensorTempl< Real > times(const RankTwoTensorTempl< Real > &b) const
OStreamProxy out

◆ truesdell()

Outputs LagrangianObjectiveRates::truesdell ( const Inputs in,
bool  need_jacobian 
)

sigma_{n+1} = J(dL)^{-1} (sigma_n + Deltasigma). Truesdell rate.

Definition at line 152 of file LagrangianObjectiveRate.C.

Referenced by compute(), and TEST().

153 {
154  Outputs out;
155  if (!need_jacobian)
156  {
157  out.cauchy_stress = advectStressSolve(in.cauchy_stress_old + in.dS, in.dL);
158  return out;
159  }
160 
161  auto [S, Jinv] = advectStress(in.cauchy_stress_old + in.dS, in.dL);
162  out.cauchy_stress = S;
163  out.dcauchy_stress_d_eigenstrain = -Jinv * in.small_jacobian;
164 
165  const RankFourTensor U = stressAdvectionDerivative(S);
166  out.cauchy_jacobian = cauchyJacobian(Jinv, in.small_jacobian, U);
167  return out;
168 }
static const std::string S
Definition: NS.h:167
OStreamProxy out