Beispiel #1
0
 def test6(self):
     print("Test 6: testing user interface (nbody units)")
     numpy.random.seed(345672)
     masses = new_salpeter_mass_distribution_nbody(1000)
     
     self.assertEqual(len(masses), 1000)
     self.assertAlmostEqual(masses.sum(),      1.0 | nbody_system.mass)
     self.assertAlmostEqual(masses.mean(), 1.0 / 1000 | nbody_system.mass)
     self.assertAlmostEqual(masses.amin(), 0.10017909529 / 0.334475937397 / 1000 | nbody_system.mass)
     self.assertAlmostEqual(masses.amax(), 19.7132849297 / 0.334475937397 / 1000 | nbody_system.mass)
Beispiel #2
0
    def test6(self):
        print "Test 6: testing user interface (nbody units)"
        numpy.random.seed(345672)
        masses = new_salpeter_mass_distribution_nbody(1000)

        self.assertEqual(len(masses), 1000)
        self.assertAlmostEqual(masses.sum(), 1.0 | nbody_system.mass)
        self.assertAlmostEqual(masses.mean(), 1.0 / 1000 | nbody_system.mass)
        self.assertAlmostEqual(masses.amin(), 0.10017909529 / 0.334475937397 / 1000 | nbody_system.mass)
        self.assertAlmostEqual(masses.amax(), 19.7132849297 / 0.334475937397 / 1000 | nbody_system.mass)
Beispiel #3
0
def new_cluster(number_of_stars=1000, radius=None):
    """
    Return a new cluster of stars with the given radii and a salpeter mass
    distribution.
    """
    if radius is None:
        radius = (0.5 / number_of_stars) | nbody_system.length

    particles = new_plummer_model(number_of_stars)
    particles.mass = new_salpeter_mass_distribution_nbody(number_of_stars)
    particles.radius = radius
    particles.move_to_center()
    return particles
Beispiel #4
0
def new_cluster(number_of_stars=1000, radius=None):
    """
    Return a new cluster of stars with the given radii and a salpeter mass
    distribution.
    """
    if radius is None:
        radius = (0.5 / number_of_stars) | nbody_system.length

    particles = new_plummer_model(number_of_stars)
    particles.mass = new_salpeter_mass_distribution_nbody(number_of_stars)
    particles.radius = radius
    particles.move_to_center()
    return particles
 def test6(self):
     print "Test all particle attributes using Hop - each different function creates its own instance of Hop"
     numpy.random.seed(123)
     nbody_plummer = new_plummer_sphere(100)
     nbody_plummer.mass = new_salpeter_mass_distribution_nbody(100)
     
     # Each different function creates its own instance of Hop
     result = nbody_plummer.new_particle_from_cluster_core(reuse_hop=True)
     result = nbody_plummer.bound_subset(G=nbody_system.G, reuse_hop=True)
     result = nbody_plummer.mass_segregation_Gini_coefficient(reuse_hop=True)
     result = nbody_plummer.LagrangianRadii(reuse_hop=True)
     result = nbody_plummer.densitycentre_coreradius_coredens(reuse_hop=True)
     
     converter = nbody_system.nbody_to_si(1.0|units.MSun, 1.0 | units.parsec)
     si_plummer = ParticlesWithUnitsConverted(nbody_plummer, converter.as_converter_from_si_to_nbody())
     functions_using_hop = [
         si_plummer.new_particle_from_cluster_core, 
         si_plummer.bound_subset, 
         si_plummer.mass_segregation_Gini_coefficient, 
         si_plummer.LagrangianRadii, 
         si_plummer.densitycentre_coreradius_coredens
     ]
     
     # Each fails since the Hop instance it tries to reuse has a different unit_converter
     for function_using_hop in functions_using_hop:
         self.assertRaises(ConvertArgumentsException, function_using_hop, unit_converter=converter,
             expected_message="error while converting parameter 'mass', error: Cannot express kg in mass, the units do not have the same bases")
     
     # Close all Hop instances:
     nbody_results = []
     nbody_results.append(nbody_plummer.new_particle_from_cluster_core(reuse_hop=False))
     nbody_results.append(nbody_plummer.bound_subset(G=nbody_system.G, reuse_hop=False))
     nbody_results.append(nbody_plummer.mass_segregation_Gini_coefficient(reuse_hop=False))
     nbody_results.append(nbody_plummer.LagrangianRadii(reuse_hop=False))
     nbody_results.append(nbody_plummer.densitycentre_coreradius_coredens(reuse_hop=False))
     
     # Now it works, because the Hop instances were closed, and new ones will be instantiated
     si_results = []
     for function_using_hop in functions_using_hop:
         si_results.append(function_using_hop(unit_converter=converter))
     
     convert = converter.as_converter_from_si_to_nbody()
     self.assertAlmostRelativeEqual(si_results[0].position, 
         ParticlesWithUnitsConverted(nbody_results[0].as_set(), convert)[0].position)
     self.assertAlmostRelativeEqual(si_results[1].position, 
         ParticlesWithUnitsConverted(nbody_results[1], convert).position)
     self.assertAlmostRelativeEqual(si_results[2], nbody_results[2], places=10)
     self.assertAlmostRelativeEqual(si_results[3][0], convert.from_target_to_source(nbody_results[3][0]), places=10)
     for in_si, in_nbody in zip(si_results[4], nbody_results[4]):
         self.assertAlmostRelativeEqual(in_si, convert.from_target_to_source(in_nbody), places=10)
