def apply(self, particle: Particle, other_particle: Particle, engine: "Engine") -> Dict[str, Set[Particle]]: if particle.mass > other_particle.mass: particle, other_particle = other_particle, particle if (other_particle not in engine.features["remove"].particles_to_remove and compute_multi_dimensional_distance( particle.position, other_particle.position) < umd # < other_particle.compute_size() + particle.compute_size() ): total_mass = particle.mass + other_particle.mass p_share = particle.mass / total_mass o_share = other_particle.mass / total_mass # todo : Move position to the weighted mean of the two particles other_particle.delay_update("_mass", total_mass) # noinspection PyProtectedMember other_particle.delay_update( "_velocity", [ p_velocity * p_share + o_velocity * o_share for p_velocity, o_velocity in zip( particle._velocity, other_particle._velocity) ], ) particles_to_remove = {particle} else: particles_to_remove = {} return {"remove": particles_to_remove}
def _loop(self): particle = Particle(Vector(WIDTH / 2, 0, 0), Vector(0, 0, 0), Vector(0, 10e-4, 0), 0.99, 10) self.clock.tick() while True: tick = self.clock.tick() particle.integrate(tick) self._draw(particle)
def _create_particles_and_constraints(self) -> None: for name, segment in TURKEY_SEGMENTS.items(): # scale the points up. scaled_points = np.asarray(segment, float) * self.scale self.segments[name] = [] for p in scaled_points: # find the particle if it already exists, otherwise create a new one. particle: Particle = next((part for part in self.particles if np.allclose(part.curr_pos, p)), Particle(position=p, mass=Turkey.mass)) if particle not in self.particles: self.particles.append(particle) # print("adding a new particle at ", particle.curr_pos) # print(len(self.particles)) # append the particle to this segment. self.segments[name].append(particle) if name == "eye": continue # create a Stick constraint for each pair within this segment. for p1, p2 in pairs(self.segments[name]): constraint = StickConstraint(p1, p2, relatice_tolerance=0.1) self.stick_constraints.append(constraint) # add more flexible stick constraints between every other node on this segment: for p1, p2 in pairs(self.segments[name][::2]): constraint = StickConstraint(p1, p2, relatice_tolerance=0.4) self.stick_constraints.append(constraint)
def manage_particle_interaction(self, particle_1: Particle, particle_2: Particle): for law in self.arbitrary_laws: output = law.apply(particle_1, particle_2, self) for feature_name, data in output.items(): self.features[feature_name].update(data) total_force = None for force_generator in self.force_generators: force = force_generator.compute_force(particle_1, particle_2) if total_force is None: total_force = force for dimension, (dimensional_total_force, dimensional_force) in enumerate( zip(total_force, force)): total_force[ dimension] = dimensional_total_force + dimensional_force particle_1.apply_force(total_force, particle_2) particle_1.run()
def create_world(): w = World((2000, 2000)) n_particles = 20 vmax = 100 for _ in range(n_particles): pos = random.randint(0, w.rect.w), random.randint(0, w.rect.h) s = random.uniform(-vmax, vmax), random.uniform(-vmax, vmax) m = 1. w.add_particle(Particle(Vector2(pos), Vector2(s), m)) return w
def asteroids(): particle1 = Particle(q0x=R, q0y=0, p0x=0, p0y=29.29 * 1e3 * Mear, m=Mear, name="Earth") particle2 = Particle(0, 0, 0, 0, m=Msol, fixed=True, name="Sun") asteroid_v_angles = [] earth_vangles = [] initial_vangles = np.array([45, 40, 30, 20, 15, 10, 5]) * math.pi / 180 masses = np.array([ 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e0, 1e1, 2e1, 5e1, 1e2, 3e2, 5e2, 7e2, 1e3 ]) # masses = np.array([1e0]) ivangle = math.pi / 2 # mass= # norm(self.px, self.py)**2/self.m/2 eccentricitiesEar = [] eccentricitiesAst = [] for i, mass in enumerate(masses): pabs = 10 * 1e3 * mass * Mear timefactor = 1.1 plotstuff = False # if mass == 3e2: # timefactor=1 # plotstuff=True particle3 = Particle(q0x=R * (1 - 0.001), q0y=0.1 * R, p0x=pabs * math.cos(ivangle), p0y=-pabs * math.sin(ivangle), m=mass * Mear, name="Massive asteroid") # particle3 = Particle(q0x=-R, q0y=0, p0x=0, p0y=-29.29*1e3*Mear, m=Mear, name="Massive asteroid") parcls = [particle1, particle2, particle3] initstate = InitialState(parcls) system = System(initstate.get_state(), SymplecticEuler, tmax=TMAX * timefactor, dt=100, stepsperframe=400) system.simulate() # system.animate(boxlimits=1.5*R, interval=20) eccentricitiesEar.append(system.eccentricity(0)) try: eccentricitiesAst.append(system.eccentricity(2)) except ValueError: print("Negative asteroid eccentricity") if plotstuff: system.plot_trajectories(show=False, new_fig=not i) # system.plot_energies() vangleAst = math.atan( system.particles[2].py / system.particles[2].px) / math.pi * 180 vangleEar = math.atan( system.particles[0].py / system.particles[0].px) / math.pi * 180 earth_vangles.append(vangleEar) asteroid_v_angles.append(vangleAst) # particles[0].name="Undisturbed Earth" # initstate = InitialState(particles) # system = System(initstate.get_state(), SymplecticEuler, tmax=TMAX*timefactor, dt=100, stepsperframe=400) # system.simulate() # system.plot_trajectory(0,show=True,new_fig=False) plt.figure() plt.plot(masses, asteroid_v_angles, '-') plt.xscale("log") plt.title("Asteroid's velocity angle after Earth slingshot") plt.xlabel("$Asteroid\ mass\ [M⊕]$") plt.ylabel("Angle [degrees]") plt.show() plt.figure() plt.plot(masses, earth_vangles, '-') plt.title("Earth's velocity angle after massive asteroid slingshot") plt.xscale("log") plt.ylabel("Angle [degrees]") plt.xlabel("$Asteroid\ mass\ [M⊕]$") plt.show() plt.figure() plt.title("Earth's orbital eccentricity after massive asteroid slingshot") plt.plot(masses, eccentricitiesEar, '-') plt.xscale("log") plt.xlabel("$Asteroid\ mass\ [M⊕]$") plt.ylabel("$eccentricity$") plt.show() plt.figure() plt.title("Asteroids's orbital eccentricity after Earth slingshot") plt.plot(masses, eccentricitiesAst, '-') plt.xscale("log") plt.xlabel("$Asteroid\ mass\ [M⊕]$") plt.ylabel("$eccentricity$") plt.show()
import numpy as np from matplotlib import pyplot as plt from physics import Particle, System, InitialState from Integrators import SymplecticEuler, Leapfrog, RungeKutta4, ForwardEuler from constants import G # a=0.5 R = 152 * 1e9 Msol = 1.9891e30 Mear = 5.972e24 TMAX = 60 * 60 * 24 * 365 * 1 particle1 = Particle(q0x=R, q0y=0, p0x=0, p0y=29.29 * 1e3 * Mear, m=Mear, name="Earth") particle2 = Particle(0, 0, 0, 0, m=Msol, fixed=False, name="Sun") particles = [particle1, particle2] initial_state = InitialState(particles) def compare_integrators(): integrators = [ForwardEuler, SymplecticEuler, Leapfrog, RungeKutta4] timesteps = [10000000, 1000000, 100000, 10000, 1000, 100] errors = np.zeros((len(integrators), len(timesteps))) energy_drifts = np.zeros((len(integrators), len(timesteps))) energy_drifts_at_tmax = np.zeros((len(integrators), len(timesteps))) for i, integrator in enumerate(integrators):
def test_visualize(): particles = [Particle(0.3, 0.5, 1), Particle(0.0, -0.5, -1), Particle(-0.1, -0.4, 3)] simulator = ParticleSimulator(particles) visualize(simulator)