/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/discretization/coordinates/coordinates.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/discretization/coordinates/coordinates.hh Source File
DiFfRG
coordinates.hh
Go to the documentation of this file.
1#pragma once
2
3// standard library
4#include <cmath>
5#include <cstddef>
6#include <stdexcept>
7#include <tuple>
8#include <type_traits>
9#include <vector>
10
11// DiFfRG
14
15namespace DiFfRG
16{
17 // A concept for what is a coordinate class
18 template <typename T>
19 concept is_coordinates = requires(T t) {
20 typename T::ctype;
21 T::dim;
22 t.size();
24 { t.from_linear_index(size_t{}) } -> std::same_as<device::array<size_t, T::dim>>;
25 };
26
32 template <typename... Coordinates> class CoordinatePackND
33 {
34 // Assert that all coordinates have the same ctype
35 static_assert((std::is_same<typename Coordinates::ctype,
36 typename device::tuple_element<0, device::tuple<Coordinates...>>::type::ctype>::value &&
37 ...),
38 "CoordinatePackND: all coordinate systems must use the same ctype");
39 static_assert(sizeof...(Coordinates) > 0, "CoordinatePackND requires at least one coordinate system");
40 // Assert that all coordinates have the dim 1
41 static_assert(((Coordinates::dim == 1) && ...), "CoordinatePackND requires all coordinates to have dim 1");
42
43 public:
44 using ctype = typename device::tuple_element<0, device::tuple<Coordinates...>>::type::ctype;
45 static constexpr size_t dim = sizeof...(Coordinates);
46
53
54 template <typename... I>
55 requires(std::is_convertible_v<std::decay_t<I>, size_t> && ...)
56 KOKKOS_FORCEINLINE_FUNCTION device::array<ctype, dim> forward(I &&...i) const
57 {
58 static_assert(sizeof...(I) == sizeof...(Coordinates));
59 return forward_impl(device::make_integer_sequence<int, sizeof...(I)>(), device::forward<I>(i)...);
60 }
61 template <typename IT>
62 KOKKOS_FORCEINLINE_FUNCTION device::array<ctype, dim> forward(const device::array<IT, dim> &coords) const
63 {
64 return device::apply([&](const auto &...iargs) { return forward(iargs...); }, coords);
65 }
66
67 template <typename... I, int... Is>
68 device::array<ctype, dim> KOKKOS_FORCEINLINE_FUNCTION forward_impl(device::integer_sequence<int, Is...>,
69 I &&...i) const
70 {
71 return {{device::get<Is>(coordinates).forward(device::get<Is>(device::tie(i...)))...}};
72 }
73
74 template <typename... I> KOKKOS_FORCEINLINE_FUNCTION device::array<ctype, sizeof...(I)> backward(I &&...i) const
75 {
76 static_assert(sizeof...(I) == sizeof...(Coordinates));
77 return backward_impl(device::make_integer_sequence<int, sizeof...(I)>(), device::forward<I>(i)...);
78 }
79
80 template <typename... I, int... Is>
81 device::array<ctype, sizeof...(I)> KOKKOS_FORCEINLINE_FUNCTION backward_impl(device::integer_sequence<int, Is...>,
82 I &&...i) const
83 {
84 return {{device::get<Is>(coordinates).backward(device::get<Is>(device::tie(i...)))...}};
85 }
86
87 template <size_t i> const auto &get_coordinates() const { return device::get<i>(coordinates); }
88
89 size_t KOKKOS_FORCEINLINE_FUNCTION size() const
90 {
91 // multiply all sizes
92 size_t size = 1;
93 constexpr_for<0, sizeof...(Coordinates), 1>([&](auto i) { size *= device::get<i>(coordinates).size(); });
94 return size;
95 }
96
97 device::array<size_t, sizeof...(Coordinates)> KOKKOS_FORCEINLINE_FUNCTION sizes() const
98 {
99 device::array<size_t, sizeof...(Coordinates)> sizes;
100 constexpr_for<0, sizeof...(Coordinates), 1>([&](auto i) { sizes[i] = device::get<i>(coordinates).size(); });
101 return sizes;
102 }
103
104 device::array<size_t, sizeof...(Coordinates)> KOKKOS_INLINE_FUNCTION from_linear_index(size_t s) const
105 {
106 device::array<size_t, sizeof...(Coordinates)> idx;
107 // calculate the index for each coordinate system
108 constexpr_for<0, sizeof...(Coordinates), 1>([&](auto i) {
109 idx[sizeof...(Coordinates) - 1 - i] = s % device::get<sizeof...(Coordinates) - 1 - i>(coordinates).size();
110 s = s / device::get<sizeof...(Coordinates) - 1 - i>(coordinates).size();
111 });
112
113 return idx;
114 }
115
116 template <typename... Coordinates2>
118 {
119 if constexpr (sizeof...(Coordinates) != sizeof...(Coordinates2)) return false; // Different number of coordinates
120 if constexpr ((!std::is_same_v<Coordinates, Coordinates2> && ...))
121 return false; // Different types of coordinates
122 else if constexpr (sizeof...(Coordinates) == 0)
123 return true; // Empty coordinate pack, always equal
124 else {
125 // Check if all coordinates are equal
126 bool equal = true;
127 constexpr_for<0, sizeof...(Coordinates), 1>(
128 [&](auto i) { equal &= (device::get<i>(r.coordinates) == device::get<i>(l.coordinates)); });
129 return equal;
130 }
131 }
132
133 std::string to_string() const
134 {
135 std::string ret = "CoordinatePackND(";
136 constexpr_for<0, dim, 1>([&](auto i) {
137 ret += device::get<i>(coordinates).to_string();
138 if (i + 1 < dim) ret += ", ";
139 });
140 ret += ")";
141 return ret;
142 }
143
144 protected:
145 const device::tuple<Coordinates...> coordinates;
146 };
147
148 template <typename Base> class SubCoordinates : public Base
149 {
150 public:
151 using ctype = typename Base::ctype;
152 static constexpr size_t dim = Base::dim;
153
154 SubCoordinates(const Base &base, size_t offset, size_t size) : Base(base), m_size(size)
155 {
156 if (size == 0) throw std::runtime_error("SubCoordinates: size must be > 0");
157 if (offset + size > base.size()) throw std::runtime_error("SubCoordinates: offset + size must be <= base.size()");
158 // calculate the offsets and sizes from the continuous index
159 offsets = base.from_linear_index(offset);
160 m_sizes = base.from_linear_index(offset + size);
161 for (size_t i = 0; i < dim; ++i)
162 m_sizes[i] -= offsets[i];
163 }
164
165 device::array<size_t, dim> KOKKOS_FORCEINLINE_FUNCTION sizes() const { return m_sizes; }
166
167 size_t KOKKOS_FORCEINLINE_FUNCTION size() const { return m_size; }
168
169 device::array<size_t, dim> KOKKOS_INLINE_FUNCTION from_linear_index(size_t s) const
170 {
172 // we do it for m_sizes
173 for (size_t i = 0; i < dim; ++i) {
174 result[dim - 1 - i] = s % m_sizes[dim - 1 - i];
175 s = s / m_sizes[dim - 1 - i];
176 }
177 return result;
178 }
179
180 template <typename... I>
181 requires(std::is_convertible_v<std::decay_t<I>, size_t> && ...)
182 KOKKOS_FORCEINLINE_FUNCTION device::array<ctype, dim> forward(I &&...i) const
183 {
184 static_assert(sizeof...(I) == dim);
185 return forward({{i...}});
186 }
187
188 template <typename IT> KOKKOS_INLINE_FUNCTION device::array<ctype, dim> forward(device::array<IT, dim> i) const
189 {
190 for (size_t j = 0; j < dim; ++j) {
191 i[j] += offsets[j];
192 }
193 return Base::forward(i);
194 }
195
196 template <typename... I> KOKKOS_FORCEINLINE_FUNCTION device::array<ctype, dim> backward(I &&...i) const
197 {
198 static_assert(sizeof...(I) == dim);
199 return backward({{i...}});
200 }
202 {
203 auto result = Base::backward(i);
204 for (size_t j = 0; j < dim; ++j) {
205 result[j] -= offsets[j];
206 }
207 return result;
208 }
209
210 std::string to_string() const
211 {
212 std::string ret = "SubCoordinates(" + Base::to_string() + ", {";
213 for (uint i = 0; i < dim; ++i) {
214 ret += std::to_string(offsets[i]);
215 if (i + 1 < dim) ret += ", ";
216 }
217 ret += "}, {";
218 for (uint i = 0; i < dim; ++i) {
219 ret += std::to_string(m_sizes[i]);
220 if (i + 1 < dim) ret += ", ";
221 }
222 return ret + "})";
223 }
224
225 private:
227 const size_t m_size;
228 };
229
230 template <typename NT = double>
231 requires std::is_floating_point_v<NT>
233 {
234 public:
235 using ctype = NT;
236 static constexpr size_t dim = 1;
237
240 {
241 if (grid_extent == 0) throw std::runtime_error("LinearCoordinates1D: grid_extent must be > 0");
242 a = (stop - start) / (grid_extent - 1.);
243 }
244
245 template <typename NT2>
247 : LinearCoordinates1D(other.size(), other.start, other.stop)
248 {
249 }
250
251 device::array<size_t, 1> KOKKOS_FORCEINLINE_FUNCTION from_linear_index(size_t i) const
252 {
253 return device::array<size_t, 1>{i};
254 }
255
262 template <typename IT> NT KOKKOS_FORCEINLINE_FUNCTION forward(const IT &x) const { return start + a * x; }
263
264 template <typename IT> device::array<NT, 1> KOKKOS_FORCEINLINE_FUNCTION forward(const device::array<IT, 1> &x) const
265 {
266 return {forward(x[0])};
267 }
268
275 NT KOKKOS_FORCEINLINE_FUNCTION backward(const NT &y) const { return (y - start) / a; }
276
277 size_t KOKKOS_FORCEINLINE_FUNCTION size() const { return grid_extent; }
278
279 device::array<size_t, 1> KOKKOS_FORCEINLINE_FUNCTION sizes() const { return {grid_extent}; }
280
281 const NT start, stop;
282
283 template <typename NT2>
285 {
286 if constexpr (!std::is_same_v<NT, NT2>) return false; // Different types, cannot be equal
287 return lhs.start == rhs.start && lhs.stop == rhs.stop && lhs.grid_extent == rhs.grid_extent;
288 }
289
290 std::string to_string() const
291 {
292 return "LinearCoordinates1D(" + std::to_string(grid_extent) + ", " + std::to_string(start) + ", " +
293 std::to_string(stop) + ")";
294 }
295
296 private:
297 const size_t grid_extent;
298 NT a;
299 };
300
301 template <typename NT = double>
302 requires std::is_floating_point_v<NT>
304 {
305 public:
306 using ctype = NT;
307 static constexpr size_t dim = 1;
308
311 gem1inv(1. / (grid_extent - 1.))
312 {
313 if (grid_extent == 0) throw std::runtime_error("LogarithmicCoordinates1D: grid_extent must be > 0");
314 using Kokkos::expm1;
315 a = bias;
316 b = (stop - start) / expm1(a);
317 c = start;
318 }
319
320 template <typename NT2>
322 : LogarithmicCoordinates1D(other.size(), other.start, other.stop, other.bias)
323 {
324 }
325
326 device::array<size_t, 1> KOKKOS_FORCEINLINE_FUNCTION from_linear_index(size_t i) const
327 {
328 return device::array<size_t, 1>{i};
329 }
330
337 template <typename IT> NT KOKKOS_FORCEINLINE_FUNCTION forward(const IT &x) const
338 {
339 using Kokkos::expm1;
340 return b * expm1(a * x * gem1inv) + c;
341 }
342
343 template <typename IT> device::array<NT, 1> KOKKOS_FORCEINLINE_FUNCTION forward(const device::array<IT, 1> &x) const
344 {
345 return {forward(x[0])};
346 }
347
354 NT KOKKOS_FORCEINLINE_FUNCTION backward(const NT &y) const
355 {
356 using Kokkos::log1p;
357 return log1p((y - c) / b) * gem1 / a;
358 }
359
360 NT KOKKOS_FORCEINLINE_FUNCTION backward_derivative(const NT &y) const { return 1. / (y - c) * gem1 / a; }
361
362 size_t KOKKOS_FORCEINLINE_FUNCTION size() const { return grid_extent; }
363
364 device::array<size_t, 1> KOKKOS_FORCEINLINE_FUNCTION sizes() const { return {grid_extent}; }
365
366 const NT start, stop, bias;
367
368 template <typename NT2>
370 {
371 if constexpr (!std::is_same_v<NT, NT2>) return false; // Different types, cannot be equal
372 return lhs.start == rhs.start && lhs.stop == rhs.stop && lhs.bias == rhs.bias &&
373 lhs.grid_extent == rhs.grid_extent;
374 }
375
376 std::string to_string() const
377 {
378 return "LogarithmicCoordinates1D(" + std::to_string(start) + ", " + std::to_string(stop) + ", " +
379 std::to_string(bias) + ", " + std::to_string(grid_extent) + ")";
380 }
381
382 private:
383 const size_t grid_extent;
384 const NT gem1, gem1inv;
385 NT a, b, c;
386 };
387
388 template <typename Coordinates> auto make_grid(const Coordinates &coordinates)
389 {
390 using ctype = typename Coordinates::ctype;
392 std::vector<cortype> grid(coordinates.size());
393 for (size_t i = 0; i < coordinates.size(); ++i) {
394 const auto forwarded = coordinates.forward(coordinates.from_linear_index(i));
395 for (size_t j = 0; j < Coordinates::dim; ++j) {
396 grid[i][j] = forwarded[j];
397 }
398 }
399 return grid;
400 }
401
402 template <typename Coordinates> auto make_idx_grid(const Coordinates &coordinates) -> std::vector<double>
403 {
404 using ctype = typename Coordinates::ctype;
406 std::vector<cortype> grid(coordinates.size());
407 for (size_t i = 0; i < coordinates.size(); ++i) {
408 const auto forwarded = coordinates.from_linear_index(i);
409 for (size_t j = 0; j < Coordinates::dim; ++j) {
410 grid[i][j] = forwarded[j];
411 }
412 }
413 return grid;
414 }
415
416 template <typename Coordinates> std::vector<typename Coordinates::ctype> dump_grid(const Coordinates &coordinates)
417 {
418 using ctype = typename Coordinates::ctype;
419 std::vector<typename Coordinates::ctype> grid(coordinates.size() * Coordinates::dim);
420 for (size_t i = 0; i < coordinates.size(); ++i) {
421 for (size_t j = 0; j < Coordinates::dim; ++j) {
422 const auto forwarded = coordinates.forward(coordinates.from_linear_index(i));
423 grid[i * coordinates.dim + j] = forwarded[j];
424 }
425 }
426 return grid;
427 }
428
429 // Definitions of useful combined coordinates
442} // namespace DiFfRG
Utility class for combining multiple coordinate systems into one.
Definition coordinates.hh:33
const auto & get_coordinates() const
Definition coordinates.hh:87
KOKKOS_FORCEINLINE_FUNCTION device::array< ctype, sizeof...(I)> backward(I &&...i) const
Definition coordinates.hh:74
size_t KOKKOS_FORCEINLINE_FUNCTION size() const
Definition coordinates.hh:89
std::string to_string() const
Definition coordinates.hh:133
KOKKOS_FORCEINLINE_FUNCTION device::array< ctype, dim > forward(I &&...i) const
Definition coordinates.hh:56
static constexpr size_t dim
Definition coordinates.hh:45
device::array< size_t, sizeof...(Coordinates)> KOKKOS_INLINE_FUNCTION from_linear_index(size_t s) const
Definition coordinates.hh:104
CoordinatePackND(Coordinates... coordinates)
Construct a new CoordinatePackND object.
Definition coordinates.hh:52
device::array< ctype, sizeof...(I)> KOKKOS_FORCEINLINE_FUNCTION backward_impl(device::integer_sequence< int, Is... >, I &&...i) const
Definition coordinates.hh:81
friend bool operator==(const CoordinatePackND< Coordinates... > &r, const CoordinatePackND< Coordinates2... > &l)
Definition coordinates.hh:117
device::array< size_t, sizeof...(Coordinates)> KOKKOS_FORCEINLINE_FUNCTION sizes() const
Definition coordinates.hh:97
device::array< ctype, dim > KOKKOS_FORCEINLINE_FUNCTION forward_impl(device::integer_sequence< int, Is... >, I &&...i) const
Definition coordinates.hh:68
const device::tuple< Coordinates... > coordinates
Definition coordinates.hh:145
KOKKOS_FORCEINLINE_FUNCTION device::array< ctype, dim > forward(const device::array< IT, dim > &coords) const
Definition coordinates.hh:62
typename device::tuple_element< 0, device::tuple< Coordinates... > >::type::ctype ctype
Definition coordinates.hh:44
Definition coordinates.hh:233
device::array< size_t, 1 > KOKKOS_FORCEINLINE_FUNCTION from_linear_index(size_t i) const
Definition coordinates.hh:251
friend bool operator==(const LinearCoordinates1D< NT > &lhs, const LinearCoordinates1D< NT2 > &rhs)
Definition coordinates.hh:284
LinearCoordinates1D(size_t grid_extent, double start, double stop)
Definition coordinates.hh:238
NT KOKKOS_FORCEINLINE_FUNCTION backward(const NT &y) const
Transform from the physical space to the grid.
Definition coordinates.hh:275
NT a
Definition coordinates.hh:298
static constexpr size_t dim
Definition coordinates.hh:236
const NT stop
Definition coordinates.hh:281
std::string to_string() const
Definition coordinates.hh:290
size_t KOKKOS_FORCEINLINE_FUNCTION size() const
Definition coordinates.hh:277
const NT start
Definition coordinates.hh:281
NT KOKKOS_FORCEINLINE_FUNCTION forward(const IT &x) const
Transform from the grid to the physical space.
Definition coordinates.hh:262
NT ctype
Definition coordinates.hh:235
LinearCoordinates1D(const LinearCoordinates1D< NT2 > &other)
Definition coordinates.hh:246
const size_t grid_extent
Definition coordinates.hh:297
device::array< size_t, 1 > KOKKOS_FORCEINLINE_FUNCTION sizes() const
Definition coordinates.hh:279
device::array< NT, 1 > KOKKOS_FORCEINLINE_FUNCTION forward(const device::array< IT, 1 > &x) const
Definition coordinates.hh:264
Definition coordinates.hh:304
const NT gem1
Definition coordinates.hh:384
LogarithmicCoordinates1D(const LogarithmicCoordinates1D< NT2 > &other)
Definition coordinates.hh:321
device::array< size_t, 1 > KOKKOS_FORCEINLINE_FUNCTION from_linear_index(size_t i) const
Definition coordinates.hh:326
NT KOKKOS_FORCEINLINE_FUNCTION backward_derivative(const NT &y) const
Definition coordinates.hh:360
const NT stop
Definition coordinates.hh:366
friend bool operator==(const LogarithmicCoordinates1D< NT > &lhs, const LogarithmicCoordinates1D< NT2 > &rhs)
Definition coordinates.hh:369
const NT gem1inv
Definition coordinates.hh:384
device::array< size_t, 1 > KOKKOS_FORCEINLINE_FUNCTION sizes() const
Definition coordinates.hh:364
std::string to_string() const
Definition coordinates.hh:376
NT KOKKOS_FORCEINLINE_FUNCTION forward(const IT &x) const
Transform from the grid to the physical space.
Definition coordinates.hh:337
const NT start
Definition coordinates.hh:366
NT a
Definition coordinates.hh:385
NT KOKKOS_FORCEINLINE_FUNCTION backward(const NT &y) const
Transform from the physical space to the grid.
Definition coordinates.hh:354
size_t KOKKOS_FORCEINLINE_FUNCTION size() const
Definition coordinates.hh:362
NT ctype
Definition coordinates.hh:306
device::array< NT, 1 > KOKKOS_FORCEINLINE_FUNCTION forward(const device::array< IT, 1 > &x) const
Definition coordinates.hh:343
LogarithmicCoordinates1D(size_t grid_extent, NT start, NT stop, NT bias)
Definition coordinates.hh:309
const NT bias
Definition coordinates.hh:366
NT b
Definition coordinates.hh:385
NT c
Definition coordinates.hh:385
static constexpr size_t dim
Definition coordinates.hh:307
const size_t grid_extent
Definition coordinates.hh:383
Definition coordinates.hh:149
const size_t m_size
Definition coordinates.hh:227
KOKKOS_FORCEINLINE_FUNCTION device::array< ctype, dim > forward(I &&...i) const
Definition coordinates.hh:182
KOKKOS_INLINE_FUNCTION device::array< ctype, dim > forward(device::array< IT, dim > i) const
Definition coordinates.hh:188
KOKKOS_FORCEINLINE_FUNCTION device::array< ctype, dim > backward(I &&...i) const
Definition coordinates.hh:196
size_t KOKKOS_FORCEINLINE_FUNCTION size() const
Definition coordinates.hh:167
device::array< size_t, dim > offsets
Definition coordinates.hh:226
static constexpr size_t dim
Definition coordinates.hh:152
device::array< size_t, dim > KOKKOS_INLINE_FUNCTION from_linear_index(size_t s) const
Definition coordinates.hh:169
SubCoordinates(const Base &base, size_t offset, size_t size)
Definition coordinates.hh:154
std::string to_string() const
Definition coordinates.hh:210
typename Base::ctype ctype
Definition coordinates.hh:151
KOKKOS_INLINE_FUNCTION device::array< ctype, dim > backward(device::array< size_t, dim > i) const
Definition coordinates.hh:201
device::array< size_t, dim > m_sizes
Definition coordinates.hh:226
device::array< size_t, dim > KOKKOS_FORCEINLINE_FUNCTION sizes() const
Definition coordinates.hh:165
Definition coordinates.hh:19
std::array< T, N > array
Definition kokkos.hh:133
std::tuple< T... > tuple
Definition kokkos.hh:132
Definition complex_math.hh:10
std::vector< typename Coordinates::ctype > dump_grid(const Coordinates &coordinates)
Definition coordinates.hh:416
constexpr void constexpr_for(F &&f)
A compile-time for loop, which calls the lambda f of signature void(integer) for each index.
Definition utils.hh:31
auto make_idx_grid(const Coordinates &coordinates) -> std::vector< double >
Definition coordinates.hh:402
unsigned int uint
Definition utils.hh:24
auto make_grid(const Coordinates &coordinates)
Definition coordinates.hh:388