35#include "system/System.hpp"
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>
57#define REQ_GHOST_SEND 100
67 char *
data() {
return buf.data(); }
68 const char *
data()
const {
return buf.data(); }
72 std::size_t
size()
const {
return buf.size(); }
78 void resize(std::size_t new_size) { buf.resize(new_size); }
82 auto &
bonds() {
return bondbuf; }
83 const auto &
bonds()
const {
return bondbuf; }
86 std::vector<char> buf;
87 std::vector<char> bondbuf;
92 std::size_t m_size = 0;
95 auto size()
const {
return m_size; }
102 template <
class T>
auto &
operator&(T &t) {
return *
this << t; }
122template <
class Archive>
132#ifdef ROTATIONAL_INERTIA
145#ifdef LB_ELECTROHYDRODYNAMICS
148#ifdef VIRTUAL_SITES_RELATIVE
151#ifdef THERMOSTAT_PER_PARTICLE
157#ifdef EXTERNAL_FORCES
171 auto pos = p.
pos() + *ghost_shift;
183#ifdef BOND_CONSTRAINT
213#ifdef BOND_CONSTRAINT
228 unsigned data_parts) {
233 return sizeof_archive.
size();
238 unsigned int data_parts) {
240 return sizeof(
unsigned int) * ghost_comm.
part_lists.size();
242 auto const n_part = boost::accumulate(
244 [](std::size_t
sum,
auto part_list) { return sum + part_list->size(); });
252 unsigned int data_parts) {
256 send_buffer.
bonds().clear();
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};
267 for (
auto part_list : ghost_comm.
part_lists) {
269 assert(part_list->size() <= std::numeric_limits<unsigned int>::max());
270 auto np =
static_cast<unsigned int>(part_list->size());
273 for (
auto &p : *part_list) {
278 bond_archiver << p.bonds();
284 assert(archiver.bytes_written() == send_buffer.
size());
292 for (
auto &p : *cell) {
300 unsigned int data_parts) {
304 recv_buffer.
bonds().clear();
310 unsigned int data_parts) {
315 for (
auto part_list : ghost_comm.
part_lists) {
321 for (
auto part_list : ghost_comm.
part_lists) {
322 for (
auto &p : *part_list) {
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);
333 for (
auto part_list : ghost_comm.
part_lists) {
334 for (
auto &p : *part_list) {
335 bond_archiver >> p.bonds();
341 assert(archiver.bytes_read() == recv_buffer.
size());
343 recv_buffer.
bonds().clear();
346#ifdef BOND_CONSTRAINT
352 for (
auto &part_list : ghost_comm.
part_lists) {
356 part.rattle_params() += pr;
366 for (
auto &part_list : ghost_comm.
part_lists) {
370 part.force_and_torque() += pf;
377 unsigned int data_parts) {
383 auto const offset = ghost_comm.
part_lists.size() / 2;
384 for (std::size_t pl = 0; pl < offset; pl++) {
386 auto *dst_list = ghost_comm.
part_lists[pl + offset];
391 auto &src_part = *src_list;
392 auto &dst_part = *dst_list;
393 assert(src_part.size() == dst_part.size());
395 for (std::size_t i = 0; i < src_part.size(); i++) {
398 auto &p1 = src_part.begin()[i];
399 auto &p2 = dst_part.begin()[i];
406 p2.bonds() = p1.bonds();
441 BoxGeometry const &box_geo,
unsigned int data_parts) {
445 static CommBuf send_buffer, recv_buffer;
471 assert(send_buffer.
size() ==
473 }
else if (prefetch) {
475 auto prefetch_ghost_comm = std::find_if(
478 return is_prefetchable(ghost_comm, this_node);
496 static_cast<int>(recv_buffer.
size()));
501 static_cast<int>(send_buffer.
size()));
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);
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);
516 if (
node == comm.rank())
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>{},
524 comm,
reinterpret_cast<double *
>(send_buffer.
data()),
525 static_cast<int>(send_buffer.
size() /
sizeof(
double)),
526 std::plus<double>{},
node);
537#ifdef BOND_CONSTRAINT
544 }
else if (poststore) {
548 auto poststore_ghost_comm = std::find_if(
551 return is_poststorable(ghost_comm, this_node);
555 assert(recv_buffer.
size() ==
560#ifdef BOND_CONSTRAINT
563 *poststore_ghost_comm);
__global__ float float * torque
__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.
const auto & bonds() const
const char * data() const
char * data()
Returns a pointer to the non-bond storage.
std::size_t size() const
Returns the number of elements in the non-bond storage.
auto & bonds()
Returns a reference to the bond storage.
void resize(std::size_t new_size)
Resizes the underlying storage s.t.
Pseudo-archive to calculate the size of the serialization buffer.
void resize(std::size_t new_size)
Resize container.
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.
static void add_rattle_correction_from_recv_buffer(CommBuf &recv_buffer, const GhostCommunication &ghost_comm)
static void prepare_recv_buffer(CommBuf &recv_buffer, GhostCommunication const &ghost_comm, BoxGeometry const &box_geo, unsigned int data_parts)
#define REQ_GHOST_SEND
Tag for ghosts communications.
static void put_recv_buffer(CommBuf &recv_buffer, GhostCommunication const &ghost_comm, BoxGeometry const &box_geo, unsigned int data_parts)
static void prepare_send_buffer(CommBuf &send_buffer, GhostCommunication const &ghost_comm, BoxGeometry const &box_geo, unsigned int data_parts)
ReductionPolicy
Type of reduction to carry out during serialization.
@ 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)
static void add_forces_from_recv_buffer(CommBuf &recv_buffer, const GhostCommunication &ghost_comm)
static void cell_cell_transfer(GhostCommunication const &ghost_comm, BoxGeometry const &box_geo, unsigned int data_parts)
static bool is_send_op(int comm_type, int node, int this_node)
static void prepare_ghost_cell(ParticleList *cell, std::size_t size)
static auto calc_transmit_size(BoxGeometry const &box_geo, unsigned data_parts)
static bool is_prefetchable(GhostCommunication const &ghost_comm, int this_node)
void ghost_communicator(GhostCommunicator const &gcr, BoxGeometry const &box_geo, unsigned int data_parts)
Do a ghost communication with the specified data parts.
static bool is_poststorable(GhostCommunication const &ghost_comm, int this_node)
SerializationDirection
Whether to save the state to or load the state from the archive.
Ghost particles and particle exchange.
#define GHOST_RECV
recv from a single node
#define GHOST_PSTSTORE
additional flag for poststoring
#define GHOST_JOBMASK
mask to the job area of the transfer type
#define GHOST_RDCE
reduce, the node entry gives the receiver
#define GHOST_LOCL
transfer data from cell to cell on this node
#define GHOST_BCST
broadcast, the node entry gives the sender
@ GHOSTTRANS_MOMENTUM
transfer ParticleMomentum
@ GHOSTTRANS_RATTLE
transfer ParticleRattle
@ GHOSTTRANS_PARTNUM
resize the receiver particle arrays to the size of the senders
@ GHOSTTRANS_POSITION
transfer ParticlePosition
@ GHOSTTRANS_PROPRTS
transfer ParticleProperties
@ GHOSTTRANS_FORCE
transfer ParticleForce
#define GHOST_SEND
send to a single node
#define GHOST_PREFETCH
additional flag for prefetching
DEVICE_QUALIFIER constexpr Span< T > make_span(T *p, std::size_t N)
Utils::Vector3d shift
Position shift for ghost particles.
int node
Node to communicate with (to use with all MPI operations).
std::vector< ParticleList * > part_lists
Pointer array to particle lists to communicate.
int type
Communication type.
Properties for a ghost communication.
boost::mpi::communicator mpi_comm
Attached mpi communicator.
std::vector< GhostCommunication > communications
List of ghost communications.
Force information on a particle.
Struct holding all information for one particle.
auto const & swimming() const
auto const & propagation() const
auto const & rinertia() const
auto const & mass() const
auto const & quat() const
auto const & rotation() const
auto const & vs_relative() const
auto const & gamma() const
auto const & pos_last_time_step() const
auto const & gamma_rot() const
auto const & torque() const
auto const & fixed() const
auto const & ext_force() const
auto const & omega() const
auto const & image_box() const
auto const & type() const
auto const & ext_torque() const
auto const & dipm() const
auto const & mol_id() const
auto const & mu_E() const
auto const & force() const
auto const & rattle_correction() const