use RustedSciThe::numerical::LSODE2::{
Lsode2AotProfile, Lsode2AotToolchain, Lsode2BackendConfig, Lsode2LinearSolverPolicy,
Lsode2LinearSystemStructure, Lsode2ProblemConfig, Lsode2ResidualJacobianSource,
Lsode2SymbolicAssemblyBackend, Lsode2SymbolicExecutionMode,
};
use RustedSciThe::symbolic::symbolic_engine::Expr;
use nalgebra::DVector;
use std::process::Command;
fn command_available(command: &str) -> bool {
let probe = if cfg!(windows) { "where" } else { "which" };
Command::new(probe)
.arg(command)
.output()
.map(|output| output.status.success())
.unwrap_or(false)
}
fn main() {
if !command_available("tcc") {
println!("LSODE2 AOT guide skipped: `tcc` is not available in PATH.");
println!("Install tcc or switch to another toolchain (gcc/zig/rust) in the config.");
return;
}
let config = Lsode2ProblemConfig::new(
vec![
Expr::parse_expression("-15.0*y1 + 14.0*y2"),
Expr::parse_expression("y1 - y2"),
],
vec!["y1".to_string(), "y2".to_string()],
"t".to_string(),
0.0,
DVector::from_vec(vec![1.0, 0.0]),
1.0,
0.02,
1e-6,
1e-8,
)
.with_backend(Lsode2BackendConfig::native_sparse_faer_aot_c_tcc(
"target/lsode2-aot-guide",
))
.with_residual_jacobian_source(Lsode2ResidualJacobianSource::Symbolic {
assembly: Lsode2SymbolicAssemblyBackend::AtomView,
execution: Lsode2SymbolicExecutionMode::Aot {
toolchain: Lsode2AotToolchain::CTcc,
profile: Lsode2AotProfile::Release,
},
})
.with_linear_system_structure(Lsode2LinearSystemStructure::Sparse)
.with_linear_solver_policy(Lsode2LinearSolverPolicy::Auto)
.with_aot_parallel_chunking(2)
.with_faithful_bdf_solve(100_000, 100_000);
let mut solver = RustedSciThe::numerical::LSODE2::Lsode2Solver::new(config)
.expect("LSODE2 preparation failed");
let _ = solver.solve();
let (t, y) = solver.get_result();
let final_t = t[t.len() - 1];
let final_y1 = y[(y.nrows() - 1, 0)];
let final_y2 = y[(y.nrows() - 1, 1)];
println!("LSODE2 AOT guide (C+tcc)");
println!("status = {}", solver.get_status().unwrap_or_default());
println!("final_t = {final_t:.6}");
println!("final_y = [{final_y1:.8e}, {final_y2:.8e}]");
println!(
"note = first run may spend time in codegen/compile; repeated runs reuse artifacts."
);
println!(
"note = for Dense/Banded, keep the same AOT execution and switch linear structure/policy."
);
if let Some(stats) = solver.get_statistics() {
println!("stats = {}", stats.table_report());
}
}