Beispiel #6
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()
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()
def run_hacs(infile=None,
             number_of_stars=128,
             nmax=2048,
             end_time=0.1 | nbody_system.time,
             delta_t=0.125 | nbody_system.time,
             dt_max=0.0625 | nbody_system.time,
             n_ngb=16,
             eta_irr=0.6,
             eta_reg=0.1,
             softening_length=0.0 | nbody_system.length):

    if infile != None: print "input file =", infile
    print "end_time =", end_time.number
    print "nstars= ", number_of_stars,
    print "nmax= ", nmax,
    print "delta_t= ", delta_t.number
    print "dt_max= ", dt_max.number
    print "n_ngb= ", n_ngb,
    print "eta_irr= ", eta_irr
    print "eta_reg= ", eta_reg
    print "eps2=    ", softening_length.number**2
    print "\ninitializing the gravity module"
    sys.stdout.flush()

    #    gravity = grav(number_of_workers = 1, redirection = "none", mode='cpu')
    gravity = grav(number_of_workers=1, redirection="none", mode='cpu')
    gravity.initialize_code()

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

    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.0 | 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.eps2)

        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
        print len(mass), len(pos), len(vel), len(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
        nmax = 2 * len(mass)

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

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

    gravity.parameters.nmax = nmax
    gravity.parameters.dtmax = dt_max
    #    gravity.parameters.n_ngb   = n_ngb;
    gravity.parameters.eta_irr = eta_irr
    gravity.parameters.eta_reg = eta_reg
    gravity.parameters.eps2 = softening_length**2
    gravity.commit_parameters()

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

    #    stopping_condition.disable()

    while time < end_time:
        if (gravity.get_time() >= time):
            time += delta_t

        gravity.evolve_model(time)

        # Ensure that the stars list is consistent with the internal
        # data in the module.

        ls = len(stars)

        # Update the bookkeeping: synchronize stars with the module data.

        # this breaks the code ...
        channel.copy()

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

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

        # 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.

        if stopping_condition.is_set():
            star1 = stopping_condition.particles(0)[0]
            star2 = stopping_condition.particles(1)[0]
            gravity.synchronize_model()
            print '\nstopping condition set at time', \
                gravity.get_time().number,'for:\n'
            print star1
            print ''
            print star2
            print ''
            gravity.particles.remove_particle(star1)
            gravity.particles.remove_particle(star2)

            gravity.recommit_particles()

            print 'ls=', len(stars)

            gravity.update_particle_set()
            gravity.particles.synchronize_to(stars)

            print 'ls=', len(stars)

        if len(stars) != ls:
            if 0:
                print "stars:"
                for s in stars:
                    print " ", s.id.number, s.mass.number, s.x.number, s.y.number, s.z.number
            else:
                print "number of stars =", len(stars)
            sys.stdout.flush()

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

    print ''
    print_log(gravity.get_time(), gravity, E0)
    sys.stdout.flush()
    gravity.stop()
Beispiel #9
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 ''
Beispiel #10
0
def run_multiples(infile = None,
                   number_of_stars = 64,
                   nmax = 2048,
                   end_time = 0.1   | nbody_system.time,
                   delta_t = 0.125 | nbody_system.time,
                   dt_max  = 0.0625 | nbody_system.time,
                   n_ngb   = 16,
                   eta_irr = 0.6,
                   eta_reg = 0.1,
                   softening_length = 0.0 | nbody_system.length,
                   random_seed = 1234):

    if infile != None: print "input file =", infile
    print "end_time =",  end_time.number
    print "nstars= ",    number_of_stars,
    print "nmax= ",      nmax,
    print "delta_t= ",   delta_t.number
    print "dt_max= ",    dt_max.number
    print "n_ngb= ",     n_ngb,
    print "eta_irr= ",   eta_irr
    print "eta_reg= ",   eta_reg
    print "eps2=    ",   softening_length.number**2
    print "\ninitializing the gravity module"
    sys.stdout.flush()

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

    gravity = grav(number_of_workers = 1, debugger="none", redirection = "none")
    gravity.initialize_code()

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

    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.0 | nbody_system.length

        print "centering stars"
        stars.move_to_center()
        print "scaling stars to virial equilibrium"
        stars.scale_to_standard(smoothing_length_squared
                                    = 0 | nbody_system.length ** 2)

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

    else:

        # Read the input data.  Units are dynamical.

        print "reading file", infile; sys.stdout.flush()

        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]))
                        id.append(count)
                        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
        nmax = 2*len(mass)

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

    global root_index
    root_index = len(stars) + 10000
    #-----------------------------------------------------------------
    
    gravity.parameters.nmax    = nmax;
    gravity.parameters.dtmax   = dt_max;
