Improved normalisation of reported residuals for block-coupled systems

This commit is contained in:
Hrvoje Jasak 2019-05-02 13:29:21 +01:00
parent 93849cea09
commit 7ef4377a9c
10 changed files with 38 additions and 35 deletions

View file

@ -72,10 +72,10 @@ Foam::BlockAMGSolver<Type>::solve
this->fieldName() this->fieldName()
); );
scalar norm = this->normFactor(x, b); Type norm = this->normFactor(x, b);
// Calculate initial residual // Calculate initial residual
solverPerf.initialResidual() = gSum(cmptMag(amg_.residual(x, b)))/norm; solverPerf.initialResidual() = cmptDivide(gSum(cmptMag(amg_.residual(x, b))),norm);
solverPerf.finalResidual() = solverPerf.initialResidual(); solverPerf.finalResidual() = solverPerf.initialResidual();
// Stop solver on divergence // Stop solver on divergence
@ -88,8 +88,8 @@ Foam::BlockAMGSolver<Type>::solve
{ {
amg_.cycle(x, b); amg_.cycle(x, b);
solverPerf.finalResidual() = solverPerf.finalResidual() =
gSum(cmptMag(amg_.residual(x, b)))/norm; cmptDivide(gSum(cmptMag(amg_.residual(x, b))), norm);
solverPerf.nIterations()++; solverPerf.nIterations()++;

View file

@ -76,7 +76,7 @@ Foam::BlockBiCGStabSolver<Type>::solve
this->fieldName() this->fieldName()
); );
scalar norm = this->normFactor(x, b); Type norm = this->normFactor(x, b);
// Multiplication helper // Multiplication helper
typename BlockCoeff<Type>::multiply mult; typename BlockCoeff<Type>::multiply mult;
@ -87,7 +87,8 @@ Foam::BlockBiCGStabSolver<Type>::solve
matrix.Amul(p, x); matrix.Amul(p, x);
Field<Type> r(b - p); Field<Type> r(b - p);
solverPerf.initialResidual() = gSum(cmptMag(r))/norm; // NOTE: Normalisation of residual per component! TU, Feb 2019
solverPerf.initialResidual() = cmptDivide(gSum(cmptMag(r)),norm);
solverPerf.finalResidual() = solverPerf.initialResidual(); solverPerf.finalResidual() = solverPerf.initialResidual();
// Check convergence, solve if not converged // Check convergence, solve if not converged
@ -160,7 +161,7 @@ Foam::BlockBiCGStabSolver<Type>::solve
r[i] = s[i] - omega*t[i]; r[i] = s[i] - omega*t[i];
} }
solverPerf.finalResidual() = gSum(cmptMag(r))/norm; solverPerf.finalResidual() = cmptDivide(gSum(cmptMag(r)), norm);
solverPerf.nIterations()++; solverPerf.nIterations()++;
} while (!this->stop(solverPerf)); } while (!this->stop(solverPerf));
} }

View file

@ -75,7 +75,7 @@ typename Foam::BlockSolverPerformance<Type> Foam::BlockCGSolver<Type>::solve
this->fieldName() this->fieldName()
); );
scalar norm = this->normFactor(x, b); Type norm = this->normFactor(x, b);
Field<Type> wA(x.size()); Field<Type> wA(x.size());
@ -83,7 +83,8 @@ typename Foam::BlockSolverPerformance<Type> Foam::BlockCGSolver<Type>::solve
matrix.Amul(wA, x); matrix.Amul(wA, x);
Field<Type> rA(b - wA); Field<Type> rA(b - wA);
solverPerf.initialResidual() = gSum(cmptMag(rA))/norm; // NOTE: Normalisation of residual per component! TU, Feb 2019
solverPerf.initialResidual() = cmptDivide(gSum(cmptMag(rA)),norm);
solverPerf.finalResidual() = solverPerf.initialResidual(); solverPerf.finalResidual() = solverPerf.initialResidual();
// Check convergence, solve if not converged // Check convergence, solve if not converged
@ -120,7 +121,7 @@ typename Foam::BlockSolverPerformance<Type> Foam::BlockCGSolver<Type>::solve
wApA = gSumProd(wA, pA); wApA = gSumProd(wA, pA);
// Check for singularity // Check for singularity
if (solverPerf.checkSingularity(mag(wApA)/norm)) if (solverPerf.checkSingularity(mag(wApA)/mag(norm)))
{ {
break; break;
} }
@ -138,7 +139,7 @@ typename Foam::BlockSolverPerformance<Type> Foam::BlockCGSolver<Type>::solve
rA[i] -= alpha*wA[i]; rA[i] -= alpha*wA[i];
} }
solverPerf.finalResidual() = gSum(cmptMag(rA))/norm; solverPerf.finalResidual() = cmptDivide(gSum(cmptMag(rA)), norm);
solverPerf.nIterations()++; solverPerf.nIterations()++;
} while (!this->stop(solverPerf)); } while (!this->stop(solverPerf));
} }

