/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/common/tuples.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/common/tuples.hh Source File
DiFfRG
Discretization Framework for functional Renormalization Group flows
tuples.hh
Go to the documentation of this file.
1#pragma once
2
3// standard library
4#include <cmath>
5#include <cstring>
6#include <iostream>
7#include <string_view>
8#include <tuple>
9#include <utility>
10#include <vector>
11
12// DiFfRG
14
15namespace DiFfRG
16{
20 template <typename T>
21 concept NamedTuple = requires(T t) {
22 typename T::tuple_type;
23 typename T::tuple_names;
24 { t.tuple } -> std::same_as<typename T::tuple_type>;
25 { t.names } -> std::same_as<typename T::tuple_names>;
26 { t.size } -> std::same_as<size_t>;
27 };
28
32 constexpr bool strings_equal(char const *a, char const *b) { return std::string_view(a) == b; }
33
34 template <FixedString... strs> struct StringSet {
35 static constexpr size_t size = sizeof...(strs);
36 static constexpr std::array<const char *, size> names{{strs...}};
37
38 // If two names are the same, the program should not compile
39 static_assert(
40 []<size_t... I>(std::index_sequence<I...>) {
41 for (size_t i : {I...})
42 for (size_t j : {I...})
43 if (i != j && strings_equal(names[i], names[j])) return false;
44 return true;
45 }(std::make_index_sequence<size>{}),
46 "Names of a StringSet must be unique!");
47 };
48
56 template <typename tuple_type, typename tuple_names> struct named_tuple {
57 static_assert(tuple_names::size == std::tuple_size_v<tuple_type>,
58 "Number of names must match number of elements in tuple");
59 tuple_type tuple;
60
61 constexpr operator tuple_type &() { return tuple; }
62
63 static constexpr size_t size = tuple_names::size;
64 static constexpr auto names = tuple_names::names;
65
66 // If two names are the same, the program should not compile
67 static_assert(
68 []<size_t... I>(std::index_sequence<I...>) {
69 for (size_t i : {I...})
70 for (size_t j : {I...})
71 if (i != j && strings_equal(names[i], names[j])) return false;
72 return true;
73 }(std::make_index_sequence<size>{}),
74 "Names of a named_tuple must be unique!");
75
76 named_tuple(tuple_type &&t) : tuple(t) {}
77 named_tuple(tuple_type &t) : tuple(t) {}
78
84 template <typename... T> static constexpr auto as(std::tuple<T...> &&tup)
85 {
86 return named_tuple<std::tuple<T...>, tuple_names>(tup);
87 }
88
94 template <typename... T> static constexpr auto as(std::tuple<T...> &tup)
95 {
96 return named_tuple<std::tuple<T...>, tuple_names>(tup);
97 }
98
99 /*
100 * @brief Get the index of the element with the given name.
101 */
102 static consteval size_t get_idx(const char *name)
103 {
104 size_t running_sum = 0;
105 for (size_t i = 0; i < names.size(); ++i) {
106 // this is a way to compare two strings at compile time https://stackoverflow.com/a/53762940
107 if (strings_equal(names[i], name)) return i;
108 running_sum += 1;
109 }
110 // produce a compile-time error if the name is not found in the list
111 return size != running_sum
112 ? 0
113 : throw std::invalid_argument("named_tuple::get_idx: Name \"" + std::string(name) +
114 "\" not found. Available names are: " + ((std::string("") + "; ") + ""));
115 }
116
117 template <size_t idx> auto &get() { return std::get<idx>(tuple); }
118 template <size_t idx> const auto &get() const { return std::get<idx>(tuple); }
119 };
120
124 template <FixedString name, typename tuple_type, typename strSet>
126 {
127 constexpr size_t idx = named_tuple<tuple_type, strSet>::get_idx(name);
128 return ob.template get<idx>();
129 }
130 template <FixedString name, typename tuple_type, typename strSet>
132 {
133 constexpr size_t idx = named_tuple<tuple_type, strSet>::get_idx(name);
134 return ob.template get<idx>();
135 }
136 template <FixedString name, typename tuple_type, typename strSet>
137 constexpr auto &get(const named_tuple<tuple_type, strSet> &ob)
138 {
139 return std::get<named_tuple<tuple_type, strSet>::get_idx(name)>(ob.tuple);
140 }
141
142 template <size_t idx, typename tuple_type, typename strSet> constexpr auto &get(named_tuple<tuple_type, strSet> &ob)
143 {
144 return ob.template get<idx>();
145 }
146 template <size_t idx, typename tuple_type, typename strSet> constexpr auto &get(named_tuple<tuple_type, strSet> &&ob)
147 {
148 return ob.template get<idx>();
149 }
150 template <size_t idx, typename tuple_type, typename strSet>
151 constexpr auto &get(const named_tuple<tuple_type, strSet> &ob)
152 {
153 return ob.template get<idx>();
154 }
155} // namespace DiFfRG
156
157// Intense Voodoo
158namespace DiFfRG
159{
160 // ----------------------------------------------------------------------
161 // AD helpers. The following are used to process the jacobians via
162 // automatic differentiation. Most of these methods are used in the
163 // file model/AD.hh
164 // ----------------------------------------------------------------------
165
169 template <typename NT, uint N, uint M = N> class SimpleMatrix
170 {
171 public:
173
177 NT &operator()(const uint n, const uint m) { return data[n * M + m]; }
178
182 const NT &operator()(const uint n, const uint m) const { return data[n * M + m]; }
183
187 void clear()
188 {
189 for (uint i = 0; i < N * M; ++i)
190 data[i] = 0.;
191 }
192
193 bool is_finite() const
194 {
195 if constexpr (std::is_floating_point_v<NT>) {
196 for (uint i = 0; i < N * M; ++i)
197 if (!std::isfinite(data[i])) return false;
198 }
199 return true;
200 }
201
205 void print() const
206 {
207 for (uint i = 0; i < N; ++i) {
208 for (uint j = 0; j < M; ++j)
209 std::cout << data[i * M + j] << " ";
210 std::cout << std::endl;
211 }
212 }
213
214 private:
215 std::array<NT, N * M> data;
216 };
217
218 template <uint n, typename NT, typename Vector> std::array<NT, n> vector_to_array(const Vector &v)
219 {
220 std::array<NT, n> x;
221 for (uint i = 0; i < n; ++i)
222 x[i] = v[i];
223 return x;
224 }
225
226 template <typename T, std::size_t... Indices>
227 auto vector_to_tuple_helper(const std::vector<T> &v, std::index_sequence<Indices...>)
228 {
229 return std::tie(v[Indices]...);
230 }
231 template <std::size_t N, typename T> auto vector_to_tuple(const std::vector<T> &v)
232 {
233 assert(v.size() >= N);
234 return vector_to_tuple_helper(v, std::make_index_sequence<N>());
235 }
236
237 template <typename Head, typename... Tail> constexpr auto tuple_tail(const std::tuple<Head, Tail...> &t)
238 {
239 return std::apply([](auto & /*head*/, auto &...tail) { return std::tie(tail...); }, t);
240 }
241 // also for named tuple
242 template <typename tuple_type, typename strSet> constexpr auto tuple_tail(const named_tuple<tuple_type, strSet> &t)
243 {
244 return tuple_tail(t.tuple);
245 }
246
247 template <int i, typename Head, typename... Tail> constexpr auto tuple_last(const std::tuple<Head, Tail...> &t)
248 {
249 if constexpr (sizeof...(Tail) == i)
250 return std::apply([](auto & /*head*/, auto &...tail) { return std::tie(tail...); }, t);
251 else
252 return std::apply([](auto & /*head*/, auto &...tail) { return tuple_last<i>(std::tie(tail...)); }, t);
253 }
254 // also for named tuple
255 template <int i, typename tuple_type, typename strSet>
257 {
258 return tuple_last<i>(t.tuple);
259 }
260
261 template <int i, typename Head, typename... Tail> constexpr auto tuple_first(const std::tuple<Head, Tail...> &t)
262 {
263 if constexpr (i == 0)
264 return std::tuple();
265 else if constexpr (i == 1)
266 return std::apply([](auto &head, auto &.../*tail*/) { return std::tie(head); }, t);
267 else
268 return std::apply(
269 [](auto &head, auto &...tail) {
270 return std::tuple_cat(std::tie(head), tuple_first<i - 1>(std::tie(tail...)));
271 },
272 t);
273 }
274 // also for named tuple
275 template <int i, typename tuple_type, typename strSet>
277 {
278 return tuple_first<i>(t.tuple);
279 }
280
281 // ----------------------------------------------------------------------
282 // Helper functions to get the local solution at a given q_index.
283 // This is specifically for the local solutions of the subsystems,
284 // i.e. only used by the LDG assembler.
285 // ----------------------------------------------------------------------
286
287 template <typename T, size_t N, size_t... IDXs>
288 auto _local_sol_tuple(const std::array<T, N> &a, std::index_sequence<IDXs...>, uint q_index)
289 {
290 return std::tie(a[IDXs][q_index]...);
291 }
292 template <typename T, size_t N> auto local_sol_q(const std::array<T, N> &a, uint q_index)
293 {
294 return _local_sol_tuple(a, std::make_index_sequence<N>{}, q_index);
295 }
296
297 template <typename T_inner, typename Model, size_t... IDXs> auto _jacobian_tuple(std::index_sequence<IDXs...>)
298 {
299 return std::tuple{SimpleMatrix<T_inner, Model::Components::count_fe_functions(0),
300 Model::Components::count_fe_functions(IDXs)>()...};
301 }
302 template <typename T_inner, typename Model> auto jacobian_tuple()
303 {
304 return _jacobian_tuple<T_inner, Model>(std::make_index_sequence<Model::Components::count_fe_subsystems()>{});
305 }
306
307 template <typename T_inner, typename Model, size_t... IDXs> auto _jacobian_2_tuple(std::index_sequence<IDXs...>)
308 {
309 return std::tuple{std::array<
310 SimpleMatrix<T_inner, Model::Components::count_fe_functions(0), Model::Components::count_fe_functions(IDXs)>,
311 2>()...};
312 }
313 template <typename T_inner, typename Model> auto jacobian_2_tuple()
314 {
315 return _jacobian_2_tuple<T_inner, Model>(std::make_index_sequence<Model::Components::count_fe_subsystems()>{});
316 }
317} // namespace DiFfRG
A simple NxM-matrix class, which is used for cell-wise Jacobians.
Definition tuples.hh:170
const NT & operator()(const uint n, const uint m) const
Access the matrix entry at (n,m).
Definition tuples.hh:182
NT & operator()(const uint n, const uint m)
Access the matrix entry at (n,m).
Definition tuples.hh:177
SimpleMatrix()
Definition tuples.hh:172
std::array< NT, N *M > data
Definition tuples.hh:215
void clear()
Set all entries to zero.
Definition tuples.hh:187
bool is_finite() const
Definition tuples.hh:193
void print() const
Print the matrix to the console.
Definition tuples.hh:205
Concept for a named tuple.
Definition tuples.hh:21
Definition complex_math.hh:10
constexpr auto tuple_tail(const std::tuple< Head, Tail... > &t)
Definition tuples.hh:237
auto _jacobian_tuple(std::index_sequence< IDXs... >)
Definition tuples.hh:297
constexpr auto tuple_first(const std::tuple< Head, Tail... > &t)
Definition tuples.hh:261
auto _jacobian_2_tuple(std::index_sequence< IDXs... >)
Definition tuples.hh:307
auto local_sol_q(const std::array< T, N > &a, uint q_index)
Definition tuples.hh:292
auto jacobian_tuple()
Definition tuples.hh:302
auto vector_to_tuple_helper(const std::vector< T > &v, std::index_sequence< Indices... >)
Definition tuples.hh:227
auto _local_sol_tuple(const std::array< T, N > &a, std::index_sequence< IDXs... >, uint q_index)
Definition tuples.hh:288
auto vector_to_tuple(const std::vector< T > &v)
Definition tuples.hh:231
consteval bool strings_equal(FixedString< N1 > s1, FixedString< N2 > s2)
Definition fixed_string.hh:49
auto jacobian_2_tuple()
Definition tuples.hh:313
constexpr auto & get(named_tuple< tuple_type, strSet > &ob)
get a reference to the element with the given name
Definition tuples.hh:125
std::array< NT, n > vector_to_array(const Vector &v)
Definition tuples.hh:218
unsigned int uint
Definition utils.hh:24
constexpr auto tuple_last(const std::tuple< Head, Tail... > &t)
Definition tuples.hh:247
A fixed size compile-time string.
Definition fixed_string.hh:12
Definition tuples.hh:34
static constexpr size_t size
Definition tuples.hh:35
static constexpr std::array< const char *, size > names
Definition tuples.hh:36
A class to store a tuple with elements that can be accessed by name. The names are stored as FixedStr...
Definition tuples.hh:56
static constexpr size_t size
Definition tuples.hh:63
static constexpr auto as(std::tuple< T... > &tup)
Convert from a tuple to a named_tuple.
Definition tuples.hh:94
named_tuple(tuple_type &&t)
Definition tuples.hh:76
static constexpr auto names
Definition tuples.hh:64
const auto & get() const
Definition tuples.hh:118
static constexpr auto as(std::tuple< T... > &&tup)
Convert from a tuple to a named_tuple.
Definition tuples.hh:84
auto & get()
Definition tuples.hh:117
tuple_type tuple
Definition tuples.hh:59
static consteval size_t get_idx(const char *name)
Definition tuples.hh:102
named_tuple(tuple_type &t)
Definition tuples.hh:77