Smith  0.1
Smith is an implicit thermal structural mechanics simulation code.
functional_objective.hpp
Go to the documentation of this file.
1 // Copyright 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 
16 #include "smith/physics/mesh.hpp"
20 
21 namespace smith {
22 
23 template <int spatial_dim, typename parameters = Parameters<>,
24  typename parameter_indices = std::make_integer_sequence<int, parameters::n>>
26 
30 template <int spatial_dim, typename... InputSpaces, int... parameter_indices>
31 class FunctionalObjective<spatial_dim, Parameters<InputSpaces...>, std::integer_sequence<int, parameter_indices...>>
32  : public ScalarObjective {
33  public:
34  using SpacesT = std::vector<const mfem::ParFiniteElementSpace*>;
35 
37 
43  FunctionalObjective(const std::string& physics_name, std::shared_ptr<Mesh> mesh, const SpacesT& input_mfem_spaces)
44  : ScalarObjective(physics_name), mesh_(mesh)
45  {
46  std::array<const mfem::ParFiniteElementSpace*, sizeof...(InputSpaces)> mfem_spaces;
47 
48  SLIC_ERROR_ROOT_IF(
49  sizeof...(InputSpaces) != input_mfem_spaces.size(),
50  std::format("{} parameter spaces given in the template argument but {} parameter names were supplied.",
51  sizeof...(InputSpaces), input_mfem_spaces.size()));
52 
53  if constexpr (sizeof...(InputSpaces) > 0) {
54  for_constexpr<sizeof...(InputSpaces)>([&](auto i) { mfem_spaces[i] = input_mfem_spaces[i]; });
55  }
56 
57  const auto& shape_disp_space = mesh_->shapeDisplacementSpace();
58 
59  objective_ =
60  std::make_unique<ShapeAwareFunctional<ShapeDispSpace, double(InputSpaces...)>>(&shape_disp_space, mfem_spaces);
61  }
62 
70  template <typename FuncOfTimeSpaceAndParams, int... all_params>
71  void addBodyIntegralImpl(std::string body_name, const FuncOfTimeSpaceAndParams& qfunction,
72  std::integer_sequence<int, all_params...>)
73  {
74  const double* dt = &dt_;
75  const size_t* cycle = &cycle_;
76  objective_->AddDomainIntegral(
78  [dt, cycle, qfunction](double time, auto X, auto... params) {
79  return qfunction(TimeInfo(time, *dt, *cycle), X, params...);
80  },
81  mesh_->domain(body_name));
82  }
83 
85  template <int... active_parameters, typename FuncOfTimeSpaceAndParams>
86  void addBodyIntegral(DependsOn<active_parameters...>, std::string body_name,
87  const FuncOfTimeSpaceAndParams& qfunction)
88  {
89  addBodyIntegralImpl(body_name, qfunction, std::integer_sequence<int, active_parameters...>{});
90  }
91 
93  template <typename FuncOfTimeSpaceAndParams>
94  void addBodyIntegral(std::string body_name, const FuncOfTimeSpaceAndParams& qfunction)
95  {
96  addBodyIntegralImpl(body_name, qfunction, std::make_integer_sequence<int, sizeof...(InputSpaces)>{});
97  }
98 
106  template <typename FuncOfTimeSpaceAndParams, int... all_params>
107  void addBoundaryIntegralImpl(std::string boundary_name, const FuncOfTimeSpaceAndParams& qfunction,
108  std::integer_sequence<int, all_params...>)
109  {
110  const double* dt = &dt_;
111  const size_t* cycle = &cycle_;
112  objective_->AddBoundaryIntegral(
114  [dt, cycle, qfunction](double time, auto X, auto... params) {
115  return qfunction(TimeInfo(time, *dt, *cycle), X, params...);
116  },
117  mesh_->domain(boundary_name));
118  }
119 
121  template <int... active_parameters, typename FuncOfTimeSpaceAndParams>
122  void addBoundaryIntegral(DependsOn<active_parameters...>, std::string boundary_name,
123  const FuncOfTimeSpaceAndParams& qfunction)
124  {
125  addBoundaryIntegralImpl(boundary_name, qfunction, std::integer_sequence<int, active_parameters...>{});
126  }
127 
129  template <typename FuncOfTimeSpaceAndParams>
130  void addBoundaryIntegral(std::string boundary_name, const FuncOfTimeSpaceAndParams& qfunction)
131  {
132  addBoundaryIntegralImpl(boundary_name, qfunction, std::make_integer_sequence<int, sizeof...(InputSpaces)>{});
133  }
134 
136  virtual double evaluate(TimeInfo time_info, ConstFieldPtr shape_disp,
137  const std::vector<ConstFieldPtr>& fields) const override
138  {
139  dt_ = time_info.dt();
140  cycle_ = time_info.cycle();
141 
142  return evaluateObjective(std::make_integer_sequence<int, sizeof...(parameter_indices)>{}, time_info.time(),
143  shape_disp, fields);
144  }
145 
147  virtual mfem::Vector gradient(TimeInfo time_info, ConstFieldPtr shape_disp, const std::vector<ConstFieldPtr>& fields,
148  size_t field_ordinal) const override
149  {
150  dt_ = time_info.dt();
151  cycle_ = time_info.cycle();
152 
153  auto grads = gradientEvaluators(std::make_integer_sequence<int, sizeof...(parameter_indices)>{}, time_info.time(),
154  shape_disp, fields);
155  auto g = smith::get<DERIVATIVE>(grads[field_ordinal](time_info.time(), shape_disp, fields));
156  return *assemble(g);
157  }
158 
160  virtual mfem::Vector mesh_coordinate_gradient(TimeInfo time_info, ConstFieldPtr shape_disp,
161  const std::vector<ConstFieldPtr>& fields) const override
162  {
163  dt_ = time_info.dt();
164  cycle_ = time_info.cycle();
165 
166  auto g = smith::get<DERIVATIVE>(
167  (*objective_)(DifferentiateWRT<0>{}, time_info.time(), *shape_disp, *fields[parameter_indices]...));
168  return *assemble(g);
169  }
170 
171  private:
173  template <int... i>
174  auto evaluateObjective(std::integer_sequence<int, i...>, double time, ConstFieldPtr shape_disp,
175  const std::vector<ConstFieldPtr>& fs) const
176  {
177  return (*objective_)(time, *shape_disp, *fs[i]...);
178  }
179 
181  template <int... i>
182  auto gradientEvaluators(std::integer_sequence<int, i...>, double time, ConstFieldPtr shape_disp,
183  const std::vector<ConstFieldPtr>& fs) const
184  {
185  using JacFuncType = std::function<decltype((*objective_)(DifferentiateWRT<1>{}, time, *shape_disp, *fs[i]...))(
186  double, ConstFieldPtr, const std::vector<ConstFieldPtr>&)>;
187  return std::array<JacFuncType, sizeof...(i)>{
188  [this](double _time, ConstFieldPtr _shape_disp, const std::vector<ConstFieldPtr>& _fs) {
189  return (*objective_)(DifferentiateWRT<i + 1>{}, _time, *_shape_disp, *_fs[i]...);
190  }...};
191  }
192 
194  mutable double dt_ = std::numeric_limits<double>::max();
195 
197  mutable size_t cycle_ = 0;
198 
200  std::shared_ptr<Mesh> mesh_;
201 
203  std::unique_ptr<ShapeAwareFunctional<ShapeDispSpace, double(InputSpaces...)>> objective_;
204 };
205 
206 } // namespace smith
void addBoundaryIntegral(DependsOn< active_parameters... >, std::string boundary_name, const FuncOfTimeSpaceAndParams &qfunction)
Add a boundary integral depending only on selected input fields.
virtual mfem::Vector gradient(TimeInfo time_info, ConstFieldPtr shape_disp, const std::vector< ConstFieldPtr > &fields, size_t field_ordinal) const override
This is an overloaded member function, provided for convenience. It differs from the above function o...
void addBodyIntegral(std::string body_name, const FuncOfTimeSpaceAndParams &qfunction)
Add a body integral to the objective function.
virtual mfem::Vector mesh_coordinate_gradient(TimeInfo time_info, ConstFieldPtr shape_disp, const std::vector< ConstFieldPtr > &fields) const override
This is an overloaded member function, provided for convenience. It differs from the above function o...
FunctionalObjective(const std::string &physics_name, std::shared_ptr< Mesh > mesh, const SpacesT &input_mfem_spaces)
construct a FunctionalObjective
virtual double evaluate(TimeInfo time_info, ConstFieldPtr shape_disp, const std::vector< ConstFieldPtr > &fields) const override
This is an overloaded member function, provided for convenience. It differs from the above function o...
void addBodyIntegral(DependsOn< active_parameters... >, std::string body_name, const FuncOfTimeSpaceAndParams &qfunction)
Add a body integral depending only on selected input fields.
void addBoundaryIntegralImpl(std::string boundary_name, const FuncOfTimeSpaceAndParams &qfunction, std::integer_sequence< int, all_params... >)
register a custom boundary integral calculation as part of the residual
void addBoundaryIntegral(std::string boundary_name, const FuncOfTimeSpaceAndParams &qfunction)
Add a boundary integral to the objective function.
void addBodyIntegralImpl(std::string body_name, const FuncOfTimeSpaceAndParams &qfunction, std::integer_sequence< int, all_params... >)
register a custom domain integral calculation as part of the residual
Abstract residual class.
This contains a class that represents the dual of a finite element vector space, i....
This file contains the declaration of structure that manages the MFEM objects that make up the state ...
Smith mesh class which assists in constructing the appropriate parallel mfem meshes and registering a...
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
DoubleState evaluateObjective(const ScalarObjective &objective, const FieldState &shape_disp, const std::vector< FieldState > &inputs, const TimeInfo &time_info)
Evaluates a DoubleState using a provided ScalarObjective reference, and the input arguments to that o...
SMITH_HOST_DEVICE auto max(dual< gradient_type > a, double b)
Implementation of max for dual numbers.
Definition: dual.hpp:229
FiniteElementState const * ConstFieldPtr
using
Definition: field_types.hpp:36
Specifies interface for evaluating scalar objective from fields and their field gradients.
Wrapper of smith::Functional for evaluating integrals and derivatives of quantities with shape displa...
Compile-time alias for a dimension.
Definition: geometry.hpp:17
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:59
struct storing time and timestep information
Definition: common.hpp:18
double dt() const
accessor for dt
Definition: common.hpp:36
size_t cycle() const
accessor for cycle
Definition: common.hpp:39
double time() const
accessor for the current time
Definition: common.hpp:33