Пример #1
0
def gen_scatteringIC(encounter_db, doMultipleClusters=False):
    global rootDir
    global cluster_name
    max_number_of_rotations = 100
    if doMultipleClusters:
        output_ICDirectory = rootDir + '/' + cluster_name + '/Scatter_IC/'
    else:
        output_ICDirectory = rootDir + '/Scatter_IC/'
    if not os.path.exists(output_ICDirectory): os.mkdir(output_ICDirectory)
    # Set up the Kepler Workers for Subroutines Now
    converter = nbody_system.nbody_to_si(1 | units.MSun, 100 | units.AU)
    kepler_workers = [
        Kepler(unit_converter=converter, redirection='none'),
        Kepler(unit_converter=converter, redirection='none')
    ]
    for kw in kepler_workers:
        kw.initialize_code()
    # Loop Through the Star_IDs
    for star_ID in list(encounter_db.keys()):
        output_KeyDirectory = output_ICDirectory + str(star_ID)
        if not os.path.exists(output_KeyDirectory):
            os.mkdir(output_KeyDirectory)
        encounter_ID = 0
        for encounter in encounter_db[star_ID]:
            # Set Up Subdirectory for this Specific Encounter
            output_EncPrefix = output_KeyDirectory + "/Enc-" + str(
                encounter_ID)
            # Set up Encounter Key for this Specific Encounter for this Specific Star
            rotation_ID = 0
            while rotation_ID <= max_number_of_rotations:
                # Set Up Output Directory for this Specific Iteration
                output_HDF5File = output_EncPrefix + "_Rot-" + str(
                    rotation_ID) + '.hdf5'
                next_outFile = output_EncPrefix + "_Rot-" + str(rotation_ID +
                                                                1) + '.hdf5'
                if os.path.exists(output_HDF5File):
                    if rotation_ID == 99:
                        rotation_ID += 1
                        continue
                    elif os.path.exists(next_outFile):
                        rotation_ID += 1
                        continue
                # Remove Jupiter and Add Desired Planetary System
                enc_bodies = replace_planetary_system(
                    encounter.copy(), kepler_workers=kepler_workers)
                write_set_to_file(enc_bodies,
                                  output_HDF5File,
                                  'hdf5',
                                  version='2.0',
                                  close_file=True)
                printID = str(star_ID) + "-" + str(encounter_ID) + "-" + str(
                    rotation_ID)
                print(util.timestamp(),
                      "Finished Generating Random Encounter ID:", printID,
                      "...")
                rotation_ID += 1
            encounter_ID += 1
    # Stop the Kepler Workers
    for kw in kepler_workers:
        kw.stop()
Пример #2
0
 def new_kepler_si(self):
     unit_converter = nbody_system.nbody_to_si(
         1 | units.MSun,
         1 | units.AU
     )
     kepler = Kepler(unit_converter)
     kepler.initialize_code()
     return kepler
Пример #3
0
def integrate_system(N, t_end, seed=None):

    gravity = ph4()
    gravity.initialize_code()
    gravity.parameters.set_defaults()
    
    if seed is not None: numpy.random.seed(seed)
    stars = new_plummer_model(N)
    stars.mass = 1./N | nbody_system.mass
    stars.scale_to_standard(smoothing_length_squared
                             = gravity.parameters.epsilon_squared)

    id = numpy.arange(N)
    stars.id = id+1

    # Set dynamical radii for encounters.

    stars.radius = 0.5*stars.mass.number | nbody_system.length

    gravity.particles.add_particles(stars)

    stopping_condition = gravity.stopping_conditions.collision_detection
    stopping_condition.enable()

    init_smalln()
    kep = Kepler(unit_converter=None)
    kep.initialize_code()
    multiples_code = multiples.Multiples(gravity, new_smalln, kep)
    multiples_code.neighbor_perturbation_limit = 0.05

    multiples_code.global_debug = 1

    #	global_debug = 0: no output from multiples
    #	               1: minimal output
    #	               2: debugging output
    #	               3: even more output

    print ''
    print 'multiples_code.neighbor_veto =', \
        multiples_code.neighbor_veto
    print 'multiples_code.neighbor_perturbation_limit =', \
        multiples_code.neighbor_perturbation_limit
    print 'multiples_code.retain_binary_apocenter =', \
        multiples_code.retain_binary_apocenter
    print 'multiples_code.wide_perturbation_limit =', \
        multiples_code.wide_perturbation_limit

    # Advance the system.

    E0 = print_diagnostics(multiples_code)
    multiples_code.evolve_model(t_end)
    print_diagnostics(multiples_code, E0)

    gravity.stop()
    kep.stop()
    stop_smalln()
Пример #4
0
def init_kepler(star1, star2):        
    try:
        star1.mass.value_in(units.kg) # see if SI units, throw exception if not
        unit_converter \
            = nbody_system.nbody_to_si(star1.mass + star2.mass,
                                       (star2.position-star1.position).length())
    except Exception as ex:
        unit_converter = None
        
    kep = Kepler(unit_converter, redirection = "none")
    kep.initialize_code()

    return kep
Пример #5
0
def init_kepler(star1, star2):        
    try:
        star1.mass.value_in(units.kg) # see if SI units, throw exception if not
        unit_converter \
            = nbody_system.nbody_to_si(star1.mass + star2.mass,
                                       (star2.position-star1.position).length())
    except Exception as ex:
        unit_converter = None
        
    kep = Kepler(unit_converter, redirection = "none")
    kep.initialize_code()

    return kep
Пример #6
0
def get_component_binary_elements(comp1, comp2):
    kep = Kepler(redirection = "none")
    kep.initialize_code()

    mass = comp1.mass + comp2.mass
    pos = comp2.position - comp1.position
    vel = comp2.velocity - comp1.velocity
    kep.initialize_from_dyn(mass, pos[0], pos[1], pos[2],
                            vel[0], vel[1], vel[2])
    a,e = kep.get_elements()
    r = kep.get_separation()
    E,J = kep.get_integrals()	# per unit reduced mass, note
    kep.stop()

    return mass,a,e,r,E
Пример #7
0
def new_system(
        star_mass = 1|units.MSun, 
        star_radius = 1|units.RSun, 
        disk_minumum_radius = 0.05 | units.AU,
        disk_maximum_radius = 10 | units.AU,
        disk_mass = 20 | MEarth,
        accurancy = 0.0001, 
        planet_density =  3 | units.g/units.cm**3,
        rng = None,
        kepler = None):
            
    central_particle = Particle()
    central_particle.mass =  star_mass
    central_particle.position = (0,0,0) | units.AU
    central_particle.velocity = (0,0,0) | units.kms
    central_particle.radius = star_radius
    
    if rng is None:
        rng = numpy.random
        
    converter = nbody_system.nbody_to_si(1|units.MSun, 1 | units.AU)
    
    if kepler is None:
        kepler = Kepler(converter)
        kepler.initialize_code()
        
    m, r, f = new_planet_distribution(
        disk_minumum_radius, disk_maximum_radius, 
        disk_mass,
        accurancy
    )
    
    planets = make_planets(
        central_particle, 
        m, r, 
        density = planet_density, 
        phi = 0, theta = None, 
        kepler = kepler, 
        rng = rng
    )
    
    central_particle.planets = planets
    kepler.stop()
    p = Particles()
    p.add_particle(central_particle)
    return p
Пример #8
0
def get_binary_elements(p):
    comp1 = p.child1
    comp2 = p.child2
    kep = Kepler(redirection="none")
    kep.initialize_code()

    mass = comp1.mass + comp2.mass
    pos = [comp2.x - comp1.x, comp2.y - comp1.y, comp2.z - comp1.z]
    vel = [comp2.vx - comp1.vx, comp2.vy - comp1.vy, comp2.vz - comp1.vz]
    kep.initialize_from_dyn(mass, pos[0], pos[1], pos[2], vel[0], vel[1],
                            vel[2])
    a, e = kep.get_elements()
    kep.stop()

    return mass, a, e
Пример #9
0
def new_multiples_code(gravity, converter):
    """
    Initialise a multiples instance with specified gravity code.
    The gravity code must support stopping conditions (collision detection).
    """
    gravity.parameters.epsilon_squared = (0.0 | units.parsec)**2
    stopping_condition = gravity.stopping_conditions.collision_detection
    stopping_condition.enable()

    init_smalln(converter)
    kep = Kepler(unit_converter=converter)
    kep.initialize_code()
    multiples_code = multiples.Multiples(
        gravity,
        new_smalln,
        kep,
        constants.G,
    )
    multiples_code.neighbor_perturbation_limit = 0.05
    multiples_code.global_debug = 0
    return multiples_code
Пример #10
0
def update_host_star(system, converter=None, kepler_worker=None):
    if kepler_worker == None:
        if converter == None:
            converter = nbody_system.nbody_to_si(
                system.mass.sum(),
                2 * np.max(system.radius.number) | system.radius.unit)
        kep_p = Kepler(unit_converter=converter, redirection='none')
        kep_p.initialize_code()
    else:
        kep_p = kepler_worker
    stars = util.get_stars(system)
    planets = util.get_planets(system)
    p_NearestStar = planets.nearest_neighbour(stars)
    for i, planet in enumerate(planets):
        likely_host = p_NearestStar[i]
        update_orb_elem(likely_host, [planet],
                        converter=converter,
                        kepler_worker=kep_p)
        if planet.eccentricity >= 1.0:
            for s in stars - likely_host:
                update_orb_elem(s, [planet],
                                converter=converter,
                                kepler_worker=kep_p)
                if planet.eccentricity < 1.0:
                    planet.host_star = s.id
                    break
                elif planet.eccentricity >= 1.0:
                    planet.host_star = -1
        else:
            planet.host_star = likely_host.id
    if kepler_worker == None:
        kep_p.stop()
Пример #11
0
def integrate_system(N, t_end, seed=None):

    total_mass = N | units.MSun
    length = 1 | units.parsec
    converter = nbody_system.nbody_to_si(total_mass, length)
    gravity = ph4(convert_nbody=converter)
    gravity.initialize_code()
    gravity.parameters.set_defaults()
    gravity.parameters.epsilon_squared = (0.0 | units.parsec)**2

    if seed is not None: numpy.random.seed(seed)
    stars = new_plummer_model(N, convert_nbody=converter)
    stars.mass = total_mass / N
    stars.scale_to_standard(
        convert_nbody=converter,
        smoothing_length_squared=gravity.parameters.epsilon_squared)
    id = numpy.arange(N)
    stars.id = id + 1
    stars.radius = 0.5 / N | units.parsec

    gravity.particles.add_particles(stars)

    stopping_condition = gravity.stopping_conditions.collision_detection
    stopping_condition.enable()

    init_smalln(converter)
    kep = Kepler(unit_converter=converter)
    kep.initialize_code()
    multiples_code = multiples.Multiples(gravity, new_smalln, kep, constants.G)
    multiples_code.neighbor_perturbation_limit = 0.05
    multiples_code.global_debug = 1
    ###BOOKLISTSTOP2###

    #	global_debug = 0: no output from multiples
    #	               1: minimal output
    #	               2: debugging output
    #	               3: even more output

    print('')
    print('multiples_code.neighbor_veto =', \
        multiples_code.neighbor_veto)
    print('multiples_code.neighbor_perturbation_limit =', \
        multiples_code.neighbor_perturbation_limit)
    print('multiples_code.retain_binary_apocenter =', \
        multiples_code.retain_binary_apocenter)
    print('multiples_code.wide_perturbation_limit =', \
        multiples_code.wide_perturbation_limit)

    time = numpy.sqrt(length**3 / (constants.G * total_mass))
    print('\ntime unit =', time.in_(units.Myr))
    ###BOOKLISTSTART3###

    E0 = print_diagnostics(multiples_code)
    multiples_code.evolve_model(t_end)
    print_diagnostics(multiples_code, E0)
    ###BOOKLISTSTOP3###

    gravity.stop()
    kep.stop()
    stop_smalln()
Пример #12
0
def get_binary_elements(p):
    comp1 = p.child1
    comp2 = p.child2
    kep = Kepler(redirection = "none")
    kep.initialize_code()

    mass = comp1.mass + comp2.mass
    pos = [comp2.x-comp1.x, comp2.y-comp1.y, comp2.z-comp1.z]
    vel = [comp2.vx-comp1.vx, comp2.vy-comp1.vy, comp2.vz-comp1.vz]
    kep.initialize_from_dyn(mass, pos[0], pos[1], pos[2],
                            vel[0], vel[1], vel[2])
    a,e = kep.get_elements()
    kep.stop()

    return mass,a,e
Пример #13
0
def integrate_system(N, t_end, seed=None):

    gravity = ph4()
    gravity.initialize_code()
    gravity.parameters.set_defaults()
    
    if seed is not None: numpy.random.seed(seed)
    stars = new_plummer_model(N)
    stars.mass = 1./N | nbody_system.mass
    stars.scale_to_standard(smoothing_length_squared
                             = gravity.parameters.epsilon_squared)

    id = numpy.arange(N)
    stars.id = id+1

    # Set dynamical radii for encounters.

    stars.radius = 0.5*stars.mass.number | nbody_system.length

    gravity.particles.add_particles(stars)

    stopping_condition = gravity.stopping_conditions.collision_detection
    stopping_condition.enable()

    init_smalln()
    kep = Kepler(unit_converter=None)
    kep.initialize_code()
    multiples_code = multiples.Multiples(gravity, new_smalln, kep)
    multiples_code.neighbor_perturbation_limit = 0.05

    multiples_code.global_debug = 1

    #	global_debug = 0: no output from multiples
    #	               1: minimal output
    #	               2: debugging output
    #	               3: even more output

    print('')
    print('multiples_code.neighbor_veto =', \
        multiples_code.neighbor_veto)
    print('multiples_code.neighbor_perturbation_limit =', \
        multiples_code.neighbor_perturbation_limit)
    print('multiples_code.retain_binary_apocenter =', \
        multiples_code.retain_binary_apocenter)
    print('multiples_code.wide_perturbation_limit =', \
        multiples_code.wide_perturbation_limit)

    # Advance the system.

    E0 = print_diagnostics(multiples_code)
    multiples_code.evolve_model(t_end)
    print_diagnostics(multiples_code, E0)

    gravity.stop()
    kep.stop()
    stop_smalln()
