def simulate_evolution_tracks(): stellar_evolution = SSE() star = datamodel.Particle() star.mass = stellar_mass star = stellar_evolution.particles.add_particle(star) luminosity_at_time = [] | units.LSun temperature_at_time = [] | units.K print("Evolving a star with mass:", stellar_mass) is_evolving = True while is_evolving and star.age < end_time: luminosity_at_time.append(star.luminosity) temperature_at_time.append(star.temperature) previous_age = star.age # if we do not specify an end_time in the evolve_model function # a stellar evolution code will evolve to the next # 'natural' timestep, this will ensure all interesting physics # is seen in the hr diagram stellar_evolution.evolve_model() is_evolving = (star.age != previous_age) stellar_evolution.stop() return temperature_at_time, luminosity_at_time
def plottillagb(): sun = datamodel.Particle( mass = 1 | units.MSun, radius = 1 | units.RSun ) sse = SSE() sse.particles.add_particle(sun) channel_from_se_to_memory = sse.particles.new_channel_to(sun.as_set()) channel_from_se_to_memory.copy() masses = []|units.MSun timerange = numpy.arange(11500, 13500,10) | units.Myr for time in timerange: sse.evolve_model(time) channel_from_se_to_memory.copy() masses.append(sun.mass) print(time.as_quantity_in(units.Myr), sun.mass.as_quantity_in(units.MSun)) sse.stop() figure = pyplot.figure(figsize= (6,6)) subplot = figure.add_subplot(1, 1, 1) subplot.plot(timerange.value_in(units.Gyr), masses.value_in(units.MSun),'.') subplot.set_xlabel('t (Gyr)') subplot.set_ylabel('mass (MSun)') pyplot.show()
def test6(self): print "Test whether a set of stars evolves synchronously..." # Create an array of stars with a range in stellar mass masses = [.5, 1., 2., 5., 10., 30.] | units.MSun number_of_stars = len(masses) stars = Particles(number_of_stars) stars.mass = masses # Initialize stellar evolution code instance = SSE() instance.commit_parameters() instance.particles.add_particles(stars) instance.commit_particles() from_code_to_model = instance.particles.new_channel_to(stars) from_code_to_model.copy() instance.evolve_model(end_time = 125 | units.Myr) from_code_to_model.copy() end_types = ( "deeply or fully convective low mass MS star", "Main Sequence star", "Main Sequence star", "Carbon/Oxygen White Dwarf", "Neutron Star", "Black Hole", ) for i in range(number_of_stars): self.assertAlmostEquals(stars[i].age, 125.0 | units.Myr) self.assertTrue(stars[i].mass <= masses[i]) self.assertEquals(str(stars[i].stellar_type), end_types[i]) instance.stop()
def test5(self): sse = SSE() sse.commit_parameters() stars = Particles(1) star = stars[0] star.mass = 35 | units.MSun star.radius = 0.0 | units.RSun stars.synchronize_to(sse.particles) channel = sse.particles.new_channel_to(stars) channel.copy_attributes(sse.particles.get_attribute_names_defined_in_store()) previous_type = star.stellar_type results = [] dt = 1 | units.Myr t = 0 | units.Myr while t < 30 | units.Myr: t += dt sse.evolve_model(t) self.assertTrue(sse.particles[0].mass.value_in(units.MSun) < 10.6) sse.stop()
def test19(self): print("SSE core_mass and CO_core_mass (high mass star)") instance = SSE() star = instance.particles.add_particle(Particle(mass = 30 | units.MSun)) instance.evolve_model(5.8 | units.Myr) print(star.mass, star.core_mass, star.CO_core_mass, star.stellar_type) self.assertEqual(str(star.stellar_type), "Main Sequence star") self.assertIsOfOrder(star.mass, 30 | units.MSun) self.assertEqual(star.core_mass, 0 | units.MSun) self.assertEqual(star.CO_core_mass, 0 | units.MSun) instance.evolve_model(6.0 | units.Myr) print(star.mass, star.core_mass, star.CO_core_mass, star.stellar_type) self.assertEqual(str(star.stellar_type), "Core Helium Burning") self.assertIsOfOrder(star.mass, 30 | units.MSun) self.assertIsOfOrder(star.core_mass, 10 | units.MSun) self.assertEqual(star.CO_core_mass, 0 | units.MSun) instance.evolve_model(6.5 | units.Myr) print(star.mass, star.core_mass, star.CO_core_mass, star.stellar_type) self.assertEqual(str(star.stellar_type), "Main Sequence Naked Helium star") self.assertIsOfOrder(star.mass, 10 | units.MSun) self.assertEqual(star.core_mass, star.mass) self.assertEqual(star.CO_core_mass, 0 | units.MSun) instance.evolve_model(6.65 | units.Myr) print(star.mass, star.core_mass, star.CO_core_mass, star.stellar_type) self.assertEqual(str(star.stellar_type), "Hertzsprung Gap Naked Helium star") self.assertIsOfOrder(star.mass, 10 | units.MSun) self.assertEqual(star.core_mass, star.mass) self.assertAlmostEqual(star.CO_core_mass, 7.12 | units.MSun, 2) instance.evolve_model(7.0 | units.Myr) print(star.mass, star.core_mass, star.CO_core_mass, star.stellar_type) self.assertEqual(str(star.stellar_type), "Black Hole") self.assertIsOfOrder(star.mass, 10 | units.MSun) self.assertEqual(star.core_mass, star.mass) self.assertEqual(star.CO_core_mass, star.mass) instance.stop()
def test19(self): print "SSE core_mass and CO_core_mass (high mass star)" instance = SSE() star = instance.particles.add_particle(Particle(mass = 30 | units.MSun)) instance.evolve_model(5.8 | units.Myr) print star.mass, star.core_mass, star.CO_core_mass, star.stellar_type self.assertEqual(str(star.stellar_type), "Main Sequence star") self.assertIsOfOrder(star.mass, 30 | units.MSun) self.assertEqual(star.core_mass, 0 | units.MSun) self.assertEqual(star.CO_core_mass, 0 | units.MSun) instance.evolve_model(6.0 | units.Myr) print star.mass, star.core_mass, star.CO_core_mass, star.stellar_type self.assertEqual(str(star.stellar_type), "Core Helium Burning") self.assertIsOfOrder(star.mass, 30 | units.MSun) self.assertIsOfOrder(star.core_mass, 10 | units.MSun) self.assertEqual(star.CO_core_mass, 0 | units.MSun) instance.evolve_model(6.5 | units.Myr) print star.mass, star.core_mass, star.CO_core_mass, star.stellar_type self.assertEqual(str(star.stellar_type), "Main Sequence Naked Helium star") self.assertIsOfOrder(star.mass, 10 | units.MSun) self.assertEqual(star.core_mass, star.mass) self.assertEqual(star.CO_core_mass, 0 | units.MSun) instance.evolve_model(6.65 | units.Myr) print star.mass, star.core_mass, star.CO_core_mass, star.stellar_type self.assertEqual(str(star.stellar_type), "Hertzsprung Gap Naked Helium star") self.assertIsOfOrder(star.mass, 10 | units.MSun) self.assertEqual(star.core_mass, star.mass) self.assertAlmostEqual(star.CO_core_mass, 7.12 | units.MSun, 2) instance.evolve_model(7.0 | units.Myr) print star.mass, star.core_mass, star.CO_core_mass, star.stellar_type self.assertEqual(str(star.stellar_type), "Black Hole") self.assertIsOfOrder(star.mass, 10 | units.MSun) self.assertEqual(star.core_mass, star.mass) self.assertEqual(star.CO_core_mass, star.mass) instance.stop()
def test3(self): sse = SSE() sse.commit_parameters() stars = Particles(1) star = stars[0] star.mass = 5 | units.MSun star.radius = 0.0 | units.RSun stars.synchronize_to(sse.particles) channel = sse.particles.new_channel_to(stars) channel.copy_attributes( sse.particles.get_attribute_names_defined_in_store()) previous_type = sse.particles.stellar_type results = [] sse.evolve_model(121.5 | units.Myr) channel.copy_attributes( sse.particles.get_attribute_names_defined_in_store()) self.assertAlmostEqual(star.mass.value_in(units.MSun), 0.997, 3) sse.stop()
def test5(self): sse = SSE() sse.commit_parameters() stars = Particles(1) star = stars[0] star.mass = 35 | units.MSun star.radius = 0.0 | units.RSun stars.synchronize_to(sse.particles) channel = sse.particles.new_channel_to(stars) channel.copy_attributes( sse.particles.get_attribute_names_defined_in_store()) previous_type = star.stellar_type results = [] dt = 1 | units.Myr t = 0 | units.Myr while t < 30 | units.Myr: t += dt sse.evolve_model(t) self.assertTrue(sse.particles[0].mass.value_in(units.MSun) < 10.6) sse.stop()
def test6(self): print("Test whether a set of stars evolves synchronously...") # Create an array of stars with a range in stellar mass masses = [.5, 1., 2., 5., 10., 30.] | units.MSun number_of_stars = len(masses) stars = Particles(number_of_stars) stars.mass = masses # Initialize stellar evolution code instance = SSE() instance.commit_parameters() instance.particles.add_particles(stars) instance.commit_particles() from_code_to_model = instance.particles.new_channel_to(stars) from_code_to_model.copy() instance.evolve_model(end_time=125 | units.Myr) from_code_to_model.copy() end_types = ( "deeply or fully convective low mass MS star", "Main Sequence star", "Main Sequence star", "Carbon/Oxygen White Dwarf", "Neutron Star", "Black Hole", ) for i in range(number_of_stars): self.assertAlmostEqual(stars[i].age, 125.0 | units.Myr) self.assertTrue(stars[i].mass <= masses[i]) self.assertEqual(str(stars[i].stellar_type), end_types[i]) instance.stop()
def plottillagb(): sun = datamodel.Particle( mass=1 | units.MSun, radius=1 | units.RSun ) sse = SSE() sse.particles.add_particle(sun) channel_from_se_to_memory = sse.particles.new_channel_to(sun.as_set()) channel_from_se_to_memory.copy() masses = [] | units.MSun timerange = numpy.arange(11500, 13500, 10) | units.Myr for time in timerange: sse.evolve_model(time) channel_from_se_to_memory.copy() masses.append(sun.mass) print(time.as_quantity_in(units.Myr), sun.mass.as_quantity_in(units.MSun)) sse.stop() figure = pyplot.figure(figsize=(6, 6)) subplot = figure.add_subplot(1, 1, 1) subplot.plot(timerange.value_in(units.Gyr), masses.value_in(units.MSun), '.') subplot.set_xlabel('t (Gyr)') subplot.set_ylabel('mass (MSun)') pyplot.show()
def evolve_to_age(stars, age, se="SSE"): if se == "SSE": se = SSE() se.particles.add_particles(stars) se.evolve_model(age) stars.luminosity = se.particles.luminosity stars.radius = se.particles.radius se.stop() return
def test1(self): sse = SSE() sse.commit_parameters() stars = Particles(1) star = stars[0] star.mass = 5 | units.MSun star.radius = 0.0 | units.RSun sse.particles.add_particles(stars) from_sse_to_model = sse.particles.new_channel_to(stars) from_sse_to_model.copy() previous_type = star.stellar_type results = [] t0 = 0 | units.Myr current_time = t0 while current_time < (125 | units.Myr): sse.update_time_steps() current_time = current_time + sse.particles[0].time_step sse.evolve_model(current_time) from_sse_to_model.copy() if not star.stellar_type == previous_type: results.append((star.age, star.mass, star.stellar_type)) previous_type = star.stellar_type self.assertEqual(len(results), 6) times = (104.0 | units.Myr, 104.4 | units.Myr, 104.7 | units.Myr, 120.1 | units.Myr, 120.9 | units.Myr, 121.5 | units.Myr) for result, expected in zip(results, times): self.assertAlmostEqual(result[0].value_in(units.Myr), expected.value_in(units.Myr), 1) masses = (5.000 | units.MSun, 5.000 | units.MSun, 4.998 | units.MSun, 4.932 | units.MSun, 4.895 | units.MSun, 0.997 | units.MSun) for result, expected in zip(results, masses): self.assertAlmostEqual(result[1].value_in(units.MSun), expected.value_in(units.MSun), 3) types = ( "Hertzsprung Gap", "First Giant Branch", "Core Helium Burning", "First Asymptotic Giant Branch", "Second Asymptotic Giant Branch", "Carbon/Oxygen White Dwarf", ) for result, expected in zip(results, types): self.assertEqual(str(result[2]), expected) sse.stop()
def test21(self): instance = SSE() stars = instance.particles.add_particles(Particles(mass = 30 | units.MSun)) mass_loss_wind = stars[0].mass_loss_wind self.assertAlmostRelativeEquals(mass_loss_wind, 1.703e-07 | units.MSun / units.yr, 3) instance.evolve_model(1 | units.Myr) dm = (1 | units.Myr)* mass_loss_wind self.assertAlmostRelativeEquals(stars[0].mass, (30 | units.MSun) - dm , 3) self.assertAlmostRelativeEquals(stars[0].mass_loss_wind, 2.053e-07 | units.MSun / units.yr, 3) instance.stop()
def test22(self): instance = SSE() stars = instance.particles.add_particles(Particles(mass = [1.0, 10.0] | units.MSun)) gyration_radius = stars.gyration_radius self.assertTrue(numpy.all(0.0 < gyration_radius)) self.assertTrue(numpy.all(gyration_radius < 1.0)) instance.evolve_model(12.4 | units.Gyr) self.assertTrue(stars[0].gyration_radius < gyration_radius[0]) self.assertTrue(stars[1].gyration_radius > gyration_radius[1]) instance.evolve_model(14 | units.Gyr) self.assertTrue(numpy.all(stars.gyration_radius > gyration_radius)) instance.stop()
def stellar_lifetime(mZAMS, z=0.02): global se if se is None: se = SSE() se.parameters.metallicity = z se.particles.add_particle(Particle(mass=mZAMS)) while not stellar_remnant_state(se.particles[0]): se.evolve_model() t_end = se.particles[0].age # tpe = se.particles[0].stellar_type se.particles.remove_particle(se.particles[0]) return t_end
def test12(self): print "Testing adding and removing particles from stellar evolution code..." particles = Particles(3) particles.mass = 1.0 | units.MSun instance = SSE() instance.initialize_code() instance.commit_parameters() self.assertEquals(len(instance.particles), 0) # before creation instance.particles.add_particles(particles[:-1]) instance.commit_particles() instance.evolve_model(1.0 | units.Myr) self.assertEquals(len(instance.particles), 2) # before remove self.assertAlmostEqual(instance.particles.age, 1.0 | units.Myr) instance.particles.remove_particle(particles[0]) self.assertEquals(len(instance.particles), 1) instance.evolve_model(2.0 | units.Myr) self.assertAlmostEqual(instance.particles[0].age, 2.0 | units.Myr) instance.particles.add_particles(particles[::2]) self.assertEquals(len(instance.particles), 3) # it's back... self.assertAlmostEqual(instance.particles[0].age, 2.0 | units.Myr) self.assertAlmostEqual(instance.particles[1].age, 0.0 | units.Myr) self.assertAlmostEqual(instance.particles[2].age, 0.0 | units.Myr) # ... and rejuvenated. instance.evolve_model(3.0 | units.Myr) # The young stars keep their age offset from the old star self.assertAlmostEqual(instance.particles.age, [3.0, 1.0, 1.0] | units.Myr) instance.evolve_model(4.0 | units.Myr) self.assertAlmostEqual(instance.particles.age, [4.0, 2.0, 2.0] | units.Myr) instance.stop()
def test20(self): print("SSE core_mass and CO_core_mass (low mass stars)") instance = SSE() stars = instance.particles.add_particles(Particles(mass = [0.6, 1.0] | units.MSun)) instance.evolve_model(100 | units.Gyr) self.assertEqual(str(stars[0].stellar_type), "Helium White Dwarf") self.assertAlmostEqual(stars[0].mass, 0.405 | units.MSun, 2) self.assertEqual(stars[0].core_mass, stars[0].mass) self.assertEqual(stars[0].CO_core_mass, 0 | units.MSun) self.assertEqual(str(stars[1].stellar_type), "Carbon/Oxygen White Dwarf") self.assertAlmostEqual(stars[1].mass, 0.520 | units.MSun, 2) self.assertEqual(stars[1].core_mass, stars[1].mass) self.assertEqual(stars[1].CO_core_mass, stars[1].mass) instance.stop()
def test20(self): print "SSE core_mass and CO_core_mass (low mass stars)" instance = SSE() stars = instance.particles.add_particles(Particles(mass = [0.6, 1.0] | units.MSun)) instance.evolve_model(100 | units.Gyr) self.assertEqual(str(stars[0].stellar_type), "Helium White Dwarf") self.assertAlmostEqual(stars[0].mass, 0.405 | units.MSun, 2) self.assertEqual(stars[0].core_mass, stars[0].mass) self.assertEqual(stars[0].CO_core_mass, 0 | units.MSun) self.assertEqual(str(stars[1].stellar_type), "Carbon/Oxygen White Dwarf") self.assertAlmostEqual(stars[1].mass, 0.520 | units.MSun, 2) self.assertEqual(stars[1].core_mass, stars[1].mass) self.assertEqual(stars[1].CO_core_mass, stars[1].mass) instance.stop()
def test12(self): print("Testing adding and removing particles from stellar evolution code...") particles = Particles(3) particles.mass = 1.0 | units.MSun instance = SSE() instance.initialize_code() instance.commit_parameters() self.assertEqual(len(instance.particles), 0) # before creation instance.particles.add_particles(particles[:-1]) instance.commit_particles() instance.evolve_model(1.0 | units.Myr) self.assertEqual(len(instance.particles), 2) # before remove self.assertAlmostEqual(instance.particles.age, 1.0 | units.Myr) instance.particles.remove_particle(particles[0]) self.assertEqual(len(instance.particles), 1) instance.evolve_model(2.0 | units.Myr) self.assertAlmostEqual(instance.particles[0].age, 2.0 | units.Myr) instance.particles.add_particles(particles[::2]) self.assertEqual(len(instance.particles), 3) # it's back... self.assertAlmostEqual(instance.particles[0].age, 2.0 | units.Myr) self.assertAlmostEqual(instance.particles[1].age, 0.0 | units.Myr) self.assertAlmostEqual(instance.particles[2].age, 0.0 | units.Myr) # ... and rejuvenated. instance.evolve_model(3.0 | units.Myr) # The young stars keep their age offset from the old star self.assertAlmostEqual(instance.particles.age, [3.0, 1.0, 1.0] | units.Myr) instance.evolve_model(4.0 | units.Myr) self.assertAlmostEqual(instance.particles.age, [4.0, 2.0, 2.0] | units.Myr) instance.stop()
def test2(self): sse = SSE() sse.commit_parameters() stars = Particles(1) star = stars[0] star.mass = 5 | units.MSun star.radius = 0.0 | units.RSun sse.particles.add_particles(stars) sse.evolve_model(120.1 | units.Myr) self.assertAlmostEqual(sse.particles[0].mass.value_in(units.MSun), 4.932, 3) self.assertAlmostEqual(sse.particles[0].temperature.value_in(units.K), 4221., 0) sse.stop()
def get_stellar_radius(star, SEVCode = None): if SEVCode == None: sev_code = SSE() else: sev_code = SEVCode temp_star = Particle() temp_star.mass = star.mass temp_star.age = star.time sev_code.particles.add_particle(temp_star) sev_code.model_time = star.time sev_code.evolve_model(star.time) radius = sev_code.particles[0].radius print(radius, sev_code.particles[0].age) if SEVCode == None: sev_code.stop() else: sev_code.particles.remove_particle(temp_star) return radius
def test7(self): print "Test: evolve particles one at a time." print "Used to be problematic, since initial_mass of idle particle is set to zero." stars = Particles(2) stars.mass = 1.0 | units.MSun for star in stars: print star stellar_evolution = SSE() stellar_evolution.commit_parameters() stellar_evolution.particles.add_particles(star.as_set()) stellar_evolution.commit_particles() from_stellar_evolution_to_model = stellar_evolution.particles.new_channel_to(star.as_set()) stellar_evolution.evolve_model() from_stellar_evolution_to_model.copy() stellar_evolution.stop() self.assertEquals(stars[0].initial_mass, stars[1].initial_mass) self.assertEquals(stars[0].luminosity, stars[1].luminosity) self.assertEquals(stars[0].age, stars[1].age) print "Solved: SSE_muse_interface.f sets initial_mass to mass when necessary."
def test7(self): print("Test: evolve particles one at a time.") print("Used to be problematic, since initial_mass of idle particle is set to zero.") stars = Particles(2) stars.mass = 1.0 | units.MSun for star in stars: print(star) stellar_evolution = SSE() stellar_evolution.commit_parameters() stellar_evolution.particles.add_particles(star.as_set()) stellar_evolution.commit_particles() from_stellar_evolution_to_model = stellar_evolution.particles.new_channel_to(star.as_set()) stellar_evolution.evolve_model() from_stellar_evolution_to_model.copy() stellar_evolution.stop() self.assertEqual(stars[0].initial_mass, stars[1].initial_mass) self.assertEqual(stars[0].luminosity, stars[1].luminosity) self.assertEqual(stars[0].age, stars[1].age) print("Solved: SSE_muse_interface.f sets initial_mass to mass when necessary.")
def test11(self): print("Test evolve_model optional arguments: end_time and keep_synchronous") stars = Particles(3) stars.mass = [1.0, 2.0, 3.0] | units.MSun instance = SSE() instance.commit_parameters() instance.particles.add_particles(stars) self.assertEqual(instance.particles.age, [0.0, 0.0, 0.0] | units.yr) self.assertAlmostEqual(instance.particles.time_step, [550.1565, 58.2081, 18.8768] | units.Myr, 3) self.assertAlmostEqual(instance.particles.radius, [0.8882494502, 1.610210385, 1.979134445] | units.RSun) print("evolve_model without arguments: use shared timestep = min(particles.time_step)") instance.evolve_model() self.assertAlmostEqual(instance.particles.age, [18.8768, 18.8768, 18.8768] | units.Myr, 3) self.assertAlmostEqual(instance.particles.time_step, [550.1565, 58.2081, 18.8768] | units.Myr, 3) self.assertAlmostEqual(instance.model_time, 18.8768 | units.Myr, 3) print("evolve_model with end_time: take timesteps, until end_time is reached exactly") instance.evolve_model(100 | units.Myr) self.assertAlmostEqual(instance.particles.age, [100.0, 100.0, 100.0] | units.Myr, 3) self.assertAlmostEqual(instance.particles.time_step, [550.1565, 58.2081, 18.8768] | units.Myr, 3) self.assertAlmostEqual(instance.model_time, 100.0 | units.Myr, 3) print("evolve_model with keep_synchronous: use non-shared timestep, particle ages will typically diverge") instance.evolve_model(keep_synchronous = False) self.assertAlmostEqual(instance.particles.age, (100 | units.Myr) + ([550.1565, 58.2081, 18.8768] | units.Myr), 3) self.assertAlmostEqual(instance.particles.time_step, [550.1565, 58.2081, 18.8768] | units.Myr, 3) self.assertAlmostEqual(instance.model_time, 100.0 | units.Myr, 3) # Unchanged! instance.stop()
def test11(self): print "Test evolve_model optional arguments: end_time and keep_synchronous" stars = Particles(3) stars.mass = [1.0, 2.0, 3.0] | units.MSun instance = SSE() instance.commit_parameters() instance.particles.add_particles(stars) self.assertEqual(instance.particles.age, [0.0, 0.0, 0.0] | units.yr) self.assertAlmostEqual(instance.particles.time_step, [550.1565, 58.2081, 18.8768] | units.Myr, 3) self.assertAlmostEqual(instance.particles.radius, [0.8882494502, 1.610210385, 1.979134445] | units.RSun) print "evolve_model without arguments: use shared timestep = min(particles.time_step)" instance.evolve_model() self.assertAlmostEqual(instance.particles.age, [18.8768, 18.8768, 18.8768] | units.Myr, 3) self.assertAlmostEqual(instance.particles.time_step, [550.1565, 58.2081, 18.8768] | units.Myr, 3) self.assertAlmostEqual(instance.model_time, 18.8768 | units.Myr, 3) print "evolve_model with end_time: take timesteps, until end_time is reached exactly" instance.evolve_model(100 | units.Myr) self.assertAlmostEqual(instance.particles.age, [100.0, 100.0, 100.0] | units.Myr, 3) self.assertAlmostEqual(instance.particles.time_step, [550.1565, 58.2081, 18.8768] | units.Myr, 3) self.assertAlmostEqual(instance.model_time, 100.0 | units.Myr, 3) print "evolve_model with keep_synchronous: use non-shared timestep, particle ages will typically diverge" instance.evolve_model(keep_synchronous = False) self.assertAlmostEqual(instance.particles.age, (100 | units.Myr) + ([550.1565, 58.2081, 18.8768] | units.Myr), 3) self.assertAlmostEqual(instance.particles.time_step, [550.1565, 58.2081, 18.8768] | units.Myr, 3) self.assertAlmostEqual(instance.model_time, 100.0 | units.Myr, 3) # Unchanged! instance.stop()
def test3(self): sse = SSE() sse.commit_parameters() stars = Particles(1) star = stars[0] star.mass = 5 | units.MSun star.radius = 0.0 | units.RSun stars.synchronize_to(sse.particles) channel = sse.particles.new_channel_to(stars) channel.copy_attributes(sse.particles.get_attribute_names_defined_in_store()) previous_type = sse.particles.stellar_type results = [] sse.evolve_model(121.5 | units.Myr) channel.copy_attributes(sse.particles.get_attribute_names_defined_in_store()) self.assertAlmostEqual(star.mass.value_in(units.MSun), 0.997, 3) sse.stop()
def planetplot(): sun, planets = new_solar_system_for_mercury() initial = 12.2138 | units.Gyr final = 12.3300 | units.Gyr step = 10000.0 | units.yr timerange = VectorQuantity.arange(initial, final, step) gd = MercuryWayWard() gd.initialize_code() # gd.stopping_conditions.timeout_detection.disable() gd.central_particle.add_particles(sun) gd.orbiters.add_particles(planets) gd.commit_particles() se = SSE() # se.initialize_code() se.commit_parameters() se.particles.add_particles(sun) se.commit_particles() channelp = gd.orbiters.new_channel_to(planets) channels = se.particles.new_channel_to(sun) for time in timerange: err = gd.evolve_model(time-initial) channelp.copy() # planets.savepoint(time) err = se.evolve_model(time) channels.copy() gd.central_particle.mass = sun.mass print( sun[0].mass.value_in(units.MSun), time.value_in(units.Myr), planets[4].x.value_in(units.AU), planets[4].y.value_in(units.AU), planets[4].z.value_in(units.AU) ) gd.stop() se.stop() for planet in planets: t, x = planet.get_timeline_of_attribute_as_vector("x") t, y = planet.get_timeline_of_attribute_as_vector("y") plot(x, y, '.') native_plot.gca().set_aspect('equal') native_plot.show()
def planetplot(): sun, planets = new_solar_system_for_mercury() initial = 12.2138 | units.Gyr final = 12.3300 | units.Gyr step = 10000.0 | units.yr timerange = VectorQuantity.arange(initial, final, step) gd = MercuryWayWard() gd.initialize_code() # gd.stopping_conditions.timeout_detection.disable() gd.central_particle.add_particles(sun) gd.orbiters.add_particles(planets) gd.commit_particles() se = SSE() # se.initialize_code() se.commit_parameters() se.particles.add_particles(sun) se.commit_particles() channelp = gd.orbiters.new_channel_to(planets) channels = se.particles.new_channel_to(sun) for time in timerange: err = gd.evolve_model(time - initial) channelp.copy() # planets.savepoint(time) err = se.evolve_model(time) channels.copy() gd.central_particle.mass = sun.mass print( (sun[0].mass.value_in(units.MSun), time.value_in(units.Myr), planets[4].x.value_in(units.AU), planets[4].y.value_in(units.AU), planets[4].z.value_in(units.AU))) gd.stop() se.stop() for planet in planets: t, x = planet.get_timeline_of_attribute_as_vector("x") t, y = planet.get_timeline_of_attribute_as_vector("y") plot(x, y, '.') native_plot.gca().set_aspect('equal') native_plot.show()
def evolve_model(self, tend): if not hasattr(self.particles, 'Emech'): self.particles.Lmech = lmech(self.particles) self.particles.Emech = (0. | units.Myr) * self.particles.Lmech stellar_type = self.particles.stellar_type.copy() prev_lm = self.particles.Lmech.copy() ret = SSE.evolve_model(self, tend) tend = self.model_time if tend > self.mech_time: dt = tend - self.mech_time self.mech_time = tend lm = lmech(self.particles) self.particles.Lmech = lm.copy() self.particles.Emech=self.particles.Emech+dt*(prev_lm+lm)/2. + \ e_supernova(self.particles.stellar_type,stellar_type) return ret
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: print("\t", t, "\t", mm.as_quantity_in(units.MSun), " \t ", dmm_dt.as_quantity_in(units.MSun / units.Myr))
def run(self, run_num): print("Setting up run %d..." % (run_num)) # Create group for run run_group = self.hdf5_file.create_group(str(run_num)) # create nbody converter thing? convert_nbody = nbody_system.nbody_to_si(100.0 | units.MSun, 1 | units.parsec) # initialize particle datamodel stars = Particles() print(" Initializing and populating clusters...") # populate/initialize clusters, add to particle model for c in self.clusters: c.populate() stars.add_particles(c.plummer) print(" Done!") # initialize codes # initialize hermite print(" Initializing hermite...") hermite_code = Hermite(convert_nbody) hermite_code.particles.add_particles(stars) detect_coll = hermite_code.stopping_conditions.collision_detection detect_coll.enable() print(" Done!") print(" Initializing SSE...") sse_code = SSE() sse_code.particles.add_particles(stars) print("Done!\n") # actually run the simulation! print("===== Run #%d =====" % (run_num)) t = 0 # time i = 1 # iteration num c = 1 # collision num while(t < self.runtime): print(" Time (Myr): %d" % (t)) print(" Simulating...") # evolve model hermite_code.evolve_model(t | units.Myr) sse_code.evolve_model(t | units.Myr) hermite_code.particles.copy_values_of_attribute_to("position", sse_code.particles) sse_code.particles.synchronize_to(hermite_code.particles) if detect_coll.is_set(): print("Detected a collision!!") print(detect_coll.particles(0)) coll_f = open(sub_folder + "/collision-" + str(c) + "_time" + str(t) + ".txt") coll_f.write( detect_coll.particles(0) ) coll_f.close() c += 1 # somehow put a log # also... eventually, "pause" the rest of the simulation and simulate the collision somehow #sse_code.particles.copy_values_of_attribute_to("mass", hermite_code.particles) #sse_code.particles.copy_values_of_attribute_to("stellar_type", hermite_code.particles) #sse_code.particles.copy_values_of_attribute_to("age", hermite_code.particles) #sse_code.particles.copy_values_of_attribute_to("luminosity", hermite_code.particles) #sse_code.particles.copy_values_of_attribute_to("temperature", hermite_code.particles) #sse_code.particles.copy_values_of_attribute_to("radius", hermite_code.particles) hermite_code.particles.mass = sse_code.particles.mass print(" Done.") # output to csv print(" Outputting to HDF5...") #file_name = sub_folder + "/data-" + str(i) + "_time-" + str(t) + ".txt" self.write_to_hdf5_file(run_group, i, t, stars) print(" Done.") #print(" Creating plot...") #plot_name = "System at " + str(t) + " Myr" #plot_path = sub_folder + "/plot-" + str(i) + "_time-" + str(t) + ".png" #plot_data(plot_name, plot_path, hermite_code.particles) #print(" Done.") t += self.timestep i += 1 print("Run complete.\n")
stars = read_set_from_file( starsfilename, filetype, close_file=True, ) if stellar_evolution: print( "Calculating luminosity/temperature for %s old stars..." % (age) ) from amuse.community.sse.interface import SSE se = SSE() se.particles.add_particles(stars) if age > 0 | units.Myr: se.evolve_model(age) stars.luminosity = se.particles.luminosity stars.radius = se.particles.radius se.stop() com = stars.center_of_mass() stars.position -= com if fieldstars: for age in np.array([400, 600, 800, 1600, 3200, 6400]) | units.Myr: fieldstars = new_field_stars( int(len(stars)/3), width=image_width, height=image_width, ) evolve_to_age(fieldstars, age) # TODO: add distance modulus
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 evolve_cluster_in_galaxy(N, Rcluster, Rinit, Vinit, galaxy_code, dt, dtout, tend, epsilon): #Setup cluster masses = new_kroupa_mass_distribution(N) Mcluster = masses.sum() #Create star cluster with origin at 0,0,0 and no net velocity converter = nbody_system.nbody_to_si(Mcluster, Rcluster) stars = new_plummer_sphere(N, converter) #Place star cluster in Galactocentric position stars.x += Rinit[0] stars.y += Rinit[1] stars.z += Rinit[2] stars.vx += Vinit[0] stars.vy += Vinit[1] stars.vz += Vinit[2] stars.mass = masses stars.scale_to_standard(convert_nbody=converter, smoothing_length_squared=epsilon**2) #Gravity code cluster_code = BHTree( converter, number_of_workers=1 ) #Change number of workers depending on CPUS available cluster_code.parameters.epsilon_squared = epsilon**2 cluster_code.parameters.opening_angle = 0.6 cluster_code.parameters.timestep = dt #cluster_code.particles.add_particles(stars) #Setup channels between stars particle dataset and the cluster code channel_from_stars_to_cluster_code = stars.new_channel_to( cluster_code.particles, attributes=["mass", "x", "y", "z", "vx", "vy", "vz"]) channel_from_cluster_code_to_stars = cluster_code.particles.new_channel_to( stars, attributes=["mass", "x", "y", "z", "vx", "vy", "vz"]) #Stellar evolution code stellar_evolution = SSE() stellar_evolution.particles.add_particle(stars) #Setup channels between stars particle dataset and stellar evolution code channel_from_stars_to_stellar_evolution = stars.new_channel_to( stellar_evolution.particles, attributes=["mass"]) channel_from_stellar_evolution_to_stars = stellar_evolution.particles.new_channel_to( stars, attributes=["mass"]) #Setup gravity bridge gravity = bridge.Bridge(use_threading=False) #stars in cluster_code depend on gravity from galaxy_code gravity.add_system(cluster_code, (galaxy_code, )) #galaxy_code still needs to be added to system so it evolves with time gravity.add_system(galaxy_code, ) #Set how often to update external potential gravity.timestep = cluster_code.parameters.timestep / 2. time = 0.0 | tend.unit first = True while time < tend: print(time.value_in(units.Myr), tend.value_in(units.Myr), stars.mass.sum().value_in(units.MSun)) stellar_evolution.evolve_model(time + dt / 2.) channel_from_stellar_evolution_to_stars.copy_attributes(["mass"]) if first: cluster_code.particles.add_particles(stars) first = False else: channel_from_stars_to_cluster_code.copy_attributes(["mass"]) gravity.evolve_model(time + dt) channel_from_cluster_code_to_stars.copy() stellar_evolution.evolve_model(time + dt) channel_from_stellar_evolution_to_stars.copy_attributes(["mass"]) channel_from_stars_to_cluster_code.copy_attributes(["mass"]) #You need to copy stars from cluster_code to output or analyse: #channel_from_cluster_code_to_stars.copy() #Output/Analyse #If you edited the stars particle set, lets say to remove stars from the array because they have #been kicked far from the cluster, you need to copy the array back to cluster_code: #channel_from_stars_to_cluster_code.copy() time = gravity.model_time #Copy back to stars for final dataset channel_from_cluster_code_to_stars.copy() gravity.stop() 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 test1(self): sse = SSE() sse.commit_parameters() stars = Particles(1) star = stars[0] star.mass = 5 | units.MSun star.radius = 0.0 | units.RSun sse.particles.add_particles(stars) from_sse_to_model = sse.particles.new_channel_to(stars) from_sse_to_model.copy() previous_type = star.stellar_type results = [] t0 = 0 | units.Myr current_time = t0 while current_time < (125 | units.Myr): sse.update_time_steps() current_time = current_time + sse.particles[0].time_step sse.evolve_model(current_time) from_sse_to_model.copy() if not star.stellar_type == previous_type: results.append((star.age, star.mass, star.stellar_type)) previous_type = star.stellar_type self.assertEqual(len(results), 6) times = ( 104.0 | units.Myr, 104.4 | units.Myr, 104.7 | units.Myr, 120.1 | units.Myr, 120.9 | units.Myr, 121.5 | units.Myr ) for result, expected in zip(results, times): self.assertAlmostEqual(result[0].value_in(units.Myr), expected.value_in(units.Myr), 1) masses = ( 5.000 | units.MSun, 5.000 | units.MSun, 4.998 | units.MSun, 4.932 | units.MSun, 4.895 | units.MSun, 0.997 | units.MSun ) for result, expected in zip(results, masses): self.assertAlmostEqual(result[1].value_in(units.MSun), expected.value_in(units.MSun), 3) types = ( "Hertzsprung Gap", "First Giant Branch", "Core Helium Burning", "First Asymptotic Giant Branch", "Second Asymptotic Giant Branch", "Carbon/Oxygen White Dwarf", ) for result, expected in zip(results, types): self.assertEquals(str(result[2]), expected) sse.stop()
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: print("\t", t, "\t", mm.as_quantity_in(units.MSun), " \t ", dmm_dt.as_quantity_in(units.MSun/units.Myr))
def main_function(number_of_stars=1000, end_time=4.0e4 | units.yr, steps=100, number_of_workers=6, animate=True, save_animation=False, escape=False, Q=0.5, D=2.6, filename="default.mp4", use_huayno=False, use_tree=False): """ Simulates a cluster of stars with varying masses. Input: :param number_of_stars: Number of stars to simulate, default: 1000 :param end_time: Total time at which to stop in nbody_system.time units (I think), default 10 | nbody_system.time :param steps: Total number of steps to save, default: 1000 :param number_of_workers: Number of cores/threads to use, does nothing when using Huayno, default: 5 :param animate: Makes an animation of the stars at each step (size depends on star mass), default: True :param save_animation: Saves the animation as mp4 file, default: True :param Q: Kinectic to potential energy fraction (I think) default: 0.5 :param D: Measure of fragmentedness, must be between 1.5 and 3, default 2.6 :param filename: Determines the name of the mp4 file, default: "default.mp4" :param use_huayno: Use alternative Huayno gravity evolver, default: False :return: (array of position arrays at each time step, array of time at each time step) """ start_time = clock_time() particles = new_cluster(number_of_stars=number_of_stars, Q=Q, D=D) total_mass = particles.mass.sum() convert_nbody = nbody_system.nbody_to_si(total_mass, 1.0 | units.parsec) # Initialize gravity can use others for tests, but hermite is used if use_huayno: gravity = Huayno(convert_nbody, number_of_workers=number_of_workers / 2) elif use_tree: gravity = BHTree(convert_nbody, number_of_workers=1, epsilon_squared=0.05 | nbody_system.length**2) else: gravity = Hermite(convert_nbody, number_of_workers=number_of_workers / 2) gravity.parameters.epsilon_squared = 0.05 | nbody_system.length**2 # gravity.parameters.epsilon_squared = 0.15 | nbody_system.length ** 2 # Used to be this gravity.particles.add_particles(particles) from_gravity_to_model = gravity.particles.new_channel_to(particles) # particles.scale_to_standard() Cannot scale to standard if not using nbody_system units # Initialize the Evolution if not use_tree: stellar_evolution = SSE(number_of_workers=number_of_workers / 2) else: stellar_evolution = SSE(number_of_workers=number_of_workers - 1) 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", "luminosity", "temperature"]) # Initial time (note * end_time for correct units) time = 0.0 * end_time # Save initial conditions and make arrays (lists) for each step total_energy_at_t0 = gravity.kinetic_energy + gravity.potential_energy save_positions = [particles.position] save_velocities = [particles.velocity] save_masses = [particles.mass] save_luminosities = [particles.luminosity] save_temperatures = [particles.temperature] times = [time] while time < end_time: time += end_time / steps # Evolve gravity gravity.evolve_model(time) from_gravity_to_model.copy() # Evolve stars stellar_evolution.evolve_model(time) from_gravity_to_model.copy() from_stellar_evolution_to_model.copy_attributes( ["mass", "luminosity", "temperature"]) # Save data save_positions.append(particles.position) save_velocities.append(particles.velocity) save_masses.append(particles.mass) save_luminosities.append(particles.luminosity) save_temperatures.append(particles.temperature) times.append(time) total_energy = gravity.kinetic_energy + gravity.potential_energy if np.abs( (total_energy - total_energy_at_t0) / total_energy_at_t0) > 0.001: print( "Warning! Total energy of the system is changing too significantly!" ) print "Time: %.4g" % time.number total_mass = particles.mass.sum() print total_mass if escape: escaped_stars_3d, escaped_stars_2d = find_escapees(particles) gravity.stop() stellar_evolution.stop() print "It took %.3g seconds clock time" % (clock_time() - start_time) if animate: make_animation(save_positions, save_luminosities, save_temperatures, times, save_animation=save_animation, filename=filename) if escape: return save_positions[-1], save_velocities[-1], save_masses[ -1], escaped_stars_3d, escaped_stars_2d else: return save_positions, save_velocities