コード例 #1
0
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
コード例 #2
0
    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()
コード例 #3
0
    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()
コード例 #4
0
    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)
コード例 #5
0
    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))
コード例 #6
0
    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)
コード例 #7
0
    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)
コード例 #8
0
    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
コード例 #9
0
    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
コード例 #10
0
    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()
コード例 #11
0
ファイル: scattering.py プロジェクト: gaybro8777/Tycho
class CloseEncounters():
    def __init__(self, Star_EncounterHistory, KeplerWorkerList = None, \
                 NBodyWorkerList = None, SecularWorker = None, SEVWorker = None):
        '''EncounterHistory should be a List of the Format {RotationKey: [Encounter0_FilePath, ...]}'''
        # Find the Main System's Host Star's ID and Assign it to 'KeySystemID'
        self.doEncounterPatching = True
        self.KeySystemID = int(Star_EncounterHistory[list(
            Star_EncounterHistory)[0]][0].split("/")[-2])
        self.ICs = defaultdict(list)
        self.StartTimes = defaultdict(list)
        self.desired_endtime = 1.0 | units.Gyr
        self.max_end_time = 0.1 | units.Myr
        self.kep = KeplerWorkerList
        self.NBodyCodes = NBodyWorkerList
        self.SecularCode = SecularWorker
        self.SEVCode = SEVWorker
        self.getOEData = True
        self.OEData = defaultdict(list)
        # Create a List of StartingTimes and Encounter Initial Conditions (ICs) for all Orientations
        for RotationKey in Star_EncounterHistory.keys():
            for i, Encounter in enumerate(Star_EncounterHistory[RotationKey]):
                self.ICs[RotationKey].append(
                    read_set_from_file(Encounter,
                                       format="hdf5",
                                       version='2.0',
                                       close_file=True))
                self.StartTimes[RotationKey].append(
                    np.max(np.unique(self.ICs[RotationKey][i].time)))
        #print(self.KeySystemID)
        self.FinalStates = defaultdict(list)

    def SimAllEncounters(self):
        ''' Call this function to run all Encounters for a System.'''
        # Start up Kepler Functions if Needed
        if self.kep == None:
            self.kep = []
            bodies = self.ICs[next(iter(self.ICs))][0]
            converter = nbody_system.nbody_to_si(
                bodies.mass.sum(),
                2 * np.max(bodies.radius.number) | bodies.radius.unit)
            self.kep.append(
                Kepler(unit_converter=converter, redirection='none'))
            self.kep.append(
                Kepler(unit_converter=converter, redirection='none'))
            self.kep[0].initialize_code()
            self.kep[1].initialize_code()
        # Start up NBodyCodes if Needed
        if self.NBodyCodes == None:
            self.NBodyCodes = [
                initialize_GravCode(ph4),
                initialize_isOverCode()
            ]
        # Start up SecularCode if Needed
        if self.SecularCode == None:
            self.SecularCode = SecularMultiple()
        if self.SEVCode == None:
            self.SEVCode = SSE()

        # Begin Looping over Rotation Keys ...
        for RotationKey in self.ICs.keys():
            for i in range(len(self.ICs[RotationKey])):
                try:
                    print(util.timestamp(), "!!! UPDATE: Starting the following encounter", \
                          "Star", self.KeySystemID, RotationKey, "-", i)

                    # Identify the Current Encounter in the List for This Rotation
                    CurrentEncounter = self.ICs[RotationKey][i]
                    #print(CurrentEncounter[0].position)

                    # Create the Encounter Instance with the Current Encounter
                    Encounter_Inst = self.SingleEncounter(CurrentEncounter)

                    # Simulate the Encounter till the Encounter is Over via N-Body Integrator
                    # -OR- the time to the Next Encounter is Reached
                    if len(self.StartTimes[RotationKey]) == 1 or i + 1 == len(
                            self.StartTimes[RotationKey]):
                        current_max_endtime = self.max_end_time
                    else:
                        current_max_endtime = self.StartTimes[RotationKey][i +
                                                                           1]
                    EndingState = Encounter_Inst.SimSingleEncounter(current_max_endtime, \
                                                                    start_time = self.StartTimes[RotationKey][i], \
                                                                    GCodes = self.NBodyCodes)
                    EndingStateTime = np.max(np.unique(EndingState.time))

                    #print(Encounter_Inst.particles[0].position)
                    print("The Encounter was over after:",
                          (EndingStateTime -
                           self.StartTimes[RotationKey][i]).value_in(
                               units.Myr))

                    #print(EndingState.id, EndingState.x)
                    print('----------')
                    #print(Encounter_Inst.particles.id, Encounter_Inst.particles.x)

                    # Strip off Anything Not Associated with the Key System
                    systems_in_current_encounter = stellar_systems.get_heirarchical_systems_from_set(
                        EndingState, kepler_workers=self.kep)

                    # Reassign the EndingState to include the Primary System ONLY
                    EndingState = systems_in_current_encounter[
                        self.KeySystemID]
                    print("Before Secular:", EndingState.id, EndingState.x)
                    #print(EndingState[0].position)

                    #print(len(self.ICs[RotationKey])-1)
                    # If Encounter Patching is Desired -AND- it isn't the last Encounter
                    if i + 1 < len(self.ICs[RotationKey]
                                   ) and self.doEncounterPatching:

                        # Identify the Next Encounter in the List
                        NextEncounter = self.ICs[RotationKey][i + 1]

                        # Simulate System till the Next Encounter's Start Time
                        Encounter_Inst = self.SingleEncounter(EndingState)
                        FinalState, data, newcode = Encounter_Inst.SimSecularSystem(self.StartTimes[RotationKey][i+1], \
                                                                     start_time = EndingStateTime, \
                                                                     GCode = self.SecularCode, getOEData=self.getOEData, \
                                                                     KeySystemID = self.KeySystemID, SCode=self.SEVCode)
                        if newcode != None:
                            self.SecularCode = newcode
                        print("After Secular:", FinalState.id)
                        # Begin Patching of the End State to the Next Encounter
                        self.ICs[RotationKey][i + 1] = self.PatchedEncounter(
                            FinalState, NextEncounter)
                    else:
                        # Simulate System till Desired Global Endtime
                        #print(CurrentEncounter[0].time.value_in(units.Myr))
                        #print(EndingState[0].time.value_in(units.Myr))
                        Encounter_Inst = self.SingleEncounter(EndingState)
                        FinalState, data, newcode = Encounter_Inst.SimSecularSystem(self.desired_endtime, \
                                                                     start_time = EndingStateTime, \
                                                                     GCode = self.SecularCode, getOEData=self.getOEData, \
                                                                     KeySystemID = self.KeySystemID, SCode=self.SEVCode)
                        if newcode != None:
                            self.SecularCode = newcode
                        print("After Secular:", FinalState.id)

                    # Append the FinalState of Each Encounter to its Dictionary
                    self.FinalStates[RotationKey].append(FinalState)
                    if self.getOEData and data != None:
                        self.OEData[RotationKey].append(data)
                except:
                    print("!!!! Alert: Skipping", RotationKey, "-", i,
                          "for Star", self.KeySystemID,
                          "due to unforseen issues!")
                    print("!!!!        The Particle Set's IDs are as follows:",
                          self.ICs[RotationKey][i].id)

        # Stop the NBody Codes if not Provided
        if self.kep == None:
            self.kep[0].stop()
            self.kep[1].stop()
        # Start up NBodyCodes if Needed
        if self.NBodyCodes == None:
            self.NBodyCodes[0].stop()
            self.NBodyCodes[1].stop()
        # Start up SecularCode if Needed
        if self.SecularCode == None:
            self.SecularCode.stop()
        return None

    def PatchedEncounter(self, EndingState, NextEncounter):
        ''' Call this function to Patch Encounter Endstates to the Next Encounter'''
        # Determine Time to Next Encounter
        current_time = max(EndingState.time)
        final_time = max(NextEncounter.time)

        # Map the Orbital Elements to the Child2 Particles (LilSis) [MUST BE A TREE SET]
        enc_patching.map_node_oe_to_lilsis(EndingState)

        # Seperate Next Encounter Systems to Locate the Primary System
        systems_at_next_encounter = stellar_systems.get_heirarchical_systems_from_set(
            NextEncounter)
        sys_1 = systems_at_next_encounter[self.KeySystemID]
        # Note: This was changed to handle encounters of which result in one
        #       bound object of multiple subsystems. ~ Joe G. | 8/24/20
        BoundObjOnly = False
        if len(systems_at_next_encounter.keys()) == 1:
            BoundObjOnly = True
        else:
            secondary_sysID = [
                key for key in list(systems_at_next_encounter.keys())
                if key != int(self.KeySystemID)
            ][0]
            sys_2 = systems_at_next_encounter[secondary_sysID]

        # Get Planet and Star Subsets for the Current and Next Encounter
        children_at_EndingState = EndingState.select(lambda x: x == False,
                                                     ["is_binary"])
        planets_at_current_encounter = util.get_planets(
            children_at_EndingState)
        hoststar_at_current_encounter = util.get_stars(
            children_at_EndingState).select(lambda x: x == self.KeySystemID,
                                            ["id"])[0]
        planets_at_next_encounter = util.get_planets(sys_1)
        print("Planets at Next Encount:", planets_at_next_encounter.id)
        hoststar_at_next_encounter = util.get_stars(sys_1).select(
            lambda x: x == self.KeySystemID, ["id"])[0]
        #print(hoststar_at_next_encounter)

        # Update Current Positions & Velocitys to Relative Coordinates from Orbital Parameters!!
        # TO-DO: Does not handle Binary Star Systems
        for planet in planets_at_current_encounter:
            #print(planet.id, planet.position)
            nbody_PlanetStarPair = \
            new_binary_from_orbital_elements(hoststar_at_current_encounter.mass, planet.mass, planet.semimajor_axis, \
                                             eccentricity = planet.eccentricity, inclination=planet.inclination, \
                                             longitude_of_the_ascending_node=planet.longitude_of_ascending_node, \
                                             argument_of_periapsis=planet.argument_of_pericenter, G=units.constants.G, \
                                             true_anomaly = 360*rp.uniform(0.0,1.0) | units.deg) # random point in the orbit
            planet.position = nbody_PlanetStarPair[1].position
            planet.velocity = nbody_PlanetStarPair[1].velocity
            #print(planet.id, planet.position)

        for planet in planets_at_current_encounter:
            print(planet.id, planet.position)

        # Release a Warning when Odd Planet Number Combinations Occur (Very Unlikely, More of a Safe Guard)
        if len(planets_at_current_encounter) != len(planets_at_next_encounter):
            print("!!!! Expected",
                  len(planets_at_next_encounter), "planets but recieved only",
                  len(planets_at_current_encounter))

        # Move Planets to Host Star in the Next Encounter
        for next_planet in planets_at_next_encounter:
            for current_planet in planets_at_current_encounter:
                if next_planet.id == current_planet.id:
                    next_planet.position = current_planet.position + hoststar_at_next_encounter.position
                    next_planet.velocity = current_planet.velocity + hoststar_at_next_encounter.velocity
                    break

        #for planet in planets_at_next_encounter:
        #    print(planet.id, planet.position)
        #for particle in sys_1:
        #    print(particle.id, particle.position)

        # Recombine Seperated Systems to Feed into SimSingleEncounter
        UpdatedNextEncounter = Particles()
        print("IDs in System 1", sys_1.id)
        UpdatedNextEncounter.add_particles(sys_1)
        if not BoundObjOnly:
            UpdatedNextEncounter.add_particles(sys_2)
            print("IDs in System 2", sys_2.id)

        # Return the Updated and Patched Encounter as a Partcile Set for the N-Body Simulation
        return UpdatedNextEncounter

    class SingleEncounter():
        def __init__(self, EncounterBodies):
            self.particles = EncounterBodies

        def SimSecularSystem(self, desired_end_time, **kwargs):
            start_time = kwargs.get("start_time", 0 | units.Myr)
            getOEData = kwargs.get("getOEData", False)
            KeySystemID = kwargs.get("KeySystemID", None)
            GCode = kwargs.get("GCode", None)
            SEVCode = kwargs.get("SCode", None)

            self.particles, data, newcode = enc_patching.run_secularmultiple(self.particles, desired_end_time, \
                                                                  start_time = start_time, N_output=1, \
                                                                  GCode=GCode, exportData=getOEData, \
                                                                  KeySystemID=KeySystemID, SEVCode=SEVCode)
            return self.particles, data, newcode

        def SimSingleEncounter(self, max_end_time, **kwargs):
            delta_time = kwargs.get("delta_time", 100 | units.yr)
            converter = kwargs.get("converter", None)
            start_time = kwargs.get("start_time", 0 | units.yr)
            doStateSaves = kwargs.get("doStateSaves", False)
            doVerbosSaves = kwargs.get("doEncPatching", False)
            GCodes = kwargs.get("GCodes", None)

            GravitatingBodies = self.particles

            # Set Up the Integrators
            if GCodes == None:
                if converter == None:
                    converter = nbody_system.nbody_to_si(GravitatingBodies.mass.sum(), \
                                                         2 * np.max(GravitatingBodies.radius.number) | GravitatingBodies.radius.unit)
                gravity = initialize_GravCode(ph4, converter=converter)
                over_grav = initialize_isOverCode(converter=converter)
            else:
                gravity = GCodes[0]
                over_grav = GCodes[1]

            # Set up SaveState if Requested
            if doStateSaves:
                pass  # Currently Massive Memory Leak Present

            # Store Initial Center of Mass Information
            rCM_i = GravitatingBodies.center_of_mass()
            vCM_i = GravitatingBodies.center_of_mass_velocity()

            # Remove Attributes that Cause Issues with SmallN
            if 'child1' in GravitatingBodies.get_attribute_names_defined_in_store(
            ):
                del GravitatingBodies.child1, GravitatingBodies.child2

            # Moving the Encounter's Center of Mass to the Origin and Setting it at Rest
            GravitatingBodies.position -= rCM_i
            GravitatingBodies.velocity -= vCM_i

            # Add and Commit the Scattering Particles
            gravity.particles.add_particles(
                GravitatingBodies)  # adds bodies to gravity calculations
            gravity.commit_particles()
            #gravity.begin_time = start_time

            # Create the Channel to Python Set & Copy it Over
            channel_from_grav_to_python = gravity.particles.new_channel_to(
                GravitatingBodies)
            channel_from_grav_to_python.copy()

            # Get Free-Fall Time for the Collision
            s = util.get_stars(GravitatingBodies)
            t_freefall = s.dynamical_timescale()
            #print(gravity.begin_time)
            #print(t_freefall)

            # Setting Coarse Timesteps
            list_of_times = np.arange(0.0, start_time.value_in(units.yr)+max_end_time.value_in(units.yr), \
                                      delta_time.value_in(units.yr)) | units.yr
            stepNumber = 0

            # Loop through the List of Coarse Timesteps
            for current_time in list_of_times:
                #print(current_time)
                #print(GravitatingBodies.time)
                #print(gravity.sync_time)
                # Evolve the Model to the Desired Current Time
                gravity.evolve_model(current_time)

                # Update Python Set in In-Code Set
                channel_from_grav_to_python.copy()  # original
                channel_from_grav_to_python.copy_attribute(
                    "index_in_code", "id")

                # Check to See if the Encounter is Over After the Freefall Time and Every 25 Steps After That
                if current_time > 1.25 * t_freefall and stepNumber % 25 == 0:
                    over = util.check_isOver(gravity.particles, over_grav)
                    print("Is it Over?", over)
                    if over:
                        #print(gravity.particles[0].position)
                        #print(GravitatingBodies[0].position)
                        current_time += 100 | units.yr
                        # Get to a Final State After Several Planet Orbits
                        gravity.evolve_model(current_time)
                        gravity.update_particle_set()
                        gravity.particles.synchronize_to(GravitatingBodies)
                        channel_from_grav_to_python.copy()
                        GravitatingBodies.time = start_time + current_time
                        # Create a Save State
                        break
                if current_time == list_of_times[-1]:
                    # Create a Save State
                    pass
                stepNumber += 1
            if GCodes == None:
                # Stop the Gravity Code Once the Encounter Finishes
                gravity.stop()
                over_grav.stop()
            else:
                # Reset the Gravity Codes Once Encounter Finishes
                gravity.reset()
                over_grav.reset()

            # Return the GravitatingBodies as they are at the End of the Simulation
            return GravitatingBodies
