#[cfg(feature = "complex")]
fn main() {
eprintln!("options_demo is disabled when the complex feature is enabled.");
}
#[cfg(all(not(feature = "backend-faer"), not(feature = "complex")))]
#[cfg(not(feature = "complex"))]
fn main() {
eprintln!("options_demo requires the backend-faer feature.");
}
#[cfg(all(feature = "backend-faer", not(feature = "complex")))]
use faer::Mat;
#[cfg(all(feature = "backend-faer", not(feature = "complex")))]
use kryst::config::options::parse_all_options;
#[cfg(all(feature = "backend-faer", not(feature = "complex")))]
use kryst::context::ksp_context::KspContext;
#[cfg(all(feature = "backend-faer", not(feature = "complex")))]
use std::env;
#[cfg(all(feature = "backend-faer", not(feature = "complex")))]
use std::sync::Arc;
#[cfg(all(feature = "backend-faer", not(feature = "complex")))]
#[cfg(not(feature = "complex"))]
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = env::args().collect();
let (ksp_opts, pc_opts) = parse_all_options(&args)?;
println!("Kryst Options Demo");
println!("==================");
println!("Parsed KSP options: {:?}", ksp_opts);
println!("Parsed PC options: {:?}", pc_opts);
println!();
let mut ksp = KspContext::new();
ksp.set_from_all_options(&ksp_opts, &pc_opts)?;
println!("KSP Context Configuration:");
println!(" Relative tolerance: {}", ksp.rtol);
println!(" Absolute tolerance: {}", ksp.atol);
println!(" Divergence tolerance: {}", ksp.dtol);
println!(" Maximum iterations: {}", ksp.maxits);
println!(" GMRES restart: {}", ksp.restart);
println!();
let a = Mat::from_fn(2, 2, |i, j| match (i, j) {
(0, 0) => 4.0,
(0, 1) | (1, 0) => 1.0,
(1, 1) => 3.0,
_ => 0.0,
});
let b = vec![1.0, 2.0];
let mut x = vec![0.0, 0.0];
println!("Solving test system:");
println!("Matrix A:");
for i in 0..2 {
print!(" [");
for j in 0..2 {
print!("{:8.3}", a[(i, j)]);
}
println!(" ]");
}
println!("Right-hand side b: {:?}", b);
println!("Initial guess x: {:?}", x);
println!();
ksp.set_operators(Arc::new(a.clone()), None);
match ksp.solve(&b, &mut x) {
Ok(stats) => {
println!("Solution Results:");
println!(
" Converged: {}",
matches!(
stats.reason,
kryst::utils::convergence::ConvergedReason::ConvergedRtol
| kryst::utils::convergence::ConvergedReason::ConvergedAtol
)
);
println!(" Iterations: {}", stats.iterations);
println!(" Final residual norm: {:.2e}", stats.final_residual);
println!(" Solution x: [{:.8}, {:.8}]", x[0], x[1]);
let mut r = vec![0.0, 0.0];
for i in 0..2 {
r[i] = b[i];
for j in 0..2 {
r[i] -= a[(i, j)] * x[j];
}
}
let residual_norm: f64 = (r[0] * r[0] + r[1] * r[1]).sqrt();
println!(" Verification residual: {:.2e}", residual_norm);
if residual_norm < 1e-10 {
println!(" ✓ Solution is accurate!");
} else {
println!(" ⚠ Solution may not be accurate");
}
}
Err(e) => {
println!("Solver failed: {}", e);
return Err(e.into());
}
}
println!();
println!("Demo completed successfully!");
println!();
println!("Try different options:");
println!(" cargo run --example options_demo -- -ksp_type gmres -ksp_rtol 1e-12");
println!(" cargo run --example options_demo -- -ksp_type bicgstab -pc_type jacobi");
println!(" cargo run --example options_demo -- -ksp_type preonly -pc_type lu");
println!(" cargo run --example options_demo -- -ksp_type preonly -pc_type qr");
println!(" cargo run --example options_demo -- -help");
Ok(())
}