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