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

Generated by: LCOV version 1.14