#    gravity.parameters.n_ngb   = n_ngb;
    gravity.parameters.eta_irr = eta_irr;
    gravity.parameters.eta_reg = eta_reg;
    gravity.parameters.eps2    = softening_length**2
    gravity.commit_parameters();

    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('hacs64', gravity)
    dEmult = 0.0
    
    # 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()
    
    # Tree structure on the stars dataset:

    stars.child1 = 0 | units.object_key
    stars.child2 = 0 | units.object_key
    
    while time < end_time:
        time += delta_t

        while gravity.get_time() < time:
            gravity.evolve_model(time)
            if stopping_condition.is_set():
                star1 = stopping_condition.particles(0)[0]
                star2 = stopping_condition.particles(1)[0]
                print '\n--------------------------------------------------'
                print 'stopping condition set at time', \
                    gravity.get_time().number

                E = print_log('hacs64', gravity, E0)
                print 'dEmult =', dEmult, 'dE =', (E-E0).number-dEmult
                # channel.copy()	# need other stars to be current in memory
                # print_energies(stars)

                # Synchronize everything for now.  Later we will just
                # synchronize neighbors if gravity supports that.  TODO
                gravity.synchronize_model()
                gravity.particles.synchronize_to(stars)

                dEmult += manage_encounter(star1, star2, stars,
                                           gravity.particles)

                # Recommit reinitializes all particles (and redundant
                # here, since done automatically).  Later we will just
                # recommit and reinitialize a list if gravity supports
                # it. TODO
                gravity.recommit_particles()

                E = print_log('hacs64', gravity, E0)
                print 'dEmult =', dEmult, 'dE =', (E-E0).number-dEmult
                print '\n--------------------------------------------------'
        
        ls = len(stars)
    
        # 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")

        if len(stars) != ls:
            if 0:
                print "stars:"
                for s in stars:
                    print " ", s.id.number, s.mass.number, \
			       s.x.number, s.y.number, s.z.number
            else:
                print "number of stars =", len(stars)
            sys.stdout.flush()

        E = print_log('hacs64', gravity, E0)
        print 'dEmult =', dEmult, 'dE =', (E-E0).number-dEmult

    print ''
    gravity.stop()
