Ejemplo n.º 1
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()
Ejemplo n.º 2
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 read_state_from_file(restart_file, gravity_code,
                         resolve_collision_code_creation_function, kep):

    stars = io.read_set_from_file(restart_file + ".stars.hdf5",
                                  'hdf5',
                                  version='2.0').copy()
    stars_python = io.read_set_from_file(restart_file + ".stars_python.hdf5",
                                         'hdf5',
                                         version='2.0').copy()
    with open(restart_file + ".bookkeeping", "rb") as f:
        bookkeeping = pickle.load(f)
    if os.path.isfile(restart_file + ".extra_stuff"):
        with open(restart_file + ".extra_stuff", "rb") as f:
            extra_stuff = pickle.load(f)
    else:
        extra_stuff = None
    print bookkeeping
    root_to_tree = {}
    for root in stars:
        if hasattr(root, 'components') and not root.components is None:
            root_to_tree[root] = datamodel.trees.BinaryTreeOnParticle(
                root.components[0])
    gravity_code.set_begin_time(bookkeeping['model_time'])
    gravity_code.particles.add_particles(stars)
    gravity_code.commit_particles()

    multiples_code = multiples.Multiples(
        gravity_code, resolve_collision_code_creation_function, kep)
    #multiples_code.neighbor_distance_factor = 1.0
    #multiples_code.neighbor_veto = False
    #multiples_code.neighbor_distance_factor = 2.0
    #multiples_code.neighbor_veto = True
    multiples_code.neighbor_distance_factor = bookkeeping[
        'neighbor_distance_factor']
    multiples_code.neighbor_veto = bookkeeping['neighbor_veto']
    multiples_code.multiples_external_tidal_correction = bookkeeping[
        'multiples_external_tidal_correction']
    multiples_code.multiples_integration_energy_error = bookkeeping[
        'multiples_integration_energy_error']
    multiples_code.multiples_internal_tidal_correction = bookkeeping[
        'multiples_internal_tidal_correction']
    multiples.root_index = bookkeeping['root_index']
    multiples_code.root_to_tree = root_to_tree
    #multiples_code.set_model_time = bookkeeping['model_time']

    with open(restart_file + ".conf", "rb") as f:
        config = pickle.load(f)
    random.setstate(pickle.loads(config["py_seed"]))
    numpy.random.set_state(pickle.loads(config["numpy_seed"]))

    return stars_python, bookkeeping['model_time'], multiples_code, extra_stuff
Ejemplo n.º 4
0
def read_state_from_file(restart_file, gravity_code, kep, MT=0):

    # Function to load from file.  If you change params in
    # write_state_to_file, make sure you match the changes here.

    stars = io.read_set_from_file(restart_file + ".stars.hdf5",
                                  'amuse',
                                  version='2.0',
                                  close_file=True).copy()
    stars_python = io.read_set_from_file(restart_file + ".stars_python.hdf5",
                                         'amuse',
                                         version='2.0',
                                         close_file=True).copy()
    with open(restart_file + ".params", "rb") as f:
        params = pickle.load(f)
        f.close()

    if MT == 0:
        root_to_tree = {}
        for root in stars:
            if hasattr(root, 'components') and not root.components is None:
                root_to_tree[root] \
                    = datamodel.trees.BinaryTreeOnParticle(root.components[0])
    else:
        root_to_tree = MT

    gravity_code.parameters.timestep_parameter = params['timestep_parameter']
    gravity_code.parameters.epsilon_squared = params['epsilon_squared']

    gravity_code.particles.add_particles(stars)
    gravity_code.commit_particles()  # sets time steps

    multiples_code = multiples.Multiples(gravity_code, new_smalln, kep)
    multiples_code.neighbor_veto = params['neighbor_veto']
    multiples_code.multiples_external_tidal_correction \
 = params['multiples_external_tidal_correction']
    multiples_code.multiples_integration_energy_error \
 = params['multiples_integration_energy_error']
    multiples_code.multiples_internal_tidal_correction \
 = params['multiples_internal_tidal_correction']
    multiples.root_index = params['root_index']
    multiples_code.root_to_tree = root_to_tree

    print("\nread state from file ", restart_file, \
          'at time', params['model_time'])

    return stars_python, params['model_time'], params['delta_t'], \
  params['EZero'], params['CPUZero'], multiples_code
Ejemplo n.º 5
0
def read_state_from_file(restart_file, gravity_code, kep, SMALLN):

    stars = read_set_from_file(restart_file + ".stars.hdf5",
                               'hdf5',
                               version='2.0',
                               close_file=True).copy()
    #    single_stars = read_set_from_file(restart_file+".singles.hdf5",'hdf5',version='2.0')
    #    multiple_stars = read_set_from_file(restart_file+".coms.hdf5",'hdf5',version='2.0')
    stars_python = read_set_from_file(restart_file + ".stars_python.hdf5",
                                      'hdf5',
                                      version='2.0',
                                      close_file=True).copy()
    with open(restart_file + ".bookkeeping", "rb") as f:
        bookkeeping = pickle.load(f)
        f.close()
    print bookkeeping
    root_to_tree = {}
    for root in stars:
        if hasattr(root, 'components') and not root.components is None:
            root_to_tree[root] = datamodel.trees.BinaryTreeOnParticle(
                root.components[0])
    gravity_code.particles.add_particles(stars)
    #    print bookkeeping['model_time']
    #    gravity_code.set_begin_time = bookkeeping['model_time']

    multiples_code = multiples.Multiples(gravity_code, SMALLN, kep)
    #    multiples_code.neighbor_distance_factor = 1.0
    #    multiples_code.neighbor_veto = False
    #    multiples_code.neighbor_distance_factor = 2.0
    #    multiples_code.neighbor_veto = True
    multiples_code.neighbor_distance_factor = bookkeeping[
        'neighbor_distance_factor']
    multiples_code.neighbor_veto = bookkeeping['neighbor_veto']
    multiples_code.multiples_external_tidal_correction = bookkeeping[
        'multiples_external_tidal_correction']
    multiples_code.multiples_integration_energy_error = bookkeeping[
        'multiples_integration_energy_error']
    multiples_code.multiples_internal_tidal_correction = bookkeeping[
        'multiples_internal_tidal_correction']
    multiples.root_index = bookkeeping['root_index']
    multiples_code.root_to_tree = root_to_tree
    #    multiples_code.set_model_time = bookkeeping['model_time']

    return stars_python, multiples_code
