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 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 2476 : NamedFieldsMap() = default; 35 : 36 : /// Destructor. 37 2476 : ~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 1762 : void Register(const std::string & field_name, std::shared_ptr<T> field) 48 : { 49 1762 : CheckFieldIsRegistrable(field_name, field.get()); 50 : 51 1762 : Deregister(field_name); 52 : 53 1762 : _field_map[field_name] = std::move(field); 54 1762 : } 55 : 56 : /// Unregister association between a field and the field_name. 57 1762 : 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 9281 : [[nodiscard]] inline bool Has(const std::string & field_name) const 61 : { 62 9281 : 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 5103 : [[nodiscard]] inline std::shared_ptr<T> GetShared(const std::string & field_name) const 67 : { 68 5103 : CheckFieldIsRegistered(field_name); 69 : 70 5103 : auto it = FindField(field_name); 71 : 72 10206 : return EnsureFieldPointerIsNonNull(it); 73 : } 74 : 75 : /// Returns a reference to a field. 76 1895 : [[nodiscard]] inline T & GetRef(const std::string & field_name) const 77 : { 78 1895 : 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 2674 : [[nodiscard]] inline T * Get(const std::string & field_name) const 83 : { 84 2674 : 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 292 : [[nodiscard]] std::vector<T *> Get(const std::vector<std::string> & keys) const 98 : { 99 292 : std::vector<T *> values; 100 : 101 442 : for (const auto & key : keys) 102 : { 103 150 : values.push_back(Get(key)); 104 : } 105 : 106 292 : values.shrink_to_fit(); 107 292 : return values; 108 0 : } 109 : 110 : /// Returns a begin const iterator to the registered fields. 111 : // NOLINTNEXTLINE(readability-identifier-naming) 112 140 : [[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 9421 : [[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 14384 : [[nodiscard]] inline const_iterator FindField(const std::string & field_name) const 124 : { 125 14384 : 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 1762 : void CheckFieldIsRegistrable(const std::string & field_name, T * field) const 130 : { 131 1762 : if (!field) 132 : { 133 0 : MFEM_ABORT("Cannot register NULL field with name '" << field_name << "'."); 134 : } 135 : 136 1762 : CheckForDoubleRegistration(field_name, field); 137 1762 : } 138 : 139 : /// Check for double-registration of a field. A double-registered field may 140 : /// result in undefined behavior. 141 1762 : void CheckForDoubleRegistration(const std::string & field_name, T * field) const 142 : { 143 1762 : if (Has(field_name) && Get(field_name) == field) 144 : { 145 0 : MFEM_ABORT("The field '" << field_name << "' is already registered."); 146 : } 147 1762 : } 148 : 149 : /// Check that a field exists in the map. 150 5103 : void CheckFieldIsRegistered(const std::string & field_name) const 151 : { 152 5103 : if (!Has(field_name)) 153 : { 154 0 : MFEM_ABORT("The field '" << field_name << "' has not been registered."); 155 : } 156 5103 : } 157 : 158 : /// Ensure that a returned shared pointer is valid. 159 5103 : inline std::shared_ptr<T> EnsureFieldPointerIsNonNull(const_iterator & iterator) const 160 : { 161 5103 : auto owned_ptr = iterator->second; 162 : 163 5103 : if (!owned_ptr) 164 : { 165 0 : MFEM_ABORT("The field '" << iterator->first << "' is NULL."); 166 : } 167 : 168 5103 : 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 2476 : void DeregisterAll() { _field_map.clear(); } 187 : 188 : private: 189 : MapType _field_map{}; 190 : }; 191 : 192 : inline std::string 193 152 : GetTimeDerivativeName(std::string name) 194 : { 195 304 : return std::string("d") + name + std::string("_dt"); 196 : } 197 : 198 : using FECollections = Moose::MFEM::NamedFieldsMap<mfem::FiniteElementCollection>; 199 : using FESpaces = Moose::MFEM::NamedFieldsMap<mfem::ParFiniteElementSpace>; 200 : using GridFunctions = Moose::MFEM::NamedFieldsMap<mfem::ParGridFunction>; 201 : using SubMeshes = Moose::MFEM::NamedFieldsMap<mfem::ParSubMesh>; 202 : 203 : } // namespace Moose::MFEM 204 : 205 : #endif