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 : 14 : #include <map> 15 : #include <set> 16 : #include <string> 17 : #include <vector> 18 : 19 : namespace Moose::MFEM 20 : { 21 : 22 : /// Lightweight adaptor over an std::map from strings to pointer to T 23 : template <typename T> 24 : class NamedFieldsMap 25 : { 26 : public: 27 : using MapType = std::map<std::string, std::shared_ptr<T>>; 28 : using const_iterator = typename MapType::const_iterator; 29 : 30 : /// Default initializer. 31 24797 : NamedFieldsMap() = default; 32 : 33 : /// Destructor. 34 24797 : ~NamedFieldsMap() { DeregisterAll(); } 35 : 36 : /// Construct new field with name field_name and register. 37 : template <class FieldType, class... FieldArgs> 38 : void Register(const std::string & field_name, FieldArgs &&... args) 39 : { 40 : Register(field_name, std::make_shared<FieldType>(std::forward<FieldArgs>(args)...)); 41 : } 42 : 43 : /// Register association between field and field_name. 44 21626 : void Register(const std::string & field_name, std::shared_ptr<T> field) 45 : { 46 21626 : CheckFieldIsRegistrable(field_name, field.get()); 47 : 48 21626 : Deregister(field_name); 49 : 50 21626 : _field_map[field_name] = std::move(field); 51 21626 : } 52 : 53 : /// Unregister association between a field and the field_name. 54 21626 : void Deregister(const std::string & field_name) { _field_map.erase(field_name); } 55 : 56 : /// Predicate to check if a field is registered with name field_name. 57 126469 : [[nodiscard]] inline bool Has(const std::string & field_name) const 58 : { 59 126469 : return FindField(field_name) != end(); 60 : } 61 : 62 : /// Returns a shared pointer to the field. This is guaranteed to return a non-null shared pointer. 63 84878 : [[nodiscard]] inline std::shared_ptr<T> GetShared(const std::string & field_name) const 64 : { 65 84878 : CheckFieldIsRegistered(field_name); 66 : 67 84878 : auto it = FindField(field_name); 68 : 69 169756 : return EnsureFieldPointerIsNonNull(it); 70 : } 71 : 72 : /// Returns a reference to a field. 73 28963 : [[nodiscard]] inline T & GetRef(const std::string & field_name) const 74 : { 75 28963 : return *GetShared(field_name); 76 : } 77 : 78 : /// Returns a non-owning pointer to the field. This is guaranteed to return a non-null pointer. 79 41274 : [[nodiscard]] inline T * Get(const std::string & field_name) const 80 : { 81 41274 : return GetShared(field_name).get(); 82 : } 83 : 84 : /// Returns a non-owning pointer to the field where TDerived is a derived class of class T. 85 : template <typename TDerived> 86 : [[nodiscard]] inline TDerived * Get(const std::string & field_name) const 87 : { 88 : auto ptr = Get(field_name); 89 : 90 : return EnsurePointerCastIsNonNull<TDerived>(ptr); 91 : } 92 : 93 : /// Returns a vector containing all values for supplied keys. 94 2774 : [[nodiscard]] std::vector<T *> Get(const std::vector<std::string> & keys) const 95 : { 96 2774 : std::vector<T *> values; 97 : 98 4700 : for (const auto & key : keys) 99 : { 100 1926 : values.push_back(Get(key)); 101 : } 102 : 103 2774 : values.shrink_to_fit(); 104 2774 : return values; 105 0 : } 106 : 107 : /// Returns a begin const iterator to the registered fields. 108 : // NOLINTNEXTLINE(readability-identifier-naming) 109 1325 : [[nodiscard]] inline const_iterator begin() const { return _field_map.begin(); } 110 : 111 : /// Returns an end const iterator to the registered fields. 112 : // NOLINTNEXTLINE(readability-identifier-naming) 113 127794 : [[nodiscard]] inline const_iterator end() const { return _field_map.end(); } 114 : 115 : /// Returns the number of elements in the map 116 1361 : int size() { return _field_map.size(); } 117 : 118 : protected: 119 : /// Returns a const iterator to the field. 120 211347 : [[nodiscard]] inline const_iterator FindField(const std::string & field_name) const 121 : { 122 211347 : return _field_map.find(field_name); 123 : } 124 : 125 : /// Check that the field pointer is valid and the field has not already been registered. 126 21626 : void CheckFieldIsRegistrable([[maybe_unused]] const std::string & field_name, 127 : [[maybe_unused]] T * field) const 128 : { 129 : mooseAssert(field, "Cannot register NULL field with name '" + field_name + "'."); 130 : mooseAssert(!Has(field_name) || Get(field_name) != field, 131 : "The field '" + field_name + "' is already registered."); 132 21626 : } 133 : 134 : /// Check that a field exists in the map. 135 84878 : void CheckFieldIsRegistered(const std::string & field_name) const 136 : { 137 84878 : if (!Has(field_name)) 138 0 : mooseError("The field '" + field_name + "' has not been registered."); 139 84878 : } 140 : 141 : /// Ensure that a returned shared pointer is valid. 142 84878 : inline std::shared_ptr<T> EnsureFieldPointerIsNonNull(const_iterator & iterator) const 143 : { 144 84878 : auto owned_ptr = iterator->second; 145 : mooseAssert(owned_ptr, "The field '" + iterator->first + "' is NULL."); 146 84878 : return owned_ptr; 147 : } 148 : 149 : /// Ensure that a dynamic cast is successful. 150 : template <typename TDerived> 151 : inline TDerived * EnsurePointerCastIsNonNull(T * ptr) const 152 : { 153 : auto derived_ptr = dynamic_cast<TDerived *>(ptr); 154 : mooseAssert(derived_ptr, "The dynamic cast performed on the field pointer failed."); 155 : return derived_ptr; 156 : } 157 : 158 : /// Clear all associations between names and fields. 159 24797 : void DeregisterAll() { _field_map.clear(); } 160 : 161 : private: 162 : MapType _field_map{}; 163 : }; 164 : 165 : /// Lightweight adaptor over a std::map relating names of GridFunctions with the name of their time 166 : /// derivatives 167 : class TimeDerivativeMap 168 : { 169 : public: 170 : using MapType = std::map<std::string, std::string>; 171 : using const_iterator = typename MapType::const_iterator; 172 : 173 151 : inline void addTimeDerivativeAssociation(const std::string & var_name, 174 : const std::string & time_derivative_var_name) 175 : { 176 151 : _field_map.emplace(var_name, time_derivative_var_name); 177 151 : } 178 : 179 290 : inline bool isTimeDerivative(const std::string & time_derivative_var_name) const 180 : { 181 459 : for (auto const & [map_var_name, map_time_derivative_var_name] : _field_map) 182 : { 183 314 : if (map_time_derivative_var_name == time_derivative_var_name) 184 145 : return true; 185 : } 186 145 : return false; 187 : } 188 : 189 : inline bool hasTimeDerivative(const std::string & var_name) const 190 : { 191 : return _field_map.count(var_name); 192 : } 193 : 194 2271 : inline const std::string & getTimeDerivativeName(const std::string & var_name) const 195 : { 196 2271 : auto it = _field_map.find(var_name); 197 2271 : if (it != _field_map.end()) 198 2271 : return it->second; 199 : else 200 : { 201 0 : mooseError("No variable representing the time derivative of ", var_name, " found."); 202 : return null_str; 203 : } 204 : } 205 : 206 145 : inline const std::string & getTimeIntegralName(const std::string & time_derivative_var_name) const 207 : { 208 157 : for (auto const & [map_var_name, map_time_derivative_var_name] : _field_map) 209 : { 210 157 : if (map_time_derivative_var_name == time_derivative_var_name) 211 145 : return map_var_name; 212 : } 213 0 : mooseError( 214 : "No variable representing the time integral of ", time_derivative_var_name, " found."); 215 : return null_str; 216 : } 217 : 218 3340 : inline static std::string createTimeDerivativeName(std::string_view name) 219 : { 220 20040 : return std::string("d") + std::string(name) + std::string("_dt"); 221 : } 222 : 223 : private: 224 : MapType _field_map; 225 : const std::string null_str; 226 : }; 227 : 228 : using FECollections = Moose::MFEM::NamedFieldsMap<mfem::FiniteElementCollection>; 229 : using FESpaces = Moose::MFEM::NamedFieldsMap<mfem::ParFiniteElementSpace>; 230 : using SubMeshes = Moose::MFEM::NamedFieldsMap<mfem::ParSubMesh>; 231 : using GridFunctions = Moose::MFEM::NamedFieldsMap<mfem::ParGridFunction>; 232 : using ComplexGridFunctions = Moose::MFEM::NamedFieldsMap<mfem::ParComplexGridFunction>; 233 : 234 : } // namespace Moose::MFEM 235 : 236 : #endif