DiFfRG
Loading...
Searching...
No Matches
coordinates.hh
Go to the documentation of this file.
1#pragma once
2
3// standard library
4#include <cmath>
5#include <stdexcept>
6#include <tuple>
7#include <vector>
8
9// DiFfRG
12
13// A concept for what is a coordinate class
14template <typename T>
15concept IsCoordinate = requires(T t) {
16 T::ctype;
17 T::dim;
18 t.size();
19};
20
21namespace DiFfRG
22{
28 template <typename... Coordinates> class CoordinatePackND
29 {
30 // Assert that all coordinates have the same ctype
31 static_assert((std::is_same<typename Coordinates::ctype,
32 typename std::tuple_element<0, std::tuple<Coordinates...>>::type::ctype>::value &&
33 ...));
34 static_assert(sizeof...(Coordinates) > 0, "CoordinatePackND requires at least one coordinate system");
35 // Assert that all coordinates have the dim 1
36 static_assert(((Coordinates::dim == 1) && ...), "CoordinatePackND requires all coordinates to have dim 1");
37
38 public:
39 using ctype = typename std::tuple_element<0, std::tuple<Coordinates...>>::type::ctype;
40 static constexpr uint dim = sizeof...(Coordinates);
41
48
49 template <typename... I> __forceinline__ __host__ __device__ std::array<ctype, dim> forward(I &&...i) const
50 {
51 static_assert(sizeof...(I) == sizeof...(Coordinates));
52 return forward_impl(std::make_integer_sequence<int, sizeof...(I)>(), std::forward<I>(i)...);
53 }
54
55 template <typename... I, int... Is>
56 __forceinline__ __host__ __device__ std::array<ctype, dim> forward_impl(std::integer_sequence<int, Is...>,
57 I &&...i) const
58 {
59 return {{std::get<Is>(coordinates).forward(std::get<Is>(std::tie(i...)))...}};
60 }
61
62 template <typename... I>
63 __forceinline__ __host__ __device__ std::array<ctype, sizeof...(I)> backward(I &&...i) const
64 {
65 static_assert(sizeof...(I) == sizeof...(Coordinates));
66 return backward_impl(std::make_integer_sequence<int, sizeof...(I)>(), std::forward<I>(i)...);
67 }
68
69 template <typename... I, int... Is>
70 std::array<ctype, sizeof...(I)> __forceinline__ __host__ __device__ backward_impl(std::integer_sequence<int, Is...>,
71 I &&...i) const
72 {
73 return {{std::get<Is>(coordinates).backward(std::get<Is>(std::tie(i...)))...}};
74 }
75
76 template <uint i> const auto &get_coordinates() const { return std::get<i>(coordinates); }
77
78 uint size() const
79 {
80 // multiply all sizes
81 uint size = 1;
82 constexpr_for<0, sizeof...(Coordinates), 1>([&](auto i) { size *= std::get<i>(coordinates).size(); });
83 return size;
84 }
85
86 std::array<uint, sizeof...(Coordinates)> sizes() const
87 {
88 std::array<uint, sizeof...(Coordinates)> sizes;
89 constexpr_for<0, sizeof...(Coordinates), 1>([&](auto i) { sizes[i] = std::get<i>(coordinates).size(); });
90 return sizes;
91 }
92
93 protected:
94 const std::tuple<Coordinates...> coordinates;
95 };
96
97 template <typename NT> class LinearCoordinates1D
98 {
99 public:
100 using ctype = NT;
101 static constexpr uint dim = 1;
102
105 {
106 if (grid_extent == 0) throw std::runtime_error("LinearCoordinates1D: grid_extent must be > 0");
107 a = (stop - start) / (grid_extent - 1.);
108 }
109
110 template <typename NT2>
112 : LinearCoordinates1D(other.size(), other.start, other.stop)
113 {
114 }
115
122 NT __forceinline__ __device__ __host__ forward(const uint &x) const { return start + a * x; }
123
130 NT __forceinline__ __device__ __host__ backward(const NT &y) const { return (y - start) / a; }
131
132 uint size() const { return grid_extent; }
133
134 const NT start, stop;
135
136 private:
138 NT a;
139 };
140
141 template <typename NT> class LogarithmicCoordinates1D
142 {
143 public:
144 using ctype = NT;
145 static constexpr uint dim = 1;
146
149 gem1inv(1. / (grid_extent - 1.))
150 {
151 if (grid_extent == 0) throw std::runtime_error("LogarithmicCoordinates1D: grid_extent must be > 0");
152 using std::expm1;
153 a = bias;
154 b = (stop - start) / expm1(a);
155 c = start;
156 }
157
158 template <typename NT2>
160 : LogarithmicCoordinates1D(other.size(), other.start, other.stop, other.bias)
161 {
162 }
163
170 NT __forceinline__ __device__ __host__ forward(const uint &x) const
171 {
172 using std::expm1;
173 return b * expm1(a * x * gem1inv) + c;
174 }
175
182 NT __forceinline__ __device__ __host__ backward(const NT &y) const
183 {
184 using std::log1p;
185 return log1p((y - c) / b) * gem1 / a;
186 }
187
188 NT __forceinline__ __device__ __host__ backward_derivative(const NT &y) const { return 1. / (y - c) * gem1 / a; }
189
190 uint size() const { return grid_extent; }
191
192 const NT start, stop, bias;
193
194 private:
196 const NT gem1, gem1inv;
197 NT a, b, c;
198 };
199
200 template <typename Coordinates> auto make_grid(const Coordinates &coordinates)
201 {
202 using ctype = typename Coordinates::ctype;
203 if constexpr (Coordinates::dim == 1) {
204 std::vector<ctype> grid(coordinates.size());
205 for (uint i = 0; i < coordinates.size(); ++i)
206 grid[i] = coordinates.forward(i);
207 return grid;
208 } else if constexpr (Coordinates::dim == 2) {
209 std::vector<std::array<ctype, 2>> grid(coordinates.size());
210 for (uint i = 0; i < coordinates.sizes()[0]; ++i)
211 for (uint j = 0; j < coordinates.sizes()[1]; ++j)
212 grid[i * coordinates.sizes()[1] + j] = coordinates.forward(i, j);
213 return grid;
214 } else if constexpr (Coordinates::dim == 3) {
215 std::vector<std::array<ctype, 3>> grid(coordinates.size());
216 for (uint i = 0; i < coordinates.sizes()[0]; ++i)
217 for (uint j = 0; j < coordinates.sizes()[1]; ++j)
218 for (uint k = 0; k < coordinates.sizes()[2]; ++k)
219 grid[i * coordinates.sizes()[1] * coordinates.sizes()[2] + j * coordinates.sizes()[2] + k] =
220 coordinates.forward(i, j, k);
221 return grid;
222 } else {
223 throw std::runtime_error("make_grid only works for 1D, 2D, and 3D coordinates");
224 }
225 }
226
227 template <typename Coordinates> auto make_idx_grid(const Coordinates &coordinates) -> std::vector<double>
228 {
229 if constexpr (Coordinates::dim == 1) {
230 std::vector<double> grid(coordinates.size());
231 for (uint i = 0; i < coordinates.size(); ++i)
232 grid[i] = i;
233 return grid;
234 } else if constexpr (Coordinates::dim == 2) {
235 std::vector<double> grid(coordinates.size());
236 for (uint i = 0; i < coordinates.sizes()[0]; ++i)
237 for (uint j = 0; j < coordinates.sizes()[1]; ++j)
238 grid[i * coordinates.sizes()[1] + j] = i * coordinates.sizes()[1] + j;
239 return grid;
240 } else if constexpr (Coordinates::dim == 3) {
241 std::vector<double> grid(coordinates.size());
242 for (uint i = 0; i < coordinates.sizes()[0]; ++i)
243 for (uint j = 0; j < coordinates.sizes()[1]; ++j)
244 for (uint k = 0; k < coordinates.sizes()[2]; ++k)
245 grid[i * coordinates.sizes()[1] * coordinates.sizes()[2] + j * coordinates.sizes()[2] + k] =
246 i * coordinates.sizes()[1] * coordinates.sizes()[2] + j * coordinates.sizes()[2] + k;
247 return grid;
248 } else {
249 throw std::runtime_error("make_idx_grid only works for 1D, 2D, and 3D coordinates");
250 }
251 }
252} // namespace DiFfRG
Utility class for combining multiple coordinate systems into one.
Definition coordinates.hh:29
const auto & get_coordinates() const
Definition coordinates.hh:76
typename std::tuple_element< 0, std::tuple< Coordinates... > >::type::ctype ctype
Definition coordinates.hh:39
static constexpr uint dim
Definition coordinates.hh:40
std::array< ctype, sizeof...(I)> __forceinline__ __host__ __device__ backward_impl(std::integer_sequence< int, Is... >, I &&...i) const
Definition coordinates.hh:70
const std::tuple< Coordinates... > coordinates
Definition coordinates.hh:94
__forceinline__ __host__ __device__ std::array< ctype, dim > forward_impl(std::integer_sequence< int, Is... >, I &&...i) const
Definition coordinates.hh:56
CoordinatePackND(Coordinates... coordinates)
Construct a new CoordinatePackND object.
Definition coordinates.hh:47
__forceinline__ __host__ __device__ std::array< ctype, sizeof...(I)> backward(I &&...i) const
Definition coordinates.hh:63
__forceinline__ __host__ __device__ std::array< ctype, dim > forward(I &&...i) const
Definition coordinates.hh:49
uint size() const
Definition coordinates.hh:78
std::array< uint, sizeof...(Coordinates)> sizes() const
Definition coordinates.hh:86
Definition coordinates.hh:98
NT __forceinline__ __device__ __host__ forward(const uint &x) const
Transform from the grid to the physical space.
Definition coordinates.hh:122
static constexpr uint dim
Definition coordinates.hh:101
NT a
Definition coordinates.hh:138
const NT stop
Definition coordinates.hh:134
uint size() const
Definition coordinates.hh:132
LinearCoordinates1D(uint grid_extent, double start, double stop)
Definition coordinates.hh:103
const NT start
Definition coordinates.hh:134
const uint grid_extent
Definition coordinates.hh:137
NT ctype
Definition coordinates.hh:100
LinearCoordinates1D(const LinearCoordinates1D< NT2 > &other)
Definition coordinates.hh:111
NT __forceinline__ __device__ __host__ backward(const NT &y) const
Transform from the physical space to the grid.
Definition coordinates.hh:130
Definition coordinates.hh:142
const NT gem1
Definition coordinates.hh:196
uint size() const
Definition coordinates.hh:190
NT __forceinline__ __device__ __host__ backward(const NT &y) const
Transform from the physical space to the grid.
Definition coordinates.hh:182
static constexpr uint dim
Definition coordinates.hh:145
LogarithmicCoordinates1D(const LogarithmicCoordinates1D< NT2 > &other)
Definition coordinates.hh:159
NT __forceinline__ __device__ __host__ backward_derivative(const NT &y) const
Definition coordinates.hh:188
const NT stop
Definition coordinates.hh:192
const NT gem1inv
Definition coordinates.hh:196
LogarithmicCoordinates1D(uint grid_extent, NT start, NT stop, NT bias)
Definition coordinates.hh:147
const NT start
Definition coordinates.hh:192
NT __forceinline__ __device__ __host__ forward(const uint &x) const
Transform from the grid to the physical space.
Definition coordinates.hh:170
NT a
Definition coordinates.hh:197
NT ctype
Definition coordinates.hh:144
const NT bias
Definition coordinates.hh:192
NT b
Definition coordinates.hh:197
const uint grid_extent
Definition coordinates.hh:195
NT c
Definition coordinates.hh:197
Definition coordinates.hh:15
Definition complex_math.hh:14
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:27
auto make_idx_grid(const Coordinates &coordinates) -> std::vector< double >
Definition coordinates.hh:227
unsigned int uint
Definition utils.hh:22
auto make_grid(const Coordinates &coordinates)
Definition coordinates.hh:200
constexpr auto & get(DiFfRG::named_tuple< tuple_type, strs... > &ob)
Definition tuples.hh:119