0

I program a solar system. ATM all the planet interact with the sun(Gravitation). Now I also want that the every planets interacts with all the other planets ( How it is in reality). I thought I could do that with a double for-loop. I tried it out but it didn't work. Could you help me? I think the mistake has something to do that with sun the planets had a fix point. But now its just always planet to planet. But I dont really know... Here is my code:

    from vpython import *

    #Konstanten zum rechnen
    s_rad0 = 6.9e8
    s_rad1 = 30 * s_rad0
    e_rad = s_rad1 * 0.9
    m_rad = e_rad * 0.4
    ae = 200 * s_rad0   #1 Astr. Einheit bezieht sich auf Ent. Sonne-Erde
    ae2 = 200 * s_rad0  #bezieht sich auf Ent. Sonne-Mond
    g = 6.6725e-11 

    framerate = 100




  #array liste von Planeten
planets = []


class Sphere(object):
    def __init__(self, pos, radius, make_trail):
        self.pos = pos
        self.radius = radius
        self.make_trail = make_trail



class planet(Sphere):
    def __init__(self, pos, radius, make_trail, mass, velocity):
        super().__init__(pos, radius, make_trail)
        self.mass = mass
        self.velocity = velocity
        planetSphere = sphere (pos = self.pos, radius = self.radius, make_trail = self.make_trail, mass = self.mass, velocity = self.velocity)


sun = planet(pos=vec(0,0,0),radius=s_rad1*1.5, make_trail=True, mass=2e30, velocity=vec(0,0,0))
mercury = planet(pos=vec(ae/3,0,0), radius=s_rad1/1.5, make_trail=True, mass=3.25e23, velocity=vec(0,0,-47000))
venus = planet(pos=vec(ae/1.6,0,0), radius=s_rad1/1.3, make_trail=True, mass=4.9e24, velocity=vec(0,0,-35000))
earth = planet(pos=vec(ae,0,0), radius=e_rad, mass=5.9e24, make_trail=True, velocity=vec(0,0,-25000))
mars =  planet(pos=vec(ae*1.52,0,0), radius=s_rad1/1.8, make_trail=True, mass=6.4e23, velocity=vec(0,0,-24000))
jupiter = planet(pos=vec(ae*5.18,0,0), radius=s_rad1/1.2, make_trail=True, mass=10e27, velocity=vec(0,0,-9678))
saturn = planet(pos=vec(ae*9.5,0,0), radius=s_rad1/1.4, make_trail=True, mass=5.7e26, velocity=vec(0,0,-7678))
uranus = planet(pos=vec(ae*19.13,0,0), radius=s_rad1/1.7, make_trail=True, mass=8.7e25, velocity=vec(0,0,-6772))
neptun = planet(pos=vec(ae*30,0,0), radius=s_rad1/1.7, make_trail=True, mass=1.02e26, velocity=vec(0,0,-5344))
pluto = planet(pos=vec(ae*39.37,0,0), radius=s_rad1/2.4, make_trail=True, mass=1.3e22, velocity=vec(0,0,-4740))

planets.extend((mercury,venus,earth,mars,jupiter,saturn,uranus,neptun,pluto))

dt = 10000
time = 0.1


    while (True):

        rate(framerate) 

        #for-Schlaufe für Berechnung jedes einzelnen Planeten

        g_forceS = vec(0,0,0)

        for planet in planets:
            g_force = g * sun.mass * planet.mass * (sun.pos - planet.pos).norm()  / (sun.pos - planet.pos).mag2


             for planet in planets:
                 g_force = g * planet.mass * planet.mass * (planet.pos - planet.pos).norm()  / (planet.pos - planet.pos).mag2




            #Sonne
            g_forceS -= g_force




            #print(sun.pos)

            #Änderung des Velocity Vektor wird zum alten addiert
            #Da a=F/m // V = a*t(a*dt) 2 Geschw. vektoriell durch F/m ausgedrückt.
            planet.velocity = planet.velocity + ( g_force / planet.mass) * dt #Richtungsänderung

            #Diese Änderung wird zur alten Position addiert = neue Position
            planet.pos += planet.velocity * dt 



        sun.velocity = sun.velocity + ( g_forceS / sun.mass) * dt #Richtungsänderung
        sun.pos += sun.velocity * dt 
