Skip to main content

scirs2_sparse/parallel_amg/
types.rs

1//! Types for Parallel Algebraic Multigrid (AMG) Coarsening
2//!
3//! This module defines configuration, result, and hierarchy types for
4//! the parallel AMG coarsening algorithms.
5
6use crate::csr::CsrMatrix;
7
8/// Configuration for parallel AMG coarsening algorithms
9#[derive(Debug, Clone)]
10pub struct ParallelAmgConfig {
11    /// Number of threads for parallel computations
12    pub n_threads: usize,
13    /// Strength-of-connection threshold (default 0.25)
14    pub strength_threshold: f64,
15    /// Coarsening method to use
16    pub coarsening: CoarsenMethod,
17    /// Maximum number of hierarchy levels
18    pub max_levels: usize,
19    /// Minimum coarse grid size (stop coarsening below this)
20    pub min_coarse_size: usize,
21    /// Coarsening ratio target (stop if ratio exceeds this)
22    pub max_coarsening_ratio: f64,
23    /// Jacobi smoothing weight for SA interpolation
24    pub omega: f64,
25}
26
27impl Default for ParallelAmgConfig {
28    fn default() -> Self {
29        Self {
30            n_threads: 1,
31            strength_threshold: 0.25,
32            coarsening: CoarsenMethod::ParallelRS,
33            max_levels: 10,
34            min_coarse_size: 4,
35            max_coarsening_ratio: 0.85,
36            omega: 4.0 / 3.0,
37        }
38    }
39}
40
41/// Method for parallel coarsening
42#[non_exhaustive]
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub enum CoarsenMethod {
45    /// Parallel Ruge-Stüben coarsening with parallel pass-1
46    ParallelRS,
47    /// Smoothed aggregation coarsening
48    ParallelSA,
49    /// Parallel Maximum Independent Set coarsening
50    PMIS,
51    /// Cleary-Luby-Jones-Plassmann coarsening
52    CLJP,
53}
54
55/// Result of a coarsening step: C/F splitting
56#[derive(Debug, Clone)]
57pub struct CoarseningResult {
58    /// Indices of coarse (C) nodes
59    pub c_nodes: Vec<usize>,
60    /// Indices of fine (F) nodes
61    pub f_nodes: Vec<usize>,
62    /// C/F labeling array: 0 = F-node, 1 = C-node
63    pub cf_splitting: Vec<u8>,
64}
65
66impl CoarseningResult {
67    /// Create a CoarseningResult from a cf_splitting array
68    pub fn from_splitting(cf_splitting: Vec<u8>) -> Self {
69        let n = cf_splitting.len();
70        let mut c_nodes = Vec::new();
71        let mut f_nodes = Vec::new();
72        for i in 0..n {
73            if cf_splitting[i] == 1 {
74                c_nodes.push(i);
75            } else {
76                f_nodes.push(i);
77            }
78        }
79        Self {
80            c_nodes,
81            f_nodes,
82            cf_splitting,
83        }
84    }
85
86    /// Number of nodes
87    pub fn n(&self) -> usize {
88        self.cf_splitting.len()
89    }
90
91    /// Number of coarse nodes
92    pub fn n_coarse(&self) -> usize {
93        self.c_nodes.len()
94    }
95
96    /// Number of fine nodes
97    pub fn n_fine(&self) -> usize {
98        self.f_nodes.len()
99    }
100
101    /// Coarsening ratio (n_coarse / n_total)
102    pub fn coarsening_ratio(&self) -> f64 {
103        let n = self.n();
104        if n == 0 {
105            return 0.0;
106        }
107        self.n_coarse() as f64 / n as f64
108    }
109}
110
111/// A single level in the parallel AMG hierarchy
112#[derive(Debug, Clone)]
113pub struct ParallelAmgLevel {
114    /// Fine-grid system matrix A
115    pub a: CsrMatrix<f64>,
116    /// Prolongation (interpolation) operator P: coarse → fine
117    pub p: CsrMatrix<f64>,
118    /// Restriction operator R: fine → coarse (= P^T for SA)
119    pub r: CsrMatrix<f64>,
120    /// Number of fine-grid unknowns
121    pub n_fine: usize,
122    /// Number of coarse-grid unknowns
123    pub n_coarse: usize,
124}
125
126impl ParallelAmgLevel {
127    /// Create a new level
128    pub fn new(
129        a: CsrMatrix<f64>,
130        p: CsrMatrix<f64>,
131        r: CsrMatrix<f64>,
132        n_fine: usize,
133        n_coarse: usize,
134    ) -> Self {
135        Self {
136            a,
137            p,
138            r,
139            n_fine,
140            n_coarse,
141        }
142    }
143}
144
145/// Complete parallel AMG hierarchy
146#[derive(Debug, Clone)]
147pub struct ParallelAmgHierarchy {
148    /// Hierarchy levels (from finest to coarsest)
149    pub levels: Vec<ParallelAmgLevel>,
150    /// Number of levels in hierarchy
151    pub n_levels: usize,
152    /// Coarsest-grid system matrix
153    pub coarsest_a: CsrMatrix<f64>,
154}
155
156impl ParallelAmgHierarchy {
157    /// Create a new hierarchy
158    pub fn new(levels: Vec<ParallelAmgLevel>, coarsest_a: CsrMatrix<f64>) -> Self {
159        let n_levels = levels.len() + 1; // levels + coarsest
160        Self {
161            levels,
162            n_levels,
163            coarsest_a,
164        }
165    }
166
167    /// Size of the fine grid
168    pub fn fine_size(&self) -> usize {
169        if self.levels.is_empty() {
170            self.coarsest_a.shape().0
171        } else {
172            self.levels[0].n_fine
173        }
174    }
175
176    /// Size of the coarsest grid
177    pub fn coarse_size(&self) -> usize {
178        self.coarsest_a.shape().0
179    }
180}