Smith  0.1
Smith is an implicit thermal structural mechanics simulation code.
field_store.hpp
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 
7 #pragma once
8 
12 #include "smith/physics/mesh.hpp"
13 
14 #include <map>
15 #include <string>
16 #include <vector>
17 #include <memory>
18 
19 namespace smith {
20 
21 class DirichletBoundaryConditions;
22 class BoundaryConditionManager;
23 
29 template <typename Space, typename Time = void*>
30 struct FieldType {
36  FieldType(std::string n, int unknown_index_ = -1) : name(n), unknown_index(unknown_index_) {}
37  std::string name;
39 };
40 
44 struct FieldStore {
50  FieldStore(std::shared_ptr<Mesh> mesh, size_t storage_size = 50);
51 
55  enum class TimeDerivative
56  {
57  VAL, //< The value of the field.
58  DOT,
59  DDOT,
60  DDDOT
61  };
62 
68  template <typename Space>
70  {
71  shape_disp_.push_back(smith::createFieldState<Space>(*graph_, Space{}, type.name, mesh_->tag()));
72  }
73 
79  template <typename Space>
81  {
82  to_params_index_[type.name] = params_.size();
83  params_.push_back(smith::createFieldState<Space>(*graph_, Space{}, type.name, mesh_->tag()));
84  }
85 
101  template <typename Space>
102  std::shared_ptr<DirichletBoundaryConditions> addIndependent(FieldType<Space>& type,
103  std::shared_ptr<TimeIntegrationRule> time_rule)
104  {
105  type.unknown_index = static_cast<int>(num_unknowns_);
106  to_states_index_[type.name] = states_.size();
107  to_unknown_index_[type.name] = num_unknowns_;
108  FieldState new_field = smith::createFieldState<Space>(*graph_, Space{}, type.name, mesh_->tag());
109  states_.push_back(new_field);
110  auto latest_bc = addBoundaryConditions(new_field.get());
111  ++num_unknowns_;
112  SLIC_ERROR_IF(num_unknowns_ != boundary_conditions_.size(),
113  "Inconcistency between num unknowns and boundary condition size");
114 
115  SLIC_ERROR_IF(!time_rule, "Invalid time_rule");
116 
117  TimeIntegrationMapping mapping;
118  mapping.primary_name = type.name;
119  independent_name_to_rule_index_[type.name] = time_integration_rules_.size();
120  time_integration_rules_.push_back({time_rule, mapping});
121 
122  return latest_bc;
123  }
124 
153  template <typename Space>
154  auto addDependent(FieldType<Space> independent_field, TimeDerivative derivative, std::string name_override = "")
155  {
156  std::string suffix;
157  if (derivative == TimeDerivative::VAL) {
158  suffix = "_old";
159  } else if (derivative == TimeDerivative::DOT) {
160  suffix = "_dot_old";
161  } else if (derivative == TimeDerivative::DDOT) {
162  suffix = "_ddot_old";
163  } else {
164  SLIC_ERROR("Unsupported TimeDerivative");
165  }
166 
167  std::string name = name_override.empty() ? independent_field.name + suffix : name_override;
168 
169  if (independent_name_to_rule_index_.count(independent_field.name)) {
170  size_t rule_idx = independent_name_to_rule_index_.at(independent_field.name);
171  auto& mapping = time_integration_rules_[rule_idx].second;
172  if (derivative == TimeDerivative::VAL) {
173  mapping.history_name = name;
174  } else if (derivative == TimeDerivative::DOT) {
175  mapping.dot_name = name;
176  } else if (derivative == TimeDerivative::DDOT) {
177  mapping.ddot_name = name;
178  }
179  } else {
180  SLIC_WARNING("Adding dependent time integration field for independent field '"
181  << independent_field.name << "' which has no registered TimeIntegrationRule.");
182  }
183 
184  to_states_index_[name] = states_.size();
185  states_.push_back(smith::createFieldState<Space>(*graph_, Space{}, name, mesh_->tag()));
186  return FieldType<Space>(name);
187  }
188 
195  void addWeakFormUnknownArg(std::string weak_form_name, std::string argument_name, size_t argument_index);
196 
203  void addWeakFormArg(std::string weak_form_name, std::string argument_name, size_t argument_index);
204 
209  size_t getNumUnknowns() const { return num_unknowns_; }
210 
221  void addWeakFormReaction(std::string weak_form_name, std::string field_name);
222 
228  std::string getWeakFormReaction(const std::string& weak_form_name) const;
229 
245  template <typename... FieldTypes>
246  std::vector<const mfem::ParFiniteElementSpace*> createSpaces(const std::string& weak_form_name,
247  const std::string& reaction_field_name,
248  FieldTypes... types)
249  {
250  addWeakFormReaction(weak_form_name, reaction_field_name);
251  std::vector<const mfem::ParFiniteElementSpace*> spaces;
252  size_t arg_num = 0;
253  auto register_field = [&](auto type) {
254  spaces.push_back(&getField(type.name).get()->space());
255  addWeakFormArg(weak_form_name, type.name, arg_num);
256  if (type.unknown_index >= 0) {
257  addWeakFormUnknownArg(weak_form_name, type.name, arg_num);
258  }
259  ++arg_num;
260  };
261  (register_field(types), ...);
262  return spaces;
263  }
264 
269  std::string primary_name;
270  std::string history_name;
271  std::string dot_name;
272  std::string ddot_name;
273  };
274 
280  const std::vector<std::pair<std::shared_ptr<TimeIntegrationRule>, TimeIntegrationMapping>>& getTimeIntegrationRules()
281  const;
282 
286  void printMap();
287 
293  std::vector<std::vector<size_t>> indexMap(const std::vector<std::string>& residual_names) const;
294 
299  std::vector<const BoundaryConditionManager*> getBoundaryConditionManagers() const;
300 
306  std::shared_ptr<DirichletBoundaryConditions> getBoundaryConditions(size_t unknown_index) const;
307 
313  size_t getFieldIndex(const std::string& field_name) const;
314 
320  size_t getUnknownIndex(const std::string& field_name) const;
321 
327  FieldState getField(const std::string& field_name) const;
328 
334  FieldState getParameter(const std::string& param_name) const;
335 
341  void setField(const std::string& field_name, FieldState updated_field);
342 
348  void setField(size_t index, FieldState updated_field);
349 
354  FieldState getShapeDisp() const;
355 
360  const std::vector<FieldState>& getAllFields() const;
361 
367  std::vector<FieldState> getStates(const std::string& weak_form_name) const;
368 
376  std::vector<FieldState> getStatesFromVectors(const std::string& weak_form_name,
377  const std::vector<FieldState>& state_fields,
378  const std::vector<FieldState>& param_fields) const;
379 
384  const std::shared_ptr<smith::Mesh>& getMesh() const;
385 
390  const std::shared_ptr<gretl::DataStore>& graph() const;
391 
392  private:
393  std::shared_ptr<Mesh> mesh_;
394  std::shared_ptr<gretl::DataStore> graph_;
395 
396  std::vector<FieldState> shape_disp_;
397  std::vector<FieldState> params_;
398  std::vector<FieldState> states_;
399 
400  std::map<std::string, size_t> to_states_index_;
401  std::map<std::string, size_t> to_params_index_;
402 
403  size_t num_unknowns_ = 0;
404  std::map<std::string, size_t> to_unknown_index_;
405  std::vector<std::shared_ptr<DirichletBoundaryConditions>> boundary_conditions_;
406 
407  struct FieldLabel {
408  std::string field_name;
409  size_t field_index_in_residual;
410  };
411 
412  std::shared_ptr<DirichletBoundaryConditions> addBoundaryConditions(FEFieldPtr field);
413 
414  std::map<std::string, std::vector<FieldLabel>> weak_form_name_to_unknown_name_index_;
415 
416  std::map<std::string, std::vector<size_t>> weak_form_name_to_field_indices_;
417  std::map<std::string, std::vector<std::string>> weak_form_name_to_field_names_;
418 
419  std::map<std::string, std::string> weak_form_to_test_field_;
420 
421  std::vector<std::pair<std::shared_ptr<TimeIntegrationRule>, TimeIntegrationMapping>> time_integration_rules_;
422  std::map<std::string, size_t> independent_name_to_rule_index_;
423 };
424 
431 template <int spatial_dim, typename TestSpaceType, typename... InputSpaceTypes>
432 auto createWeakForm(std::string name, FieldType<TestSpaceType> test_type, FieldStore& field_store,
433  FieldType<InputSpaceTypes>... field_types)
434 {
435  return std::make_shared<TimeDiscretizedWeakForm<spatial_dim, TestSpaceType, Parameters<InputSpaceTypes...>>>(
436  name, field_store.getMesh(), field_store.getField(test_type.name).get()->space(),
437  field_store.createSpaces(name, test_type.name, field_types...));
438 }
439 
440 } // namespace smith
Smith mesh class which assists in constructing the appropriate parallel mfem meshes and registering a...
Accelerator functionality.
Definition: smith.cpp:36
std::vector< const mfem::ParFiniteElementSpace * > spaces(const std::vector< FieldState > &states, const std::vector< FieldState > &params={})
Get the spaces from the primal fields of a vector of field states.
std::shared_ptr< FiniteElementState > FEFieldPtr
typedef
Definition: field_state.hpp:20
auto createWeakForm(std::string name, FieldType< TestSpaceType > test_type, FieldStore &field_store, FieldType< InputSpaceTypes >... field_types)
Create a TimeDiscretizedWeakForm and register its fields in the FieldStore.
gretl::State< FEFieldPtr, FEDualPtr > FieldState
typedef
Definition: field_state.hpp:22
Mapping between primary and history/derivative fields for time integration.
std::string history_name
Previous time step value field name.
std::string primary_name
Primary unknown field name.
std::string ddot_name
Second time derivative field name.
std::string dot_name
First time derivative field name.
Manages storage and metadata for fields, parameters, and weak forms.
Definition: field_store.hpp:44
size_t getUnknownIndex(const std::string &field_name) const
Get the unknown index of a field by name.
void printMap()
Print the internal field maps for debugging.
Definition: field_store.cpp:48
const std::vector< std::pair< std::shared_ptr< TimeIntegrationRule >, TimeIntegrationMapping > > & getTimeIntegrationRules() const
Get all registered time integration rules and their mappings.
void addParameter(FieldType< Space > type)
Add a parameter field to the store.
Definition: field_store.hpp:80
const std::vector< FieldState > & getAllFields() const
Get all fields stored in the FieldStore.
std::vector< std::vector< size_t > > indexMap(const std::vector< std::string > &residual_names) const
Generate an index map for the residuals.
Definition: field_store.cpp:59
std::vector< const BoundaryConditionManager * > getBoundaryConditionManagers() const
Get the boundary condition managers for all independent fields.
Definition: field_store.cpp:80
std::string getWeakFormReaction(const std::string &weak_form_name) const
Get the name of the reaction (test) field for a weak form.
std::shared_ptr< DirichletBoundaryConditions > addIndependent(FieldType< Space > &type, std::shared_ptr< TimeIntegrationRule > time_rule)
Add an independent field (a solver unknown) to the store.
std::shared_ptr< DirichletBoundaryConditions > getBoundaryConditions(size_t unknown_index) const
Get the Dirichlet boundary conditions for an independent field by its unknown index.
Definition: field_store.cpp:89
const std::shared_ptr< smith::Mesh > & getMesh() const
Get the associated mesh.
void setField(const std::string &field_name, FieldState updated_field)
Update a field in the store by name.
void addWeakFormArg(std::string weak_form_name, std::string argument_name, size_t argument_index)
Register an argument to a weak form.
Definition: field_store.cpp:36
FieldStore(std::shared_ptr< Mesh > mesh, size_t storage_size=50)
Construct a new FieldStore object.
Definition: field_store.cpp:14
TimeDerivative
Enum for different types of time derivatives.
Definition: field_store.hpp:56
@ DDDOT
The third time derivative.
@ DOT
The first time derivative.
@ DDOT
The second time derivative.
void addWeakFormReaction(std::string weak_form_name, std::string field_name)
Register the reaction (test) field for a weak form.
FieldState getParameter(const std::string &param_name) const
Get a parameter field by name.
size_t getFieldIndex(const std::string &field_name) const
Get the internal index of a field by name.
Definition: field_store.cpp:95
std::vector< FieldState > getStates(const std::string &weak_form_name) const
Get the state fields associated with a weak form.
void addShapeDisp(FieldType< Space > type)
Add a shape displacement field to the store.
Definition: field_store.hpp:69
FieldState getShapeDisp() const
Get the shape displacement field.
void addWeakFormUnknownArg(std::string weak_form_name, std::string argument_name, size_t argument_index)
Register an argument to a weak form as an unknown.
Definition: field_store.cpp:26
std::vector< const mfem::ParFiniteElementSpace * > createSpaces(const std::string &weak_form_name, const std::string &reaction_field_name, FieldTypes... types)
Register all input fields for a weak form and return their FE spaces.
auto addDependent(FieldType< Space > independent_field, TimeDerivative derivative, std::string name_override="")
Add a dependent field (history value, velocity, or acceleration) to the store.
std::vector< FieldState > getStatesFromVectors(const std::string &weak_form_name, const std::vector< FieldState > &state_fields, const std::vector< FieldState > &param_fields) const
Extract state fields for a weak form from provided state and parameter vectors.
size_t getNumUnknowns() const
Get the number of unknowns in the field store.
FieldState getField(const std::string &field_name) const
Get a FieldState by name.
const std::shared_ptr< gretl::DataStore > & graph() const
Get the associated data store graph.
Representation of a field type with a name and an optional unknown index.
Definition: field_store.hpp:30
std::string name
Name of the field.
Definition: field_store.hpp:37
FieldType(std::string n, int unknown_index_=-1)
Construct a new FieldType object.
Definition: field_store.hpp:36
int unknown_index
Index of the unknown in the solver.
Definition: field_store.hpp:38
a struct that is used in the physics modules to clarify which template arguments are user-controlled ...
Definition: common.hpp:45
Wraps FunctionalWeakForm to provide TimeInfo (time, dt, cycle) to integrands instead of just time.
Provides templated implementations for discretizing values, velocities and accelerations from current...