2021-02-08 21:05:44 +01:00
|
|
|
#include "rebound.h"
|
2021-02-15 21:13:34 +01:00
|
|
|
#include <math.h>
|
2021-02-08 21:05:44 +01:00
|
|
|
|
|
|
|
double min_distance_from_sun_squared = 0;
|
|
|
|
double max_distance_from_sun_squared = 0;
|
|
|
|
|
|
|
|
struct hb_event {
|
|
|
|
uint32_t hash;
|
|
|
|
double time;
|
|
|
|
unsigned int new;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct hb_event hb_escapes[500];
|
2021-08-20 18:00:04 +02:00
|
|
|
struct hb_event hb_wide_orbits[500];
|
2021-02-08 21:05:44 +01:00
|
|
|
struct hb_event hb_sun_collisions[500];
|
|
|
|
|
|
|
|
int hb_escape_index = 0;
|
2021-08-20 18:00:04 +02:00
|
|
|
int hb_wide_orbit_index = 0;
|
2021-02-08 21:05:44 +01:00
|
|
|
int hb_sun_collision_index = 0;
|
|
|
|
|
2021-02-09 10:05:00 +01:00
|
|
|
int needs_synchronize = 0;
|
2021-02-09 09:42:10 +01:00
|
|
|
|
2021-04-13 17:10:58 +02:00
|
|
|
FILE *logfile;
|
|
|
|
|
|
|
|
void init_logfile(char *filename) {
|
|
|
|
FILE *f = fopen(filename, "a");
|
|
|
|
logfile = f;
|
|
|
|
}
|
|
|
|
|
2021-08-20 18:00:04 +02:00
|
|
|
double elliptical_orbit_velocity(struct reb_simulation *sim, double m0, double m1, double a, double r)
|
|
|
|
// Computes the orbital velocity on a bound orbit with semi-major axis 'a' of masses 'm0' and 'm1' at distance 'r'.
|
|
|
|
// uses Vis-Viva equation
|
|
|
|
{
|
|
|
|
double v_sqr = sim->G * (m0 + m1) * (2.0 / r - 1.0 / a);
|
|
|
|
return sqrt(v_sqr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-02-08 21:05:44 +01:00
|
|
|
void heartbeat(struct reb_simulation *sim) {
|
2021-08-20 18:00:04 +02:00
|
|
|
if ((sim->steps_done % 100) == 0) {
|
2021-02-08 21:05:44 +01:00
|
|
|
const struct reb_particle *const particles = sim->particles;
|
|
|
|
int N = sim->N - sim->N_var;
|
|
|
|
for (int i = 1; i < N; i++) { // skip sun
|
|
|
|
struct reb_particle p = particles[i];
|
|
|
|
double distance_squared = p.x * p.x + p.y * p.y + p.z * p.z;
|
2021-08-20 18:00:04 +02:00
|
|
|
struct reb_orbit tmp_orbit = reb_tools_particle_to_orbit(sim->G, p, sim->particles[0]);
|
|
|
|
double perihelion_dist = tmp_orbit.a * (1.0 - tmp_orbit.e);
|
2021-02-08 21:05:44 +01:00
|
|
|
if (distance_squared > max_distance_from_sun_squared) {
|
|
|
|
printf("remove %u at t=%f (max)\n", p.hash, sim->t);
|
|
|
|
reb_remove_by_hash(sim, p.hash, 1);
|
|
|
|
hb_escapes[hb_escape_index].hash = p.hash;
|
|
|
|
hb_escapes[hb_escape_index].time = sim->t;
|
|
|
|
hb_escapes[hb_escape_index].new = 1;
|
2021-02-09 09:42:10 +01:00
|
|
|
|
2021-02-08 21:05:44 +01:00
|
|
|
hb_escape_index++;
|
2021-02-09 10:05:00 +01:00
|
|
|
needs_synchronize = 1;
|
2021-08-20 18:00:04 +02:00
|
|
|
} else if (distance_squared < min_distance_from_sun_squared ||
|
2021-08-20 18:05:14 +02:00
|
|
|
(tmp_orbit.e < 1.0 &&
|
|
|
|
perihelion_dist * perihelion_dist <
|
|
|
|
min_distance_from_sun_squared)
|
|
|
|
) {
|
2021-02-08 21:05:44 +01:00
|
|
|
printf("remove %u at t=%f (min)\n", p.hash, sim->t);
|
2021-03-16 14:08:08 +01:00
|
|
|
double mass = p.m;
|
2021-02-08 21:05:44 +01:00
|
|
|
reb_remove_by_hash(sim, p.hash, 1);
|
|
|
|
hb_sun_collisions[hb_sun_collision_index].hash = p.hash;
|
|
|
|
hb_sun_collisions[hb_sun_collision_index].time = sim->t;
|
|
|
|
hb_sun_collisions[hb_sun_collision_index].new = 1;
|
|
|
|
|
2021-03-16 14:08:08 +01:00
|
|
|
// add mass of deleted particle to sun
|
|
|
|
struct reb_particle sun = sim->particles[0];
|
|
|
|
sun.m += mass;
|
|
|
|
|
2021-02-08 21:05:44 +01:00
|
|
|
hb_sun_collision_index++;
|
2021-02-09 10:05:00 +01:00
|
|
|
needs_synchronize = 1;
|
2021-08-20 18:05:14 +02:00
|
|
|
} else if (tmp_orbit.e < 1.0 && perihelion_dist > 11.) {
|
2021-08-20 18:00:04 +02:00
|
|
|
// remove bodies if their perihel distance is above 11AU
|
|
|
|
printf("remove %u at t=%f (max)\n", p.hash, sim->t);
|
|
|
|
reb_remove_by_hash(sim, p.hash, 1);
|
|
|
|
hb_wide_orbits[hb_wide_orbit_index].hash = p.hash;
|
|
|
|
hb_wide_orbits[hb_wide_orbit_index].time = sim->t;
|
|
|
|
hb_wide_orbits[hb_wide_orbit_index].new = 1;
|
|
|
|
|
|
|
|
hb_escape_index++;
|
|
|
|
needs_synchronize = 1;
|
2021-02-08 21:05:44 +01:00
|
|
|
}
|
2021-08-20 18:00:04 +02:00
|
|
|
|
2021-02-09 09:42:10 +01:00
|
|
|
if (needs_synchronize) {
|
2021-02-15 21:13:34 +01:00
|
|
|
printf("distance: %f\n", sqrt(distance_squared));
|
|
|
|
needs_synchronize = 0;
|
2021-02-08 21:05:44 +01:00
|
|
|
N--;
|
|
|
|
reb_move_to_com(sim);
|
|
|
|
reb_integrator_synchronize(sim);
|
|
|
|
sim->ri_mercurius.recalculate_coordinates_this_timestep = 1;
|
|
|
|
sim->ri_mercurius.recalculate_dcrit_this_timestep = 1;
|
2021-08-20 18:00:04 +02:00
|
|
|
} else {
|
|
|
|
double perihelion_vel = elliptical_orbit_velocity(
|
|
|
|
sim,
|
|
|
|
sim->particles[0].m, sim->particles[i].m,
|
|
|
|
tmp_orbit.a, perihelion_dist);
|
|
|
|
double T_eff = 2.0 * M_PI * perihelion_dist / perihelion_vel;
|
|
|
|
if (T_eff < sim->dt * 20) {
|
|
|
|
printf("Warning: effective orbital period too low (%f < %f)\n", T_eff, sim->dt * 20);
|
|
|
|
}
|
2021-02-08 21:05:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-04-13 17:10:58 +02:00
|
|
|
if ((sim->steps_done % 10000) == 0) { // ~ every 100 years
|
|
|
|
fprintf(logfile, "%f, %f\n", sim->t, reb_tools_energy(sim));
|
|
|
|
}
|
2021-02-08 21:05:44 +01:00
|
|
|
}
|