Beispiel #11
0
def run_smallN(infile=None,
               number_of_stars=10,
               end_time=10 | nbody_system.time,
               delta_t=1 | nbody_system.time,
               accuracy_parameter=0.1):

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

    gravity = grav(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.0 | nbody_system.length

        print "centering stars"
        stars.move_to_center()
        print "scaling stars to virial equilibrium"
        stars.scale_to_standard(smoothing_length_squared = 0 \
     | nbody_system.length*nbody_system.length)

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

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

    gravity.parameters.timestep_parameter = accuracy_parameter

    print "adding particles"
    # print stars
    sys.stdout.flush()
    gravity.parameters.begin_time = time
    gravity.particles.add_particles(stars)
    print "committing particles"
    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)

    while time < end_time:
        time += delta_t
        #gravity.parameters.outfile = 'abc'
        gravity.evolve_model(time)

        # Ensure that the stars list is consistent with the internal
        # data in the module.

        ls = len(stars)

        # Update the bookkeeping: synchronize stars with the module data.

        try:
            gravity.update_particle_set()
            gravity.particles.synchronize_to(stars)
        except:
            pass

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

        if len(stars) != ls:
            if 0:
                print "stars:"
                for s in stars:
                    print " ", s.id.number, s.mass.number, \
          s.x.number, s.y.number, s.z.number
            else:
                print "number of stars =", len(stars)
            sys.stdout.flush()

        print_log(time, gravity, E0)

        over = gravity.is_over()
        if over:
            gravity.update_particle_tree()
            gravity.update_particle_set()
            gravity.particles.synchronize_to(stars)
            channel.copy()
            channel.copy_attribute("index_in_code", "id")
            print "binaries:"
            x = trees.BinaryTreesOnAParticleSet(stars, "child1", "child2")
            roots = list(x.iter_roots())
            for r in roots:
                for level, particle in r.iter_levels():
                    print '  ' * level, int(particle.id),
                    if not particle.child1 is None:
                        m, a, e = get_binary_elements(particle)
                        print ' (', m, a, e, ')'
                    else:
                        print ''
            break

        sys.stdout.flush()

    if not over:
        print '\ninteraction is not over'
    gravity.stop()
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()
Beispiel #13
0
def run_multiples(infile=None,
                  number_of_stars=64,
                  nmax=2048,
                  end_time=0.1 | nbody_system.time,
                  delta_t=0.125 | nbody_system.time,
                  dt_max=0.0625 | nbody_system.time,
                  n_ngb=16,
                  eta_irr=0.6,
                  eta_reg=0.1,
                  softening_length=0.0 | nbody_system.length,
                  random_seed=1234):

    if infile != None: print("input file =", infile)
    print("end_time =", end_time.number)
    print("nstars= ", number_of_stars, end=' ')
    print("nmax= ", nmax, end=' ')
    print("delta_t= ", delta_t.number)
    print("dt_max= ", dt_max.number)
    print("n_ngb= ", n_ngb, end=' ')
    print("eta_irr= ", eta_irr)
    print("eta_reg= ", eta_reg)
    print("eps2=    ", softening_length.number**2)
    print("\ninitializing the gravity module")
    sys.stdout.flush()

    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)

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

    gravity = grav(number_of_workers=1, debugger="none", redirection="none")
    gravity.initialize_code()

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

    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.0 | nbody_system.length

        print("centering stars")
        stars.move_to_center()
        print("scaling stars to virial equilibrium")
        stars.scale_to_standard(smoothing_length_squared=0
                                | nbody_system.length**2)

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

    else:

        # Read the input data.  Units are dynamical.

        print("reading file", infile)
        sys.stdout.flush()

        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]))
                        id.append(count)
                        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
        nmax = 2 * len(mass)

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

    global root_index
    root_index = len(stars) + 10000
    #-----------------------------------------------------------------

    gravity.parameters.nmax = nmax
    gravity.parameters.dtmax = dt_max
    #    gravity.parameters.n_ngb   = n_ngb;
    gravity.parameters.eta_irr = eta_irr
    gravity.parameters.eta_reg = eta_reg
    gravity.parameters.eps2 = softening_length**2
    gravity.commit_parameters()

    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('hacs64', gravity)
    dEmult = 0.0

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

    # Tree structure on the stars dataset:

    stars.child1 = 0 | units.object_key
    stars.child2 = 0 | units.object_key

    while time < end_time:
        time += delta_t

        while gravity.get_time() < time:
            gravity.evolve_model(time)
            if stopping_condition.is_set():
                star1 = stopping_condition.particles(0)[0]
                star2 = stopping_condition.particles(1)[0]
                print('\n--------------------------------------------------')
                print('stopping condition set at time', \
                    gravity.get_time().number)

                E = print_log('hacs64', gravity, E0)
                print('dEmult =', dEmult, 'dE =', (E - E0).number - dEmult)
                # channel.copy()	# need other stars to be current in memory
                # print_energies(stars)

                # Synchronize everything for now.  Later we will just
                # synchronize neighbors if gravity supports that.  TODO
                gravity.synchronize_model()
                gravity.particles.synchronize_to(stars)

                dEmult += manage_encounter(star1, star2, stars,
                                           gravity.particles)

                # Recommit reinitializes all particles (and redundant
                # here, since done automatically).  Later we will just
                # recommit and reinitialize a list if gravity supports
                # it. TODO
                gravity.recommit_particles()

                E = print_log('hacs64', gravity, E0)
                print('dEmult =', dEmult, 'dE =', (E - E0).number - dEmult)
                print('\n--------------------------------------------------')

        ls = len(stars)

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

        if len(stars) != ls:
            if 0:
                print("stars:")
                for s in stars:
                    print(" ", s.id.number, s.mass.number, \
          s.x.number, s.y.number, s.z.number)
            else:
                print("number of stars =", len(stars))
            sys.stdout.flush()

        E = print_log('hacs64', gravity, E0)
        print('dEmult =', dEmult, 'dE =', (E - E0).number - dEmult)

    print('')
    gravity.stop()