def new_system(star_mass=1 | units.MSun,
               star_radius=1 | units.RSun,
               disk_minimum_radius=0.05 | units.AU,
               disk_maximum_radius=10 | units.AU,
               disk_mass=20 | MEarth,
               accurancy=0.0001,
               planet_density=3 | units.g / units.cm**3,
               rng=None,
               kepler=None):

    central_particle = Particle()
    central_particle.mass = star_mass
    central_particle.position = (0, 0, 0) | units.AU
    central_particle.velocity = (0, 0, 0) | units.kms
    central_particle.radius = star_radius
    central_particle.name = "star"
    central_particle.type = "star"
    central_particle.id = 0

    if rng is None:
        rng = numpy.random

    converter = nbody_system.nbody_to_si(1 | units.MSun, 1 | units.AU)

    if kepler is None:
        kepler = Kepler(converter)
        kepler.initialize_code()

    m, r, f = new_planet_distribution(disk_minimum_radius, disk_maximum_radius,
                                      disk_mass, accurancy)

    planets = make_planets(central_particle,
                           m,
                           r,
                           density=planet_density,
                           phi=0,
                           theta=None,
                           kepler=kepler,
                           rng=rng)
    planets.name = "planet"
    planets.type = "planet"
    for i in range(len(planets)):
        planets[i].id = i

    central_particle.planets = planets
    kepler.stop()
    p = Particles()
    p.add_particle(central_particle)
    return p
def orbital_parameters_for_the_planets(bodies, verbose=True):
    from amuse.community.kepler.interface import Kepler
    kepler = Kepler(redirection = "none")
    kepler.initialize_code()
#    kep_converter=nbody_system.nbody_to_si(1|units.MSun, 10|units.AU)
    converter=nbody_system.nbody_to_si(1.0|units.MSun, 1|units.AU)
    a = [] | units.AU
    e = []
    m = [] | units.MSun
    name = []
    for bi in bodies[1:]:
        ai, ei, M, ms = calculate_orbital_elements(bodies[0], bi, kepler, converter)
        name.append(bi.name)
        a.append(ai)
        e.append(ei)
        m.append(ms)
    kepler.stop()
    if verbose:
        for i in range(len(a)):
            print("Planet: ", name[i], a[i], e[i], m[i]) 
    return a, e
Пример #16
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()
Пример #17
0
    #-----------------------------------------------------------------

    assert is_mpd_running()

    # Instantiate workers once only and pass to scatter3 as arguments.

    gravity = SmallN(redirection="none")
    #gravity = SmallN(redirection = "none", debugger="valgrind") # search for
    # memory leaks
    gravity.initialize_code()
    gravity.parameters.set_defaults()
    gravity.parameters.timestep_parameter = accuracy_parameter
    gravity.parameters.unperturbed_threshold = gamma

    kep = Kepler(redirection="none")  #, debugger="gdb")
    kep.initialize_code()
    kep.set_random(random_seed)  # ** Note potential conflict between C++
    # ** and Python random generators.

    # Timing:

    cpu = numpy.zeros(4)

    for i in range(nscatter):

        final, dcpu = scatter3(init, kep, gravity, gamma, delta_t, t_end)
        cpu += dcpu

        print ''
        if final.is_over == 0:
Пример #18
0
    stopping_condition.enable()
    sys.stdout.flush()

# Adding and Committing Particles to PH4
    gravity.particles.add_particles(MasterSet)
    gravity.commit_particles()
    #print gravity.particles[-5:]

# Starting the AMUSE Channel for PH4
    grav_to_MS_channel = gravity.particles.new_channel_to(MasterSet)
    MS_to_grav_channel = MasterSet.new_channel_to(gravity.particles, 
                            attributes=["x","y","z","vx","vy","vz"])

    SmallScaleConverter = nbody_system.nbody_to_si(2*np.mean(MasterSet.mass), 2*np.mean(MasterSet.radius))
# Initializing Kepler and SmallN
    kep = Kepler(unit_converter=SmallScaleConverter, redirection = "none")
    kep.initialize_code()
    util.init_smalln(unit_converter=SmallScaleConverter)

# Initializing MULTIPLES, Testing to See if a Crash Exists First
    if read_from_file and crash:
        time, multiples_code = read.recover_crash(crash_file, gravity, kep, util.new_smalln)
    else:
        multiples_code = multiples.Multiples(gravity, util.new_smalln, kep, 
                                             gravity_constant=units.constants.G)
        multiples_code.neighbor_perturbation_limit = 0.05
        #multiples_code.neighbor_distance_factor = 1.0
        multiples_code.neighbor_veto = True

# Initializing Stellar Evolution (SeBa)
    sev_code = SeBa()
Пример #19
0
def new_kepler():
    from amuse.community.kepler.interface import Kepler
    converter = nbody_system.nbody_to_si(1 | units.MSun, 1 | units.AU)
    kepler = Kepler(converter)
    kepler.initialize_code()
    return kepler
Пример #20
0
def run_ph4(infile = None, outfile = None,
             number_of_stars = 100, number_of_binaries = 0,
             end_time = 10 | nbody_system.time,
             delta_t = 1 | nbody_system.time,
             n_workers = 1, use_gpu = 1, gpu_worker = 1,
             salpeter = 0,
             accuracy_parameter = 0.1,
             softening_length = 0.0 | nbody_system.length,
             manage_encounters = 1, random_seed = 1234):

    if random_seed <= 0:
        numpy.random.seed()
        random_seed = numpy.random.randint(1, pow(2,31)-1)
    numpy.random.seed(random_seed)
    print "random seed =", random_seed

    if infile != None: print "input file =", infile
    print "end_time =", end_time.number
    print "delta_t =", delta_t.number
    print "n_workers =", n_workers
    print "use_gpu =", use_gpu
    print "manage_encounters =", manage_encounters
    print "\ninitializing the gravity module"
    sys.stdout.flush()

    init_smalln()
    
    # Note that there are actually three GPU options:
    #
    #	1. use the GPU code and allow GPU use (default)
    #	2. use the GPU code but disable GPU use (-g)
    #	3. use the non-GPU code (-G)

    if gpu_worker == 1:
        try:
            gravity = grav(number_of_workers = n_workers,
                           redirection = "none", mode = "gpu")
        except Exception as ex:
            gravity = grav(number_of_workers = n_workers,
                           redirection = "none")
    else:
        gravity = grav(number_of_workers = n_workers,
                       redirection = "none")

    gravity.initialize_code()
    gravity.parameters.set_defaults()

    #-----------------------------------------------------------------

    if infile == None:

        print "making a Plummer model"
        stars = new_plummer_model(number_of_stars)

        id = numpy.arange(number_of_stars)
        stars.id = id+1

        print "setting particle masses and radii"
        if salpeter == 0:
            print 'equal masses'
            total_mass = 1.0 | nbody_system.mass
            scaled_mass = total_mass / number_of_stars
        else:
            print 'salpeter mass function'
            scaled_mass = new_salpeter_mass_distribution_nbody(number_of_stars) 
        stars.mass = scaled_mass

        print "centering stars"
        stars.move_to_center()
        print "scaling stars to virial equilibrium"
        stars.scale_to_standard(smoothing_length_squared
                                    = gravity.parameters.epsilon_squared)

    else:

        # Read the input data.  Units are dynamical (sorry).
        # Format:  id  mass  pos[3]  vel[3]

        print "reading file", infile

        id = []
        mass = []
        pos = []
        vel = []

        f = open(infile, 'r')
        count = 0
        for line in f:
            if len(line) > 0:
                count += 1
                cols = line.split()
                if count == 1: snap = int(cols[0])
                elif count == 2: number_of_stars = int(cols[0])
                elif count == 3: time = float(cols[0]) | nbody_system.time
                else:
                    if len(cols) >= 8:
                        id.append(int(cols[0]))
                        mass.append(float(cols[1]))
                        pos.append((float(cols[2]),
                                    float(cols[3]), float(cols[4])))
                        vel.append((float(cols[5]),
                                    float(cols[6]), float(cols[7])))
        f.close()

        stars = datamodel.Particles(number_of_stars)
        stars.id = id
        stars.mass = mass | nbody_system.mass
        stars.position = pos | nbody_system.length
        stars.velocity = vel | nbody_system.speed
        #stars.radius = 0. | nbody_system.length

    total_mass = stars.mass.sum()
    ke = pa.kinetic_energy(stars)
    kT = ke/(1.5*number_of_stars)

    if number_of_binaries > 0:

        # Turn selected stars into binary components.
        # Only tested for equal-mass case.

        kep = Kepler(redirection = "none")
        kep.initialize_code()

        added_mass = 0.0 | nbody_system.mass

        # Work with energies rather than semimajor axes.

        Emin = 10*kT
        Emax = 20*kT
        ecc = 0.1

        id_count = number_of_stars
        nbin = 0
        for i in range(0, number_of_stars,
                       number_of_stars/number_of_binaries):

            # Star i is CM, becomes component, add other star at end.

            nbin += 1

            mass = stars[i].mass
            new_mass = numpy.random.uniform()*mass	# uniform q?
            mbin = mass + new_mass
            fac = new_mass/mbin
            E = Emin + numpy.random.uniform()*(Emax-Emin)
            a = 0.5*nbody_system.G*mass*new_mass/E

            kep.initialize_from_elements(mbin, a, ecc)
            dr = quantities.AdaptingVectorQuantity()
            dr.extend(kep.get_separation_vector())
            dv = quantities.AdaptingVectorQuantity()
            dv.extend(kep.get_velocity_vector())

            newstar = datamodel.Particles(1)
            newstar.mass = new_mass
            newstar.position = stars[i].position + (1-fac)*dr
            newstar.velocity = stars[i].velocity + (1-fac)*dv
            # stars[i].mass = mass
            stars[i].position = stars[i].position - fac*dr
            stars[i].velocity = stars[i].velocity - fac*dv

            id_count += 1
            newstar.id = id_count
            stars.add_particles(newstar)
            added_mass += new_mass

            if nbin >= number_of_binaries: break

        kep.stop()

        print 'created', nbin, 'binaries'
        sys.stdout.flush()

        stars.mass = stars.mass * total_mass/(total_mass+added_mass)
        number_of_stars += nbin

    # Set dynamical radii (assuming virial equilibrium and standard
    # units).  Note that this choice should be refined, and updated
    # as the system evolves.  Probably the choice of radius should be
    # made entirely in the multiples module.  TODO.  In these units,
    # M = 1 and <v^2> = 0.5, so the mean 90-degree turnaround impact
    # parameter is
    #
    #		b_90 = G (m_1+m_2) / vrel^2
    #		     = 2 <m> / 2<v^2>
    #		     = 2 / N			for equal masses
    #
    # Taking r_i = m_i / 2<v^2> = m_i in virial equilibrium means
    # that, approximately, "contact" means a 90-degree deflection (r_1
    # + r_2 = b_90).  A more conservative choice with r_i less than
    # this value will isolates encounters better, but also place more
    # load on the large-N dynamical module.

    stars.radius = stars.mass.number | nbody_system.length

    time = 0.0 | nbody_system.time
    # print "IDs:", stars.id.number

    print "recentering stars"
    stars.move_to_center()
    sys.stdout.flush()

    #-----------------------------------------------------------------

    if softening_length < 0.0 | nbody_system.length:

        # Use ~interparticle spacing.  Assuming standard units here.  TODO

        eps2 = 0.25*(float(number_of_stars))**(-0.666667) \
			| nbody_system.length**2
    else:
        eps2 = softening_length*softening_length
    print 'softening length =', eps2.sqrt()

    gravity.parameters.timestep_parameter = accuracy_parameter
    gravity.parameters.epsilon_squared = eps2
    gravity.parameters.use_gpu = use_gpu
    # gravity.parameters.manage_encounters = manage_encounters

    print ''
    print "adding particles"
    # print stars
    sys.stdout.flush()
    gravity.particles.add_particles(stars)
    gravity.commit_particles()

    print ''
    print "number_of_stars =", number_of_stars
    print "evolving to time =", end_time.number, \
          "in steps of", delta_t.number
    sys.stdout.flush()

    # Channel to copy values from the code to the set in memory.
    channel = gravity.particles.new_channel_to(stars)

    stopping_condition = gravity.stopping_conditions.collision_detection
    stopping_condition.enable()

    # Debugging: prevent the multiples code from being called.
    if 0:
        stopping_condition.disable()
        print 'stopping condition disabled'
        sys.stdout.flush()

    # -----------------------------------------------------------------
    # Create the coupled code and integrate the system to the desired
    # time, managing interactions internally.

    kep = init_kepler(stars[0], stars[1])
    multiples_code = multiples.Multiples(gravity, new_smalln, kep)

    multiples_code.neighbor_perturbation_limit = 0.1
    #multiples_code.neighbor_distance_factor = 1.0
    #multiples_code.neighbor_veto = False
    #multiples_code.neighbor_distance_factor = 2.0
    multiples_code.neighbor_veto = True

    print ''
    print 'multiples_code.initial_scale_factor =', \
        multiples_code.initial_scale_factor
    print 'multiples_code.neighbor_perturbation_limit =', \
        multiples_code.neighbor_perturbation_limit
    print 'multiples_code.neighbor_veto =', \
        multiples_code.neighbor_veto
    print 'multiples_code.final_scale_factor =', \
        multiples_code.final_scale_factor
    print 'multiples_code.initial_scatter_factor =', \
        multiples_code.initial_scatter_factor
    print 'multiples_code.final_scatter_factor =', \
        multiples_code.final_scatter_factor
    print 'multiples_code.retain_binary_apocenter =', \
        multiples_code.retain_binary_apocenter
    print 'multiples_code.wide_perturbation_limit =', \
        multiples_code.wide_perturbation_limit

    pre = "%%% "
    E0,cpu0 = print_log(pre, time, multiples_code)

    while time < end_time:

        time += delta_t
        multiples_code.evolve_model(time)

        # Copy values from the module to the set in memory.

        channel.copy()
    
        # Copy the index (ID) as used in the module to the id field in
        # memory.  The index is not copied by default, as different
        # codes may have different indices for the same particle and
        # we don't want to overwrite silently.

        channel.copy_attribute("index_in_code", "id")

        print_log(pre, time, multiples_code, E0, cpu0)
        sys.stdout.flush()

    #-----------------------------------------------------------------

    if not outfile == None:

        # Write data to a file.

        f = open(outfile, 'w')

        #--------------------------------------------------
        # Need to save top-level stellar data and parameters.
        # Need to save multiple data and parameters.

        f.write('%.15g\n'%(time.number))
        for s in multiples_code.stars: write_star(s, f)

        #--------------------------------------------------

        f.close()
        print 'wrote file', outfile

    print ''
    gravity.stop()
