High Order Symplectic Integrators (C)
This example uses a high order symplectic integrators WHCKL and SABA(10,6,4) to integrate all planets of the Solar System.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include "rebound.h"
double ss_pos[10][3] =
{
{3.256101656448802E-03 , -1.951205394420489E-04 , -1.478264728548705E-04},
{-1.927589645545195E-01 , 2.588788361485397E-01 , 3.900432597062033E-02 },
{-5.976537074581466E-01 , 3.918678996109574E-01 , 3.990356741282203E-02 },
{-7.986189029000561E-01 , -6.086873314992410E-01 , -1.250824315650566E-04},
{7.897942807177173E-01 , 1.266671734964037E+00 , 7.092292179885432E-03 },
{-4.314503046344270E+00 , 3.168094294126697E+00 , 8.331048545353310E-02 },
{-4.882304833383455E+00 , -8.689263067189865E+00 , 3.453930436208210E-01 },
{1.917757033372740E+01 , 5.671738750949031E+00 , -2.273858614425555E-01},
{2.767031517959636E+01 , -1.150331645280942E+01 , -4.008018419157927E-01},
{7.765250227278298E+00 , -3.190996242617413E+01 , 1.168394015703735E+00 },
};
double ss_vel[10][3] =
{
{3.039963463108432E-06 , 6.030576499910942E-06 , -7.992931269075703E-08},
{-2.811550184725887E-02, -1.586532995282261E-02, 1.282829413699522E-03 },
{-1.113090630745269E-02, -1.703310700277280E-02, 4.089082927733997E-04 },
{1.012305635253317E-02 , -1.376389620972473E-02, 3.482505080431706E-07 },
{-1.135279609707971E-02, 8.579013475676980E-03 , 4.582774369441005E-04 },
{-4.555986691913995E-03, -5.727124269621595E-03, 1.257262404884127E-04 },
{4.559352462922572E-03 , -2.748632232963112E-03, -1.337915989241807E-04},
{-1.144087185031310E-03, 3.588282323722787E-03 , 2.829006644043203E-05 },
{1.183702780101068E-03 , 2.917115980784960E-03 , -8.714411604869349E-05},
{3.112825364672655E-03 , 1.004673400082409E-04 , -9.111652976208292E-04},
};
double ss_mass[10] =
{
1.988544e30,
3.302e23,
48.685e23,
6.0477246e24,
6.4185e23,
1898.13e24,
5.68319e26,
86.8103e24,
102.41e24,
1.4639248e+22,
};
struct reb_simulation* create_sim(){
// Setup constants
struct reb_simulation* r = reb_create_simulation();
r->dt = 4; // in days
r->G = 1.0e-34; // in AU^3 / kg / day^2.
// Initial conditions (from NASA Horizons)
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);
}
return r;
}
int main(int argc, char* argv[]){
double tmax = 1e5; // 1e5 days ~ 273 years
// Run the simulation with the WHCKL method.
{
struct reb_simulation* r = create_sim();
r->integrator = REB_INTEGRATOR_WHFAST;
r->ri_whfast.safe_mode = 0; // Turn off safe mode (Need to call reb_integrator_synchronize() before outputs).
r->ri_whfast.corrector = 17; // 17th order symplectic corrector
r->ri_whfast.kernel = REB_WHFAST_KERNEL_LAZY; // Using the lazy implementers method which supports additional forces
double e_init = reb_tools_energy(r);
reb_integrate(r, tmax);
double e = reb_tools_energy(r);
printf("Relative energy error WHCKL: %e\n", fabs((e_init-e)/e_init));
}
// Run the same simulation with the SABA(10,6,4) method.
// Note that this method has 8 force evaluations per timestep and is therefore
// quite a bit slower for a fixed timestep.
{
struct reb_simulation* r = create_sim();
r->integrator = REB_INTEGRATOR_SABA;
r->ri_saba.type = REB_SABA_10_6_4; // Chooses the type of SABA integrator.
r->ri_saba.safe_mode = 0; // Turn off safe mode.
double e_init = reb_tools_energy(r);
reb_integrate(r, tmax);
double e = reb_tools_energy(r);
printf("Relative energy error SABA(10,6,4): %e\n", fabs((e_init-e)/e_init));
}
// Run the same simulation with the standard WH method.
{
struct reb_simulation* r = create_sim();
r->integrator = REB_INTEGRATOR_WHFAST; // All WHFast settings default to the standard WH method
r->ri_whfast.safe_mode = 0; // Turn off safe mode.
double e_init = reb_tools_energy(r);
reb_integrate(r, tmax);
double e = reb_tools_energy(r);
printf("Relative energy error WH: %e\n", fabs((e_init-e)/e_init));
}
}
This example is located in the directory examples/high_order_symplectic