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 "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 : 33 : /// Lightweight adaptor over an std::map from strings to pointer to T 34 : template <typename T> 35 : class NamedFieldsMap 36 : { 37 : public: 38 : using MapType = std::map<std::string, std::shared_ptr<T>>; 39 : using const_iterator = typename MapType::const_iterator; 40 : 41 : /// Default initializer. 42 31466 : NamedFieldsMap() = default; 43 : 44 : /// Destructor. 45 31278 : ~NamedFieldsMap() { DeregisterAll(); } 46 : 47 : /// Construct new field with name field_name and register. 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 : 54 : /// Register association between field and field_name. 55 27510 : void Register(const std::string & field_name, std::shared_ptr<T> field) 56 : { 57 27510 : CheckFieldIsRegistrable(field_name, field.get()); 58 : 59 27510 : Deregister(field_name); 60 : 61 27510 : _field_map[field_name] = std::move(field); 62 27510 : } 63 : 64 : /// Unregister association between a field and the field_name. 65 27510 : void Deregister(const std::string & field_name) { _field_map.erase(field_name); } 66 : 67 : /// Predicate to check if a field is registered with name field_name. 68 149048 : [[nodiscard]] inline bool Has(const std::string & field_name) const 69 : { 70 149048 : return FindField(field_name) != end(); 71 : } 72 : 73 : /// Returns a shared pointer to the field. This is guaranteed to return a non-null shared pointer. 74 95967 : [[nodiscard]] inline std::shared_ptr<T> GetShared(const std::string & field_name) const 75 : { 76 95967 : CheckFieldIsRegistered(field_name); 77 : 78 95967 : auto it = FindField(field_name); 79 : 80 191934 : return EnsureFieldPointerIsNonNull(it); 81 : } 82 : 83 : /// Returns a reference to a field. 84 37649 : [[nodiscard]] inline T & GetRef(const std::string & field_name) const 85 : { 86 37649 : return *GetShared(field_name); 87 : } 88 : 89 : /// Returns a non-owning pointer to the field. This is guaranteed to return a non-null pointer. 90 41213 : [[nodiscard]] inline T * Get(const std::string & field_name) const 91 : { 92 41213 : return GetShared(field_name).get(); 93 : } 94 : 95 : /// Returns a non-owning pointer to the field where TDerived is a derived class of class T. 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 : 104 : /// Returns a vector containing all values for supplied keys. 105 3204 : [[nodiscard]] std::vector<T *> Get(const std::vector<std::string> & keys) const 106 : { 107 3204 : std::vector<T *> values; 108 : 109 5434 : for (const auto & key : keys) 110 : { 111 2230 : values.push_back(Get(key)); 112 : } 113 : 114 3204 : values.shrink_to_fit(); 115 3204 : return values; 116 0 : } 117 : 118 : /// Returns a begin const iterator to the registered fields. 119 : // NOLINTNEXTLINE(readability-identifier-naming) 120 3970 : [[nodiscard]] inline const_iterator begin() const { return _field_map.begin(); } 121 : 122 : /// Returns an end const iterator to the registered fields. 123 : // NOLINTNEXTLINE(readability-identifier-naming) 124 153018 : [[nodiscard]] inline const_iterator end() const { return _field_map.end(); } 125 : 126 : /// Returns the number of elements in the map 127 1586 : int size() { return _field_map.size(); } 128 : 129 : protected: 130 : /// Returns a const iterator to the field. 131 245015 : [[nodiscard]] inline const_iterator FindField(const std::string & field_name) const 132 : { 133 245015 : return _field_map.find(field_name); 134 : } 135 : 136 : /// Check that the field pointer is valid and the field has not already been registered. 137 27510 : 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 27510 : } 144 : 145 : /// Check that a field exists in the map. 146 95967 : void CheckFieldIsRegistered(const std::string & field_name) const 147 : { 148 95967 : if (!Has(field_name)) 149 0 : mooseError("The field '" + field_name + "' has not been registered."); 150 95967 : } 151 : 152 : /// Ensure that a returned shared pointer is valid. 153 95967 : inline std::shared_ptr<T> EnsureFieldPointerIsNonNull(const_iterator & iterator) const 154 : { 155 95967 : auto owned_ptr = iterator->second; 156 : mooseAssert(owned_ptr, "The field '" + iterator->first + "' is NULL."); 157 95967 : return owned_ptr; 158 : } 159 : 160 : /// Ensure that a dynamic cast is successful. 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 : 169 : /// Clear all associations between names and fields. 170 31278 : void DeregisterAll() { _field_map.clear(); } 171 : 172 : private: 173 : MapType _field_map{}; 174 : }; 175 : 176 : /// Lightweight adaptor over a std::map relating names of GridFunctions with the name of their time 177 : /// derivatives 178 : class TimeDerivativeMap 179 : { 180 : public: 181 : using MapType = std::map<std::string, std::string>; 182 : using const_iterator = typename MapType::const_iterator; 183 : 184 225 : inline void addTimeDerivativeAssociation(const std::string & var_name, 185 : const std::string & time_derivative_var_name) 186 : { 187 225 : _field_map.emplace(var_name, time_derivative_var_name); 188 225 : } 189 : 190 378 : inline bool isTimeDerivative(const std::string & time_derivative_var_name) const 191 : { 192 591 : for (auto const & [map_var_name, map_time_derivative_var_name] : _field_map) 193 : { 194 396 : if (map_time_derivative_var_name == time_derivative_var_name) 195 183 : return true; 196 : } 197 195 : 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 3461 : inline const std::string & getTimeDerivativeName(const std::string & var_name) const 206 : { 207 3461 : auto it = _field_map.find(var_name); 208 3461 : if (it != _field_map.end()) 209 3461 : return it->second; 210 : else 211 : { 212 0 : mooseError("No variable representing the time derivative of ", var_name, " found."); 213 : return null_str; 214 : } 215 : } 216 : 217 183 : inline const std::string & getTimeIntegralName(const std::string & time_derivative_var_name) const 218 : { 219 195 : for (auto const & [map_var_name, map_time_derivative_var_name] : _field_map) 220 : { 221 195 : if (map_time_derivative_var_name == time_derivative_var_name) 222 183 : return map_var_name; 223 : } 224 0 : mooseError( 225 : "No variable representing the time integral of ", time_derivative_var_name, " found."); 226 : return null_str; 227 : } 228 : 229 3794 : inline static std::string createTimeDerivativeName(std::string_view name) 230 : { 231 22764 : return std::string("d") + std::string(name) + std::string("_dt"); 232 : } 233 : 234 : private: 235 : MapType _field_map; 236 : const std::string null_str; 237 : }; 238 : 239 : using FECollections = NamedFieldsMap<mfem::FiniteElementCollection>; 240 : using FESpaces = NamedFieldsMap<mfem::ParFiniteElementSpace>; 241 : using SubMeshes = NamedFieldsMap<mfem::ParSubMesh>; 242 : using GridFunctions = NamedFieldsMap<mfem::ParGridFunction>; 243 : using ComplexGridFunctions = NamedFieldsMap<mfem::ParComplexGridFunction>; 244 : using FESpaceHierarchies = NamedFieldsMap<mfem::ParFiniteElementSpaceHierarchy>; 245 : 246 : } // namespace Moose::MFEM 247 : 248 : #endif