mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: runTimeControl FO - added exact window averaging to the averageCondition
This commit is contained in:
@ -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);
|
||||
|
||||
@ -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
|
||||
);
|
||||
|
||||
@ -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_)
|
||||
|
||||
Reference in New Issue
Block a user