Line data Source code
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 : 25 : /// Lightweight adaptor over an std::map from strings to pointer to T 26 : template <typename T> 27 : class NamedFieldsMap 28 : { 29 : public: 30 : using MapType = std::map<std::string, std::shared_ptr<T>>; 31 : using const_iterator = typename MapType::const_iterator; 32 : 33 : /// Default initializer. 34 7864 : NamedFieldsMap() = default; 35 : 36 : /// Destructor. 37 7864 : ~NamedFieldsMap() { DeregisterAll(); } 38 : 39 : /// Construct new field with name field_name and register. 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 : 46 : /// Register association between field and field_name. 47 8391 : void Register(const std::string & field_name, std::shared_ptr<T> field) 48 : { 49 8391 : CheckFieldIsRegistrable(field_name, field.get()); 50 : 51 8391 : Deregister(field_name); 52 : 53 8391 : _field_map[field_name] = std::move(field); 54 8391 : } 55 : 56 : /// Unregister association between a field and the field_name. 57 8391 : void Deregister(const std::string & field_name) { _field_map.erase(field_name); } 58 : 59 : /// Predicate to check if a field is registered with name field_name. 60 68550 : [[nodiscard]] inline bool Has(const std::string & field_name) const 61 : { 62 68550 : return FindField(field_name) != end(); 63 : } 64 : 65 : /// Returns a shared pointer to the field. This is guaranteed to return a non-null shared pointer. 66 37282 : [[nodiscard]] inline std::shared_ptr<T> GetShared(const std::string & field_name) const 67 : { 68 37282 : CheckFieldIsRegistered(field_name); 69 : 70 37282 : auto it = FindField(field_name); 71 : 72 74564 : return EnsureFieldPointerIsNonNull(it); 73 : } 74 : 75 : /// Returns a reference to a field. 76 10433 : [[nodiscard]] inline T & GetRef(const std::string & field_name) const 77 : { 78 10433 : return *GetShared(field_name); 79 : } 80 : 81 : /// Returns a non-owning pointer to the field. This is guaranteed to return a non-null pointer. 82 23132 : [[nodiscard]] inline T * Get(const std::string & field_name) const 83 : { 84 23132 : return GetShared(field_name).get(); 85 : } 86 : 87 : /// Returns a non-owning pointer to the field where TDerived is a derived class of class T. 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 : 96 : /// Returns a vector containing all values for supplied keys. 97 706 : [[nodiscard]] std::vector<T *> Get(const std::vector<std::string> & keys) const 98 : { 99 706 : std::vector<T *> values; 100 : 101 1340 : for (const auto & key : keys) 102 : { 103 634 : values.push_back(Get(key)); 104 : } 105 : 106 706 : values.shrink_to_fit(); 107 706 : return values; 108 0 : } 109 : 110 : /// Returns a begin const iterator to the registered fields. 111 : // NOLINTNEXTLINE(readability-identifier-naming) 112 363 : [[nodiscard]] inline const_iterator begin() const { return _field_map.begin(); } 113 : 114 : /// Returns an end const iterator to the registered fields. 115 : // NOLINTNEXTLINE(readability-identifier-naming) 116 68913 : [[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: 122 : /// Returns a const iterator to the field. 123 105832 : [[nodiscard]] inline const_iterator FindField(const std::string & field_name) const 124 : { 125 105832 : return _field_map.find(field_name); 126 : } 127 : 128 : /// Check that the field pointer is valid and the field has not already been registered. 129 8391 : void CheckFieldIsRegistrable(const std::string & field_name, T * field) const 130 : { 131 8391 : if (!field) 132 : { 133 0 : MFEM_ABORT("Cannot register NULL field with name '" << field_name << "'."); 134 : } 135 : 136 8391 : CheckForDoubleRegistration(field_name, field); 137 8391 : } 138 : 139 : /// Check for double-registration of a field. A double-registered field may 140 : /// result in undefined behavior. 141 8391 : void CheckForDoubleRegistration(const std::string & field_name, T * field) const 142 : { 143 8391 : if (Has(field_name) && Get(field_name) == field) 144 : { 145 0 : MFEM_ABORT("The field '" << field_name << "' is already registered."); 146 : } 147 8391 : } 148 : 149 : /// Check that a field exists in the map. 150 37282 : void CheckFieldIsRegistered(const std::string & field_name) const 151 : { 152 37282 : if (!Has(field_name)) 153 : { 154 0 : MFEM_ABORT("The field '" << field_name << "' has not been registered."); 155 : } 156 37282 : } 157 : 158 : /// Ensure that a returned shared pointer is valid. 159 37282 : inline std::shared_ptr<T> EnsureFieldPointerIsNonNull(const_iterator & iterator) const 160 : { 161 37282 : auto owned_ptr = iterator->second; 162 : 163 37282 : if (!owned_ptr) 164 : { 165 0 : MFEM_ABORT("The field '" << iterator->first << "' is NULL."); 166 : } 167 : 168 37282 : return owned_ptr; 169 0 : } 170 : 171 : /// Ensure that a dynamic cast is successful. 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 : 185 : /// Clear all associations between names and fields. 186 7864 : void DeregisterAll() { _field_map.clear(); } 187 : 188 : private: 189 : MapType _field_map{}; 190 : }; 191 : 192 : /// Lightweight adaptor over a std::map relating names of GridFunctions with the name of their time 193 : /// derivatives 194 : class TimeDerivativeMap 195 : { 196 : public: 197 : using MapType = std::map<std::string, std::string>; 198 : using const_iterator = typename MapType::const_iterator; 199 : 200 128 : inline void addTimeDerivativeAssociation(const std::string & var_name, 201 : const std::string & time_derivative_var_name) 202 : { 203 128 : _field_map.emplace(var_name, time_derivative_var_name); 204 128 : } 205 : 206 235 : inline bool isTimeDerivative(const std::string & time_derivative_var_name) const 207 : { 208 371 : for (auto const & [map_var_name, map_time_derivative_var_name] : _field_map) 209 : { 210 254 : if (map_time_derivative_var_name == time_derivative_var_name) 211 118 : return true; 212 : } 213 117 : 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 2716 : inline const std::string & getTimeDerivativeName(const std::string & var_name) const 222 : { 223 2716 : auto it = _field_map.find(var_name); 224 2716 : if (it != _field_map.end()) 225 2716 : return it->second; 226 : else 227 : { 228 0 : mooseError("No variable representing the time derivative of ", var_name, " found."); 229 : return null_str; 230 : } 231 : } 232 : 233 818 : inline const std::string & getTimeIntegralName(const std::string & time_derivative_var_name) const 234 : { 235 850 : for (auto const & [map_var_name, map_time_derivative_var_name] : _field_map) 236 : { 237 850 : if (map_time_derivative_var_name == time_derivative_var_name) 238 818 : return map_var_name; 239 : } 240 0 : mooseError( 241 : "No variable representing the time integral of ", time_derivative_var_name, " found."); 242 : return null_str; 243 : } 244 : 245 871 : inline static std::string createTimeDerivativeName(std::string_view name) 246 : { 247 5226 : return std::string("d") + std::string(name) + std::string("_dt"); 248 : } 249 : 250 : private: 251 : MapType _field_map; 252 : const std::string null_str; 253 : }; 254 : 255 : using FECollections = Moose::MFEM::NamedFieldsMap<mfem::FiniteElementCollection>; 256 : using FESpaces = Moose::MFEM::NamedFieldsMap<mfem::ParFiniteElementSpace>; 257 : using GridFunctions = Moose::MFEM::NamedFieldsMap<mfem::ParGridFunction>; 258 : using SubMeshes = Moose::MFEM::NamedFieldsMap<mfem::ParSubMesh>; 259 : 260 : } // namespace Moose::MFEM 261 : 262 : #endif