diff --git a/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrix.H b/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrix.H index 6ed2091a77..db730d7a97 100644 --- a/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrix.H +++ b/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrix.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2019-2021 OpenCFD Ltd. + Copyright (C) 2019-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -54,6 +54,7 @@ SourceFiles #define Foam_LduMatrix_H #include "lduMesh.H" +#include "lduMatrix.H" #include "Field.H" #include "FieldField.H" #include "LduInterfaceFieldPtrsList.H" @@ -69,8 +70,7 @@ namespace Foam // Forward Declarations -template -class LduMatrix; +template class LduMatrix; template Ostream& operator<< @@ -119,16 +119,13 @@ public: // Protected Data - //- Default maximum number of iterations in the solver - static const label defaultMaxIter_ = 1000; - word fieldName_; const LduMatrix& matrix_; - //- Dictionary of controls + //- Dictionary of solution controls dictionary controlDict_; - //- Level of verbosity in the solver output statements + //- Verbosity level for solver output statements int log_; //- Minimum number of iterations in the solver @@ -137,6 +134,9 @@ public: //- Maximum number of iterations in the solver label maxIter_; + //- The matrix normalisation type + lduMatrix::normTypes normType_; + //- Final convergence tolerance Type tolerance_; @@ -146,7 +146,7 @@ public: // Protected Member Functions - //- Read the control parameters from the controlDict_ + //- Read the control parameters from controlDict_ virtual void readControls(); @@ -206,6 +206,7 @@ public: // Constructors + //- Construct for given field name, matrix and controls solver ( const word& fieldName, @@ -225,9 +226,8 @@ public: ); - // Destructor - - virtual ~solver() = default; + //- Destructor + virtual ~solver() = default; // Member Functions @@ -244,21 +244,33 @@ public: //- Read and reset the solver parameters from the given dictionary - virtual void read(const dictionary& solverDict); + virtual void read(const dictionary&); virtual SolverPerformance solve ( Field& psi ) const = 0; + //- Return the matrix norm using the specified norm method + Type normFactor + ( + const Field& psi, + const Field& Apsi, + Field& tmpField, + const lduMatrix::normTypes normType + ) const; + //- Return the matrix norm used to normalise the residual for the - // stopping criterion + //- stopping criterion Type normFactor ( const Field& psi, const Field& Apsi, Field& tmpField - ) const; + ) const + { + return this->normFactor(psi, Apsi, tmpField, normType_); + } }; @@ -314,6 +326,7 @@ public: // Constructors + //- Construct for given field name and matrix smoother ( const word& fieldName, @@ -332,9 +345,8 @@ public: ); - // Destructor - - virtual ~smoother() = default; + //- Destructor + virtual ~smoother() = default; // Member Functions @@ -405,10 +417,8 @@ public: // Constructors - preconditioner - ( - const solver& sol - ) + //- Construct for given solver + preconditioner(const solver& sol) : solver_(sol) {} @@ -424,16 +434,15 @@ public: ); - // Destructor - - virtual ~preconditioner() = default; + //- Destructor + virtual ~preconditioner() = default; // Member functions //- Read and reset the preconditioner parameters - // from the given dictionary - virtual void read(const dictionary& preconditionerDict) + //- from the given dictionary + virtual void read(const dictionary&) {} //- Return wA the preconditioned form of residual rA @@ -444,7 +453,7 @@ public: ) const = 0; //- Return wT the transpose-matrix preconditioned form of - // residual rT. + //- residual rT. // This is only required for preconditioning asymmetric matrices. virtual void preconditionT ( @@ -480,17 +489,16 @@ public: LduMatrix(const lduMesh&, Istream&); - // Destructor - - ~LduMatrix(); + //- Destructor + ~LduMatrix(); - // Member functions + // Member Functions // Access to addressing //- Return the LDU mesh from which the addressing is obtained - const lduMesh& mesh() const + const lduMesh& mesh() const noexcept { return lduMesh_; } @@ -554,43 +562,43 @@ public: } - bool hasDiag() const + bool hasDiag() const noexcept { return (diagPtr_); } - bool hasUpper() const + bool hasUpper() const noexcept { return (upperPtr_); } - bool hasLower() const + bool hasLower() const noexcept { return (lowerPtr_); } - bool hasSource() const + bool hasSource() const noexcept { return (sourcePtr_); } - bool diagonal() const + bool diagonal() const noexcept { return (diagPtr_ && !lowerPtr_ && !upperPtr_); } - bool symmetric() const + bool symmetric() const noexcept { return (diagPtr_ && (!lowerPtr_ && upperPtr_)); } - bool asymmetric() const + bool asymmetric() const noexcept { return (diagPtr_ && lowerPtr_ && upperPtr_); } - // operations + // Operations void sumDiag(); void negSumDiag(); @@ -640,7 +648,7 @@ public: tmp> faceH(const tmp>&) const; - // Member operators + // Member Operators void operator=(const LduMatrix&); @@ -653,7 +661,7 @@ public: void operator*=(scalar); - // Ostream operator + // Ostream Operator friend Ostream& operator<< ( diff --git a/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrixSolver.C b/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrixSolver.C index 59d117381e..a9598b03a6 100644 --- a/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrixSolver.C +++ b/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrixSolver.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2019-2021 OpenCFD Ltd. + Copyright (C) 2019-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -131,8 +131,9 @@ Foam::LduMatrix::solver::solver log_(1), minIter_(0), - maxIter_(defaultMaxIter_), - tolerance_(1e-6*pTraits::one), + maxIter_(lduMatrix::defaultMaxIter), + normType_(lduMatrix::normTypes::DEFAULT_NORM), + tolerance_(lduMatrix::defaultTolerance*pTraits::one), relTol_(Zero) { readControls(); @@ -145,6 +146,8 @@ template void Foam::LduMatrix::solver::readControls() { controlDict_.readIfPresent("log", log_); + normType_ = lduMatrix::normTypes::DEFAULT_NORM; + lduMatrix::normTypesNames_.readIfPresent("norm", controlDict_, normType_); controlDict_.readIfPresent("minIter", minIter_); controlDict_.readIfPresent("maxIter", maxIter_); controlDict_.readIfPresent("tolerance", tolerance_); @@ -168,21 +171,45 @@ Type Foam::LduMatrix::solver::normFactor ( const Field& psi, const Field& Apsi, - Field& tmpField + Field& tmpField, + const lduMatrix::normTypes normType ) const { - // --- Calculate A dot reference value of psi - matrix_.sumA(tmpField); - cmptMultiply(tmpField, tmpField, gAverage(psi)); + switch (normType) + { + case lduMatrix::normTypes::NO_NORM : + { + break; + } - return stabilise - ( - gSum(cmptMag(Apsi - tmpField) + cmptMag(matrix_.source() - tmpField)), - SolverPerformance::small_ - ); + case lduMatrix::normTypes::DEFAULT_NORM : + case lduMatrix::normTypes::L1_SCALED_NORM : + { + // --- Calculate A dot reference value of psi + matrix_.sumA(tmpField); + cmptMultiply(tmpField, tmpField, gAverage(psi)); - // At convergence this simpler method is equivalent to the above - // return stabilise(2*gSumCmptMag(matrix_.source()), matrix_.small_); + return stabilise + ( + gSum + ( + cmptMag(Apsi - tmpField) + + cmptMag(matrix_.source() - tmpField) + ), + SolverPerformance::small_ + ); + + // Equivalent at convergence: + // return stabilise + // ( + // 2*gSumCmptMag(matrix_.source()), matrix_.small_ + // ); + break; + } + } + + // Fall-through: no norm + return pTraits::one; } diff --git a/src/OpenFOAM/matrices/LduMatrix/Solvers/DiagonalSolver/DiagonalSolver.H b/src/OpenFOAM/matrices/LduMatrix/Solvers/DiagonalSolver/DiagonalSolver.H index 47055b7808..8918142637 100644 --- a/src/OpenFOAM/matrices/LduMatrix/Solvers/DiagonalSolver/DiagonalSolver.H +++ b/src/OpenFOAM/matrices/LduMatrix/Solvers/DiagonalSolver/DiagonalSolver.H @@ -34,8 +34,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef DiagonalSolver_H -#define DiagonalSolver_H +#ifndef Foam_DiagonalSolver_H +#define Foam_DiagonalSolver_H #include "LduMatrix.H" @@ -53,7 +53,9 @@ class DiagonalSolver : public LduMatrix::solver { - // Private Member Functions +public: + + // Generated Methods //- No copy construct DiagonalSolver(const DiagonalSolver&) = delete; @@ -62,8 +64,6 @@ class DiagonalSolver void operator=(const DiagonalSolver&) = delete; -public: - //- Runtime type information TypeName("diagonal"); diff --git a/src/OpenFOAM/matrices/LduMatrix/Solvers/SmoothSolver/SmoothSolver.H b/src/OpenFOAM/matrices/LduMatrix/Solvers/SmoothSolver/SmoothSolver.H index 278d29e776..9909a5db6d 100644 --- a/src/OpenFOAM/matrices/LduMatrix/Solvers/SmoothSolver/SmoothSolver.H +++ b/src/OpenFOAM/matrices/LduMatrix/Solvers/SmoothSolver/SmoothSolver.H @@ -37,8 +37,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef SmoothSolver_H -#define SmoothSolver_H +#ifndef Foam_SmoothSolver_H +#define Foam_SmoothSolver_H #include "lduMatrix.H" @@ -56,10 +56,9 @@ class SmoothSolver : public LduMatrix::solver { - protected: - // Protected data + // Protected Data //- Number of sweeps before the evaluation of residual label nSweeps_; diff --git a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.C b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.C index 546d5db0c7..0ecf015fd4 100644 --- a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.C +++ b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.C @@ -41,7 +41,16 @@ namespace Foam } -const Foam::label Foam::lduMatrix::solver::defaultMaxIter_ = 1000; +const Foam::Enum +< + Foam::lduMatrix::normTypes +> +Foam::lduMatrix::normTypesNames_ +({ + { normTypes::NO_NORM, "none" }, + { normTypes::DEFAULT_NORM, "default" }, + { normTypes::L1_SCALED_NORM, "L1_scaled" }, +}); // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.H b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.H index d19365b63b..6ebb028e56 100644 --- a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.H +++ b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2016-2021 OpenCFD Ltd. + Copyright (C) 2016-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -50,8 +50,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef lduMatrix_H -#define lduMatrix_H +#ifndef Foam_lduMatrix_H +#define Foam_lduMatrix_H #include "lduMesh.H" #include "primitiveFieldsFwd.H" @@ -62,6 +62,7 @@ SourceFiles #include "runTimeSelectionTables.H" #include "solverPerformance.H" #include "InfoProxy.H" +#include "Enum.H" #include "profilingTrigger.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -70,7 +71,6 @@ namespace Foam { // Forward Declarations - class lduMatrix; Ostream& operator<<(Ostream&, const lduMatrix&); @@ -95,6 +95,26 @@ class lduMatrix public: + // Public Types + + //- Enumerated matrix normalisation types + enum class normTypes : char + { + NO_NORM, //!< "none" norm (returns 1) + DEFAULT_NORM, //!< "default" norm (== L1_scaled) + L1_SCALED_NORM, //!< "L1_scaled" norm + }; + + //- Names for the normTypes + static const Enum normTypesNames_; + + //- Default maximum number of iterations for solvers + static constexpr label defaultMaxIter = 1000; + + //- Default (absolute) tolerance + static constexpr scalar defaultTolerance = 1e-6; + + //- Abstract base-class for lduMatrix solvers class solver { @@ -102,19 +122,16 @@ public: // Protected Data - //- Default maximum number of iterations in the solver - static const label defaultMaxIter_; - word fieldName_; const lduMatrix& matrix_; const FieldField& interfaceBouCoeffs_; const FieldField& interfaceIntCoeffs_; lduInterfaceFieldPtrsList interfaces_; - //- Dictionary of controls + //- Dictionary of solution controls dictionary controlDict_; - //- Level of verbosity in the solver output statements + //- Verbosity level for solver output statements int log_; //- Minimum number of iterations in the solver @@ -123,18 +140,22 @@ public: //- Maximum number of iterations in the solver label maxIter_; + //- The normalisation type + lduMatrix::normTypes normType_; + //- Final convergence tolerance scalar tolerance_; //- Convergence tolerance relative to the initial scalar relTol_; + //- Profiling instrumentation profilingTrigger profiling_; // Protected Member Functions - //- Read the control parameters from the controlDict_ + //- Read the control parameters from controlDict_ virtual void readControls(); @@ -195,6 +216,7 @@ public: // Constructors + //- Construct solver for given field name, matrix etc solver ( const word& fieldName, @@ -272,6 +294,16 @@ public: const direction cmpt=0 ) const; + //- Return the matrix norm using the specified norm method + solveScalarField::cmptType normFactor + ( + const solveScalarField& psi, + const solveScalarField& source, + const solveScalarField& Apsi, + solveScalarField& tmpField, + const lduMatrix::normTypes normType + ) const; + //- Return the matrix norm used to normalise the residual for the //- stopping criterion solveScalarField::cmptType normFactor @@ -280,7 +312,10 @@ public: const solveScalarField& source, const solveScalarField& Apsi, solveScalarField& tmpField - ) const; + ) const + { + return this->normFactor(psi, source, Apsi, tmpField, normType_); + } }; @@ -354,6 +389,7 @@ public: // Constructors + //- Construct for given field name, matrix etc smoother ( const word& fieldName, @@ -479,10 +515,8 @@ public: // Constructors - preconditioner - ( - const solver& sol - ) + //- Construct for given solver + explicit preconditioner(const solver& sol) : solver_(sol) {} @@ -564,7 +598,7 @@ public: // Access to addressing //- Return the LDU mesh from which the addressing is obtained - const lduMesh& mesh() const + const lduMesh& mesh() const noexcept { return lduMesh_; } @@ -606,38 +640,38 @@ public: const scalarField& diag() const; const scalarField& upper() const; - bool hasDiag() const + bool hasDiag() const noexcept { return (diagPtr_); } - bool hasUpper() const + bool hasUpper() const noexcept { return (upperPtr_); } - bool hasLower() const + bool hasLower() const noexcept { return (lowerPtr_); } - bool diagonal() const + bool diagonal() const noexcept { return (diagPtr_ && !lowerPtr_ && !upperPtr_); } - bool symmetric() const + bool symmetric() const noexcept { return (diagPtr_ && (!lowerPtr_ && upperPtr_)); } - bool asymmetric() const + bool asymmetric() const noexcept { return (diagPtr_ && lowerPtr_ && upperPtr_); } - // operations + // Operations void sumDiag(); void negSumDiag(); diff --git a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixSolver.C b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixSolver.C index bae0f3d9e7..1ffcf3bdb0 100644 --- a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixSolver.C +++ b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixSolver.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2016-2021 OpenCFD Ltd. + Copyright (C) 2016-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -152,6 +152,14 @@ Foam::lduMatrix::solver::solver interfaceIntCoeffs_(interfaceIntCoeffs), interfaces_(interfaces), controlDict_(solverControls), + + log_(1), + minIter_(0), + maxIter_(lduMatrix::defaultMaxIter), + normType_(lduMatrix::normTypes::DEFAULT_NORM), + tolerance_(lduMatrix::defaultTolerance), + relTol_(Zero), + profiling_("lduMatrix::solver." + fieldName) { readControls(); @@ -162,11 +170,19 @@ Foam::lduMatrix::solver::solver void Foam::lduMatrix::solver::readControls() { - log_ = controlDict_.getOrDefault("log", 1); - minIter_ = controlDict_.getOrDefault