Exemplo n.º 1
0
def compress_binary_components(comp1, comp2, scale):

    # Compress the two-body system consisting of comp1 and comp2 to
    # lie within distance scale of one another.

    pos1 = comp1.position
    pos2 = comp2.position
    sep12 = ((pos2 - pos1)**2).sum()

    if sep12 > scale * scale:
        print('\ncompressing components', int(comp1.id.number), \
              'and', int(comp2.id.number), 'to separation', scale.number)
        sys.stdout.flush()
        mass1 = comp1.mass
        mass2 = comp2.mass
        total_mass = mass1 + mass2
        vel1 = comp1.velocity
        vel2 = comp2.velocity
        cmpos = (mass1 * pos1 + mass2 * pos2) / total_mass
        cmvel = (mass1 * vel1 + mass2 * vel2) / total_mass

        # For now, create and delete a temporary kepler
        # process to handle the transformation.  Obviously
        # more efficient to define a single kepler at the
        # start of the calculation and reuse it.

        kep = Kepler(redirection="none")
        kep.initialize_code()
        mass = comp1.mass + comp2.mass
        rel_pos = pos2 - pos1
        rel_vel = vel2 - vel1
        kep.initialize_from_dyn(mass, rel_pos[0], rel_pos[1], rel_pos[2],
                                rel_vel[0], rel_vel[1], rel_vel[2])
        M, th = kep.get_angles()
        a, e = kep.get_elements()
        if e < 1:
            peri = a * (1 - e)
            apo = a * (1 + e)
        else:
            peri = a * (e - 1)
            apo = 2 * a  # OK - used ony to reset scale
        limit = peri + 0.01 * (apo - peri)
        if scale < limit: scale = limit

        if M < 0:
            # print 'approaching'
            kep.advance_to_periastron()
            kep.advance_to_radius(limit)
        else:
            # print 'receding'
            if kep.get_separation() < scale:
                kep.advance_to_radius(limit)
            else:
                kep.return_to_radius(scale)

        # a,e = kep.get_elements()
        # r = kep.get_separation()
        # E,J = kep.get_integrals()
        # print 'kepler: a,e,r =', a.number, e.number, r.number
        # print 'E, J =', E, J

        # Note: if periastron > scale, we are now just past periastron.

        new_rel_pos = kep.get_separation_vector()
        new_rel_vel = kep.get_velocity_vector()
        kep.stop()

        # Enew = 0
        # r2 = 0
        # for k in range(3):
        #     Enew += 0.5*(new_rel_vel[k].number)**2
        #     r2 += (new_rel_pos[k].number)**2
        # rnew = math.sqrt(r2)
        # Enew -= mass.number/r1
        # print 'E, Enew, rnew =', E.number, E1, r1

        # Problem: the vectors returned by kepler are lists,
        # not numpy arrays, and it looks as though we can say
        # comp1.position = pos, but not comp1.position[k] =
        # xxx, as we'd like...  Also, we don't know how to
        # copy a numpy array with units...  TODO

        newpos1 = pos1 - pos1  # stupid trick to create zero vectors
        newpos2 = pos2 - pos2  # with the proper form and units...
        newvel1 = vel1 - vel1
        newvel2 = vel2 - vel2

        frac2 = mass2 / total_mass
        for k in range(3):
            dxk = new_rel_pos[k]
            dvk = new_rel_vel[k]
            newpos1[k] = cmpos[k] - frac2 * dxk
            newpos2[k] = cmpos[k] + (1 - frac2) * dxk
            newvel1[k] = cmvel[k] - frac2 * dvk
            newvel2[k] = cmvel[k] + (1 - frac2) * dvk

        # Perform the changes to comp1 and comp2, and recursively
        # transmit them to the (currently absolute) coordinates of
        # all lower components.

        offset_particle_tree(comp1, newpos1 - pos1, newvel1 - vel1)
        offset_particle_tree(comp2, newpos2 - pos2, newvel2 - vel2)
