Skip to content

Commit 162830d

Browse files
authored
Merge pull request #2651 from su2code/chore_catch_ortho_fail
Regularize matrices to fix FGMRES orthogonalization error
2 parents 3dba507 + 8282722 commit 162830d

File tree

1 file changed

+30
-2
lines changed

1 file changed

+30
-2
lines changed

Common/src/linear_algebra/CSysMatrix.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,18 @@ void CSysMatrix<ScalarType>::SetValDiagonalZero() {
494494
END_SU2_OMP_FOR
495495
}
496496

497+
/*--- Helper function to regularize small pivots ---*/
498+
template <class ScalarType>
499+
inline void RegularizePivot(ScalarType& pivot, unsigned long row, unsigned long col, const char* context) {
500+
const float eps = 1e-12;
501+
if (std::abs(pivot) < eps) {
502+
pivot = std::copysign(eps, SU2_TYPE::GetValue(pivot));
503+
#ifndef NDEBUG
504+
std::cout << context << ": Regularized small pivot A(" << row << "," << col << ") to " << pivot << std::endl;
505+
#endif
506+
}
507+
}
508+
497509
template <class ScalarType>
498510
void CSysMatrix<ScalarType>::Gauss_Elimination(ScalarType* matrix, ScalarType* vec) const {
499511
#ifdef USE_MKL_LAPACK
@@ -505,9 +517,14 @@ void CSysMatrix<ScalarType>::Gauss_Elimination(ScalarType* matrix, ScalarType* v
505517
#define A(I, J) matrix[(I)*nVar + (J)]
506518

507519
/*--- Transform system in Upper Matrix ---*/
520+
508521
for (auto iVar = 1ul; iVar < nVar; iVar++) {
509522
for (auto jVar = 0ul; jVar < iVar; jVar++) {
523+
/*--- Regularize pivot if too small to prevent divide-by-zero ---*/
524+
RegularizePivot(A(jVar, jVar), jVar, jVar, "DEBUG Gauss_Elimination");
525+
510526
ScalarType weight = A(iVar, jVar) / A(jVar, jVar);
527+
511528
for (auto kVar = jVar; kVar < nVar; kVar++) A(iVar, kVar) -= weight * A(jVar, kVar);
512529
vec[iVar] -= weight * vec[jVar];
513530
}
@@ -517,6 +534,10 @@ void CSysMatrix<ScalarType>::Gauss_Elimination(ScalarType* matrix, ScalarType* v
517534
for (auto iVar = nVar; iVar > 0ul;) {
518535
iVar--; // unsigned type
519536
for (auto jVar = iVar + 1; jVar < nVar; jVar++) vec[iVar] -= A(iVar, jVar) * vec[jVar];
537+
538+
/*--- Regularize diagonal if too small ---*/
539+
RegularizePivot(A(iVar, iVar), iVar, iVar, "DEBUG Gauss_Elimination backsubst");
540+
520541
vec[iVar] /= A(iVar, iVar);
521542
}
522543
#undef A
@@ -550,8 +571,10 @@ void CSysMatrix<ScalarType>::MatrixInverse(ScalarType* matrix, ScalarType* inver
550571
/*--- Transform system in Upper Matrix ---*/
551572
for (auto iVar = 1ul; iVar < nVar; iVar++) {
552573
for (auto jVar = 0ul; jVar < iVar; jVar++) {
553-
ScalarType weight = A(iVar, jVar) / A(jVar, jVar);
574+
/*--- Regularize pivot if too small to prevent divide-by-zero ---*/
575+
RegularizePivot(A(jVar, jVar), jVar, jVar, "MatrixInverse");
554576

577+
ScalarType weight = A(iVar, jVar) / A(jVar, jVar);
555578
for (auto kVar = jVar; kVar < nVar; kVar++) A(iVar, kVar) -= weight * A(jVar, kVar);
556579

557580
/*--- at this stage M is lower triangular so not all cols need updating ---*/
@@ -565,7 +588,12 @@ void CSysMatrix<ScalarType>::MatrixInverse(ScalarType* matrix, ScalarType* inver
565588
for (auto jVar = iVar + 1; jVar < nVar; jVar++)
566589
for (auto kVar = 0ul; kVar < nVar; kVar++) M(iVar, kVar) -= A(iVar, jVar) * M(jVar, kVar);
567590

568-
for (auto kVar = 0ul; kVar < nVar; kVar++) M(iVar, kVar) /= A(iVar, iVar);
591+
/*--- Regularize diagonal if too small ---*/
592+
RegularizePivot(A(iVar, iVar), iVar, iVar, "DEBUG MatrixInverse backsubst");
593+
594+
for (auto kVar = 0ul; kVar < nVar; kVar++) {
595+
M(iVar, kVar) /= A(iVar, iVar);
596+
}
569597
}
570598
#undef A
571599
#endif

0 commit comments

Comments
 (0)