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