ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
interpolation.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2026 The ESPResSo project
3 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010
4 * Max-Planck-Institute for Polymer Research, Theory Group
5 *
6 * This file is part of ESPResSo.
7 *
8 * ESPResSo is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * ESPResSo is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#pragma once
23
24#include <config/config.hpp>
25
26#include <utils/index.hpp>
28
29#include <Kokkos_Core.hpp>
30
31#include <algorithm>
32#include <cassert>
33#include <cstddef>
34#include <iterator>
35#include <span>
36#include <tuple>
37#include <utility>
38#include <vector>
39
40/**
41 * @brief Interpolation weights for one point.
42 *
43 * Interpolation weights and grid offset for one point.
44 *
45 * @tparam cao Interpolation order.
46 */
47template <int cao> struct InterpolationWeights {
48 /** Linear index of the corner of the interpolation cube. */
49 int ind;
50 /** Weights for the directions */
52};
53
54template <int cao> struct InterpolationWeightsView {
55 /** Linear index of the corner of the interpolation cube. */
56 int ind;
57 /** Weights for the directions */
58 std::span<double const, cao> w_x, w_y, w_z;
59};
60
61/**
62 * @brief Cache for interpolation weights.
63 *
64 * This is a storage container for interpolation weights of
65 * type InterpolationWeights.
66 */
68 int m_cao = 0;
69 /** Charge fractions for mesh assignment. */
71 std::vector<double> ca_frac_spillover;
72 /** index of first mesh point for charge assignment. */
74 std::vector<int> ca_fmp_spillover;
75
76public:
78 : ca_frac("p3m_interpolation_cache::ca_frac", 0, 0),
79 ca_fmp("p3m_interpolation_cache::ca_fmp", 0, 0) {}
80
81 /**
82 * @brief Number of points in the cache.
83 * @return Number of points currently in the cache.
84 */
85 auto size() const { return ca_fmp.size() + ca_fmp_spillover.size(); }
86
87 /**
88 * @brief Charge assignment order the weights are for.
89 * @return The charge assignment order.
90 */
91 auto cao() const { return m_cao; }
92
93 /**
94 * @brief Fill cache with zero-initialized data.
95 * Meant for the parallel weight interpolation calculation.
96 * @param size Number of elements.
97 */
98 void zfill(std::size_t size) {
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);
103 }
104 assert(ca_frac_spillover.empty());
105 assert(ca_fmp_spillover.empty());
106 // data must be contiguous in memory
107 assert(size == 0 or
108 (std::distance(&ca_fmp(0), &ca_fmp(size - 1)) == size - 1));
109 }
110
111 /**
112 * @brief Push back weights for one point.
113 *
114 * @tparam cao Interpolation order has to match the order
115 * set at last call to @ref p3m_interpolation_cache::reset.
116 * @param weights Interpolation weights to store.
117 */
118 template <int cao> void store(InterpolationWeights<cao> const &weights) {
119 assert(cao == m_cao);
120
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);
126 }
127
128 /**
129 * @brief Insert weights for one point.
130 *
131 * @tparam cao Interpolation order has to match the order
132 * set at last call to @ref p3m_interpolation_cache::reset.
133 * @param p_index Particle index.
134 * @param weights Interpolation weights to store.
135 */
136 template <int cao>
137 void store_at(std::size_t p_index, InterpolationWeights<cao> const &weights) {
138 assert(cao == m_cao);
139 assert(p_index < ca_fmp.size());
140
141 auto copy_weights = [](InterpolationWeights<cao> const &src, auto dst) {
142 std::copy_n(src.w_x.data(), cao, dst);
143 std::advance(dst, cao);
144 std::copy_n(src.w_y.data(), cao, dst);
145 std::advance(dst, cao);
146 std::copy_n(src.w_z.data(), cao, dst);
147 };
148
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);
152 }
153
154 /**
155 * @brief Load entry from the cache.
156 *
157 * This loads an entry at an index from the cache,
158 * the entries are indexed by the order they were stored.
159 *
160 * @tparam cao Interpolation order has to match the order
161 * set at last call to @ref p3m_interpolation_cache::reset.
162 * @param p_index Index of the entry to load.
163 * @return Interpolation weights.
164 */
165 template <int cao>
166 InterpolationWeightsView<cao> load(std::size_t p_index) const {
167 assert(cao == m_cao);
168 assert(p_index < size());
169
170 int index = -1;
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;
177 } else {
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;
181 }
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};
188 }
189
190 /**
191 * @brief Reset the cache.
192 *
193 * @param cao Interpolation order.
194 */
195 void reset(int cao) {
196 m_cao = cao;
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();
201 }
202};
203
204/**
205 * @brief Calculate the P-th order interpolation weights.
206 *
207 * As described in from @cite hockney88a 5-189 (or 8-61).
208 * The weights are also tabulated in @cite deserno98a @cite deserno98b.
209 */
210template <int cao, Utils::MemoryOrder memory_order>
212p3m_calculate_interpolation_weights(std::span<const double, 3> position,
213 Utils::Vector3d const &ai,
214 P3MLocalMesh const &local_mesh) {
215 /** position shift for calc. of first assignment mesh point. */
216 auto const pos_shift = std::floor((cao - 1) / 2.0) - (cao % 2) / 2.0;
217
218 /* distance to nearest mesh point */
219 Utils::Vector3d dist;
220
221 /* nearest mesh point */
222 Utils::Vector3i nmp;
223
224 for (unsigned int d = 0; d < 3; d++) {
225 /* particle position in mesh coordinates */
226 auto const pos = ((position[d] - local_mesh.ld_pos[d]) * ai[d]) - pos_shift;
227
228 nmp[d] = static_cast<int>(pos);
229
230 /* distance to nearest mesh point */
231 dist[d] = (pos - nmp[d]) - 0.5;
232 }
233
235
236 /* 3d-array index of nearest mesh point */
237 ret.ind = Utils::get_linear_index<memory_order>(nmp, local_mesh.dim);
238
239 assert((nmp + Utils::Vector3i::broadcast(cao)) <= local_mesh.dim);
240 for (int i = 0; i < cao; i++) {
241 using Utils::bspline;
242
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]);
246 }
247
248 return ret;
249}
250
251/**
252 * @brief P3M grid interpolation.
253 *
254 * This runs an kernel for every interpolation point
255 * in a set of interpolation weights with the linear
256 * grid index and the weight of the point as arguments.
257 *
258 * @param local_mesh Mesh info.
259 * @param weights Set of weights
260 * @param kernel The kernel to run.
261 */
262template <int cao, template <int> class WeightsStorage, class Kernel>
263void p3m_interpolate(P3MLocalMesh const &local_mesh,
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);
273 q_ind++;
274 }
275 q_ind += local_mesh.q_2_off;
276 }
277 q_ind += local_mesh.q_21_off;
278 }
279}
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.
Definition Vector.hpp:131
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.
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.
Definition bspline.hpp:43
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
Definition Array.hpp:132