29#include <Kokkos_Core.hpp>
71 std::vector<double> ca_frac_spillover;
74 std::vector<int> ca_fmp_spillover;
78 : ca_frac(
"p3m_interpolation_cache::ca_frac", 0, 0),
79 ca_fmp(
"p3m_interpolation_cache::ca_fmp", 0, 0) {}
85 auto size()
const {
return ca_fmp.size() + ca_fmp_spillover.size(); }
91 auto cao()
const {
return m_cao; }
99 auto const size_frac =
size *
static_cast<std::size_t
>(m_cao * 3);
100 if (ca_fmp.size() !=
size or ca_frac.size() != size_frac) {
101 Kokkos::realloc(Kokkos::WithoutInitializing, ca_fmp,
size);
102 Kokkos::realloc(Kokkos::WithoutInitializing, ca_frac, size_frac);
104 assert(ca_frac_spillover.empty());
105 assert(ca_fmp_spillover.empty());
108 (std::distance(&ca_fmp(0), &ca_fmp(
size - 1)) ==
size - 1));
119 assert(
cao == m_cao);
121 ca_fmp_spillover.emplace_back(weights.ind);
122 auto it = std::back_inserter(ca_frac_spillover);
123 std::ranges::copy(weights.w_x, it);
124 std::ranges::copy(weights.w_y, it);
125 std::ranges::copy(weights.w_z, it);
138 assert(
cao == m_cao);
139 assert(p_index < ca_fmp.size());
143 std::advance(dst,
cao);
145 std::advance(dst,
cao);
149 ca_fmp(p_index) = weights.ind;
150 auto const offset = p_index *
static_cast<std::size_t
>(
cao * 3);
151 copy_weights(weights, ca_frac.data() + offset);
167 assert(
cao == m_cao);
168 assert(p_index <
size());
171 double const *ptr =
nullptr;
172 if (p_index >= ca_fmp.size()) {
173 p_index -= ca_fmp.size();
174 index = ca_fmp_spillover[p_index];
175 auto const offset = p_index *
static_cast<std::size_t
>(
cao * 3);
176 ptr = std::as_const(ca_frac_spillover).data() + offset;
178 index = ca_fmp(p_index);
179 auto const offset = p_index *
static_cast<std::size_t
>(
cao * 3);
180 ptr = std::as_const(ca_frac).data() + offset;
182 std::span<double const, cao> w_x(ptr,
cao);
183 std::advance(ptr,
cao);
184 std::span<double const, cao> w_y(ptr,
cao);
185 std::advance(ptr,
cao);
186 std::span<double const, cao> w_z(ptr,
cao);
187 return {index, w_x, w_y, w_z};
197 Kokkos::realloc(Kokkos::WithoutInitializing, ca_fmp, 0ul);
198 Kokkos::realloc(Kokkos::WithoutInitializing, ca_frac, 0ul);
199 ca_frac_spillover.clear();
200 ca_fmp_spillover.clear();
210template <
int cao, Utils::MemoryOrder memory_order>
216 auto const pos_shift = std::floor((cao - 1) / 2.0) - (cao % 2) / 2.0;
224 for (
unsigned int d = 0; d < 3; d++) {
226 auto const pos = ((position[d] - local_mesh.
ld_pos[d]) * ai[d]) - pos_shift;
228 nmp[d] =
static_cast<int>(pos);
231 dist[d] = (pos - nmp[d]) - 0.5;
237 ret.
ind = Utils::get_linear_index<memory_order>(nmp, local_mesh.
dim);
240 for (
int i = 0; i < cao; i++) {
243 ret.
w_x[i] = bspline<cao>(i, dist[0]);
244 ret.
w_y[i] = bspline<cao>(i, dist[1]);
245 ret.
w_z[i] = bspline<cao>(i, dist[2]);
262template <
int cao,
template <
int>
class WeightsStorage,
class Kernel>
264 WeightsStorage<cao>
const &weights, Kernel kernel) {
265 auto q_ind = weights.ind;
266 for (
int i0 = 0; i0 < cao; i0++) {
267 auto const w_x = weights.w_x[i0];
268 for (
int i1 = 0; i1 < cao; i1++) {
269 auto const w_xy = w_x * weights.w_y[i1];
270 for (
int i2 = 0; i2 < cao; i2++) {
271 auto const w_xyz = w_xy * weights.w_z[i2];
272 kernel(q_ind, w_xyz);
static DEVICE_QUALIFIER constexpr Vector< T, N > broadcast(typename Base::value_type const &value) noexcept
Create a vector that has all entries set to the same value.
Cache for interpolation weights.
void zfill(std::size_t size)
Fill cache with zero-initialized data.
void store(InterpolationWeights< cao > const &weights)
Push back weights for one point.
void store_at(std::size_t p_index, InterpolationWeights< cao > const &weights)
Insert weights for one point.
auto cao() const
Charge assignment order the weights are for.
void reset(int cao)
Reset the cache.
InterpolationWeightsView< cao > load(std::size_t p_index) const
Load entry from the cache.
p3m_interpolation_cache()
auto size() const
Number of points in the cache.
InterpolationWeights< cao > p3m_calculate_interpolation_weights(std::span< const double, 3 > position, Utils::Vector3d const &ai, P3MLocalMesh const &local_mesh)
Calculate the P-th order interpolation weights.
void p3m_interpolate(P3MLocalMesh const &local_mesh, WeightsStorage< cao > const &weights, Kernel kernel)
P3M grid interpolation.
DEVICE_QUALIFIER auto bspline(int i, T x) -> T requires((order > 0) and(order<=7))
Formula of the B-spline.
int ind
Linear index of the corner of the interpolation cube.
std::span< double const, cao > w_z
std::span< double const, cao > w_x
Weights for the directions.
std::span< double const, cao > w_y
Interpolation weights for one point.
Utils::Array< double, cao > w_y
Utils::Array< double, cao > w_x
Weights for the directions.
int ind
Linear index of the corner of the interpolation cube.
Utils::Array< double, cao > w_z
Properties of the local mesh.
Utils::Vector3i dim
dimension (size) of local mesh including halo layers.
int q_2_off
offset between mesh lines of the last dimension
Utils::Vector3d ld_pos
position of the first local mesh point.
int q_21_off
offset between mesh lines of the two last dimensions
DEVICE_QUALIFIER constexpr pointer data() noexcept