#[cfg(feature = "local_sparse")]
use russell_lab::*;
#[cfg(feature = "local_sparse")]
use russell_sparse::prelude::*;
#[cfg(feature = "local_sparse")]
use russell_sparse::StrError;
#[cfg(feature = "local_sparse")]
fn main() -> Result<(), StrError> {
let ndim = 5; let nnz = 13;
let mut mumps = SolverMUMPS::new()?;
let mut coo = CooMatrix::new(ndim, ndim, nnz, Sym::No)?;
coo.put(0, 0, 1.0)?; coo.put(0, 0, 1.0)?; coo.put(1, 0, 3.0)?;
coo.put(0, 1, 3.0)?;
coo.put(2, 1, -1.0)?;
coo.put(4, 1, 4.0)?;
coo.put(1, 2, 4.0)?;
coo.put(2, 2, -3.0)?;
coo.put(3, 2, 1.0)?;
coo.put(4, 2, 2.0)?;
coo.put(2, 3, 2.0)?;
coo.put(1, 4, 6.0)?;
coo.put(4, 4, 1.0)?;
let mut params = LinSolParams::new();
params.compute_error_estimates = true;
params.compute_condition_numbers = true;
params.verbose = false;
mumps.factorize(&coo, Some(params))?;
let mut x = Vector::new(ndim);
let rhs = Vector::from(&[8.0, 45.0, -3.0, 3.0, 19.0]);
mumps.solve(&mut x, &rhs, false)?;
println!("x =\n{}", x);
let correct = vec![1.0, 2.0, 3.0, 4.0, 5.0];
vec_approx_eq(&x, &correct, 1e-14);
let a = coo.as_dense();
let mut ai = Matrix::new(5, 5);
let det_a = mat_inverse(&mut ai, &a).unwrap();
let norm_a = mat_norm(&a, Norm::Inf);
let norm_ai = mat_norm(&ai, Norm::Inf);
let cond = norm_a * norm_ai;
let rcond = 1.0 / cond;
let verify = VerifyLinSys::from(&coo, &x, &rhs).unwrap();
let mut stats = StatsLinSol::new();
mumps.update_stats(&mut stats);
let s = &stats.mumps_stats;
println!("\n___ ANALYSIS ________________________");
println!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
println!("a =\n{}", a);
println!("a⁻¹ =\n{:.5}", ai);
println!(" det(a) = {:?}", det_a);
println!(" ‖a‖∞ = {:?}", norm_a);
println!(" ‖a⁻¹‖∞ = {:?}", norm_ai);
println!("cond = ‖a‖∞ · ‖a⁻¹‖∞ = {:?}", cond);
println!(" rcond = 1 / cond = {:?}", rcond);
println!(" max_abs_a = {:?}", verify.max_abs_a);
println!(" max_abs_ax = {:?}", verify.max_abs_ax);
println!(" max_abs_diff = {:?}", verify.max_abs_diff);
println!(" relative_error = {:?}", verify.relative_error);
println!(" norm_a = {:?}", &s.inf_norm_a);
println!(" norm_x = {:?}", &s.inf_norm_x);
println!(" residual = {:?}", &s.scaled_residual);
println!(" omega1 = {:?}", &s.backward_error_omega1);
println!(" omega2 = {:?}", &s.backward_error_omega2);
println!(" delta = {:?}", &s.normalized_delta_x);
println!(" cond1 = {:?}", &s.condition_number1);
println!(" cond2 = {:?}", &s.condition_number2);
Ok(())
}
#[cfg(not(feature = "local_sparse"))]
fn main() {
println!("MUMPS is not available");
}