Help - Search - Members - Calendar
Full Version: Problem with my python proggie
GeekNewz Community > Computers > Support & Discussion > Development Area > Programming
psYchotic
So I want to make some kinda gravity simulation with python, and I came up with this thus far (I know it isn't much, but once I get past my problem, I'll make it better somehow):
CODE
t=0
G = 6.6726e-11    #gravitational constant
x = 5     #distance between the two masses
m1 = 30000     #mass1
m2 = 50000     #mass2
dt = 1         #step
v1=0        #speed1
v2=0        #speed2

while t<10000:
print 'distance: ',x
print 'speed1: ',v1
print 'speed2: ',v2,'\n'
Fg = (G*m1*m2)/(x**2)     #gravitational force
a1 = Fg/m1        #Seeing how  F = a * m, a would be F/m. So this is the acceleration of the first mass
a2 = Fg/m2        #Acceleration of the second mass
s1 = 0.5*a1*(dt**2)+v1*dt
s2 = 0.5*a2*(dt**2)+v2*dt
x = x-s1-s2
v1 = (a1*dt)+v1
v2 = (a2*dt)+v2
t = t+dt

So that's it. But there's a problem. It seems to be working just fine at first, but when the masses get past each other (ie: x < 0), they suddenly go away from each other at a great speed. I don't get it, because when x is negative, so will be Fg, so both the accelerations should be negative as well, which means the speeds will decrease and become negative after a while as well. But that doesn't happen...
Any ideas on why and how I could fix it?
Thanks in advance smile.gif

PS: I tried to attach a copy of the file but was told the following: "The requested file upload failed because suitable permissions have not been enabled on the 'uploads' directory. Please contact the board administrator and inform them of this error." cryingsmiley.gif
M$ Agent #2
Seems to be a problem with the logical function of your program. So your saying if you plot 2 objects they should atract then after they "hit" they should bounce back at each other but it glitches out and there is acceleration.... I know im just restating the problem tongue.gif anyway I dont see anything in your math to allow for gravity to decelerate another object (I could be wrong but im hopeing this helps ?) Math was never my good point its not that im bad at it... just hate memorizing formula ! if you could comment your code a little more it would be a huge help (only to people like me who cant read code very well)
Invalid_Entry
"because when x is negative, so will be Fg":
No, sir, no. Fg is Gm1m2 over x SQUARED!! Sqauring a negative ALWAYS yeilds a positive number. There are two ways you could go wtih this, off the top of my head: (Note: I used QUOTE instead of CODE to show color where I changed your original code)

Option 1 - Simply run the simulation until the two objects collide, then stop:
QUOTE
t=0
G = 6.6726e-11    #gravitational constant
x = 5     #distance between the two masses
m1 = 30000     #mass1
m2 = 50000     #mass2
dt = 1         #step
v1=0        #speed1
v2=0        #speed2

while x>0:
print 'distance: ',x
print 'speed1: ',v1
print 'speed2: ',v2,'\n'
Fg = (G*m1*m2)/(x**2)     #gravitational force
a1 = Fg/m1        #Seeing how  F = a * m, a would be F/m. So this is the acceleration of the first mass
a2 = Fg/m2        #Acceleration of the second mass
s1 = 0.5*a1*(dt**2)+v1*dt        #DISPLACEMENT, not LOCATION of m1
s2 = 0.5*a2*(dt**2)+v2*dt        #DISPLACEMENT, not LOCATION of m2
x = x-s1-s2
v1 = (a1*dt)+v1
v2 = (a2*dt)+v2
t = t+dt        #Time incrementation

NOTE: Option 1 will estimate the time of collision as sometime between t-2 and t-1 seconds (after your final time incrementation, that is). This time will be a rough estimate only. For a more precise collision time, you will need to use integration.

Option 2 - Run the simulation using location instead of displacement:
QUOTE
t=0
G = 6.6726e-11    #gravitational constant
x = 5     #distance between the two masses
m1 = 30000     #mass1
m2 = 50000     #mass2
dt = 1         #step
v1=0        #vector1
v2=0        #vector2
L1 = 0        #Initial location of m1 (origin)
L2 = x        #Initial location of m2 (x, which is 5)


while t<10000:
print 'distance: ',x
print 'vector1: ',v1
print 'vector2: ',v2,'\n'
Fg = (G*m1*m2)/(x**2)     #gravitational force
a1 = (Fg/m1)*((L2-L1)/abs(L2-L1))        #a=F/m, but this will ensure you accellerate in the correct direction
a2 = (Fg/m2)*((L1-L2)/abs(L1-L2))        #mass2 will accellerate in the opposite direction as mass1
s1 = 0.5*a1*(dt**2)+v1*dt+L1        #LOCATION of m1 (At t=0, location is at the origin, or 0)
s2 = 0.5*a2*(dt**2)+v2*dt+L2        #LOCATION of m2 (At t=0, location is at 5 right of the origin)
L1 = s1        #The location (L1) will now change to the updated location (s1)
L2 = s2        #The location (L2) will now change to the updated location (s2)

x = L2-L1        #Since each mass has a location, and m2 is initially greater than m1, distance is difference of location
v1 = (a1*dt)+v1        #Because we are now dealing with positive and negative speeds, these are technically 1-dimensional vectors, not speeds
v2 = (a2*dt)+v2        #Because we are now dealing with positive and negative speeds, these are technically 1-dimensional vectors, not speeds
t = t+dt

