131 lines
4.6 KiB
Rust
131 lines
4.6 KiB
Rust
//! The scenarios the Orekit fixtures were generated from, timed.
|
|
//!
|
|
//! The same force compositions over the same arcs, so the figures sit beside the ones
|
|
//! `scripts/generate-orekit-fixtures.sh --time` reports for Orekit.
|
|
//!
|
|
//! The tolerances are not literally equal — Orekit is asked for a nanometer of position
|
|
//! accuracy and this runs at `Accuracy::High` — so before reading a ratio, check that the
|
|
//! two took a comparable number of steps. Measured once, they do: between 1752 and 2473
|
|
//! here against 1932 and 2092 there, within a quarter of each other across every
|
|
//! scenario. A ratio of times is therefore close to a ratio of per-step cost, which is
|
|
//! the thing worth comparing. If a future scenario's step counts diverge, its timing
|
|
//! ratio means nothing until they are brought back together.
|
|
//!
|
|
//! One scenario is not like for like however the steps come out. Orekit's radiation
|
|
//! pressure registers eclipse event detectors, so its integrator locates the shadow
|
|
//! boundaries by root finding; this crate integrates straight through them. That is work
|
|
//! Orekit does and this does not, and it is arguably the better treatment, so the
|
|
//! radiation row is not purely a speed difference.
|
|
|
|
use std::path::Path;
|
|
use std::sync::Arc;
|
|
|
|
use astrokit::kernels;
|
|
use astrokit::prelude::*;
|
|
use criterion::{criterion_group, criterion_main, Criterion};
|
|
use nalgebra::Vector3;
|
|
use std::hint::black_box;
|
|
|
|
const ARC: f64 = 86400.0;
|
|
|
|
fn almanac() -> Option<Arc<anise::almanac::Almanac>> {
|
|
let directory = kernels::directory()
|
|
.unwrap_or_else(|| Path::new(env!("CARGO_MANIFEST_DIR")).join("data/kernels"));
|
|
kernels::load(&directory).ok().map(Arc::new)
|
|
}
|
|
|
|
fn bench(c: &mut Criterion) {
|
|
let Some(almanac) = almanac() else {
|
|
eprintln!("skipped: kernels not fetched, run scripts/fetch-kernels.sh");
|
|
return;
|
|
};
|
|
let epoch = Epoch::from_gregorian_utc_hms(2026, 1, 1, 0, 0, 0);
|
|
let high = Orbit
|
|
.with_position(Vector3::new(6.978e6, 0.0, 0.0))
|
|
.with_velocity(Vector3::new(0.0, 7.56e3, 0.0));
|
|
// Drag is measured lower down, where there is an atmosphere worth integrating.
|
|
let low = Orbit
|
|
.with_position(Vector3::new(6.778e6, 0.0, 0.0))
|
|
.with_velocity(Vector3::new(0.0, 7.668e3, 0.0));
|
|
let vehicle = Spacecraft::cannonball(500.0, 5.0, 2.2, 1.3);
|
|
|
|
let scenarios: Vec<(&str, State<f64, 6, Orbit>, Vec<Dynamics>)> = vec![
|
|
("two-body", high, vec![TwoBody { body: Body::EARTH }]),
|
|
(
|
|
"gravity-8",
|
|
high,
|
|
vec![Gravity {
|
|
field: GravityModel::Egm96,
|
|
degree: 8,
|
|
order: 8,
|
|
}],
|
|
),
|
|
(
|
|
"gravity-20",
|
|
high,
|
|
vec![Gravity {
|
|
field: GravityModel::Egm96,
|
|
degree: 20,
|
|
order: 20,
|
|
}],
|
|
),
|
|
(
|
|
"third-body",
|
|
high,
|
|
vec![
|
|
TwoBody { body: Body::EARTH },
|
|
ThirdBody { body: Body::MOON },
|
|
ThirdBody { body: Body::SUN },
|
|
],
|
|
),
|
|
(
|
|
"radiation",
|
|
high,
|
|
vec![TwoBody { body: Body::EARTH }, Sunshine],
|
|
),
|
|
(
|
|
"drag-harris-priester",
|
|
low,
|
|
vec![
|
|
TwoBody { body: Body::EARTH },
|
|
Drag {
|
|
density: DensityModel::harris_priester(),
|
|
},
|
|
],
|
|
),
|
|
#[cfg(feature = "msis")]
|
|
(
|
|
"drag-msis",
|
|
low,
|
|
vec![
|
|
TwoBody { body: Body::EARTH },
|
|
Drag {
|
|
density: DensityModel::Nrlmsise00,
|
|
},
|
|
],
|
|
),
|
|
];
|
|
|
|
let mut group = c.benchmark_group("reference scenarios");
|
|
// A day-long arc takes milliseconds, so the default hundred samples would make this
|
|
// the longest thing in the repository for no extra resolution.
|
|
group.sample_size(20);
|
|
for (name, initial, forces) in &scenarios {
|
|
group.bench_function(*name, |b| {
|
|
b.iter(|| {
|
|
let mut propagation = Propagation::new(epoch, *initial, forces)
|
|
.frame(Frame::EARTH_J2000)
|
|
.spacecraft(vehicle.clone())
|
|
.almanac(almanac.clone())
|
|
.duration(Duration::from_seconds(ARC))
|
|
.accuracy(Accuracy::High);
|
|
black_box(propagation.run().states.len())
|
|
})
|
|
});
|
|
}
|
|
group.finish();
|
|
}
|
|
|
|
criterion_group!(benches, bench);
|
|
criterion_main!(benches);
|