OGS
IntegrationMethodRegistry.cpp
Go to the documentation of this file.
1
11
12#include <unordered_map>
13
14#include "BaseLib/Error.h"
17
18static constexpr unsigned MAX_ORDER_REGULAR = 4u;
19
20template <typename MeshElement>
22
23template <typename IntegrationPolicy_>
25 unsigned const order)
26{
27 typename IntegrationPolicy_::IntegrationMethod meth{order};
28 unsigned const np = meth.getNumberOfPoints();
29
30 std::vector<MathLib::WeightedPoint> wps;
31 wps.reserve(np);
32
33 for (unsigned ip = 0; ip < np; ++ip)
34 {
35 wps.emplace_back(meth.getWeightedPoint(ip));
36
37 if (wps.back() != meth.getWeightedPoint(ip))
38 {
39 throw std::runtime_error(
40 "createGenericIntegrationMethod mismatch for ip=" +
41 std::to_string(ip) + ", order=" + std::to_string(order) +
42 ", method=" + typeid(decltype(meth)).name());
43 }
44 }
45
46 return NumLib::GenericIntegrationMethod{order, std::move(wps)};
47}
48
49template <typename MeshElement>
51 std::unordered_map<std::type_index,
52 std::vector<NumLib::GenericIntegrationMethod>>&
53 integration_methods_by_mesh_element_type,
54 unsigned max_order)
55{
56 std::vector<NumLib::GenericIntegrationMethod> integration_methods;
57 integration_methods.reserve(max_order + 1);
58
59 // order 0 -> no valid weighted points
60 NumLib::GenericIntegrationMethod invalidMethod{0, {}};
61 integration_methods.push_back(std::move(invalidMethod));
62
63 for (unsigned order = 1; order <= max_order; ++order)
64 {
65 integration_methods.push_back(
67 order));
68 }
69
70 integration_methods_by_mesh_element_type.emplace(
71 std::type_index(typeid(MeshElement)), std::move(integration_methods));
72}
73
75 std::unordered_map<std::type_index,
76 std::vector<NumLib::GenericIntegrationMethod>>&
77 integration_methods_by_mesh_element_type)
78{
80 integration_methods_by_mesh_element_type,
81 MAX_ORDER_REGULAR /* arbitrary cutoff */);
82}
83
85 std::unordered_map<std::type_index,
86 std::vector<NumLib::GenericIntegrationMethod>>&
87 integration_methods_by_mesh_element_type)
88{
90 integration_methods_by_mesh_element_type, MAX_ORDER_REGULAR);
91
93 integration_methods_by_mesh_element_type, MAX_ORDER_REGULAR);
94}
95
97 std::unordered_map<std::type_index,
98 std::vector<NumLib::GenericIntegrationMethod>>&
99 integration_methods_by_mesh_element_type)
100{
102 integration_methods_by_mesh_element_type, MAX_ORDER_REGULAR);
103
105 integration_methods_by_mesh_element_type, MAX_ORDER_REGULAR);
106
108 integration_methods_by_mesh_element_type, MAX_ORDER_REGULAR);
109
111 integration_methods_by_mesh_element_type, 4);
112
114 integration_methods_by_mesh_element_type, 4);
115}
116
118 std::unordered_map<std::type_index,
119 std::vector<NumLib::GenericIntegrationMethod>>&
120 integration_methods_by_mesh_element_type)
121{
123 integration_methods_by_mesh_element_type, MAX_ORDER_REGULAR);
124
126 integration_methods_by_mesh_element_type, MAX_ORDER_REGULAR);
127
129 integration_methods_by_mesh_element_type, 4);
130
132 integration_methods_by_mesh_element_type, 4);
133
135 integration_methods_by_mesh_element_type, 4);
136
138 integration_methods_by_mesh_element_type, 4);
139
140 /* Note: Currently (July 22) OGS has pyramid integration schemes only up to
141 * order 3 (see MathLib/Integration/GaussLegendrePyramid.h), and for order 4
142 * the third order is re-used (see
143 * NumLib/Fem/Integration/IntegrationGaussLegendrePyramid.h).
144 * I.e., a user can request 4th order integration on pyramids and OGS will
145 * just run fine, albeit with a lower integration order.
146 * To keep that behavior, in particular not crash if a user requests 4th
147 * order pyramid integration, we set the limit to 4, here.
148 */
149
151 integration_methods_by_mesh_element_type, 4 /* see note above */);
152
154 integration_methods_by_mesh_element_type, 4 /* see note above */);
155}
156
157static std::unordered_map<std::type_index,
158 std::vector<NumLib::GenericIntegrationMethod>>
160{
161 std::unordered_map<std::type_index,
162 std::vector<NumLib::GenericIntegrationMethod>>
163 integration_methods_by_mesh_element_type;
164
165 putIntegrationMethodsForDim0(integration_methods_by_mesh_element_type);
166 putIntegrationMethodsForDim1(integration_methods_by_mesh_element_type);
167 putIntegrationMethodsForDim2(integration_methods_by_mesh_element_type);
168 putIntegrationMethodsForDim3(integration_methods_by_mesh_element_type);
169
170 return integration_methods_by_mesh_element_type;
171}
172
174{
176 std::type_index const mesh_element_type, IntegrationOrder const order)
177{
178 if (order.order == 0)
179 {
180 // For 0D elements (points) the order does not matter, still we don't
181 // want order zero there. For all other element types integration order
182 // does matter.
183 OGS_FATAL("An integration order of 0 is not supported.");
184 }
185
186 // The actual integration method registry.
187 //
188 // A mapping \code [mesh element type] -> [list of integration
189 // methods]\endcode, where each entry in the list corresponds to integration
190 // order 0, 1, 2, ...
191 //
192 // Having this as a static __local__ variable circumvents the static
193 // initialization order fiasco we would have if this was a static __global__
194 // variable. The fiasco arises, because this registry uses static global
195 // data from MathLib. Currently (Feb 2022) we cannot circumvent the problem
196 // with constinit due to lack of compiler support.
197 static const std::unordered_map<
198 std::type_index,
199 std::vector<NumLib::GenericIntegrationMethod>>
200 integration_methods_by_mesh_element_type = initIntegrationMethods();
201
202 if (auto it =
203 integration_methods_by_mesh_element_type.find(mesh_element_type);
204 it != integration_methods_by_mesh_element_type.end())
205 {
206 auto& integration_methods = it->second;
207
208 if (order.order >= integration_methods.size())
209 {
210 OGS_FATAL(
211 "Integration order {} is not supported for mesh elements of "
212 "type {}",
213 order.order,
214 mesh_element_type.name());
215 }
216
217 return integration_methods[order.order];
218 }
219
220 OGS_FATAL(
221 "No integration methods are available for mesh elements of type {}",
222 mesh_element_type.name());
223}
224} // namespace NumLib::IntegrationMethodRegistry
#define OGS_FATAL(...)
Definition Error.h:26
static void putIntegrationMethodsForDim1(std::unordered_map< std::type_index, std::vector< NumLib::GenericIntegrationMethod > > &integration_methods_by_mesh_element_type)
static std::unordered_map< std::type_index, std::vector< NumLib::GenericIntegrationMethod > > initIntegrationMethods()
static NumLib::GenericIntegrationMethod createGenericIntegrationMethod(unsigned const order)
static void putIntegrationMethodsForDim3(std::unordered_map< std::type_index, std::vector< NumLib::GenericIntegrationMethod > > &integration_methods_by_mesh_element_type)
static void putIntegrationMethodsFor(std::unordered_map< std::type_index, std::vector< NumLib::GenericIntegrationMethod > > &integration_methods_by_mesh_element_type, unsigned max_order)
static void putIntegrationMethodsForDim0(std::unordered_map< std::type_index, std::vector< NumLib::GenericIntegrationMethod > > &integration_methods_by_mesh_element_type)
static constexpr unsigned MAX_ORDER_REGULAR
static void putIntegrationMethodsForDim2(std::unordered_map< std::type_index, std::vector< NumLib::GenericIntegrationMethod > > &integration_methods_by_mesh_element_type)
GenericIntegrationMethod const & getIntegrationMethod(std::type_index const mesh_element_type, IntegrationOrder const order)