programming a pipe
in
Programming Questions
•
1 year ago
Hi, I once made a sketch of bouncing balls. Now I want to simulate a pipe in wich the fluid is hunk of little balls. I can make the sketch using fluid mechanics knodledge cause I know how balls should move, but I prefer let the balls move free adding forces and letting them bounce between them and with walls. I´ve tried to add viscosity so particles closest to walls should move slower.
By now I,ve made only a vertical pipe in wich particles that reach the botton returns upside. It should not be horizontal movement, but because of the parts of the program that separate balls between them or from the walls, there are little horizontal movement that end causing a lot of bouncing that shouldnt be. I dont want to force vertical movement because I want the particles moving free, because later I want to change the pipes direction.
Programming movement and physics brings always instability problems. I don´t know if Im facing this problem correctly. I know is hard to simulate it accurately.
I would like to know if Im making mistakes or not using the best way, or if there are other examples online of the same idea.
This is the code:
class ball{
PVector x;
PVector v;
color c;
int r=3;
float f = 0.1;
float g = 0.1;
float force;
ball(int x0, int y0){
x=new PVector(x0,y0);
v=new PVector(0,0);
PVector x;
PVector v;
color c;
int r=3;
float f = 0.1;
float g = 0.1;
float force;
ball(int x0, int y0){
x=new PVector(x0,y0);
v=new PVector(0,0);
}
void update(){
force = 0.05 * ( g/visc );
v.y = v.y + force ;
x.add(v);
v.mult(1-f);
}
void render(){
if (abs(x.x-middle)<0.4 * pipediam){
set(int(x.x),int(x.y),color(255));;
}
}
}
void update(){
force = 0.05 * ( g/visc );
v.y = v.y + force ;
x.add(v);
v.mult(1-f);
}
void render(){
if (abs(x.x-middle)<0.4 * pipediam){
set(int(x.x),int(x.y),color(255));;
}
}
}
int width=800;
int height=600;
float g=2;
ArrayList balls= new ArrayList();
float k=1;//factor to increment distance between balls
float c= 4;//maximun penetrance in walls
float vlim=10;//maximum speed
float population=1000;//population limit
float suck = 10;// distance of influence
float leftborder;
float rightborder;
float visc;
float limitlayer = 10;
float pipediam = 100;
float middle;
void setup(){
noStroke();
frameRate(48);
size(800,600);
leftborder = width/2-pipediam/2;
rightborder = width/2 + pipediam/2;
middle =(leftborder + rightborder)/2;
for (int i = 0; i < population; i++){
balls.add(new ball(int(random(leftborder,rightborder)), int(random(0,height))));
}
}
noStroke();
frameRate(48);
size(800,600);
leftborder = width/2-pipediam/2;
rightborder = width/2 + pipediam/2;
middle =(leftborder + rightborder)/2;
for (int i = 0; i < population; i++){
balls.add(new ball(int(random(leftborder,rightborder)), int(random(0,height))));
}
}
void draw(){
fill (0,100);
rect(0,0,width, height);
for(int i=0;i<balls.size();i++){
ball b = (ball) balls.get(i);
// speed limit
if (b.v.y>vlim){b.v.y=vlim;}
// bounce against walls
if (b.x.x<b.r){b.v.x=abs(b.v.x);}
if (b.x.x>width-b.r){b.v.x=-abs(b.v.x);}
if (b.x.y>height-b.r){b.x.y = 0;}
//separate from walls
if(b.x.x>rightborder-b.r+c){b.x.x-=5;}
if(b.x.x<leftborder + b.r-c){b.x.x+=5;}
if(b.x.y>height-b.r+c){b.x.y-=5;}
//bounce between them
//viscosity
visc = 0.3 * (sq(15*(b.x.x - middle))/sq(15*pipediam/2));
//b.v.y = b.v.y - visc;
for(int j=i+1;j<balls.size();j++){
ball b2 = (ball) balls.get(j);
//separate embedded balls
PVector dx=PVector.sub(b2.x,b.x);
if (dx.mag()<(b.r+b2.r)*k){
float inc1=b.r-dx.mag()/2;
float inc2=b2.r-dx.mag()/2;
dx.normalize();
dx.mult(inc1);
PVector dx1=dx;
dx1.mult(inc2/inc1);
if((b2.x.x+dx.x<width-b2.r)&&(b2.x.x+dx.x>b2.r)&&(b2.x.y+dx.y<height-b2.r)&&(b.x.x+dx1.x<width-b.r)&&(b.x.x+dx1.x>b.r)&&(b.x.y+dx1.y<height-b.r)){
b2.x.add(dx);
dx.mult(inc2/inc1);
b.x.sub(dx);
}
//bounce between them
PVector acum=b.v;
b.v=b2.v;
b2.v=acum;
}
//repulsion between balls
if (dx.mag() < suck){
dx.normalize();
dx.mult(0.1);
b2.v.add(dx);
dx.mult(-1);
b.v.add(dx);
}
}
//limit layer
if ((b.x.x - leftborder < limitlayer) || (rightborder - b.x.x <limitlayer)){
b.v.x = 0;
b.v.y = 0;
}
b.update();
// corrections
if (b.v.y < 0){b.v.y = 0;}
b.render();
}
fill (0,100);
rect(0,0,width, height);
for(int i=0;i<balls.size();i++){
ball b = (ball) balls.get(i);
// speed limit
if (b.v.y>vlim){b.v.y=vlim;}
// bounce against walls
if (b.x.x<b.r){b.v.x=abs(b.v.x);}
if (b.x.x>width-b.r){b.v.x=-abs(b.v.x);}
if (b.x.y>height-b.r){b.x.y = 0;}
//separate from walls
if(b.x.x>rightborder-b.r+c){b.x.x-=5;}
if(b.x.x<leftborder + b.r-c){b.x.x+=5;}
if(b.x.y>height-b.r+c){b.x.y-=5;}
//bounce between them
//viscosity
visc = 0.3 * (sq(15*(b.x.x - middle))/sq(15*pipediam/2));
//b.v.y = b.v.y - visc;
for(int j=i+1;j<balls.size();j++){
ball b2 = (ball) balls.get(j);
//separate embedded balls
PVector dx=PVector.sub(b2.x,b.x);
if (dx.mag()<(b.r+b2.r)*k){
float inc1=b.r-dx.mag()/2;
float inc2=b2.r-dx.mag()/2;
dx.normalize();
dx.mult(inc1);
PVector dx1=dx;
dx1.mult(inc2/inc1);
if((b2.x.x+dx.x<width-b2.r)&&(b2.x.x+dx.x>b2.r)&&(b2.x.y+dx.y<height-b2.r)&&(b.x.x+dx1.x<width-b.r)&&(b.x.x+dx1.x>b.r)&&(b.x.y+dx1.y<height-b.r)){
b2.x.add(dx);
dx.mult(inc2/inc1);
b.x.sub(dx);
}
//bounce between them
PVector acum=b.v;
b.v=b2.v;
b2.v=acum;
}
//repulsion between balls
if (dx.mag() < suck){
dx.normalize();
dx.mult(0.1);
b2.v.add(dx);
dx.mult(-1);
b.v.add(dx);
}
}
//limit layer
if ((b.x.x - leftborder < limitlayer) || (rightborder - b.x.x <limitlayer)){
b.v.x = 0;
b.v.y = 0;
}
b.update();
// corrections
if (b.v.y < 0){b.v.y = 0;}
b.render();
}
}
1