# Total Conservation Problem![SOLVED]

This topic is 4426 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello, This may seem dumb to some of you physics scholars out there, but I'm trying to create totally elastic collisions between spheres. In other words, no energy is lost or gained. I thought I had it, until I added up the forces to make sure it was being conserved. It turns out, each time a collision occurs, the total force is changed, but it seems to gain or lose energy from collisions randomly, and the total energy seems to stay within a certain range. I'm trying to figure out where in the world I made my mistake. Here is my source, but I don't see any mistakes in it, and I've been over it a million times. What is wrong!?
void DAC()
{
double gammav=0,gammaxy=0,dgamma=0, a=0,alpha=0,dist=0,mindist=0,dr=0,dvx2=0,pi2;
double x,y,x2,y2,vx1,vy1,vx2,vy2,r1,r2,m1,m2;
int l,l1;
for(l=0;l<B;l++)
{
for(l1=0;l1<B;l1++)
{
if(l!=l1)
{
x=ast[l].x;y=ast[l].y;vx1=ast[l].vx;vy1=ast[l].vy;m1=ast[l].m;r1=ast[l].r;
x2=ast[l1].x;y2=ast[l1].y;vx2=ast[l1].vx;vy2=ast[l1].vy;m2=ast[l1].m;r2=ast[l1].r;
pi2=2*acos(-1.0E0);
dist=sqrt(pow(x2-x,2)+pow(y2-y,2));
mindist=r1+r2;
gammav=atan2(-(vy2-vy1),-(vx2-vx1));
gammaxy=atan2(y2-y,x2-x);
dgamma=gammaxy-gammav;
if (dgamma>pi2)dgamma=dgamma-pi2;
else if (dgamma<-pi2)dgamma=dgamma+pi2;
dr=dist*sin(dgamma)/(r1+r2);
if((fabs(dgamma)>pi2/4 && fabs(dgamma)<0.75*pi2) || fabs(dr)>1 )
{
}
else
{
alpha=asin(dr);
a=tan( gammav +alpha);
dvx2=-2*((vx2-vx1) +a*(vy2-vy1)) /((1+a*a)*(1+(m2/m1)));
if(dist<mindist)
{
ast[l1].vx=vx2+dvx2;
ast[l1].vy=vy2+a*dvx2;
ast[l].vx=vx1-(m2/m1)*dvx2;
ast[l].vy=vy1-a*(m2/m1)*dvx2;
}
}
}
}
}

}


[Edited by - levjs on January 5, 2006 3:55:55 PM]

##### Share on other sites
I think your best bet would be to avoid angles at all. In this situation, you want to try to conserve momentum between collisions. That means (m1v1+m2v2)i = (m1v1+m2v2)f

An easy way to handle this is considering that objects of similiar mass tend to transfer momentum during a collision. That means that mv of object 1 before a collision will equal mv of object 2 after the collision.

Hope this helps

On a side note,
pi2=2*acos(-1.0E0);
is kind of wasteful. You should use
pi2=2*M_PI;

##### Share on other sites
*EDIT: void, sorry, wrong topic

##### Share on other sites
Original post by erissian
I think your best bet would be to avoid angles at all. In this situation, you want to try to conserve momentum between collisions. That means (m1v1+m2v2)i = (m1v1+m2v2)f

An easy way to handle this is considering that objects of similiar mass tend to transfer momentum during a collision. That means that mv of object 1 before a collision will equal mv of object 2 after the collision.

Hope this helps

Ok, I understand that, but how would you use that formula to get the velocity(with direction and speed) after a collision?
And also, I've been working on this for soooo long on and off, and I'd like to figure out if something is wrong with my code or something else is wrong!
It is true, that when you add the total velocities together(x+x and y+y, of all the balls, and then add those together, that number should never change, right??????)
Thanks
Levi

##### Share on other sites
Quote:
 Ok, I understand that, but how would you use that formula to get the velocity(with direction and speed) after a collision?

The equations for the velocities after collision can be easily found through combination of preservation of linear momentum and preservation of kinetic energy.
If you leave out any angular effects (kinetic energy = mu^2/2), the equations for the elastic collision of two objects, become:
v1f = v1i*(m1-m2)/(m1+m2) + v2i*2*m2/(m1+m2)
v2f = v1i*2*m1/(m1+m2) + v2i*(m2-m1)/(m1+m2)

(The 'i' and 'f' denote 'initial' and 'final')
Remember also, that these are vector equations. Therefore, a snapshot of each of these formulas must hold for each component of the velocity vectors. This means that you'll have to calculate these 2 or 3 times (depending on your simulation beaing 2d or 3d) for each component of the bodies' velocities.

Quote:
 It is true, that when you add the total velocities together(x+x and y+y, of all the balls, and then add those together, that number should never change, right??????)

I'm not quite sure I understand what you mean. You don't discriminate anywhere between initial and final velocities.