Пример #21
0
    else:
        directory = os.getcwd()
        cluster_name = directory.split("/")[-1]

    base_planet_ID = 50000

    orig_stdout = sys.stdout
    log_file = open(os.getcwd() + "/cut_encounters.log", "w")
    sys.stdout = log_file

    # Create the Kepler Workers
    KeplerWorkerList = []
    converter = nbody_system.nbody_to_si(1 | units.MSun, 100 | units.AU)
    for i in range(3):
        KeplerWorkerList.append(
            Kepler(unit_converter=converter, redirection='none'))
        KeplerWorkerList[-1].initialize_code()

    # Read in Encounter Directory
    encounter_file = open(os.getcwd() + "/" + cluster_name + "_encounters.pkl",
                          "rb")
    encounter_db = pickle.load(encounter_file)
    encounter_file.close()

    sys.stdout.flush()
    print(util.timestamp(), "Performing First Cut on Encounter Database ...")
    print(len(encounter_db.keys()))
    sys.stdout.flush()
    # Perform a Cut on the Encounter Database
    for star_ID in list(encounter_db.keys()):
        # Cut Out Stars Recorded with Only Initialization Pickups
Пример #22
0
def get_component_binary_elements(comp1, comp2):
    kep = Kepler(redirection="none")
    kep.initialize_code()

    mass = comp1.mass + comp2.mass
    pos = comp2.position - comp1.position
    vel = comp2.velocity - comp1.velocity
    kep.initialize_from_dyn(mass, pos[0], pos[1], pos[2], vel[0], vel[1],
                            vel[2])
    a, e = kep.get_elements()
    r = kep.get_separation()
    E, J = kep.get_integrals()  # per unit reduced mass, note
    kep.stop()

    return mass, a, e, r, E
Пример #23
0
def run_ph4(initial_file=None,
            end_time=0 | nbody_system.time,
            input_delta_t=0.0 | nbody_system.time,
            input_Delta_t=1.0 | nbody_system.time,
            input_timestep_parameter=0.0,
            input_softening_length=-1.0 | nbody_system.length,
            n_workers=1,
            use_gpu=1,
            gpu_worker=1,
            use_multiples=True,
            save_restart=False,
            strict_restart=False):

    # Read an N-body system from a file and run it to the specified
    # time using the specified steps.  Print log information and
    # optionally save a restart file after every step.  If the
    # specified time is less than the time in the initial file, don't
    # take a step, but still print out the log info.  (Hence run_ph4
    # also functions like Starlab sys_stats.)

    print "initial_file =", initial_file
    print "end_time =", end_time.number
    print "n_workers =", n_workers
    print "use_gpu =", use_gpu
    print "use_multiples =", use_multiples
    print "save_restart =", save_restart
    print "strict_restart =", strict_restart
    print "\ninitializing the gravity module"
    sys.stdout.flush()

    init_smalln()

    # Note that there are actually three GPU options:
    #
    #	1. use the GPU code and allow GPU use (default)
    #	2. use the GPU code but disable GPU use (-g)
    #	3. use the non-GPU code (-G)

    if gpu_worker == 1:
        try:
            gravity = grav(number_of_workers=n_workers,
                           redirection="none",
                           mode="gpu")
        except Exception as ex:
            gravity = grav(number_of_workers=n_workers, redirection="none")
    else:
        gravity = grav(number_of_workers=n_workers, redirection="none")

    gravity.initialize_code()
    gravity.parameters.set_defaults()

    kep = Kepler(None, redirection="none")
    kep.initialize_code()

    stars, time, delta_t, E0, cpu0, multiples_code \
         = read_state_from_file(initial_file, gravity, kep)

    # Allow overrides of the restored data (OK for delta_t, NOT
    # recommended for timestep_parameter or softening_length).  Note
    # that reading the state also commits the particles, and hence
    # calculates the initial time steps.  Probably should reinitialize
    # if timestep_parameter or softening_length are changed.  TODO

    if input_delta_t.number > 0:
        if input_delta_t != delta_t:
            print 'modifying delta_t from stored', delta_t, \
    'to input', input_delta_t
            delta_t = input_delta_t
    else:
        print "using stored delta_t =", delta_t

    print input_timestep_parameter
    print gravity.parameters.timestep_parameter

    if input_timestep_parameter > 0:
        if input_timestep_parameter != gravity.parameters.timestep_parameter:
            print 'modifying timestep_parameter from stored', \
               gravity.parameters.timestep_parameter, \
    'to input', input_timestep_parameter
            gravity.parameters.timestep_parameter \
  = input_timestep_parameter
    else:
        print 'timestep_parameter =', gravity.parameters.timestep_parameter

    if input_softening_length.number >= 0:
        if input_softening_length*input_softening_length \
  != gravity.parameters.epsilon_squared:
            print 'modifying softening_length from stored', \
               gravity.parameters.epsilon_squared.sqrt(), \
    'to input', input_softening_length
            gravity.parameters.epsilon_squared \
                = softening_length*softening_length
    else:
        print 'softening length =', gravity.parameters.epsilon_squared.sqrt()

    gravity.parameters.use_gpu = use_gpu
    gravity.parameters.begin_time = time

    if 0:
        print ''
        print gravity.parameters.begin_time
        print stars.mass
        #print stars.position
        for s in stars:
            print '%.18e %.18e %.18e' % (s.x.number, s.y.number, s.z.number)
        print stars.velocity

    channel = gravity.particles.new_channel_to(stars)

    if use_multiples:
        stopping_condition = gravity.stopping_conditions.collision_detection
        stopping_condition.enable()

    gravity.parameters.force_sync = 1  # end exactly at the specified time

    pre = "%%% "
    print_log(pre, time, multiples_code, E0, cpu0)

    tsave = time + Delta_t
    save_file = ''

    while time < end_time:

        time += delta_t
        multiples_code.evolve_model(time)  #, callback=handle_callback)

        # Copy values from the module to the set in memory.

        channel.copy()

        # Copy the index (ID) as used in the module to the id field in
        # memory.  The index is not copied by default, as different
        # codes may have different indices for the same particle and
        # we don't want to overwrite silently.

        channel.copy_attribute("index_in_code", "id")

        # Write log information.

        print_log(pre, time, multiples_code, E0, cpu0)
        sys.stdout.flush()

        # Optionally create a restart file.

        if save_restart and time >= tsave:
            #save_file = 't='+'{:07.2f}'.format(time.number) # not in Python 2.6
            save_file = 't=%07.2f' % time.number
            write_state_to_file(time, stars, gravity, multiples_code,
                                save_file, delta_t, E0, cpu0)
            sys.stdout.flush()
            tsave += Delta_t
            if strict_restart: break

    gravity.stop()
    kep.stop()
    stop_smalln()

    return time, save_file
Пример #24
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)
Пример #25
0
def CutOrAdvance(enc_bodies, primary_sysID, converter=None):
    bodies = enc_bodies.copy()
    if converter==None:
        converter = nbody_system.nbody_to_si(bodies.mass.sum(), 2 * np.max(bodies.radius.number) | bodies.radius.unit)
    systems = stellar_systems.get_heirarchical_systems_from_set(bodies, converter=converter, RelativePosition=False)
    # Deal with Possible Key Issues with Encounters with 3+ Star Particles Being Run More than Other Systems ...
    if int(primary_sysID) not in systems.keys():
        print "...: Error: Previously run binary system has been found! Not running this system ..."
        print primary_sysID
        print systems.keys()
        print "---------------------------------"
        return None
    # As this function is pulling from Multiples, there should never be more or less than 2 "Root" Particles ...
    if len(systems) != 2:
        print "...: Error: Encounter has more roots than expected! Total Root Particles:", len(systems)
        print bodies
        print "---------------------------------"
        return None
    # Assign the Primary System to #1 and Perturbing System to #2
    sys_1 = systems[int(primary_sysID)]
    secondary_sysID = [key for key in systems.keys() if key!=int(primary_sysID)][0]
    sys_2 = systems[secondary_sysID]
    print 'All System Keys:', systems.keys()
    print 'Primary System Key:', primary_sysID
    print 'System 1 IDs:', sys_1.id
    print 'System 2 IDs:', sys_2.id
    # Calculate Useful Quantities
    mass_ratio = sys_2.mass.sum()/sys_1.mass.sum()
    total_mass = sys_1.mass.sum() + sys_2.mass.sum()
    rel_pos = sys_1.center_of_mass() - sys_2.center_of_mass()
    rel_vel = sys_1.center_of_mass_velocity() - sys_2.center_of_mass_velocity()
    # Initialize Kepler Worker
    kep = Kepler(unit_converter = converter, redirection = 'none')
    kep.initialize_code()
    kep.initialize_from_dyn(total_mass, rel_pos[0], rel_pos[1], rel_pos[2], rel_vel[0], rel_vel[1], rel_vel[2])
    # Check to See if the Periastron is within the Ignore Distance for 10^3 Perturbation
    p = kep.get_periastron()
    ignore_distance = mass_ratio**(1./3.) * 600 | units.AU
    if p > ignore_distance:
        print "Encounter Ignored due to Periastron of", p.in_(units.AU), "and an IgnoreDistance of",ignore_distance
        kep.stop()
        print "---------------------------------"
        return None
    # Move the Particles to be Relative to their Respective Center of Mass
    cm_sys_1, cm_sys_2 = sys_1.center_of_mass(), sys_2.center_of_mass()
    cmv_sys_1, cmv_sys_2 = sys_1.center_of_mass_velocity(), sys_2.center_of_mass_velocity()
    for particle in sys_1:
        particle.position -= cm_sys_1
        particle.velocity -= cmv_sys_1
    for particle in sys_2:
        particle.position -= cm_sys_2
        particle.velocity -= cmv_sys_2
    # Check to See if the Planets are Closer than the Ignore Distance
    # Note: This shouldn't happen in the main code, but this prevents overshooting the periastron in debug mode.
    if kep.get_separation() > ignore_distance:
        kep.advance_to_radius(ignore_distance)
    # Advance the Center of Masses to the Desired Distance in Reduced Mass Coordinates
    x, y, z = kep.get_separation_vector()
    rel_pos_f = rel_pos.copy()
    rel_pos_f[0], rel_pos_f[1], rel_pos_f[2] = x, y, z
    vx, vy, vz = kep.get_velocity_vector()
    rel_vel_f = rel_vel.copy()
    rel_vel_f[0], rel_vel_f[1], rel_vel_f[2] = vx, vy, vz
    # Transform to Absolute Coordinates from Kepler Reduced Mass Coordinates
    cm_pos_1, cm_pos_2 = sys_2.mass.sum() * rel_pos_f / total_mass, -sys_1.mass.sum() * rel_pos_f / total_mass
    cm_vel_1, cm_vel_2 = sys_2.mass.sum() * rel_vel_f / total_mass, -sys_1.mass.sum() * rel_vel_f / total_mass
    # Move the Particles to the New Postions of their Respective Center of Mass
    for particle in sys_1:
        particle.position += cm_pos_1
        particle.velocity += cm_vel_1
    for particle in sys_2:
        particle.position += cm_pos_2
        particle.velocity += cm_vel_2
    # Stop Kepler and Return the Systems as a Particle Set
    kep.stop()
    # Collect the Collective Particle Set to be Returned Back
    final_set = Particles()
    final_set.add_particles(sys_1)
    final_set.add_particles(sys_2)
    print "---------------------------------"
    return final_set
Пример #26
0
    if random_seed <= 0:
        numpy.random.seed()
        random_seed = numpy.random.randint(1, pow(2,31)-1)
    numpy.random.seed(random_seed)
    print "random seed =", random_seed, numpy.random.random()

    #-----------------------------------------------------------------

    assert is_mpd_running()

    # Instantiate worker modules once only and pass them to scatter32
    # as arguments.

    # Kepler manages two-body dynamics.

    kep = Kepler(redirection = "none") #, debugger="gdb")
    kep.initialize_code()
    kep.set_random(random_seed)	  # ** Note potential conflict between C++
				  # ** and Python random generators.

    # Gravity manages the N-body integration.

    gravity = SmallN(redirection = "none")
    gravity.initialize_code()
    gravity.parameters.set_defaults()
    gravity.parameters.timestep_parameter = accuracy_parameter
    gravity.parameters.unperturbed_threshold = gamma

    # Treecheck determines the structure of the 3-body system.
    # Treecheck = gravity is OK.
