94 lines
3.5 KiB
Rust
94 lines
3.5 KiB
Rust
//! What an evaluation costs.
|
|
//!
|
|
//! The altitudes are chosen for the paths they take, not for being round: above 72.5 km
|
|
//! the model is the thermosphere alone, below it the mesosphere splines are built on top of
|
|
//! a thermosphere evaluation at 72.5 km, and below 32.5 km a second set of splines is built
|
|
//! on top of that. The three cost noticeably different amounts.
|
|
//!
|
|
//! The dual-number cases are the reason the crate exists, so they are measured alongside:
|
|
//! one seeded input gives the altitude partial, three give the position gradient a drag
|
|
//! calculation wants.
|
|
|
|
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
|
use nrlmsise00::{Input, MagneticActivity, Model, Scalar};
|
|
use num_dual::{Dual64, DualSVec64};
|
|
use std::hint::black_box;
|
|
|
|
/// The baseline of the reference's published cases, at an altitude of the caller's choice.
|
|
fn input<T: Scalar>(altitude_km: T) -> Input<T> {
|
|
Input {
|
|
day_of_year: 172,
|
|
seconds_of_day: T::lift(29000.0),
|
|
altitude_km,
|
|
latitude_deg: T::lift(60.0),
|
|
longitude_deg: T::lift(-70.0),
|
|
local_solar_time_h: T::lift(16.0),
|
|
f107_average: T::lift(150.0),
|
|
f107: T::lift(150.0),
|
|
magnetic: MagneticActivity::History {
|
|
ap: [100.0; 7].map(T::lift),
|
|
},
|
|
}
|
|
}
|
|
|
|
/// An altitude in each of the model's three vertical regions, and one in the exosphere.
|
|
const ALTITUDES: [(&str, f64); 4] = [
|
|
("20 km, three splines", 20.0),
|
|
("50 km, two splines", 50.0),
|
|
("400 km, thermosphere", 400.0),
|
|
("1000 km, exosphere", 1000.0),
|
|
];
|
|
|
|
fn gtd7d(c: &mut Criterion) {
|
|
let model = Model::new();
|
|
let mut group = c.benchmark_group("gtd7d");
|
|
for (name, altitude) in ALTITUDES {
|
|
group.bench_with_input(BenchmarkId::new("f64", name), &altitude, |b, altitude| {
|
|
b.iter(|| model.gtd7d(black_box(&input(*altitude))));
|
|
});
|
|
}
|
|
group.finish();
|
|
}
|
|
|
|
fn derivatives(c: &mut Criterion) {
|
|
let model = Model::new();
|
|
let mut group = c.benchmark_group("gtd7d with derivatives");
|
|
for (name, altitude) in ALTITUDES {
|
|
// One partial: the altitude derivative a scale height comes from.
|
|
group.bench_with_input(
|
|
BenchmarkId::new("one partial", name),
|
|
&altitude,
|
|
|b, altitude| {
|
|
let seeded = Dual64::from(*altitude).derivative();
|
|
b.iter(|| model.gtd7d(black_box(&input(seeded))));
|
|
},
|
|
);
|
|
// Three at once: the position gradient, which is what a drag partial needs.
|
|
group.bench_with_input(
|
|
BenchmarkId::new("three partials", name),
|
|
&altitude,
|
|
|b, altitude| {
|
|
// Seeded in the first of three slots, as a position gradient would be.
|
|
let seeded = DualSVec64::<3>::from(*altitude).derivative(0);
|
|
b.iter(|| model.gtd7d(black_box(&input(seeded))));
|
|
},
|
|
);
|
|
}
|
|
group.finish();
|
|
}
|
|
|
|
/// The two entry points, to show that the drag total costs nothing extra.
|
|
fn entry_points(c: &mut Criterion) {
|
|
let model = Model::new();
|
|
let mut group = c.benchmark_group("entry points at 400 km");
|
|
group.bench_function("gtd7", |b| b.iter(|| model.gtd7(black_box(&input(400.0)))));
|
|
group.bench_function("gtd7d", |b| {
|
|
b.iter(|| model.gtd7d(black_box(&input(400.0))))
|
|
});
|
|
group.bench_function("gts7", |b| b.iter(|| model.gts7(black_box(&input(400.0)))));
|
|
group.finish();
|
|
}
|
|
|
|
criterion_group!(benches, gtd7d, derivatives, entry_points);
|
|
criterion_main!(benches);
|