edit start:
Do you mean the preservation of kinetic energy in elastic collision?
This is quite obvious, Sum[k=1,...,#bodies][mk*(vki)2]==Sum[k=1,...,#bodies][mk*(vkf)2]
:end edit

However, it holds true, that the relative velocities between the objects remain constant in magnitude but completely change direction. (if that's what you meant)
Thus: vi1-vi2 = -(vf1-vf2)

##### Share on other sites
Thanks for the equations, I'll give them a try. : )

What I mean is, say that I have two spheres in two dimensions. If I add the x components of the velocities of each spere to the x component of the other, and the same for the y. If I then add the numbers I got, I would come up with one number of the total force, right? And this number should not change no matter how many times the spheres collided? Is that any clearer?

My collisions as is look like they should. The spheres bounce off eachother correctly, with(it looks like) the right speed according to mass. The only thing I'm not getting is why the number I described above changes everytime any spheres collide.
Thanks alot.
Levi

##### Share on other sites
I get the question, but I don't see why something like that should hold, unless you impose such a constraint yourself. I guess I'll have to sleep on it...

##### Share on other sites
I guess because if there is a conservation of energy, then it would hold because the total energy should be the same?? I'm going to die if I find out that I've had it right, and this is just some stupid thing I made up!!!!
Here's the code that adds up the velocities. The total(number that changes is xtotal+ytotal).
xtotal=0.0;ytotal=0.0;for(int l=0;l<B;l++){	xtotal+=ast[l].vx;	ytotal+=ast[l].vy;}

So the code in my original post looks fine?? [grin]
Levi

##### Share on other sites
You could break this down componentwise, where you have two equations,
I. px,i = px,f
II. py,i = py,f
(where px = m*vx)

This should be fine for what you need. It could work something like this:
float vx1,vx2,m1,m2;float px1,px2;/* Collision! *//* Calculate momentum */px1 = vx1 * m1;px2 = vx2 * m2;/* Exchange momentum */float a = px1;px1 = px2;px2 = a;/* Find new velocities */vx1 = px1 / m1;vx2 = px2 / m2;

Where adding new dimensions is simplify repeating this process for each dimension.

##### Share on other sites
The sum of velocities in all dimensions present should be constant if the masses of the objects are identical and all collisions are head on.

A non head on collision transferes accelerative force from one dimension to another in a non-linear manner.

The accelerative force propergation is dependant on the masses involved.

##### Share on other sites
Quote:
 The sum of velocities in all dimensions present should be constant if the masses of the objects are identical and all collisions are head on.

My mases are not the same, and the collisions are not head on.

And the force is transffered between the balls. The only problem I'm having, is that making sure no force is lost or gained. If you want a look, download it from http://www.backyardproductions.org/downloads/collision.exe The three numbers are, from left to right, the xtotal force, the ytotal force, and the total force(the sum of the previous two numbers) where the x and y total force is calculated using
double xtotal=0,ytotal=0;for(int l=0;l<level[whichlevel].nrocks;l++){	if(ast[l].xdir>0)xtotal+=ast[l].xdir;	if(ast[l].xdir<0)xtotal-=ast[l].xdir;	if(ast[l].ydir>0)ytotal+=ast[l].ydir;	if(ast[l].ydir<0)ytotal-=ast[l].ydir;}

[Edited by - levjs on January 5, 2006 8:32:15 AM]

##### Share on other sites
Here, I dug this out of an ancient project:
/* Collide elastically */void particle::bounce( particle *b ){        /* Rewind to the moment of the collision */        double timelost = ( radius + b->radius                        - this->p.distance(b->p))                        / this->v.distance(b->v);        move(-timelost);        b->move(-timelost);        /* U and V are momentum vectors                       *         * Subscripts i and f are for initial and final state *         * C is the incidence of collision                    */        Vector Ui = v*mass;        Vector Vi = b->v * b->mass;        Vector C  = b->p - p;        Vector Uf = Ui - Ui.proj(C) + Vi.proj(-C);        Vector Vf = Vi - Vi.proj(C) + Ui.proj(-C);        /* Find new velocities from momenta */        v = Uf/mass;        b->v = Vf/b->mass;        /* Replay corrected motion */        move(timelost);        b->move(timelost);}Vector Vector::proj(Vector a){       return a * this->dot(a) / a.length_squared();}

##### Share on other sites
Momentum is mass times velocity. Momentum is a conserved quantity. Therefore if you add up the masses of the spheres multiplied by their x velocities, this quantity, the momentum in the x axis, should be conserved. The same is true of the momentum in the y axis.

Energy is different than momentum. Kinetic energy is proportional to mass times velocity squared. Since there is no potential energy in your system, this quantity should also be conserved.

In practice there will likely be drift away from perfect conservation due to approximation errors. More advanced techniques (not generally used in video games) are used to compensate for this in physical simulations. In video games, the physical simulation is usually limited anyway, with energy being constantly drained from the system by friction, fluid resistance, inelastic collisions, implicit integration, and possibly ad hoc methods to ensure stability.

##### Share on other sites
Hi,
I think that my program is correct after all. Here is how I tested it. I set up a perfectly head on collision, with two spheres of equal mass, one of which is still at the beggining. When the two balls hit, the entire momentum of the first ball was transfered to the second, and the first stopped entirely, while the second had the same speed the first had. : )
Levi

##### Share on other sites
Great!

So then, a good series of tests to follow up with would be:

1. That same test with unequal masses
2. Same masses but different velocities
3. Two equal masses, one still, the other moving in a glancing collision
4. Two masses, one moving up, andother moving left

If it behaves predictably in these situations, then you should be all set!

##### Share on other sites
Ooook, I think I've finally got it. Thanks erissian for those test. Everything looks fine. I got around to messing with it, and using
xtotal=0.0;ytotal=0.0;	for(loop=0;loop<B;loop++)	{		xtotal+=0.5*(pow(ast[loop].vx,2)*ast[loop].m);		ytotal+=0.5*(pow(ast[loop].vy,2)*ast[loop].m);			}

and adding the two together to get the total kinetic energy, the total energy remains totally constant!! I am so happy. : ) Before, I wasnot taking the mass of the spheres into account when I was measuring there energy, which is stupid, because obviously, a sphere of larger mass is going to have more energy than one of smaller mass. : )
Thank you everyone who helped!
Levi