12#ifndef MFEM_ELASTICITY_MAT_NEOHOOKEAN_HPP
13#define MFEM_ELASTICITY_MAT_NEOHOOKEAN_HPP
39template <
int dim = 3, GradientType gradient_type = GradientType::Symbolic>
42 static_assert(
dim == 3,
"NeoHookean model currently implemented only in 3D");
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 / (T) pow(J, 5.0 / 3.0)) * devB;
71 MFEM_HOST_DEVICE
static void
97 dev(dudx + transpose(dudx) + dot(dudx, transpose(dudx)));
100 return make_tensor<dim, dim, dim, dim>([&](
int i,
int j,
int k,
103 return 2 * (
D1 * J * (i == j) -
107 ((i == k) * F[j][l] + F[i][l] * (j == k) -
127#ifdef MFEM_USE_ENZYME
154 auto sigma =
stress(make_tensor<dim, dim>([&](
int i,
int j)
158 return make_tensor<dim, dim>(
159 [&](
int i,
int j) {
return sigma[i][j].gradient; });
162#ifdef MFEM_USE_ENZYME
183 for (
int i = 0; i <
dim; i++)
185 for (
int j = 0; j <
dim; j++)
218 dev(du_dx + transpose(du_dx) + dot(du_dx, transpose(du_dx)));
224 return ((2 *
D1 * J * a1 -
mfem::real_t(4.0 / 3.0) * coef * a2) * I -
226 (2 * coef) * (dot(ddu_dx, transpose(F)) + dot(F, transpose(ddu_dx))));
real_t sigma(const Vector &x)
typename Args MFEM_HOST_DEVICE return_type __enzyme_autodiff(Args...)
MFEM_HOST_DEVICE return_type __enzyme_fwddiff(Args...)
MFEM_HOST_DEVICE constexpr isotropic_tensor< real_t, m, m > IsotropicIdentity()
MFEM_HOST_DEVICE constexpr auto make_tensor(lambda_type f) -> tensor< decltype(f())>
Creates a tensor of requested dimension by subsequent calls to a functor Can be thought of as analogo...
real_t p(const Vector &x, real_t t)
MFEM_HOST_DEVICE tensor< mfem::real_t, dim, dim > action_of_gradient(const tensor< mfem::real_t, dim, dim > &dudx, const tensor< mfem::real_t, dim, dim > &ddudx) const
Apply the gradient of the stress.
MFEM_HOST_DEVICE tensor< mfem::real_t, dim, dim > action_of_gradient_symbolic(const tensor< mfem::real_t, dim, dim > &du_dx, const tensor< mfem::real_t, dim, dim > &ddu_dx) const
MFEM_HOST_DEVICE tensor< mfem::real_t, dim, dim > action_of_gradient_enzyme_rev(const tensor< mfem::real_t, dim, dim > &dudx, const tensor< mfem::real_t, dim, dim > &ddudx) const
MFEM_HOST_DEVICE tensor< mfem::real_t, dim, dim > action_of_gradient_finite_diff(const tensor< mfem::real_t, dim, dim > &dudx, const tensor< mfem::real_t, dim, dim > &ddudx) const
static MFEM_HOST_DEVICE void stress_wrapper(NeoHookeanMaterial< dim, gradient_type > *self, tensor< mfem::real_t, dim, dim > &dudx, tensor< mfem::real_t, dim, dim > &sigma)
A method to wrap the stress calculation into a static function.
MFEM_HOST_DEVICE tensor< mfem::real_t, dim, dim > action_of_gradient_dual(const tensor< mfem::real_t, dim, dim > &dudx, const tensor< mfem::real_t, dim, dim > &ddudx) const
MFEM_HOST_DEVICE tensor< mfem::real_t, dim, dim > action_of_gradient_enzyme_fwd(const tensor< mfem::real_t, dim, dim > &dudx, const tensor< mfem::real_t, 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< mfem::real_t, dim, dim, dim, dim > gradient(tensor< mfem::real_t, dim, dim > dudx) const
Compute the gradient.
Dual number struct (value plus gradient)
Implementation of the tensor class.