33#include "communication.hpp"
35#include "system/System.hpp"
39#include <boost/mpi/collectives/all_reduce.hpp>
40#include <boost/variant.hpp>
61 auto const id = p.id();
63 if (id < 0 || id > max_id) {
64 throw std::runtime_error(
"Particle id out of bounds.");
68 throw std::runtime_error(
"Invalid local particle index entry.");
73 std::size_t local_part_cnt = 0u;
78 throw std::runtime_error(
"local_particles part has corrupted id.");
84 throw std::runtime_error(
86 std::to_string(local_part_cnt) +
" parts in local_particles");
92 for (
auto const &p : cell->particles()) {
93 if (particle_to_cell(p) != cell) {
94 throw std::runtime_error(
"misplaced particle with id " +
95 std::to_string(p.id()));
102 auto remove_all_bonds_to = [id](
BondList &bl) {
103 for (
auto it = bl.begin(); it != bl.end();) {
113 auto &parts = c->particles();
115 for (
auto it = parts.begin(); it != parts.end();) {
116 if (it->id() == id) {
117 it = parts.erase(it);
121 remove_all_bonds_to(it->bonds());
129 auto const sort_cell = particle_to_cell(p);
132 return std::addressof(
133 append_indexed_particle(sort_cell->particles(), std::move(p)));
140 auto const sort_cell = particle_to_cell(p);
149 return std::addressof(
150 append_indexed_particle(cell->particles(), std::move(p)));
154 auto it = std::find_if(m_particle_index.rbegin(), m_particle_index.rend(),
155 [](
const Particle *p) { return p != nullptr; });
157 return (it != m_particle_index.rend()) ? (*it)->id() : -1;
162 c->particles().clear();
165 m_particle_index.clear();
171 using namespace Cells;
179#ifdef BOND_CONSTRAINT
198#ifdef BOND_CONSTRAINT
222 static std::vector<ParticleChange> diff;
225 m_decomposition->resort(global_flag, diff);
227 for (
auto d : diff) {
228 boost::apply_visitor(UpdateParticleIndexVisitor{
this}, d);
231 auto const &lebc =
get_system().box_geo->lees_edwards_bc();
232 m_rebuild_verlet_list =
true;
233 m_le_pos_offset_at_last_resort = lebc.pos_offset;
235#ifdef ADDITIONAL_CHECKS
243 auto &local_geo = *system.local_geo;
244 auto const &box_geo = *system.box_geo;
245 set_particle_decomposition(
246 std::make_unique<AtomDecomposition>(
::comm_cart, box_geo));
248 local_geo.set_cell_structure_type(m_type);
249 system.on_cell_structure_change();
253 double range, std::optional<std::pair<int, int>> fully_connected_boundary) {
255 auto &local_geo = *system.local_geo;
256 auto const &box_geo = *system.box_geo;
257 set_particle_decomposition(std::make_unique<RegularDecomposition>(
258 ::comm_cart, range, box_geo, local_geo, fully_connected_boundary));
260 local_geo.set_cell_structure_type(m_type);
261 system.on_cell_structure_change();
265 std::set<int> n_square_types) {
267 auto &local_geo = *system.local_geo;
268 auto const &box_geo = *system.box_geo;
269 set_particle_decomposition(std::make_unique<HybridDecomposition>(
271 [&system]() {
return system.get_global_ghost_flags(); }, box_geo,
272 local_geo, n_square_types));
274 local_geo.set_cell_structure_type(m_type);
275 system.on_cell_structure_change();
280 m_verlet_skin = value;
281 m_verlet_skin_set =
true;
287 auto const max_cut =
get_system().maximal_cutoff();
289 throw std::runtime_error(
290 "cannot automatically determine skin, please set it manually");
295 auto const new_skin = std::min(0.4 * max_cut,
max_range - max_cut);
301 auto constexpr resort_only_parts =
304 auto const global_resort = boost::mpi::all_reduce(
305 ::comm_cart, m_resort_particles, std::bit_or<unsigned>());
@ NSQUARE
Atom decomposition (N-square).
@ HYBRID
Hybrid decomposition.
@ REGULAR
Regular decomposition.
unsigned map_data_parts(unsigned data_parts)
Map the data parts flags from cells to those used internally by the ghost communication.
unsigned map_data_parts(unsigned data_parts)
Map the data parts flags from cells to those used internally by the ghost communication.
Atom decomposition cell system.
virtual std::span< Cell *const > local_cells() const =0
Get pointer to local cells.
boost::mpi::communicator comm_cart
The communicator.
void ghost_communicator(GhostCommunicator const &gcr, BoxGeometry const &box_geo, unsigned int data_parts)
Do a ghost communication with the specified data parts.
@ 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
@ DATA_PART_PROPERTIES
Particle::p.
@ DATA_PART_BONDS
Particle::bonds.
bool contains(InputIt first, InputIt last, T const &value)
Check whether an iterator range contains a value.
Describes a cell structure / cell system.
ParticleRange ghost_particles() const
Particle * get_local_particle(int id)
Get a local particle by id.
void check_particle_sorting() const
Check that particles are in the correct cell.
void clear_resort_particles()
Set the resort level to sorted.
auto is_verlet_skin_set() const
Whether the Verlet skin is set.
ParticleDecomposition const & decomposition() const
Get the underlying particle decomposition.
void update_ghosts_and_resort_particle(unsigned data_parts)
Update ghost particles, with particle resort if needed.
Particle * add_local_particle(Particle &&p)
Add a particle.
void set_verlet_skin_heuristic()
Set the Verlet skin using a heuristic.
void set_verlet_skin(double value)
Set the Verlet skin.
void ghosts_update(unsigned data_parts)
Update ghost particles.
CellStructure(BoxGeometry const &box)
void update_particle_index(int id, Particle *p)
Update local particle index.
void ghosts_reduce_forces()
Add forces from ghost particles to real particles.
Utils::Vector3d max_range() const
Maximal pair range supported by current cell system.
void ghosts_count()
Synchronize number of ghosts.
void set_resort_particles(Cells::Resort level)
Increase the local resort level at least to level.
void remove_particle(int id)
Remove a particle.
Particle * add_particle(Particle &&p)
Add a particle.
void resort_particles(bool global_flag)
Resort particles.
void check_particle_index() const
Check that particle index is commensurate with particles.
void set_regular_decomposition(double range, std::optional< std::pair< int, int > > fully_connected_boundary)
Set the particle decomposition to RegularDecomposition.
void set_atom_decomposition()
Set the particle decomposition to AtomDecomposition.
void remove_all_particles()
Remove all particles from the cell system.
ParticleRange local_particles() const
void ghosts_reduce_rattle_correction()
Add rattle corrections from ghost particles to real particles.
void set_hybrid_decomposition(double cutoff_regular, std::set< int > n_square_types)
Set the particle decomposition to HybridDecomposition.
int get_max_local_particle_id() const
Get the maximal particle id on this node.
Utils::Vector3d max_cutoff() const
Maximal cutoff supported by current cell system.
Struct holding all information for one particle.
Apply a ParticleChange to a particle index.
void operator()(RemovedParticle rp) const
void operator()(ModifiedList mp) const