def evolve_quadruple(N_output, end_time, m1, m2, m3, m4, aA, aB, aC, eA, eB, eC, iA, iB, iC, ApA, ApB, ApC, LANA, LANB, LANC): masses = [m1, m2, m3, m4] semimajor_axis = [aA, aB, aC] eccentricity = [eA, eB, eC] inclination = numpy.deg2rad([iA, iB, iC]) argument_of_percienter = numpy.deg2rad([ApA, ApB, ApC]) longitude_of_ascending_node = numpy.deg2rad([LANA, LANB, LANC]) print longitude_of_ascending_node N_bodies = 4 N_binaries = N_bodies-1 particles, binaries = initialize_multiple_system(N_bodies, masses, semimajor_axis, eccentricity, inclination, argument_of_percienter, longitude_of_ascending_node) code = SecularMultiple() code.particles.add_particles(particles) channel_from_particles_to_code = particles.new_channel_to(code.particles) channel_from_code_to_particles = code.particles.new_channel_to(particles) channel_from_particles_to_code.copy() ### set up some arrays for plotting ### print_smas_AU = [[] for x in range(N_binaries)] print_rps_AU = [[] for x in range(N_binaries)] print_parent_is_deg = [[] for x in range(N_binaries)] print_times_Myr = [] time = 0.0|units.yr output_time_step = end_time/float(N_output) while time <= end_time: time += output_time_step code.evolve_model(time) channel_from_code_to_particles.copy() print '='*50 print 't/Myr',time.value_in(units.Myr) print 'e',binaries.eccentricity print 'i/deg', numpy.rad2deg(binaries.inclination) print 'AP/deg', \ numpy.rad2deg(binaries.argument_of_pericenter) print 'LAN/deg', \ numpy.rad2deg(binaries.longitude_of_ascending_node) ### write to output arrays ### print_times_Myr.append(time.value_in(units.Myr)) for index_binary in range(N_binaries): print_smas_AU[index_binary].append( binaries[index_binary].semimajor_axis.value_in(units.AU) ) print_rps_AU[index_binary].append( binaries[index_binary].semimajor_axis.value_in(units.AU)*(1.0 - binaries[index_binary].eccentricity) ) print_parent_is_deg[index_binary].append( numpy.rad2deg(binaries[index_binary].inclination_relative_to_parent) ) ### compute the `canonical' maximum eccentricity/periapsis distance that applies in the quadrupole-order test-particle limit if the `outer' binary is replaced by a point mass ### print inclination[0],inclination[2],longitude_of_ascending_node[0],longitude_of_ascending_node[2] i_AC_init = compute_mutual_inclination(inclination[0],inclination[2],longitude_of_ascending_node[0],longitude_of_ascending_node[2]) i_BC_init = compute_mutual_inclination(inclination[1],inclination[2],longitude_of_ascending_node[1],longitude_of_ascending_node[2]) canonical_rp_min_A_AU = (semimajor_axis[0]*(1.0 - numpy.sqrt( 1.0 - (5.0/3.0)*numpy.cos(i_AC_init)**2 ) )).value_in(units.AU) canonical_rp_min_B_AU = (semimajor_axis[1]*(1.0 - numpy.sqrt( 1.0 - (5.0/3.0)*numpy.cos(i_BC_init)**2 ) )).value_in(units.AU) data = print_times_Myr,print_smas_AU,print_rps_AU,print_parent_is_deg,canonical_rp_min_A_AU,canonical_rp_min_B_AU return data
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 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.assertEquals(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 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 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 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 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 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 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
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 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 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 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 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_TB.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 run_secularmultiple(particle_set, end_time, start_time=(0 |units.Myr), \ N_output=100, debug_mode=False, genT4System=False, \ exportData=True, useAMD=True, GCode = None, \ KeySystemID=None, SEVCode=None): '''Does what it says on the tin.''' try: hierarchical_test = [x for x in particle_set if x.is_binary == True] print("The supplied set has", len(hierarchical_test), "node particles and is a tree.") py_particles = particle_set except: print("The supplied set is NOT a tree set! Building tree ...") py_particles = get_full_hierarchical_structure(particle_set, KeySystemID=KeySystemID, SEVCode=SEVCode) hierarchical_test = [x for x in py_particles if x.is_binary == True] print("Tree has been built with", len(hierarchical_test), "node particles.") nodes = py_particles.select(lambda x: x == True, ["is_binary"]) Num_nodes = len(nodes) stellarCollisionOccured = False if GCode == None: code = SecularMultiple() else: code = GCode if exportData: plot_a_AU = defaultdict(list) plot_e = defaultdict(list) plot_peri_AU = defaultdict(list) plot_stellar_inc_deg = defaultdict(list) if useAMD: plot_AMDBeta = defaultdict(list) plot_times_Myr = [] if genT4System: print(nodes.inclination) nodes.inclination = [-18.137, 0.0, 23.570] | units.deg print(nodes.inclination) if debug_mode: print('=' * 50) print('t/kyr', 0.00) print('a/AU', nodes.semimajor_axis) print('p/day', nodes.period) print('e', nodes.eccentricity) print('i/deg', nodes.inclination) print('AP/deg', \ nodes.argument_of_pericenter) print('LAN/deg', \ nodes.longitude_of_ascending_node) #print(py_particles) code.particles.add_particles(py_particles) #code.commit_particles() #print(code.particles.semimajor_axis) code.model_time = start_time #print(py_particles.id, py_particles.semimajor_axis) channel_from_particles_to_code = py_particles.new_channel_to( code.particles) channel_from_code_to_particles = code.particles.new_channel_to( py_particles) #print(py_particles.id, py_particles.semimajor_axis) channel_from_particles_to_code.copy( ) #copy_attributes(['semimajor_axis', 'eccentricity', \ #'longitude_of_ascending_node', 'argument_of_pericenter', 'inclination']) #print('This is After the First Channel Copy:', code.particles.semimajor_axis) time = start_time if useAMD: #print(py_particles.id, py_particles.mass) jovianParent = get_jovian_parent(py_particles) output_time_step = 1000 * jovianParent.period.value_in( units.Myr) | units.Myr PS = initialize_PlanetarySystem_from_HierarchicalSet(py_particles) PS.get_SystemBetaValues() if exportData: for planet in PS.planets: plot_AMDBeta[planet.id].append(planet.AMDBeta) else: output_time_step = end_time / float(N_output) if exportData: plot_times_Myr.append(time.value_in(units.Myr)) for i, node in enumerate(nodes): plot_a_AU[node.child2.id].append( node.semimajor_axis.value_in(units.AU)) plot_e[node.child2.id].append(node.eccentricity) plot_peri_AU[node.child2.id].append( node.semimajor_axis.value_in(units.AU) * (1.0 - node.eccentricity)) plot_stellar_inc_deg[node.child2.id].append( node.inclination.value_in(units.deg)) counter = 0 while time <= end_time: #print('Start of Time Loop') #print(output_time_step) time += output_time_step counter += 1 #print(time) #print(code.model_time) #print(code.particles.semimajor_axis) code.evolve_model(time) #print('Evolved model to:', time.value_in(units.Myr), "Myr") #print(code.particles.semimajor_axis) channel_from_code_to_particles.copy() #channel_from_code_to_particles.copy_attributes(['semimajor_axis', 'eccentricity', \ #'longitude_of_ascending_node', 'argument_of_pericenter', 'inclination']) #print('Hello') py_particles.time = time if exportData: plot_times_Myr.append(time.value_in(units.Myr)) nodes = py_particles.select(lambda x: x == True, ["is_binary"]) for i, node in enumerate(nodes): plot_a_AU[node.child2.id].append( node.semimajor_axis.value_in(units.AU)) plot_e[node.child2.id].append(node.eccentricity) plot_peri_AU[node.child2.id].append( node.semimajor_axis.value_in(units.AU) * (1.0 - node.eccentricity)) plot_stellar_inc_deg[node.child2.id].append( node.inclination.value_in(units.deg)) if time == end_time + output_time_step: map_node_oe_to_lilsis(py_particles) if debug_mode: if time == end_time or time == output_time_step: print('=' * 50) print('t/kyr', time.value_in(units.kyr)) print('a/AU', nodes.semimajor_axis) print('p/day', nodes.period) print('e', nodes.eccentricity) print('i/deg', nodes.inclination) print('AP/deg', \ nodes.argument_of_pericenter) print('LAN/deg', \ nodes.longitude_of_ascending_node) # Check for Planet Destruction from Star #print(py_particles.id, py_particles.semimajor_axis) temp = check_for_stellar_collision(py_particles) #print(temp) # Returns 'None' if No Destruction! if temp != None: code.stop() code = SecularMultiple() code.model_time = time py_particles = Particles() py_particles.add_particles(temp) code.particles.add_particles(py_particles) py_particles.time = time #code.commit_particles() channel_from_particles_to_code = py_particles.new_channel_to( code.particles) channel_from_code_to_particles = code.particles.new_channel_to( py_particles) channel_from_particles_to_code.copy() nodes = py_particles.select(lambda x: x == True, ["is_binary"]) stellarCollisionOccured = True if useAMD: PS = initialize_PlanetarySystem_from_HierarchicalSet( py_particles) #channel_from_code_to_particles.copy_attributes(['semimajor_axis', 'eccentricity', \ #'longitude_of_ascending_node', 'argument_of_pericenter', 'inclination']) #print(code.particles.semimajor_axis) # AMD Checking if useAMD: PS = update_oe_for_PlanetarySystem(PS, py_particles) PS.get_SystemBetaValues() if exportData: for planet in PS.planets: plot_AMDBeta[planet.id].append(planet.AMDBeta) if counter % 100 == 0 and len( PS.planets.select(lambda x: x < 1.0, ["AMDBeta"])) > 1: break if GCode == None: code.stop() else: code = reset_secularmultiples(code) if exportData: if useAMD: data = plot_times_Myr, plot_a_AU, plot_e, plot_peri_AU, plot_stellar_inc_deg, plot_AMDBeta else: data = plot_times_Myr, plot_a_AU, plot_e, plot_peri_AU, plot_stellar_inc_deg else: data = None # Set the Output Code to be the New Code if a Stellar Collision Occured. if stellarCollisionOccured: newcode = code else: newcode = None return py_particles, data, newcode
def evolve_quadruple(N_output, end_time, m1, m2, m3, m4, aA, aB, aC, eA, eB, eC, iA, iB, iC, ApA, ApB, ApC, LANA, LANB, LANC): masses = [m1, m2, m3, m4] semimajor_axis = [aA, aB, aC] eccentricity = [eA, eB, eC] inclination = numpy.deg2rad([iA, iB, iC]) argument_of_percienter = numpy.deg2rad([ApA, ApB, ApC]) longitude_of_ascending_node = numpy.deg2rad([LANA, LANB, LANC]) print longitude_of_ascending_node N_bodies = 4 N_binaries = N_bodies - 1 particles, binaries = initialize_multiple_system( N_bodies, masses, semimajor_axis, eccentricity, inclination, argument_of_percienter, longitude_of_ascending_node) code = SecularMultiple() code.particles.add_particles(particles) channel_from_particles_to_code = particles.new_channel_to(code.particles) channel_from_code_to_particles = code.particles.new_channel_to(particles) channel_from_particles_to_code.copy() ### set up some arrays for plotting ### print_smas_AU = [[] for x in range(N_binaries)] print_rps_AU = [[] for x in range(N_binaries)] print_parent_is_deg = [[] for x in range(N_binaries)] print_times_Myr = [] time = 0.0 | units.yr output_time_step = end_time / float(N_output) while time <= end_time: time += output_time_step code.evolve_model(time) channel_from_code_to_particles.copy() print '=' * 50 print 't/Myr', time.value_in(units.Myr) print 'e', binaries.eccentricity print 'i/deg', numpy.rad2deg(binaries.inclination) print 'AP/deg', \ numpy.rad2deg(binaries.argument_of_pericenter) print 'LAN/deg', \ numpy.rad2deg(binaries.longitude_of_ascending_node) ### write to output arrays ### print_times_Myr.append(time.value_in(units.Myr)) for index_binary in range(N_binaries): print_smas_AU[index_binary].append( binaries[index_binary].semimajor_axis.value_in(units.AU)) print_rps_AU[index_binary].append( binaries[index_binary].semimajor_axis.value_in(units.AU) * (1.0 - binaries[index_binary].eccentricity)) print_parent_is_deg[index_binary].append( numpy.rad2deg( binaries[index_binary].inclination_relative_to_parent)) ### compute the `canonical' maximum eccentricity/periapsis distance that applies in the quadrupole-order test-particle limit if the `outer' binary is replaced by a point mass ### print inclination[0], inclination[2], longitude_of_ascending_node[ 0], longitude_of_ascending_node[2] i_AC_init = compute_mutual_inclination(inclination[0], inclination[2], longitude_of_ascending_node[0], longitude_of_ascending_node[2]) i_BC_init = compute_mutual_inclination(inclination[1], inclination[2], longitude_of_ascending_node[1], longitude_of_ascending_node[2]) canonical_rp_min_A_AU = ( semimajor_axis[0] * (1.0 - numpy.sqrt(1.0 - (5.0 / 3.0) * numpy.cos(i_AC_init)**2))).value_in( units.AU) canonical_rp_min_B_AU = ( semimajor_axis[1] * (1.0 - numpy.sqrt(1.0 - (5.0 / 3.0) * numpy.cos(i_BC_init)**2))).value_in( units.AU) data = print_times_Myr, print_smas_AU, print_rps_AU, print_parent_is_deg, canonical_rp_min_A_AU, canonical_rp_min_B_AU return data
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()