I made this Manipulate
code which shows a pack of particles randomly moving inside a box. It has a huge performance issue. What should be the best way in doing "hard" bounces on the walls ? I used an oscillator trick to do the bounces (there's surely a better way). The code below is working but is way too slow for just a few particles, and yet the particles don't even interact ! So I need advices/suggestions to do a better "gaz of particles in a box".
L1 = 20; (* Box size along X *)
L2 = 10; (* Box size along Y *)
L3 = 5; (* Box size along Z *)
r = 1; (* randomizer parameter *)
box = Graphics3D[{Opacity[0.1], Cuboid[{-L1/2, -L2/2, -L3/2}, {L1/2, L2/2, L3/2}]}];
(* Random initial conditions : *)
X0[n_, r_] := X0[n, r] = {RandomReal[{-1, 1}] L1/2, RandomReal[{-1, 1}] L2/2, RandomReal[{-1, 1}] L3/2}
V0[n_, r_] := V0[n, r] = RandomReal[{-1, 1}, 3]
(* Solving the equations of motion. Surely a better way of doing this : *)
motion[n_, r_] := NDSolve[{
x''[t] == If[-L1/2 < x[t] < L1/2, 0, -10 x[t]],
y''[t] == If[-L2/2 < y[t] < L2/2, 0, -10 y[t]],
z''[t] == If[-L3/2 < z[t] < L3/2, 0, -10 z[t]],
x[0] == {1, 0, 0}.X0[n, r],
y[0] == {0, 1, 0}.X0[n, r],
z[0] == {0, 0, 1}.X0[n, r],
x'[0] == {1, 0, 0}.V0[n, r],
y'[0] == {0, 1, 0}.V0[n, r],
z'[0] == {0, 0, 1}.V0[n, r]
}, {x, y, z}, {t, 0, 50},
Method -> Automatic, MaxSteps -> Automatic
]
color[n_] := color[n] = RGBColor[RandomReal[{0, 1}, 3]]
particles[t_, Np_, r_] := Graphics3D[Table[{color[n], PointSize -> 0.01,
Point[Evaluate[{x[t], y[t], z[t]}/.motion[n, r]]]
}, {n, 1, Np}]]
trajectory[t_, n_, r_] := ParametricPlot3D[
Evaluate[{x[s], y[s], z[s]}/.motion[n, r]], {s, 0.001, t},
PlotStyle -> color[n]]
Manipulate[
Show[{box, particles[t, Np, r],
Table[trajectory[t, n, r], {n, 1, Np}]},
PlotRange -> {{-1, 1} L1/2, {-1, 1} L2/2, {-1, 1} L3/2},
Boxed -> False, Axes -> False,
ImageSize -> {600, 600},
SphericalRegion -> True,
Method -> {"RotationControl" -> "Globe"}],
{{t, 0, Style["Time", 10]}, 0, 50, 0.01, ImageSize -> Large},
{{Np, 1, Style["Number or particles", 10]}, 1, 100, 1, ImageSize -> Large},
Delimiter,
Button[Style["Randomize", Bold, Red, 12], {r = RandomReal[]},
Appearance -> "Palette", ImageSize -> {100, 24}],
ControlPlacement -> Bottom
]
Preview :
EDIT : I know that the analytical solution to the equations of motion is simply a straight line (with the random initial conditions defined above) :
X[t_, n_, r_] := X0[n, r] + V0[n, r] t
which describes the motion between the start (at t = 0
) and the first collision through a wall. It's certainly preferable to use this function instead of solving the differential equations. But I'm still struggling with the collisions. How to reverse the velocity at each collision, without solving the diff equations ?
EDIT 2 :
I've adapted the code from tsuresuregusa, and here's a preview of the sweet results :
I've added a fade effect on the trails. It's really fun to see the animation.
Here's an animation of 6 particles :
I used ViewPoint -> {Sin[0.05t], Cos[0.05t], 1}
for the revolution around the box. What would you suggest for a better effect ?
Manipulate
code. $\endgroup$