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 manage_encounter(star1, star2, stars, gravity_stars): # Manage an encounter between star1 and star2. stars is the # python memory data set. gravity_stars points to the gravity # module data. Return value is the energy correction due to # multiples. # Establish child flags for use during the encounter calculation. stars.is_a_child = 0 | units.none parents = stars.select(is_a_parent, ["child1", "child2"]) for s in stars: for p in parents: if p.child1 == s or p.child2 == s: s.is_a_child = 1 | units.none # Currently we don't include neighbors in the integration and the # size limitation on any final multiple is poorly implemented. print '\nin manage_encounter' sys.stdout.flush() # 1. Star1 and star2 reflect the data in the gravity module. Find # the corresponding particles in the local particle set. star1_in_memory = star1.as_particle_in_set(stars) # pointers star2_in_memory = star2.as_particle_in_set(stars) # 1a. Copy the current position and velocity to mememory (need to # create a better call for this, for example: # star1.copy_to(star1_in_memory) star1_in_memory.position = star1.position star1_in_memory.velocity = star1.velocity star2_in_memory.position = star2.position star2_in_memory.velocity = star2.velocity # Basic diagnostics: print_pair_of_stars('**encounter**', star1_in_memory, star2_in_memory) print '' find_nnn(star1_in_memory, star2_in_memory, stars) find_nnn(star2_in_memory, star1_in_memory, stars) # 1b. Calculate the potential of [star1, star2] relative to the # other top-level objects in the stars list (later: just use # neighbors TODO). Start the correction of dEmult by removing # the initial top-level energy of the interacting particles # from it. (Add in the final energy later, on return from # scale_top_level_list.) slist = [star1_in_memory, star2_in_memory] etot = total_energy(slist) print 'initial etot =', etot dEmult = -etot klist = [star1_in_memory, star2_in_memory] phi_external_init = relative_potential(slist, klist, stars) print 'phi_external_init =', phi_external_init # 2. Create a particle set to perform the close encounter # calculation. particles_in_encounter = datamodel.Particles(0) # 3. Add stars to the encounter set, add in components when we # encounter a binary. if not star1_in_memory.child1 is None: openup_tree(star1_in_memory, stars, particles_in_encounter) else: particles_in_encounter.add_particle(star1_in_memory) if not star2_in_memory.child1 is None: openup_tree(star2_in_memory, stars, particles_in_encounter) else: particles_in_encounter.add_particle(star2_in_memory) # particles_in_encounter.id = -1 | units.none # need to make this -1 to # ensure smallN will set the # IDs, or else smallN seems # to fail... TODO # *** Desirable to propagate the IDs into smallN, for internal # *** diagnostic purposes... # print 'particles in smallN encounter:' # print particles_in_encounter.to_string(['x','y','z', # 'vx','vy','vz','mass','id']) print '\nparticles in encounter (flat tree):' for p in particles_in_encounter: print_multiple(p) initial_scale \ = math.sqrt(((star1.position -star2.position).number**2).sum())|nbody_system.length print 'initial_scale =', initial_scale.number sys.stdout.flush() # 4. Run the small-N encounter in the center of mass frame. # Probably desirable to make this a true scattering experiment by # separating star1 and star2 to a larger distance before starting # smallN. TODO total_mass = star1.mass + star2.mass cmpos = (star1.mass * star1.position + star2.mass * star2.position) / total_mass cmvel = (star1.mass * star1.velocity + star2.mass * star2.velocity) / total_mass print 'CM KE =', 0.5 * total_mass.number * ((cmvel.number)**2).sum() for p in particles_in_encounter: p.position -= cmpos p.velocity -= cmvel run_smallN(particles_in_encounter) for p in particles_in_encounter: p.position += cmpos p.velocity += cmvel # print 'after smallN:' # print particles_in_encounter.to_string(['x','y','z', # 'vx','vy','vz', # 'mass', 'id']) # sys.stdout.flush() # 5. Carry out bookkeeping after the encounter and update the # gravity module with the new data. # 5a. Remove star1 and star2 from the gravity module. gravity_stars.remove_particle(star1) gravity_stars.remove_particle(star2) # 5b. Create an object to handle the new binary information. binaries = trees.BinaryTreesOnAParticleSet(particles_in_encounter, "child1", "child2") # 5bb. Compress the top-level nodes before adding them to the # gravity code. Also recompute the external potential and # absorb the tidal error into the top-level nodes of the # encounter list. Fially, add the change in top-level energy # of the interacting subset into dEmult, so E(hacs64) + dEmult # should be conserved. dEmult += scale_top_level_list(binaries, initial_scale, stars, klist, phi_external_init) # 5c. Update the positions and velocities of the stars (leaves) in # the encounter; copy the position and velocity attributes of # all stars updated during the encounter to the stars particle # set in memory. Do not copy child or any other attributes. tmp_channel = particles_in_encounter.new_channel_to(stars) tmp_channel.copy_attributes(['x', 'y', 'z', 'vx', 'vy', 'vz']) # 5d. Add stars not in a binary to the gravity code. stars_not_in_a_multiple = binaries.particles_not_in_a_multiple() stars_not_in_a_multiple_in_stars = \ stars_not_in_a_multiple.get_intersecting_subset_in(stars) if len(stars_not_in_a_multiple_in_stars) > 0: gravity_stars.add_particles(stars_not_in_a_multiple_in_stars) # 5e. Add the inner (CM) nodes (root plus subnodes) to the stars # in memory (the descendant nodes are already part of the # set). for root in binaries.iter_roots(): stars_in_a_multiple = root.get_descendants_subset() # print 'root.get_inner_nodes_subset():' # print root.get_inner_nodes_subset(); sys.stdout.flush() stars.add_particles(root.get_inner_nodes_subset()) # 5f. Add roots of the binaries tree to the gravity code. # Must set radii to reflect multiple structure. TODO for root in binaries.iter_roots(): root_in_stars = root.particle.as_particle_in_set(stars) root_in_stars.id = new_root_index() # print 'root_in_stars:' # print root_in_stars; sys.stdout.flush(); sys.stdout.flush() gravity_stars.add_particle(root_in_stars) # 5g. Store the original position and velocity of the root so that # the subparticle position can be updated later. for root in binaries.iter_roots(): root_in_stars = root.particle.as_particle_in_set(stars) # Save root position and velocity so we can update the # position and velocity of the components when we open up the # binary tree. root_in_stars.original_x = root_in_stars.x root_in_stars.original_y = root_in_stars.y root_in_stars.original_z = root_in_stars.z root_in_stars.original_vx = root_in_stars.vx root_in_stars.original_vy = root_in_stars.vy root_in_stars.original_vz = root_in_stars.vz return dEmult
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_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, 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() # 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 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 test8(self): code = Hermite() particles_in_binary = self.new_binary(0.1 | nbody_system.mass, 0.1 | nbody_system.mass, 0.01 | nbody_system.length, keyoffset=1) particles_in_binary.radius = 0.001 | nbody_system.length binary = datamodel.Particle(key=3) binary.child1 = particles_in_binary[0] binary.child2 = particles_in_binary[1] binary.radius = 0.5 | nbody_system.length binary.mass = 0.2 | nbody_system.mass binary.position = [0.0, 0.0, 0.0] | nbody_system.length binary.velocity = [0.0, 0.0, 0.0] | nbody_system.speed encounter_code = encounters.HandleEncounter( kepler_code=self.new_kepler(), resolve_collision_code=self.new_smalln(), interaction_over_code=None) encounter_code.parameters.hard_binary_factor = 1 encounter_code.small_scale_factor = 1 multiples_code = encounters.Multiples( gravity_code=code, handle_encounter_code=encounter_code) multiples_code.singles_in_binaries.add_particles(particles_in_binary) multiples_code.binaries.add_particle(binary) multiples_code.must_handle_one_encounter_per_stopping_condition = False field_particle = datamodel.Particle(key=4) field_particle.mass = 0.5 | nbody_system.mass field_particle.radius = 0.1 | nbody_system.length field_particle.position = [0.0, 0.2, 0.0] | nbody_system.length field_particle.velocity = [0.0, 0.0, 0.0] | nbody_system.speed multiples_code.singles.add_particle(field_particle) self.assertEquals(len(multiples_code.singles_in_binaries), 2) self.assertEquals(id(multiples_code.binaries[0].child1.particles_set), id(multiples_code.singles_in_binaries)) multiples_code.commit_particles() multiples_code.multiples.radius = 0.5 | nbody_system.length initial_energy = multiples_code.get_total_energy() self.assertEquals(len(multiples_code.multiples), 1) self.assertEquals(len(multiples_code.components_of_multiples), 2) self.assertEquals(len(multiples_code.particles), 2) stopping_condition = multiples_code.stopping_conditions.encounter_detection stopping_condition.enable() singles = datamodel.Particles() singles.add_particles(particles_in_binary) singles.add_particle(field_particle) singles_energy = singles.kinetic_energy() + singles.potential_energy( G=nbody_system.G) self.assertAlmostRelativeEquals(initial_energy, singles_energy, 3) multiples_code.evolve_model(2 | nbody_system.time) final_energy = multiples_code.get_total_energy() self.assertTrue(stopping_condition.is_set()) self.assertAlmostRelativeEquals(initial_energy, final_energy, 7)
def test10(self): code = Hermite() particles_in_binary = self.new_binary(0.1 | nbody_system.mass, 0.1 | nbody_system.mass, 0.01 | nbody_system.length, keyoffset=1) particles_in_binary.radius = 0.001 | nbody_system.length encounter_code = encounters.HandleEncounter( kepler_code=self.new_kepler(), resolve_collision_code=self.new_smalln(), ) encounter_code.parameters.hard_binary_factor = 1 encounter_code.small_scale_factor = 1 others = datamodel.Particles(key=[4, 5, 6]) for i in range(3): others[i].position = [i, 0, 0] | nbody_system.length others[i].velocity = [0, 0, i] | nbody_system.speed others[i].mass = 1 | nbody_system.mass others[i].radius = 0.05 | nbody_system.length multiples_code = encounters.Multiples( gravity_code=code, handle_encounter_code=encounter_code) multiples_code.must_handle_one_encounter_per_stopping_condition = False multiples_code.singles.add_particles(particles_in_binary) multiples_code.singles.add_particles(others) multiples_code.commit_particles() multiples_code.evolve_model(1 | nbody_system.time) self.assertEquals(len(multiples_code.multiples), 1) self.assertEquals(len(multiples_code.components_of_multiples), 2) self.assertEquals(len(multiples_code.singles), 3) self.assertEquals(len(multiples_code.particles), 4) self.assertEquals(len(code.particles), 4) self.assertEquals(id(multiples_code.singles_in_binaries), id(multiples_code.binaries[0].child1.particles_set)) self.assertEquals( id(multiples_code.components_of_multiples), id(multiples_code.multiples[0].components[0].particles_set)) #multiples_code.singles_in_binaries[0].mass = 0.2 | nbody_system.mass print multiples_code.particles.mass self.assertAlmostRelativeEquals(multiples_code.particles[-1].mass, 1.1 | nbody_system.mass) self.assertAlmostRelativeEquals(multiples_code.particles.mass.sum(), 0.1 + 0.1 + 3.0 | nbody_system.mass) multiples_code.update_model() self.assertAlmostRelativeEquals(multiples_code.particles[-1].mass, 1.1 | nbody_system.mass) index = -1 if not code.particles[index].mass > 1.0 | nbody_system.mass: index = -2 self.assertAlmostRelativeEquals(code.particles[index].mass, 1.1 | nbody_system.mass) multiples_code.singles_in_binaries[0].mass += 0.2 | nbody_system.mass multiples_code.update_model() self.assertAlmostRelativeEquals(multiples_code.particles[-1].mass, 1.3 | nbody_system.mass) self.assertAlmostRelativeEquals(code.particles[index].mass, 1.3 | nbody_system.mass)
def new_particle(self, mass): particles = datamodel.Particles(len(mass)) particles.mass = mass self.my_particles.add_particles(particles) return list( range(len(self.my_particles) - len(mass), len(self.my_particles)))
def merge_clusters_with_gas(sfeff=[0.3, 0.3], Nstar=[1000, 1000], totalNgas=40000, t_end=30. | units.Myr, dt_plot=0.05 | units.Myr, Rscale=units.parsec([0.25, 0.25]), tmerge=2.5 | units.Myr, eps_star=0.001 | units.parsec, runid="runtest", feedback_efficiency=0.01, subvirialfac=1.): try: os.mkdir(runid) except: pass print "Nstar, Ngas:", Nstar, totalNgas eps = 0.05 * Rscale.mean() IMF = SalpeterIMF(mass_max=100. | units.MSun) mean_star_mass = IMF.mass_mean() approx_gas_mass = 0. * mean_star_mass for e, N in zip(sfeff, Nstar): approx_gas_mass += (1 - e) * N * mean_star_mass / e mgas = approx_gas_mass / totalNgas print "gas particle mass:", mgas.in_(units.MSun) stars = [] gas = [] total_mass = 0. | units.MSun total_gas_mass = 0. | units.MSun total_star_mass = 0. | units.MSun for e, Ns, r in zip(sfeff, Nstar, Rscale): s, g = generate_cluster_with_gas(IMF, e, Ns, r, mgas, subvirialfac=subvirialfac, t_end=t_end) stars.append(s) gas.append(g) total_mass += s.mass.sum() + g.mass.sum() total_star_mass += s.mass.sum() total_gas_mass += g.mass.sum() print "total mass:", total_mass.in_(units.MSun) print "total star mass:", total_star_mass.in_(units.MSun) print "total gas mass:", total_gas_mass.in_(units.MSun) print "t_end:", t_end Rsep = (constants.G * total_mass * tmerge**2)**(1. / 3) stars[0].x = stars[0].x - Rsep / 2 stars[1].x = stars[1].x + Rsep / 2 gas[0].x = gas[0].x - Rsep / 2 gas[1].x = gas[1].x + Rsep / 2 conv = nbody_system.nbody_to_si(total_mass, Rsep) print "tmerge:", tmerge print "Rsep:", Rsep.in_(units.parsec) allgas = datamodel.Particles(0) allstars = datamodel.Particles(0) allgas.add_particles(gas[0]) allgas.add_particles(gas[1]) allstars.add_particles(stars[0]) allstars.add_particles(stars[1]) allgas.h_smooth = 0. | units.parsec allstars.radius = eps_star mu = 1.4 | units.amu gamma1 = 1.6667 - 1 # print 'min Temp:', (gamma1*min(allgas.u)*(1.4*units.amu)/constants.kB).in_(units.K) print 'min Temp:', (gamma1 * min(allgas.u) * mu / constants.kB).in_( units.K) print max(allgas.u)**0.5 dt = smaller_nbody_power_of_two(dt_plot, conv) dt_star = smaller_nbody_power_of_two(0.001 | units.Myr, conv) #0.001 dt_sph = dt_star dt_fast = dt_star # 8 dt_feedback = dt_fast * 4 # 2 if not dt_star <= dt_fast <= dt_feedback: raise Exception print 'dt_plot:', conv.to_nbody(dt_plot), dt_plot.in_(units.Myr) print 'dt:', conv.to_nbody(dt), dt.in_(units.Myr) print 'dt_feedback:', conv.to_nbody(dt_feedback), dt_feedback.in_( units.Myr) print 'dt_fast:', conv.to_nbody(dt_fast), dt_fast.in_(units.Myr) print 'dt_star:', conv.to_nbody(dt_star), dt_star.in_(units.Myr) print 'dt_sph:', conv.to_nbody(dt_sph), dt_sph.in_(units.Myr) sys = grav_gas_sse( PhiGRAPE, Gadget2, SSEplus, Octgrav, conv, mgas, allstars, allgas, dt_feedback, dt_fast, grav_parameters=(["epsilon_squared", eps_star**2], ["timestep_parameter", 0.001]), # ["timestep", dt_star]), gas_parameters=( ["time_max", 32. | units.Myr], # ["courant", 0.15 | units.none], ["n_smooth", 64 | units.none], # ["artificial_viscosity_alpha",1.| units.none], ["n_smooth_tol", 0.005 | units.none], ## NB # ["max_size_timestep",7500. | units.yr], ## NB ["time_limit_cpu", 3600000 | units.s]), couple_parameters=(["epsilon_squared", eps**2], ["opening_angle", 0.5]), feedback_efficiency=feedback_efficiency, feedback_radius=0.025 * Rscale) nsnap = 0 sys.synchronize_model() t = sys.model_time tout = t.value_in(units.Myr) ek = sys.kinetic_energy.value_in(1.e51 * units.erg) ep = sys.potential_energy.value_in(1.e51 * units.erg) eth = sys.thermal_energy.value_in(1.e51 * units.erg) ef = sys.feedback_energy.value_in(1.e51 * units.erg) print 't Ek Ep Eth Ef:', tout, ek, ep, eth, ef, ek + ep + eth - ef sys.dump_system_state(runid + "/dump-%6.6i" % nsnap) print 'max smooth:', max(sys.sph.gas_particles.radius).in_(units.parsec) print 'mean smooth:', sys.sph.gas_particles.radius.mean().in_(units.parsec) print 'min smooth:', min(sys.sph.gas_particles.radius).in_(units.parsec) print 'eps:', eps.in_(units.parsec) print 'feedback radius:', (0.01 * Rscale).in_(units.parsec) while (t < t_end - dt / 2): sys.evolve_model(t + dt) sys.synchronize_model() t = sys.model_time tout = t.value_in(units.Myr) ek = sys.kinetic_energy.value_in(1.e51 * units.erg) ep = sys.potential_energy.value_in(1.e51 * units.erg) eth = sys.thermal_energy.value_in(1.e51 * units.erg) ef = sys.feedback_energy.value_in(1.e51 * units.erg) print 't Ek Ep Eth Ef:', tout, ek, ep, eth, ef, ek + ep + eth - ef nsnap += 1 sys.dump_system_state(runid + "/dump-%6.6i" % nsnap)
def _run_collision_with_integrator(self, inttype_parameter): particles = datamodel.Particles(7) particles.mass = 0.001 | nbody_system.mass particles.radius = 0.01 | nbody_system.length particles.x = [-101.0, -100.0, -0.5, 0.5, 100.0, 101.0, 104.0 ] | nbody_system.length particles.y = 0 | nbody_system.length particles.z = 0 | nbody_system.length particles.velocity = [[2, 0, 0], [-2, 0, 0] ] * 3 + [[-4, 0, 0]] | nbody_system.speed instance = Huayno() instance.parameters.inttype_parameter = inttype_parameter instance.particles.add_particles(particles) collisions = instance.stopping_conditions.collision_detection collisions.enable() instance.evolve_model(1.0 | nbody_system.time) self.assertTrue(collisions.is_set()) self.assertTrue(instance.model_time < 0.5 | nbody_system.time) self.assertEquals(len(collisions.particles(0)), 3) self.assertEquals(len(collisions.particles(1)), 3) self.assertEquals( len(particles - collisions.particles(0) - collisions.particles(1)), 1) self.assertEquals( abs(collisions.particles(0).x - collisions.particles(1).x) <= (collisions.particles(0).radius + collisions.particles(1).radius), [True, True, True]) sticky_merged = datamodel.Particles(len(collisions.particles(0))) sticky_merged.mass = collisions.particles( 0).mass + collisions.particles(1).mass sticky_merged.radius = collisions.particles(0).radius for p1, p2, merged in zip(collisions.particles(0), collisions.particles(1), sticky_merged): merged.position = (p1 + p2).center_of_mass() merged.velocity = (p1 + p2).center_of_mass_velocity() print instance.model_time print instance.particles instance.particles.remove_particles( collisions.particles(0) + collisions.particles(1)) instance.particles.add_particles(sticky_merged) instance.evolve_model(1.0 | nbody_system.time) print print instance.model_time print instance.particles self.assertTrue(collisions.is_set()) self.assertTrue(instance.model_time < 1.0 | nbody_system.time) self.assertEquals(len(collisions.particles(0)), 1) self.assertEquals(len(collisions.particles(1)), 1) self.assertEquals( len(instance.particles - collisions.particles(0) - collisions.particles(1)), 2) self.assertEquals( abs(collisions.particles(0).x - collisions.particles(1).x) <= (collisions.particles(0).radius + collisions.particles(1).radius), [True]) instance.stop()
def add_planets(stars, number_of_planets, converter, cluster_name, Neptune=True, Double=False, write_file=True): """ This is a function created to add planets to a set of stars in a cluster. The Function Returns: Nothing. It appends the planets to provided dataset. """ # Creates the empty AMUSE Particle Set for the Planets planets = datamodel.Particles(number_of_planets) # Creates the List of Star Indices that will Host Plantes number_of_stars = len(stars) select_stars_indices = random.sample(xrange(0, number_of_stars), number_of_planets) i = 0 # Creates One Jupiter-Like Planet Around the Each Star in the Subset if Neptune: for planet in planets: j = select_stars_indices[i] planet.id = 5000000 + i + 1 planet.host_star = stars[j].id planet.mass = converter.to_nbody(0.05 | units.MJupiter) planet.radius = planet.mass.number | nbody_system.length initial_orbit_radius = converter.to_nbody(30 | units.AU) planet.x = stars[j].x + initial_orbit_radius planet.y = stars[j].y planet.z = stars[j].z initial_orbit_speed = np.sqrt(stars[j].mass*nbody_system.G/initial_orbit_radius) planet.vx = stars[j].vx planet.vy = stars[j].vy + initial_orbit_speed planet.vz = stars[j].vz eulerAngle(planet, stars[j]) i+=1 stars.add_particles(planets) # Creates two Jupiters on Opposite Sides of Each Star in the Subset if Double: for planet in planets[:number_of_planets/2]: j = select_stars_indices[i] planet.id = 5000000 + i + 1 planet.host_star = stars[j].id planet.mass = converter.to_nbody(1.0 | units.MJupiter) planet.radius = planet.mass.number | nbody_system.length initial_orbit_radius = converter.to_nbody(2 | units.AU) planet.x = stars[j].x + initial_orbit_radius planet.y = stars[j].y planet.z = stars[j].z initial_orbit_speed = np.sqrt(stars[j].mass*nbody_system.G/initial_orbit_radius) planet.vx = stars[j].vx planet.vy = stars[j].vy + initial_orbit_speed planet.vz = stars[j].vz i+=1 i = 0 for planet in planets[number_of_planets/2:]: j = select_stars_indices[i] planet.id = 5000000 + number_of_planets/2+i + 1 planet.host_star = stars[j].id planet.mass = converter.to_nbody(0.053953 | units.MJupiter) planet.radius = planet.mass.number | nbody_system.length initial_orbit_radius = converter.to_nbody(30 | units.AU) planet.x = stars[j].x - initial_orbit_radius planet.y = stars[j].y planet.z = stars[j].z initial_orbit_speed = np.sqrt(stars[j].mass*nbody_system.G/initial_orbit_radius) planet.vx = stars[j].vx planet.vy = stars[j].vy - initial_orbit_speed planet.vz = stars[j].vz i+=1 stars.add_particles(planets) print planets
def test17(self): print "Testing BHTree collision_detection" particles = datamodel.Particles(7) particles.mass = 0.001 | nbody_system.mass particles.radius = 0.01 | nbody_system.length particles.x = [-101.0, -100.0, -0.5, 0.5, 100.0, 101.0, 104.0 ] | nbody_system.length particles.y = 0 | nbody_system.length particles.z = 0 | nbody_system.length particles.velocity = [[2, 0, 0], [-2, 0, 0] ] * 3 + [[-4, 0, 0]] | nbody_system.speed instance = BHTree(redirection='none') instance.initialize_code() instance.parameters.set_defaults() # Uncommenting any of the following two lines will suppress collision detection #~ instance.parameters.use_self_gravity = 0 #~ instance.parameters.epsilon_squared = 0.0 | nbody_system.length**2 instance.parameters.opening_angle = 0.1 instance.particles.add_particles(particles) collisions = instance.stopping_conditions.collision_detection collisions.enable() instance.evolve_model(1.0 | nbody_system.time) self.assertTrue(collisions.is_set()) self.assertTrue(instance.model_time < 0.5 | nbody_system.time) self.assertEquals(len(collisions.particles(0)), 3) self.assertEquals(len(collisions.particles(1)), 3) self.assertEquals( len(particles - collisions.particles(0) - collisions.particles(1)), 1) self.assertEquals( abs(collisions.particles(0).x - collisions.particles(1).x) < (collisions.particles(0).radius + collisions.particles(1).radius), [True, True, True]) sticky_merged = datamodel.Particles(len(collisions.particles(0))) sticky_merged.mass = collisions.particles( 0).mass + collisions.particles(1).mass sticky_merged.radius = collisions.particles(0).radius for p1, p2, merged in zip(collisions.particles(0), collisions.particles(1), sticky_merged): merged.position = (p1 + p2).center_of_mass() merged.velocity = (p1 + p2).center_of_mass_velocity() print instance.model_time print instance.particles instance.particles.remove_particles( collisions.particles(0) + collisions.particles(1)) instance.particles.add_particles(sticky_merged) instance.evolve_model(1.0 | nbody_system.time) print print instance.model_time print instance.particles self.assertTrue(collisions.is_set()) self.assertTrue(instance.model_time < 1.0 | nbody_system.time) self.assertEquals(len(collisions.particles(0)), 1) self.assertEquals(len(collisions.particles(1)), 1) self.assertEquals( len(instance.particles - collisions.particles(0) - collisions.particles(1)), 2) self.assertEquals( abs(collisions.particles(0).x - collisions.particles(1).x) < (collisions.particles(0).radius + collisions.particles(1).radius), [True]) instance.stop()
def scatter32(init, kep, gravity, treecheck, gamma = 1.e-6, delta_t = 0 | nbody_system.time, t_end = 1.e4 | nbody_system.time): # Kepler manages the two-body dynamics. # Gravity manages the N-body integration. # Treecheck determines the structure of the 3-body system. # Treecheck = gravity is OK. t1 = clock() # <----------------- t1 ----------------- # Create the 3-body system; time = 0 at outer peri. #time, id, mass, pos, vel = make_triple(init, kep, gamma) time, id, mass, pos, vel = make_triple2(init, kep, gamma) stars = datamodel.Particles(3) stars.id = id stars.mass = mass stars.position = pos stars.velocity = vel stars.radius = 0. | nbody_system.length #print stars print("adding particles") sys.stdout.flush() gravity.set_time(time) gravity.particles.add_particles(stars) #print "committing particles" #gravity.commit_particles() sys.stdout.flush() # Channel to copy values from the codes to the set in memory. channel = gravity.particles.new_channel_to(stars) if treecheck != gravity: channel2 = treecheck.particles.new_channel_to(stars) else: channel2 = channel # Don't have a proper unperturbed termination criterion in smallN. # For now, insist that the final time exceed minus the initial # time (recall that outer peri is at t = 0). t_crit = -time if delta_t.number <= 0.0: delta_t = 2*t_crit # for efficiency print("evolving triple to completion in steps of", delta_t.number) sys.stdout.flush() t2 = clock() # <----------------- t2 ----------------- dt_init = t2 - t1 dt_evolve = 0.0 dt_over = 0.0 dt_tree = 0.0 dt_clean = 0.0 final = Final_state() over = 0 while time < t_end and over == 0: tt3 = clock() # <----------------- tt3 ---------------- time += delta_t gravity.evolve_model(time) energy = gravity.get_kinetic_energy()+gravity.get_potential_energy() print("time =", time.number, "energy =", energy.number) tt4 = clock() # <----------------- tt4 ---------------- if time > t_crit: # Check to see if the interaction is over. # Update the local stars data from the module. # Should still be a flat tree, even for SmallN. ttt5 = clock() # <---------------- ttt5 ---------------- if treecheck != gravity: channel.copy() channel.copy_attribute("index_in_code", "id") # Send the data to the treecheck module and test if the # interaction is over. treecheck.particles.add_particles(stars) treecheck.commit_particles() over = treecheck.is_over() ttt6 = clock() # <---------------- ttt6 ---------------- if over: #print '\nscatter32: interaction is over' # The rest of the work is done by treecheck. Note # that we are assuming that the outcomes of gravity # and treecheck are qualitatively similar... treecheck.update_particle_tree() # builds an internal tree # in the SmallN case treecheck.update_particle_set() # updates local bookkeeping treecheck.particles.synchronize_to(stars) channel2.copy() channel2.copy_attribute("index_in_code", "id") # Determine the final state. final = get_final_state(stars, kep) final.time = time.number ttt7 = clock() # <---------------- ttt7 ---------------- # Clean up treecheck for the next use. #treecheck.particles.remove_particles(treecheck.particles) treecheck.reset() ttt8 = clock() # <---------------- ttt8 ---------------- dt_over += ttt6 - ttt5 dt_tree += ttt7 - ttt6 dt_clean += ttt8 - ttt7 dt_evolve += tt4 - tt3 if not over: #print '\nscatter32: interaction is not over' final.is_over = 0 final.mbinary = -1.0 final.semimajoraxis = -1.0 final.eccentricity = -1.0 final.escaper = -1 final.mescaper = -1.0 final.separation = -1.0 final.v_rel = -1.0 # Clean up internal data for recycling. # Reset children so that the garbage collection can do its work. stars.child1 = None stars.child2 = None gravity.reset() return final,numpy.array([dt_init, dt_evolve, dt_over, dt_tree, dt_clean])
def new_sets_from_arrays(self): offset = 0 ids_per_set = [] for x in self.header_struct.Npart: ids_per_set.append(self.ids[offset:offset + x]) offset += x if self.ids_are_keys: sets = [datamodel.Particles(len(x), keys=x) for x in ids_per_set] else: sets = [datamodel.Particles(len(x)) for x in ids_per_set] for set, x in zip(sets, ids_per_set): if len(set) > 0: set.id = x offset = 0 for x in sets: length = len(x) if length == 0: continue x.position = nbody_system.length.new_quantity( self.positions[offset:offset + length]) x.velocity = nbody_system.speed.new_quantity( self.velocities[offset:offset + length]) if self.convert_gadget_w_to_velocity: x.velocity *= numpy.sqrt(1.0 + self.header_struct.Redshift) if not self.pot is None: x.potential_energy = nbody_system.energy.new_quantity( self.pot[offset:offset + length]) if not self.acc is None: x.acceleration = nbody_system.acceleration.new_quantity( self.acc[offset:offset + length]) if not self.dt is None: x.timestep = nbody_system.time.new_quantity( self.dt[offset:offset + length]) offset += length offset = 0 for x, mass in zip(sets, self.header_struct.Massarr): length = len(x) if length == 0: continue if mass == 0.0: x.mass = nbody_system.mass.new_quantity( self.masses[offset:offset + length]) offset += length else: x.mass = nbody_system.mass.new_quantity(mass) if self.number_of_gas_particles > 0: gas_set = sets[self.GAS] unit = (nbody_system.length / nbody_system.time)**2 gas_set.u = unit.new_quantity(self.u) unit = nbody_system.mass / nbody_system.length**3 if not self.density is None: gas_set.rho = unit.new_quantity(self.density) if not self.hsml is None: gas_set.h_smooth = nbody_system.length.new_quantity(self.hsml) return sets
def scatter3(init, kep, gravity, gamma=1.e-6, delta_t=0 | nbody_system.time, t_end=1.e4 | nbody_system.time): t1 = clock() # <----------------- t1 ----------------- # Create the 3-body system; time = 0 at outer periastron. #time, id, mass, pos, vel = make_triple(init, kep, gamma) time, id, mass, pos, vel = make_triple2(init, kep, gamma) stars = datamodel.Particles(3) stars.id = id stars.mass = mass stars.position = pos stars.velocity = vel stars.radius = 0. | nbody_system.length #print stars print("adding particles") sys.stdout.flush() gravity.set_time(time) gravity.particles.add_particles(stars) #print "committing particles" #gravity.commit_particles() sys.stdout.flush() # Channel to copy values from the code to the set in memory. channel = gravity.particles.new_channel_to(stars) # Don't have a proper unperturbed termination criterion in smallN. # For now, insist that the final time exceed minus the initial # time (recall that outer peri is at t = 0). t_crit = -time if delta_t.number <= 0.0: delta_t = 2 * t_crit # for efficiency print("evolving triple to completion in steps of", delta_t.number) sys.stdout.flush() t2 = clock() # <----------------- t2 ----------------- dt_init = t2 - t1 dt_evolve = 0.0 dt_over = 0.0 dt_tree = 0.0 final = Final_state() over = 0 while time < t_end and over == 0: tt3 = clock() # <----------------- tt3 ---------------- time += delta_t gravity.evolve_model(time) energy = gravity.get_kinetic_energy() + gravity.get_potential_energy() print("time =", time.number, "energy =", energy.number) tt4 = clock() # <----------------- tt4 ---------------- if time > t_crit: ttt5 = clock() # <---------------- ttt5 ---------------- over = gravity.is_over() ttt6 = clock() # <---------------- ttt6 ---------------- if over: #print '\nscatter3: interaction is over' gravity.update_particle_tree() gravity.update_particle_set() gravity.particles.synchronize_to(stars) channel.copy() channel.copy_attribute("index_in_code", "id") # Determine the final state. final = get_final_state(stars, kep) final.time = time.number ttt7 = clock() # <---------------- ttt7 ---------------- dt_over += ttt6 - ttt5 dt_tree += ttt7 - ttt6 dt_evolve += tt4 - tt3 if not over: #print '\nscatter3: interaction is not over' final.is_over = 0 final.mbinary = -1.0 final.semimajoraxis = -1.0 final.eccentricity = -1.0 final.escaper = -1 final.mescaper = -1.0 final.separation = -1.0 final.v_rel = -1.0 # Clean up internal data for recycling. # Reset children so that the garbage collection can do its work. stars.child1 = None stars.child2 = None gravity.reset() return final, numpy.array([dt_init, dt_evolve, dt_over, dt_tree])
from amuse.units import units from amuse.units import nbody_system from amuse.units.quantities import VectorQuantity from amuse.plot import (plot, native_plot) def simulate_massloss(time): return units.MSun(0.5 * (1.0 + 1.0 / (1.0 + numpy.exp( (time.value_in(time.unit) - 70.0) / 15.)))) if __name__ == "__main__": convert_nbody = nbody_system.nbody_to_si(1.0 | units.MSun, 1.0 | units.AU) particles = datamodel.Particles(2) sun = particles[0] sun.mass = 1.0 | units.MSun sun.position = [0.0, 0.0, 0.0] | units.AU sun.velocity = [0.0, 0.0, 0.0] | units.AU / units.yr sun.radius = 1.0 | units.RSun earth = particles[1] earth.mass = 5.9736e24 | units.kg earth.radius = 6371.0 | units.km earth.position = [0.0, 1.0, 0.0] | units.AU earth.velocity = [2.0 * numpy.pi, -0.0001, 0.0] | units.AU / units.yr instance = Hermite(convert_nbody) instance.particles.add_particles(particles)
def test7(self): converter = nbody_system.nbody_to_si(units.MSun, units.parsec) code = Hermite(converter) stars = datamodel.Particles(keys=(1, 2)) stars.mass = converter.to_si(1 | nbody_system.mass) stars.position = converter.to_si([ [0, 0, 0], [1.1, 0, 0], ] | nbody_system.length) stars.velocity = converter.to_si([ [0, 0, 0], [-0.5, 1.5, 0], ] | nbody_system.speed) stars.radius = converter.to_si(0.55 | nbody_system.length) encounter_code = encounters.HandleEncounter( kepler_code=self.new_kepler_si(), resolve_collision_code=self.new_smalln_si(), interaction_over_code=None, G=constants.G) encounter_code.small_scale_factor = 1.0 encounter_code.parameters.hard_binary_factor = 1 multiples_code = encounters.Multiples( gravity_code=code, handle_encounter_code=encounter_code, G=constants.G) multiples_code.must_handle_one_encounter_per_stopping_condition = False multiples_code.singles.add_particles(stars) multiples_code.commit_particles() stopping_condition = multiples_code.stopping_conditions.encounter_detection stopping_condition.enable() end_time = converter.to_si(3.0 | nbody_system.time) print end_time.as_quantity_in(units.Myr) multiples_code.evolve_model(end_time) self.assertTrue(stopping_condition.is_set()) print multiples_code.model_time.as_quantity_in(units.Myr) #self.assertAlmostRelativeEquals(multiples_code.model_time , 5.96955 | units.Myr, 4) self.assertEquals(len(stopping_condition.particles(0)), 1) model = stopping_condition.particles(0)[0] self.assertEquals(len(model.particles_before_encounter), 2) self.assertEquals(len(model.particles_after_encounter), 2) before = model.particles_before_encounter after = model.particles_after_encounter self.assertAlmostRelativeEquals(before.center_of_mass(), after.center_of_mass(), 7) self.assertAlmostRelativeEquals(before.center_of_mass_velocity(), after.center_of_mass_velocity(), 7) total_energy_before = before.kinetic_energy( ) + before.potential_energy(G=constants.G) total_energy_after = after.kinetic_energy() + after.potential_energy( G=constants.G) self.assertAlmostRelativeEquals(total_energy_before, total_energy_after, 7)
def test9(self): x = datamodel.Particles(2) x.mass = [1.0, 2.0] | units.kg self.assertRaises(AmuseException, io.write_set_to_file, x, "test_unit.bogus", "bogus", expected_message = "You tried to load or save a file with fileformat 'bogus'" ", but this format is not in the supported formats list")
def test9(self): code = Hermite() particles_in_binary = self.new_binary(0.1 | nbody_system.mass, 0.1 | nbody_system.mass, 0.01 | nbody_system.length, keyoffset=1) particles_in_binary.radius = 0.001 | nbody_system.length binary = datamodel.Particle(key=3) binary.child1 = particles_in_binary[0] binary.child2 = particles_in_binary[1] binary.radius = 0.5 | nbody_system.length binary.mass = 0.2 | nbody_system.mass encounter_code = encounters.HandleEncounter( kepler_code=self.new_kepler(), resolve_collision_code=self.new_smalln(), ) others = datamodel.Particles(key=[4, 5, 6]) for i in range(3): others[i].position = [i, 0, 0] | nbody_system.length others[i].velocity = [0, 0, i] | nbody_system.speed others[i].mass = 1 | nbody_system.mass others[i].radius = 0 | nbody_system.length multiples_code = encounters.Multiples( gravity_code=code, handle_encounter_code=encounter_code) multiples_code.singles_in_binaries.add_particles(particles_in_binary) multiples_code.binaries.add_particle(binary) multiples_code.singles.add_particles(others) multiples_code.commit_particles() self.assertEquals(len(multiples_code.multiples), 1) self.assertEquals(len(multiples_code.components_of_multiples), 2) self.assertEquals(len(multiples_code.singles), 3) self.assertEquals(len(multiples_code.particles), 4) self.assertEquals(len(code.particles), 4) self.assertAlmostRelativeEquals(multiples_code.particles[-1].mass, 0.2 | nbody_system.mass) self.assertAlmostRelativeEquals(code.particles[-1].mass, 0.2 | nbody_system.mass) self.assertAlmostRelativeEquals(code.particles[-1].position, [0, 0, 0] | nbody_system.length, 6) self.assertAlmostRelativeEquals(code.particles[-1].velocity, [0, 0, 0] | nbody_system.speed, 6) multiples_code.update_model() self.assertAlmostRelativeEquals(multiples_code.particles[-1].mass, 0.2 | nbody_system.mass) self.assertAlmostRelativeEquals(code.particles[-1].mass, 0.2 | nbody_system.mass) self.assertAlmostRelativeEquals(code.particles[-1].position, [0, 0, 0] | nbody_system.length, 6) self.assertAlmostRelativeEquals(code.particles[-1].velocity, [0, 0, 0] | nbody_system.speed, 6) multiples_code.singles_in_binaries[0].mass = 0.2 | nbody_system.mass multiples_code.update_model() print code.particles.mass self.assertAlmostRelativeEquals(multiples_code.particles[-1].mass, 0.3 | nbody_system.mass) self.assertAlmostRelativeEquals(code.particles[-1].mass, 0.3 | nbody_system.mass) print code.particles[-1].position print code.particles[-1].velocity self.assertAlmostRelativeEquals(code.particles[-1].position, [0.00166666666667, 0, 0] | nbody_system.length, 6) self.assertAlmostRelativeEquals(code.particles[-1].velocity, [0, 0.7453559925, 0] | nbody_system.speed, 6)
def new_set(self, number_of_items, keys=[]): if len(keys) > 0: return datamodel.Particles(number_of_items, keys=keys) else: return datamodel.Particles(number_of_items)
def test16(self): code = Hermite() n = 10 singles = datamodel.Particles(keys=range(1, n + 1)) singles.mass = 1 | nbody_system.mass for x in range(n): singles[x].position = [x * x, 0, 0] | nbody_system.length singles.velocity = [0, 0, 0] | nbody_system.speed singles.radius = 0.5 | nbody_system.length multiples_code = encounters.Multiples( gravity_code=code, handle_encounter_code=encounters.StickyHandleEncounter()) multiples_code.singles.add_particles(singles) multiples_code.commit_particles() multiples_code.evolve_model(1 | nbody_system.time) print len(multiples_code.multiples) self.assertEquals(len(multiples_code.multiples), 1) self.assertEquals(len(multiples_code.particles), 9) self.assertEquals(len(multiples_code.singles), 8) self.assertEquals(len(multiples_code.binaries), 1) self.assertEquals(len(multiples_code.singles_in_binaries), 2) self.assertEquals( id(multiples_code.components_of_multiples), id(multiples_code.multiples[0].components[0].particles_set)) print multiples_code.multiples[0].components io.write_set_to_file( (multiples_code.singles, multiples_code.singles_in_binaries, multiples_code.binaries, multiples_code.components_of_multiples, multiples_code.multiples), "multiples.hdf5", "hdf5", version="2.0", names=("singles", "singles_in_binaries", "binaries", "components_of_multiples", "multiples")) multiples_code_loaded = encounters.Multiples( gravity_code=Hermite(), handle_encounter_code=encounters.StickyHandleEncounter()) (singles, singles_in_binaries, binaries, components_of_multiples, multiples) = io.read_set_from_file( "multiples.hdf5", "hdf5", version="2.0", names=("singles", "singles_in_binaries", "binaries", "components_of_multiples", "multiples")) self.assertEquals(len(multiples), 1) self.assertEquals(len(singles), 8) self.assertEquals(len(binaries), 1) self.assertEquals(len(singles_in_binaries), 2) #self.assertEquals(id(components_of_multiples), id(multiples[0].components[0].particles_set)) multiples_code_loaded.singles.add_particles(singles) multiples_code_loaded.singles_in_binaries.add_particles( singles_in_binaries) multiples_code_loaded.binaries.add_particles(binaries) multiples_code_loaded.components_of_multiples.add_particles( components_of_multiples) multiples_code_loaded.multiples.add_particles(multiples) multiples_code_loaded.commit_particles() self.assertEquals(len(multiples_code_loaded.multiples), 1) self.assertEquals(len(multiples_code_loaded.particles), 9) self.assertEquals(len(multiples_code_loaded.singles), 8) self.assertEquals(len(multiples_code_loaded.binaries), 1) self.assertEquals(len(multiples_code_loaded.singles_in_binaries), 2) #self.assertEquals(id(multiples_code_loaded.components_of_multiples), id(multiples_code_loaded.multiples[0].components[0].particles_set)) multiples_code.evolve_model(4 | nbody_system.time) # need to use 3 here as the model_time is reset when doing a restart and we dit not set it after creating Hermite multiples_code_loaded.evolve_model(3.0 | nbody_system.time) print len(multiples_code.multiples), multiples_code.particles print multiples_code.particles.position - multiples_code_loaded.particles.position self.assertAlmostRelativeEquals( multiples_code.particles.position - multiples_code_loaded.particles.position, [0, 0, 0] | nbody_system.length) for code in [multiples_code, multiples_code_loaded]: self.assertEquals(len(code.multiples), 1) self.assertEquals(len(code.particles), 8) self.assertEquals(len(code.singles), 7) self.assertEquals(len(code.binaries), 1) self.assertEquals(len(code.singles_in_binaries), 2) self.assertEquals(len(code.components_of_multiples), 3) self.assertEquals( id(code.components_of_multiples), id(code.multiples[0].components[0].particles_set))
def cleanup_code(self): self.particles = datamodel.Particles()