Exemplo n.º 2
0
def compress_binary_components(comp1, comp2, scale):

    # Compress the two-body system consisting of comp1 and comp2 to
    # lie within distance scale of one another.

    pos1 = comp1.position
    pos2 = comp2.position
    sep12 = ((pos2-pos1)**2).sum()

    if sep12 > scale*scale:
        print '\ncompressing components', int(comp1.id.number), \
              'and', int(comp2.id.number), 'to separation', scale.number
        sys.stdout.flush()
        mass1 = comp1.mass
        mass2 = comp2.mass
        total_mass = mass1 + mass2
        vel1 = comp1.velocity
        vel2 = comp2.velocity
        cmpos = (mass1*pos1+mass2*pos2)/total_mass
        cmvel = (mass1*vel1+mass2*vel2)/total_mass

        # For now, create and delete a temporary kepler
        # process to handle the transformation.  Obviously
        # more efficient to define a single kepler at the
        # start of the calculation and reuse it.

        kep = Kepler(redirection = "none")
        kep.initialize_code()
        mass = comp1.mass + comp2.mass
        rel_pos = pos2 - pos1
        rel_vel = vel2 - vel1
        kep.initialize_from_dyn(mass,
                                rel_pos[0], rel_pos[1], rel_pos[2],
                                rel_vel[0], rel_vel[1], rel_vel[2])
        M,th = kep.get_angles()
        a,e = kep.get_elements()
        if e < 1:
            peri = a*(1-e)
            apo = a*(1+e)
        else:
            peri = a*(e-1)
            apo = 2*a		# OK - used ony to reset scale
        limit = peri + 0.01*(apo-peri)
        if scale < limit: scale = limit

        if M < 0:
            # print 'approaching'
            kep.advance_to_periastron()
            kep.advance_to_radius(limit)
        else:
            # print 'receding'
            if kep.get_separation() < scale:
                kep.advance_to_radius(limit)
            else:
                kep.return_to_radius(scale)

        # a,e = kep.get_elements()
        # r = kep.get_separation()
        # E,J = kep.get_integrals()
        # print 'kepler: a,e,r =', a.number, e.number, r.number
        # print 'E, J =', E, J

        # Note: if periastron > scale, we are now just past periastron.

        new_rel_pos = kep.get_separation_vector()
        new_rel_vel = kep.get_velocity_vector()
        kep.stop()

        # Enew = 0
        # r2 = 0
        # for k in range(3):
        #     Enew += 0.5*(new_rel_vel[k].number)**2
        #     r2 += (new_rel_pos[k].number)**2
        # rnew = math.sqrt(r2)
        # Enew -= mass.number/r1
        # print 'E, Enew, rnew =', E.number, E1, r1

        # Problem: the vectors returned by kepler are lists,
        # not numpy arrays, and it looks as though we can say
        # comp1.position = pos, but not comp1.position[k] =
        # xxx, as we'd like...  Also, we don't know how to
        # copy a numpy array with units...  TODO

        newpos1 = pos1 - pos1	# stupid trick to create zero vectors
        newpos2 = pos2 - pos2	# with the proper form and units...
        newvel1 = vel1 - vel1
        newvel2 = vel2 - vel2

        frac2 = mass2/total_mass
        for k in range(3):
            dxk = new_rel_pos[k]
            dvk = new_rel_vel[k]
            newpos1[k] = cmpos[k] - frac2*dxk
            newpos2[k] = cmpos[k] + (1-frac2)*dxk
            newvel1[k] = cmvel[k] - frac2*dvk
            newvel2[k] = cmvel[k] + (1-frac2)*dvk

        # Perform the changes to comp1 and comp2, and recursively
        # transmit them to the (currently absolute) coordinates of
        # all lower components.

        offset_particle_tree(comp1, newpos1-pos1, newvel1-vel1)
        offset_particle_tree(comp2, newpos2-pos2, newvel2-vel2)
Exemplo n.º 3
0
def get_bodies_in_orbit(m0, m_ffp, m_bp, a_bp, e_bp, phi_bp, inc_bp, lan_bp, b_ffp, r_inf):

    #Bodies
    bodies = Particles()

    ##Get BP in orbit
    #Binary
    star_planet = new_binary_from_orbital_elements(m0, m_bp, a_bp, e_bp, true_anomaly=phi_bp, inclination = inc_bp, longitude_of_the_ascending_node = lan_bp)
    #Planet attributes
    star_planet.eccentricity = e_bp
    star_planet.semimajoraxis = a_bp
    #Center on the star
    star_planet.position -= star_planet[0].position
    star_planet.velocity -= star_planet[0].velocity
    cm_p = star_planet.center_of_mass()
    cm_v = star_planet.center_of_mass_velocity()

    ##Get FFP in orbit
    #Particle set
    m0_ffp = Particles(2)
    #Zeros and parabolic velocity
    zero_p = 0.0 | nbody_system.length
    zero_v = 0.0 | nbody_system.speed
    parabolic_velocity = get_parabolic_velocity(m0, m_bp, b_ffp, r_inf)
    #Central star
    m0_ffp[0].mass = m0
    m0_ffp[0].position = (zero_p,zero_p,zero_p)
    m0_ffp[0].velocity = (zero_v,zero_v,zero_v)
    #Free-floating planet
    m0_ffp[1].mass = m_ffp
    m0_ffp[1].position = (-r_inf+cm_p[0], b_ffp+cm_p[1], cm_p[2])
    m0_ffp[1].velocity = (parabolic_velocity+cm_v[0], cm_v[1], cm_v[2])

    #To find the orbital period of the BP
    G = (1.0 | nbody_system.length**3 * nbody_system.time**-2 * nbody_system.mass**-1)
    orbital_period_bp = 2*math.pi*((a_bp**3)/(G*m0)).sqrt()

    #To find the distance and time to periastron
    kep = Kepler()
    kep.initialize_code()

    star_planet_as_one = Particles(1)
    star_planet_as_one.mass = m0 + m_bp
    star_planet_as_one.position = cm_p
    star_planet_as_one.velocity = cm_v

    kepler_bodies = Particles()
    kepler_bodies.add_particle(star_planet_as_one[0])
    kepler_bodies.add_particle(m0_ffp[1])

    kep.initialize_from_particles(kepler_bodies)

    kep.advance_to_periastron()
    time_pericenter = kep.get_time()
    
    kep.stop()

    binary = [star_planet_as_one[0], m0_ffp[1]]
    sma, e, inclination, long_asc_node, arg_per = my_orbital_elements_from_binary(binary)
    m0_ffp.eccentricity = e
    m0_ffp.semimajoraxis = sma

    #Adding bodies. Order: star, ffp, bp
    bodies.add_particle(m0_ffp[0])
    bodies.add_particle(m0_ffp[1])
    bodies.add_particle(star_planet[1])

    return bodies, time_pericenter, orbital_period_bp