Skip to content

Commit 4103a13

Browse files
committed
first commit for Hermite-GRX
0 parents  commit 4103a13

37 files changed

+4294
-0
lines changed

GalacticCenter.py

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
from amuse.lab import *
2+
from amuse.units.units import *
3+
from amuse.units import constants
4+
5+
import orbital_elements as orb_elem
6+
from hermitepn.interface import *
7+
8+
import numpy as np
9+
import time
10+
from math import *
11+
import subprocess
12+
import os
13+
14+
def evolve_sim(grav, out_particles, perturbation, t_end):
15+
start = time.time()
16+
# Try evolving
17+
grav.evolve_model(t_end)
18+
19+
E_delta = 0 | kg * m**2 / s**2
20+
21+
while grav.stopping_conditions.collision_detection.is_set():
22+
# Collision between black hole and star
23+
p = grav.stopping_conditions.collision_detection.particles
24+
25+
colliding_particles = Particles()
26+
if p(1).mass < p(0).mass:
27+
colliding_particles.add_particle(p(0))
28+
colliding_particles.add_particle(p(1))
29+
else:
30+
colliding_particles.add_particle(p(1))
31+
colliding_particles.add_particle(p(0))
32+
33+
# Print orbital param
34+
try:
35+
print(orb_elem.orbital_elements_from_binary(colliding_particles, constants.G))
36+
except Exception:
37+
pass
38+
39+
if perturbation != None:
40+
E_begin = grav.get_total_energy_with(perturbation)
41+
42+
# Merge the star into the black hole, taking into account momentum and center of mass
43+
grav.large_particles[0].position = colliding_particles.center_of_mass()
44+
grav.large_particles[0].velocity = colliding_particles.center_of_mass_velocity()
45+
grav.large_particles[0].mass = colliding_particles.total_mass()
46+
47+
# Remove the star from the simulation
48+
grav.small_particles.remove_particle(colliding_particles[1])
49+
50+
E_end = grav.get_total_energy_with(perturbation)
51+
else:
52+
E_begin = grav.get_kinetic_energy() + grav.get_potential_energy()
53+
54+
# Remove star particle and save mbh
55+
grav.particles.remove_particle(colliding_particles[1])
56+
mbh = grav.particles[np.nonzero(grav.particles.key == colliding_particles[0].key)[0]]
57+
58+
# Add new particle which is the merged of the colliding particles
59+
mbh.position = colliding_particles.center_of_mass()
60+
mbh.velocity = colliding_particles.center_of_mass_velocity()
61+
mbh.mass = colliding_particles.total_mass()
62+
63+
E_end = grav.get_kinetic_energy() + grav.get_potential_energy()
64+
65+
# Record energy difference
66+
E_delta += E_begin - E_end
67+
68+
# Setting its mass zero in out_particles
69+
index = np.nonzero(out_particles.key == colliding_particles[1].key)[0]
70+
out_particles[index].mass = 0 | MSun
71+
72+
grav.particles.new_channel_to(out_particles).copy()
73+
74+
print(out_particles.mass)
75+
76+
print('RESOLVED A COLLISION at t =', grav.get_time().in_(yr))
77+
78+
# Reduce timeout by number of seconds already evolved
79+
if grav.stopping_conditions.timeout_detection.is_enabled():
80+
end = time.time()
81+
timeevolved = (end - start) | s
82+
start = time.time()
83+
84+
timeout = grav.parameters.stopping_conditions_timeout
85+
grav.parameters.stopping_conditions_timeout = timeout - timeevolved
86+
87+
# Try evolving again
88+
grav.evolve_model(t_end)
89+
90+
return E_delta
91+
92+
def setup_sim(initial, num_threads, dt_param, integrator, perturbation):
93+
mbh, bhs, converter = initial
94+
95+
if perturbation != None:
96+
grav = HermitePN(converter)
97+
grav.parameters.light_speed = constants.c
98+
grav.parameters.perturbation = perturbation
99+
grav.parameters.integrator = integrator
100+
grav.parameters.num_threads = num_threads
101+
102+
grav.large_particles.add_particle(mbh)
103+
grav.small_particles.add_particles(bhs)
104+
else:
105+
grav = Hermite(converter, number_of_workers = num_threads)
106+
grav.particles.add_particle(mbh)
107+
grav.particles.add_particles(bhs)
108+
109+
grav.parameters.dt_param = dt_param
110+
grav.stopping_conditions.collision_detection.enable()
111+
112+
out_particles = Particles()
113+
out_particles.add_particle(mbh)
114+
out_particles.add_particles(bhs)
115+
116+
channel = grav.particles.new_channel_to(out_particles)
117+
channel.copy()
118+
119+
return grav, out_particles, channel
120+
121+
# Load the latest snapshot of a saved run.
122+
# Create a new saved run if it doesn't exist.
123+
def load_snapshot(initial, runname):
124+
mbh, bhs, converter = initial
125+
126+
snapshot_number = 0
127+
128+
# Check if run already exists
129+
directory = '../../Data/%s/' % runname
130+
if os.path.isdir(directory):
131+
if len(os.listdir(directory)) != 0:
132+
# Read the last snapshot
133+
files = np.sort(os.listdir(directory))
134+
lastfile = files[-1]
135+
while not lastfile.endswith('.hdf'):
136+
files = files[:-1]
137+
lastfile = files[-1]
138+
139+
particles = read_set_from_file(directory + lastfile, 'amuse', close_file = True)
140+
mbh = particles[0]
141+
bhs = particles[1:]
142+
143+
# Remove particles with zero mass as they were captured by the mbh
144+
bhs.remove_particles(bhs[bhs.mass == 0 | MSun])
145+
146+
snapshot_number = int(files[-1][:-4])
147+
148+
print('Loaded snapshot #%d of %s.' % (snapshot_number, runname))
149+
else:
150+
os.mkdir(directory)
151+
152+
print('Started run %s.' % runname)
153+
154+
return snapshot_number, directory, (mbh, bhs, converter)
155+
156+
def save_snapshot(directory, out_particles, snapshot_number, E, E_delta, w):
157+
filename = '%05d.hdf' % snapshot_number
158+
write_set_to_file(out_particles, directory + filename, 'amuse')
159+
160+
if snapshot_number != 0:
161+
dat = np.loadtxt(directory + 'info.txt')
162+
if dat.ndim == 1:
163+
# Only one entry
164+
dat = [dat]
165+
else:
166+
dat = list(dat)
167+
168+
E_init = dat[0][1] | kg * m**2 / s**2
169+
E_delta += dat[-1][3] | kg * m**2 / s**2
170+
w += dat[-1][4]
171+
else:
172+
E_init = E
173+
dat = []
174+
175+
dat.append(np.array([snapshot_number, E.value_in(kg * m**2 / s**2), (E - E_init + E_delta) / E_init, E_delta.value_in(kg * m**2 / s**2), w]))
176+
np.savetxt(directory + 'info.txt', dat)
177+
178+
print('Saved snapshot #%d.' % snapshot_number)
179+
180+
def saved_run(initial, t_end, num_threads, dt_param, integrator, perturbation, runname, dt=100|yr):
181+
i, directory, initial = load_snapshot(initial, runname)
182+
grav, out_particles, channel = setup_sim(initial, num_threads, dt_param, integrator, perturbation)
183+
184+
if i == 0:
185+
if perturbation != None:
186+
E = grav.get_total_energy_with(perturbation)[0]
187+
else:
188+
E = grav.get_kinetic_energy() + grav.get_potential_energy()
189+
save_snapshot(directory, out_particles, i, E, 0 | kg * m**2 / s**2, 0)
190+
191+
t = i * dt
192+
t_start = t
193+
194+
while t < t_end:
195+
t += dt
196+
i += 1
197+
198+
start = time.time()
199+
E_delta = evolve_sim(grav, out_particles, perturbation, t - t_start)
200+
end = time.time()
201+
w = end - start
202+
203+
if perturbation != None:
204+
E = grav.get_total_energy_with(perturbation)[0]
205+
else:
206+
E = grav.get_kinetic_energy() + grav.get_potential_energy()
207+
208+
print('t =', (grav.get_time() + t_start).in_(yr))
209+
print('remaining=', w * (t_end - grav.get_time()) / dt / 60, 'min')
210+
print('E_tot =', E)
211+
212+
channel.copy()
213+
save_snapshot(directory, out_particles, i, E, E_delta, w)
214+
215+
grav.stop()
216+
217+
def timed_run(initial, num_threads, dt_param, integrator, perturbation, t_end = 1e6 | yr, timeout= -1 | s):
218+
grav, out_particles, channel = setup_sim(initial, num_threads, dt_param, integrator, perturbation)
219+
220+
evolve_sim(grav, out_particles, perturbation, 0.0001 | yr)
221+
222+
if perturbation == None:
223+
E_init = grav.get_kinetic_energy() + grav.get_potential_energy()
224+
else:
225+
E_init = grav.get_total_energy_with(perturbation)
226+
227+
if timeout > 0 | s:
228+
grav.stopping_conditions.timeout_detection.enable()
229+
grav.parameters.stopping_conditions_timeout = timeout
230+
231+
start = time.time()
232+
E_delta = evolve_sim(grav, out_particles, perturbation, t_end)
233+
end = time.time()
234+
235+
if perturbation == None:
236+
E_post = grav.get_kinetic_energy() + grav.get_potential_energy()
237+
else:
238+
E_post = grav.get_total_energy_with(perturbation)
239+
240+
gtime = grav.get_time()
241+
242+
grav.stop()
243+
return end - start, E_init, E_post+E_delta, gtime

