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 * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -57,21 +68,35 @@ Foam::functionObjects::runTimeControls::averageCondition::averageCondition
|
|||||||
fieldNames_(dict.get<wordList>("fields")),
|
fieldNames_(dict.get<wordList>("fields")),
|
||||||
tolerance_(dict.get<scalar>("tolerance")),
|
tolerance_(dict.get<scalar>("tolerance")),
|
||||||
window_(dict.lookupOrDefault<scalar>("window", -1)),
|
window_(dict.lookupOrDefault<scalar>("window", -1)),
|
||||||
totalTime_(fieldNames_.size(), obr_.time().deltaTValue()),
|
windowType_
|
||||||
resetOnRestart_(false)
|
(
|
||||||
|
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();
|
||||||
{
|
|
||||||
const dictionary& dict = conditionDict();
|
|
||||||
|
|
||||||
forAll(fieldNames_, fieldi)
|
forAll(fieldNames_, fieldi)
|
||||||
{
|
{
|
||||||
const word& fieldName = fieldNames_[fieldi];
|
const word& fieldName = fieldNames_[fieldi];
|
||||||
|
|
||||||
if (dict.found(fieldName))
|
if (resetOnRestart_)
|
||||||
{
|
{
|
||||||
const dictionary& valueDict = dict.subDict(fieldName);
|
conditionDict.set(fieldName, dictionary());
|
||||||
valueDict.readEntry("totalTime", totalTime_[fieldi]);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (conditionDict.found(fieldName))
|
||||||
|
{
|
||||||
|
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;
|
return satisfied;
|
||||||
}
|
}
|
||||||
|
|
||||||
scalar dt = obr_.time().deltaTValue();
|
const scalar dt = obr_.time().deltaTValue();
|
||||||
|
|
||||||
if (log_) Info<< " " << type() << ": " << name_ << " averages:" << nl;
|
if (log_) Info<< " " << type() << ": " << name_ << " averages:" << nl;
|
||||||
|
|
||||||
@ -97,40 +122,19 @@ bool Foam::functionObjects::runTimeControls::averageCondition::apply()
|
|||||||
|
|
||||||
forAll(fieldNames_, fieldi)
|
forAll(fieldNames_, fieldi)
|
||||||
{
|
{
|
||||||
const word& fieldName(fieldNames_[fieldi]);
|
totalTime_[fieldi] += dt;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool processed = false;
|
bool processed = false;
|
||||||
calc<scalar>(fieldName, alpha, beta, satisfied, processed);
|
calc<scalar>(fieldi, satisfied, processed);
|
||||||
calc<vector>(fieldName, alpha, beta, satisfied, processed);
|
calc<vector>(fieldi, satisfied, processed);
|
||||||
calc<sphericalTensor>(fieldName, alpha, beta, satisfied, processed);
|
calc<sphericalTensor>(fieldi, satisfied, processed);
|
||||||
calc<symmTensor>(fieldName, alpha, beta, satisfied, processed);
|
calc<symmTensor>(fieldi, satisfied, processed);
|
||||||
calc<tensor>(fieldName, alpha, beta, satisfied, processed);
|
calc<tensor>(fieldi, satisfied, processed);
|
||||||
|
|
||||||
if (!processed)
|
if (!processed)
|
||||||
{
|
{
|
||||||
unprocessedFields.append(fieldi);
|
unprocessedFields.append(fieldi);
|
||||||
}
|
}
|
||||||
|
|
||||||
totalTime_[fieldi] += dt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unprocessedFields.size())
|
if (unprocessedFields.size())
|
||||||
@ -159,7 +163,6 @@ void Foam::functionObjects::runTimeControls::averageCondition::write()
|
|||||||
{
|
{
|
||||||
const word& fieldName = fieldNames_[fieldi];
|
const word& fieldName = fieldNames_[fieldi];
|
||||||
|
|
||||||
// value dictionary should be present - mean values are written there
|
|
||||||
if (conditionDict.found(fieldName))
|
if (conditionDict.found(fieldName))
|
||||||
{
|
{
|
||||||
dictionary& valueDict = conditionDict.subDict(fieldName);
|
dictionary& valueDict = conditionDict.subDict(fieldName);
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
|
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
|
||||||
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
|
\\/ M anipulation | Copyright (C) 2016-2018 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -39,7 +39,7 @@ SourceFiles
|
|||||||
|
|
||||||
#include "runTimeCondition.H"
|
#include "runTimeCondition.H"
|
||||||
#include "Switch.H"
|
#include "Switch.H"
|
||||||
|
#include "Enum.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -58,6 +58,20 @@ class averageCondition
|
|||||||
:
|
:
|
||||||
public runTimeCondition
|
public runTimeCondition
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Public enumerations
|
||||||
|
|
||||||
|
enum class windowType
|
||||||
|
{
|
||||||
|
NONE,
|
||||||
|
APPROXIMATE,
|
||||||
|
EXACT
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Enum<windowType> windowTypeNames;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Protected data
|
// Protected data
|
||||||
@ -74,6 +88,9 @@ protected:
|
|||||||
//- Averaging window
|
//- Averaging window
|
||||||
const scalar window_;
|
const scalar window_;
|
||||||
|
|
||||||
|
//- Averaging window type
|
||||||
|
windowType windowType_;
|
||||||
|
|
||||||
//- Average time per field
|
//- Average time per field
|
||||||
List<scalar> totalTime_;
|
List<scalar> totalTime_;
|
||||||
|
|
||||||
@ -87,9 +104,7 @@ protected:
|
|||||||
template<class Type>
|
template<class Type>
|
||||||
void calc
|
void calc
|
||||||
(
|
(
|
||||||
const word& fieldName,
|
const label fieldi,
|
||||||
const scalar alpha,
|
|
||||||
const scalar beta,
|
|
||||||
bool& satisfied,
|
bool& satisfied,
|
||||||
bool& processed
|
bool& processed
|
||||||
);
|
);
|
||||||
|
|||||||
@ -23,18 +23,21 @@ License
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "Time.H"
|
||||||
|
#include "FIFOStack.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
|
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
void Foam::functionObjects::runTimeControls::averageCondition::calc
|
void Foam::functionObjects::runTimeControls::averageCondition::calc
|
||||||
(
|
(
|
||||||
const word& fieldName,
|
const label fieldi,
|
||||||
const scalar alpha,
|
|
||||||
const scalar beta,
|
|
||||||
bool& satisfied,
|
bool& satisfied,
|
||||||
bool& processed
|
bool& processed
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
const word& fieldName = fieldNames_[fieldi];
|
||||||
|
|
||||||
const word valueType =
|
const word valueType =
|
||||||
state_.objectResultType(functionObjectName_, fieldName);
|
state_.objectResultType(functionObjectName_, fieldName);
|
||||||
|
|
||||||
@ -43,14 +46,117 @@ void Foam::functionObjects::runTimeControls::averageCondition::calc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type currentValue =
|
const scalar dt = obr_.time().deltaTValue();
|
||||||
state_.getObjectResult<Type>(functionObjectName_, fieldName);
|
|
||||||
|
|
||||||
|
const Type currentValue =
|
||||||
|
state_.getObjectResult<Type>(functionObjectName_, fieldName);
|
||||||
const word meanName(fieldName + "Mean");
|
const word meanName(fieldName + "Mean");
|
||||||
|
|
||||||
|
// Current mean value
|
||||||
Type meanValue = state_.getResult<Type>(meanName);
|
Type meanValue = state_.getResult<Type>(meanName);
|
||||||
|
|
||||||
|
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;
|
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);
|
scalar delta = mag(meanValue - currentValue);
|
||||||
|
|
||||||
if (log_)
|
if (log_)
|
||||||
@ -59,6 +165,8 @@ void Foam::functionObjects::runTimeControls::averageCondition::calc
|
|||||||
<< ", delta: " << delta << nl;
|
<< ", delta: " << delta << nl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: Writing result to owner function object and not the local run-time
|
||||||
|
// condition
|
||||||
state_.setResult(meanName, meanValue);
|
state_.setResult(meanName, meanValue);
|
||||||
|
|
||||||
if (delta > tolerance_)
|
if (delta > tolerance_)
|
||||||
|
|||||||
Reference in New Issue
Block a user