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

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/physics/interpolation/spline_interpolator_1d.hh Source File
DiFfRG
Discretization Framework for functional Renormalization Group flows
spline_interpolator_1d.hh
Go to the documentation of this file.
1#pragma once
2
3// DiFfRG
7
8// std
9#include <cmath>
10#include <cstring>
11#include <limits>
12#include <stdexcept>
13#include <vector>
14
15namespace DiFfRG
16{
25 template <typename NT, typename Coordinates> class SplineInterpolator1D
26 {
27 static_assert(Coordinates::dim == 1, "SplineInterpolator1D requires 1D coordinates");
28 // The spline coefficients come from a non-cyclic tridiagonal solve with boundary conditions at the grid edges,
29 // which cannot close a periodic axis. Use LinearInterpolator1D there instead.
31 "SplineInterpolator1D does not support periodic coordinates; use LinearInterpolator1D.");
32
33 // SoA layout: separate views for values and spline coefficients, for coalesced GPU access
34 using ValueViewType = Kokkos::View<NT *, GPU_memory, Kokkos::MemoryTraits<Kokkos::RandomAccess>>;
36 using HostValueViewType = typename ValueViewType::host_mirror_type;
37 using HostCoeffViewType = typename CoeffViewType::host_mirror_type;
38
39 static constexpr bool has_separate_device =
40 !std::is_same_v<typename ValueViewType::memory_space, typename HostValueViewType::memory_space>;
41
42 public:
43 using ctype = typename Coordinates::ctype;
44 using value_type = NT;
45 static constexpr size_t dim = 1;
46
54 device_values("SplineInterpolator1D_values", coordinates.size()),
55 device_coeffs("SplineInterpolator1D_coeffs", coordinates.size()),
56 host_values(Kokkos::create_mirror_view(device_values)),
57 host_coeffs(Kokkos::create_mirror_view(device_coeffs))
58 {
59 }
60
62 KOKKOS_DEFAULTED_FUNCTION SplineInterpolator1D(const SplineInterpolator1D &) = default;
63
70 template <typename NT2>
71 void update(const NT2 *in_data, const ctype lower_y1 = std::numeric_limits<ctype>::max(),
72 const ctype upper_y1 = std::numeric_limits<ctype>::max())
73 {
74 // Copy values from input data
75 for (size_t i = 0; i < size; ++i)
76 host_values(i) = in_data[i];
77
78 // Build the spline coefficients
79 build_y2(lower_y1, upper_y1);
80
81 if constexpr (has_separate_device) {
82 typename ValueViewType::execution_space exec;
83 Kokkos::deep_copy(exec, device_values, host_values);
84 Kokkos::deep_copy(exec, device_coeffs, host_coeffs);
85 exec.fence();
86 }
87 }
88
92 NT operator[](size_t i) const { return host_values(i); }
93
106 ctype KOKKOS_FUNCTION index(const typename Coordinates::ctype x) const { return coordinates.backward(x); }
107
116 NT KOKKOS_FUNCTION at(const ctype raw_idx) const
117 {
118 // Clamp the index to the range [0, size - 1]
119 const ctype idx = Kokkos::max(static_cast<ctype>(0),
120 Kokkos::min(raw_idx, static_cast<ctype>(size - 1)));
121 const size_t lidx = Kokkos::min(size_t(Kokkos::floor(idx)), size - 2);
122 const size_t uidx = lidx + 1;
123 // t is the fractional part of the index
124 const ctype t = idx - lidx;
125
126 const NT lower = value(lidx);
127 const NT upper = value(uidx);
128 const NT cl = coeff(lidx);
129 const NT cu = coeff(uidx);
130
131 const ctype tm1 = t - 1;
132 const NT cubic = t * tm1 * ((t + 1) * cl - (t - 2) * cu);
133
134 if constexpr (std::is_arithmetic_v<NT>)
135 return Kokkos::fma(t, upper, Kokkos::fma(-t, lower, lower)) + cubic; // linear + cubic
136 else
137 return t * upper + (1 - t) * lower + cubic; // linear + cubic
138 }
139
146 NT KOKKOS_FUNCTION operator()(const typename Coordinates::ctype x) const { return at(index(x)); }
147
153 const Coordinates &get_coordinates() const { return coordinates; }
154
161 const NT *data() const { return host_values.data(); }
162
163 private:
165 KOKKOS_FORCEINLINE_FUNCTION NT value(const size_t i) const
166 {
167 KOKKOS_IF_ON_DEVICE((return device_values(i);))
168 KOKKOS_IF_ON_HOST((return host_values(i);))
169 }
170
172 KOKKOS_FORCEINLINE_FUNCTION NT coeff(const size_t i) const
173 {
174 KOKKOS_IF_ON_DEVICE((return device_coeffs(i);))
175 KOKKOS_IF_ON_HOST((return host_coeffs(i);))
176 }
177
178 const Coordinates coordinates;
179 const size_t size;
180
185
186 void build_y2(const ctype lower_y1, const ctype upper_y1)
187 {
188 NT p, qn, sig, un;
189 std::vector<NT> u(size - 1);
190
191 if (!std::isfinite(lower_y1) || lower_y1 >= std::numeric_limits<ctype>::max() / 2)
192 host_coeffs(0) = u[0] = 0.0;
193 else {
194 host_coeffs(0) = -0.5;
195 u[0] = 3.0 * ((host_values(1) - host_values(0)) - lower_y1);
196 }
197 for (size_t i = 1; i < size - 1; i++) {
198 sig = 0.5;
199 p = sig * host_coeffs(i - 1) + 2.0;
200 host_coeffs(i) = (sig - 1.0) / p;
201 u[i] = (host_values(i + 1) - host_values(i)) - (host_values(i) - host_values(i - 1));
202 u[i] = (6.0 * u[i] / 2. - sig * u[i - 1]) / p;
203 }
204 if (!std::isfinite(upper_y1) || upper_y1 >= std::numeric_limits<ctype>::max() / 2)
205 qn = un = 0.0;
206 else {
207 qn = 0.5;
208 un = 3.0 * (upper_y1 - (host_values(size - 1) - host_values(size - 2)));
209 }
210 host_coeffs(size - 1) = (un - qn * u[size - 2]) / (qn * host_coeffs(size - 2) + 1);
211 for (int k = size - 2; k >= 0; k--)
212 host_coeffs(k) = host_coeffs(k) * host_coeffs(k + 1) + u[k];
213
214 // Precompute division by 6 so operator() avoids per-call divides
215 for (size_t k = 0; k < size; ++k)
216 host_coeffs(k) /= (ctype)6;
217 }
218 };
219} // namespace DiFfRG
A spline interpolator for 1D data, callable from host AND device code.
Definition spline_interpolator_1d.hh:26
ctype KOKKOS_FUNCTION index(const typename Coordinates::ctype x) const
Map a physical coordinate onto the (clamped) grid index.
Definition spline_interpolator_1d.hh:106
HostValueViewType host_values
Definition spline_interpolator_1d.hh:183
ValueViewType CoeffViewType
Definition spline_interpolator_1d.hh:35
const Coordinates & get_coordinates() const
Get the coordinate system of the data.
Definition spline_interpolator_1d.hh:153
ValueViewType device_values
Definition spline_interpolator_1d.hh:181
typename CoeffViewType::host_mirror_type HostCoeffViewType
Definition spline_interpolator_1d.hh:37
NT KOKKOS_FUNCTION operator()(const typename Coordinates::ctype x) const
Interpolate the data at a given point.
Definition spline_interpolator_1d.hh:146
const size_t size
Definition spline_interpolator_1d.hh:179
const NT * data() const
Read-only handle to the host values.
Definition spline_interpolator_1d.hh:161
HostCoeffViewType host_coeffs
Definition spline_interpolator_1d.hh:184
KOKKOS_DEFAULTED_FUNCTION SplineInterpolator1D(const SplineInterpolator1D &)=default
Shallow copy of ALL views, valid in host and in device code. See LinearInterpolator1D.
void update(const NT2 *in_data, const ctype lower_y1=std::numeric_limits< ctype >::max(), const ctype upper_y1=std::numeric_limits< ctype >::max())
Replace the data, leaving host AND device current. The only mutator.
Definition spline_interpolator_1d.hh:71
KOKKOS_FORCEINLINE_FUNCTION NT value(const size_t i) const
Read one value from whichever buffer belongs to the executing side.
Definition spline_interpolator_1d.hh:165
static constexpr size_t dim
Definition spline_interpolator_1d.hh:45
typename Coordinates::ctype ctype
Definition spline_interpolator_1d.hh:43
const Coordinates coordinates
Definition spline_interpolator_1d.hh:178
KOKKOS_FORCEINLINE_FUNCTION NT coeff(const size_t i) const
Read one spline coefficient from whichever buffer belongs to the executing side.
Definition spline_interpolator_1d.hh:172
CoeffViewType device_coeffs
Definition spline_interpolator_1d.hh:182
typename ValueViewType::host_mirror_type HostValueViewType
Definition spline_interpolator_1d.hh:36
NT operator[](size_t i) const
Host-side element access. Always valid, including on a copy.
Definition spline_interpolator_1d.hh:92
Kokkos::View< NT *, GPU_memory, Kokkos::MemoryTraits< Kokkos::RandomAccess > > ValueViewType
Definition spline_interpolator_1d.hh:34
NT KOKKOS_FUNCTION at(const ctype raw_idx) const
Interpolate at a grid index previously obtained from index().
Definition spline_interpolator_1d.hh:116
void build_y2(const ctype lower_y1, const ctype upper_y1)
Definition spline_interpolator_1d.hh:186
NT value_type
Definition spline_interpolator_1d.hh:44
SplineInterpolator1D(const Coordinates &coordinates)
Construct a SplineInterpolator1D with internal, zeroed data and a coordinate system.
Definition spline_interpolator_1d.hh:52
static constexpr bool has_separate_device
Definition spline_interpolator_1d.hh:39
Definition complex_math.hh:10
constexpr bool is_periodic_coordinate_v
Whether a 1D coordinate class describes a periodic axis, i.e. one where the last grid point is follow...
Definition coordinates.hh:43
Definition kokkos.hh:538