https://mooseframework.inl.gov
CoefficientMap.h
Go to the documentation of this file.
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 
37 template <class T, class Tpw>
39 {
40 public:
41  CoefficientMap() = default;
42 
44  template <class P, class... Args>
45  std::shared_ptr<P> make(Args &&... args)
46  {
47  auto result = std::make_shared<P>(args...);
48  this->_iterable_coefficients.push_back(result);
49  return result;
50  }
51 
54  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  const auto [_, inserted] = this->_coefficients.emplace(name, std::move(coeff));
62  if (!inserted)
63  mooseError("Coefficient with name '" + name + "' already present in CoefficientMap object");
64  }
65 
70  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  if (blocks.size() == 0)
76  {
77  this->addCoefficient(name, coeff);
78  return;
79  }
80 
81  // Initialise property with empty coefficients, if it does not already exist
82  if (!this->hasCoefficient(name))
83  this->_coefficients.insert({name, this->emptyPWData(coeff)});
84  PWData * data = std::get_if<PWData>(&this->_coefficients[name]);
85  // Throw an exception if the data is not piecewise
86  if (!data)
87  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  auto & [pw_coeff, coeff_map] = *data;
93  this->checkPWData(coeff, pw_coeff, name);
94 
95  for (const auto & block : blocks)
96  {
97  if (coeff_map.count(block) > 0)
98  mooseError("Property with name '" + name + "' already assigned to block " + block +
99  " in CoefficientMap object");
100  coeff_map[block] = coeff;
101  pw_coeff->UpdateCoefficient(std::stoi(block), *coeff);
102  }
103  }
104 
105  T & getCoefficient(const std::string & name) { return *this->getCoefficientPtr(name); }
106 
107  std::shared_ptr<T> getCoefficientPtr(const std::string & name)
108  {
109  try
110  {
111  auto & coeff = this->_coefficients.at(name);
112  try
113  {
114  return std::get<std::shared_ptr<T>>(coeff);
115  }
116  catch (const std::bad_variant_access &)
117  {
118  return std::get<0>(std::get<PWData>(coeff));
119  }
120  }
121  catch (const std::out_of_range &)
122  {
123  mooseError("Property with name '" + name + "' has not been declared.");
124  }
125  }
126 
127  bool hasCoefficient(const std::string & name) const
128  {
129  return this->_coefficients.count(name) > 0;
130  }
131 
132  bool propertyDefinedOnBlock(const std::string & name, const std::string & block) const
133  {
134  if (!this->hasCoefficient(name))
135  return false;
136  auto & coeff = libmesh_map_find(this->_coefficients, name);
137  if (std::holds_alternative<std::shared_ptr<T>>(coeff))
138  return true;
139  auto block_map = std::get<1>(std::get<PWData>(coeff));
140  return block_map.count(block) > 0;
141  }
142 
143  void setTime(const double time)
144  {
145  for (auto & coef : this->_iterable_coefficients)
146  coef->SetTime(time);
147  }
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  PWData emptyPWData(std::shared_ptr<T> /*coeff*/)
155  {
156  return std::make_tuple(this->template make<Tpw>(),
157  std::map<const std::string, std::shared_ptr<T>>());
158  }
159  void checkPWData(std::shared_ptr<T> /*coeff*/,
160  std::shared_ptr<Tpw> /* existing_pw*/,
161  const std::string & /*name*/)
162  {
163  }
164 };
165 
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
std::string name(const ElemQuality q)
bool propertyDefinedOnBlock(const std::string &name, const std::string &block) const
PWData emptyPWData(std::shared_ptr< T >)
char ** blocks
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302
std::tuple< std::shared_ptr< mfem::PWMatrixCoefficient >, std::map< const std::string, std::shared_ptr< mfem::MatrixCoefficient > >> PWData
void addCoefficient(const std::string &name, std::shared_ptr< T > coeff)
Add a named global coefficient.
T & getCoefficient(const std::string &name)
void setTime(const double time)
std::shared_ptr< T > getCoefficientPtr(const std::string &name)
Class to manage MFEM coefficient objects representing material properties.
void addPiecewiseBlocks(const std::string &name, std::shared_ptr< T > coeff, const std::vector< std::string > &blocks)
Add piecewise material property.
std::vector< std::shared_ptr< T > > _iterable_coefficients
std::shared_ptr< P > make(Args &&... args)
Make arbitrary coefficients which will be tracked by this object.
std::map< const std::string, std::variant< std::shared_ptr< T >, PWData > > _coefficients
void checkPWData(std::shared_ptr< T >, std::shared_ptr< Tpw >, const std::string &)
bool hasCoefficient(const std::string &name) const