def simulate_system_until(particles, end_time): convert_nbody = nbody_system.nbody_to_si(1.0 | units.MSun, 149.5e6 | units.km) instance = Hermite(convert_nbody) instance.parameters.epsilon_squared = 0.0 | units.AU**2 instance.particles.add_particles(particles) t0 = 0 | units.day dt = 10 | units.day t = t0 earth = instance.particles[1] x_values = quantities.AdaptingVectorQuantity() y_values = quantities.AdaptingVectorQuantity() while t < end_time: instance.evolve_model(t) x_values.append(earth.x) y_values.append(earth.y) t += dt instance.stop() return x_values, y_values
def test8(self): """ test minimum periapse occurrence """ particles = create_nested_multiple( 3, [1.0 | units.MSun, 1.2 | units.MSun, 0.9 | units.MSun], [1.0 | units.AU, 100.0 | units.AU], [0.1, 0.5], [0.01, 80.0 * numpy.pi / 180.0], [0.01, 0.01], [0.01, 0.01]) binaries = particles[particles.is_binary] stars = particles - binaries binaries.check_for_minimum_periapse_distance = True rp_min = 0.1 | units.AU binaries.check_for_minimum_periapse_distance_value = rp_min code = SecularMultiple(redirection='none') code.particles.add_particles(particles) channel_to_code = particles.new_channel_to(code.particles) channel_from_code = code.particles.new_channel_to(particles) channel_to_code.copy() t = 0.0 | units.Myr dt = 5.0e-3 | units.Myr tend = 1.0e-1 | units.Myr t_print_array = quantities.AdaptingVectorQuantity() a_print_array = quantities.AdaptingVectorQuantity() e_print_array = quantities.AdaptingVectorQuantity() while (t < tend): t += dt code.evolve_model(t) flag = code.flag channel_from_code.copy() print('secular_breakdown_has_occurred', binaries.secular_breakdown_has_occurred) print('dynamical_instability_has_occurred', binaries.dynamical_instability_has_occurred) print('physical_collision_or_orbit_crossing_has_occurred', binaries.physical_collision_or_orbit_crossing_has_occurred) print('minimum_periapse_distance_has_occurred', binaries.minimum_periapse_distance_has_occurred) print('RLOF_at_pericentre_has_occurred', binaries.RLOF_at_pericentre_has_occurred) if flag == 2: print('root found') break print('t_end', code.model_time.value_in(units.Myr)) t_print_array.append(t) a_print_array.append(binaries[0].semimajor_axis) e_print_array.append(binaries[0].eccentricity | units.none)
def test3(self): """ test GW emission in 2-body system + collision detection """ particles = create_nested_multiple( 2, [1.0 | units.MSun, 1.0 | units.MJupiter], [0.1 | units.AU], [0.994], [0.01], [0.01], [0.01]) binaries = particles[particles.is_binary] stars = particles - binaries stars.radius = 0.0001 | units.AU binaries.check_for_physical_collision_or_orbit_crossing = True binaries.include_pairwise_25PN_terms = True code = SecularMultiple(redirection='none') code.particles.add_particles(particles) channel_to_code = particles.new_channel_to(code.particles) channel_from_code = code.particles.new_channel_to(particles) channel_to_code.copy() t_print_array = quantities.AdaptingVectorQuantity() a_print_array = quantities.AdaptingVectorQuantity() e_print_array = quantities.AdaptingVectorQuantity() AP_print_array = quantities.AdaptingVectorQuantity() tend = 1.0 | units.Gyr N = 0 t = 0.0 | units.Myr dt = 100.0 | units.Myr while (t < tend): t += dt N += 1 code.evolve_model(t) flag = code.flag if flag == 2: print('root found') break channel_from_code.copy() t_print_array.append(t) a_print_array.append(binaries[0].semimajor_axis) e_print_array.append(binaries[0].eccentricity | units.none) AP_print_array.append(binaries[0].argument_of_pericenter | units.none) print('e', binaries.eccentricity, 'a/AU', binaries.semimajor_axis.value_in(units.AU), 'rp/AU', (binaries.semimajor_axis * (1.0 - binaries.eccentricity)).value_in(units.AU))
def integrate_solar_system(sun, planets, time_end=5.0 | units.yr, n_steps=500): """ evolve the system using kepler_orbiters """ converter = nbody_system.nbody_to_si(1 | units.MSun, 1 | units.AU) planets_around_sun = Kepler(converter, channel_type="sockets") # central particle planets_around_sun.central_particle.add_particles(sun[0:1]) # to set the central particle at the center of the coordinate system #planets_around_sun.central_particle.position = (0.0, 0.0, 0.0) | units.AU #planets_around_sun.central_particle.velocity = (0.0, 0.0, 0.0) | units.kms # orbiters planets_around_sun.orbiters.add_particles(planets) planets_around_sun.commit_particles() # to change the integration method #planets_around_sun.parameters.method = 1 #print planets_around_sun.get_method() channel_from_planetets_to_framework = planets_around_sun.orbiters.new_channel_to( planets) channel_from_sun_to_framework = planets_around_sun.central_particle.new_channel_to( sun) positions_sun = quantities.AdaptingVectorQuantity() positions_planets = quantities.AdaptingVectorQuantity() dt = time_end / float(n_steps) time = 0.0 | units.yr print " ** evolving solar system for", time_end.in_( units.yr), ", with time-step of", dt.in_(units.yr) print " this might take a while" while time <= time_end: #print "\t", time.in_(units.yr) planets_around_sun.evolve_model(time) channel_from_planetets_to_framework.copy() channel_from_sun_to_framework.copy() positions_sun.append(sun.position) positions_planets.append(planets.position) time += dt print " **" planets_around_sun.stop() return positions_sun, positions_planets
def test2(self): """ test 1PN precession in 2-body system """ particles = create_nested_multiple( 2, [1.0 | units.MSun, 1.0 | units.MJupiter], [1.0 | units.AU], [0.99], [0.01], [0.01], [0.01]) binaries = particles[particles.is_binary] binaries.include_pairwise_1PN_terms = True code = SecularMultiple(redirection='none') code.particles.add_particles(particles) channel_to_code = particles.new_channel_to(code.particles) channel_from_code = code.particles.new_channel_to(particles) channel_to_code.copy() t = 0.0 | units.Myr dt = 1.0e-1 | units.Myr tend = 1.0e0 | units.Myr t_print_array = quantities.AdaptingVectorQuantity() a_print_array = quantities.AdaptingVectorQuantity() e_print_array = quantities.AdaptingVectorQuantity() AP_print_array = quantities.AdaptingVectorQuantity() N = 0 while (t < tend): t += dt N += 1 code.evolve_model(t) channel_from_code.copy() print('t/Myr', t.value_in(units.Myr), 'omega', binaries[0].argument_of_pericenter | units.none) t_print_array.append(t) a_print_array.append(binaries[0].semimajor_axis) e_print_array.append(binaries[0].eccentricity | units.none) AP_print_array.append(binaries[0].argument_of_pericenter | units.none) a = binaries[0].semimajor_axis e = binaries[0].eccentricity M = binaries[0].mass rg = constants.G * M / (constants.c**2) P = 2.0 * numpy.pi * numpy.sqrt(a**3 / (constants.G * M)) t_1PN = (1.0 / 3.0) * P * (1.0 - e**2) * (a / rg)
def make_histograms(self): """ plots histograms of the final sma results with respect to the initial sma values of the particles sma = semi-major axis """ ###### RE-FORMAT THIS ###### two_stars = self.initial_state[0:2] transferred_sma = quantities.AdaptingVectorQuantity() keys_passing = self.passing[-1].key transferred = self.initial_state.select(lambda x : x in keys_passing , ["key"]) for b in transferred: s_b = self.shift_to_star(b, two_stars, star_choice = 0) a, ecc, T = ps.orbital_parameters(s_b.position, s_b.velocity, self.info.m0) transferred_sma.append(a) ejected_sma = quantities.AdaptingVectorQuantity() keys_unbound = self.unbound[-1].key ejected = self.initial_state.select(lambda x : x in keys_unbound , ["key"]) for b in ejected: s_b = self.shift_to_star(b, two_stars, star_choice = 0) a, ecc, T = ps.orbital_parameters(s_b.position, s_b.velocity, self.info.m0) ejected_sma.append(a) ###### RE-FORMAT THIS ###### global_max = max( len(transferred_sma), len(ejected_sma) ) name = "/plot_transferred_semimajor_axes_histogram.png" ps.make_sm_axis_histogram(transferred_sma, name, PlotFactory.c_PASSING, step_size = 5, max_count = global_max) name = "/plot_transferred_semimajor_axes_histogram_cum.png" ps.make_sm_axis_histogram(transferred_sma, name, PlotFactory.c_PASSING, cum = True, max_count = global_max) name = "/plot_ejected_semimajor_axes_histogram.png" ps.make_sm_axis_histogram(ejected_sma, name, PlotFactory.c_UNBOUND, step_size = 5, max_count = global_max) name = "/plot_ejected_semimajor_axes_histogram_cum.png" ps.make_sm_axis_histogram(ejected_sma, name, PlotFactory.c_UNBOUND, cum = True, max_count = global_max)
def test1(self): """ test reference system of Naoz et al. (2009) """ particles = create_nested_multiple( 3, [1.0 | units.MSun, 1.0 | units.MJupiter, 40.0 | units.MJupiter], [6.0 | units.AU, 100.0 | units.AU], [0.001, 0.6], [0.0001, 65.0 * numpy.pi / 180.0], [45.0 * numpy.pi / 180.0, 0.0001], [0.01, 0.01]) binaries = particles[particles.is_binary] binaries.include_pairwise_1PN_terms = False code = SecularMultiple(redirection='none') code.particles.add_particles(particles) channel_to_code = particles.new_channel_to(code.particles) channel_from_code = code.particles.new_channel_to(particles) channel_to_code.copy() self.assertEqual(0.6, code.particles[particles.is_binary][1].eccentricity) t = 0.0 | units.Myr dt = 1.0e-2 | units.Myr tend = 3.0e0 | units.Myr t_print_array = quantities.AdaptingVectorQuantity() a_print_array = quantities.AdaptingVectorQuantity() e_print_array = quantities.AdaptingVectorQuantity() INCL_print_array = quantities.AdaptingVectorQuantity() AP_print_array = quantities.AdaptingVectorQuantity() N = 0 while (t < tend): t += dt N += 1 code.evolve_model(t) print('t/Myr = ', code.model_time.value_in(units.Myr)) channel_from_code.copy() t_print_array.append(t) a_print_array.append(binaries[0].semimajor_axis) e_print_array.append(binaries[0].eccentricity | units.none) INCL_print_array.append(binaries[0].inclination_relative_to_parent | units.none) AP_print_array.append(binaries[0].argument_of_pericenter | units.none)
def execute_main(o, arguments): """ the main method (callable internally (pseudo_main(args)) or from command line) """ # Orbital Elements planet_elements = Orb_Kepler(o.a_pl, o.e_pl, o.i_pl, o.M_pl, o.argw_pl, o.node_pl) binary_elements = Orb_Kepler(o.a_bin, o.e_bin, o.i_bin, o.M_bin, o.argw_bin, o.node_bin) # Star Masses mass_one = (o.mass_bin) * (1 - o.u_bin) mass_two = (o.mass_bin) * (o.u_bin) star_masses = quantities.AdaptingVectorQuantity() star_masses.append(mass_one) star_masses.append(mass_two) print star_masses, o.a_pl mkdir(o.dir) run_simulation(planet_elements, binary_elements, star_masses, o.eta, o.sim_time, o.n_steps, o.dir, o.fout, file_redir=o.file_redir)
def plot_distances(time, bodies): """ star distances vs time """ distances = quantities.AdaptingVectorQuantity() fig = init_fig() for b in bodies.history: two_stars = b[0:2] rel_position = two_stars[0].position - two_stars[1].position separation = rel_position.lengths() distances.append(separation) pyplot.xlabel('time (in kyr)') pyplot.ylabel('distance (in AU)') pyplot.plot(time.value_in(1000 * units.yr), distances.value_in(units.AU), c=colors[c_STARS]) pyplot.title("Star Separation Over Time") fn = snapshot_dir + "/star_separation.png" pyplot.savefig(fn) pyplot.cla() return distances
def get_list_element(self, index_in_the_list, index_of_the_particle ): """Returns an array of the positions for the indices in index_of_the_particle """ if not hasattr(index_in_the_list, '__iter__'): index_in_the_list = [index_in_the_list,] if not hasattr(index_of_the_particle, '__iter__'): index_of_the_particle = [index_of_the_particle,] value1 = quantities.AdaptingVectorQuantity() value2 = quantities.AdaptingVectorQuantity() for index_of_one_particle, index_of_one_element in zip(index_of_the_particle, index_in_the_list): value1.append(index_of_one_particle | units.none) value2.append(index_of_one_element | units.none) return value1, value2
def evolve_triple_system(binaries, end_time, output_time_step): code = SecularTriple() code.binaries.add_particles(binaries) ### quantities later used for plotting ### times_array = quantities.AdaptingVectorQuantity() e_in_array = [] i_tot_array = [] g_in_array = [] ### evolve system ### time = 0.0 | units.Myr while (time < end_time): code.evolve_model(time) time += output_time_step times_array.append(time) e_in_array.append(code.binaries[0].eccentricity) g_in_array.append(code.binaries[0].argument_of_pericenter) i_tot_array.append(code.binaries[0].inclination) print 'time/Myr', time.value_in( units.Myr), 'ein', code.binaries[0].eccentricity e_in_array = numpy.array(e_in_array) g_in_array = numpy.array(g_in_array) i_tot_array = numpy.array(i_tot_array) return times_array, e_in_array, g_in_array, i_tot_array
def get_position(self, index_of_the_particle): """Returns an array of the positions for the indices in index_of_the_particle """ xresult = quantities.AdaptingVectorQuantity() yresult = quantities.AdaptingVectorQuantity() zresult = quantities.AdaptingVectorQuantity() for index_element in index_of_the_particle: particle = self.mapping_from_id_to_particle[index_element] xresult.append(particle[2]) yresult.append(particle[3]) zresult.append(particle[4]) self.log("retrieved position of particle with id {0} (x = {1}, y = {2}, z = {3})", index_element, particle[2], particle[3], particle[4]) return xresult, yresult, zresult
def __init__(self, number, snapshot_dir = None, output_loc = None, snapshot_loc = None): # Output File number = '%03d' % number self.f1 = "outfile" + number + ".hdf5" if output_loc is not None: self.f1 = output_loc + "/" + self.f1 # Snapshot Directory if snapshot_dir is None: snapshot_dir = "snap" + number if snapshot_loc is not None: snapshot_dir = snapshot_loc + "/" + snapshot_dir self.snapshot_dir = snapshot_dir # Updates Here ps.set_snapshot_dir(snapshot_dir) # Updates Elsewhere # Bodies self.bodies = ps.parse_file(self.f1) # Simulation Info self.read_info_file() # Time self.times = quantities.AdaptingVectorQuantity() # Initialize States self.init_states() self.num_snapshots = len(self.times) self.save_star_separation() # Sorted Bodies + Keys (Change this to particle sets instead) self.unbound = np.zeros(len(self.times), dtype = np.ndarray) # These are arrays of Particle sets self.central = np.zeros(len(self.times), dtype = np.ndarray) self.passing = np.zeros(len(self.times), dtype = np.ndarray) self.both = np.zeros(len(self.times), dtype = np.ndarray) self.tmp_mask = np.zeros(len(self.times)) # for before the mask is applied self.mask = np.zeros(len(self.times)) # 1 indicates 'sorting' has occured at particular timestep # This mask needs to be incorporated into functions using sorted sets # For instance, the self.times array will need to be restricted to masked values ################# DO NOT MODIFY THE MASK DIRECTLY!!!!!! (switch to private?) ################ # Restore Sorts print " *** Restoring *** " self.restore() # Misc self.tmp_movie_dir = "tmp_movies_for_factory"
def compress_array(self, array, mask): """ Given an array and a mask of equal length, return the array where the masked entries are selected""" copy = list(array) compressed = [ x for i,x in enumerate(copy) if mask[i] ] # e.g. array = [1,2,3,4,5], mask = [1,0,0,1,0] ---> compressed = [1,4] vector = quantities.AdaptingVectorQuantity() # formatting issues (is there a better way?) for x in compressed: vector.append(x) return vector
def get_state(self, index_of_the_particle): """Returns arrays for the mass, x, y and z values """ massresult = quantities.AdaptingVectorQuantity() xresult = quantities.AdaptingVectorQuantity() yresult = quantities.AdaptingVectorQuantity() zresult = quantities.AdaptingVectorQuantity() for index_element in index_of_the_particle: particle = self.mapping_from_id_to_particle[index_element] massresult.append(particle[1]) xresult.append(particle[2]) yresult.append(particle[3]) zresult.append(particle[4]) self.log("retrieved state of particle with id {0}", index_element) return massresult, xresult, yresult, zresult
def get_value(self, parameter, object): if self.must_set_before_get and not parameter.is_set: self.set_default_value(parameter, object) if self.get_method is None: return self.stored_value else: list_of_scalars = getattr(object, self.get_method)() result = quantities.AdaptingVectorQuantity() result.extend(list_of_scalars) return result.copy()
def evolve_triple_system(binaries,end_time,output_time_step): code = SecularTriple() code.binaries.add_particles(binaries) code.parameters.equations_of_motion_specification = 0 code.parameters.f_quad = 1.0 code.parameters.f_oct = 1.0 code.parameters.f_mass_transfer = 0.0 code.parameters.f_1PN_in = 0.0 code.parameters.f_1PN_out = 0.0 code.parameters.f_25PN_in = 0.0 code.parameters.f_25PN_out = 0.0 # code.parameters.f_quad = 1.0 # code.parameters.f_oct = 1.0 # code.parameters.f_tides = 1.0 # code.parameters.f_mass_transfer = 0.0 ### quantities later used for plotting ### times_array = quantities.AdaptingVectorQuantity() a_in_array = quantities.AdaptingVectorQuantity() e_in_array = [] i_tot_array = [] g_in_array = [] time = 0.0 | units.Myr while (time < end_time): code.evolve_model(time) time += output_time_step times_array.append(time) e_in_array.append(code.binaries[0].eccentricity) a_in_array.append(code.binaries[0].semimajor_axis) g_in_array.append(code.binaries[0].argument_of_pericenter) i_tot_array.append(code.binaries[0].inclination) print 'time/Myr',time.value_in(units.Myr),'ein',code.binaries[0].eccentricity,'ain/AU',code.binaries[0].semimajor_axis.value_in(units.AU),'Omega1/(/yr)',code.binaries[0].child1.spin_angular_frequency.value_in(1.0/units.yr) e_in_array = numpy.array(e_in_array) g_in_array = numpy.array(g_in_array) i_tot_array = numpy.array(i_tot_array) return times_array,a_in_array,e_in_array,g_in_array,i_tot_array
def get_gravity_at_point(self, radius, x, y, z): positions = self.particles.position m1 = self.particles.mass result_ax = quantities.AdaptingVectorQuantity() result_ay = quantities.AdaptingVectorQuantity() result_az = quantities.AdaptingVectorQuantity() for i in range(len(x)): dx = x[i] - positions.x dy = y[i] - positions.y dz = z[i] - positions.z dr_squared = ((dx * dx) + (dy * dy) + (dz * dz) + self._softening_lengths_squared() + radius[i]**2) ax = -self.gravity_constant * (m1 * dx / dr_squared**1.5).sum() ay = -self.gravity_constant * (m1 * dy / dr_squared**1.5).sum() az = -self.gravity_constant * (m1 * dz / dr_squared**1.5).sum() result_ax.append(ax) result_ay.append(ay) result_az.append(az) return result_ax, result_ay, result_az
def get_potential_at_point(self, radius, x, y, z): positions = self.particles.position result = quantities.AdaptingVectorQuantity() for i in range(len(x)): dx = x[i] - positions.x dy = y[i] - positions.y dz = z[i] - positions.z dr_squared = (dx * dx) + (dy * dy) + (dz * dz) dr = (dr_squared + self.softening_lengths_squared).sqrt() energy_of_this_particle = (self.particles.mass / dr).sum() result.append(-self.gravity_constant * energy_of_this_particle) return result
def get_mass(self, index_of_the_particle): """Returns an array for the masses of the indices int the index_of_the_particle array """ massresult = quantities.AdaptingVectorQuantity() for index_element in index_of_the_particle: particle = self.mapping_from_id_to_particle[index_element] massresult.append(particle[1]) self.log("retrieved mass of particle with id {0} (mass = {1})", index_element, particle[1]) return massresult
def integrate_solar_system(particles, end_time): from amuse.lab import Huayno, nbody_system from amuse.units import quantities convert_nbody = nbody_system.nbody_to_si(particles.mass.sum(), particles[1].position.length()) gravity = Huayno(convert_nbody) gravity.particles.add_particles(particles) venus = gravity.particles[1] earth = gravity.particles[2] x_earth = quantities.AdaptingVectorQuantity() y_earth = quantities.AdaptingVectorQuantity() x_venus = quantities.AdaptingVectorQuantity() y_venus = quantities.AdaptingVectorQuantity() while gravity.model_time < end_time: gravity.evolve_model(gravity.model_time + (10 | units.day)) x_earth.append(earth.x) y_earth.append(earth.y) x_venus.append(venus.x) y_venus.append(venus.y) gravity.stop() return x_earth, y_earth, x_venus, y_venus
def minmax(self): "The extent of the grid, array with 6 float xmin, xmax, ymin, ymax, zmin, zmax" if not self.set is None: xmin = self.set.x.min() xmax = self.set.x.max() ymin = self.set.y.min() ymax = self.set.y.max() zmin = self.set.z.min() zmax = self.set.z.max() result = quantities.AdaptingVectorQuantity() result.append(xmin) result.append(xmax) result.append(ymin) result.append(ymax) result.append(zmin) result.append(zmax) return result.append(zmax) if 'x' in self.attribute_names and 'y' in self.attribute_names and 'z' in self.attribute_names: pass
def test7(self): """ test collision detection in 3-body system """ particles = create_nested_multiple( 3, [1.0 | units.MSun, 1.2 | units.MSun, 0.9 | units.MSun], [1.0 | units.AU, 100.0 | units.AU], [0.1, 0.5], [0.01, 80.0 * numpy.pi / 180.0], [0.01, 0.01], [0.01, 0.01]) binaries = particles[particles.is_binary] stars = particles - binaries binaries.check_for_physical_collision_or_orbit_crossing = True stars.radius = 0.03 | units.AU code = SecularMultiple(redirection='none') code.particles.add_particles(particles) channel_to_code = particles.new_channel_to(code.particles) channel_from_code = code.particles.new_channel_to(particles) channel_to_code.copy() t = 0.0 | units.Myr dt = 1.0e-2 | units.Myr tend = 1.0e-1 | units.Myr t_print_array = quantities.AdaptingVectorQuantity() a_print_array = quantities.AdaptingVectorQuantity() e_print_array = quantities.AdaptingVectorQuantity() while (t < tend): t += dt code.evolve_model(t) flag = code.flag channel_from_code.copy() print('secular_breakdown_has_occurred', binaries.secular_breakdown_has_occurred) print('dynamical_instability_has_occurred', binaries.dynamical_instability_has_occurred) print('physical_collision_or_orbit_crossing_has_occurred', binaries.physical_collision_or_orbit_crossing_has_occurred) print('minimum_periapse_distance_has_occurred', binaries.minimum_periapse_distance_has_occurred) print('RLOF_at_pericentre_has_occurred', binaries.RLOF_at_pericentre_has_occurred) if flag == 2: print('root found') break print('t_end', code.model_time.value_in(units.Myr)) t_print_array.append(t) a_print_array.append(binaries[0].semimajor_axis) e_print_array.append(binaries[0].eccentricity | units.none) if HAS_MATPLOTLIB == True: fig = pyplot.figure() plot = fig.add_subplot(2, 1, 1) plot.plot(t_print_array.value_in(units.Myr), e_print_array.value_in(units.none)) plot = fig.add_subplot(2, 1, 2) plot.plot( t_print_array.value_in(units.Myr), a_print_array.value_in(units.AU) * (1.0 - e_print_array.value_in(units.none))) plot.axhline(y=stars[0].radius.value_in(units.AU) + stars[1].radius.value_in(units.AU), color='k') pyplot.show()
def test6(self): """ test precession due to rotation """ M = 1.0 | units.MJupiter R = 1.5 | units.RJupiter m_per = 1.0 | units.MSun a0 = 30.0 | units.AU e0 = 0.999 P0 = 2.0 * numpy.pi * numpy.sqrt(a0**3 / (constants.G * (M + m_per))) n0 = 2.0 * numpy.pi / P0 aF = a0 * (1.0 - e0**2) nF = numpy.sqrt(constants.G * (M + m_per) / (aF**3)) particles = create_nested_multiple(2, [m_per, M], [a0], [e0], [1.0e-5], [1.0e-5], [1.0e-5]) binaries = particles[particles.is_binary] particles[0].radius = 1.0 | units.RSun particles[1].radius = R particles[1].spin_vec_x = 0.0 | 1.0 / units.day particles[1].spin_vec_y = 0.0 | 1.0 / units.day Omega_PS0 = n0 * (33.0 / 10.0) * pow(a0 / aF, 3.0 / 2.0) particles[1].spin_vec_z = Omega_PS0 k_L = 0.51 k_AM = k_L / 2.0 rg = 0.25 particles[1].tides_method = 1 particles[1].include_tidal_friction_terms = False particles[1].include_tidal_bulges_precession_terms = False particles[1].include_rotation_precession_terms = True particles[1].minimum_eccentricity_for_tidal_precession = 1.0e-5 particles[1].tides_apsidal_motion_constant = k_AM particles[1].tides_gyration_radius = rg code = SecularMultiple(redirection='none') code.particles.add_particles(particles) channel_to_code = particles.new_channel_to(code.particles) channel_from_code = code.particles.new_channel_to(particles) channel_to_code.copy() t = 0.0 | units.Myr dt = 1.0e1 | units.Myr tend = 1.0e2 | units.Myr t_print_array = quantities.AdaptingVectorQuantity() a_print_array = quantities.AdaptingVectorQuantity() e_print_array = quantities.AdaptingVectorQuantity() AP_print_array = quantities.AdaptingVectorQuantity() Omega_vec = [ particles[1].spin_vec_x, particles[1].spin_vec_y, particles[1].spin_vec_z ] Omega = numpy.sqrt(Omega_vec[0]**2 + Omega_vec[1]**2 + Omega_vec[2]**2) print('Omega/n', Omega / n0) g_dot_rot = n0 * (1.0 + m_per / M) * k_AM * pow( R / a0, 5.0) * (Omega / n0)**2 / ((1.0 - e0**2)**2) t_rot = 2.0 * numpy.pi / g_dot_rot print('t_rot/Myr', t_rot.value_in(units.Myr)) N = 0 while (t < tend): t += dt code.evolve_model(t) print('flag', code.flag, t, binaries[0].semimajor_axis, binaries[0].eccentricity) channel_from_code.copy() t_print_array.append(t) a_print_array.append(binaries[0].semimajor_axis) e_print_array.append(binaries[0].eccentricity | units.none) AP_print_array.append(binaries[0].argument_of_pericenter | units.none) N += 1 if HAS_MATPLOTLIB == True: fig = pyplot.figure(figsize=(16, 10)) plot1 = fig.add_subplot(4, 1, 1) plot2 = fig.add_subplot(4, 1, 2, yscale="log") plot3 = fig.add_subplot(4, 1, 3, yscale="log") plot4 = fig.add_subplot(4, 1, 4, yscale="log") plot1.plot(t_print_array.value_in(units.Myr), AP_print_array.value_in(units.none), color='r') points = numpy.linspace(0.0, tend.value_in(units.Myr), N) AP = 0.01 + 2.0 * numpy.pi * points / (t_rot.value_in(units.Myr)) AP = (AP + numpy.pi) % (2.0 * numpy.pi) - numpy.pi ### -pi < AP < pi plot1.plot(points, AP, color='g') plot2.plot(t_print_array.value_in(units.Myr), numpy.fabs( (AP - AP_print_array.value_in(units.none)) / AP), color='r') plot3.plot(t_print_array.value_in(units.Myr), numpy.fabs((a0 - a_print_array) / a0), color='r') plot4.plot(t_print_array.value_in(units.Myr), numpy.fabs((e0 - e_print_array) / e0), color='r') fontsize = 15 plot1.set_ylabel("$\omega$", fontsize=fontsize) plot2.set_ylabel("$|(\omega_p-\omega)/\omega_p|$", fontsize=fontsize) plot3.set_ylabel("$|(a_0-a)/a_0|$", fontsize=fontsize) plot4.set_ylabel("$|(e_0-e)/e_0|$", fontsize=fontsize) pyplot.show()
def test4(self): """ test tidal friction in 2-body system """ M = 1.0 | units.MJupiter R = 40.0 | units.RJupiter m_per = 1.0 | units.MSun m = m_per mu = m * M / (m + M) a0 = 0.1 | units.AU e0 = 0.3 P0 = 2.0 * numpy.pi * numpy.sqrt(a0**3 / (constants.G * (M + m_per))) n0 = 2.0 * numpy.pi / P0 aF = a0 * (1.0 - e0**2) nF = numpy.sqrt(constants.G * (M + m_per) / (aF**3)) particles = create_nested_multiple(2, [m_per, M], [a0], [e0], [0.01], [0.01], [0.01]) binaries = particles[particles.is_binary] particles[0].radius = 1.0 | units.RSun particles[1].radius = R particles[1].spin_vec_x = 0.0 | 1.0 / units.day particles[1].spin_vec_y = 0.0 | 1.0 / units.day particles[1].spin_vec_z = 4.0e-2 | 1.0 / units.day k_L = 0.38 k_AM = k_L / 2.0 rg = 0.25 tau = 0.66 | units.s I = rg * M * R**2 alpha = I / (mu * a0**2) T = R**3 / (constants.G * M * tau) t_V = 3.0 * (1.0 + 1.0 / k_L) * T particles[1].tides_method = 2 particles[1].include_tidal_friction_terms = True particles[1].include_tidal_bulges_precession_terms = False particles[1].include_rotation_precession_terms = False particles[1].minimum_eccentricity_for_tidal_precession = 1.0e-8 particles[1].tides_apsidal_motion_constant = k_AM particles[1].tides_viscous_time_scale = t_V particles[1].tides_gyration_radius = rg tD = M * aF**8 / (3.0 * k_L * tau * constants.G * m_per * (M + m_per) * R**5) particles[2].check_for_physical_collision_or_orbit_crossing = True code = SecularMultiple(redirection='none') code.particles.add_particles(particles) code.parameters.relative_tolerance = 1.0e-14 channel_to_code = particles.new_channel_to(code.particles) channel_from_code = code.particles.new_channel_to(particles) channel_to_code.copy() t = 0.0 | units.Myr dt = 1.0e-5 | units.Myr tend = 1.0e-4 | units.Myr t_print_array = quantities.AdaptingVectorQuantity() a_print_array = quantities.AdaptingVectorQuantity() n_print_array = quantities.AdaptingVectorQuantity() e_print_array = quantities.AdaptingVectorQuantity() AP_print_array = quantities.AdaptingVectorQuantity() spin_print_array = quantities.AdaptingVectorQuantity() while (t < tend): t += dt code.evolve_model(t) print('flag', code.flag, t, 'a/AU', binaries[0].semimajor_axis, 'e', binaries[0].eccentricity) channel_from_code.copy() t_print_array.append(t) a_print_array.append(binaries[0].semimajor_axis) n_print_array.append( numpy.sqrt(constants.G * (M + m) / (binaries[0].semimajor_axis**3))) e_print_array.append(binaries[0].eccentricity | units.none) AP_print_array.append(binaries[0].argument_of_pericenter | units.none) spin_print_array.append( numpy.sqrt(particles[1].spin_vec_x**2 + particles[1].spin_vec_y**2 + particles[1].spin_vec_z**2)) binaries = particles[particles.is_binary] bodies = particles - binaries print('S_x', bodies.spin_vec_x.value_in(1.0 / units.day)) print('S_y', bodies.spin_vec_y.value_in(1.0 / units.day)) print('S_z', bodies.spin_vec_z.value_in(1.0 / units.day)) print('=' * 50) if HAS_MATPLOTLIB == True: fig = pyplot.figure() fontsize = 12 N_p = 4 plot1 = fig.add_subplot(N_p, 1, 1) plot1.plot(t_print_array.value_in(units.Myr), a_print_array.value_in(units.AU), color='r') plot1.set_ylabel("$a/\mathrm{AU}$", fontsize=fontsize) plot2 = fig.add_subplot(N_p, 1, 2) plot2.plot(t_print_array.value_in(units.Myr), e_print_array.value_in(units.none), color='k') plot2.set_ylabel("$e$", fontsize=fontsize) plot3 = fig.add_subplot(N_p, 1, 3, yscale="log") plot3.plot(t_print_array.value_in(units.Myr), a_print_array.value_in(units.AU) * (1.0 - e_print_array.value_in(units.none)**2), color='k') plot3.axhline(y=a0.value_in(units.AU) * (1.0 - e0**2), color='k') plot3.set_ylabel("$a(1-e^2)/\mathrm{AU}$", fontsize=fontsize) plot4 = fig.add_subplot(N_p, 1, 4) plot4.plot(t_print_array.value_in(units.Myr), spin_print_array / n_print_array) plot4.set_ylabel("$\Omega/n$", fontsize=fontsize) plot4.set_xlabel("$t/\mathrm{Myr}$", fontsize=fontsize) pyplot.show()
def test3(self): """ test GW emission in 2-body system + collision detection """ particles = create_nested_multiple( 2, [1.0 | units.MSun, 1.0 | units.MJupiter], [0.1 | units.AU], [0.994], [0.01], [0.01], [0.01]) binaries = particles[particles.is_binary] stars = particles - binaries stars.radius = 0.0001 | units.AU binaries.check_for_physical_collision_or_orbit_crossing = True binaries.include_pairwise_25PN_terms = True code = SecularMultiple(redirection='none') code.particles.add_particles(particles) channel_to_code = particles.new_channel_to(code.particles) channel_from_code = code.particles.new_channel_to(particles) channel_to_code.copy() t_print_array = quantities.AdaptingVectorQuantity() a_print_array = quantities.AdaptingVectorQuantity() e_print_array = quantities.AdaptingVectorQuantity() AP_print_array = quantities.AdaptingVectorQuantity() tend = 1.0 | units.Gyr N = 0 t = 0.0 | units.Myr dt = 100.0 | units.Myr while (t < tend): t += dt N += 1 code.evolve_model(t) flag = code.flag if flag == 2: print('root found') break channel_from_code.copy() t_print_array.append(t) a_print_array.append(binaries[0].semimajor_axis) e_print_array.append(binaries[0].eccentricity | units.none) AP_print_array.append(binaries[0].argument_of_pericenter | units.none) print('e', binaries.eccentricity, 'a/AU', binaries.semimajor_axis.value_in(units.AU), 'rp/AU', (binaries.semimajor_axis * (1.0 - binaries.eccentricity)).value_in(units.AU)) if HAS_MATPLOTLIB == True: fig = pyplot.figure(figsize=(16, 10)) plot1 = fig.add_subplot(2, 1, 1) plot2 = fig.add_subplot(2, 1, 2, yscale="log") plot1.plot(t_print_array.value_in(units.Myr), e_print_array.value_in(units.none), color='r') plot2.plot(t_print_array.value_in(units.Myr), a_print_array.value_in(units.AU), color='r') fontsize = 15 plot1.set_ylabel("$e$", fontsize=fontsize) plot2.set_ylabel("$a/\mathrm{AU}$", fontsize=fontsize) plot2.set_xlabel("$t/\mathrm{Myr}$", fontsize=fontsize) pyplot.show()
def test2(self): """ test 1PN precession in 2-body system """ particles = create_nested_multiple( 2, [1.0 | units.MSun, 1.0 | units.MJupiter], [1.0 | units.AU], [0.99], [0.01], [0.01], [0.01]) binaries = particles[particles.is_binary] binaries.include_pairwise_1PN_terms = True code = SecularMultiple(redirection='none') code.particles.add_particles(particles) channel_to_code = particles.new_channel_to(code.particles) channel_from_code = code.particles.new_channel_to(particles) channel_to_code.copy() t = 0.0 | units.Myr dt = 1.0e-1 | units.Myr tend = 1.0e0 | units.Myr t_print_array = quantities.AdaptingVectorQuantity() a_print_array = quantities.AdaptingVectorQuantity() e_print_array = quantities.AdaptingVectorQuantity() AP_print_array = quantities.AdaptingVectorQuantity() N = 0 while (t < tend): t += dt N += 1 code.evolve_model(t) channel_from_code.copy() print('t/Myr', t.value_in(units.Myr), 'omega', binaries[0].argument_of_pericenter | units.none) t_print_array.append(t) a_print_array.append(binaries[0].semimajor_axis) e_print_array.append(binaries[0].eccentricity | units.none) AP_print_array.append(binaries[0].argument_of_pericenter | units.none) a = binaries[0].semimajor_axis e = binaries[0].eccentricity M = binaries[0].mass rg = constants.G * M / (constants.c**2) P = 2.0 * numpy.pi * numpy.sqrt(a**3 / (constants.G * M)) t_1PN = (1.0 / 3.0) * P * (1.0 - e**2) * (a / rg) if HAS_MATPLOTLIB == True: fig = pyplot.figure(figsize=(16, 10)) plot1 = fig.add_subplot(4, 1, 1) plot2 = fig.add_subplot(4, 1, 2, yscale="log") plot3 = fig.add_subplot(4, 1, 3, yscale="log") plot4 = fig.add_subplot(4, 1, 4, yscale="log") plot1.plot(t_print_array.value_in(units.Myr), AP_print_array.value_in(units.none), color='r') points = numpy.linspace(0.0, tend.value_in(units.Myr), N) AP = 0.01 + 2.0 * numpy.pi * points / (t_1PN.value_in(units.Myr)) AP = (AP + numpy.pi) % (2.0 * numpy.pi) - numpy.pi ### -pi < AP < pi plot1.plot(points, AP, color='g') plot2.plot(t_print_array.value_in(units.Myr), numpy.fabs( (AP - AP_print_array.value_in(units.none)) / AP), color='r') plot3.plot(t_print_array.value_in(units.Myr), numpy.fabs((a - a_print_array) / a), color='r') plot4.plot(t_print_array.value_in(units.Myr), numpy.fabs((e - e_print_array) / e), color='r') fontsize = 15 plot1.set_ylabel("$\omega$", fontsize=fontsize) plot2.set_ylabel("$|(\omega_p-\omega)/\omega_p|$", fontsize=fontsize) plot3.set_ylabel("$|(a_0-a)/a_0|$", fontsize=fontsize) plot4.set_ylabel("$|(e_0-e)/e_0|$", fontsize=fontsize) pyplot.show()
def test1(self): """ test reference system of Naoz et al. (2009) """ particles = create_nested_multiple( 3, [1.0 | units.MSun, 1.0 | units.MJupiter, 40.0 | units.MJupiter], [6.0 | units.AU, 100.0 | units.AU], [0.001, 0.6], [0.0001, 65.0 * numpy.pi / 180.0], [45.0 * numpy.pi / 180.0, 0.0001], [0.01, 0.01]) binaries = particles[particles.is_binary] binaries.include_pairwise_1PN_terms = False code = SecularMultiple(redirection='none') code.particles.add_particles(particles) channel_to_code = particles.new_channel_to(code.particles) channel_from_code = code.particles.new_channel_to(particles) channel_to_code.copy() self.assertEqual(0.6, code.particles[particles.is_binary][1].eccentricity) t = 0.0 | units.Myr dt = 1.0e-2 | units.Myr tend = 3.0e0 | units.Myr t_print_array = quantities.AdaptingVectorQuantity() a_print_array = quantities.AdaptingVectorQuantity() e_print_array = quantities.AdaptingVectorQuantity() INCL_print_array = quantities.AdaptingVectorQuantity() AP_print_array = quantities.AdaptingVectorQuantity() N = 0 while (t < tend): t += dt N += 1 code.evolve_model(t) print('t/Myr = ', code.model_time.value_in(units.Myr)) channel_from_code.copy() t_print_array.append(t) a_print_array.append(binaries[0].semimajor_axis) e_print_array.append(binaries[0].eccentricity | units.none) INCL_print_array.append(binaries[0].inclination_relative_to_parent | units.none) AP_print_array.append(binaries[0].argument_of_pericenter | units.none) if HAS_MATPLOTLIB == True: fig = pyplot.figure(figsize=(16, 10)) plot1 = fig.add_subplot(2, 1, 1) plot2 = fig.add_subplot(2, 1, 2, yscale="log") plot1.plot(t_print_array.value_in(units.Myr), (180.0 / numpy.pi) * INCL_print_array.value_in(units.none), color='k') plot2.plot(t_print_array.value_in(units.Myr), 1.0 - e_print_array.value_in(units.none), color='k') fontsize = 15 plot1.set_ylabel("$i$", fontsize=fontsize) plot2.set_ylabel("$1-e$", fontsize=fontsize) plot2.set_xlabel("$t/\mathrm{Myr}$", fontsize=fontsize) pyplot.show()
def test6(self): """ test precession due to rotation """ M = 1.0 | units.MJupiter R = 1.5 | units.RJupiter m_per = 1.0 | units.MSun a0 = 30.0 | units.AU e0 = 0.999 P0 = 2.0 * numpy.pi * numpy.sqrt(a0**3 / (constants.G * (M + m_per))) n0 = 2.0 * numpy.pi / P0 aF = a0 * (1.0 - e0**2) nF = numpy.sqrt(constants.G * (M + m_per) / (aF**3)) particles = create_nested_multiple(2, [m_per, M], [a0], [e0], [1.0e-5], [1.0e-5], [1.0e-5]) binaries = particles[particles.is_binary] particles[0].radius = 1.0 | units.RSun particles[1].radius = R particles[1].spin_vec_x = 0.0 | 1.0 / units.day particles[1].spin_vec_y = 0.0 | 1.0 / units.day Omega_PS0 = n0 * (33.0 / 10.0) * pow(a0 / aF, 3.0 / 2.0) particles[1].spin_vec_z = Omega_PS0 k_L = 0.51 k_AM = k_L / 2.0 rg = 0.25 particles[1].tides_method = 1 particles[1].include_tidal_friction_terms = False particles[1].include_tidal_bulges_precession_terms = False particles[1].include_rotation_precession_terms = True particles[1].minimum_eccentricity_for_tidal_precession = 1.0e-5 particles[1].tides_apsidal_motion_constant = k_AM particles[1].tides_gyration_radius = rg code = SecularMultiple(redirection='none') code.particles.add_particles(particles) channel_to_code = particles.new_channel_to(code.particles) channel_from_code = code.particles.new_channel_to(particles) channel_to_code.copy() t = 0.0 | units.Myr dt = 1.0e1 | units.Myr tend = 1.0e2 | units.Myr t_print_array = quantities.AdaptingVectorQuantity() a_print_array = quantities.AdaptingVectorQuantity() e_print_array = quantities.AdaptingVectorQuantity() AP_print_array = quantities.AdaptingVectorQuantity() Omega_vec = [ particles[1].spin_vec_x, particles[1].spin_vec_y, particles[1].spin_vec_z ] Omega = numpy.sqrt(Omega_vec[0]**2 + Omega_vec[1]**2 + Omega_vec[2]**2) print('Omega/n', Omega / n0) g_dot_rot = n0 * (1.0 + m_per / M) * k_AM * pow( R / a0, 5.0) * (Omega / n0)**2 / ((1.0 - e0**2)**2) t_rot = 2.0 * numpy.pi / g_dot_rot print('t_rot/Myr', t_rot.value_in(units.Myr)) N = 0 while (t < tend): t += dt code.evolve_model(t) print('flag', code.flag, t, binaries[0].semimajor_axis, binaries[0].eccentricity) channel_from_code.copy() t_print_array.append(t) a_print_array.append(binaries[0].semimajor_axis) e_print_array.append(binaries[0].eccentricity | units.none) AP_print_array.append(binaries[0].argument_of_pericenter | units.none) N += 1
def test5(self): """ test precession due to tidal bulges """ M = 1.0 | units.MJupiter R = 1.0 | units.RJupiter m_per = 1.0 | units.MSun a0 = 30.0 | units.AU e0 = 0.999 P0 = 2.0 * numpy.pi * numpy.sqrt(a0**3 / (constants.G * (M + m_per))) n0 = 2.0 * numpy.pi / P0 particles = create_nested_multiple(2, [m_per, M], [a0], [e0], [0.01], [0.01], [0.01]) binaries = particles[particles.is_binary] particles[0].radius = 1.0 | units.RSun particles[1].radius = R k_L = 0.41 k_AM = k_L / 2.0 particles[1].tides_method = 0 particles[1].include_tidal_friction_terms = False particles[1].include_tidal_bulges_precession_terms = True particles[1].include_rotation_precession_terms = False particles[1].minimum_eccentricity_for_tidal_precession = 1.0e-5 particles[1].tides_apsidal_motion_constant = k_AM particles[1].tides_gyration_radius = 0.25 code = SecularMultiple(redirection='none') code.particles.add_particles(particles) channel_to_code = particles.new_channel_to(code.particles) channel_from_code = code.particles.new_channel_to(particles) channel_to_code.copy() t = 0.0 | units.Myr dt = 1.0e1 | units.Myr tend = 1.0e2 | units.Myr t_print_array = quantities.AdaptingVectorQuantity() a_print_array = quantities.AdaptingVectorQuantity() e_print_array = quantities.AdaptingVectorQuantity() AP_print_array = quantities.AdaptingVectorQuantity() g_dot_TB = (15.0 / 8.0) * n0 * (8.0 + 12.0 * e0**2 + e0**4) * ( m_per / M) * k_AM * pow(R / a0, 5.0) / pow(1.0 - e0**2, 5.0) t_TB = 2.0 * numpy.pi / g_dot_TB N = 0 while (t < tend): t += dt code.evolve_model(t) print('flag', code.flag, t, binaries[0].semimajor_axis, binaries[0].eccentricity) channel_from_code.copy() t_print_array.append(t) a_print_array.append(binaries[0].semimajor_axis) e_print_array.append(binaries[0].eccentricity | units.none) AP_print_array.append(binaries[0].argument_of_pericenter | units.none) N += 1