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-2026 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 <limits>
54#include <span>
55#include <vector>
56
57/** Tag for ghosts communications. */
58#define REQ_GHOST_SEND 100
59
60/**
61 * Class that stores marshalled data for ghost communications.
62 * To store and retrieve data, use the adapter classes below.
63 */
64class CommBuf {
65public:
66 /** Returns a pointer to the non-bond storage.
67 */
68 char *data() { return buf.data(); }
69 const char *data() const { return buf.data(); }
70
71 /** Returns the number of elements in the non-bond storage.
72 */
73 std::size_t size() const { return buf.size(); }
74
75 /** Resizes the underlying storage s.t. the object is capable
76 * of holding "new_size" chars.
77 * @param new_size new size
78 */
79 void resize(std::size_t new_size) { buf.resize(new_size); }
80
81 /** Returns a reference to the bond storage.
82 */
83 auto &bonds() { return bondbuf; }
84 const auto &bonds() const { return bondbuf; }
85
86 auto make_span() { return std::span(buf.data(), buf.size()); }
87
88private:
89 std::vector<char> buf; ///< Buffer for everything but bonds
90 std::vector<char> bondbuf; ///< Buffer for bond lists
91};
92
93/** @brief Pseudo-archive to calculate the size of the serialization buffer. */
95 std::size_t m_size = 0;
96
97public:
98 auto size() const { return m_size; }
99
100 template <class T> auto &operator<<(T &) {
101 m_size += sizeof(T);
102 return *this;
103 }
104
105 template <class T> auto &operator&(T &t) { return *this << t; }
106};
107
108/** @brief Type of reduction to carry out during serialization. */
109enum class ReductionPolicy {
110 /** @brief Reduction for domain-to-domain particle communication. */
111 MOVE,
112 /** @brief Reduction for cell-to-cell particle update. */
113 UPDATE,
114};
115
116/** @brief Whether to save the state to or load the state from the archive. */
118
119/**
120 * @brief Serialize particle data, possibly with reduction.
121 * The reduction can take place during the save stage, e.g. to apply
122 * a ghost shift to the particle position, or during the load stage,
123 * e.g. to transfer momentum between particles in two local cells.
124 */
125template <class Archive>
126static void
128 ReductionPolicy policy, SerializationDirection direction,
129 BoxGeometry const &box_geo,
132 ar & p.id() & p.mol_id() & p.type() & p.propagation();
133#ifdef ESPRESSO_ROTATION
134 ar & p.rotation();
135#ifdef ESPRESSO_ROTATIONAL_INERTIA
136 ar & p.rinertia();
137#endif
138#endif
139#ifdef ESPRESSO_MASS
140 ar & p.mass();
141#endif
142#ifdef ESPRESSO_ELECTROSTATICS
143 ar & p.q();
144#endif
145#ifdef ESPRESSO_DIPOLES
146 ar & p.dipm();
147#endif
148#ifdef ESPRESSO_LB_ELECTROHYDRODYNAMICS
149 ar & p.mu_E();
150#endif
151#ifdef ESPRESSO_VIRTUAL_SITES_RELATIVE
152 ar & p.vs_relative();
153#endif
154#ifdef ESPRESSO_THERMOSTAT_PER_PARTICLE
155 ar & p.gamma();
156#ifdef ESPRESSO_ROTATION
157 ar & p.gamma_rot();
158#endif
159#endif
160#ifdef ESPRESSO_EXTERNAL_FORCES
161 ar & p.fixed();
162 ar & p.ext_force();
163#ifdef ESPRESSO_ROTATION
164 ar & p.ext_torque();
165#endif
166#endif
167#ifdef ESPRESSO_ENGINE
168 ar & p.swimming();
169#endif
170 }
172 if (direction == SerializationDirection::SAVE and ghost_shift != nullptr) {
173 /* ok, this is not nice, but perhaps fast */
174 auto pos = p.pos() + *ghost_shift;
175 auto img = p.image_box();
176 box_geo.fold_position(pos, img);
177 ar & pos;
178 ar & img;
179 } else {
180 ar & p.pos();
181 ar & p.image_box();
182 }
183#ifdef ESPRESSO_ROTATION
184 ar & p.quat();
185#endif
186#ifdef ESPRESSO_BOND_CONSTRAINT
188#endif
189 }
191 ar & p.v();
192#ifdef ESPRESSO_ROTATION
193 ar & p.omega();
194#endif
195 }
197 if (policy == ReductionPolicy::UPDATE and
198 direction == SerializationDirection::LOAD) {
199 Utils::Vector3d force;
200 ar & force;
201 p.force() += force;
202 } else {
203 ar & p.force();
204 }
205#ifdef ESPRESSO_ROTATION
206 if (policy == ReductionPolicy::UPDATE and
207 direction == SerializationDirection::LOAD) {
208 Utils::Vector3d torque;
209 ar & torque;
210 p.torque() += torque;
211 } else {
212 ar & p.torque();
213 }
214#endif
215 }
216#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
218 if (policy == ReductionPolicy::UPDATE and
219 direction == SerializationDirection::LOAD) {
220 Utils::Vector3d dip_fld;
221 ar & dip_fld;
222 p.dip_fld() += dip_fld;
223 } else {
224 ar & p.dip_fld();
225 }
226 }
227#endif
228#ifdef ESPRESSO_BOND_CONSTRAINT
230 if (policy == ReductionPolicy::UPDATE and
231 direction == SerializationDirection::LOAD) {
232 Utils::Vector3d correction;
233 ar & correction;
234 p.rattle_correction() += correction;
235 } else {
236 ar & p.rattle_correction();
237 }
238 }
239#endif
240}
241
250
252 BoxGeometry const &box_geo,
253 unsigned int data_parts) {
255 return sizeof(unsigned int) * ghost_comm.part_lists.size();
256
257 auto const n_part = boost::accumulate(
258 ghost_comm.part_lists, std::size_t{0},
259 [](std::size_t sum, auto part_list) { return sum + part_list->size(); });
260
261 return n_part * calc_transmit_size(box_geo, data_parts);
262}
263
266 BoxGeometry const &box_geo,
267 unsigned int data_parts) {
268
269 /* reallocate send buffer */
271 send_buffer.bonds().clear();
272
273 auto archiver = Utils::MemcpyOArchive{send_buffer.make_span()};
274
275 /* Construct archive that pushes back to the bond buffer */
276 namespace io = boost::iostreams;
277 io::stream<io::back_insert_device<std::vector<char>>> os{
278 io::back_inserter(send_buffer.bonds())};
279 boost::archive::binary_oarchive bond_archiver{os};
280
281 /* put in data */
282 for (auto part_list : ghost_comm.part_lists) {
284 assert(part_list->size() <= std::numeric_limits<unsigned int>::max());
285 auto np = static_cast<unsigned int>(part_list->size());
286 archiver << np;
287 } else {
288 for (auto &p : *part_list) {
291 &ghost_comm.shift);
293 bond_archiver << p.bonds();
294 }
295 }
296 }
297 }
298
299 assert(archiver.bytes_written() == send_buffer.size());
300}
301
302static void prepare_ghost_cell(ParticleList *cell, std::size_t size) {
303 /* Adapt size */
304 cell->resize(size);
305
306 /* Mark particles as ghosts */
307 for (auto &p : *cell) {
308 p.set_ghost(true);
309 }
310}
311
314 BoxGeometry const &box_geo,
315 unsigned int data_parts) {
316 /* reallocate recv buffer */
318 /* clear bond buffer */
319 recv_buffer.bonds().clear();
320}
321
324 BoxGeometry const &box_geo,
325 unsigned int data_parts) {
326 /* put back data */
327 auto archiver = Utils::MemcpyIArchive{recv_buffer.make_span()};
328
330 for (auto part_list : ghost_comm.part_lists) {
331 unsigned int np;
332 archiver >> np;
334 }
335 } else {
336 for (auto part_list : ghost_comm.part_lists) {
337 for (auto &p : *part_list) {
339 SerializationDirection::LOAD, box_geo, nullptr);
340 }
341 }
343 namespace io = boost::iostreams;
344 io::stream<io::array_source> bond_stream(io::array_source{
345 recv_buffer.bonds().data(), recv_buffer.bonds().size()});
346 boost::archive::binary_iarchive bond_archiver(bond_stream);
347
348 for (auto part_list : ghost_comm.part_lists) {
349 for (auto &p : *part_list) {
350 bond_archiver >> p.bonds();
351 }
352 }
353 }
354 }
355
356 assert(archiver.bytes_read() == recv_buffer.size());
357
358 recv_buffer.bonds().clear();
359}
360
361#ifdef ESPRESSO_BOND_CONSTRAINT
362static void
365 /* put back data */
366 auto archiver = Utils::MemcpyIArchive{recv_buffer.make_span()};
367 for (auto &part_list : ghost_comm.part_lists) {
368 for (Particle &part : *part_list) {
370 archiver >> pr;
371 part.rattle_params() += pr;
372 }
373 }
374}
375#endif
376
379 /* put back data */
380 auto archiver = Utils::MemcpyIArchive{recv_buffer.make_span()};
381 for (auto &part_list : ghost_comm.part_lists) {
382 for (Particle &part : *part_list) {
384 archiver >> pf;
385 part.force_and_torque() += pf;
386 }
387 }
388}
389
390#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
393 auto archiver = Utils::MemcpyIArchive{recv_buffer.make_span()};
394 for (auto &part_list : ghost_comm.part_lists) {
395 for (Particle &part : *part_list) {
396 Utils::Vector3d dip_fld;
397 archiver >> dip_fld;
398 part.dip_fld() += dip_fld;
399 }
400 }
401}
402#endif
403
405 BoxGeometry const &box_geo,
406 unsigned int data_parts) {
407 CommBuf buffer;
409 buffer.resize(calc_transmit_size(box_geo, data_parts));
410 }
411 /* transfer data */
412 auto const offset = ghost_comm.part_lists.size() / 2;
413 for (std::size_t pl = 0; pl < offset; pl++) {
414 auto *src_list = ghost_comm.part_lists[pl];
415 auto *dst_list = ghost_comm.part_lists[pl + offset];
416
419 } else {
420 auto &src_part = *src_list;
421 auto &dst_part = *dst_list;
422 assert(src_part.size() == dst_part.size());
423
424 for (std::size_t i = 0; i < src_part.size(); i++) {
425 auto ar_out = Utils::MemcpyOArchive{buffer.make_span()};
426 auto ar_in = Utils::MemcpyIArchive{buffer.make_span()};
427 auto &p1 = src_part.begin()[i];
428 auto &p2 = dst_part.begin()[i];
431 &ghost_comm.shift);
433 SerializationDirection::LOAD, box_geo, nullptr);
435 p2.bonds() = p1.bonds();
436 }
437 }
438 }
439 }
440}
441
442static bool is_send_op(int comm_type, int node, int this_node) {
443 return ((comm_type == GHOST_SEND) || (comm_type == GHOST_RDCE) ||
444 (comm_type == GHOST_BCST && node == this_node));
445}
446
447static bool is_recv_op(int comm_type, int node, int this_node) {
448 return ((comm_type == GHOST_RECV) ||
449 (comm_type == GHOST_BCST && node != this_node) ||
450 (comm_type == GHOST_RDCE && node == this_node));
451}
452
454 int this_node) {
455 int const comm_type = ghost_comm.type & GHOST_JOBMASK;
456 int const prefetch = ghost_comm.type & GHOST_PREFETCH;
457 int const node = ghost_comm.node;
458 return is_send_op(comm_type, node, this_node) && prefetch;
459}
460
462 int this_node) {
463 int const comm_type = ghost_comm.type & GHOST_JOBMASK;
464 int const poststore = ghost_comm.type & GHOST_PSTSTORE;
465 int const node = ghost_comm.node;
466 return is_recv_op(comm_type, node, this_node) && poststore;
467}
468
470 BoxGeometry const &box_geo, unsigned int data_parts) {
472 return;
473
475
476 auto const &comm = gcr.mpi_comm;
477
478 for (auto cit = gcr.communications.cbegin(); cit != gcr.communications.cend();
479 ++cit) {
480 auto const &ghost_comm = *cit;
481 int const comm_type = ghost_comm.type & GHOST_JOBMASK;
482
483 if (comm_type == GHOST_LOCL) {
485 continue;
486 }
487
488 int const prefetch = ghost_comm.type & GHOST_PREFETCH;
489 int const poststore = ghost_comm.type & GHOST_PSTSTORE;
490 int const node = ghost_comm.node;
491
492 /* prepare send buffer if necessary */
493 if (is_send_op(comm_type, node, comm.rank())) {
494 /* ok, we send this step, prepare send buffer if not yet done */
495 if (!prefetch) {
497 }
498 // Check prefetched send buffers (must also hold for buffers allocated
499 // in the previous lines.)
500 assert(send_buffer.size() ==
502 } else if (prefetch) {
503 /* we do not send this time, let's look for a prefetch */
505 std::find_if(std::next(cit), gcr.communications.cend(),
506 [this_node = comm.rank()](auto const &other_ghost_comm) {
507 return is_prefetchable(other_ghost_comm, this_node);
508 });
509
510 if (prefetch_ghost_comm != gcr.communications.end())
512 data_parts);
513 }
514
515 /* recv buffer for recv and multinode operations to this node */
516 if (is_recv_op(comm_type, node, comm.rank()))
518
519 /* transfer data */
520 // Use two send/recvs in order to avoid having to serialize CommBuf
521 // (which consists of already serialized data).
522 switch (comm_type) {
523 case GHOST_RECV:
524 comm.recv(node, REQ_GHOST_SEND, recv_buffer.data(),
525 static_cast<int>(recv_buffer.size()));
526 comm.recv(node, REQ_GHOST_SEND, recv_buffer.bonds());
527 break;
528 case GHOST_SEND:
529 comm.send(node, REQ_GHOST_SEND, send_buffer.data(),
530 static_cast<int>(send_buffer.size()));
531 comm.send(node, REQ_GHOST_SEND, send_buffer.bonds());
532 break;
533 case GHOST_BCST:
534 if (node == comm.rank()) {
535 boost::mpi::broadcast(comm, send_buffer.data(),
536 static_cast<int>(send_buffer.size()), node);
537 boost::mpi::broadcast(comm, send_buffer.bonds(), node);
538 } else {
539 boost::mpi::broadcast(comm, recv_buffer.data(),
540 static_cast<int>(recv_buffer.size()), node);
541 boost::mpi::broadcast(comm, recv_buffer.bonds(), node);
542 }
543 break;
544 case GHOST_RDCE:
545 if (node == comm.rank())
546 boost::mpi::reduce(
547 comm, reinterpret_cast<double *>(send_buffer.data()),
548 static_cast<int>(send_buffer.size() / sizeof(double)),
549 reinterpret_cast<double *>(recv_buffer.data()), std::plus<double>{},
550 node);
551 else
552 boost::mpi::reduce(
553 comm, reinterpret_cast<double *>(send_buffer.data()),
554 static_cast<int>(send_buffer.size() / sizeof(double)),
555 std::plus<double>{}, node);
556 break;
557 }
558
559 // recv op; write back data directly, if no PSTSTORE delay is requested.
560 if (is_recv_op(comm_type, node, comm.rank())) {
561 if (!poststore) {
562 /* forces have to be added, the rest overwritten. Exception is RDCE,
563 * where the addition is integrated into the communication. */
566#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
569#endif
570#ifdef ESPRESSO_BOND_CONSTRAINT
573#endif
574 else
576 }
577 } else if (poststore) {
578 /* send op; write back delayed data from last recv, when this was a
579 * prefetch send. */
580 /* find previous action where we recv and which has PSTSTORE set */
581 auto poststore_ghost_comm = std::find_if(
582 std::make_reverse_iterator(cit), gcr.communications.crend(),
583 [this_node = comm.rank()](auto const &other_ghost_comm) {
584 return is_poststorable(other_ghost_comm, this_node);
585 });
586
587 if (poststore_ghost_comm != gcr.communications.rend()) {
588 assert(recv_buffer.size() ==
590 /* as above */
593#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
596#endif
597#ifdef ESPRESSO_BOND_CONSTRAINT
601#endif
602 else
604 data_parts);
605 }
606 }
607 }
608}
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:64
const auto & bonds() const
Definition ghosts.cpp:84
const char * data() const
Definition ghosts.cpp:69
char * data()
Returns a pointer to the non-bond storage.
Definition ghosts.cpp:68
auto make_span()
Definition ghosts.cpp:86
std::size_t size() const
Returns the number of elements in the non-bond storage.
Definition ghosts.cpp:73
auto & bonds()
Returns a reference to the bond storage.
Definition ghosts.cpp:83
void resize(std::size_t new_size)
Resizes the underlying storage s.t.
Definition ghosts.cpp:79
Pseudo-archive to calculate the size of the serialization buffer.
Definition ghosts.cpp:94
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.
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
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:127
static void add_rattle_correction_from_recv_buffer(CommBuf &recv_buffer, const GhostCommunication &ghost_comm)
Definition ghosts.cpp:363
static void prepare_recv_buffer(CommBuf &recv_buffer, GhostCommunication const &ghost_comm, BoxGeometry const &box_geo, unsigned int data_parts)
Definition ghosts.cpp:312
#define REQ_GHOST_SEND
Tag for ghosts communications.
Definition ghosts.cpp:58
static void put_recv_buffer(CommBuf &recv_buffer, GhostCommunication const &ghost_comm, BoxGeometry const &box_geo, unsigned int data_parts)
Definition ghosts.cpp:322
static void prepare_send_buffer(CommBuf &send_buffer, GhostCommunication const &ghost_comm, BoxGeometry const &box_geo, unsigned int data_parts)
Definition ghosts.cpp:264
ReductionPolicy
Type of reduction to carry out during serialization.
Definition ghosts.cpp:109
@ 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:447
static void add_forces_from_recv_buffer(CommBuf &recv_buffer, const GhostCommunication &ghost_comm)
Definition ghosts.cpp:377
static void cell_cell_transfer(GhostCommunication const &ghost_comm, BoxGeometry const &box_geo, unsigned int data_parts)
Definition ghosts.cpp:404
static bool is_send_op(int comm_type, int node, int this_node)
Definition ghosts.cpp:442
static void prepare_ghost_cell(ParticleList *cell, std::size_t size)
Definition ghosts.cpp:302
static auto calc_transmit_size(BoxGeometry const &box_geo, unsigned data_parts)
Definition ghosts.cpp:242
static bool is_prefetchable(GhostCommunication const &ghost_comm, int this_node)
Definition ghosts.cpp:453
static void add_dip_fld_from_recv_buffer(CommBuf &recv_buffer, GhostCommunication const &ghost_comm)
Definition ghosts.cpp:391
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:469
static bool is_poststorable(GhostCommunication const &ghost_comm, int this_node)
Definition ghosts.cpp:461
SerializationDirection
Whether to save the state to or load the state from the archive.
Definition ghosts.cpp:117
Ghost particles and particle exchange.
#define GHOST_RECV
recv from a single node
Definition ghosts.hpp:108
#define GHOST_PSTSTORE
additional flag for poststoring
Definition ghosts.hpp:121
#define GHOST_JOBMASK
mask to the job area of the transfer type
Definition ghosts.hpp:117
#define GHOST_RDCE
reduce, the node entry gives the receiver
Definition ghosts.hpp:112
#define GHOST_LOCL
transfer data from cell to cell on this node
Definition ghosts.hpp:114
#define GHOST_BCST
broadcast, the node entry gives the sender
Definition ghosts.hpp:110
@ GHOSTTRANS_MOMENTUM
transfer ParticleMomentum
Definition ghosts.hpp:132
@ GHOSTTRANS_RATTLE
transfer ParticleRattle
Definition ghosts.hpp:137
@ GHOSTTRANS_DIPFLD
transfer dipole field tracking data
Definition ghosts.hpp:145
@ GHOSTTRANS_PARTNUM
resize the receiver particle arrays to the size of the senders
Definition ghosts.hpp:140
@ GHOSTTRANS_POSITION
transfer ParticlePosition
Definition ghosts.hpp:130
@ GHOSTTRANS_PROPRTS
transfer ParticleProperties
Definition ghosts.hpp:128
@ GHOSTTRANS_FORCE
transfer ParticleForce
Definition ghosts.hpp:134
@ GHOSTTRANS_NONE
Definition ghosts.hpp:126
@ GHOSTTRANS_BONDS
transfer bonds data
Definition ghosts.hpp:142
#define GHOST_SEND
send to a single node
Definition ghosts.hpp:106
#define GHOST_PREFETCH
additional flag for prefetching
Definition ghosts.hpp:119
Properties for a ghost communication.
Definition ghosts.hpp:164
Force information on a particle.
Definition Particle.hpp:331
Struct holding all information for one particle.
Definition Particle.hpp:436
constexpr auto const & dip_fld() const
Definition Particle.hpp:590
constexpr auto const & quat() const
Definition Particle.hpp:527
constexpr auto const & pos() const
Definition Particle.hpp:476
constexpr auto const & swimming() const
Definition Particle.hpp:653
constexpr auto const & rattle_correction() const
Definition Particle.hpp:661
constexpr auto const & rinertia() const
Definition Particle.hpp:593
constexpr auto const & mass() const
Definition Particle.hpp:500
constexpr auto const & dipm() const
Definition Particle.hpp:543
constexpr auto const & type() const
Definition Particle.hpp:459
constexpr auto const & omega() const
Definition Particle.hpp:531
constexpr auto const & ext_force() const
Definition Particle.hpp:646
constexpr auto const & propagation() const
Definition Particle.hpp:462
constexpr auto const & ext_torque() const
Definition Particle.hpp:534
constexpr auto const & rotation() const
Definition Particle.hpp:505
constexpr auto const & force() const
Definition Particle.hpp:480
constexpr auto const & vs_relative() const
Definition Particle.hpp:617
constexpr auto const & fixed() const
Definition Particle.hpp:629
constexpr auto const & gamma() const
Definition Particle.hpp:621
constexpr auto const & gamma_rot() const
Definition Particle.hpp:624
constexpr auto const & image_box() const
Definition Particle.hpp:489
constexpr auto const & mu_E() const
Definition Particle.hpp:602
constexpr auto const & id() const
Definition Particle.hpp:455
constexpr auto const & mol_id() const
Definition Particle.hpp:457
constexpr auto const & q() const
Definition Particle.hpp:597
constexpr auto const & pos_last_time_step() const
Definition Particle.hpp:657
constexpr auto const & v() const
Definition Particle.hpp:478
constexpr auto const & torque() const
Definition Particle.hpp:529