Beispiel #14
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, gpu_id = -1,
             accuracy_parameter = 0.1,
             softening_length = -1 | nbody_system.length,
             manage_encounters = 1):

    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 "initializing the gravity module"
    sys.stdout.flush()

    # Note that there are actually really 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)

    #print "1"; sys.stdout.flush()
    
    gpu = 0
    if gpu_worker == 1:
        try:
            gravity = grav(number_of_workers = n_workers,
                           redirection = "none", mode = "gpu")
            #              debugger='valgrind')
            gpu = 1
        except Exception as ex:
            print \
                '*** GPU worker code not found. Reverting to non-GPU code. ***'
            gpu = 0

    if gpu == 0:
        gravity = grav(number_of_workers = n_workers,
                       redirection = "none")
        #              debugger='valgrind')

    #print "2"; sys.stdout.flush()
    gravity.initialize_code()

    #print "3"; sys.stdout.flush()
    gravity.parameters.set_defaults()

    gravity.parameters.gpu_id = gpu_id

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

    #print "4"; sys.stdout.flush()

    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
    if 0:
        scaled_mass = new_salpeter_mass_distribution_nbody(number_of_stars) 
        stars.mass = scaled_mass
    stars.radius = 0.0 | nbody_system.length

    print "centering stars"
    stars.move_to_center()
    if 0:
        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()

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

    #print "5"; 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

    #print "6"; sys.stdout.flush()
    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
    sys.stdout.flush()

    E0,cpu0,wall0 = 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()

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

    cpu0 = cputime()
    t0 = 0.
    pi = math.pi
    times = [1., 2., pi, 4*pi/3, 5., 2*pi, 2*pi + pi/100,
             2*pi + pi/5, 7., 8., 3*pi, 10.]

    gravity.parameters.force_sync = 1	# stays set until explicitly unset

    for t in times:
        time = t|nbody_system.time

        print "\nEvolving to time", time
        sys.stdout.flush()

        gravity.parameters.block_steps = 0
        gravity.parameters.total_steps = 0
        gravity.evolve_model(time)

        dt = t - t0
        t0 = t
        cpu = cputime()
        dcpu = cpu - cpu0
        cpu0 = cpu

        # Ensure that the stars list is consistent with the internal
        # data in the module.

        ls = len(stars)

	# Update the bookkeeping: synchronize stars with the module data.

        try:
            gravity.update_particle_set()
            gravity.particles.synchronize_to(stars)
        except:
            pass
    
        # 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")

        if stopping_condition.is_set():
            star1 = stopping_condition.particles(0)[0]
            star2 = stopping_condition.particles(1)[0]
            print '\nstopping condition set at time', \
                gravity.get_time().number,'for:\n'
            print star1
            print ''
            print star2
            print ''
            raise Exception("no encounter handling")

        if len(stars) != ls:
            if 0:
                print "stars:"
                for s in stars:
                    print " ", s.id.number, s.mass.number, \
			       s.x.number, s.y.number, s.z.number
            else:
                print "number of stars =", len(stars)
            sys.stdout.flush()

        print_log('', time, gravity, E0, cpu0, wall0)

        print '@@@'
        print '@@@ t =', time.number, ' dt =', dt
        print '@@@ sync_time =', gravity.parameters.sync_time.number
        print '@@@ dcpu/dt =', dcpu/dt
        nb = gravity.parameters.block_steps
        ns = gravity.parameters.total_steps
        print '@@@ d(block_steps) =', nb, ' #/dt =', nb/dt
        print '@@@ d(total steps) =', ns, ' #/dt =', ns/dt

        #print stars
        sys.stdout.flush()

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

    print ''
    gravity.stop()
