Serac  0.1
Serac is an implicit thermal strucural mechanics simulation code.
base_physics.hpp
Go to the documentation of this file.
1 // Copyright (c) 2019-2023, Lawrence Livermore National Security, LLC and
2 // other Serac 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 <functional>
16 #include <memory>
17 
18 #include "mfem.hpp"
19 #include "axom/sidre.hpp"
20 
26 #include "serac/physics/common.hpp"
27 
28 namespace serac {
29 
30 namespace detail {
37 std::string addPrefix(const std::string& prefix, const std::string& target);
38 
44 std::string removePrefix(const std::string& prefix, const std::string& target);
45 
46 } // namespace detail
47 
51 class BasePhysics {
52 public:
62  BasePhysics(std::string physics_name, std::string mesh_tag, int cycle = 0, double time = 0.0,
63  bool checkpoint_to_disk = false);
64 
70  BasePhysics(BasePhysics&& other) = default;
71 
77  virtual double time() const;
78 
84  virtual int cycle() const;
85 
91  virtual double maxTime() const;
92 
98  virtual double minTime() const;
99 
105  virtual int maxCycle() const;
106 
112  virtual int minCycle() const;
113 
119  bool isQuasistatic() const { return is_quasistatic_; }
120 
126  virtual std::vector<double> timesteps() const;
127 
134  virtual void resetStates(int cycle = 0, double time = 0.0) = 0;
135 
142  virtual void completeSetup() = 0;
143 
150  virtual const FiniteElementState& state(const std::string& state_name) const = 0;
151 
155  virtual void setState(const std::string&, const FiniteElementState&) = 0;
156 
162  virtual std::vector<std::string> stateNames() const = 0;
163 
170  virtual const FiniteElementState& adjoint(const std::string& adjoint_name) const = 0;
171 
177  virtual std::vector<std::string> adjointNames() const { return {}; }
178 
185 
195  const FiniteElementState& parameter(const std::string& parameter_name) const
196  {
197  std::string appended_name = detail::addPrefix(name_, parameter_name);
198 
199  for (auto& parameter : parameters_) {
200  if (appended_name == parameter.state->name()) {
201  return *parameter.state;
202  }
203  }
204 
205  SLIC_ERROR_ROOT(axom::fmt::format("Parameter {} requested from physics module {}, but it doesn't exist.",
206  parameter_name, name_));
207 
208  return *states_[0];
209  }
210 
217  const FiniteElementState& parameter(std::size_t parameter_index) const
218  {
219  SLIC_ERROR_ROOT_IF(
220  parameter_index >= parameters_.size(),
221  axom::fmt::format("Parameter index {} requested, but only {} parameters exist in physics module {}.",
222  parameter_index, parameters_.size(), name_));
223 
224  return *parameters_[parameter_index].state;
225  }
226 
232  std::vector<std::string> parameterNames()
233  {
234  std::vector<std::string> parameter_names;
235 
236  for (auto& parameter : parameters_) {
237  parameter_names.emplace_back(detail::removePrefix(name_, parameter.state->name()));
238  }
239 
240  return parameter_names;
241  }
242 
255  void setParameter(const size_t parameter_index, const FiniteElementState& parameter_state);
256 
265  void setShapeDisplacement(const FiniteElementState& shape_displacement);
266 
275  virtual const FiniteElementDual& computeTimestepSensitivity(size_t /* parameter_index */)
276  {
277  SLIC_ERROR_ROOT(axom::fmt::format("Parameter sensitivities not enabled in physics module {}", name_));
278  return *parameters_[0].sensitivity;
279  }
280 
290  {
291  SLIC_ERROR_ROOT(axom::fmt::format("Shape sensitivities not enabled in physics module {}", name_));
293  }
294 
303  virtual const std::unordered_map<std::string, const serac::FiniteElementDual&> computeInitialConditionSensitivity()
304  {
305  SLIC_ERROR_ROOT(axom::fmt::format("Initial condition sensitivities not enabled in physics module {}", name_));
306  return {};
307  }
308 
314  virtual void advanceTimestep(double dt) = 0;
315 
319  virtual void setAdjointLoad(std::unordered_map<std::string, const serac::FiniteElementDual&>)
320  {
321  SLIC_ERROR_ROOT(axom::fmt::format("Adjoint analysis not defined for physics module {}", name_));
322  }
323 
328  virtual void reverseAdjointTimestep()
329  {
330  SLIC_ERROR_ROOT(axom::fmt::format("Adjoint analysis not defined for physics module {}", name_));
331  }
332 
339  virtual void outputStateToDisk(std::optional<std::string> paraview_output_dir = {}) const;
340 
349  FiniteElementState loadCheckpointedState(const std::string& state_name, int cycle) const;
350 
356  virtual double getCheckpointedTimestep(int cycle) const;
357 
365  virtual void initializeSummary(axom::sidre::DataStore& datastore, const double t_final, const double dt) const;
366 
373  virtual void saveSummary(axom::sidre::DataStore& datastore, const double t) const;
374 
378  virtual ~BasePhysics() = default;
379 
383  const mfem::ParMesh& mesh() const { return mesh_; }
385  mfem::ParMesh& mesh() { return mesh_; }
386 
387 protected:
391  void CreateParaviewDataCollection() const;
392 
398  void UpdateParaviewDataCollection(const std::string& paraview_output_dir) const;
399 
407  void initializeBasePhysicsStates(int cycle, double time);
408 
416  virtual std::unordered_map<std::string, FiniteElementState> getCheckpointedStates(int cycle) const;
417 
419  std::string name_ = {};
420 
422  std::string mesh_tag_ = {};
423 
427  mfem::ParMesh& mesh_;
428 
432  MPI_Comm comm_;
433 
437  std::vector<const serac::FiniteElementState*> states_;
438 
442  std::vector<const serac::FiniteElementState*> adjoints_;
443 
447  std::vector<const serac::FiniteElementDual*> duals_;
448 
450  struct ParameterInfo {
459  template <typename FunctionSpace>
460  ParameterInfo(mfem::ParMesh& mesh, FunctionSpace space, const std::string& name = "")
461  {
462  state = std::make_unique<FiniteElementState>(mesh, space, name);
463  previous_state = std::make_unique<FiniteElementState>(mesh, space, "previous_" + name);
464  sensitivity = std::make_unique<FiniteElementDual>(mesh, space, name + "_sensitivity");
467  }
468 
470  std::unique_ptr<serac::FiniteElementState> state;
471 
473  std::unique_ptr<serac::FiniteElementState> previous_state;
474 
480  std::unique_ptr<serac::FiniteElementDual> sensitivity;
481  };
482 
484  std::vector<ParameterInfo> parameters_;
485 
489 
494  std::unique_ptr<FiniteElementDual> shape_displacement_sensitivity_;
495 
497  mutable std::unordered_map<std::string, std::vector<serac::FiniteElementState>> checkpoint_states_;
498 
506  mutable std::unordered_map<std::string, serac::FiniteElementState> cached_checkpoint_states_;
507 
509  mutable std::optional<int> cached_checkpoint_cycle_;
510 
514  bool is_quasistatic_ = true;
515 
519  static constexpr int FLOAT_PRECISION_ = 8;
520 
524  double time_;
525 
529  double max_time_;
530 
534  double min_time_;
535 
539  std::vector<double> timesteps_;
540 
544  int cycle_;
545 
550 
555 
560 
565 
570 
574  mutable std::unique_ptr<mfem::ParaViewDataCollection> paraview_dc_;
575 
579  mutable std::unordered_map<std::string, std::unique_ptr<mfem::ParGridFunction>> paraview_dual_grid_functions_;
580 
584  mutable std::unique_ptr<mfem::ParGridFunction> shape_sensitivity_grid_function_;
585 
590 
593 };
594 
595 } // namespace serac
This file contains the declaration of the boundary condition manager class.
This is the abstract base class for a generic forward solver.
virtual std::vector< double > timesteps() const
Get a vector of the timestep sizes (i.e. s) taken by the forward solver.
std::optional< int > cached_checkpoint_cycle_
An optional int for disk-based checkpointing containing the cycle number of the last retrieved checkp...
virtual const std::unordered_map< std::string, const serac::FiniteElementDual & > computeInitialConditionSensitivity()
Compute the implicit sensitivity of the quantity of interest with respect to the initial condition fi...
const FiniteElementState & parameter(std::size_t parameter_index) const
Accessor for getting indexed finite element state parameter fields from the physics modules.
mfem::ParMesh & mesh_
The primary mesh.
virtual void completeSetup()=0
Complete the setup and allocate the necessary data structures.
int mpi_rank_
MPI rank.
std::unordered_map< std::string, serac::FiniteElementState > cached_checkpoint_states_
A container relating a checkpointed cycle and the associated finite element state fields.
virtual void setState(const std::string &, const FiniteElementState &)=0
Set the primal solution field values of the underlying physics solver.
std::vector< const serac::FiniteElementDual * > duals_
List of finite element duals associated with this physics module.
virtual void initializeSummary(axom::sidre::DataStore &datastore, const double t_final, const double dt) const
Initializes the Sidre structure for simulation summary data.
virtual void saveSummary(axom::sidre::DataStore &datastore, const double t) const
Saves the summary data to the Sidre Datastore.
std::unique_ptr< FiniteElementDual > shape_displacement_sensitivity_
Sensitivity with respect to the shape displacement field.
double max_time_
The maximum time reached for the forward solver.
virtual std::vector< std::string > stateNames() const =0
Get a vector of the finite element state primal solution names.
int cycle_
Current cycle (forward pass time iteration count)
std::vector< const serac::FiniteElementState * > states_
List of finite element primal states associated with this physics module.
virtual double time() const
Get the current forward-solution time.
virtual ~BasePhysics()=default
Destroy the Base Solver object.
std::unordered_map< std::string, std::vector< serac::FiniteElementState > > checkpoint_states_
A map containing optionally in-memory checkpointed primal states for transient adjoint solvers.
double min_time_
The time the forward solver was initialized to.
std::vector< std::string > parameterNames()
Get a vector of the finite element state parameter names.
virtual std::vector< std::string > adjointNames() const
Get a vector of the finite element state adjoint solution names.
bool isQuasistatic() const
Check if the physics is setup as quasistatic.
double time_
Current time for the forward pass.
virtual void reverseAdjointTimestep()
Solve the adjoint reverse timestep problem.
virtual void resetStates(int cycle=0, double time=0.0)=0
Base method to reset physics states to zero. This does not reset design parameters or shape.
FiniteElementState & shape_displacement_
The parameter info associated with the shape displacement field.
virtual const FiniteElementState & adjoint(const std::string &adjoint_name) const =0
Accessor for getting named finite element state adjoint solution from the physics modules.
virtual const FiniteElementDual & computeTimestepSensitivity(size_t)
Compute the implicit sensitivity of the quantity of interest used in defining the adjoint load with r...
int min_cycle_
The cycle the forward solver was initialized to.
bool checkpoint_to_disk_
A flag denoting whether to save the state to disk or memory as needed for dynamic adjoint solves.
double ode_time_point_
The value of time at which the ODE solver wants to evaluate the residual.
int max_cycle_
The maximum cycle (forward pass iteration count) reached by the forward solver.
virtual int cycle() const
Get the current forward-solution cycle iteration number.
const FiniteElementState & shapeDisplacement() const
Accessor for getting the shape displacement field from the physics modules.
void setShapeDisplacement(const FiniteElementState &shape_displacement)
Set the current shape displacement for the underlying mesh.
virtual const FiniteElementDual & computeTimestepShapeSensitivity()
Compute the implicit sensitivity of the quantity of interest used in defining the adjoint load with r...
const FiniteElementState & parameter(const std::string &parameter_name) const
Accessor for getting named finite element state parameter fields from the physics modules.
BoundaryConditionManager bcs_
Boundary condition manager instance.
bool is_quasistatic_
Whether the simulation is time-independent.
BasePhysics(BasePhysics &&other)=default
Construct a new Base Physics object (copy constructor)
void UpdateParaviewDataCollection(const std::string &paraview_output_dir) const
Update the paraview states, duals, parameters, and metadata (cycle, time) in preparation for output.
const mfem::ParMesh & mesh() const
Returns a reference to the mesh object.
virtual const FiniteElementState & state(const std::string &state_name) const =0
Accessor for getting named finite element state primal solution from the physics modules.
virtual void setAdjointLoad(std::unordered_map< std::string, const serac::FiniteElementDual & >)
Set the loads for the adjoint reverse timestep solve.
virtual double minTime() const
Get the initial time used by the forward solver.
virtual void advanceTimestep(double dt)=0
Advance the state variables according to the chosen time integrator.
std::string mesh_tag_
ID of the corresponding MFEMSidreDataCollection (denoting a mesh)
std::unique_ptr< mfem::ParaViewDataCollection > paraview_dc_
DataCollection pointer for optional paraview output.
FiniteElementState loadCheckpointedState(const std::string &state_name, int cycle) const
Accessor for getting a single named finite element state primal solution from the physics modules at ...
std::unique_ptr< mfem::ParGridFunction > shape_sensitivity_grid_function_
A optional view of the shape sensitivity in grid function form for paraview output.
virtual double getCheckpointedTimestep(int cycle) const
Get a timestep increment which has been previously checkpointed at the give cycle.
virtual void outputStateToDisk(std::optional< std::string > paraview_output_dir={}) const
Output the current state of the PDE fields in Sidre format and optionally in Paraview format if parav...
void setParameter(const size_t parameter_index, const FiniteElementState &parameter_state)
Deep copy a parameter field into the internally-owned parameter used for simulations.
std::vector< ParameterInfo > parameters_
A vector of the parameters associated with this physics module.
virtual std::unordered_map< std::string, FiniteElementState > getCheckpointedStates(int cycle) const
Accessor for getting all of the primal solutions from the physics modules at a given checkpointed cyc...
int mpi_size_
MPI size.
std::string name_
Name of the physics module.
virtual int minCycle() const
Get the initial cycle (timestep iteration number) used by the forward solver.
void CreateParaviewDataCollection() const
Create a paraview data collection for the physics package if requested.
std::vector< const serac::FiniteElementState * > adjoints_
List of finite element adjoint states associated with this physics module.
virtual double maxTime() const
Get the maximum time reached by the forward solver.
std::unordered_map< std::string, std::unique_ptr< mfem::ParGridFunction > > paraview_dual_grid_functions_
A optional map of the dual names and duals in grid function form for paraview output.
void initializeBasePhysicsStates(int cycle, double time)
Protected, non-virtual method to reset physics states to zero. This does not reset design parameters ...
mfem::ParMesh & mesh()
This is an overloaded member function, provided for convenience. It differs from the above function o...
MPI_Comm comm_
The MPI communicator.
std::vector< double > timesteps_
A vector of the timestep sizes (i.e. ) taken by the forward solver.
static constexpr int FLOAT_PRECISION_
Number of significant figures to output for floating-point.
BasePhysics(std::string physics_name, std::string mesh_tag, int cycle=0, double time=0.0, bool checkpoint_to_disk=false)
Empty constructor.
virtual int maxCycle() const
The maximum cycle (timestep iteration number) reached by the forward solver.
A container for the boundary condition information relating to a specific physics module.
Class for encapsulating the dual vector space of a finite element space (i.e. the space of linear for...
Class for encapsulating the critical MFEM components of a primal finite element field.
std::string name() const
Returns the name of the FEState (field)
static void storeDual(FiniteElementDual &dual)
Store a pre-constructed finite element dual in the state manager.
static void storeState(FiniteElementState &state)
Store a pre-constructed finite element state in the state manager.
A file defining some enums and structs that are used by the different physics modules.
This file contains the declaration of an equation solver wrapper.
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 ...
Accelerator functionality.
Definition: serac.cpp:38
This file contains the declaration of the StateManager class.
The information needed for the physics parameters stored as Finite Element State fields.
std::unique_ptr< serac::FiniteElementState > state
The finite element states representing user-defined and owned parameter fields.
std::unique_ptr< serac::FiniteElementState > previous_state
The finite element state representing the parameter at the previous evaluation.
std::unique_ptr< serac::FiniteElementDual > sensitivity
The sensitivities (dual vectors) of the QOI encoded in the adjoint load with respect to each of the i...
ParameterInfo(mfem::ParMesh &mesh, FunctionSpace space, const std::string &name="")
Construct a new Parameter Info object.