// Program for velocity and density distribution

// inelastic collisions - Arshad Kudrolli

//

// Event driven simulation of particles in one dimension colliding

// inelastically. The particle-particle collisions are inelastic,

// particle-left wall is elastic, and particle right wall imparts

// random velocity.

//

// The program resets if a numerical error is detected.

//

// Some of the program structure is from a program written by

// Kelly Jo Brown found in www.gamelan.com.

import java.awt.*;

import java.applet.*;

import java.lang.*;

public class inelastic extends Applet implements Runnable{

Graphics img;

Image screen, ball;

double x[]; // x position of particles

double y[]; // y position

double v[]; // velocity of particles

double vold[];

double t[]; // time between events

double terr = 1.0e-15; // underestimate of time to prevent crossings

int unit=1;

int zero=0;

int two =2;

int offset = 33; // size of the particle gif 23

double max_v = 10.0; //max value of velocity at right wall.

double time = (double)unit; //time intervel after which positions are evaluated.

int pause=50; // wait time between frames

int caught=0,flag;

int num_par=5; // number of particles

int L = 520 - num_par * offset;

int px,py,tempx,tempy,slide=5,slide2=num_par*10;

int num_c =0; // number of collisions

double r = 1.0 - (double)slide/100.0;

double e= (1.0 - r)/2.0;

// e between 0 and 0.5

Thread kicker = null;

MediaTracker tracker;

public void run()

{

int i;

double rad,delta_angle,radius;

Thread.currentThread().setPriority(Thread.MIN_PRIORITY);

while(kicker != null)

{

// calculate time to the next collision - left wall

if ( v[0] > 1e-20 || v[0] < -1e-20) {

t[0] = - x[0]/v[0];

}

else {

t[0] = 1e10;

}

// interparticle collision times

for (i=1; i < num_par; i++) {

if ( x[i] - x[i-1] < (double)zero ) {

flag = 1;

}

t[i] = - (x[i] - x[i-1])/(v[i] - v[i-1]);

}

if ( x[0]< (double)zero ) {

flag = 1;

}

if ( flag == 1) {

init();

}

// collision with right wall

if ( v[num_par-1] > 1e-20 || v[num_par-1] < -1e-20) {

t[num_par] = ((double)L - x[num_par-1])/v[num_par-1];

}

else {

t[num_par] = 1e10;

}

// check which event will occur first

double tmin =1.0e30;

int event = -1;

for (i=0; i< num_par+1; i++) {

if (t[i] > (double)zero && t[i] < tmin ) {

tmin = t[i];

event = i;

}

// System.out.print(x[i]+" "); //check

}

// System.out.println(event); //check

if ( tmin > time) {

// calculate the position after time.

for(i=0;i<num_par;i++)

{

x[i] = x[i] + v[i] * time;

y[i]= 200;

vold[i] = v[i];

}

}

else {

// Side wall conditions - give random kick at right wall.

if ( event == num_par ) {

// v[num_par-1] = - Math.round(Math.random()*max_v - 1.0);

v[num_par-1] = - (Math.random()*max_v);

}

// Side wall condition - elastic collision.

else if ( event == 0 ) {

v[0] = -v[0];

}

// Interparticle collisions.

else {

v[event] = (e * vold[event] + ((double)unit-e) * vold[event-1]);

v[event-1] = (((double)unit-e)*vold[event] + e * vold[event-1]);

num_c++;

}

// Calculate the positions just after collision

for(i=0;i<num_par;i++)

{

// x[i] = x[i] + vold[i] * (tmin - terr);

x[i] = x[i] + vold[i] * (tmin -terr) + 1e-15*(double)(i+1);

y[i]= 200;

vold[i] = v[i];

}

if (x[num_par -1] > (double)L)

{

if ( num_par > 1 )

{

if ( x[num_par-2] < ((double)L - 1e-15))

{

x[num_par -1] = (double)L - 1e-15;

}

else {

x[num_par -1] = (double)L - ((double)L - x[num_par-

2])/(double)two;

}

}

else {

x[num_par -1] = (double)L - 1e-15;

}

v[num_par-1] = - Math.random()* max_v;

vold[num_par-1] = v[num_par-1];

}

}

repaint();

try {Thread.sleep(pause);} catch (InterruptedException e){};

}

}

public void init()

{

int i;

flag =0;

num_c=0;

x=new double[20];

y=new double[20];

v=new double[20];

vold = new double[20];

t = new double[20];

for(i=0;i<num_par;i++)

{

x[i]=( (double)(i+1) * (double)L / (double)(num_par+unit));

v[i]= ((double)unit/(double)two - Math.random())*max_v;

y[i]= 200;

}

// Load images

ball=getImage(getDocumentBase(),"ball.gif");

// Add tracker to see if images loaded

tracker = new MediaTracker(this);

tracker.addImage(ball,0);

}

public void start()

{

if(kicker == null)

{

kicker = new Thread(this);

kicker.start();

}

}

public void stop()

{

kicker = null;

}

public boolean mouseDown(Event evt, int x, int y)

{

if(y > 101)

{

if(kicker==null)

start();

else

kicker=null;

}

else if ( y > 40 && y < 70 && x < 90 && x > 40 )

{

// num_c =0;

init();

}

return true;

}

public boolean mouseDrag(Event evt, int x, int y)

{

// Clicked on slidebar, slide it

if(x>450 && x<500 && y>0 && y<101)

{

slide=y;

e=(double)(slide/200.0);

// num_c =0;

}

else if (x > 350 && x < 380 && y >0 && y < 101) {

slide2 = y;

num_par = (int)(110 - y)/10;

num_c =0;

L = 520 - offset * num_par;

init();

}

return true;

}

public final synchronized void update(Graphics g)

{

String str;

int i;

if(screen == null)

{

screen = createImage(520,300);

img = screen.getGraphics();

}

// Fill black background

img.setColor(Color.black);

img.fillRect(0,100,520,199);

// Fill white background

img.setColor(Color.white);

img.fillRect(0,0,520,99);

// Fill blue top bar

img.setColor(Color.blue);

img.fillRect(0,0,300,10);

// Fill bar for r

img.setColor(Color.red);

img.fillRect(450,0,30,100);

img.fillRect(40,40,50,30);

img.setColor(Color.lightGray);

img.fillRect(350,0,30,100);

img.setColor(Color.black);

img.drawRect(450,0,30,100);

img.drawRect(350,0,30,100);

img.drawRect(40,40,50,30);

if(tracker.statusID(0,true)!=MediaTracker.COMPLETE)

{

img.drawString("Please Wait Loading Graphics",20,160);

}

else

{

// print the inelastic value to screen

r = 1.0 - e * 2.0 ;

img.drawString("r = "+r,399,49);

img.drawString("N = "+num_par,299,49);

img.drawString("Max = 1",400,10);

img.drawString("Min = 0",400,90);

img.setColor(Color.white);

img.drawString("Number of Collisions = "+num_c,149,149);

img.drawString("v_0 = "+v[0],20,279);

img.drawString("v_N = "+v[num_par-1],280,279);

img.drawString("Reset",45,59);

// Print

img.setColor(Color.black);

for(i=0;i<num_par;i++)

{

int xx = (int)x[i] + i*offset;

int yy = (int)y[i];

img.drawImage(ball,xx,yy,this);

}

img.drawRect(448, slide, 34, 2);

img.drawRect(348, slide2, 34, 2);

}

paint(img);


g.drawImage(screen,0,0,null);

}


}