View file

@ -111,7 +111,7 @@ Foam::BlockGMRESSolver<Type>::solve
this->fieldName() this->fieldName()
); );
scalar norm = this->normFactor(x, b); Type norm = this->normFactor(x, b);
Field<Type> wA(x.size()); Field<Type> wA(x.size());
@ -119,7 +119,7 @@ Foam::BlockGMRESSolver<Type>::solve
matrix.Amul(wA, x); matrix.Amul(wA, x);
Field<Type> rA(b - wA); Field<Type> rA(b - wA);
solverPerf.initialResidual() = gSum(cmptMag(rA))/norm; solverPerf.initialResidual() = cmptDivide(gSum(cmptMag(rA)),norm);
solverPerf.finalResidual() = solverPerf.initialResidual(); solverPerf.finalResidual() = solverPerf.initialResidual();
// Check convergence, solve if not converged // Check convergence, solve if not converged
@ -234,7 +234,7 @@ Foam::BlockGMRESSolver<Type>::solve
rA[raI] = b[raI] - wA[raI]; rA[raI] = b[raI] - wA[raI];
} }
solverPerf.finalResidual() = gSum(cmptMag(rA))/norm; solverPerf.finalResidual() = cmptDivide(gSum(cmptMag(rA)), norm);
solverPerf.nIterations()++; solverPerf.nIterations()++;
} while (!this->stop(solverPerf)); } while (!this->stop(solverPerf));
} }

View file

@ -72,7 +72,7 @@ Foam::BlockGaussSeidelSolver<Type>::solve
this->fieldName() this->fieldName()
); );
scalar norm = this->normFactor(x, b); Type norm = this->normFactor(x, b);
Field<Type> wA(x.size()); Field<Type> wA(x.size());
@ -80,7 +80,7 @@ Foam::BlockGaussSeidelSolver<Type>::solve
matrix.Amul(wA, x); matrix.Amul(wA, x);
wA -= b; wA -= b;
solverPerf.initialResidual() = gSum(cmptMag(wA))/norm; solverPerf.initialResidual() = cmptDivide(gSum(cmptMag(wA)),norm);
solverPerf.finalResidual() = solverPerf.initialResidual(); solverPerf.finalResidual() = solverPerf.initialResidual();
// Check convergence, solve if not converged // Check convergence, solve if not converged
@ -103,7 +103,7 @@ Foam::BlockGaussSeidelSolver<Type>::solve
matrix.Amul(wA, x); matrix.Amul(wA, x);
wA -= b; wA -= b;
solverPerf.finalResidual() = gSum(cmptMag(wA))/norm; solverPerf.finalResidual() = cmptDivide(gSum(cmptMag(wA)), norm);
} while (!this->stop(solverPerf)); } while (!this->stop(solverPerf));
} }

View file

