10namespace mapping_detail {
11template <
class ExecSpace,
class Type>
12struct MappingAccessibility : std::false_type
21template <
typename Type,
template <
typename ClassType>
typename Attribute>
22class CheckClassAttributeExistence
32 template <
typename ClassType>
33 static char attribute(check<Attribute<ClassType>>*);
36 template <
typename ClassType>
37 static long attribute(...);
41 static constexpr bool has_attribute = (
sizeof(attribute<Type>(0)) ==
sizeof(
char));
47template <
typename Type>
50 template <
typename ClassType>
51 using coord_arg_type =
typename ClassType::CoordArg;
52 template <
typename ClassType>
53 using coord_result_type =
typename ClassType::CoordResult;
55 static bool constexpr is_mapping()
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>;
70 static constexpr bool value = is_mapping();
73template <
typename Type,
typename CoordinateType>
74class Defines2DJacobian
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);
89 static std::tuple<bool, const char*>
constexpr has_2d_jacobian_methods()
91 if (!CheckClassAttributeExistence<Type, jacobian_type>::has_attribute) {
92 return std::make_tuple(
false,
"A 2D Mapping must define the jacobian_matrix function");
94 if (!CheckClassAttributeExistence<Type, jacobian_11>::has_attribute) {
95 return std::make_tuple(
false,
"A 2D Mapping must define the jacobian_11 function");
97 if (!CheckClassAttributeExistence<Type, jacobian_12>::has_attribute) {
98 return std::make_tuple(
false,
"A 2D Mapping must define the jacobian_12 function");
100 if (!CheckClassAttributeExistence<Type, jacobian_21>::has_attribute) {
101 return std::make_tuple(
false,
"A 2D Mapping must define the jacobian_21 function");
103 if (!CheckClassAttributeExistence<Type, jacobian_22>::has_attribute) {
104 return std::make_tuple(
false,
"A 2D Mapping must define the jacobian_22 function");
106 if (!CheckClassAttributeExistence<Type, jacobian>::has_attribute) {
107 return std::make_tuple(
false,
"A 2D Mapping must define the jacobian function");
109 return std::make_tuple(
true,
"");
112 static std::tuple<bool, const char*>
constexpr has_2d_jacobian()
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<
118 decltype(&Type::jacobian_matrix),
122 return std::make_tuple(
124 "The jacobian_matrix method of a 2D Mapping must take a Coordinate and a "
125 "Matrix_2x2& as an argument and return nothing.");
127 if (!std::is_invocable_r_v<
129 decltype(&Type::jacobian_11),
132 return std::make_tuple(
134 "The jacobian_11 method of a 2D Mapping must take a Coordinate as an "
135 "argument and return a double.");
137 if (!std::is_invocable_r_v<
139 decltype(&Type::jacobian_12),
142 return std::make_tuple(
144 "The jacobian_12 method of a 2D Mapping must take a Coordinate as an "
145 "argument and return a double.");
147 if (!std::is_invocable_r_v<
149 decltype(&Type::jacobian_21),
152 return std::make_tuple(
154 "The jacobian_21 method of a 2D Mapping must take a Coordinate as an "
155 "argument and return a double.");
157 if (!std::is_invocable_r_v<
159 decltype(&Type::jacobian_22),
162 return std::make_tuple(
164 "The jacobian_22 method of a 2D Mapping must take a Coordinate as an "
165 "argument and return a double.");
167 if (!std::is_invocable_r_v<
double,
decltype(&Type::jacobian), Type, CoordinateType>) {
168 return std::make_tuple(
170 "The jacobian method of a 2D Mapping must take a Coordinate as an argument "
171 "and return a double.");
173 return std::make_tuple(
true,
"");
178 static constexpr std::tuple<bool, const char*> has_2d_jacobian_output = has_2d_jacobian();
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);
187template <
typename Type,
typename CoordinateType>
188class Defines2DInvJacobian
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);
201 static std::tuple<bool, const char*>
constexpr has_2d_inv_jacobian_methods()
203 if (!CheckClassAttributeExistence<Type, inv_jacobian_type>::has_attribute) {
205 make_tuple(
false,
"A 2D Mapping must define the inv_jacobian_matrix function");
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");
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");
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");
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");
219 return std::make_tuple(
true,
"");
222 static std::tuple<bool, const char*>
constexpr has_2d_inv_jacobian()
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<
228 decltype(&Type::inv_jacobian_matrix),
232 return std::make_tuple(
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.");
237 if (!std::is_invocable_r_v<
239 decltype(&Type::inv_jacobian_11),
242 return std::make_tuple(
244 "The inv_jacobian_11 method of a 2D Mapping must take a Coordinate as an "
245 "argument and return a double.");
247 if (!std::is_invocable_r_v<
249 decltype(&Type::inv_jacobian_12),
252 return std::make_tuple(
254 "The inv_jacobian_12 method of a 2D Mapping must take a Coordinate as an "
255 "argument and return a double.");
257 if (!std::is_invocable_r_v<
259 decltype(&Type::inv_jacobian_21),
262 return std::make_tuple(
264 "The inv_jacobian_21 method of a 2D Mapping must take a Coordinate as an "
265 "argument and return a double.");
267 if (!std::is_invocable_r_v<
269 decltype(&Type::inv_jacobian_22),
272 return std::make_tuple(
274 "The inv_jacobian_22 method of a 2D Mapping must take a Coordinate as an "
275 "argument and return a double.");
277 return std::make_tuple(
true,
"");
282 static constexpr std::tuple<bool, const char*> has_2d_inv_jacobian_output
283 = has_2d_inv_jacobian();
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);
292template <
class Mapping>
293struct IsCurvilinear2DMapping : std::false_type
297template <
typename Type>
298class IsAnalyticalMapping
301 template <
typename ClassType>
302 using inverse_mapping =
decltype(&ClassType::get_inverse_mapping);
304 static bool constexpr is_analytical_mapping()
306 constexpr bool success = CheckClassAttributeExistence<Type, inverse_mapping>::has_attribute;
307 if constexpr (success) {
308 return std::is_invocable_v<inverse_mapping<Type>, Type>;
315 static constexpr bool value = is_analytical_mapping();
318template <
class Mapping>
319struct SingularOPointInvJacobian : std::false_type
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;
329template <
class Mapping>
330static constexpr bool is_mapping_v = mapping_detail::IsMapping<Mapping>::value;
332template <
class Mapping,
class CoordinateType>
333static constexpr bool has_2d_jacobian_v
334 = mapping_detail::Defines2DJacobian<Mapping, CoordinateType>::value;
336template <
class Mapping,
class CoordinateType>
337static constexpr bool has_2d_inv_jacobian_v
338 = mapping_detail::Defines2DInvJacobian<Mapping, CoordinateType>::value;
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;
344template <
class Mapping>
345static constexpr bool is_analytical_mapping_v = mapping_detail::IsAnalyticalMapping<Mapping>::value;
347template <
class Mapping>
348using inverse_mapping_t =
decltype(std::declval<Mapping>().get_inverse_mapping());
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;