LCOV - code coverage report
Current view: top level - include/mfem/containers - MFEMContainers.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #31706 (f8ed4a) with base bb0a08 Lines: 61 69 88.4 %
Date: 2025-11-03 17:23:24 Functions: 190 200 95.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             : #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

Generated by: LCOV version 1.14