Beispiel #15
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()
Beispiel #16
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, gpu_id = -1,
             accuracy_parameter = 0.1,
             softening_length = -1 | nbody_system.length,
             manage_encounters = 1):

    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)

    #print "1"; sys.stdout.flush()
    
    gpu = 0
    if gpu_worker == 1:
        try:
            gravity = grav(number_of_workers = n_workers,
                           redirection = "none", mode = "gpu")
            #              debugger='valgrind')
            gpu = 1
        except Exception as ex:
            print '*** GPU worker code not found. Reverting to non-GPU code. ***'
            gpu = 0

    if gpu == 0:
        gravity = grav(number_of_workers = n_workers,
                       redirection = "none")
        #              debugger='valgrind')

    #print "2"; sys.stdout.flush()
    gravity.initialize_code()

    #print "3"; sys.stdout.flush()
    gravity.parameters.set_defaults()

    gravity.parameters.gpu_id = gpu_id

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

    #print "4"; sys.stdout.flush()
    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
        if 0:
            scaled_mass = new_salpeter_mass_distribution_nbody(number_of_stars) 
            stars.mass = scaled_mass
        stars.radius = 0.0 | nbody_system.length

        print "centering stars"
        stars.move_to_center()
        if 0:
            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()

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

    #print "5"; 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

    #print "6"; sys.stdout.flush()
    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,cpu0,wall0 = 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()
    
    while time < end_time:
        time += delta_t
        gravity.evolve_model(time)

        # Ensure that the stars list is consistent with the internal
        # data in the module.

        ls = len(stars)

    # Update the bookkeeping: synchronize stars with the module data.

        try:
            gravity.update_particle_set()
            gravity.particles.synchronize_to(stars)
        except:
            pass
    
        # 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")

        if stopping_condition.is_set():
            star1 = stopping_condition.particles(0)[0]
            star2 = stopping_condition.particles(1)[0]
            print '\nstopping condition set at time', \
                gravity.get_time().number,'for:\n'
            print star1
            print ''
            print star2
            print ''
            raise Exception("no encounter handling")

        if len(stars) != ls:
            if 0:
                print "stars:"
                for s in stars:
                    print " ", s.id.number, s.mass.number, \
                    s.x.number, s.y.number, s.z.number
            else:
                print "number of stars =", len(stars)
            sys.stdout.flush()

        print_log('', time, gravity, E0, cpu0, wall0)
        sys.stdout.flush()

    print ''
    gravity.stop()
