Loading [MathJax]/extensions/TeX/AMSmath.js
ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
BindAtPointOfCollision.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2011-2024 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <config/config.hpp>
21
22#ifdef COLLISION_DETECTION
23#ifdef VIRTUAL_SITES_RELATIVE
24
26#include "CollisionPair.hpp"
27#include "utils.hpp"
28
29#include "BoxGeometry.hpp"
30#include "Particle.hpp"
32#include "cell_system/Cell.hpp"
34#include "communication.hpp"
36#include "system/System.hpp"
37#include "virtual_sites.hpp"
38
39#include <utils/Vector.hpp>
40#include <utils/math/sqr.hpp>
42
43#include <boost/mpi/collectives.hpp>
44#include <boost/mpi/operations.hpp>
45
46#include <cassert>
47#include <stdexcept>
48#include <utility>
49#include <vector>
50
51namespace CollisionDetection {
52
54 // Validate distance
55 if (distance <= 0.) {
56 throw std::domain_error("Parameter 'distance' must be > 0");
57 }
58 // Cache square of cutoff
60
61 // Check vs placement parameter
62 if (vs_placement < 0. or vs_placement > 1.) {
63 throw std::domain_error("Parameter 'vs_placement' must be between 0 and 1");
64 }
65
66 // Check if bond exists
67 assert(system.bonded_ias->contains(bond_vs));
68 // The bond between the virtual sites can be pair or triple
69 auto const n_partners = number_of_partners(*system.bonded_ias->at(bond_vs));
70 if (n_partners != 1 and n_partners != 2) {
71 throw std::runtime_error("The bond type to be used for binding virtual "
72 "sites needs to be a pair bond");
73 }
74
75 // Create particle types
76 if (part_type_vs < 0) {
77 throw std::domain_error("Collision detection particle type for virtual "
78 "sites needs to be >=0");
79 }
80 system.nonbonded_ias->make_particle_type_exist(part_type_vs);
81}
82
84 System::System &system, std::vector<CollisionPair> &local_collision_queue) {
85 auto &cell_structure = *system.cell_structure;
86 auto const min_global_cut = system.get_min_global_cut();
87 auto const &box_geo = *system.box_geo;
88
89 add_bind_centers(local_collision_queue, system, bond_centers);
90
91 // Gather the global collision queue, because only one node has a collision
92 // across node boundaries in its queue.
93 // The other node might still have to change particle properties on its
94 // non-ghost particle
95 auto global_collision_queue = gather_collision_queue(local_collision_queue);
96
97 // Synchornize max_seen_part
98 auto const global_max_seen_particle = boost::mpi::all_reduce(
99 ::comm_cart, cell_structure.get_max_local_particle_id(),
100 boost::mpi::maximum<int>());
101
102 int current_vs_pid = global_max_seen_particle + 1;
103
104 // Iterate over global collision queue
105 for (auto &c : global_collision_queue) {
106
107 // Get particle pointers
108 Particle *p1 = cell_structure.get_local_particle(c.first);
109 Particle *p2 = cell_structure.get_local_particle(c.second);
110
111 // Only nodes take part in particle creation and binding
112 // that see both particles
113
114 // If we cannot access both particles, both are ghosts,
115 // or one is ghost and one is not accessible
116 // we only increase the counter for the ext id to use based on the
117 // number of particles created by other nodes
118 if (((!p1 or p1->is_ghost()) and (!p2 or p2->is_ghost())) or !p1 or !p2) {
119 // Increase local counters
120 current_vs_pid += 2;
121 continue;
122 }
123 // We consider the pair because one particle is local to the node and
124 // the other is local or ghost.
125
126 // Enable rotation on the particles to which vs will be attached
129
130 // Positions of the virtual sites
131 auto const vec21 = box_geo.get_mi_vector(p1->pos(), p2->pos());
132 auto const pos1 = p1->pos() - vec21 * vs_placement;
133 auto const pos2 = p1->pos() - vec21 * (1. - vs_placement);
134
135 auto handle_particle = [&](Particle *p, Utils::Vector3d const &pos) {
136 if (not p->is_ghost()) {
137 place_vs_and_relate_to_particle(cell_structure, box_geo, part_type_vs,
138 min_global_cut, current_vs_pid, pos,
139 p->id());
140 // Particle storage locations may have changed due to
141 // added particle
142 p1 = cell_structure.get_local_particle(c.first);
143 p2 = cell_structure.get_local_particle(c.second);
144 }
145 };
146
147 // place virtual sites on the node where the base particle is not a ghost
148 handle_particle(p1, pos1);
149 // Increment counter
150 current_vs_pid++;
151
152 handle_particle(p2, pos2);
153 // Increment counter
154 current_vs_pid++;
155
156 // Create bonds
157 auto const n_partners = number_of_partners(*system.bonded_ias->at(bond_vs));
158 if (n_partners == 1) {
159 // Create bond between the virtual particles
160 const int bondG[] = {current_vs_pid - 2};
161 // Only add bond if vs was created on this node
162 if (auto p = cell_structure.get_local_particle(current_vs_pid - 1))
163 p->bonds().insert({bond_vs, bondG});
164 }
165 if (n_partners == 2) {
166 // Create 1st bond between the virtual particles
167 const int bondG[] = {c.first, c.second};
168 // Only add bond if vs was created on this node
169 if (auto p = cell_structure.get_local_particle(current_vs_pid - 1))
170 p->bonds().insert({bond_vs, bondG});
171 if (auto p = cell_structure.get_local_particle(current_vs_pid - 2))
172 p->bonds().insert({bond_vs, bondG});
173 }
174 } // Loop over all collisions in the queue
175
176#ifdef ADDITIONAL_CHECKS
177 assert(Utils::Mpi::all_compare(::comm_cart, current_vs_pid) &&
178 "Nodes disagree about current_vs_pid");
179#endif
180
181 // If any node had a collision, all nodes need to resort
182 if (not global_collision_queue.empty()) {
183 cell_structure.set_resort_particles(Cells::RESORT_GLOBAL);
184 cell_structure.update_ghosts_and_resort_particle(
187 }
188}
189
190} // namespace CollisionDetection
191
192#endif // VIRTUAL_SITES_RELATIVE
193#endif // COLLISION_DETECTION
Vector implementation and trait types for boost qvm interoperability.
Data structures for bonded interactions.
int number_of_partners(Bonded_IA_Parameters const &iaparams)
Get the number of bonded partners for the specified bond.
void handle_collisions(System::System &system, std::vector< CollisionPair > &local_collision_queue)
int part_type_vs
particle type for virtual sites created on collision
int bond_centers
bond type used between centers of colliding particles
double distance_sq
Square of distance at which particle are bound.
Main system class.
void update_used_propagations()
Update the global propagation bitmask.
std::shared_ptr< BondedInteractionsMap > bonded_ias
auto get_min_global_cut() const
Get min_global_cut.
std::shared_ptr< CellStructure > cell_structure
std::shared_ptr< BoxGeometry > box_geo
std::shared_ptr< InteractionsNonBonded > nonbonded_ias
boost::mpi::communicator comm_cart
The communicator.
This file contains the defaults for ESPResSo.
@ DATA_PART_PROPERTIES
Particle::p.
@ DATA_PART_BONDS
Particle::bonds.
void place_vs_and_relate_to_particle(CellStructure &cell_structure, BoxGeometry const &box_geo, int const part_type_vs, double const min_global_cut, int const current_vs_pid, Utils::Vector3d const &pos, int const relate_to)
auto gather_collision_queue(std::vector< CollisionPair > const &local)
void add_bind_centers(std::vector< CollisionPair > &collision_queue, System::System &system, int bond_id)
bool all_compare(boost::mpi::communicator const &comm, T const &value)
Compare values on all nodes.
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
Definition sqr.hpp:28
Various procedures concerning interactions between particles.
Struct holding all information for one particle.
Definition Particle.hpp:395
auto const & bonds() const
Definition Particle.hpp:428
bool is_ghost() const
Definition Particle.hpp:440
auto const & pos() const
Definition Particle.hpp:431
void set_can_rotate_all_axes()
Definition Particle.hpp:473
auto const & id() const
Definition Particle.hpp:414