コード例 #12
0
    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()
コード例 #13
0
ファイル: scattering.py プロジェクト: gaybro8777/Tycho
    def SimAllEncounters(self):
        ''' Call this function to run all Encounters for a System.'''
        # Start up Kepler Functions if Needed
        if self.kep == None:
            self.kep = []
            bodies = self.ICs[next(iter(self.ICs))][0]
            converter = nbody_system.nbody_to_si(
                bodies.mass.sum(),
                2 * np.max(bodies.radius.number) | bodies.radius.unit)
            self.kep.append(
                Kepler(unit_converter=converter, redirection='none'))
            self.kep.append(
                Kepler(unit_converter=converter, redirection='none'))
            self.kep[0].initialize_code()
            self.kep[1].initialize_code()
        # Start up NBodyCodes if Needed
        if self.NBodyCodes == None:
            self.NBodyCodes = [
                initialize_GravCode(ph4),
                initialize_isOverCode()
            ]
        # Start up SecularCode if Needed
        if self.SecularCode == None:
            self.SecularCode = SecularMultiple()
        if self.SEVCode == None:
            self.SEVCode = SSE()

        # Begin Looping over Rotation Keys ...
        for RotationKey in self.ICs.keys():
            for i in range(len(self.ICs[RotationKey])):
                try:
                    print(util.timestamp(), "!!! UPDATE: Starting the following encounter", \
                          "Star", self.KeySystemID, RotationKey, "-", i)

                    # Identify the Current Encounter in the List for This Rotation
                    CurrentEncounter = self.ICs[RotationKey][i]
                    #print(CurrentEncounter[0].position)

                    # Create the Encounter Instance with the Current Encounter
                    Encounter_Inst = self.SingleEncounter(CurrentEncounter)

                    # Simulate the Encounter till the Encounter is Over via N-Body Integrator
                    # -OR- the time to the Next Encounter is Reached
                    if len(self.StartTimes[RotationKey]) == 1 or i + 1 == len(
                            self.StartTimes[RotationKey]):
                        current_max_endtime = self.max_end_time
                    else:
                        current_max_endtime = self.StartTimes[RotationKey][i +
                                                                           1]
                    EndingState = Encounter_Inst.SimSingleEncounter(current_max_endtime, \
                                                                    start_time = self.StartTimes[RotationKey][i], \
                                                                    GCodes = self.NBodyCodes)
                    EndingStateTime = np.max(np.unique(EndingState.time))

                    #print(Encounter_Inst.particles[0].position)
                    print("The Encounter was over after:",
                          (EndingStateTime -
                           self.StartTimes[RotationKey][i]).value_in(
                               units.Myr))

                    #print(EndingState.id, EndingState.x)
                    print('----------')
                    #print(Encounter_Inst.particles.id, Encounter_Inst.particles.x)

                    # Strip off Anything Not Associated with the Key System
                    systems_in_current_encounter = stellar_systems.get_heirarchical_systems_from_set(
                        EndingState, kepler_workers=self.kep)

                    # Reassign the EndingState to include the Primary System ONLY
                    EndingState = systems_in_current_encounter[
                        self.KeySystemID]
                    print("Before Secular:", EndingState.id, EndingState.x)
                    #print(EndingState[0].position)

                    #print(len(self.ICs[RotationKey])-1)
                    # If Encounter Patching is Desired -AND- it isn't the last Encounter
                    if i + 1 < len(self.ICs[RotationKey]
                                   ) and self.doEncounterPatching:

                        # Identify the Next Encounter in the List
                        NextEncounter = self.ICs[RotationKey][i + 1]

                        # Simulate System till the Next Encounter's Start Time
                        Encounter_Inst = self.SingleEncounter(EndingState)
                        FinalState, data, newcode = Encounter_Inst.SimSecularSystem(self.StartTimes[RotationKey][i+1], \
                                                                     start_time = EndingStateTime, \
                                                                     GCode = self.SecularCode, getOEData=self.getOEData, \
                                                                     KeySystemID = self.KeySystemID, SCode=self.SEVCode)
                        if newcode != None:
                            self.SecularCode = newcode
                        print("After Secular:", FinalState.id)
                        # Begin Patching of the End State to the Next Encounter
                        self.ICs[RotationKey][i + 1] = self.PatchedEncounter(
                            FinalState, NextEncounter)
                    else:
                        # Simulate System till Desired Global Endtime
                        #print(CurrentEncounter[0].time.value_in(units.Myr))
                        #print(EndingState[0].time.value_in(units.Myr))
                        Encounter_Inst = self.SingleEncounter(EndingState)
                        FinalState, data, newcode = Encounter_Inst.SimSecularSystem(self.desired_endtime, \
                                                                     start_time = EndingStateTime, \
                                                                     GCode = self.SecularCode, getOEData=self.getOEData, \
                                                                     KeySystemID = self.KeySystemID, SCode=self.SEVCode)
                        if newcode != None:
                            self.SecularCode = newcode
                        print("After Secular:", FinalState.id)

                    # Append the FinalState of Each Encounter to its Dictionary
                    self.FinalStates[RotationKey].append(FinalState)
                    if self.getOEData and data != None:
                        self.OEData[RotationKey].append(data)
                except:
                    print("!!!! Alert: Skipping", RotationKey, "-", i,
                          "for Star", self.KeySystemID,
                          "due to unforseen issues!")
                    print("!!!!        The Particle Set's IDs are as follows:",
                          self.ICs[RotationKey][i].id)

        # Stop the NBody Codes if not Provided
        if self.kep == None:
            self.kep[0].stop()
            self.kep[1].stop()
        # Start up NBodyCodes if Needed
        if self.NBodyCodes == None:
            self.NBodyCodes[0].stop()
            self.NBodyCodes[1].stop()
        # Start up SecularCode if Needed
        if self.SecularCode == None:
            self.SecularCode.stop()
        return None
