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 <int... active_parameters, typename FuncOfTimeSpaceAndParams>
71  void addBodyIntegral(DependsOn<active_parameters...>, std::string body_name,
72  const FuncOfTimeSpaceAndParams& qfunction)
73  {
74  objective_->AddDomainIntegral(smith::Dimension<spatial_dim>{}, smith::DependsOn<active_parameters...>{}, qfunction,
75  mesh_->domain(body_name));
76  }
77 
85  template <int... active_parameters, typename FuncOfTimeSpaceAndParams>
86  void addBoundaryIntegral(DependsOn<active_parameters...>, std::string boundary_name,
87  const FuncOfTimeSpaceAndParams& qfunction)
88  {
89  objective_->AddBoundaryIntegral(smith::Dimension<spatial_dim>{}, smith::DependsOn<active_parameters...>{},
90  qfunction, mesh_->domain(boundary_name));
91  }
92 
94  virtual double evaluate(TimeInfo time_info, ConstFieldPtr shape_disp,
95  const std::vector<ConstFieldPtr>& fields) const override
96  {
97  dt_ = time_info.dt();
98  cycle_ = time_info.cycle();
99 
100  return evaluateObjective(std::make_integer_sequence<int, sizeof...(parameter_indices)>{}, time_info.time(),
101  shape_disp, fields);
102  }
103 
105  virtual mfem::Vector gradient(TimeInfo time_info, ConstFieldPtr shape_disp, const std::vector<ConstFieldPtr>& fields,
106  size_t field_ordinal) const override
107  {
108  dt_ = time_info.dt();
109  cycle_ = time_info.cycle();
110 
111  auto grads = gradientEvaluators(std::make_integer_sequence<int, sizeof...(parameter_indices)>{}, time_info.time(),
112  shape_disp, fields);
113  auto g = smith::get<DERIVATIVE>(grads[field_ordinal](time_info.time(), shape_disp, fields));
114  return *assemble(g);
115  }
116 
118  virtual mfem::Vector mesh_coordinate_gradient(TimeInfo time_info, ConstFieldPtr shape_disp,
119  const std::vector<ConstFieldPtr>& fields) const override
120  {
121  dt_ = time_info.dt();
122  cycle_ = time_info.cycle();
123 
124  auto g = smith::get<DERIVATIVE>(
125  (*objective_)(DifferentiateWRT<0>{}, time_info.time(), *shape_disp, *fields[parameter_indices]...));
126  return *assemble(g);
127  }
128 
129  private:
131  template <int... i>
132  auto evaluateObjective(std::integer_sequence<int, i...>, double time, ConstFieldPtr shape_disp,
133  const std::vector<ConstFieldPtr>& fs) const
134  {
135  return (*objective_)(time, *shape_disp, *fs[i]...);
136  }
137 
139  template <int... i>
140  auto gradientEvaluators(std::integer_sequence<int, i...>, double time, ConstFieldPtr shape_disp,
141  const std::vector<ConstFieldPtr>& fs) const
142  {
143  using JacFuncType = std::function<decltype((*objective_)(DifferentiateWRT<1>{}, time, *shape_disp, *fs[i]...))(
144  double, ConstFieldPtr, const std::vector<ConstFieldPtr>&)>;
145  return std::array<JacFuncType, sizeof...(i)>{
146  [this](double _time, ConstFieldPtr _shape_disp, const std::vector<ConstFieldPtr>& _fs) {
147  return (*objective_)(DifferentiateWRT<i + 1>{}, _time, *_shape_disp, *_fs[i]...);
148  }...};
149  }
150 
152  mutable double dt_ = std::numeric_limits<double>::max();
153 
155  mutable size_t cycle_ = 0;
156 
158  std::shared_ptr<Mesh> mesh_;
159 
161  std::unique_ptr<ShapeAwareFunctional<ShapeDispSpace, double(InputSpaces...)>> objective_;
162 };
163 
164 } // namespace smith
void addBoundaryIntegral(DependsOn< active_parameters... >, std::string boundary_name, const FuncOfTimeSpaceAndParams &qfunction)
register a custom boundary integral calculation as part of the residual
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...
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)
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:45
struct storing time and timestep information
Definition: common.hpp:18
double dt() const
accessor for dt
Definition: common.hpp:29
size_t cycle() const
accessor for cycle
Definition: common.hpp:32
double time() const
accessor for the current time
Definition: common.hpp:26