librebound-sys 4.6.0

Raw FFI bindings and safe RAII wrappers for the REBOUND N-body integrator
Documentation
// helpers.c — Thin C accessors for reb_simulation fields.
//
// reb_simulation is enormous (~5KB with nested integrator structs).
// Rather than reproducing it in Rust, we treat it as opaque and
// expose only the handful of fields the FFI layer needs.

#include <string.h>
#include "rebound.h"

// --- reb_simulation field accessors ---

double assist_rs_sim_get_t(const struct reb_simulation* r) { return r->t; }
void   assist_rs_sim_set_t(struct reb_simulation* r, double t) { r->t = t; }

double assist_rs_sim_get_dt(const struct reb_simulation* r) { return r->dt; }
void   assist_rs_sim_set_dt(struct reb_simulation* r, double dt) { r->dt = dt; }

unsigned long long assist_rs_sim_get_steps_done(const struct reb_simulation* r) { return r->steps_done; }

// Zero IAS15's compensated-summation accumulators (csx, csv) and predictor
// arrays (b, e, br, er, g) in place, leaving their allocations intact. This
// is equivalent to `reb_integrator_ias15_reset` for correctness — it clears
// all state that carries across `reb_simulation_integrate` calls — but
// avoids the 13 free/malloc pairs that reset incurs. Required between
// propagations of two unrelated orbits that share the same simulation.
void assist_rs_ias15_zero_state(struct reb_simulation* r) {
    const int N_allocated = r->ri_ias15.N_allocated;
    if (N_allocated == 0) { return; }   // never stepped; nothing to zero

    // Compensated-summation accumulators for positions and velocities.
    memset(r->ri_ias15.csx,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.csv,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.csa0, 0, sizeof(double) * N_allocated);

    // b/e/br/er/g: 7-component tables of length N3 each. Zero all p0..p6.
    memset(r->ri_ias15.b.p0,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.b.p1,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.b.p2,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.b.p3,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.b.p4,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.b.p5,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.b.p6,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.e.p0,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.e.p1,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.e.p2,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.e.p3,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.e.p4,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.e.p5,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.e.p6,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.br.p0, 0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.br.p1, 0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.br.p2, 0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.br.p3, 0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.br.p4, 0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.br.p5, 0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.br.p6, 0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.er.p0, 0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.er.p1, 0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.er.p2, 0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.er.p3, 0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.er.p4, 0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.er.p5, 0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.er.p6, 0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.g.p0,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.g.p1,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.g.p2,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.g.p3,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.g.p4,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.g.p5,  0, sizeof(double) * N_allocated);
    memset(r->ri_ias15.g.p6,  0, sizeof(double) * N_allocated);
}

unsigned int assist_rs_sim_get_N(const struct reb_simulation* r) { return r->N; }
int assist_rs_sim_get_N_var(const struct reb_simulation* r) { return r->N_var; }
int assist_rs_sim_get_N_active(const struct reb_simulation* r) { return r->N_active; }
void assist_rs_sim_set_N_active(struct reb_simulation* r, int n) { r->N_active = n; }

struct reb_particle* assist_rs_sim_get_particles(const struct reb_simulation* r) {
    return r->particles;
}

int assist_rs_sim_get_exact_finish_time(const struct reb_simulation* r) {
    return r->exact_finish_time;
}
void assist_rs_sim_set_exact_finish_time(struct reb_simulation* r, int v) {
    r->exact_finish_time = v;
}

unsigned int assist_rs_sim_get_force_is_velocity_dependent(const struct reb_simulation* r) {
    return r->force_is_velocity_dependent;
}

int assist_rs_sim_get_status(const struct reb_simulation* r) { return r->status; }

void* assist_rs_sim_get_extras(const struct reb_simulation* r) { return r->extras; }

// Integrator enum (inline in reb_simulation, not a separate field)
int assist_rs_sim_get_integrator(const struct reb_simulation* r) { return r->integrator; }
void assist_rs_sim_set_integrator(struct reb_simulation* r, int i) { r->integrator = i; }

// Gravity enum
int assist_rs_sim_get_gravity(const struct reb_simulation* r) { return r->gravity; }
void assist_rs_sim_set_gravity(struct reb_simulation* r, int g) { r->gravity = g; }

// IAS15 epsilon
double assist_rs_sim_get_ias15_epsilon(const struct reb_simulation* r) {
    return r->ri_ias15.epsilon;
}
void assist_rs_sim_set_ias15_epsilon(struct reb_simulation* r, double eps) {
    r->ri_ias15.epsilon = eps;
}

// IAS15 minimum timestep floor. When the adaptive step would shrink below
// this value, the integrator clamps it instead of grinding toward zero.
// Default 0 = no floor.
double assist_rs_sim_get_ias15_min_dt(const struct reb_simulation* r) {
    return r->ri_ias15.min_dt;
}
void assist_rs_sim_set_ias15_min_dt(struct reb_simulation* r, double min_dt) {
    r->ri_ias15.min_dt = min_dt;
}

// IAS15 adaptive-mode selector: 0=Individual, 1=Global, 2=PRS23 (REBOUND
// default since 2024-01), 3=Aarseth85.
int assist_rs_sim_get_ias15_adaptive_mode(const struct reb_simulation* r) {
    return (int)r->ri_ias15.adaptive_mode;
}
void assist_rs_sim_set_ias15_adaptive_mode(struct reb_simulation* r, int mode) {
    r->ri_ias15.adaptive_mode = mode;
}

// Diagnostic counter: number of IAS15 steps where the predictor-corrector
// loop hit the iteration cap without converging. Monotone-increasing across
// the simulation lifetime.
unsigned long long assist_rs_sim_get_ias15_iterations_max_exceeded(const struct reb_simulation* r) {
    return r->ri_ias15.iterations_max_exceeded;
}