Пример #27
0
def run_ph4(options,
            time=None,
            stars=None,
            mc_root_to_tree=None,
            randomize=True):
    infile = options.infile
    outfile = options.outfile
    restart_file = options.restart_file
    number_of_stars = options.N
    number_of_binaries = options.Nbin
    end_time = options.t_end | nbody_system.time
    delta_t = options.delta_t | nbody_system.time
    n_workers = options.n_workers
    use_gpu = options.use_gpu
    gpu_worker = options.gpu_worker
    salpeter = options.salpeter
    accuracy_parameter = options.accuracy_parameter
    softening_length = options.softening_length | nbody_system.length
    manage_encounters = options.manage_encounters
    random_seed = options.random_seed

    if randomize:
        if random_seed <= 0:
            numpy.random.seed()
            random_seed = numpy.random.randint(1, pow(2, 31) - 1)
        numpy.random.seed(random_seed)
        print "random seed =", random_seed

    if infile is not None: print "input file =", infile
    if restart_file is not None: print "restart file =", restart_file
    if restart_file is not None and infile is not None:
        print "restart file overrides input file"
    print "end_time =", end_time.number
    print "delta_t =", delta_t.number
    print "n_workers =", n_workers
    print "use_gpu =", use_gpu
    print "manage_encounters =", manage_encounters
    print "n =", number_of_stars
    print "nbin=", number_of_binaries
    print "\ninitializing the gravity module"
    sys.stdout.flush()

    init_smalln()

    # Note that there are actually three GPU options:
    #
    #	1. use the GPU code and allow GPU use (default)
    #	2. use the GPU code but disable GPU use (-g)
    #	3. use the non-GPU code (-G)

    if gpu_worker == 1:
        try:
            #gravity = GravityModule(number_of_workers = n_workers,
            #               redirection = "xterm")
            gravity = GravityModule(number_of_workers=n_workers,
                                    redirection="none",
                                    mode="gpu")
        except Exception as ex:
            gravity = GravityModule(number_of_workers=n_workers,
                                    redirection="none")
    else:
        gravity = GravityModule(number_of_workers=n_workers,
                                redirection="none")

    gravity.initialize_code()
    gravity.parameters.set_defaults()

    if softening_length < 0.0 | nbody_system.length:

        # Use ~interparticle spacing.  Assuming standard units here.  TODO

        eps2 = 0.25*(float(number_of_stars))**(-0.666667) \
            | nbody_system.length**2
    else:
        eps2 = softening_length * softening_length
    print 'softening length =', eps2.sqrt()

    gravity.parameters.timestep_parameter = accuracy_parameter
    gravity.parameters.epsilon_squared = eps2
    gravity.parameters.use_gpu = use_gpu

    kep = Kepler(redirection="none")
    kep.initialize_code()

    multiples_code = None
    Xtra = numpy.zeros(2)

    #-----------------------------------------------------------------

    if (restart_file is None
            or not os.path.exists(restart_file + ".stars.hdf5")
        ) and infile is None and stars is None:

        print "making a Plummer model"
        stars = new_plummer_model(number_of_stars)

        id = numpy.arange(number_of_stars)
        stars.id = id + 1

        print "setting particle masses and radii"
        if salpeter == 0:
            print 'equal masses'
            total_mass = 1.0 | nbody_system.mass
            scaled_mass = total_mass / number_of_stars
        else:
            print 'salpeter mass function'
            scaled_mass = new_salpeter_mass_distribution_nbody(number_of_stars)
        stars.mass = scaled_mass

        print "centering stars"
        stars.move_to_center()
        print "scaling stars to virial equilibrium"
        stars.scale_to_standard(
            smoothing_length_squared=gravity.parameters.epsilon_squared)
        time = 0.0 | nbody_system.time

        total_mass = stars.mass.sum()
        ke = pa.kinetic_energy(stars)
        kT = ke / (1.5 * number_of_stars)

        # Set dynamical radii (assuming virial equilibrium and standard
        # units).  Note that this choice should be refined, and updated
        # as the system evolves.  Probably the choice of radius should be
        # made entirely in the multiples module.  TODO.  In these units,
        # M = 1 and <v^2> = 0.5, so the mean 90-degree turnaround impact
        # parameter is
        #
        #		b_90 = G (m_1+m_2) / vrel^2
        #		     = 2 <m> / 2<v^2>
        #		     = 2 / N			for equal masses
        #
        # Taking r_i = m_i / 2<v^2> = m_i in virial equilibrium means
        # that, approximately, "contact" means a 90-degree deflection (r_1
        # + r_2 = b_90).  A more conservative choice with r_i less than
        # this value will isolates encounters better, but also place more
        # load on the large-N dynamical module.

        stars.radius = stars.mass.number | nbody_system.length

        if number_of_binaries > 0:

            # Turn selected stars into binary components.
            # Only tested for equal-mass case.

            added_mass = 0.0 | nbody_system.mass

            # Work with energies rather than semimajor axes.

            Emin = 10 * kT
            Emax = 20 * kT
            ecc = 0.1

            id_count = number_of_stars
            nbin = 0
            for i in range(0, number_of_stars,
                           number_of_stars / number_of_binaries):

                # Star i is CM, becomes component, add other star at end.

                nbin += 1

                mass = stars[i].mass
                #new_mass = numpy.random.uniform()*mass	# uniform q?
                new_mass = mass  # uniform q?
                mbin = mass + new_mass
                fac = new_mass / mbin
                E = Emin + numpy.random.uniform() * (Emax - Emin)
                a = 0.5 * nbody_system.G * mass * new_mass / E

                kep.initialize_from_elements(mbin, a, ecc)
                dr = quantities.AdaptingVectorQuantity()
                dr.extend(kep.get_separation_vector())
                dv = quantities.AdaptingVectorQuantity()
                dv.extend(kep.get_velocity_vector())

                newstar = datamodel.Particles(1)
                newstar.mass = new_mass
                newstar.position = stars[i].position + (1 - fac) * dr
                newstar.velocity = stars[i].velocity + (1 - fac) * dv
                newstar.radius = newstar.mass.number | nbody_system.length
                #newstar.radius = 3.0*stars[i].radius    # HACK: try to force collision
                # stars[i].mass = mass
                stars[i].position = stars[i].position - fac * dr
                stars[i].velocity = stars[i].velocity - fac * dv

                id_count += 1
                newstar.id = id_count
                stars.add_particles(newstar)
                added_mass += new_mass

                if nbin >= number_of_binaries: break

            kep.stop()

            print 'created', nbin, 'binaries'
            sys.stdout.flush()

            stars.mass = stars.mass * total_mass / (total_mass + added_mass)
            number_of_stars += nbin
            Xtra = numpy.zeros(2)
        print "recentering stars"
        stars.move_to_center()
        sys.stdout.flush()

        stars.savepoint(time)

        print ''
        print "adding particles"
        # print stars
        sys.stdout.flush()
        gravity.particles.add_particles(stars)
        gravity.commit_particles()
    else:
        print "Restart detected.  Loading parameters from restart."
        new_end = options.t_end
        stars, time, multiples_code, Xtra = MRest.read_state_from_file(
            restart_file, gravity, new_smalln, kep)
        options.t_end = new_end

    total_mass = stars.mass.sum()
    ke = pa.kinetic_energy(stars)
    kT = ke / (1.5 * number_of_stars)

    # print "IDs:", stars.id.number

    print ''
    print "number_of_stars =", number_of_stars
    print "evolving to time =", end_time.number, \
          "in steps of", delta_t.number
    sys.stdout.flush()

    # Channel to copy values from the code to the set in memory.
    channel = gravity.particles.new_channel_to(stars)

    stopping_condition = gravity.stopping_conditions.collision_detection
    stopping_condition.enable()

    # -----------------------------------------------------------------
    # Create the coupled code and integrate the system to the desired
    # time, managing interactions internally.

    kep = init_kepler(stars[0], stars[1])
    if not multiples_code:
        multiples_code = multiples.Multiples(gravity, new_smalln, kep)

        multiples_code.neighbor_distance_factor = 1.0
        multiples_code.neighbor_veto = True
        #multiples_code.neighbor_distance_factor = 2.0
        #multiples_code.neighbor_veto = True
        multiples_code.retain_binary_apocenter = False

    print ''
    print 'multiples_code.initial_scale_factor =', \
        multiples_code.initial_scale_factor
    print 'multiples_code.neighbor_distance_factor =', \
        multiples_code.neighbor_distance_factor
    print 'multiples_code.neighbor_veto =', \
        multiples_code.neighbor_veto
    print 'multiples_code.final_scale_factor =', \
        multiples_code.final_scale_factor
    print 'multiples_code.initial_scatter_factor =', \
        multiples_code.initial_scatter_factor
    print 'multiples_code.final_scatter_factor =', \
        multiples_code.final_scatter_factor
    print 'multiples_code.retain_binary_apocenter =', \
        multiples_code.retain_binary_apocenter

    #    if mc_root_to_tree is not None:
    #        multiples_code.root_to_tree = mc_root_to_tree
    #        print 'multiples code re-loaded with binary trees snapshot'

    pre = "%%% "
    E0, cpu0 = print_log(pre, time, multiples_code)

    while time < end_time:

        time += delta_t
        multiples_code.evolve_model(time)

        # Copy values from the module to the set in memory.

        channel.copy()

        # Copy the index (ID) as used in the module to the id field in
        # memory.  The index is not copied by default, as different
        # codes may have different indices for the same particle and
        # we don't want to overwrite silently.

        channel.copy_attribute("index_in_code", "id")

        print_log(pre, time, multiples_code, E0, cpu0)
        stars.savepoint(time)
        MRest.write_state_to_file(time,
                                  stars,
                                  gravity,
                                  multiples_code,
                                  options.restart_file,
                                  Xtra,
                                  backup=1)
        sys.stdout.flush()

    #-----------------------------------------------------------------

    if not outfile is None:

        # Write data to a file.

        f = open(outfile, 'w')

        #--------------------------------------------------
        # Need to save top-level stellar data and parameters.
        # Need to save multiple data and parameters.

        f.write('%.15g\n' % time.number)
        for s in multiples_code.stars:
            write_star(s, f)

        #--------------------------------------------------

        f.close()
        print 'wrote file', outfile

    print ''
    gravity.stop()
Пример #28
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
def relative_position_and_velocity_from_orbital_elements(
        mass1, mass2, semimajor_axis, eccentricity, mean_anomaly, seed=None):
    """
  Function that returns relative positions and velocity vectors or orbiters with masses 
  mass2 of the central body with mass mass1 in Cartesian coordinates;
  for vectors of orbital elements -- semi-major axes, eccentricities, mean anomalies.
  3D orientation of orbits (inclination, longitude of ascending node and argument of periapsis) are random.
  (cos(incl) is uniform -1--1, longitude of ascending node and argument of periapsis are uniform 0--2pi)
  Assuming mass1 is static in the center [0,0,0] m, [0,0,0] km/s (that is mass2<<mass1)
  """
    position_vectors = []
    velocity_vectors = []
    converter = nbody_system.nbody_to_si(1 | units.MSun, 1 | units.AU)
    kepler = Kepler(converter)
    kepler.initialize_code()
    r_vec = (0., 0., 0.) | units.AU
    v_vec = (0., 0., 0.) | units.kms
    # to change seed for each particle
    if seed is not None:
        i = 0
    for m2_i, a_i, ecc_i, ma_i in zip(mass2, semimajor_axis, eccentricity,
                                      mean_anomaly):
        #print m2_i, a_i, ecc_i, ma_i
        if seed is not None:
            kepler.set_random(seed + i)
            i = i + 1
        kepler.initialize_from_elements(mass=(mass1 + m2_i),
                                        semi=a_i,
                                        ecc=ecc_i,
                                        mean_anomaly=ma_i,
                                        random_orientation=-1)
        ri = kepler.get_separation_vector()
        vi = kepler.get_velocity_vector()
        # this is to get ~half of the orbits retrograde (that is with inclination
        # of 90--180 degrees) --> velocity = -velocity
        vel_vec_dir = numpy.random.random()
        if (vel_vec_dir <= 0.5):
            vel_orientation = 1.
        else:
            vel_orientation = -1.
        position_vectors.append([ri[0], ri[1], ri[2]])
        velocity_vectors.append([
            vel_orientation * vi[0], vel_orientation * vi[1],
            vel_orientation * vi[2]
        ])
    kepler.stop()
    return position_vectors, velocity_vectors
