Gyselalib++
 
Loading...
Searching...
No Matches
mapping_tools.hpp
1// SPDX-License-Identifier: MIT
2#pragma once
3
4#include <array>
5#include <type_traits>
6#include <utility>
7
8#include <sll/view.hpp>
9
10namespace mapping_detail {
11template <class ExecSpace, class Type>
12struct MappingAccessibility : std::false_type
13{
14};
15
21template <typename Type, template <typename ClassType> typename Attribute>
22class CheckClassAttributeExistence
23{
24private:
25 // Class for SFINAE deduction
26 template <typename U>
27 class check
28 {
29 };
30
31 // Function that will be chosen if ClassType has a attribute called idx_range with 0 arguments
32 template <typename ClassType>
33 static char attribute(check<Attribute<ClassType>>*);
34
35 // Function that will be chosen by default
36 template <typename ClassType>
37 static long attribute(...);
38
39public:
41 static constexpr bool has_attribute = (sizeof(attribute<Type>(0)) == sizeof(char));
42};
43
47template <typename Type>
48class IsMapping
49{
50 template <typename ClassType>
51 using coord_arg_type = typename ClassType::CoordArg;
52 template <typename ClassType>
53 using coord_result_type = typename ClassType::CoordResult;
54
55 static bool constexpr is_mapping()
56 {
57 constexpr bool success
58 = CheckClassAttributeExistence<Type, coord_arg_type>::has_attribute
59 && CheckClassAttributeExistence<Type, coord_result_type>::has_attribute;
60 if constexpr (success) {
61 using CoordArg = typename Type::CoordArg;
62 using CoordResult = typename Type::CoordResult;
63 return std::is_invocable_r_v<CoordResult, Type, CoordArg>;
64 }
65 return success;
66 }
67
68public:
70 static constexpr bool value = is_mapping();
71};
72
73template <typename Type, typename CoordinateType>
74class Defines2DJacobian
75{
76 template <typename ClassType>
77 using jacobian_type = decltype(&ClassType::jacobian_matrix);
78 template <typename ClassType>
79 using jacobian_11 = decltype(&ClassType::jacobian_11);
80 template <typename ClassType>
81 using jacobian_12 = decltype(&ClassType::jacobian_12);
82 template <typename ClassType>
83 using jacobian_21 = decltype(&ClassType::jacobian_21);
84 template <typename ClassType>
85 using jacobian_22 = decltype(&ClassType::jacobian_22);
86 template <typename ClassType>
87 using jacobian = decltype(&ClassType::jacobian);
88
89 static std::tuple<bool, const char*> constexpr has_2d_jacobian_methods()
90 {
91 if (!CheckClassAttributeExistence<Type, jacobian_type>::has_attribute) {
92 return std::make_tuple(false, "A 2D Mapping must define the jacobian_matrix function");
93 }
94 if (!CheckClassAttributeExistence<Type, jacobian_11>::has_attribute) {
95 return std::make_tuple(false, "A 2D Mapping must define the jacobian_11 function");
96 }
97 if (!CheckClassAttributeExistence<Type, jacobian_12>::has_attribute) {
98 return std::make_tuple(false, "A 2D Mapping must define the jacobian_12 function");
99 }
100 if (!CheckClassAttributeExistence<Type, jacobian_21>::has_attribute) {
101 return std::make_tuple(false, "A 2D Mapping must define the jacobian_21 function");
102 }
103 if (!CheckClassAttributeExistence<Type, jacobian_22>::has_attribute) {
104 return std::make_tuple(false, "A 2D Mapping must define the jacobian_22 function");
105 }
106 if (!CheckClassAttributeExistence<Type, jacobian>::has_attribute) {
107 return std::make_tuple(false, "A 2D Mapping must define the jacobian function");
108 }
109 return std::make_tuple(true, "");
110 }
111
112 static std::tuple<bool, const char*> constexpr has_2d_jacobian()
113 {
114 constexpr std::tuple<bool, const char*> success = has_2d_jacobian_methods();
115 if constexpr (std::get<bool>(success)) {
116 if (!std::is_invocable_r_v<
117 void,
118 decltype(&Type::jacobian_matrix),
119 Type,
120 CoordinateType,
121 Matrix_2x2&>) {
122 return std::make_tuple(
123 false,
124 "The jacobian_matrix method of a 2D Mapping must take a Coordinate and a "
125 "Matrix_2x2& as an argument and return nothing.");
126 }
127 if (!std::is_invocable_r_v<
128 double,
129 decltype(&Type::jacobian_11),
130 Type,
131 CoordinateType>) {
132 return std::make_tuple(
133 false,
134 "The jacobian_11 method of a 2D Mapping must take a Coordinate as an "
135 "argument and return a double.");
136 }
137 if (!std::is_invocable_r_v<
138 double,
139 decltype(&Type::jacobian_12),
140 Type,
141 CoordinateType>) {
142 return std::make_tuple(
143 false,
144 "The jacobian_12 method of a 2D Mapping must take a Coordinate as an "
145 "argument and return a double.");
146 }
147 if (!std::is_invocable_r_v<
148 double,
149 decltype(&Type::jacobian_21),
150 Type,
151 CoordinateType>) {
152 return std::make_tuple(
153 false,
154 "The jacobian_21 method of a 2D Mapping must take a Coordinate as an "
155 "argument and return a double.");
156 }
157 if (!std::is_invocable_r_v<
158 double,
159 decltype(&Type::jacobian_22),
160 Type,
161 CoordinateType>) {
162 return std::make_tuple(
163 false,
164 "The jacobian_22 method of a 2D Mapping must take a Coordinate as an "
165 "argument and return a double.");
166 }
167 if (!std::is_invocable_r_v<double, decltype(&Type::jacobian), Type, CoordinateType>) {
168 return std::make_tuple(
169 false,
170 "The jacobian method of a 2D Mapping must take a Coordinate as an argument "
171 "and return a double.");
172 }
173 return std::make_tuple(true, "");
174 }
175 return success;
176 }
177
178 static constexpr std::tuple<bool, const char*> has_2d_jacobian_output = has_2d_jacobian();
179
180public:
182 static constexpr bool value = std::get<bool>(has_2d_jacobian_output);
184 static constexpr const char* error_msg = std::get<const char*>(has_2d_jacobian_output);
185};
186
187template <typename Type, typename CoordinateType>
188class Defines2DInvJacobian
189{
190 template <typename ClassType>
191 using inv_jacobian_type = decltype(&ClassType::inv_jacobian_matrix);
192 template <typename ClassType>
193 using inv_jacobian_11 = decltype(&ClassType::inv_jacobian_11);
194 template <typename ClassType>
195 using inv_jacobian_12 = decltype(&ClassType::inv_jacobian_12);
196 template <typename ClassType>
197 using inv_jacobian_21 = decltype(&ClassType::inv_jacobian_21);
198 template <typename ClassType>
199 using inv_jacobian_22 = decltype(&ClassType::inv_jacobian_22);
200
201 static std::tuple<bool, const char*> constexpr has_2d_inv_jacobian_methods()
202 {
203 if (!CheckClassAttributeExistence<Type, inv_jacobian_type>::has_attribute) {
204 return std::
205 make_tuple(false, "A 2D Mapping must define the inv_jacobian_matrix function");
206 }
207 if (!CheckClassAttributeExistence<Type, inv_jacobian_11>::has_attribute) {
208 return std::make_tuple(false, "A 2D Mapping must define the inv_jacobian_11 function");
209 }
210 if (!CheckClassAttributeExistence<Type, inv_jacobian_12>::has_attribute) {
211 return std::make_tuple(false, "A 2D Mapping must define the inv_jacobian_12 function");
212 }
213 if (!CheckClassAttributeExistence<Type, inv_jacobian_21>::has_attribute) {
214 return std::make_tuple(false, "A 2D Mapping must define the inv_jacobian_21 function");
215 }
216 if (!CheckClassAttributeExistence<Type, inv_jacobian_22>::has_attribute) {
217 return std::make_tuple(false, "A 2D Mapping must define the inv_jacobian_22 function");
218 }
219 return std::make_tuple(true, "");
220 }
221
222 static std::tuple<bool, const char*> constexpr has_2d_inv_jacobian()
223 {
224 constexpr std::tuple<bool, const char*> success = has_2d_inv_jacobian_methods();
225 if constexpr (std::get<bool>(success)) {
226 if (!std::is_invocable_r_v<
227 void,
228 decltype(&Type::inv_jacobian_matrix),
229 Type,
230 CoordinateType,
231 Matrix_2x2&>) {
232 return std::make_tuple(
233 false,
234 "The inv_jacobian_matrix method of a 2D Mapping must take a Coordinate and "
235 "a Matrix_2x2& as an argument and return nothing.");
236 }
237 if (!std::is_invocable_r_v<
238 double,
239 decltype(&Type::inv_jacobian_11),
240 Type,
241 CoordinateType>) {
242 return std::make_tuple(
243 false,
244 "The inv_jacobian_11 method of a 2D Mapping must take a Coordinate as an "
245 "argument and return a double.");
246 }
247 if (!std::is_invocable_r_v<
248 double,
249 decltype(&Type::inv_jacobian_12),
250 Type,
251 CoordinateType>) {
252 return std::make_tuple(
253 false,
254 "The inv_jacobian_12 method of a 2D Mapping must take a Coordinate as an "
255 "argument and return a double.");
256 }
257 if (!std::is_invocable_r_v<
258 double,
259 decltype(&Type::inv_jacobian_21),
260 Type,
261 CoordinateType>) {
262 return std::make_tuple(
263 false,
264 "The inv_jacobian_21 method of a 2D Mapping must take a Coordinate as an "
265 "argument and return a double.");
266 }
267 if (!std::is_invocable_r_v<
268 double,
269 decltype(&Type::inv_jacobian_22),
270 Type,
271 CoordinateType>) {
272 return std::make_tuple(
273 false,
274 "The inv_jacobian_22 method of a 2D Mapping must take a Coordinate as an "
275 "argument and return a double.");
276 }
277 return std::make_tuple(true, "");
278 }
279 return success;
280 }
281
282 static constexpr std::tuple<bool, const char*> has_2d_inv_jacobian_output
283 = has_2d_inv_jacobian();
284
285public:
287 static constexpr bool value = std::get<bool>(has_2d_inv_jacobian_output);
289 static constexpr const char* error_msg = std::get<const char*>(has_2d_inv_jacobian_output);
290};
291
292template <class Mapping>
293struct IsCurvilinear2DMapping : std::false_type
294{
295};
296
297template <typename Type>
298class IsAnalyticalMapping
299{
300private:
301 template <typename ClassType>
302 using inverse_mapping = decltype(&ClassType::get_inverse_mapping);
303
304 static bool constexpr is_analytical_mapping()
305 {
306 constexpr bool success = CheckClassAttributeExistence<Type, inverse_mapping>::has_attribute;
307 if constexpr (success) {
308 return std::is_invocable_v<inverse_mapping<Type>, Type>;
309 }
310 return success;
311 }
312
313public:
315 static constexpr bool value = is_analytical_mapping();
316};
317
318template <class Mapping>
319struct SingularOPointInvJacobian : std::false_type
320{
321};
322
323} // namespace mapping_detail
324
325template <class ExecSpace, class Type>
326static constexpr bool is_accessible_v = mapping_detail::
327 MappingAccessibility<ExecSpace, std::remove_const_t<std::remove_reference_t<Type>>>::value;
328
329template <class Mapping>
330static constexpr bool is_mapping_v = mapping_detail::IsMapping<Mapping>::value;
331
332template <class Mapping, class CoordinateType>
333static constexpr bool has_2d_jacobian_v
334 = mapping_detail::Defines2DJacobian<Mapping, CoordinateType>::value;
335
336template <class Mapping, class CoordinateType>
337static constexpr bool has_2d_inv_jacobian_v
338 = mapping_detail::Defines2DInvJacobian<Mapping, CoordinateType>::value;
339
340template <class Mapping>
341static constexpr bool is_curvilinear_2d_mapping_v = mapping_detail::IsCurvilinear2DMapping<
342 std::remove_const_t<std::remove_reference_t<Mapping>>>::value;
343
344template <class Mapping>
345static constexpr bool is_analytical_mapping_v = mapping_detail::IsAnalyticalMapping<Mapping>::value;
346
347template <class Mapping>
348using inverse_mapping_t = decltype(std::declval<Mapping>().get_inverse_mapping());
349
350template <class Mapping>
351static constexpr bool has_singular_o_point_inv_jacobian_v
352 = mapping_detail::SingularOPointInvJacobian<
353 std::remove_const_t<std::remove_reference_t<Mapping>>>::value;