int main(int argc, char* argv[]){ struct reb_simulation* r = reb_create_simulation(); r->dt = 0.0012*2.*M_PI; // initial timestep r->integrator = REB_INTEGRATOR_MERCURIUS; r->heartbeat = heartbeat; struct reb_particle star = {0}; star.m = 1; reb_add(r, star); // Add planets int N_planets = 3; for (int i=0;i<N_planets;i++){ double a = 1.+.1*(double)i; // semi major axis double v = sqrt(1./a); // velocity (circular orbit) struct reb_particle planet = {0}; planet.m = 2e-5; planet.x = a; planet.vy = v; reb_add(r, planet); } reb_move_to_com(r); // This makes sure the planetary systems stays within the computational domain and doesn't drift. e_init = reb_tools_energy(r); system("rm -rf energy.txt"); reb_integrate(r, INFINITY); }
int main(int argc, char* argv[]){ struct reb_simulation* r = reb_create_simulation(); // Setup constants r->dt = 4; // in days tmax = 7.3e10; // 200 Myr r->G = 1.4880826e-34; // in AU^3 / kg / day^2. r->ri_whfast.safe_mode = 0; // Turn off safe mode. Need to call reb_integrator_synchronize() before outputs. r->ri_whfast.corrector = 11; // 11th order symplectic corrector r->integrator = REB_INTEGRATOR_WHFAST; r->heartbeat = heartbeat; r->exact_finish_time = 1; // Finish exactly at tmax in reb_integrate(). Default is already 1. //r->integrator = REB_INTEGRATOR_IAS15; // Alternative non-symplectic integrator // Initial conditions for (int i=0;i<10;i++){ struct reb_particle p = {0}; p.x = ss_pos[i][0]; p.y = ss_pos[i][1]; p.z = ss_pos[i][2]; p.vx = ss_vel[i][0]; p.vy = ss_vel[i][1]; p.vz = ss_vel[i][2]; p.m = ss_mass[i]; reb_add(r, p); } reb_move_to_com(r); e_init = reb_tools_energy(r); system("rm -f energy.txt"); reb_integrate(r, tmax); }
void heartbeat(struct reb_simulation* r){ if (reb_output_check(r, 10000.)){ reb_output_timing(r, tmax); reb_integrator_synchronize(r); FILE* f = fopen("energy.txt","a"); double e = reb_tools_energy(r); fprintf(f,"%e %e\n",r->t, fabs((e-e_init)/e_init)); fclose(f); } }
void heartbeat(struct reb_simulation* r){ if (reb_output_check(r, 10.*2.*M_PI)){ reb_output_timing(r, 0); } if (reb_output_check(r, 2.*M_PI)){ // Once per year, output the relative energy error to a text file FILE* f = fopen("energy.txt","a"); reb_integrator_synchronize(r); double e = reb_tools_energy(r); fprintf(f,"%e %e\n",r->t, fabs((e-e_init)/e_init)); fclose(f); } }
void reb_integrator_hermes_part2(struct reb_simulation* r){ reb_integrator_whfast_part2(r); calc_forces_on_planets(r, r->ri_hermes.a_f); struct reb_simulation* mini = r->ri_hermes.mini; r->ri_hermes.steps++; if (r->ri_hermes.mini_active){ r->ri_hermes.steps_miniactive++; r->ri_hermes.steps_miniN += mini->N; reb_integrate(mini,r->t); for (int i=0; i<mini->N; i++){ r->particles[r->ri_hermes.global_index_from_mini_index[i]] = mini->particles[i]; r->particles[r->ri_hermes.global_index_from_mini_index[i]].sim = r; } // Correct for energy jump in collision if(r->ri_hermes.collision_this_global_dt && r->track_energy_offset){ double Ef = reb_tools_energy(r); r->energy_offset += r->ri_hermes.energy_before_timestep - Ef; } } }
int main(int argc, char* argv[]) { struct reb_simulation* r = reb_create_simulation(); // Setup constants const double k = 0.01720209895; // Gaussian constant r->dt = 40; // in days r->G = k * k; // These are the same units as used by the mercury6 code. r->ri_whfast.safe_mode = 0; // Turn of safe mode. Need to call integrator_synchronize() before outputs. r->ri_whfast.corrector = 11; // Turn on symplectic correctors (11th order). // Setup callbacks: r->heartbeat = heartbeat; r->force_is_velocitydependent = 0; // Force only depends on positions. r->integrator = REB_INTEGRATOR_WHFAST; //r->integrator = REB_INTEGRATOR_IAS15; //r->integrator = REB_INTEGRATOR_WH; // Initial conditions for (int i = 0; i < 6; i++) { struct reb_particle p; p.x = ss_pos[i][0]; p.y = ss_pos[i][1]; p.z = ss_pos[i][2]; p.vx = ss_vel[i][0]; p.vy = ss_vel[i][1]; p.vz = ss_vel[i][2]; p.ax = 0; p.ay = 0; p.az = 0; p.m = ss_mass[i]; reb_add(r, p); } if (r->integrator == REB_INTEGRATOR_WH) { struct reb_particle* const particles = r->particles; // Move to heliocentric frame (required by WH integrator) for (int i = 1; i < r->N; i++) { particles[i].x -= particles[0].x; particles[i].y -= particles[0].y; particles[i].z -= particles[0].z; particles[i].vx -= particles[0].vx; particles[i].vy -= particles[0].vy; particles[i].vz -= particles[0].vz; } particles[0].x = 0; particles[0].y = 0; particles[0].z = 0; particles[0].vx = 0; particles[0].vy = 0; particles[0].vz = 0; } else { reb_move_to_com(r); } r->N_active = r->N - 1; // Pluto is treated as a test-particle. double e_initial = reb_tools_energy(r); // Start integration reb_integrate(r, tmax); double e_final = reb_tools_energy(r); printf("Done. Final time: %.4f. Relative energy error: %e\n", r->t, fabs((e_final - e_initial) / e_initial)); }
void reb_integrator_hermes_part1(struct reb_simulation* r){ r->gravity_ignore_10 = 0; const int _N_active = ((r->N_active==-1)?r->N:r->N_active) - r->N_var; struct reb_simulation* mini = r->ri_hermes.mini; if (mini == NULL){ mini = reb_create_simulation(); r->ri_hermes.mini = mini; mini->usleep = -1; // Disable visualiation mini->integrator = REB_INTEGRATOR_IAS15; mini->gravity = REB_GRAVITY_BASIC; mini->dt = r->dt; mini->additional_forces = reb_integrator_hermes_additional_forces_mini; mini->ri_hermes.global = r; //set to != 0 so that collision.c knows to remove from both } mini->testparticle_type = r->testparticle_type; mini->collision = r->collision; mini->collision_resolve = r->collision_resolve; mini->collision_resolve_keep_sorted = r->collision_resolve_keep_sorted; mini->track_energy_offset = r->track_energy_offset; mini->force_is_velocity_dependent = r->force_is_velocity_dependent; mini->post_timestep_modifications = r->post_timestep_modifications; // Remove all particles from mini mini->t = r->t; int mini_previously_active = r->ri_hermes.mini_active; mini->N = 0; mini->energy_offset = 0.; r->ri_hermes.mini_active = 0; r->ri_hermes.global_index_from_mini_index_N = 0; r->ri_hermes.collision_this_global_dt = 0; if (_N_active>r->ri_hermes.a_Nmax){ r->ri_hermes.a_i = realloc(r->ri_hermes.a_i,sizeof(double)*3*_N_active); r->ri_hermes.a_f = realloc(r->ri_hermes.a_f,sizeof(double)*3*_N_active); r->ri_hermes.a_Nmax = _N_active; } //reset is_in_mini if (r->N>r->ri_hermes.is_in_mini_Nmax){ r->ri_hermes.is_in_mini_Nmax = r->N; r->ri_hermes.is_in_mini = realloc(r->ri_hermes.is_in_mini,r->N*sizeof(int)); } for(int i=_N_active;i<r->N;i++)r->ri_hermes.is_in_mini[i] = 0; // Add all massive particles for (int i=0; i<_N_active; i++){ reb_add(r->ri_hermes.mini, r->particles[i]); r->ri_hermes.is_in_mini[i] = 1; if (r->ri_hermes.global_index_from_mini_index_N>=r->ri_hermes.global_index_from_mini_index_Nmax){ r->ri_hermes.global_index_from_mini_index_Nmax += 32; r->ri_hermes.global_index_from_mini_index = realloc(r->ri_hermes.global_index_from_mini_index,r->ri_hermes.global_index_from_mini_index_Nmax*sizeof(int)); } r->ri_hermes.global_index_from_mini_index[r->ri_hermes.global_index_from_mini_index_N] = i; r->ri_hermes.global_index_from_mini_index_N++; } r->ri_hermes.mini->N_active = _N_active; reb_integrator_hermes_check_for_encounter(r); if (r->N != r->ri_hermes.mini->N || mini_previously_active==0) { reb_integrator_ias15_clear(r->ri_hermes.mini); } calc_forces_on_planets(r, r->ri_hermes.a_i); if(r->ri_hermes.mini_active && r->track_energy_offset){ r->ri_hermes.energy_before_timestep = reb_tools_energy(r); } reb_integrator_whfast_part1(r); }