OGS
ReflectionIPData.h
Go to the documentation of this file.
1
11#pragma once
12
13#include <boost/mp11.hpp>
14
16#include "ReflectionData.h"
17
19{
20namespace detail
21{
22template <typename T>
23concept has_reflect = requires { T::reflect(); };
24
25template <typename... Ts>
26auto reflect(std::type_identity<std::tuple<Ts...>>)
27{
28 using namespace boost::mp11;
29
30 // The types Ts... must be unique. Duplicate types are incompatible with the
31 // concept of "reflected" I/O: they would lead to duplicate names for the
32 // I/O data.
33 static_assert(mp_is_set<mp_list<Ts...>>::value);
34
35 return reflectWithoutName<std::tuple<Ts...>>(
36 [](auto& tuple_) -> auto& { return std::get<Ts>(tuple_); }...);
37}
38
39template <has_reflect T>
40auto reflect(std::type_identity<T>)
41{
42 return T::reflect();
43}
44
45template <typename T>
46concept is_reflectable = requires {
47 ProcessLib::Reflection::detail::reflect(std::type_identity<T>{});
48};
49
57template <typename T>
58struct is_raw_data : std::false_type
59{
60};
61
62template <>
63struct is_raw_data<double> : std::true_type
64{
65};
66
67template <int N>
68struct is_raw_data<Eigen::Matrix<double, N, 1, Eigen::ColMajor, N, 1>>
69 : std::true_type
70{
71};
72
73template <int N, int M>
74struct is_raw_data<Eigen::Matrix<double, N, M, Eigen::RowMajor, N, M>>
75 : std::true_type
76{
77};
78
79template <typename T>
81
82template <typename T>
84
85template <>
86struct NumberOfRows<double> : std::integral_constant<unsigned, 1>
87{
88};
89
90template <int N>
91struct NumberOfRows<Eigen::Matrix<double, N, 1, Eigen::ColMajor, N, 1>>
92 : std::integral_constant<unsigned, N>
93{
94};
95
96template <int N, int M>
97struct NumberOfRows<Eigen::Matrix<double, N, M, Eigen::RowMajor, N, M>>
98 : std::integral_constant<unsigned, N>
99{
100};
101
102template <typename T>
104
105template <>
106struct NumberOfColumns<double> : std::integral_constant<unsigned, 1>
107{
108};
109
110template <int N>
111struct NumberOfColumns<Eigen::Matrix<double, N, 1, Eigen::ColMajor, N, 1>>
112 : std::integral_constant<unsigned, 1>
113{
114};
115
116template <int N, int M>
117struct NumberOfColumns<Eigen::Matrix<double, N, M, Eigen::RowMajor, N, M>>
118 : std::integral_constant<unsigned, M>
119{
120};
121
122template <typename T>
124 : std::integral_constant<unsigned,
125 NumberOfRows<T>::value * NumberOfColumns<T>::value>
126{
127};
128
184template <int Dim, typename Accessor_IPDataVecInLocAsm,
185 typename Accessor_CurrentLevelFromIPDataVecElement>
187{
188 static_assert(!std::is_reference_v<Accessor_IPDataVecInLocAsm>);
189 static_assert(
190 !std::is_reference_v<Accessor_CurrentLevelFromIPDataVecElement>);
191
192 Accessor_IPDataVecInLocAsm accessor_ip_data_vec_in_loc_asm;
193 Accessor_CurrentLevelFromIPDataVecElement
195
196 template <typename LocAsm>
197 std::vector<double> operator()(LocAsm const& loc_asm) const
198 {
199 using IPDataVector = std::remove_cvref_t<
200 std::invoke_result_t<Accessor_IPDataVecInLocAsm, LocAsm const&>>;
201 using IPDataVectorElement = typename IPDataVector::value_type;
202
203 // the concrete IP data, e.g. double or Eigen::Vector
204 using ConcreteIPData = std::remove_cvref_t<
205 std::invoke_result_t<Accessor_CurrentLevelFromIPDataVecElement,
206 IPDataVectorElement const&>>;
208 "This method only deals with raw data. The given "
209 "ConcreteIPData is not raw data.");
210
211 constexpr unsigned num_rows = NumberOfRows<ConcreteIPData>::value;
212 constexpr unsigned num_cols = NumberOfColumns<ConcreteIPData>::value;
213 constexpr unsigned num_comp = num_rows * num_cols;
214 auto const& ip_data_vector = accessor_ip_data_vec_in_loc_asm(loc_asm);
215 auto const num_ips = ip_data_vector.size();
216
217 std::vector<double> result(num_comp * num_ips);
218
219 for (std::size_t ip = 0; ip < num_ips; ++ip)
220 {
221 auto const& ip_data_vector_element = ip_data_vector[ip];
222 auto const& ip_data =
224 ip_data_vector_element);
225
226 if constexpr (num_comp == 1)
227 {
228 // scalar
229 result[ip] = ip_data;
230 }
231 else if constexpr (num_rows == MathLib::KelvinVector::
233 num_cols == 1)
234 {
235 // Kelvin vector
236 auto const converted =
238 ip_data);
239
240 for (unsigned comp = 0; comp < num_comp; ++comp)
241 {
242 result[ip * num_comp + comp] = converted[comp];
243 }
244 }
245 else if constexpr (num_cols == MathLib::KelvinVector::
247 num_rows == 1)
248 {
249 static_assert(
250 num_rows != 1 /* always false in this branch */,
251 "We support Kelvin column-vectors, but not Kelvin "
252 "row-vectors. The latter are unusual and confusion with "
253 "generic vectors might be possible.");
254 }
255 else if constexpr (num_rows == 1 || num_cols == 1)
256 {
257 // row or column vector
258 for (unsigned comp = 0; comp < num_comp; ++comp)
259 {
260 result[ip * num_comp + comp] = ip_data[comp];
261 }
262 }
263 else
264 {
265 // matrix
266 // row-major traversal
267 for (unsigned row = 0; row < num_rows; ++row)
268 {
269 for (unsigned col = 0; col < num_cols; ++col)
270 {
271 result[ip * num_comp + row * num_cols + col] =
272 ip_data(row, col);
273 }
274 }
275 }
276 }
277 return result;
278 }
279};
280
281// Convenience function for template argument deduction with
282// GetFlattenedIPDataFromLocAsm
283template <int Dim, typename Accessor_IPDataVecInLocAsm,
284 typename Accessor_CurrentLevelFromIPDataVecElement>
285GetFlattenedIPDataFromLocAsm<
286 Dim, std::remove_cvref_t<Accessor_IPDataVecInLocAsm>,
287 std::remove_cvref_t<Accessor_CurrentLevelFromIPDataVecElement>>
289 Accessor_IPDataVecInLocAsm accessor_ip_data_vec_in_loc_asm,
290 Accessor_CurrentLevelFromIPDataVecElement
291 accessor_current_level_from_ip_data_vec_element)
292{
293 return {std::forward<Accessor_IPDataVecInLocAsm>(
294 accessor_ip_data_vec_in_loc_asm),
295 std::forward<Accessor_CurrentLevelFromIPDataVecElement>(
296 accessor_current_level_from_ip_data_vec_element)};
297}
298
299// Convenience function for template argument deduction with
300// GetFlattenedIPDataFromLocAsm. Overload of the function above with less
301// arguments.
302template <int Dim, typename Accessor_IPDataVecInLocAsm>
304 Accessor_IPDataVecInLocAsm&& accessor_ip_data_vec_in_loc_asm)
305{
306 return getFlattenedIPDataFromLocAsm<Dim>(
307 std::forward<Accessor_IPDataVecInLocAsm>(
308 accessor_ip_data_vec_in_loc_asm),
309 std::identity{});
310}
311
322template <int Dim, typename Callback, typename ReflectionDataTuple,
323 typename Accessor_IPDataVecInLocAsm,
324 typename Accessor_CurrentLevelFromIPDataVecElement>
326 Callback const& callback, ReflectionDataTuple const& reflection_data,
327 Accessor_IPDataVecInLocAsm const& accessor_ip_data_vec_in_loc_asm,
328 Accessor_CurrentLevelFromIPDataVecElement const&
329 accessor_current_level_from_ip_data_vec_element)
330{
331 boost::mp11::tuple_for_each(
332 reflection_data,
333 [&accessor_ip_data_vec_in_loc_asm,
334 &accessor_current_level_from_ip_data_vec_element,
335 &callback]<typename Class, typename Accessor>(
336 ReflectionData<Class, Accessor> const& refl_data)
337 {
338 using MemberRef = std::invoke_result_t<Accessor, Class const&>;
339 using Member = std::remove_cvref_t<MemberRef>;
340
341 auto accessor_member_from_ip_data_vec_element =
342 [accessor_next_level = refl_data.accessor,
343 accessor_current_level_from_ip_data_vec_element](
344 auto const& ip_data_vec_element) -> Member const&
345 {
346 return accessor_next_level(
347 accessor_current_level_from_ip_data_vec_element(
348 ip_data_vec_element));
349 };
350
351 if constexpr (is_reflectable<Member>)
352 {
353 forEachReflectedFlattenedIPDataAccessor<Dim>(
354 callback, detail::reflect(std::type_identity<Member>{}),
355 accessor_ip_data_vec_in_loc_asm,
356 accessor_member_from_ip_data_vec_element);
357 }
358 else
359 {
360 static_assert(is_raw_data<Member>::value,
361 "The current member is not reflectable, so we "
362 "expect it to be raw data.");
363
364 constexpr unsigned num_comp = NumberOfComponents<Member>::value;
365
366 callback(refl_data.name, num_comp,
367 getFlattenedIPDataFromLocAsm<Dim>(
368 accessor_ip_data_vec_in_loc_asm,
369 accessor_member_from_ip_data_vec_element));
370 }
371 });
372}
373
374// Overload of the function above with less arguments
375template <int Dim, typename Callback, typename ReflectionDataTuple,
376 typename Accessor_IPDataVecInLocAsm>
378 Callback const& callback,
379 ReflectionDataTuple const& reflection_data,
380 Accessor_IPDataVecInLocAsm const& accessor_ip_data_vec_in_loc_asm)
381{
382 forEachReflectedFlattenedIPDataAccessor<Dim>(
383 callback, reflection_data, accessor_ip_data_vec_in_loc_asm,
384 std::identity{});
385}
386
387} // namespace detail
388
400template <int Dim, typename LocAsmIF, typename Callback, typename ReflData>
401void forEachReflectedFlattenedIPDataAccessor(ReflData const& reflection_data,
402 Callback const& callback)
403{
404 boost::mp11::tuple_for_each(
405 reflection_data,
406 [&callback]<typename Class, typename Accessor>(
407 ReflectionData<Class, Accessor> const& refl_data)
408 {
409 static_assert(std::is_same_v<Class, LocAsmIF>,
410 "The currently processed reflection data is not for "
411 "the given LocAsmIF but for a different class.");
412
413 using AccessorResultRef =
414 std::invoke_result_t<Accessor, Class const&>;
415 using AccessorResult = std::remove_cvref_t<AccessorResultRef>;
416
417 // AccessorResult must be a std::vector<SomeType, SomeAllocator>. We
418 // check that, now.
419 static_assert(boost::mp11::mp_is_list<AccessorResult>::
420 value); // std::vector<SomeType, SomeAllocator>
421 // is a list in the Boost MP11 sense
422 static_assert(
423 std::is_same_v<
424 AccessorResult,
425 boost::mp11::mp_rename<AccessorResult, std::vector>>,
426 "We expect a std::vector, here.");
427 // Now, we know that AccessorResult is std::vector<Member>. To be
428 // more specific, AccessorResult is a std::vector<IPData> and Member
429 // is IPData.
430 using Member = typename AccessorResult::value_type;
431
432 auto accessor_ip_data_vec_in_loc_asm =
433 [ip_data_vector_accessor =
434 refl_data.accessor](LocAsmIF const& loc_asm) -> auto const&
435 { return ip_data_vector_accessor(loc_asm); };
436
437 if constexpr (detail::is_reflectable<Member>)
438 {
439 detail::forEachReflectedFlattenedIPDataAccessor<Dim>(
440 callback,
441 detail::reflect(std::type_identity<Member>{}),
442 accessor_ip_data_vec_in_loc_asm);
443 }
444 else
445 {
447 "The current member is not reflectable, so we "
448 "expect it to be raw data.");
449
450 constexpr unsigned num_comp =
452
453 callback(refl_data.name, num_comp,
454 detail::getFlattenedIPDataFromLocAsm<Dim>(
455 accessor_ip_data_vec_in_loc_asm));
456 }
457 });
458}
459} // namespace ProcessLib::Reflection
Eigen::Matrix< double, 4, 1 > kelvinVectorToSymmetricTensor(Eigen::Matrix< double, 4, 1, Eigen::ColMajor, 4, 1 > const &v)
constexpr int kelvin_vector_dimensions(int const displacement_dim)
Kelvin vector dimensions for given displacement dimension.
GetFlattenedIPDataFromLocAsm< Dim, std::remove_cvref_t< Accessor_IPDataVecInLocAsm >, std::remove_cvref_t< Accessor_CurrentLevelFromIPDataVecElement > > getFlattenedIPDataFromLocAsm(Accessor_IPDataVecInLocAsm accessor_ip_data_vec_in_loc_asm, Accessor_CurrentLevelFromIPDataVecElement accessor_current_level_from_ip_data_vec_element)
auto reflect(std::type_identity< std::tuple< Ts... > >)
void forEachReflectedFlattenedIPDataAccessor(Callback const &callback, ReflectionDataTuple const &reflection_data, Accessor_IPDataVecInLocAsm const &accessor_ip_data_vec_in_loc_asm, Accessor_CurrentLevelFromIPDataVecElement const &accessor_current_level_from_ip_data_vec_element)
void forEachReflectedFlattenedIPDataAccessor(ReflData const &reflection_data, Callback const &callback)
auto reflectWithoutName(Accessors &&... accessors)
Accessor_CurrentLevelFromIPDataVecElement accessor_current_level_from_ip_data_vec_element
std::vector< double > operator()(LocAsm const &loc_asm) const