12 #ifndef MFEM_ELASTICITY_MAT_NEOHOOKEAN_HPP 13 #define MFEM_ELASTICITY_MAT_NEOHOOKEAN_HPP 20 using mfem::internal::tensor;
21 using mfem::internal::make_tensor;
39 template <
int dim = 3, GradientType gradient_type = GradientType::Symbolic>
42 static_assert(
dim == 3,
"NeoHookean model currently implemented only in 3D");
51 MFEM_HOST_DEVICE tensor<T, dim, dim>
52 stress(
const tensor<T, dim, dim> &dudx)
const 54 static constexpr
auto I = mfem::internal::IsotropicIdentity<dim>();
56 T
p = -2.0 *
D1 * J * (J - 1);
57 auto devB = dev(dudx + transpose(dudx) + dot(dudx, transpose(dudx)));
58 auto sigma = -(
p / J) * I + 2 * (
C1 / pow(J, 5.0 / 3.0)) * devB;
72 MFEM_HOST_DEVICE
static void 74 tensor<double, dim, dim> &dudx,
75 tensor<double, dim, dim> &
sigma)
77 sigma =
self->stress(dudx);
90 MFEM_HOST_DEVICE tensor<double, dim, dim, dim, dim>
93 static constexpr
auto I = mfem::internal::IsotropicIdentity<dim>();
95 tensor<double, dim, dim> F = I + dudx;
96 tensor<double, dim, dim> invF = inv(F);
97 tensor<double, dim, dim> devB =
98 dev(dudx + transpose(dudx) + dot(dudx, transpose(dudx)));
100 double coef = (
C1 / pow(J, 5.0 / 3.0));
101 return make_tensor<dim, dim, dim, dim>([&](
int i,
int j,
int k,
104 return 2.0 * (
D1 * J * (i == j) - (5.0 / 3.0) * coef * devB[i][j]) *
107 ((i == k) * F[j][l] + F[i][l] * (j == k) -
108 (2.0 / 3.0) * ((i == j) * F[k][l]));
119 MFEM_HOST_DEVICE tensor<double, dim, dim>
121 const tensor<double, dim, dim> &ddudx)
const 127 #ifdef MFEM_USE_ENZYME 147 return tensor<double, dim, dim>{};
150 MFEM_HOST_DEVICE tensor<double, dim, dim>
152 const tensor<double, dim, dim> &ddudx)
const 154 auto sigma =
stress(make_tensor<dim, dim>([&](
int i,
int j)
156 return mfem::internal::dual<double, double> {dudx[i][j], ddudx[i][j]};
158 return make_tensor<dim, dim>(
159 [&](
int i,
int j) {
return sigma[i][j].gradient; });
162 #ifdef MFEM_USE_ENZYME 163 MFEM_HOST_DEVICE tensor<double, dim, dim>
165 const tensor<double, dim, dim> &ddudx)
const 167 tensor<double, dim, dim>
sigma{};
168 tensor<double, dim, dim> dsigma{};
175 MFEM_HOST_DEVICE tensor<double, dim, dim>
177 const tensor<double, dim, dim> &ddudx)
const 179 tensor<double, dim, dim, dim, dim>
gradient{};
180 tensor<double, dim, dim>
sigma{};
181 tensor<double, dim, dim> dir{};
183 for (
int i = 0; i <
dim; i++)
185 for (
int j = 0; j <
dim; j++)
198 MFEM_HOST_DEVICE tensor<double, dim, dim>
200 const tensor<double, dim, dim> &ddudx)
const 202 return (
stress(dudx + 1.0e-8 * ddudx) -
stress(dudx - 1.0e-8 * ddudx)) /
208 MFEM_HOST_DEVICE tensor<double, dim, dim>
210 const tensor<double, dim, dim> &ddu_dx)
const 212 static constexpr
auto I = mfem::internal::IsotropicIdentity<dim>();
214 tensor<double, dim, dim> F = I + du_dx;
215 tensor<double, dim, dim> invFT = inv(transpose(F));
216 tensor<double, dim, dim> devB =
217 dev(du_dx + transpose(du_dx) + dot(du_dx, transpose(du_dx)));
219 double coef = (
C1 / pow(J, 5.0 / 3.0));
220 double a1 = ddot(invFT, ddu_dx);
221 double a2 = ddot(F, ddu_dx);
223 return (2.0 *
D1 * J * a1 - (4.0 / 3.0) * coef * a2) * I -
224 ((10.0 / 3.0) * coef * a1) * devB +
225 (2 * coef) * (dot(ddu_dx, transpose(F)) + dot(F, transpose(ddu_dx)));
MFEM_HOST_DEVICE tensor< double, dim, dim > action_of_gradient_dual(const tensor< double, dim, dim > &dudx, const tensor< double, dim, dim > &ddudx) const
MFEM_HOST_DEVICE tensor< double, dim, dim > action_of_gradient_enzyme_fwd(const tensor< double, dim, dim > &dudx, const tensor< double, dim, dim > &ddudx) const
MFEM_HOST_DEVICE tensor< T, dim, dim > stress(const tensor< T, dim, dim > &dudx) const
Compute the stress response.
MFEM_HOST_DEVICE tensor< double, dim, dim, dim, dim > gradient(tensor< double, dim, dim > dudx) const
Compute the gradient.
Implementation of the tensor class.
double p(const Vector &x, double t)
MFEM_HOST_DEVICE tensor< double, dim, dim > action_of_gradient_enzyme_rev(const tensor< double, dim, dim > &dudx, const tensor< double, dim, dim > &ddudx) const
MFEM_HOST_DEVICE tensor< double, dim, dim > action_of_gradient(const tensor< double, dim, dim > &dudx, const tensor< double, dim, dim > &ddudx) const
Apply the gradient of the stress.
static MFEM_HOST_DEVICE void stress_wrapper(NeoHookeanMaterial< dim, gradient_type > *self, tensor< double, dim, dim > &dudx, tensor< double, dim, dim > &sigma)
A method to wrap the stress calculation into a static function.
MFEM_HOST_DEVICE tensor< double, dim, dim > action_of_gradient_symbolic(const tensor< double, dim, dim > &du_dx, const tensor< double, dim, dim > &ddu_dx) const
MFEM_HOST_DEVICE tensor< double, dim, dim > action_of_gradient_finite_diff(const tensor< double, dim, dim > &dudx, const tensor< double, dim, dim > &ddudx) const
double sigma(const Vector &x)