ENH: Updated fieldAverage FO windowing. See #525

When specifying the averaging data, a new `windowType` option is
available, taking the values:

- none: no windowing
- approximate: past functionality (v1706 and earlier)
- exact: exact moving average - will store and write (for restart) all
  fields in the window
This commit is contained in:
Andrew Heather
2017-08-09 16:52:03 +01:00
parent c51ee22101
commit 4fc4f49cef
9 changed files with 1065 additions and 337 deletions

View File

@ -579,9 +579,8 @@ bool Foam::functionObjectList::execute()
} }
} }
} }
// Force writing of state dictionary after function object execution // Force writing of state dictionary after function object execution
if (time_.outputTime()) if (time_.writeTime())
{ {
label oldPrecision = IOstream::precision_; label oldPrecision = IOstream::precision_;
IOstream::precision_ = 16; IOstream::precision_ = 16;

View File

@ -44,21 +44,21 @@ namespace functionObjects
void Foam::functionObjects::fieldAverage::resetFields() void Foam::functionObjects::fieldAverage::resetFields()
{ {
forAll(faItems_, i) for (const fieldAverageItem& item : faItems_)
{ {
if (faItems_[i].mean()) if (item.mean())
{ {
if (obr().found(faItems_[i].meanFieldName())) if (obr().found(item.meanFieldName()))
{ {
obr().checkOut(*obr()[faItems_[i].meanFieldName()]); obr().checkOut(*obr()[item.meanFieldName()]);
} }
} }
if (faItems_[i].prime2Mean()) if (item.prime2Mean())
{ {
if (obr().found(faItems_[i].prime2MeanFieldName())) if (obr().found(item.prime2MeanFieldName()))
{ {
obr().checkOut(*obr()[faItems_[i].prime2MeanFieldName()]); obr().checkOut(*obr()[item.prime2MeanFieldName()]);
} }
} }
} }
@ -67,25 +67,9 @@ void Foam::functionObjects::fieldAverage::resetFields()
void Foam::functionObjects::fieldAverage::initialize() void Foam::functionObjects::fieldAverage::initialize()
{ {
if (!totalIter_.size()) for (fieldAverageItem& item : faItems_)
{ {
totalIter_.setSize(faItems_.size(), 1); item.restart(0, false);
}
if (!totalTime_.size())
{
totalTime_.setSize(faItems_.size(), obr_.time().deltaTValue());
}
else
{
// Check if totalTime_ has been set otherwise initialize
forAll(totalTime_, fieldi)
{
if (totalTime_[fieldi] < 0)
{
totalTime_[fieldi] = obr_.time().deltaTValue();
}
}
} }
resetFields(); resetFields();
@ -93,28 +77,39 @@ void Foam::functionObjects::fieldAverage::initialize()
Log << type() << " " << name() << ":" << nl; Log << type() << " " << name() << ":" << nl;
// Add mean fields to the field lists // Add mean fields to the field lists
forAll(faItems_, fieldi) for (fieldAverageItem& item : faItems_)
{ {
addMeanField<scalar>(fieldi); addMeanField<scalar>(item);
addMeanField<vector>(fieldi); addMeanField<vector>(item);
addMeanField<sphericalTensor>(fieldi); addMeanField<sphericalTensor>(item);
addMeanField<symmTensor>(fieldi); addMeanField<symmTensor>(item);
addMeanField<tensor>(fieldi); addMeanField<tensor>(item);
} }
// Add prime-squared mean fields to the field lists // Add prime-squared mean fields to the field lists
forAll(faItems_, fieldi) for (fieldAverageItem& item : faItems_)
{ {
addPrime2MeanField<scalar, scalar>(fieldi); addPrime2MeanField<scalar, scalar>(item);
addPrime2MeanField<vector, symmTensor>(fieldi); addPrime2MeanField<vector, symmTensor>(item);
} }
forAll(faItems_, fieldi) // Add window fields to the field lists
for (const fieldAverageItem& item : faItems_)
{ {
if (!faItems_[fieldi].active()) restoreWindowFields<scalar>(item);
restoreWindowFields<vector>(item);
restoreWindowFields<sphericalTensor>(item);
restoreWindowFields<symmTensor>(item);
restoreWindowFields<tensor>(item);
}
for (const fieldAverageItem& item : faItems_)
{
if (!item.active())
{ {
WarningInFunction WarningInFunction
<< "Field " << faItems_[fieldi].fieldName() << "Field " << item.fieldName()
<< " not found in database for averaging"; << " not found in database for averaging";
} }
} }
@ -133,8 +128,10 @@ void Foam::functionObjects::fieldAverage::restart()
<< obr().time().timeOutputValue() << obr().time().timeOutputValue()
<< nl << endl; << nl << endl;
totalIter_.clear(); for (fieldAverageItem& item : faItems_)
totalTime_.clear(); {
item.restart(0, true);
}
initialize(); initialize();
} }
@ -180,6 +177,17 @@ void Foam::functionObjects::fieldAverage::calcAverages()
Log << type() << " " << name() << " write:" << nl Log << type() << " " << name() << " write:" << nl
<< " Calculating averages" << nl; << " Calculating averages" << nl;
forAll(faItems_, fieldi)
{
faItems_[fieldi].evolve(obr());
}
storeWindowFields<scalar>();
storeWindowFields<vector>();
storeWindowFields<sphericalTensor>();
storeWindowFields<symmTensor>();
storeWindowFields<tensor>();
addMeanSqrToPrime2Mean<scalar, scalar>(); addMeanSqrToPrime2Mean<scalar, scalar>();
addMeanSqrToPrime2Mean<vector, symmTensor>(); addMeanSqrToPrime2Mean<vector, symmTensor>();
@ -192,12 +200,6 @@ void Foam::functionObjects::fieldAverage::calcAverages()
calculatePrime2MeanFields<scalar, scalar>(); calculatePrime2MeanFields<scalar, scalar>();
calculatePrime2MeanFields<vector, symmTensor>(); calculatePrime2MeanFields<vector, symmTensor>();
forAll(faItems_, fieldi)
{
totalIter_[fieldi]++;
totalTime_[fieldi] += obr().time().deltaTValue();
}
Log << endl; Log << endl;
} }
@ -218,28 +220,17 @@ void Foam::functionObjects::fieldAverage::writeAverages() const
void Foam::functionObjects::fieldAverage::writeAveragingProperties() void Foam::functionObjects::fieldAverage::writeAveragingProperties()
{ {
forAll(faItems_, fieldi) for (const fieldAverageItem& item : faItems_)
{ {
const word& fieldName = faItems_[fieldi].fieldName();
dictionary propsDict; dictionary propsDict;
propsDict.add("totalIter", totalIter_[fieldi]); item.writeState(propsDict);
propsDict.add("totalTime", totalTime_[fieldi]); setProperty(item.fieldName(), propsDict);
setProperty(fieldName, propsDict);
} }
} }
void Foam::functionObjects::fieldAverage::readAveragingProperties() void Foam::functionObjects::fieldAverage::readAveragingProperties()
{ {
totalIter_.clear();
totalIter_.setSize(faItems_.size(), 1);
// Initialize totalTime with negative values
// to indicate that it has not been set
totalTime_.clear();
totalTime_.setSize(faItems_.size(), -1);
if (restartOnRestart_ || restartOnOutput_) if (restartOnRestart_ || restartOnOutput_)
{ {
Info<< " Starting averaging at time " Info<< " Starting averaging at time "
@ -251,22 +242,20 @@ void Foam::functionObjects::fieldAverage::readAveragingProperties()
Info<< " Restarting averaging for fields:" << nl; Info<< " Restarting averaging for fields:" << nl;
forAll(faItems_, fieldi) for (fieldAverageItem& item : faItems_)
{ {
const word& fieldName = faItems_[fieldi].fieldName(); const word& fieldName = item.fieldName();
if (foundProperty(fieldName)) if (foundProperty(fieldName))
{ {
dictionary fieldDict; dictionary fieldDict;
getDict(fieldName, fieldDict); getDict(fieldName, fieldDict);
item.readState(fieldDict);
totalIter_[fieldi] = readLabel(fieldDict.lookup("totalIter"));
totalTime_[fieldi] = readScalar(fieldDict.lookup("totalTime"));
scalar userTotalTime = scalar userTotalTime =
obr().time().timeToUserTime(totalTime_[fieldi]); obr().time().timeToUserTime(item.totalTime());
Info<< " " << fieldName Info<< " " << fieldName
<< " iters = " << totalIter_[fieldi] << " iters = " << item.totalIter()
<< " time = " << userTotalTime << nl; << " time = " << userTotalTime << nl;
} }
else else
@ -298,8 +287,6 @@ Foam::functionObjects::fieldAverage::fieldAverage
restartTime_(GREAT), restartTime_(GREAT),
initialised_(false), initialised_(false),
faItems_(), faItems_(),
totalIter_(),
totalTime_(),
periodIndex_(1) periodIndex_(1)
{ {
read(dict); read(dict);
@ -321,10 +308,10 @@ bool Foam::functionObjects::fieldAverage::read(const dictionary& dict)
// Make certain that the values are consistent with the defaults: // Make certain that the values are consistent with the defaults:
initialised_ = false; initialised_ = false;
restartOnRestart_ = false; restartOnRestart_ = false;
restartOnOutput_ = false; restartOnOutput_ = false;
periodicRestart_ = false; periodicRestart_ = false;
restartPeriod_ = GREAT; restartPeriod_ = GREAT;
restartTime_ = GREAT; restartTime_ = GREAT;
Info<< type() << " " << name() << ":" << nl; Info<< type() << " " << name() << ":" << nl;

View File

@ -86,6 +86,7 @@ Usage
mean on; mean on;
prime2Mean on; prime2Mean on;
base time; base time;
windowType exact;
window 10.0; window 10.0;
windowName w1; windowName w1;
} }
@ -131,6 +132,7 @@ SourceFiles
#define functionObjects_fieldAverage_H #define functionObjects_fieldAverage_H
#include "fvMeshFunctionObject.H" #include "fvMeshFunctionObject.H"
#include "FIFOStack.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -208,19 +210,19 @@ protected:
//- Add mean average field to database //- Add mean average field to database
template<class Type> template<class Type>
void addMeanFieldType(const label fieldi); void addMeanFieldType(fieldAverageItem& item);
//- Add mean average field to database //- Add mean average field to database
template<class Type> template<class Type>
void addMeanField(const label fieldi); void addMeanField(fieldAverageItem& item);
//- Add prime-squared average field to database //- Add prime-squared average field to database
template<class Type1, class Type2> template<class Type1, class Type2>
void addPrime2MeanFieldType(const label fieldi); void addPrime2MeanFieldType(fieldAverageItem& item);
//- Add prime-squared average field to database //- Add prime-squared average field to database
template<class Type1, class Type2> template<class Type1, class Type2>
void addPrime2MeanField(const label fieldi); void addPrime2MeanField(fieldAverageItem& item);
// Calculation functions // Calculation functions
@ -228,30 +230,33 @@ protected:
//- Main calculation routine //- Main calculation routine
virtual void calcAverages(); virtual void calcAverages();
//- Calculate mean average fields
template<class Type>
void calculateMeanFieldType(const label fieldi) const;
//- Calculate mean average fields //- Calculate mean average fields
template<class Type> template<class Type>
void calculateMeanFields() const; void calculateMeanFields() const;
//- Calculate prime-squared average fields
template<class Type1, class Type2>
void calculatePrime2MeanFieldType(const label fieldi) const;
//- Calculate prime-squared average fields //- Calculate prime-squared average fields
template<class Type1, class Type2> template<class Type1, class Type2>
void calculatePrime2MeanFields() const; void calculatePrime2MeanFields() const;
//- Add mean-squared field value to prime-squared mean field //- Add mean-squared field value to prime-squared mean field
template<class Type1, class Type2> template<class Type1, class Type2>
void addMeanSqrToPrime2MeanType(const label fieldi) const; void addMeanSqrToPrime2MeanType(const fieldAverageItem& item) const;
//- Add mean-squared field value to prime-squared mean field //- Add mean-squared field value to prime-squared mean field
template<class Type1, class Type2> template<class Type1, class Type2>
void addMeanSqrToPrime2Mean() const; void addMeanSqrToPrime2Mean() const;
template<class Type>
void storeWindowFieldType(fieldAverageItem& item);
template<class Type>
void storeWindowFields();
template<class Type>
void restoreWindowFieldsType(const fieldAverageItem& item);
template<class Type>
void restoreWindowFields(const fieldAverageItem& item);
// I-O // I-O

View File

@ -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) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -32,6 +32,7 @@ const Foam::word Foam::functionObjects::fieldAverageItem::EXT_MEAN
"Mean" "Mean"
); );
const Foam::word Foam::functionObjects::fieldAverageItem::EXT_PRIME2MEAN const Foam::word Foam::functionObjects::fieldAverageItem::EXT_PRIME2MEAN
( (
"Prime2Mean" "Prime2Mean"
@ -49,6 +50,18 @@ Foam::functionObjects::fieldAverageItem::baseTypeNames_
}; };
const Foam::Enum
<
Foam::functionObjects::fieldAverageItem::windowType
>
Foam::functionObjects::fieldAverageItem::windowTypeNames_
{
{ windowType::NONE, "none" },
{ windowType::APPROXIMATE, "approximate" },
{ windowType::EXACT, "exact" },
};
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::fieldAverageItem::fieldAverageItem() Foam::functionObjects::fieldAverageItem::fieldAverageItem()
@ -59,9 +72,15 @@ Foam::functionObjects::fieldAverageItem::fieldAverageItem()
meanFieldName_("unknown"), meanFieldName_("unknown"),
prime2Mean_(0), prime2Mean_(0),
prime2MeanFieldName_("unknown"), prime2MeanFieldName_("unknown"),
base_(ITER), base_(baseType::ITER),
window_(-1.0), totalIter_(0),
windowName_("") totalTime_(-1),
window_(-1),
windowName_(""),
windowType_(windowType::NONE),
windowTimes_(),
windowFieldNames_()
{} {}
@ -77,8 +96,14 @@ Foam::functionObjects::fieldAverageItem::fieldAverageItem
prime2Mean_(faItem.prime2Mean_), prime2Mean_(faItem.prime2Mean_),
prime2MeanFieldName_(faItem.prime2MeanFieldName_), prime2MeanFieldName_(faItem.prime2MeanFieldName_),
base_(faItem.base_), base_(faItem.base_),
totalIter_(faItem.totalIter_),
totalTime_(faItem.totalTime_),
window_(faItem.window_), window_(faItem.window_),
windowName_(faItem.windowName_) windowName_(faItem.windowName_),
windowType_(faItem.windowType_),
windowTimes_(faItem.windowTimes_),
windowFieldNames_(faItem.windowFieldNames_)
{} {}
@ -88,6 +113,94 @@ Foam::functionObjects::fieldAverageItem::~fieldAverageItem()
{} {}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::functionObjects::fieldAverageItem::addToWindow
(
const word& fieldName,
const scalar deltaT
)
{
windowTimes_.push(deltaT);
windowFieldNames_.push(fieldName);
}
void Foam::functionObjects::fieldAverageItem::evolve(const objectRegistry& obr)
{
totalIter_++;
totalTime_ += obr.time().deltaTValue();
forAllIters(windowTimes_, timeIter)
{
timeIter() += obr.time().deltaTValue();
}
// Remove any fields that have passed out of the window
bool removeItem = true;
while (removeItem && windowTimes_.size())
{
removeItem = !(inWindow(windowTimes_.first()));
if (removeItem)
{
windowTimes_.pop();
const word fieldName = windowFieldNames_.pop();
//Info<< "evolve: removing field: " << fieldName << endl;
obr.checkOut(*obr[fieldName]);
}
}
}
void Foam::functionObjects::fieldAverageItem::restart
(
const scalar time0,
const bool override
)
{
if (totalTime_ < 0 || override)
{
totalIter_ = 0;
totalTime_ = time0;
windowTimes_.clear();
windowFieldNames_.clear();
}
}
bool Foam::functionObjects::fieldAverageItem::readState(const dictionary& dict)
{
dict.lookup("totalIter") >> totalIter_;
dict.lookup("totalTime") >> totalTime_;
if (window_ > 0)
{
dict.lookup("windowTimes") >> windowTimes_;
dict.lookup("windowFieldNames") >> windowFieldNames_;
}
return true;
}
void Foam::functionObjects::fieldAverageItem::writeState
(
dictionary& dict
) const
{
dict.add("totalIter", totalIter_);
dict.add("totalTime", totalTime_);
if (window_ > 0)
{
dict.add("windowTimes", windowTimes_);
dict.add("windowFieldNames", windowFieldNames_);
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
void Foam::functionObjects::fieldAverageItem::operator= void Foam::functionObjects::fieldAverageItem::operator=
@ -111,8 +224,13 @@ void Foam::functionObjects::fieldAverageItem::operator=
prime2Mean_ = rhs.prime2Mean_; prime2Mean_ = rhs.prime2Mean_;
prime2MeanFieldName_ = rhs.prime2MeanFieldName_; prime2MeanFieldName_ = rhs.prime2MeanFieldName_;
base_ = rhs.base_; base_ = rhs.base_;
totalIter_ = rhs.totalIter_;
totalTime_ = rhs.totalTime_;
window_ = rhs.window_; window_ = rhs.window_;
windowName_ = rhs.windowName_; windowName_ = rhs.windowName_;
windowType_ = rhs.windowType_;
windowTimes_ = rhs.windowTimes_;
windowFieldNames_ = rhs.windowFieldNames_;
} }

View File

@ -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) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -35,12 +35,19 @@ Description
base time; // iteration base time; // iteration
window 200; // optional averaging window window 200; // optional averaging window
windowName w1; // optional window name (default = "") windowName w1; // optional window name (default = "")
windowType approximate; // window type
} }
\endverbatim \endverbatim
The averaging window corresponds to the averaging interval (iters or time) The averaging window corresponds to the averaging interval (iters or time)
If not specified, the averaging is over 'all iters/time' If not specified, the averaging is over 'all iters/time'
Available window types:
- \c none : no windowing
- \c exact : exact windowing - additional files will be stored and written
- \c approximate : approximate variant that does not store/write additional
fields
SourceFiles SourceFiles
fieldAverageItem.C fieldAverageItem.C
fieldAverageItemIO.C fieldAverageItemIO.C
@ -52,6 +59,7 @@ SourceFiles
#include "Enum.H" #include "Enum.H"
#include "Switch.H" #include "Switch.H"
#include "FIFOStack.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -61,6 +69,7 @@ namespace Foam
// Forward declaration of classes // Forward declaration of classes
class Istream; class Istream;
class Ostream; class Ostream;
class objectRegistry;
namespace functionObjects namespace functionObjects
{ {
@ -88,13 +97,22 @@ public:
//- Prime-squared average //- Prime-squared average
static const word EXT_PRIME2MEAN; static const word EXT_PRIME2MEAN;
//- Enumeration defining the averaging base type //- Enumeration defining the averaging base type
enum baseType enum class baseType
{ {
ITER, ITER,
TIME TIME
}; };
//- Enumeration defining the averaging window type
enum class windowType
{
NONE,
APPROXIMATE,
EXACT
};
private: private:
@ -124,12 +142,30 @@ private:
//- Averaging base type //- Averaging base type
baseType base_; baseType base_;
//- Total number of iterations item has been evolved
label totalIter_;
//- Total time item has been evolved
scalar totalTime_;
//- Averaging window - defaults to -1 for 'all iters/time' //- Averaging window - defaults to -1 for 'all iters/time'
scalar window_; scalar window_;
//- Averaging window name - defaults to 'window' //- Averaging window name - defaults to 'window'
word windowName_; word windowName_;
//- Averaging window type
windowType windowType_;
//- Averaging window type names
static const Enum<windowType> windowTypeNames_;
//- List of window times (windowType = EXACT)
FIFOStack<scalar> windowTimes_;
//- List of window field names (windowType = EXACT)
FIFOStack<word> windowFieldNames_;
public: public:
@ -154,86 +190,87 @@ public:
// Access // Access
//- Return const access to the active flag //- Return const access to the active flag
bool active() const inline bool active() const;
{
return active_;
}
//- Return non-const access to the active flag //- Return non-const access to the active flag
bool& active() inline bool& active();
{
return active_;
}
//- Return const access to the field name //- Return const access to the field name
const word& fieldName() const inline const word& fieldName() const;
{
return fieldName_;
}
//- Return const access to the mean flag //- Return const access to the mean flag
bool mean() const inline bool mean() const;
{
return mean_;
}
//- Return non-const access to the mean flag //- Return non-const access to the mean flag
bool& mean() inline bool& mean();
{
return mean_;
}
//- Return const access to the mean field name //- Return const access to the mean field name
const word& meanFieldName() const inline const word& meanFieldName() const;
{
return meanFieldName_;
}
//- Return const access to the prime-squared mean flag //- Return const access to the prime-squared mean flag
bool prime2Mean() const inline bool prime2Mean() const;
{
return prime2Mean_;
}
//- Return non-const access to the prime-squared mean flag //- Return non-const access to the prime-squared mean flag
bool& prime2Mean() inline bool& prime2Mean();
{
return prime2Mean_;
}
//- Return const access to the prime-squared mean field name //- Return const access to the prime-squared mean field name
const word& prime2MeanFieldName() const inline const word& prime2MeanFieldName() const;
{
return prime2MeanFieldName_;
}
//- Return averaging base type name //- Return averaging base type name
const word base() const inline const word& base() const;
{
return baseTypeNames_[base_];
}
//- Return true if base is ITER //- Return the total number of iterations item has been evolved
bool iterBase() const inline label totalIter() const;
{
return base_ == ITER;
}
//- Return true if base is time //- Return the total time item has been evolved
bool timeBase() const inline scalar totalTime() const;
{
return base_ == TIME;
}
scalar window() const //- Return the window length (iterations or seconds)
{ inline scalar window() const;
return window_;
}
const word& windowName() const //- Return the (optional) window name
{ inline const word& windowName() const;
return windowName_;
} //- Return the list of window times (windowType = EXACT)
inline const FIFOStack<scalar>& windowTimes() const;
//- Return the list of window field names (windowType = EXACT)
inline const FIFOStack<word>& windowFieldNames() const;
//- Return the current time interval
inline scalar dt(const scalar deltaT) const;
//- Return the total time interval
inline scalar Dt() const;
//- Helper function to construct a window field name
inline word windowFieldName(const word& prefix) const;
//- Return true if time is inside window (including boundaries)
inline bool inWindow(const scalar t) const;
//- Add field to window
void addToWindow(const word& fieldName, const scalar deltaT);
//- Evolve and update
void evolve(const objectRegistry& obr);
//- Restart
void restart(const scalar time0, const bool override);
//- Read state and re-initialise values
bool readState(const dictionary& dict);
//- Write state for restart
void writeState(dictionary& dict) const;
//- Calculate the mean field value
template<class Type>
bool calculateMeanField(const objectRegistry& obr) const;
//- Calculate prime-squared average fields
template<class Type1, class Type2>
bool calculatePrime2MeanField(const objectRegistry& obr) const;
// Member Operators // Member Operators
@ -257,8 +294,11 @@ public:
&& a.prime2Mean_ == b.prime2Mean_ && a.prime2Mean_ == b.prime2Mean_
&& a.prime2MeanFieldName_ == b.prime2MeanFieldName_ && a.prime2MeanFieldName_ == b.prime2MeanFieldName_
&& a.base_ == b.base_ && a.base_ == b.base_
&& a.totalIter_ == b.totalIter_
&& a.totalTime_ == b.totalTime_
&& a.window_ == b.window_ && a.window_ == b.window_
&& a.windowName_ == b.windowName_; && a.windowName_ == b.windowName_
&& a.windowType_ == b.windowType_;
} }
friend bool operator!= friend bool operator!=
@ -285,6 +325,16 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "fieldAverageItemI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "fieldAverageItemTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif #endif
// ************************************************************************* // // ************************************************************************* //

View File

@ -0,0 +1,212 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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/>.
\*---------------------------------------------------------------------------*/
bool Foam::functionObjects::fieldAverageItem::active() const
{
return active_;
}
bool& Foam::functionObjects::fieldAverageItem::active()
{
return active_;
}
const Foam::word& Foam::functionObjects::fieldAverageItem::fieldName() const
{
return fieldName_;
}
bool Foam::functionObjects::fieldAverageItem::mean() const
{
return mean_;
}
bool& Foam::functionObjects::fieldAverageItem::mean()
{
return mean_;
}
const Foam::word&
Foam::functionObjects::fieldAverageItem::meanFieldName() const
{
return meanFieldName_;
}
bool Foam::functionObjects::fieldAverageItem::prime2Mean() const
{
return prime2Mean_;
}
bool& Foam::functionObjects::fieldAverageItem::prime2Mean()
{
return prime2Mean_;
}
const Foam::word& Foam::functionObjects::fieldAverageItem::prime2MeanFieldName() const
{
return prime2MeanFieldName_;
}
const Foam::word& Foam::functionObjects::fieldAverageItem::base() const
{
return baseTypeNames_[base_];
}
Foam::label Foam::functionObjects::fieldAverageItem::totalIter() const
{
return totalIter_;
}
Foam::scalar Foam::functionObjects::fieldAverageItem::totalTime() const
{
return totalTime_;
}
Foam::scalar Foam::functionObjects::fieldAverageItem::window() const
{
return window_;
}
const Foam::word& Foam::functionObjects::fieldAverageItem::windowName() const
{
return windowName_;
}
const Foam::FIFOStack<Foam::scalar>&
Foam::functionObjects::fieldAverageItem::windowTimes() const
{
return windowTimes_;
}
const Foam::FIFOStack<Foam::word>&
Foam::functionObjects::fieldAverageItem::windowFieldNames() const
{
return windowFieldNames_;
}
Foam::scalar Foam::functionObjects::fieldAverageItem::dt
(
const scalar deltaT
) const
{
switch (base_)
{
case baseType::TIME:
{
return deltaT;
}
case baseType::ITER:
{
return scalar(1);
}
default:
{
FatalErrorInFunction
<< "Unhandled enumeration " << baseTypeNames_[base_]
<< abort(FatalError);
}
}
return 0.0;
}
Foam::scalar Foam::functionObjects::fieldAverageItem::Dt() const
{
switch (base_)
{
case baseType::TIME:
{
return totalTime_;
}
case baseType::ITER:
{
return scalar(totalIter_);
}
default:
{
FatalErrorInFunction
<< "Unhandled enumeration " << baseTypeNames_[base_]
<< abort(FatalError);
}
}
return 0.0;
}
Foam::word Foam::functionObjects::fieldAverageItem::windowFieldName
(
const word& prefix
) const
{
return prefix + ':' + fieldName_ + ':' + Foam::name(totalIter_);
}
bool Foam::functionObjects::fieldAverageItem::inWindow(const scalar t) const
{
switch (base_)
{
case baseType::ITER:
{
return round(t) <= round(window_) + 1;
}
case baseType::TIME:
{
return t <= window_;
}
default:
{
FatalErrorInFunction
<< "Unhandled baseType enumeration "
<< baseTypeNames_[base_]
<< abort(FatalError);
}
}
return false;
}
// ************************************************************************* //

View File

@ -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) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. \\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -37,8 +37,15 @@ Foam::functionObjects::fieldAverageItem::fieldAverageItem(Istream& is)
meanFieldName_("unknown"), meanFieldName_("unknown"),
prime2Mean_(0), prime2Mean_(0),
prime2MeanFieldName_("unknown"), prime2MeanFieldName_("unknown"),
base_(ITER), base_(baseType::ITER),
window_(-1.0) totalIter_(0),
totalTime_(-1),
window_(-1.0),
windowName_(""),
windowType_(windowType::NONE),
windowTimes_(),
windowFieldNames_()
{ {
is.check(FUNCTION_NAME); is.check(FUNCTION_NAME);
@ -49,11 +56,21 @@ Foam::functionObjects::fieldAverageItem::fieldAverageItem(Istream& is)
prime2Mean_ = readBool(entry.lookup("prime2Mean")); prime2Mean_ = readBool(entry.lookup("prime2Mean"));
base_ = baseTypeNames_.lookup("base", entry); base_ = baseTypeNames_.lookup("base", entry);
window_ = entry.lookupOrDefault<scalar>("window", -1.0); window_ = entry.lookupOrDefault<scalar>("window", -1.0);
windowName_ = entry.lookupOrDefault<word>("windowName", "");
if (window_ > 0)
{
windowName_ = entry.lookupOrDefault<word>("windowName", "");
windowType_ = windowTypeNames_.lookup("windowType", entry);
if (windowType_ == windowType::NONE)
{
window_ = -1;
}
}
meanFieldName_ = fieldName_ + EXT_MEAN; meanFieldName_ = fieldName_ + EXT_MEAN;
prime2MeanFieldName_ = fieldName_ + EXT_PRIME2MEAN; prime2MeanFieldName_ = fieldName_ + EXT_PRIME2MEAN;
if ((window_ > 0) && (windowName_ != "")) if ((window_ > 0) && (!windowName_.empty()))
{ {
meanFieldName_ = meanFieldName_ + "_" + windowName_; meanFieldName_ = meanFieldName_ + "_" + windowName_;
prime2MeanFieldName_ = prime2MeanFieldName_ + "_" + windowName_; prime2MeanFieldName_ = prime2MeanFieldName_ + "_" + windowName_;
@ -79,13 +96,24 @@ Foam::Istream& Foam::functionObjects::operator>>
faItem.prime2Mean_ = readBool(entry.lookup("prime2Mean")); faItem.prime2Mean_ = readBool(entry.lookup("prime2Mean"));
faItem.base_ = faItem.baseTypeNames_.lookup("base", entry); faItem.base_ = faItem.baseTypeNames_.lookup("base", entry);
faItem.window_ = entry.lookupOrDefault<scalar>("window", -1.0); faItem.window_ = entry.lookupOrDefault<scalar>("window", -1.0);
faItem.windowName_ = entry.lookupOrDefault<word>("windowName", "");
if (faItem.window_ > 0)
{
faItem.windowName_ = entry.lookupOrDefault<word>("windowName", "");
faItem.windowType_ =
faItem.windowTypeNames_.lookup("windowType", entry);
if (faItem.windowType_ == fieldAverageItem::windowType::NONE)
{
faItem.window_ = -1;
}
}
faItem.meanFieldName_ = faItem.fieldName_ + fieldAverageItem::EXT_MEAN; faItem.meanFieldName_ = faItem.fieldName_ + fieldAverageItem::EXT_MEAN;
faItem.prime2MeanFieldName_ = faItem.prime2MeanFieldName_ =
faItem.fieldName_ + fieldAverageItem::EXT_PRIME2MEAN; faItem.fieldName_ + fieldAverageItem::EXT_PRIME2MEAN;
if ((faItem.window_ > 0) && (faItem.windowName_ != "")) if ((faItem.window_ > 0) && (!faItem.windowName_.empty()))
{ {
faItem.meanFieldName_ = faItem.meanFieldName_ =
faItem.meanFieldName_ + "_" + faItem.windowName_; faItem.meanFieldName_ + "_" + faItem.windowName_;
@ -105,7 +133,8 @@ Foam::Ostream& Foam::functionObjects::operator<<
{ {
os.check(FUNCTION_NAME); os.check(FUNCTION_NAME);
os << faItem.fieldName_ << nl << token::BEGIN_BLOCK << nl; os.beginBlock(faItem.fieldName_);
os.writeKeyword("mean") << faItem.mean_ << token::END_STATEMENT << nl; os.writeKeyword("mean") << faItem.mean_ << token::END_STATEMENT << nl;
os.writeKeyword("prime2Mean") << faItem.prime2Mean_ os.writeKeyword("prime2Mean") << faItem.prime2Mean_
<< token::END_STATEMENT << nl; << token::END_STATEMENT << nl;
@ -114,19 +143,24 @@ Foam::Ostream& Foam::functionObjects::operator<<
if (faItem.window_ > 0) if (faItem.window_ > 0)
{ {
os.writeKeyword("window") << faItem.window_ os.writeEntry("window", faItem.window_);
<< token::END_STATEMENT << nl;
if (faItem.windowName_ != "") if (!faItem.windowName_.empty())
{ {
os.writeKeyword("windowName") << faItem.windowName_ os.writeEntry("windowName", faItem.windowName_);
<< token::END_STATEMENT << nl;
} }
os.writeEntry
(
"windowType",
faItem.windowTypeNames_[faItem.windowType_]
);
} }
os << token::END_BLOCK << nl; os.endBlock() << flush;
os.check(FUNCTION_NAME); os.check(FUNCTION_NAME);
return os; return os;
} }

View File

@ -0,0 +1,291 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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 "objectRegistry.H"
#include "Time.H"
template<class Type>
bool Foam::functionObjects::fieldAverageItem::calculateMeanField
(
const objectRegistry& obr
) const
{
if (!mean_)
{
return false;
}
const Type* baseFieldPtr = obr.lookupObjectPtr<Type>(fieldName_);
if (!baseFieldPtr)
{
return false;
}
const Type& baseField = *baseFieldPtr;
Type& meanField = obr.lookupObjectRef<Type>(meanFieldName_);
switch (windowType_)
{
case windowType::NONE:
{
scalar dt = this->dt(obr.time().deltaTValue());
scalar Dt = this->Dt();
scalar beta = dt/Dt;
meanField = (1 - beta)*meanField + beta*baseField;
break;
}
case windowType::APPROXIMATE:
{
scalar dt = this->dt(obr.time().deltaTValue());
scalar Dt = this->Dt();
scalar beta = dt/Dt;
if (Dt - dt >= window_)
{
beta = dt/window_;
}
meanField = (1 - beta)*meanField + beta*baseField;
break;
}
case windowType::EXACT:
{
switch (base_)
{
case baseType::ITER:
{
// Uniform time step - can use simplified algorithm
// Note: stores an additional old time field, but only
// needs to do 1 field lookup
label n = windowTimes_.size();
const Type& lastField =
obr.lookupObject<Type>(windowFieldNames_.first());
if (n <= round(window_))
{
scalar beta = 1.0/scalar(n);
meanField = (1 - beta)*meanField + beta*baseField;
}
else
{
meanField += (baseField - lastField)/scalar(n - 1);
}
break;
}
case baseType::TIME:
{
// Assuming non-uniform time step
// Note: looks up all window fields from the registry
meanField = 0*baseField;
FIFOStack<scalar>::const_iterator timeIter =
windowTimes_.begin();
FIFOStack<word>::const_iterator nameIter =
windowFieldNames_.begin();
const Type* wOld = nullptr;
for
(
;
timeIter != windowTimes_.end();
++timeIter, ++nameIter
)
{
const word& fieldName = nameIter();
const scalar dt = timeIter();
const Type* w = obr.lookupObjectPtr<Type>(fieldName);
meanField += dt*(*w);
if (wOld)
{
meanField -= dt*(*wOld);
}
wOld = w;
}
meanField /= windowTimes_.first();
break;
}
default:
{
FatalErrorInFunction
<< "Unhandled baseType enumeration "
<< baseTypeNames_[base_]
<< abort(FatalError);
}
}
break;
}
default:
{
FatalErrorInFunction
<< "Unhandled windowType enumeration "
<< windowTypeNames_[windowType_]
<< abort(FatalError);
}
}
return true;
}
template<class Type1, class Type2>
bool Foam::functionObjects::fieldAverageItem::calculatePrime2MeanField
(
const objectRegistry& obr
) const
{
if (!prime2Mean_)
{
return false;
}
const Type1* baseFieldPtr = obr.lookupObjectPtr<Type1>(fieldName_);
if (!baseFieldPtr)
{
return false;
}
const Type1& baseField = *baseFieldPtr;
const Type1& meanField = obr.lookupObject<Type1>(meanFieldName_);
Type2& prime2MeanField =
obr.lookupObjectRef<Type2>(prime2MeanFieldName_);
switch (windowType_)
{
case windowType::NONE:
{
scalar dt = this->dt(obr.time().deltaTValue());
scalar Dt = this->Dt();
scalar beta = dt/Dt;
prime2MeanField =
(1 - beta)*prime2MeanField
+ beta*sqr(baseField)
- sqr(meanField);
break;
}
case windowType::APPROXIMATE:
{
scalar dt = this->dt(obr.time().deltaTValue());
scalar Dt = this->Dt();
scalar beta = dt/Dt;
if (Dt - dt >= window_)
{
beta = dt/window_;
}
prime2MeanField =
(1 - beta)*prime2MeanField
+ beta*sqr(baseField)
- sqr(meanField);
break;
}
case windowType::EXACT:
{
// Not storing old time mean fields - treat all as TIME (integrated)
prime2MeanField = 0*prime2MeanField;
FIFOStack<scalar>::const_iterator timeIter =
windowTimes_.begin();
FIFOStack<word>::const_iterator nameIter =
windowFieldNames_.begin();
switch (base_)
{
case baseType::ITER:
{
// ITER method stores an additional entry compared to TIME
++timeIter;
++nameIter;
if (timeIter == windowTimes_.end()) return false;
break;
}
default:
{}
}
scalar windowLength = timeIter();
const Type1* wOld = nullptr;
for
(
;
timeIter != windowTimes_.end();
++timeIter, ++nameIter
)
{
const word& fieldName = nameIter();
const scalar dt = timeIter();
const Type1* w = obr.lookupObjectPtr<Type1>(fieldName);
prime2MeanField += dt*(sqr((*w) - meanField));
if (wOld)
{
prime2MeanField -= dt*(sqr((*wOld) - meanField));
}
wOld = w;
}
prime2MeanField /= windowLength;
break;
}
default:
{
FatalErrorInFunction
<< "Unhandled windowType enumeration "
<< windowTypeNames_[windowType_]
<< abort(FatalError);
}
}
return true;
}
// ************************************************************************* //

View File

@ -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) 2011-2017 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015-2016 OpenCFD Ltd. \\/ M anipulation | Copyright (C) 2015-2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -32,13 +32,22 @@ License
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type> template<class Type>
void Foam::functionObjects::fieldAverage::addMeanFieldType(const label fieldi) void Foam::functionObjects::fieldAverage::addMeanFieldType
(
fieldAverageItem& item
)
{ {
// Field has been found, so set active flag to true const word& fieldName = item.fieldName();
faItems_[fieldi].active() = true;
const word& fieldName = faItems_[fieldi].fieldName(); if (!foundObject<Type>(fieldName))
const word& meanFieldName = faItems_[fieldi].meanFieldName(); {
return;
}
// Field has been found, so set active flag to true
item.active() = true;
const word& meanFieldName = item.meanFieldName();
Log << " Reading/initialising field " << meanFieldName << endl; Log << " Reading/initialising field " << meanFieldName << endl;
@ -50,7 +59,7 @@ void Foam::functionObjects::fieldAverage::addMeanFieldType(const label fieldi)
<< " since an object with that name already exists." << " since an object with that name already exists."
<< " Disabling averaging for field." << endl; << " Disabling averaging for field." << endl;
faItems_[fieldi].mean() = false; item.mean() = false;
} }
else else
{ {
@ -66,9 +75,9 @@ void Foam::functionObjects::fieldAverage::addMeanFieldType(const label fieldi)
meanFieldName, meanFieldName,
obr().time().timeName(obr().time().startTime().value()), obr().time().timeName(obr().time().startTime().value()),
obr(), obr(),
restartOnOutput_ restartOnOutput_ ?
? IOobject::NO_READ IOobject::NO_READ
: IOobject::READ_IF_PRESENT, : IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
1*baseField 1*baseField
@ -79,41 +88,102 @@ void Foam::functionObjects::fieldAverage::addMeanFieldType(const label fieldi)
template<class Type> template<class Type>
void Foam::functionObjects::fieldAverage::addMeanField(const label fieldi) void Foam::functionObjects::fieldAverage::addMeanField
(
fieldAverageItem& item
)
{ {
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType; typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType; typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType; typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
if (faItems_[fieldi].mean()) if (item.mean())
{ {
const word& fieldName = faItems_[fieldi].fieldName(); addMeanFieldType<VolFieldType>(item);
addMeanFieldType<SurfaceFieldType>(item);
addMeanFieldType<SurfFieldType>(item);
}
}
if (foundObject<VolFieldType>(fieldName))
template<class Type>
void Foam::functionObjects::fieldAverage::restoreWindowFieldsType
(
const fieldAverageItem& item
)
{
if (restartOnOutput_)
{
return;
}
const word& fieldName = item.fieldName();
const Type* fieldPtr = lookupObjectPtr<Type>(fieldName);
if (!fieldPtr)
{
return;
}
const FIFOStack<word>& fieldNames = item.windowFieldNames();
forAllConstIters(fieldNames, fieldIter)
{
const word& name = fieldIter();
IOobject io
(
name,
obr().time().timeName(obr().time().startTime().value()),
obr(),
IOobject::MUST_READ,
IOobject::NO_WRITE
);
if (io.typeHeaderOk<dictionary>(false))
{ {
addMeanFieldType<VolFieldType>(fieldi); DebugInfo << "Read and store: " << name << endl;
} obr().store(new Type(io, fieldPtr->mesh()));
else if (foundObject<SurfaceFieldType>(fieldName))
{
addMeanFieldType<SurfaceFieldType>(fieldi);
}
else if (foundObject<SurfFieldType>(fieldName))
{
addMeanFieldType<SurfFieldType>(fieldi);
} }
} }
} }
template<class Type>
void Foam::functionObjects::fieldAverage::restoreWindowFields
(
const fieldAverageItem& item
)
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
if (item.window() > 0)
{
restoreWindowFieldsType<VolFieldType>(item);
restoreWindowFieldsType<SurfaceFieldType>(item);
restoreWindowFieldsType<SurfFieldType>(item);
}
}
template<class Type1, class Type2> template<class Type1, class Type2>
void Foam::functionObjects::fieldAverage::addPrime2MeanFieldType void Foam::functionObjects::fieldAverage::addPrime2MeanFieldType
( (
const label fieldi fieldAverageItem& item
) )
{ {
const word& fieldName = faItems_[fieldi].fieldName(); const word& fieldName = item.fieldName();
const word& meanFieldName = faItems_[fieldi].meanFieldName();
const word& prime2MeanFieldName = faItems_[fieldi].prime2MeanFieldName(); if (!foundObject<Type1>(fieldName))
{
return;
}
const word& meanFieldName = item.meanFieldName();
const word& prime2MeanFieldName = item.prime2MeanFieldName();
Log << " Reading/initialising field " << prime2MeanFieldName << nl; Log << " Reading/initialising field " << prime2MeanFieldName << nl;
@ -125,7 +195,7 @@ void Foam::functionObjects::fieldAverage::addPrime2MeanFieldType
<< " since an object with that name already exists." << " since an object with that name already exists."
<< " Disabling averaging for field." << endl; << " Disabling averaging for field." << endl;
faItems_[fieldi].prime2Mean() = false; item.prime2Mean() = false;
} }
else else
{ {
@ -142,9 +212,9 @@ void Foam::functionObjects::fieldAverage::addPrime2MeanFieldType
prime2MeanFieldName, prime2MeanFieldName,
obr().time().timeName(obr().time().startTime().value()), obr().time().timeName(obr().time().startTime().value()),
obr(), obr(),
restartOnOutput_ restartOnOutput_?
? IOobject::NO_READ IOobject::NO_READ
: IOobject::READ_IF_PRESENT, : IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
sqr(baseField) - sqr(meanField) sqr(baseField) - sqr(meanField)
@ -155,7 +225,10 @@ void Foam::functionObjects::fieldAverage::addPrime2MeanFieldType
template<class Type1, class Type2> template<class Type1, class Type2>
void Foam::functionObjects::fieldAverage::addPrime2MeanField(const label fieldi) void Foam::functionObjects::fieldAverage::addPrime2MeanField
(
fieldAverageItem& item
)
{ {
typedef GeometricField<Type1, fvPatchField, volMesh> VolFieldType1; typedef GeometricField<Type1, fvPatchField, volMesh> VolFieldType1;
typedef GeometricField<Type1, fvsPatchField, surfaceMesh> SurfaceFieldType1; typedef GeometricField<Type1, fvsPatchField, surfaceMesh> SurfaceFieldType1;
@ -165,79 +238,80 @@ void Foam::functionObjects::fieldAverage::addPrime2MeanField(const label fieldi)
typedef GeometricField<Type2, fvsPatchField, surfaceMesh> SurfaceFieldType2; typedef GeometricField<Type2, fvsPatchField, surfaceMesh> SurfaceFieldType2;
typedef DimensionedField<Type2, surfGeoMesh> SurfFieldType2; typedef DimensionedField<Type2, surfGeoMesh> SurfFieldType2;
if (faItems_[fieldi].prime2Mean()) if (item.prime2Mean())
{ {
const word& fieldName = faItems_[fieldi].fieldName(); if (!item.mean())
if (!faItems_[fieldi].mean())
{ {
FatalErrorInFunction FatalErrorInFunction
<< "To calculate the prime-squared average, the " << "To calculate the prime-squared average, the "
<< "mean average must also be selected for field " << "mean average must also be selected for field "
<< fieldName << nl << exit(FatalError); << item.fieldName() << nl << exit(FatalError);
} }
if (foundObject<VolFieldType1>(fieldName)) addPrime2MeanFieldType<VolFieldType1, VolFieldType2>(item);
{ addPrime2MeanFieldType<SurfaceFieldType1, SurfaceFieldType2>(item);
addPrime2MeanFieldType<VolFieldType1, VolFieldType2>(fieldi); addPrime2MeanFieldType<SurfFieldType1, SurfFieldType2>(item);
}
else if (foundObject<SurfaceFieldType1>(fieldName))
{
addPrime2MeanFieldType<SurfaceFieldType1, SurfaceFieldType2>
(
fieldi
);
}
else if (foundObject<SurfFieldType1>(fieldName))
{
addPrime2MeanFieldType<SurfFieldType1, SurfFieldType2>
(
fieldi
);
}
} }
} }
template<class Type> template<class Type>
void Foam::functionObjects::fieldAverage::calculateMeanFieldType void Foam::functionObjects::fieldAverage::storeWindowFieldType
( (
const label fieldi fieldAverageItem& item
) const )
{ {
const word& fieldName = faItems_[fieldi].fieldName(); const word& fieldName = item.fieldName();
if (foundObject<Type>(fieldName)) if (!foundObject<Type>(fieldName))
{ {
const Type& baseField = lookupObject<Type>(fieldName); return;
}
Type& meanField = const_cast<Type&> const Type& baseField = lookupObject<Type>(fieldName);
const word windowFieldName = item.windowFieldName(this->name());
// Store on registry
obr().store
(
new Type
( (
lookupObject<Type>(faItems_[fieldi].meanFieldName()) IOobject
); (
windowFieldName,
obr().time().timeName(obr().time().startTime().value()),
obr(),
restartOnOutput_ ?
IOobject::NO_READ
: IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE
),
1*baseField
)
);
scalar dt = obr().time().deltaTValue(); DebugInfo << "Create and store: " << windowFieldName << endl;
scalar Dt = totalTime_[fieldi];
if (faItems_[fieldi].iterBase()) item.addToWindow(windowFieldName, obr().time().deltaTValue());
}
template<class Type>
void Foam::functionObjects::fieldAverage::storeWindowFields()
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
for (fieldAverageItem& item : faItems_)
{
if (item.window() > 0)
{ {
dt = 1; storeWindowFieldType<VolFieldType>(item);
Dt = scalar(totalIter_[fieldi]); storeWindowFieldType<SurfaceFieldType>(item);
storeWindowFieldType<SurfFieldType>(item);
} }
scalar beta = dt/Dt;
if (faItems_[fieldi].window() > 0)
{
const scalar w = faItems_[fieldi].window();
if (Dt - dt >= w)
{
beta = dt/w;
}
}
meanField = (1 - beta)*meanField + beta*baseField;
} }
} }
@ -249,60 +323,11 @@ void Foam::functionObjects::fieldAverage::calculateMeanFields() const
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType; typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType; typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
forAll(faItems_, i) for (const fieldAverageItem& item : faItems_)
{ {
if (faItems_[i].mean()) item.calculateMeanField<VolFieldType>(obr());
{ item.calculateMeanField<SurfaceFieldType>(obr());
calculateMeanFieldType<VolFieldType>(i); item.calculateMeanField<SurfFieldType>(obr());
calculateMeanFieldType<SurfaceFieldType>(i);
calculateMeanFieldType<SurfFieldType>(i);
}
}
}
template<class Type1, class Type2>
void Foam::functionObjects::fieldAverage::calculatePrime2MeanFieldType
(
const label fieldi
) const
{
const word& fieldName = faItems_[fieldi].fieldName();
if (foundObject<Type1>(fieldName))
{
const Type1& baseField = lookupObject<Type1>(fieldName);
const Type1& meanField =
lookupObject<Type1>(faItems_[fieldi].meanFieldName());
Type2& prime2MeanField =
lookupObjectRef<Type2>(faItems_[fieldi].prime2MeanFieldName());
scalar dt = obr().time().deltaTValue();
scalar Dt = totalTime_[fieldi];
if (faItems_[fieldi].iterBase())
{
dt = 1;
Dt = scalar(totalIter_[fieldi]);
}
scalar beta = dt/Dt;
if (faItems_[fieldi].window() > 0)
{
const scalar w = faItems_[fieldi].window();
if (Dt - dt >= w)
{
beta = dt/w;
}
}
prime2MeanField =
(1 - beta)*prime2MeanField
+ beta*sqr(baseField)
- sqr(meanField);
} }
} }
@ -318,21 +343,14 @@ void Foam::functionObjects::fieldAverage::calculatePrime2MeanFields() const
typedef GeometricField<Type2, fvsPatchField, surfaceMesh> SurfaceFieldType2; typedef GeometricField<Type2, fvsPatchField, surfaceMesh> SurfaceFieldType2;
typedef DimensionedField<Type2, surfGeoMesh> SurfFieldType2; typedef DimensionedField<Type2, surfGeoMesh> SurfFieldType2;
forAll(faItems_, i) for (const fieldAverageItem& item : faItems_)
{ {
if (faItems_[i].prime2Mean()) item.calculatePrime2MeanField<VolFieldType1, VolFieldType2>(obr());
{ item.calculatePrime2MeanField<SurfaceFieldType1, SurfaceFieldType2>
calculatePrime2MeanFieldType<VolFieldType1, VolFieldType2>(i); (
calculatePrime2MeanFieldType<SurfaceFieldType1, SurfaceFieldType2> obr()
( );
i item.calculatePrime2MeanField<SurfFieldType1, SurfFieldType2>(obr());
);
calculatePrime2MeanFieldType<SurfFieldType1, SurfFieldType2>
(
i
);
}
} }
} }
@ -340,21 +358,21 @@ void Foam::functionObjects::fieldAverage::calculatePrime2MeanFields() const
template<class Type1, class Type2> template<class Type1, class Type2>
void Foam::functionObjects::fieldAverage::addMeanSqrToPrime2MeanType void Foam::functionObjects::fieldAverage::addMeanSqrToPrime2MeanType
( (
const label fieldi const fieldAverageItem& item
) const ) const
{ {
const word& fieldName = faItems_[fieldi].fieldName(); const word& fieldName = item.fieldName();
if (foundObject<Type1>(fieldName)) if (!foundObject<Type1>(fieldName))
{ {
const Type1& meanField = return;
lookupObject<Type1>(faItems_[fieldi].meanFieldName());
Type2& prime2MeanField =
lookupObjectRef<Type2>(faItems_[fieldi].prime2MeanFieldName());
prime2MeanField += sqr(meanField);
} }
const Type1& meanField = lookupObject<Type1>(item.meanFieldName());
Type2& prime2MeanField = lookupObjectRef<Type2>(item.prime2MeanFieldName());
prime2MeanField += sqr(meanField);
} }
@ -369,13 +387,16 @@ void Foam::functionObjects::fieldAverage::addMeanSqrToPrime2Mean() const
typedef GeometricField<Type2, fvsPatchField, surfaceMesh> SurfaceFieldType2; typedef GeometricField<Type2, fvsPatchField, surfaceMesh> SurfaceFieldType2;
typedef DimensionedField<Type2, surfGeoMesh> SurfFieldType2; typedef DimensionedField<Type2, surfGeoMesh> SurfFieldType2;
forAll(faItems_, i) for (const fieldAverageItem& item : faItems_)
{ {
if (faItems_[i].prime2Mean()) if (item.prime2Mean())
{ {
addMeanSqrToPrime2MeanType<VolFieldType1, VolFieldType2>(i); addMeanSqrToPrime2MeanType<VolFieldType1, VolFieldType2>(item);
addMeanSqrToPrime2MeanType<SurfaceFieldType1, SurfaceFieldType2>(i); addMeanSqrToPrime2MeanType<SurfaceFieldType1, SurfaceFieldType2>
addMeanSqrToPrime2MeanType<SurfFieldType1, SurfFieldType2>(i); (
item
);
addMeanSqrToPrime2MeanType<SurfFieldType1, SurfFieldType2>(item);
} }
} }
} }
@ -402,22 +423,33 @@ void Foam::functionObjects::fieldAverage::writeFields() const
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType; typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType; typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
forAll(faItems_, i) for (const fieldAverageItem& item : faItems_)
{ {
if (faItems_[i].mean()) if (item.mean())
{ {
const word& fieldName = faItems_[i].meanFieldName(); const word& fieldName = item.meanFieldName();
writeFieldType<VolFieldType>(fieldName); writeFieldType<VolFieldType>(fieldName);
writeFieldType<SurfaceFieldType>(fieldName); writeFieldType<SurfaceFieldType>(fieldName);
writeFieldType<SurfFieldType>(fieldName); writeFieldType<SurfFieldType>(fieldName);
} }
if (faItems_[i].prime2Mean()) if (item.prime2Mean())
{ {
const word& fieldName = faItems_[i].prime2MeanFieldName(); const word& fieldName = item.prime2MeanFieldName();
writeFieldType<VolFieldType>(fieldName); writeFieldType<VolFieldType>(fieldName);
writeFieldType<SurfaceFieldType>(fieldName); writeFieldType<SurfaceFieldType>(fieldName);
writeFieldType<SurfFieldType>(fieldName); writeFieldType<SurfFieldType>(fieldName);
} }
if (item.window() > 0)
{
FIFOStack<word> fieldNames = item.windowFieldNames();
forAllConstIters(fieldNames, fieldNameIter)
{
const word& fieldName = fieldNameIter();
writeFieldType<VolFieldType>(fieldName);
writeFieldType<SurfaceFieldType>(fieldName);
writeFieldType<SurfFieldType>(fieldName);
}
}
} }
} }