LCOV - code coverage report
Current view: top level - include/mfem/utils - CoefficientMap.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 53 54 98.1 %
Date: 2025-07-17 01:28:37 Functions: 53 53 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 MFEM_ENABLED
      11             : 
      12             : #pragma once
      13             : #include <map>
      14             : #include <memory>
      15             : #include <string>
      16             : #include <tuple>
      17             : #include <utility>
      18             : #include <variant>
      19             : #include <vector>
      20             : 
      21             : #include "MooseException.h"
      22             : #include "MooseError.h"
      23             : 
      24             : #include "libmesh/ignore_warnings.h"
      25             : #include <mfem.hpp>
      26             : #include "libmesh/restore_warnings.h"
      27             : #include "libmesh/utility.h"
      28             : 
      29             : namespace Moose::MFEM
      30             : {
      31             : 
      32             : /**
      33             :  * Class to manage MFEM coefficient objects representing material
      34             :  * properties. It can build up piecewise coefficients representing
      35             :  * properties defined across multiple materials.
      36             :  */
      37             : template <class T, class Tpw>
      38             : class CoefficientMap
      39             : {
      40             : public:
      41         964 :   CoefficientMap() = default;
      42             : 
      43             :   /// Make arbitrary coefficients which will be tracked by this object
      44             :   template <class P, class... Args>
      45         879 :   std::shared_ptr<P> make(Args &&... args)
      46             :   {
      47         879 :     auto result = std::make_shared<P>(args...);
      48         879 :     this->_iterable_coefficients.push_back(result);
      49         879 :     return result;
      50           0 :   }
      51             : 
      52             :   /// Add a named global coefficient. It must have been created with
      53             :   /// the `make` method on this object.
      54         752 :   void addCoefficient(const std::string & name, std::shared_ptr<T> coeff)
      55             :   {
      56             :     mooseAssert(std::find(this->_iterable_coefficients.cbegin(),
      57             :                           this->_iterable_coefficients.cend(),
      58             :                           coeff) != this->_iterable_coefficients.cend(),
      59             :                 "Coefficient object was not created by this CoefficientMap.");
      60             : 
      61         752 :     const auto [_, inserted] = this->_coefficients.emplace(name, std::move(coeff));
      62         752 :     if (!inserted)
      63          12 :       mooseError("Coefficient with name '" + name + "' already present in CoefficientMap object");
      64         748 :   }
      65             : 
      66             :   /// Add piecewise material property. The coefficient must have been created with the `make` method on this object.
      67             :   ///
      68             :   /// Note: If you attempt to overwrite an existing block then an exception will be thrown and data
      69             :   /// for that property will be left in an undefined state.
      70         138 :   void addPiecewiseBlocks(const std::string & name,
      71             :                           std::shared_ptr<T> coeff,
      72             :                           const std::vector<std::string> & blocks)
      73             :   {
      74             :     // If list of blocks is empty then treat as a global coefficient
      75         138 :     if (blocks.size() == 0)
      76             :     {
      77           8 :       this->addCoefficient(name, coeff);
      78           8 :       return;
      79             :     }
      80             : 
      81             :     // Initialise property with empty coefficients, if it does not already exist
      82         130 :     if (!this->hasCoefficient(name))
      83          87 :       this->_coefficients.insert({name, this->emptyPWData(coeff)});
      84         130 :     PWData * data = std::get_if<PWData>(&this->_coefficients[name]);
      85             :     // Throw an exception if the data is not piecewise
      86         130 :     if (!data)
      87           3 :       mooseError("Global coefficient with name '" + name + "' already present in CoefficientMap");
      88             :     mooseAssert(std::find(this->_iterable_coefficients.cbegin(),
      89             :                           this->_iterable_coefficients.cend(),
      90             :                           coeff) != this->_iterable_coefficients.cend(),
      91             :                 "Coefficient object was not created by the appropriate coefficient manager.");
      92         129 :     auto & [pw_coeff, coeff_map] = *data;
      93         133 :     this->checkPWData(coeff, pw_coeff, name);
      94             : 
      95         303 :     for (const auto & block : blocks)
      96             :     {
      97         177 :       if (coeff_map.count(block) > 0)
      98           5 :         mooseError("Property with name '" + name + "' already assigned to block " + block +
      99             :                    " in CoefficientMap object");
     100         176 :       coeff_map[block] = coeff;
     101         176 :       pw_coeff->UpdateCoefficient(std::stoi(block), *coeff);
     102             :     }
     103             :   }
     104             : 
     105           7 :   T & getCoefficient(const std::string & name) { return *this->getCoefficientPtr(name); }
     106             : 
     107         736 :   std::shared_ptr<T> getCoefficientPtr(const std::string & name)
     108             :   {
     109             :     try
     110             :     {
     111         736 :       auto & coeff = this->_coefficients.at(name);
     112             :       try
     113             :       {
     114         733 :         return std::get<std::shared_ptr<T>>(coeff);
     115             :       }
     116         380 :       catch (const std::bad_variant_access &)
     117             :       {
     118         190 :         return std::get<0>(std::get<PWData>(coeff));
     119             :       }
     120             :     }
     121           6 :     catch (const std::out_of_range &)
     122             :     {
     123           9 :       mooseError("Property with name '" + name + "' has not been declared.");
     124             :     }
     125             :   }
     126             : 
     127         970 :   bool hasCoefficient(const std::string & name) const
     128             :   {
     129         970 :     return this->_coefficients.count(name) > 0;
     130             :   }
     131             : 
     132         130 :   bool propertyDefinedOnBlock(const std::string & name, const std::string & block) const
     133             :   {
     134         130 :     if (!this->hasCoefficient(name))
     135          78 :       return false;
     136          52 :     auto & coeff = libmesh_map_find(this->_coefficients, name);
     137          52 :     if (std::holds_alternative<std::shared_ptr<T>>(coeff))
     138          21 :       return true;
     139          31 :     auto block_map = std::get<1>(std::get<PWData>(coeff));
     140          31 :     return block_map.count(block) > 0;
     141          31 :   }
     142             : 
     143         204 :   void setTime(const double time)
     144             :   {
     145         600 :     for (auto & coef : this->_iterable_coefficients)
     146         396 :       coef->SetTime(time);
     147         204 :   }
     148             : 
     149             : private:
     150             :   using PWData = std::tuple<std::shared_ptr<Tpw>, std::map<const std::string, std::shared_ptr<T>>>;
     151             :   std::map<const std::string, std::variant<std::shared_ptr<T>, PWData>> _coefficients;
     152             :   std::vector<std::shared_ptr<T>> _iterable_coefficients;
     153             : 
     154          52 :   PWData emptyPWData(std::shared_ptr<T> /*coeff*/)
     155             :   {
     156             :     return std::make_tuple(this->template make<Tpw>(),
     157          52 :                            std::map<const std::string, std::shared_ptr<T>>());
     158             :   }
     159          76 :   void checkPWData(std::shared_ptr<T> /*coeff*/,
     160             :                    std::shared_ptr<Tpw> /* existing_pw*/,
     161             :                    const std::string & /*name*/)
     162             :   {
     163          76 :   }
     164             : };
     165             : 
     166             : using ScalarMap = CoefficientMap<mfem::Coefficient, mfem::PWCoefficient>;
     167             : using VectorMap = CoefficientMap<mfem::VectorCoefficient, mfem::PWVectorCoefficient>;
     168             : using MatrixMap = CoefficientMap<mfem::MatrixCoefficient, mfem::PWMatrixCoefficient>;
     169             : 
     170             : template <>
     171             : VectorMap::PWData VectorMap::emptyPWData(std::shared_ptr<mfem::VectorCoefficient> coeff);
     172             : 
     173             : template <>
     174             : MatrixMap::PWData MatrixMap::emptyPWData(std::shared_ptr<mfem::MatrixCoefficient> coeff);
     175             : 
     176             : template <>
     177             : void VectorMap::checkPWData(std::shared_ptr<mfem::VectorCoefficient> coeff,
     178             :                             std::shared_ptr<mfem::PWVectorCoefficient> existing_pw,
     179             :                             const std::string & name);
     180             : 
     181             : template <>
     182             : void MatrixMap::checkPWData(std::shared_ptr<mfem::MatrixCoefficient> coeff,
     183             :                             std::shared_ptr<mfem::PWMatrixCoefficient> existing_pw,
     184             :                             const std::string & name);
     185             : } // namespace Moose::MFEM
     186             : 
     187             : #endif

Generated by: LCOV version 1.14