Skip to content

Commit c810728

Browse files
jngrad1234someshmebrito
committed
Rewrite Collision detection feature
Co-authored-by: Somesh Kurahatti <[email protected]> Co-authored-by: Mariano B <[email protected]>
1 parent 8c90c3d commit c810728

20 files changed

+1238
-658
lines changed

src/core/collision.cpp

+318-239
Large diffs are not rendered by default.

src/core/collision.hpp

+33-91
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,17 @@
1919

2020
#pragma once
2121

22-
#include "config/config.hpp"
23-
2422
#include "BondList.hpp"
2523
#include "Particle.hpp"
2624
#include "cell_system/CellStructure.hpp"
25+
#include "collision/protocols.hpp"
26+
#include "config/config.hpp"
2727
#include "nonbonded_interactions/nonbonded_interaction_data.hpp"
2828
#include "system/Leaf.hpp"
2929

30+
#include <memory>
31+
#include <variant>
3032
/** @brief Protocols for collision handling. */
31-
enum class CollisionModeType : int {
32-
/** @brief Deactivate collision detection. */
33-
OFF = 0,
34-
/** @brief Create bond between centers of colliding particles. */
35-
BIND_CENTERS = 1,
36-
/**
37-
* @brief Create a bond between the centers of the colliding particles,
38-
* plus two virtual sites at the point of collision and bind them
39-
* together. This prevents the particles from sliding against each
40-
* other. Requires VIRTUAL_SITES_RELATIVE.
41-
*/
42-
BIND_VS = 2,
43-
/** @brief Glue a particle to a specific spot on another particle. */
44-
GLUE_TO_SURF = 3,
45-
};
4633

