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