This simulator computes all possible intersections, then checks which of those possible intersections is soonest to occur, and checks if it is a real intersection that will happen, if it will, the simulator runs for Δt time, which is enough for that collision to occur. Once the intersection occurs, the whole process runs again. The idea is that CUDA allows this to occur very fast, by computing a lot of data in parallel (all segments and intersections), and is very precise, not losing precision to particles teleporting.
p1 .---------------->. p3 /
| | |Δd
a . . b /
| |
p2 .---------------->. p4
/-----------------/
ΔT * v0
a: Particle position at start of timestep
b: Particle position at end of timestep
Δd: Particle radius
ΔT: maximum time step
v0: fixed particle velocity
p1 p3: Particle boundary during timestep
p2 p4: Particle boundary during timestep
a b: Particle path (only used for perpendiculars)
Points ≈
Velocities ≈
Collsion time ≈
Radius of particle ≈
Distance between particles ≈
Then:
Then:
And we use:
-
$d < 0$ : No intersect -
$b > -1e-6$ : Glancing -
$b >= 0$ : Getting farther -
$t0 < 0$ and$t1 > 0$ and$b <= -1e-6$ : No intersect
Point ≈
Position (this is the same axis as wall, x for side collision, y for top/bottom) ≈
Velocity (this is the same axis as wall, x for side collision, y for top/bottom) ≈
Collision time ≈
Radius of particle ≈
Wall position (this is the X coordinate for the sides, and Y coordinate for top/bottom) ≈
Distance between particle and wall ≈
Then:
Then:
And we use:
-
$d < 0$ : No intersect -
$b > -1e-6$ : Glancing -
$b >= 0$ : Getting farther -
$t0 < 0$ and$t1 > 0$ and$b <= -1e-6$ : No intersect
Particle A position before ≈
Particle A position after ≈
Particle A velocity ≈
timestep ≈
Velocity is only updated for colliding particles as there is no acceleration.
Particle position ≈
Particle velocity before ≈
Particle velocity after ≈
Particle A position ≈
Particle A velocity before ≈
Particle A velocity after ≈ $(A'{vx}, A'{vy})$
Particle B position ≈
Particle B velocity before ≈
Particle B velocity after ≈ $(B'{vx}, B'{vy})$
$$({A'}{vx}, {A'}{vy}) = \frac{(B_{vx}, B_{vy})}{||(B_{vx}, B_{vy})||} * ||(A_{vx}, A_{vy})|| $$
$$({B'}{vx}, {B'}{vy}) = \frac{(A_{vx}, A_{vy})}{||(A_{vx}, A_{vy})||} * ||(B_{vx}, B_{vy})|| $$
all calls to cudaAlloc ≈ allocation
graph optimization ≈ optimization
setting particle position, initial velocities in device global memory ≈ initialization
Move particles and cleanup sim ≈ advanceSimulation
amount of particles ≈ PARTICLES
CUDA = (||^(PARTICLES * PARTICLES)_i=1 i: i.computeIntersectionTime) -> (||^(PARTICLES)_i=1 i: i.calculateIntersectionBorderTime)
-> (||^(1)_i=1 i: i.minimum) -> advanceSimulation
SIMULATION = CUDA -> SIMULATION
DEVICE = CUDA -> DEVICE
HOST = allocation -> initialization -> checkDistances -> optimization -> SIMULATION
SYSTEM = HOST || DEVICE
Particle A ≈ i
Particle B ≈ j
Collision time between A and a wall ≈ a
Collision time between A and B ≈ b
Data isn't saved because it would be duplicated ≈ x
i
0 1 2 3 4 5
0 a | b | b | b | b | b |
1 x | a | b | b | b | b |
j 2 x | x | a | b | b | b |
3 x | x | x | a | b | b |
4 x | x | x | x | a | b |
5 x | x | x | x | x | a |