ENH: Refactored valueAverage FO and average runTimeCondition

This commit is contained in:
Andrew Heather
2022-02-02 13:35:29 +00:00
committed by Mark Olesen
parent bb04f5759d
commit 3d134167dd
10 changed files with 493 additions and 448 deletions

View File

@ -5,8 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2015 OpenFOAM Foundation
Copyright (C) 2015-2022 OpenCFD Ltd.
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,7 +27,6 @@ License
#include "averageCondition.H"
#include "addToRunTimeSelectionTable.H"
#include "Time.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -44,18 +42,6 @@ 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 * * * * * * * * * * * * * * //
Foam::functionObjects::runTimeControls::averageCondition::averageCondition
@ -67,45 +53,15 @@ Foam::functionObjects::runTimeControls::averageCondition::averageCondition
)
:
runTimeCondition(name, obr, dict, state),
functionObjectName_(dict.get<word>("functionObject")),
fieldNames_(dict.get<wordList>("fields")),
tolerance_(dict.get<scalar>("tolerance")),
window_(dict.getOrDefault<scalar>("window", -1)),
windowType_
(
window_ > 0
? windowTypeNames.get("windowType", dict)
: windowType::NONE
),
totalTime_(fieldNames_.size(), scalar(0)),
resetOnRestart_(dict.getOrDefault("resetOnRestart", false)),
valueAverageBase(name, obr_, dict, state, false),
nIterStartUp_(dict.getOrDefault<label>("nIterStartUp", 10)),
iter_(-1)
{
dictionary& conditionDict = this->conditionDict();
readState(conditionDict);
conditionDict.readIfPresent("iter", iter_);
if (resetOnRestart_)
{
reset();
}
else
{
forAll(fieldNames_, fieldi)
{
const word& fieldName = fieldNames_[fieldi];
if (conditionDict.found(fieldName))
{
const dictionary& valueDict = conditionDict.subDict(fieldName);
valueDict.readIfPresent("totalTime", totalTime_[fieldi]);
}
else
{
conditionDict.set(fieldName, dictionary());
}
}
}
}
@ -118,53 +74,18 @@ bool Foam::functionObjects::runTimeControls::averageCondition::apply()
return true;
}
bool satisfied = iter_ > nIterStartUp_;
bool running = iter_ > nIterStartUp_;
++iter_;
const scalar dt = obr_.time().deltaTValue();
dictionary& conditionDict = this->conditionDict();
Log << " " << type() << ": " << name_ << " averages:" << nl;
DynamicList<label> unprocessedFields(fieldNames_.size());
Info<< incrIndent;
running = valueAverageBase::calculate(conditionDict) && running;
Info<< decrIndent;
forAll(fieldNames_, fieldi)
{
totalTime_[fieldi] += dt;
bool processed = false;
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);
}
}
if (unprocessedFields.size())
{
WarningInFunction
<< "From function object: " << functionObjectName_ << nl
<< "Unprocessed fields:" << nl;
for (const label fieldi : unprocessedFields)
{
Info<< " " << fieldNames_[fieldi] << nl;
}
if (unprocessedFields.size() == fieldNames_.size())
{
satisfied = false;
}
}
Log << endl;
return satisfied;
return running;
}
@ -172,22 +93,7 @@ void Foam::functionObjects::runTimeControls::averageCondition::write()
{
dictionary& conditionDict = this->conditionDict();
forAll(fieldNames_, fieldi)
{
const word& fieldName = fieldNames_[fieldi];
if (conditionDict.found(fieldName))
{
dictionary& valueDict = conditionDict.subDict(fieldName);
valueDict.add("totalTime", totalTime_[fieldi], true);
}
else
{
dictionary valueDict;
valueDict.add("totalTime", totalTime_[fieldi], true);
conditionDict.add(fieldName, valueDict);
}
}
valueAverageBase::writeState(conditionDict);
conditionDict.set("iter", iter_);
}
@ -195,18 +101,9 @@ void Foam::functionObjects::runTimeControls::averageCondition::write()
void Foam::functionObjects::runTimeControls::averageCondition::reset()
{
dictionary& conditionDict = this->conditionDict();
valueAverageBase::resetState(this->conditionDict());
forAll(fieldNames_, fieldi)
{
const word& fieldName = fieldNames_[fieldi];
conditionDict.set(fieldName, dictionary());
totalTime_[fieldi] = 0;
}
iter_ = -1;
conditionDict.set("iter", iter_);
iter_ = 0;
}

