Loading [MathJax]/extensions/TeX/AMSmath.js
ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
send_mesh.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2024 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#include "config/config.hpp"
23
24#if defined(P3M) or defined(DP3M)
25
26#include "fft/fft.hpp"
27#include "p3m/common.hpp"
28#include "p3m/packing.hpp"
29#include "p3m/send_mesh.hpp"
30
31#include <utils/Vector.hpp>
33
34#include <boost/mpi/communicator.hpp>
35#include <boost/mpi/datatype.hpp>
36
37#include <mpi.h>
38
39#include <algorithm>
40#include <complex>
41#include <cstddef>
42#include <span>
43#include <utility>
44
45template <typename T>
46static void mesh_sendrecv(T const *const sendbuf, int scount, int dest,
47 T *const recvbuf, int rcount, int source,
48 boost::mpi::communicator const &comm, int tag) {
49 auto const type = boost::mpi::get_mpi_datatype<T>(*sendbuf);
50 MPI_Sendrecv(reinterpret_cast<void const *>(sendbuf), scount, type, dest, tag,
51 reinterpret_cast<void *>(recvbuf), rcount, type, source, tag,
52 comm, MPI_STATUS_IGNORE);
53}
54
55/** Add values of a 3d-grid input block (size[3]) to values of 3d-grid
56 * output array with dimension dim[3] at start position start[3].
57 *
58 * \param in Pointer to first element of input block data.
59 * \param out Pointer to first element of output grid.
60 * \param start Start position of block in output grid.
61 * \param size Dimensions of the block
62 * \param dim Dimensions of the output grid.
63 */
64template <typename FloatType>
65static void p3m_add_block(FloatType const *in, FloatType *out,
66 int const start[3], int const size[3],
67 int const dim[3]) {
68 /* fast, mid and slow changing indices */
69 int f, m, s;
70 /* linear index of in grid, linear index of out grid */
71 int li_in = 0, li_out = 0;
72 /* offsets for indices in output grid */
73 int m_out_offset, s_out_offset;
74
75 li_out = start[2] + (dim[2] * (start[1] + (dim[1] * start[0])));
76 m_out_offset = dim[2] - size[2];
77 s_out_offset = (dim[2] * (dim[1] - size[1]));
78
79 for (s = 0; s < size[0]; s++) {
80 for (m = 0; m < size[1]; m++) {
81 for (f = 0; f < size[2]; f++) {
82 out[li_out++] += in[li_in++];
83 }
84 li_out += m_out_offset;
85 }
86 li_out += s_out_offset;
87 }
88}
89
90template <typename FloatType>
91void p3m_send_mesh<FloatType>::resize(boost::mpi::communicator const &comm,
92 P3MLocalMesh const &local_mesh) {
93 int done[3] = {0, 0, 0};
94 /* send grids */
95 for (int i = 0; i < 3; i++) {
96 for (int j = 0; j < 3; j++) {
97 /* left */
98 s_ld[i * 2][j] = 0 + done[j] * local_mesh.margin[j * 2];
99 if (j == i)
100 s_ur[i * 2][j] = local_mesh.margin[j * 2];
101 else
102 s_ur[i * 2][j] =
103 local_mesh.dim[j] - done[j] * local_mesh.margin[(j * 2) + 1];
104 /* right */
105 if (j == i)
106 s_ld[(i * 2) + 1][j] = local_mesh.in_ur[j];
107 else
108 s_ld[(i * 2) + 1][j] = 0 + done[j] * local_mesh.margin[j * 2];
109 s_ur[(i * 2) + 1][j] =
110 local_mesh.dim[j] - done[j] * local_mesh.margin[(j * 2) + 1];
111 }
112 done[i] = 1;
113 }
114 max = 0;
115 for (int i = 0; i < 6; i++) {
116 s_size[i] = 1;
117 for (int j = 0; j < 3; j++) {
118 s_dim[i][j] = s_ur[i][j] - s_ld[i][j];
119 s_size[i] *= s_dim[i][j];
120 }
121 max = std::max(max, s_size[i]);
122 }
123 /* communication */
124 auto const node_neighbors = Utils::Mpi::cart_neighbors<3>(comm);
125
126 int r_margin[6];
127 for (int i = 0; i < 6; i++) {
128 auto const j = (i % 2 == 0) ? i + 1 : i - 1;
129
130 if (node_neighbors[i] != comm.rank()) {
131 mesh_sendrecv(&(local_mesh.margin[i]), 1, node_neighbors[i],
132 &(r_margin[j]), 1, node_neighbors[j], comm, REQ_P3M_INIT);
133 } else {
134 r_margin[j] = local_mesh.margin[i];
135 }
136 }
137 /* recv grids */
138 for (int i = 0; i < 3; i++) {
139 for (int j = 0; j < 3; j++) {
140 if (j == i) {
141 r_ld[i * 2][j] = s_ld[i * 2][j] + local_mesh.margin[2 * j];
142 r_ur[i * 2][j] = s_ur[i * 2][j] + r_margin[2 * j];
143 r_ld[(i * 2) + 1][j] = s_ld[(i * 2) + 1][j] - r_margin[(2 * j) + 1];
144 r_ur[(i * 2) + 1][j] =
145 s_ur[(i * 2) + 1][j] - local_mesh.margin[(2 * j) + 1];
146 } else {
147 r_ld[i * 2][j] = s_ld[i * 2][j];
148 r_ur[i * 2][j] = s_ur[i * 2][j];
149 r_ld[(i * 2) + 1][j] = s_ld[(i * 2) + 1][j];
150 r_ur[(i * 2) + 1][j] = s_ur[(i * 2) + 1][j];
151 }
152 }
153 }
154 for (int i = 0; i < 6; i++) {
155 r_size[i] = 1;
156 for (int j = 0; j < 3; j++) {
157 r_dim[i][j] = r_ur[i][j] - r_ld[i][j];
158 r_size[i] *= r_dim[i][j];
159 }
160 max = std::max(max, r_size[i]);
161 }
162}
163
164template <typename FloatType>
165void p3m_send_mesh<FloatType>::gather_grid(boost::mpi::communicator const &comm,
166 std::span<FloatType *> meshes,
167 Utils::Vector3i const &dim) {
168 auto const node_neighbors = Utils::Mpi::cart_neighbors<3>(comm);
169 send_grid.resize(max * meshes.size());
170 recv_grid.resize(max * meshes.size());
171
172 /* direction loop */
173 for (int s_dir = 0; s_dir < 6; s_dir++) {
174 auto const r_dir = (s_dir % 2 == 0) ? s_dir + 1 : s_dir - 1;
175
176 /* pack send block */
177 if (s_size[s_dir] > 0) {
178 for (std::size_t i = 0; i < meshes.size(); i++) {
179 fft_pack_block(meshes[i], send_grid.data() + i * s_size[s_dir],
180 s_ld[s_dir], s_dim[s_dir], dim.data(), 1);
181 }
182 }
183
184 /* communication */
185 if (node_neighbors[s_dir] != comm.rank()) {
186 auto const send_size = static_cast<int>(meshes.size()) * s_size[s_dir];
187 auto const recv_size = static_cast<int>(meshes.size()) * r_size[r_dir];
188 mesh_sendrecv(send_grid.data(), send_size, node_neighbors[s_dir],
189 recv_grid.data(), recv_size, node_neighbors[r_dir], comm,
190 REQ_P3M_GATHER);
191 } else {
192 std::swap(send_grid, recv_grid);
193 }
194 /* add recv block */
195 if (r_size[r_dir] > 0) {
196 for (std::size_t i = 0; i < meshes.size(); i++) {
197 p3m_add_block(recv_grid.data() + i * r_size[r_dir], meshes[i],
198 r_ld[r_dir], r_dim[r_dir], dim.data());
199 }
200 }
201 }
202}
203
204template <typename FloatType>
205void p3m_send_mesh<FloatType>::spread_grid(boost::mpi::communicator const &comm,
206 std::span<FloatType *> meshes,
207 Utils::Vector3i const &dim) {
208 auto const node_neighbors = Utils::Mpi::cart_neighbors<3>(comm);
209 send_grid.resize(max * meshes.size());
210 recv_grid.resize(max * meshes.size());
211
212 /* direction loop */
213 for (int s_dir = 5; s_dir >= 0; s_dir--) {
214 auto const r_dir = (s_dir % 2 == 0) ? s_dir + 1 : s_dir - 1;
215
216 /* pack send block */
217 if (r_size[r_dir] > 0) {
218 for (std::size_t i = 0; i < meshes.size(); i++) {
219 fft_pack_block(meshes[i], send_grid.data() + i * r_size[r_dir],
220 r_ld[r_dir], r_dim[r_dir], dim.data(), 1);
221 }
222 }
223 /* communication */
224 if (node_neighbors[r_dir] != comm.rank()) {
225 auto const send_size = static_cast<int>(meshes.size()) * r_size[r_dir];
226 auto const recv_size = static_cast<int>(meshes.size()) * s_size[s_dir];
227 mesh_sendrecv(send_grid.data(), send_size, node_neighbors[r_dir],
228 recv_grid.data(), recv_size, node_neighbors[s_dir], comm,
229 REQ_P3M_SPREAD);
230 } else {
231 std::swap(send_grid, recv_grid);
232 }
233 /* unpack recv block */
234 if (s_size[s_dir] > 0) {
235 for (std::size_t i = 0; i < meshes.size(); i++) {
236 fft_unpack_block(recv_grid.data() + i * s_size[s_dir], meshes[i],
237 s_ld[s_dir], s_dim[s_dir], dim.data(), 1);
238 }
239 }
240 }
241}
242
243template class p3m_send_mesh<float>;
244template class p3m_send_mesh<double>;
245
246#endif // defined(P3M) or defined(DP3M)
Vector implementation and trait types for boost qvm interoperability.
P3M halo communicator.
Definition send_mesh.hpp:38
void gather_grid(boost::mpi::communicator const &comm, std::span< FloatType * > meshes, Utils::Vector3i const &dim)
void spread_grid(boost::mpi::communicator const &comm, std::span< FloatType * > meshes, Utils::Vector3i const &dim)
void resize(boost::mpi::communicator const &comm, P3MLocalMesh const &local_mesh)
Definition send_mesh.cpp:91
This file contains the defaults for ESPResSo.
Routines, row decomposition, data structures and communication for the 3D-FFT.
Common functions for dipolar and charge P3M.
void fft_pack_block(FloatType const *const in, FloatType *const out, int const *start, int const *size, int const *dim, int element)
Pack a 3D-block of size size starting at start of an input 3D-grid in with dimension dim into an outp...
Definition packing.hpp:44
void fft_unpack_block(FloatType const *const in, FloatType *const out, int const *start, int const *size, int const *dim, int element)
Unpack a 3D-block in of size size into an output 3D-grid out of size dim starting at position start.
Definition packing.hpp:83
static void p3m_add_block(FloatType const *in, FloatType *out, int const start[3], int const size[3], int const dim[3])
Add values of a 3d-grid input block (size[3]) to values of 3d-grid output array with dimension dim[3]...
Definition send_mesh.cpp:65
static void mesh_sendrecv(T const *const sendbuf, int scount, int dest, T *const recvbuf, int rcount, int source, boost::mpi::communicator const &comm, int tag)
Definition send_mesh.cpp:46
Properties of the local mesh.
Utils::Vector3i dim
dimension (size) of local mesh including halo layers.
int margin[6]
number of margin mesh points.
Utils::Vector3i in_ur
inner up right grid point + (1,1,1)
DEVICE_QUALIFIER constexpr pointer data() noexcept
Definition Array.hpp:132