Beispiel #17
0
def run_smallN(infile = None, number_of_stars = 10,
             end_time = 10 | nbody_system.time,
             delta_t = 1 | nbody_system.time,
             accuracy_parameter = 0.1):

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

    gravity = grav(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.0 | nbody_system.length

        print "centering stars"
        stars.move_to_center()
        print "scaling stars to virial equilibrium"
        stars.scale_to_standard(smoothing_length_squared = 0 \
				 | nbody_system.length*nbody_system.length)

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

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

    gravity.parameters.timestep_parameter = accuracy_parameter

    print "adding particles"
    # print stars
    sys.stdout.flush()
    gravity.parameters.begin_time = time
    gravity.particles.add_particles(stars)
    print "committing particles"
    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)

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

        # Ensure that the stars list is consistent with the internal
        # data in the module.

        ls = len(stars)

	# Update the bookkeeping: synchronize stars with the module data.

        try:
            gravity.update_particle_set()
            gravity.particles.synchronize_to(stars)
        except:
            pass

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

        if len(stars) != ls:
            if 0:
                print "stars:"
                for s in stars:
                    print " ", s.id.number, s.mass.number, \
			       s.x.number, s.y.number, s.z.number
            else:
                print "number of stars =", len(stars)
            sys.stdout.flush()

        print_log(time, gravity, E0)

        over = gravity.is_over()
        if over:
            gravity.update_particle_tree()
            gravity.update_particle_set()
            gravity.particles.synchronize_to(stars)
            channel.copy()
            channel.copy_attribute("index_in_code", "id")
            print "binaries:"
            x = trees.BinaryTreesOnAParticleSet(stars, "child1", "child2")
            roots = list(x.iter_roots())
            for r in roots:
                for level, particle in r.iter_levels():
                    print '  '*level, int(particle.id),
                    if not particle.child1 is None:
                        m,a,e = get_binary_elements(particle)
                        print ' (', m, a, e, ')'
                    else:
                        print ''
            break
    
        sys.stdout.flush()

    if not over:
        print '\ninteraction is not over'
    gravity.stop()
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 ''
Beispiel #19
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()
    def test6(self):
        print "Test all particle attributes using Hop - each different function creates its own instance of Hop"
        numpy.random.seed(123)
        nbody_plummer = new_plummer_sphere(100)
        nbody_plummer.mass = new_salpeter_mass_distribution_nbody(100)

        # Each different function creates its own instance of Hop
        result = nbody_plummer.new_particle_from_cluster_core(reuse_hop=True)
        result = nbody_plummer.bound_subset(G=nbody_system.G, reuse_hop=True)
        result = nbody_plummer.mass_segregation_Gini_coefficient(
            reuse_hop=True)
        result = nbody_plummer.LagrangianRadii(reuse_hop=True)
        result = nbody_plummer.densitycentre_coreradius_coredens(
            reuse_hop=True)

        converter = nbody_system.nbody_to_si(1.0 | units.MSun,
                                             1.0 | units.parsec)
        si_plummer = ParticlesWithUnitsConverted(
            nbody_plummer, converter.as_converter_from_si_to_nbody())
        functions_using_hop = [
            si_plummer.new_particle_from_cluster_core, si_plummer.bound_subset,
            si_plummer.mass_segregation_Gini_coefficient,
            si_plummer.LagrangianRadii,
            si_plummer.densitycentre_coreradius_coredens
        ]

        # Each fails since the Hop instance it tries to reuse has a different unit_converter
        for function_using_hop in functions_using_hop:
            self.assertRaises(
                ConvertArgumentsException,
                function_using_hop,
                unit_converter=converter,
                expected_message=
                "error while converting parameter 'mass', error: Cannot express kg in mass, the units do not have the same bases"
            )

        # Close all Hop instances:
        nbody_results = []
        nbody_results.append(
            nbody_plummer.new_particle_from_cluster_core(reuse_hop=False))
        nbody_results.append(
            nbody_plummer.bound_subset(G=nbody_system.G, reuse_hop=False))
        nbody_results.append(
            nbody_plummer.mass_segregation_Gini_coefficient(reuse_hop=False))
        nbody_results.append(nbody_plummer.LagrangianRadii(reuse_hop=False))
        nbody_results.append(
            nbody_plummer.densitycentre_coreradius_coredens(reuse_hop=False))

        # Now it works, because the Hop instances were closed, and new ones will be instantiated
        si_results = []
        for function_using_hop in functions_using_hop:
            si_results.append(function_using_hop(unit_converter=converter))

        convert = converter.as_converter_from_si_to_nbody()
        self.assertAlmostRelativeEqual(
            si_results[0].position,
            ParticlesWithUnitsConverted(nbody_results[0].as_set(),
                                        convert)[0].position)
        self.assertAlmostRelativeEqual(
            si_results[1].position,
            ParticlesWithUnitsConverted(nbody_results[1], convert).position)
        self.assertAlmostRelativeEqual(si_results[2],
                                       nbody_results[2],
                                       places=10)
        self.assertAlmostRelativeEqual(si_results[3][0],
                                       convert.from_target_to_source(
                                           nbody_results[3][0]),
                                       places=10)
        for in_si, in_nbody in zip(si_results[4], nbody_results[4]):
            self.assertAlmostRelativeEqual(
                in_si, convert.from_target_to_source(in_nbody), places=10)
