Python Forum
Using an Array in a While Loop
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Using an Array in a While Loop
#11
(Jun-14-2017, 05:29 AM)Skaperen Wrote: yes, you could do it with separate lists, where a common list index is your system body identification. if you already know Fortran (still in common use in physics) then you probably see that as the classic way there.

too bad you don't have the time to do it right. but then, if you did do it right they might not understand it.

Yeah this is for a computational physics class, and it's my first experience with any type of programming. I plan on using python for more than just physics though, so I'll definitely have to learn the right way.
Reply
#12
sure, you can stick to your original setup. However in any case I would add second nested loop for calculating the gravity effect, instead of defining variable for each planet
Reply
#13
What would using a nested loop do here? Maybe I'm missing something obvious, but won't it still need an individual calculation for each planet? Confused
Reply
#14
looking at this part of your code
while True:
    for i in arange(0,9,1):
        rate(1000000)
        t=t+dt
        rsun = posit[0]-posit[i]
         
        if mag(rsun) == 0:
            continue
        Fsun = ((G*mass[0]*mass[i])/(mag(rsun)**2))* norm(rsun) #Calculating the force of gravity from the sun
 
        rmerc = posit[1]-posit[i]
        if mag(rmerc)==0:
            continue
        Fmerc = ((G*mass[1]*mass[i])/(mag(rmerc)**2))* norm(rmerc)
 
        rven = posit[2]-posit[i]
        if mag(rven)==0:
            continue
        Fven = ((G*mass[2]*mass[i])/(mag(rven)**2))* norm(rven)
 
        rear = posit[3]-posit[i]
        if mag(rear)==0:
            continue
        Fear = ((G*mass[3]*mass[i])/(mag(rear)**2))* norm(rear)
 
        rmars = posit[4]-posit[i]
        if mag(rmars)==0:
            continue
        Fmars = ((G*mass[4]*mass[i])/(mag(rmars)**2))* norm(rmars)
 
        rjup = posit[5]-posit[i]
        if mag(rjup)==0:
            continue
        Fjup = ((G*mass[5]*mass[i])/(mag(rjup)**2))* norm(rjup)
 
        rsat = posit[6]-posit[i]
        if mag(rsat)==0:
            continue
        Fsat = ((G*mass[6]*mass[i])/(mag(rsat)**2))* norm(rsat)
 
        ruran = posit[7]-posit[i]
        if mag(ruran)==0:
            continue
        Furan = ((G*mass[7]*mass[i])/(mag(ruran)**2))* norm(ruran)
 
        rnep = posit[8]-posit[i]
        if mag(rnep)==0:
            continue
        Fnep = ((G*mass[8]*mass[i])/(mag(rnep)**2))* norm(rnep)
         
        Fnet = Fsun + Fmerc + Fven + Fear + Fmars + Fjup + Fsat + Furan + Fnep
        acc[i]=Fnet/mass[i]
        vel[i]=vel[i] + acc[i]*dt
        posit[i]=posit[i] + vel[i]*dt
Not 100% sure, but it looks like it will never calculate anything - you loop over all objects so at least one mag will be 0, so it will continue with next i, without even reaching Fnet = Fsun + Fmerc + Fven + Fear + Fmars + Fjup + Fsat + Furan + Fnep and next lines. Not to mention repeating code

I think what you want is

while True:
    for i in arange(0,9,1):
        Fnet = 0
        for j in range(i+1,9,1):
            rate(1000000)
            t=t+dt
            r = posit[j]-posit[i]
            F = ((G*mass[j]*mass[i])/(mag(r)**2))* norm(r) #Calculating the force of gravity from object j over object i
            Fnet += F

        acc[i]=Fnet/mass[i]
        vel[i]=vel[i] + acc[i]*dt
        posit[i]=posit[i] + vel[i]*dt
   
 
        sun.pos=posit[0]
        mercury.pos=posit[1]
        venus.pos=posit[2]
        earth.pos=posit[3]
        mars.pos=posit[4]
        jupiter.pos=posit[5]
        saturn.pos=posit[6]
        uranus.pos=posit[7]
        neptune.pos=posit[8]



this way, when i=0, j will take values from 1 to 8
when i=1, j will take values from 2 to 8, etc.

PS. Not sure where the best place for rate(1000000) is...
Reply
#15
and in the setup with single list

from visual import * # I HATE this

myuniv = display(range=vector(7*10**12,7*10**12,7*10**12))

G = 6.674*10**-11  #Gravitational constant

# define objects
cosmic_objects = (('sun', {'r':9.9*10**10, 'mass':1.989*10**30, 'pos':vector(0,0,0), 'vel':vector(0,0,0), 'acc':vector(0,0,0), 'color':color.yellow}),
           ('mercury', {'r':2.44*10**6, 'mass':3.285*10**23,'pos':vector(5.791*10**10,0,0), 'vel': vector(0,4.87*10**4,0), 'acc':vector(0,0,0), 'color':color.red}),
           ('venus', {'r':6.052*10**6, 'mass':4.867*10**24, 'pos':vector(1.082*10**11,0,0), 'vel':vector(0,3.502*10**4,0), 'acc':vector(0,0,0), 'color':color.yellow}), # I added color here
           ('earth', {'r':6.371*10**6, 'mass':5.972*10**24, 'pos':vector(1.496*10**11,0,0), 'vel':vector(0,2.98*10**4,0), 'acc':vector(0,0,0), 'color':color.green}),
           ('mars', {'r':3.39*10**6, 'mass':6.39*10**23, 'pos':vector(2.279*10**11,0,0), 'vel':vector(0,2.401*10**4,0), 'acc':vector(0,0,0), 'color':color.red}),
           ('jupiter', {'r':6.99*10**7, 'mass':1.898*10**27, 'pos':vector(7.785*10**11,0,0), 'vel':vector(0,1.307*10**4,0), 'acc':vector(0,0,0), 'color':color.blue}),
           ('saturn', {'r':5.823*10**7, 'mass':5.68*10**26, 'pos':vector(1.429*10**12,0,0), 'vel':vector(0,9.69*10**3,0), 'acc':vector(0,0,0), 'color':color.yellow}),
           ('uranus', {'r':2.536*10**7, 'mass':8.68*10**25, 'pos':vector(2.871*10**12,0,0), 'vel':vector(0,6.81*10**3,0), 'acc':vector(0,0,0), 'color':color.cyan}),
           ('neptune', {'r':2.462*10**7, 'mass':1.024*10**26, 'pos':vector(4.498*10**12,0,00), 'vel':vector(0,5.43*10**3,0), 'acc':vector(0,0,0), 'color':color.blue})) # I added color here

