39#ifdef ESPRESSO_VIRTUAL_SITES_CENTER_OF_MASS
47#include "communication.hpp"
52#include <boost/archive/text_iarchive.hpp>
53#include <boost/archive/text_oarchive.hpp>
54#include <boost/mpi/collectives/all_gather.hpp>
55#include <boost/mpi/collectives/all_reduce.hpp>
56#include <boost/mpi/collectives/broadcast.hpp>
57#include <boost/serialization/unordered_set.hpp>
58#include <boost/serialization/utility.hpp>
59#include <boost/serialization/vector.hpp>
66#include <unordered_map>
67#include <unordered_set>
83 template <
class Archive>
84 void serialize(Archive &ar,
unsigned int const version) {
99 auto constexpr parallel_execution_policy =
false;
100 std::vector<int> pids;
104 pids.emplace_back(p.id());
107 parallel_execution_policy);
109 std::optional<int> result = std::nullopt;
110 if (not pids.empty()) {
111 assert(pids.size() == 1ul);
112 result = pids.front();
123template <
typename K,
typename V>
125 std::vector<std::pair<K, V>> flat_map{map_data.begin(), map_data.end()};
127 boost::mpi::broadcast(
comm_cart, flat_map, 0);
128 map_data = {flat_map.begin(), flat_map.end()};
134 auto constexpr parallel_execution_policy =
false;
140 std::unordered_map<ParticleId, MoleculeId> virtual_site_id_for_mol_id;
143 std::unordered_map<MoleculeId, ComInfo> m_com_by_mol_id;
148 assert(not virtual_site_id_for_mol_id.contains(p.
mol_id()));
149 virtual_site_id_for_mol_id[p.
mol_id()] = p.
id();
151 if (not m_com_by_mol_id.contains(p.
mol_id())) {
154 auto const pos_unfolded =
156 m_com_by_mol_id[p.
mol_id()].total_mass += p.
mass();
157 m_com_by_mol_id[p.
mol_id()].weighted_position +=
158 p.
mass() * pos_unfolded;
161 parallel_execution_policy);
165 std::unordered_set<MoleculeId> local_mol_ids;
166 for (
auto const &mol_id : m_com_by_mol_id | std::views::keys) {
167 local_mol_ids.insert(mol_id);
171 std::vector<std::unordered_set<MoleculeId>> global_mol_ids{};
172 boost::mpi::all_gather(
comm_cart, local_mol_ids, global_mol_ids);
173 std::unordered_set<MoleculeId> unique_mol_ids{};
174 for (
auto const &mol_id_set : global_mol_ids) {
175 for (
auto const &mol_id : mol_id_set) {
176 unique_mol_ids.insert(mol_id);
179 std::vector<MoleculeId> flattened_mol_ids{unique_mol_ids.begin(),
180 unique_mol_ids.end()};
181 std::ranges::sort(flattened_mol_ids);
184 for (
auto const mol_id : flattened_mol_ids) {
185 double local_total_mass = 0.;
188 if (m_com_by_mol_id.contains(mol_id)) {
189 local_total_mass = m_com_by_mol_id[mol_id].total_mass;
190 local_weighted_position = m_com_by_mol_id[mol_id].weighted_position;
193 auto const total_mass =
194 boost::mpi::all_reduce(
comm_cart, local_total_mass, std::plus{});
195 auto const weighted_position =
196 boost::mpi::all_reduce(
comm_cart, local_weighted_position, std::plus{});
198 if (m_com_by_mol_id.contains(mol_id)) {
199 m_com_by_mol_id[mol_id].total_mass = total_mass;
200 m_com_by_mol_id[mol_id].weighted_position = weighted_position;
212 for (
auto const &[mol_id, com_info] : m_com_by_mol_id) {
213 if (not virtual_site_id_for_mol_id.contains(mol_id)) {
216 auto const vs_id = virtual_site_id_for_mol_id[mol_id];
218 auto folded_pos = com_info.weighted_position / com_info.total_mass;
223 vs_ptr->image_box() = image_box;
224 vs_ptr->mass() = com_info.total_mass;
225 vs_ptr->pos() = folded_pos;
234 auto constexpr parallel_execution_policy =
false;
240 std::unordered_map<ParticleId, Utils::Vector3d> force_for_vs_id;
242 std::unordered_map<ParticleId, double> mass_for_vs_id;
246 std::unordered_map<MoleculeId, ParticleId> virtual_site_id_for_mol_id;
250 assert(not virtual_site_id_for_mol_id.contains(p.
mol_id()));
251 virtual_site_id_for_mol_id[p.
mol_id()] = p.
id();
252 force_for_vs_id[p.
id()] = p.
force();
253 mass_for_vs_id[p.
id()] = p.
mass();
256 parallel_execution_policy);
271 not virtual_site_id_for_mol_id.contains(p.
mol_id())) {
274 auto const vs_id = virtual_site_id_for_mol_id.at(p.
mol_id());
276 (p.
mass() / mass_for_vs_id.at(vs_id)) * force_for_vs_id.at(vs_id);
278 parallel_execution_policy);
Vector implementation and trait types for boost qvm interoperability.
This file contains everything related to the global cell structure / cell system.
auto unfolded_position(Utils::Vector3d const &pos, Utils::Vector3i const &image_box) const noexcept
Unfold particle coordinates to image box.
void fold_position(Utils::Vector3d &pos, Utils::Vector3i &image_box) const
Fold coordinates to primary simulation box in-place.
Describes a cell structure / cell system.
Particle * get_local_particle(int id)
Get a local particle by id.
void for_each_local_particle(ParticleCallback auto &&f, bool parallel=true) const
Run a kernel on all local particles.
void ghosts_update(unsigned data_parts)
Update ghost particles.
void ghosts_reset_forces()
Set forces and torques on all ghosts to zero.
void ghosts_reduce_forces()
Add forces and torques from ghost particles to real particles.
static bool is_vs_com(Particle const &p)
void vs_com_back_transfer_forces_and_torques(CellStructure &cell_structure)
std::optional< int > get_pid_for_vs_com(CellStructure &cell_structure, int mol_id)
decltype(ParticleProperties::mol_id) MoleculeId
void gather_buffer_map(std::unordered_map< K, V > &map_data)
Synchronize a map across all MPI ranks.
void vs_com_update_particles(CellStructure &cell_structure, BoxGeometry const &box_geo)
decltype(ParticleProperties::identity) ParticleId
boost::mpi::communicator comm_cart
The communicator.
@ DATA_PART_POSITION
Particle::r.
@ TRANS_VS_CENTER_OF_MASS
void gather_buffer(std::vector< T, Allocator > &buffer, boost::mpi::communicator const &comm, int root=0)
Gather buffer with different size on each node.
Center of mass information for a molecule.
void serialize(Archive &ar, unsigned int const version)
double total_mass
Sum of the masses of all constituent particles.
friend class boost::serialization::access
Utils::Vector3d weighted_position
Sum of (mass * position) for all constituent particles.
int identity
unique identifier for the particle.
int mol_id
Molecule identifier.
Struct holding all information for one particle.
constexpr auto const & pos() const
constexpr auto const & mass() const
constexpr auto const & propagation() const
constexpr auto const & force() const
constexpr auto is_virtual() const
constexpr auto const & image_box() const
constexpr auto const & id() const
constexpr auto const & mol_id() const