use crate::somelinalg::iterative_solvers_cpu::GMRES_mult_api::filter_zeros;
use faer::linalg::solvers::Solve;
use faer::mat::Mat;
use faer::sparse::{SparseColMat, Triplet};
use rayon::prelude::*;
pub fn invers_Mat_LU(
mat: SparseColMat<usize, f64>,
tol: f64,
_max_iter: usize,
) -> Option<SparseColMat<usize, f64>> {
let (n, m) = mat.shape();
assert_eq!(n, m, "matrix must be square");
let LU = mat.as_dyn().sp_lu().unwrap();
let mut vec_of_triplets: Vec<Triplet<usize, usize, f64>> = Vec::new();
let triplets: Vec<Vec<Triplet<usize, usize, f64>>> = (0..n)
.into_par_iter()
.map(|i| {
let mut b: Mat<f64> = Mat::<f64>::zeros(n, 1); b[(i, 0)] = 1.0;
let res = LU.solve(b);
filter_zeros(&res, i, tol) })
.collect();
for triplet in triplets {
vec_of_triplets.extend(triplet);
}
let inverted_matrix: SparseColMat<usize, f64> =
SparseColMat::<usize, f64>::try_new_from_triplets(n, m, &vec_of_triplets).unwrap();
Some(inverted_matrix)
}
pub fn solve_with_upper_triangular(
mat: SparseColMat<usize, f64>,
tol: f64,
_max_iter: usize,
) -> Option<SparseColMat<usize, f64>> {
println!("mat = {:?}", mat.row_idx());
for j in 0..mat.shape().0 {
let row_indices_of_col_raw: Vec<usize> = mat.as_dyn().row_idx_of_col(j).collect();
println!("{}-th col {:?}", j, row_indices_of_col_raw);
row_indices_of_col_raw.into_iter().for_each(|k| {
if k < j {
println!("k<j, k={},j={},element = {}", k, j, mat[(k, j)])
}
});
}
let (n, m) = mat.shape();
assert_eq!(n, m, "matrix must be square");
let mut vec_of_triplets: Vec<Triplet<usize, usize, f64>> = Vec::new();
let triplets: Vec<Vec<Triplet<usize, usize, f64>>> = (0..n)
.into_par_iter()
.map(|i| {
let mut b: Mat<f64> = Mat::<f64>::zeros(n, 1);
b[(i, 0)] = 1.0;
mat.sp_solve_upper_triangular_in_place(&mut b);
filter_zeros(&b, i, tol)
})
.collect();
for triplet in triplets {
vec_of_triplets.extend(triplet);
}
let inverted_matrix: SparseColMat<usize, f64> =
SparseColMat::<usize, f64>::try_new_from_triplets(n, m, &vec_of_triplets).unwrap();
Some(inverted_matrix)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::somelinalg::iterative_solvers_cpu::GMRES_mult_api::dense_to_sparse;
use faer_gmres::gmres;
use nalgebra::DMatrix;
#[test]
fn test_Lusolver() {
let test_jac = vec![
-0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0, -0.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
-1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, -0.9, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.1, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
1.0, -0.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, -0.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.1, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, -0.9, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 1.0, -0.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, -0.9, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.1, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 1.0, -0.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, -1.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, -0.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.1, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
];
println!("{}", test_jac.len());
let jac_DM: DMatrix<f64> = DMatrix::from_row_slice(20, 20, &test_jac.as_slice());
let sparse_jac = dense_to_sparse(jac_DM);
println!("JAC: {:?},{:?}", sparse_jac, sparse_jac.shape());
let mut b: Mat<f64> = Mat::<f64>::zeros(20, 1);
b[(0, 0)] = 1.0;
let mut x = Mat::<f64>::zeros(20, 1);
let (_err, _iterss) =
gmres(sparse_jac.as_ref(), b.as_ref(), x.as_mut(), 100, 1e-8, None).unwrap();
assert_eq!(b.shape(), (20, 1));
let inverted1 = invers_Mat_LU(sparse_jac.clone(), 1e-13, 100).unwrap();
for j in 0..inverted1.shape().1 {
let _row = inverted1.val_of_col(j);
}
assert_eq!(inverted1.shape(), (20, 20));
}
}