Documentation 6b54b78464
Loading...
Searching...
No Matches
CSysMatrix.inl
Go to the documentation of this file.
1/*!
2 * \file CSysMatrix.inl
3 * \brief Inline subroutines of the <i>CSysMatrix.hpp</i> file.
4 * \note These are the "private" inlines, they are not needed outside
5 * of the .cpp file and so they are hidden to avoid triggering
6 * recompilation of other units when changes are made here.
7 * \author F. Palacios, A. Bueno, T. Economon, P. Gomes
8 * \version 8.5.0 "Harrier"
9 *
10 * SU2 Project Website: https://su2code.github.io
11 *
12 * The SU2 Project is maintained by the SU2 Foundation
13 * (http://su2foundation.org)
14 *
15 * Copyright 2012-2026, SU2 Contributors (cf. AUTHORS.md)
16 *
17 * SU2 is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License as published by the Free Software Foundation; either
20 * version 2.1 of the License, or (at your option) any later version.
21 *
22 * SU2 is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * Lesser General Public License for more details.
26 *
27 * You should have received a copy of the GNU Lesser General Public
28 * License along with SU2. If not, see <http://www.gnu.org/licenses/>.
29 */
30
31#pragma once
32
33#include "CSysMatrix.hpp"
34
35template <class ScalarType>
36FORCEINLINE ScalarType* CSysMatrix<ScalarType>::GetBlock_ILUMatrix(unsigned long block_i, unsigned long block_j) {
37 if (block_i == block_j) return &ilu.d[block_i * nVar * nVar];
38 const auto* __restrict row_ptr = block_j < block_i ? ilu.row_ptr_l : ilu.row_ptr_u;
39 const auto* __restrict col_ind = block_j < block_i ? ilu.col_ind_l : ilu.col_ind_u;
40 auto* __restrict vals = block_j < block_i ? ilu.l : ilu.u;
41 for (auto k = row_ptr[block_i]; k < row_ptr[block_i + 1]; ++k) {
42 if (col_ind[k] == block_j) return vals + k * nVar * nVar;
43 }
44 return nullptr;
45}
46
47namespace {
48
49template <class T, bool alpha, bool beta, bool transp>
50FORCEINLINE void gemv_impl(unsigned long n, unsigned long m, const T* a, const T* b, T* c) {
51 /*---
52 This is a templated version of GEMV with the constants as boolean
53 template parameters so that they can be optimized away at compilation.
54 This is still the traditional "row dot vector" method.
55 ---*/
56 if (!transp) {
57 for (auto i = 0ul; i < n; i++) {
58 if (!beta) c[i] = 0.0;
59 for (auto j = 0ul; j < m; j++) c[i] += (alpha ? 1 : -1) * a[i * m + j] * b[j];
60 }
61 } else {
62 if (!beta)
63 for (auto j = 0ul; j < m; j++) c[j] = 0.0;
64 for (auto i = 0ul; i < n; i++)
65 for (auto j = 0ul; j < m; j++) c[j] += (alpha ? 1 : -1) * a[i * n + j] * b[i];
66 }
67}
68
69template <class T>
70FORCEINLINE void gemm_impl(unsigned long n, const T* a, const T* b, T* c) {
71 /*--- Same deal as for GEMV but here only the type is templated. ---*/
72 unsigned long i, j, k;
73 for (i = 0; i < n; i++) {
74 for (j = 0; j < n; j++) {
75 c[i * n + j] = 0.0;
76 for (k = 0; k < n; k++) c[i * n + j] += a[i * n + k] * b[k * n + j];
77 }
78 }
79}
80} // namespace
81
82#define __MATVECPROD_SIGNATURE__(TYPE, NAME) \
83 FORCEINLINE void CSysMatrix<TYPE>::NAME(const TYPE* matrix, const TYPE* vector, TYPE* product) const
84
85#define MATVECPROD_SIGNATURE(NAME) \
86 template <class ScalarType> \
87 __MATVECPROD_SIGNATURE__(ScalarType, NAME)
88
89#if !defined(USE_MKL)
90MATVECPROD_SIGNATURE(MatrixVectorProduct) {
91 /*---
92 Without MKL (default) picture copying the body of gemv_impl
93 here and resolving the conditionals at compilation.
94 ---*/
95 gemv_impl<ScalarType, true, false, false>(nVar, nEqn, matrix, vector, product);
96}
97
98MATVECPROD_SIGNATURE(MatrixVectorProductAdd) {
99 gemv_impl<ScalarType, true, true, false>(nVar, nEqn, matrix, vector, product);
100}
101
102MATVECPROD_SIGNATURE(MatrixVectorProductSub) {
103 gemv_impl<ScalarType, false, true, false>(nVar, nEqn, matrix, vector, product);
104}
105
106template <class ScalarType>
107FORCEINLINE void CSysMatrix<ScalarType>::MatrixMatrixProduct(const ScalarType* matrix_a, const ScalarType* matrix_b,
108 ScalarType* product) const {
109 gemm_impl<ScalarType>(nVar, matrix_a, matrix_b, product);
110}
111#else
112MATVECPROD_SIGNATURE(MatrixVectorProduct) {
113 /*--- With MKL we use the just-in-time kernels instead of the naive implementation. ---*/
114 MatrixVectorProductKernelBetaZero(MatrixVectorProductJitterBetaZero, const_cast<ScalarType*>(vector),
115 const_cast<ScalarType*>(matrix), product);
116}
117
118MATVECPROD_SIGNATURE(MatrixVectorProductAdd) {
119 MatrixVectorProductKernelBetaOne(MatrixVectorProductJitterBetaOne, const_cast<ScalarType*>(vector),
120 const_cast<ScalarType*>(matrix), product);
121}
122
123MATVECPROD_SIGNATURE(MatrixVectorProductSub) {
124 MatrixVectorProductKernelAlphaMinusOne(MatrixVectorProductJitterAlphaMinusOne, const_cast<ScalarType*>(vector),
125 const_cast<ScalarType*>(matrix), product);
126}
127
128template <class ScalarType>
129FORCEINLINE void CSysMatrix<ScalarType>::MatrixMatrixProduct(const ScalarType* matrix_a, const ScalarType* matrix_b,
130 ScalarType* product) const {
131 MatrixMatrixProductKernel(MatrixMatrixProductJitter, const_cast<ScalarType*>(matrix_a),
132 const_cast<ScalarType*>(matrix_b), product);
133}
134#endif
135
136#undef MATVECPROD_SIGNATURE
137#undef __MATVECPROD_SIGNATURE__
138
139template <class ScalarType>
140FORCEINLINE void CSysMatrix<ScalarType>::GaussElimination(unsigned long block_i, ScalarType* rhs) const {
141 /*--- Copy block, as the algorithm modifies the matrix ---*/
142 ScalarType block[MAXNVAR * MAXNVAR];
143 MatrixCopy(&mat.d[block_i * nVar * nVar], block);
144 GaussElimination(block, rhs);
145}
146
147template <class ScalarType>
148FORCEINLINE void CSysMatrix<ScalarType>::QuantizedGaussElimination(unsigned long block_i, ScalarType* rhs) const {
149 ScalarType block[MAXNVAR * MAXNVAR];
150 const QuantScaleType* __restrict qs = &q_scale.d[block_i * nVar];
151 const QuantType* __restrict qv = &q_blocks.d[block_i * nVar * nVar];
152 for (auto r = 0ul; r < nVar; ++r) {
153 const float row_scale = DecodeQuantScale(qs[r]);
154 for (auto c = 0ul; c < nVar; ++c) block[r * nVar + c] = static_cast<ScalarType>(qv[r * nVar + c] * row_scale);
155 }
156 GaussElimination(block, rhs);
157}
158
159template <class ScalarType>
160FORCEINLINE void CSysMatrix<ScalarType>::InverseDiagonalBlock(unsigned long block_i, ScalarType* invBlock) const {
161 /*--- Copy block, as the algorithm modifies the matrix ---*/
162 ScalarType block[MAXNVAR * MAXNVAR];
163 MatrixCopy(&mat.d[block_i * nVar * nVar], block);
164
165 MatrixInverse(block, invBlock);
166}
167
168template <class ScalarType>
169FORCEINLINE const ScalarType* CSysMatrix<ScalarType>::InvertDiagonalBlockILUMatrix(unsigned long block_i) {
170 /*--- Copy block, as the algorithm modifies the matrix ---*/
171 auto* Uii = &ilu.d[block_i * nVar * nVar];
172 ScalarType block[MAXNVAR * MAXNVAR];
173 MatrixCopy(Uii, block);
174 MatrixInverse(block, Uii);
175 return Uii;
176}
177
178template <class ScalarType>
179FORCEINLINE void CSysMatrix<ScalarType>::QuantizedMatVecAdd(const QuantScaleType* __restrict qs,
180 const QuantType* __restrict qv,
181 const ScalarType* __restrict vec,
182 ScalarType* __restrict prod) const {
183 for (auto r = 0ul; r < nVar; ++r) {
184 const float row_scale = DecodeQuantScale(qs[r]);
185 auto sum = ScalarType(0);
186 for (auto c = 0ul; c < nVar; ++c) sum += qv[r * nVar + c] * vec[c];
187 prod[r] += row_scale * sum;
188 }
189}
190
191template <class ScalarType>
193 ScalarType* prod) const {
194 for (auto iVar = 0ul; iVar < nVar; iVar++) prod[iVar] = 0.0;
195
196 for (auto k = mat.row_ptr_l[row_i]; k < mat.row_ptr_l[row_i + 1]; k++) {
197 MatrixVectorProductAdd(&mat.l[k * nVar * nEqn], &vec[mat.col_ind_l[k] * nEqn], prod);
198 }
199 MatrixVectorProductAdd(&mat.d[row_i * nVar * nEqn], &vec[row_i * nEqn], prod);
200
201 for (auto k = mat.row_ptr_u[row_i]; k < mat.row_ptr_u[row_i + 1]; k++) {
202 MatrixVectorProductAdd(&mat.u[k * nVar * nEqn], &vec[mat.col_ind_u[k] * nEqn], prod);
203 }
204}
205
206template <class ScalarType>
208 unsigned long col_ub, ScalarType* prod) const {
209 for (auto iVar = 0ul; iVar < nVar; iVar++) prod[iVar] = 0.0;
210
211 for (auto index = mat.row_ptr_u[row_i]; index < mat.row_ptr_u[row_i + 1]; index++) {
212 auto col_j = mat.col_ind_u[index];
213
214 if (col_j < col_ub || col_j >= nPointDomain) {
215 MatrixVectorProductAdd(&mat.u[index * nVar * nEqn], &vec[col_j * nEqn], prod);
216 }
217 }
218}
219
220template <class ScalarType>
222 unsigned long col_lb, ScalarType* prod) const {
223 for (auto iVar = 0ul; iVar < nVar; iVar++) prod[iVar] = 0.0;
224
225 for (auto index = mat.row_ptr_l[row_i]; index < mat.row_ptr_l[row_i + 1]; index++) {
226 auto col_j = mat.col_ind_l[index];
227 if (col_j >= col_lb) {
228 MatrixVectorProductAdd(&mat.l[index * nVar * nEqn], &vec[col_j * nEqn], prod);
229 }
230 }
231}
232
233template <class ScalarType>
235 ScalarType* prod) const {
236 MatrixVectorProduct(&mat.d[row_i * nVar * nEqn], &vec[row_i * nEqn], prod);
237}
238
239template <class ScalarType>
241 ScalarType* prod) const {
242 for (auto iVar = 0ul; iVar < nVar; iVar++) prod[iVar] = 0.0;
243
244 for (auto k = mat.row_ptr_l[row_i]; k < mat.row_ptr_l[row_i + 1]; k++) {
245 QuantizedMatVecAdd(&q_scale.l[k * nVar], &q_blocks.l[k * nVar * nEqn], &vec[mat.col_ind_l[k] * nEqn], prod);
246 }
247 QuantizedMatVecAdd(&q_scale.d[row_i * nVar], &q_blocks.d[row_i * nVar * nEqn], &vec[row_i * nEqn], prod);
248
249 for (auto k = mat.row_ptr_u[row_i]; k < mat.row_ptr_u[row_i + 1]; k++) {
250 QuantizedMatVecAdd(&q_scale.u[k * nVar], &q_blocks.u[k * nVar * nEqn], &vec[mat.col_ind_u[k] * nEqn], prod);
251 }
252}
253
254template <class ScalarType>
256 unsigned long col_ub, ScalarType* prod) const {
257 for (auto iVar = 0ul; iVar < nVar; iVar++) prod[iVar] = 0.0;
258
259 for (auto index = mat.row_ptr_u[row_i]; index < mat.row_ptr_u[row_i + 1]; index++) {
260 auto col_j = mat.col_ind_u[index];
261 if (col_j < col_ub || col_j >= nPointDomain) {
262 QuantizedMatVecAdd(&q_scale.u[index * nVar], &q_blocks.u[index * nVar * nEqn], &vec[col_j * nEqn], prod);
263 }
264 }
265}
266
267template <class ScalarType>
269 unsigned long col_lb, ScalarType* prod) const {
270 for (auto iVar = 0ul; iVar < nVar; iVar++) prod[iVar] = 0.0;
271
272 for (auto index = mat.row_ptr_l[row_i]; index < mat.row_ptr_l[row_i + 1]; index++) {
273 auto col_j = mat.col_ind_l[index];
274 if (col_j >= col_lb) {
275 QuantizedMatVecAdd(&q_scale.l[index * nVar], &q_blocks.l[index * nVar * nEqn], &vec[col_j * nEqn], prod);
276 }
277 }
278}
279
280template <class ScalarType>
282 unsigned long row_i, ScalarType* prod) const {
283 for (auto iVar = 0ul; iVar < nVar; iVar++) prod[iVar] = 0.0;
284 QuantizedMatVecAdd(&q_scale.d[row_i * nVar], &q_blocks.d[row_i * nVar * nEqn], &vec[row_i * nEqn], prod);
285}
Declaration of the block-sparse matrix class. The implemtation is in CSysMatrix.cpp.
float DecodeQuantScale(uint8_t e) noexcept
Reconstruct the float row-scale from a stored uint8 binary exponent. e is stored already biased,...
Definition CSysMatrix.hpp:121
#define MATVECPROD_SIGNATURE(NAME)
Definition CSysMatrix.inl:85
Main class for defining block-compressed-row-storage sparse matrices.
Definition CSysMatrix.hpp:256
Class for holding and manipulating vectors needed by linear solvers.
Definition CSysVector.hpp:195
#define FORCEINLINE
Definition code_config.hpp:44
void MatrixInverse(unsigned long nVar, ScalarType *matrix, ScalarType *inverse)
Invert the nVar by nVar dense matrix matrix into inverse via Gauss-Jordan elimination with partial pi...
Definition CMatrixInverse.hpp:57