Skip to content

Commit 7ac3ce5

Browse files
authored
Substitute BatchedTridiagonalSolver in SmootherGive (#173)
1 parent 2104614 commit 7ac3ce5

File tree

8 files changed

+575
-618
lines changed

8 files changed

+575
-618
lines changed

include/LinearAlgebra/Solvers/tridiagonal_solver.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,20 @@ class BatchedTridiagonalSolver
2323
assign(sub_diagonal_, T(0));
2424
}
2525

26+
/* ------------------- */
27+
/* Accessors for sizes */
28+
/* ------------------- */
29+
30+
int matrixDimension() const
31+
{
32+
return matrix_dimension_;
33+
}
34+
35+
int batchCount() const
36+
{
37+
return batch_count_;
38+
}
39+
2640
/* ---------------------------- */
2741
/* Accessors for matrix entries */
2842
/* ---------------------------- */
@@ -288,4 +302,4 @@ class BatchedTridiagonalSolver
288302

289303
bool is_cyclic_;
290304
bool is_factorized_;
291-
};
305+
};

include/Smoother/SmootherGive/smootherGive.h

Lines changed: 134 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,101 +2,184 @@
22

33
#include "../smoother.h"
44

5+
// The smoother implements the coupled circle-radial smoothing procedure.
6+
// It performs iterative updates on different parts of the grid based
7+
// on the circle/radial section of the grid and black/white line coloring.
8+
//
9+
// The smoother solves linear systems of the form:
10+
// A_sc * u_sc = f_sc − A_sc^ortho * u_sc^ortho
11+
// where:
12+
// - s in {Circle, Radial} denotes the smoother section type,
13+
// - c in {Black, White} denotes the coloring (even/odd line sub-system).
14+
//
15+
// The update sequence is as follows:
16+
// 1. Black-Circle update (u_bc):
17+
// A_bc * u_bc = f_bc − A_bc^ortho * u_bc^ortho
18+
// 2. White-Circle update (u_wc):
19+
// A_wc * u_wc = f_wc − A_wc^ortho * u_wc^ortho
20+
// 3. Black-Radial update (u_br):
21+
// A_br * u_br = f_br − A_br^ortho * u_br^ortho
22+
// 4. White-Radial update (u_wr):
23+
// A_wr * u_wr = f_wr − A_wr^ortho * u_wr^ortho
24+
//
25+
// Algorithm details:
26+
// - 'rhs' corresponds to the f vector, 'x' stores the final solution,
27+
// and 'temp' is used for temporary storage during updates.
28+
// - First, temp is updated with f_sc − A_sc^ortho * u_sc^ortho.
29+
// - The system is then solved in-place in temp, and the results
30+
// are copied back to x.
31+
// - Using 'temp' isn't strictly necessary as all updates could be performed in place in 'x'.
32+
// - The stencil is applied using the A-Give method.
33+
//
34+
// Solver and matrix structure:
35+
// - The matrix A_sc is block tridiagonal due to the smoother-based
36+
// grid indexing, which allows efficient line-wise factorization.
37+
// - The inner boundary requires special handling because it
38+
// contains an additional across-origin coupling, making it
39+
// non-tridiagonal; therefore, a more general solver is used there.
40+
// When using the MUMPS solver, the matrix is assembled in COO format.
41+
// When using the in-house solver, the matrix is stored in CSR format.
42+
// - Circular line matrices are cyclic tridiagonal due to angular
43+
// periodicity, whereas radial line matrices are strictly tridiagonal.
44+
// - Dirichlet boundary contributions in radial matrices are shifted
45+
// into the right-hand side to make A_sc symmetric.
46+
547
class SmootherGive : public Smoother
648
{
749
public:
50+
// Constructs the coupled circle-radial smoother.
51+
// Builds the A_sc smoother matrices and prepares the solvers.
852
explicit SmootherGive(const PolarGrid& grid, const LevelCache& level_cache, const DomainGeometry& domain_geometry,
953
const DensityProfileCoefficients& density_profile_coefficients, bool DirBC_Interior,
1054
int num_omp_threads);
55+
56+
// If MUMPS is enabled, this cleans up the inner boundary solver.
1157
~SmootherGive() override;
1258

59+
// Performs one full coupled smoothing sweep:
60+
// BC -> WC -> BR -> WR
61+
// Parallel implementation using OpenMP:
62+
// Scedule every 2nd/4th line in parallel to avoid race conditions arising from the A-Give distribution.
63+
// Sceduling every 3rd line in parallel would also be possible, but is less natural for the 2 coloring.
1364
void smoothing(Vector<double> x, ConstVector<double> rhs, Vector<double> temp) override;
1465

1566
private:
16-
void smoothingSequential(Vector<double> x, ConstVector<double> rhs, Vector<double> temp);
17-
void smoothingForLoop(Vector<double> x, ConstVector<double> rhs, Vector<double> temp);
18-
19-
// The A_sc matrix on i_r = 0 is defined through the COO/CSR matrix
20-
// 'inner_boundary_circle_matrix_' due to the across-origin treatment.
21-
// It isn't tridiagonal and thus it requires a more advanced solver.
22-
// Note that circle_tridiagonal_solver_[0] is thus unused!
23-
// Additionally 'circle_tridiagonal_solver_[index]' will refer to the circular line i_r = index and
24-
// 'radial_tridiagonal_solver_[index] will refer to the radial line i_theta = index.
67+
/* ------------------- */
68+
/* Tridiagonal solvers */
69+
/* ------------------- */
70+
71+
// Batched solver for cyclic-tridiagonal circle line A_sc matrices.
72+
BatchedTridiagonalSolver<double> circle_tridiagonal_solver_;
73+
74+
// Batched solver for tridiagonal radial circle line A_sc matrices.
75+
BatchedTridiagonalSolver<double> radial_tridiagonal_solver_;
76+
77+
// The A_sc matrix on i_r = 0 (inner circle) is NOT tridiagonal because
78+
// it potentially includes across-origin coupling. Therefore, it is assembled
79+
// into a sparse matrix and solved using a general-purpose sparse solver.
80+
// When using the MUMPS solver, the matrix is assembled in COO format.
81+
// When using the in-house solver, the matrix is stored in CSR format.
2582
#ifdef GMGPOLAR_USE_MUMPS
2683
using MatrixType = SparseMatrixCOO<double>;
2784
DMUMPS_STRUC_C inner_boundary_mumps_solver_;
2885
#else
2986
using MatrixType = SparseMatrixCSR<double>;
3087
SparseLUSolver<double> inner_boundary_lu_solver_;
3188
#endif
89+
// Sparse matrix for the non-tridiagonal inner boundary circle block.
3290
MatrixType inner_boundary_circle_matrix_;
3391

34-
std::vector<SymmetricTridiagonalSolver<double>> circle_tridiagonal_solver_;
35-
std::vector<SymmetricTridiagonalSolver<double>> radial_tridiagonal_solver_;
92+
// Note:
93+
// - circle_tridiagonal_solver_[batch=0] is unused. Use the COO/CSR matrix instead.
94+
// - circle_tridiagonal_solver_[batch=i_r] solves circle line i_r.
95+
// - radial_tridiagonal_solver_[batch=i_theta] solves radial line i_theta.
96+
97+
/* ------------------- */
98+
/* Stencil definitions */
99+
/* ------------------- */
100+
101+
// Stencils encode neighborhood connectivity for A_sc matrix assembly.
102+
// It is only used in the construction of COO/CSR matrices.
103+
// Thus it is only used for the interior boundary matrix and not needed for the tridiagonal matrices.
104+
// The Stencil class stores the offset for each position.
105+
// - Non-zero matrix indicesare obtained via `ptr + offset`
106+
// - A offset value of `-1` means the position is not included in the stencil pattern.
107+
// - Other values (0, 1, 2, ..., stencil_size - 1) correspond to valid stencil indices.
36108

37109
// clang-format off
38110
const Stencil stencil_DB_ = {
39111
-1, -1, -1,
40112
-1, 0, -1,
41113
-1, -1, -1
42114
};
43-
/* Circle Stencils */
44-
const Stencil circle_stencil_interior_ = {
45-
-1, 2, -1,
46-
-1, 0, -1,
47-
-1, 1, -1
48-
};
49115
const Stencil circle_stencil_across_origin_ = {
50116
-1, 3, -1,
51117
1, 0, -1,
52118
-1, 2, -1
53119
};
54-
/* Radial Stencils */
55-
const Stencil radial_stencil_interior_ = {
56-
-1, -1, -1,
57-
1, 0, 2,
58-
-1, -1, -1
59-
};
60-
const Stencil radial_stencil_next_outer_DB_ = {
61-
-1, -1, -1,
62-
1, 0, -1,
63-
-1, -1, -1
64-
};
65-
const Stencil radial_stencil_next_circular_smoothing_ = {
66-
-1, -1, -1,
67-
-1, 0, 1,
68-
-1, -1, -1
69-
};
120+
70121
// clang-format on
71122

72-
const Stencil& getStencil(int i_r) const;
73-
int getNonZeroCountCircleAsc(const int i_r) const;
74-
int getNonZeroCountRadialAsc(const int i_theta) const;
123+
// Select correct stencil depending on the grid position.
124+
const Stencil& getStencil(int i_r) const; /* Only i_r = 0 implemented */
125+
// Number of nonzero A_sc entries.
126+
int getNonZeroCountCircleAsc(int i_r) const; /* Only i_r = 0 implemented */
127+
// Obtain a ptr to index into COO matrices.
128+
// It accumulates all stencil sizes within a line up to, but excluding the current node.
129+
int getCircleAscIndex(int i_r, int i_theta) const; /* Only i_r = 0 implemented */
75130

76-
int getCircleAscIndex(const int i_r, const int i_theta) const;
77-
int getRadialAscIndex(const int i_r, const int i_theta) const;
131+
/* --------------- */
132+
/* Matrix assembly */
133+
/* --------------- */
78134

135+
// Build all A_sc matrices for circle and radial smoothers.
79136
void buildAscMatrices();
80-
void buildAscCircleSection(const int i_r);
81-
void buildAscRadialSection(const int i_theta);
137+
// Build A_sc matrix block for a single circular line.
138+
void buildAscCircleSection(int i_r);
139+
// Build A_sc matrix block for a single radial line.
140+
void buildAscRadialSection(int i_theta);
141+
// Build A_sc for a specific node (i_r, i_theta)
142+
void nodeBuildAscGive(int i_r, int i_theta, const PolarGrid& grid, bool DirBC_Interior,
143+
MatrixType& inner_boundary_circle_matrix,
144+
BatchedTridiagonalSolver<double>& circle_tridiagonal_solver,
145+
BatchedTridiagonalSolver<double>& radial_tridiagonal_solver, double arr, double att,
146+
double art, double detDF, double coeff_beta);
147+
148+
/* ---------------------- */
149+
/* Orthogonal application */
150+
/* ---------------------- */
82151

83-
void applyAscOrthoCircleSection(const int i_r, const SmootherColor smoother_color, ConstVector<double> x,
152+
// Compute temp = f_sc − A_sc^ortho * u_sc^ortho (precomputed right-hand side)
153+
// where x = u_sc and rhs = f_sc
154+
void applyAscOrthoCircleSection(int i_r, const SmootherColor smoother_color, ConstVector<double> x,
84155
ConstVector<double> rhs, Vector<double> temp);
85-
void applyAscOrthoRadialSection(const int i_theta, const SmootherColor smoother_color, ConstVector<double> x,
156+
void applyAscOrthoRadialSection(int i_theta, const SmootherColor smoother_color, ConstVector<double> x,
86157
ConstVector<double> rhs, Vector<double> temp);
87158

88-
void solveCircleSection(const int i_r, Vector<double> x, Vector<double> temp, Vector<double> solver_storage_1,
89-
Vector<double> solver_storage_2);
90-
void solveRadialSection(const int i_theta, Vector<double> x, Vector<double> temp, Vector<double> solver_storage);
159+
/* ----------------- */
160+
/* Line-wise solvers */
161+
/* ----------------- */
91162

163+
// Solve the linear system:
164+
// A_sc * u_sc = f_sc − A_sc^ortho * u_sc^ortho
165+
// Parameter mapping:
166+
// x = u_sc (solution vector for section s and color c)
167+
// temp = f_sc − A_sc^ortho * u_sc^ortho (precomputed right-hand side)
168+
// where:
169+
// s in {Circle, Radial} denotes the smoother section type,
170+
// c in {Black, White} denotes the line coloring.
171+
void solveBlackCircleSection(Vector<double> x, Vector<double> temp);
172+
void solveWhiteCircleSection(Vector<double> x, Vector<double> temp);
173+
void solveBlackRadialSection(Vector<double> x, Vector<double> temp);
174+
void solveWhiteRadialSection(Vector<double> x, Vector<double> temp);
175+
176+
/* ----------------------------------- */
177+
/* Initialize and destroy MUMPS solver */
178+
/* ----------------------------------- */
92179
#ifdef GMGPOLAR_USE_MUMPS
180+
// Initialize sparse MUMPS solver with assembled COO matrix.
93181
void initializeMumpsSolver(DMUMPS_STRUC_C& mumps_solver, SparseMatrixCOO<double>& solver_matrix);
182+
// Release MUMPS internal memory and MPI structures.
94183
void finalizeMumpsSolver(DMUMPS_STRUC_C& mumps_solver);
95184
#endif
96-
97-
void nodeBuildSmootherGive(int i_r, int i_theta, const PolarGrid& grid, bool DirBC_Interior,
98-
MatrixType& inner_boundary_circle_matrix,
99-
std::vector<SymmetricTridiagonalSolver<double>>& circle_tridiagonal_solver,
100-
std::vector<SymmetricTridiagonalSolver<double>>& radial_tridiagonal_solver, double arr,
101-
double att, double art, double detDF, double coeff_beta);
102185
};

src/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,12 @@ set(SMOOTHER_SOURCES
117117
${CMAKE_CURRENT_SOURCE_DIR}/Smoother/smoother.cpp
118118

119119
# SmootherGive
120+
${CMAKE_CURRENT_SOURCE_DIR}/Smoother/SmootherGive/applyAscOrtho.cpp
120121
${CMAKE_CURRENT_SOURCE_DIR}/Smoother/SmootherGive/buildMatrix.cpp
121122
${CMAKE_CURRENT_SOURCE_DIR}/Smoother/SmootherGive/initializeMumps.cpp
122123
${CMAKE_CURRENT_SOURCE_DIR}/Smoother/SmootherGive/matrixStencil.cpp
123124
${CMAKE_CURRENT_SOURCE_DIR}/Smoother/SmootherGive/smootherGive.cpp
124-
${CMAKE_CURRENT_SOURCE_DIR}/Smoother/SmootherGive/smootherSolver.cpp
125+
${CMAKE_CURRENT_SOURCE_DIR}/Smoother/SmootherGive/solveAscSystem.cpp
125126

126127
# SmootherTake
127128
${CMAKE_CURRENT_SOURCE_DIR}/Smoother/SmootherTake/buildMatrix.cpp

0 commit comments

Comments
 (0)