/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/physics/interpolation/linear_interpolator_2d.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/physics/interpolation/linear_interpolator_2d.hh Source File
DiFfRG
linear_interpolator_2d.hh
Go to the documentation of this file.
1#pragma once
2
3// DiFfRG
6
7namespace DiFfRG
8{
15 template <typename NT, typename Coordinates, typename DefaultMemorySpace = CPU_memory> class LinearInterpolator2D
16 {
17 static_assert(Coordinates::dim == 2, "LinearInterpolator2D requires 2D coordinates");
18
19 public:
20 using memory_space = DefaultMemorySpace;
22 using ctype = typename Coordinates::ctype;
23 using value_type = NT;
24 static constexpr size_t dim = 2;
25
34 {
35 // Allocate Kokkos View
36 device_data = ViewType("LinearInterpolator2D_data", sizes[0], sizes[1]);
37 // Create host mirror
38 host_data = Kokkos::create_mirror_view(device_data);
39 }
40
45 KOKKOS_FUNCTION
48 {
49 // Use the same data
51 }
52
53 KOKKOS_FUNCTION ~LinearInterpolator2D()
54 {
55 KOKKOS_IF_ON_HOST((if (owns_other_instance) delete other_instance;))
56 }
57
58 template <typename NT2> void update(const NT2 *in_data)
59 {
60 // Check if the host data is already allocated
61 if (!host_data.is_allocated())
62 throw std::runtime_error(
63 "LinearInterpolator2D: You probably called update() on a copied instance. This is not allowed. "
64 "You need to call update() on the original instance.");
65 // Make a View from the input data
66 Kokkos::View<const NT2 **, Kokkos::LayoutRight, Kokkos::HostSpace, Kokkos::MemoryTraits<Kokkos::Unmanaged>>
67 in_view(in_data, sizes[0], sizes[1]);
68 update(in_view);
69 }
70
71 template <typename View>
72 requires Kokkos::is_view<View>::value
73 void update(const View &view)
74 {
75 // Check if the host data is already allocated
76 if (!host_data.is_allocated())
77 throw std::runtime_error(
78 "LinearInterpolator2D: You probably called update() on a copied instance. This is not allowed. "
79 "You need to call update() on the original instance.");
80 // Populate host mirror
81 Kokkos::deep_copy(host_data, view);
82 // Copy data to device
83 Kokkos::deep_copy(device_data, host_data);
84 }
85
86 NT operator[](size_t i) const
87 {
88 // Check if the host data is already allocated
89 if (!host_data.is_allocated())
90 throw std::runtime_error(
91 "LinearInterpolator2D: You probably called operator[]() on a copied instance. This is not allowed. "
92 "You need to call operator[]() on the original instance.");
93 return host_data.data()[i]; // Access the host data directly
94 }
95
102 NT KOKKOS_FUNCTION operator()(const typename Coordinates::ctype x, const typename Coordinates::ctype y) const
103 {
104 using Kokkos::min, Kokkos::max;
105 auto [idx_x, idx_y] = coordinates.backward(x, y);
106 idx_x = max(static_cast<decltype(idx_x)>(0), min(idx_x, static_cast<decltype(idx_x)>(sizes[0] - 1)));
107 idx_y = max(static_cast<decltype(idx_y)>(0), min(idx_y, static_cast<decltype(idx_y)>(sizes[1] - 1)));
108
109 // Lower index clamped to [0, sizes-2], upper = lower+1
110 const size_t x0 = min(size_t(Kokkos::floor(idx_x)), sizes[0] - 2);
111 const size_t y0 = min(size_t(Kokkos::floor(idx_y)), sizes[1] - 2);
112 const size_t x1 = x0 + 1;
113 const size_t y1 = y0 + 1;
114
115 const auto corner00 = device_data(x0, y0);
116 const auto corner01 = device_data(x0, y1);
117 const auto corner10 = device_data(x1, y0);
118 const auto corner11 = device_data(x1, y1);
119
120 const auto tx = idx_x - x0;
121 const auto ty = idx_y - y0;
122
123 if constexpr (std::is_arithmetic_v<NT>)
124 return Kokkos::fma(ty, Kokkos::fma(tx, corner11, Kokkos::fma(-tx, corner01, corner01)),
125 (1 - ty) * Kokkos::fma(tx, corner10, Kokkos::fma(-tx, corner00, corner00)));
126 else
127 return corner00 * (1 - tx) * (1 - ty) + corner01 * (1 - tx) * ty + corner10 * tx * (1 - ty) +
128 corner11 * tx * ty;
129 }
130
131 auto &CPU() const { return get_on<CPU_memory>(); }
132 auto &GPU() const { return get_on<GPU_memory>(); }
133
134 template <typename MemorySpace> auto &get_on() const
135 {
136 // Check if the host data is already allocated
137 if (!host_data.is_allocated())
138 throw std::runtime_error(
139 "LinearInterpolator2D: You probably called get_on[]() on a copied instance. This is not allowed. "
140 "You need to call get_on[]() on the original instance.");
141
142 if constexpr (std::is_same_v<MemorySpace, DefaultMemorySpace>) {
143 // remove constness
144 return const_cast<LinearInterpolator2D<NT, Coordinates, MemorySpace> &>(*this);
145 } else {
146 // Create a new instance with the same data but in the requested memory space
147 if (other_instance == nullptr) {
149 owns_other_instance = true;
150 other_instance->other_instance = const_cast<std::decay_t<decltype(*this)> *>(this);
151 }
152 // Copy the data from the current instance to the new one
153 other_instance->update(host_data);
154 // Return the new instance
155 return *other_instance;
156 }
157 }
158
164 const Coordinates &get_coordinates() const { return coordinates; }
165
166 NT *data()
167 {
168 if (!host_data.is_allocated())
169 throw std::runtime_error(
170 "LinearInterpolator1D: You probably called data() on a copied instance. This is not allowed. "
171 "You need to call data() on the original instance.");
172 return host_data.data();
173 }
174
175 friend class LinearInterpolator2D<NT, Coordinates, other_memory_space>;
176
177 private:
178 const Coordinates coordinates;
180 const size_t total_size;
181
182 using ViewType = Kokkos::View<NT **, DefaultMemorySpace, Kokkos::MemoryTraits<Kokkos::RandomAccess>>;
183 using HostViewType = typename ViewType::host_mirror_type;
184
187
189 mutable bool owns_other_instance = false;
190 };
191} // namespace DiFfRG
A linear interpolator for 2D data, both on GPU and CPU.
Definition linear_interpolator_2d.hh:16
auto & get_on() const
Definition linear_interpolator_2d.hh:134
bool owns_other_instance
Definition linear_interpolator_2d.hh:189
const Coordinates & get_coordinates() const
Get the coordinate system of the data.
Definition linear_interpolator_2d.hh:164
NT KOKKOS_FUNCTION operator()(const typename Coordinates::ctype x, const typename Coordinates::ctype y) const
Interpolate the data at a given point.
Definition linear_interpolator_2d.hh:102
void update(const NT2 *in_data)
Definition linear_interpolator_2d.hh:58
KOKKOS_FUNCTION ~LinearInterpolator2D()
Definition linear_interpolator_2d.hh:53
NT value_type
Definition linear_interpolator_2d.hh:23
NT operator[](size_t i) const
Definition linear_interpolator_2d.hh:86
DefaultMemorySpace memory_space
Definition linear_interpolator_2d.hh:20
HostViewType host_data
Definition linear_interpolator_2d.hh:186
const size_t total_size
Definition linear_interpolator_2d.hh:180
auto & GPU() const
Definition linear_interpolator_2d.hh:132
const Coordinates coordinates
Definition linear_interpolator_2d.hh:178
other_memory_space_t< DefaultMemorySpace > other_memory_space
Definition linear_interpolator_2d.hh:21
const device::array< size_t, 2 > sizes
Definition linear_interpolator_2d.hh:179
void update(const View &view)
Definition linear_interpolator_2d.hh:73
static constexpr size_t dim
Definition linear_interpolator_2d.hh:24
typename ViewType::host_mirror_type HostViewType
Definition linear_interpolator_2d.hh:183
LinearInterpolator2D(const Coordinates &coordinates)
Construct a LinearInterpolator2D with internal, zeroed data and a coordinate system.
Definition linear_interpolator_2d.hh:32
Kokkos::View< NT **, DefaultMemorySpace, Kokkos::MemoryTraits< Kokkos::RandomAccess > > ViewType
Definition linear_interpolator_2d.hh:182
typename Coordinates::ctype ctype
Definition linear_interpolator_2d.hh:22
ViewType device_data
Definition linear_interpolator_2d.hh:185
KOKKOS_FUNCTION LinearInterpolator2D(const LinearInterpolator2D &other)
Copy constructor for LinearInterpolator2D. This is ONLY for usage inside Kokkos parallel loops.
Definition linear_interpolator_2d.hh:46
auto & CPU() const
Definition linear_interpolator_2d.hh:131
LinearInterpolator2D< NT, Coordinates, other_memory_space > * other_instance
Definition linear_interpolator_2d.hh:188
NT * data()
Definition linear_interpolator_2d.hh:166
std::array< T, N > array
Definition kokkos.hh:133
Definition complex_math.hh:10
std::conditional_t< std::is_same_v< MemorySpace, GPU_memory >, CPU_memory, GPU_memory > other_memory_space_t
Definition kokkos.hh:58