Smith  0.1
Smith is an implicit thermal structural mechanics simulation code.
dfem_solid_weak_form.hpp
Go to the documentation of this file.
1 // Copyright (c) Lawrence Livermore National Security, LLC and
2 // other Smith Project Developers. See the top-level LICENSE file for
3 // details.
4 //
5 // SPDX-License-Identifier: (BSD-3-Clause)
6 
13 #pragma once
14 
15 #include "smith/smith_config.hpp"
16 
17 #ifdef SMITH_USE_ENZYME
18 
20 
22 
23 namespace smith {
24 
25 template <int Idx>
26 struct ScalarParameter {
27  static constexpr int index = Idx;
28  using QFunctionInput = double;
29  template <int FieldId>
30  using QFunctionFieldOp = mfem::future::Value<FieldId>;
31 };
32 
33 template <typename Material, typename... Parameters>
34 struct StressDivQFunction {
35  SMITH_HOST_DEVICE inline auto operator()(
36  // mfem::real_t dt, // TODO: figure out how to pass this in
37  const mfem::future::tensor<mfem::real_t, Material::dim, Material::dim>& du_dxi,
38  const mfem::future::tensor<mfem::real_t, Material::dim, Material::dim>& dv_dxi,
39  const mfem::future::tensor<mfem::real_t, Material::dim, Material::dim>&,
40  const mfem::future::tensor<mfem::real_t, Material::dim, Material::dim>& dX_dxi, mfem::real_t weight,
41  typename Parameters::QFunctionInput... params) const
42  {
43  auto dxi_dX = mfem::future::inv(dX_dxi);
44  auto du_dX = mfem::future::dot(du_dxi, dxi_dX);
45  auto dv_dX = mfem::future::dot(dv_dxi, dxi_dX);
46  double dt = 1.0; // TODO: figure out how to pass this in to the qfunction
47  auto P = mfem::future::get<0>(material.pkStress(dt, du_dX, dv_dX, params...));
48  auto JxW = mfem::future::det(dX_dxi) * weight * mfem::future::transpose(dxi_dX);
49  return mfem::future::tuple{-P * JxW};
50  }
51 
52  Material material;
53 };
54 
60 class DfemSolidWeakForm : public DfemWeakForm {
61  public:
64  template <typename T>
65  using qdata_type = std::shared_ptr<QuadratureData<T>>;
66 
68  static constexpr int NUM_STATE_VARS = 4;
69 
71  enum STATE
72  {
73  DISPLACEMENT,
74  VELOCITY,
75  ACCELERATION,
76  COORDINATES,
77  NUM_STATES
78  };
79 
88  DfemSolidWeakForm(std::string physics_name, std::shared_ptr<Mesh> mesh, const mfem::ParFiniteElementSpace& test_space,
89  std::vector<const mfem::ParFiniteElementSpace*> parameter_fe_spaces = {})
90  : DfemWeakForm(physics_name, mesh, test_space, makeInputSpaces(test_space, mesh, parameter_fe_spaces))
91  {
92  }
93 
111  template <typename MaterialType, typename... ParameterTypes>
112  void setMaterial(const mfem::Array<int>& domain_attributes, const MaterialType& material,
113  const mfem::IntegrationRule& displacement_ir)
114  {
115  SLIC_ERROR_IF(material.dim != DfemWeakForm::mesh_->mfemParMesh().Dimension(),
116  "Material model dimension does not match mesh dimension.");
117  auto stress_div_integral = StressDivQFunction<MaterialType, ParameterTypes...>{.material = material};
118  mfem::future::tuple<mfem::future::Gradient<DISPLACEMENT>, mfem::future::Gradient<VELOCITY>,
119  mfem::future::Gradient<ACCELERATION>, mfem::future::Gradient<COORDINATES>, mfem::future::Weight,
120  typename ParameterTypes::template QFunctionFieldOp<NUM_STATE_VARS + ParameterTypes::index>...>
121  stress_div_integral_inputs{};
122  mfem::future::tuple<mfem::future::Gradient<NUM_STATE_VARS + sizeof...(ParameterTypes)>>
123  stress_div_integral_outputs{};
124  DfemWeakForm::addBodyIntegral(domain_attributes, stress_div_integral, stress_div_integral_inputs,
125  stress_div_integral_outputs, displacement_ir,
126  std::index_sequence<DISPLACEMENT, NUM_STATE_VARS + ParameterTypes::index...>{});
127  }
128 
129  protected:
138  std::vector<const mfem::ParFiniteElementSpace*> makeInputSpaces(
139  const mfem::ParFiniteElementSpace& test_space, const std::shared_ptr<Mesh>& mesh,
140  const std::vector<const mfem::ParFiniteElementSpace*>& parameter_fe_spaces)
141  {
142  std::vector<const mfem::ParFiniteElementSpace*> input_spaces;
143  input_spaces.reserve(NUM_STATE_VARS + parameter_fe_spaces.size());
144  for (int i = 0; i < 3; ++i) {
145  input_spaces.push_back(&test_space);
146  }
147  input_spaces.push_back(static_cast<const mfem::ParFiniteElementSpace*>(mesh->mfemParMesh().GetNodalFESpace()));
148  for (auto space : parameter_fe_spaces) {
149  input_spaces.push_back(space);
150  }
151  return input_spaces;
152  }
153 };
154 
155 } // namespace smith
156 
157 #endif
This file contains the interface used for initializing/terminating any hardware accelerator-related f...
#define SMITH_HOST_DEVICE
Macro that evaluates to __host__ __device__ when compiling with nvcc or amdclang and does nothing on ...
Definition: accelerator.hpp:37
Implements the WeakForm interface using dfem. Allows for generic specification of body and boundary i...
Accelerator functionality.
Definition: smith.cpp:36
tuple(T...) -> tuple< T... >
Class template argument deduction rule for tuples.
constexpr SMITH_HOST_DEVICE auto inv(const isotropic_tensor< T, m, m > &I)
return the inverse of an isotropic tensor
constexpr SMITH_HOST_DEVICE auto transpose(const isotropic_tensor< T, m, m > &I)
return the transpose of an isotropic tensor
constexpr SMITH_HOST_DEVICE auto det(const isotropic_tensor< T, m, m > &I)
compute the determinant of an isotropic tensor
mfem::ParFiniteElementSpace & space(FieldState field)
Get the space from the primal field of a field states.
constexpr SMITH_HOST_DEVICE auto dot(const isotropic_tensor< S, m, m > &I, const tensor< T, m, n... > &A)
dot product between an isotropic and (nonisotropic) tensor