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
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