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