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-2022 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 <utils/index.hpp>
26
27#include <algorithm>
28#include <cassert>
29#include <cstddef>
30#include <span>
31#include <tuple>
32#include <utility>
33#include <vector>
34
35/**
36 * @brief Interpolation weights for one point.
37 *
38 * Interpolation weights and grid offset for one point.
39 *
40 * @tparam cao Interpolation order.
41 */
42template <int cao> struct InterpolationWeights {
43 /** Linear index of the corner of the interpolation cube. */
44 int ind;
45 /** Weights for the directions */
47};
48
49/**
50 * @brief Cache for interpolation weights.
51 *
52 * This is a storage container for interpolation weights of
53 * type InterpolationWeights.
54 */
56 int m_cao = 0;
57 /** Charge fractions for mesh assignment. */
58 std::vector<double> ca_frac;
59 /** index of first mesh point for charge assignment. */
60 std::vector<int> ca_fmp;
61
62public:
63 /**
64 * @brief Number of points in the cache.
65 * @return Number of points currently in the cache.
66 */
67 auto size() const { return ca_fmp.size(); }
68
69 /**
70 * @brief Charge assignment order the weights are for.
71 * @return The charge assignment order.
72 */
73 auto cao() const { return m_cao; }
74
75 /**
76 * @brief Push back weights for one point.
77 *
78 * @tparam cao Interpolation order has to match the order
79 * set at last call to @ref p3m_interpolation_cache::reset.
80 * @param w Interpolation weights to store.
81 */
82 template <int cao> void store(const InterpolationWeights<cao> &w) {
83 assert(cao == m_cao);
84
85 ca_fmp.push_back(w.ind);
86 auto it = std::back_inserter(ca_frac);
87 std::ranges::copy(w.w_x, it);
88 std::ranges::copy(w.w_y, it);
89 std::ranges::copy(w.w_z, it);
90 }
91
92 /**
93 * @brief Load entry from the cache.
94 *
95 * This loads an entry at an index from the cache,
96 * the entries are indexed by the order they were stored.
97 *
98 * @tparam cao Interpolation order has to match the order
99 * set at last call to @ref p3m_interpolation_cache::reset.
100 * @param i Index of the entry to load.
101 * @return i-it interpolation weights.
102 */
103 template <int cao> InterpolationWeights<cao> load(std::size_t i) const {
104 assert(cao == m_cao);
105 assert(i < size());
106
108 ret.ind = ca_fmp[i];
109
110 auto const view = std::span(std::as_const(ca_frac));
111 auto const offset = 3ul * i * static_cast<std::size_t>(cao);
112
113 std::ranges::copy(view.subspan(offset + 0ul * cao, cao), ret.w_x.begin());
114 std::ranges::copy(view.subspan(offset + 1ul * cao, cao), ret.w_y.begin());
115 std::ranges::copy(view.subspan(offset + 2ul * cao, cao), ret.w_z.begin());
116
117 return ret;
118 }
119
120 /**
121 * @brief Reset the cache.
122 *
123 * @param cao Interpolation order.
124 */
125 void reset(int cao) {
126 m_cao = cao;
127 ca_frac.clear();
128 ca_fmp.clear();
129 }
130};
131
132/**
133 * @brief Calculate the P-th order interpolation weights.
134 *
135 * As described in from @cite hockney88a 5-189 (or 8-61).
136 * The weights are also tabulated in @cite deserno98a @cite deserno98b.
137 */
138template <int cao>
141 const Utils::Vector3d &ai,
142 P3MLocalMesh const &local_mesh) {
143 /** position shift for calc. of first assignment mesh point. */
144 auto const pos_shift = std::floor((cao - 1) / 2.0) - (cao % 2) / 2.0;
145
146 /* distance to nearest mesh point */
147 Utils::Vector3d dist;
148
149 /* nearest mesh point */
150 Utils::Vector3i nmp;
151
152 for (unsigned int d = 0; d < 3; d++) {
153 /* particle position in mesh coordinates */
154 auto const pos = ((position[d] - local_mesh.ld_pos[d]) * ai[d]) - pos_shift;
155
156 nmp[d] = static_cast<int>(pos);
157
158 /* distance to nearest mesh point */
159 dist[d] = (pos - nmp[d]) - 0.5;
160 }
161
163
164 /* 3d-array index of nearest mesh point */
165 ret.ind = Utils::get_linear_index(nmp, local_mesh.dim,
167
168 assert((nmp + Utils::Vector3i::broadcast(cao)) <= local_mesh.dim);
169 for (int i = 0; i < cao; i++) {
170 using Utils::bspline;
171
172 ret.w_x[i] = bspline<cao>(i, dist[0]);
173 ret.w_y[i] = bspline<cao>(i, dist[1]);
174 ret.w_z[i] = bspline<cao>(i, dist[2]);
175 }
176
177 return ret;
178}
179
180/**
181 * @brief P3M grid interpolation.
182 *
183 * This runs an kernel for every interpolation point
184 * in a set of interpolation weights with the linear
185 * grid index and the weight of the point as arguments.
186 *
187 * @param local_mesh Mesh info.
188 * @param weights Set of weights
189 * @param kernel The kernel to run.
190 */
191template <int cao, class Kernel>
192void p3m_interpolate(P3MLocalMesh const &local_mesh,
193 InterpolationWeights<cao> const &weights, Kernel kernel) {
194 auto q_ind = weights.ind;
195 for (int i0 = 0; i0 < cao; i0++) {
196 auto const tmp0 = weights.w_x[i0];
197 for (int i1 = 0; i1 < cao; i1++) {
198 auto const tmp1 = tmp0 * weights.w_y[i1];
199 for (int i2 = 0; i2 < cao; i2++) {
200 kernel(q_ind, tmp1 * weights.w_z[i2]);
201
202 q_ind++;
203 }
204 q_ind += local_mesh.q_2_off;
205 }
206 q_ind += local_mesh.q_21_off;
207 }
208}
static DEVICE_QUALIFIER constexpr Vector< T, N > broadcast(typename Base::value_type const &value)
Create a vector that has all entries set to the same value.
Definition Vector.hpp:110
Cache for interpolation weights.
void store(const InterpolationWeights< cao > &w)
Push back weights for one point.
InterpolationWeights< cao > load(std::size_t i) const
Load entry from the cache.
auto cao() const
Charge assignment order the weights are for.
void reset(int cao)
Reset the cache.
auto size() const
Number of points in the cache.
void p3m_interpolate(P3MLocalMesh const &local_mesh, InterpolationWeights< cao > const &weights, Kernel kernel)
P3M grid interpolation.
InterpolationWeights< cao > p3m_calculate_interpolation_weights(const Utils::Vector3d &position, const Utils::Vector3d &ai, P3MLocalMesh const &local_mesh)
Calculate the P-th order interpolation weights.
int get_linear_index(int a, int b, int c, const Vector3i &adim, MemoryOrder memory_order=MemoryOrder::COLUMN_MAJOR)
get the linear index from the position (a,b,c) in a 3D grid of dimensions adim.
Definition index.hpp:43
DEVICE_QUALIFIER auto bspline(int i, T x) -> std::enable_if_t<(order > 0) &&(order<=7), T >
Formula of the B-spline.
Definition bspline.hpp:32
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.
int q_2_off
offset between mesh lines of the last dimension
double ld_pos[3]
position of the first local mesh point.
int q_21_off
offset between mesh lines of the two last dimensions
DEVICE_QUALIFIER constexpr iterator begin() noexcept
Definition Array.hpp:128