Ragnarök
  • 138
  • 10
  • this [Is it possible to make realistic n-body solar system simulation in matter of size and mass?](https://stackoverflow.com/a/28020934/2521214) might interest you. – Spektre Sep 07 '18 at 08:11

2 Answers2

2

The indentation in your question is all messed up, but as it stands it looks like you're doing the loop wrong.

for planet in planets:
    g_force = g * sun.mass * planet.mass * (sun.pos - planet.pos).norm()  / (sun.pos - planet.pos).mag2

    for planet in planets:
        g_force = g * planet.mass * planet.mass * (planet.pos - planet.pos).norm()  / (planet.pos - planet.pos).mag2

    g_forceS -= g_force

There are several mistakes here. You should go through your own code step by step to see what. Adding print statements will help understand. Two things to observe though. One: the variable name in the inner loop is the same as the variable in the outer loop. The outer loop sets planet each time (i.e. 9 times) but then the inner loop overwrites it. You need to maintain the concept of one body and the other body in separate variables. Two: you only update g_forceS once, after the inner loop runs, so this just updates using the most recent value of planet instead of updating 9 times.

Rewrite your code to have this structure:

for body in bodies:    # Update each of the bodies in turn.
    force = np.zeros(3)    # We need to work out the force on the body.
    for other_body in bodies:    # The force is the result of all the other bodies.
        if other_body is not body:    # The main body doesn't count as another body.
            force += gravity(body, other_body)
    body.update(force)    # Update the body according to the force on it.
Denziloe
  • 7,473
  • 3
  • 24
  • 34
  • and why np.zeros(3) ? – Ragnarök Sep 06 '18 at 21:41
  • Because force is a vector in 3-dimensional space. It starts off at **0** and then you add more 3-vectors to it. Though you could use a different number of dimensions, e.g. 2 if you want to place all of the objects in a plane. – Denziloe Sep 06 '18 at 21:57
  • 2
    @Denziloe almost complete so +1 but the `body.update(force)` should be in separate loop after the initial `O(n^2)` force computatin. That also require that the force is a member of planet !!! otherwise the update will screw computation of the not yet processed planets. This is common mistake causing the simulation will shift the planets positions away in some direction each iteration so the solar system will float away ... and also it corrupts the shape and periods of the orbits ... – Spektre Sep 07 '18 at 08:03
  • @Spektre Yes I was just trying to code properly what was in the original question, but as you say it will probably have physical problems because some updated positions are used to calculate forces. This could also be fixed by giving each body a "next position" attribute and then only updating all of the true positions at the very end. – Denziloe Sep 07 '18 at 09:09
  • @Denziloe This approach has also another drawback but it can be significantly diminished by a small change in computation see [Edit3: Improving Newton d'Lambert integration precision even more](https://stackoverflow.com/a/28020934/2521214) – Spektre Sep 07 '18 at 09:54
0

I have now this solution and its working

dt = 10000
time = 0.1

while (True):

    rate(framerate) 



    for planet in planets:
        g_force = vec(0,0,0)
        for planet1 in planets:
            if planet != planet1:
                g_force += g * planet1.mass * planet.mass * (planet1.pos - planet.pos).norm()  / (planet1.pos - planet.pos).mag2
        #print((sun.pos - planet.pos).mag2)






        #Änderung des Velocity Vektor wird zum alten addiert
        #Da a=F/m // V = a*t(a*dt) 2 Geschw. vektoriell durch F/m ausgedrückt.
        planet.velocity = planet.velocity + ( (g_force) / planet.mass) * dt 

        #Diese Änderung wird zur alten Position addiert = neue Position
        planet.pos += planet.velocity * dt 
Ragnarök
  • 138
  • 10