View File

@ -5,8 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2015 OpenFOAM Foundation
Copyright (C) 2016-2022 OpenCFD Ltd.
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -31,18 +30,20 @@ Description
Average run time condition - satisfied when average does not change by
more than a given value.
See also
- Foam::functionObjects::valueAverageBase
SourceFiles
averageCondition.H
averageCondition.C
\*---------------------------------------------------------------------------*/
#ifndef averageCondition_H
#define averageCondition_H
#ifndef functionObjects_runTimeControls_averageCondition_H
#define functionObjects_runTimeControls_averageCondition_H
#include "runTimeCondition.H"
#include "Switch.H"
#include "Enum.H"
#include "valueAverageBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -59,64 +60,19 @@ namespace runTimeControls
class averageCondition
:
public runTimeCondition
public runTimeCondition,
public valueAverageBase
{
public:
// Public enumerations
enum class windowType
{
NONE,
APPROXIMATE,
EXACT
};
static const Enum<windowType> windowTypeNames;
protected:
// Protected Data
//- Name of function object to retrieve data from
word functionObjectName_;
//- List of fields on which to operate
wordList fieldNames_;
//- Satisfied when difference in mean values is less than this value
const scalar tolerance_;
//- Averaging window
const scalar window_;
//- Averaging window type
windowType windowType_;
//- Average time per field
List<scalar> totalTime_;
//- Reset the averaging process on restart flag
Switch resetOnRestart_;
//- Number of start-up iterations before allowing satisfied checks
label nIterStartUp_;
//- Current iteration count
label iter_;
// Protected Member Functions
//- Templated function to calculate the average
template<class Type>
void calc
(
const label fieldi,
bool& satisfied,
bool& processed
);
public:
@ -157,12 +113,6 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "averageConditionTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,179 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2015 OpenFOAM Foundation
Copyright (C) 2015-2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "Time.H"
#include "FIFOStack.H"
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
template<class Type>
void Foam::functionObjects::runTimeControls::averageCondition::calc
(
const label fieldi,
bool& satisfied,
bool& processed
)
{
const word& fieldName = fieldNames_[fieldi];
const word valueType =
state_.objectResultType(functionObjectName_, fieldName);
if (pTraits<Type>::typeName != valueType)
{
return;
}
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);
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
auto timeIter = windowTimes.cbegin();
auto valueIter = windowValues.cbegin();
meanValue = pTraits<Type>::zero;
Type valueOld(pTraits<Type>::zero);
for
(
label i = 0;
timeIter.good();
++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);
Log << " " << meanName << ": " << meanValue
<< ", delta: " << delta << nl;
// Note: Writing result to owner function object and not the local run-time
// condition
state_.setResult(meanName, meanValue);
if (delta > tolerance_)
{
satisfied = false;
}
processed = true;
}
// ************************************************************************* //

View File

@ -58,6 +58,7 @@ Foam::functionObjects::runTimeControls::runTimeControl::satisfiedActionNames
{ satisfiedAction::SET_TRIGGER, "setTrigger"},
};
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::runTimeControls::runTimeControl::runTimeControl
@ -100,6 +101,8 @@ bool Foam::functionObjects::runTimeControls::runTimeControl::read
if (fvMeshFunctionObject::read(dict))
{
Info<< type() << " " << name() << ":" << nl;
const dictionary& conditionsDict = dict.subDict("conditions");
const wordList conditionNames(conditionsDict.toc());
conditions_.setSize(conditionNames.size());
@ -129,9 +132,7 @@ bool Foam::functionObjects::runTimeControls::runTimeControl::read
// Check that some conditions are set
if (conditions_.empty())
{
Info<< type() << " " << name() << " output:" << nl
<< " No conditions present" << nl
<< endl;
Info<< " No conditions present" << endl;
}
else
{
@ -148,12 +149,12 @@ bool Foam::functionObjects::runTimeControls::runTimeControl::read
if (!check)
{
Info<< type() << " " << name() << " output:" << nl
<< " All conditions are inactive" << nl
<< endl;
Info<< " All conditions are inactive" << endl;
}
}
Info<< endl;
// Set the action to perform when all conditions are satisfied
// - set to end for backwards compatibility with v1806
satisfiedAction_ =