https://mooseframework.inl.gov
MFEMContainers.h
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #ifdef MOOSE_MFEM_ENABLED
11 
12 #pragma once
13 
14 #include "MooseError.h"
15 
16 #include <map>
17 #include <string>
18 #include <vector>
19 
20 namespace mfem
21 {
22 class FiniteElementCollection;
23 class ParFiniteElementSpace;
24 class ParSubMesh;
25 class ParGridFunction;
26 class ParComplexGridFunction;
27 class ParFiniteElementSpaceHierarchy;
28 }
29 
30 namespace Moose::MFEM
31 {
32 
34 template <typename T>
36 {
37 public:
38  using MapType = std::map<std::string, std::shared_ptr<T>>;
39  using const_iterator = typename MapType::const_iterator;
40 
42  NamedFieldsMap() = default;
43 
46 
48  template <class FieldType, class... FieldArgs>
49  void Register(const std::string & field_name, FieldArgs &&... args)
50  {
51  Register(field_name, std::make_shared<FieldType>(std::forward<FieldArgs>(args)...));
52  }
53 
55  void Register(const std::string & field_name, std::shared_ptr<T> field)
56  {
57  CheckFieldIsRegistrable(field_name, field.get());
58 
59  Deregister(field_name);
60 
61  _field_map[field_name] = std::move(field);
62  }
63 
65  void Deregister(const std::string & field_name) { _field_map.erase(field_name); }
66 
68  [[nodiscard]] inline bool Has(const std::string & field_name) const
69  {
70  return FindField(field_name) != end();
71  }
72 
74  [[nodiscard]] inline std::shared_ptr<T> GetShared(const std::string & field_name) const
75  {
76  CheckFieldIsRegistered(field_name);
77 
78  auto it = FindField(field_name);
79 
80  return EnsureFieldPointerIsNonNull(it);
81  }
82 
84  [[nodiscard]] inline T & GetRef(const std::string & field_name) const
85  {
86  return *GetShared(field_name);
87  }
88 
90  [[nodiscard]] inline T * Get(const std::string & field_name) const
91  {
92  return GetShared(field_name).get();
93  }
94 
96  template <typename TDerived>
97  [[nodiscard]] inline TDerived * Get(const std::string & field_name) const
98  {
99  auto ptr = Get(field_name);
100 
101  return EnsurePointerCastIsNonNull<TDerived>(ptr);
102  }
103 
105  [[nodiscard]] std::vector<T *> Get(const std::vector<std::string> & keys) const
106  {
107  std::vector<T *> values;
108 
109  for (const auto & key : keys)
110  {
111  values.push_back(Get(key));
112  }
113 
114  values.shrink_to_fit();
115  return values;
116  }
117 
119  // NOLINTNEXTLINE(readability-identifier-naming)
120  [[nodiscard]] inline const_iterator begin() const { return _field_map.begin(); }
121 
123  // NOLINTNEXTLINE(readability-identifier-naming)
124  [[nodiscard]] inline const_iterator end() const { return _field_map.end(); }
125 
127  int size() { return _field_map.size(); }
128 
129 protected:
131  [[nodiscard]] inline const_iterator FindField(const std::string & field_name) const
132  {
133  return _field_map.find(field_name);
134  }
135 
137  void CheckFieldIsRegistrable([[maybe_unused]] const std::string & field_name,
138  [[maybe_unused]] T * field) const
139  {
140  mooseAssert(field, "Cannot register NULL field with name '" + field_name + "'.");
141  mooseAssert(!Has(field_name) || Get(field_name) != field,
142  "The field '" + field_name + "' is already registered.");
143  }
144 
146  void CheckFieldIsRegistered(const std::string & field_name) const
147  {
148  if (!Has(field_name))
149  mooseError("The field '" + field_name + "' has not been registered.");
150  }
151 
153  inline std::shared_ptr<T> EnsureFieldPointerIsNonNull(const_iterator & iterator) const
154  {
155  auto owned_ptr = iterator->second;
156  mooseAssert(owned_ptr, "The field '" + iterator->first + "' is NULL.");
157  return owned_ptr;
158  }
159 
161  template <typename TDerived>
162  inline TDerived * EnsurePointerCastIsNonNull(T * ptr) const
163  {
164  auto derived_ptr = dynamic_cast<TDerived *>(ptr);
165  mooseAssert(derived_ptr, "The dynamic cast performed on the field pointer failed.");
166  return derived_ptr;
167  }
168 
170  void DeregisterAll() { _field_map.clear(); }
171 
172 private:
174 };
175 
179 {
180 public:
181  using MapType = std::map<std::string, std::string>;
182  using const_iterator = typename MapType::const_iterator;
183 
184  inline void addTimeDerivativeAssociation(const std::string & var_name,
185  const std::string & time_derivative_var_name)
186  {
187  _field_map.emplace(var_name, time_derivative_var_name);
188  }
189 
190  inline bool isTimeDerivative(const std::string & time_derivative_var_name) const
191  {
192  for (auto const & [map_var_name, map_time_derivative_var_name] : _field_map)
193  {
194  if (map_time_derivative_var_name == time_derivative_var_name)
195  return true;
196  }
197  return false;
198  }
199 
200  inline bool hasTimeDerivative(const std::string & var_name) const
201  {
202  return _field_map.count(var_name);
203  }
204 
205  inline const std::string & getTimeDerivativeName(const std::string & var_name) const
206  {
207  auto it = _field_map.find(var_name);
208  if (it != _field_map.end())
209  return it->second;
210  else
211  {
212  mooseError("No variable representing the time derivative of ", var_name, " found.");
213  return null_str;
214  }
215  }
216 
217  inline const std::string & getTimeIntegralName(const std::string & time_derivative_var_name) const
218  {
219  for (auto const & [map_var_name, map_time_derivative_var_name] : _field_map)
220  {
221  if (map_time_derivative_var_name == time_derivative_var_name)
222  return map_var_name;
223  }
224  mooseError(
225  "No variable representing the time integral of ", time_derivative_var_name, " found.");
226  return null_str;
227  }
228 
229  inline static std::string createTimeDerivativeName(std::string_view name)
230  {
231  return std::string("d") + std::string(name) + std::string("_dt");
232  }
233 
234 private:
236  const std::string null_str;
237 };
238 
245 
246 } // namespace Moose::MFEM
247 
248 #endif
std::string name(const ElemQuality q)
static std::string createTimeDerivativeName(std::string_view name)
std::map< std::string, std::string > MapType
void CheckFieldIsRegistrable([[maybe_unused]] const std::string &field_name, [[maybe_unused]] T *field) const
Check that the field pointer is valid and the field has not already been registered.
bool Has(const std::string &field_name) const
Predicate to check if a field is registered with name field_name.
bool isTimeDerivative(const std::string &time_derivative_var_name) const
typename MapType::const_iterator const_iterator
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
bool hasTimeDerivative(const std::string &var_name) const
void CheckFieldIsRegistered(const std::string &field_name) const
Check that a field exists in the map.
const_iterator FindField(const std::string &field_name) const
Returns a const iterator to the field.
std::shared_ptr< T > EnsureFieldPointerIsNonNull(const_iterator &iterator) const
Ensure that a returned shared pointer is valid.
Lightweight adaptor over a std::map relating names of GridFunctions with the name of their time deriv...
const std::string & getTimeIntegralName(const std::string &time_derivative_var_name) const
Lightweight adaptor over an std::map from strings to pointer to T.
typename MapType::const_iterator const_iterator
const_iterator end() const
Returns an end const iterator to the registered fields.
std::map< std::string, std::shared_ptr< mfem::ParNonlinearForm > > MapType
TDerived * EnsurePointerCastIsNonNull(T *ptr) const
Ensure that a dynamic cast is successful.
void addTimeDerivativeAssociation(const std::string &var_name, const std::string &time_derivative_var_name)
T * Get(const std::string &field_name) const
Returns a non-owning pointer to the field. This is guaranteed to return a non-null pointer...
const_iterator begin() const
Returns a begin const iterator to the registered fields.
std::shared_ptr< T > GetShared(const std::string &field_name) const
Returns a shared pointer to the field. This is guaranteed to return a non-null shared pointer...
NamedFieldsMap()=default
Default initializer.
void Register(const std::string &field_name, std::shared_ptr< T > field)
Register association between field and field_name.
TDerived * Get(const std::string &field_name) const
Returns a non-owning pointer to the field where TDerived is a derived class of class T...
void Deregister(const std::string &field_name)
Unregister association between a field and the field_name.
void Register(const std::string &field_name, FieldArgs &&... args)
Construct new field with name field_name and register.
int size()
Returns the number of elements in the map.
Utilities for converting between vector(s) of libMesh Points and MFEM Vector(s).
T & GetRef(const std::string &field_name) const
Returns a reference to a field.
void DeregisterAll()
Clear all associations between names and fields.
std::vector< T * > Get(const std::vector< std::string > &keys) const
Returns a vector containing all values for supplied keys.
const std::string & getTimeDerivativeName(const std::string &var_name) const