def main(): "Test class with an IMF" import sys import numpy from amuse.units import units numpy.random.seed(11) try: from amuse_masc import make_a_star_cluster use_masc = True except ImportError: use_masc = False if len(sys.argv) > 1: from amuse.io import read_set_from_file stars = read_set_from_file(sys.argv[1], "amuse") elif use_masc: stars = make_a_star_cluster.new_cluster(number_of_stars=10001) else: from amuse.ic.salpeter import new_salpeter_mass_distribution stars = Particles(10000) stars.mass = new_salpeter_mass_distribution(len(stars)) print("Number of stars: %i" % (len(stars))) code = StellarEvolutionCode(evo_code=SeBa) code.particles.add_particles(stars) print(code.parameters) timestep = 0.2 | units.Myr for step in range(10): time = step * timestep code.evolve_model(time) print("Evolved to %s" % code.model_time.in_(units.Myr)) print("Most massive star: %s" % code.particles.mass.max())
def test16(self): print "test evolution of 1000 star sampled over flattish IMF" number_of_stars=1000 class notsorandom(object): def random(self,N): return numpy.array(range(N))/(N-1.) def random_sample(self,N): return numpy.array(range(N))/(N-1.) masses = new_salpeter_mass_distribution( number_of_stars, mass_min = 0.1 | units.MSun, mass_max = 100.0 | units.MSun, alpha = -1.01,random=notsorandom() ) stars=Particles(mass=masses) instance=SSE() instance.particles.add_particles(stars) i=0 for p in instance.particles: print i,p.mass, p.evolve_for(13.2 | units.Gyr) print p.mass i+=1 instance.stop()
def test16(self): print("test evolution of 1000 star sampled over flattish IMF") number_of_stars = 1000 class notsorandom(object): def random(self, N): return numpy.array(range(N)) / (N - 1.) def random_sample(self, N): return numpy.array(range(N)) / (N - 1.) masses = new_salpeter_mass_distribution(number_of_stars, mass_min=0.1 | units.MSun, mass_max=100.0 | units.MSun, alpha=-1.01, random=notsorandom()) stars = Particles(mass=masses) instance = SSE() instance.particles.add_particles(stars) i = 0 for p in instance.particles: p.evolve_for(13.2 | units.Gyr) i += 1 instance.stop()
def __init__(self, num_stars, xoffset, yoffset, zoffset, repopulate_every_run=True): self.num_stars = num_stars self.xoffset = xoffset self.yoffset = yoffset self.zoffset = zoffset self.repopulate_every_run = repopulate_every_run if repopulate_every_run is False: # create nbody_converter thing? convert_nbody = nbody_system.nbody_to_si(100.0 | units.MSun, 1 | units.parsec) # instantiate plummer sphere self.initial_plummer = new_plummer_sphere(self.num_stars, convert_nbody) self.initial_plummer.x += self.xoffset | units.lightyear self.initial_plummer.y += self.yoffset | units.lightyear self.initial_plummer.z += self.zoffset | units.lightyear # provide mass distribution for stars self.initial_plummer.mass = new_salpeter_mass_distribution( self.num_stars) self.plummer = None
def stellar_population(number_of_stars = 1000,min_mass=0.1, max_mass=125, alpha=-2.35): """ Generates a stellar population that follows the Salpeter mass function """ masses = new_salpeter_mass_distribution(number_of_stars, min_mass | units.MSun, max_mass | units.MSun, alpha = alpha) return masses
def xslowtest16(self): print "test full evolution of 1000 star sampled over flattish IMF" number_of_stars=1000 from amuse.ic.salpeter import new_salpeter_mass_distribution import numpy class notsorandom(object): def random(self,N): return numpy.array(range(N))/(N-1.) masses = new_salpeter_mass_distribution( number_of_stars, mass_min = 0.1 | units.MSun, mass_max = 100.0 | units.MSun, alpha = -1.01,random=notsorandom() ) stars = Particles(mass=masses) instance=EVtwin() instance.parameters.maximum_number_of_stars=number_of_stars instance.particles.add_particles(stars) for p in instance.particles: p.evolve_for(13.2 | units.Gyr)
def demo3(N): salpeter_masses = new_salpeter_mass_distribution(N) total_mass = salpeter_masses.sum() convert_nbody = nbody_system.nbody_to_si(total_mass, 1.0 | units.parsec) print convert_nbody.to_nbody(100 | units.Myr) parts = new_plummer_model(N, convert_nbody) parts.radius = 0. | units.RSun parts.mass = salpeter_masses parts.move_to_center() gravity = PhiGRAPE(convert_nbody, use_gl=True) eps = 0.001 | units.parsec gravity.parameters.epsilon_squared = eps**2 gravity.particles.add_particles(parts) stellar_evolution = SSE() stellar_evolution.initialize_module_with_default_parameters() stellar_evolution.particles.add_particles(parts) return gravity, stellar_evolution
def create_stars(number_of_stars, size): masses = new_salpeter_mass_distribution(number_of_stars, mass_min = 2|units.MSun) converter = nbody_system.nbody_to_si(masses.sum(), size) stars = new_plummer_model(number_of_stars, convert_nbody=converter) stars.mass = masses stars.zams_mass = masses return stars, converter
def create_stars(number_of_stars, size): masses = new_salpeter_mass_distribution(number_of_stars, mass_min=2 | units.MSun) converter = nbody_system.nbody_to_si(masses.sum(), size) stars = new_plummer_model(number_of_stars, convert_nbody=converter) stars.mass = masses stars.zams_mass = masses return stars, converter
def test5(self): print("Test 5: testing user interface (SI units)") numpy.random.seed(345672) masses = new_salpeter_mass_distribution(1000) self.assertEqual(len(masses), 1000) self.assertAlmostEqual(masses.mean(), 0.334475937397 | units.MSun) self.assertAlmostRelativeEqual(masses.mean(), SalpeterIMF().mass_mean(), 1) self.assertAlmostEqual(masses.amin(), 0.10017909529 | units.MSun) self.assertAlmostEqual(masses.amax(), 19.7132849297 | units.MSun)
def test5(self): print "Test 5: testing user interface (SI units)" numpy.random.seed(345672) masses = new_salpeter_mass_distribution(1000) self.assertEqual(len(masses), 1000) self.assertAlmostEqual(masses.mean(), 0.334475937397 | units.MSun) self.assertAlmostRelativeEqual(masses.mean(), SalpeterIMF().mass_mean(), 1) self.assertAlmostEqual(masses.amin(), 0.10017909529 | units.MSun) self.assertAlmostEqual(masses.amax(), 19.7132849297 | units.MSun)
def new_cluster(number_of_stars=1000): masses = new_salpeter_mass_distribution(number_of_stars, mass_min=0.1 | units.MSun, mass_max=125.0 | units.MSun, alpha=-2.35) nbody_converter = nbody_system.nbody_to_si(masses.sum(), 1 | units.parsec) particles = new_plummer_model(number_of_stars, nbody_converter) particles.mass = masses particles.move_to_center() return particles
def new_cluster(number_of_stars = 1000): masses = new_salpeter_mass_distribution( number_of_stars, mass_min = 0.1 | units.MSun, mass_max = 125.0 | units.MSun, alpha = -2.35 ) nbody_converter = nbody_system.nbody_to_si(masses.sum(), 1 | units.parsec) particles = new_plummer_model(number_of_stars, nbody_converter) particles.mass = masses particles.move_to_center() return particles
def new_cluster(number_of_stars=1000): masses = new_salpeter_mass_distribution(number_of_stars, mass_min=0.1 | units.MSun, mass_max=125.0 | units.MSun, alpha=-2.35) particles = Particles(number_of_stars) particles.mass = masses particles.x = units.parsec(random.gamma(2.0, 1.0, number_of_stars)) particles.y = units.parsec(random.gamma(1.0, 1.0, number_of_stars)) particles.z = units.parsec(random.random(number_of_stars)) return particles
def new_cluster(number_of_stars = 1000): masses = new_salpeter_mass_distribution( number_of_stars, mass_min = 0.1 | units.MSun, mass_max = 125.0 | units.MSun, alpha = -2.35 ) particles = Particles(number_of_stars) particles.mass = masses particles.x = units.parsec(random.gamma(2.0, 1.0, number_of_stars)) particles.y = units.parsec(random.gamma(1.0, 1.0, number_of_stars)) particles.z = units.parsec(random.random(number_of_stars)) return particles
def create_cluster(Ncl, Mstar, Rcl, Mcut): """ Create a cluster with Salpeter IMF from 0.1 - Mstar | units.MSun, distributed in a virialzed Plummer sphere. Split stars into two particle sets: below_cut and above_cut for m < Mcut; m >= Mcut. """ print "Deriving a set of", str(Ncl), "random masses",\ "following a Salpeter IMF between 0.1 and",\ str(Mstar), "MSun (alpha = -2.35)." salpeter_masses = new_salpeter_mass_distribution(Ncl, mass_max=Mstar) total_mass = salpeter_masses.sum() print "Distributing particles in a virialized Plummer sphere." nbody_converter = nbody_system.nbody_to_si(total_mass, Rcl) particles = new_plummer_model(Ncl, nbody_converter) particles.move_to_center() print "Setting masses of the stars in Plummer sphere." particles.mass = salpeter_masses print "Cluster virial radius", particles.virial_radius() # NB ParticlesSubset does not have the savepoint attribute?! # Without ,copy(), we have amuse.datamodel.particles.ParticlesSubset # With .copy(), we have amuse.datamodel.particles.Particles; save works (: stars_below_cut = particles.select(lambda m: m < Mcut, ["mass"]) stars_above_cut = particles.select(lambda m: m >= Mcut, ["mass"]) print "Number of stars below", str(Mcut), "=", len(stars_below_cut) print "Number of stars above", str(Mcut), "=", len(stars_above_cut) try: import Gnuplot print "Plotting distribution of stars below and above cut-off." plotter = Gnuplot.Gnuplot() plotter('set terminal post enhance color') plotter('set output "CA_Exam_TLRH_PlummerSphere_SalpeterIMF_splitup.ps"') plotter.splot(stars_below_cut.position.value_in(units.parsec), stars_above_cut.position.value_in(units.parsec),) except ImportError: print "Unable to produce plot: couldn't find Gnuplot." except AssertionError: print "Fails because on of the sets is empty" # I return the particles superset because the particles superset is saved # when the subset is changed. This superset can be written to file. (: return particles, stars_below_cut, stars_above_cut, nbody_converter
def simulate_stellar_evolution( stellar_evolution=SSE(), number_of_stars=1000, end_time=1000.0 | units.Myr, name_of_the_figure="cluster_HR_diagram.png", ): """ A cluster of stars will be created, with masses following a Salpeter IMF. The stellar evolution will be simulated using any of the legacy codes (SSE, EVtwin, or MESA). Finally, a Hertzsprung-Russell diagram will be produced for the final state of the simulation. """ print("The evolution of", str(number_of_stars), "stars will be ", "simulated until t =", str(end_time), "...") stellar_evolution.commit_parameters() print( "Deriving a set of", str(number_of_stars), "random masses", "following a Salpeter IMF between 0.1 and 125 MSun (alpha = -2.35).") salpeter_masses = new_salpeter_mass_distribution(number_of_stars) print("Initializing the particles") stars = datamodel.Particles(number_of_stars) stars.mass = salpeter_masses print("Stars to evolve:") print(stars) stars = stellar_evolution.particles.add_particles(stars) stellar_evolution.commit_particles() # print stars.temperature print("Start evolving...") stellar_evolution.evolve_model(end_time) print("Evolved model successfully.") temperatures = stars.temperature luminosities = stars.luminosity stellar_evolution.stop() plot_HR_diagram(temperatures, luminosities, name_of_the_figure, end_time) print("All done!")
def simulate_stellar_evolution( stellar_evolution=SSE(), number_of_stars=1000, end_time=1000.0 | units.Myr, name_of_the_figure="cluster_HR_diagram.png", ): """ A cluster of stars will be created, with masses following a Salpeter IMF. The stellar evolution will be simulated using any of the legacy codes (SSE, EVtwin, or MESA). Finally, a Hertzsprung-Russell diagram will be produced for the final state of the simulation. """ print "The evolution of", str(number_of_stars), "stars will be ", \ "simulated until t =", str(end_time), "..." stellar_evolution.commit_parameters() print ( "Deriving a set of", str(number_of_stars), "random masses", "following a Salpeter IMF between 0.1 and 125 MSun (alpha = -2.35).") salpeter_masses = new_salpeter_mass_distribution(number_of_stars) print "Initializing the particles" stars = datamodel.Particles(number_of_stars) stars.mass = salpeter_masses print "Stars to evolve:" print stars stars = stellar_evolution.particles.add_particles(stars) stellar_evolution.commit_particles() # print stars.temperature print "Start evolving..." stellar_evolution.evolve_model(end_time) print "Evolved model successfully." temperatures = stars.temperature luminosities = stars.luminosity stellar_evolution.stop() plot_HR_diagram(temperatures, luminosities, name_of_the_figure, end_time) print "All done!"
def populate(self): if self.repopulate_every_run: # create nbody_converter thing? convert_nbody = nbody_system.nbody_to_si(100.0 | units.MSun, 1 | units.parsec) # instantiate plummer sphere self.plummer = new_plummer_sphere(self.num_stars, convert_nbody) self.plummer.x += self.xoffset | units.lightyear self.plummer.y += self.yoffset | units.lightyear self.plummer.z += self.zoffset | units.lightyear # provide mass distribution for stars self.plummer.mass = new_salpeter_mass_distribution(self.num_stars) else: self.plummer = self.initial_plummer
def new_field_stars( N, width=10 | units.parsec, height=10 | units.parsec, depth=100 | units.parsec, massdistribution="salpeter", agespread=3 | units.Gyr, seed=1701, ): np.random.seed(seed) stars = Particles(N) stars.x = (np.random.random(N) - 0.5) * width stars.y = (np.random.random(N) - 0.5) * height stars.z = (np.random.random(N) - 0.02) * depth if massdistribution == "salpeter": stars.mass = new_salpeter_mass_distribution(N) return stars
def demo2(N): salpeter_masses = new_salpeter_mass_distribution(N) total_mass = salpeter_masses.sum() convert_nbody = nbody_system.nbody_to_si(total_mass, 1.0 | units.parsec) parts = new_plummer_model(N, convert_nbody) parts.radius = 0. | nbody_system.length parts.mass = salpeter_masses parts.move_to_center() interface = PhiGRAPE(convert_nbody, use_gl=True) eps = 0.001 | units.parsec interface.parameters.epsilon_squared = eps**2 interface.particles.add_particles(parts) return interface
def main(): assert is_mpd_running() seed = None nstars = 128 if len(sys.argv) > 1: stars = int(sys.argv[1]) with_units = len(sys.argv) > 2 if not with_units: mass_unit = nbody_system.mass length_unit = nbody_system.length else: mass_unit = units.MSun length_unit = units.parsec m_min = 0.1 | mass_unit m_max = 100 | mass_unit alpha = -2.35 r_vir = 1 | length_unit masses = new_salpeter_mass_distribution(nstars, m_min, m_max, alpha) m_tot = masses.sum() if not with_units: convert_nbody = None masses /= m_tot.value_in(nbody_system.mass) # scale to unit mass m_tot = 1 | nbody_system.mass else: convert_nbody = nbody_system.nbody_to_si(m_tot, r_vir) convert_nbody.set_as_default() print m_tot stars = new_plummer_model(nstars, convert_nbody, random_state=seed) stars.mass = masses LagrangianRadii(stars, verbose=True)
def generate_cluster(number_of_stars, mass_of_cluster, radius_of_cluster): # numpy.random.seed(1) if (mass_of_cluster > 0 | units.MSun): number_of_stars = int(mass_of_cluster.value_in(units.MSun)) * 5 salpeter_masses = new_salpeter_mass_distribution(number_of_stars) imf = salpeter_masses if (mass_of_cluster > 0 | units.MSun): print("sorted sampling salpeter IMF, total mass:", mass_of_cluster) imf_cumsum = imf.cumsum() pick_up_number = (imf_cumsum <= mass_of_cluster).sum() if (pick_up_number < number_of_stars): imf_pick_up = imf[:pick_up_number + 1] sorted_imf_pick_up = np.sort(imf_pick_up) if (sorted_imf_pick_up[pick_up_number] - mass_of_cluster < mass_of_cluster - sorted_imf_pick_up[pick_up_number - 1]): pick_up_number += 1 imf = sorted_imf_pick_up[:pick_up_number] number_of_stars = pick_up_number total_mass = imf.sum() convert_nbody = nbody_system.nbody_to_si(total_mass, radius_of_cluster | units.parsec) print("generate plummer model, N=", number_of_stars) particles = new_plummer_model(number_of_stars, convert_nbody) print("setting masses of the stars") particles.radius = 0.0 | units.RSun particles.mass = imf #particles.mass[0] = 40.0 |units.MSun #particles.mass[1] = 50.0 |units.MSun return particles, convert_nbody
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'
t_end = o.t_end | units.Myr dt = o.dt | units.Myr stellar_evolution = SSE() stellar_evolution.commit_parameters() stars = Particles(o.N) Mmin = o.Mmin | units.MSun Mmax = o.Mmax | units.MSun if o.verbose: print("#Selected parameters: ") print("#\tN=", o.N) print("#\tIMF=", o.Mmin, "MSun", o.Mmax, "MSun", o.x_imf) print("#\t t [Myr] \t <m> [MSun] \t\t d<m>/dt [MSun/Myr]") stars.mass = new_salpeter_mass_distribution( o.N, mass_min=Mmin, mass_max=Mmax, alpha=o.x_imf) stars = stellar_evolution.particles.add_particles(stars) stellar_evolution.commit_particles() t = 0 | units.Myr mm = stars.mass.sum()/len(stars) while t < t_end: mm_last = mm t += dt stellar_evolution.evolve_model(t) mm = stars.mass.sum()/len(stars) dmm_dt = (mm_last-mm)/dt if o.verbose: print("t = ", t, "<m>=", mm.as_quantity_in(units.MSun), " d<m>/dt = ", dmm_dt.as_quantity_in(units.MSun/units.Myr)) else:
def randomparticles_w_ss(N=20, L=1000. | units.AU, dv=2.5 | units.kms): from amuse.ic.salpeter import new_salpeter_mass_distribution conv = nbody_system.nbody_to_si(N * 1. | units.MSun, 1000. | units.AU) conv_sub = nbody_system.nbody_to_si(1. | units.MSun, 50. | units.AU) dt = smaller_nbody_power_of_two(1000. | units.day, conv) print(dt.in_(units.day)) dt_param = 0.02 LL = L.value_in(units.AU) def radius(sys, eta=dt_param, _G=constants.G): radius = ((_G * sys.total_mass() * dt**2 / eta**2)**(1. / 3.)) # xcm,ycm,zcm=sys.center_of_mass() # r2max=((sys.x-xcm)**2+(sys.y-ycm)**2+(sys.z-zcm)**2).max() # if radius < 10 | units.AU: # radius=20. | units.AU # return max(radius,r2max**0.5) return radius * ((len(sys) + 1) / 2.)**0.75 def timestep(ipart, jpart, eta=dt_param / 2, _G=constants.G): dx = ipart.x - jpart.x dy = ipart.y - jpart.y dz = ipart.z - jpart.z dr2 = dx**2 + dy**2 + dz**2 # if dr2>0: dr = dr2**0.5 dr3 = dr * dr2 mu = _G * (ipart.mass + jpart.mass) tau = eta / 2. / 2.**0.5 * (dr3 / mu)**0.5 return tau numpy.random.seed(7654304) masses = new_salpeter_mass_distribution(N, mass_min=0.3 | units.MSun, mass_max=10. | units.MSun) #masses=([1.]*10) | units.MSun stars = Particles(N, mass=masses) stars.x = L * numpy.random.uniform(-1., 1., N) stars.y = L * numpy.random.uniform(-1., 1., N) stars.z = L * 0. stars.vx = dv * numpy.random.uniform(-1., 1., N) stars.vy = dv * numpy.random.uniform(-1., 1., N) stars.vz = dv * 0. stars.radius = (1. | units.RSun) * (stars.mass / (1. | units.MSun))**(1. / 3.) stars.move_to_center() parts = HierarchicalParticles(stars) # ss=new_solar_system()[[0,5,6,7,8]] # parts.assign_subsystem(ss,parts[0]) def parent_worker(): code = Hermite(conv) code.parameters.epsilon_squared = 0. | units.AU**2 code.parameters.end_time_accuracy_factor = 0. code.parameters.dt_param = 0.001 print(code.parameters.dt_dia.in_(units.yr)) return code def sub_worker(parts): mode = system_type(parts) if mode == "twobody": code = TwoBody(conv_sub) elif mode == "solarsystem": code = Mercury(conv_sub) elif mode == "nbody": code = Huayno(conv_sub) code.parameters.inttype_parameter = code.inttypes.SHARED4 return code def py_worker(): code = CalculateFieldForParticles(gravity_constant=constants.G) return code nemesis = Nemesis(parent_worker, sub_worker, py_worker) nemesis.timestep = dt nemesis.distfunc = timestep nemesis.threshold = dt nemesis.radius = radius nemesis.commit_parameters() nemesis.particles.add_particles(parts) nemesis.commit_particles() tend = 3200. | units.yr t = 0 | units.yr dtdiag = dt * 2 time = [0.] allparts = nemesis.particles.all() E = allparts.potential_energy() + allparts.kinetic_energy() E1 = nemesis.potential_energy + nemesis.kinetic_energy com = allparts.center_of_mass() mom = allparts.total_momentum() ang = allparts.total_angular_momentum() E0 = E A0 = (ang[0]**2 + ang[1]**2 + ang[2]**2)**0.5 P0 = mom[0].value_in(units.MSun * units.kms) totalE = [0.] totalA = [0.] totalP = [0.] ss = nemesis.particles.all() x = (ss.x).value_in(units.AU) xx = [x] y = (ss.y).value_in(units.AU) yy = [y] nstep = 0 while t < tend - dtdiag / 2: t += dtdiag nemesis.evolve_model(t) print(t.in_(units.yr)) print(len(nemesis.particles)) time.append(t.value_in(units.yr)) allparts = nemesis.particles.all() E = allparts.potential_energy() + allparts.kinetic_energy() E1 = nemesis.potential_energy + nemesis.kinetic_energy ang = allparts.total_angular_momentum() mom = allparts.total_momentum() A = (ang[0]**2 + ang[1]**2 + ang[2]**2)**0.5 P = mom[0].value_in(units.MSun * units.kms) totalE.append(abs((E0 - E) / E0)) totalA.append(abs((A0 - A) / A0)) totalP.append(abs(P0 - P)) print(totalE[-1], (E - E1) / E) # print allparts.potential_energy(),nemesis.potential_energy ss = nemesis.particles.all() x = (ss.x).value_in(units.AU) y = (ss.y).value_in(units.AU) lowm = numpy.where(ss.mass.value_in(units.MSun) < 0.1)[0] highm = numpy.where(ss.mass.value_in(units.MSun) >= 0.1)[0] xcm = nemesis.particles.x.value_in(units.AU) ycm = nemesis.particles.y.value_in(units.AU) r = (nemesis.particles.radius).value_in(units.AU) xx.append(x) yy.append(y) key = ss.key f = pyplot.figure(figsize=(8, 8)) ax = f.gca() circles = [] # for i in range(len(xx[0])): # pyplot.plot(xx[-1][i],yy[-1][i],colors[key[i]%numpy.uint64(len(colors))]+ # markerstyles[key[i]%numpy.uint64(len(markerstyles))],markersize=8,mew=2) pyplot.plot(xx[-1][highm], yy[-1][highm], 'go', markersize=8, mew=2) pyplot.plot(xx[-1][lowm], yy[-1][lowm], 'b+', markersize=6, mew=1.5) for p in nemesis.particles: # if nemesis.particles.collection_attributes.subsystems.has_key(p): c = 'k' ls = 'solid' code_colors = dict(TwoBody='b', Mercury='r', Huayno='g', Hermite='y') code_ls = dict(TwoBody='dotted', Mercury='dashed', Huayno='dashdot', Hermite='solid') if nemesis.subcodes.has_key(p): c = code_colors[nemesis.subcodes[p].__class__.__name__] ls = code_ls[nemesis.subcodes[p].__class__.__name__] x = p.x.value_in(units.AU) y = p.y.value_in(units.AU) r = p.radius.value_in(units.AU) circles.append( pyplot.Circle((x, y), r, color=c, lw=0.8, ls=ls, fill=False)) for c in circles: ax.add_artist(c) # pyplot.plot(xcm,ycm,'k+', markersize=4,mew=1) pyplot.xlim(-1.2 * LL, 1.2 * LL) pyplot.ylim(-1.2 * LL, 1.2 * LL) pyplot.xlabel("AU") pyplot.text(-580, -580, '%8.2f' % t.value_in(units.yr), fontsize=18) # pyplot.text(-400,-400,len(nemesis.particles),fontsize=18) pyplot.savefig('xy%6.6i.png' % nstep, bbox_inches='tight') f.clear() pyplot.close(f) nstep += 1 time = numpy.array(time) totalE = numpy.array(totalE) totalA = numpy.array(totalA) totalP = numpy.array(totalP) xx = numpy.array(xx) yy = numpy.array(yy) f = pyplot.figure(figsize=(8, 8)) pyplot.semilogy(time, totalE, 'r') pyplot.semilogy(time, totalA, 'g') pyplot.semilogy(time, totalP, 'b') pyplot.savefig('dEdA.png') f = pyplot.figure(figsize=(8, 8)) for i in range(len(xx[0])): pyplot.plot(xx[:, i], yy[:, i], colors[i % len(colors)] + linestyles[i % len(linestyles)]) pyplot.xlim(-LL, LL) pyplot.ylim(-LL, LL) pyplot.savefig('all-xy.png')
def simulate_small_cluster(number_of_stars, end_time=40 | units.Myr, name_of_the_figure="test-2.svg"): random.seed() salpeter_masses = new_salpeter_mass_distribution(number_of_stars) total_mass = salpeter_masses.sum() convert_nbody = nbody_system.nbody_to_si(total_mass, 1.0 | units.parsec) convert_nbody.set_as_default() particles = new_plummer_model(number_of_stars, convert_nbody) gravity = PhiGRAPE(convert_nbody, mode="gpu") gravity.initialize_code() gravity.parameters.timestep_parameter = 0.01 gravity.parameters.initial_timestep_parameter = 0.01 gravity.parameters.epsilon_squared = 0.000001 | units.parsec**2 stellar_evolution = SSE() stellar_evolution.initialize_module_with_default_parameters() #print "setting masses of the stars" particles.radius = 0.0 | units.RSun #comment out to get plummer masses particles.mass = salpeter_masses gravity.particles.add_particles(particles) gravity.initialize_particles(0.0) from_model_to_gravity = particles.new_channel_to(gravity.particles) from_gravity_to_model = gravity.particles.new_channel_to(particles) time = 0.0 | units.Myr particles.savepoint(time) move_particles_to_center_of_mass(particles) kineticEnergy = gravity.kinetic_energy.value_in(units.J) potentialEnergy = gravity.potential_energy.value_in(units.J) ToverV = kineticEnergy / potentialEnergy file.write(str(time.value_in(units.Myr))) file.write(' ') file.write(str(ToverV)) file.write('\n') while time < end_time: time += 0.25 | units.Myr gravity.evolve_model(time) from_gravity_to_model.copy() print "Evolved model to t =", str(time) print "Evolved model to t =", str( convert_nbody.to_nbody(time.value_in(units.Myr) | units.Myr)) kineticEnergy = gravity.kinetic_energy.value_in(units.J) potentialEnergy = gravity.potential_energy.value_in(units.J) ToverV = kineticEnergy / potentialEnergy print "Kin / Pot =", ToverV #print "Particle Mass =", particles[1].mass file.write(str(time.value_in(units.Myr))) file.write(' ') file.write(str(ToverV)) file.write('\n') file.close() if os.path.exists('small.hdf5'): os.remove('small.hdf5') storage = store.StoreHDF("small.hdf5") storage.store(particles) del gravity del stellar_evolution
cluster_populations = [] j = 0 #counter while j <= Nclusters: Mcluster = masses[j] | units.MSun Nstars, Mmin_star, Mmax_star = 100, 0.1, 100. mZams_flag = 0 while mZams_flag == 0: mZams = new_salpeter_mass_distribution(Nstars, Mmin_star | units.MSun, Mmax_star | units.MSun, random=np.random) mass_difference_ratio = (Mcluster - mZams.sum()) / Mcluster if mass_difference_ratio > 0.01: Nstars += 1 if mass_difference_ratio < -0.01: Nstars -= 1 if np.abs(mass_difference_ratio) <= 0.01: mZams_flag = 1 star_masses = mZams.value_in(units.MSun) np.savetxt('star_masses_index=%i.txt' % j, star_masses)
stars = int(sys.argv[1]) with_units = len(sys.argv) > 2 if not with_units: mass_unit = nbody_system.mass length_unit = nbody_system.length else: mass_unit = units.MSun length_unit = units.parsec m_min = 0.1 | mass_unit m_max = 100 | mass_unit alpha = -2.35 r_vir = 1 | length_unit masses = new_salpeter_mass_distribution(nstars, m_min, m_max, alpha) m_tot = masses.sum() if not with_units: convert_nbody = None masses /= m_tot.value_in(nbody_system.mass) # scale to unit mass m_tot = 1 | nbody_system.mass else: convert_nbody = nbody_system.nbody_to_si(m_tot, r_vir) convert_nbody.set_as_default() print m_tot stars = new_plummer_model(nstars, convert_nbody, random_state=seed) stars.mass = masses LagrangianRadii(stars, verbose=1)
def simulate_small_cluster(number_of_stars, end_time=40 | units.Myr, name_of_the_figure="test-2.svg"): random.seed() salpeter_masses = new_salpeter_mass_distribution(number_of_stars) total_mass = salpeter_masses.sum() convert_nbody = nbody_system.nbody_to_si(total_mass, 1.0 | units.parsec) convert_nbody.set_as_default() print 'end_time:', convert_nbody.to_nbody(end_time) print convert_nbody.to_nbody(total_mass) particles = new_plummer_model(number_of_stars, convert_nbody) gravity = PhiGRAPE(convert_nbody, mode="gpu", use_gl="true") gravity.parameters.timestep_parameter = 0.01 gravity.parameters.initial_timestep_parameter = 0.01 gravity.parameters.epsilon_squared = 0.0015 | units.parsec**2 particles.radius = 0.0 | units.RSun # particles.mass = salpeter_masses move_particles_to_center_of_mass(particles) gravity.particles.add_particles(particles) gravity.initialize_particles(0.0) gravity.start_viewer() from_model_to_gravity = particles.new_channel_to(gravity.particles) from_gravity_to_model = gravity.particles.new_channel_to(particles) time = 0.0 | units.Myr # particles.savepoint(time) kineticEnergy = gravity.kinetic_energy.value_in(units.J) potentialEnergy = gravity.potential_energy.value_in(units.J) ToverV = kineticEnergy / potentialEnergy E0 = convert_nbody.to_nbody(gravity.kinetic_energy + gravity.potential_energy) file.write(str(time.value_in(units.Myr))) file.write(' ') file.write(str(ToverV)) file.write('\n') gravity.parameters.timestep_parameter = 0.01 gravity.parameters.initial_timestep_parameter = 0.01 while time < end_time: time += 0.5 * convert_nbody.to_si(1 | nbody_system.time) gravity.evolve_model(time) gravity.synchronize_model() from_gravity_to_model.copy() print "Evolved model to t =", str(time) kineticEnergy = gravity.kinetic_energy.value_in(units.J) potentialEnergy = gravity.potential_energy.value_in(units.J) ToverV = kineticEnergy / potentialEnergy Et = convert_nbody.to_nbody(gravity.kinetic_energy + gravity.potential_energy) print "Kin / Pot =", ToverV, (Et - E0) / E0 file.write(str(time.value_in(units.Myr))) file.write(' ') file.write(str(ToverV)) file.write('\n') file.close() if os.path.exists('small.hdf5'): os.remove('small.hdf5') storage = store.StoreHDF("small.hdf5") storage.store(particles) del gravity del stellar_evolution
def simulate_small_cluster(number_of_stars, end_time=40 | units.Myr, name_of_the_figure="test-2.svg"): # numpy.random.seed(1) salpeter_masses = new_salpeter_mass_distribution(number_of_stars) total_mass = salpeter_masses.sum() convert_nbody = nbody_system.nbody_to_si(total_mass, 1.0 | units.parsec) particles = new_plummer_model(number_of_stars, convert_nbody) gravity = BHTree(convert_nbody) # print gravity.parameters.timestep.as_quantity_in(units.Myr) gravity.parameters.timestep = 0.0001 | units.Myr # tiny! gravity.parameters.epsilon_squared \ = (float(number_of_stars)**(-0.333333) | units.parsec) ** 2 stellar_evolution = SSE() print "setting masses of the stars" particles.radius = 0.0 | units.RSun particles.mass = salpeter_masses print "initializing the particles" stellar_evolution.particles.add_particles(particles) from_stellar_evolution_to_model \ = stellar_evolution.particles.new_channel_to(particles) from_stellar_evolution_to_model.copy_attributes(["mass"]) print "centering the particles" particles.move_to_center() print "scaling particles to viridial equilibrium" particles.scale_to_standard(convert_nbody) gravity.particles.add_particles(particles) from_model_to_gravity = particles.new_channel_to(gravity.particles) from_gravity_to_model = gravity.particles.new_channel_to(particles) time = 0.0 | units.Myr particles.savepoint(time) total_energy_at_t0 = gravity.kinetic_energy + gravity.potential_energy print "evolving the model until t = " + str(end_time) while time < end_time: time += 0.25 | units.Myr print "gravity evolve step starting" gravity.evolve_model(time) print "gravity evolve step done" print "stellar evolution step starting" stellar_evolution.evolve_model(time) print "stellar evolution step done" from_gravity_to_model.copy() from_stellar_evolution_to_model.copy_attributes(["mass", "radius"]) particles.savepoint(time) from_model_to_gravity.copy_attributes(["mass"]) total_energy_at_this_time \ = gravity.kinetic_energy + gravity.potential_energy print_log(time, gravity, particles, total_energy_at_t0, total_energy_at_this_time) test_results_path = get_path_to_results() output_file = os.path.join(test_results_path, "small.hdf5") if os.path.exists(output_file): os.remove(output_file) storage = store.StoreHDF(output_file) storage.store(particles) gravity.stop() stellar_evolution.stop() plot_particles(particles, name_of_the_figure)
def kira(tend, N, R, Nbin): logging.basicConfig(level=logging.ERROR) mass = new_salpeter_mass_distribution(N, mass_min=10 | units.MSun) converter = nbody_system.nbody_to_si(mass.sum(), R) code = Hermite(converter) stars = new_plummer_model(N, convert_nbody=converter) stars.mass = mass stars.radius = 0.01/len(stars) | R.unit single_stars, binary_stars, singles_in_binaries \ = make_secondaries(stars, Nbin) print(binary_stars) stellar = SeBa() stellar.particles.add_particles(single_stars) stellar.particles.add_particles(singles_in_binaries) stellar.binaries.add_particles(binary_stars) channel_to_stars = stellar.particles.new_channel_to(stars) encounter_code = encounters.HandleEncounter( kepler_code=new_kepler(converter), resolve_collision_code=new_smalln(converter), interaction_over_code=None, G=constants.G ) multiples_code = encounters.Multiples( gravity_code=code, handle_encounter_code=encounter_code, G=constants.G ) multiples_code.particles.add_particles((stars-binary_stars).copy()) multiples_code.singles_in_binaries.add_particles(singles_in_binaries) multiples_code.binaries.add_particles(binary_stars) multiples_code.commit_particles() channel_from_stars_to_particles \ = stellar.particles.new_channel_to(multiples_code.particles) stopping_condition \ = multiples_code.stopping_conditions.binaries_change_detection stopping_condition.enable() from matplotlib import pyplot from distinct_colours import get_distinct pyplot.rcParams.update({'font.size': 30}) figure = pyplot.figure(figsize=(12, 9)) ax = pyplot.gca() ax.get_yaxis().get_major_formatter().set_useOffset(False) ax.xaxis._autolabelpos = True ax.yaxis._autolabelpos = True color = get_distinct(2) pyplot.scatter(numpy.log10(stellar.binaries.semi_major_axis. value_in(units.AU)), stellar.binaries.eccentricity, c=color[0], s=200, lw=0) t = quantities.linspace(0*tend, tend, 11) for ti in t: print(("t, Energy=", ti, multiples_code.particles.mass.sum(), multiples_code.get_total_energy())) multiples_code.evolve_model(ti) print(("at t=", multiples_code.model_time, "Nmultiples:", len(multiples_code.multiples))) if stopping_condition.is_set(): resolve_changed_binaries(stopping_condition, stellar, converter) stellar.evolve_model(ti) channel_from_stars_to_particles.copy_attributes(["mass", "radius"]) update_dynamical_binaries_from_stellar(stellar, multiples_code, converter) print(("Lagrangian radii:", multiples_code.all_singles.LagrangianRadii(converter))) print(("MC.particles", multiples_code.particles)) print(("Lagrangian radii:", multiples_code.particles.LagrangianRadii(converter))) print(("t, Energy=", ti, multiples_code.get_total_energy())) pyplot.scatter(numpy.log10(stellar.binaries.semi_major_axis .value_in(units.AU)), stellar.binaries.eccentricity, c=color[1], lw=0, s=50) pyplot.xlabel("$\log_{10}(a/R_\odot)$") pyplot.ylabel("eccentricity") save_file = 'kira_a_vs_e.pdf' pyplot.savefig(save_file) print('\nSaved figure in file', save_file, '\n') pyplot.show() stellar.stop()
dt = o.dt | units.Myr stellar_evolution = SSE() stellar_evolution.commit_parameters() stars = Particles(o.N) Mmin = o.Mmin | units.MSun Mmax = o.Mmax | units.MSun if o.verbose: print("#Selected parameters: ") print("#\tN=", o.N) print("#\tIMF=", o.Mmin, "MSun", o.Mmax, "MSun", o.x_imf) print("#\t t [Myr] \t <m> [MSun] \t\t d<m>/dt [MSun/Myr]") stars.mass = new_salpeter_mass_distribution(o.N, mass_min=Mmin, mass_max=Mmax, alpha=o.x_imf) stars = stellar_evolution.particles.add_particles(stars) stellar_evolution.commit_particles() t = 0 | units.Myr mm = stars.mass.sum() / len(stars) while t < t_end: mm_last = mm t += dt stellar_evolution.evolve_model(t) mm = stars.mass.sum() / len(stars) dmm_dt = (mm_last - mm) / dt if o.verbose: print("t = ", t, "<m>=", mm.as_quantity_in(units.MSun), " d<m>/dt = ", dmm_dt.as_quantity_in(units.MSun / units.Myr))
def assignment_2d(): current_cluster_mass = 400 | units.MSun initial_mass_fraction = 0.84 desired_initial_mass = current_cluster_mass / initial_mass_fraction masses = new_salpeter_mass_distribution(100000) mean_salpeter_mass = masses.mean() print "mean salpeter mass", mean_salpeter_mass N = int(desired_initial_mass / mean_salpeter_mass) print "N", N Rvir = 10 | units.lightyear z = 0.17 masses = new_salpeter_mass_distribution(N) converter = nbody_system.nbody_to_si(masses.sum(), Rvir) G_SI = converter.to_si(nbody_system.G) bodies = new_plummer_sphere(N, convert_nbody=converter) bodies.mass = masses bodies.metalicity = z # start the gravity solver gravity = BHTree(converter) gravity.initialize_code() gravity.parameters.timestep = 0.1 | units.Myr # start the stellar evolution solver stellar = SSE() stars = stellar.particles.add_particles(bodies) from_stellar_evolution_to_model \ = stellar.particles.new_channel_to(bodies) from_stellar_evolution_to_model.copy_attributes(["mass"]) bodies.scale_to_standard(converter) gravity.particles.add_particles(bodies) from_model_to_gravity = bodies.new_channel_to(gravity.particles) from_gravity_to_model = gravity.particles.new_channel_to(bodies) gravity.commit_particles() end_time = 1000 | units.Myr current_time = 0 | units.Myr cluster = "Hyades" bound_stars_counts = [] main_sequence_stars_counts = [] giant_stars_counts = [] remnant_stars_counts = [] max_radii = [] | units.parsec virial_radii = [] | units.parsec times = [] | units.Myr while current_time < end_time: name_of_the_figure = "isochrone_with_grav_"+str(int(current_time.value_in(units.Myr)))+".png" gravity.evolve_model(current_time) stellar.evolve_model(current_time) from_gravity_to_model.copy() from_stellar_evolution_to_model.copy_attributes(["mass", "radius"]) from_model_to_gravity.copy_attributes(["mass"]) remnant_count = 0 main_sequence_count = 0 giant_count = 0 for star in stars: if stellar_remnant_state(star): remnant_count += 1 if stellar_giant_state(star): giant_count += 1 if stellar_main_sequence_state(star): main_sequence_count += 1 max_radius = bodies.total_radius() virial_radius = bodies.virial_radius() bound_star_count = len(bodies.bound_subset(unit_converter=converter, G=G_SI)) print "bound stars:", bound_star_count print "main sequence stars:", main_sequence_count print "giant stars:", giant_count print "remnant stars:", remnant_count print "cluster radius(max from centre):", max_radius print "virial radius:", virial_radius print current_time times.append(current_time) remnant_stars_counts.append(remnant_count) giant_stars_counts.append(giant_count) main_sequence_stars_counts.append(main_sequence_count) max_radii.append(max_radius) virial_radii.append(virial_radius) bound_stars_counts.append(bound_star_count) temperatures = stars.temperature luminosities = stars.luminosity plot_HR_diagram(temperatures, luminosities, cluster+"/", name_of_the_figure, current_time) current_time += 10 | units.Myr data = {} data["bound_stars_at_time"] = bound_stars_counts data["remnant_stars_at_time"] = remnant_stars_counts data["giant_stars_at_time"] = giant_stars_counts data["main_sequence_stars_at_time"] = main_sequence_stars_counts data["max_radius_at_time"] = max_radii data["virial_radii"] = virial_radii data["times"] = times pickle.dump(data, open(cluster+"/assignment2d.dat", "wb"))
stars = int(sys.argv[1]) with_units = len(sys.argv) > 2 if not with_units : mass_unit = nbody_system.mass length_unit = nbody_system.length else : mass_unit = units.MSun length_unit = units.parsec m_min = 0.1 | mass_unit m_max = 100 | mass_unit alpha = -2.35 r_vir = 1 | length_unit masses = new_salpeter_mass_distribution(nstars, m_min, m_max, alpha) m_tot = masses.sum() if not with_units : convert_nbody = None masses /= m_tot.value_in(nbody_system.mass) # scale to unit mass m_tot = 1 | nbody_system.mass else : convert_nbody = nbody_system.nbody_to_si(m_tot, r_vir) convert_nbody.set_as_default() print m_tot stars = new_plummer_model(nstars, convert_nbody, random_state = seed); stars.mass = masses LagrangianRadii(stars, verbose=1)
def make_a_star_cluster( stellar_mass=False, initial_mass_function="salpeter", upper_mass_limit=125. | units.MSun, number_of_stars=1024, effective_radius=3.0 | units.parsec, star_distribution="plummer", star_distribution_w0=7.0, star_distribution_fd=2.0, star_metallicity=0.01, # initial_binary_fraction=0, **kwargs): """ Create stars. When using an IMF, either the stellar mass is fixed (within stochastic error) or the number of stars is fixed. When using equal-mass stars, both are fixed. """ if stellar_mass: # Add stars to cluster, until mass limit reached (inclusive!) if initial_mass_function == "kroupa": from amuse.ic.brokenimf import new_kroupa_mass_distribution mass = new_kroupa_mass_distribution(0) while mass.sum() < stellar_mass: mass.append( new_kroupa_mass_distribution( 1, mass_max=upper_mass_limit, )[0]) total_mass = mass.sum() number_of_stars = len(mass) elif initial_mass_function == "salpeter": from amuse.ic.salpeter import new_salpeter_mass_distribution mass = new_salpeter_mass_distribution(0) while mass.sum() < stellar_mass: mass.append( new_salpeter_mass_distribution( 1, mass_max=upper_mass_limit, )[0]) total_mass = mass.sum() number_of_stars = len(mass) elif initial_mass_function == "fixed": mass_of_individual_star = stellar_mass / number_of_stars mass = mass_of_individual_star total_mass = stellar_mass else: return -1, "No mass function" else: # Give stars their mass if initial_mass_function == "kroupa": from amuse.ic.brokenimf import new_kroupa_mass_distribution mass = new_kroupa_mass_distribution( number_of_stars, mass_max=upper_mass_limit, ) total_mass = mass.sum() elif initial_mass_function == "salpeter": from amuse.ic.salpeter import new_salpeter_mass_distribution mass = new_salpeter_mass_distribution( number_of_stars, mass_max=upper_mass_limit, ) total_mass = mass.sum() elif initial_mass_function == "fixed": mass = mass_of_individual_star total_mass = number_of_stars * mass else: return -1, "No mass function" converter = generic_unit_converter.ConvertBetweenGenericAndSiUnits( total_mass, 1. | units.kms, effective_radius, ) # Give stars a position and velocity, based on the distribution model. if star_distribution == "plummer": from amuse.ic.plummer import new_plummer_sphere stars = new_plummer_sphere( number_of_stars, convert_nbody=converter, ) elif star_distribution == "king": from amuse.ic.kingmodel import new_king_model stars = new_king_model( number_of_stars, star_distribution_w0, convert_nbody=converter, ) elif star_distribution == "fractal": from amuse.ic.fractalcluster import new_fractal_cluster_model stars = new_fractal_cluster_model( number_of_stars, fractal_dimension=star_distribution_fd, convert_nbody=converter, ) else: return -1, "No stellar distribution" # set the stellar mass. stars.mass = mass # set other stellar parameters. stars.metallicity = star_metallicity # Virialize the star cluster stars.move_to_center() stars.scale_to_standard( convert_nbody=converter, # virial_ratio=virial_ratio, # smoothing_length_squared= ..., ) # Record the cluster's initial parameters to the particle distribution stars.collection_attributes.initial_mass_function = initial_mass_function stars.collection_attributes.upper_mass_limit = upper_mass_limit stars.collection_attributes.number_of_stars = number_of_stars stars.collection_attributes.effective_radius = effective_radius stars.collection_attributes.star_distribution = star_distribution stars.collection_attributes.star_distribution_w0 = star_distribution_w0 stars.collection_attributes.star_distribution_fd = star_distribution_fd stars.collection_attributes.star_metallicity = star_metallicity # Derived/legacy values stars.collection_attributes.converter_mass = \ converter.to_si(1 | nbody_system.mass) stars.collection_attributes.converter_length =\ converter.to_si(1 | nbody_system.length) stars.collection_attributes.converter_speed =\ converter.to_si(1 | nbody_system.speed) return stars
def simulate_small_cluster(number_of_stars, end_time=40 | units.Myr, name_of_the_figure="test-2.svg"): # numpy.random.seed(1) salpeter_masses = new_salpeter_mass_distribution(number_of_stars) total_mass = salpeter_masses.sum() convert_nbody = nbody_system.nbody_to_si(total_mass, 1.0 | units.parsec) particles = new_plummer_model(number_of_stars, convert_nbody) gravity = BHTree(convert_nbody) gravity.initialize_code() # gravity.parameters.set_defaults() # print gravity.parameters.timestep.as_quantity_in(units.Myr) gravity.parameters.timestep = 0.0001 | units.Myr # tiny! gravity.parameters.epsilon_squared \ = (float(number_of_stars)**(-0.333333) | units.parsec) ** 2 stellar_evolution = SSE() stellar_evolution.initialize_module_with_default_parameters() print "setting masses of the stars" particles.radius = 0.0 | units.RSun particles.mass = salpeter_masses print "initializing the particles" stellar_evolution.particles.add_particles(particles) from_stellar_evolution_to_model \ = stellar_evolution.particles.new_channel_to(particles) from_stellar_evolution_to_model.copy_attributes(["mass"]) print "centering the particles" particles.move_to_center() print "scaling particles to viridial equilibrium" particles.scale_to_standard(convert_nbody) gravity.particles.add_particles(particles) from_model_to_gravity = particles.new_channel_to(gravity.particles) from_gravity_to_model = gravity.particles.new_channel_to(particles) gravity.commit_particles() time = 0.0 | units.Myr particles.savepoint(time) total_energy_at_t0 = gravity.kinetic_energy + gravity.potential_energy print "evolving the model until t = " + str(end_time) while time < end_time: time += 0.25 | units.Myr print "Gravity evolve step starting" gravity_evolve = gravity.evolve_model.async(time) print "Stellar evolution step starting" stellar_evolution_evolve = stellar_evolution.evolve_model(time) print "Stellar evolution step done." gravity_evolve.result() print "Gravity evolve step done." from_gravity_to_model.copy() from_stellar_evolution_to_model.copy_attributes(["mass", "radius"]) particles.savepoint(time) from_model_to_gravity.copy_attributes(["mass"]) total_energy_at_this_time \ = gravity.kinetic_energy + gravity.potential_energy print_log(time, gravity, particles, total_energy_at_t0, total_energy_at_this_time) test_results_path = get_path_to_results() output_file = os.path.join(test_results_path, "small.hdf5") if os.path.exists(output_file): os.remove(output_file) storage = store.StoreHDF(output_file) storage.store(particles) gravity.stop() stellar_evolution.stop() plot_particles(particles, name_of_the_figure)
def create_cluster_isochrone(cluster, algorithm=SSE, number_of_stars=1339, end_time=1000 | units.Myr, z=0.012 ): """ Code for Assignment 2B. @param cluster: Name of cluter (used as dir to store data) @param stellar: specify the stellar evolution code. valid options are: MESA, EVtwin (both Henyey) SSE, SeBa (both parameterized) @param number_of_stars: how many stars to evolve @param end_time: how long the cluster is evolved @return: dumps the data to file """ data = {} stellar = algorithm() algorithm_name = str(algorithm).split('.')[-1][:-2] print "Deriving a set of {0} random masses ".format(number_of_stars), print "following a Salpeter IMF between 0.1 and 125 Msun", print "(alpha = -2.35)." salpeter_masses = new_salpeter_mass_distribution(number_of_stars) print "Initializing the particles" stars = datamodel.Particles(number_of_stars) stars.mass = salpeter_masses total_mass = 0 | units.MSun for m in stars.mass: total_mass += m print "total mass =", total_mass data['initial_total_mass'] = total_mass stars.metallicity = z print "The evolution of {0} stars will be".format(number_of_stars), print "simulated until t = {0}".format(end_time), print ", using algorithm {0}".format(algorithm_name) stellar.commit_parameters() print "Stars to evolve:" print stars data['stars'] = stars stars = stellar.particles.add_particles(stars) stellar.commit_particles() print "Start evolving..." # stellar.evolve_model(end_time) times = [] | units.Myr luminosity_at_time = [] | units.LSun temperatures_at_time = [] | units.K mass_at_time = [] | units.MSun current_time = 0 | units.Myr while current_time < end_time: name_of_the_figure = "isochrone_{0}_{1}_{2}.png".\ format(algorithm_name, number_of_stars, int(current_time.value_in(units.Myr))) stellar.evolve_model(current_time) temperatures = stars.temperature luminosities = stars.luminosity times.append(current_time) luminosity_at_time.append(luminosities) temperatures_at_time.append(temperatures) mass_at_time.append(stars.total_mass()) print current_time plot_HR_diagram(temperatures, luminosities, cluster+"/", name_of_the_figure, current_time) current_time += 10 | units.Myr print "Evolved model successfully." stellar.stop() print "All done!" data['times'] = times data['luminosity_at_time'] = luminosity_at_time data['temperatures_at_time'] = temperatures_at_time data['mass_at_time'] = mass_at_time print data pickle.dump(data, open(cluster+"/assignment2b.dat", "wb"))