Smith  0.1
Smith is an implicit thermal structural mechanics simulation code.
time_discretized_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 
23 #pragma once
24 
26 #include "smith/physics/mesh.hpp"
29 
30 namespace smith {
31 
32 template <int spatial_dim, typename OutputSpace, typename inputs = Parameters<>>
34 
46 template <int spatial_dim, typename OutputSpace, typename... InputSpaces>
47 class TimeDiscretizedWeakForm<spatial_dim, OutputSpace, Parameters<InputSpaces...>>
48  : public FunctionalWeakForm<spatial_dim, OutputSpace, Parameters<InputSpaces...>> {
49  public:
50  using Base = FunctionalWeakForm<spatial_dim, OutputSpace, Parameters<InputSpaces...>>;
51 
59  TimeDiscretizedWeakForm(std::string physics_name, std::shared_ptr<Mesh> mesh,
60  const mfem::ParFiniteElementSpace& output_mfem_space,
61  const typename Base::SpacesT& input_mfem_spaces)
62  : Base(physics_name, mesh, output_mfem_space, input_mfem_spaces)
63  {
64  }
65 
79  template <int... active_parameters, typename BodyIntegralType>
80  void addBodyIntegral(DependsOn<active_parameters...> depends_on, std::string body_name, BodyIntegralType integrand)
81  {
82  const double* dt = &this->dt_;
83  const size_t* cycle = &this->cycle_;
84  Base::addBodyIntegral(depends_on, body_name, [dt, cycle, integrand](double t, auto X, auto... inputs) {
85  TimeInfo time_info(t, *dt, *cycle);
86  return integrand(time_info, X, inputs...);
87  });
88  }
89 
96  template <typename BodyIntegralType>
97  void addBodyIntegral(std::string body_name, BodyIntegralType integrand)
98  {
99  constexpr int num_inputs = sizeof...(InputSpaces);
100  addBodyIntegralWithAllParams(body_name, integrand, std::make_integer_sequence<int, num_inputs>{});
101  }
102 
111  template <int... active_parameters, typename BodyLoadType>
112  void addBodySource(DependsOn<active_parameters...> depends_on, std::string body_name, BodyLoadType load_function)
113  {
114  addBodyIntegral(depends_on, body_name, [load_function](auto t_info, auto X, auto... inputs) {
115  return smith::tuple{-load_function(t_info, get<VALUE>(X), get<VALUE>(inputs)...), smith::zero{}};
116  });
117  }
118 
121  template <typename BodyLoadType>
122  void addBodySource(std::string body_name, BodyLoadType load_function)
123  {
124  constexpr int num_inputs = sizeof...(InputSpaces);
125  addBodySourceWithAllParams(body_name, load_function, std::make_integer_sequence<int, num_inputs>{});
126  }
127 
136  template <int... active_parameters, typename BoundaryIntegralType>
137  void addBoundaryIntegral(DependsOn<active_parameters...> depends_on, std::string boundary_name,
138  BoundaryIntegralType integrand)
139  {
140  const double* dt = &this->dt_;
141  const size_t* cycle = &this->cycle_;
142  Base::addBoundaryIntegral(depends_on, boundary_name, [dt, cycle, integrand](double t, auto X, auto... inputs) {
143  TimeInfo time_info(t, *dt, *cycle);
144  return integrand(time_info, X, inputs...);
145  });
146  }
147 
150  template <typename BoundaryIntegralType>
151  void addBoundaryIntegral(std::string boundary_name, BoundaryIntegralType integrand)
152  {
153  constexpr int num_inputs = sizeof...(InputSpaces);
154  addBoundaryIntegralWithAllParams(boundary_name, integrand, std::make_integer_sequence<int, num_inputs>{});
155  }
156 
165  template <int... active_parameters, typename BoundaryFluxType>
166  void addBoundaryFlux(DependsOn<active_parameters...> depends_on, std::string boundary_name,
167  BoundaryFluxType flux_function)
168  {
169  const double* dt = &this->dt_;
170  const size_t* cycle = &this->cycle_;
171  Base::addBoundaryFlux(depends_on, boundary_name,
172  [dt, cycle, flux_function](double t, auto X, auto n, auto... inputs) {
173  TimeInfo time_info(t, *dt, *cycle);
174  return flux_function(time_info, X, n, inputs...);
175  });
176  }
177 
180  template <typename BoundaryFluxType>
181  void addBoundaryFlux(std::string boundary_name, BoundaryFluxType flux_function)
182  {
183  constexpr int num_inputs = sizeof...(InputSpaces);
184  addBoundaryFluxWithAllParams(boundary_name, flux_function, std::make_integer_sequence<int, num_inputs>{});
185  }
186 
195  template <int... active_parameters, typename InteriorIntegralType>
196  void addInteriorBoundaryIntegral(DependsOn<active_parameters...> depends_on, std::string interior_name,
197  InteriorIntegralType integrand)
198  {
199  const double* dt = &this->dt_;
200  const size_t* cycle = &this->cycle_;
201  Base::addInteriorBoundaryIntegral(depends_on, interior_name,
202  [dt, cycle, integrand](double t, auto X, auto... inputs) {
203  TimeInfo time_info(t, *dt, *cycle);
204  return integrand(time_info, X, inputs...);
205  });
206  }
207 
210  template <typename InteriorIntegralType>
211  void addInteriorBoundaryIntegral(std::string interior_name, InteriorIntegralType integrand)
212  {
213  constexpr int num_inputs = sizeof...(InputSpaces);
214  addInteriorBoundaryIntegralWithAllParams(interior_name, integrand, std::make_integer_sequence<int, num_inputs>{});
215  }
216 
217  private:
218  template <typename BodyIntegralType, int... all_params>
219  void addBodyIntegralWithAllParams(std::string body_name, BodyIntegralType integrand,
220  std::integer_sequence<int, all_params...>)
221  {
222  addBodyIntegral(DependsOn<all_params...>{}, body_name, integrand);
223  }
224 
225  template <typename BodyLoadType, int... all_params>
226  void addBodySourceWithAllParams(std::string body_name, BodyLoadType load_function,
227  std::integer_sequence<int, all_params...>)
228  {
229  addBodySource(DependsOn<all_params...>{}, body_name, load_function);
230  }
231 
232  template <typename BoundaryIntegralType, int... all_params>
233  void addBoundaryIntegralWithAllParams(std::string boundary_name, BoundaryIntegralType integrand,
234  std::integer_sequence<int, all_params...>)
235  {
236  addBoundaryIntegral(DependsOn<all_params...>{}, boundary_name, integrand);
237  }
238 
239  template <typename InteriorIntegralType, int... all_params>
240  void addInteriorBoundaryIntegralWithAllParams(std::string interior_name, InteriorIntegralType integrand,
241  std::integer_sequence<int, all_params...>)
242  {
243  addInteriorBoundaryIntegral(DependsOn<all_params...>{}, interior_name, integrand);
244  }
245 
246  template <typename BoundaryFluxType, int... all_params>
247  void addBoundaryFluxWithAllParams(std::string boundary_name, BoundaryFluxType flux_function,
248  std::integer_sequence<int, all_params...>)
249  {
250  addBoundaryFlux(DependsOn<all_params...>{}, boundary_name, flux_function);
251  }
252 };
253 
256  public:
257  std::shared_ptr<WeakForm> time_discretized_weak_form;
258  std::shared_ptr<WeakForm> final_reaction_weak_form;
259 };
260 
261 template <int spatial_dim, typename OutputSpace, typename inputs = Parameters<>>
263 
265 template <int spatial_dim, typename OutputSpace, typename TrialInputSpace, typename... InputSpaces>
266 class SecondOrderTimeDiscretizedWeakForm<spatial_dim, OutputSpace, Parameters<TrialInputSpace, InputSpaces...>>
268  public:
269  static constexpr int NUM_STATE_VARS = 4;
270 
273  TimeDiscretizedWeakForm<spatial_dim, OutputSpace, Parameters<TrialInputSpace, InputSpaces...>>;
275  using FinalReactionFormT = TimeDiscretizedWeakForm<spatial_dim, OutputSpace, Parameters<InputSpaces...>>;
276 
278  SecondOrderTimeDiscretizedWeakForm(std::string physics_name, std::shared_ptr<Mesh> mesh,
280  const mfem::ParFiniteElementSpace& output_mfem_space,
281  const typename TimeDiscretizedWeakFormT::SpacesT& input_mfem_spaces)
282  : time_rule_(time_rule)
283  {
284  time_discretized_weak_form_ =
285  std::make_shared<TimeDiscretizedWeakFormT>(physics_name, mesh, output_mfem_space, input_mfem_spaces);
286  time_discretized_weak_form = time_discretized_weak_form_;
287 
288  typename TimeDiscretizedWeakFormT::SpacesT trial_removed_spaces(std::next(input_mfem_spaces.begin()),
289  input_mfem_spaces.end());
290  final_reaction_weak_form_ =
291  std::make_shared<FinalReactionFormT>(physics_name, mesh, output_mfem_space, trial_removed_spaces);
292  final_reaction_weak_form = final_reaction_weak_form_;
293  }
294 
296  template <int... active_parameters, typename BodyIntegralType>
297  void addBodyIntegral(DependsOn<active_parameters...> /*depends_on*/, std::string body_name,
298  BodyIntegralType integrand)
299  {
300  auto time_rule = time_rule_;
301  time_discretized_weak_form_->addBodyIntegral(
303  [integrand, time_rule](const TimeInfo& t, auto X, auto U, auto U_old, auto U_dot_old, auto U_dot_dot_old,
304  auto... inputs) {
305  return integrand(t, X, time_rule.value(t, U, U_old, U_dot_old, U_dot_dot_old),
306  time_rule.dot(t, U, U_old, U_dot_old, U_dot_dot_old),
307  time_rule.ddot(t, U, U_old, U_dot_old, U_dot_dot_old), inputs...);
308  });
309  final_reaction_weak_form_->addBodyIntegral(DependsOn<0, 1, 2, NUM_STATE_VARS - 1 + active_parameters...>{},
310  body_name, integrand);
311  }
312 
314  template <typename BodyIntegralType>
315  void addBodyIntegral(std::string body_name, BodyIntegralType integrand)
316  {
317  addBodyIntegral(DependsOn<>{}, body_name, integrand);
318  }
319 
321  template <int... active_parameters, typename BodyLoadType>
322  void addBodySource(DependsOn<active_parameters...> /*depends_on*/, std::string body_name, BodyLoadType load_function)
323  {
324  auto time_rule = time_rule_;
325  time_discretized_weak_form_->addBodyIntegral(
327  [load_function, time_rule](const TimeInfo& t, auto X, auto U, auto U_old, auto U_dot_old, auto U_dot_dot_old,
328  auto... inputs) {
329  return smith::tuple{
330  -load_function(t.time(), get<VALUE>(X),
331  get<VALUE>(time_rule.value(t, U, U_old, U_dot_old, U_dot_dot_old)),
332  get<VALUE>(time_rule.dot(t, U, U_old, U_dot_old, U_dot_dot_old)),
333  get<VALUE>(time_rule.ddot(t, U, U_old, U_dot_old, U_dot_dot_old)), get<VALUE>(inputs)...),
334  smith::zero{}};
335  });
336  final_reaction_weak_form_->addBodyIntegral(
338  [load_function](const TimeInfo& t, auto X, auto... inputs) {
339  return smith::tuple{-load_function(t.time(), get<VALUE>(X), get<VALUE>(inputs)...), smith::zero{}};
340  });
341  }
342 
344  template <typename BodyLoadType>
345  void addBodySource(std::string body_name, BodyLoadType load_function)
346  {
347  addBodySource(DependsOn<>{}, body_name, load_function);
348  }
349 
350  private:
351  std::shared_ptr<TimeDiscretizedWeakFormT> time_discretized_weak_form_;
352  std::shared_ptr<FinalReactionFormT> final_reaction_weak_form_;
354 };
355 
356 } // namespace smith
void addBodySource(DependsOn< active_parameters... >, std::string body_name, BodyLoadType load_function)
Add a body source using corrected second-order kinematics.
SecondOrderTimeDiscretizedWeakForm(std::string physics_name, std::shared_ptr< Mesh > mesh, ImplicitNewmarkSecondOrderTimeIntegrationRule time_rule, const mfem::ParFiniteElementSpace &output_mfem_space, const typename TimeDiscretizedWeakFormT::SpacesT &input_mfem_spaces)
Construct paired weak forms for second-order systems.
void addBodyIntegral(DependsOn< active_parameters... >, std::string body_name, BodyIntegralType integrand)
Add a body integral using corrected second-order kinematics.
void addBodyIntegral(std::string body_name, BodyIntegralType integrand)
Add a body integral using all trailing inputs.
void addBodySource(std::string body_name, BodyLoadType load_function)
Add a body source using all trailing inputs.
A container holding the weak forms useful for second-order time-discretized systems.
std::shared_ptr< WeakForm > final_reaction_weak_form
Weak form in terms of converged kinematic states.
std::shared_ptr< WeakForm > time_discretized_weak_form
Weak form in terms of predicted/current unknown.
void addBodySource(DependsOn< active_parameters... > depends_on, std::string body_name, BodyLoadType load_function)
Add a body source (body load) with TimeInfo.
void addBodyIntegral(std::string body_name, BodyIntegralType integrand)
Add a body integral with TimeInfo (defaults to all input fields).
void addInteriorBoundaryIntegral(DependsOn< active_parameters... > depends_on, std::string interior_name, InteriorIntegralType integrand)
Add an interior boundary integral with TimeInfo.
void addBoundaryIntegral(DependsOn< active_parameters... > depends_on, std::string boundary_name, BoundaryIntegralType integrand)
Add a boundary integral with TimeInfo.
void addBodyIntegral(DependsOn< active_parameters... > depends_on, std::string body_name, BodyIntegralType integrand)
Add a body integral with TimeInfo.
TimeDiscretizedWeakForm(std::string physics_name, std::shared_ptr< Mesh > mesh, const mfem::ParFiniteElementSpace &output_mfem_space, const typename Base::SpacesT &input_mfem_spaces)
Construct a time-discretized weak form.
void addInteriorBoundaryIntegral(std::string interior_name, InteriorIntegralType integrand)
void addBoundaryFlux(DependsOn< active_parameters... > depends_on, std::string boundary_name, BoundaryFluxType flux_function)
Add a boundary flux with TimeInfo.
Implements the WeakForm interface using smith::ShapeAwareFunctional. Allows for generic specification...
Smith mesh class which assists in constructing the appropriate parallel mfem meshes and registering a...
Accelerator functionality.
Definition: smith.cpp:36
mfem::future::tuple< T... > tuple
Expose MFEM tuple in the Smith namespace.
Definition: tuple.hpp:241
encodes rules for time discretizing second order odes (involving first and second time derivatives)....
a struct that is used in the physics modules to clarify which template arguments are user-controlled ...
Definition: common.hpp:45
struct storing time and timestep information
Definition: common.hpp:18
A sentinel struct for eliding no-op tensor operations.
Definition: tensor.hpp:122
Provides templated implementations for discretizing values, velocities and accelerations from current...