{{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