def sma_determinator(primary, secondary): binary = Particles(0) binary.add_particle(primary) binary.add_particle(secondary) orbital_params = get_orbital_elements_from_binary(binary, G=constants.G) return orbital_params[2]
def create_pre_tack_giants_system(): #Create a pre_tack_giants_system by first recreating the sun. pre_tack_giants_system = Particles(1) pre_tack_giants_system[0].name = "Sun" pre_tack_giants_system[0].mass = 1.0 | units.MSun pre_tack_giants_system[0].radius = 1.0 | units.RSun pre_tack_giants_system[0].position = (0, 0, 0) | units.AU pre_tack_giants_system[0].velocity = (0, 0, 0) | units.kms pre_tack_giants_system[0].density = 3 * pre_tack_giants_system[0].mass / ( 4 * np.pi * pre_tack_giants_system[0].radius**3) #The pre tack orbital elements for the planets as below names = ["Jupiter", "Saturn", "Uranus", "Neptune"] masses = np.array([317.8, 30, 5, 5]) | units.MEarth radii = np.array([0.10049, 0.083703, 0.036455, 0.035392]) | units.RSun a = np.array([3.5, 4.5, 6.013, 8.031]) | units.AU inclinations = np.random.uniform(-5, 5, 4) | units.deg true_anomalies = np.random.uniform(0, 360, 4) | units.deg longs_of_ascending_node = np.random.uniform(0, 360, 4) | units.deg args_of_periapsis = np.random.uniform(0, 360, 4) | units.deg #Create the four planets as binaries with the sun and add them to the pre_tack_giants_system for i in range(4): sun_and_planet = new_binary_from_orbital_elements( pre_tack_giants_system[0].mass, masses[i], a[i], 0, true_anomalies[i], inclinations[i], longs_of_ascending_node[i], args_of_periapsis[i], G=constants.G) planet = Particles(1) planet.name = names[i] planet.mass = masses[i] planet.radius = radii[ i] # This is purely non-zero for collisional purposes planet.position = (sun_and_planet[1].x - (0 | units.AU), sun_and_planet[1].y - (0 | units.AU), sun_and_planet[1].z - (0 | units.AU)) planet.velocity = (sun_and_planet[1].vx - (0 | units.kms), sun_and_planet[1].vy - (0 | units.kms), sun_and_planet[1].vz - (0 | units.kms)) planet.density = 3 * planet.mass / (4 * np.pi * planet.radius**3) pre_tack_giants_system.add_particle(planet) return pre_tack_giants_system
def create_system(): system = new_solar_system() system = system[system.mass > 10**-5 | units.MSun] # Takes gas giants and Sun only system.move_to_center() sun = Particles(1) sun.name = "Sun" sun.mass = 1.0 | units.MSun sun.radius = 1.0 | units.RSun sun.position = (0, 0, 0) | units.AU sun.velocity = (0, 0, 0) | units.kms sun.density = 3*sun.mass/(4*np.pi*sun.radius**3) names = ["Jupiter", "Saturn", "Uranus", "Neptune"] masses = [317.8, 90, 15, 17] | units.MEarth radii = [0.10049, 0.083703, 0.036455, 0.035392] | units.RSun semis = [5.4, 7.1, 10.5, 13] | units.AU #[3.5, 4.9, 6.4, 8.4] trues = [0, 90, 180, 270]| units.deg#np.random.uniform(0, 360, 4) | units.deg longs = np.random.uniform(0, 360, 4) | units.deg args = np.random.uniform(0, 360, 4) | units.deg for i in range(4): orbital_elements = get_orbital_elements_from_binary(system[0]+ system[i+1], G=constants.G) eccentricity, inclination = 0, orbital_elements[5] sun_and_plan = new_binary_from_orbital_elements(sun[0].mass, masses[i], semis[i], 0, trues[i], inclination, longs[i], args[i], G=constants.G) planet = Particles(1) planet.name = system[i+1].name planet.mass = system[i+1].mass planet.radius = system[i+1].radius # This is purely non-zero for collisional purposes planet.position = (sun_and_plan[1].x-sun_and_plan[0].x, sun_and_plan[1].y-sun_and_plan[0].y, sun_and_plan[1].z-sun_and_plan[0].z) planet.velocity = (sun_and_plan[1].vx-sun_and_plan[0].vx, sun_and_plan[1].vy-sun_and_plan[0].vy, sun_and_plan[1].vz-sun_and_plan[0].vz) planet.density = 3*planet.mass/(4*np.pi*planet.radius**3) sun.add_particle(planet) return sun
def evolve_sun_jupiter(particles, tend, dt): SunJupiter = Particles() SunJupiter.add_particle(particles[0]) SunJupiter.add_particle(particles[1]) converter = nbody_system.nbody_to_si(particles.mass.sum(), particles[1].position.length()) gravity = ph4(converter) gravity.particles.add_particles(particles) channel_from_to_SunJupiter = gravity.particles.new_channel_to(SunJupiter) semi_major_axis = [] eccentricity = [] times = quantities.arange(0 | units.yr, tend, dt) for i, t in enumerate(times): print "Time=", t.in_(units.yr) channel_from_to_SunJupiter.copy() orbital_elements = orbital_elements_from_binary(SunJupiter, G=constants.G) a = orbital_elements[2] e = orbital_elements[3] semi_major_axis.append(a.value_in(units.AU)) eccentricity.append(e) gravity.evolve_model(t, timestep=dt) # Plot fig = plt.figure(figsize=(8, 6)) ax1 = fig.add_subplot(211, xlabel='time(yr)', ylabel='semi major axis (AU)') ax1.plot(times.value_in(units.yr), semi_major_axis) ax2 = fig.add_subplot(212, xlabel='time(yr)', ylabel='eccentriity') ax2.plot(times.value_in(units.yr), eccentricity) plt.show() gravity.stop()
def evolve_sun_jupiter(particles, tend, dt): SunJupiter = Particles() SunJupiter.add_particle(particles[0]) SunJupiter.add_particle(particles[1]) converter=nbody_system.nbody_to_si(particles.mass.sum(), particles[1].position.length()) gravity = ph4(converter) gravity.particles.add_particles(particles) channel_from_to_SunJupiter = gravity.particles.new_channel_to(SunJupiter) semi_major_axis = list() eccentricity = list() times = quantities.arange(0|units.yr, tend+dt, dt) for i,t in enumerate(times): #print "Time =", t.in_(units.yr) channel_from_to_SunJupiter.copy() orbital_elements = orbital_elements_from_binary(SunJupiter, G=constants.G) a = orbital_elements[2] e = orbital_elements[3] semi_major_axis.append(a.value_in(units.AU)) eccentricity.append(e) gravity.evolve_model(t, timestep=dt) gravity.stop() # save the data: times, semi_major_axis and eccentricity of Jupiter's orbit t_a_e = np.column_stack((times.value_in(units.yr), semi_major_axis, eccentricity)) np.savetxt('t_a_e.txt', t_a_e, delimiter=',') # make plots fig = plt.figure(figsize = (8, 6)) ax1 = fig.add_subplot(211, xlabel = 'time(yr)', ylabel = 'semi major axis (AU)') ax1.plot(times.value_in(units.yr), semi_major_axis) ax2 = fig.add_subplot(212, xlabel = 'time(yr)', ylabel = 'eccentriity') ax2.plot(times.value_in(units.yr), eccentricity) plt.show()
def create_post_tack_giants_system(): #Create the present day solar system and keep only the sun and the giants present_day_solar_system = new_solar_system() present_day_solar_system = present_day_solar_system[present_day_solar_system.mass > 10**-5 | units.MSun] # Takes gas giants and Sun only present_day_solar_system.move_to_center() #Create a post_tack_giants_system by first recreating the sun. post_tack_giants_system = Particles(1) post_tack_giants_system[0].name = "Sun" post_tack_giants_system[0].mass = 1.0 | units.MSun post_tack_giants_system[0].radius = 1.0 | units.RSun post_tack_giants_system[0].position = (0, 0, 0) | units.AU post_tack_giants_system[0].velocity = (0, 0, 0) | units.kms #The post tack orbital elements for the planets as below a = np.array([5.4, 7.1, 10.5, 13]) | units.AU true_anomalies = np.random.uniform(0, 360, 4) | units.deg long_of_ascending_node = np.random.uniform(0, 360, 4) | units.deg args_of_periapsis = np.random.uniform(0, 360, 4) | units.deg #Create the four planets as binaries with the sun and add them to the post_tack_giants_system for i in range(4): orbital_elements = get_orbital_elements_from_binary(present_day_solar_system[0]+ present_day_solar_system[i+1], G=constants.G) inclination = orbital_elements[5] #Make sure we have a sensable inclination for the giants sun_and_planet = new_binary_from_orbital_elements(post_tack_giants_system.mass[0], present_day_solar_system[i+1].mass, a[i], 0, true_anomalies[i], inclination, long_of_ascending_node[i], args_of_periapsis[i], G=constants.G) planet = Particles(1) planet.name = present_day_solar_system[i+1].name planet.mass = present_day_solar_system[i+1].mass planet.radius = present_day_solar_system[i+1].radius planet.position = (sun_and_planet[1].x-sun_and_planet[0].x, sun_and_planet[1].y-sun_and_planet[0].y, sun_and_planet[1].z-sun_and_planet[0].z) planet.velocity = (sun_and_planet[1].vx-sun_and_planet[0].vx, sun_and_planet[1].vy-sun_and_planet[0].vy, sun_and_planet[1].vz-sun_and_planet[0].vz) post_tack_giants_system.add_particle(planet) return post_tack_giants_system
def vanilla_tack_evolver(complete_pre_tack_system, converter, N_objects, times, save_file_times): #Initialise the gravity code and add the particles to it gravity_code = MercuryWayWard(converter) gravity_code.initialize_code() gravity_code.central_particle.add_particle(complete_pre_tack_system[0]) gravity_code.orbiters.add_particles(complete_pre_tack_system[1:]) gravity_code.commit_particles channel = gravity_code.particles.new_channel_to(complete_pre_tack_system) #---------------------------------------------------------------------------------------------------- #Here we define the 'correct' sma's for the different migrations. Also, the initial #planetary inclinations are stored for later use. initial_sma = np.array([3.5, 4.5, 6.013, 8.031]) | units.AU saturn_sma = np.array([1.5, 4.5, 6.013, 8.031]) | units.AU outward_sma = np.array([1.5, 1.5 * ((3 / 2)**(2 / 3)), 6.013, 8.031]) | units.AU post_tack_sma = np.array([5.4, 7.1, 10.5, 13.]) | units.AU current_sma = [3.5, 4.5, 6.013, 8.031] | units.AU inclinations = [0, 0, 0, 0] | units.deg for k in range(4): orbital_elements = get_orbital_elements_from_binary( complete_pre_tack_system[0] + complete_pre_tack_system[k + 1], G=constants.G) inclinations[k] = orbital_elements[5] #---------------------------------------------------------------------------------------------------- #Here we define the parameters used in the 'semi_major_axis_next_step' functions #The sma's are based on exact resonances. The time_scales are taken from literature. #The 0 values will be changed during the evolution of the model. #pre_resonant is used in the outward migration, when jupiter and saturn are #already in resonance with eachother, so that pre_resonant = True a_start = [1.5, 1.5 * ((3 / 2)**(2 / 3)), 0, 0] | units.AU a_end = [ 5.4, 5.4 * ((3 / 2)**(2 / 3)), 5.4 * ((3 / 2)**(2 / 3) * (9 / 5)**(2 / 3)), 5.4 * ((3 / 2)**(2 / 3) * (5 / 2)**(2 / 3)) ] | units.AU time_start = [1.025 * 10**5, 1.025 * 10**5, 0, 0] | units.yr time_scale = [5 * 10**5, 5 * 10**5, 0, 0] | units.yr resonances = [2 / 3, 3 / 2, 9 / 5, 5 / 2] pre_resonant = [False, False, True, True] outward_migration_started = False dead_comets = [] #---------------------------------------------------------------------------------------------------- #Below, the evolution starts. for i in tqdm(range(len(times) - 1)): gravity_code.evolve_model(times[i]) channel.copy() #Save the model when we want it to if times[i] in save_file_times: write_set_to_file( gravity_code.orbiters, directory + 'Vanilla_Tack_run' + str(run_number) + '_time=' + str(np.log10(times[i].value_in(units.yr)))[0:5] + '.hdf5', format='hdf5', overwrite_file=True) #For each timestep determine the current sma's for j in range(4): current_sma[j] = sma_determinator(gravity_code.central_particle, gravity_code.orbiters[j]) #----------------------------------------------------------------------------------------------------- #This chunk of code describes the inward migration of jupiter #The first orbiter and the second particle in the gravity_code. if times[i] < 10**5 | units.yr: #This pushes Jupiter slightly inward sma_next_step = semi_major_axis_next_step_in_jup( times[i + 1], 10**5 | units.yr, 3.5 | units.AU, 1.5 | units.AU) binary = Particles(0) binary.add_particle(gravity_code.central_particle) binary.add_particle(gravity_code.orbiters[0]) orbital_params = get_orbital_elements_from_binary(binary, G=constants.G) true_anomaly, ascending_node, pericenter = orbital_params[4].in_( units.deg), orbital_params[6].in_( units.deg), orbital_params[7].in_(units.deg) sun_and_planet = new_binary_from_orbital_elements( 1 | units.MSun, orbital_params[1], sma_next_step, 0, true_anomaly, inclinations[0], ascending_node, pericenter, G=constants.G) gravity_code.particles[1].position = (sun_and_planet[1].x - (0 | units.AU), sun_and_planet[1].y - (0 | units.AU), sun_and_planet[1].z - (0 | units.AU)) gravity_code.particles[1].velocity = (sun_and_planet[1].vx - (0 | units.kms), sun_and_planet[1].vy - (0 | units.kms), sun_and_planet[1].vz - (0 | units.kms)) #During the tack, the masses of the planets increase towards their current values gravity_code.particles[2].mass *= 2**(1.5 / (10**5)) gravity_code.particles[3].mass *= 1.2**(1.5 / (10**5)) gravity_code.particles[4].mass *= 1.2**(1.5 / (10**5)) #This keeps the other planets in place for j in range(3): binary = Particles(0) binary.add_particle(gravity_code.central_particle) binary.add_particle(gravity_code.orbiters[j + 1]) orbital_params = get_orbital_elements_from_binary( binary, G=constants.G) true_anomaly, ascending_node, pericenter = orbital_params[ 4].in_(units.deg), orbital_params[6].in_( units.deg), orbital_params[7].in_(units.deg) sun_and_planet = new_binary_from_orbital_elements( 1 | units.MSun, orbital_params[1], initial_sma[1 + j], 0, true_anomaly, inclinations[j + 1], ascending_node, pericenter, G=constants.G) gravity_code.particles[j + 2].position = (sun_and_planet[1].x - (0 | units.AU), sun_and_planet[1].y - (0 | units.AU), sun_and_planet[1].z - (0 | units.AU)) gravity_code.particles[j + 2].velocity = ( sun_and_planet[1].vx - (0 | units.kms), sun_and_planet[1].vy - (0 | units.kms), sun_and_planet[1].vz - (0 | units.kms)) #------------------------------------------------------------------------------------------------------------ #This chunk of code describes the inward migration of saturn elif 1 * 10**5 | units.yr <= times[i] < 1.025 * 10**5 | units.yr: #This pushes Saturn slightly inward sma_next_step = semi_major_axis_next_step_in_sat( times[i + 1], 2.5 * 10**3 | units.yr, 4.5 | units.AU, 1.5 * ((3 / 2)**(2 / 3)) | units.AU) binary = Particles(0) binary.add_particle(gravity_code.central_particle) binary.add_particle(gravity_code.orbiters[1]) orbital_params = get_orbital_elements_from_binary(binary, G=constants.G) true_anomaly, ascending_node, pericenter = orbital_params[4].in_( units.deg), orbital_params[6].in_( units.deg), orbital_params[7].in_(units.deg) sun_and_planet = new_binary_from_orbital_elements( 1 | units.MSun, orbital_params[1], sma_next_step, 0, true_anomaly, inclinations[1], ascending_node, pericenter, G=constants.G) gravity_code.particles[2].position = (sun_and_planet[1].x - (0 | units.AU), sun_and_planet[1].y - (0 | units.AU), sun_and_planet[1].z - (0 | units.AU)) gravity_code.particles[2].velocity = (sun_and_planet[1].vx - (0 | units.kms), sun_and_planet[1].vy - (0 | units.kms), sun_and_planet[1].vz - (0 | units.kms)) gravity_code.particles[2].mass *= 1.5**(0.5 / (2500)) gravity_code.particles[3].mass *= (17.15 / 6)**(0.5 / (5 * 10**5)) gravity_code.particles[4].mass *= (14.54 / 6)**(0.5 / (5 * 10**5)) #This keeps the other planets in place for j in [0, 2, 3]: binary = Particles(0) binary.add_particle(gravity_code.central_particle) binary.add_particle(gravity_code.orbiters[j]) orbital_params = get_orbital_elements_from_binary( binary, G=constants.G) true_anomaly, ascending_node, pericenter = orbital_params[ 4].in_(units.deg), orbital_params[6].in_( units.deg), orbital_params[7].in_(units.deg) sun_and_planet = new_binary_from_orbital_elements( 1 | units.MSun, orbital_params[1], saturn_sma[j], 0, true_anomaly, inclinations[j], ascending_node, pericenter, G=constants.G) gravity_code.particles[j + 1].position = (sun_and_planet[1].x - (0 | units.AU), sun_and_planet[1].y - (0 | units.AU), sun_and_planet[1].z - (0 | units.AU)) gravity_code.particles[j + 1].velocity = ( sun_and_planet[1].vx - (0 | units.kms), sun_and_planet[1].vy - (0 | units.kms), sun_and_planet[1].vz - (0 | units.kms)) #------------------------------------------------------------------------------------------------------------ #This chunk of code describes the outward migration of all planets elif 1.025 * 10**5 | units.yr <= times[i] < 6 * 10**5 | units.yr: #This bit checks if uranus and neptune already should start migrating for k in range(4): if pre_resonant[k] == True: if current_sma[k] / current_sma[1] < (resonances[k])**(2 / 3): pre_resonant[k] = False a_start[k] = current_sma[k] time_start[k] = times[i] time_scale[k] = (6 * 10**5 | units.yr) - times[i] #If pre_resonant == False, pushes the planet outward. If true, keeps it in place for l in range(4): if pre_resonant[l] == False: sma_next_step = semi_major_axis_next_step_out( times[i + 1], time_start[l], a_end[l], a_start[l], time_scale[l]) binary = Particles(0) binary.add_particle(gravity_code.central_particle) binary.add_particle(gravity_code.orbiters[l]) orbital_params = get_orbital_elements_from_binary( binary, G=constants.G) true_anomaly, ascending_node, pericenter = orbital_params[ 4].in_(units.deg), orbital_params[6].in_( units.deg), orbital_params[7].in_(units.deg) sun_and_planet = new_binary_from_orbital_elements( 1 | units.MSun, orbital_params[1], sma_next_step, 0, true_anomaly, inclinations[l], ascending_node, pericenter, G=constants.G) gravity_code.particles[l + 1].position = ( sun_and_planet[1].x - (0 | units.AU), sun_and_planet[1].y - (0 | units.AU), sun_and_planet[1].z - (0 | units.AU)) gravity_code.particles[l + 1].velocity = ( sun_and_planet[1].vx - (0 | units.kms), sun_and_planet[1].vy - (0 | units.kms), sun_and_planet[1].vz - (0 | units.kms)) else: binary = Particles(0) binary.add_particle(gravity_code.central_particle) binary.add_particle(gravity_code.orbiters[l]) orbital_params = get_orbital_elements_from_binary( binary, G=constants.G) true_anomaly, ascending_node, pericenter = orbital_params[ 4].in_(units.deg), orbital_params[6].in_( units.deg), orbital_params[7].in_(units.deg) sun_and_planet = new_binary_from_orbital_elements( 1 | units.MSun, orbital_params[1], outward_sma[l], 0, true_anomaly, inclinations[l], ascending_node, pericenter, G=constants.G) gravity_code.particles[l + 1].position = ( sun_and_planet[1].x - (0 | units.AU), sun_and_planet[1].y - (0 | units.AU), sun_and_planet[1].z - (0 | units.AU)) gravity_code.particles[l + 1].velocity = ( sun_and_planet[1].vx - (0 | units.kms), sun_and_planet[1].vy - (0 | units.kms), sun_and_planet[1].vz - (0 | units.kms)) gravity_code.particles[3].mass *= (17.15 / 6)**(15 / (5 * 10**5)) gravity_code.particles[4].mass *= (14.54 / 6)**(15 / (5 * 10**5)) #------------------------------------------------------------------------------------------------------------ else: #--------------------------------------------------------------------------------------------------------------- for l in range(4): if abs(current_sma[l] / post_tack_sma[l]) > 1.25 or abs( current_sma[l] / post_tack_sma[l] ) < 0.75: #The orbits are too much perturbed, so we end the simulation return elif abs(current_sma[l] / post_tack_sma[l]) > 1.05 or abs( current_sma[l] / post_tack_sma[l] ) < 0.95: #The orbits are slightly perturbed, so we redefinie them print("Here", complete_pre_tack_system[l + 1].name, "was redefined") binary = Particles(0) binary.add_particle(gravity_code.central_particle) binary.add_particle(gravity_code.orbiters[l]) orbital_params = get_orbital_elements_from_binary( binary, G=constants.G) true_anomaly, ascending_node, pericenter = orbital_params[ 4].in_(units.deg), orbital_params[6].in_( units.deg), orbital_params[7].in_(units.deg) sun_and_planet = new_binary_from_orbital_elements( 1 | units.MSun, orbital_params[1], post_tack_sma[l], 0, true_anomaly, inclinations[l], ascending_node, pericenter, G=constants.G) gravity_code.particles[l + 1].position = ( sun_and_planet[1].x - (0 | units.AU), sun_and_planet[1].y - (0 | units.AU), sun_and_planet[1].z - (0 | units.AU)) gravity_code.particles[l + 1].velocity = ( sun_and_planet[1].vx - (0 | units.kms), sun_and_planet[1].vy - (0 | units.kms), sun_and_planet[1].vz - (0 | units.kms)) else: pass #---------------------------------------------------------------------------------------------------------------------- #Here we look for 'escaped' and 'out of bounds' comets out_of_bounds, escaped_comets = [], [] for i in range(len(gravity_code.orbiters)): if gravity_code.orbiters[i].position.length() > 500 | units.AU: escaped_comets.append(gravity_code.orbiters[i]) if gravity_code.orbiters[i].position.length( ) > 250000 | units.AU: out_of_bounds.append(gravity_code.orbiters[i]) dead_comets.append(gravity_code.orbiters[i]) for particle in out_of_bounds: complete_pre_tack_system.remove_particle(particle) complete_pre_tack_system.synchronize_to(gravity_code.particles) if i % 1000 == 0: print("The amount of currently escaped comets is ", len(escaped_comets)) print("The amount of dead comets is ", len(dead_comets)) if i % 1000 == 0: print("The sma's are: ", current_sma[0], current_sma[1], current_sma[2], current_sma[3]) gravity_code.stop() return complete_pre_tack_system
def vanilla_evolver(particle_system, converter, N_objects, end_time, time_step): names = ['Sun', 'Jupiter', 'Saturn', 'Uranus', 'Neptune'] gravity_code = MercuryWayWard() gravity_code.initialize_code() gravity_code.central_particle.add_particle(particle_system[0]) gravity_code.orbiters.add_particles(particle_system[1:]) gravity_code.commit_particles ch_g2l = gravity_code.particles.new_channel_to(particle_system) times = np.arange(0., end_time, time_step) | units.yr dead_comets = [] #--------------------------------------------------------------------------------------------------------- sma = [0, 0, 0, 0] | units.AU correct_sma = [5.4, 7.1, 10.5, 13] | units.AU eccentricities = [0, 0, 0, 0] inclinations = [0, 0, 0, 0] | units.deg system = new_solar_system() system = system[system.mass > 10**-5 | units.MSun] # Takes gas giants and Sun only system.move_to_center() for k in range(4): orbital_elements = get_orbital_elements_from_binary(system[0]+ system[k+1], G=constants.G) inclinations[k] = orbital_elements[5] #------------------------------------------------------------------------------------------------------------ for i in tqdm(range(len(times))): gravity_code.evolve_model(times[i]) ch_g2l.copy() #--------------------------------------------------------------------------------------------------------------- for j in range(4): sma[j] = sma_determinator(gravity_code.central_particle, gravity_code.orbiters[j]) for l in range(4): if abs(sma[l]/correct_sma[l]) > 1.25 or abs(sma[l]/correct_sma[l]) < 0.75: return elif abs(sma[l]/correct_sma[l]) > 1.05 or abs(sma[l]/correct_sma[l]) < 0.95: print("Here", names[l+1], "was redefined") binary = Particles(0) binary.add_particle(gravity_code.central_particle) binary.add_particle(gravity_code.orbiters[l]) orbital_params = get_orbital_elements_from_binary(binary, G = constants.G) true_anomaly, ascending_node, pericenter = orbital_params[4].in_(units.deg), orbital_params[6].in_(units.deg), orbital_params[7].in_(units.deg) sun_and_plan = new_binary_from_orbital_elements(1 | units.MSun, orbital_params[1], correct_sma[l], eccentricities[l], true_anomaly, inclinations[l], ascending_node, pericenter, G=constants.G) gravity_code.particles[l+1].position = (sun_and_plan[1].x-sun_and_plan[0].x, sun_and_plan[1].y-sun_and_plan[0].y, sun_and_plan[1].z-sun_and_plan[0].z) gravity_code.particles[l+1].velocity = (sun_and_plan[1].vx-sun_and_plan[0].vx, sun_and_plan[1].vy-sun_and_plan[0].vy, sun_and_plan[1].vz-sun_and_plan[0].vz) else: pass #---------------------------------------------------------------------------------------------------------------------- if i%1000 == 0: write_set_to_file(gravity_code.orbiters, directory + 'Vanilla_run16_time=' + str(np.log10(times[i].value_in(units.yr)))[0:5] + '.hdf5', format='hdf5', overwrite_file = True) out_of_bounds, escaped_comets = [], [] for i in range(len(particle_system)): if particle_system[i].position.length() > 500 | units.AU: escaped_comets.append(particle_system[i].name) if particle_system[i].position.length() > 250000 | units.AU: out_of_bounds.append(particle_system[i]) dead_comets.append(particle_system[i]) for particle in out_of_bounds: particle_system.remove_particle(particle) particle_system.synchronize_to(gravity_code.particles) print("The amount of currently escaped comets is ", len(escaped_comets)) print("The amount of dead comets is ", len(dead_comets)) print("The planetary positions are ", gravity_code.orbiters[0].position.length().in_(units.AU), gravity_code.orbiters[1].position.length().in_(units.AU), gravity_code.orbiters[2].position.length().in_(units.AU), gravity_code.orbiters[3].position.length().in_(units.AU)) gravity_code.stop() write_set_to_file(gravity_code.orbiters, directory + 'Vanilla_run16_final.hdf5', format='hdf5', overwrite_file = True) return particle_system
def MWG_evolver(complete_post_tack_system, converter, N_objects, potential, end_time, time_step): #Initialise the gravity code and add the particles to it gravity_code = Huayno(converter) gravity_code.particles.add_particles(complete_post_tack_system) channel = gravity_code.particles.new_channel_to(complete_post_tack_system) gravity_bridge = 0 gravity_bridge = bridge.Bridge(use_threading=False) gravity_bridge.add_system(gravity_code, (potential,)) gravity_bridge.timestep = 100 |units.yr times = np.arange(0., end_time, time_step) | units.yr #All time steps to which we want to evolve the model #--------------------------------------------------------------------------------------------------------- #Here we define the planetary orbital parameters that should be returned to if the planets start moving too much current_sma = np.array([0, 0, 0, 0]) | units.AU correct_sma = np.array([5.4, 7.1, 10.5, 13]) | units.AU inclinations = np.array([0, 0, 0, 0]) | units.deg system = new_solar_system() system = system[system.mass > 10**-5 | units.MSun] # Takes gas giants and Sun only system.move_to_center() for k in range(4): orbital_elements = get_orbital_elements_from_binary(system[0]+ system[k+1], G=constants.G) inclinations[k] = orbital_elements[5] #------------------------------------------------------------------------------------------------------------ dead_comets = [] #Here all 'dead' comets are stored #Below the evolving starts for i in tqdm(range(len(times))): gravity_bridge.evolve_model(times[i]) channel.copy() #--------------------------------------------------------------------------------------------------------------- #Here we check if the planetary orbits are still 'correct' and act for three degrees of incorrectness. for j in range(4): current_sma[j] = sma_determinator(gravity_code.particles[0], gravity_code.particles[j+1]) for l in range(4): if abs(current_sma[l]/correct_sma[l]) > 1.25 or abs(current_sma[l]/correct_sma[l]) < 0.75: #The orbits are too much perturbed, so we end the simulation return elif abs(current_sma[l]/correct_sma[l]) > 1.05 or abs(current_sma[l]/correct_sma[l]) < 0.95: #The orbits are slightly perturbed, so we redefinie them print("Here", complete_post_tack_system[l+1].name, "was redefined") binary = Particles(0) binary.add_particle(gravity_code.particles[0]) binary.add_particle(gravity_code.particles[l+1]) orbital_params = get_orbital_elements_from_binary(binary, G = constants.G) true_anomaly, ascending_node, pericenter = orbital_params[4].in_(units.deg), orbital_params[6].in_(units.deg), orbital_params[7].in_(units.deg) sun_and_plan = new_binary_from_orbital_elements(1 | units.MSun, orbital_params[1], #We keep the current angles, but change the a, e and i back correct_sma[l], 0, true_anomaly, inclinations[l], ascending_node, pericenter, G=constants.G) gravity_code.particles[l+1].position = (sun_and_plan[1].x+gravity_code.particles[0].x, sun_and_plan[1].y+gravity_code.particles[0].y, sun_and_plan[1].z+gravity_code.particles[0].z) gravity_code.particles[l+1].velocity = (sun_and_plan[1].vx+gravity_code.particles[0].vx, sun_and_plan[1].vy+gravity_code.particles[0].vy, sun_and_plan[1].vz+gravity_code.particles[0].vz) else: #The orbits do not need changing pass #---------------------------------------------------------------------------------------------------------------------- #Once we checked for the orbital correctness, we can save data if i%4000 == 0: write_set_to_file(gravity_code.particles, directory + 'MWG_run' + str(run_number) +'_time=' + str(np.log10(times[i].value_in(units.yr)))[0:5] + '.hdf5', format='hdf5', overwrite_file = True) #-------------------------------------------------------------------------------------------------------------------- #Here we look for 'escaped' and 'out of bounds' comets out_of_bounds, escaped_comets = [], [] for i in range(len(gravity_code.particles)): if (gravity_code.particles[i].position-gravity_code.particles[0].position).length() > 500 | units.AU: escaped_comets.append(gravity_code.particles[i]) if (gravity_code.particles[i].position-gravity_code.particles[0].position).length() > 250000 | units.AU: out_of_bounds.append(gravity_code.particles[i]) dead_comets.append(gravity_code.particles[i]) for particle in out_of_bounds: #Out of bounds comets are removed completely complete_post_tack_system.remove_particle(particle) complete_post_tack_system.synchronize_to(gravity_code.particles) if i%100 == 0: print("The amount of currently escaped comets is ", len(escaped_comets)) print("The amount of dead comets is ", len(dead_comets)) for m in range(4): print(complete_post_tack_system[m+1].name, " is at ", (gravity_code.particles[m+1].position-gravity_code.particles[0].position).length().in_(units.AU)) gravity_code.stop() write_set_to_file(gravity_code.orbiters, directory + 'MWG_run' + str(run_number) +'_final.hdf5', format='hdf5', overwrite_file = True) return complete_post_tack