Snapshot WIP: Probe calibration path, faer LU backend, and BPHX phase-change duty.
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>
This commit is contained in:
2026-07-19 21:44:01 +02:00
parent 2f1f7ecb80
commit 3808e0f11b
39 changed files with 3648 additions and 265 deletions

View File

@@ -0,0 +1,85 @@
//! 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);