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 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 
34 template <class T, class Tpw>
36 {
37 public:
38  CoefficientMap() = default;
39 
41  template <class P, class... Args>
42  std::shared_ptr<P> make(Args &&... args)
43  {
44  auto result = std::make_shared<P>(args...);
45  this->_iterable_coefficients.push_back(result);
46  return result;
47  }
48 
51  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  const auto [_, inserted] = this->_coefficients.emplace(name, std::move(coeff));
59  if (!inserted)
60  mooseError("Coefficient with name '" + name + "' already present in CoefficientMap object");
61  }
62 
67  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  if (blocks.size() == 0)
73  {
74  this->addCoefficient(name, coeff);
75  return;
76  }
77 
78  // Initialise property with empty coefficients, if it does not already exist
79  if (!this->hasCoefficient(name))
80  this->_coefficients.insert({name, this->emptyPWData(coeff)});
81  PWData * data = std::get_if<PWData>(&this->_coefficients[name]);
82  // Throw an exception if the data is not piecewise
83  if (!data)
84  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  auto & [pw_coeff, coeff_map] = *data;
90  this->checkPWData(coeff, pw_coeff, name);
91 
92  for (const auto & block : blocks)
93  {
94  if (coeff_map.count(block) > 0)
95  mooseError("Property with name '" + name + "' already assigned to block " + block +
96  " in CoefficientMap object");
97  coeff_map[block] = coeff;
98  pw_coeff->UpdateCoefficient(std::stoi(block), *coeff);
99  }
100  }
101 
102  T & getCoefficient(const std::string & name) { return *this->getCoefficientPtr(name); }
103 
104  std::shared_ptr<T> getCoefficientPtr(const std::string & name)
105  {
106  try
107  {
108  auto & coeff = this->_coefficients.at(name);
109  try
110  {
111  return std::get<std::shared_ptr<T>>(coeff);
112  }
113  catch (const std::bad_variant_access &)
114  {
115  return std::get<0>(std::get<PWData>(coeff));
116  }
117  }
118  catch (const std::out_of_range &)
119  {
120  mooseError("Property with name '" + name + "' has not been declared.");
121  }
122  }
123 
124  bool hasCoefficient(const std::string & name) const
125  {
126  return this->_coefficients.count(name) > 0;
127  }
128 
129  bool propertyDefinedOnBlock(const std::string & name, const std::string & block) const
130  {
131  if (!this->hasCoefficient(name))
132  return false;
133  auto & coeff = libmesh_map_find(this->_coefficients, name);
134  if (std::holds_alternative<std::shared_ptr<T>>(coeff))
135  return true;
136  auto block_map = std::get<1>(std::get<PWData>(coeff));
137  return block_map.count(block) > 0;
138  }
139 
140  void setTime(const mfem::real_t time)
141  {
142  for (auto & coef : this->_iterable_coefficients)
143  coef->SetTime(time);
144  }
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  PWData emptyPWData(std::shared_ptr<T> /*coeff*/)
152  {
153  return std::make_tuple(this->template make<Tpw>(),
154  std::map<const std::string, std::shared_ptr<T>>());
155  }
156  void checkPWData(std::shared_ptr<T> /*coeff*/,
157  std::shared_ptr<Tpw> /* existing_pw*/,
158  const std::string & /*name*/)
159  {
160  }
161 };
162 
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
std::string name(const ElemQuality q)
bool propertyDefinedOnBlock(const std::string &name, const std::string &block) const
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:40
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:311
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.
void setTime(const mfem::real_t time)
T & getCoefficient(const std::string &name)
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.
Utilities for converting between vector(s) of libMesh Points and MFEM Vector(s).
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