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 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 
118  // Returns the number of elements in the map
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 
192 inline std::string
193 GetTimeDerivativeName(std::string name)
194 {
195  return std::string("d") + name + std::string("_dt");
196 }
197 
202 
203 } // namespace Moose::MFEM
204 
205 #endif
std::string name(const ElemQuality q)
bool Has(const std::string &field_name) const
Predicate to check if a field is registered with name field_name.
typename MapType::const_iterator const_iterator
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 an std::map from strings to pointer to T.
const_iterator end() const
Returns an end const iterator to the registered fields.
std::string GetTimeDerivativeName(std::string name)
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.
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.
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.