31#include "../CConfig.hpp"
32#include "../code_config.hpp"
35#include "../toolboxes/graph_toolbox.hpp"
44#if defined(HAVE_MKL) && !defined(CODI_FORWARD_TYPE)
47#error Could not determine the MKL version
50#if __INTEL_MKL__ >= 2019
56#if defined(__INTEL_COMPILER) && defined(MKL_DIRECT_CALL_SEQ) && !defined(CODI_REVERSE_TYPE)
60struct mkl_jit_wrapper {
61 using gemm_t = dgemm_jit_kernel_t;
62 template <
class... Ts>
63 static void create_gemm(Ts&&... args) {
64 mkl_jit_create_dgemm(args...);
66 static gemm_t get_gemm(
void* jitter) {
return mkl_jit_get_dgemm_ptr(jitter); }
69struct mkl_jit_wrapper<float> {
70 using gemm_t = sgemm_jit_kernel_t;
71 template <
class... Ts>
72 static void create_gemm(Ts&&... args) {
73 mkl_jit_create_sgemm(args...);
75 static gemm_t get_gemm(
void* jitter) {
return mkl_jit_get_sgemm_ptr(jitter); }
78#warning The current version of MKL does not support JIT gemm kernels
122 const uint32_t bits =
static_cast<uint32_t
>(e) << 23;
124 return __uint_as_float(bits);
127 memcpy(&scale, &bits,
sizeof(bits));
145 unsigned long r)
noexcept {
147#define EQR_PASSIVE(ROW, COL) f(ROW, COL)
149#define EQR_PASSIVE(ROW, COL) SU2_TYPE::PassiveValue(f(ROW, COL))
153 constexpr uint32_t eps_bits = 0x34000000u;
154 uint32_t max_abs_bits = eps_bits;
155 for (
auto c = 0ul; c < nVar; ++c) {
156 const auto fv =
static_cast<float>(
EQR_PASSIVE(r, c));
158 const uint32_t fb = __float_as_uint(fv);
161 memcpy(&fb, &fv,
sizeof(fb));
165 max_abs_bits = max(max_abs_bits, fb & 0x7F800000u);
171 qs =
static_cast<uint8_t
>((max_abs_bits >> 23) - 6);
175 const uint32_t inv_bits = 0x82000000u - max_abs_bits;
177 const float inv_rscale = __uint_as_float(inv_bits);
180 memcpy(&inv_rscale, &inv_bits,
sizeof(inv_rscale));
182 for (
auto c = 0ul; c < nVar; ++c) {
184 const float t = max(-128.f, min(127.f,
static_cast<float>(
EQR_PASSIVE(r, c) * inv_rscale)));
185 qv[c] =
static_cast<int8_t
>(t + copysignf(0.5f, t));
197 unsigned long nVar)
noexcept {
198 for (
auto r = 0ul; r < nVar; ++r)
EncodeQuantRow(f, qs[r], qv + r * nVar, nVar, r);
207template <
class ScalarType>
209 using QuantType = std::conditional_t<std::is_const_v<ScalarType>,
const int8_t, int8_t>;
210 using QuantScaleType = std::conditional_t<std::is_const_v<ScalarType>,
const uint8_t, uint8_t>;
212 ScalarType*
ptr =
nullptr;
218 explicit operator bool()
const {
return ptr ||
qs; }
221 std::remove_const_t<ScalarType>
operator()(
unsigned long i,
unsigned long j)
const {
222 using T = std::remove_const_t<ScalarType>;
234 template <
bool Overwrite,
class F,
class S = ScalarType, su2enable_if<!std::is_const_v<S>> = 0>
237 for (
auto i = 0ul; i <
nVar; ++i)
238 for (
auto j = 0ul; j <
nVar; ++j) {
239 if constexpr (Overwrite)
244 }
else if constexpr (Overwrite) {
255template <
class ScalarType>
265 enum :
size_t { MAXNVAR = 20 };
267 enum { OMP_MAX_SIZE_L = 8192 };
268 enum { OMP_MAX_SIZE_H = 512 };
269 enum { OMP_MIN_SIZE = 32 };
270 unsigned long omp_light_size;
271 unsigned long omp_heavy_size;
272 unsigned long omp_num_parts;
273 unsigned long* omp_partitions;
275 unsigned long nPoint;
276 unsigned long nPointDomain;
295 const su2uint* row_ptr_l =
nullptr;
296 const su2uint* col_ind_l =
nullptr;
297 const su2uint* row_ptr_u =
nullptr;
298 const su2uint* col_ind_u =
nullptr;
299 unsigned long nnz_l = 0;
300 unsigned long nnz_u = 0;
306 LDU<ScalarType> gpu_ilu;
307 ScalarType* d_invM =
nullptr;
310 using QuantType = int8_t;
313 using QuantScaleType = uint8_t;
321#ifndef CODI_REVERSE_TYPE
322 bool quantized_mode =
false;
324 static constexpr bool quantized_mode =
false;
330 LDU<QuantScaleType> q_scale;
332 LDU<QuantType> q_blocks;
335 LDU<QuantScaleType> d_q_scale;
336 LDU<QuantType> d_q_blocks;
338 bool useCuda =
false;
342 bool jacobi_on_device =
false;
354 unsigned short ilu_fill_in;
372 unsigned short ilu_gpu_sweeps = 1;
374 vector<su2uint> ilu_color_ptr;
375 su2uint* d_ilu_color_idx =
nullptr;
377 vector<su2uint> precond_level_ptr;
378 su2uint* d_precond_level_idx =
nullptr;
384 mutable struct CUgraphExec_st* ilu_build_graph_exec =
nullptr;
393 mutable bool ilu_can_refine =
true;
394 mutable struct CUgraphExec_st* precond_fwd_graph_exec =
nullptr;
395 mutable struct CUgraphExec_st* precond_bwd_graph_exec =
nullptr;
396 mutable const ScalarType* precond_fwd_graph_vec =
nullptr;
402 mutable ScalarType* precond_fwd_graph_prod =
nullptr;
403 mutable ScalarType* precond_bwd_graph_prod =
nullptr;
416 mutable struct CUstream_st* aux_stream =
nullptr;
417 mutable struct CUevent_st* htd_event =
nullptr;
422 mutable vector<vector<const ScalarType*>>
424 mutable vector<vector<ScalarType>>
426 mutable vector<vector<ScalarType>>
430 using gemm_t =
typename mkl_jit_wrapper<ScalarType>::gemm_t;
431 void* MatrixMatrixProductJitter;
432 gemm_t MatrixMatrixProductKernel;
433 void* MatrixVectorProductJitterBetaZero;
434 gemm_t MatrixVectorProductKernelBetaZero;
435 void* MatrixVectorProductJitterBetaOne;
436 gemm_t MatrixVectorProductKernelBetaOne;
437 void* MatrixVectorProductJitterAlphaMinusOne;
439 gemm_t MatrixVectorProductKernelAlphaMinusOne;
450 template <class DstType, class SrcType, su2enable_if<std::is_arithmetic<DstType>::value> = 0>
451 FORCEINLINE static DstType ActiveAssign(
const SrcType& val) {
455 template <class DstType, class SrcType, su2enable_if<!std::is_arithmetic<DstType>::value> = 0>
456 FORCEINLINE static DstType ActiveAssign(
const SrcType& val) {
463 template <
class SrcType>
464 FORCEINLINE static ScalarType PassiveAssign(
const SrcType& val) {
474 void MatrixVectorProduct(
const ScalarType* matrix,
const ScalarType* vector, ScalarType* product)
const;
482 void MatrixVectorProductAdd(
const ScalarType* matrix,
const ScalarType* vector, ScalarType* product)
const;
490 void MatrixVectorProductSub(
const ScalarType* matrix,
const ScalarType* vector, ScalarType* product)
const;
495 void MatrixMatrixProduct(
const ScalarType* matrix_a,
const ScalarType* matrix_b, ScalarType* product)
const;
500 FORCEINLINE void VectorSubtraction(
const ScalarType* a,
const ScalarType* b, ScalarType* c)
const {
501 for (
unsigned long iVar = 0; iVar < nVar; iVar++) c[iVar] = a[iVar] - b[iVar];
507 FORCEINLINE void MatrixSubtraction(
const ScalarType* a,
const ScalarType* b, ScalarType* c)
const {
509 for (
unsigned long iVar = 0; iVar < nVar * nEqn; iVar++) c[iVar] = a[iVar] - b[iVar];
515 FORCEINLINE void MatrixCopy(
const ScalarType* src, ScalarType* dst)
const {
517 for (
auto iVar = 0ul; iVar < nVar * nEqn; ++iVar) dst[iVar] = src[iVar];
523 FORCEINLINE void ZeroMatrix(ScalarType* mat)
const {
525 for (
auto iVar = 0ul; iVar < nVar * nEqn; ++iVar) mat[iVar] = 0;
533 void GaussElimination(ScalarType* matrix, ScalarType* vec)
const;
540 void MatrixInverse(ScalarType* matrix, ScalarType* inverse)
const;
548 inline void GaussElimination(
unsigned long block_i, ScalarType* rhs)
const;
555 inline void InverseDiagonalBlock(
unsigned long block_i, ScalarType* invBlock)
const;
562 inline const ScalarType* InvertDiagonalBlockILUMatrix(
unsigned long block_i);
568 inline ScalarType* GetBlock_ILUMatrix(
unsigned long block_i,
unsigned long block_j);
578 ScalarType* prod)
const;
588 ScalarType* prod)
const;
596 inline void DiagonalProduct(
const CSysVector<ScalarType>& vec,
unsigned long row_i, ScalarType* prod)
const;
613 inline void QuantizedMatVecAdd(
const QuantScaleType* qs,
const QuantType* qv,
const ScalarType* vec,
614 ScalarType* prod)
const;
618 inline void QuantizeBlock(
const ScalarType* blk, QuantScaleType* qs, QuantType* qv)
const {
619 EncodeQuantBlock([&](
unsigned long r,
unsigned long c) {
return blk[r * nVar + c]; }, qs, qv, nVar);
623 inline void QuantizedRowProduct(
const CSysVector<ScalarType>& vec,
unsigned long row_i, ScalarType* prod)
const;
626 inline void QuantizedUpperProduct(
const CSysVector<ScalarType>& vec,
unsigned long row_i,
unsigned long col_ub,
627 ScalarType* prod)
const;
630 inline void QuantizedLowerProduct(
const CSysVector<ScalarType>& vec,
unsigned long row_i,
unsigned long col_lb,
631 ScalarType* prod)
const;
634 inline void QuantizedDiagonalProduct(
const CSysVector<ScalarType>& vec,
unsigned long row_i, ScalarType* prod)
const;
638 inline void QuantizedGaussElimination(
unsigned long block_i, ScalarType* rhs)
const;
652 void QuantizeDiagonalBlocksGPU();
658 void BuildJacobiPreconditionerGPU();
670 void BuildILUPreconditionerGPU();
680 void BuildLU_SGSPreconditionerGPU();
729 void Initialize(
unsigned long npoint,
unsigned long npointdomain,
unsigned short nvar,
unsigned short neqn,
730 bool EdgeConnect,
CGeometry* geometry,
const CConfig* config,
bool needTranspPtr =
false,
731 bool allow_quant =
false, std::optional<unsigned short> override_prec = std::nullopt);
761 if (block_i == block_j)
return &mat.d[block_i * nVar * nEqn];
762 if (block_j < block_i) {
763 for (
auto index = mat.row_ptr_l[block_i]; index < mat.row_ptr_l[block_i + 1]; ++index)
764 if (mat.col_ind_l[index] == block_j)
return &mat.l[index * nVar * nEqn];
767 for (
auto index = mat.row_ptr_u[block_i]; index < mat.row_ptr_u[block_i + 1]; ++index)
768 if (mat.col_ind_u[index] == block_j)
return &mat.u[index * nVar * nEqn];
777 return const_cast<ScalarType*
>(const_this.
GetBlock(block_i, block_j));
786#define GET_BLOCK_VIEW_IMPL \
787 if (!quantized_mode || block_i == block_j) { \
788 return {GetBlock(block_i, block_j), nullptr, nullptr, nVar}; \
790 if (block_j < block_i) { \
791 for (auto k = mat.row_ptr_l[block_i]; k < mat.row_ptr_l[block_i + 1]; ++k) \
792 if (mat.col_ind_l[k] == block_j) return {nullptr, &q_scale.l[k * nVar], &q_blocks.l[k * nVar * nVar], nVar}; \
794 for (auto k = mat.row_ptr_u[block_i]; k < mat.row_ptr_u[block_i + 1]; ++k) \
795 if (mat.col_ind_u[k] == block_j) return {nullptr, &q_scale.u[k * nVar], &q_blocks.u[k * nVar * nVar], nVar}; \
806#undef GET_BLOCK_VIEW_IMPL
819 template <
bool Overwrite = true,
class MatrixType>
820 inline void SetBlock(
unsigned long block_i,
unsigned long block_j, MatrixType& val_block,
821 std::decay_t<typename MatrixType::Scalar> alpha = 1.0) {
824 view.template apply<Overwrite>(
825 [&](
unsigned long i,
unsigned long j) {
return PassiveAssign(alpha * val_block(i, j)); });
831 template <bool Overwrite = true, class OtherType, su2enable_if<!is_pointer<OtherType>::value> = 0>
832 inline void SetBlock(
unsigned long block_i,
unsigned long block_j,
const OtherType* val_block,
833 std::decay_t<OtherType> alpha = 1.0) {
836 view.template apply<Overwrite>(
837 [&](
unsigned long i,
unsigned long j) {
return PassiveAssign(alpha * val_block[i * nEqn + j]); });
843 template <
bool Overwrite = true,
class OtherType>
844 inline void SetBlock(
unsigned long block_i,
unsigned long block_j,
const OtherType*
const* val_block,
845 std::decay_t<OtherType> alpha = 1.0) {
848 view.template apply<Overwrite>(
849 [&](
unsigned long i,
unsigned long j) {
return PassiveAssign(alpha * val_block[i][j]); });
859 template <
class T,
class OtherType = ScalarType>
860 inline void AddBlock(
unsigned long block_i,
unsigned long block_j,
const T& val_block, OtherType alpha = 1.0) {
861 SetBlock<false>(block_i, block_j, val_block, alpha);
871 inline void SubtractBlock(
unsigned long block_i,
unsigned long block_j,
const T& val_block) {
872 AddBlock(block_i, block_j, val_block, -1);
883 inline void GetBlocks(
unsigned long iEdge,
unsigned long iPoint,
unsigned long jPoint, ScalarType*& bii,
884 ScalarType*& bij, ScalarType*& bji, ScalarType*& bjj) {
885 const auto blkSz = nVar * nEqn;
886 bii = &mat.d[iPoint * blkSz];
887 bjj = &mat.d[jPoint * blkSz];
888 bij = &mat.u[iEdge * blkSz];
889 bji = &mat.l[edge_ptr_l[iEdge] * blkSz];
902 template <
bool OverwriteOffDiag = false,
class MatrixType,
class OtherType = ScalarType>
903 inline void UpdateBlocks(
unsigned long iEdge,
unsigned long iPoint,
unsigned long jPoint,
const MatrixType& block_i,
904 const MatrixType& block_j, OtherType scale = 1) {
905 const auto blkSz = nVar * nEqn;
906 auto* bii = &mat.d[iPoint * blkSz];
907 auto* bjj = &mat.d[jPoint * blkSz];
909 unsigned long iVar, jVar, offset = 0;
911 if (quantized_mode) {
912 assert(OverwriteOffDiag);
914 ScalarType bij_buf[MAXNVAR * MAXNVAR], bji_buf[MAXNVAR * MAXNVAR];
915 for (iVar = 0; iVar < nVar; iVar++)
916 for (jVar = 0; jVar < nEqn; jVar++, ++offset) {
917 bii[offset] += PassiveAssign(block_i[iVar][jVar] * scale);
918 bjj[offset] -= PassiveAssign(block_j[iVar][jVar] * scale);
919 bij_buf[offset] = PassiveAssign(block_j[iVar][jVar] * scale);
920 bji_buf[offset] = -PassiveAssign(block_i[iVar][jVar] * scale);
922 QuantizeBlock(bij_buf, &q_scale.u[iEdge * nVar], &q_blocks.u[iEdge * blkSz]);
923 const auto k_l = edge_ptr_l[iEdge];
924 QuantizeBlock(bji_buf, &q_scale.l[k_l * nVar], &q_blocks.l[k_l * blkSz]);
928 auto* bij = &mat.u[iEdge * blkSz];
929 auto* bji = &mat.l[edge_ptr_l[iEdge] * blkSz];
930 for (iVar = 0; iVar < nVar; iVar++) {
931 for (jVar = 0; jVar < nEqn; jVar++) {
932 bii[offset] += PassiveAssign(block_i[iVar][jVar] * scale);
933 bjj[offset] -= PassiveAssign(block_j[iVar][jVar] * scale);
934 if constexpr (OverwriteOffDiag) {
935 bij[offset] = PassiveAssign(block_j[iVar][jVar] * scale);
936 bji[offset] = -PassiveAssign(block_i[iVar][jVar] * scale);
938 bij[offset] += PassiveAssign(block_j[iVar][jVar] * scale);
939 bji[offset] -= PassiveAssign(block_i[iVar][jVar] * scale);
949 template <
class MatrixType>
950 inline void UpdateBlocksSub(
unsigned long iEdge,
unsigned long iPoint,
unsigned long jPoint,
951 const MatrixType& block_i,
const MatrixType& block_j) {
952 UpdateBlocks<false, MatrixType, ScalarType>(iEdge, iPoint, jPoint, block_i, block_j, -1);
959 template <
class MatTypeSIMD,
size_t N,
class I,
class F = ScalarType>
961 const MatTypeSIMD& block_i,
const MatTypeSIMD& block_j,
simd::Array<F, N> mask = 1) {
962 static_assert(MatTypeSIMD::StaticSize,
"This method requires static size blocks.");
963 static_assert(MatTypeSIMD::IsRowMajor,
"Block storage is not compatible with matrix.");
964 constexpr size_t blkSz = MatTypeSIMD::StaticSize;
965 assert(blkSz == nVar * nEqn);
966 constexpr size_t nVar = MatTypeSIMD::StaticNRows;
970 ScalarType blk_i[N][blkSz], blk_j[N][blkSz];
972 for (
size_t i = 0; i < blkSz; ++i) {
974 for (
size_t k = 0; k < N; ++k) {
975 blk_i[k][i] = PassiveAssign(-mask[k] * block_i.data()[i][k]);
976 blk_j[k][i] = PassiveAssign(mask[k] * block_j.data()[i][k]);
981 for (
size_t k = 0; k < N; ++k) {
982 if (mask[k] == 0)
continue;
984 auto bii = &mat.d[iPoint[k] * blkSz];
985 auto bjj = &mat.d[jPoint[k] * blkSz];
987 if (quantized_mode) {
989 for (
size_t i = 0; i < blkSz; ++i) {
990 bii[i] -= blk_i[k][i];
991 bjj[i] -= blk_j[k][i];
993 EncodeQuantBlock([&, k](
unsigned long r,
unsigned long c) {
return blk_j[k][r * nVar + c]; },
994 &q_scale.u[iEdge[k] * nVar], &q_blocks.u[iEdge[k] * blkSz], nVar);
995 const auto k_l = edge_ptr_l[iEdge[k]];
996 EncodeQuantBlock([&, k](
unsigned long r,
unsigned long c) {
return blk_i[k][r * nVar + c]; },
997 &q_scale.l[k_l * nVar], &q_blocks.l[k_l * blkSz], nVar);
999 auto bij = &mat.u[iEdge[k] * blkSz];
1000 auto bji = &mat.l[edge_ptr_l[iEdge[k]] * blkSz];
1004 for (
size_t i = 0; i < blkSz; ++i) {
1005 bii[i] -= blk_i[k][i];
1006 bjj[i] -= blk_j[k][i];
1007 bij[i] = blk_j[k][i];
1008 bji[i] = blk_i[k][i];
1024 template <
class MatrixType,
class OtherType = ScalarType,
bool Overwrite = true>
1025 inline void SetBlocks(
unsigned long iEdge,
const MatrixType& block_i,
const MatrixType& block_j,
1026 OtherType scale = 1) {
1027 const auto blkSz = nVar * nEqn;
1028 unsigned long iVar, jVar, offset = 0;
1030 if (quantized_mode) {
1032 ScalarType bij_buf[MAXNVAR * MAXNVAR], bji_buf[MAXNVAR * MAXNVAR];
1033 for (iVar = 0; iVar < nVar; iVar++)
1034 for (jVar = 0; jVar < nEqn; jVar++, ++offset) {
1035 bij_buf[offset] = PassiveAssign(block_j[iVar][jVar] * scale);
1036 bji_buf[offset] = -PassiveAssign(block_i[iVar][jVar] * scale);
1038 QuantizeBlock(bij_buf, &q_scale.u[iEdge * nVar], &q_blocks.u[iEdge * blkSz]);
1039 const auto k_l = edge_ptr_l[iEdge];
1040 QuantizeBlock(bji_buf, &q_scale.l[k_l * nVar], &q_blocks.l[k_l * blkSz]);
1044 ScalarType* bij = &mat.u[iEdge * blkSz];
1045 ScalarType* bji = &mat.l[edge_ptr_l[iEdge] * blkSz];
1046 for (iVar = 0; iVar < nVar; iVar++) {
1047 for (jVar = 0; jVar < nEqn; jVar++) {
1048 bij[offset] = (Overwrite ? ScalarType(0) : bij[offset]) + PassiveAssign(block_j[iVar][jVar] * scale);
1049 bji[offset] = (Overwrite ? ScalarType(0) : bji[offset]) - PassiveAssign(block_i[iVar][jVar] * scale);
1058 template <
class MatrixType,
class OtherType = ScalarType>
1059 inline void UpdateBlocks(
unsigned long iEdge,
const MatrixType& block_i,
const MatrixType& block_j,
1060 OtherType scale = 1) {
1061 SetBlocks<MatrixType, OtherType, false>(iEdge, block_i, block_j, scale);
1067 template <
class MatrixType>
1068 inline void UpdateBlocksSub(
unsigned long iEdge,
const MatrixType& block_i,
const MatrixType& block_j) {
1069 SetBlocks<MatrixType, ScalarType, false>(iEdge, block_i, block_j, -1);
1076 template <
class MatrixType,
class OtherType = ScalarType>
1077 inline void SetBlocks(
unsigned long iEdge,
unsigned long iPoint,
unsigned long jPoint,
const MatrixType& jac_ii,
1078 const MatrixType& jac_ij,
const MatrixType& jac_ji,
const MatrixType& jac_jj,
1079 OtherType mask = 1) {
1080 const auto blkSz = nVar * nEqn;
1081 auto* bii = &mat.d[iPoint * blkSz];
1082 auto* bjj = &mat.d[jPoint * blkSz];
1083 unsigned long iVar, jVar, offset = 0;
1085 if (quantized_mode) {
1086 ScalarType bij_buf[MAXNVAR * MAXNVAR], bji_buf[MAXNVAR * MAXNVAR];
1087 for (iVar = 0; iVar < nVar; iVar++)
1088 for (jVar = 0; jVar < nEqn; jVar++, ++offset) {
1089 bii[offset] += PassiveAssign(jac_ii[iVar][jVar] * mask);
1090 bjj[offset] += PassiveAssign(jac_jj[iVar][jVar] * mask);
1091 bij_buf[offset] = PassiveAssign(jac_ij[iVar][jVar] * mask);
1092 bji_buf[offset] = PassiveAssign(jac_ji[iVar][jVar] * mask);
1094 QuantizeBlock(bij_buf, &q_scale.u[iEdge * nVar], &q_blocks.u[iEdge * blkSz]);
1095 const auto k_l = edge_ptr_l[iEdge];
1096 QuantizeBlock(bji_buf, &q_scale.l[k_l * nVar], &q_blocks.l[k_l * blkSz]);
1100 auto* bij = &mat.u[iEdge * blkSz];
1101 auto* bji = &mat.l[edge_ptr_l[iEdge] * blkSz];
1102 for (iVar = 0; iVar < nVar; iVar++) {
1103 for (jVar = 0; jVar < nEqn; jVar++) {
1104 bii[offset] += PassiveAssign(jac_ii[iVar][jVar] * mask);
1105 bjj[offset] += PassiveAssign(jac_jj[iVar][jVar] * mask);
1106 bij[offset] = PassiveAssign(jac_ij[iVar][jVar] * mask);
1107 bji[offset] = PassiveAssign(jac_ji[iVar][jVar] * mask);
1116 template <
class MatrixType,
class OtherType = ScalarType>
1117 inline void SetOffDiagBlocks(
unsigned long iEdge,
const MatrixType& jac_ij,
const MatrixType& jac_ji,
1118 OtherType mask = 1) {
1119 const auto blkSz = nVar * nEqn;
1120 unsigned long iVar, jVar, offset = 0;
1122 if (quantized_mode) {
1123 ScalarType bij_buf[MAXNVAR * MAXNVAR], bji_buf[MAXNVAR * MAXNVAR];
1124 for (iVar = 0; iVar < nVar; iVar++)
1125 for (jVar = 0; jVar < nEqn; jVar++, ++offset) {
1126 bij_buf[offset] = PassiveAssign(jac_ij[iVar][jVar] * mask);
1127 bji_buf[offset] = PassiveAssign(jac_ji[iVar][jVar] * mask);
1129 QuantizeBlock(bij_buf, &q_scale.u[iEdge * nVar], &q_blocks.u[iEdge * blkSz]);
1130 const auto k_l = edge_ptr_l[iEdge];
1131 QuantizeBlock(bji_buf, &q_scale.l[k_l * nVar], &q_blocks.l[k_l * blkSz]);
1135 auto* bij = &mat.u[iEdge * blkSz];
1136 auto* bji = &mat.l[edge_ptr_l[iEdge] * blkSz];
1137 for (iVar = 0; iVar < nVar; iVar++) {
1138 for (jVar = 0; jVar < nEqn; jVar++) {
1139 bij[offset] = PassiveAssign(jac_ij[iVar][jVar] * mask);
1140 bji[offset] = PassiveAssign(jac_ji[iVar][jVar] * mask);
1150 template <
class MatTypeSIMD,
size_t N,
class I,
class F = ScalarType>
1153 static_assert(MatTypeSIMD::StaticSize,
"This method requires static size blocks.");
1154 static_assert(MatTypeSIMD::IsRowMajor,
"Block storage is not compatible with matrix.");
1155 constexpr size_t blkSz = MatTypeSIMD::StaticSize;
1156 assert(blkSz == nVar * nEqn);
1157 constexpr size_t nVar = MatTypeSIMD::StaticNRows;
1161 ScalarType blk_i[N][blkSz], blk_j[N][blkSz];
1163 for (
size_t i = 0; i < blkSz; ++i) {
1165 for (
size_t k = 0; k < N; ++k) {
1166 blk_i[k][i] = PassiveAssign(-mask[k] * block_i.data()[i][k]);
1167 blk_j[k][i] = PassiveAssign(mask[k] * block_j.data()[i][k]);
1172 for (
size_t k = 0; k < N; ++k) {
1173 if (mask[k] == 0)
continue;
1175 if (quantized_mode) {
1176 EncodeQuantBlock([&, k](
unsigned long r,
unsigned long c) {
return blk_j[k][r * nVar + c]; },
1177 &q_scale.u[iEdge[k] * nVar], &q_blocks.u[iEdge[k] * blkSz], nVar);
1178 const auto k_l = edge_ptr_l[iEdge[k]];
1179 EncodeQuantBlock([&, k](
unsigned long r,
unsigned long c) {
return blk_i[k][r * nVar + c]; },
1180 &q_scale.l[k_l * nVar], &q_blocks.l[k_l * blkSz], nVar);
1182 ScalarType* bij = &mat.u[iEdge[k] * blkSz];
1183 ScalarType* bji = &mat.l[edge_ptr_l[iEdge[k]] * blkSz];
1187 for (
size_t i = 0; i < blkSz; ++i) {
1188 bij[i] = blk_j[k][i];
1189 bji[i] = blk_i[k][i];
1203 template <
class OtherType,
bool Overwrite = true,
class T = ScalarType>
1204 inline void SetBlock2Diag(
unsigned long block_i,
const OtherType& val_block, T alpha = 1.0) {
1205 auto mat_ii = &mat.d[block_i * nVar * nEqn];
1207 for (
auto iVar = 0ul; iVar < nVar; iVar++)
1208 for (
auto jVar = 0ul; jVar < nEqn; jVar++) {
1209 *mat_ii = (Overwrite ? ScalarType(0) : *mat_ii) + PassiveAssign(alpha * val_block[iVar][jVar]);
1217 template <
class OtherType,
class T = ScalarType>
1218 inline void AddBlock2Diag(
unsigned long block_i,
const OtherType& val_block, T alpha = 1.0) {
1219 SetBlock2Diag<OtherType, false>(block_i, val_block, alpha);
1225 template <
class OtherType>
1236 template <
class OtherType>
1237 inline void AddVal2Diag(
unsigned long block_i, OtherType val_matrix) {
1238 auto d = &mat.d[block_i * nVar * nVar];
1239 for (
auto iVar = 0ul; iVar < nVar; iVar++) d[iVar * (nVar + 1)] += PassiveAssign(val_matrix);
1249 template <
class OtherType>
1250 inline void AddVal2Diag(
unsigned long block_i,
unsigned long iVar, OtherType val) {
1251 mat.d[block_i * nVar * nVar + iVar * (nVar + 1)] += PassiveAssign(val);
1260 template <
class OtherType>
1261 inline void SetVal2Diag(
unsigned long block_i, OtherType val_matrix) {
1264 for (
auto iVar = 0ul; iVar < nVar * nVar; iVar++) mat.d[block_i * nVar * nVar + iVar] = 0.0;
1282 template <
class OtherType>
1288 template <
class OtherType>
An interface to the INRIA solver PaStiX (http://pastix.gforge.inria.fr/files/README-txt....
#define GET_BLOCK_VIEW_IMPL
void EncodeQuantBlock(const F &f, uint8_t *__restrict qs, int8_t *__restrict qv, unsigned long nVar) noexcept
Encode one nVar×nVar block into per-row int8 quantized storage, see EncodeQuantRow (each row's scale/...
Definition CSysMatrix.hpp:196
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 EQR_PASSIVE(ROW, COL)
void EncodeQuantRow(const F &f, uint8_t &qs, int8_t *__restrict qv, unsigned long nVar, unsigned long r) noexcept
Encode one row of an nVar×nVar block into int8 quantized storage: qs receives the row's scale exponen...
Definition CSysMatrix.hpp:144
Declararion and inlines of the vector class used in the solution of large, distributed,...
#define B(i, j)
Definition blas_structure.cpp:132
Main class for defining the problem; basically this class reads the configuration file,...
Definition CConfig.hpp:64
Parent class for defining the geometry of the problem (complete geometry, multigrid agglomerated geom...
Definition CGeometry.hpp:75
Wrapper class that converts between SU2 sparse format and PaStiX format and simplifies calls to the e...
Definition CPastixWrapper.hpp:55
Main class for defining block-compressed-row-storage sparse matrices.
Definition CSysMatrix.hpp:256
void GetBlocks(unsigned long iEdge, unsigned long iPoint, unsigned long jPoint, ScalarType *&bii, ScalarType *&bij, ScalarType *&bji, ScalarType *&bjj)
Returns the 4 blocks ii, ij, ji, jj used by "UpdateBlocks".
Definition CSysMatrix.hpp:883
void SetVal2Diag(unsigned long block_i, OtherType val_matrix)
Sets the specified value to the diagonal of the (i, i) subblock of the matrix-by-blocks structure.
Definition CSysMatrix.hpp:1261
void ComputeLineletPreconditioner(const CSysVector< ScalarType > &vec, CSysVector< ScalarType > &prod, CGeometry *geometry, const CConfig *config) const
Multiply CSysVector by the preconditioner.
Definition CSysMatrix.cpp:1484
void SetBlocks(simd::Array< I, N > iEdge, const MatTypeSIMD &block_i, const MatTypeSIMD &block_j, simd::Array< F, N > mask=1)
SIMD version, does the update for multiple edges.
Definition CSysMatrix.hpp:1151
void EnforceSolutionAtNode(unsigned long node_i, const OtherType *x_i, CSysVector< OtherType > &b)
Modifies this matrix (A) and a rhs vector (b) such that (A^-1 * b)_i = x_i.
Definition CSysMatrix.cpp:1605
void UpdateBlocksSub(unsigned long iEdge, unsigned long iPoint, unsigned long jPoint, const MatrixType &block_i, const MatrixType &block_j)
Short-hand for the "subtractive" version (sub from i* add to j*) of UpdateBlocks.
Definition CSysMatrix.hpp:950
void BuildLineletPreconditioner(const CGeometry *geometry, const CConfig *config)
Build the Linelet preconditioner.
Definition CSysMatrix.cpp:1454
void BuildILUPreconditioner()
Build the ILU preconditioner.
Definition CSysMatrix.cpp:1064
void DeleteValsRowi(unsigned long block_i, unsigned long row)
Deletes the values of a row of the sparse matrix.
Definition CSysMatrix.cpp:922
void MatrixMatrixAddition(ScalarType alpha, const CSysMatrix &B)
Add a scaled sparse matrix to "this" (axpy-type operation, A = A+alpha*B).
Definition CSysMatrix.cpp:1795
~CSysMatrix()
Destructor of the class.
Definition CSysMatrix.cpp:120
void SetDiagonalAsColumnSum()
Sets the diagonal entries of the matrix as the sum of the blocks in the corresponding column.
Definition CSysMatrix.cpp:1677
void HtDTransfer(bool trigger=true) const
Performs the memory copy from host to device.
Definition CSysMatrixGPU.cu:1016
void SubtractBlock2Diag(unsigned long block_i, const OtherType &val_block)
Short-hand to AddBlock2Diag with alpha = -1, i.e. subtracts from the current diagonal.
Definition CSysMatrix.hpp:1226
void TransposeInPlace()
Transposes the matrix, any preconditioner that was computed may be invalid.
Definition CSysMatrix.cpp:1710
void SetValDiagonalZero()
Sets to zero all the block diagonal entries of the sparse matrix.
Definition CSysMatrix.cpp:836
void AddVal2Diag(unsigned long block_i, unsigned long iVar, OtherType val)
Adds the specified value to the diagonal of the (i, i) subblock of the matrix-by-blocks structure.
Definition CSysMatrix.hpp:1250
void SetValZero()
Sets to zero all the entries of the sparse matrix.
Definition CSysMatrix.cpp:810
void AddBlock2Diag(unsigned long block_i, const OtherType &val_block, T alpha=1.0)
Non overwrite version of SetBlock2Diag, also with scaling.
Definition CSysMatrix.hpp:1218
void EnforceZeroProjection(unsigned long node_i, const OtherType *n, CSysVector< OtherType > &b)
Similar to EnforceSolutionAtNode, but for 0 projection in a given direction.
Definition CSysMatrix.cpp:1640
void ComputeILUPreconditioner(const CSysVector< ScalarType > &vec, CSysVector< ScalarType > &prod, CGeometry *geometry, const CConfig *config) const
Multiply CSysVector by the preconditioner.
Definition CSysMatrix.cpp:1207
void SetBlocks(unsigned long iEdge, unsigned long iPoint, unsigned long jPoint, const MatrixType &jac_ii, const MatrixType &jac_ij, const MatrixType &jac_ji, const MatrixType &jac_jj, OtherType mask=1)
Set the four blocks of an edge, for fluxes whose i and j contributions are independent.
Definition CSysMatrix.hpp:1077
void ComputePastixPreconditioner(const CSysVector< ScalarType > &vec, CSysVector< ScalarType > &prod, CGeometry *geometry, const CConfig *config) const
Apply the PaStiX factorization to CSysVec.
Definition CSysMatrix.cpp:1831
void SetBlock2Diag(unsigned long block_i, const OtherType &val_block, T alpha=1.0)
Sets the specified block to the (i, i) subblock of the sparse matrix. Scales the input block by facto...
Definition CSysMatrix.hpp:1204
void SetBlock(unsigned long block_i, unsigned long block_j, MatrixType &val_block, std::decay_t< typename MatrixType::Scalar > alpha=1.0)
Set the value of a scaled block in the sparse matrix.
Definition CSysMatrix.hpp:820
const ScalarType * GetBlock(unsigned long block_i, unsigned long block_j) const
Get a pointer to the start of block "ij".
Definition CSysMatrix.hpp:760
ScalarType * GetBlock(unsigned long block_i, unsigned long block_j)
Get a pointer to the start of block "ij", non-const version.
Definition CSysMatrix.hpp:775
void UpdateBlocks(unsigned long iEdge, unsigned long iPoint, unsigned long jPoint, const MatrixType &block_i, const MatrixType &block_j, OtherType scale=1)
Update 4 blocks ii, ij, ji, jj (add to i* sub from j*).
Definition CSysMatrix.hpp:903
CBlockView< ScalarType > GetBlockView(unsigned long block_i, unsigned long block_j)
Definition CSysMatrix.hpp:804
void AddBlock(unsigned long block_i, unsigned long block_j, const T &val_block, OtherType alpha=1.0)
Add a scaled block (in flat format) to the sparse matrix (see SetBlock).
Definition CSysMatrix.hpp:860
CSysMatrix()
Constructor of the class.
Definition CSysMatrix.cpp:70
void BuildLU_SGSPreconditioner()
Build the LU-SGS preconditioner.
Definition CSysMatrix.cpp:1302
void ComputeResidual(const CSysVector< ScalarType > &sol, const CSysVector< ScalarType > &f, CSysVector< ScalarType > &res) const
Compute the linear residual.
Definition CSysMatrix.cpp:1590
void BuildJacobiPreconditioner()
Build the Jacobi preconditioner.
Definition CSysMatrix.cpp:1004
void BuildPastixPreconditioner(CGeometry *geometry, const CConfig *config, unsigned short kind_fact)
Factorize matrix using PaStiX.
Definition CSysMatrix.cpp:1815
void SubtractBlock(unsigned long block_i, unsigned long block_j, const T &val_block)
Subtracts the specified block to the sparse matrix (see AddBlock).
Definition CSysMatrix.hpp:871
void SetBlock(unsigned long block_i, unsigned long block_j, const OtherType *val_block, std::decay_t< OtherType > alpha=1.0)
Definition CSysMatrix.hpp:832
void SetOffDiagBlocks(unsigned long iEdge, const MatrixType &jac_ij, const MatrixType &jac_ji, OtherType mask=1)
Set the off-diagonal blocks of an edge, the diagonal being assembled elsewhere.
Definition CSysMatrix.hpp:1117
void UpdateBlocksSub(unsigned long iEdge, const MatrixType &block_i, const MatrixType &block_j)
Short-hand for the "subtractive" version (sub from i* add to j*) of SetBlocks.
Definition CSysMatrix.hpp:1068
void SetBlocks(simd::Array< I, N > iEdge, simd::Array< I, N > iPoint, simd::Array< I, N > jPoint, const MatTypeSIMD &block_i, const MatTypeSIMD &block_j, simd::Array< F, N > mask=1)
SIMD version, does the update for multiple edges and points.
Definition CSysMatrix.hpp:960
void SetBlocks(unsigned long iEdge, const MatrixType &block_i, const MatrixType &block_j, OtherType scale=1)
Sets 2 blocks ij and ji (add to i* sub from j*) associated with one edge of an FVM-type sparse patter...
Definition CSysMatrix.hpp:1025
void AddVal2Diag(unsigned long block_i, OtherType val_matrix)
Adds the specified value to the diagonal of the (i, i) subblock of the matrix-by-blocks structure.
Definition CSysMatrix.hpp:1237
void UpdateBlocks(unsigned long iEdge, const MatrixType &block_i, const MatrixType &block_j, OtherType scale=1)
Short-hand for the "additive overwrite" version of SetBlocks.
Definition CSysMatrix.hpp:1059
void Initialize(unsigned long npoint, unsigned long npointdomain, unsigned short nvar, unsigned short neqn, bool EdgeConnect, CGeometry *geometry, const CConfig *config, bool needTranspPtr=false, bool allow_quant=false, std::optional< unsigned short > override_prec=std::nullopt)
Initializes the sparse matrix.
Definition CSysMatrix.cpp:184
void SetBlock(unsigned long block_i, unsigned long block_j, const OtherType *const *val_block, std::decay_t< OtherType > alpha=1.0)
Definition CSysMatrix.hpp:844
void ComputeLU_SGSPreconditioner(const CSysVector< ScalarType > &vec, CSysVector< ScalarType > &prod, CGeometry *geometry, const CConfig *config) const
Multiply CSysVector by the preconditioner.
Definition CSysMatrix.cpp:1324
void QuantizeDiagonalBlocks()
Compresses off-diagonal blocks into quantized form for use with USE_QUANTIZATION.
Definition CSysMatrix.cpp:779
CBlockView< const ScalarType > GetBlockView(unsigned long block_i, unsigned long block_j) const
Read-only view of block (block_i, block_j). In Q_LU_SGS mode values are decoded on access inside CBlo...
Definition CSysMatrix.hpp:785
void ComputeJacobiPreconditioner(const CSysVector< ScalarType > &vec, CSysVector< ScalarType > &prod, CGeometry *geometry, const CConfig *config) const
Multiply CSysVector by the preconditioner.
Definition CSysMatrix.cpp:1033
Class for holding and manipulating vectors needed by linear solvers.
Definition CSysVector.hpp:195
A simple SIMD type relying on implicit vectorization, i.e. done by the compiler, explicitly vectorize...
Definition vectorization.hpp:89
#define SU2_CUDA_HOST_DEVICE
Definition code_config.hpp:57
uint32_t su2uint
Definition code_config.hpp:121
#define FORCEINLINE
Definition code_config.hpp:44
passivedouble GetValue(const su2double &data)
Get the (primitive) value of the datatype (needs to be specialized for active types).
Definition datatype_structure.hpp:113
#define SU2_OMP_SIMD
Definition omp_structure.hpp:125
#define SU2_OMP_SIMD_IF_NOT_AD
Definition omp_structure.hpp:129
MPI_QUANTITIES
Vertex-based quantities exchanged in MPI point-to-point communications.
Definition option_structure.hpp:2873
@ SOLUTION_MATRIX
Matrix solution communication.
View of one matrix block, const-correct via the ScalarType template parameter. CBlockView<const Scala...
Definition CSysMatrix.hpp:208
QuantType * qv
Quantized values (row-major); non-null iff quantized.
Definition CSysMatrix.hpp:214
unsigned long nVar
Definition CSysMatrix.hpp:215
std::conditional_t< std::is_const_v< ScalarType >, const int8_t, int8_t > QuantType
Definition CSysMatrix.hpp:209
std::remove_const_t< ScalarType > operator()(unsigned long i, unsigned long j) const
Return entry (row i, col j), decoding quantization if necessary.
Definition CSysMatrix.hpp:221
QuantScaleType * qs
Per-row biased binary exponent; non-null iff quantized.
Definition CSysMatrix.hpp:213
ScalarType * ptr
Full-precision block; non-null iff not quantized.
Definition CSysMatrix.hpp:212
std::conditional_t< std::is_const_v< ScalarType >, const uint8_t, uint8_t > QuantScaleType
Definition CSysMatrix.hpp:210
void apply(const F &f) const
Write the block from callable f(i,j). Overwrite=true overwrites (or quantizes for Q_LU_SGS off-diagon...
Definition CSysMatrix.hpp:235
Helper to communicate distributed vectors.
Definition CSysMatrix.hpp:88
static void Complete(CSysVector< T > &x, CGeometry *geometry, const CConfig *config, MPI_QUANTITIES commType=MPI_QUANTITIES::SOLUTION_MATRIX)
Routine to complete the set of non-blocking communications launched by Initiate() and unpacking of th...
Definition CSysMatrix.cpp:663
static void Initiate(const CSysVector< T > &x, CGeometry *geometry, const CConfig *config, MPI_QUANTITIES commType=MPI_QUANTITIES::SOLUTION_MATRIX)
Routine to load a vector quantity into the data structures for MPI point-to-point communication and t...
Definition CSysMatrix.cpp:547