Пример #30
0
def CutOrAdvance(enc_bodies, primary_sysID, converter=None, **kwargs):
    bodies = enc_bodies.copy()
    KeplerWorkerList = kwargs.get("kepler_workers", None)
    # Initialize Kepler Workers if they Don't Exist
    if KeplerWorkerList == None:
        if converter == None:
            converter = nbody_system.nbody_to_si(
                bodies.mass.sum(),
                2 * np.max(bodies.radius.number) | bodies.radius.unit)
        KeplerWorkerList = []
        for i in range(3):
            KeplerWorkerList.append(
                Kepler(unit_converter=converter, redirection='none'))
            KeplerWorkerList[-1].initialize_code()
    systems = stellar_systems.get_heirarchical_systems_from_set(bodies, \
                                    kepler_workers=KeplerWorkerList[:2], \
                                    RelativePosition=False)
    # Deal with Possible Key Issues with Encounters with 3+ Star Particles Being Run More than Other Systems ...
    if int(primary_sysID) not in list(systems.keys()):
        print(
            "...: Error: Previously run binary system has been found! Not running this system ..."
        )
        print(primary_sysID)
        print(list(systems.keys()))
        print("---------------------------------")
        return None
    # As this function is pulling from Multiples, there should never be more or less than 2 "Root" Particles ...
    if len(systems) != 2:
        print(
            "...: Error: Encounter has more roots than expected! Total Root Particles:",
            len(systems))
        print(bodies)
        print("---------------------------------")
        return None
    # Assign the Primary System to #1 and Perturbing System to #2
    sys_1 = systems[int(primary_sysID)]
    secondary_sysID = [
        key for key in list(systems.keys()) if key != int(primary_sysID)
    ][0]
    sys_2 = systems[secondary_sysID]
    print('All System Keys:', list(systems.keys()))
    print('Primary System Key:', primary_sysID)
    print('System 1 IDs:', sys_1.id)
    print('System 2 IDs:', sys_2.id)
    # Calculate Useful Quantities
    mass_ratio = sys_2.mass.sum() / sys_1.mass.sum()
    total_mass = sys_1.mass.sum() + sys_2.mass.sum()
    rel_pos = sys_1.center_of_mass() - sys_2.center_of_mass()
    rel_vel = sys_1.center_of_mass_velocity() - sys_2.center_of_mass_velocity()
    # Initialize Kepler Worker
    kep = KeplerWorkerList[-1]
    kep.initialize_from_dyn(total_mass, rel_pos[0], rel_pos[1], rel_pos[2],
                            rel_vel[0], rel_vel[1], rel_vel[2])
    # Check to See if the Periastron is within the Ignore Distance for 10^3 Perturbation
    p = kep.get_periastron()
    ignore_distance = mass_ratio**(1. / 3.) * 600 | units.AU
    if p > ignore_distance:
        print("Encounter Ignored due to Periastron of", p.in_(units.AU),
              "and an IgnoreDistance of", ignore_distance)
        if KeplerWorkerList == None:
            for K in KeplerWorkerList:
                K.stop()
        print("---------------------------------")
        return None
    # Move the Particles to be Relative to their Respective Center of Mass
    cm_sys_1, cm_sys_2 = sys_1.center_of_mass(), sys_2.center_of_mass()
    cmv_sys_1, cmv_sys_2 = sys_1.center_of_mass_velocity(
    ), sys_2.center_of_mass_velocity()
    for particle in sys_1:
        particle.position -= cm_sys_1
        particle.velocity -= cmv_sys_1
    for particle in sys_2:
        particle.position -= cm_sys_2
        particle.velocity -= cmv_sys_2
    # Check to See if the Planets are Closer than the Ignore Distance
    # Note: This shouldn't happen in the main code, but this prevents overshooting the periastron in debug mode.
    if kep.get_separation() > ignore_distance:
        kep.advance_to_radius(ignore_distance)
    # Advance the Center of Masses to the Desired Distance in Reduced Mass Coordinates
    x, y, z = kep.get_separation_vector()
    rel_pos_f = rel_pos.copy()
    rel_pos_f[0], rel_pos_f[1], rel_pos_f[2] = x, y, z
    vx, vy, vz = kep.get_velocity_vector()
    rel_vel_f = rel_vel.copy()
    rel_vel_f[0], rel_vel_f[1], rel_vel_f[2] = vx, vy, vz
    # Transform to Absolute Coordinates from Kepler Reduced Mass Coordinates
    cm_pos_1, cm_pos_2 = sys_2.mass.sum(
    ) * rel_pos_f / total_mass, -sys_1.mass.sum() * rel_pos_f / total_mass
    cm_vel_1, cm_vel_2 = sys_2.mass.sum(
    ) * rel_vel_f / total_mass, -sys_1.mass.sum() * rel_vel_f / total_mass
    # Move the Particles to the New Postions of their Respective Center of Mass
    for particle in sys_1:
        particle.position += cm_pos_1
        particle.velocity += cm_vel_1
    for particle in sys_2:
        particle.position += cm_pos_2
        particle.velocity += cm_vel_2
    # If not provided, stop Kepler and return the Systems as a Particle Set
    if KeplerWorkerList == None:
        for K in KeplerWorkerList:
            K.stop()
    # Collect the Collective Particle Set to be Returned Back
    final_set = Particles()
    final_set.add_particles(sys_1)
    final_set.add_particles(sys_2)
    print("---------------------------------")
    return final_set
Пример #31
0
class StellarEncounterInHydrodynamics(object):
    """
    Resolves collisions between stars by converting them to SPH models, let them 
    collide in an SPH code, and converting the resulting SPH particle distribution 
    back to a 1D stellar evolution model.
    
    Requires a stellar evolution code to supply the internal structure of the 
    stars for the convert_stellar_model_to_SPH routine.
    Requires a gravity code to set up the initial configuration. The stars in the 
    gravity code have typically already collided, so they are first "evolved" back 
    in time up to a certain separation, assuming Keplerian motion.
    
    :argument number_of_particles: Total number of gas particles in the SPH simulation
    :argument hydrodynamics: SPH code class for the simulation
    :argument initial_separation: a factor relative to the sum of the radii (1 means in contact, default: 5)
    """
    
    stellar_evolution_code_required = True
    gravity_code_required = True
    
    def __init__(
            self, 
            number_of_particles,
            hydrodynamics, 
            initial_separation = 5, 
            relax_sph_models = True,
            verbose = False, 
            debug = False, 
            hydrodynamics_arguments = dict(),
            hydrodynamics_parameters = dict(),
            star_to_sph_arguments = dict(),
            sph_to_star_arguments = dict(),
        ):
        
        self.number_of_particles = number_of_particles
        self.hydrodynamics = hydrodynamics
        self.initial_separation = initial_separation
        if not relax_sph_models:
            self.relax = self.no_relax
        self.verbose = verbose
        self.debug = debug
        self.hydrodynamics_arguments = hydrodynamics_arguments
        self.hydrodynamics_parameters = hydrodynamics_parameters
        self.star_to_sph_arguments = star_to_sph_arguments
        self.sph_to_star_arguments = sph_to_star_arguments
        
        self.dynamical_timescales_per_step = 1.0 # encounter_is_over check is performed at this interval
        self.extra_steps_when_encounter_is_over = 3
        
        self.continue_with_kepler = False
    
    def handle_collision(self, primary, secondary, stellar_evolution_code=None, gravity_code=None):
        particles = self.local_copy_of_particles(primary, secondary)
        self.collect_required_attributes(particles, gravity_code, stellar_evolution_code)
        self.backtrack_particles(particles)
        gas_particles = self.convert_stars(particles, stellar_evolution_code)
        self.simulate_collision(gas_particles)
        self.models = [convert_SPH_to_stellar_model(group, **self.sph_to_star_arguments) for group in self.groups_after_encounter]
        return self.new_particles_with_internal_structure_from_models()
    
    def new_particles_with_internal_structure_from_models(self):
        def get_internal_structure(set, particle=None):
            return self.models[(set.key == particle.key).nonzero()[0]]
        
        result = Particles(len(self.models))
        result.add_function_attribute("get_internal_structure", None, get_internal_structure)
        result.mass = [model.dmass.sum().as_quantity_in(self.mass_unit) for model in self.models]
        result.radius = [model.radius[-1].as_quantity_in(self.radius_unit) for model in self.models]
        result.position = (self.original_center_of_mass + self.stars_after_encounter.position).as_quantity_in(self.position_unit)
        result.velocity = (self.original_center_of_mass_velocity + self.stars_after_encounter.velocity).as_quantity_in(self.velocity_unit)
        return result
    
    def local_copy_of_particles(self, primary, secondary):
        particles = Particles(0)
        particles.add_particle(primary)
        particles.add_particle(secondary)
        return particles
    
    def collect_required_attributes(self, particles, gravity_code, stellar_evolution_code):
        # Collect the required attributes and copy to the particles in memory
        required_attributes = set(["mass", "x","y","z", "vx","vy","vz", "radius"])
        required_attributes -= set(particles.get_attribute_names_defined_in_store())
        for code in [stellar_evolution_code, gravity_code]:
            attrs_in_code = required_attributes & set(code.particles.get_attribute_names_defined_in_store())
            if len(attrs_in_code) > 0:
                code.particles.copy_values_of_attributes_to(list(attrs_in_code), particles)
                required_attributes -= attrs_in_code
        
        self.mass_unit = particles.mass.unit
        self.radius_unit = particles.radius.unit
        self.position_unit = particles.position.unit
        self.velocity_unit = particles.velocity.unit
        self.dynamical_timescale = numpy.pi * (particles.radius.sum()**3 / (8 * constants.G * particles.total_mass())).sqrt()
    
    def start_kepler(self, mass_unit, length_unit):
        unit_converter = nbody_system.nbody_to_si(mass_unit, length_unit)
        self.kepler = Kepler(unit_converter, redirection = "none" if self.debug else "null")
        self.kepler.initialize_code()
    
    def initialize_binary_in_kepler(self, star_a, star_b):
        self.kepler.initialize_from_dyn(
            star_a.mass + star_b.mass, 
            star_a.x - star_b.x, star_a.y - star_b.y, star_a.z - star_b.z,
            star_a.vx-star_b.vx, star_a.vy-star_b.vy, star_a.vz-star_b.vz
        )
        return self.kepler
    
    def backtrack_particles(self, particles):
        self.original_center_of_mass = particles.center_of_mass()
        self.original_center_of_mass_velocity = particles.center_of_mass_velocity()
        
        initial_separation = self.initial_separation * particles.radius.sum()
        if self.verbose:
            print "Particles at collision:"
            print particles
            print "Backtrack particles to initial separation", initial_separation.as_string_in(units.RSun)
        
        self.start_kepler(particles.total_mass(), initial_separation)
        kepler = self.initialize_binary_in_kepler(particles[0], particles[1])
        kepler.return_to_radius(initial_separation)
        self.begin_time = kepler.get_time()
        
        particles[1].position = kepler.get_separation_vector()
        particles[1].velocity = kepler.get_velocity_vector()
        kepler.advance_to_periastron()
        self.begin_time -= kepler.get_time()
        particles[0].position = [0, 0, 0] | units.m
        particles[0].velocity = [0, 0, 0] | units.m / units.s
        particles.move_to_center()
        if self.verbose:
            print "Backtracking particles done. Initial conditions:"
            print particles
    
    def convert_stars(self, particles, stellar_evolution_code):
        n_particles = self.divide_number_of_particles(particles)
        se_colliders = particles.get_intersecting_subset_in(stellar_evolution_code.particles)
        if self.verbose:
            print "Converting stars of {0} to SPH models of {1} particles, respectively.".format(particles.mass, n_particles)
        sph_models = (
            self.relax(convert_stellar_model_to_SPH(se_colliders[0], n_particles[0], **self.star_to_sph_arguments)),
            self.relax(convert_stellar_model_to_SPH(se_colliders[1], n_particles[1], **self.star_to_sph_arguments))
        )
        gas_particles = Particles()
        for particle, sph_model in zip(particles, sph_models):
            sph_model.position += particle.position
            sph_model.velocity += particle.velocity
            gas_particles.add_particles(sph_model)
        if self.verbose:
            print "Converting stars to SPH particles done"
        if self.debug:
            print gas_particles
        return gas_particles
    
    def divide_number_of_particles(self, particles):
        n1 = int(0.5 + self.number_of_particles * particles[0].mass / particles.total_mass())
        return (n1, self.number_of_particles - n1)
    
    def relax(self, sph_model):
        if self.debug:
            monitor = dict(time=[]|units.day, kinetic=[]|units.J, potential=[]|units.J, thermal=[]|units.J)
        gas_particles = sph_model.gas_particles
        hydro = self.new_hydrodynamics(gas_particles)
        hydro.parameters.artificial_viscosity_alpha = 0.0 # Viscous damping doesn't seem to be very important, but turned off just in case...
        channel_from_hydro = hydro.gas_particles.new_channel_to(gas_particles)
        channel_to_hydro = gas_particles.new_channel_to(hydro.gas_particles)
        
        dynamical_timescale = numpy.pi * (gas_particles.total_radius()**3 / (8 * constants.G * gas_particles.total_mass())).sqrt()
        t_end_in_t_dyn = 2.5 # Relax for this many dynamical timescales
        n_steps = 100
        velocity_damp_factor = 1.0 - (2.0*numpy.pi*t_end_in_t_dyn)/n_steps # Critical damping
        if self.verbose:
            print "Relaxing SPH model with {0} for {1} ({2} dynamical timescales).".format(
                self.hydrodynamics.__name__, 
                (t_end_in_t_dyn*dynamical_timescale).as_string_in(units.day),
                t_end_in_t_dyn)
        for i_step, time in enumerate(t_end_in_t_dyn*dynamical_timescale * numpy.linspace(1.0/n_steps, 1.0, n_steps)):
            hydro.evolve_model(time)
            channel_from_hydro.copy_attributes(["mass","x","y","z","vx","vy","vz","u"])
            gas_particles.position -= gas_particles.center_of_mass()
            gas_particles.velocity = velocity_damp_factor * (gas_particles.velocity - gas_particles.center_of_mass_velocity())
            channel_to_hydro.copy_attributes(["x","y","z","vx","vy","vz"])
            if self.debug:
                K, U, Q = hydro.kinetic_energy, hydro.potential_energy, hydro.thermal_energy
                print "t, K, U, Q:", time, K, U, Q
                monitor["time"].append(time)
                monitor["kinetic"].append(K)
                monitor["potential"].append(U)
                monitor["thermal"].append(Q)
                
        hydro.stop()
        if self.debug:
            energy_evolution_plot(monitor["time"], monitor["kinetic"], monitor["potential"], monitor["thermal"])
        return gas_particles
    
    def no_relax(self, sph_model):
        return sph_model.gas_particles
    
    def new_hop(self, particles):
        converter = nbody_system.nbody_to_si(particles.total_mass(), 1.0 | units.RSun)
        if self.debug:
            print "Output of Hop is redirected to hop_out.log"
            options = dict(redirection="file", redirect_file="hop_out.log")
        else:
            options = dict()
        hop = Hop(unit_converter=converter, **options)
        hop.parameters.number_of_neighbors_for_hop = 100
        hop.parameters.saddle_density_threshold_factor = 0.8
        hop.parameters.relative_saddle_density_threshold = True
        return hop
    
    def new_hydrodynamics(self, gas_particles):
        unit_converter = nbody_system.nbody_to_si(gas_particles.total_mass(), self.dynamical_timescale)
        hydro = self.hydrodynamics(unit_converter, **self.hydrodynamics_arguments)
        hydro.initialize_code()
        for par, value in self.hydrodynamics_parameters.iteritems():
            setattr(hydro.parameters, par, value)
        hydro.commit_parameters()
        hydro.gas_particles.add_particles(gas_particles)
        hydro.commit_particles()
        return hydro
    
    def simulate_collision(self, gas_particles):
        self.hop = self.new_hop(gas_particles)
        hydro = self.new_hydrodynamics(gas_particles)
        channel = hydro.gas_particles.new_channel_to(gas_particles)
        
        if self.verbose:
            print "Simulating collision with {0} from {1} to {2}.".format(
                self.hydrodynamics.__name__, 
                self.begin_time.as_string_in(units.day), 
                (self.dynamical_timescales_per_step * self.dynamical_timescale).as_string_in(units.day))
        
        hydro.evolve_model(self.dynamical_timescales_per_step * self.dynamical_timescale - self.begin_time)
        channel.copy_attributes(["x","y","z","vx","vy","vz","pressure","density","u"])
        extra_steps_counter = 0
        while True:
            if self.encounter_is_over(gas_particles):
                extra_steps_counter += 1
                if extra_steps_counter > self.extra_steps_when_encounter_is_over:
                    print "Encounter is over and finished extra steps."
                    break
                else:
                    print "Encounter is over. Now performing step {0} out of {1} extra steps".format(
                        extra_steps_counter, self.extra_steps_when_encounter_is_over)
            else:
                extra_steps_counter = 0
            print "Continuing to {0}.".format((hydro.model_time + self.next_dt + self.begin_time).as_string_in(units.day))
            if self.continue_with_kepler:
                self.evolve_with_kepler(hydro)
            hydro.evolve_model(hydro.model_time + self.next_dt)
            channel.copy_attributes(["x","y","z","vx","vy","vz","pressure","density","u"])
        
        hydro.stop()
        self.hop.stop()
        self.kepler.stop()
    
    def encounter_is_over(self, gas_particles):
        self.next_dt = self.dynamical_timescales_per_step * self.dynamical_timescale
        groups = self.group_bound_particles(gas_particles)
        stars = self.convert_groups_to_stars(groups)
        self.groups_after_encounter = groups
        self.stars_after_encounter = stars
        if len(stars) > 1:
            # Should do full check for stable binaries, triple, multiples, two escapers,
            # escaping star + binary, etc.
            # For now we only check whether the two most massive groups will (re)collide
            a, b = stars.sorted_by_attribute("mass")[-2:]
            if self.debug: print "System consists of {0} groups. The two most massive are: {1} and {2}.".format(len(stars), a.mass.as_string_in(units.MSun), b.mass.as_string_in(units.MSun))
            if self.binary_will_collide(a, b):
                return False
        
        if self.verbose:
            print "Encounter is over, {0} stars after encounter.".format(len(groups))
        return True
    
    def group_bound_particles(self, gas_particles):
        groups, lost = self.analyze_particle_distribution(gas_particles)
        while len(lost) > 0:
            if self.debug:
                group_plot(groups, lost)
            previous_number_of_lost_particles = len(lost)
            groups, lost = self.select_bound_particles(groups, lost)
            if len(lost) == previous_number_of_lost_particles:
                break
        return groups
    
    def convert_groups_to_stars(self, groups):
        stars = Particles(len(groups))
        for star, group in zip(stars, groups):
            star.mass = group.total_mass()
            star.position = group.center_of_mass()
            star.velocity = group.center_of_mass_velocity()
            star.radius = group.LagrangianRadii(mf=[0.9], cm=star.position)[0][0]
        return stars
    
    def analyze_particle_distribution(self, gas_particles):
        if self.verbose:
            print "Analyzing particle distribution using Hop"
        if "density" in gas_particles.get_attribute_names_defined_in_store():
            if self.debug: print "Using the original particles' density"
            self.hop.parameters.outer_density_threshold = 0.5 * gas_particles.density.mean()
            self.hop.particles.add_particles(gas_particles)
            gas_particles.copy_values_of_attribute_to("density", self.hop.particles)
        else:
            if self.debug: print "Using Hop to calculate the density"
            self.hop.particles.add_particles(gas_particles)
            self.hop.calculate_densities()
            self.hop.parameters.outer_density_threshold = 0.5 * self.hop.particles.density.mean()
        self.hop.do_hop()
        result = []
        for group in self.hop.groups():
            result.append(group.get_intersecting_subset_in(gas_particles))
        lost = self.hop.no_group().get_intersecting_subset_in(gas_particles)
        self.hop.particles.remove_particles(self.hop.particles)
        return result, lost
    
    def select_bound_particles(self, groups, lost):
        specific_total_energy_relative_to_group = [] | (units.m / units.s)**2
        for group in groups:
            group_mass = group.total_mass()
            group_com = group.center_of_mass()
            group_com_velocity = group.center_of_mass_velocity()
            specific_total_energy_relative_to_group.append(
                (lost.velocity - group_com_velocity).lengths_squared() + lost.u - 
                constants.G * group_mass / (lost.position - group_com).lengths())
        index_minimum = specific_total_energy_relative_to_group.argmin(axis=0)
        bound=lost[:0]
        for i, group in enumerate(groups):
            bound_to_group = lost[numpy.logical_and(
                index_minimum == i, 
                specific_total_energy_relative_to_group[i] < 0 | (units.m / units.s)**2
            )]
            bound += bound_to_group
            groups[i] = group + bound_to_group
        return groups, lost - bound
    
    def binary_will_collide(self, a, b):
        self.continue_with_kepler = False
        if self.verbose:
            print "Using Kepler to check whether the two stars will (re)collide."
        kepler = self.initialize_binary_in_kepler(a, b)
        
        true_anomaly = kepler.get_angles()[1]
        eccentricity = kepler.get_elements()[1]
        if true_anomaly > 0.0 and eccentricity >= 1.0:
            if self.verbose:
                print "Stars are on hyperbolic/parabolic orbits and moving away from each other, interaction is over."
            return False
        
        periastron = kepler.get_periastron()
        will_collide = periastron < a.radius + b.radius
        if self.verbose:
            print "Stars {0} collide. Distance at periastron: {1}, sum of radii: {2}".format(
                "will" if will_collide else "won't",
                periastron.as_string_in(units.RSun), (a.radius + b.radius).as_string_in(units.RSun))
        
        if will_collide:
            # 1) check whether the stars are still relaxing: less than ~3 t_dyn passed since last moment of contact --> relax
            # 2) check whether the stars are already within 'initial_separation', else skip (dtmax?)
            
            kepler.advance_to_periastron()
            self.next_dt = kepler.get_time() + self.dynamical_timescales_per_step * self.dynamical_timescale
            if self.debug:
                print "Time to collision: {0}, next_dt: {1}".format(
                    kepler.get_time().as_string_in(units.day), self.next_dt.as_string_in(units.day))
            if kepler.get_time() > 3 * self.dynamical_timescale and kepler.get_apastron() > 2.0 * self.initial_separation * (a.radius + b.radius):
                # evolve for 3 * self.dynamical_timescale and skip the rest until ~initial_separation
                kepler.return_to_apastron()
                kepler.return_to_radius(a.radius + b.radius)
                if -kepler.get_time() > 2.9 * self.dynamical_timescale: # If ~3 t_dyn have passed since the end of the collision
                    if self.verbose: print "~3 t_dyn have passed since the end of the collision -> skip to next collision"
                    self.continue_with_kepler = True
                    kepler.advance_to_apastron()
                    kepler.advance_to_radius(2.0 * self.initial_separation * (a.radius + b.radius))
                    self.skip_to_relative_position_velocity = (kepler.get_separation_vector(), kepler.get_velocity_vector())
                    self.begin_time = kepler.get_time()
                    kepler.advance_to_periastron()
                    self.next_dt = self.dynamical_timescales_per_step * self.dynamical_timescale + kepler.get_time() - self.begin_time
                else:
                    self.next_dt = 3 * self.dynamical_timescale + kepler.get_time()
        return will_collide
    
    def evolve_with_kepler(self, hydro):
        if self.verbose: print "evolve_with_kepler"
        indices_two_most_massive = self.stars_after_encounter.mass.argsort()[-2:]
        groups = [self.groups_after_encounter[i] for i in indices_two_most_massive]
        old_particles = self.stars_after_encounter[indices_two_most_massive]
        new_particles = Particles(2)
        new_particles.mass = old_particles.mass
        new_particles[0].position, new_particles[0].velocity = self.skip_to_relative_position_velocity
        new_particles.move_to_center()
        for group, old_particle, new_particle in zip(groups, old_particles, new_particles):
            in_hydro = group.get_intersecting_subset_in(hydro.gas_particles)
            if self.verbose: print in_hydro.center_of_mass().as_quantity_in(units.RSun), old_particle.position.as_quantity_in(units.RSun), new_particle.position.as_quantity_in(units.RSun)
            in_hydro.position += new_particle.position - old_particle.position
            in_hydro.velocity += new_particle.velocity - old_particle.velocity
