Compare commits

...

2 Commits

Author SHA1 Message Date
29e4d6b961 wip 2020-06-04 22:31:53 +02:00
2970275410 ENH: constexpr for scalar constants in SolverPerformance
STYLE: simplify coding in SolverPerformance
2020-06-04 11:34:55 +02:00
6 changed files with 192 additions and 125 deletions

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -36,10 +37,9 @@ bool Foam::SolverPerformance<Type>::checkSingularity
const Type& wApA const Type& wApA
) )
{ {
for(direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++) for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; ++cmpt)
{ {
singular_[cmpt] = singular_[cmpt] = (component(wApA, cmpt) < vsmall_);
component(wApA, cmpt) < vsmall_;
} }
return singular(); return singular();
@ -49,15 +49,43 @@ bool Foam::SolverPerformance<Type>::checkSingularity
template<class Type> template<class Type>
bool Foam::SolverPerformance<Type>::singular() const bool Foam::SolverPerformance<Type>::singular() const
{ {
for(direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++) for (const bool val : singular_)
{ {
if (!singular_[cmpt]) return false; if (!val) return false;
} }
return true; return true;
} }
template<class Type>
double Foam::SolverPerformance<Type>::timing() const
{
double ret{0};
for (const double val : timing_)
{
ret += val;
}
return ret;
}
template<class Type>
double Foam::SolverPerformance<Type>::maxTiming() const
{
double ret{0};
for (const double val : timing_)
{
ret = Foam::max(ret, val);
}
return ret;
}
template<class Type> template<class Type>
bool Foam::SolverPerformance<Type>::checkConvergence bool Foam::SolverPerformance<Type>::checkConvergence
( (
@ -73,7 +101,7 @@ bool Foam::SolverPerformance<Type>::checkConvergence
<< endl; << endl;
} }
if converged_ =
( (
finalResidual_ < Tolerance finalResidual_ < Tolerance
|| ( || (
@ -81,14 +109,7 @@ bool Foam::SolverPerformance<Type>::checkConvergence
> small_*pTraits<Type>::one > small_*pTraits<Type>::one
&& finalResidual_ < cmptMultiply(RelTolerance, initialResidual_) && finalResidual_ < cmptMultiply(RelTolerance, initialResidual_)
) )
) );
{
converged_ = true;
}
else
{
converged_ = false;
}
return converged_; return converged_;
} }
@ -100,30 +121,26 @@ void Foam::SolverPerformance<Type>::print
Ostream& os Ostream& os
) const ) const
{ {
for(direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++) for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; ++cmpt)
{ {
if (pTraits<Type>::nComponents == 1) os << solverName_ << ": Solving for " << fieldName_;
if (pTraits<Type>::nComponents > 1)
{ {
os << solverName_ << ": Solving for " << fieldName_; os << pTraits<Type>::componentNames[cmpt];
}
else
{
os << solverName_ << ": Solving for "
<< word(fieldName_ + pTraits<Type>::componentNames[cmpt]);
} }
if (singular_[cmpt]) if (singular_[cmpt])
{ {
os << ": solution singularity" << endl; os << ": solution singularity";
} }
else else
{ {
os << ", Initial residual = " << component(initialResidual_, cmpt) os << ", Initial residual = " << component(initialResidual_, cmpt)
<< ", Final residual = " << component(finalResidual_, cmpt) << ", Final residual = " << component(finalResidual_, cmpt)
<< ", No Iterations " << nIterations_ << ", No Iterations " << nIterations_
<< endl; << ", Timing = " << timing_[cmpt];
} }
os << endl;
} }
} }
@ -139,12 +156,13 @@ void Foam::SolverPerformance<Type>::replace
finalResidual_.replace(cmpt, sp.finalResidual()); finalResidual_.replace(cmpt, sp.finalResidual());
nIterations_.replace(cmpt, sp.nIterations()); nIterations_.replace(cmpt, sp.nIterations());
singular_[cmpt] = sp.singular(); singular_[cmpt] = sp.singular();
timing_[cmpt] = sp.timing();
} }
template<class Type> template<class Type>
Foam::SolverPerformance<typename Foam::pTraits<Type>::cmptType> Foam::SolverPerformance<typename Foam::pTraits<Type>::cmptType>
Foam::SolverPerformance<Type>::max() Foam::SolverPerformance<Type>::max() const
{ {
return SolverPerformance<typename pTraits<Type>::cmptType> return SolverPerformance<typename pTraits<Type>::cmptType>
( (
@ -154,46 +172,49 @@ Foam::SolverPerformance<Type>::max()
cmptMax(finalResidual_), cmptMax(finalResidual_),
cmptMax(nIterations_), cmptMax(nIterations_),
converged_, converged_,
singular() singular(),
maxTiming()
); );
} }
template<class Type> template<class Type>
bool Foam::SolverPerformance<Type>::operator!= bool Foam::operator!=
( (
const SolverPerformance<Type>& sp const SolverPerformance<Type>& a,
) const const SolverPerformance<Type>& b
)
{ {
return return
( (
solverName() != sp.solverName() a.solverName() != b.solverName()
|| fieldName() != sp.fieldName() || a.fieldName() != b.fieldName()
|| initialResidual() != sp.initialResidual() || a.initialResidual() != b.initialResidual()
|| finalResidual() != sp.finalResidual() || a.finalResidual() != b.finalResidual()
|| nIterations() != sp.nIterations() || a.nIterations() != b.nIterations()
|| converged() != sp.converged() || a.converged() != b.converged()
|| singular() != sp.singular() || a.singular() != b.singular()
); );
} }
template<class Type> template<class Type>
typename Foam::SolverPerformance<Type> Foam::max Foam::SolverPerformance<Type> Foam::max
( (
const typename Foam::SolverPerformance<Type>& sp1, const SolverPerformance<Type>& a,
const typename Foam::SolverPerformance<Type>& sp2 const SolverPerformance<Type>& b
) )
{ {
return SolverPerformance<Type> return SolverPerformance<Type>
( (
sp1.solverName(), a.solverName(),
sp1.fieldName_, a.fieldName(),
max(sp1.initialResidual(), sp2.initialResidual()), max(a.initialResidual(), b.initialResidual()),
max(sp1.finalResidual(), sp2.finalResidual()), max(a.finalResidual(), b.finalResidual()),
max(sp1.nIterations(), sp2.nIterations()), max(a.nIterations(), b.nIterations()),
sp1.converged() && sp2.converged(), a.converged() && b.converged(),
sp1.singular() || sp2.singular() a.singular() || b.singular(),
max(a.maxTiming(), b.maxTiming())
); );
} }
@ -212,7 +233,8 @@ Foam::Istream& Foam::operator>>
>> sp.finalResidual_ >> sp.finalResidual_
>> sp.nIterations_ >> sp.nIterations_
>> sp.converged_ >> sp.converged_
>> sp.singular_; >> sp.singular_
>> sp.timing_;
is.readEnd("SolverPerformance"); is.readEnd("SolverPerformance");
return is; return is;
@ -234,6 +256,7 @@ Foam::Ostream& Foam::operator<<
<< sp.nIterations_ << token::SPACE << sp.nIterations_ << token::SPACE
<< sp.converged_ << token::SPACE << sp.converged_ << token::SPACE
<< sp.singular_ << token::SPACE << sp.singular_ << token::SPACE
<< sp.timing_ << token::SPACE
<< token::END_LIST; << token::END_LIST;
return os; return os;

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2012-2016 OpenFOAM Foundation Copyright (C) 2012-2016 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -40,37 +41,28 @@ SourceFiles
#include "word.H" #include "word.H"
#include "FixedList.H" #include "FixedList.H"
#include "clockValue.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
// Forward declaration of friend functions and operators // Forward Declarations
template<class Type> class SolverPerformance;
template<class Type>
class SolverPerformance;
template<class Type> template<class Type>
SolverPerformance<Type> max SolverPerformance<Type> max
( (
const SolverPerformance<Type>&, const SolverPerformance<Type>& sp1,
const SolverPerformance<Type>& const SolverPerformance<Type>& sp2
); );
template<class Type> template<class Type>
Istream& operator>> Istream& operator>>(Istream& is, SolverPerformance<Type>& sp);
(
Istream&,
SolverPerformance<Type>&
);
template<class Type> template<class Type>
Ostream& operator<< Ostream& operator<<(Ostream& os, const SolverPerformance<Type>& sp);
(
Ostream&,
const SolverPerformance<Type>&
);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
@ -83,7 +75,7 @@ class SolverPerformance
// Label type corresponding to Type // Label type corresponding to Type
typedef typename pTraits<Type>::labelType labelType; typedef typename pTraits<Type>::labelType labelType;
// Private data // Private Data
word solverName_; word solverName_;
word fieldName_; word fieldName_;
@ -92,37 +84,44 @@ class SolverPerformance
labelType nIterations_; labelType nIterations_;
bool converged_; bool converged_;
FixedList<bool, pTraits<Type>::nComponents> singular_; FixedList<bool, pTraits<Type>::nComponents> singular_;
FixedList<double, pTraits<Type>::nComponents> timing_;
public: public:
// Static data // Static Data
// Declare name of the class and its debug switch //- Declare name of the class and its debug switch
ClassName("SolverPerformance"); ClassName("SolverPerformance");
//- Large Type for the use in solvers //- Large value for the use in solvers
static const scalar great_; static constexpr scalar great_ = 1e20;
//- Small Type for the use in solvers //- Small value for the use in solvers
static const scalar small_; static constexpr scalar small_ = 1e-20;
//- Very small value for the use in solvers
static constexpr scalar vsmall_ = VSMALL;
//- Very small Type for the use in solvers
static const scalar vsmall_;
// Constructors // Constructors
//- Default construct, zero-initialized
SolverPerformance() SolverPerformance()
: :
solverName_(),
fieldName_(),
initialResidual_(Zero), initialResidual_(Zero),
finalResidual_(Zero), finalResidual_(Zero),
nIterations_(Zero), nIterations_(Zero),
converged_(false), converged_(false),
singular_(false) singular_(false),
timing_(Zero)
{} {}
//- Construct for given solver and field, zero-initialized
SolverPerformance SolverPerformance
( (
const word& solverName, const word& solverName,
@ -131,7 +130,8 @@ public:
const Type& fRes = pTraits<Type>::zero, const Type& fRes = pTraits<Type>::zero,
const labelType& nIter = pTraits<labelType>::zero, const labelType& nIter = pTraits<labelType>::zero,
const bool converged = false, const bool converged = false,
const bool singular = false const bool singular = false,
const scalar timingValue = 0
) )
: :
solverName_(solverName), solverName_(solverName),
@ -140,11 +140,15 @@ public:
finalResidual_(fRes), finalResidual_(fRes),
nIterations_(nIter), nIterations_(nIter),
converged_(converged), converged_(converged),
singular_(singular) singular_(singular),
{} timing_(Zero)
{
// Single-value assignment affects single component only
timing_.first() = timingValue;
}
// Member functions // Member Functions
//- Return solver name //- Return solver name
const word& solverName() const const word& solverName() const
@ -158,7 +162,6 @@ public:
return solverName_; return solverName_;
} }
//- Return field name //- Return field name
const word& fieldName() const const word& fieldName() const
{ {
@ -204,7 +207,6 @@ public:
return nIterations_; return nIterations_;
} }
//- Has the solver converged? //- Has the solver converged?
bool converged() const bool converged() const
{ {
@ -214,6 +216,24 @@ public:
//- Is the matrix singular? //- Is the matrix singular?
bool singular() const; bool singular() const;
//- Return total timing, the sum of all components
double timing() const;
//- Add to single-component timing
void addTiming(double timingValue)
{
timing_.first() += timingValue;
}
//- Set single-component timing
void setTiming(double timingValue)
{
timing_.first() = timingValue;
}
//- Return the max timing
double maxTiming() const;
//- Check, store and return convergence //- Check, store and return convergence
bool checkConvergence bool checkConvergence
( (
@ -221,7 +241,7 @@ public:
const Type& relTolerance const Type& relTolerance
); );
//- Singularity test //- Test singularity
bool checkSingularity(const Type& residual); bool checkSingularity(const Type& residual);
//- Print summary of solver performance to the given stream //- Print summary of solver performance to the given stream
@ -236,61 +256,56 @@ public:
//- Return the summary maximum of SolverPerformance<Type> //- Return the summary maximum of SolverPerformance<Type>
// Effectively it will mostly return solverPerformanceScalar // Effectively it will mostly return solverPerformanceScalar
SolverPerformance<typename pTraits<Type>::cmptType> max(); SolverPerformance<typename pTraits<Type>::cmptType> max() const;
// Member Operators
bool operator!=(const SolverPerformance<Type>&) const;
// Friend functions
//- Return the element-wise maximum of two SolverPerformance<Type>s
friend SolverPerformance<Type> Foam::max <Type>
(
const SolverPerformance<Type>&,
const SolverPerformance<Type>&
);
// Ostream Operator // Ostream Operator
friend Istream& operator>> <Type> friend Istream& operator>> <Type>
( (
Istream&, Istream& is,
SolverPerformance<Type>& SolverPerformance<Type>& sp
); );
friend Ostream& operator<< <Type> friend Ostream& operator<< <Type>
( (
Ostream&, Ostream& os,
const SolverPerformance<Type>& const SolverPerformance<Type>& sp
); );
}; };
// Global Operators
//- Test for inequality
template<class Type>
bool operator!=
(
const SolverPerformance<Type>& a,
const SolverPerformance<Type>& b
);
// Global Functions
//- Return element-wise maximum of SolverPerformance
template<class Type>
SolverPerformance<Type> max
(
const SolverPerformance<Type>& a,
const SolverPerformance<Type>& b
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam } // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#define makeSolverPerformance(Type) \ #define makeSolverPerformance(Type) \
\ typedef Foam::SolverPerformance<Type> solverPerformance##Type; \
typedef Foam::SolverPerformance<Type> \ defineNamedTemplateTypeNameAndDebug(solverPerformance##Type, 0);
solverPerformance##Type; \
\
defineNamedTemplateTypeNameAndDebug(solverPerformance##Type, 0); \
\
template<> \
const scalar solverPerformance##Type::great_(1e20); \
\
template<> \
const scalar solverPerformance##Type::small_(1e-20); \
\
template<> \
const scalar solverPerformance##Type::vsmall_(VSMALL); \
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2012-2015 OpenFOAM Foundation Copyright (C) 2012-2015 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -40,10 +41,24 @@ namespace Foam
template<> template<>
Foam::SolverPerformance<Foam::scalar> Foam::SolverPerformance<Foam::scalar>
Foam::SolverPerformance<Foam::scalar>::max() Foam::SolverPerformance<Foam::scalar>::max() const
{ {
return *this; return *this;
} }
template<>
double Foam::SolverPerformance<Foam::scalar>::timing() const
{
return timing_.first();
}
template<>
double Foam::SolverPerformance<Foam::scalar>::maxTiming() const
{
return timing_.first();
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2012-2015 OpenFOAM Foundation Copyright (C) 2012-2015 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -45,9 +46,17 @@ namespace Foam
{ {
typedef SolverPerformance<scalar> solverPerformance; typedef SolverPerformance<scalar> solverPerformance;
// Specialization of the max function for scalar object // Specialize max() member function for scalar
template<> template<>
SolverPerformance<scalar> SolverPerformance<scalar>::max(); SolverPerformance<scalar> SolverPerformance<scalar>::max() const;
// Specialize timing() member function for scalar
template<>
double SolverPerformance<scalar>::timing() const;
// Specialize maxTiming() member function for scalar
template<>
double SolverPerformance<scalar>::maxTiming() const;
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2019 OpenCFD Ltd. Copyright (C) 2019-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -129,10 +129,10 @@ Foam::SolverPerformance<Type> Foam::faMatrix<Type>::solve
); );
} }
solverPerformance solverPerf;
// Solver call // Solver call
solverPerf = lduMatrix::solver::New const auto timing = clockValue::now();
solverPerformance solverPerf = lduMatrix::solver::New
( (
psi_.name() + pTraits<Type>::componentNames[cmpt], psi_.name() + pTraits<Type>::componentNames[cmpt],
*this, *this,
@ -142,6 +142,8 @@ Foam::SolverPerformance<Type> Foam::faMatrix<Type>::solve
solverControls solverControls
)->solve(psiCmpt, sourceCmpt, cmpt); )->solve(psiCmpt, sourceCmpt, cmpt);
solverPerf.setTiming(timing.elapsedTime());
if (SolverPerformance<Type>::debug) if (SolverPerformance<Type>::debug)
{ {
solverPerf.print(Info); solverPerf.print(Info);

View File

@ -203,10 +203,11 @@ Foam::SolverPerformance<Type> Foam::fvMatrix<Type>::solveSegregated
); );
} }
solverPerformance solverPerf;
// Solver call // Solver call
solverPerf = lduMatrix::solver::New const auto timing = clockValue::now();
solverPerformance solverPerf = lduMatrix::solver::New
( (
psi.name() + pTraits<Type>::componentNames[cmpt], psi.name() + pTraits<Type>::componentNames[cmpt],
*this, *this,
@ -216,6 +217,8 @@ Foam::SolverPerformance<Type> Foam::fvMatrix<Type>::solveSegregated
solverControls solverControls
)->solve(psiCmpt, sourceCmpt, cmpt); )->solve(psiCmpt, sourceCmpt, cmpt);
solverPerf.setTiming(timing.elapsedTime());
if (SolverPerformance<Type>::debug) if (SolverPerformance<Type>::debug)
{ {
solverPerf.print(Info.masterStream(this->mesh().comm())); solverPerf.print(Info.masterStream(this->mesh().comm()));