def evolve_model(self): convert_nbody = nbody_system.nbody_to_si(1.0 | units.MSun, 149.5e6 | units.km) hermite = Hermite(convert_nbody) hermite.initialize_code() hermite.parameters.epsilon_squared = 0.0 | units.AU**2 stars = self.new_system_of_sun_and_earth() earth = stars[1] sun = stars[0] Earth = blender.Primitives.sphere(10, 10, 0.1) # Make the earth avatar Sun = blender.Primitives.sphere(32, 32, 1) # Make the sun avatar hermite.particles.add_particles(stars) for i in range(1 * 365): hermite.evolve_model(i | units.day) hermite.particles.copy_values_of_all_attributes_to(stars) # update avatar positions: Earth.loc = (1 * earth.position.value_in(units.AU)[0], 1 * earth.position.value_in(units.AU)[1], earth.position.value_in(units.AU)[2]) Sun.loc = (1 * sun.position.value_in(units.AU)[0], 1 * sun.position.value_in(units.AU)[1], sun.position.value_in(units.AU)[2]) blender.Redraw() hermite.print_refs() hermite.stop()
def test13(self): particles = plummer.new_plummer_model(31) instance = Hermite(number_of_workers=1)#, debugger="xterm") instance.initialize_code() instance.parameters.epsilon_squared = 0.01 | nbody_system.length ** 2 instance.particles.add_particles(particles) instance.evolve_model(0.1 | nbody_system.time) instance.synchronize_model() expected_positions = instance.particles.position instance.stop() positions_per_workers = [] for n in [2,3,4,5]: instance = Hermite(number_of_workers=n) instance.initialize_code() instance.parameters.epsilon_squared = 0.01 | nbody_system.length ** 2 instance.particles.add_particles(particles) instance.evolve_model(0.1 | nbody_system.time) instance.synchronize_model() positions_per_workers.append(instance.particles.position) instance.stop() for index, n in enumerate([2,3,4,5]): self.assertAlmostEqual(expected_positions, positions_per_workers[index], 15)
def simulate_small_cluster(number_of_stars=1000, end_time=40 | nbody_system.time, number_of_workers=1): particles = new_plummer_model(number_of_stars) particles.scale_to_standard() gravity = Hermite(number_of_workers=number_of_workers) gravity.parameters.epsilon_squared = 0.15 | nbody_system.length**2 gravity.particles.add_particles(particles) from_gravity_to_model = gravity.particles.new_channel_to(particles) time = 0.0 * end_time total_energy_at_t0 = gravity.kinetic_energy + gravity.potential_energy positions_at_different_times = [] positions_at_different_times.append(particles.position) times = [] times.append(time) print("evolving the model until t = " + str(end_time)) while time < end_time: time += end_time / 3.0 gravity.evolve_model(time) from_gravity_to_model.copy() positions_at_different_times.append(particles.position) times.append(time) print_log(time, gravity, particles, total_energy_at_t0) gravity.stop() return times, positions_at_different_times
def test3(self): convert_nbody = nbody_system.nbody_to_si(1.0 | units.MSun, 149.5e6 | units.km) instance = Hermite(convert_nbody) instance.initialize_code() instance.parameters.epsilon_squared = 0.00001 | units.AU**2 instance.dt_dia = 5000 stars = datamodel.Stars(2) star1 = stars[0] star2 = stars[1] star1.mass = units.MSun(1.0) star1.position = units.AU(numpy.array((-1.0,0.0,0.0))) star1.velocity = units.AUd(numpy.array((0.0,0.0,0.0))) star1.radius = units.RSun(1.0) star2.mass = units.MSun(1.0) star2.position = units.AU(numpy.array((1.0,0.0,0.0))) star2.velocity = units.AUd(numpy.array((0.0,0.0,0.0))) star2.radius = units.RSun(100.0) instance.particles.add_particles(stars) for x in range(1,2000,10): instance.evolve_model(x | units.day) instance.particles.copy_values_of_all_attributes_to(stars) stars.savepoint() instance.cleanup_code() instance.stop()
def test12(self): particles = datamodel.Particles(2) particles.x = [0.0, 1.00] | nbody_system.length particles.y = [0.0, 0.0] | nbody_system.length particles.z = [0.0, 0.0] | nbody_system.length particles.radius = 0.005 | nbody_system.length particles.vx = [5.1, 0.0] | nbody_system.speed particles.vy = [0.0, 0.0] | nbody_system.speed particles.vz = [0.0, 0.0] | nbody_system.speed particles.mass = [0.1, 0.1] | nbody_system.mass instance = Hermite() instance.initialize_code() instance.parameters.stopping_conditions_out_of_box_size = .5 | nbody_system.length self.assertEqual( instance.parameters.stopping_conditions_out_of_box_size, .5 | nbody_system.length) instance.particles.add_particles(particles) instance.stopping_conditions.out_of_box_detection.enable() instance.evolve_model(0.1 | nbody_system.time) self.assertTrue( instance.stopping_conditions.out_of_box_detection.is_set()) self.assertAlmostEqual( instance.stopping_conditions.out_of_box_detection.particles(0).x, 1.0 | nbody_system.length, 3) instance.stop()
def test22(self): hermite = Hermite() hermite.parameters.epsilon_squared = 0.0 | nbody_system.length**2 particles = datamodel.Particles(2) particles.position = ([0, 0, 0], [1, 0, 0]) | nbody_system.length particles.velocity = ([-2, 0, 0], [2, 0, 0]) | nbody_system.speed particles.radius = 0 | nbody_system.length particles.mass = 0.1 | nbody_system.mass hermite.particles.add_particles(particles) hermite.stopping_conditions.out_of_box_detection.enable() hermite.parameters.stopping_conditions_out_of_box_size = 2 | nbody_system.length hermite.parameters.stopping_conditions_out_of_box_use_center_of_mass = False hermite.evolve_model(1 | nbody_system.time) print(hermite.particles.x) print(hermite.particles.key, particles[1].key) print(hermite.stopping_conditions.out_of_box_detection.particles(0)) self.assertTrue( hermite.stopping_conditions.out_of_box_detection.is_set()) self.assertEqual( len(hermite.stopping_conditions.out_of_box_detection.particles(0)), 1) self.assertEqual( hermite.stopping_conditions.out_of_box_detection.particles(0) [0].key, particles[1].key) hermite.stop()
def simulate_system_until(particles, end_time): convert_nbody = nbody_system.nbody_to_si(1.0 | units.MSun, 149.5e6 | units.km) instance = Hermite(convert_nbody) instance.parameters.epsilon_squared = 0.0 | units.AU**2 instance.particles.add_particles(particles) t0 = 0 | units.day dt = 10 | units.day t = t0 earth = instance.particles[1] x_values = quantities.AdaptingVectorQuantity() y_values = quantities.AdaptingVectorQuantity() while t < end_time: instance.evolve_model(t) x_values.append(earth.x) y_values.append(earth.y) t += dt instance.stop() return x_values, y_values
def evolve_model(end_time, double_star, stars): converter = nbody_system.nbody_to_si(double_star.mass, double_star.semimajor_axis) gravity = Hermite(converter) gravity.particles.add_particle(stars) to_stars = gravity.particles.new_channel_to(stars) # from_stars = stars.new_channel_to(gravity.particles) time = 0 | units.yr dt = end_time / 100. a = [] | units.au t = [] | units.yr while time < end_time: time += dt gravity.evolve_model(1 | units.yr) to_stars.copy() orbital_elements = orbital_elements_from_binary(stars, G=constants.G) a.append(orbital_elements[2]) t.append(time) gravity.stop() from matplotlib import pyplot pyplot.scatter(t.value_in(units.yr), a.value_in(units.au)) pyplot.show()
def test18(self): particles = datamodel.Particles(2) particles.x = [0.0,1.0] | nbody_system.length particles.y = 0.0 | nbody_system.length particles.z = 0.0 | nbody_system.length particles.vx = 0.0 | nbody_system.speed particles.vy = 0.0 | nbody_system.speed particles.vz = 0.0 | nbody_system.speed particles.mass = 1.0 | nbody_system.mass instance = Hermite() instance.particles.add_particles(particles) instance.commit_particles() self.assertEqual(instance.particles[0].radius, 0.0 | nbody_system.length) instance.parameters.end_time_accuracy_factor = 1.0 instance.evolve_model(0.1 | nbody_system.time) self.assertAlmostRelativeEquals(instance.model_time, 0.10563767746 |nbody_system.time, 5) instance.parameters.end_time_accuracy_factor = -1.0 instance.evolve_model(0.3 | nbody_system.time) self.assertAlmostRelativeEquals(instance.model_time, 0.266758127609 |nbody_system.time, 5) instance.parameters.end_time_accuracy_factor = 0.0 instance.evolve_model(0.4 | nbody_system.time) self.assertAlmostRelativeEquals(instance.model_time, 0.4 |nbody_system.time, 6) instance.parameters.end_time_accuracy_factor = -0.5 instance.evolve_model(0.5 | nbody_system.time) self.assertAlmostRelativeEquals(instance.model_time, 0.48974930698 |nbody_system.time, 6) instance.parameters.end_time_accuracy_factor = +0.5 instance.evolve_model(0.6 | nbody_system.time) self.assertAlmostRelativeEquals(instance.model_time, 0.6042733579 |nbody_system.time, 6) instance.stop()
def test8(self): print("Testing Hermite collision_detection") particles = datamodel.Particles(7) particles.mass = 0.001 | nbody_system.mass particles.radius = 0.01 | nbody_system.length particles.x = [-101.0, -100.0, -0.5, 0.5, 100.0, 101.0, 104.0] | nbody_system.length particles.y = 0 | nbody_system.length particles.z = 0 | nbody_system.length particles.velocity = [[2, 0, 0], [-2, 0, 0]]*3 + [[-4, 0, 0]] | nbody_system.speed instance = Hermite() instance.initialize_code() instance.parameters.set_defaults() instance.particles.add_particles(particles) collisions = instance.stopping_conditions.collision_detection collisions.enable() instance.evolve_model(1.0 | nbody_system.time) self.assertTrue(collisions.is_set()) self.assertTrue(instance.model_time < 0.5 | nbody_system.time) self.assertEqual(len(collisions.particles(0)), 3) self.assertEqual(len(collisions.particles(1)), 3) self.assertEqual(len(particles - collisions.particles(0) - collisions.particles(1)), 1) self.assertEqual(abs(collisions.particles(0).x - collisions.particles(1).x) <= (collisions.particles(0).radius + collisions.particles(1).radius), [True, True, True]) sticky_merged = datamodel.Particles(len(collisions.particles(0))) sticky_merged.mass = collisions.particles(0).mass + collisions.particles(1).mass sticky_merged.radius = collisions.particles(0).radius for p1, p2, merged in zip(collisions.particles(0), collisions.particles(1), sticky_merged): merged.position = (p1 + p2).center_of_mass() merged.velocity = (p1 + p2).center_of_mass_velocity() print(instance.model_time) print(instance.particles) instance.particles.remove_particles(collisions.particles(0) + collisions.particles(1)) instance.particles.add_particles(sticky_merged) instance.evolve_model(1.0 | nbody_system.time) print() print(instance.model_time) print(instance.particles) self.assertTrue(collisions.is_set()) self.assertTrue(instance.model_time < 1.0 | nbody_system.time) self.assertEqual(len(collisions.particles(0)), 1) self.assertEqual(len(collisions.particles(1)), 1) self.assertEqual(len(instance.particles - collisions.particles(0) - collisions.particles(1)), 2) self.assertEqual(abs(collisions.particles(0).x - collisions.particles(1).x) <= (collisions.particles(0).radius + collisions.particles(1).radius), [True]) instance.stop()
def test19(self): particles = datamodel.Particles(2) particles.x = [0.0,200.0] | nbody_system.length particles.y = 0.0 | nbody_system.length particles.z = 0.0 | nbody_system.length particles.vx = 0.0 | nbody_system.speed particles.vy = 0.0 | nbody_system.speed particles.vz = 0.0 | nbody_system.speed particles.mass = 1.0 | nbody_system.mass instance = Hermite() instance.particles.add_particles(particles) instance.commit_particles() self.assertEqual(instance.particles[0].radius, 0.0 | nbody_system.length) instance.parameters.end_time_accuracy_factor = 0.0 instance.evolve_model(0.1 | nbody_system.time) self.assertAlmostRelativeEquals(instance.model_time, 0.1 |nbody_system.time, 5) instance.stop()
def test7(self): print("Test7: Testing effect of Hermite parameter epsilon_squared") convert_nbody = nbody_system.nbody_to_si(1.0 | units.MSun, 1.0 | units.AU) particles = datamodel.Particles(2) sun = particles[0] sun.mass = 1.0 | units.MSun sun.position = [0.0, 0.0, 0.0] | units.AU sun.velocity = [0.0, 0.0, 0.0] | units.AU / units.yr sun.radius = 1.0 | units.RSun earth = particles[1] earth.mass = 5.9736e24 | units.kg earth.radius = 6371.0 | units.km earth.position = [0.0, 1.0, 0.0] | units.AU earth.velocity = [2.0 * numpy.pi, -0.0001, 0.0] | units.AU / units.yr initial_direction = math.atan((earth.velocity[0] / earth.velocity[1])) final_direction = [] for log_eps2 in range(-9, 10, 2): instance = Hermite(convert_nbody) instance.parameters.end_time_accuracy_factor = 0.0 instance.parameters.epsilon_squared = 10.0**log_eps2 | units.AU**2 instance.particles.add_particles(particles) instance.commit_particles() instance.evolve_model(0.25 | units.yr) final_direction.append( math.atan((instance.particles[1].velocity[0] / instance.particles[1].velocity[1]))) instance.stop() # Small values of epsilon_squared should result in normal earth-sun dynamics: rotation of 90 degrees self.assertAlmostEqual(abs(final_direction[0]), abs(initial_direction + math.pi / 2.0), 2) # Large values of epsilon_squared should result in ~ no interaction self.assertAlmostEqual(final_direction[-1], initial_direction, 2) # Outcome is most sensitive to epsilon_squared when epsilon_squared = d(earth, sun)^2 delta = [ abs(final_direction[i + 1] - final_direction[i]) for i in range(len(final_direction) - 1) ] self.assertEqual(delta[len(final_direction) // 2 - 1], max(delta))
def test23(self): hermite = Hermite() hermite.parameters.epsilon_squared = 0.0 | nbody_system.length**2 particles = datamodel.Particles(1) particles.position = ([0,0,0] )| nbody_system.length particles.velocity = ([1,0,0] )| nbody_system.speed particles.radius = 0| nbody_system.length particles.mass = 0.1| nbody_system.mass hermite.particles.add_particles(particles) hermite.evolve_model(1 | nbody_system.time) print(hermite.particles.x) self.assertAlmostRelativeEquals(hermite.model_time, 1 | nbody_system.time) self.assertAlmostRelativeEquals(hermite.particles[0].x, 1 | nbody_system.length) hermite.evolve_model(1.5 | nbody_system.time) print(hermite.particles.x) self.assertAlmostRelativeEquals(hermite.model_time, 1.5 | nbody_system.time) self.assertAlmostRelativeEquals(hermite.particles[0].x, 1.5 | nbody_system.length) hermite.stop()
def test2(self): convert_nbody = nbody_system.nbody_to_si(1.0 | units.MSun, 149.5e6 | units.km) instance = Hermite(convert_nbody) instance.initialize_code() instance.parameters.epsilon_squared = 0.0 | units.AU**2 instance.dt_dia = 5000 stars = self.new_system_of_sun_and_earth() earth = stars[1] instance.particles.add_particles(stars) for x in range(1, 500, 10): instance.evolve_model(x | units.day) instance.particles.copy_values_of_all_attributes_to(stars) stars.savepoint() if HAS_MATPLOTLIB: figure = pyplot.figure() plot = figure.add_subplot(1,1,1) x_points = earth.get_timeline_of_attribute("x") y_points = earth.get_timeline_of_attribute("y") x_points_in_AU = [t_x[1].value_in(units.AU) for t_x in x_points] y_points_in_AU = [t_x1[1].value_in(units.AU) for t_x1 in y_points] plot.scatter(x_points_in_AU,y_points_in_AU, color="b", marker='o') plot.set_xlim(-1.5, 1.5) plot.set_ylim(-1.5, 1.5) test_results_path = self.get_path_to_results() output_file = os.path.join(test_results_path, "hermite-earth-sun2.svg") figure.savefig(output_file) instance.cleanup_code() instance.stop()
def test10(self): convert_nbody = nbody_system.nbody_to_si(1.0 | units.MSun, 149.5e6 | units.km) instance = Hermite(convert_nbody) instance.initialize_code() instance.parameters.epsilon_squared = 0.0 | units.AU**2 instance.parameters.stopping_conditions_number_of_steps = 10 self.assertEqual(instance.parameters.stopping_conditions_number_of_steps,10) stars = self.new_system_of_sun_and_earth() earth = stars[1] instance.particles.add_particles(stars) instance.stopping_conditions.number_of_steps_detection.enable() instance.evolve_model(365.0 | units.day) self.assertTrue(instance.stopping_conditions.number_of_steps_detection.is_set()) instance.particles.copy_values_of_all_attributes_to(stars) instance.cleanup_code() instance.stop()
def test1(self): convert_nbody = nbody_system.nbody_to_si(1.0 | units.MSun, 149.5e6 | units.km) hermite = Hermite(convert_nbody) hermite.initialize_code() hermite.parameters.epsilon_squared = 0.0 | units.AU**2 hermite.parameters.end_time_accuracy_factor = 0.0 hermite.dt_dia = 5000 stars = self.new_system_of_sun_and_earth() earth = stars[1] hermite.particles.add_particles(stars) hermite.evolve_model(365.0 | units.day) hermite.particles.copy_values_of_all_attributes_to(stars) position_at_start = earth.position.value_in(units.AU)[0] position_after_full_rotation = earth.position.value_in(units.AU)[0] self.assertAlmostRelativeEqual(position_at_start, position_after_full_rotation, 6) hermite.evolve_model(365.0 + (365.0 / 2) | units.day) hermite.particles.copy_values_of_all_attributes_to(stars) position_after_half_a_rotation = earth.position.value_in(units.AU)[0] self.assertAlmostRelativeEqual(-position_at_start, position_after_half_a_rotation, 3) hermite.evolve_model(365.0 + (365.0 / 2) + (365.0 / 4) | units.day) hermite.particles.copy_values_of_all_attributes_to(stars) position_after_half_a_rotation = earth.position.value_in(units.AU)[1] self.assertAlmostRelativeEqual(-position_at_start, position_after_half_a_rotation, 3) hermite.cleanup_code() hermite.stop()
def test11(self): particles = datamodel.Particles(2) particles.x = [0.0,10.0] | nbody_system.length particles.y = 0 | nbody_system.length particles.z = 0 | nbody_system.length particles.radius = 0.005 | nbody_system.length particles.vx = 0 | nbody_system.speed particles.vy = 0 | nbody_system.speed particles.vz = 0 | nbody_system.speed particles.mass = 1.0 | nbody_system.mass instance = Hermite() instance.initialize_code() instance.parameters.stopping_conditions_number_of_steps = 2 self.assertEqual(instance.parameters.stopping_conditions_number_of_steps, 2) instance.particles.add_particles(particles) instance.stopping_conditions.number_of_steps_detection.enable() instance.evolve_model(10 | nbody_system.time) self.assertTrue(instance.stopping_conditions.number_of_steps_detection.is_set()) self.assertTrue(instance.model_time < 10 | nbody_system.time) instance.stop()
def supernova_in_binary_nbody(M0, m0, a0, tsn): stars = make_circular_binary(M0, m0, a0) M, m, a, e, ta_out, inc, lan_out, aop_out = orbital_elements_from_binary( stars, G=constants.G) print("Initial binary: a=", a.in_( units.AU), "e=", e, "M=", stars[0].mass, "and m=", stars[1].mass) converter = nbody_system.nbody_to_si(M + m, a) gravity = Hermite(converter) gravity.particles.add_particles(stars) print("Integrate binary to t=", tsn.in_(units.day)) gravity.evolve_model(tsn) M, m, a, e, ta_out, inc, lan_out, aop_out = orbital_elements_from_binary( stars, G=constants.G) print("Pre supernova orbit: a=", a.in_(units.AU), "e=", e) stars[0].mass *= 0.1 print("Reduce stellar mass to: M=", stars[0].mass, "and m=", stars[1].mass) v_kick = (0, 0, 0) | units.kms stars[0].velocity += v_kick gravity.evolve_model(2 * tsn) M, m, a, e, ta_out, inc, lan_out, aop_out = orbital_elements_from_binary( stars, G=constants.G) print("Post supernova orbit: a=", a.in_(units.AU), "e=", e) r0 = a a_ana = post_supernova_semimajor_axis( M0, m0, stars[0].mass, stars[1].mass, a, r0) e_ana = post_supernova_eccentricity( M0, m0, stars[0].mass, stars[1].mass, a, r0) print( "Analytic solution to post orbit orbital parameters: a=", a_ana, "e=", e_ana, ) gravity.stop()
def evolve_model(end_time, double_star, stars): time = 0 | units.yr dt = 0.5*end_time/1000. converter = nbody_system.nbody_to_si(double_star.mass, double_star.semimajor_axis) gravity = Hermite(converter) gravity.particles.add_particle(stars) to_stars = gravity.particles.new_channel_to(stars) from_stars = stars.new_channel_to(gravity.particles) period = ( 2*numpy.pi * ( double_star.semimajor_axis*double_star.semimajor_axis*double_star.semimajor_axis / (constants.G*double_star.mass) ).sqrt() ) print("Period =", period.as_string_in(units.yr)) print("Mass loss timestep =", dt) print("Steps per period: = {:1.2f}".format(period/dt)) a_an = [] | units.au e_an = [] atemp = double_star.semimajor_axis etemp = double_star.eccentricity print(atemp) a = [] | units.au e = [] m = [] | units.MSun t = [] | units.yr while time<end_time: time += dt gravity.evolve_model(time) to_stars.copy() dmdt = mass_loss_rate(stars.mass) dadt = dadt_masschange(atemp, stars.mass, dmdt) dedt = dedt_masschange(etemp, stars.mass, dmdt) atemp = atemp + dadt*dt etemp = etemp + dedt*dt a_an.append(atemp) e_an.append(etemp) stars.mass += dmdt * dt from_stars.copy() orbital_elements = orbital_elements_from_binary(stars, G=constants.G) a.append(orbital_elements[2]) e.append(orbital_elements[3]) m.append(stars.mass.sum()) t.append(time) print("time=", time.in_(units.yr), "a=", a[-1].in_(units.RSun), "e=", e[-1], "m=", stars.mass.in_(units.MSun), end="\r") gravity.stop() from matplotlib import pyplot fig, axis = pyplot.subplots(nrows=2, ncols=2, sharex=True) axis[0][0].plot(t.value_in(units.yr), a.value_in(units.RSun), label="nbody") axis[0][0].plot(t.value_in(units.yr), a_an.value_in(units.RSun), label="analytic") axis[0][0].set_ylabel("a [$R_\odot$]") axis[0][0].legend() axis[0][1].plot(t.value_in(units.yr), m.value_in(units.MSun)) axis[0][1].set_ylabel("M [$M_\odot$]") axis[1][1].plot(t.value_in(units.yr), e) axis[1][1].plot(t.value_in(units.yr), e_an) axis[1][1].set_ylabel("e") axis[1][1].set_xlabel("time [yr]") axis[1][0].set_xlabel("time [yr]") pyplot.savefig("mloss.png") pyplot.show()
def evolve_model(end_time, double_star, stars): time = 0 | units.yr dt = 0.5 * end_time / 1000. * 2 converter = nbody_system.nbody_to_si(double_star.mass, double_star.semimajor_axis) stars2 = stars.copy() gravity = Hermite(converter) gravity.particles.add_particle(stars) to_stars = gravity.particles.new_channel_to(stars) from_stars = stars.new_channel_to(gravity.particles) gravity2 = Hermite(converter) gravity2.particles.add_particle(stars2) to_stars2 = gravity2.particles.new_channel_to(stars2) from_stars2 = stars2.new_channel_to(gravity2.particles) period = (2 * numpy.pi * (double_star.semimajor_axis * double_star.semimajor_axis * double_star.semimajor_axis / (constants.G * double_star.mass)).sqrt()) print("Period =", period.as_string_in(units.yr)) print("Mass loss timestep =", dt) print("Steps per period: = {:1.2f}".format(period / dt)) a_an = [] | units.au e_an = [] atemp = double_star.semimajor_axis etemp = double_star.eccentricity a = [] | units.au e = [] ome = [] a2 = [] | units.au e2 = [] ome2 = [] m1 = [] | units.MSun m2 = [] | units.MSun t = [] | units.yr while time < end_time: time += dt gravity.evolve_model(time) gravity2.evolve_model(time) to_stars.copy() to_stars2.copy() dmdtloss = mass_loss_rate(stars.mass) dmdtacc = dmdt_acc(dmdtloss) orbital_elements = orbital_elements_from_binary(stars, G=constants.G) orbital_elements2 = orbital_elements_from_binary(stars2, G=constants.G) # etemp = orbital_elements[3] # atemp = orbital_elements[2] dadt = dadt_masschange(atemp, stars.mass, dmdtloss + dmdtacc) dedt = dedt_masschange(etemp, stars.mass, dmdtloss + dmdtacc) dadt += dadt_momentumchange(atemp, etemp, stars.mass, dmdtacc) dedt += dedt_momentumchange(etemp, stars.mass, dmdtacc) h = (constants.G * stars.mass.sum() * atemp * (1 - etemp * etemp))**0.5 dhdt = dhdt_momentumchange(h, stars.mass, dmdtacc) atemp = atemp + dadt * dt etemp = etemp + dedt * dt a_an.append(atemp) e_an.append(etemp) kick_from_accretion(stars, dmdtacc, dt) dhdt_dadt_to_kick(stars2, dhdt, dadt, dmdtloss + dmdtacc, dt) stars.mass += (dmdtloss + dmdtacc) * dt stars2.mass += (dmdtloss + dmdtacc) * dt from_stars.copy() from_stars2.copy() a.append(orbital_elements[2]) e.append(orbital_elements[3]) ome.append(orbital_elements[7]) a2.append(orbital_elements2[2]) e2.append(orbital_elements2[3]) ome2.append(orbital_elements2[7]) m1.append(stars[0].mass) m2.append(stars[1].mass) t.append(time) print("time=", time.in_(units.yr), "a=", a[-1].in_(units.RSun), "e=", e[-1], "m=", stars.mass.in_(units.MSun), "end=\r") gravity.stop() gravity2.stop() from matplotlib import pyplot pyplot.rc('text', usetex=True) pyplot.rcParams.update({'font.size': 16}) fig, axis = pyplot.subplots(nrows=2, ncols=2, sharex=True, figsize=(13, 6)) axis[0][0].plot(t.value_in(units.yr), a.value_in(units.RSun), label="nbody (direct)", lw=2) axis[0][0].plot(t.value_in(units.yr), a2.value_in(units.RSun), label="nbody (heuristic)", lw=2, ls="--") axis[0][0].plot(t.value_in(units.yr), a_an.value_in(units.RSun), label="analytic", lw=2, ls="-.") axis[0][0].set_ylabel("a [$R_\odot$]") axis[0][0].legend() axis[0][1].plot(t.value_in(units.yr), m1.value_in(units.MSun), label="m1", lw=2, c="tab:red") axis[0][1].plot(t.value_in(units.yr), m2.value_in(units.MSun), label="m2", lw=2, c="tab:cyan") axis[0][1].set_ylabel("M [$M_\odot$]") axis[0][1].legend() axis[1][1].plot(t.value_in(units.yr), e, lw=2) axis[1][1].plot(t.value_in(units.yr), e2, lw=2, ls="--") axis[1][1].plot(t.value_in(units.yr), e_an, lw=2, ls="-.") axis[1][1].set_ylabel("e") axis[1][0].plot(t.value_in(units.yr), ome, lw=2, label="nbody (direct)") axis[1][0].plot(t.value_in(units.yr), ome2, lw=2, ls="--", label="nbody (heuristic)") axis[1][0].set_ylabel("$\omega$ [degrees]") axis[1][1].set_xlabel("time [yr]") axis[1][0].set_xlabel("time [yr]") pyplot.tight_layout() pyplot.subplots_adjust(hspace=0, top=0.93, bottom=0.1) pyplot.suptitle("mloss+macc+momentum change, same model") pyplot.savefig("comparisons.png") pyplot.show()
def evolve_model(end_time, double_star, stars): time = 0 | units.yr converter = nbody_system.nbody_to_si(double_star.mass, double_star.semimajor_axis) #time = 10.0017596364 | units.yr #inname = "binstar_10.0017596364.hdf5" #stars = read_set_from_file(inname, "hdf5") gravity = Hermite(converter) gravity.particles.add_particle(stars) to_stars = gravity.particles.new_channel_to(stars) from_stars = stars.new_channel_to(gravity.particles) period = (2 * numpy.pi * (double_star.semimajor_axis * double_star.semimajor_axis * double_star.semimajor_axis / (constants.G * double_star.mass)).sqrt()) print("Period =", period.as_string_in(units.yr)) dt = period / 32. print("Mass loss timestep =", dt) print("Steps per period: = {:1.2f}".format(period / dt)) print("Radii", stars.radius) print("Taulag", stars.taulag) print("K", stars.kaps) QT = QuickTides(double_star.semimajor_axis, double_star.eccentricity, stars[0].mass, stars[1].mass, stars[0].radius, stars[1].radius, stars[0].kaps, stars[1].kaps, stars[0].taulag, stars[1].taulag) print(stars) a_an = [] | units.au e_an = [] atemp = double_star.semimajor_axis etemp = double_star.eccentricity a = [] | units.au e = [] m = [] | units.MSun t = [] | units.yr while time < end_time: time += dt gravity.evolve_model(time) to_stars.copy() dadt, dedt = QT.dadt_dedt(atemp, etemp) atemp = atemp + dadt * dt etemp = etemp + dedt * dt a_an.append(atemp) e_an.append(etemp) kick_stars_tides(stars, dt) from_stars.copy() orbital_elements = orbital_elements_from_binary(stars, G=constants.G) a.append(orbital_elements[2]) e.append(orbital_elements[3]) m.append(stars.mass.sum()) t.append(time) if check_collision(stars): break print("time=", time.in_(units.yr), "a=", a[-1].in_(units.RSun), "e=", e[-1], "m=", stars.mass.in_(units.MSun), end="\r") gravity.stop() from matplotlib import pyplot fig, axis = pyplot.subplots(nrows=2, ncols=2, sharex=True) axis[0][0].plot(t.value_in(units.yr), a.value_in(units.au), label="nbody") axis[0][0].plot(t.value_in(units.yr), a_an.value_in(units.au), label="analytic") axis[0][0].set_ylabel("a [$R_\odot$]") axis[0][0].legend() write_set_to_file(stars, "binstar_" + str(time.value_in(units.yr)) + ".hdf5", "hdf5") numpy.savetxt( "ae_{:d}.txt".format(numpy.random.randint(0, 1000)), numpy.vstack([t.value_in(units.yr), a.value_in(units.au), e]).T) axis[0][1].plot(t.value_in(units.yr), m.value_in(units.MSun)) axis[0][1].set_ylabel("M [$M_\odot$]") axis[1][1].plot(t.value_in(units.yr), e) axis[1][1].plot(t.value_in(units.yr), e_an) axis[1][1].set_ylabel("e") axis[1][1].set_xlabel("time [yr]") axis[1][0].set_xlabel("time [yr]") pyplot.savefig("mloss.png") pyplot.show()
def evolve_model(end_time, double_star, stars): time = 0 | units.yr dt = 0.5 * end_time / 1000. converter = nbody_system.nbody_to_si(double_star.mass, double_star.semimajor_axis) gravity = Hermite(converter) gravity.particles.add_particle(stars) to_stars = gravity.particles.new_channel_to(stars) from_stars = stars.new_channel_to(gravity.particles) a_an = [] | units.au e_an = [] # dt_an = dt/1000. atemp = double_star.semimajor_axis etemp = double_star.eccentricity print(atemp) a = [] | units.au e = [] m = [] | units.MSun t = [] | units.yr while time < end_time: # ana_time = time # ana_time_end = time + dt # while ana_time < ana_time_end: # dmdt_ana = -1*mass_loss_rate(stars.mass) # print(atemp) # dadt = dadt_massloss(atemp, stars.mass, dmdt_ana) # dedt = dedt_massloss(etemp, stars.mass, dmdt_ana) # atemp = dadt*dt # etemp = dedt*dt # ana_time += dt_an time += dt gravity.evolve_model(time) to_stars.copy() dmdt = mass_loss_rate(stars.mass) dadt = dadt_massloss(atemp, stars.mass, dmdt) dedt = dedt_massloss(etemp, stars.mass, dmdt) atemp = atemp + dadt * dt etemp = etemp + dedt * dt a_an.append(atemp) e_an.append(etemp) stars.mass -= dmdt * dt from_stars.copy() orbital_elements = orbital_elements_from_binary(stars, G=constants.G) a.append(orbital_elements[2]) e.append(orbital_elements[3]) m.append(stars.mass.sum()) t.append(time) print("time=", time.in_(units.yr), "a=", a[-1].in_(units.RSun), "e=", e[-1], "m=", stars.mass.in_(units.MSun)) gravity.stop() from matplotlib import pyplot fig, axis = pyplot.subplots(nrows=2, ncols=2, sharex=True) axis[0][0].scatter(t.value_in(units.yr), a.value_in(units.RSun)) axis[0][0].scatter(t.value_in(units.yr), a_an.value_in(units.RSun)) axis[0][0].set_ylabel("a [$R_\odot$]") axis[0][1].scatter(t.value_in(units.yr), m.value_in(units.MSun)) axis[0][1].set_ylabel("M [$M_\odot$]") axis[1][1].scatter(t.value_in(units.yr), e) axis[1][1].scatter(t.value_in(units.yr), e_an) axis[1][1].set_ylabel("e") axis[1][1].set_xlabel("time [yr]") axis[1][0].set_xlabel("time [yr]") pyplot.show() pyplot.savefig("mloss.png")
def evolve_model(end_time, double_star, stars): time = 0 | units.yr dt = 0.05 * end_time / 1000. converter = nbody_system.nbody_to_si(double_star.mass, double_star.semimajor_axis) gravity = Hermite(converter) gravity.particles.add_particle(stars) to_stars = gravity.particles.new_channel_to(stars) from_stars = stars.new_channel_to(gravity.particles) period = get_period(double_star) print("Period =", period.as_string_in(units.yr)) print("Mass loss timestep =", dt) print("Steps per period: = {:1.2f}".format(period / dt)) a_an = [] | units.au e_an = [] atemp = double_star.semimajor_axis etemp = double_star.eccentricity ###### COMMON ENVELOPE STUFF ############### final_a = 40 | units.RSun mu = double_star.mass * constants.G Eps0 = mu / (2 * double_star.semimajor_axis) Eps1 = mu / (2 * final_a) # Eps_ce should come from alpha lambda model, but we just fix the final semimajor axis here for simplicity Eps_ce = Eps1 - Eps0 print("Eps_ce/Eps0", Eps_ce / Eps0) Tce = 1000 | units.yr Kce = K_from_eps(Eps0, Eps_ce, Tce, mu) print("Kce", Kce) Avisc = -Kce * Tce print("Avisc", Avisc.as_string_in(units.RSun**2)) Rvisc = Avisc.sqrt() / (4 * constants.pi) print("Rvisc", Rvisc.as_string_in(units.RSun)) vorb = (mu / double_star.semimajor_axis).sqrt() ###### END COMMON ENVELOPE STUFF ############### collision = False a = [] | units.au e = [] m = [] | units.MSun t = [] | units.yr while time < end_time: time += dt if not collision: gravity.evolve_model(time) to_stars.copy() kick_stars_comenv2(stars, dt, Kce, Avisc) from_stars.copy() from_stars.copy() orbital_elements = orbital_elements_from_binary(stars, G=constants.G) collision = check_collisions(stars) if atemp.number > 0: dadt = dadt_comenv_k0(atemp, etemp, Kce / Avisc) dedt = dedt_comenv_k0(atemp, etemp, Kce / Avisc) atemp = atemp + dadt * dt etemp = etemp + dedt * dt if collision and atemp.number < 0: break a_an.append(atemp) e_an.append(etemp) a.append(orbital_elements[2]) e.append(orbital_elements[3]) m.append(stars.mass.sum()) t.append(time) print("time=", time.in_(units.yr), "a=", a[-1].in_(units.RSun), "e=", e[-1], "m=", stars.mass.in_(units.MSun), end="\r") gravity.stop() from matplotlib import pyplot import seaborn as sns sns.set(font_scale=1.33) sns.set_style("ticks") fig, axis = pyplot.subplots(nrows=2, sharex=True) axis[0].plot(t.value_in(units.yr), a.value_in(units.RSun), label="nbody k=0") axis[0].plot(t.value_in(units.yr), a_an.value_in(units.RSun), label="analytic") axis[0].set_ylabel("semimajor axis [$R_\odot$]") axis[0].legend() axis[1].plot(t.value_in(units.yr), e) axis[1].plot(t.value_in(units.yr), e_an) axis[1].set_ylabel("eccentricity") axis[1].set_xlabel("time [yr]") axis[0].set_xlabel("time [yr]") pyplot.tight_layout() pyplot.subplots_adjust(hspace=0.0) pyplot.savefig("comenv2.png") pyplot.show()
) subplot.set_xlim(-1, 1) subplot.set_ylim(-1, 1) subplot.set_xlabel('x (nbody length)') subplot.set_ylabel('y (nbody length)') pyplot.show() if __name__ == "__main__": numpy.random.seed(1212) particles = new_cluster(128) code = Hermite() code.particles.add_particles(particles) stopping_condition = code.stopping_conditions.collision_detection stopping_condition.enable() code.evolve_model(4 | nbody_system.time) if not stopping_condition.is_set(): raise Exception( "No stopping collision detected in the given timeframe.") plot_particles_and_highlight_collision(particles, stopping_condition.particles(0), stopping_condition.particles(1))
def evolve_model(end_time, double_star, stars): time = 0 | units.yr dt = 0.5 * end_time / 1000. * 2 converter = nbody_system.nbody_to_si(double_star.mass, double_star.semimajor_axis) gravity = Hermite(converter) gravity.particles.add_particle(stars) to_stars = gravity.particles.new_channel_to(stars) from_stars = stars.new_channel_to(gravity.particles) period = (2 * numpy.pi * (double_star.semimajor_axis * double_star.semimajor_axis * double_star.semimajor_axis / (constants.G * double_star.mass)).sqrt()) print("Period =", period.as_string_in(units.yr)) print("Mass loss timestep =", dt) print("Steps per period: = {:1.2f}".format(period / dt)) E_an = [] | (units.km / units.s)**2 h_an = [] | units.km**2 / units.s Etemp = -double_star.mass * constants.G / (2 * double_star.semimajor_axis) htemp = (double_star.mass * constants.G * double_star.semimajor_axis * (1 - double_star.eccentricity * double_star.eccentricity))**0.5 E_num = [] | (units.km / units.s)**2 h_num = [] | units.km**2 / units.s m1 = [] | units.MSun m2 = [] | units.MSun t = [] | units.yr t_an = [] | units.yr dt_an = period * 2.5 time_an = 0 | units.yr while time < end_time: time += dt gravity.evolve_model(time) to_stars.copy() dmdtloss = mass_loss_rate(stars.mass) dmdtacc = dmdt_acc(dmdtloss) orbital_elements = orbital_elements_from_binary(stars, G=constants.G) h = h_from_stars(stars) E = E_from_stars(stars) if time > time_an: #atemp = orbital_elements[2] #htemp = h E_an.append(Etemp) h_an.append(htemp) t_an.append(time) dEdt = dEdt_momentum_secular(htemp, Etemp, stars.mass, dmdtacc) dhdt = dhdt_momentum_secular(htemp, stars.mass, dmdtacc) Etemp = Etemp + dEdt * dt_an htemp = htemp + dhdt * dt_an E_an.append(Etemp) h_an.append(htemp) t_an.append(time + dt_an) time_an += dt_an kick_from_accretion(stars, dmdtacc, dt) #stars.mass += (dmdtloss + dmdtacc) * dt #stars2.mass += (dmdtloss + dmdtacc) * dt from_stars.copy() h_num.append(h) E_num.append(E) m1.append(stars[0].mass) m2.append(stars[1].mass) t.append(time) print("time=", time.in_(units.yr), "h=", h.in_(units.km**2 / units.s), "E=", E.in_((units.km / units.s)**2), "m=", stars.mass.in_(units.MSun), end="\r") gravity.stop() from matplotlib import pyplot pyplot.rc('text', usetex=True) pyplot.rcParams.update({'font.size': 16}) fig, axis = pyplot.subplots(nrows=2, ncols=2, sharex=True, figsize=(13, 6)) axis[0][0].plot(t.value_in(units.yr), E_num.value_in((units.km / units.s)**2), label="nbody (direct)", lw=2) axis[0][0].plot(t_an.value_in(units.yr), E_an.value_in((units.km / units.s)**2), label="analytic", lw=2, ls="-.") axis[0][0].set_ylabel("E [km/s]") axis[0][0].legend() axis[0][1].plot(t.value_in(units.yr), m1.value_in(units.MSun), label="m1", lw=2, c="tab:red") axis[0][1].plot(t.value_in(units.yr), m2.value_in(units.MSun), label="m2", lw=2, c="tab:cyan") axis[0][1].set_ylabel("M [$M_\odot$]") axis[0][1].legend() axis[1][1].plot(t.value_in(units.yr), h_num.value_in(units.km**2 / units.s), lw=2) axis[1][1].plot(t_an.value_in(units.yr), h_an.value_in(units.km**2 / units.s), lw=2, ls="-.") axis[1][1].set_ylabel("h [km$^2$/s]") #axis[1][0].plot(t.value_in(units.yr), ome, lw=2, label="nbody (direct)") #axis[1][0].set_ylabel("$\omega$ [degrees]") axis[1][1].set_xlabel("time [yr]") axis[1][0].set_xlabel("time [yr]") pyplot.tight_layout() pyplot.subplots_adjust(hspace=0, top=0.93, bottom=0.1) pyplot.suptitle("mloss+macc+momentum change, same model") pyplot.savefig("debug.png") pyplot.show()
instance = Hermite(convert_nbody) instance.particles.add_particles(particles) channelp = instance.particles.new_channel_to(particles) start = 0 | units.yr end = 150 | units.yr step = 10 | units.day timerange = VectorQuantity.arange(start, end, step) masses = [] | units.MSun for i, time in enumerate(timerange): instance.evolve_model(time) channelp.copy() particles.savepoint(time) if (i % 220 == 0): instance.particles[0].mass = simulate_massloss(time) masses.append(instance.particles[0].mass) instance.stop() particle = particles[1] t, pos = particle.get_timeline_of_attribute_as_vector("position") distances = pos.lengths().as_quantity_in(units.AU) plot(timerange, distances, timerange, masses)