Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : #pragma once
11 :
12 : // MOOSE includes
13 : #include "Moose.h"
14 : #include "MooseTypes.h"
15 : #include "RankTwoTensorForward.h"
16 : #include "RankFourTensorForward.h"
17 :
18 : #include <tuple>
19 :
20 : namespace Moose
21 : {
22 :
23 : /**
24 : * Serial access requires object data to be stored contiguously. Specialize this template
25 : * to support more types.
26 : */
27 : template <typename T>
28 : struct SerialAccess
29 : {
30 : static_assert(always_false<T>, "Specialize SerialAccess for this type.");
31 : };
32 :
33 : // Specializations for scalar types
34 : #define SERIAL_ACCESS_SCALAR(type) \
35 : template <> \
36 : struct SerialAccess<type> \
37 : { \
38 : static type * data(type & obj) { return &obj; } \
39 : static constexpr std::size_t size(type &) { return 1u; } \
40 : static constexpr std::size_t size() { return 1u; } \
41 : }
42 :
43 119941 : SERIAL_ACCESS_SCALAR(Real);
44 38403 : SERIAL_ACCESS_SCALAR(const Real);
45 3 : SERIAL_ACCESS_SCALAR(ADReal);
46 0 : SERIAL_ACCESS_SCALAR(const ADReal);
47 :
48 : // constant size containers
49 : #define SERIAL_ACCESS_CONST_SIZE(type, dataptr, sizeval) \
50 : template <typename T> \
51 : struct SerialAccess<type<T>> \
52 : { \
53 : static auto * data(type<T> & obj) { return dataptr; } \
54 : static constexpr std::size_t size(type<T> &) { return sizeval; } \
55 : static constexpr std::size_t size() { return sizeval; } \
56 : }
57 :
58 119944 : SERIAL_ACCESS_CONST_SIZE(libMesh::VectorValue, &obj(0u), Moose::dim);
59 99843 : SERIAL_ACCESS_CONST_SIZE(const libMesh::VectorValue, &obj(0u), Moose::dim);
60 119941 : SERIAL_ACCESS_CONST_SIZE(RankTwoTensorTempl, &obj(0u, 0u), RankTwoTensorTempl<T>::N2);
61 284160 : SERIAL_ACCESS_CONST_SIZE(const RankTwoTensorTempl, &obj(0u, 0u), RankTwoTensorTempl<T>::N2);
62 119941 : SERIAL_ACCESS_CONST_SIZE(RankFourTensorTempl, &obj(0u, 0u, 0u, 0u), RankFourTensorTempl<T>::N4);
63 2496003 : SERIAL_ACCESS_CONST_SIZE(const RankFourTensorTempl,
64 : &obj(0u, 0u, 0u, 0u),
65 : RankFourTensorTempl<T>::N4);
66 :
67 : // dynamic size containers (determining size requires an object instance)
68 : #define SERIAL_ACCESS_DYNAMIC_SIZE(type, dataptr, sizeval) \
69 : template <typename T> \
70 : struct SerialAccess<type<T>> \
71 : { \
72 : static auto * data(type<T> & obj) { return dataptr; } \
73 : static constexpr std::size_t size(type<T> & obj) { return sizeval; } \
74 : }
75 :
76 : SERIAL_ACCESS_DYNAMIC_SIZE(DenseVector, &obj(0u), obj.size());
77 :
78 : /**
79 : * Value type helper (necessary for any type that does not have a value_type
80 : * member or where value_type doesn't have a suitable meaning (ADReal)).
81 : */
82 : template <typename T>
83 : struct SerialAccessValueTypeHelper
84 : {
85 : typedef typename T::value_type value_type;
86 : };
87 : template <>
88 : struct SerialAccessValueTypeHelper<ADReal>
89 : {
90 : typedef ADReal value_type;
91 : };
92 : template <>
93 : struct SerialAccessValueTypeHelper<Real>
94 : {
95 : typedef Real value_type;
96 : };
97 :
98 : template <typename T>
99 : class SerialAccessRange
100 : {
101 : public:
102 : /// Value type of the components of T
103 : typedef typename SerialAccessValueTypeHelper<typename std::remove_const<T>::type>::value_type R;
104 : /// Value type with the correct constness
105 : typedef typename std::conditional<std::is_const_v<T>, const R, R>::type V;
106 :
107 : class iterator
108 : {
109 : public:
110 2265106 : iterator(V * i) : _i(i) {}
111 :
112 4957367 : V & operator*() const { return *_i; }
113 :
114 3994807 : const iterator & operator++()
115 : {
116 3994807 : ++_i;
117 3994807 : return *this;
118 : }
119 :
120 : iterator operator++(int)
121 : {
122 : iterator returnval(*this);
123 : ++_i;
124 : return returnval;
125 : }
126 :
127 4164800 : bool operator==(const iterator & j) const { return (_i == j._i); }
128 4164800 : bool operator!=(const iterator & j) const { return !(*this == j); }
129 :
130 : private:
131 : V * _i;
132 : };
133 :
134 1132553 : SerialAccessRange(T & obj)
135 1132553 : : _begin(SerialAccess<T>::data(obj)),
136 1132553 : _end(SerialAccess<T>::data(obj) + SerialAccess<T>::size(obj))
137 : {
138 1132553 : }
139 :
140 169993 : iterator begin() const { return _begin; }
141 169993 : iterator end() const { return _end; }
142 :
143 962560 : V & operator[](int i) { return *(&*_begin + i); }
144 :
145 : private:
146 : iterator _begin, _end;
147 : };
148 :
149 : template <typename T>
150 : SerialAccessRange<T>
151 1132553 : serialAccess(T & obj)
152 : {
153 1132553 : return SerialAccessRange<T>(obj);
154 : }
155 :
156 : /// Helper structure to hold a list of types
157 : template <typename... Ts>
158 : struct TypeList
159 : {
160 : typedef std::tuple<Ts...> Tuple;
161 : typedef std::tuple<Ts *...> PointerTuple;
162 : static constexpr std::size_t size = sizeof...(Ts);
163 : };
164 :
165 : /// Type loop
166 : template <template <typename, int> class L, int I, typename T, typename... Ts, typename... As>
167 : void
168 1152 : typeLoopInternal(TypeList<T, Ts...>, As... args)
169 : {
170 1152 : L<T, I>::apply(args...);
171 : if constexpr (sizeof...(Ts) > 0)
172 864 : typeLoopInternal<L, I + 1>(TypeList<Ts...>{}, args...);
173 1152 : }
174 :
175 : /// Type loop
176 : template <template <typename, int> class L, typename... Ts, typename... As>
177 : void
178 288 : typeLoop(TypeList<Ts...>, As... args)
179 : {
180 288 : typeLoopInternal<L, 0>(TypeList<Ts...>{}, args...);
181 288 : }
182 :
183 : } // namespace Moose;
|