Some checks failed
CI / check (push) Has been cancelled
Checkpoint incomplete calibration work (cond SDT green, evap SST failing) plus related solver/UI changes so the next pass can fix and extend safely. Co-authored-by: Cursor <cursoragent@cursor.com>
86 lines
2.8 KiB
Rust
86 lines
2.8 KiB
Rust
//! Story 1.5 comparative benchmark: nalgebra vs faer dense LU backends.
|
||
//!
|
||
//! Measures factorization (`set_linearisation`) and per-RHS solve
|
||
//! (`solve_in_place`) on the mock-cycle Jacobian (9×9) and a synthetic 50×50
|
||
//! dense Jacobian — the sizes Entropyk Newton actually sees.
|
||
|
||
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
|
||
use entropyk_solver::linear::NalgebraLuSolver;
|
||
use entropyk_solver::linear_faer::FaerLuSolver;
|
||
use entropyk_solver::LinearSolver;
|
||
|
||
mod common;
|
||
|
||
fn dense_entries(n: usize) -> Vec<(usize, usize, f64)> {
|
||
let mut entries = Vec::with_capacity(n * n);
|
||
for i in 0..n {
|
||
for j in 0..n {
|
||
let v = if i == j {
|
||
4.0 + 0.01 * (i as f64)
|
||
} else {
|
||
1.0 / (1.0 + (i as f64 - j as f64).abs())
|
||
};
|
||
entries.push((i, j, v));
|
||
}
|
||
}
|
||
entries
|
||
}
|
||
|
||
fn bench_pair(c: &mut Criterion, label: &str, entries: &[(usize, usize, f64)], n: usize) {
|
||
let mut group = c.benchmark_group(label);
|
||
let rhs: Vec<f64> = (0..n)
|
||
.map(|i| (i as f64 * 0.7 - 1.3).sin() * 100.0)
|
||
.collect();
|
||
|
||
let mut nal = NalgebraLuSolver::new();
|
||
nal.set_problem(n, n).unwrap();
|
||
let mut faer = FaerLuSolver::new();
|
||
faer.set_problem(n, n).unwrap();
|
||
|
||
group.bench_function(BenchmarkId::new("factor", "nalgebra"), |b| {
|
||
b.iter(|| {
|
||
black_box(nal.set_linearisation(black_box(entries))).unwrap();
|
||
});
|
||
});
|
||
group.bench_function(BenchmarkId::new("factor", "faer"), |b| {
|
||
b.iter(|| {
|
||
black_box(faer.set_linearisation(black_box(entries))).unwrap();
|
||
});
|
||
});
|
||
|
||
nal.set_linearisation(entries).unwrap();
|
||
faer.set_linearisation(entries).unwrap();
|
||
group.bench_function(BenchmarkId::new("solve", "nalgebra"), |b| {
|
||
b.iter(|| {
|
||
let mut rhs = rhs.clone();
|
||
let _ = black_box(nal.solve_in_place(black_box(&mut rhs)));
|
||
});
|
||
});
|
||
group.bench_function(BenchmarkId::new("solve", "faer"), |b| {
|
||
b.iter(|| {
|
||
let mut rhs = rhs.clone();
|
||
let _ = black_box(faer.solve_in_place(black_box(&mut rhs)));
|
||
});
|
||
});
|
||
group.finish();
|
||
}
|
||
|
||
fn bench_lu_backends(c: &mut Criterion) {
|
||
let (system, state) = common::build_mock_system();
|
||
let jacobian = common::assemble_jacobian(&system, &state);
|
||
let n = jacobian.nrows();
|
||
let jm = jacobian.as_matrix();
|
||
let entries: Vec<(usize, usize, f64)> = (0..n)
|
||
.flat_map(|i| (0..n).map(move |j| (i, j, jm[(i, j)])))
|
||
.collect();
|
||
bench_pair(c, "lu_mock_9x9", &entries, n);
|
||
|
||
let entries50 = dense_entries(50);
|
||
bench_pair(c, "lu_dense_50x50", &entries50, 50);
|
||
|
||
let _ = state;
|
||
}
|
||
|
||
criterion_group!(benches, bench_lu_backends);
|
||
criterion_main!(benches);
|