From e64a87cd8e3531a4e4e74e2b0fcd6d078b4bc79a Mon Sep 17 00:00:00 2001 From: Andrew Heather <> Date: Mon, 20 Aug 2018 14:03:57 +0100 Subject: [PATCH] ENH: runTimeControl FO - added exact window averaging to the averageCondition --- .../averageCondition/averageCondition.C | 81 ++++++------ .../averageCondition/averageCondition.H | 25 +++- .../averageConditionTemplates.C | 120 +++++++++++++++++- 3 files changed, 176 insertions(+), 50 deletions(-) diff --git a/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageCondition.C b/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageCondition.C index 0b3951bf99..0c66af7fb0 100644 --- a/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageCondition.C +++ b/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageCondition.C @@ -41,6 +41,17 @@ namespace runTimeControls } } +const Foam::Enum +< + Foam::functionObjects::runTimeControls::averageCondition::windowType +> +Foam::functionObjects::runTimeControls::averageCondition::windowTypeNames +{ + { windowType::NONE, "none" }, + { windowType::APPROXIMATE, "approximate" }, + { windowType::EXACT, "exact" } +}; + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -57,21 +68,35 @@ Foam::functionObjects::runTimeControls::averageCondition::averageCondition fieldNames_(dict.get("fields")), tolerance_(dict.get("tolerance")), window_(dict.lookupOrDefault("window", -1)), - totalTime_(fieldNames_.size(), obr_.time().deltaTValue()), - resetOnRestart_(false) + windowType_ + ( + window_ > 0 ? + windowTypeNames.read(dict.lookup("windowType")) + : windowType::NONE + ), + totalTime_(fieldNames_.size(), scalar(0)), + resetOnRestart_(dict.lookupOrDefault("resetOnRestart", false)) { - if (resetOnRestart_) + dictionary& conditionDict = this->conditionDict(); + + forAll(fieldNames_, fieldi) { - const dictionary& dict = conditionDict(); + const word& fieldName = fieldNames_[fieldi]; - forAll(fieldNames_, fieldi) + if (resetOnRestart_) { - const word& fieldName = fieldNames_[fieldi]; - - if (dict.found(fieldName)) + conditionDict.set(fieldName, dictionary()); + } + else + { + if (conditionDict.found(fieldName)) { - const dictionary& valueDict = dict.subDict(fieldName); - valueDict.readEntry("totalTime", totalTime_[fieldi]); + const dictionary& valueDict = conditionDict.subDict(fieldName); + valueDict.readIfPresent("totalTime", totalTime_[fieldi]); + } + else + { + conditionDict.set(fieldName, dictionary()); } } } @@ -89,7 +114,7 @@ bool Foam::functionObjects::runTimeControls::averageCondition::apply() return satisfied; } - scalar dt = obr_.time().deltaTValue(); + const scalar dt = obr_.time().deltaTValue(); if (log_) Info<< " " << type() << ": " << name_ << " averages:" << nl; @@ -97,40 +122,19 @@ bool Foam::functionObjects::runTimeControls::averageCondition::apply() forAll(fieldNames_, fieldi) { - const word& fieldName(fieldNames_[fieldi]); - - scalar Dt = totalTime_[fieldi]; - scalar alpha = (Dt - dt)/Dt; - scalar beta = dt/Dt; - - if (window_ > 0) - { - if (Dt - dt >= window_) - { - alpha = (window_ - dt)/window_; - beta = dt/window_; - } - else - { - // Ensure that averaging is performed over window time - // before condition can be satisfied - satisfied = false; - } - } + totalTime_[fieldi] += dt; bool processed = false; - calc(fieldName, alpha, beta, satisfied, processed); - calc(fieldName, alpha, beta, satisfied, processed); - calc(fieldName, alpha, beta, satisfied, processed); - calc(fieldName, alpha, beta, satisfied, processed); - calc(fieldName, alpha, beta, satisfied, processed); + calc(fieldi, satisfied, processed); + calc(fieldi, satisfied, processed); + calc(fieldi, satisfied, processed); + calc(fieldi, satisfied, processed); + calc(fieldi, satisfied, processed); if (!processed) { unprocessedFields.append(fieldi); } - - totalTime_[fieldi] += dt; } if (unprocessedFields.size()) @@ -159,7 +163,6 @@ void Foam::functionObjects::runTimeControls::averageCondition::write() { const word& fieldName = fieldNames_[fieldi]; - // value dictionary should be present - mean values are written there if (conditionDict.found(fieldName)) { dictionary& valueDict = conditionDict.subDict(fieldName); diff --git a/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageCondition.H b/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageCondition.H index 5c647b2981..c295602515 100644 --- a/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageCondition.H +++ b/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageCondition.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2015 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2016-2018 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -39,7 +39,7 @@ SourceFiles #include "runTimeCondition.H" #include "Switch.H" - +#include "Enum.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -58,6 +58,20 @@ class averageCondition : public runTimeCondition { +public: + + // Public enumerations + + enum class windowType + { + NONE, + APPROXIMATE, + EXACT + }; + + static const Enum windowTypeNames; + + protected: // Protected data @@ -74,6 +88,9 @@ protected: //- Averaging window const scalar window_; + //- Averaging window type + windowType windowType_; + //- Average time per field List totalTime_; @@ -87,9 +104,7 @@ protected: template void calc ( - const word& fieldName, - const scalar alpha, - const scalar beta, + const label fieldi, bool& satisfied, bool& processed ); diff --git a/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageConditionTemplates.C b/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageConditionTemplates.C index 9b0b134987..1631bd43fb 100644 --- a/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageConditionTemplates.C +++ b/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageConditionTemplates.C @@ -23,18 +23,21 @@ License \*---------------------------------------------------------------------------*/ +#include "Time.H" +#include "FIFOStack.H" + // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * // template void Foam::functionObjects::runTimeControls::averageCondition::calc ( - const word& fieldName, - const scalar alpha, - const scalar beta, + const label fieldi, bool& satisfied, bool& processed ) { + const word& fieldName = fieldNames_[fieldi]; + const word valueType = state_.objectResultType(functionObjectName_, fieldName); @@ -43,13 +46,116 @@ void Foam::functionObjects::runTimeControls::averageCondition::calc return; } - Type currentValue = - state_.getObjectResult(functionObjectName_, fieldName); + const scalar dt = obr_.time().deltaTValue(); + const Type currentValue = + state_.getObjectResult(functionObjectName_, fieldName); const word meanName(fieldName + "Mean"); + // Current mean value Type meanValue = state_.getResult(meanName); - meanValue = alpha*meanValue + beta*currentValue; + + switch (windowType_) + { + case windowType::NONE: + { + const scalar Dt = totalTime_[fieldi]; + const scalar alpha = (Dt - dt)/Dt; + const scalar beta = dt/Dt; + meanValue = alpha*meanValue + beta*currentValue; + + break; + } + case windowType::APPROXIMATE: + { + const scalar Dt = totalTime_[fieldi]; + scalar alpha = (Dt - dt)/Dt; + scalar beta = dt/Dt; + if (Dt - dt >= window_) + { + alpha = (window_ - dt)/window_; + beta = dt/window_; + } + else + { + // Ensure that averaging is performed over window time + // before condition can be satisfied + satisfied = false; + } + + meanValue = alpha*meanValue + beta*currentValue; + totalTime_[fieldi] += dt; + break; + } + case windowType::EXACT: + { + FIFOStack windowTimes; + FIFOStack windowValues; + dictionary& dict = this->conditionDict().subDict(fieldName); + dict.readIfPresent("windowTimes", windowTimes); + dict.readIfPresent("windowValues", windowValues); + + // Increment time for all existing values + for (scalar& dti : windowTimes) + { + dti += dt; + } + + // Remove any values outside the window + bool removeValue = true; + while (removeValue && windowTimes.size()) + { + removeValue = windowTimes.first() > window_; + + if (removeValue) + { + windowTimes.pop(); + windowValues.pop(); + } + } + + // Add the current value + windowTimes.push(dt); + windowValues.push(currentValue); + + // Calculate the window average + typename FIFOStack::const_iterator timeIter = + windowTimes.begin(); + typename FIFOStack::const_iterator valueIter = + windowValues.begin(); + + meanValue = pTraits::zero; + Type valueOld(pTraits::zero); + + for + ( + label i = 0; + timeIter != windowTimes.end(); + ++i, ++timeIter, ++valueIter + ) + { + const Type& value = valueIter(); + const scalar dt = timeIter(); + + meanValue += dt*value; + + if (i) + { + meanValue -= dt*valueOld; + } + + valueOld = value; + } + + meanValue /= windowTimes.first(); + + // Store the state information for the next step + dict.set("windowTimes", windowTimes); + dict.set("windowValues", windowValues); + + break; + } + } scalar delta = mag(meanValue - currentValue); @@ -59,6 +165,8 @@ void Foam::functionObjects::runTimeControls::averageCondition::calc << ", delta: " << delta << nl; } + // Note: Writing result to owner function object and not the local run-time + // condition state_.setResult(meanName, meanValue); if (delta > tolerance_)