-
aoclsparse_status aoclsparse_ssymgs(aoclsparse_operation trans, aoclsparse_matrix A, const aoclsparse_mat_descr descr, const float alpha, const float *b, float *x)#
-
aoclsparse_status aoclsparse_dsymgs(aoclsparse_operation trans, aoclsparse_matrix A, const aoclsparse_mat_descr descr, const double alpha, const double *b, double *x)#
-
aoclsparse_status aoclsparse_csymgs(aoclsparse_operation trans, aoclsparse_matrix A, const aoclsparse_mat_descr descr, const aoclsparse_float_complex alpha, const aoclsparse_float_complex *b, aoclsparse_float_complex *x)#
-
aoclsparse_status aoclsparse_zsymgs(aoclsparse_operation trans, aoclsparse_matrix A, const aoclsparse_mat_descr descr, const aoclsparse_double_complex alpha, const aoclsparse_double_complex *b, aoclsparse_double_complex *x)#
Symmetric Gauss Seidel(SYMGS) Preconditioner for real/complex single and double data precisions.
aoclsparse_?symgsperforms an iteration of Gauss Seidel preconditioning. Krylov methods such as CG (Conjugate Gradient) and GMRES (Generalized Minimal Residual) are used to solve large sparse linear systems of the form\[ op(A)\; x = \alpha b, \]where \(A\) is a sparse matrix of size \(m\), \(op()\) is a linear operator, \(b\) is a dense right-hand side vector and \(x\) is the unknown dense vector, while \(\alpha\) is a scalar. This Gauss Seidel(GS) relaxation is typically used either as a preconditioner for a Krylov solver directly, or as a smoother in a V –cycle of a multigrid preconditioner to accelerate the convergence rate. The Symmetric Gauss Seidel algorithm performs a forward sweep followed by a backward sweep to maintain symmetry of the matrix operation.To solve a linear system \(Ax = b\), Gauss Seidel(GS) iteration is based on the matrix splitting
\[ A = L + D + U = -E + D - F \]where \(-E\) or \(L\) is strictly lower triangle, \(D\) is diagonal and \(-F\) or \(D\) is strictly upper triangle. Gauss-Seidel is best derived as element-wise (refer Yousef Saad’s book Iterative Methods for Sparse Linear Systems, Second Edition, Chapter 4.1, p. 125 onwards):\[ x_i = \frac{1}{a_{ii}} \; \left (b_i - \sum_{j=1}^{i-1} a_{ij} \; x_j - \sum_{j=i+1}^n a_{ij} \; x_j\right) \]where the first sum is lower triangle i.e., \(-Ex\) and the second sum is upper triangle i.e., \(-Fx\). If we iterate through the rowsi=1tonand keep overwriting/reusing the new \(x_{i}\), we get forward GS, expressed in matrix form as,\[ (D-E) \; x_{k+1} = F \; x_k + b \]Iterating through the rows in reverse order fromi=nto1, the upper triangle keeps using the new \(x_{k+1}\) elements and we get backward GS, expressed in matrix form as,\[ (D-F) \; x_{k+1} = E \; x_k + b \]The above two equations can be expressed in terms ofL,DandUas follows,\[ (L + D)\;x_1 = b - U\;x_0 \]\[ (U + D)\;x = b - L\;x_1 \]So, Symmetric Gauss Seidel (SYMGS) can be computed using twoaoclsparse_?mvand twoaoclsparse_?trsvoperations.The sparse matrix \(A\) can be either a symmetric or a Hermitian matrix, whose fill is indicated by
fill_modefrom the matrix descriptordescrwhere either upper or lower triangular portion of the matrix is used. Matrix \(A\) must be of full rank, that is, the matrix must be invertible. The linear operator \(op()\) can define the transposition or conjugate transposition operations. By default, no transposition is performed. The right-hand-side vector \(b\) and the solution vector \(x\) are dense and must be of the correct size, that is \(m\). If used as fixed point iterative method, the convergence is guaranteed for strictly diagonally dominant and symmetric positive definite matrices from any starting point,x0. However, the API can be applied to wider types of input or as a preconditioning step. Refer Yousef Saad’s Iterative Methods for Sparse Linear Systems 2nd Edition, Theorem 4.9 and related literature for mathematical theory.1. If the matrix descriptor
descrspecifies that the matrix \(A\) is to be regarded as having a unitary diagonal, then the main diagonal entries of matrix \(A\) are not accessed and are considered to all be ones.2. If the matrix \(A\) is described as upper triangular, then only the upper triangular portion of the matrix is referenced. Conversely, if the matrix \(A\) is described lower triangular, then only the lower triangular portion of the matrix is used.
3. This set of APIs allocates couple of work array buffers of size \(m\) for to store intermediate results
4. If the input matrix is of triangular type, the SGS is computed using a single
aoclsparse_?trsvoperation and a quick return is made without going through the 3-step reference(described above)1/* ************************************************************************ 2 * Copyright (c) 2024 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 * THE SOFTWARE. 21 * 22 * ************************************************************************ */ 23 24#include "aoclsparse.h" 25 26#include <cmath> 27#include <iomanip> 28#include <iostream> 29#include <limits> 30#include <vector> 31 32int main(void) 33{ 34 std::cout << "------------------------------------------------" << std::endl 35 << " Symmetric Gauss Seidel Preconditioner" << std::endl 36 << " sample program for real data type" << std::endl 37 << "------------------------------------------------" << std::endl 38 << std::endl; 39 40 /* 41 * This example illustrates how to use Symmetric Gauss Seidel API with an iterative solver, 42 here we have simulated that effect using a loop. The real matrix used is 43 A = [ 44 10 -1 2 0; 45 -1 11 -1 3; 46 2 -1 10 -1; 47 0 3 -1 8; 48 ] 49 */ 50 51 // Create a tri-diagonal matrix in CSR format 52 const aoclsparse_int n = 4, m = 4, nnz = 14; 53 aoclsparse_int icrow[5] = {0, 3, 7, 11, 14}; 54 aoclsparse_int icol[14] = {0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3}; 55 double aval[14] = {10, -1, 2, -1, 11, -1, 3, 2, -1, 10, -1, 3, -1, 8}; 56 aoclsparse_status status; 57 bool oki, ok; 58 59 const double macheps = std::numeric_limits<double>::epsilon(); 60 const double safe_macheps = (double)2.0 * macheps; 61 double exp_tol = 20.0 * sqrt(safe_macheps); 62 63 // Create aoclsparse matrix and its descriptor 64 aoclsparse_matrix A; 65 aoclsparse_index_base base = aoclsparse_index_base_zero; 66 aoclsparse_mat_descr descr_a; 67 aoclsparse_operation trans; 68 status = aoclsparse_create_dcsr(&A, base, m, n, nnz, icrow, icol, aval); 69 if(status != aoclsparse_status_success) 70 { 71 std::cerr << "Error returned from aoclsparse_create_dcsr, status = " << status << "." 72 << std::endl; 73 return 3; 74 } 75 aoclsparse_create_mat_descr(&descr_a); 76 77 double alpha = 1.0; 78 double x[m] = {1, 1, 1, 1}; 79 80 double b[m] = {14, 30, 26, 35}; 81 std::vector<double> xref; 82 xref.assign({1.0, 2.0, 3.0, 4.0}); 83 84 // Indicate to access the lower part of matrix A 85 aoclsparse_set_mat_type(descr_a, aoclsparse_matrix_type_symmetric); 86 aoclsparse_set_mat_fill_mode(descr_a, aoclsparse_fill_mode_lower); 87 trans = aoclsparse_operation_none; 88 89 status = aoclsparse_set_symgs_hint(A, trans, descr_a, 1); 90 if(status != aoclsparse_status_success) 91 { 92 std::cerr << "Error returned from aoclsparse_set_symgs_hint, status = " << status << "." 93 << std::endl; 94 return 3; 95 } 96 status = aoclsparse_optimize(A); 97 if(status != aoclsparse_status_success) 98 { 99 std::cerr << "Error returned from aoclsparse_optimize, status = " << status << "." 100 << std::endl; 101 return 3; 102 } 103 // Solve till convergence 104 std::cout << std::setw(12) << " iter"; 105 for(int i = 0; i < n; i++) 106 std::cout << std::setw(15) << "x[" << i << "]"; 107 std::cout << std::endl; 108 for(int i = 0; i < 8; i++) 109 { 110 status = aoclsparse_dsymgs(trans, A, descr_a, alpha, b, x); 111 if(status != aoclsparse_status_success) 112 { 113 std::cerr << "Error returned from aoclsparse_dsymgs, status = " << status << "." 114 << std::endl; 115 return 3; 116 } 117 std::cout << std::setw(12) << (int)i << " "; 118 for(int j = 0; j < m; ++j) 119 { 120 std::cout << std::setw(16) << std::scientific << x[j] << " "; 121 } 122 std::cout << std::endl; 123 } 124 // Print and check the result 125 std::cout << "Solving A x = alpha b" << std::endl; 126 std::cout << " where x and b are dense vectors" << std::endl; 127 std::cout << " Solution found after 8 iterations, x = " << std::endl; 128 std::cout << std::fixed; 129 std::cout.precision(6); 130 ok = true; 131 for(int i = 0; i < m; ++i) 132 { 133 oki = std::abs(x[i] - xref[i]) <= exp_tol; 134 std::cout << x[i] << (oki ? " " : "! "); 135 ok &= oki; 136 } 137 std::cout << std::endl; 138 139 // Destroy the aoclsparse memory 140 aoclsparse_destroy_mat_descr(descr_a); 141 aoclsparse_destroy(&A); 142 143 return ok ? 0 : 5; 144}
1/* ************************************************************************ 2 * Copyright (c) 2024 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 * THE SOFTWARE. 21 * 22 * ************************************************************************ */ 23 24#include "aoclsparse.h" 25 26#include <cmath> 27#include <complex> 28#include <iomanip> 29#include <iostream> 30#include <limits> 31#include <vector> 32 33int main(void) 34{ 35 std::cout << "------------------------------------------------" << std::endl 36 << " Symmetric Gauss Seidel Preconditioner" << std::endl 37 << " sample program for complex data type" << std::endl 38 << "------------------------------------------------" << std::endl 39 << std::endl; 40 41 /* 42 * This example illustrates how to use Symmetric Gauss Seidel API for complex data 43 with an iterative solver, here we have simulated that effect using a loop. 44 The complex matrix used is 45 A = [ 46 10+i -1-0.1i 2+0.2i 0; 47 -1-0.1i 11+1.1i -1-0.1i 3+0.3i; 48 2+0.2i -1-0.1i 10+i -1-0.1i; 49 0 3+0.3i -1-0.1i 8+0.8i; 50 ] 51 */ 52 53 // Create a tri-diagonal matrix in CSR format 54 const aoclsparse_int n = 4, m = 4, nnz = 14; 55 aoclsparse_int icrow[5] = {0, 3, 7, 11, 14}; 56 aoclsparse_int icol[14] = {0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3}; 57 std::vector<aoclsparse_double_complex> aval; 58 // clang-format off 59 aval.assign({{10,1}, {-1,-0.1}, {2,0.2}, {-1,-0.1}, 60 {11,1.1}, {-1,-0.1}, {3,0.3}, {2,0.2}, 61 {-1,-0.1}, {10,1}, {-1,-0.1}, {3, 0.3}, 62 {-1,-0.1}, {8, 0.8}}); 63 // clang-format on 64 aoclsparse_status status; 65 bool oki, ok; 66 67 const double macheps = std::numeric_limits<double>::epsilon(); 68 const double safe_macheps = (double)2.0 * macheps; 69 double exp_tol = 20.0 * sqrt(safe_macheps); 70 71 // Create aoclsparse matrix and its descriptor 72 aoclsparse_matrix A; 73 aoclsparse_index_base base = aoclsparse_index_base_zero; 74 aoclsparse_mat_descr descr_a; 75 aoclsparse_operation trans; 76 status = aoclsparse_create_zcsr(&A, base, m, n, nnz, icrow, icol, &aval[0]); 77 if(status != aoclsparse_status_success) 78 { 79 std::cerr << "Error returned from aoclsparse_create_dcsr, status = " << status << "." 80 << std::endl; 81 return 3; 82 } 83 aoclsparse_create_mat_descr(&descr_a); 84 85 aoclsparse_double_complex alpha = {1.0, 0.}; 86 87 std::vector<aoclsparse_double_complex> x, b, xref; 88 x.assign({{1, 0.1}, {1, 0.1}, {1, 0.1}, {1, 0.1}}); 89 b.assign({{13.859999999999999, 2.7999999999999998}, 90 {29.699999999999999, 6}, 91 {25.739999999999998, 5.2000000000000002}, 92 {34.649999999999999, 7}}); 93 xref.assign({{0.99999999992700483, 0.099999999992700442}, 94 {2.0000000217847944, 0.20000000217847949}, 95 {3.0000000112573724, 0.30000000112573733}, 96 {3.9999999237056727, 0.39999999237056733}}); 97 98 // Indicate to access the lower part of matrix A 99 aoclsparse_set_mat_type(descr_a, aoclsparse_matrix_type_symmetric); 100 aoclsparse_set_mat_fill_mode(descr_a, aoclsparse_fill_mode_lower); 101 trans = aoclsparse_operation_none; 102 103 status = aoclsparse_set_symgs_hint(A, trans, descr_a, 1); 104 if(status != aoclsparse_status_success) 105 { 106 std::cerr << "Error returned from aoclsparse_set_symgs_hint, status = " << status << "." 107 << std::endl; 108 return 3; 109 } 110 status = aoclsparse_optimize(A); 111 if(status != aoclsparse_status_success) 112 { 113 std::cerr << "Error returned from aoclsparse_optimize, status = " << status << "." 114 << std::endl; 115 return 3; 116 } 117 // Solve till convergence 118 std::cout << std::setw(12) << " iter"; 119 for(int i = 0; i < n; i++) 120 std::cout << std::setw(33) << "x[" << i << "]"; 121 std::cout << std::endl; 122 for(int i = 0; i < 8; i++) 123 { 124 status = aoclsparse_zsymgs(trans, A, descr_a, alpha, &b[0], &x[0]); 125 if(status != aoclsparse_status_success) 126 { 127 std::cerr << "Error returned from aoclsparse_zsymgs, status = " << status << "." 128 << std::endl; 129 return 3; 130 } 131 std::cout << std::setw(12) << (int)i << " "; 132 for(int j = 0; j < m; ++j) 133 { 134 std::cout << std::setw(8) << std::scientific << std::setprecision(6) << "(" << x[j].real 135 << ", " << x[j].imag << ")"; 136 } 137 std::cout << std::endl; 138 } 139 // Print and check the result 140 std::cout << "Solving A x = alpha b" << std::endl; 141 std::cout << " where x and b are dense vectors" << std::endl; 142 std::cout << " Solution found after 8 iterations, x = " << std::endl; 143 std::cout << std::fixed; 144 std::cout.precision(6); 145 ok = true; 146 for(int i = 0; i < m; ++i) 147 { 148 oki = std::abs(x[i].real - xref[i].real) <= exp_tol 149 && std::abs(x[i].imag - xref[i].imag) <= exp_tol; 150 std::cout << "(" << x[i].real << ", " << x[i].imag << "i) " << (oki ? " " : "! "); 151 ok &= oki; 152 } 153 std::cout << std::endl; 154 155 // Destroy the aoclsparse memory 156 aoclsparse_destroy_mat_descr(descr_a); 157 aoclsparse_destroy(&A); 158 159 return ok ? 0 : 5; 160}
Note
- Parameters:
trans – [in] matrix operation to perform on \(A\). Possible values are aoclsparse_operation_none, aoclsparse_operation_transpose, and aoclsparse_operation_conjugate_transpose.
A – [in] sparse matrix \(A\) of size \(m\).
descr – [in] descriptor of the sparse matrix \(A\).
alpha – [in] scalar \(\alpha\).
b – [in] dense vector, of size \(m\).
x – [out] solution vector \(x,\) dense vector of size \(m\).
- Return values:
aoclsparse_status_success – indicates that the operation completed successfully.
aoclsparse_status_invalid_size – informs that either
m,nornnzis invalid. The error code also informs if the given sparse matrix \(A\) is not square.aoclsparse_status_invalid_value – informs that either
base,trans, matrix typedescr->typeor fill modedescr->fill_modeis invalid. If the sparse matrix \(A\) is not of full rank, the error code is returned to indicate that the linear system cannot be solved.aoclsparse_status_invalid_pointer – informs that either
descr,A,b, orxpointer is invalid.aoclsparse_status_not_implemented – this error occurs when the provided matrix’s aoclsparse_fill_mode is aoclsparse_diag_type_unit or the input format is not aoclsparse_csr_mat, or when aoclsparse_matrix_type is aoclsparse_matrix_type_general and
transis aoclsparse_operation_conjugate_transpose.
-
aoclsparse_status aoclsparse_ssymgs_mv(aoclsparse_operation trans, aoclsparse_matrix A, const aoclsparse_mat_descr descr, const float alpha, const float *b, float *x, float *y)#
-
aoclsparse_status aoclsparse_dsymgs_mv(aoclsparse_operation trans, aoclsparse_matrix A, const aoclsparse_mat_descr descr, const double alpha, const double *b, double *x, double *y)#
-
aoclsparse_status aoclsparse_csymgs_mv(aoclsparse_operation trans, aoclsparse_matrix A, const aoclsparse_mat_descr descr, const aoclsparse_float_complex alpha, const aoclsparse_float_complex *b, aoclsparse_float_complex *x, aoclsparse_float_complex *y)#
-
aoclsparse_status aoclsparse_zsymgs_mv(aoclsparse_operation trans, aoclsparse_matrix A, const aoclsparse_mat_descr descr, const aoclsparse_double_complex alpha, const aoclsparse_double_complex *b, aoclsparse_double_complex *x, aoclsparse_double_complex *y)#
Symmetric Gauss Seidel Preconditioner followed by SPMV for single and double precision datatypes.
For full details refer to
aoclsparse_?symgs().This variation of SYMGS, namely with a suffix of _mv, performs matrix-vector multiplication between the sparse matrix \(A\) and the Gauss Seidel solution vector \(x\).
1/* ************************************************************************ 2 * Copyright (c) 2024 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 * THE SOFTWARE. 21 * 22 * ************************************************************************ */ 23 24#include "aoclsparse.h" 25 26#include <cmath> 27#include <iomanip> 28#include <iostream> 29#include <limits> 30#include <vector> 31 32int main(void) 33{ 34 std::cout 35 << "------------------------------------------------" << std::endl 36 << " Symmetric Gauss Seidel Preconditioner followed by sparse matrix-vector multiplication" 37 << std::endl 38 << " sample program for real data type" << std::endl 39 << "------------------------------------------------" << std::endl 40 << std::endl; 41 42 /* 43 * This example illustrates how to use Symmetric Gauss Seidel API to solve 44 * linear system of equations. The real matrix used is 45 * | 111 2 0 0 | 46 * A = | 2 111 2 0 | 47 * | 0 2 111 2 | 48 * | 0 0 2 111 | 49 */ 50 51 // Create a tri-diagonal matrix in CSR format 52 const aoclsparse_int n = 4, m = 4, nnz = 10; 53 aoclsparse_int icrow[5] = {0, 2, 5, 8, 10}; 54 aoclsparse_int icol[10] = {0, 1, 0, 1, 2, 1, 2, 3, 2, 3}; 55 double aval[10] = {111, 2, 2, 111, 2, 2, 111, 2, 2, 111}; 56 aoclsparse_status status; 57 bool oki, ok; 58 59 const double macheps = std::numeric_limits<double>::epsilon(); 60 const double safe_macheps = (double)2.0 * macheps; 61 double exp_tol = 20.0 * sqrt(safe_macheps); 62 63 // Create aoclsparse matrix and its descriptor 64 aoclsparse_matrix A; 65 aoclsparse_index_base base = aoclsparse_index_base_zero; 66 aoclsparse_mat_descr descr_a; 67 aoclsparse_operation trans; 68 status = aoclsparse_create_dcsr(&A, base, m, n, nnz, icrow, icol, aval); 69 if(status != aoclsparse_status_success) 70 { 71 std::cerr << "Error returned from aoclsparse_create_dcsr, status = " << status << "." 72 << std::endl; 73 return 3; 74 } 75 aoclsparse_create_mat_descr(&descr_a); 76 77 double alpha = 1.0; 78 double x[m] = {1, 1, 1, 1}; 79 double y[m] = {0, 0, 0, 0}; 80 81 double b[m] = {115, 230, 345, 450}; 82 std::vector<double> xref; 83 xref.assign({1.000006, 1.999687, 2.999374, 3.999038}); 84 std::vector<double> yref; 85 yref.assign({115.0000000, 229.9639753, 344.9279505, 449.8919266}); 86 87 // Indicate to access the lower part of matrix A 88 aoclsparse_set_mat_type(descr_a, aoclsparse_matrix_type_symmetric); 89 aoclsparse_set_mat_fill_mode(descr_a, aoclsparse_fill_mode_lower); 90 trans = aoclsparse_operation_none; 91 92 status = aoclsparse_set_symgs_hint(A, trans, descr_a, 1); 93 if(status != aoclsparse_status_success) 94 { 95 std::cerr << "Error returned from aoclsparse_set_symgs_hint, status = " << status << "." 96 << std::endl; 97 return 3; 98 } 99 status = aoclsparse_optimize(A); 100 if(status != aoclsparse_status_success) 101 { 102 std::cerr << "Error returned from aoclsparse_optimize, status = " << status << "." 103 << std::endl; 104 return 3; 105 } 106 // Solve 107 status = aoclsparse_dsymgs_mv(trans, A, descr_a, alpha, b, x, y); 108 if(status != aoclsparse_status_success) 109 { 110 std::cerr << "Error returned from aoclsparse_dsymgs_mv, status = " << status << "." 111 << std::endl; 112 return 3; 113 } 114 // Print and check the result 115 std::cout << "Solving A x = alpha b" << std::endl; 116 std::cout << " where x and b are dense vectors" << std::endl; 117 std::cout << " Solution vector x = " << std::endl; 118 std::cout << std::fixed; 119 std::cout.precision(1); 120 ok = true; 121 for(int i = 0; i < m; ++i) 122 { 123 oki = std::abs(x[i] - xref[i]) <= exp_tol; 124 std::cout << x[i] << (oki ? " " : "! "); 125 ok &= oki; 126 } 127 std::cout << std::endl; 128 std::cout << " and Product vector y = " << std::endl; 129 for(int i = 0; i < m; ++i) 130 { 131 oki = std::abs(y[i] - yref[i]) <= exp_tol; 132 std::cout << y[i] << (oki ? " " : "! "); 133 ok &= oki; 134 } 135 std::cout << std::endl; 136 137 // Destroy the aoclsparse memory 138 aoclsparse_destroy_mat_descr(descr_a); 139 aoclsparse_destroy(&A); 140 141 return ok ? 0 : 5; 142}
1/* ************************************************************************ 2 * Copyright (c) 2024 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 * THE SOFTWARE. 21 * 22 * ************************************************************************ */ 23 24#include "aoclsparse.h" 25 26#include <cmath> 27#include <complex> 28#include <iomanip> 29#include <iostream> 30#include <limits> 31#include <vector> 32 33int main(void) 34{ 35 std::cout 36 << "------------------------------------------------" << std::endl 37 << " Symmetric Gauss Seidel Preconditioner followed by sparse matrix-vector multiplication" 38 << std::endl 39 << " sample program for complex data type" << std::endl 40 << "------------------------------------------------" << std::endl 41 << std::endl; 42 43 /* 44 * This example illustrates how to use Symmetric Gauss Seidel API to solve 45 * linear system of equations. The complex matrix used is 46 * | 111+11.1i 2+0.2i 0 0 | 47 * A = | 2+0.2i 111+11.1i 2+0.2i 0 | 48 * | 0 2+0.2i 111+11.1i 2+0.2i | 49 * | 0 0 2+0.2i 111+11.1i | 50 */ 51 52 // Create a tri-diagonal matrix in CSR format 53 const aoclsparse_int n = 4, m = 4, nnz = 10; 54 aoclsparse_int icrow[5] = {0, 2, 5, 8, 10}; 55 aoclsparse_int icol[10] = {0, 1, 0, 1, 2, 1, 2, 3, 2, 3}; 56 std::vector<aoclsparse_double_complex> aval; 57 // clang-format off 58 aval.assign({{111,11.1}, {2,0.2}, {2,0.2}, {111,11.1}, 59 {2,0.2}, {2,0.2}, {111,11.1}, {2,0.2}, 60 {2,0.2}, {111,11.1}}); 61 // clang-format on 62 aoclsparse_status status; 63 bool oki, ok; 64 65 const double macheps = std::numeric_limits<double>::epsilon(); 66 const double safe_macheps = (double)2.0 * macheps; 67 double exp_tol = 20.0 * sqrt(safe_macheps); 68 69 // Create aoclsparse matrix and its descriptor 70 aoclsparse_matrix A; 71 aoclsparse_index_base base = aoclsparse_index_base_zero; 72 aoclsparse_mat_descr descr_a; 73 aoclsparse_operation trans; 74 status = aoclsparse_create_zcsr(&A, base, m, n, nnz, icrow, icol, &aval[0]); 75 if(status != aoclsparse_status_success) 76 { 77 std::cerr << "Error returned from aoclsparse_create_dcsr, status = " << status << "." 78 << std::endl; 79 return 3; 80 } 81 aoclsparse_create_mat_descr(&descr_a); 82 83 aoclsparse_double_complex alpha = {1.0, 0.}; 84 85 std::vector<aoclsparse_double_complex> x, b, y, xref, yref; 86 x.assign({{1, 0.1}, {1, 0.1}, {1, 0.1}, {1, 0.1}}); 87 b.assign({{113.850000, 23.000000}, 88 {227.700000, 46.000000}, 89 {341.550000, 69.000000}, 90 {445.500000, 90.000000}}); 91 y.assign({{0, 0.0}, {0, 0.0}, {0, 0.0}, {0, 0.0}}); 92 xref.assign({{1.0000056, 0.1000006}, 93 {1.9996866, 0.1999687}, 94 {2.9993739, 0.2999374}, 95 {3.9990376, 0.3999038}}); 96 yref.assign({{113.8500000, 23.0000000}, 97 {227.6643355, 45.9927951}, 98 {341.4786710, 68.9855901}, 99 {445.3930073, 89.9783853}}); 100 101 // Indicate to access the lower part of matrix A 102 aoclsparse_set_mat_type(descr_a, aoclsparse_matrix_type_symmetric); 103 aoclsparse_set_mat_fill_mode(descr_a, aoclsparse_fill_mode_lower); 104 trans = aoclsparse_operation_none; 105 106 status = aoclsparse_set_symgs_hint(A, trans, descr_a, 1); 107 if(status != aoclsparse_status_success) 108 { 109 std::cerr << "Error returned from aoclsparse_set_symgs_hint, status = " << status << "." 110 << std::endl; 111 return 3; 112 } 113 status = aoclsparse_optimize(A); 114 if(status != aoclsparse_status_success) 115 { 116 std::cerr << "Error returned from aoclsparse_optimize, status = " << status << "." 117 << std::endl; 118 return 3; 119 } 120 // Solve 121 status = aoclsparse_zsymgs_mv(trans, A, descr_a, alpha, &b[0], &x[0], &y[0]); 122 if(status != aoclsparse_status_success) 123 { 124 std::cerr << "Error returned from aoclsparse_zsymgs, status = " << status << "." 125 << std::endl; 126 return 3; 127 } 128 // Print and check the result 129 std::cout << "Solving A x = alpha b" << std::endl; 130 std::cout << " where x and b are dense vectors" << std::endl; 131 std::cout << " Solution vector x = " << std::endl; 132 std::cout << std::fixed; 133 std::cout.precision(1); 134 ok = true; 135 for(int i = 0; i < m; ++i) 136 { 137 oki = std::abs(x[i].real - xref[i].real) <= exp_tol 138 && std::abs(x[i].imag - xref[i].imag) <= exp_tol; 139 std::cout << "(" << x[i].real << ", " << x[i].imag << "i) " << (oki ? " " : "! "); 140 ok &= oki; 141 } 142 std::cout << std::endl; 143 std::cout << " Product vector x = " << std::endl; 144 for(int i = 0; i < m; ++i) 145 { 146 oki = std::abs(y[i].real - yref[i].real) <= exp_tol 147 && std::abs(y[i].imag - yref[i].imag) <= exp_tol; 148 std::cout << "(" << y[i].real << ", " << y[i].imag << "i) " << (oki ? " " : "! "); 149 ok &= oki; 150 } 151 std::cout << std::endl; 152 // Destroy the aoclsparse memory 153 aoclsparse_destroy_mat_descr(descr_a); 154 aoclsparse_destroy(&A); 155 156 return ok ? 0 : 5; 157}
- Parameters:
trans – [in] matrix operation to perform on \(A\). Possible values are aoclsparse_operation_none, aoclsparse_operation_transpose, and aoclsparse_operation_conjugate_transpose.
A – [in] sparse matrix \(A\) of size \(m\).
descr – [in] descriptor of the sparse matrix \(A\).
alpha – [in] scalar \(\alpha\).
b – [in] dense vector, of size \(m\).
x – [out] solution vector \(x,\) dense vector of size \(m\).
y – [out] sparse-product vector \(y,\) dense vector of size \(m\).
- Return values:
aoclsparse_status_success – indicates that the operation completed successfully.
aoclsparse_status_invalid_size – informs that either
m,nornnzis invalid. The error code also informs if the given sparse matrix \(A\) is not square.aoclsparse_status_invalid_value – informs that either
base,trans, matrix typedescr->typeor fill modedescr->fill_modeis invalid. If the sparse matrix \(A\) is not of full rank, the error code is returned to indicate that the linear system cannot be solved.aoclsparse_status_invalid_pointer – informs that either
descr,A,b,xorypointer is invalid.aoclsparse_status_not_implemented – this error occurs when the provided matrix’s aoclsparse_fill_mode is aoclsparse_diag_type_unit or the input format is not aoclsparse_csr_mat, or when aoclsparse_matrix_type is aoclsparse_matrix_type_general and
transis aoclsparse_operation_conjugate_transpose.