Ejemplo n.º 6
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
Ejemplo n.º 7
0
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
# codes may have different indices for the same particle and
# we don't want to overwrite silently.
grav_channel.copy_attribute("index_in_code", "id")

write.write_state_to_file(time, MasterSet, gravity, multiples_code, write_file)
Ejemplo n.º 8
0
    def __init__(self,
                 nstars=10,
                 endtime=10,
                 total_mass=1000,
                 rscale=1.0,
                 interaction_radius=-1.0,
                 star_code='hermite',
                 star_smoothing_fraction=0.0,
                 seed=-1,
                 ntimesteps=10,
                 must_do_plot=True,
                 **ignored_options):
        if seed >= 0:
            numpy.random.seed(seed)

        if interaction_radius < 0.0:
            self.interaction_radius = 0.01 | nbody_system.length
        else:
            self.interaction_radius = interaction_radius | nbody_system.length

        self.must_do_plot = must_do_plot
        self.line = None
        self.line2 = None

        self.ntimesteps = ntimesteps
        self.nstars = nstars

        self.total_mass = total_mass | nbody_system.mass
        self.rscale = rscale | nbody_system.length

        self.star_epsilon = star_smoothing_fraction * self.rscale

        self.star_mass = self.total_mass

        self.endtime = endtime | nbody_system.time
        self.delta_t = self.endtime / self.ntimesteps

        self.create_code(star_code)

        self.code = multiples.Multiples(self.star_code, self.new_smalln)

        time = 0
        sum_energy = self.code.kinetic_energy + self.code.potential_energy
        energy0 = sum_energy.value_in(nbody_system.energy)
        coreradius = self.star_code.particles.virial_radius().value_in(
            self.rscale.to_unit())

        print("Time          :", time)
        print("Energy        :", energy0)
        print("Virial radius :", coreradius)

        self.evolve_model()

        if must_do_plot:
            pylab.show()
            pylab.savefig("multiples-{0}-{1}.png".format(star_code, nstars))

        time = self.code.model_time.value_in(nbody_system.time)
        sum_energy = self.code.kinetic_energy + \
            self.code.potential_energy - self.code.multiples_energy_correction
        energy = sum_energy.value_in(nbody_system.energy)
        coreradius = self.star_code.particles.virial_radius().value_in(
            self.rscale.to_unit())

        print("Time          :", time)
        print("Energy        :", energy)
        print("Delta E       :", (energy - energy0) / energy0)
        print("Virial radius :", coreradius)

        self.stop()

        if must_do_plot:
            input('Press enter...')
Ejemplo n.º 9
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()
Ejemplo n.º 10
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()
Ejemplo n.º 11
0
def make_nbody(number_of_stars=100,
               time=0.0,
               n_workers=1,
               use_gpu=1,
               gpu_worker=1,
               salpeter=0,
               delta_t=1.0 | nbody_system.time,
               timestep_parameter=0.1,
               softening_length=0.0 | nbody_system.length,
               random_seed=1234):

    # Make an N-body system, print out some statistics on it, and save
    # it in a restart file.  The restart file name is of the form
    # 't=nnnn.n.xxx', where the default time is 0.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

    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()

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

    # Make a standard N-body system.

    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'
        mmin = 0.5 | nbody_system.mass
        mmax = 10.0 | nbody_system.mass
        scaled_mass = new_salpeter_mass_distribution_nbody(number_of_stars,
                                                           mass_min=mmin,
                                                           mass_max=mmax)

    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)

    # 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 isolate encounters better, but also place more
    # load on the large-N dynamical module.

    stars.radius = 0.5 * 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

        softening_length = 0.5*float(number_of_stars)**(-0.3333333) \
    | nbody_system.length
    print 'softening length =', softening_length

    gravity.parameters.timestep_parameter = timestep_parameter
    gravity.parameters.epsilon_squared = softening_length * softening_length
    gravity.parameters.use_gpu = use_gpu

    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
    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])
    multiples_code = multiples.Multiples(gravity, new_smalln, kep)

    multiples_code.neighbor_perturbation_limit = 0.1
    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

    # Take a dummy step, just in case...

    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")

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

    # file = 't='+'{:07.2f}'.format(time.number)        # fails in Python 2.6
    file = 't=%07.2f' % time.number
    write_state_to_file(time, stars, gravity, multiples_code, file, delta_t,
                        E0, cpu0)
    tree_copy = multiples_code.root_to_tree.copy()

    del multiples_code
    sys.stdout.flush()

    gravity.stop()
    kep.stop()
    stop_smalln()
    print ''
Ejemplo n.º 12
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()