コード例 #14
0
    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()
コード例 #15
0
    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()
コード例 #16
0
    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()
コード例 #17
0
    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()
コード例 #18
0
    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()
コード例 #19
0
 def test0(self):
     instance = SecularMultiple()
     print(instance.parameters)
コード例 #20
0
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
コード例 #21
0
    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()
コード例 #22
0
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
コード例 #23
0
    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()
コード例 #24
0
    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()
コード例 #25
0
    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()
コード例 #26
0
def simulate_all_close_encounters(rootExecDir, **kwargs):
    '''
    This function will run all scatters for a single cluster in serial.
    str rootExecDir -> The absolute root directory for all single cluster files.
    '''
    max_number_of_rotations = kwargs.get("maxRotations", 100)
    max_runtime = kwargs.get("maxRunTime", 10**5)  # Units Years
    delta_time = kwargs.get("dt", 10)  # Units Years
    # Strip off Extra '/' if added by user to bring inline with os.cwd()
    if rootExecDir.endswith("/"):
        rootExecDir = rootExecDir[:-1]
    # Define the Cluster's Name
    cluster_name = rootExecDir.split("/")[-1]
    # Generate List of Scattering IC HDF5 Paths
    enc_dict = scattering.build_ClusterEncounterHistory(rootExecDir)
    # Find all Primary Star IDs
    star_IDs = enc_dict.keys()  # Integer tied to StarID
    # Set Up Output Directory Structure
    output_MainDirectory = rootExecDir + "/Encounters"
    if not os.path.exists(output_MainDirectory):
        os.mkdir(output_MainDirectory)
    # Initialize the Necessary Worker Lists
    converter = nbody_system.nbody_to_si(1 | units.MSun, 100 | units.AU)
    KepW = []
    for i in range(2):
        KepW.append(Kepler(unit_converter=converter, redirection='none'))
        KepW[-1].initialize_code()
    NBodyW = [
        scattering.initialize_GravCode(ph4),
        scattering.initialize_isOverCode()
    ]
    SecW = SecularMultiple()
    SEVW = SSE()

    # Loop Over the Stars
    for star_ID in star_IDs:
        # Load the Close Encounter class for the Star
        EncounterHandler = scattering.CloseEncounters(enc_dict[star_ID], KeplerWorkerList = KepW, \
                                           NBodyWorkerList = NBodyW, SecularWorker = SecW, SEVWorker = SEVW)
        # Simulate Encounter
        EncounterHandler.SimAllEncounters()
        # Prepare Data for Pickling
        file_name = output_MainDirectory + "/" + str(
            star_ID) + "_EncounterHandler.pk"
        p_file = open(file_name, "wb")
        # Remove Worker Lists from Class for Storage
        EncounterHandler.kep = None
        EncounterHandler.NBodyCodes = None
        EncounterHandler.SecularCode = None
        EncounterHandler.SEVCode = None
        # Pickle EncounterHandler Class
        # Note: This allows for ease-of-use when you want to revisit
        #       a specific star's simulation set in detail.
        pickle.dump(EncounterHandler, p_file)
        p_file.close()
        # Note: Ensure the EncounterHandler class is deleted incase
        #       of a memory leak is possible in future updates.
        del EncounterHandler
    # Stop all Workers
    for Worker in KepW + NBodyW + [SecW] + SEVW:
        Worker.stop()