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
GlueToSurface.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
25#include "CollisionPair.hpp"
26#include "GlueToSurface.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 if (part_type_vs < 0) {
62 throw std::domain_error("Collision detection particle type for virtual "
63 "sites needs to be >=0");
64 }
65 system.nonbonded_ias->make_particle_type_exist(part_type_vs);
66
67 if (part_type_to_be_glued < 0) {
68 throw std::domain_error("Collision detection particle type to be glued "
69 "needs to be >=0");
70 }
71 system.nonbonded_ias->make_particle_type_exist(part_type_to_be_glued);
72
74 throw std::domain_error("Collision detection particle type to attach "
75 "the virtual site to needs to be >=0");
76 }
77 system.nonbonded_ias->make_particle_type_exist(part_type_to_attach_vs_to);
78
80 throw std::domain_error("Collision detection particle type after gluing "
81 "needs to be >=0");
82 }
83 system.nonbonded_ias->make_particle_type_exist(part_type_after_glueing);
84}
85
87 System::System &system, std::vector<CollisionPair> &local_collision_queue) {
88 auto &cell_structure = *system.cell_structure;
89 auto const min_global_cut = system.get_min_global_cut();
90 auto const &box_geo = *system.box_geo;
91 // Note that the glue to surface mode adds bonds between the centers
92 // but does so later in the process. This is needed to guarantee that
93 // a particle can only be glued once, even if queued twice in a single
94 // time step
95
96 // Gather the global collision queue, because only one node has a collision
97 // across node boundaries in its queue.
98 // The other node might still have to change particle properties on its
99 // non-ghost particle
100 auto global_collision_queue = gather_collision_queue(local_collision_queue);
101
102 // Sync max_seen_part
103 auto const global_max_seen_particle = boost::mpi::all_reduce(
104 ::comm_cart, cell_structure.get_max_local_particle_id(),
105 boost::mpi::maximum<int>());
106
107 int current_vs_pid = global_max_seen_particle + 1;
108
109 // Iterate over global collision queue
110 for (auto &c : global_collision_queue) {
111
112 // Get particle pointers
113 Particle *p1 = cell_structure.get_local_particle(c.first);
114 Particle *p2 = cell_structure.get_local_particle(c.second);
115
116 // Only nodes take part in particle creation and binding
117 // that see both particles
118
119 // If we cannot access both particles, both are ghosts,
120 // or one is ghost and one is not accessible
121 // we only increase the counter for the ext id to use based on the
122 // number of particles created by other nodes
123 if (((!p1 or p1->is_ghost()) and (!p2 or p2->is_ghost())) or !p1 or !p2) {
124 // For glue to surface, we have only one vs
125 current_vs_pid++;
126
127 if (p1 and p1->type() == part_type_to_be_glued) {
129 }
130 if (p2 and p2->type() == part_type_to_be_glued) {
132 }
133 continue;
134 }
135 // If particles are made inert by a type change on collision:
136 // We skip the pair if one of the particles has already reacted
137 // but we still increase the particle counters, as other nodes
138 // can not always know whether or not a vs is placed
140 if ((p1->type() == part_type_after_glueing) or
141 (p2->type() == part_type_after_glueing)) {
142 current_vs_pid++;
143 continue;
144 }
145 }
146
147 double ratio = -1.;
148 auto const vec21 = box_geo.get_mi_vector(p1->pos(), p2->pos());
149 auto const dist = vec21.norm();
150
151 // Find out, which is the particle to be glued.
152 if ((p1->type() == part_type_to_be_glued) and
153 (p2->type() == part_type_to_attach_vs_to)) {
154 ratio = 1. - dist_glued_part_to_vs / dist;
155 } else if ((p2->type() == part_type_to_be_glued) and
156 (p1->type() == part_type_to_attach_vs_to)) {
157 ratio = dist_glued_part_to_vs / dist;
158 }
159 assert(ratio != -1.);
160 auto const pos = p2->pos() + vec21 * ratio;
161 auto const &attach_vs_to =
162 (p1->type() == part_type_to_attach_vs_to) ? *p1 : *p2;
163
164 // Add a bond between the centers of the colliding particles
165 // The bond is placed on the node that has p1
166 if (!p1->is_ghost()) {
167 const int bondG[] = {c.second};
168 get_part(cell_structure, c.first).bonds().insert({bond_centers, bondG});
169 }
170
171 // Change type of particle being attached, to make it inert
172 if (p1->type() == part_type_to_be_glued) {
174 }
175 if (p2->type() == part_type_to_be_glued) {
177 }
178
179 if (attach_vs_to.is_ghost()) {
180 current_vs_pid++;
181 } else {
182 // VS placement happens on the node that has p1
183 place_vs_and_relate_to_particle(cell_structure, box_geo, part_type_vs,
184 min_global_cut, current_vs_pid, pos,
185 attach_vs_to.id());
186 // Particle storage locations may have changed due to added particle
187 p1 = cell_structure.get_local_particle(c.first);
188 p2 = cell_structure.get_local_particle(c.second);
189 current_vs_pid++;
190 }
191 // Create bond between the virtual particles
192 auto const p = (p1->type() == part_type_after_glueing) ? p1 : p2;
193 int const bondG[] = {current_vs_pid - 1};
194 get_part(cell_structure, p->id()).bonds().insert({bond_vs, bondG});
195 } // Loop over all collisions in the queue
196
197#ifdef ADDITIONAL_CHECKS
198 assert(Utils::Mpi::all_compare(::comm_cart, current_vs_pid) &&
199 "Nodes disagree about current_vs_pid");
200#endif
201
202 // If any node had a collision, all nodes need to resort
203 if (not global_collision_queue.empty()) {
204 cell_structure.set_resort_particles(Cells::RESORT_GLOBAL);
205 cell_structure.update_ghosts_and_resort_particle(
208 }
209}
210
211} // namespace CollisionDetection
212
213#endif // VIRTUAL_SITES_RELATIVE
214#endif // COLLISION_DETECTION
Vector implementation and trait types for boost qvm interoperability.
Data structures for bonded interactions.
int part_type_vs
particle type for virtual sites created on collision
double dist_glued_part_to_vs
Distance from the particle which is to be glued to the new virtual site.
int bond_centers
bond type used between centers of colliding particles
double distance_sq
Square of distance at which particle are bound.
double distance
Distance at which particle are bound.
int part_type_to_attach_vs_to
The particle type to which virtuals site are attached (the large particle)
int bond_vs
bond type used between virtual sites
int part_type_after_glueing
Particle type to which the newly glued particle is converted.
void initialize(System::System &system)
void handle_collisions(System::System &system, std::vector< CollisionPair > &local_collision_queue)
int part_type_to_be_glued
The particle type being glued (the small particle)
Main system class.
void update_used_propagations()
Update the global propagation bitmask.
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)
auto & get_part(CellStructure &cell_structure, int 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 & type() const
Definition Particle.hpp:418
auto const & bonds() const
Definition Particle.hpp:428
bool is_ghost() const
Definition Particle.hpp:440
auto const & pos() const
Definition Particle.hpp:431