Exemplo n.º 1
0
def update_orb_elem(host_star, planets, converter=None, kepler_worker=None):
    if kepler_worker == None:
        if converter == None:
            tot_sys = Particles(particles=(host_star, planets))
            converter = nbody_system.nbody_to_si(tot_sys.mass.sum(),
                                                 2 * host_star.radius)
        kep_p = Kepler(unit_converter=converter, redirection='none')
        kep_p.initialize_code()
    else:
        kep_p = kepler_worker
    for planet in planets:
        total_mass = host_star.mass + planet.mass
        kep_pos = host_star.position - planet.position
        kep_vel = host_star.velocity - planet.velocity
        kep_p.initialize_from_dyn(total_mass, kep_pos[0], kep_pos[1],
                                  kep_pos[2], kep_vel[0], kep_vel[1],
                                  kep_vel[2])
        planet.semimajor_axis, planet.eccentricity = kep_p.get_elements()
        planet.period = kep_p.get_period()
        planet.true_anomaly, planet.mean_anomaly = kep_p.get_angles()
    if kepler_worker == None:
        kep_p.stop()
Exemplo n.º 2
0
def get_heirarchical_systems_from_set(bodies,
                                      kepler_workers=None,
                                      converter=None,
                                      RelativePosition=False):
    # Initialize Kepler
    if kepler_workers == None:
        if converter == None:
            converter = nbody_system.nbody_to_si(
                bodies.mass.sum(),
                2 * np.max(bodies.radius.number) | bodies.radius.unit)
        kep_p = Kepler(unit_converter=converter, redirection='none')
        kep_p.initialize_code()
        kep_s = Kepler(unit_converter=converter, redirection='none')
        kep_s.initialize_code()
    else:
        kep_p = kepler_workers[0]
        kep_s = kepler_workers[1]
    # Seperate Out Planets and Stars from Bodies
    stars, planets = util.get_stars(bodies), util.get_planets(bodies)
    num_stars, num_planets = len(stars), len(planets)
    # Initialize the Dictionary that Contains all Planetary Systems
    systems = {}
    # Initialize the List Used to Check Star IDs Against Already Classified Binaries
    binary_ids = []
    # Find Nearest Neighbors of the Set
    closest_neighbours = stars.nearest_neighbour()
    # Start Looping Through Stars to Find Bound Planets
    for index, star in enumerate(stars):
        # If the star is already in Binary_IDs, just go to the next star.
        if star.id in binary_ids:
            continue
        # If not, Set the System ID and Set-up Data Structure.
        system_id = star.id
        current_system = systems.setdefault(system_id, Particles())
        current_system.add_particle(star)
        noStellarHierarchy = False
        # If there is only one stars, there is obviously no stellar heirarchy in
        # the encounter that is occuring.
        if len(stars) == 1:
            noStellarHierarchy = True
        if not noStellarHierarchy:
            # Check to see if the Nearest Neighbor is Mutual
            star_neighbour_id = closest_neighbours[index].id
            neighbour_neighbour_id = closest_neighbours[
                stars.id == star_neighbour_id].id[0]
            for other_star in (stars - star):
                # Check to see if the two stars are bound.
                kep_s.initialize_from_dyn(
                    star.mass + other_star.mass, star.x - other_star.x,
                    star.y - other_star.y, star.z - other_star.z,
                    star.vx - other_star.vx, star.vy - other_star.vy,
                    star.vz - other_star.vz)
                a_s, e_s = kep_s.get_elements()
                print(star.id, other_star.id, e_s)
                # If they ARE NOT bound ...
                if e_s >= 1.0:
                    noStellarHierarchy = True
                # If they ARE bound ...
                else:
                    # If the star is the star's neighbour's neighbour and visa-versa, then proceed.
                    print(star.id, other_star.id, star_neighbour_id,
                          neighbour_neighbour_id)
                    if star.id == neighbour_neighbour_id and other_star.id == star_neighbour_id:
                        noStellarHierarchy = False
                        print("Binary composed of Star", star.id, "and Star",
                              other_star.id, "has been detected!")
                        current_system.add_particle(other_star)
                        binary_ids.append(star.id)
                        binary_ids.append(other_star.id)
                    else:
                        print(
                            "!!! Alert: Bound Stars are not closest neighbours ..."
                        )
                        print("!!! Current Star:", star.id, "| Other Star:",
                              other_star.id)
                        print("!!! CS's Neighbour:", star_neighbour_id, \
                              "| CS's Neighbour's Neighbour:", neighbour_neighbour_id)
    checked_planet_ids = []
    for KeyID in systems.keys():
        current_system = systems[KeyID]
        sys_stars = util.get_stars(current_system)
        noStellarHierarchy = False
        # If there is only one stars, there is obviously no stellar heirarchy in
        # the encounter that is occuring.
        if len(sys_stars) == 1:
            noStellarHierarchy = True
        for planet in planets:
            if planet.id in checked_planet_ids:
                continue
            star = sys_stars[sys_stars.id == KeyID][0]
            total_mass = star.mass + planet.mass
            kep_pos = star.position - planet.position
            kep_vel = star.velocity - planet.velocity
            kep_p.initialize_from_dyn(total_mass, kep_pos[0], kep_pos[1],
                                      kep_pos[2], kep_vel[0], kep_vel[1],
                                      kep_vel[2])
            a_p, e_p = kep_p.get_elements()
            P_p = kep_p.get_period()
            Ta_p, Ma_p = kep_p.get_angles()
            host_star_id = star.id
            if e_p < 1.0:
                # Check to See if The Planetary System is tied to a Stellar Binary
                # Note: Things get complicated if it is ...
                if noStellarHierarchy:
                    # Get Additional Information on Orbit
                    planet.semimajor_axis = a_p
                    planet.eccentricity = e_p
                    planet.period = P_p
                    planet.true_anomaly = Ta_p
                    planet.mean_anomaly = Ma_p
                    planet.host_star = star.id
                    # Add the Planet to the System Set
                    current_system.add_particle(planet)
                else:
                    # Handling for Planetary Systems in Stellar Heirarchical Structures
                    # Note: We check to see which other star in the current systems
                    #       have a better boundness with the planet and choose that
                    #       as the new host star.
                    for other_star in sys_stars - star:
                        total_mass = other_star.mass + planet.mass
                        kep_pos = other_star.position - planet.position
                        kep_vel = other_star.velocity - planet.velocity
                        kep_p.initialize_from_dyn(total_mass, kep_pos[0],
                                                  kep_pos[1], kep_pos[2],
                                                  kep_vel[0], kep_vel[1],
                                                  kep_vel[2])
                        a_p2, e_p2 = kep_p.get_elements()
                        # Check to see if the planet is more bound to 'star' or
                        # 'other_star'. If its more bound to 'other_star',
                        # set the attributes to the more bound object. This will
                        # replace *_p with the better values with each loop.
                        if e_p2 < e_p:
                            a_p = a_p2
                            e_p = e_p2
                            P_p = kep_p.get_period()
                            Ta_p, Ma_p = kep_p.get_angles()
                            host_star_id = other_star.id
                    planet.semimajor_axis = a_p
                    planet.eccentricity = e_p
                    planet.period = P_p
                    planet.true_anomaly = Ta_p
                    planet.mean_anomaly = Ma_p
                    planet.host_star = host_star_id
                    # Add the Planet to the System Set
                    current_system.add_particle(planet)
                checked_planet_ids.append(planet.id)
            elif not noStellarHierarchy:
                # Handling for Planetary Systems in Stellar Heirarchical Structures
                # Note: We check to see which other star in the current systems
                #       have a better boundness with the planet and choose that
                #       as the new host star.
                for other_star in sys_stars - star:
                    total_mass = other_star.mass + planet.mass
                    kep_pos = other_star.position - planet.position
                    kep_vel = other_star.velocity - planet.velocity
                    kep_p.initialize_from_dyn(total_mass, kep_pos[0],
                                              kep_pos[1], kep_pos[2],
                                              kep_vel[0], kep_vel[1],
                                              kep_vel[2])
                    a_p2, e_p2 = kep_p.get_elements()
                    # Check to see if the planet is more bound to 'star' or
                    # 'other_star'. If its more bound to 'other_star',
                    # set the attributes to the more bound object. This will
                    # replace *_p with the better values with each loop.
                    if e_p2 < e_p:
                        a_p = a_p2
                        e_p = e_p2
                        P_p = kep_p.get_period()
                        Ta_p, Ma_p = kep_p.get_angles()
                        host_star_id = other_star.id
                planet.semimajor_axis = a_p
                planet.eccentricity = e_p
                planet.period = P_p
                planet.true_anomaly = Ta_p
                planet.mean_anomaly = Ma_p
                planet.host_star = host_star_id
                # Add the Planet to the System Set
                current_system.add_particle(planet)
            else:
                print(
                    "!!! Alert: Planet is not bound nor is it bound to any other star."
                )
    if kepler_workers == None:
        kep_p.stop()
        kep_s.stop()
    return systems
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_planetary_systems_from_set(bodies,
                                   converter=None,
                                   RelativePosition=False):
    # Initialize Kepler
    if converter == None:
        converter = nbody_system.nbody_to_si(
            bodies.mass.sum(),
            2 * np.max(bodies.radius.number) | bodies.radius.unit)
    kep_p = Kepler(unit_converter=converter, redirection='none')
    kep_p.initialize_code()
    kep_s = Kepler(unit_converter=converter, redirection='none')
    kep_s.initialize_code()
    # Seperate Out Planets and Stars from Bodies
    stars, planets = util.get_stars(bodies), util.get_planets(bodies)
    num_stars, num_planets = len(stars), len(planets)
    # Initialize the Dictionary that Contains all Planetary Systems
    systems = {}
    # Start Looping Through Stars to Find Bound Planets
    for star in stars:
        system_id = star.id
        #star.semimajor_axis, star.eccentricity, star.period, star.true_anomaly, star.mean_anomaly, star.kep_energy, star.angular_momentum = \
        #    None, None, None, None, None, None, None
        current_system = systems.setdefault(system_id, Particles())
        current_system.add_particle(star)
        for planet in planets:
            total_mass = star.mass + planet.mass
            kep_pos = star.position - planet.position
            kep_vel = star.velocity - planet.velocity
            kep_p.initialize_from_dyn(total_mass, kep_pos[0], kep_pos[1],
                                      kep_pos[2], kep_vel[0], kep_vel[1],
                                      kep_vel[2])
            a_p, e_p = kep_p.get_elements()
            if e_p < 1.0:
                # Check to See if The Stellar System is a Binary
                # Note: Things get complicated if it is ...
                noStellarHeirarchy = False
                for other_star in (stars - star):
                    kep_s.initialize_from_dyn(
                        star.mass + other_star.mass, star.x - other_star.x,
                        star.y - other_star.y, star.z - other_star.z,
                        star.vx - other_star.vx, star.vy - other_star.vy,
                        star.vz - other_star.vz)
                    a_s, e_s = kep_s.get_elements()
                    r_apo = kep_s.get_apastron()
                    HillR = util.calc_HillRadius(a_s, e_s, other_star.mass,
                                                 star.mass)
                    if e_s >= 1.0 or HillR < r_apo:
                        noStellarHeirarchy = True
                    else:
                        noStellarHeirarchy = False
                if noStellarHeirarchy:
                    # Get Additional Information on Orbit
                    planet.semimajor_axis = a_p
                    planet.eccentricity = e_p
                    planet.period = kep_p.get_period()
                    planet.true_anomaly, planet.mean_anomaly = kep_p.get_angles(
                    )
                    #planet.kep_energy, planet.angular_momentum = kep_p.get_integrals()
                    # Add the Planet to the System Set
                    current_system.add_particle(planet)
                else:
                    # Handling for Planetary Systems in Stellar Heirarchical Structures
                    # Note: This is empty for now, maybe consider doing it by the heaviest bound stellar object as the primary.
                    pass
            else:
                continue
    kep_p.stop()
    kep_s.stop()
    return systems
Exemplo n.º 5
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)