{{https://i.ibb.co/48VrRGH/Code.png}}
===== Main.py: =====
# -*- coding: utf-8 -*-
from model import World, WorldOutput
from file_model import WorldFileInput, WorldFileOutput
from physics_euler import PhysicsEngineEuler
from physics_rk4 import PhysicsEngineRK4
from physics_leapfrog import PhysicsEngineLeap
from physics_skyfield import PhysicsEngineSkyfield
from render import RenderEngineVPython
import sys
class WorldLogOutput(WorldOutput):
def start(self):
self.print_state()
def step(self):
self.print_state()
def print_state(self):
for key, wo in self.world.world_objects:
print('{time},{key},{wo}'.format(
time=self.world.time, key=key, wo=wo))
input_type = sys.argv[1]
output_types = sys.argv[2].split(',')
end_time = float(sys.argv[3])
path = sys.argv[4]
world = World()
if input_type.startswith('file'):
world.input = WorldFileInput(world, path)
elif input_type.startswith('euler'):
#Init world
o = WorldFileOutput(world, path)
parts = input_type.split(':')
dt = 1.0
if len(parts) > 1:
dt = float(parts[1])
world.input = PhysicsEngineEuler(world, dt)
elif input_type.startswith('rk4'):
#Init world
o = WorldFileOutput(world, path)
parts = input_type.split(':')
dt = 1.0
if len(parts) > 1:
dt = float(parts[1])
world.input = PhysicsEngineRK4(world, dt)
elif input_type.startswith('leapfrog'):
#Init world
o = WorldFileOutput(world, path)
parts = input_type.split(':')
dt = 1.0
if len(parts) > 1:
dt = float(parts[1])
world.input = PhysicsEngineLeap(world, dt)
elif input_type.startswith('skyfield'):
#Init world
o = WorldFileOutput(world, path)
parts = input_type.split(':')
dt = 1.0
if len(parts) > 1:
dt = float(parts[1])
world.input = PhysicsEngineSkyfield(world, dt)
for output_type in output_types:
if output_type.startswith('vpython'):
parts = output_type.split(':')
time_scale = 1.0
radius_scale = 1.0
if len(parts) > 1:
time_scale = float(parts[1])
if len(parts) > 2:
radius_scale = float(parts[2])
world.outputs.append(RenderEngineVPython(world, time_scale, radius_scale))
if output_type.startswith('file'):
world.outputs.append(WorldFileOutput(world, path))
if output_type.startswith('log'):
world.outputs.append(WorldLogOutput(world))
world.start(end_time)
\\
\\
=====physics_leapfrog.py:=====
# -*- coding: utf-8 -*-
from physics import PhysicsEngine
from itertools import combinations
import numpy as np
class PhysicsEngineLeap(PhysicsEngine):
dt = None
def __init__(self, world, dt):
super(PhysicsEngineLeap, self).__init__(world)
self.dt = dt
def calc_acceleration(self, wo):
return wo.force / wo.mass
def step(self):
world_objects = self.world.world_objects.values()
#reset force
for wo in world_objects:
wo.force = np.array([0.0,0.0,0.0])
pairs = combinations(world_objects, 2)
#force-loop
for wo1, wo2 in pairs:
force = self.grav_force(wo1.position, wo2.position, wo1.mass, wo2.mass)
wo1.force += force
wo2.force -= force
#first velocity-loop
for wo in world_objects:
wo.velocity += self.calc_acceleration(wo) * self.dt / 2
#position-loop
for wo in world_objects:
wo.position += wo.velocity * self.dt
for wo in world_objects:
wo.force = np.array([0.0,0.0,0.0])
pairs = combinations(world_objects, 2)
#force-loop
for wo1, wo2 in pairs:
force = self.grav_force(wo1.position, wo2.position, wo1.mass, wo2.mass)
wo1.force += force
wo2.force -= force
#second velocity-loop:
for wo in world_objects:
wo.velocity += self.calc_acceleration(wo) * self.dt / 2
self.world.time += self.dt