https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
26namespace Moose::MFEM
27{
28
34template <class T, class Tpw>
36{
37public:
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
147 template <class F>
148 void apply(F && func)
149 {
150 for (auto & coef : this->_iterable_coefficients)
151 func(*coef);
152 }
153
154private:
155 using PWData = std::tuple<std::shared_ptr<Tpw>, std::map<const std::string, std::shared_ptr<T>>>;
156 std::map<const std::string, std::variant<std::shared_ptr<T>, PWData>> _coefficients;
157 std::vector<std::shared_ptr<T>> _iterable_coefficients;
158
159 PWData emptyPWData(std::shared_ptr<T> /*coeff*/)
160 {
161 return std::make_tuple(this->template make<Tpw>(),
162 std::map<const std::string, std::shared_ptr<T>>());
163 }
164 void checkPWData(std::shared_ptr<T> /*coeff*/,
165 std::shared_ptr<Tpw> /* existing_pw*/,
166 const std::string & /*name*/)
167 {
168 }
169};
170
174
175template <>
176VectorMap::PWData VectorMap::emptyPWData(std::shared_ptr<mfem::VectorCoefficient> coeff);
177
178template <>
179MatrixMap::PWData MatrixMap::emptyPWData(std::shared_ptr<mfem::MatrixCoefficient> coeff);
180
181template <>
182void VectorMap::checkPWData(std::shared_ptr<mfem::VectorCoefficient> coeff,
183 std::shared_ptr<mfem::PWVectorCoefficient> existing_pw,
184 const std::string & name);
185
186template <>
187void MatrixMap::checkPWData(std::shared_ptr<mfem::MatrixCoefficient> coeff,
188 std::shared_ptr<mfem::PWMatrixCoefficient> existing_pw,
189 const std::string & name);
190} // namespace Moose::MFEM
191
192#endif
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
char ** blocks
Class to manage MFEM coefficient objects representing material properties.
std::map< const std::string, std::variant< std::shared_ptr< T >, PWData > > _coefficients
std::shared_ptr< P > make(Args &&... args)
Make arbitrary coefficients which will be tracked by this object.
bool propertyDefinedOnBlock(const std::string &name, const std::string &block) const
std::vector< std::shared_ptr< T > > _iterable_coefficients
void addCoefficient(const std::string &name, std::shared_ptr< T > coeff)
Add a named global coefficient.
bool hasCoefficient(const std::string &name) const
void addPiecewiseBlocks(const std::string &name, std::shared_ptr< T > coeff, const std::vector< std::string > &blocks)
Add piecewise material property.
void checkPWData(std::shared_ptr< T >, std::shared_ptr< Tpw >, const std::string &)
std::shared_ptr< T > getCoefficientPtr(const std::string &name)
void setTime(const mfem::real_t time)
void apply(F &&func)
Apply a function to every coefficient created by this map.
T & getCoefficient(const std::string &name)
PWData emptyPWData(std::shared_ptr< T >)
std::tuple< std::shared_ptr< Tpw >, std::map< const std::string, std::shared_ptr< T > > > PWData
Utilities for converting between vector(s) of libMesh Points and MFEM Vector(s).