Пример #32
0
def relative_position_and_velocity_from_orbital_elements(mass1,
                                                         mass2,
                                                         semimajor_axis,
                                                         eccentricity,
                                                         mean_anomaly,
                                                         seed=None):
  """
  Function that returns relative positions and velocity vectors or orbiters with masses 
  mass2 of the central body with mass mass1 in Cartesian coordinates;
  for vectors of orbital elements -- semi-major axes, eccentricities, mean anomalies.
  3D orientation of orbits (inclination, longitude of ascending node and argument of periapsis) are random.
  (cos(incl) is uniform -1--1, longitude of ascending node and argument of periapsis are uniform 0--2pi)
  Assuming mass1 is static in the center [0,0,0] m, [0,0,0] km/s (that is mass2<<mass1)
  """
  position_vectors = []
  velocity_vectors = []
  converter = nbody_system.nbody_to_si(1|units.MSun,1|units.AU)
  kepler = Kepler(converter)
  kepler.initialize_code()
  r_vec = (0.,0.,0.) | units.AU
  v_vec = (0.,0.,0.) | units.kms
  # to change seed for each particle
  if seed is not None:
    i=0
  for m2_i, a_i, ecc_i, ma_i in zip(mass2, semimajor_axis, eccentricity, mean_anomaly):
    #print m2_i, a_i, ecc_i, ma_i
    if seed is not None:
      kepler.set_random(seed+i)
      i=i+1
    kepler.initialize_from_elements(mass=(mass1+m2_i),semi=a_i,ecc=ecc_i,mean_anomaly=ma_i,random_orientation=-1)
    ri = kepler.get_separation_vector()
    vi = kepler.get_velocity_vector()
    # this is to get ~half of the orbits retrograde (that is with inclination
    # of 90--180 degrees) --> velocity = -velocity
    vel_vec_dir = numpy.random.random()
    if (vel_vec_dir<=0.5):
      vel_orientation = 1.
    else:
      vel_orientation = -1.
    position_vectors.append([ri[0], ri[1], ri[2]])
    velocity_vectors.append([vel_orientation*vi[0], vel_orientation*vi[1], vel_orientation*vi[2]])
  kepler.stop()
  return position_vectors, velocity_vectors
Пример #33
0
gravity.parameters.gpu_id = gpu_ID

# Setting Up the Stopping Conditions in PH4
stopping_condition = gravity.stopping_conditions.collision_detection
stopping_condition.enable()
sys.stdout.flush()

# Adding and Committing Particles to PH4
gravity.particles.add_particles(MasterSet)
gravity.commit_particles()

# Starting the AMUSE Channel for PH4
grav_channel = gravity.particles.new_channel_to(MasterSet)

# Initializing Kepler and SmallN
kep = Kepler(None, redirection="none")
kep.initialize_code()
util.init_smalln()

# Initializing MULTIPLES
multiples_code = multiples.Multiples(gravity, util.new_smalln, kep)
multiples_code.neighbor_distance_factor = 1.0
multiples_code.neighbor_veto = True

multiples_code.evolve_model(time)
gravity.synchronize_model()
# Copy values from the module to the set in memory.
grav_channel.copy()

# Copy the index (ID) as used in the module to the id field in
# memory.  The index is not copied by default, as different
Пример #34
0
def run_ph4(infile=None,
            number_of_stars=40,
            end_time=10 | nbody_system.time,
            delta_t=1 | nbody_system.time,
            n_workers=1,
            use_gpu=1,
            gpu_worker=1,
            accuracy_parameter=0.1,
            softening_length=-1 | nbody_system.length,
            manage_encounters=1,
            random_seed=1234):

    if random_seed <= 0:
        numpy.random.seed()
        random_seed = numpy.random.randint(1, pow(2, 31) - 1)
    numpy.random.seed(random_seed)
    print("random seed =", random_seed)

    if infile != None: print("input file =", infile)
    print("end_time =", end_time.number)
    print("delta_t =", delta_t.number)
    print("n_workers =", n_workers)
    print("use_gpu =", use_gpu)
    print("manage_encounters =", manage_encounters)
    print("\ninitializing the gravity module")
    sys.stdout.flush()

    # Note that there are actually three GPU options to test:
    #
    #	1. use the GPU code and allow GPU use (default)
    #	2. use the GPU code but disable GPU use (-g)
    #	3. use the non-GPU code (-G)

    if gpu_worker == 1:
        try:
            gravity = grav(number_of_workers=n_workers,
                           redirection="none",
                           mode="gpu")
        except Exception as ex:
            gravity = grav(number_of_workers=n_workers, redirection="none")
    else:
        gravity = grav(number_of_workers=n_workers, redirection="none")

    gravity.initialize_code()
    gravity.parameters.set_defaults()

    #-----------------------------------------------------------------

    if infile == None:

        print("making a Plummer model")
        stars = new_plummer_model(number_of_stars)

        id = numpy.arange(number_of_stars)
        stars.id = id + 1

        print("setting particle masses and radii")
        #stars.mass = (1.0 / number_of_stars) | nbody_system.mass
        scaled_mass = new_salpeter_mass_distribution_nbody(number_of_stars)
        stars.mass = scaled_mass
        stars.radius = 0.02 | nbody_system.length

        print("centering stars")
        stars.move_to_center()
        print("scaling stars to virial equilibrium")
        stars.scale_to_standard(
            smoothing_length_squared=gravity.parameters.epsilon_squared)

        time = 0.0 | nbody_system.time
        sys.stdout.flush()

    else:

        # Read the input data.  Units are dynamical.

        print("reading file", infile)

        id = []
        mass = []
        pos = []
        vel = []

        f = open(infile, 'r')
        count = 0
        for line in f:
            if len(line) > 0:
                count += 1
                cols = line.split()
                if count == 1: snap = int(cols[0])
                elif count == 2: number_of_stars = int(cols[0])
                elif count == 3: time = float(cols[0]) | nbody_system.time
                else:
                    if len(cols) >= 8:
                        id.append(int(cols[0]))
                        mass.append(float(cols[1]))
                        pos.append(
                            (float(cols[2]), float(cols[3]), float(cols[4])))
                        vel.append(
                            (float(cols[5]), float(cols[6]), float(cols[7])))
        f.close()

        stars = datamodel.Particles(number_of_stars)
        stars.id = id
        stars.mass = mass | nbody_system.mass
        stars.position = pos | nbody_system.length
        stars.velocity = vel | nbody_system.speed
        stars.radius = 0. | nbody_system.length

    # print "IDs:", stars.id.number
    sys.stdout.flush()

    #-----------------------------------------------------------------

    if softening_length == -1 | nbody_system.length:
        eps2 = 0.25*(float(number_of_stars))**(-0.666667) \
   | nbody_system.length**2
    else:
        eps2 = softening_length * softening_length

    gravity.parameters.timestep_parameter = accuracy_parameter
    gravity.parameters.epsilon_squared = eps2
    gravity.parameters.use_gpu = use_gpu
    # gravity.parameters.manage_encounters = manage_encounters

    print("adding particles")
    # print stars
    sys.stdout.flush()
    gravity.particles.add_particles(stars)
    gravity.commit_particles()

    print('')
    print("number_of_stars =", number_of_stars)
    print("evolving to time =", end_time.number, \
          "in steps of", delta_t.number)
    sys.stdout.flush()

    E0 = print_log(time, gravity)

    # Channel to copy values from the code to the set in memory.
    channel = gravity.particles.new_channel_to(stars)

    stopping_condition = gravity.stopping_conditions.collision_detection
    stopping_condition.enable()

    kep = Kepler(redirection="none")
    kep.initialize_code()
    multiples_code = multiples.Multiples(gravity, new_smalln, kep)

    while time < end_time:
        time += delta_t
        multiples_code.evolve_model(time)

        # Copy values from the module to the set in memory.

        channel.copy()

        # Copy the index (ID) as used in the module to the id field in
        # memory.  The index is not copied by default, as different
        # codes may have different indices for the same particle and
        # we don't want to overwrite silently.

        channel.copy_attribute("index_in_code", "id")

        print_log(time, gravity, E0)
        sys.stdout.flush()

    print('')
    gravity.stop()
