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

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/physics/interpolation/linear_interpolator_1d.hh Source File
DiFfRG
linear_interpolator_1d.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 LinearInterpolator1D
16 {
17 static_assert(Coordinates::dim == 1, "LinearInterpolator1D requires 1D 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 = 1;
25
34 {
35 // Allocate Kokkos View
36 device_data = ViewType("LinearInterpolator1D_data", size);
37 // Create host mirror
38 host_data = Kokkos::create_mirror_view(device_data);
39 }
40
45 KOKKOS_FUNCTION
47 : coordinates(other.coordinates), size(other.size)
48 {
49 // Use the same data
51 }
52
53 KOKKOS_FUNCTION ~LinearInterpolator1D()
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 "LinearInterpolator1D: You probably called update() on a copied instance. This is not allowed. "
64 "You need to call update() on the original instance.");
65
66 Kokkos::View<const NT2 *, Kokkos::LayoutRight, Kokkos::HostSpace, Kokkos::MemoryTraits<Kokkos::Unmanaged>>
67 in_view(in_data, size);
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 "LinearInterpolator1D: 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 if (!host_data.is_allocated())
89 throw std::runtime_error(
90 "LinearInterpolator1D: You probably called operator[]() on a copied instance. This is not allowed. "
91 "You need to call operator[]() on the original instance.");
92 return host_data.data()[i]; // Access the host data directly
93 }
94
101 NT KOKKOS_FUNCTION operator()(const typename Coordinates::ctype x) const
102 {
103 auto idx = coordinates.backward(x);
104 // Clamp the index to the range [0, size - 1]
105 idx = Kokkos::max(static_cast<decltype(idx)>(0), Kokkos::min(idx, static_cast<decltype(idx)>(size - 1)));
106 // t is the fractional part of the index
107 const auto t = idx - Kokkos::floor(idx);
108 // Do the linear interpolation, clamping upper index to valid range
109 const size_t lower_idx = Kokkos::min(size_t(Kokkos::floor(idx)), size - 2);
110 const size_t upper_idx = lower_idx + 1;
111 const auto lower = device_data[lower_idx];
112 const auto upper = device_data[upper_idx];
113 if constexpr (std::is_arithmetic_v<NT>)
114 return Kokkos::fma(t, upper, Kokkos::fma(-t, lower, lower));
115 else
116 return t * upper + (1 - t) * lower;
117 }
118
124 const Coordinates &get_coordinates() const { return coordinates; }
125
126 auto &CPU() const { return get_on<CPU_memory>(); }
127 auto &GPU() const { return get_on<GPU_memory>(); }
128
129 template <typename MemorySpace> auto &get_on() const
130 {
131 if (!host_data.is_allocated())
132 throw std::runtime_error(
133 "LinearInterpolator1D: You probably called get_on() on a copied instance. This is not allowed. "
134 "You need to call get_on() on the original instance.");
135
136 if constexpr (std::is_same_v<MemorySpace, DefaultMemorySpace>) {
137 // remove constness
138 return const_cast<LinearInterpolator1D<NT, Coordinates, MemorySpace> &>(*this);
139 } else {
140 // Create a new instance with the same data but in the requested memory space
141 if (other_instance == nullptr) {
143 owns_other_instance = true;
144 other_instance->other_instance = const_cast<std::decay_t<decltype(*this)> *>(this);
145 }
146 // Copy the data from the current instance to the new one
147 other_instance->update(host_data);
148 // Return the new instance
149 return *other_instance;
150 }
151 }
152
153 NT *data()
154 {
155 if (!host_data.is_allocated())
156 throw std::runtime_error(
157 "LinearInterpolator1D: You probably called data() on a copied instance. This is not allowed. "
158 "You need to call data() on the original instance.");
159 return host_data.data();
160 }
161
162 friend class LinearInterpolator1D<NT, Coordinates, other_memory_space>;
163
164 private:
165 const Coordinates coordinates;
166 const size_t size;
167
168 using ViewType = Kokkos::View<NT *, DefaultMemorySpace, Kokkos::MemoryTraits<Kokkos::RandomAccess>>;
169 using HostViewType = typename ViewType::host_mirror_type;
170
173
175 mutable bool owns_other_instance = false;
176 };
177} // namespace DiFfRG
A linear interpolator for 1D data, both on GPU and CPU.
Definition linear_interpolator_1d.hh:16
LinearInterpolator1D< NT, Coordinates, other_memory_space > * other_instance
Definition linear_interpolator_1d.hh:174
NT * data()
Definition linear_interpolator_1d.hh:153
void update(const NT2 *in_data)
Definition linear_interpolator_1d.hh:58
const Coordinates & get_coordinates() const
Get the coordinate system of the data.
Definition linear_interpolator_1d.hh:124
NT operator[](size_t i) const
Definition linear_interpolator_1d.hh:86
Kokkos::View< NT *, DefaultMemorySpace, Kokkos::MemoryTraits< Kokkos::RandomAccess > > ViewType
Definition linear_interpolator_1d.hh:168
NT value_type
Definition linear_interpolator_1d.hh:23
void update(const View &view)
Definition linear_interpolator_1d.hh:73
HostViewType host_data
Definition linear_interpolator_1d.hh:172
DefaultMemorySpace memory_space
Definition linear_interpolator_1d.hh:20
KOKKOS_FUNCTION ~LinearInterpolator1D()
Definition linear_interpolator_1d.hh:53
auto & CPU() const
Definition linear_interpolator_1d.hh:126
NT KOKKOS_FUNCTION operator()(const typename Coordinates::ctype x) const
Interpolate the data at a given point.
Definition linear_interpolator_1d.hh:101
static constexpr size_t dim
Definition linear_interpolator_1d.hh:24
other_memory_space_t< DefaultMemorySpace > other_memory_space
Definition linear_interpolator_1d.hh:21
ViewType device_data
Definition linear_interpolator_1d.hh:171
auto & get_on() const
Definition linear_interpolator_1d.hh:129
auto & GPU() const
Definition linear_interpolator_1d.hh:127
const size_t size
Definition linear_interpolator_1d.hh:166
LinearInterpolator1D(const Coordinates &coordinates)
Construct a LinearInterpolator1D with internal, zeroed data and a coordinate system.
Definition linear_interpolator_1d.hh:32
KOKKOS_FUNCTION LinearInterpolator1D(const LinearInterpolator1D &other)
Copy constructor for LinearInterpolator1D. This is ONLY for usage inside Kokkos parallel loops.
Definition linear_interpolator_1d.hh:46
typename Coordinates::ctype ctype
Definition linear_interpolator_1d.hh:22
typename ViewType::host_mirror_type HostViewType
Definition linear_interpolator_1d.hh:169
const Coordinates coordinates
Definition linear_interpolator_1d.hh:165
bool owns_other_instance
Definition linear_interpolator_1d.hh:175
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