ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
ghosts.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/** \file
22 * Ghost particles and particle exchange.
23 *
24 * For more information on ghosts,
25 * see \ref ghosts.hpp "ghosts.hpp"
26 *
27 * Note on variable naming:
28 * - a "GhostCommunicator" is always named "gcr",
29 * - a "GhostCommunication" is always named "ghost_comm".
30 */
31#include "ghosts.hpp"
32
33#include "BoxGeometry.hpp"
34#include "Particle.hpp"
35#include "system/System.hpp"
36
37#include <utils/Span.hpp>
39
40#include <boost/archive/binary_iarchive.hpp>
41#include <boost/archive/binary_oarchive.hpp>
42#include <boost/iostreams/device/array.hpp>
43#include <boost/iostreams/device/back_inserter.hpp>
44#include <boost/iostreams/stream.hpp>
45#include <boost/mpi/collectives.hpp>
46#include <boost/range/numeric.hpp>
47#include <boost/serialization/vector.hpp>
48
49#include <algorithm>
50#include <cassert>
51#include <cstddef>
52#include <functional>
53#include <iterator>
54#include <vector>
55
56/** Tag for ghosts communications. */
57#define REQ_GHOST_SEND 100
58
59/**
60 * Class that stores marshalled data for ghost communications.
61 * To store and retrieve data, use the adapter classes below.
62 */
63class CommBuf {
64public:
65 /** Returns a pointer to the non-bond storage.
66 */
67 char *data() { return buf.data(); }
68 const char *data() const { return buf.data(); }
69
70 /** Returns the number of elements in the non-bond storage.
71 */
72 std::size_t size() const { return buf.size(); }
73
74 /** Resizes the underlying storage s.t. the object is capable
75 * of holding "new_size" chars.
76 * @param new_size new size
77 */
78 void resize(std::size_t new_size) { buf.resize(new_size); }
79
80 /** Returns a reference to the bond storage.
81 */
82 auto &bonds() { return bondbuf; }
83 const auto &bonds() const { return bondbuf; }
84
85private:
86 std::vector<char> buf; ///< Buffer for everything but bonds
87 std::vector<char> bondbuf; ///< Buffer for bond lists
88};
89
90/** @brief Pseudo-archive to calculate the size of the serialization buffer. */
92 std::size_t m_size = 0;
93
94public:
95 auto size() const { return m_size; }
96
97 template <class T> auto &operator<<(T &) {
98 m_size += sizeof(T);
99 return *this;
100 }
101
102 template <class T> auto &operator&(T &t) { return *this << t; }
103};
104
105/** @brief Type of reduction to carry out during serialization. */
106enum class ReductionPolicy {
107 /** @brief Reduction for domain-to-domain particle communication. */
108 MOVE,
109 /** @brief Reduction for cell-to-cell particle update. */
110 UPDATE,
111};
112
113/** @brief Whether to save the state to or load the state from the archive. */
115
116/**
117 * @brief Serialize particle data, possibly with reduction.
118 * The reduction can take place during the save stage, e.g. to apply
119 * a ghost shift to the particle position, or during the load stage,
120 * e.g. to transfer momentum between particles in two local cells.
121 */
122template <class Archive>
123static void
124serialize_and_reduce(Archive &ar, Particle &p, unsigned int data_parts,
125 ReductionPolicy policy, SerializationDirection direction,
126 BoxGeometry const &box_geo,
127 Utils::Vector3d const *ghost_shift) {
128 if (data_parts & GHOSTTRANS_PROPRTS) {
129 ar & p.id() & p.mol_id() & p.type() & p.propagation();
130#ifdef ROTATION
131 ar & p.rotation();
132#ifdef ROTATIONAL_INERTIA
133 ar & p.rinertia();
134#endif
135#endif
136#ifdef MASS
137 ar & p.mass();
138#endif
139#ifdef ELECTROSTATICS
140 ar & p.q();
141#endif
142#ifdef DIPOLES
143 ar & p.dipm();
144#endif
145#ifdef LB_ELECTROHYDRODYNAMICS
146 ar & p.mu_E();
147#endif
148#ifdef VIRTUAL_SITES_RELATIVE
149 ar & p.vs_relative();
150#endif
151#ifdef THERMOSTAT_PER_PARTICLE
152 ar & p.gamma();
153#ifdef ROTATION
154 ar & p.gamma_rot();
155#endif
156#endif
157#ifdef EXTERNAL_FORCES
158 ar & p.fixed();
159 ar & p.ext_force();
160#ifdef ROTATION
161 ar & p.ext_torque();
162#endif
163#endif
164#ifdef ENGINE
165 ar & p.swimming();
166#endif
167 }
168 if (data_parts & GHOSTTRANS_POSITION) {
169 if (direction == SerializationDirection::SAVE and ghost_shift != nullptr) {
170 /* ok, this is not nice, but perhaps fast */
171 auto pos = p.pos() + *ghost_shift;
172 auto img = p.image_box();
173 box_geo.fold_position(pos, img);
174 ar & pos;
175 ar & img;
176 } else {
177 ar & p.pos();
178 ar & p.image_box();
179 }
180#ifdef ROTATION
181 ar & p.quat();
182#endif
183#ifdef BOND_CONSTRAINT
184 ar & p.pos_last_time_step();
185#endif
186 }
187 if (data_parts & GHOSTTRANS_MOMENTUM) {
188 ar & p.v();
189#ifdef ROTATION
190 ar & p.omega();
191#endif
192 }
193 if (data_parts & GHOSTTRANS_FORCE) {
194 if (policy == ReductionPolicy::UPDATE and
195 direction == SerializationDirection::LOAD) {
197 ar & force;
198 p.force() += force;
199 } else {
200 ar & p.force();
201 }
202#ifdef ROTATION
203 if (policy == ReductionPolicy::UPDATE and
204 direction == SerializationDirection::LOAD) {
206 ar & torque;
207 p.torque() += torque;
208 } else {
209 ar & p.torque();
210 }
211#endif
212 }
213#ifdef BOND_CONSTRAINT
214 if (data_parts & GHOSTTRANS_RATTLE) {
215 if (policy == ReductionPolicy::UPDATE and
216 direction == SerializationDirection::LOAD) {
217 Utils::Vector3d correction;
218 ar & correction;
219 p.rattle_correction() += correction;
220 } else {
221 ar & p.rattle_correction();
222 }
223 }
224#endif
225}
226
227static auto calc_transmit_size(BoxGeometry const &box_geo,
228 unsigned data_parts) {
229 SerializationSizeCalculator sizeof_archive;
230 Particle p{};
231 serialize_and_reduce(sizeof_archive, p, data_parts, ReductionPolicy::MOVE,
232 SerializationDirection::SAVE, box_geo, nullptr);
233 return sizeof_archive.size();
234}
235
236static auto calc_transmit_size(GhostCommunication const &ghost_comm,
237 BoxGeometry const &box_geo,
238 unsigned int data_parts) {
239 if (data_parts & GHOSTTRANS_PARTNUM)
240 return sizeof(unsigned int) * ghost_comm.part_lists.size();
241
242 auto const n_part = boost::accumulate(
243 ghost_comm.part_lists, std::size_t{0},
244 [](std::size_t sum, auto part_list) { return sum + part_list->size(); });
245
246 return n_part * calc_transmit_size(box_geo, data_parts);
247}
248
249static void prepare_send_buffer(CommBuf &send_buffer,
250 GhostCommunication const &ghost_comm,
251 BoxGeometry const &box_geo,
252 unsigned int data_parts) {
253
254 /* reallocate send buffer */
255 send_buffer.resize(calc_transmit_size(ghost_comm, box_geo, data_parts));
256 send_buffer.bonds().clear();
257
258 auto archiver = Utils::MemcpyOArchive{Utils::make_span(send_buffer)};
259
260 /* Construct archive that pushes back to the bond buffer */
261 namespace io = boost::iostreams;
262 io::stream<io::back_insert_device<std::vector<char>>> os{
263 io::back_inserter(send_buffer.bonds())};
264 boost::archive::binary_oarchive bond_archiver{os};
265
266 /* put in data */
267 for (auto part_list : ghost_comm.part_lists) {
268 if (data_parts & GHOSTTRANS_PARTNUM) {
269 assert(part_list->size() <= std::numeric_limits<unsigned int>::max());
270 auto np = static_cast<unsigned int>(part_list->size());
271 archiver << np;
272 } else {
273 for (auto &p : *part_list) {
274 serialize_and_reduce(archiver, p, data_parts, ReductionPolicy::MOVE,
276 &ghost_comm.shift);
277 if (data_parts & GHOSTTRANS_BONDS) {
278 bond_archiver << p.bonds();
279 }
280 }
281 }
282 }
283
284 assert(archiver.bytes_written() == send_buffer.size());
285}
286
287static void prepare_ghost_cell(ParticleList *cell, std::size_t size) {
288 /* Adapt size */
289 cell->resize(size);
290
291 /* Mark particles as ghosts */
292 for (auto &p : *cell) {
293 p.set_ghost(true);
294 }
295}
296
297static void prepare_recv_buffer(CommBuf &recv_buffer,
298 GhostCommunication const &ghost_comm,
299 BoxGeometry const &box_geo,
300 unsigned int data_parts) {
301 /* reallocate recv buffer */
302 recv_buffer.resize(calc_transmit_size(ghost_comm, box_geo, data_parts));
303 /* clear bond buffer */
304 recv_buffer.bonds().clear();
305}
306
307static void put_recv_buffer(CommBuf &recv_buffer,
308 GhostCommunication const &ghost_comm,
309 BoxGeometry const &box_geo,
310 unsigned int data_parts) {
311 /* put back data */
312 auto archiver = Utils::MemcpyIArchive{Utils::make_span(recv_buffer)};
313
314 if (data_parts & GHOSTTRANS_PARTNUM) {
315 for (auto part_list : ghost_comm.part_lists) {
316 unsigned int np;
317 archiver >> np;
318 prepare_ghost_cell(part_list, np);
319 }
320 } else {
321 for (auto part_list : ghost_comm.part_lists) {
322 for (auto &p : *part_list) {
323 serialize_and_reduce(archiver, p, data_parts, ReductionPolicy::MOVE,
324 SerializationDirection::LOAD, box_geo, nullptr);
325 }
326 }
327 if (data_parts & GHOSTTRANS_BONDS) {
328 namespace io = boost::iostreams;
329 io::stream<io::array_source> bond_stream(io::array_source{
330 recv_buffer.bonds().data(), recv_buffer.bonds().size()});
331 boost::archive::binary_iarchive bond_archiver(bond_stream);
332
333 for (auto part_list : ghost_comm.part_lists) {
334 for (auto &p : *part_list) {
335 bond_archiver >> p.bonds();
336 }
337 }
338 }
339 }
340
341 assert(archiver.bytes_read() == recv_buffer.size());
342
343 recv_buffer.bonds().clear();
344}
345
346#ifdef BOND_CONSTRAINT
347static void
349 const GhostCommunication &ghost_comm) {
350 /* put back data */
351 auto archiver = Utils::MemcpyIArchive{Utils::make_span(recv_buffer)};
352 for (auto &part_list : ghost_comm.part_lists) {
353 for (Particle &part : *part_list) {
355 archiver >> pr;
356 part.rattle_params() += pr;
357 }
358 }
359}
360#endif
361
362static void add_forces_from_recv_buffer(CommBuf &recv_buffer,
363 const GhostCommunication &ghost_comm) {
364 /* put back data */
365 auto archiver = Utils::MemcpyIArchive{Utils::make_span(recv_buffer)};
366 for (auto &part_list : ghost_comm.part_lists) {
367 for (Particle &part : *part_list) {
368 ParticleForce pf;
369 archiver >> pf;
370 part.force_and_torque() += pf;
371 }
372 }
373}
374
375static void cell_cell_transfer(GhostCommunication const &ghost_comm,
376 BoxGeometry const &box_geo,
377 unsigned int data_parts) {
378 CommBuf buffer;
379 if (!(data_parts & GHOSTTRANS_PARTNUM)) {
380 buffer.resize(calc_transmit_size(box_geo, data_parts));
381 }
382 /* transfer data */
383 auto const offset = ghost_comm.part_lists.size() / 2;
384 for (std::size_t pl = 0; pl < offset; pl++) {
385 auto *src_list = ghost_comm.part_lists[pl];
386 auto *dst_list = ghost_comm.part_lists[pl + offset];
387
388 if (data_parts & GHOSTTRANS_PARTNUM) {
389 prepare_ghost_cell(dst_list, src_list->size());
390 } else {
391 auto &src_part = *src_list;
392 auto &dst_part = *dst_list;
393 assert(src_part.size() == dst_part.size());
394
395 for (std::size_t i = 0; i < src_part.size(); i++) {
396 auto ar_out = Utils::MemcpyOArchive{Utils::make_span(buffer)};
397 auto ar_in = Utils::MemcpyIArchive{Utils::make_span(buffer)};
398 auto &p1 = src_part.begin()[i];
399 auto &p2 = dst_part.begin()[i];
400 serialize_and_reduce(ar_out, p1, data_parts, ReductionPolicy::UPDATE,
402 &ghost_comm.shift);
403 serialize_and_reduce(ar_in, p2, data_parts, ReductionPolicy::UPDATE,
404 SerializationDirection::LOAD, box_geo, nullptr);
405 if (data_parts & GHOSTTRANS_BONDS) {
406 p2.bonds() = p1.bonds();
407 }
408 }
409 }
410 }
411}
412
413static bool is_send_op(int comm_type, int node, int this_node) {
414 return ((comm_type == GHOST_SEND) || (comm_type == GHOST_RDCE) ||
415 (comm_type == GHOST_BCST && node == this_node));
416}
417
418static bool is_recv_op(int comm_type, int node, int this_node) {
419 return ((comm_type == GHOST_RECV) ||
420 (comm_type == GHOST_BCST && node != this_node) ||
421 (comm_type == GHOST_RDCE && node == this_node));
422}
423
424static bool is_prefetchable(GhostCommunication const &ghost_comm,
425 int this_node) {
426 int const comm_type = ghost_comm.type & GHOST_JOBMASK;
427 int const prefetch = ghost_comm.type & GHOST_PREFETCH;
428 int const node = ghost_comm.node;
429 return is_send_op(comm_type, node, this_node) && prefetch;
430}
431
432static bool is_poststorable(GhostCommunication const &ghost_comm,
433 int this_node) {
434 int const comm_type = ghost_comm.type & GHOST_JOBMASK;
435 int const poststore = ghost_comm.type & GHOST_PSTSTORE;
436 int const node = ghost_comm.node;
437 return is_recv_op(comm_type, node, this_node) && poststore;
438}
439
441 BoxGeometry const &box_geo, unsigned int data_parts) {
442 if (GHOSTTRANS_NONE == data_parts)
443 return;
444
445 static CommBuf send_buffer, recv_buffer;
446
447 auto const &comm = gcr.mpi_comm;
448
449 for (auto it = gcr.communications.begin(); it != gcr.communications.end();
450 ++it) {
451 const GhostCommunication &ghost_comm = *it;
452 int const comm_type = ghost_comm.type & GHOST_JOBMASK;
453
454 if (comm_type == GHOST_LOCL) {
455 cell_cell_transfer(ghost_comm, box_geo, data_parts);
456 continue;
457 }
458
459 int const prefetch = ghost_comm.type & GHOST_PREFETCH;
460 int const poststore = ghost_comm.type & GHOST_PSTSTORE;
461 int const node = ghost_comm.node;
462
463 /* prepare send buffer if necessary */
464 if (is_send_op(comm_type, node, comm.rank())) {
465 /* ok, we send this step, prepare send buffer if not yet done */
466 if (!prefetch) {
467 prepare_send_buffer(send_buffer, ghost_comm, box_geo, data_parts);
468 }
469 // Check prefetched send buffers (must also hold for buffers allocated
470 // in the previous lines.)
471 assert(send_buffer.size() ==
472 calc_transmit_size(ghost_comm, box_geo, data_parts));
473 } else if (prefetch) {
474 /* we do not send this time, let's look for a prefetch */
475 auto prefetch_ghost_comm = std::find_if(
476 std::next(it), gcr.communications.end(),
477 [this_node = comm.rank()](GhostCommunication const &ghost_comm) {
478 return is_prefetchable(ghost_comm, this_node);
479 });
480
481 if (prefetch_ghost_comm != gcr.communications.end())
482 prepare_send_buffer(send_buffer, *prefetch_ghost_comm, box_geo,
483 data_parts);
484 }
485
486 /* recv buffer for recv and multinode operations to this node */
487 if (is_recv_op(comm_type, node, comm.rank()))
488 prepare_recv_buffer(recv_buffer, ghost_comm, box_geo, data_parts);
489
490 /* transfer data */
491 // Use two send/recvs in order to avoid having to serialize CommBuf
492 // (which consists of already serialized data).
493 switch (comm_type) {
494 case GHOST_RECV:
495 comm.recv(node, REQ_GHOST_SEND, recv_buffer.data(),
496 static_cast<int>(recv_buffer.size()));
497 comm.recv(node, REQ_GHOST_SEND, recv_buffer.bonds());
498 break;
499 case GHOST_SEND:
500 comm.send(node, REQ_GHOST_SEND, send_buffer.data(),
501 static_cast<int>(send_buffer.size()));
502 comm.send(node, REQ_GHOST_SEND, send_buffer.bonds());
503 break;
504 case GHOST_BCST:
505 if (node == comm.rank()) {
506 boost::mpi::broadcast(comm, send_buffer.data(),
507 static_cast<int>(send_buffer.size()), node);
508 boost::mpi::broadcast(comm, send_buffer.bonds(), node);
509 } else {
510 boost::mpi::broadcast(comm, recv_buffer.data(),
511 static_cast<int>(recv_buffer.size()), node);
512 boost::mpi::broadcast(comm, recv_buffer.bonds(), node);
513 }
514 break;
515 case GHOST_RDCE:
516 if (node == comm.rank())
517 boost::mpi::reduce(
518 comm, reinterpret_cast<double *>(send_buffer.data()),
519 static_cast<int>(send_buffer.size() / sizeof(double)),
520 reinterpret_cast<double *>(recv_buffer.data()), std::plus<double>{},
521 node);
522 else
523 boost::mpi::reduce(
524 comm, reinterpret_cast<double *>(send_buffer.data()),
525 static_cast<int>(send_buffer.size() / sizeof(double)),
526 std::plus<double>{}, node);
527 break;
528 }
529
530 // recv op; write back data directly, if no PSTSTORE delay is requested.
531 if (is_recv_op(comm_type, node, comm.rank())) {
532 if (!poststore) {
533 /* forces have to be added, the rest overwritten. Exception is RDCE,
534 * where the addition is integrated into the communication. */
535 if (data_parts == GHOSTTRANS_FORCE && comm_type != GHOST_RDCE)
536 add_forces_from_recv_buffer(recv_buffer, ghost_comm);
537#ifdef BOND_CONSTRAINT
538 else if (data_parts == GHOSTTRANS_RATTLE && comm_type != GHOST_RDCE)
539 add_rattle_correction_from_recv_buffer(recv_buffer, ghost_comm);
540#endif
541 else
542 put_recv_buffer(recv_buffer, ghost_comm, box_geo, data_parts);
543 }
544 } else if (poststore) {
545 /* send op; write back delayed data from last recv, when this was a
546 * prefetch send. */
547 /* find previous action where we recv and which has PSTSTORE set */
548 auto poststore_ghost_comm = std::find_if(
549 std::make_reverse_iterator(it), gcr.communications.rend(),
550 [this_node = comm.rank()](GhostCommunication const &ghost_comm) {
551 return is_poststorable(ghost_comm, this_node);
552 });
553
554 if (poststore_ghost_comm != gcr.communications.rend()) {
555 assert(recv_buffer.size() ==
556 calc_transmit_size(*poststore_ghost_comm, box_geo, data_parts));
557 /* as above */
558 if (data_parts == GHOSTTRANS_FORCE && comm_type != GHOST_RDCE)
559 add_forces_from_recv_buffer(recv_buffer, *poststore_ghost_comm);
560#ifdef BOND_CONSTRAINT
561 else if (data_parts == GHOSTTRANS_RATTLE && comm_type != GHOST_RDCE)
563 *poststore_ghost_comm);
564#endif
565 else
566 put_recv_buffer(recv_buffer, *poststore_ghost_comm, box_geo,
567 data_parts);
568 }
569 }
570 }
571}
float sum
__global__ float float * torque
__global__ float * force
__shared__ int pos[MAXDEPTH *THREADS5/WARPSIZE]
__shared__ int node[MAXDEPTH *THREADS5/WARPSIZE]
void fold_position(Utils::Vector3d &pos, Utils::Vector3i &image_box) const
Fold coordinates to primary simulation box in-place.
Class that stores marshalled data for ghost communications.
Definition ghosts.cpp:63
const auto & bonds() const
Definition ghosts.cpp:83
const char * data() const
Definition ghosts.cpp:68
char * data()
Returns a pointer to the non-bond storage.
Definition ghosts.cpp:67
std::size_t size() const
Returns the number of elements in the non-bond storage.
Definition ghosts.cpp:72
auto & bonds()
Returns a reference to the bond storage.
Definition ghosts.cpp:82
void resize(std::size_t new_size)
Resizes the underlying storage s.t.
Definition ghosts.cpp:78
Pseudo-archive to calculate the size of the serialization buffer.
Definition ghosts.cpp:91
void resize(std::size_t new_size)
Resize container.
Definition Bag.hpp:129
Archive that deserializes from a buffer via memcpy.
Archive that serializes to a buffer via memcpy.
int this_node
The number of this node.
static void serialize_and_reduce(Archive &ar, Particle &p, unsigned int data_parts, ReductionPolicy policy, SerializationDirection direction, BoxGeometry const &box_geo, Utils::Vector3d const *ghost_shift)
Serialize particle data, possibly with reduction.
Definition ghosts.cpp:124
static void add_rattle_correction_from_recv_buffer(CommBuf &recv_buffer, const GhostCommunication &ghost_comm)
Definition ghosts.cpp:348
static void prepare_recv_buffer(CommBuf &recv_buffer, GhostCommunication const &ghost_comm, BoxGeometry const &box_geo, unsigned int data_parts)
Definition ghosts.cpp:297
#define REQ_GHOST_SEND
Tag for ghosts communications.
Definition ghosts.cpp:57
static void put_recv_buffer(CommBuf &recv_buffer, GhostCommunication const &ghost_comm, BoxGeometry const &box_geo, unsigned int data_parts)
Definition ghosts.cpp:307
static void prepare_send_buffer(CommBuf &send_buffer, GhostCommunication const &ghost_comm, BoxGeometry const &box_geo, unsigned int data_parts)
Definition ghosts.cpp:249
ReductionPolicy
Type of reduction to carry out during serialization.
Definition ghosts.cpp:106
@ UPDATE
Reduction for cell-to-cell particle update.
@ MOVE
Reduction for domain-to-domain particle communication.
static bool is_recv_op(int comm_type, int node, int this_node)
Definition ghosts.cpp:418
static void add_forces_from_recv_buffer(CommBuf &recv_buffer, const GhostCommunication &ghost_comm)
Definition ghosts.cpp:362
static void cell_cell_transfer(GhostCommunication const &ghost_comm, BoxGeometry const &box_geo, unsigned int data_parts)
Definition ghosts.cpp:375
static bool is_send_op(int comm_type, int node, int this_node)
Definition ghosts.cpp:413
static void prepare_ghost_cell(ParticleList *cell, std::size_t size)
Definition ghosts.cpp:287
static auto calc_transmit_size(BoxGeometry const &box_geo, unsigned data_parts)
Definition ghosts.cpp:227
static bool is_prefetchable(GhostCommunication const &ghost_comm, int this_node)
Definition ghosts.cpp:424
void ghost_communicator(GhostCommunicator const &gcr, BoxGeometry const &box_geo, unsigned int data_parts)
Do a ghost communication with the specified data parts.
Definition ghosts.cpp:440
static bool is_poststorable(GhostCommunication const &ghost_comm, int this_node)
Definition ghosts.cpp:432
SerializationDirection
Whether to save the state to or load the state from the archive.
Definition ghosts.cpp:114
Ghost particles and particle exchange.
#define GHOST_RECV
recv from a single node
Definition ghosts.hpp:106
#define GHOST_PSTSTORE
additional flag for poststoring
Definition ghosts.hpp:119
#define GHOST_JOBMASK
mask to the job area of the transfer type
Definition ghosts.hpp:115
#define GHOST_RDCE
reduce, the node entry gives the receiver
Definition ghosts.hpp:110
#define GHOST_LOCL
transfer data from cell to cell on this node
Definition ghosts.hpp:112
#define GHOST_BCST
broadcast, the node entry gives the sender
Definition ghosts.hpp:108
@ GHOSTTRANS_MOMENTUM
transfer ParticleMomentum
Definition ghosts.hpp:130
@ GHOSTTRANS_RATTLE
transfer ParticleRattle
Definition ghosts.hpp:135
@ GHOSTTRANS_PARTNUM
resize the receiver particle arrays to the size of the senders
Definition ghosts.hpp:138
@ GHOSTTRANS_POSITION
transfer ParticlePosition
Definition ghosts.hpp:128
@ GHOSTTRANS_PROPRTS
transfer ParticleProperties
Definition ghosts.hpp:126
@ GHOSTTRANS_FORCE
transfer ParticleForce
Definition ghosts.hpp:132
@ GHOSTTRANS_NONE
Definition ghosts.hpp:124
@ GHOSTTRANS_BONDS
Definition ghosts.hpp:139
#define GHOST_SEND
send to a single node
Definition ghosts.hpp:104
#define GHOST_PREFETCH
additional flag for prefetching
Definition ghosts.hpp:117
DEVICE_QUALIFIER constexpr Span< T > make_span(T *p, std::size_t N)
Definition Span.hpp:112
Utils::Vector3d shift
Position shift for ghost particles.
Definition ghosts.hpp:153
int node
Node to communicate with (to use with all MPI operations).
Definition ghosts.hpp:146
std::vector< ParticleList * > part_lists
Pointer array to particle lists to communicate.
Definition ghosts.hpp:149
int type
Communication type.
Definition ghosts.hpp:144
Properties for a ghost communication.
Definition ghosts.hpp:157
boost::mpi::communicator mpi_comm
Attached mpi communicator.
Definition ghosts.hpp:163
std::vector< GhostCommunication > communications
List of ghost communications.
Definition ghosts.hpp:166
Force information on a particle.
Definition Particle.hpp:290
Struct holding all information for one particle.
Definition Particle.hpp:393
auto const & swimming() const
Definition Particle.hpp:559
auto const & propagation() const
Definition Particle.hpp:419
auto const & rinertia() const
Definition Particle.hpp:500
auto const & mass() const
Definition Particle.hpp:450
auto const & quat() const
Definition Particle.hpp:475
auto const & rotation() const
Definition Particle.hpp:456
auto const & vs_relative() const
Definition Particle.hpp:525
auto const & q() const
Definition Particle.hpp:506
auto const & gamma() const
Definition Particle.hpp:529
auto const & pos_last_time_step() const
Definition Particle.hpp:563
auto const & gamma_rot() const
Definition Particle.hpp:532
auto const & v() const
Definition Particle.hpp:431
auto const & torque() const
Definition Particle.hpp:477
auto const & fixed() const
Definition Particle.hpp:537
auto const & ext_force() const
Definition Particle.hpp:552
auto const & omega() const
Definition Particle.hpp:479
auto const & image_box() const
Definition Particle.hpp:442
auto const & type() const
Definition Particle.hpp:416
auto const & ext_torque() const
Definition Particle.hpp:482
auto const & dipm() const
Definition Particle.hpp:491
auto const & mol_id() const
Definition Particle.hpp:414
auto const & pos() const
Definition Particle.hpp:429
auto const & mu_E() const
Definition Particle.hpp:512
auto const & force() const
Definition Particle.hpp:433
auto const & id() const
Definition Particle.hpp:412
auto const & rattle_correction() const
Definition Particle.hpp:567