diff --git a/src/petsc4Foam/utils/petscCacheManager.H b/src/petsc4Foam/utils/petscCacheManager.H index 8238127252879e988dbf61abec388b7db55843a7..b69712be855d9cf4a994c64d910845f4981a3805 100644 --- a/src/petsc4Foam/utils/petscCacheManager.H +++ b/src/petsc4Foam/utils/petscCacheManager.H @@ -99,20 +99,23 @@ struct Caching // Member Data - //- Caching update + //- Caching update type updateTypes updateType_; //- Cache update frequency (for Periodic) int updateFreq_; + //- Relative iteration (for Adaptive or Periodic) + int relIter_; + //- Elapsed time (s) for current iteration - double timeIter; + double timeIter_; //- Elapsed time (s) for first iteration - double time0; + double time0_; //- Elapsed time (s) for second iteration - double time1; + double time1_; //- Timer value clockValue timer_; @@ -125,30 +128,152 @@ struct Caching : updateType_{updateTypes::Always}, updateFreq_{1}, - timeIter{0}, - time0{0}, - time1{0} + relIter_{0}, + timeIter_{0}, + time0_{0}, + time1_{0} {} - void init(const word& key, const dictionary& dict) - { - dictionary cacheDict = dict.subOrEmptyDict(key); - updateType_ = - updateTypeNames_.getOrDefault - ( - "update", - cacheDict, - updateTypes::Always, - false // non-failsafe - Fatal on bad enumeration - ); - - if (updateType_ == updateTypes::Periodic) + // Member Functions + + //- The caching type + updateTypes type() const noexcept { - dictionary coeffs(cacheDict.subOrEmptyDict("periodicCoeffs")); - updateFreq_ = coeffs.getOrDefault<int>("frequency", 1); + return updateType_; + } + + //- True if caching type is Adaptive + bool isAdaptive() const noexcept + { + return updateTypes::Adaptive == updateType_; + } + + //- True if caching type is Periodic + bool isPeriodic() const noexcept + { + return updateTypes::Periodic == updateType_; + } + + + //- Initialize from dictionay + void init(const word& key, const dictionary& dict) + { + relIter_ = 0; + + dictionary cacheDict = dict.subOrEmptyDict(key); + updateType_ = + updateTypeNames_.getOrDefault + ( + "update", + cacheDict, + updateTypes::Always, + false // non-failsafe - Fatal on bad enumeration + ); + + if (updateTypes::Periodic == updateType_) + { + dictionary coeffs(cacheDict.subOrEmptyDict("periodicCoeffs")); + updateFreq_ = coeffs.getOrDefault<int>("frequency", 1); + } + } + + + //- Begin/restart timing for iterations + void beginTimes() + { + timer_.update(); + } + + + //- Update timing for iterations + void updateTimes() + { + // Elapsed timing interval (s) + timeIter_ = timer_.elapsed(); + + if (relIter_ == 0) + { + time0_ = timeIter_; + } + else if (relIter_ == 1) + { + time1_ = timeIter_; + } + } + + + //- Check if an update is required + bool needsUpdate() + { + // Default: Always update + bool need = true; + + switch (updateType_) + { + case updateTypes::Never: + { + need = false; + break; + } + + case updateTypes::Always: + { + break; + } + + case updateTypes::Periodic: + { + if + ( + updateFreq_ <= 1 + || (relIter_ % updateFreq_) == 0 + ) + { + relIter_ = 0; + } + else + { + need = false; + } + break; + } + + case updateTypes::Adaptive: + { + if (relIter_ > 3) // Need at least three iterations + { + const double ratio0 = time0_ / timeIter_; + + const double ratio1 = time1_ / timeIter_; + + const int nsteps = + min(1e5, ratio0 * (1. / mag(1. - ratio1 + 1e-6))); + + if (relIter_ >= nsteps) + { + relIter_ = 0; + } + else + { + need = false; + } + } + break; + } + } + + return need; + } + + + // Member Operators + + //- Increment the relative iteration + void operator++() + { + ++relIter_; } - } }; } // End namespace PetscUtils @@ -162,12 +287,6 @@ class petscCacheManager { // Private Data - //- The current (relative) iterations for matrix - label miter; - - //- The current (relative) iterations for preconditioner - label piter; - PetscUtils::Caching matrixCaching; PetscUtils::Caching precondCaching; @@ -177,11 +296,7 @@ public: // Constructors //- Default construct - petscCacheManager() - : - miter{0}, - piter{0} - {} + petscCacheManager() = default; //- Destructor @@ -197,124 +312,43 @@ public: // Member Functions - bool needsMatrixUpdate() - { - return needsUpdate(matrixCaching, miter); - } - - bool needsPrecondUpdate() - { - return needsUpdate(precondCaching, piter); - } - - void eventBegin() - { - if (precondCaching.updateType_ == PetscUtils::Caching::Adaptive) + bool needsMatrixUpdate() { - // Begin timing interval - precondCaching.timer_.update(); + return matrixCaching.needsUpdate(); } - } - void eventEnd() - { - if (precondCaching.updateType_ == PetscUtils::Caching::Adaptive) + bool needsPrecondUpdate() { - // Elapsed timing interval (s) - precondCaching.timeIter = precondCaching.timer_.elapsed(); + return precondCaching.needsUpdate(); + } - if (piter == 0) - { - precondCaching.time0 = precondCaching.timeIter; - } - else if (piter == 1) + void eventBegin() + { + if (precondCaching.isAdaptive()) { - precondCaching.time1 = precondCaching.timeIter; + precondCaching.beginTimes(); } - } - if - ( - precondCaching.updateType_ == PetscUtils::Caching::Periodic - || precondCaching.updateType_ == PetscUtils::Caching::Adaptive - ) - { - ++piter; + // Should we handle/disable Adaptive for matrixCaching? } - if - ( - matrixCaching.updateType_ == PetscUtils::Caching::Periodic - ) - { - ++miter; - } - } - -private: - - bool needsUpdate(const PetscUtils::Caching& caching, label& iter) const - { - // Default: Always update - bool need = true; - - switch (caching.updateType_) + void eventEnd() { - case PetscUtils::Caching::Never: + if (precondCaching.isAdaptive()) { - need = false; - break; + precondCaching.updateTimes(); + ++precondCaching; } - - case PetscUtils::Caching::Always: + else if (precondCaching.isPeriodic()) { - break; - } - - case PetscUtils::Caching::Periodic: - { - if - ( - caching.updateFreq_ <= 1 - || (iter % caching.updateFreq_) == 0 - ) - { - iter = 0; - } - else - { - need = false; - } - break; + ++precondCaching; } - case PetscUtils::Caching::Adaptive: + // Should we handle/disable Adaptive for matrixCaching? + if (matrixCaching.isPeriodic()) { - if (iter > 3) // we need at least three times - { - const double ratio0 = - caching.time0 / caching.timeIter; - - const double ratio1 = - caching.time1 / caching.timeIter; - - const int nsteps = - min(1e5, ratio0 * (1. / mag(1. - ratio1 + 1e-6))); - - if (iter >= nsteps) - { - iter = 0; - } - else - { - need = false; - } - } - break; + ++matrixCaching; } - } - - return need; } };