def setup_stellar_evolution_model(): out_pickle_file = os.path.join(get_path_to_results(), "super_giant_stellar_structure.pkl") if os.path.exists(out_pickle_file): return out_pickle_file stellar_evolution = MESA(redirection="none") stars = Particles(1) stars.mass = 10.0 | units.MSun stellar_evolution.initialize_module_with_default_parameters() stellar_evolution.particles.add_particles(stars) stellar_evolution.commit_particles() print "Evolving a MESA star with mass:", stellar_evolution.particles[ 0].mass try: while True: stellar_evolution.evolve_model() except AmuseException as ex: print "Evolved star to", stellar_evolution.particles[0].age print "Radius:", stellar_evolution.particles[0].radius pickle_stellar_model(stellar_evolution.particles[0], out_pickle_file) stellar_evolution.stop() return out_pickle_file
def setup_stellar_evolution_model(): out_pickle_file = os.path.join(get_path_to_results(), "super_giant_stellar_structure.pkl") if os.path.exists(out_pickle_file): return out_pickle_file stellar_evolution = MESA(redirection="none") stars = Particles(1) stars.mass = 10.0 | units.MSun stellar_evolution.particles.add_particles(stars) """ print "Evolving a MESA star with mass:", stellar_evolution.particles[0].mass try: while True: stellar_evolution.evolve_model() except AmuseException as ex: print "Evolved star to t=", stellar_evolution.particles[0].age, print "Mass:", stellar_evolution.particles[0].mass print "Radius:", stellar_evolution.particles[0].radius print "core-mass:", stellar_evolution.particles[0].core_mass """ while stellar_evolution.particles[0].stellar_type <= 12 | units.stellar_type: stellar_evolution.evolve_model() pickle_stellar_model(stellar_evolution.particles[0], out_pickle_file) stellar_evolution.stop() return out_pickle_file
def brunt_vaisala_frequency_squared_profile(mass, age): stellar_evolution = MESA() star = stellar_evolution.particles.add_particle(Particle(mass=mass)) star.evolve_for(age) radius_profile = star.get_radius_profile() brunt_profile = star.get_brunt_vaisala_frequency_squared_profile() stellar_evolution.stop() return radius_profile.as_quantity_in(units.RSun), brunt_profile
def mesa(self, number_of_stars): result = MESA() result.initialize_code() if number_of_stars > (10): warnings.warn("You're simulating a large number of stars with MESA. This may not be such a good idea...") if number_of_stars > (1000): raise Exception("You want to simulate with more than 1000 stars using MESA, this is not supported") return result
def main(): temperatures_original = [] | units.K luminosities_original = [] | units.LSun temperatures_helium = [] | units.K luminosities_helium = [] | units.LSun star = Particle() star.mass = 12.0 | units.MSun stop_radius = 100 | units.RSun stellar_evolution = MESA() se_star = stellar_evolution.particles.add_particle(star) print("Evolving a", star.mass, "star with", stellar_evolution.__class__.__name__, end=' ') print("until its radius exceeds", stop_radius) while (se_star.radius < stop_radius): se_star.evolve_one_step() temperatures_original.append(se_star.temperature) luminosities_original.append(se_star.luminosity) ###BOOKLISTSTART1### number_of_zones = se_star.get_number_of_zones() composition = se_star.get_chemical_abundance_profiles() index = (composition[0] > 1.0e-9).nonzero()[0][0] # first zone with X > 1.0e-9 print("Creating helium star, from the inner", index, "(out of", str(number_of_zones)+") shells.") helium_star = stellar_evolution.new_particle_from_model(dict( mass = (se_star.get_cumulative_mass_profile() * se_star.mass)[:index], radius = se_star.get_radius_profile()[:index], rho = se_star.get_density_profile()[:index], temperature = se_star.get_temperature_profile()[:index], luminosity = se_star.get_luminosity_profile()[:index], X_H = composition[0][:index], X_He = composition[1][:index] + composition[2][:index], X_C = composition[3][:index], X_N = composition[4][:index], X_O = composition[5][:index], X_Ne = composition[6][:index], X_Mg = composition[7][:index], X_Si = composition[7][:index]*0.0, X_Fe = composition[7][:index]*0.0), 0.0 | units.Myr) ###BOOKLISTSTOP1### print("\nStar properties before helium star evolution:\n", stellar_evolution.particles) for i in range(1000): helium_star.evolve_one_step() temperatures_helium.append(helium_star.temperature) luminosities_helium.append(helium_star.luminosity) print("\nStar properties after helium star evolution:\n", stellar_evolution.particles) stellar_evolution.stop() return temperatures_original, luminosities_original, \ temperatures_helium, luminosities_helium
def mesa(self, number_of_stars): result = MESA() result.initialize_code() if number_of_stars > (10): warnings.warn( "You're simulating a large number of stars with MESA. This may not be such a good idea...") if number_of_stars > (1000): raise Exception( "You want to simulate with more than 1000 stars using MESA, this is not supported") return result
def setup_stellar_evolution_model(): out_pickle_file = os.path.join( get_path_to_results(), "super_giant_stellar_structure.pkl") if os.path.exists(out_pickle_file): return out_pickle_file stellar_evolution = MESA(redirection="none") stars = Particles(1) stars.mass = 10.0 | units.MSun stellar_evolution.initialize_module_with_default_parameters() stellar_evolution.particles.add_particles(stars) stellar_evolution.commit_particles() print( "Evolving a MESA star with mass:", stellar_evolution.particles[0].mass ) try: while True: stellar_evolution.evolve_model() except AmuseException as ex: print "Evolved star to", stellar_evolution.particles[0].age print "Radius:", stellar_evolution.particles[0].radius pickle_stellar_model(stellar_evolution.particles[0], out_pickle_file) stellar_evolution.stop() return out_pickle_file
def code_factory(self): try: MESA() except Exception as message: self.skip( "Tried to instantiate a new object of the optional code with type '{0}', but this code is not available" .format(MESA)) return MESA
def setup_stellar_evolution_model(): out_pickle_file = os.path.join(get_path_to_results(), "super_giant_stellar_structure.pkl") if os.path.exists(out_pickle_file): return out_pickle_file print "Creating initial conditions from a MESA stellar evolution model..." stellar_evolution = MESA(redirection = "none") stars = Particles(1) stars.mass = 10.0 | units.MSun stellar_evolution.particles.add_particles(stars) while stellar_evolution.particles[0].stellar_type <= 12|units.stellar_type: stellar_evolution.evolve_model() pickle_stellar_model(stellar_evolution.particles[0], out_pickle_file) stellar_evolution.stop() return out_pickle_file
def setup_stellar_evolution_model(): out_pickle_file = os.path.join(get_path_to_results(), "super_giant_stellar_structure.pkl") if os.path.exists(out_pickle_file): return out_pickle_file stellar_evolution = MESA(redirection = "none") stars = Particles(1) stars.mass = 10.0 | units.MSun stellar_evolution.particles.add_particles(stars) """ print "Evolving a MESA star with mass:", stellar_evolution.particles[0].mass try: while True: stellar_evolution.evolve_model() except AmuseException as ex: print "Evolved star to t=", stellar_evolution.particles[0].age, print "Mass:", stellar_evolution.particles[0].mass print "Radius:", stellar_evolution.particles[0].radius print "core-mass:", stellar_evolution.particles[0].core_mass """ while stellar_evolution.particles[0].stellar_type <= 12|units.stellar_type: stellar_evolution.evolve_model() # while stellar_evolution.particles[0].stellar_type <= 3|units.stellar_type: # stellar_evolution.evolve_model() pickle_stellar_model(stellar_evolution.particles[0], out_pickle_file) stellar_evolution.stop() return out_pickle_file
def slowtest3(self): print "Testing ParallelStellarEvolution evolve_model" particles = Particles(4) particles.mass = range(1, 1 + len(particles)) | units.MSun serial = MESA() inserial = serial.particles.add_particles(particles) self.assertAlmostEqual(inserial.mass, range(1, 1 + len(particles)) | units.MSun) serial.evolve_model(0.2 | units.Myr) parallel = ParallelStellarEvolution(MESA, number_of_workers=3, **default_options) inparallel = parallel.particles.add_particles(particles) self.assertAlmostEqual(inparallel.mass, range(1, 1 + len(particles)) | units.MSun) parallel.evolve_model(0.2 | units.Myr) self.assertEqual(parallel.model_time, 0.2 | units.Myr) self.assertTrue(numpy.all(inparallel.age >= (0.2 | units.Myr))) self.assertTrue( numpy.all( inparallel.age - inparallel.time_step <= (0.2 | units.Myr))) self.assertEqual(inserial.luminosity, inparallel.luminosity) self.assertEqual(inserial.time_step, inparallel.time_step) self.assertEqual(inserial.temperature, inparallel.temperature) serial.stop() parallel.stop()
def slowtest3(self): print "Testing ParallelStellarEvolution evolve_model" particles = Particles(4) particles.mass = range(1, 1+len(particles)) | units.MSun serial = MESA() inserial = serial.particles.add_particles(particles) self.assertAlmostEqual(inserial.mass, range(1, 1+len(particles)) | units.MSun) serial.evolve_model(0.2 | units.Myr) parallel = ParallelStellarEvolution(MESA, number_of_workers=3, **default_options) inparallel = parallel.particles.add_particles(particles) self.assertAlmostEqual(inparallel.mass, range(1, 1+len(particles)) | units.MSun) parallel.evolve_model(0.2 | units.Myr) self.assertEqual(parallel.model_time, 0.2 | units.Myr) self.assertTrue(numpy.all(inparallel.age >= (0.2 | units.Myr))) self.assertTrue(numpy.all(inparallel.age - inparallel.time_step <= (0.2 | units.Myr))) self.assertEqual(inserial.luminosity, inparallel.luminosity) self.assertEqual(inserial.time_step, inparallel.time_step) self.assertEqual(inserial.temperature, inparallel.temperature) serial.stop() parallel.stop()
def simulate_evolution_tracks( masses=[0.5, 1.0, 1.25, 1.5, 2.25, 3.0, 5.0, 9.0, 15.0] | units.MSun): stellar_evolution = MESA() stellar_evolution.parameters.AGB_wind_scheme = 0 stellar_evolution.parameters.RGB_wind_scheme = 0 stars = datamodel.Particles(len(masses), mass=masses) stars = stellar_evolution.pre_ms_stars.add_particles(stars) data = {} for star in stars: luminosity = [] | units.LSun temperature = [] | units.K time = [] | units.yr print('Evolving pre main sequence star with') print(' mass:', star.mass) print(' luminosity:', star.luminosity) print(' radius:', star.radius) while star.stellar_type == 17 | units.stellar_type: luminosity.append(star.luminosity) temperature.append(star.temperature) time.append(star.age) star.evolve_one_step() print('Evolved pre main sequence star to:', star.stellar_type) print(' age:', star.age) print(' mass:', star.mass) print(' luminosity:', star.luminosity) print(' radius:', star.radius) print() stardata = {} stardata['luminosity'] = luminosity stardata['temperature'] = temperature stardata['time'] = time data[star.mass] = stardata return data
def evolve_star_and_apply_mass_loss(radius, mdot): print("Evolve to radius = ", radius, "and then apply mdot =", mdot) stev = MESA(redirection='none') # We have to switch off all wind mass loss for manual mass loss to work stev.parameters.AGB_wind_scheme = 0 stev.parameters.RGB_wind_scheme = 0 star = stev.particles.add_particle(Particle(mass=2 | units.MSun)) while star.radius < radius: star.evolve_one_step() print("evolved to:", star.age, "->", star.radius) star1 = star.copy() # High mass loss rates can only be calculated for small time steps star.time_step = 1. | units.yr star.mass_change = mdot print(star.mass_change) star.evolve_one_step() print_report(star1, star, mdot)
def setup_stellar_evolution_model(): out_pickle_file = os.path.join(get_path_to_results(), "super_giant_stellar_structure.pkl") if os.path.exists(out_pickle_file): return out_pickle_file print("Creating initial conditions from a MESA stellar evolution model...") stellar_evolution = MESA(redirection="none") stars = Particles(1) stars.mass = 10.0 | units.MSun stellar_evolution.particles.add_particles(stars) while stellar_evolution.particles[ 0].stellar_type <= 12 | units.stellar_type: stellar_evolution.evolve_model() pickle_stellar_model(stellar_evolution.particles[0], out_pickle_file) stellar_evolution.stop() return out_pickle_file
def head_on_stellar_merger( masses=[0.3, 3.0] | units.MSun, star_age=310.0 | units.Myr, initial_separation=4.0 | units.RSun, angle=numpy.pi / 3, initial_speed=3000.0 | units.km / units.s, initial_speed_perpendicular=30.0 | units.km / units.s, number_of_sph_particles=50000, t_end=1.0e4 | units.s, sph_code=Fi, ): """ masses: Mass of the two stars star_age: Initial age of the stars number_of_sph_particles: Total number of particles of both stars, divided according to their masses t_end: (Physical, not computational) duration of the hydrodynamics simulation sph_code: Code to use for the hydrodynamics simulation """ # Convert some of the input parameters to string, for use in output file # names: n_string = "n" + ("%1.0e" % (number_of_sph_particles) ).replace("+0", "").replace("+", "") t_end_string = "t" + ("%1.0e" % (t_end.value_in(units.s)) ).replace("+0", "").replace("+", "") base_output_file_name = os.path.join( get_path_to_results(), "stellar_merger_"+n_string+"_"+t_end_string) stars = Particles(2) stars.mass = masses try: stellar_evolution = MESA() stellar_evolution.initialize_code() except: print "MESA was not built. Returning." return stellar_evolution.commit_parameters() stellar_evolution.particles.add_particles(stars) stellar_evolution.commit_particles() print "Evolving stars with MESA..." stellar_evolution.evolve_model(star_age) number_of_sph_particles_1 = int( round( number_of_sph_particles * ( stellar_evolution.particles[0].mass / stellar_evolution.particles.mass.sum() ) ) ) number_of_sph_particles_2 = ( number_of_sph_particles - number_of_sph_particles_1 ) print "Creating initial conditions from a MESA stellar evolution model:" print( stellar_evolution.particles[0].mass, "star consisting of", number_of_sph_particles_1, "particles." ) sph_particles_1 = convert_stellar_model_to_SPH( stellar_evolution.particles[0], number_of_sph_particles_1, seed=12345 ).gas_particles print( stellar_evolution.particles[1].mass, "star consisting of", number_of_sph_particles_2, "particles." ) sph_particles_2 = convert_stellar_model_to_SPH( stellar_evolution.particles[1], number_of_sph_particles_2 ).gas_particles initial_separation += stellar_evolution.particles.radius.sum() sph_particles_2.x += numpy.cos(angle) * initial_separation sph_particles_2.y += numpy.sin(angle) * initial_separation sph_particles_1.vx += numpy.cos(angle) * initial_speed - \ numpy.sin(angle) * initial_speed_perpendicular sph_particles_1.vy += numpy.cos(angle) * initial_speed_perpendicular + \ numpy.sin(angle) * initial_speed view = [-0.5, 0.5, -0.5, 0.5] * \ (initial_separation + stellar_evolution.particles.radius.sum()) stellar_evolution.stop() all_sph_particles = ParticlesSuperset([sph_particles_1, sph_particles_2]) all_sph_particles.move_to_center() unit_converter = ConvertBetweenGenericAndSiUnits( 1.0 | units.RSun, constants.G, t_end) hydro_legacy_code = sph_code(unit_converter) n_steps = 100 hydro_legacy_code.parameters.n_smooth = 96 try: hydro_legacy_code.parameters.timestep = t_end / n_steps except Exception as exc: if "parameter is read-only" not in str(exc): raise hydro_legacy_code.gas_particles.add_particles(all_sph_particles) print "Evolving to t =", t_end, " (using", sph_code.__name__, "SPH code)." for time, i_step in [(i*t_end/n_steps, i) for i in range(1, n_steps+1)]: hydro_legacy_code.evolve_model(time) if not i_step % 4: hydro_plot( view, hydro_legacy_code, (300, 300), base_output_file_name + "_hydro_image{0:=03}.png".format(i_step) ) hydro_legacy_code.stop() print "All done!\n"
def head_on_stellar_merger( masses = [0.3, 3.0] | units.MSun, star_age = 310.0 | units.Myr, maximally_evolved_stars = False, initial_separation = 4.0 | units.RSun, angle = numpy.pi / 3, initial_speed = 3000.0 | units.km / units.s, initial_speed_perpendicular = 30.0 | units.km / units.s, number_of_sph_particles = 1000, t_end = 1.0e4 | units.s, sph_code = Fi, steps_per_snapshot = 4, snapshot_size = 100, use_stored_stellar_models = True ): """ masses: Mass of the two stars star_age: Initial age of the stars (if maximally_evolved_stars is False) maximally_evolved_stars: Evolve stars as far as the Stellar Evolution code can get number_of_sph_particles: Total number of particles of both stars, divided according to their masses t_end: (Physical, not computational) duration of the hydrodynamics simulation sph_code: Code to use for the hydrodynamics simulation steps_per_snapshot: A hydroplot snapshot is generated each time after this many steps (0 or None means no snapshots) snapshot_size: Size of the snapshot in pixels along one dimension use_stored_stellar_models: Flag to use previously stored stellar model files (for speed-up). """ # Convert some of the input parameters to string, for use in output file names: n_string = "n" + ("%1.0e"%(number_of_sph_particles)).replace("+0","").replace("+","") t_end_string = "t" + ("%1.0e"%(t_end.value_in(units.s))).replace("+0","").replace("+","") masses_string = ("m1_" + ("%0.3e"%(masses[0].value_in(units.MSun))).replace("+0","").replace("+","") + "_m2_" + ("%0.3e"%(masses[1].value_in(units.MSun))).replace("+0","").replace("+","")) if maximally_evolved_stars: star_age_string = "a_max" else: star_age_string = "a" + ("%0.3e"%(star_age.value_in(units.Myr))).replace("+0","").replace("+","") base_output_file_name = os.path.join(get_path_to_results(), "stellar_merger_"+n_string+"_"+t_end_string) pickle_file_1 = os.path.join(get_path_to_results(), "stellar_merger_"+masses_string+"_"+star_age_string+"_1.pkl") pickle_file_2 = os.path.join(get_path_to_results(), "stellar_merger_"+masses_string+"_"+star_age_string+"_2.pkl") if not use_stored_stellar_models or not (os.path.exists(pickle_file_1) and os.path.exists(pickle_file_2)): stars = Particles(2) stars.mass = masses try: stellar_evolution = MESA() stellar_evolution.initialize_code() except: print "MESA was not built. Returning." return stellar_evolution.commit_parameters() stellar_evolution.particles.add_particles(stars) stellar_evolution.commit_particles() if maximally_evolved_stars: try: while True: stellar_evolution.evolve_model() except AmuseException as exception: print exception else: stellar_evolution.evolve_model(star_age) if os.path.exists(pickle_file_1): print "Could not save stellar model 1: file already exists." else: pickle_stellar_model(stellar_evolution.particles[0], pickle_file_1) print "Stellar model 1 saved at:", pickle_file_1 if os.path.exists(pickle_file_2): print "Could not save stellar model 2: file already exists." else: pickle_stellar_model(stellar_evolution.particles[1], pickle_file_2) print "Stellar model 2 saved at:", pickle_file_2 stellar_evolution.stop() model_1 = StellarModel2SPH(None, None, pickle_file = pickle_file_1) model_2 = StellarModel2SPH(None, None, pickle_file = pickle_file_2) model_1.unpickle_stellar_structure() model_2.unpickle_stellar_structure() composition = model_2.composition_profile midpoints = model_2.midpoints_profile[1:-1] specific_internal_energy = model_2.specific_internal_energy_profile number_of_sph_particles_1 = int(round(number_of_sph_particles * (model_1.mass / (model_1.mass + model_2.mass)))) number_of_sph_particles_2 = number_of_sph_particles - number_of_sph_particles_1 print "Creating initial conditions from a MESA stellar evolution model:" print model_1.mass, "star consisting of", number_of_sph_particles_1, "particles." sph_particles_1 = convert_stellar_model_to_SPH( None, number_of_sph_particles_1, seed=12345, pickle_file = pickle_file_1 ).gas_particles print model_2.mass, "star consisting of", number_of_sph_particles_2, "particles." sph_particles_2 = convert_stellar_model_to_SPH( None, number_of_sph_particles_2, pickle_file = pickle_file_2 ).gas_particles initial_separation += model_1.radius + model_2.radius sph_particles_2.x += numpy.cos(angle) * initial_separation sph_particles_2.y += numpy.sin(angle) * initial_separation sph_particles_1.vx += numpy.cos(angle) * initial_speed - numpy.sin(angle) * initial_speed_perpendicular sph_particles_1.vy += numpy.cos(angle) * initial_speed_perpendicular + numpy.sin(angle) * initial_speed view = [-0.5, 0.5, -0.5, 0.5] * (initial_separation + model_1.radius + model_2.radius) all_sph_particles = ParticlesSuperset([sph_particles_1, sph_particles_2]) all_sph_particles.move_to_center() unit_converter = ConvertBetweenGenericAndSiUnits(1.0 | units.RSun, constants.G, t_end) hydro_legacy_code = sph_code(unit_converter) n_steps = 100 hydro_legacy_code.parameters.n_smooth = 96 try: hydro_legacy_code.parameters.timestep = t_end / n_steps except Exception as exc: if not "parameter is read-only" in str(exc): raise hydro_legacy_code.gas_particles.add_particles(all_sph_particles) times = [] | units.Myr kinetic_energies = [] | units.J potential_energies = [] | units.J thermal_energies = [] | units.J print "Evolving to:", t_end for time, i_step in [(i*t_end/n_steps, i) for i in range(1, n_steps+1)]: hydro_legacy_code.evolve_model(time) times.append(time) kinetic_energies.append( hydro_legacy_code.kinetic_energy) potential_energies.append( hydro_legacy_code.potential_energy) thermal_energies.append( hydro_legacy_code.thermal_energy) if steps_per_snapshot and (not i_step % steps_per_snapshot): hydro_plot( view, hydro_legacy_code, (snapshot_size, snapshot_size), base_output_file_name + "_hydro_image{0:=03}.png".format(i_step) ) hydro_legacy_code.gas_particles.new_channel_to(all_sph_particles).copy_attributes( ['mass', 'x','y','z', 'vx','vy','vz', 'u']) center_of_mass = all_sph_particles.center_of_mass().as_quantity_in(units.RSun) center_of_mass_velocity = all_sph_particles.center_of_mass_velocity().as_quantity_in(units.km / units.s) print print "center_of_mass:", center_of_mass print "center_of_mass_velocity:", center_of_mass_velocity all_sph_particles.position -= center_of_mass sph_midpoints = all_sph_particles.position.lengths() energy_plot( times, kinetic_energies, potential_energies, thermal_energies, base_output_file_name+"_energy_evolution.png" ) thermal_energy_plot( times, thermal_energies, base_output_file_name+"_thermal_energy_evolution.png" ) composition_comparison_plot( midpoints, composition[0], sph_midpoints, all_sph_particles.h1, base_output_file_name+"_composition_h1.png" ) internal_energy_comparison_plot( midpoints, specific_internal_energy, sph_midpoints, all_sph_particles.u, base_output_file_name+"_new_u.png" ) hydro_plot( [-2.0, 2.0, -2.0, 2.0] | units.RSun, hydro_legacy_code, (100, 100), base_output_file_name + "_hydro_image.png" ) hydro_legacy_code.stop() print "All done!\n"
def head_on_stellar_merger( masses=[0.3, 3.0] | units.MSun, star_age=310.0 | units.Myr, maximally_evolved_stars=False, initial_separation=4.0 | units.RSun, angle=numpy.pi / 3, initial_speed=3000.0 | units.km / units.s, initial_speed_perpendicular=30.0 | units.km / units.s, number_of_sph_particles=1000, t_end=1.0e4 | units.s, sph_code=Fi, steps_per_snapshot=4, snapshot_size=100, use_stored_stellar_models=True ): """ masses: Mass of the two stars star_age: Initial age of the stars (if maximally_evolved_stars is False) maximally_evolved_stars: Evolve stars as far as the Stellar Evolution code can get number_of_sph_particles: Total number of particles of both stars, divided according to their masses t_end: (Physical, not computational) duration of the hydrodynamics simulation sph_code: Code to use for the hydrodynamics simulation steps_per_snapshot: A hydroplot snapshot is generated each time after this many steps (0 or None means no snapshots) snapshot_size: Size of the snapshot in pixels along one dimension use_stored_stellar_models: Flag to use previously stored stellar model files (for speed-up). """ # Convert some of the input parameters to string, for use in output file # names: n_string = "n" + ("%1.0e" % (number_of_sph_particles) ).replace("+0", "").replace("+", "") t_end_string = "t" + ("%1.0e" % (t_end.value_in(units.s)) ).replace("+0", "").replace("+", "") masses_string = ( "m1_" + ( "%0.3e" % (masses[0].value_in(units.MSun)) ).replace("+0", "").replace("+", "") + "_m2_" + ( "%0.3e" % (masses[1].value_in(units.MSun)) ).replace("+0", "").replace("+", "") ) if maximally_evolved_stars: star_age_string = "a_max" else: star_age_string = "a" + \ ("%0.3e" % (star_age.value_in(units.Myr))).replace( "+0", "").replace("+", "") base_output_file_name = os.path.join( get_path_to_results(), "stellar_merger_"+n_string+"_"+t_end_string) pickle_file_1 = os.path.join(get_path_to_results( ), "stellar_merger_"+masses_string+"_"+star_age_string+"_1.pkl") pickle_file_2 = os.path.join(get_path_to_results( ), "stellar_merger_"+masses_string+"_"+star_age_string+"_2.pkl") if not use_stored_stellar_models or not (os.path.exists(pickle_file_1) and os.path.exists(pickle_file_2)): stars = Particles(2) stars.mass = masses try: stellar_evolution = MESA() stellar_evolution.initialize_code() except: print("MESA was not built. Returning.") return stellar_evolution.commit_parameters() stellar_evolution.particles.add_particles(stars) stellar_evolution.commit_particles() if maximally_evolved_stars: try: while True: stellar_evolution.evolve_model() except AmuseException as exception: print(exception) else: stellar_evolution.evolve_model(star_age) if os.path.exists(pickle_file_1): print("Could not save stellar model 1: file already exists.") else: pickle_stellar_model(stellar_evolution.particles[0], pickle_file_1) print("Stellar model 1 saved at:", pickle_file_1) if os.path.exists(pickle_file_2): print("Could not save stellar model 2: file already exists.") else: pickle_stellar_model(stellar_evolution.particles[1], pickle_file_2) print("Stellar model 2 saved at:", pickle_file_2) stellar_evolution.stop() model_1 = StellarModel2SPH(None, None, pickle_file=pickle_file_1) model_2 = StellarModel2SPH(None, None, pickle_file=pickle_file_2) model_1.unpickle_stellar_structure() model_2.unpickle_stellar_structure() composition = model_2.composition_profile midpoints = model_2.midpoints_profile[1:-1] specific_internal_energy = model_2.specific_internal_energy_profile number_of_sph_particles_1 = int( round( number_of_sph_particles * (model_1.mass / (model_1.mass + model_2.mass)) ) ) number_of_sph_particles_2 = ( number_of_sph_particles - number_of_sph_particles_1 ) print("Creating initial conditions from a MESA stellar evolution model:") print( model_1.mass, "star consisting of", number_of_sph_particles_1, "particles." ) sph_particles_1 = convert_stellar_model_to_SPH( None, number_of_sph_particles_1, seed=12345, pickle_file = pickle_file_1 ).gas_particles print( model_2.mass, "star consisting of", number_of_sph_particles_2, "particles." ) sph_particles_2 = convert_stellar_model_to_SPH( None, number_of_sph_particles_2, pickle_file=pickle_file_2 ).gas_particles initial_separation += model_1.radius + model_2.radius sph_particles_2.x += numpy.cos(angle) * initial_separation sph_particles_2.y += numpy.sin(angle) * initial_separation sph_particles_1.vx += ( numpy.cos(angle) * initial_speed - numpy.sin(angle) * initial_speed_perpendicular ) sph_particles_1.vy += ( numpy.cos(angle) * initial_speed_perpendicular + numpy.sin(angle) * initial_speed ) view = ( [-0.5, 0.5, -0.5, 0.5] * (initial_separation + model_1.radius + model_2.radius) ) all_sph_particles = ParticlesSuperset([sph_particles_1, sph_particles_2]) all_sph_particles.move_to_center() unit_converter = ConvertBetweenGenericAndSiUnits( 1.0 | units.RSun, constants.G, t_end) hydro_legacy_code = sph_code(unit_converter) n_steps = 100 hydro_legacy_code.parameters.n_smooth = 96 try: hydro_legacy_code.parameters.timestep = t_end / n_steps except Exception as exc: if "parameter is read-only" not in str(exc): raise hydro_legacy_code.gas_particles.add_particles(all_sph_particles) times = [] | units.Myr kinetic_energies = [] | units.J potential_energies = [] | units.J thermal_energies = [] | units.J print("Evolving to:", t_end) for time, i_step in [(i*t_end/n_steps, i) for i in range(1, n_steps+1)]: hydro_legacy_code.evolve_model(time) times.append(time) kinetic_energies.append(hydro_legacy_code.kinetic_energy) potential_energies.append(hydro_legacy_code.potential_energy) thermal_energies.append(hydro_legacy_code.thermal_energy) if steps_per_snapshot and (not i_step % steps_per_snapshot): hydro_plot( view, hydro_legacy_code, (snapshot_size, snapshot_size), base_output_file_name + "_hydro_image{0:=03}.png".format(i_step) ) hydro_legacy_code.gas_particles.new_channel_to( all_sph_particles ).copy_attributes( ['mass', 'x', 'y', 'z', 'vx', 'vy', 'vz', 'u'] ) center_of_mass = all_sph_particles.center_of_mass( ).as_quantity_in(units.RSun) center_of_mass_velocity = all_sph_particles.center_of_mass_velocity( ).as_quantity_in(units.km / units.s) print() print("center_of_mass:", center_of_mass) print("center_of_mass_velocity:", center_of_mass_velocity) all_sph_particles.position -= center_of_mass sph_midpoints = all_sph_particles.position.lengths() energy_plot( times, kinetic_energies, potential_energies, thermal_energies, base_output_file_name+"_energy_evolution.png" ) thermal_energy_plot( times, thermal_energies, base_output_file_name+"_thermal_energy_evolution.png" ) composition_comparison_plot( midpoints, composition[0], sph_midpoints, all_sph_particles.h1, base_output_file_name+"_composition_h1.png" ) internal_energy_comparison_plot( midpoints, specific_internal_energy, sph_midpoints, all_sph_particles.u, base_output_file_name+"_new_u.png" ) hydro_plot( [-2.0, 2.0, -2.0, 2.0] | units.RSun, hydro_legacy_code, (100, 100), base_output_file_name + "_hydro_image.png" ) hydro_legacy_code.stop() print("All done!\n")