There is an awesome simulation https://mathematica.stackexchange.com/a/124926/87086 which shows N particles bouncing in a box (with elastic collisions), made by @Feyre https://mathematica.stackexchange.com/users/7312/feyre. Since then, they have moved on from commenting on StackExchange, and I was wondering how one could modify such an example's WhenEvent(s) such that when any number of particles collide, instead of ricocheting off of one another, they "stick" together and continue on as clump, with momentum:
m*v1 + m*v2 + ...m*v_n = n*m*v3
(where n is the number of particles in the clump)
Once stuck, I would like them to remain in contact with one another (maintaining their clumpiness) and be treated as a new body which is made up of the n particles that have collided (not a single particle with mass n*m and velocity v3).
Is there any way to go about doing this with WhenEvents at all? I have been at it for a while, and am at a loss as of now. Any insight would be greatly appreciated.
I have included the code below, but upon following the first link listed in this post you will find the simulation that @Feyre produced.
data = Table[{RandomReal[{-0.85, 0.85}, {3}],
RandomReal[{-1, 1}, {3}],
RGBColor[RandomReal[{-1, 1}], RandomReal[{-1, 1}],
RandomReal[{-1, 1}]]}, {i, 10}];
n = Length[data];
positions = Transpose[Table[data[[i, 1]], {i, n}]];
velocities = Transpose[Table[data[[i, 2]], {i, n}]];
(Setting up stuff for NDSolve[])
{xt, yt,
zt} = {ToExpression[Table["x" <> ToString[i], {i, n}]],
ToExpression[Table["y" <> ToString[i], {i, n}]],
ToExpression[Table["z" <> ToString[i], {i, n}]]};
{xm, ym, zm} = {Through[xt[t]], Through[yt[t]], Through[zt[t]]};
{xz, yz, zz} = {Through[xt[0]], Through[yt[0]], Through[zt[0]]};
yt = ToExpression[Table["y" <> ToString[i], {i, n}]];
zt = ToExpression[Table["z" <> ToString[i], {i, n}]];
rm = Flatten[
Table[If[i != j,
Sqrt[(xm[[j]] - xm[[i]])^2 + (ym[[j]] - ym[[i]])^2 + (zm[[j]] -
zm[[i]])^2]], {i, n}, {j, n}]] /. Null -> Sequence[];
(No friction or gravity:)
xf = Thread[D[D[xm, t], t] == ConstantArray[0, n]];
yf = Thread[D[D[ym, t], t] == ConstantArray[0, n]];
zf = Thread[D[D[zm, t], t] == ConstantArray[0, n]];
(Friction and gravity:)
xf = Thread[D[D[xm, t], t] == -0.01 D[xm, t]];
yf = Thread[D[D[ym, t], t] == -0.01 D[ym, t]];
zf = Thread[D[D[zm, t], t] == -0.01 D[zm, t] - ConstantArray[0.5, n]];
(The final equations for the differential equation:)
pos = {Thread[xz == positions[[1]]], Thread[yz == positions[[2]]],
Thread[zz == positions[[3]]]};
vel = {Thread[D[xm, t] == velocities[[1]]] /. t -> 0,
Thread[D[ym, t] == velocities[[2]]] /. t -> 0,
Thread[D[zm, t] == velocities[[3]]] /. t -> 0};
col = Table[data[[i, 3]], {i, n}];
we = {};
(Events)
Table[AppendTo[we,
WhenEvent[
Sqrt[(xm[[i]] - xm[[j]])^2 + (ym[[i]] - ym[[j]])^2 + (zm[[i]] -
zm[[j]])^2] <= 0.2 // Evaluate, {
D[xm[[i]], t] -> 0.5 (D[xm[[i]], t] + D[xm[[j]], t]),
D[xm[[j]], t] -> 0.5 (D[xm[[i]], t] + D[xm[[j]], t]),
D[xm[[i]], t] -> 0.5 (D[ym[[i]], t] + D[ym[[j]], t]),
D[xm[[j]], t] -> 0.5 (D[ym[[i]], t] + D[ym[[j]], t]),
D[xm[[i]], t] -> 0.5 (D[zm[[i]], t] + D[zm[[j]], t]),
D[xm[[j]], t] -> 0.5 (D[zm[[i]], t] + D[ym[[j]], t])} //
Evaluate]], {i, n - 1}, {j, i + 1, n}];
Table[AppendTo[we,
WhenEvent[Abs[xm[[i]]] >= 0.9 // Evaluate,
D[xm[[i]], t] -> -D[xm[[i]], t] // Evaluate]], {i, n}];
Table[AppendTo[we,
WhenEvent[Abs[ym[[i]]] >= 0.9 // Evaluate,
D[ym[[i]], t] -> -D[ym[[i]], t] // Evaluate]], {i, n}];
Table[AppendTo[we,
WhenEvent[Abs[zm[[i]]] >= 0.9 // Evaluate,
D[zm[[i]], t] -> -D[zm[[i]], t] // Evaluate]], {i, n}];
s = NDSolve[Flatten[{xf, yf, zf,
vel, pos, we}], Flatten[{xt, yt, zt}], {t, 0, 50},
MaxSteps -> ∞];
Manipulate[
Graphics3D[
Transpose[{col,
Thread[Sphere[
Evaluate[
Flatten[Thread[Transpose[{xm, ym, zm} /. t -> a] /. s], 1]],
0.1]]}], PlotRange -> {{-1, 1}, {-1, 1}, {-1, 1}}], {a, 0, 50,
0.1}]```

-.85.....85speaks forradius==0.15. Also the box is in the range of-1...+1, thoughradius=?=1isn't plausibel. – Ulrich Neumann Jul 22 '22 at 15:43