def evolve_coupled_system(binary_system, giant_system, t_end, n_steps, do_energy_evolution_plot, previous_data=None): directsum = CalculateFieldForParticles(particles=giant_system.particles, gravity_constant=constants.G) directsum.smoothing_length_squared = giant_system.parameters.gas_epsilon**2 coupled_system = Bridge(timestep=(t_end / (2 * n_steps)), verbose=False, use_threading=True) coupled_system.add_system(binary_system, (directsum,), False) coupled_system.add_system(giant_system, (binary_system,), False) times = (t_end * list(range(1, n_steps+1)) / n_steps).as_quantity_in(units.day) if previous_data: with open(previous_data, 'rb') as file: (all_times, potential_energies, kinetic_energies, thermal_energies, giant_center_of_mass, ms1_position, ms2_position, giant_center_of_mass_velocity, ms1_velocity, ms2_velocity) = pickle.load(file) all_times.extend(times + all_times[-1]) else: all_times = times if do_energy_evolution_plot: potential_energies = coupled_system.particles.potential_energy().as_vector_with_length(1).as_quantity_in(units.erg) kinetic_energies = coupled_system.particles.kinetic_energy().as_vector_with_length(1).as_quantity_in(units.erg) thermal_energies = coupled_system.gas_particles.thermal_energy().as_vector_with_length(1).as_quantity_in(units.erg) else: potential_energies = kinetic_energies = thermal_energies = None giant_center_of_mass = [] | units.RSun ms1_position = [] | units.RSun ms2_position = [] | units.RSun giant_center_of_mass_velocity = [] | units.km / units.s ms1_velocity = [] | units.km / units.s ms2_velocity = [] | units.km / units.s i_offset = len(giant_center_of_mass) giant_total_mass = giant_system.particles.total_mass() ms1_mass = binary_system.particles[0].mass ms2_mass = binary_system.particles[1].mass print(" Evolving for", t_end) for i_step, time in enumerate(times): coupled_system.evolve_model(time) print(" Evolved to:", time, end=' ') if do_energy_evolution_plot: potential_energies.append(coupled_system.particles.potential_energy()) kinetic_energies.append(coupled_system.particles.kinetic_energy()) thermal_energies.append(coupled_system.gas_particles.thermal_energy()) giant_center_of_mass.append(giant_system.particles.center_of_mass()) ms1_position.append(binary_system.particles[0].position) ms2_position.append(binary_system.particles[1].position) giant_center_of_mass_velocity.append(giant_system.particles.center_of_mass_velocity()) ms1_velocity.append(binary_system.particles[0].velocity) ms2_velocity.append(binary_system.particles[1].velocity) a_giant, e_giant = calculate_orbital_elements(ms1_mass, ms2_mass, ms1_position, ms2_position, ms1_velocity, ms2_velocity, giant_total_mass, giant_center_of_mass, giant_center_of_mass_velocity) print("Outer Orbit:", time.in_(units.day), a_giant[-1].in_(units.AU), e_giant[-1], ms1_mass.in_(units.MSun), ms2_mass.in_(units.MSun), giant_total_mass.in_(units.MSun)) if i_step % 10 == 9: snapshotfile = os.path.join("snapshots", "hydro_triple_{0:=04}_gas.amuse".format(i_step + i_offset)) write_set_to_file(giant_system.gas_particles, snapshotfile, format='amuse') snapshotfile = os.path.join("snapshots", "hydro_triple_{0:=04}_core.amuse".format(i_step + i_offset)) write_set_to_file(giant_system.dm_particles, snapshotfile, format='amuse') snapshotfile = os.path.join("snapshots", "hydro_triple_{0:=04}_binary.amuse".format(i_step + i_offset)) write_set_to_file(binary_system.particles, snapshotfile, format='amuse') datafile = os.path.join("snapshots", "hydro_triple_{0:=04}_info.amuse".format(i_step + i_offset)) with open(datafile, 'wb') as outfile: pickle.dump((all_times[:len(giant_center_of_mass)], potential_energies, kinetic_energies, thermal_energies, giant_center_of_mass, ms1_position, ms2_position, giant_center_of_mass_velocity, ms1_velocity, ms2_velocity), outfile) figname1 = os.path.join("plots", "hydro_triple_small{0:=04}.png".format(i_step + i_offset)) figname2 = os.path.join("plots", "hydro_triple_large{0:=04}.png".format(i_step + i_offset)) print(" - Hydroplots are saved to: ", figname1, "and", figname2) for plot_range, plot_name in [(8|units.AU, figname1), (40|units.AU, figname2)]: if HAS_PYNBODY: pynbody_column_density_plot(coupled_system.gas_particles, width=plot_range, vmin=26, vmax=32) scatter(coupled_system.dm_particles.x, coupled_system.dm_particles.y, c="w") else: pyplot.figure(figsize = [16, 16]) sph_particles_plot(coupled_system.gas_particles, gd_particles=coupled_system.dm_particles, view=plot_range*[-0.5, 0.5, -0.5, 0.5]) pyplot.savefig(plot_name) pyplot.close() coupled_system.stop() make_movie() if do_energy_evolution_plot: energy_evolution_plot(all_times[:len(kinetic_energies)-1], kinetic_energies, potential_energies, thermal_energies) print(" Calculating semimajor axis and eccentricity evolution for inner binary") # Some temporary variables to calculate semimajor_axis and eccentricity evolution total_mass = ms1_mass + ms2_mass rel_position = ms1_position - ms2_position rel_velocity = ms1_velocity - ms2_velocity separation_in = rel_position.lengths() speed_squared_in = rel_velocity.lengths_squared() # Now calculate the important quantities: semimajor_axis_binary = (constants.G * total_mass * separation_in / (2 * constants.G * total_mass - separation_in * speed_squared_in)).as_quantity_in(units.AU) eccentricity_binary = numpy.sqrt(1.0 - (rel_position.cross(rel_velocity)**2).sum(axis=1) / (constants.G * total_mass * semimajor_axis_binary)) print(" Calculating semimajor axis and eccentricity evolution of the giant's orbit") # Some temporary variables to calculate semimajor_axis and eccentricity evolution rel_position = ((ms1_mass * ms1_position + ms2_mass * ms2_position)/total_mass - giant_center_of_mass) rel_velocity = ((ms1_mass * ms1_velocity + ms2_mass * ms2_velocity)/total_mass - giant_center_of_mass_velocity) total_mass += giant_total_mass separation = rel_position.lengths() speed_squared = rel_velocity.lengths_squared() # Now calculate the important quantities: semimajor_axis_giant = (constants.G * total_mass * separation / (2 * constants.G * total_mass - separation * speed_squared)).as_quantity_in(units.AU) eccentricity_giant = numpy.sqrt(1.0 - (rel_position.cross(rel_velocity)**2).sum(axis=1) / (constants.G * total_mass * semimajor_axis_giant)) orbit_parameters_plot(semimajor_axis_binary, semimajor_axis_giant, all_times[:len(semimajor_axis_binary)]) orbit_ecc_plot(eccentricity_binary, eccentricity_giant, all_times[:len(eccentricity_binary)]) orbit_parameters_plot(separation_in.as_quantity_in(units.AU), separation.as_quantity_in(units.AU), all_times[:len(eccentricity_binary)], par_symbol="r", par_name="separation") orbit_parameters_plot(speed_squared_in.as_quantity_in(units.km**2 / units.s**2), speed_squared.as_quantity_in(units.km**2 / units.s**2), all_times[:len(eccentricity_binary)], par_symbol="v^2", par_name="speed_squared")
# Increase the Step Counter step_index += 1 # Log that a Step was Taken print '\n-------------' print '[UPDATE] Step Taken at %s!' %(tp.strftime("%Y/%m/%d-%H:%M:%S", tp.gmtime())) print '-------------\n' sys.stdout.flush() # Log that the Simulation Ended & Switch to Terminal Output print '\n[UPDATE] Run Finished at %s! \n' %(tp.strftime("%Y/%m/%d-%H:%M:%S", tp.gmtime())) sys.stdout = orig_stdout f.close() # Pickle the Final Encounter Information Dictionary encounter_file = open("Encounters/"+cluster_name+"_encounters.pkl", "wb") pickle.dump(encounterInformation, encounter_file) encounter_file.close() # Alerts the Terminal User that the Run has Ended! print '\n[UPDATE] Run Finished at %s! \n' %(tp.strftime("%Y/%m/%d-%H:%M:%S", tp.gmtime())) sys.stdout.flush() print_diagnostics(multiples_code, E0) # Closes PH4, Kepler & SmallN Instances sev_code.stop() gravity.stop() kep.stop() util.stop_smalln() bridge_code.stop()
stars.stellar_mass += stars.initial_disk_mass - new_mass stars.initial_disk_mass = new_mass stars.viscous_timescale *= (np.divide( new_radius, stars.initial_characteristic_disk_radius))**(2 - gamma) stars.initial_characteristic_disk_radius = new_radius stars.last_encounter = t + t_ini write_set_to_file( stars, '{0}/R{1}_{2}.hdf5'.format( path, Rvir.value_in(units.parsec), int((t + t_ini).value_in(units.yr))), 'amuse') if gas_presence or gas_expulsion: gas_gravity.stop() gravity.stop() E_handle.close() Q_handle.close() def new_option_parser(): """ Parses command line input for code. """ from amuse.units.optparse import OptionParser result = OptionParser() # Cluster parameters result.add_option("-N",
class GravityHydroStellar(object): def __init__(self, gravity, hydro, stellar, gravity_to_hydro, hydro_to_gravity, time_step_bridge, time_step_feedback, feedback_gas_particle_mass, feedback_efficiency=0.01, feedback_radius=0.01 | units.parsec, verbose=True): self.gravity = gravity self.hydro = hydro self.stellar = stellar self.gravity_to_hydro = gravity_to_hydro self.hydro_to_gravity = hydro_to_gravity self.time_step_bridge = time_step_bridge self.time_step_feedback = time_step_feedback self.feedback_gas_particle_mass = feedback_gas_particle_mass self.feedback_efficiency = feedback_efficiency self.feedback_radius = feedback_radius self.verbose = verbose self.bridge = Bridge(verbose=verbose, timestep=self.time_step_bridge, use_threading=False) self.bridge.add_system(self.hydro, (self.gravity_to_hydro, )) self.bridge.add_system(self.gravity, (self.hydro_to_gravity, )) self.star_particles = self.stars_with_mechanical_luminosity( self.stellar.particles) self.total_feedback_energy = zero self.current_time = 0.0 | units.Myr def stars_with_mechanical_luminosity(self, particles): result = ParticlesOverlay(particles) def lmech_function(temperature, mass, luminosity, radius): T = temperature.value_in(units.K) M = mass.value_in(units.MSun) L = luminosity.value_in(units.LSun) R = radius.value_in(units.RSun) # Reimers wind below 8000K mass_loss = (4.0e-13 | units.MSun / units.yr) * L * R / M # ... wind above 8000K i = numpy.where(temperature > 8000 | units.K)[0] mass_loss[i] = (10**-24.06 | units.MSun / units.yr) * ( L**2.45 * M**(-1.1) * T.clip(1000, 8.0e4)**(1.31)) t4 = numpy.log10(T * 1.0e-4).clip(0.0, 1.0) v_terminal = (30 + 4000 * t4) | units.km / units.s return 0.5 * mass_loss * v_terminal**2 result.add_calculated_attribute( "mechanical_luminosity", lmech_function, attributes_names=["temperature", "mass", "luminosity", "radius"]) result.L_mech = result.mechanical_luminosity result.E_mech = (0.0 | units.Myr) * result.L_mech result.E_mech_last_feedback = result.E_mech result.previous_mass = result.mass # Store the mass of the star at the last moment of feedback return result def evolve_model(self, end_time): while self.current_time < end_time - 0.5 * self.time_step_feedback: self.current_time += self.time_step_feedback if self.verbose: time_begin = time.time() print print "GravityHydroStellar: Start evolving..." self.bridge.evolve_model(self.current_time) self.stellar.evolve_model(self.current_time) if self.verbose: print "GravityHydroStellar: Evolved to:", self.current_time model_times = [ getattr(self, code).model_time.as_quantity_in(units.Myr) for code in ["stellar", "bridge", "gravity", "hydro"] ] print " (Stellar: {0}, Bridge: {1}, Gravity: {2}, Hydro: {3})".format( *model_times) print "GravityHydroStellar: Call mechanical_feedback" self.mechanical_feedback(self.time_step_feedback) if self.verbose: print "GravityHydroStellar: store system state" self.store_system_state() if self.verbose: print "GravityHydroStellar: Iteration took {0} seconds.".format( time.time() - time_begin) def mechanical_feedback(self, time_step): L_mech_new = self.star_particles.mechanical_luminosity self.star_particles.E_mech += time_step * 0.5 * ( self.star_particles.L_mech + L_mech_new) self.star_particles.L_mech = L_mech_new self.star_particles.dmass = self.star_particles.previous_mass - self.star_particles.mass self.star_particles.n_feedback_particles = numpy.array( self.star_particles.dmass / self.feedback_gas_particle_mass).astype(int) losers = self.star_particles.select_array(lambda x: x > 0, ["n_feedback_particles"]) if self.verbose: print "GravityHydroStellar: Number of particles providing mechanical feedback during this step:", len( losers) if len(losers) == 0: return channel = self.gravity.particles.new_channel_to(losers) channel.copy_attributes(["x", "y", "z", "vx", "vy", "vz"]) number_of_new_particles = losers.n_feedback_particles.sum() new_sph_all = Particles(number_of_new_particles) new_sph_all.mass = self.feedback_gas_particle_mass new_sph_all.h_smooth = 0.0 | units.parsec offsets = self.draw_random_position_offsets(number_of_new_particles) i = 0 for loser in losers: i_next = i + loser.n_feedback_particles new = new_sph_all[i:i_next] new.position = loser.position + offsets[i:i_next] new.velocity = loser.velocity new.u = self.feedback_efficiency * ( loser.E_mech - loser.E_mech_last_feedback) / loser.dmass i = i_next losers.previous_mass -= self.feedback_gas_particle_mass * losers.n_feedback_particles losers.E_mech_last_feedback = losers.E_mech channel = losers.new_channel_to(self.gravity.particles) channel.copy_attribute("previous_mass", "mass") if self.verbose: print "GravityHydroStellar: New SPH particles:" print new_sph_all self.hydro.gas_particles.add_particles(new_sph_all) self.total_feedback_energy += (new_sph_all.mass * new_sph_all.u).sum() def draw_random_position_offsets(self, number_of_new_particles): r = numpy.random.uniform(0.0, 1.0, number_of_new_particles) theta = numpy.random.uniform(0.0, numpy.pi, number_of_new_particles) phi = numpy.random.uniform(0.0, 2 * numpy.pi, number_of_new_particles) return self.feedback_radius * numpy.array( (r * sin(theta) * cos(phi), r * sin(theta) * sin(phi), r * cos(theta))).transpose() @property def kinetic_energy(self): return self.bridge.kinetic_energy @property def potential_energy(self): return self.bridge.potential_energy @property def thermal_energy(self): return self.bridge.thermal_energy @property def feedback_energy(self): return self.total_feedback_energy @property def model_time(self): return self.bridge.model_time @property def particles(self): return self.bridge.particles @property def gas_particles(self): return self.bridge.gas_particles def store_system_state(self): snapshot_number = int(0.5 + self.current_time / self.time_step_feedback) filename = os.path.join( "snapshots", "cluster_snapshot_{0:=06}_".format(snapshot_number)) stars = Particles(keys=self.star_particles.key) self.star_particles.copy_values_of_attributes_to([ "mass", "temperature", "stellar_type", "radius", "luminosity", "age", "L_mech", "E_mech", "E_mech_last_feedback", "previous_mass" ], stars) self.gravity.particles.copy_values_of_attributes_to( ["x", "y", "z", "vx", "vy", "vz"], stars) write_set_to_file(stars, filename + "stars.amuse", "amuse") write_set_to_file(self.hydro.gas_particles, filename + "gas.amuse", "amuse") with open(filename + "info.pkl", "wb") as outfile: cPickle.dump( (self.gravity.unit_converter, self.hydro.unit_converter, self.time_step_bridge, self.time_step_feedback, self.feedback_gas_particle_mass, self.feedback_efficiency, self.feedback_radius, self.verbose, self.total_feedback_energy, self.current_time), outfile) def load_system_state(self, info_file, stars_file): stars = read_set_from_file(stars_file, 'amuse') channel = stars.new_channel_to(self.star_particles) channel.copy_attributes( ["L_mech", "E_mech", "E_mech_last_feedback", "previous_mass"]) with open(info_file, "rb") as infile: (tmp1, tmp2, self.time_step_bridge, self.time_step_feedback, self.feedback_gas_particle_mass, self.feedback_efficiency, self.feedback_radius, self.verbose, self.total_feedback_energy, self.current_time) = cPickle.load(infile) def stop(self): print "STOP fieldcode" self.bridge.codes[0].field_codes[0].code.stop() print "STOP fieldcode" self.bridge.codes[1].field_codes[0].code.stop() print "STOP bridge" self.bridge.stop() print "STOP stellar" self.stellar.stop()
def evolve_coupled_system(binary_system, giant_system, t_end, n_steps, do_energy_evolution_plot, previous_data=None): directsum = CalculateFieldForParticles(particles=giant_system.particles, gravity_constant=constants.G) directsum.smoothing_length_squared = giant_system.parameters.gas_epsilon**2 coupled_system = Bridge(timestep=(t_end / (2 * n_steps)), verbose=False, use_threading=True) coupled_system.add_system(binary_system, (directsum,), False) coupled_system.add_system(giant_system, (binary_system,), False) times = (t_end * range(1, n_steps+1) / n_steps).as_quantity_in(units.day) if previous_data: with open(previous_data, 'rb') as file: (all_times, potential_energies, kinetic_energies, thermal_energies, giant_center_of_mass, ms1_position, ms2_position, giant_center_of_mass_velocity, ms1_velocity, ms2_velocity) = pickle.load(file) all_times.extend(times + all_times[-1]) else: all_times = times if do_energy_evolution_plot: potential_energies = coupled_system.particles.potential_energy().as_vector_with_length(1).as_quantity_in(units.erg) kinetic_energies = coupled_system.particles.kinetic_energy().as_vector_with_length(1).as_quantity_in(units.erg) thermal_energies = coupled_system.gas_particles.thermal_energy().as_vector_with_length(1).as_quantity_in(units.erg) else: potential_energies = kinetic_energies = thermal_energies = None giant_center_of_mass = [] | units.RSun ms1_position = [] | units.RSun ms2_position = [] | units.RSun giant_center_of_mass_velocity = [] | units.km / units.s ms1_velocity = [] | units.km / units.s ms2_velocity = [] | units.km / units.s i_offset = len(giant_center_of_mass) giant_total_mass = giant_system.particles.total_mass() ms1_mass = binary_system.particles[0].mass ms2_mass = binary_system.particles[1].mass print " Evolving for", t_end for i_step, time in enumerate(times): coupled_system.evolve_model(time) print " Evolved to:", time, if do_energy_evolution_plot: potential_energies.append(coupled_system.particles.potential_energy()) kinetic_energies.append(coupled_system.particles.kinetic_energy()) thermal_energies.append(coupled_system.gas_particles.thermal_energy()) giant_center_of_mass.append(giant_system.particles.center_of_mass()) ms1_position.append(binary_system.particles[0].position) ms2_position.append(binary_system.particles[1].position) giant_center_of_mass_velocity.append(giant_system.particles.center_of_mass_velocity()) ms1_velocity.append(binary_system.particles[0].velocity) ms2_velocity.append(binary_system.particles[1].velocity) a_giant, e_giant = calculate_orbital_elements(ms1_mass, ms2_mass, ms1_position, ms2_position, ms1_velocity, ms2_velocity, giant_total_mass, giant_center_of_mass, giant_center_of_mass_velocity) print "Outer Orbit:", time.in_(units.day), a_giant[-1].in_(units.AU), e_giant[-1], ms1_mass.in_(units.MSun), ms2_mass.in_(units.MSun), giant_total_mass.in_(units.MSun) if i_step % 10 == 9: snapshotfile = os.path.join("snapshots", "hydro_triple_{0:=04}_gas.amuse".format(i_step + i_offset)) write_set_to_file(giant_system.gas_particles, snapshotfile, format='amuse') snapshotfile = os.path.join("snapshots", "hydro_triple_{0:=04}_core.amuse".format(i_step + i_offset)) write_set_to_file(giant_system.dm_particles, snapshotfile, format='amuse') snapshotfile = os.path.join("snapshots", "hydro_triple_{0:=04}_binary.amuse".format(i_step + i_offset)) write_set_to_file(binary_system.particles, snapshotfile, format='amuse') datafile = os.path.join("snapshots", "hydro_triple_{0:=04}_info.amuse".format(i_step + i_offset)) with open(datafile, 'wb') as outfile: pickle.dump((all_times[:len(giant_center_of_mass)], potential_energies, kinetic_energies, thermal_energies, giant_center_of_mass, ms1_position, ms2_position, giant_center_of_mass_velocity, ms1_velocity, ms2_velocity), outfile) figname1 = os.path.join("plots", "hydro_triple_small{0:=04}.png".format(i_step + i_offset)) figname2 = os.path.join("plots", "hydro_triple_large{0:=04}.png".format(i_step + i_offset)) print " - Hydroplots are saved to: ", figname1, "and", figname2 for plot_range, plot_name in [(8|units.AU, figname1), (40|units.AU, figname2)]: if HAS_PYNBODY: pynbody_column_density_plot(coupled_system.gas_particles, width=plot_range, vmin=26, vmax=32) scatter(coupled_system.dm_particles.x, coupled_system.dm_particles.y, c="w") else: pyplot.figure(figsize = [16, 16]) sph_particles_plot(coupled_system.gas_particles, gd_particles=coupled_system.dm_particles, view=plot_range*[-0.5, 0.5, -0.5, 0.5]) pyplot.savefig(plot_name) pyplot.close() coupled_system.stop() make_movie() if do_energy_evolution_plot: energy_evolution_plot(all_times[:len(kinetic_energies)-1], kinetic_energies, potential_energies, thermal_energies) print " Calculating semimajor axis and eccentricity evolution for inner binary" # Some temporary variables to calculate semimajor_axis and eccentricity evolution total_mass = ms1_mass + ms2_mass rel_position = ms1_position - ms2_position rel_velocity = ms1_velocity - ms2_velocity separation_in = rel_position.lengths() speed_squared_in = rel_velocity.lengths_squared() # Now calculate the important quantities: semimajor_axis_binary = (constants.G * total_mass * separation_in / (2 * constants.G * total_mass - separation_in * speed_squared_in)).as_quantity_in(units.AU) eccentricity_binary = numpy.sqrt(1.0 - (rel_position.cross(rel_velocity)**2).sum(axis=1) / (constants.G * total_mass * semimajor_axis_binary)) print " Calculating semimajor axis and eccentricity evolution of the giant's orbit" # Some temporary variables to calculate semimajor_axis and eccentricity evolution rel_position = ((ms1_mass * ms1_position + ms2_mass * ms2_position)/total_mass - giant_center_of_mass) rel_velocity = ((ms1_mass * ms1_velocity + ms2_mass * ms2_velocity)/total_mass - giant_center_of_mass_velocity) total_mass += giant_total_mass separation = rel_position.lengths() speed_squared = rel_velocity.lengths_squared() # Now calculate the important quantities: semimajor_axis_giant = (constants.G * total_mass * separation / (2 * constants.G * total_mass - separation * speed_squared)).as_quantity_in(units.AU) eccentricity_giant = numpy.sqrt(1.0 - (rel_position.cross(rel_velocity)**2).sum(axis=1) / (constants.G * total_mass * semimajor_axis_giant)) orbit_parameters_plot(semimajor_axis_binary, semimajor_axis_giant, all_times[:len(semimajor_axis_binary)]) orbit_ecc_plot(eccentricity_binary, eccentricity_giant, all_times[:len(eccentricity_binary)]) orbit_parameters_plot(separation_in.as_quantity_in(units.AU), separation.as_quantity_in(units.AU), all_times[:len(eccentricity_binary)], par_symbol="r", par_name="separation") orbit_parameters_plot(speed_squared_in.as_quantity_in(units.km**2 / units.s**2), speed_squared.as_quantity_in(units.km**2 / units.s**2), all_times[:len(eccentricity_binary)], par_symbol="v^2", par_name="speed_squared")