NOTE: Option 2 will predict that mass1 continues to travel left of mass2 (though constantly decellerating) and visa versa, because you are using 1 second intervals of time. This is HIGHLY inaccurate, and the forces and distances will be very rough estimates with large chunks of relevant data missing. To accurately predict this system of forces, you will have to use integration.

I'm not at all familiar with this programming language, so I have no way to check for typing errors, but as far as the math is concerned, I believe these two ways will work. To test, I converted these to C and wrote a quick console app, with output dumped to a text file.

My apologies if I misinterpreted your intent with this program. I'm not sure if you wanted to simulate the gravity of two ojects affecting each other until collision (Option 1), or if you wanted the objects to be able to pass through one another based on their momentum (Option 2).
psYchotic
Option 2 is basically what I want, and I am aware that ie. -2**2 will still give 4 and not -4. And I tried doing something like that.
I've been looking at the output my program gives, and it seems that when the distance between the two masses approaches zero, the acceleration becomes huge (which is quite normal, coz x/0=infinite and then some).
Anyway, I think I'll have to make some kind of grid system in which the distance between the two masses will always be positive. I'll have to anyway, because I want to make it visual once I get it to work properly. Another thing I'll want to do is to be able to do the very same thing with more than just 2 masses, which means I'll have to calculate the size and direction of each of the forces...
psYchotic
Hmm, I just took a look at what you changed, but basically, the same problem persists cryingsmiley.gif
QUOTE
distance:  -480.179886356
vector1:  0.0631204521883
vector2:  -0.037872271313

distance:  -480.280879079
vector1:  0.0631204521738
vector2:  -0.0378722713043

distance:  -480.381871803
vector1:  0.0631204521593
vector2:  -0.0378722712956

distance:  -480.482864526
vector1:  0.0631204521449
vector2:  -0.0378722712869

As you can see, there's an explosive growth in speed, so somehow the deceleration isn't working, or there's something with python that makes this impossible somehow. Let me try and make that in some other language.
M$ Agent #2
Slingshot effect ? This is realy realy interesting to me becouse I just downloaded Python like a week ago smile.gif Keep up the good work !
Invalid_Entry
The distance never actually becomes 0 during the simulation, so you don't need to worry about infinite force. Just to be safe, however, you could add

if(x==0)
Fg=0

Even adding this, you will still have the same problem you face now. As I said in the NOTE concluding Option 2, you will not be able to accurately simulate this system of forces without using integration. The closer the two objects get to one another, the greater (MUCH greater) the force of attraction becomes. At one point in your simulation, the distance gets very very small, boosting each accelleration up very high. This increases the velocities. The problem is, they move (within one unit of time) so far past 0 distance, that the negative force generated by the "next frame" is far, FAR less than that of the previous frame, because the distance is greater. This means that the sum of negative forces will never add up to cancel the accumulated positive forces.

In other words, using your program, the masses will, every time, either continue off with mass1 going forever right and mass2 going forever left, or visa versa. The only ways (as far as I know) to get them working cleanly are A: to set the two masses to just the right numbers (so that the resulting sums of velocities will negate one another once distance becomes negative) while making sure to avoid division by zero, and B: to use integration to accurately calculate the accelleration at EVERY point in time from start to finish.

Sorry to say, this is what happens when one tries to estimate a constantly changing system using quantized increments of time. A LOT of the important data will be left out, and you may very well end up with "exploding numbers".

Because there are holes in the sumation, the incorrect numbers may result in each of the masses having speeds greater than that of the escape velocity of the system! They never come back toward each other.
Invalid_Entry
Hey, sorry this took me so long to realize... I'm building the physics core for the game we're developing right now, and we deal with gravitation, orbit, and magnetism (all of which directly relate mathematically to your question). I was having a similar problem with non-colliding masses that overlapped and then exploded away from each other. Well, I developed a nice little fix that you can apply directly to your program to simulate a nice spring-like oscillation of your two masses: they will fall, move past one another, slow, and fall again, and again!

Each of your two masses must have a radius. Something at least 1000 m should do nicely. Your force of gravity check is good, but you must also add the following:

CODE

d = sqrt( (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1) );
d2 = ( (r1 + r2) / 2 );

if( d <= d2 )
{
  //#gravitational force of overlapping masses
  Fg = ( (GRAV * _cl[i].mass * _cl[j].mass) / (d2 * d2) );
  Fg = Fg * (d / d2);
}
else
{
  //#original calculation of gravitational force
  Fg = ( (GRAV * _cl[i].mass * _cl[j].mass) / (d * d) );
}

// Here you write your accelleration, movement, etc, as written before


The first Fg (dealing with d2) basically REDUCES the accelleration due to gravity as the objects begin to overlap. This is realistic (in a multi-dimensional sci-fi sort of way) because as the objects overlap, the mass begins to surround the objects, and thus accelleration due to gravity begins to pull them in multiple directions (the opposite pulls cancel, and the total accelleration is reduced). The second Fg (dealing just with d) is the standard force of gravity calculation, and works well when distances are large (aka, the objects do not overlap).

Try this code out yourself and see if it fixes your problem. It fixed mine smile.gif If you'd like, email me (Invalid_Mailbox@hotmail.com) and I'll send you my gravity test program to demonstrate the results graphically in 2D.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2009 Invision Power Services, Inc.