LCOV - code coverage report
Current view: top level - include/mfem/containers - MFEMContainers.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #33416 (b10b36) with base 9fbd27 Lines: 56 60 93.3 %
Date: 2026-07-23 16:15:30 Functions: 318 318 100.0 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.14