Beispiel #21
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,
            gpu_id=-1,
            accuracy_parameter=0.1,
            softening_length=-1 | nbody_system.length,
            manage_encounters=1):

    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)

    #print "1"; sys.stdout.flush()

    gpu = 0
    if gpu_worker == 1:
        try:
            gravity = grav(number_of_workers=n_workers,
                           redirection="none",
                           mode="gpu")
            #              debugger='valgrind')
            gpu = 1
        except Exception as ex:
            print '*** GPU worker code not found. Reverting to non-GPU code. ***'
            gpu = 0

    if gpu == 0:
        gravity = grav(number_of_workers=n_workers, redirection="none")
        #              debugger='valgrind')

    #print "2"; sys.stdout.flush()
    gravity.initialize_code()

    #print "3"; sys.stdout.flush()
    gravity.parameters.set_defaults()

    gravity.parameters.gpu_id = gpu_id

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

    #print "4"; sys.stdout.flush()
    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
        if 0:
            scaled_mass = new_salpeter_mass_distribution_nbody(number_of_stars)
            stars.mass = scaled_mass
        stars.radius = 0.0 | nbody_system.length

        print "centering stars"
        stars.move_to_center()
        if 0:
            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()

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

    #print "5"; 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

    #print "6"; sys.stdout.flush()
    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, cpu0, wall0 = 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()

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

        # Ensure that the stars list is consistent with the internal
        # data in the module.

        ls = len(stars)

        # Update the bookkeeping: synchronize stars with the module data.

        try:
            gravity.update_particle_set()
            gravity.particles.synchronize_to(stars)
        except:
            pass

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

        if stopping_condition.is_set():
            star1 = stopping_condition.particles(0)[0]
            star2 = stopping_condition.particles(1)[0]
            print '\nstopping condition set at time', \
                gravity.get_time().number,'for:\n'
            print star1
            print ''
            print star2
            print ''
            raise Exception("no encounter handling")

        if len(stars) != ls:
            if 0:
                print "stars:"
                for s in stars:
                    print " ", s.id.number, s.mass.number, \
          s.x.number, s.y.number, s.z.number
            else:
                print "number of stars =", len(stars)
            sys.stdout.flush()

        print_log('', time, gravity, E0, cpu0, wall0)
        sys.stdout.flush()

    print ''
    gravity.stop()
Beispiel #22
0
def run_hacs(infile = None,
              number_of_stars = 128,
              nmax = 2048,
              end_time = 0.1   | nbody_system.time,
              delta_t = 0.125 | nbody_system.time,
              dt_max  = 0.0625 | nbody_system.time,
              n_ngb   = 16,
              eta_irr = 0.6,
              eta_reg = 0.1,
              softening_length = 0.0 | nbody_system.length):

    if infile != None: print "input file =", infile
    print "end_time =",  end_time.number
    print "nstars= ",    number_of_stars,
    print "nmax= ",      nmax,
    print "delta_t= ",   delta_t.number
    print "dt_max= ",    dt_max.number
    print "n_ngb= ",     n_ngb,
    print "eta_irr= ",   eta_irr
    print "eta_reg= ",   eta_reg
    print "eps2=    ",   softening_length.number**2
    print "\ninitializing the gravity module"
    sys.stdout.flush()

#    gravity = grav(number_of_workers = 1, redirection = "none", mode='cpu')
    gravity = grav(number_of_workers = 1, redirection = "none", mode='cpu')
    gravity.initialize_code()
    
    #-----------------------------------------------------------------

    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.0 | 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.eps2)

        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 
        print len(mass), len(pos), len(vel), len(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
        nmax = 2*len(mass)

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

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

    gravity.parameters.nmax    = nmax;
    gravity.parameters.dtmax   = dt_max;
#    gravity.parameters.n_ngb   = n_ngb;
    gravity.parameters.eta_irr = eta_irr;
    gravity.parameters.eta_reg = eta_reg;
    gravity.parameters.eps2    = softening_length**2
    gravity.commit_parameters();


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

#    stopping_condition.disable()

    while time < end_time:
        if (gravity.get_time() >= time):
          time += delta_t

        gravity.evolve_model(time)


        # Ensure that the stars list is consistent with the internal
        # data in the module.

        ls = len(stars)

    	  # Update the bookkeeping: synchronize stars with the module data.

        # this breaks the code ...
        channel.copy()
  
        # Copy values from the module to the set in memory.
        
        channel.copy_attribute("index_in_code", "id")
    
        # 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.

        if stopping_condition.is_set():
            star1 = stopping_condition.particles(0)[0]
            star2 = stopping_condition.particles(1)[0]
            gravity.synchronize_model()
            print '\nstopping condition set at time', \
                gravity.get_time().number,'for:\n'
            print star1
            print ''
            print star2
            print ''
            gravity.particles.remove_particle(star1)
            gravity.particles.remove_particle(star2)
           
            gravity.recommit_particles();
            
            print 'ls=', len(stars)
            
            gravity.update_particle_set()
            gravity.particles.synchronize_to(stars)
            
            
            print 'ls=', len(stars)
            

        if len(stars) != ls:
           if 0:
                print "stars:"
                for s in stars:
                    print " ", s.id.number, s.mass.number, s.x.number, s.y.number, s.z.number
           else:
             print "number of stars =", len(stars)
           sys.stdout.flush()

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

    print ''
    print_log(gravity.get_time(), gravity, E0)
    sys.stdout.flush()
    gravity.stop()