use crate::csr::CsrMatrix;
#[derive(Debug, Clone)]
pub struct ParallelAmgConfig {
pub n_threads: usize,
pub strength_threshold: f64,
pub coarsening: CoarsenMethod,
pub max_levels: usize,
pub min_coarse_size: usize,
pub max_coarsening_ratio: f64,
pub omega: f64,
}
impl Default for ParallelAmgConfig {
fn default() -> Self {
Self {
n_threads: 1,
strength_threshold: 0.25,
coarsening: CoarsenMethod::ParallelRS,
max_levels: 10,
min_coarse_size: 4,
max_coarsening_ratio: 0.85,
omega: 4.0 / 3.0,
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CoarsenMethod {
ParallelRS,
ParallelSA,
PMIS,
CLJP,
}
#[derive(Debug, Clone)]
pub struct CoarseningResult {
pub c_nodes: Vec<usize>,
pub f_nodes: Vec<usize>,
pub cf_splitting: Vec<u8>,
}
impl CoarseningResult {
pub fn from_splitting(cf_splitting: Vec<u8>) -> Self {
let n = cf_splitting.len();
let mut c_nodes = Vec::new();
let mut f_nodes = Vec::new();
for i in 0..n {
if cf_splitting[i] == 1 {
c_nodes.push(i);
} else {
f_nodes.push(i);
}
}
Self {
c_nodes,
f_nodes,
cf_splitting,
}
}
pub fn n(&self) -> usize {
self.cf_splitting.len()
}
pub fn n_coarse(&self) -> usize {
self.c_nodes.len()
}
pub fn n_fine(&self) -> usize {
self.f_nodes.len()
}
pub fn coarsening_ratio(&self) -> f64 {
let n = self.n();
if n == 0 {
return 0.0;
}
self.n_coarse() as f64 / n as f64
}
}
#[derive(Debug, Clone)]
pub struct ParallelAmgLevel {
pub a: CsrMatrix<f64>,
pub p: CsrMatrix<f64>,
pub r: CsrMatrix<f64>,
pub n_fine: usize,
pub n_coarse: usize,
}
impl ParallelAmgLevel {
pub fn new(
a: CsrMatrix<f64>,
p: CsrMatrix<f64>,
r: CsrMatrix<f64>,
n_fine: usize,
n_coarse: usize,
) -> Self {
Self {
a,
p,
r,
n_fine,
n_coarse,
}
}
}
#[derive(Debug, Clone)]
pub struct ParallelAmgHierarchy {
pub levels: Vec<ParallelAmgLevel>,
pub n_levels: usize,
pub coarsest_a: CsrMatrix<f64>,
}
impl ParallelAmgHierarchy {
pub fn new(levels: Vec<ParallelAmgLevel>, coarsest_a: CsrMatrix<f64>) -> Self {
let n_levels = levels.len() + 1; Self {
levels,
n_levels,
coarsest_a,
}
}
pub fn fine_size(&self) -> usize {
if self.levels.is_empty() {
self.coarsest_a.shape().0
} else {
self.levels[0].n_fine
}
}
pub fn coarse_size(&self) -> usize {
self.coarsest_a.shape().0
}
}