Пример #35
0
def integrate_system(N, t_end, seed=None):

    # Initialize an N-body module and load a stellar system.

    mass = N|units.MSun
    length = 1|units.parsec
    converter = nbody_system.nbody_to_si(mass, length)
    gravity = ph4(convert_nbody=converter)
    gravity.initialize_code()
    gravity.parameters.set_defaults()
    gravity.parameters.epsilon_squared = (0.0|units.parsec)**2

    if seed is not None: numpy.random.seed(seed)
    stars = new_plummer_model(N, convert_nbody=converter)
    stars.mass = mass/N
    stars.scale_to_standard(convert_nbody=converter,
                            smoothing_length_squared
                             = gravity.parameters.epsilon_squared)

    # Star IDs are important, as they are used in multiples bookkeeping.
    id = numpy.arange(N)
    stars.id = id+1

    # Set dynamical radii.

    #stars.radius = 0.5/N | units.parsec
    stars.radius = 2000 | units.AU

    gravity.particles.add_particles(stars)

    # Add Planets
    do_planets = True
    if do_planets:
        systems_SI = create.planetary_systems(stars, N-1, 'test_planets', Jupiter=True)
        gravity.particles.add_particles(systems_SI)

    # Enable collision detection.

    stopping_condition = gravity.stopping_conditions.collision_detection
    stopping_condition.enable()

    SmallScaleConverter = nbody_system.nbody_to_si(2*mass/N, 4000 | units.AU)
    # Define the small-N code.

    init_smalln(SmallScaleConverter)

    # Define a Kepler module.

    kep = Kepler(unit_converter=SmallScaleConverter)
    kep.initialize_code()

    # Create the multiples module.
    global multiples_code
    multiples_code = multiples2.Multiples(gravity, new_smalln, kep,
                                         constants.G)
    multiples_code.neighbor_perturbation_limit = 0.05
    multiples_code.neighbor_veto = True

    multiples_code.global_debug = 1	    # 0: no output from multiples
                                        # 1: minimal output
                                        # 2: debugging output
                                        # 3: even more output
                                        
    # Setting Up the Encounter Handler
    encounters = EncounterHandler()
    multiples_code.callback = encounters.handle_encounter_v3

    # Print selected multiples settings.

    print ''
    print 'multiples_code.neighbor_veto =', \
        multiples_code.neighbor_veto
    print 'multiples_code.neighbor_perturbation_limit =', \
        multiples_code.neighbor_perturbation_limit
    print 'multiples_code.retain_binary_apocenter =', \
        multiples_code.retain_binary_apocenter
    print 'multiples_code.wide_perturbation_limit =', \
        multiples_code.wide_perturbation_limit

    # Advance the system.
    time = numpy.sqrt(length**3/(constants.G*mass))
    print '\ntime unit =', time.in_(units.Myr)
    
    E0 = print_diagnostics(multiples_code)
    dt = 0.1 | units.Myr
    t_current = 0.0 | units.Myr
    #gravity.particles[-1].mass += 1 | units.MSun
    while t_current <= t_end:
        t_current += dt
        multiples_code.evolve_model(t_current)
        print gravity.particles.index_in_code #, gravity.particles[0].x
        #print multiples_code.particles[-1].key, multiples_code.particles[-1].x
        print multiples_code._inmemory_particles.id, #multiples_code._inmemory_particles[-1].x
        #print stars[0].id
        # Testing the Multiples & Gravity Particle Set Differences
        #test_psystem_id = systems_SI[0].host_star
        #test_psystem_hs_grav = [star.x for star in gravity.particles if star.index_in_code == test_psystem_id]
        #test_psystem_hs_mult = [star.x for star in multiples_code.particles if star.idex_in_code == test_psystem_id]
        #print "-----------------------------"
        #print "X Position in PH4", test_pystem_hs_grav.in_(units.parsec)
        #print "X Position in Multiples", test_psystem_hs_mult.in_(units.parsec)
        #print "Difference in Particle Sets", test_pystem_hs_grav.in_(units.parsec) - test_psystem_hs_mult.in_(units.parsec)
        #print "-----------------------------"
    print_diagnostics(multiples_code, E0)

    gravity.stop()
    kep.stop()
    stop_smalln()
Пример #36
0
def run_ph4(infile = None, outfile = None,
            number_of_stars = 100, number_of_binaries = 0,
            end_time = 10 | nbody_system.time,
            delta_t = 1 | nbody_system.time,
            n_workers = 1, use_gpu = 1, gpu_worker = 1,
            salpeter = 0,
            accuracy_parameter = 0.1,
            softening_length = 0.0 | nbody_system.length,
            manage_encounters = 1, random_seed = 1234):

    if random_seed <= 0:
        numpy.random.seed()
        random_seed = numpy.random.randint(1, pow(2,31)-1)
    numpy.random.seed(random_seed)
    print "random seed =", random_seed

    if infile != None: print "input file =", infile
    print "end_time =", end_time.number
    print "delta_t =", delta_t.number
    print "n_workers =", n_workers
    print "use_gpu =", use_gpu
    print "manage_encounters =", manage_encounters
    print "\ninitializing the gravity module"
    sys.stdout.flush()

    init_smalln()
    
    # Note that there are actually three GPU options:
    #
    #	1. use the GPU code and allow GPU use (default)
    #	2. use the GPU code but disable GPU use (-g)
    #	3. use the non-GPU code (-G)

    if gpu_worker == 1:
        try:
            gravity = grav(number_of_workers = n_workers,
                           redirection = "none", mode = "gpu")
        except Exception as ex:
            gravity = grav(number_of_workers = n_workers,
                           redirection = "none")
    else:
        gravity = grav(number_of_workers = n_workers,
                       redirection = "none")

    gravity.initialize_code()
    gravity.parameters.set_defaults()

    #-----------------------------------------------------------------

    if infile == None:

        print "making a Plummer model"
        stars = new_plummer_model(number_of_stars)

        id = numpy.arange(number_of_stars)
        stars.id = id+1

        print "setting particle masses and radii"
        if salpeter == 0:
            print 'equal masses'
            total_mass = 1.0 | nbody_system.mass
            scaled_mass = total_mass / number_of_stars
        else:
            print 'salpeter mass function'
            scaled_mass = new_salpeter_mass_distribution_nbody(number_of_stars) 
        stars.mass = scaled_mass

        print "centering stars"
        stars.move_to_center()
        print "scaling stars to virial equilibrium"
        stars.scale_to_standard(smoothing_length_squared
                                    = gravity.parameters.epsilon_squared)

    else:

        # Read the input data.  Units are dynamical (sorry).
        # Format:  id  mass  pos[3]  vel[3]

        print "reading file", infile

        id = []
        mass = []
        pos = []
        vel = []

        f = open(infile, 'r')
        count = 0
        for line in f:
            if len(line) > 0:
                count += 1
                cols = line.split()
                if count == 1: snap = int(cols[0])
                elif count == 2: number_of_stars = int(cols[0])
                elif count == 3: time = float(cols[0]) | nbody_system.time
                else:
                    if len(cols) >= 8:
                        id.append(int(cols[0]))
                        mass.append(float(cols[1]))
                        pos.append((float(cols[2]),
                                    float(cols[3]), float(cols[4])))
                        vel.append((float(cols[5]),
                                    float(cols[6]), float(cols[7])))
        f.close()

        stars = datamodel.Particles(number_of_stars)
        stars.id = id
        stars.mass = mass | nbody_system.mass
        stars.position = pos | nbody_system.length
        stars.velocity = vel | nbody_system.speed
        #stars.radius = 0. | nbody_system.length

    total_mass = stars.mass.sum()
    ke = pa.kinetic_energy(stars)
    kT = ke/(1.5*number_of_stars)

    if number_of_binaries > 0:

        # Turn selected stars into binary components.
        # Only tested for equal-mass case.

        kep = Kepler(redirection = "none")
        kep.initialize_code()

        added_mass = 0.0 | nbody_system.mass

        # Work with energies rather than semimajor axes.

        Emin = 10*kT
        Emax = 20*kT
        ecc = 0.1

        id_count = number_of_stars
        nbin = 0
        for i in range(0, number_of_stars,
                       number_of_stars/number_of_binaries):

            # Star i is CM, becomes component, add other star at end.

            nbin += 1

            mass = stars[i].mass
            new_mass = numpy.random.uniform()*mass	# uniform q?
            mbin = mass + new_mass
            fac = new_mass/mbin
            E = Emin + numpy.random.uniform()*(Emax-Emin)
            a = 0.5*nbody_system.G*mass*new_mass/E

            kep.initialize_from_elements(mbin, a, ecc)
            dr = quantities.AdaptingVectorQuantity()
            dr.extend(kep.get_separation_vector())
            dv = quantities.AdaptingVectorQuantity()
            dv.extend(kep.get_velocity_vector())

            newstar = datamodel.Particles(1)
            newstar.mass = new_mass
            newstar.position = stars[i].position + (1-fac)*dr
            newstar.velocity = stars[i].velocity + (1-fac)*dv
            # stars[i].mass = mass
            stars[i].position = stars[i].position - fac*dr
            stars[i].velocity = stars[i].velocity - fac*dv

            id_count += 1
            newstar.id = id_count
            stars.add_particles(newstar)
            added_mass += new_mass

            if nbin >= number_of_binaries: break

        kep.stop()

        print 'created', nbin, 'binaries'
        sys.stdout.flush()

        stars.mass = stars.mass * total_mass/(total_mass+added_mass)
        number_of_stars += nbin

    # Set dynamical radii (assuming virial equilibrium and standard
    # units).  Note that this choice should be refined, and updated
    # as the system evolves.  Probably the choice of radius should be
    # made entirely in the multiples module.  TODO.  In these units,
    # M = 1 and <v^2> = 0.5, so the mean 90-degree turnaround impact
    # parameter is
    #
    #		b_90 = G (m_1+m_2) / vrel^2
    #		     = 2 <m> / 2<v^2>
    #		     = 2 / N			for equal masses
    #
    # Taking r_i = m_i / 2<v^2> = m_i in virial equilibrium means
    # that, approximately, "contact" means a 90-degree deflection (r_1
    # + r_2 = b_90).  A more conservative choice with r_i less than
    # this value will isolates encounters better, but also place more
    # load on the large-N dynamical module.

    stars.radius = stars.mass.number | nbody_system.length

    time = 0.0 | nbody_system.time
    # print "IDs:", stars.id.number

    print "recentering stars"
    stars.move_to_center()
    sys.stdout.flush()

    #-----------------------------------------------------------------

    if softening_length < 0.0 | nbody_system.length:

        # Use ~interparticle spacing.  Assuming standard units here.  TODO

        eps2 = 0.25*(float(number_of_stars))**(-0.666667) \
			| nbody_system.length**2
    else:
        eps2 = softening_length*softening_length
    print 'softening length =', eps2.sqrt()

    gravity.parameters.timestep_parameter = accuracy_parameter
    gravity.parameters.epsilon_squared = eps2
    gravity.parameters.use_gpu = use_gpu
    # gravity.parameters.manage_encounters = manage_encounters

    print ''
    print "adding particles"
    # print stars
    sys.stdout.flush()
    gravity.particles.add_particles(stars)
    gravity.commit_particles()

    print ''
    print "number_of_stars =", number_of_stars
    print "evolving to time =", end_time.number, \
          "in steps of", delta_t.number
    sys.stdout.flush()

    # Channel to copy values from the code to the set in memory.
    channel = gravity.particles.new_channel_to(stars)

    stopping_condition = gravity.stopping_conditions.collision_detection
    stopping_condition.enable()

    # Debugging: prevent the multiples code from being called.
    if 0:
        stopping_condition.disable()
        print 'stopping condition disabled'
        sys.stdout.flush()

    # -----------------------------------------------------------------
    # Create the coupled code and integrate the system to the desired
    # time, managing interactions internally.

    kep = init_kepler(stars[0], stars[1])
    multiples_code = multiples.Multiples(gravity, new_smalln, kep)

    multiples_code.neighbor_perturbation_limit = 0.1
    #multiples_code.neighbor_distance_factor = 1.0
    #multiples_code.neighbor_veto = False
    #multiples_code.neighbor_distance_factor = 2.0
    multiples_code.neighbor_veto = True

    print ''
    print 'multiples_code.initial_scale_factor =', \
        multiples_code.initial_scale_factor
    print 'multiples_code.neighbor_perturbation_limit =', \
        multiples_code.neighbor_perturbation_limit
    print 'multiples_code.neighbor_veto =', \
        multiples_code.neighbor_veto
    print 'multiples_code.final_scale_factor =', \
        multiples_code.final_scale_factor
    print 'multiples_code.initial_scatter_factor =', \
        multiples_code.initial_scatter_factor
    print 'multiples_code.final_scatter_factor =', \
        multiples_code.final_scatter_factor
    print 'multiples_code.retain_binary_apocenter =', \
        multiples_code.retain_binary_apocenter
    print 'multiples_code.wide_perturbation_limit =', \
        multiples_code.wide_perturbation_limit

    pre = "%%% "
    E0,cpu0 = print_log(pre, time, multiples_code)

    while time < end_time:

        time += delta_t
        multiples_code.evolve_model(time)

        # Copy values from the module to the set in memory.

        channel.copy()
    
        # Copy the index (ID) as used in the module to the id field in
        # memory.  The index is not copied by default, as different
        # codes may have different indices for the same particle and
        # we don't want to overwrite silently.

        channel.copy_attribute("index_in_code", "id")

        print_log(pre, time, multiples_code, E0, cpu0)
        sys.stdout.flush()

    #-----------------------------------------------------------------

    if not outfile == None:

        # Write data to a file.

        f = open(outfile, 'w')

        #--------------------------------------------------
        # Need to save top-level stellar data and parameters.
        # Need to save multiple data and parameters.

        f.write('%.15g\n'%(time.number))
        for s in multiples_code.stars: write_star(s, f)

        #--------------------------------------------------

        f.close()
        print 'wrote file', outfile

    print ''
    gravity.stop()