@ -72,7 +72,7 @@ Foam::BlockILUSolver<Type>::solve
this->fieldName() this->fieldName()
); );
scalar norm = this->normFactor(x, b); Type norm = this->normFactor(x, b);
Field<Type> residual(x.size()); Field<Type> residual(x.size());
@ -84,7 +84,7 @@ Foam::BlockILUSolver<Type>::solve
residual[i] = b[i] - residual[i]; residual[i] = b[i] - residual[i];
} }
solverPerf.initialResidual() = gSum(cmptMag(residual))/norm; solverPerf.initialResidual() = cmptDivide(gSum(cmptMag(residual)),norm);
solverPerf.finalResidual() = solverPerf.initialResidual(); solverPerf.finalResidual() = solverPerf.initialResidual();
// Check convergence, solve if not converged // Check convergence, solve if not converged
@ -114,7 +114,7 @@ Foam::BlockILUSolver<Type>::solve
residual[i] = b[i] - residual[i]; residual[i] = b[i] - residual[i];
} }
solverPerf.finalResidual() = gSum(cmptMag(residual))/norm; solverPerf.finalResidual() = cmptDivide(gSum(cmptMag(residual)), norm);
} while (!this->stop(solverPerf)); } while (!this->stop(solverPerf));
} }

View file

@ -50,7 +50,7 @@ Foam::BlockIterativeSolver<Type>::BlockIterativeSolver
// * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * * //
template<class Type> template<class Type>
Foam::scalar Foam::BlockIterativeSolver<Type>::normFactor Type Foam::BlockIterativeSolver<Type>::normFactor
( (
Field<Type>& x, Field<Type>& x,
const Field<Type>& b const Field<Type>& b
@ -77,7 +77,13 @@ Foam::scalar Foam::BlockIterativeSolver<Type>::normFactor
Field<Type>(nRows, xRef) Field<Type>(nRows, xRef)
); );
scalar normFactor = gSum(mag(wA - pA) + mag(b - pA)) + this->small_; // The components of the normalisation factor cannot be equal to 0 since it
// appears in the denominator: replace zero with small_
Type small = pTraits<Type>::one*this->small_;
// Norm factor for the block matrix is not a scalar since each component
// should be normalised with a value corresponding to a particular variable
Type normFactor = gSum(cmptMag(wA - pA) + cmptMag(b - pA)) + small;
if (blockLduMatrix::debug >= 2) if (blockLduMatrix::debug >= 2)
{ {

View file

@ -84,7 +84,7 @@ protected:
// Protected Member Functions // Protected Member Functions
//- Return normalisation factor //- Return normalisation factor
scalar normFactor Type normFactor
( (
Field<Type>& x, Field<Type>& x,
const Field<Type>& b const Field<Type>& b
@ -107,10 +107,9 @@ public:
); );
// Destructor //- Destructor
virtual ~BlockIterativeSolver()
virtual ~BlockIterativeSolver() {}
{}
// Member Functions // Member Functions

View file

@ -39,14 +39,9 @@ bool Foam::BlockSolverPerformance<Type>::checkConvergence
{ {
Info<< solverName_ Info<< solverName_
<< ": Iteration " << nIterations_ << ": Iteration " << nIterations_
<< " residual = " << finalResidual_; << " residual = " << finalResidual_
<< " mag = " << mag(finalResidual_)
if (pTraits<Type>::rank > 0) << " tol = "
{
Info<< " mag = " << mag(finalResidual_);
}
Info<< " tol = "
<< Foam::max(Tolerance, RelTolerance*mag(initialResidual_)) << Foam::max(Tolerance, RelTolerance*mag(initialResidual_))
<< endl; << endl;
} }

View file

@ -41,6 +41,7 @@ defineNamedTemplateTypeNameAndDebug(BlockSolverPerformanceVector, 1);
defineNamedTemplateTypeNameAndDebug(BlockSolverPerformanceSphericalTensor, 1); defineNamedTemplateTypeNameAndDebug(BlockSolverPerformanceSphericalTensor, 1);
defineNamedTemplateTypeNameAndDebug(BlockSolverPerformanceSymmTensor, 1); defineNamedTemplateTypeNameAndDebug(BlockSolverPerformanceSymmTensor, 1);
defineNamedTemplateTypeNameAndDebug(BlockSolverPerformanceTensor, 1); defineNamedTemplateTypeNameAndDebug(BlockSolverPerformanceTensor, 1);
}; };