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 get_orbit_ini(m0, m1, peri, ecc, incl, omega, 
                  rel_force=0.01, r_disk=50|units.AU):
  converter=nbody_system.nbody_to_si(1|units.MSun,1|units.AU)
  
  # semi-major axis
  if ecc!=1.0:
    semi = peri/(1.0-ecc)
  else:
    semi = 1.0e10 | units.AU
  
  # relative position and velocity vectors at the pericenter using kepler
  kepler = Kepler_twobody(converter)
  kepler.initialize_code()
  kepler.initialize_from_elements(mass=(m0+m1), semi=semi, ecc=ecc, periastron=peri) # at pericenter
  
  # moving particle backwards to radius r where: F_m1(r) = rel_force*F_m0(r_disk)
  #r_disk = peri
  r_ini = r_disk*(1.0 + numpy.sqrt(m1/m0)/rel_force)
  kepler.return_to_radius(radius=r_ini)
  
  rl = kepler.get_separation_vector()
  r = [rl[0].value_in(units.AU), rl[1].value_in(units.AU), rl[2].value_in(units.AU)] | units.AU
  vl = kepler.get_velocity_vector()
  v = [vl[0].value_in(units.kms), vl[1].value_in(units.kms), vl[2].value_in(units.kms)] | units.kms
  period_kepler = kepler.get_period()
  time_peri = kepler.get_time()
  
  kepler.stop()
  
  # rotation of the orbital plane by inclination and argument of periapsis
  a1 = ([1.0, 0.0, 0.0], [0.0, numpy.cos(incl), -numpy.sin(incl)], [0.0, numpy.sin(incl), numpy.cos(incl)])
  a2 = ([numpy.cos(omega), -numpy.sin(omega), 0.0], [numpy.sin(omega), numpy.cos(omega), 0.0], [0.0, 0.0, 1.0])
  rot = numpy.dot(a1,a2)
  r_au = numpy.reshape(r.value_in(units.AU), 3, 1)
  v_kms = numpy.reshape(v.value_in(units.kms), 3, 1)
  r_rot = numpy.dot(rot, r_au) | units.AU
  v_rot = numpy.dot(rot, v_kms) | units.kms
  
  bodies = Particles(2)
  bodies[0].mass = m0
  bodies[0].radius = 1.0|units.RSun
  bodies[0].position = (0,0,0) | units.AU
  bodies[0].velocity = (0,0,0) | units.kms
  bodies[1].mass = m1
  bodies[1].radius = 1.0|units.RSun
  bodies[1].x = r_rot[0]
  bodies[1].y = r_rot[1]
  bodies[1].z = r_rot[2]
  bodies[1].vx = v_rot[0]
  bodies[1].vy = v_rot[1]
  bodies[1].vz = v_rot[2]
  
  bodies.age = 0.0 | units.yr
  bodies.move_to_center()
  
  print "\t r_rel_ini  = ", r_rot.in_(units.AU)
  print "\t v_rel_ini  = ", v_rot.in_(units.kms)
  print "\t time since peri = ", time_peri.in_(units.yr)
  a_orbit, e_orbit, p_orbit = orbital_parameters(r_rot, v_rot, (m0+m1))
  print "\t a = ", a_orbit.in_(units.AU), "\t e = ", e_orbit, "\t period = ", p_orbit.in_(units.yr)
  
  return bodies, time_peri
Exemplo n.º 3
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.º 4
0
def get_orbit_ini(m0,
                  m1,
                  peri,
                  ecc,
                  incl,
                  omega,
                  rel_force=0.01,
                  r_disk=50 | units.AU):
    converter = nbody_system.nbody_to_si(1 | units.MSun, 1 | units.AU)

    # semi-major axis
    if ecc != 1.0:
        semi = peri / (1.0 - ecc)
    else:
        semi = 1.0e10 | units.AU

    # relative position and velocity vectors at the pericenter using kepler
    kepler = Kepler_twobody(converter)
    kepler.initialize_code()
    kepler.initialize_from_elements(mass=(m0 + m1),
                                    semi=semi,
                                    ecc=ecc,
                                    periastron=peri)  # at pericenter

    # moving particle backwards to radius r where: F_m1(r) = rel_force*F_m0(r_disk)
    #r_disk = peri
    r_ini = r_disk * (1.0 + numpy.sqrt(m1 / m0) / rel_force)
    kepler.return_to_radius(radius=r_ini)

    rl = kepler.get_separation_vector()
    r = [
        rl[0].value_in(units.AU), rl[1].value_in(units.AU), rl[2].value_in(
            units.AU)
    ] | units.AU
    vl = kepler.get_velocity_vector()
    v = [
        vl[0].value_in(units.kms), vl[1].value_in(units.kms), vl[2].value_in(
            units.kms)
    ] | units.kms
    period_kepler = kepler.get_period()
    time_peri = kepler.get_time()

    kepler.stop()

    # rotation of the orbital plane by inclination and argument of periapsis
    a1 = ([1.0, 0.0,
           0.0], [0.0, numpy.cos(incl),
                  -numpy.sin(incl)], [0.0,
                                      numpy.sin(incl),
                                      numpy.cos(incl)])
    a2 = ([numpy.cos(omega), -numpy.sin(omega),
           0.0], [numpy.sin(omega), numpy.cos(omega), 0.0], [0.0, 0.0, 1.0])
    rot = numpy.dot(a1, a2)
    r_au = numpy.reshape(r.value_in(units.AU), 3, 1)
    v_kms = numpy.reshape(v.value_in(units.kms), 3, 1)
    r_rot = numpy.dot(rot, r_au) | units.AU
    v_rot = numpy.dot(rot, v_kms) | units.kms

    bodies = Particles(2)
    bodies[0].mass = m0
    bodies[0].radius = 1.0 | units.RSun
    bodies[0].position = (0, 0, 0) | units.AU
    bodies[0].velocity = (0, 0, 0) | units.kms
    bodies[1].mass = m1
    bodies[1].radius = 1.0 | units.RSun
    bodies[1].x = r_rot[0]
    bodies[1].y = r_rot[1]
    bodies[1].z = r_rot[2]
    bodies[1].vx = v_rot[0]
    bodies[1].vy = v_rot[1]
    bodies[1].vz = v_rot[2]

    bodies.age = 0.0 | units.yr
    bodies.move_to_center()

    print "\t r_rel_ini  = ", r_rot.in_(units.AU)
    print "\t v_rel_ini  = ", v_rot.in_(units.kms)
    print "\t time since peri = ", time_peri.in_(units.yr)
    a_orbit, e_orbit, p_orbit = orbital_parameters(r_rot, v_rot, (m0 + m1))
    print "\t a = ", a_orbit.in_(
        units.AU), "\t e = ", e_orbit, "\t period = ", p_orbit.in_(units.yr)

    return bodies, time_peri