def __init__(self, name, Mtot=(1e15 | units.MSun), Rvir=(500 | units.kpc)): self.name = name self.converter = nbody_system.nbody_to_si(Mtot, Rvir) self.number_of_dm_particles = 1e2 self.number_of_gas_particles = 1e3 # Set up numerical smoothing fractions self.dm_smoothing_fraction = 0.001 self.gas_smoothing_fraction = 0.05 self.dm_epsilon = self.dm_smoothing_fraction * Rvir self.gas_epsilon = self.gas_smoothing_fraction * Rvir # Setup up gas and dark matter fractions and gas/dm mass self.gas_fraction = 0.1 self.dm_fraction = 1.0 - self.gas_fraction self.dm_mass = self.dm_fraction * Mtot self.gas_mass = self.gas_fraction * Mtot # Set up dark matter particles # TODO: probably not use Plummer sphere self.dm = new_plummer_model(self.number_of_dm_particles, convert_nbody=self.converter) self.dm.radius = self.dm_epsilon self.dm.mass = (1.0 / self.number_of_dm_particles) * self.dm_mass self.dm.move_to_center() # Set up virialized gas sphere of N gas particles, Plummer sphere # TODO: probably not use Plummer sphere self.gas = new_plummer_gas_model(self.number_of_gas_particles, convert_nbody=self.converter) self.gas.h_smooth = self.gas_epsilon self.gas.move_to_center() self.gas.mass = (1.0 / self.number_of_gas_particles) * self.gas_mass print "Created ", str(self)
def main(N, Lstar, boxsize, rho, t_end): source = Particle() source.position = (0, 0, 0) | units.parsec source.flux = Lstar / (20. | units.eV) source.rho = rho source.xion = 0.0 source.u = (9. | units.kms)**2 converter = nbody_system.nbody_to_si(1 | units.MSun, 3 | units.parsec) ism = new_plummer_gas_model(N, converter) ism.rho = rho ism.flux = 0. | units.s**-1 ism.xion = source.xion ism = ism.select(lambda r: r.length() < 0.5 * boxsize, ["position"]) radiative = SimpleX() radiative.parameters.box_size = boxsize radiative.parameters.timestep = 100 | units.yr radiative.particles.add_particle(source) radiative.particles.add_particles(ism) radiative.evolve_model(t_end) print "min ionization:", radiative.particles.xion.min() print "average ionization:", radiative.particles.xion.mean() print "max ionization:", radiative.particles.xion.max() plot_ionization_fraction(radiative.particles.position, radiative.particles.xion) radiative.stop()
def cloud_init(Ngas, Mgas, Rgas): '''Initialises the cloud''' converter = nbody_system.nbody_to_si(Mgas, Rgas) #cloud = molecular_cloud(targetN=Ngas, convert_nbody=converter,\ # base_grid=body_centered_grid_unit_cube).result cloud = new_plummer_gas_model(Ngas, convert_nbody=converter) return cloud, converter
def test_gas_init(): "Test if the gas class works" numpy.random.seed(123) number_of_gas = 1000 gas = new_plummer_gas_model(number_of_gas) masses = gas.mass cloud = GasCode(gas) assert len(cloud.particles) == number_of_gas assert cloud.particles.mass.sum() == masses.sum() cloud.stop()
def plummer_model_B(nbody, N, Mcloud, Rcloud, parameters=[]): np.random.seed(424) converter = nbody_system.nbody_to_si(Mcloud, Rcloud) bodies = new_plummer_gas_model(N, convert_nbody=converter) code = nbody(converter) for name, value in parameters: setattr(code.parameters, name, value) code.particles.add_particles(bodies) return code
def test5(self): print("Test 5: test new_plummer_gas_model with do_scale") gas = new_plummer_gas_model(100, do_scale = True) self.assertEqual(len(gas), 100) self.assertAlmostEqual(gas.kinetic_energy(), 0.00 | nbody_system.energy) self.assertAlmostEqual(gas.thermal_energy(), 0.25 | nbody_system.energy) self.assertAlmostEqual(gas.potential_energy(G=nbody_system.G), -0.50 | nbody_system.energy) self.assertAlmostEqual(gas.center_of_mass(), [0,0,0] | nbody_system.length) self.assertAlmostEqual(gas.center_of_mass_velocity(), [0,0,0] | nbody_system.speed) self.assertAlmostEqual(gas.total_mass(), 1.00 | nbody_system.mass) self.assertAlmostEqual(gas.virial_radius(), 1.00 | nbody_system.length)
def test5(self): print "Test 5: test new_plummer_gas_model with do_scale" gas = new_plummer_gas_model(100, do_scale = True) self.assertEqual(len(gas), 100) self.assertAlmostEqual(gas.kinetic_energy(), 0.00 | nbody_system.energy) self.assertAlmostEqual(gas.thermal_energy(), 0.25 | nbody_system.energy) self.assertAlmostEqual(gas.potential_energy(G=nbody_system.G), -0.50 | nbody_system.energy) self.assertAlmostEqual(gas.center_of_mass(), [0,0,0] | nbody_system.length) self.assertAlmostEqual(gas.center_of_mass_velocity(), [0,0,0] | nbody_system.speed) self.assertAlmostEqual(gas.total_mass(), 1.00 | nbody_system.mass) self.assertAlmostEqual(gas.virial_radius(), 1.00 | nbody_system.length)
def cloud_init(Ngas, Mgas, Rgas, use_plummer=True, seed=1): '''Initialises the cloud''' np.random.seed(seed) converter = nbody_system.nbody_to_si(Mgas, Rgas) if use_plummer == True: cloud = new_plummer_gas_model(Ngas, convert_nbody=converter) else: cloud = molecular_cloud(targetN=Ngas, convert_nbody=converter,\ base_grid=body_centered_grid_unit_cube).result return cloud, converter
def generate_ism_initial_conditions(N, boxsize): converter = nbody_system.nbody_to_si(10|units.MSun, 3|units.parsec) ism = new_plummer_gas_model(N, converter) ism.flux = 0. | units.s**-1 ism.xion = 0.0 hydro = Fi(converter) hydro.gas_particles.add_particles(ism) hydro.evolve_model(1|units.hour) hydro.gas_particles.new_channel_to(ism).copy() hydro.stop() ism = ism.select(lambda r: r.length() < 0.5*boxsize,["position"]) print "Max density:", ism.rho.max().in_(units.MSun/units.parsec**3), \ ism.rho.max().in_(units.amu/units.cm**3) return ism
def test4(self): print "Test 4: test new_plummer_gas_model, model properties" numpy.random.seed(345672) gas = new_plummer_gas_model(100) self.assertEqual(len(gas), 100) self.assertAlmostEqual(gas.kinetic_energy(), 0.00 | nbody_system.energy) self.assertIsOfOrder( gas.thermal_energy(), 0.25 | nbody_system.energy) self.assertAlmostEqual(gas.thermal_energy(), 0.238075609078 | nbody_system.energy) self.assertIsOfOrder( gas.potential_energy(G=nbody_system.G), -0.50 | nbody_system.energy) self.assertAlmostEqual(gas.potential_energy(G=nbody_system.G), -0.447052244411 | nbody_system.energy) self.assertAlmostEqual(gas.center_of_mass(), [0,0,0] | nbody_system.length) self.assertAlmostEqual(gas.center_of_mass_velocity(), [0,0,0] | nbody_system.speed) self.assertAlmostEqual(gas.total_mass(), 1.00 | nbody_system.mass) self.assertIsOfOrder(gas.virial_radius(), 1.00 | nbody_system.length) self.assertAlmostEqual(gas.virial_radius(), 1.11843751206 | nbody_system.length)
def test4(self): print("Test 4: test new_plummer_gas_model, model properties") numpy.random.seed(345672) gas = new_plummer_gas_model(100) self.assertEqual(len(gas), 100) self.assertAlmostEqual(gas.kinetic_energy(), 0.00 | nbody_system.energy) self.assertIsOfOrder( gas.thermal_energy(), 0.25 | nbody_system.energy) self.assertAlmostEqual(gas.thermal_energy(), 0.238075609078 | nbody_system.energy) self.assertIsOfOrder( gas.potential_energy(G=nbody_system.G), -0.50 | nbody_system.energy) self.assertAlmostEqual(gas.potential_energy(G=nbody_system.G), -0.447052244411 | nbody_system.energy) self.assertAlmostEqual(gas.center_of_mass(), [0,0,0] | nbody_system.length) self.assertAlmostEqual(gas.center_of_mass_velocity(), [0,0,0] | nbody_system.speed) self.assertAlmostEqual(gas.total_mass(), 1.00 | nbody_system.mass) self.assertIsOfOrder(gas.virial_radius(), 1.00 | nbody_system.length) self.assertAlmostEqual(gas.virial_radius(), 1.11843751206 | nbody_system.length)
def test2(self): print "Test 2: testing user interface, with convert_nbody -> SI units" convert_nbody = nbody_system.nbody_to_si(6 | units.kg, 7 | units.m) gas = new_plummer_gas_model(2, convert_nbody) self.assertEquals(gas[0].mass.value_in(units.kg), 3.0) self.assertEquals(gas[1].mass.value_in(units.kg), 3.0)
def res_increase( gas=None, recalculate_h_density=False, seed=123, make_cutout=False, make_circular_cutout=False, circular_rmax=3000 | units.pc, x_center=None, y_center=None, width=None, res_increase_factor=85, ): numpy.random.seed(seed) if gas is None: if len(sys.argv) > 2: from amuse.io import read_set_from_file filename = sys.argv[1] res_increase_factor = int(sys.argv[2]) gas = read_set_from_file(filename, 'amuse') if hasattr(gas, "itype"): gas = gas[gas.itype == 1] del gas.itype else: from amuse.ic.gasplummer import new_plummer_gas_model converter = nbody_system.nbody_to_si(10000 | units.MSun, 10 | units.pc) filename = "test" gas = new_plummer_gas_model(10000, converter) res_increase_factor = 85 sph = Fi(converter, mode="openmp") gas_in_code = sph.gas_particles.add_particles(gas) gas.h_smooth = gas_in_code.h_smooth gas.density = gas_in_code.density sph.stop() write_set_to_file(gas, "old-%s" % filename, "amuse") print("old gas created") if make_circular_cutout: r2 = gas.x**2 + gas.y**2 cutout = gas[r2 <= circular_rmax**2] gas = cutout converter = nbody_system.nbody_to_si(gas.total_mass(), width) sph = Fi(converter, mode="openmp") gas_in_code = sph.gas_particles.add_particles(gas) gas.h_smooth = gas_in_code.h_smooth gas.density = gas_in_code.density sph.stop() if make_cutout: if (x_center is None or y_center is None or width is None): raise Exception("Need to set x_center, y_center and width!") cutout = gas.sorted_by_attribute("x") cutout = cutout[cutout.x - x_center < width / 2] cutout = cutout[cutout.x - x_center > -width / 2] cutout = cutout.sorted_by_attribute("y") cutout = cutout[cutout.y - y_center < width / 2] cutout = cutout[cutout.y - y_center > -width / 2] gas = cutout converter = nbody_system.nbody_to_si(gas.total_mass(), width) sph = Fi(converter, mode="openmp") gas_in_code = sph.gas_particles.add_particles(gas) gas.h_smooth = gas_in_code.h_smooth gas.density = gas_in_code.density sph.stop() # boundary = test_cutout.h_smooth.max() if res_increase_factor == 1: return gas original_number_of_particles = len(gas) new_number_of_particles = (res_increase_factor * original_number_of_particles) converter = nbody_system.nbody_to_si( gas.total_mass(), 1 | units.kpc, ) new_gas = Particles(new_number_of_particles) # new_gas.h_smooth = gas.h_smooth shells, particles_per_shell, shell_radii = find_shell_struct( res_increase_factor) relative_positions = pos_shift( shell_radii, particles_per_shell, res_increase_factor=res_increase_factor, ) relative_velocities = numpy.zeros( res_increase_factor * 3, dtype=float).reshape(res_increase_factor, 3) | gas.velocity.unit random_samples = 50 number_of_particles = len(gas) starting_index = 0 for r in range(random_samples): print("%i / %i random sample done" % (r, random_samples)) number_of_particles_remaining = len(gas) number_of_particles_in_sample = min( number_of_particles_remaining, int(1 + number_of_particles / random_samples)) gas_sample = gas.random_sample(number_of_particles_in_sample).copy() gas.remove_particles(gas_sample) end_index = (starting_index + number_of_particles_in_sample * res_increase_factor) new_gas_sample = new_gas[starting_index:end_index] psi = 2 * numpy.pi * numpy.random.random() theta = 2 * numpy.pi * numpy.random.random() phi = 2 * numpy.pi * numpy.random.random() relative_positions = rotated(relative_positions, phi, theta, psi) # print(len(gas_sample), len(new_gas_sample)) for i in range(res_increase_factor): new_gas_sample[i::res_increase_factor].mass = (gas_sample.mass / res_increase_factor) new_gas_sample[i::res_increase_factor].x = ( gas_sample.x + relative_positions[i, 0] * gas_sample.h_smooth) new_gas_sample[i::res_increase_factor].y = ( gas_sample.y + relative_positions[i, 1] * gas_sample.h_smooth) new_gas_sample[i::res_increase_factor].z = ( gas_sample.z + relative_positions[i, 2] * gas_sample.h_smooth) new_gas_sample[i::res_increase_factor].vx = ( gas_sample.vx + relative_velocities[i, 0]) new_gas_sample[i::res_increase_factor].vy = ( gas_sample.vy + relative_velocities[i, 1]) new_gas_sample[i::res_increase_factor].vz = ( gas_sample.vz + relative_velocities[i, 2]) new_gas_sample[i::res_increase_factor].density = gas_sample.density new_gas_sample[i::res_increase_factor].u = gas_sample.u starting_index += number_of_particles_in_sample * res_increase_factor new_gas.h_smooth = ((3 * new_gas.mass / (4 * pi * new_gas.density))**(1 / 3)) # sph = Fi(converter, mode="openmp", redirection="none") # new_gas_in_code = sph.gas_particles.add_particles(new_gas) # new_gas.h_smooth = new_gas_in_code.h_smooth # new_gas.density = new_gas_in_code.density # sph.stop() print("particles now have a mass of %s" % (new_gas[0].mass.in_(units.MSun))) return new_gas
def generate_ism_initial_conditions(N, M=10|units.MSun, R=3|units.parsec, boxsize=10|units.parsec, which=1): converter = nbody_system.nbody_to_si(M, R) # Option 0: Plummer model with mass M and virial radius R. # Option 1: Homogeneous sphere with radius R and same central # density as the Plummer model. a = R/1.7 # Plummer parameter rho0 = 3*M/(4*numpy.pi*a**3) # Plummer model central density rhp = 1.3*a # Plummer model half-mass radius print 'a =', a.in_(units.parsec) print 'rhp =', rhp.in_(units.parsec) print 'rho0 =', rho0.in_(units.MSun/units.parsec**3) if which == 0: rmax = boxsize ism = new_plummer_gas_model(N, converter) else: Ru = R rmax = Ru ism = new_uniform_spherical_particle_distribution(N, Ru, 4*numpy.pi*rho0*Ru**3/3, type="random") rhu = Ru/3**0.5 print 'rhu =', rhu.in_(units.parsec) ism.vx = 0.|units.kms ism.vy = 0.|units.kms ism.vz = 0.|units.kms ism.u = (0.075|units.kms)**2 print 'M =', ism.mass.sum().in_(units.MSun) #print 'mean u =', ism.u.sum().in_(units.kms**2)/N #print 'max u =', ism.u.max().in_(units.kms**2) rr = ((ism.position)**2).sum(axis=1).sqrt().value_in(units.parsec) ii = numpy.argsort(rr) print 'rh =', rr[ii[N/2]], 'parsec' ism.flux = 0. | units.s**-1 ism.xion = 0.0 hydro = Fi(converter) hydro.gas_particles.add_particles(ism) hydro.evolve_model(1|units.yr) hydro.gas_particles.new_channel_to(ism).copy() hydro.stop() ''' plot_density(rr, ism.rho.value_in(units.MSun/units.parsec**3), rho0.value_in(units.MSun/units.parsec**3), a.value_in(units.parsec)) ''' #print 'max density =', ism.rho.max().in_(units.MSun/units.parsec**3) rc = a/3. cent = ism.select(lambda r: r.length() < rc, ["position"]) print 'approximate central density =', \ (3*cent.mass.sum()/(4*numpy.pi*rc**3)).in_(units.MSun/units.parsec**3) ism = ism.select(lambda r: r.length() < 0.5*boxsize, ["position"]) #print "max density in box =", \ # ism.rho.max().in_(units.MSun/units.parsec**3), \ # ism.rho.max().in_(units.amu/units.cm**3) if rmax > boxsize/2: rmax = boxsize/2 return ism,rho0,a,M,rmax
def new_gas_cluster(self): particles = gasplummer.new_plummer_gas_model( self.ngas, convert_nbody=self.converter) particles.h_smooth = self.gas_epsilon particles.mass = (1.0 / self.ngas) * self.gas_mass return particles
class TestSinkAccretion(TestWithMPI): converter = nbody_system.nbody_to_si(2 | units.pc, 10000 | units.MSun) gas = new_plummer_gas_model(100000, converter) gas.h_smooth = 0.1 | units.pc gas.u = temperature_to_u(10 | units.K) origin_gas = Particle() origin_gas.x = 0 | units.pc origin_gas.y = 0 | units.pc origin_gas.z = 0 | units.pc origin_gas.vx = 0 | units.kms origin_gas.vy = 0 | units.kms origin_gas.vz = 0 | units.kms origin_gas.mass = gas[0].mass origin_gas.h_smooth = 0.03 | units.pc origin_gas.u = 100 | units.kms**2 def test_forming(self): """ Tests if this cloud indeed forms a sink from origin particle """ result, message = should_a_sink_form( self.origin_gas, self.gas, check_thermal=True, accretion_radius=0.1 | units.pc, ) self.assertEqual([True], result) def test_divergence(self): self.skip("Not yet implemented") def test_smoothing_length_too_large(self): """ Tests if this cloud fails to form a sink from origin particle because its smoothing length is too large """ h_smooth = 0.05 | units.pc origin_gas = self.origin_gas.copy() origin_gas.h_smooth = h_smooth result, message = should_a_sink_form( origin_gas, self.gas, check_thermal=True, accretion_radius=1.99 * h_smooth, ) self.assertEqual([False], result) self.assertEqual(["smoothing length too large"], message) def test_too_hot(self): """ Tests if this cloud fails to form a sink from origin particle because its thermal energy is too high """ gas = self.gas.copy() gas.u = temperature_to_u(20 | units.K) result, message = should_a_sink_form( self.origin_gas, gas, check_thermal=True, accretion_radius=0.1 | units.pc, ) self.assertEqual([False], result) self.assertEqual(["e_th/e_pot > 0.5"], message) def test_expanding(self): """ Tests if this cloud fails to form a sink from origin particle because its kinetic energy is too high """ gas = self.gas.copy() gas.vx = gas.x / (10 | units.kyr) gas.vy = gas.y / (10 | units.kyr) gas.vz = gas.z / (10 | units.kyr) result, message = should_a_sink_form( self.origin_gas, gas, check_thermal=True, accretion_radius=0.1 | units.pc, ) self.assertEqual([False], result) self.assertEqual(["e_tot < 0"], message) def test_rotating(self): """ Tests if this cloud fails to form a sink from origin particle because it is rotating """ gas = self.gas.copy() gas.vx = gas.y / (10 | units.kyr) gas.vy = -gas.x / (10 | units.kyr) result, message = should_a_sink_form( self.origin_gas, gas, check_thermal=True, accretion_radius=0.1 | units.pc, ) self.assertEqual(["e_rot too big"], message) self.assertEqual([False], result)
def new_gas_cluster(self): particles=gasplummer.new_plummer_gas_model(self.ngas,convert_nbody=self.converter) particles.h_smooth= self.gas_epsilon particles.mass = (1.0/self.ngas) * self.gas_mass return particles
def test2(self): print "Test 2: testing user interface, with convert_nbody -> SI units" convert_nbody = nbody_system.nbody_to_si(6|units.kg, 7 | units.m) gas = new_plummer_gas_model(2, convert_nbody) self.assertEquals(gas[0].mass.value_in(units.kg), 3.0) self.assertEquals(gas[1].mass.value_in(units.kg), 3.0)
def test3(self): print "Test 3: testing user interface, without convert_nbody -> nbody units" gas = new_plummer_gas_model(2, None) self.assertEquals(gas[0].mass.value_in(nbody_system.mass), 0.5) self.assertEquals(gas[1].mass.value_in(nbody_system.mass), 0.5)
def run_hydrodynamics(N=100, Mtot=1|units.MSun, Rvir=1|units.RSun, t_end=0.5|units.day, n_steps=10,\ vx = 0 |(units.RSun/units.day),\ vy = 0 |(units.RSun/units.day),\ vz = 0 |(units.RSun/units.day),\ plummer1=None, plummer2=None,\ bodyname = None): """ Runs the hydrodynamics simulation and returns a HydroResults instance. FUNCTION WALKTHROUGH: In the following explanation 'plummer1' and 'plummer2' are assumed to be hdf5 files written by the function write_set_to_file(). Case 1: If 'plummer1' and 'plummer2' are filenames of hdf5 files, then these two plummer spheres will be smashed together. Case 2: If only plummer1 is supplied, then it will evolve plummer1 with t_end timerange and n_steps steps. Case 3: If no plummers spheres are supplied, then it will generate a new plummer sphere using the default/supplied initial conditions. OUTPUT FILES: If 'results_out' is specified, the HydroResult instance is written to file in HDF5 format. This however does not use write_set_to_file() which writes the entire Particles class and its attributes to file at each dt, but uses write_to_hdf5() from the 'support' module which is tailored to writing HydroResults instances to file. This HDF5 contains all necessary data to plot the required plots of the assignment. In addition, the last snapshot of the Particles instance is written to file using write_set_to_file(), the latter file is written to the 'bodies' directory. Only the last snapshot is written to file because the history of a Particle set is not of interest when reloading them to smash plummer spheres. """ converter = nbody_system.nbody_to_si(Mtot, Rvir) fi = Fi(converter) if plummer1 and plummer2: eta_smash = 0.3 |units.day if plummer1 == plummer2: bodies1 = read_set_from_file(plummer1, format='hdf5') bodies2 = bodies1.copy() bodies2.key += 1 else: bodies1 = read_set_from_file(plummer1, format='hdf5') bodies2 = read_set_from_file(plummer2, format='hdf5') bodies1.move_to_center() bodies2.move_to_center() if vx.value_in(vx.unit) == 0 and vy.value_in(vy.unit) == 0 \ and vz.value_in(vz.unit) == 0: bodies1.x += -1 |units.RSun bodies2.x += 1 |units.RSun else: bodies1.x += (-1)*vx*eta_smash bodies2.x += 1*vx*eta_smash bodies1.vx += vx bodies2.vx += (-1)*vx bodies1.vy += vy bodies2.vy += (-1)*vy bodies1.vz += vz bodies2.vz += (-1)*vz bodies1.add_particles(bodies2) bodies = bodies1 elif plummer1 or plummer2: if plummer1: bodies = read_set_from_file(plummer1) else: bodies = read_set_from_file(plummer2) bodies.move_to_center() else: bodies = new_plummer_gas_model(N, convert_nbody=converter) fi.gas_particles.add_particles(bodies) fi_to_framework = fi.gas_particles.new_channel_to(bodies) fi.parameters.self_gravity_flag = True data = {'lagrangianradii':AdaptingVectorQuantity(),\ 'angular_momentum':AdaptingVectorQuantity(),\ 'time':AdaptingVectorQuantity(),\ 'positions':AdaptingVectorQuantity(),\ 'kinetic_energy':AdaptingVectorQuantity(),\ 'potential_energy':AdaptingVectorQuantity(),\ 'total_energy':AdaptingVectorQuantity() } mass_fractions = [0.10, 0.25, 0.50, 0.75] setattr(data['lagrangianradii'], 'mf', mass_fractions) data['radius_initial'], data['densities_initial'] = radial_density(\ fi.particles.x, fi.particles.mass, N=10, dim=1) timerange = numpy.linspace(0, t_end.value_in(t_end.unit),\ n_steps) | t_end.unit data['time'].extend(timerange) fi.parameters.timestep = t_end/(n_steps+1) widget = drawwidget("Evolving") pbar = pb.ProgressBar(widgets=widget, maxval=len(timerange)).start() for i, t in enumerate(timerange): fi.evolve_model(t) data['kinetic_energy'].append(fi.kinetic_energy) data['potential_energy'].append(fi.potential_energy) data['total_energy'].append(fi.total_energy) data['positions'].append(fi.particles.position) data['angular_momentum'].append(fi.gas_particles.\ total_angular_momentum()) data['lagrangianradii'].append(fi.particles.LagrangianRadii(\ unit_converter=converter,\ mf=mass_fractions)[0]) if t == timerange[-1] and bodyname: if os.path.dirname(bodyname) == '': filename = "bodies/"+bodyname fi_to_framework.copy() write_set_to_file(bodies.savepoint(t), filename, "hdf5") pbar.update(i) pbar.finish() data['radius_final'], data['densities_final'] = radial_density(\ fi.particles.x, fi.particles.mass, N=10, dim=1) fi.stop() results = HydroResults(data) return results
def clustergas(sfeff=0.05, Nstar=1000, Ngas=1000, t_end=30. | units.Myr, dt_plot=0.05 | units.Myr, Rscale=0.5 | units.parsec, runid="runtest", feedback_efficiency=0.03, subvirialfac=1., grav_code=PhiGRAPE, gas_code=Gadget2, se_code=SSEplus, grav_couple_code=Octgrav, grav_code_extra=dict(mode='gpu', redirection='none'), gas_code_extra=dict(number_of_workers=3, use_gl=False, redirection='none'), se_code_extra=dict(redirection='none'), grav_couple_code_extra=dict()): try: os.mkdir(runid) except: pass print "Nstar, Ngas:", Nstar, Ngas eps = 0.05 * Rscale eps_star = 0.001 * Rscale star_masses = new_salpeter_mass_distribution(Nstar, mass_max=100. | units.MSun) total_star_mass = star_masses.sum() total_mass = total_star_mass / sfeff print "maxmass:", max(star_masses) print "Tcross", (2.8 * (Rscale**3 / constants.G / total_star_mass)**0.5).in_( units.Myr) print sorted(star_masses)[-10:] # raise Exception conv = nbody_system.nbody_to_si(total_mass, Rscale) star_parts = new_plummer_model(Nstar, convert_nbody=conv) star_parts.mass = star_masses star_parts.radius = eps_star # sub-virialized star_parts.vx = star_parts.vx * subvirialfac star_parts.vy = star_parts.vy * subvirialfac star_parts.vz = star_parts.vz * subvirialfac print "total cluster mass:", total_mass.in_(units.MSun) print "star mass:", total_star_mass.in_(units.MSun) print "gas mass:", (total_mass - total_star_mass).in_(units.MSun) print "t_end:", conv.to_nbody(t_end) gas_parts = new_plummer_gas_model(Ngas, convert_nbody=conv, base_grid=body_centered_grid_unit_cube) gas_parts.h_smooth = 0. | units.parsec gas_parts.mass = gas_parts.mass * (1 - sfeff) print "gas particle mass:", ((total_mass - total_star_mass) / len(gas_parts)).in_(units.MSun) mu = 1.4 | units.amu gamma1 = 1.6667 - 1 # print 'min Temp:', (gamma1*min(gas_parts.u)*(1.4*units.amu)/constants.kB).in_(units.K) print 'min Temp:', (gamma1 * min(gas_parts.u) * mu / constants.kB).in_( units.K) mgas = (total_mass - total_star_mass) / len(gas_parts) print max(gas_parts.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 #original settings # dt_sph=dt_star # dt_fast=dt_star*8 # 8 # dt_feedback=dt_fast*2 # 1 #new, improved, more snapshots (thanks inti) dt_fast = dt / 2 # 8 dt_feedback = dt # 1 feedback_dt = (10. | units.yr, dt_fast) 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) star_parts.move_to_center() gas_parts.move_to_center() sys = grav_gas_sse( grav_code, gas_code, se_code, grav_couple_code, conv, mgas, star_parts, gas_parts, dt_feedback, dt_fast, grav_parameters=(["epsilon_squared", eps_star**2], ["timestep_parameter", 0.1]), # ["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", dt_fast], ## 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, feedback_dt=feedback_dt, grav_code_extra=grav_code_extra, gas_code_extra=gas_code_extra, se_code_extra=se_code_extra, grav_couple_code_extra=grav_couple_code_extra) 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): beginning = time.time() 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) end = time.time() print 'iteration', nsnap, 'took:', (end - beginning), 'seconds'
escapers=self.particles.select_array( lambda x,y,z: (x**2+y**2+z**2 > outofbox**2), ["x","y","z"]) print "***", len(escapers) if len(escapers)>0: self.escapers.add_particles(escapers) self.particles.remove_particles(escapers) # Fi.evolve_model(self,*args, **kargs) self.overridden().evolve_model(*args,**kargs) if __name__=="__main__": Ngas=1000 conv = nbody_system.nbody_to_si(100 | units.MSun, 1 | units.parsec) dt=conv.to_si(1|nbody_system.time)/100 print dt.in_(units.Myr) parts=new_plummer_gas_model(Ngas,convert_nbody=conv) parts.h_smooth=0 | units.parsec outofbox=0.9*10. | units.parsec escapers=parts.select_array( lambda x,y,z: (x**2+y**2+z**2 > outofbox**2), ["x","y","z"]) print "**",len(escapers),outofbox.in_(units.parsec) parts.remove_particles(escapers) print len(parts) sph=BoxedFi(convert_nbody=conv,use_gl=True) sph.parameters.pboxsize=20. | units.parsec sph.parameters.timestep=dt sph.parameters.self_gravity_flag=False sph.gas_particles.add_particles(parts)
def generate_ism_initial_conditions(N, M=10 | units.MSun, R=3 | units.parsec, boxsize=10 | units.parsec, which=1): converter = nbody_system.nbody_to_si(M, R) # Option 0: Plummer model with mass M and virial radius R. # Option 1: Homogeneous sphere with radius R and same central # density as the Plummer model. a = R / 1.7 # Plummer parameter rho0 = 3 * M / (4 * numpy.pi * a**3) # Plummer model central density rhp = 1.3 * a # Plummer model half-mass radius print('a =', a.in_(units.parsec)) print('rhp =', rhp.in_(units.parsec)) print('rho0 =', rho0.in_(units.MSun / units.parsec**3)) if which == 0: rmax = boxsize ism = new_plummer_gas_model(N, converter) else: Ru = R rmax = Ru ism = new_uniform_spherical_particle_distribution(N, Ru, 4 * numpy.pi * rho0 * Ru**3 / 3, type="random") rhu = Ru / 3**0.5 print('rhu =', rhu.in_(units.parsec)) ism.vx = 0. | units.kms ism.vy = 0. | units.kms ism.vz = 0. | units.kms ism.u = (0.075 | units.kms)**2 print('M =', ism.mass.sum().in_(units.MSun)) #print 'mean u =', ism.u.sum().in_(units.kms**2)/N #print 'max u =', ism.u.max().in_(units.kms**2) rr = ((ism.position)**2).sum(axis=1).sqrt().value_in(units.parsec) ii = numpy.argsort(rr) print('rh =', rr[ii[N / 2]], 'parsec') ism.flux = 0. | units.s**-1 ism.xion = 0.0 hydro = Fi(converter) hydro.gas_particles.add_particles(ism) hydro.evolve_model(1 | units.yr) hydro.gas_particles.new_channel_to(ism).copy() hydro.stop() ''' plot_density(rr, ism.rho.value_in(units.MSun/units.parsec**3), rho0.value_in(units.MSun/units.parsec**3), a.value_in(units.parsec)) ''' #print 'max density =', ism.rho.max().in_(units.MSun/units.parsec**3) rc = a / 3. cent = ism.select(lambda r: r.length() < rc, ["position"]) print('approximate central density =', \ (3*cent.mass.sum()/(4*numpy.pi*rc**3)).in_(units.MSun/units.parsec**3)) ism = ism.select(lambda r: r.length() < 0.5 * boxsize, ["position"]) #print "max density in box =", \ # ism.rho.max().in_(units.MSun/units.parsec**3), \ # ism.rho.max().in_(units.amu/units.cm**3) if rmax > boxsize / 2: rmax = boxsize / 2 return ism, rho0, a, M, rmax
def run_hydrodynamics(N=100, Mtot=1|units.MSun, Rvir=1|units.RSun, t_end=0.5|units.day, n_steps=10,\ vx = 0 |(units.RSun/units.day),\ vy = 0 |(units.RSun/units.day),\ vz = 0 |(units.RSun/units.day),\ plummer1=None, plummer2=None,\ bodyname = None): """ Runs the hydrodynamics simulation and returns a HydroResults instance. FUNCTION WALKTHROUGH: In the following explanation 'plummer1' and 'plummer2' are assumed to be hdf5 files written by the function write_set_to_file(). Case 1: If 'plummer1' and 'plummer2' are filenames of hdf5 files, then these two plummer spheres will be smashed together. Case 2: If only plummer1 is supplied, then it will evolve plummer1 with t_end timerange and n_steps steps. Case 3: If no plummers spheres are supplied, then it will generate a new plummer sphere using the default/supplied initial conditions. OUTPUT FILES: If 'results_out' is specified, the HydroResult instance is written to file in HDF5 format. This however does not use write_set_to_file() which writes the entire Particles class and its attributes to file at each dt, but uses write_to_hdf5() from the 'support' module which is tailored to writing HydroResults instances to file. This HDF5 contains all necessary data to plot the required plots of the assignment. In addition, the last snapshot of the Particles instance is written to file using write_set_to_file(), the latter file is written to the 'bodies' directory. Only the last snapshot is written to file because the history of a Particle set is not of interest when reloading them to smash plummer spheres. """ converter = nbody_system.nbody_to_si(Mtot, Rvir) fi = Fi(converter) if plummer1 and plummer2: eta_smash = 0.3 | units.day if plummer1 == plummer2: bodies1 = read_set_from_file(plummer1, format='hdf5') bodies2 = bodies1.copy() bodies2.key += 1 else: bodies1 = read_set_from_file(plummer1, format='hdf5') bodies2 = read_set_from_file(plummer2, format='hdf5') bodies1.move_to_center() bodies2.move_to_center() if vx.value_in(vx.unit) == 0 and vy.value_in(vy.unit) == 0 \ and vz.value_in(vz.unit) == 0: bodies1.x += -1 | units.RSun bodies2.x += 1 | units.RSun else: bodies1.x += (-1) * vx * eta_smash bodies2.x += 1 * vx * eta_smash bodies1.vx += vx bodies2.vx += (-1) * vx bodies1.vy += vy bodies2.vy += (-1) * vy bodies1.vz += vz bodies2.vz += (-1) * vz bodies1.add_particles(bodies2) bodies = bodies1 elif plummer1 or plummer2: if plummer1: bodies = read_set_from_file(plummer1) else: bodies = read_set_from_file(plummer2) bodies.move_to_center() else: bodies = new_plummer_gas_model(N, convert_nbody=converter) fi.gas_particles.add_particles(bodies) fi_to_framework = fi.gas_particles.new_channel_to(bodies) fi.parameters.self_gravity_flag = True data = {'lagrangianradii':AdaptingVectorQuantity(),\ 'angular_momentum':AdaptingVectorQuantity(),\ 'time':AdaptingVectorQuantity(),\ 'positions':AdaptingVectorQuantity(),\ 'kinetic_energy':AdaptingVectorQuantity(),\ 'potential_energy':AdaptingVectorQuantity(),\ 'total_energy':AdaptingVectorQuantity() } mass_fractions = [0.10, 0.25, 0.50, 0.75] setattr(data['lagrangianradii'], 'mf', mass_fractions) data['radius_initial'], data['densities_initial'] = radial_density(\ fi.particles.x, fi.particles.mass, N=10, dim=1) timerange = numpy.linspace(0, t_end.value_in(t_end.unit),\ n_steps) | t_end.unit data['time'].extend(timerange) fi.parameters.timestep = t_end / (n_steps + 1) widget = drawwidget("Evolving") pbar = pb.ProgressBar(widgets=widget, maxval=len(timerange)).start() for i, t in enumerate(timerange): fi.evolve_model(t) data['kinetic_energy'].append(fi.kinetic_energy) data['potential_energy'].append(fi.potential_energy) data['total_energy'].append(fi.total_energy) data['positions'].append(fi.particles.position) data['angular_momentum'].append(fi.gas_particles.\ total_angular_momentum()) data['lagrangianradii'].append(fi.particles.LagrangianRadii(\ unit_converter=converter,\ mf=mass_fractions)[0]) if t == timerange[-1] and bodyname: if os.path.dirname(bodyname) == '': filename = "bodies/" + bodyname fi_to_framework.copy() write_set_to_file(bodies.savepoint(t), filename, "hdf5") pbar.update(i) pbar.finish() data['radius_final'], data['densities_final'] = radial_density(\ fi.particles.x, fi.particles.mass, N=10, dim=1) fi.stop() results = HydroResults(data) return results