ENH: runTimeControl FO - added exact window averaging to the averageCondition

This commit is contained in:
Andrew Heather
2018-08-20 14:03:57 +01:00
parent 8b387961d9
commit e64a87cd8e
3 changed files with 176 additions and 50 deletions

View File

@ -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<wordList>("fields")),
tolerance_(dict.get<scalar>("tolerance")),
window_(dict.lookupOrDefault<scalar>("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<bool>("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<scalar>(fieldName, alpha, beta, satisfied, processed);
calc<vector>(fieldName, alpha, beta, satisfied, processed);
calc<sphericalTensor>(fieldName, alpha, beta, satisfied, processed);
calc<symmTensor>(fieldName, alpha, beta, satisfied, processed);
calc<tensor>(fieldName, alpha, beta, satisfied, processed);
calc<scalar>(fieldi, satisfied, processed);
calc<vector>(fieldi, satisfied, processed);
calc<sphericalTensor>(fieldi, satisfied, processed);
calc<symmTensor>(fieldi, satisfied, processed);
calc<tensor>(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);

View File

@ -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<windowType> windowTypeNames;
protected:
// Protected data
@ -74,6 +88,9 @@ protected:
//- Averaging window
const scalar window_;
//- Averaging window type
windowType windowType_;
//- Average time per field
List<scalar> totalTime_;
@ -87,9 +104,7 @@ protected:
template<class Type>
void calc
(
const word& fieldName,
const scalar alpha,
const scalar beta,
const label fieldi,
bool& satisfied,
bool& processed
);

View File

@ -23,18 +23,21 @@ License
\*---------------------------------------------------------------------------*/
#include "Time.H"
#include "FIFOStack.H"
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
template<class Type>
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<Type>(functionObjectName_, fieldName);
const scalar dt = obr_.time().deltaTValue();
const Type currentValue =
state_.getObjectResult<Type>(functionObjectName_, fieldName);
const word meanName(fieldName + "Mean");
// Current mean value
Type meanValue = state_.getResult<Type>(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<scalar> windowTimes;
FIFOStack<Type> 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<scalar>::const_iterator timeIter =
windowTimes.begin();
typename FIFOStack<Type>::const_iterator valueIter =
windowValues.begin();
meanValue = pTraits<Type>::zero;
Type valueOld(pTraits<Type>::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_)