objects_sorted_by_mass = sorted(cosmic_objects, key=lambda x:x[1]['mass'], reverse=True) # all objects, sorted by mass descending

#visualize objects
solar_system = {}
for name, obj in cosmic_objects:
    solar_system[name] = sphere(pos=obj['pos'], radius=obj['r'], color=obj['color'], make_trail=True)

t = 0.0
dt = 150000

while True:
    for i, obj_name, obj in enumerate(objects_sorted_by_mass): # loop over all objects, sorted by mass descending
        Fnet = 0
        for obj_name2, obj2 in objects_sorted_by_mass[:i]:
            rate(1000000)
            t=t+dt
            r =  obj2['pos'] - obj['pos'] # distance between obj2 and obj
            Fnet += ((G*obj2['mass']*obj['mass'])/(mag(r)**2))* norm(r) #Calculating the force of gravity from obj2 to the obj
            obj['acc'] = Fnet/obj['mass']
            obj['vel'] += obj['acc']*dt
            obj['pos'] += obj['vel']*dt
        solar_system[obj_name].pos = obj['pos']
Reply
#16
(Jun-14-2017, 08:23 AM)buran Wrote: this way, when i=0, j will take values from 1 to 8
when i=1, j will take values from 2 to 8, etc.

Okay that makes a lot of sense. I just changed Fnet to a vector.

while True:
    for i in arange(0,9,1):
        
        Fnet = vector(0,0,0)
        for j in range(i+1,9,1):
            rate(1000000)
            t=t+dt
            r = posit[j]-posit[i]
            F = ((G*mass[j]*mass[i])/(mag(r)**2))* norm(r) #Calculating the force of gravity from object j over object i
            Fnet += F
 
        acc[i]=Fnet/mass[i]
        vel[i]=vel[i] + acc[i]*dt
        posit[i]=posit[i] + vel[i]*dt
    
  
        sun.pos=posit[0]
        mercury.pos=posit[1]
        venus.pos=posit[2]
        earth.pos=posit[3]
        mars.pos=posit[4]
        jupiter.pos=posit[5]
        saturn.pos=posit[6]
        uranus.pos=posit[7]
        neptune.pos=posit[8]
No more errors, but for some reason the planets just go in a straight line. They're accelerating like there's some kind of force on them , but only in one direction...is this because when i = 0 , j = 1 every time? That would mean only mercury is effected by the suns gravity, and only venus is effected by mercuries gravity and so on.
Reply
#17
(Jun-14-2017, 10:03 AM)JakeWitten Wrote: is this because when i = 0 , j = 1 every time?
no, that is not correct

for i in range (0,9,1):
    for j in range(i+1,9,1):
        print 'i:{}, j:{}'.format(i,j)
Output:
i:0, j:1 i:0, j:2 i:0, j:3 i:0, j:4 i:0, j:5 i:0, j:6 i:0, j:7 i:0, j:8 i:1, j:2 i:1, j:3 i:1, j:4 i:1, j:5 i:1, j:6 i:1, j:7 i:1, j:8 i:2, j:3 i:2, j:4 i:2, j:5 i:2, j:6 i:2, j:7 i:2, j:8 i:3, j:4 i:3, j:5 i:3, j:6 i:3, j:7 i:3, j:8 i:4, j:5 i:4, j:6 i:4, j:7 i:4, j:8 i:5, j:6 i:5, j:7 i:5, j:8 i:6, j:7 i:6, j:8 i:7, j:8
I think that is what you meant by "For example, when calculating mercury, 'i' needs to be in the range 1-9, rather than 0-9. For venus it needs to be 2-9. Otherwise the forces end up canceling out and the planets don't move."
Reply
#18
Is my understanding correct that the F force calculated for each pair, e.g. i=0, j=1 is net, i.e. no need to calculate also for i=1, j=0?
Reply
#19
(Jun-14-2017, 10:40 AM)buran Wrote: Is my understanding correct that the F force calculated for each pair, e.g. i=0, j=1 is net, i.e. no need to calculate also for i=1, j=0?
Yes, its net.
It didn't occur to me that the nested loop would cycle through the full range of j for every i value, so that's not the problem...
I still don't know what the issue is then. It kind of looks like the force from the sun isn't being accounted for, but I don't see why it wouldn't be.
Reply
#20
(Jun-14-2017, 10:58 AM)JakeWitten Wrote: It kind of looks like the force from the sun isn't being accounted for, but I don't see why it wouldn't be.
I think it is accounted for when i=0 and j is 1 to 8...
Of course I'm not an expert in the field :-)
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020