4734
/// Data type holding the info about a single collision
4835
struct CollisionPair {
@@ -51,50 +38,31 @@ struct CollisionPair {
5138
};
5239

5340
class CollisionDetection : public System::Leaf<CollisionDetection> {
54-
public:
55-
CollisionDetection()
56-
: mode(CollisionModeType::OFF), distance(0.), distance_sq(0.),
57-
bond_centers(-1), bond_vs(-1) {}
58-
59-
/// collision protocol
60-
CollisionModeType mode;
61-
/// distance at which particles are bound
62-
double distance;
63-
// Square of distance at which particle are bound
64-
double distance_sq;
65-
66-
/// bond type used between centers of colliding particles
67-
int bond_centers;
68-
/// bond type used between virtual sites
69-
int bond_vs;
70-
/// particle type for virtual sites created on collision
71-
int vs_particle_type;
72-
73-
/// For mode "glue to surface": The distance from the particle which is to be
74-
/// glued to the new virtual site
75-
double dist_glued_part_to_vs;
76-
/// For mode "glue to surface": The particle type being glued
77-
int part_type_to_be_glued;
78-
/// For mode "glue to surface": The particle type to which the virtual site is
79-
/// attached
80-
int part_type_to_attach_vs_to;
81-
/// Particle type to which the newly glued particle is converted
82-
int part_type_after_glueing;
83-
/** Placement of virtual sites for MODE_VS.
84-
* 0=on same particle as related to,
85-
* 1=on collision partner,
86-
* 0.5=in the middle between
87-
*/
88-
double vs_placement;
41+
public: // private: TODO make private again!
42+
std::shared_ptr<Collision::ActiveProtocol> m_protocol;
8943

44+
public:
45+
CollisionDetection() = default;
46+
/** @brief Get currently active Collision protocol. */
47+
auto get_protocol() const { return m_protocol; }
48+
/** @brief Set a new Collision protocol. */
49+
void set_protocol(std::shared_ptr<Collision::ActiveProtocol> protocol);
50+
/** @brief Delete the currently active Collision protocol. */
51+
void unset_protocol();
9052
/** @brief Validates parameters and creates particle types if needed. */
9153
void initialize();
9254

55+
auto is_off() const {
56+
return m_protocol == nullptr or
57+
std::get_if<Collision::Off>(m_protocol.get()) != nullptr;
58+
}
59+
9360
auto cutoff() const {
94-
if (mode != CollisionModeType::OFF) {
95-
return distance;
61+
if (m_protocol == nullptr) {
62+
return INACTIVE_CUTOFF;
9663
}
97-
return INACTIVE_CUTOFF;
64+
return std::visit([](auto const &protocol) { return protocol.cutoff(); },
65+
*m_protocol);
9866
}
9967

10068
/// Handle queued collisions
@@ -105,47 +73,21 @@ class CollisionDetection : public System::Leaf<CollisionDetection> {
10573
/** @brief Detect (and queue) a collision between the given particles. */
10674
void detect_collision(Particle const &p1, Particle const &p2,
10775
double const dist_sq) {
108-
if (dist_sq > distance_sq)
109-
return;
110-
111-
// If we are in the glue to surface mode, check that the particles
112-
// are of the right type
113-
if (mode == CollisionModeType::GLUE_TO_SURF)
114-
if (!glue_to_surface_criterion(p1, p2))
115-
return;
116-
117-
// Ignore virtual particles
118-
if (p1.is_virtual() or p2.is_virtual())
119-
return;
120-
121-
// Check, if there's already a bond between the particles
122-
if (pair_bond_exists_on(p1.bonds(), p2.id(), bond_centers))
123-
return;
124-
125-
if (pair_bond_exists_on(p2.bonds(), p1.id(), bond_centers))
126-
return;
127-
128-
/* If we're still here, there is no previous bond between the particles,
129-
we have a new collision */
130-
131-
// do not create bond between ghost particles
132-
if (p1.is_ghost() and p2.is_ghost()) {
133-
return;
76+
if (m_protocol) {
77+
bool collision_detected = std::visit(
78+
[&p1, &p2, dist_sq](auto const &protocol) {
79+
return protocol.detect_collision(p1, p2, dist_sq);
80+
},
81+
*m_protocol);
82+
83+
if (collision_detected) {
84+
local_collision_queue.push_back({p1.id(), p2.id()});
85+
}
13486
}
135-
local_collision_queue.push_back({p1.id(), p2.id()});
13687
}
137-
13888
// private:
13989
/// During force calculation, colliding particles are recorded in the queue.
14090
/// The queue is processed after force calculation, when it is safe to add
14191
/// particles.
14292
std::vector<CollisionPair> local_collision_queue;
143-
144-
/** @brief Check additional criteria for the glue_to_surface collision mode */
145-
bool glue_to_surface_criterion(Particle const &p1, Particle const &p2) const {
146-
return (((p1.type() == part_type_to_be_glued) and
147-
(p2.type() == part_type_to_attach_vs_to)) or
148-
((p2.type() == part_type_to_be_glued) and
149-
(p1.type() == part_type_to_attach_vs_to)));
150-
}
15193
};

src/core/collision/protocols.hpp

+230
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
#pragma once
2+
3+
#include <config/config.hpp>
4+
5+
#ifdef COLLISION_DETECTION
6+
7+
#include "bonded_interactions/bonded_interaction_data.hpp"
8+
#include "nonbonded_interactions/nonbonded_interaction_data.hpp"
9+
10+
#include <variant>
11+
12+
struct CollisionPair;
13+
14+
namespace Collision {
15+
16+
class Off {
17+
public:
18+
Off() = default;
19+
20+
auto cutoff() const { return INACTIVE_CUTOFF; }
21+
22+
void initialize(BondedInteractionsMap &, InteractionsNonBonded &) { return; }
23+
24+
void handle_collisions(System::System &system, std::vector<CollisionPair> &) {
25+
}
26+
bool detect_collision(Particle const &p1, Particle const &p2,
27+
double const dist_sq) const {
28+
return false;
29+
}
30+
};
31+
32+
class BindCenters {
33+
34+
public:
35+
double distance;
36+
// Square of distance at which particle are bound
37+
double distance_sq;
38+
39+
/// bond type used between centers of colliding particles
40+
int bond_centers;
41+
42+
BindCenters(double distance, int bond_centers)
43+
: distance{distance}, distance_sq{distance * distance},
44+
bond_centers{bond_centers} {}
45+
46+
void initialize(BondedInteractionsMap &bonded_ias,
47+
InteractionsNonBonded &nonbonded_ias);
48+
49+
auto cutoff() const { return distance; }
50+
51+
void handle_collisions(System::System &system,
52+
std::vector<CollisionPair> &local_collision_queue);
53+
54+
bool detect_collision(Particle const &p1, Particle const &p2,
55+
double const dist_sq) const {
56+
if (dist_sq > distance_sq)
57+
return false;
58+
59+
// Ignore virtual particles
60+
if (p1.is_virtual() or p2.is_virtual())
61+
return false;
62+
63+
// Check, if there's already a bond between the particles
64+
if (pair_bond_exists_on(p1.bonds(), p2.id(), bond_centers))
65+
return false;
66+
67+
if (pair_bond_exists_on(p2.bonds(), p1.id(), bond_centers))
68+
return false;
69+
70+
/* If we're still here, there is no previous bond between the particles,
71+
we have a new collision */
72+
73+
// do not create bond between ghost particles
74+
if (p1.is_ghost() and p2.is_ghost()) {
75+
return false;
76+
}
77+
return true;
78+
}
79+
};
80+
81+
#ifdef VIRTUAL_SITES_RELATIVE
82+
class BindVS {
83+
public:
84+
double distance;
85+
// Square of distance at which particle are bound
86+
double distance_sq;
87+
88+
/// bond type used between centers of colliding particles
89+
int bond_centers;
90+
/// bond type used between virtual sites
91+
int bond_vs;
92+
/** Placement of virtual sites for MODE_VS.
93+
* 0=on same particle as related to,
94+
* 1=on collision partner,
95+
* 0.5=in the middle between
96+
*/
97+
double vs_placement;
98+
/// particle type for virtual sites created on collision
99+
int part_type_vs;
100+
101+
BindVS(double distance, int bond_centers, int bond_vs, double vs_placement,
102+
int part_type_vs)
103+
: distance{distance}, distance_sq{distance * distance},
104+
bond_centers{bond_centers}, bond_vs{bond_vs},
105+
vs_placement{vs_placement}, part_type_vs{part_type_vs} {}
106+
107+
void initialize(BondedInteractionsMap &bonded_ias,
108+
InteractionsNonBonded &nonbonded_ias);
109+
110+
auto cutoff() const { return distance; }
111+
112+
void handle_collisions(System::System &system,
113+
std::vector<CollisionPair> &local_collision_queue);
114+
115+
bool detect_collision(Particle const &p1, Particle const &p2,
116+
double const dist_sq) const {
117+
if (dist_sq > distance_sq)
118+
return false;
119+
120+
// Ignore virtual particles
121+
if (p1.is_virtual() or p2.is_virtual())
122+
return false;
123+
124+
// Check, if there's already a bond between the particles
125+
if (pair_bond_exists_on(p1.bonds(), p2.id(), bond_centers))
126+
return false;
127+
128+
if (pair_bond_exists_on(p2.bonds(), p1.id(), bond_centers))
129+
return false;
130+
131+
/* If we're still here, there is no previous bond between the particles,
132+
we have a new collision */
133+
134+
// do not create bond between ghost particles
135+
if (p1.is_ghost() and p2.is_ghost()) {
136+
return false;
137+
}
138+
return true;
139+
}
140+
};
141+
142+
class GlueToSurf {
143+
public:
144+
double distance;
145+
// Square of distance at which particle are bound
146+
double distance_sq;
147+
/// bond type used between centers of colliding particles
148+
int bond_centers;
149+
/// bond type used between virtual sites
150+
int bond_vs;
151+
/// particle type for virtual sites created on collision
152+
int part_type_vs;
153+
/// For mode "glue to surface": The distance from the particle which is to be
154+
/// glued to the new virtual site
155+
double dist_glued_part_to_vs;
156+
/// For mode "glue to surface": The particle type being glued
157+
int part_type_to_be_glued;
158+
/// For mode "glue to surface": The particle type to which the virtual site is
159+
/// attached
160+
int part_type_to_attach_vs_to;
161+
/// Particle type to which the newly glued particle is converted
162+
int part_type_after_glueing;
163+
164+
GlueToSurf(double distance, int bond_centers, int bond_vs, int part_type_vs,
165+
double dist_glued_part_to_vs, int part_type_to_be_glued,
166+
int part_type_to_attach_vs_to, int part_type_after_glueing)
167+
: distance{distance}, distance_sq{distance * distance},
168+
bond_centers{bond_centers}, bond_vs{bond_vs},
169+
part_type_vs{part_type_vs},
170+
dist_glued_part_to_vs{dist_glued_part_to_vs},
171+
part_type_to_be_glued{part_type_to_be_glued},
172+
part_type_to_attach_vs_to{part_type_to_attach_vs_to},
173+
part_type_after_glueing{part_type_after_glueing} {}
174+
175+
void initialize(BondedInteractionsMap &bonded_ias,
176+
InteractionsNonBonded &nonbonded_ias);
177+
178+
auto cutoff() const { return distance; }
179+
180+
/** @brief Check additional criteria for the glue_to_surface collision mode */
181+
bool glue_to_surface_criterion(Particle const &p1, Particle const &p2) const {
182+
return (((p1.type() == part_type_to_be_glued) and
183+
(p2.type() == part_type_to_attach_vs_to)) or
184+
((p2.type() == part_type_to_be_glued) and
185+
(p1.type() == part_type_to_attach_vs_to)));
186+
}
187+
188+
void handle_collisions(System::System &system,
189+
std::vector<CollisionPair> &local_collision_queue);
190+
191+
bool detect_collision(Particle const &p1, Particle const &p2,
192+
double const dist_sq) const {
193+
if (dist_sq > distance_sq)
194+
return false;
195+
196+
// If we are in the glue to surface mode, check that the particles
197+
// are of the right type
198+
199+
if (!glue_to_surface_criterion(p1, p2))
200+
return false;
201+
202+
// Ignore virtual particles
203+
if (p1.is_virtual() or p2.is_virtual())
204+
return false;
205+
206+
// Check, if there's already a bond between the particles
207+
if (pair_bond_exists_on(p1.bonds(), p2.id(), bond_centers))
208+
return false;
209+
210+
if (pair_bond_exists_on(p2.bonds(), p1.id(), bond_centers))
211+
return false;
212+
213+
/* If we're still here, there is no previous bond between the particles,
214+
we have a new collision */
215+
216+
// do not create bond between ghost particles
217+
if (p1.is_ghost() and p2.is_ghost()) {
218+
return false;
219+
}
220+
return true;
221+
}
222+
};
223+
#endif // VIRTUAL_SITES_RELATIVE
224+
using ActiveProtocol = std::variant<Off, BindCenters,
225+
#ifdef VIRTUAL_SITES_RELATIVE
226+
BindVS, GlueToSurf
227+
#endif // VIRTUAL_SITES_RELATIVE
228+
>;
229+
} // namespace Collision
230+
#endif

0 commit comments

Comments
 (0)