Пример #37
0
 def new_kepler(self):
     kepler = Kepler()
     kepler.initialize_code()
     return kepler
Пример #38
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)
Пример #39
0
 def start_kepler(self, mass_unit, length_unit):
     unit_converter = nbody_system.nbody_to_si(mass_unit, length_unit)
     self.kepler = Kepler(unit_converter,
                          redirection="none" if self.debug else "null")
     self.kepler.initialize_code()
Пример #40
0
        gravity = grav(number_of_workers = num_workers, redirection = "none")


# Initializing PH4 with Initial Conditions
    gravity.initialize_code()
    gravity.parameters.set_defaults()
    gravity.parameters.begin_time = time
    gravity.parameters.epsilon_squared = eps2
    gravity.parameters.timestep_parameter = delta_t.number

# Setting up the Code to Run with GPUs Provided by Command Line
    gravity.parameters.use_gpu = use_gpu
    gravity.parameters.gpu_id = gpu_ID

# Initializing Kepler and SmallN
    kep = Kepler(None, redirection = "none")
    kep.initialize_code()
    util.init_smalln()

    print time

    time, multiples_code = read.recover_crash(crash_file, gravity, kep, util.new_smalln)
    

# Setting Up the Stopping Conditions in PH4
    stopping_condition = gravity.stopping_conditions.collision_detection
    stopping_condition.enable()
    sys.stdout.flush()

# Starting the AMUSE Channel for PH4
    grav_channel = gravity.particles.new_channel_to(MasterSet)
Пример #41
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
Пример #42
0
def run_kepler(mass, semi, ecc, time):

    kep = Kepler(redirection='none')
    kep.initialize_code()

    kep.set_longitudinal_unit_vector(1.0, 1.0,
                                     0.0)
    kep.initialize_from_elements(mass, semi, ecc)
    a,e = kep.get_elements()
    p = kep.get_periastron()
    print "elements:", a, e, p
    kep.transform_to_time(time)
    x,y,z = kep.get_separation_vector()
    print "separation:", x,y,z
    x,y,z = kep.get_longitudinal_unit_vector()
    print "longitudinal:", x,y,z

    pos = [1, 0, 0] | nbody_system.length
    vel = [0, 0.5, 0] | nbody_system.speed
    kep.initialize_from_dyn(mass, pos[0], pos[1], pos[2],
                            vel[0], vel[1], vel[2])
    a,e = kep.get_elements()
    p = kep.get_periastron()
    print "elements:", a, e, p
    kep.transform_to_time(time)
    x,y,z = kep.get_separation_vector()
    print "separation:", x,y,z
    x,y,z = kep.get_velocity_vector()
    print "velocity:", x,y,z
    x,y,z = kep.get_longitudinal_unit_vector()
    print "longitudinal:", x,y,z

    kep.set_random(42)
    kep.make_binary_scattering(0.5 | nbody_system.mass,
                               0.5,
                               0.5 | nbody_system.mass,
                               0.0 | nbody_system.speed,
                               0.0 | nbody_system.length,
                               1.e-6,
                               0)
    kep.stop()
Пример #43
0
 def start_kepler(self, mass_unit, length_unit):
     unit_converter = nbody_system.nbody_to_si(mass_unit, length_unit)
     self.kepler = Kepler(unit_converter, redirection = "none" if self.debug else "null")
     self.kepler.initialize_code()
Пример #44
0
    def test11(self):
        """
        testing orbital_elements_for_rel_posvel_arrays for unbound orbits
        """
        
        from amuse.community.kepler.interface import Kepler
        
        numpy.random.seed(66)
        N = 10
        
        mass_sun = 1. | units.MSun
        mass1 = numpy.ones(N) * mass_sun
        mass2 = numpy.zeros(N) | units.MSun
        semi_major_axis=-1000.*(random.random(N)) | units.AU 
        eccentricity = (1.+random.random(N))*10.-9.
        inclination = numpy.pi*random.random(N)
        longitude_of_the_ascending_node = 2.*numpy.pi*random.random(N)-numpy.pi
        argument_of_periapsis = 2.*numpy.pi*random.random(N)-numpy.pi      
        
        # kepler.initialize_from_elements initializes orbits with mean_anomaly=0 and true_anomaly=0
        true_anomaly = 0.*(360.*random.random(N)-180.)
        
        comets = datamodel.Particles(N)
        
        converter = nbody_system.nbody_to_si(1|units.MSun,1|units.AU)
        kepler = Kepler(converter)
        kepler.initialize_code()
        for i,arg in enumerate(zip(mass1,mass2,semi_major_axis,eccentricity,true_anomaly,inclination, 
                                   longitude_of_the_ascending_node,argument_of_periapsis)):
            kepler.initialize_from_elements(mass=(mass1[i]+mass2[i]),
                                            semi=semi_major_axis[i],
                                            ecc=eccentricity[i])
            ri = kepler.get_separation_vector()
            vi = kepler.get_velocity_vector()
            
            om = longitude_of_the_ascending_node[i]
            w = argument_of_periapsis[i]
            incl = inclination[i]
            a1 = ([numpy.cos(om), -numpy.sin(om), 0.0], [numpy.sin(om), numpy.cos(om), 0.0], [0.0, 0.0, 1.0])
            a2 = ([1.0, 0.0, 0.0], [0.0, numpy.cos(incl), -numpy.sin(incl)], [0.0, numpy.sin(incl), numpy.cos(incl)])
            a3 = ([numpy.cos(w), -numpy.sin(w), 0.0], [numpy.sin(w), numpy.cos(w), 0.0], [0.0, 0.0, 1.0])
            A = numpy.dot(numpy.dot(a1,a2),a3)

            r_vec = numpy.dot(A,numpy.reshape(ri,3,1))
            v_vec = numpy.dot(A,numpy.reshape(vi,3,1))
          
            r = (0.0, 0.0, 0.0) | units.AU
            v = (0.0, 0.0, 0.0) | (units.AU / units.day)
            r[0] = r_vec[0]
            r[1] = r_vec[1]
            r[2] = r_vec[2]
            v[0] = v_vec[0]
            v[1] = v_vec[1]
            v[2] = v_vec[2]
  
            comets[i].mass = mass2[i]
            comets[i].position = r_vec
            comets[i].velocity = v_vec
        
        kepler.stop()
        
        semi_major_axis_ext, eccentricity_ext, ta_ext, inclination_ext, \
        longitude_of_the_ascending_node_ext, argument_of_periapsis_ext = \
        orbital_elements(comets.position,
                                               comets.velocity,
                                               comets.mass + mass_sun,
                                               G=constants.G)
        
        self.assertAlmostEqual(semi_major_axis,semi_major_axis_ext.in_(units.AU))
        self.assertAlmostEqual(eccentricity,eccentricity_ext)
        self.assertAlmostEqual(inclination,inclination_ext)
        self.assertAlmostEqual(longitude_of_the_ascending_node,longitude_of_the_ascending_node_ext)
        self.assertAlmostEqual(argument_of_periapsis,argument_of_periapsis_ext)
        self.assertAlmostEqual(true_anomaly,ta_ext)
Пример #45
0
def run_ph4(infile = None, number_of_stars = 40,
             end_time = 10 | nbody_system.time,
             delta_t = 1 | nbody_system.time,
             n_workers = 1, use_gpu = 1, gpu_worker = 1,
             accuracy_parameter = 0.1,
             softening_length = -1 | nbody_system.length,
             manage_encounters = 1, random_seed = 1234):

    if random_seed <= 0:
        numpy.random.seed()
        random_seed = numpy.random.randint(1, pow(2,31)-1)
    numpy.random.seed(random_seed)
    print "random seed =", random_seed

    if infile != None: print "input file =", infile
    print "end_time =", end_time.number
    print "delta_t =", delta_t.number
    print "n_workers =", n_workers
    print "use_gpu =", use_gpu
    print "manage_encounters =", manage_encounters
    print "\ninitializing the gravity module"
    sys.stdout.flush()

    # Note that there are actually three GPU options to test:
    #
    #	1. use the GPU code and allow GPU use (default)
    #	2. use the GPU code but disable GPU use (-g)
    #	3. use the non-GPU code (-G)

    if gpu_worker == 1:
        try:
            gravity = grav(number_of_workers = n_workers,
                           redirection = "none", mode = "gpu")
        except Exception as ex:
            gravity = grav(number_of_workers = n_workers, redirection = "none")
    else:
        gravity = grav(number_of_workers = n_workers, redirection = "none")

    gravity.initialize_code()
    gravity.parameters.set_defaults()

    #-----------------------------------------------------------------

    if infile == None:

        print "making a Plummer model"
        stars = new_plummer_model(number_of_stars)

        id = numpy.arange(number_of_stars)
        stars.id = id+1

        print "setting particle masses and radii"
	#stars.mass = (1.0 / number_of_stars) | nbody_system.mass
        scaled_mass = new_salpeter_mass_distribution_nbody(number_of_stars) 
        stars.mass = scaled_mass
        stars.radius = 0.02 | nbody_system.length

        print "centering stars"
        stars.move_to_center()
        print "scaling stars to virial equilibrium"
        stars.scale_to_standard(smoothing_length_squared
                                    = gravity.parameters.epsilon_squared)

        time = 0.0 | nbody_system.time
        sys.stdout.flush()

    else:

        # Read the input data.  Units are dynamical.

        print "reading file", infile

        id = []
        mass = []
        pos = []
        vel = []

        f = open(infile, 'r')
        count = 0
        for line in f:
            if len(line) > 0:
                count += 1
                cols = line.split()
                if count == 1: snap = int(cols[0])
                elif count == 2: number_of_stars = int(cols[0])
                elif count == 3: time = float(cols[0]) | nbody_system.time
                else:
                    if len(cols) >= 8:
                        id.append(int(cols[0]))
                        mass.append(float(cols[1]))
                        pos.append((float(cols[2]),
                                    float(cols[3]), float(cols[4])))
                        vel.append((float(cols[5]),
                                    float(cols[6]), float(cols[7])))
        f.close()

        stars = datamodel.Particles(number_of_stars)
        stars.id = id
        stars.mass = mass | nbody_system.mass
        stars.position = pos | nbody_system.length
        stars.velocity = vel | nbody_system.speed
        stars.radius = 0. | nbody_system.length

    # print "IDs:", stars.id.number
    sys.stdout.flush()

    #-----------------------------------------------------------------

    if softening_length == -1 | nbody_system.length:
        eps2 = 0.25*(float(number_of_stars))**(-0.666667) \
			| nbody_system.length**2
    else:
        eps2 = softening_length*softening_length

    gravity.parameters.timestep_parameter = accuracy_parameter
    gravity.parameters.epsilon_squared = eps2
    gravity.parameters.use_gpu = use_gpu
    # gravity.parameters.manage_encounters = manage_encounters

    print "adding particles"
    # print stars
    sys.stdout.flush()
    gravity.particles.add_particles(stars)
    gravity.commit_particles()

    print ''
    print "number_of_stars =", number_of_stars
    print "evolving to time =", end_time.number, \
          "in steps of", delta_t.number
    sys.stdout.flush()

    E0 = print_log(time, gravity)
    
    # Channel to copy values from the code to the set in memory.
    channel = gravity.particles.new_channel_to(stars)

    stopping_condition = gravity.stopping_conditions.collision_detection
    stopping_condition.enable()

    kep = Kepler(redirection = "none")
    kep.initialize_code()
    multiples_code = multiples.Multiples(gravity, new_smalln, kep)
    

    while time < end_time:
        time += delta_t
        multiples_code.evolve_model(time)

        # Copy values from the module to the set in memory.

        channel.copy()
    
        # Copy the index (ID) as used in the module to the id field in
        # memory.  The index is not copied by default, as different
        # codes may have different indices for the same particle and
        # we don't want to overwrite silently.

        channel.copy_attribute("index_in_code", "id")

        print_log(time, gravity, E0)
        sys.stdout.flush()

    print ''
    gravity.stop()
Пример #46
0
 def new_kepler_si(self):
     unit_converter = nbody_system.nbody_to_si(1 | units.MSun, 1 | units.AU)
     kepler = Kepler(unit_converter)
     kepler.initialize_code()
     return kepler
Пример #47
0
 def new_kepler(self):
     kepler = Kepler()
     kepler.initialize_code()
     return kepler
Пример #48
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
Пример #49
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