Smith  0.1
Smith is an implicit thermal structural mechanics simulation code.
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 
14 #pragma once
15 
17 
18 namespace smith {
19 
20 template <int order, int dim, typename InputSpaces = Parameters<>>
22 
32 template <int order, int dim, typename... InputSpaces>
33 class SolidWeakForm<order, dim, Parameters<InputSpaces...>>
34  : public FunctionalWeakForm<dim, H1<order, dim>,
35  Parameters<H1<order, dim>, H1<order, dim>, H1<order, dim>, InputSpaces...>> {
36  public:
40 
43  template <typename T>
44  using qdata_type = std::shared_ptr<QuadratureData<T>>;
45 
47  static constexpr int NUM_STATE_VARS = 3;
48 
50  enum STATE
51  {
52  DISPLACEMENT,
53  VELOCITY,
54  ACCELERATION,
55  NUM_STATES
56  };
57 
66  SolidWeakForm(std::string physics_name, std::shared_ptr<Mesh> mesh, const mfem::ParFiniteElementSpace& test_space,
67  std::vector<const mfem::ParFiniteElementSpace*> parameter_fe_spaces = {})
68  : BaseWeakFormT(physics_name, mesh, test_space, constructAllSpaces(test_space, parameter_fe_spaces))
69  {
70  }
71 
96  template <int... active_parameters, typename MaterialType, typename StateType = Empty>
97  void setMaterial(DependsOn<active_parameters...>, std::string body_name, const MaterialType& material,
99  {
100  static_assert(std::is_same_v<StateType, Empty> || std::is_same_v<StateType, typename MaterialType::State>,
101  "invalid quadrature data provided in setMaterial()");
102  MaterialStressFunctor<MaterialType> material_functor(material);
103  BaseWeakFormT::weak_form_->AddDomainIntegral(
104  Dimension<dim>{}, DependsOn<0, 2, active_parameters + NUM_STATE_VARS...>{}, std::move(material_functor),
105  BaseWeakFormT::mesh_->domain(body_name), qdata);
106 
107  BaseWeakFormT::v_dot_weak_form_residual_->AddDomainIntegral(
108  Dimension<dim>{}, DependsOn<0, 1, 3, active_parameters + 1 + NUM_STATE_VARS...>{},
109  [material_functor](double t, auto X, auto state, auto V, auto... params) {
110  auto flux = material_functor(t, X, state, params...);
111  return smith::inner(get<VALUE>(V), get<VALUE>(flux)) +
112  smith::inner(get<DERIVATIVE>(V), get<DERIVATIVE>(flux));
113  },
114  BaseWeakFormT::mesh_->domain(body_name), qdata);
115  }
116 
118  template <typename MaterialType, typename StateType = Empty>
119  void setMaterial(std::string body_name, const MaterialType& material,
120  std::shared_ptr<QuadratureData<StateType>> qdata = EmptyQData)
121  {
122  setMaterial(DependsOn<>{}, body_name, material, qdata);
123  }
124 
149  template <int... active_parameters, typename MaterialType, typename StateType = Empty>
150  void setRateMaterial(DependsOn<active_parameters...>, std::string body_name, const MaterialType& material,
152  {
153  static_assert(std::is_same_v<StateType, Empty> || std::is_same_v<StateType, typename MaterialType::State>,
154  "invalid quadrature data provided in setMaterial()");
155  RateMaterialStressFunctor<MaterialType> material_functor(material, &this->dt_);
156  BaseWeakFormT::weak_form_->AddDomainIntegral(
157  Dimension<dim>{}, DependsOn<0, 1, 2, active_parameters + NUM_STATE_VARS...>{}, std::move(material_functor),
158  BaseWeakFormT::mesh_->domain(body_name), qdata);
159 
160  BaseWeakFormT::v_dot_weak_form_residual_->AddDomainIntegral(
161  Dimension<dim>{}, DependsOn<0, 1, 2, 3, active_parameters + 1 + NUM_STATE_VARS...>{},
162  [material_functor, qdata](double t, auto X, auto state, auto V, auto... params) {
163  auto flux = material_functor(t, X, state, params...);
164  return smith::inner(get<VALUE>(V), get<VALUE>(flux)) +
165  smith::inner(get<DERIVATIVE>(V), get<DERIVATIVE>(flux));
166  },
167  BaseWeakFormT::mesh_->domain(body_name), qdata);
168  }
169 
171  template <typename MaterialType, typename StateType = Empty>
172  void setRateMaterial(std::string body_name, const MaterialType& material,
173  std::shared_ptr<QuadratureData<StateType>> qdata = EmptyQData)
174  {
175  setRateMaterial(DependsOn<>{}, body_name, material, qdata);
176  }
177 
200  template <int... active_parameters, typename PressureType>
201  void addPressure(DependsOn<active_parameters...>, std::string boundary_name, PressureType pressure_function)
202  {
203  BaseWeakFormT::weak_form_->AddBoundaryIntegral(
204  Dimension<dim - 1>{}, DependsOn<0, active_parameters + NUM_STATE_VARS...>{},
205  [pressure_function](double t, auto X, auto displacement, auto... params) {
206  // Calculate the position and normal in the shape perturbed deformed configuration
207  auto x = X + displacement;
208  auto n = cross(get<DERIVATIVE>(x));
209  // smith::Functional's boundary integrals multiply the q-function output by
210  // norm(cross(dX_dxi)) at that quadrature point, but if we impose a shape displacement
211  // then that weight needs to be corrected. The new weight should be
212  // norm(cross(dX_dxi + du_dxi + dp_dxi)) where u is displacement and p is shape displacement. This implies:
213  //
214  // pressure * normalize(normal_new) * w_new
215  // = pressure * normalize(normal_new) * (w_new / w_old) * w_old
216  // = pressure * normalize(normal_new) * (norm(normal_new) / norm(normal_old)) * w_old
217  // = pressure * (normal_new / norm(normal_new)) * (norm(normal_new) / norm(normal_old)) * w_old
218  // = pressure * (normal_new / norm(normal_old)) * w_old
219 
220  // We always query the pressure function in the undeformed configuration
221  return pressure_function(t, get<VALUE>(X), params...) * (n / norm(cross(get<DERIVATIVE>(X))));
222  },
223  BaseWeakFormT::mesh_->domain(boundary_name));
224 
225  BaseWeakFormT::v_dot_weak_form_residual_->AddBoundaryIntegral(
226  Dimension<dim - 1>{}, DependsOn<0, 1, active_parameters + 1 + NUM_STATE_VARS...>{},
227  [pressure_function](double t, auto X, auto V, auto displacement, auto... params) {
228  auto x = X + displacement;
229  auto n = cross(get<DERIVATIVE>(x));
230  auto pressure = pressure_function(t, get<VALUE>(X), params...) * (n / norm(cross(get<DERIVATIVE>(X))));
231  return inner(get<VALUE>(V), pressure);
232  },
233  BaseWeakFormT::mesh_->domain(boundary_name));
234  }
235 
237  template <typename PressureType>
238  void addPressure(std::string boundary_name, PressureType pressure_function)
239  {
240  addPressure(DependsOn<>{}, boundary_name, pressure_function);
241  }
242 
243  protected:
249  std::vector<const mfem::ParFiniteElementSpace*> constructAllSpaces(
250  const mfem::ParFiniteElementSpace& state_space, const std::vector<const mfem::ParFiniteElementSpace*>& spaces)
251  {
252  std::vector<const mfem::ParFiniteElementSpace*> all_spaces{&state_space, &state_space, &state_space};
253  for (auto& s : spaces) {
254  all_spaces.push_back(s);
255  }
256  return all_spaces;
257  }
258 
263  template <typename Material>
264  struct MaterialStressFunctor {
266  MaterialStressFunctor(Material material) : material_(material) {}
267 
269  Material material_;
270 
286  template <typename X, typename State, typename Displacement, typename Acceleration, typename... Params>
287  auto SMITH_HOST_DEVICE operator()(double, X, State& state, Displacement displacement, Acceleration acceleration,
288  Params... params) const
289  {
290  auto du_dX = get<DERIVATIVE>(displacement);
291  auto d2u_dt2 = get<VALUE>(acceleration);
292  auto stress = material_.pkStress(state, du_dX, params...);
293  return smith::tuple{material_.density(params...) * d2u_dt2, stress};
294  }
295  };
296 
301  template <typename Material>
302  struct RateMaterialStressFunctor {
304  RateMaterialStressFunctor(Material material, const double* dt) : material_(material), dt_(dt) {}
305 
307  Material material_;
308 
310  const double* dt_;
311 
329  template <typename X, typename State, typename Displacement, typename Velocity, typename Acceleration,
330  typename... Params>
331  auto SMITH_HOST_DEVICE operator()(double /*t*/, X, State& state, Displacement displacement, Velocity velocity,
332  Acceleration acceleration, Params... params) const
333  {
334  auto du_dX = get<DERIVATIVE>(displacement);
335  auto dv_dX = get<DERIVATIVE>(velocity);
336  auto d2u_dt2 = get<VALUE>(acceleration);
337  auto stress = material_.pkStress(*dt_, state, du_dX, dv_dX, params...);
338  return smith::tuple{material_.density(params...) * d2u_dt2, stress};
339  }
340  };
341 };
342 
346 template <int order, int dim, typename... ParameterSpaces>
347 auto create_solid_weak_form(const std::string& physics_name, std::shared_ptr<smith::Mesh> mesh,
348  const std::vector<smith::FiniteElementState*>& states, // u, v, a, e
349  const std::vector<smith::FiniteElementState*>& params)
350 {
352  enum FieldNumbering
353  {
354  DISP,
355  VELO,
356  ACCEL,
357  };
358 
359  std::vector<const mfem::ParFiniteElementSpace*> parameter_fe_spaces;
360 
361  if constexpr (sizeof...(ParameterSpaces) > 0) {
362  for_constexpr<sizeof...(ParameterSpaces)>([&](auto i) { parameter_fe_spaces.push_back(&params[i]->space()); });
363  }
364 
365  using WeakFormT = SolidWeakForm<order, dim, Parameters<ParameterSpaces...>>;
366 
367  return std::make_shared<WeakFormT>(physics_name, mesh, states[DISP]->space(), parameter_fe_spaces);
368 }
369 
370 } // namespace smith
#define SMITH_HOST_DEVICE
Macro that evaluates to __host__ __device__ when compiling with nvcc and does nothing on a host compi...
Definition: accelerator.hpp:38
void setRateMaterial(std::string body_name, const MaterialType &material, std::shared_ptr< QuadratureData< StateType >> qdata=EmptyQData)
This is an overloaded member function, provided for convenience. It differs from the above function o...
SolidWeakForm(std::string physics_name, std::shared_ptr< Mesh > mesh, const mfem::ParFiniteElementSpace &test_space, std::vector< const mfem::ParFiniteElementSpace * > parameter_fe_spaces={})
Construct a new SolidWeakForm object.
void addPressure(DependsOn< active_parameters... >, std::string boundary_name, PressureType pressure_function)
Set the pressure boundary condition.
std::shared_ptr< QuadratureData< T > > qdata_type
a container holding quadrature point data of the specified type
void setRateMaterial(DependsOn< active_parameters... >, std::string body_name, const MaterialType &material, qdata_type< StateType > qdata=EmptyQData)
Set the material stress response and mass properties for the physics module.
std::vector< const mfem::ParFiniteElementSpace * > constructAllSpaces(const mfem::ParFiniteElementSpace &state_space, const std::vector< const mfem::ParFiniteElementSpace * > &spaces)
For use in the constructor, combined the correct number of state spaces (disp,velo,...
void setMaterial(std::string body_name, const MaterialType &material, std::shared_ptr< QuadratureData< StateType >> qdata=EmptyQData)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void addPressure(std::string boundary_name, PressureType pressure_function)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void setMaterial(DependsOn< active_parameters... >, std::string body_name, const MaterialType &material, qdata_type< StateType > qdata=EmptyQData)
Set the material stress response and mass properties for the physics module.
Implements the WeakForm interface using smith::ShapeAwareFunctional. Allows for generic specification...
constexpr SMITH_HOST_DEVICE void for_constexpr(const lambda &f)
multidimensional loop tool that evaluates the lambda body inside the innermost loop.
Accelerator functionality.
Definition: smith.cpp:36
constexpr SMITH_HOST_DEVICE auto norm(const isotropic_tensor< T, m, m > &I)
compute the Frobenius norm (sqrt(tr(dot(transpose(I), I)))) of an isotropic tensor
std::shared_ptr< QuadratureData< Empty > > EmptyQData
a single instance of a QuadratureData container of Emptys, since they are all interchangeable
auto create_solid_weak_form(const std::string &physics_name, std::shared_ptr< smith::Mesh > mesh, const std::vector< smith::FiniteElementState * > &states, const std::vector< smith::FiniteElementState * > &params)
Utility function for creating a shared_ptr<SolidWeakForm<>>
constexpr SMITH_HOST_DEVICE auto inner(const dual< S > &A, const dual< T > &B)
Definition: dual.hpp:281
auto cross(const tensor< T, 3, 2 > &A)
compute the cross product of the columns of A: A(:,1) x A(:,2)
Definition: tensor.hpp:959
Compile-time alias for a dimension.
Definition: geometry.hpp:17
see Nothing for a complete description of this class and when to use it
H1 elements of order p.
a struct that is used in the physics modules to clarify which template arguments are user-controlled ...
Definition: common.hpp:21
A class for storing and access user-defined types at quadrature points.
auto SMITH_HOST_DEVICE operator()(double, X, State &state, Displacement displacement, Acceleration acceleration, Params... params) const
Material stress response call.
auto SMITH_HOST_DEVICE operator()(double, X, State &state, Displacement displacement, Velocity velocity, Acceleration acceleration, Params... params) const
Material stress response call.
RateMaterialStressFunctor(Material material, const double *dt)
Constructor for the functor.
This is a class that mimics most of std::tuple's interface, except that it is usable in CUDA kernels ...
Definition: tuple.hpp:28