Smith  0.1
Smith is an implicit thermal structural mechanics simulation code.
base_physics.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 
13 #pragma once
14 
15 #include <functional>
16 #include <memory>
17 #include <cstddef>
18 #include <optional>
19 #include <string>
20 #include <unordered_map>
21 #include <vector>
22 
23 #include "mpi.h"
24 #include "mfem.hpp"
25 #include "axom/sidre.hpp"
26 #include "axom/fmt.hpp"
27 #include "axom/slic.hpp"
28 
34 #include "smith/physics/common.hpp"
35 
36 namespace smith {
37 
38 class Mesh;
39 
40 namespace detail {
47 std::string addPrefix(const std::string& prefix, const std::string& target);
48 
54 std::string removePrefix(const std::string& prefix, const std::string& target);
55 
56 } // namespace detail
57 
61 class BasePhysics {
62  public:
72  BasePhysics(std::string physics_name, std::shared_ptr<smith::Mesh> mesh, int cycle = 0, double time = 0.0,
73  bool checkpoint_to_disk = false);
74 
80  BasePhysics(BasePhysics&& other) = default;
81 
87  virtual double time() const;
88 
94  virtual int cycle() const;
95 
101  virtual double maxTime() const;
102 
108  virtual double minTime() const;
109 
115  virtual int maxCycle() const;
116 
122  virtual int minCycle() const;
123 
129  bool isQuasistatic() const { return is_quasistatic_; }
130 
136  virtual const std::vector<double>& timesteps() const;
137 
144  virtual void resetStates(int cycle = 0, double time = 0.0) = 0;
145 
151  virtual void resetAdjointStates()
152  {
153  time_ = max_time_;
154  cycle_ = max_cycle_;
155  }
156 
163  virtual void completeSetup() = 0;
164 
171  virtual const FiniteElementState& state(const std::string& state_name) const = 0;
172 
176  virtual void setState(const std::string&, const FiniteElementState&) = 0;
177 
183  virtual std::vector<std::string> stateNames() const = 0;
184 
191  virtual const FiniteElementState& adjoint(const std::string& adjoint_name) const = 0;
192 
198  virtual std::vector<std::string> adjointNames() const { return {}; }
199 
205  virtual std::vector<std::string> dualNames() const { return {}; }
206 
213  virtual const FiniteElementDual& dual(const std::string& dual_name) const
214  {
215  SLIC_ERROR_ROOT(axom::fmt::format("dual '{}' requested from physics module '{}' which does not support duals",
216  dual_name, name_));
217  return *duals_[0];
218  }
219 
227  virtual const FiniteElementState& dualAdjoint(const std::string& dual_name) const
228  {
229  SLIC_ERROR_ROOT(axom::fmt::format(
230  "dualAdjoint '{}' requested from physics module '{}' which does not support duals", dual_name, name_));
231  return *dual_adjoints_[0];
232  }
233 
239  virtual const FiniteElementState& shapeDisplacement() const;
240 
250  virtual const FiniteElementState& parameter(const std::string& parameter_name) const
251  {
252  std::string appended_name = detail::addPrefix(name_, parameter_name);
253 
254  for (auto& parameter : parameters_) {
255  if (appended_name == parameter.state->name()) {
256  return *parameter.state;
257  }
258  }
259 
260  SLIC_ERROR_ROOT(axom::fmt::format("Parameter {} requested from physics module {}, but it doesn't exist.",
261  parameter_name, name_));
262 
263  return *states_[0];
264  }
265 
272  virtual const FiniteElementState& parameter(std::size_t parameter_index) const
273  {
274  SLIC_ERROR_ROOT_IF(
275  parameter_index >= parameters_.size(),
276  axom::fmt::format("Parameter index {} requested, but only {} parameters exist in physics module {}.",
277  parameter_index, parameters_.size(), name_));
278 
279  return *parameters_[parameter_index].state;
280  }
281 
287  virtual std::vector<std::string> parameterNames() const
288  {
289  std::vector<std::string> parameter_names;
290 
291  for (auto& parameter : parameters_) {
292  parameter_names.emplace_back(detail::removePrefix(name_, parameter.state->name()));
293  }
294 
295  return parameter_names;
296  }
297 
310  virtual void setParameter(const size_t parameter_index, const FiniteElementState& parameter_state);
311 
320  virtual void setShapeDisplacement(const FiniteElementState& shape_displacement);
321 
331  virtual FiniteElementDual computeTimestepSensitivity(size_t parameter_index);
332 
342 
351  virtual const std::unordered_map<std::string, const smith::FiniteElementDual&> computeInitialConditionSensitivity()
352  const
353  {
354  SLIC_WARNING_ROOT(axom::fmt::format("Initial condition sensitivities not enabled in physics module {}", name_));
355  return {};
356  }
357 
365  virtual void advanceTimestep(double dt) = 0;
366 
372  virtual void setAdjointLoad(std::unordered_map<std::string, const smith::FiniteElementDual&> string_to_dual)
373  {
374  if (!string_to_dual.empty()) {
375  SLIC_ERROR_ROOT(
376  axom::fmt::format("Failed to setAdjointLoad. Adjoint analysis not defined for physics module {}", name_));
377  }
378  }
379 
386  virtual void setDualAdjointBcs(std::unordered_map<std::string, const smith::FiniteElementState&> string_to_bc)
387  {
388  if (!string_to_bc.empty()) {
389  SLIC_ERROR_ROOT(
390  axom::fmt::format("Failed to setDualAdjointBCs. Adjoint analysis not defined for physics module {}", name_));
391  }
392  }
393 
399  virtual void reverseAdjointTimestep()
400  {
401  SLIC_ERROR_ROOT(axom::fmt::format("Adjoint analysis not defined for physics module {}", name_));
402  }
403 
407  virtual void initializationStep() {}
408 
413 
420  virtual void outputStateToDisk(std::optional<std::string> paraview_output_dir = {}) const;
421 
428 
437  virtual FiniteElementState loadCheckpointedState(const std::string& state_name, int cycle);
438 
447  virtual FiniteElementDual loadCheckpointedDual([[maybe_unused]] const std::string& state_name,
448  [[maybe_unused]] int cycle)
449  {
450  SLIC_ERROR_ROOT(axom::fmt::format("loadCheckpointedDual not enabled in physics module {}", name_));
451  return *duals_[0];
452  }
453 
459  virtual double getCheckpointedTimestep(int cycle) const;
460 
468  virtual void initializeSummary(axom::sidre::DataStore& datastore, const double t_final, const double dt) const;
469 
476  virtual void saveSummary(axom::sidre::DataStore& datastore, const double t) const;
477 
481  virtual ~BasePhysics() = default;
482 
486  const smith::Mesh& mesh() const;
487 
491  const mfem::ParMesh& mfemParMesh() const;
492 
496  mfem::ParMesh& mfemParMesh();
497 
501  std::string name() const { return name_; }
502 
503  protected:
510 
514  void CreateParaviewDataCollection() const;
515 
521  void UpdateParaviewDataCollection(const std::string& paraview_output_dir) const;
522 
530  void initializeBasePhysicsStates(int cycle, double time);
531 
539  std::unordered_map<std::string, FiniteElementState> getCheckpointedStates(int cycle);
540 
542  std::string name_ = {};
543 
547  std::shared_ptr<smith::Mesh> mesh_;
548 
552  MPI_Comm comm_;
553 
557  std::vector<const smith::FiniteElementState*> states_;
558 
562  std::vector<const smith::FiniteElementState*> adjoints_;
563 
567  std::vector<const smith::FiniteElementDual*> duals_;
568 
572  std::vector<const smith::FiniteElementState*> dual_adjoints_;
573 
575  struct ParameterInfo {
584  template <typename FunctionSpace>
585  ParameterInfo(mfem::ParMesh& mesh, FunctionSpace space, const std::string& name = "")
586  {
587  state = std::make_unique<FiniteElementState>(mesh, space, name);
588  previous_state = std::make_unique<FiniteElementState>(mesh, space, "previous_" + name);
589  sensitivity = std::make_unique<FiniteElementDual>(mesh, space, name + "_sensitivity");
592  }
593 
595  std::unique_ptr<smith::FiniteElementState> state;
596 
598  std::unique_ptr<smith::FiniteElementState> previous_state;
599 
605  std::unique_ptr<smith::FiniteElementDual> sensitivity;
606  };
607 
609  std::vector<ParameterInfo> parameters_;
610 
612  mutable std::unordered_map<std::string, std::vector<smith::FiniteElementState>> checkpoint_states_;
613 
621  mutable std::unordered_map<std::string, smith::FiniteElementState> cached_checkpoint_states_;
622 
624  mutable std::optional<int> cached_checkpoint_cycle_;
625 
629  bool is_quasistatic_ = true;
630 
634  static constexpr int FLOAT_PRECISION_ = 8;
635 
639  double time_;
640 
644  double dt_;
645 
649  double max_time_;
650 
654  double min_time_;
655 
659  std::vector<double> timesteps_;
660 
664  int cycle_;
665 
670 
675 
680 
685 
690 
694  mutable std::unique_ptr<mfem::ParaViewDataCollection> paraview_dc_;
695 
699  mutable std::unordered_map<std::string, std::unique_ptr<mfem::ParGridFunction>> paraview_dual_grid_functions_;
700 
704  mutable std::unique_ptr<mfem::ParGridFunction> shape_sensitivity_grid_function_;
705 
710 
715 
720 
723 };
724 
725 } // namespace smith
This file contains the declaration of the boundary condition manager class.
This is the abstract base class for a generic forward solver.
virtual const FiniteElementState & parameter(const std::string &parameter_name) const
Accessor for getting named finite element state parameter fields from the physics modules.
std::string name_
Name of the physics module.
virtual int maxCycle() const
The maximum cycle (timestep iteration number) reached by the forward solver.
virtual const std::vector< double > & timesteps() const
Get a vector of the timestep sizes (i.e. s) taken by the forward solver.
virtual 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::shared_ptr< smith::Mesh > mesh_
The primary mesh.
virtual ~BasePhysics()=default
Destroy the Base Solver object.
virtual FiniteElementDual loadCheckpointedDual([[maybe_unused]] const std::string &state_name, [[maybe_unused]] int cycle)
Accessor for getting a single named finite element dual solution from the physics modules at a given ...
void UpdateParaviewDataCollection(const std::string &paraview_output_dir) const
Update the paraview states, duals, parameters, and metadata (cycle, time) in preparation for output.
void CreateParaviewDataCollection() const
Create a paraview data collection for the physics package if requested.
virtual void setDualAdjointBcs(std::unordered_map< std::string, const smith::FiniteElementState & > string_to_bc)
Set the dual loads (dirichlet values) for the adjoint reverse timestep solve This must be called afte...
std::vector< const smith::FiniteElementState * > states_
List of finite element primal states associated with this physics module.
double min_time_
The time the forward solver was initialized to.
virtual void resetAdjointStates()
Base method to reset physics states back to the end of time to start adjoint calculations again....
int cycle_
Current cycle (forward pass time iteration count)
double ode_time_point_
The value of time at which the ODE solver wants to evaluate the residual.
virtual const FiniteElementState & adjoint(const std::string &adjoint_name) const =0
Accessor for getting named finite element state adjoint solution from the physics modules.
std::unordered_map< std::string, FiniteElementState > getCheckpointedStates(int cycle)
Accessor for getting all of the primal solutions from the physics modules at a given checkpointed cyc...
std::vector< const smith::FiniteElementDual * > duals_
List of finite element duals associated with this physics module.
virtual void initializationStep()
Initialize any fields nessary for before the first step of the time integration.
virtual void initializeSummary(axom::sidre::DataStore &datastore, const double t_final, const double dt) const
Initializes the Sidre structure for simulation summary data.
std::string name() const
Return the name of the physics.
std::vector< double > timesteps_
A vector of the timestep sizes (i.e. ) taken by the forward solver.
std::vector< ParameterInfo > parameters_
A vector of the parameters associated with this physics module.
virtual void setShapeDisplacement(const FiniteElementState &shape_displacement)
Set the current shape displacement for the underlying mesh.
virtual double time() const
Get the current forward-solution time.
std::optional< int > cached_checkpoint_cycle_
An optional int for disk-based checkpointing containing the cycle number of the last retrieved checkp...
std::vector< const smith::FiniteElementState * > dual_adjoints_
List of adjoint finite element duals associated with this physics module.
int max_cycle_
The maximum cycle (forward pass iteration count) reached by the forward solver.
smith::FiniteElementDual shape_displacement_dual_
The shape displacement field sensitivity.
BasePhysics(std::string physics_name, std::shared_ptr< smith::Mesh > mesh, int cycle=0, double time=0.0, bool checkpoint_to_disk=false)
Empty constructor.
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...
MPI_Comm comm_
The MPI communicator.
virtual double maxTime() const
Get the maximum time reached by the forward solver.
virtual void advanceTimestep(double dt)=0
Advance the state variables according to the chosen time integrator.
std::unordered_map< std::string, std::vector< smith::FiniteElementState > > checkpoint_states_
A map containing optionally in-memory checkpointed primal states for transient adjoint solvers.
virtual void completeSetup()=0
Complete the setup and allocate the necessary data structures.
virtual void setState(const std::string &, const FiniteElementState &)=0
Set the primal solution field values of the underlying physics solver.
static constexpr int FLOAT_PRECISION_
Number of significant figures to output for floating-point.
virtual std::vector< std::string > adjointNames() const
Get a vector of the finite element state adjoint solution names.
std::unique_ptr< mfem::ParaViewDataCollection > paraview_dc_
DataCollection pointer for optional paraview output.
virtual const FiniteElementState & shapeDisplacement() const
Accessor for getting the shape displacement field from the physics modules.
const smith::Mesh & mesh() const
Returns a reference to the mesh object.
virtual const FiniteElementState & parameter(std::size_t parameter_index) const
Accessor for getting indexed finite element state parameter fields from the physics modules.
double dt_
Current time step.
int mpi_rank_
MPI rank.
int mpi_size_
MPI size.
double time_
Current time for the forward pass.
virtual int cycle() const
Get the current forward-solution cycle iteration number.
virtual const FiniteElementDual & computeTimestepShapeSensitivity()
Compute the implicit sensitivity of the quantity of interest used in defining the adjoint load with r...
virtual void resetStates(int cycle=0, double time=0.0)=0
Base method to reset physics states to the initial time. This does not reset design parameters or sha...
BoundaryConditionManager bcs_
Boundary condition manager instance.
virtual void reverseAdjointTimestep()
Solve the adjoint reverse timestep problem.
bool is_quasistatic_
Whether the simulation is time-independent.
std::unique_ptr< mfem::ParGridFunction > shape_sensitivity_grid_function_
A optional view of the shape sensitivity in grid function form for paraview output.
bool isQuasistatic() const
Check if the physics is setup as quasistatic.
std::unordered_map< std::string, smith::FiniteElementState > cached_checkpoint_states_
A container relating a checkpointed cycle and the associated finite element state fields.
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.
virtual int minCycle() const
Get the initial cycle (timestep iteration number) used by the forward solver.
virtual double getCheckpointedTimestep(int cycle) const
Get a timestep increment which has been previously checkpointed at the give cycle.
double max_time_
The maximum time reached for the forward solver.
virtual FiniteElementDual computeTimestepSensitivity(size_t parameter_index)
Compute the implicit sensitivity of the quantity of interest used in defining the adjoint load with r...
const FiniteElementDual & shapeDisplacementSensitivity() const
Internally used accessor for getting the shape displacement sensitivity from the physics modules.
virtual void saveSummary(axom::sidre::DataStore &datastore, const double t) const
Saves the summary data to the Sidre Datastore.
virtual const std::unordered_map< std::string, const smith::FiniteElementDual & > computeInitialConditionSensitivity() const
Compute the implicit sensitivity of the quantity of interest with respect to the initial condition fi...
virtual std::vector< std::string > dualNames() const
Get a vector of the finite element state dual (reaction) solution names.
bool checkpoint_to_disk_
A flag denoting whether to save the state to disk or memory as needed for dynamic adjoint solves.
std::vector< const smith::FiniteElementState * > adjoints_
List of finite element adjoint states associated with this physics module.
virtual const FiniteElementDual & dual(const std::string &dual_name) const
Accessor for getting named finite element state dual (reaction) solution from the physics modules.
virtual std::vector< std::string > parameterNames() const
Get a vector of the finite element state parameter names.
BasePhysics(BasePhysics &&other)=default
Construct a new Base Physics object (copy constructor)
virtual const FiniteElementState & state(const std::string &state_name) const =0
Accessor for getting named finite element state primal solution from the physics modules.
int min_cycle_
The cycle the forward solver was initialized to.
const mfem::ParMesh & mfemParMesh() const
Returns a reference to the mfem ParMesh object.
virtual void reverseAdjointInitializationStep()
Compute adjoint sensitivities back through initializationStep.
void initializeBasePhysicsStates(int cycle, double time)
Protected, non-virtual method to reset physics states to zero. This does not reset design parameters ...
void loadCheckpointedStatesFromDisk(int cycle)
load checkpointed states from disk into states array
virtual FiniteElementState loadCheckpointedState(const std::string &state_name, int cycle)
Accessor for getting a single named finite element state primal solution from the physics modules at ...
virtual double minTime() const
Get the initial time used by the forward solver.
smith::FiniteElementState shape_displacement_
The shape displacement field.
virtual std::vector< std::string > stateNames() const =0
Get a vector of the finite element state primal solution names.
virtual void setAdjointLoad(std::unordered_map< std::string, const smith::FiniteElementDual & > string_to_dual)
Set the loads for the adjoint reverse timestep solve.
virtual const FiniteElementState & dualAdjoint(const std::string &dual_name) const
Accessor for getting named finite element state dual adjoint (reaction adjoint load) from the physics...
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)
Helper class for constructing a mesh consistent with Smith.
Definition: mesh.hpp:37
static void storeState(FiniteElementState &state)
Store a pre-constructed finite element state in the state manager.
static void storeDual(FiniteElementDual &dual)
Store a pre-constructed finite element dual 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: smith.cpp:36
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< smith::FiniteElementState > previous_state
The finite element state representing the parameter at the previous evaluation.
std::unique_ptr< smith::FiniteElementDual > sensitivity
The sensitivities (dual vectors) of the QOI encoded in the adjoint load with respect to each of the i...
std::unique_ptr< smith::FiniteElementState > state
The finite element states representing user-defined and owned parameter fields.
ParameterInfo(mfem::ParMesh &mesh, FunctionSpace space, const std::string &name="")
Construct a new Parameter Info object.
a small POD class for tracking function space metadata