kryst 3.2.1

Krylov subspace and preconditioned iterative solvers for dense and sparse linear systems, with shared and distributed memory parallelism.
use crate::algebra::prelude::*;
use crate::context::ksp_context::Workspace;
use crate::parallel::{NoComm, UniverseComm};
use crate::preconditioner::PcSide;
use crate::solver::LinearSolver;
use crate::solver::block::{BlockKrylovOptions, bicgstab::BlockBicgstabSolver, gmres::BlockGmresSolver};
use crate::utils::convergence::ConvergedReason;

#[test]
fn block_gmres_converges_on_block_rhs() {
    let mut opts = BlockKrylovOptions::default();
    opts.block_size = 2;
    opts.restart_blocks = 4;
    opts.max_iters = 50;
    let mut solver = BlockGmresSolver::new(opts);
    let a = super::util::spd_poisson2d(4);
    let n = a.nrows();
    let mut b: Vec<R> = vec![R::default(); n * 2];
    for col in 0..2 {
        for row in 0..n {
            b[col * n + row] = R::from(1.0 + (col + row) as f64);
        }
    }
    let mut x: Vec<R> = vec![R::default(); n * 2];
    let mut ws = Workspace::default();
    let comm = UniverseComm::NoComm(NoComm);
    let op: &dyn crate::matrix::op::LinOp<S = f64> = &a;
    let stats = solver
        .solve(
            op,
            None,
            &b,
            &mut x,
            PcSide::Left,
            &comm,
            None,
            Some(&mut ws),
        )
        .unwrap();
    assert!(matches!(
        stats.reason,
        ConvergedReason::ConvergedAtol | ConvergedReason::ConvergedRtol
    ));
}

#[test]
fn block_bicgstab_converges_on_block_rhs() {
    let mut opts = BlockKrylovOptions::default();
    opts.block_size = 2;
    opts.max_iters = 100;
    let mut solver = BlockBicgstabSolver::new(opts);
    let a = super::util::spd_poisson2d(4);
    let n = a.nrows();
    let mut b: Vec<R> = vec![R::default(); n * 2];
    for col in 0..2 {
        for row in 0..n {
            b[col * n + row] = R::from(1.0 + (col + row) as f64);
        }
    }
    let mut x: Vec<R> = vec![R::default(); n * 2];
    let mut ws = Workspace::default();
    let comm = UniverseComm::NoComm(NoComm);
    let op: &dyn crate::matrix::op::LinOp<S = f64> = &a;
    let stats = solver
        .solve(
            op,
            None,
            &b,
            &mut x,
            PcSide::Left,
            &comm,
            None,
            Some(&mut ws),
        )
        .unwrap();
    assert!(matches!(
        stats.reason,
        ConvergedReason::ConvergedAtol | ConvergedReason::ConvergedRtol
    ));
}