https://mooseframework.inl.gov
LagrangianObjectiveRateTest.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 
10 #include "gtest/gtest.h"
11 
13 #include "RankTwoTensor.h"
14 #include "RankFourTensor.h"
15 
16 // Unit tests for the objective-stress-rate free functions. These exercise the rate math in
17 // isolation -- no host material, no assembly -- which is exactly what the free-function form
18 // (vs the former host-coupled strategy hierarchy) enables.
19 
20 using namespace LagrangianObjectiveRates;
21 
22 namespace
23 {
26 isotropicC()
27 {
29  C.fillFromInputVector({100.0, 60.0}, RankFourTensor::symmetric_isotropic); // {lambda, mu}
30  return C;
31 }
32 
34 const RankTwoTensor kSigmaOld(30.0, -10.0, 15.0, 4.0, -3.0, 6.0);
35 
40 Inputs
41 makeInputs(const RankFourTensor & C, const RankTwoTensor & dL)
42 {
43  Inputs in;
44  in.small_jacobian = C;
45  in.cauchy_stress_old = kSigmaOld;
46  in.dL = dL;
47  in.dW = 0.5 * (dL - dL.transpose());
48  in.dS = C * (0.5 * (dL + dL.transpose()));
50  // d(skew(A))/dA = 1/2 (I^(4) - swap_ij), swap_ij = I^(4) with its first index pair transposed.
51  in.d_dW_d_F =
53  return in;
54 }
55 
57 void
58 checkJacobianFD(Outputs (*rate)(const Inputs &, bool),
59  const RankFourTensor & C,
60  const RankTwoTensor & dL)
61 {
62  const RankFourTensor J = rate(makeInputs(C, dL), true).cauchy_jacobian;
63  const Real eps = 1.0e-6;
64  RankFourTensor Jfd;
65  for (unsigned int k = 0; k < 3; ++k)
66  for (unsigned int l = 0; l < 3; ++l)
67  {
68  RankTwoTensor dLp = dL, dLm = dL;
69  dLp(k, l) += eps;
70  dLm(k, l) -= eps;
71  const RankTwoTensor d = (rate(makeInputs(C, dLp), false).cauchy_stress -
72  rate(makeInputs(C, dLm), false).cauchy_stress) /
73  (2.0 * eps);
74  for (unsigned int i = 0; i < 3; ++i)
75  for (unsigned int j = 0; j < 3; ++j)
76  Jfd(i, j, k, l) = d(i, j);
77  }
78  EXPECT_LT((Jfd - J).L2norm(), 1.0e-4 * J.L2norm());
79 }
80 }
81 
82 // With no kinematic increment every rate leaves the stress unadvected: sigma_{n+1} = sigma_n + dS.
83 TEST(LagrangianObjectiveRateTest, zeroIncrement)
84 {
85  Inputs in = makeInputs(isotropicC(), RankTwoTensor()); // dL = 0 -> dS = 0, dW = 0
90  const RankTwoTensor expected = in.cauchy_stress_old + in.dS;
91  EXPECT_LT((truesdell(in, false).cauchy_stress - expected).L2norm(), 1.0e-12);
92  EXPECT_LT((jaumann(in, false).cauchy_stress - expected).L2norm(), 1.0e-12);
93  EXPECT_LT((greenNaghdi(in, false).cauchy_stress - expected).L2norm(), 1.0e-12);
94  EXPECT_LT((rashid(in, false).cauchy_stress - expected).L2norm(), 1.0e-12);
95 }
96 
97 // Consistent-tangent checks: the returned cauchy_jacobian must equal d(cauchy_stress)/d(dL).
98 TEST(LagrangianObjectiveRateTest, truesdellJacobian)
99 {
100  checkJacobianFD(&truesdell, isotropicC(), RankTwoTensor(0.03, -0.02, 0.01, 0.015, -0.01, 0.02));
101 }
102 
103 TEST(LagrangianObjectiveRateTest, jaumannJacobian)
104 {
105  checkJacobianFD(&jaumann, isotropicC(), RankTwoTensor(0.03, -0.02, 0.01, 0.015, -0.01, 0.02));
106 }
107 
108 TEST(LagrangianObjectiveRateTest, rashidJacobian)
109 {
110  // Add an antisymmetric part so r_hat = exp(skew(dL)) != I and the Rodrigues chain is exercised.
111  RankTwoTensor dL(0.03, -0.02, 0.01, 0.015, -0.01, 0.02);
112  dL(0, 1) += 0.02;
113  dL(1, 0) -= 0.02;
114  checkJacobianFD(&rashid, isotropicC(), dL);
115 }
static RankFourTensorTempl< Real > IdentityFour()
T L2norm(const RankTwoTensorTempl< T > &r2tensor)
const Real eps
TEST(LagrangianObjectiveRateTest, zeroIncrement)
RankFourTensor d_dL_d_F
d(dL)/dF and d(dW)/dF from the strain calculator.
Per-qp quantities a rate reads.
Objective-stress-rate updates as stateless free functions.
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.
static RankTwoTensorTempl Identity()
RankTwoTensor dS
Constitutive small-stress increment (_small_stress - _small_stress_old).
RankTwoTensor cauchy_stress_old
Cumulative Cauchy stress at step n.
RankTwoTensorTempl< Real > transpose() const
RankFourTensorTempl< T > transposeIj() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
RankTwoTensor rotation
Green-Naghdi only: polar-decomposition rotation R (n+1 and n), the inverse incremental deformation gr...
Outputs truesdell(const Inputs &in, bool need_jacobian)
sigma_{n+1} = J(dL)^{-1} (sigma_n + Deltasigma). Truesdell rate.
RankTwoTensor dL
Spatial velocity gradient increment dL and its vorticity (skew) part dW.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
Per-qp outputs a rate produces.
RankFourTensor small_jacobian
Small-strain algorithmic tangent.
Outputs rashid(const Inputs &in, bool need_jacobian)
sigma_{n+1} = r_hat (sigma_n + Deltasigma) r_hat^T, r_hat = exp(Deltaw).
static const std::string k
Definition: NS.h:134
static const std::string C
Definition: NS.h:172