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 #include <map>
14 #include <set>
15 #include <string>
16 #include <memory>
17 #include <vector>
18 #include "libmesh/ignore_warnings.h"
19 #include <mfem.hpp>
20 #include "libmesh/restore_warnings.h"
21 
22 namespace Moose::MFEM
23 {
24 
26 template <typename T>
28 {
29 public:
30  using MapType = std::map<std::string, std::shared_ptr<T>>;
31  using const_iterator = typename MapType::const_iterator;
32 
34  NamedFieldsMap() = default;
35 
38 
40  template <class FieldType, class... FieldArgs>
41  void Register(const std::string & field_name, FieldArgs &&... args)
42  {
43  Register(field_name, std::make_shared<FieldType>(std::forward<FieldArgs>(args)...));
44  }
45 
47  void Register(const std::string & field_name, std::shared_ptr<T> field)
48  {
49  CheckFieldIsRegistrable(field_name, field.get());
50 
51  Deregister(field_name);
52 
53  _field_map[field_name] = std::move(field);
54  }
55 
57  void Deregister(const std::string & field_name) { _field_map.erase(field_name); }
58 
60  [[nodiscard]] inline bool Has(const std::string & field_name) const
61  {
62  return FindField(field_name) != end();
63  }
64 
66  [[nodiscard]] inline std::shared_ptr<T> GetShared(const std::string & field_name) const
67  {
68  CheckFieldIsRegistered(field_name);
69 
70  auto it = FindField(field_name);
71 
72  return EnsureFieldPointerIsNonNull(it);
73  }
74 
76  [[nodiscard]] inline T & GetRef(const std::string & field_name) const
77  {
78  return *GetShared(field_name);
79  }
80 
82  [[nodiscard]] inline T * Get(const std::string & field_name) const
83  {
84  return GetShared(field_name).get();
85  }
86 
88  template <typename TDerived>
89  [[nodiscard]] inline TDerived * Get(const std::string & field_name) const
90  {
91  auto ptr = Get(field_name);
92 
93  return EnsurePointerCastIsNonNull<TDerived>(ptr);
94  }
95 
97  [[nodiscard]] std::vector<T *> Get(const std::vector<std::string> & keys) const
98  {
99  std::vector<T *> values;
100 
101  for (const auto & key : keys)
102  {
103  values.push_back(Get(key));
104  }
105 
106  values.shrink_to_fit();
107  return values;
108  }
109 
111  // NOLINTNEXTLINE(readability-identifier-naming)
112  [[nodiscard]] inline const_iterator begin() const { return _field_map.begin(); }
113 
115  // NOLINTNEXTLINE(readability-identifier-naming)
116  [[nodiscard]] inline const_iterator end() const { return _field_map.end(); }
117 
119  int size() { return _field_map.size(); }
120 
121 protected:
123  [[nodiscard]] inline const_iterator FindField(const std::string & field_name) const
124  {
125  return _field_map.find(field_name);
126  }
127 
129  void CheckFieldIsRegistrable(const std::string & field_name, T * field) const
130  {
131  if (!field)
132  {
133  MFEM_ABORT("Cannot register NULL field with name '" << field_name << "'.");
134  }
135 
136  CheckForDoubleRegistration(field_name, field);
137  }
138 
141  void CheckForDoubleRegistration(const std::string & field_name, T * field) const
142  {
143  if (Has(field_name) && Get(field_name) == field)
144  {
145  MFEM_ABORT("The field '" << field_name << "' is already registered.");
146  }
147  }
148 
150  void CheckFieldIsRegistered(const std::string & field_name) const
151  {
152  if (!Has(field_name))
153  {
154  MFEM_ABORT("The field '" << field_name << "' has not been registered.");
155  }
156  }
157 
159  inline std::shared_ptr<T> EnsureFieldPointerIsNonNull(const_iterator & iterator) const
160  {
161  auto owned_ptr = iterator->second;
162 
163  if (!owned_ptr)
164  {
165  MFEM_ABORT("The field '" << iterator->first << "' is NULL.");
166  }
167 
168  return owned_ptr;
169  }
170 
172  template <typename TDerived>
173  inline TDerived * EnsurePointerCastIsNonNull(T * ptr) const
174  {
175  auto derived_ptr = dynamic_cast<TDerived *>(ptr);
176 
177  if (!derived_ptr)
178  {
179  MFEM_ABORT("The dynamic cast performed on the field pointer failed.");
180  }
181 
182  return derived_ptr;
183  }
184 
186  void DeregisterAll() { _field_map.clear(); }
187 
188 private:
190 };
191 
195 {
196 public:
197  using MapType = std::map<std::string, std::string>;
198  using const_iterator = typename MapType::const_iterator;
199 
200  inline void addTimeDerivativeAssociation(const std::string & var_name,
201  const std::string & time_derivative_var_name)
202  {
203  _field_map.emplace(var_name, time_derivative_var_name);
204  }
205 
206  inline bool isTimeDerivative(const std::string & time_derivative_var_name) const
207  {
208  for (auto const & [map_var_name, map_time_derivative_var_name] : _field_map)
209  {
210  if (map_time_derivative_var_name == time_derivative_var_name)
211  return true;
212  }
213  return false;
214  }
215 
216  inline bool hasTimeDerivative(const std::string & var_name) const
217  {
218  return _field_map.count(var_name);
219  }
220 
221  inline const std::string & getTimeDerivativeName(const std::string & var_name) const
222  {
223  auto it = _field_map.find(var_name);
224  if (it != _field_map.end())
225  return it->second;
226  else
227  {
228  mooseError("No variable representing the time derivative of ", var_name, " found.");
229  return null_str;
230  }
231  }
232 
233  inline const std::string & getTimeIntegralName(const std::string & time_derivative_var_name) const
234  {
235  for (auto const & [map_var_name, map_time_derivative_var_name] : _field_map)
236  {
237  if (map_time_derivative_var_name == time_derivative_var_name)
238  return map_var_name;
239  }
240  mooseError(
241  "No variable representing the time integral of ", time_derivative_var_name, " found.");
242  return null_str;
243  }
244 
245  inline static std::string createTimeDerivativeName(std::string_view name)
246  {
247  return std::string("d") + std::string(name) + std::string("_dt");
248  }
249 
250 private:
252  const std::string null_str;
253 };
254 
259 
260 } // namespace Moose::MFEM
261 
262 #endif
std::string name(const ElemQuality q)
static std::string createTimeDerivativeName(std::string_view name)
std::map< std::string, std::string > MapType
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:323
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.
void CheckForDoubleRegistration(const std::string &field_name, T *field) const
Check for double-registration of a field.
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...
void CheckFieldIsRegistrable(const std::string &field_name, T *field) const
Check that the field pointer is valid and the field has not already been registered.
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.
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