Multiple collisions

advertisement
Easy Java Simulations step-by-step series of examples
Multiple collisions
Description
This simulation models the collision of planar disks which move inside a box with
uniformly accelerated motion (when gravity is turned on) and which collide with the
walls of the box and among themselves. Collisions can be elastic or inelastic and may
take place simultaneously.
We will need to define a rather sophisticated event to take care of all possible
simultaneous collisions that may take place.
Model
Variables
For clarity, we create three pages of variables:



n indicates the number of disks in the box.
The arrays x, y, vx, and vy contain the disks positions and velocities.
The arrays mass and diameter contain the physical characteristics of the disks
(which can be different from disk to disk).
Throwing a ball (parabolic throw)
page 1 of 9
Easy Java Simulations step-by-step series of examples






The minimum and maximum x and y variables indicate the box boundaries.
t is the time.
g is the acceleration due to gravity.
k is the restitution coefficient for all collisions (1 when the collisions are elastic).
energy is a variable that we will use to compute the total mechanical energy of
the system. Keeping the energy constant (for elastic collisions) is a good test for
our collision algorithm.
The gravityOn boolean variable indicates whether gravity is acting on the
particles.
This final page of variables contains variables that we will use in the events.
Initialization
The code for the initialization sets random initial positions and velocities for our disks.
However, it is important that this configuration is legal. This means that no two disks
can overlap each other. If this were the case, the event algorithm would fail and we
would get a nasty error message at start-up.
The code below tries up to 50 times to get such a legal initial configuration:
t = 0; // reset the time
_setDelay(1); // run very fast (a delay of 1 millisecond only)
// Search for a random legal state
for (int attempts=0; attempts<50; attempts++) { // Try 50 times
Throwing a ball (parabolic throw)
page 2 of 9
Easy Java Simulations step-by-step series of examples
for (int i=0; i<n; i++) {
x[i] = xmin+0.5*diameter[i] + (xmax-xmin-diameter[i])*Math.random();
vx[i] = (xmax-xmin)*(Math.random()-0.5);
y[i] = ymin+0.5*diameter[i] + (ymax-ymin-diameter[i])*Math.random();
vy[i] = (ymax-ymin)*(Math.random()-0.5);
}
// Check for illegal states
boolean legalState = true;
for (int i=0; i<n; i++) {
if (!legalState) break;
for (int j=i+1; j<n; j++) {
double d1 = x[j]-x[i];
double d2 = y[j]-y[i];
double result = d1*d1+d2*d2(diameter[i]+diameter[j])*(diameter[i]+diameter[j])/4;
if (result<0) { legalState = false; break; }
}
}
if (legalState) break; // exit for attempts
}
Evolution
The evolution uses first a page of ODEs.
Notice that the vertical acceleration is given by a method acc that we will need to define
in the Custom panel. Also, the ODE defines two pages of events. These pages are good
examples of how to create events for systems of particles.
Throwing a ball (parabolic throw)
page 3 of 9
Easy Java Simulations step-by-step series of examples
The code for the Zero Condition of the first page of events is given by:
double min = TOLERANCE;
for (int i=0; i<n; i++) {
double radius = diameter[i]/2;
double d = y[i]-ymin-radius;
if (vy[i]<0 && d<min) {
horizontalRebound = false;
ballRebounded = i;
min=d;
}
d = ymax-radius-y[i];
if (vy[i]>0 && d<min) {
horizontalRebound = false;
ballRebounded = i;
min=d;
}
d = x[i]-xmin-radius;
if (vx[i]<0 && d<min) {
horizontalRebound = true;
ballRebounded = i;
min=d;
}
d = xmax-radius-x[i];
if (vx[i]>0 && d<min) {
horizontalRebound = true;
ballRebounded = i;
min=d;
}
}
return min;
Notice how the code uses the global variables horizontalRebound and ballRebounded to
keep the type of rebound and the index of the disk which rebounded against a wall.
Throwing a ball (parabolic throw)
page 4 of 9
Easy Java Simulations step-by-step series of examples
These variables are then used by the Action code of the event to correctly invert the
horizontal or vertical velocity of the disk which rebounded. The fact that these global
variables don’t change from the detection of the event to the invocation of the action
code is an important feature of Ejs’ event handler.
The line:
if (Math.abs(vy[ballRebounded])<TOLERANCE) vy[ballRebounded] = 0.0;
in the Action code of this event is required, together with a clever definition of the acc
custom method below, to avoid the terrible “Zeno effect” that would happen if the
restitution coefficient was smaller than one and, eventually, disks rebounded with less
and less energy against the lower wall. The Zeno effect could otherwise freeze (hang)
our simulation.
Similarly, the code for the Zero Condition of the second event (which deals with the
collision among disks) is given by:
double min = TOLERANCE;
for (int i=0; i<n; i++) {
for (int j=i+1; j<n; j++) {
double deltax = x[j]-x[i], deltay = y[j]-y[i];
double allowed = (diameter[i]+diameter[j])/2;
double distance = deltax*deltax+deltay*deltay-allowed*allowed;
if (distance<min) {
double deltaVx = vx[j]-vx[i], deltaVy = vy[j]-vy[i];
if (deltax*deltaVx+deltay*deltaVy<0) {
collision1 = i; collision2 = j; min = distance;
}
}
}
}
return min;
Throwing a ball (parabolic throw)
page 5 of 9
Easy Java Simulations step-by-step series of examples
And the corresponding Action code, which computes the velocities after the collision
takes place, is given by:
double deltax = x[collision2]-x[collision1];
double deltay = y[collision2]-y[collision1];
double distance = Math.sqrt(deltax*deltax+deltay*deltay);
double rx=deltax/distance, ry=deltay/distance; // Unit vector joining centers
double sx=-ry, sy=rx; // Vector ortogonal to the previous one
double vr1=(vx[collision1]*rx+vy[collision1]*ry),
vs1=(vx[collision1]*sx+vy[collision1]*sy); // Projections for disk 1
double vr2=(vx[collision2]*rx+vy[collision2]*ry),
vs2=(vx[collision2]*sx+vy[collision2]*sy); // Projections for disk 2
double vr1d=( 2*mass[collision2]*vr2 + (mass[collision1]mass[collision2])*vr1 )/(mass[collision1]+mass[collision2]); // New velocity
for disk 1
double vr2d=( 2*mass[collision1]*vr1 + (mass[collision2]mass[collision1])*vr2 )/(mass[collision1]+mass[collision2]); // New velocity
for disk 2
// Undo the projections
vx[collision1]=vr1d*rx+vs1*sx; vy[collision1]=vr1d*ry+vs1*sy;
vx[collision2]=vr2d*rx+vs2*sx; vy[collision2]=vr2d*ry+vs2*sy;
No Zeno-effect can take place fro this second event (at least under normal
circumstances) in our problem.
Constraints
A single page of constraints computes the total mechanical energy of the system:
Throwing a ball (parabolic throw)
page 6 of 9
Easy Java Simulations step-by-step series of examples
Custom code
A page of custom code is used to define the acc method.
As mentioned above, the line:
if (h[i]-ymin-0.5*diameter[i]<TOLERANCE && vh[i]==0) return 0;
// on the floor
is needed to avoid the Zeno effect.
View
The view starts with the compound element based on a drawing panel, with the default
particle replaced by a ParticleSet. The rest of the interface is rather standard.
The main properties that need to be modified are shown in the colored fields of the
property panels below:
Throwing a ball (parabolic throw)
page 7 of 9
Easy Java Simulations step-by-step series of examples
Note: The _resetSolvers predefined method is required only by advanced ODE solvers
to correctly reset their internal states when the user interacts with the interface to change
the state of the ODE. Although the solver method selected for the example does not
need this (thus calling the method has no real effect), we call this method on the On
Drag property of the particle set in prevision the reader decides to select a different
solver in the future.
Throwing a ball (parabolic throw)
page 8 of 9
Easy Java Simulations step-by-step series of examples
Running the simulation
A sample execution with a value of 0.6 for the restitution coefficient and gravity turned
on leads eventually to the following state:
Author
Francisco Esquembre
Universidad de Murcia, Spain
July 2007
Throwing a ball (parabolic throw)
page 9 of 9
Download