HTPHermite.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
from amuse.lab import *
2+
from amuse.units.units import *
3+
from amuse.units import constants
4+
from hermitepn.interface import *
5+
6+
def HTpulsar(m1, m2, a, e):
7+
converter = nbody_system.nbody_to_si(m1+m2, a)
8+
from amuse.ext.orbital_elements import new_binary_from_orbital_elements
9+
HTbinary = new_binary_from_orbital_elements(m1, m2, a, e,
10+
G=constants.G)
11+
HTbinary.radius = 10 | units.km
12+
return HTbinary, converter
13+
14+
15+
def get_trajectories(initial, grav, t_end, pert=None):
16+
grav.particles.add_particles(initial[0])
17+
18+
pre_energy = get_energy(grav, pert)
19+
x1 = [] | units.AU
20+
x2 = [] | units.AU
21+
y1 = [] | units.AU
22+
y2 = [] | units.AU
23+
z1 = [] | units.AU
24+
z2 = [] | units.AU
25+
time = [] |units.yr
26+
E = [] | units.J
27+
28+
t = 0 * t_end
29+
dt = t_end / 100.0
30+
i = 0.
31+
32+
while t < t_end:
33+
x1.append(grav.particles[0].position.x)
34+
y1.append(grav.particles[0].position.y)
35+
z1.append(grav.particles[0].position.z)
36+
x2.append(grav.particles[1].position.x)
37+
y2.append(grav.particles[1].position.y)
38+
z2.append(grav.particles[1].position.z)
39+
40+
time.append(t)
41+
E.append(get_energy(grav, pert))
42+
43+
t += dt
44+
i += 1
45+
grav.evolve_model(t)
46+
47+
return x1, y1, z1, x2, y2, z2, time, E
48+
49+
m1 = 1.441 | units.MSun
50+
m2 = 1.397 | units.MSun
51+
a = 1950100 | units.km
52+
e = 0.6171334
53+
initial = HTpulsar(m1, m2, a, e)
54+
bodies = initial[0]
55+
Porb = 7.751938773864 | units.hour
56+
57+
converter = initial[1]
58+
Nbody_code = Hermite
59+
grav = Nbody_code(converter)
60+
grav.parameters.dt_param = 0.1
61+
62+
x1, y1, z1, x2, y2, z2, time, E = get_trajectories(initial,
63+
grav,
64+
10*Porb)
65+
66+
print("n=", len(x1))
67+
from matplotlib import pyplot
68+
pyplot.plot(x1.value_in(units.au), y1.value_in(units.au), c='r', lw=1)
69+
pyplot.plot(x2.value_in(units.au), y2.value_in(units.au), c='g', lw=1)
70+
pyplot.show()
71+
72+
pyplot.scatter(time.value_in(units.yr), E/E[0], c='g')
73+
pyplot.sh

0 commit comments

Comments
 (0)