Merge branch 'feature-fieldAverage-windowing' into 'develop'

Feature field average windowing

See merge request Development/OpenFOAM-plus!165
This commit is contained in:
Andrew Heather
2017-11-13 08:59:36 +00:00
9 changed files with 1170 additions and 385 deletions

View File

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

View File

@ -42,79 +42,50 @@ namespace functionObjects
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::functionObjects::fieldAverage::resetFields()
{
forAll(faItems_, i)
{
if (faItems_[i].mean())
{
if (obr().found(faItems_[i].meanFieldName()))
{
obr().checkOut(*obr()[faItems_[i].meanFieldName()]);
}
}
if (faItems_[i].prime2Mean())
{
if (obr().found(faItems_[i].prime2MeanFieldName()))
{
obr().checkOut(*obr()[faItems_[i].prime2MeanFieldName()]);
}
}
}
}
void Foam::functionObjects::fieldAverage::initialize()
{
if (!totalIter_.size())
for (fieldAverageItem& item : faItems_)
{
totalIter_.setSize(faItems_.size(), 1);
// Note: not clearing data needed for restart
item.clear(obr(), 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();
Log << type() << " " << name() << ":" << nl;
// Add mean fields to the field lists
forAll(faItems_, fieldi)
for (fieldAverageItem& item : faItems_)
{
addMeanField<scalar>(fieldi);
addMeanField<vector>(fieldi);
addMeanField<sphericalTensor>(fieldi);
addMeanField<symmTensor>(fieldi);
addMeanField<tensor>(fieldi);
addMeanField<scalar>(item);
addMeanField<vector>(item);
addMeanField<sphericalTensor>(item);
addMeanField<symmTensor>(item);
addMeanField<tensor>(item);
}
// Add prime-squared mean fields to the field lists
forAll(faItems_, fieldi)
for (fieldAverageItem& item : faItems_)
{
addPrime2MeanField<scalar, scalar>(fieldi);
addPrime2MeanField<vector, symmTensor>(fieldi);
addPrime2MeanField<scalar, scalar>(item);
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
<< "Field " << faItems_[fieldi].fieldName()
<< "Field " << item.fieldName()
<< " not found in database for averaging";
}
}
@ -133,8 +104,10 @@ void Foam::functionObjects::fieldAverage::restart()
<< obr().time().timeOutputValue()
<< nl << endl;
totalIter_.clear();
totalTime_.clear();
for (fieldAverageItem& item : faItems_)
{
item.clear(obr(), true);
}
initialize();
}
@ -180,6 +153,17 @@ void Foam::functionObjects::fieldAverage::calcAverages()
Log << type() << " " << name() << " write:" << 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<vector, symmTensor>();
@ -192,12 +176,6 @@ void Foam::functionObjects::fieldAverage::calcAverages()
calculatePrime2MeanFields<scalar, scalar>();
calculatePrime2MeanFields<vector, symmTensor>();
forAll(faItems_, fieldi)
{
totalIter_[fieldi]++;
totalTime_[fieldi] += obr().time().deltaTValue();
}
Log << endl;
}
@ -218,28 +196,17 @@ void Foam::functionObjects::fieldAverage::writeAverages() const
void Foam::functionObjects::fieldAverage::writeAveragingProperties()
{
forAll(faItems_, fieldi)
for (const fieldAverageItem& item : faItems_)
{
const word& fieldName = faItems_[fieldi].fieldName();
dictionary propsDict;
propsDict.add("totalIter", totalIter_[fieldi]);
propsDict.add("totalTime", totalTime_[fieldi]);
setProperty(fieldName, propsDict);
item.writeState(propsDict);
setProperty(item.fieldName(), propsDict);
}
}
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_)
{
Info<< " Starting averaging at time "
@ -251,23 +218,32 @@ void Foam::functionObjects::fieldAverage::readAveragingProperties()
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))
{
dictionary fieldDict;
getDict(fieldName, fieldDict);
item.readState(fieldDict);
totalIter_[fieldi] = readLabel(fieldDict.lookup("totalIter"));
totalTime_[fieldi] = readScalar(fieldDict.lookup("totalTime"));
if (item.allowRestart())
{
scalar userTotalTime =
obr().time().timeToUserTime(item.totalTime());
scalar userTotalTime =
obr().time().timeToUserTime(totalTime_[fieldi]);
Info<< " " << fieldName
<< ": iters = " << item.totalIter()
<< " time = " << userTotalTime << nl;
}
else
{
item.clear(obr(), true);
Info<< " " << fieldName
<< " iters = " << totalIter_[fieldi]
<< " time = " << userTotalTime << nl;
Info<< " " << fieldName
<< ": starting averaging at time "
<< obr().time().timeOutputValue() << endl;
}
}
else
{
@ -298,8 +274,6 @@ Foam::functionObjects::fieldAverage::fieldAverage
restartTime_(GREAT),
initialised_(false),
faItems_(),
totalIter_(),
totalTime_(),
periodIndex_(1)
{
read(dict);
@ -321,10 +295,10 @@ bool Foam::functionObjects::fieldAverage::read(const dictionary& dict)
// Make certain that the values are consistent with the defaults:
initialised_ = false;
restartOnRestart_ = false;
restartOnOutput_ = false;
periodicRestart_ = false;
restartPeriod_ = GREAT;
restartTime_ = GREAT;
restartOnOutput_ = false;
periodicRestart_ = false;
restartPeriod_ = GREAT;
restartTime_ = GREAT;
Info<< type() << " " << name() << ":" << nl;

View File

@ -86,6 +86,7 @@ Usage
mean on;
prime2Mean on;
base time;
windowType exact;
window 10.0;
windowName w1;
}
@ -131,6 +132,7 @@ SourceFiles
#define functionObjects_fieldAverage_H
#include "fvMeshFunctionObject.H"
#include "FIFOStack.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -195,10 +197,6 @@ protected:
// Initialisation routines
//- Checkout fields (causes deletion) from the database
// and reset lists
void resetFields();
//- Reset lists (clear existing values) and initialize averaging.
// Check requested field averages are valid, populate field lists
void initialize();
@ -208,19 +206,19 @@ protected:
//- Add mean average field to database
template<class Type>
void addMeanFieldType(const label fieldi);
void addMeanFieldType(fieldAverageItem& item);
//- Add mean average field to database
template<class Type>
void addMeanField(const label fieldi);
void addMeanField(fieldAverageItem& item);
//- Add prime-squared average field to database
template<class Type1, class Type2>
void addPrime2MeanFieldType(const label fieldi);
void addPrime2MeanFieldType(fieldAverageItem& item);
//- Add prime-squared average field to database
template<class Type1, class Type2>
void addPrime2MeanField(const label fieldi);
void addPrime2MeanField(fieldAverageItem& item);
// Calculation functions
@ -228,30 +226,33 @@ protected:
//- Main calculation routine
virtual void calcAverages();
//- Calculate mean average fields
template<class Type>
void calculateMeanFieldType(const label fieldi) const;
//- Calculate mean average fields
template<class Type>
void calculateMeanFields() const;
//- Calculate prime-squared average fields
template<class Type1, class Type2>
void calculatePrime2MeanFieldType(const label fieldi) const;
//- Calculate prime-squared average fields
template<class Type1, class Type2>
void calculatePrime2MeanFields() const;
//- Add mean-squared field value to prime-squared mean field
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
template<class Type1, class Type2>
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

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,6 +32,7 @@ const Foam::word Foam::functionObjects::fieldAverageItem::EXT_MEAN
"Mean"
);
const Foam::word Foam::functionObjects::fieldAverageItem::EXT_PRIME2MEAN
(
"Prime2Mean"
@ -49,19 +50,38 @@ 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 * * * * * * * * * * * * * * //
Foam::functionObjects::fieldAverageItem::fieldAverageItem()
:
active_(false),
fieldName_("unknown"),
mean_(0),
mean_(false),
meanFieldName_("unknown"),
prime2Mean_(0),
prime2Mean_(false),
prime2MeanFieldName_("unknown"),
base_(ITER),
window_(-1.0),
windowName_("")
base_(baseType::ITER),
totalIter_(0),
totalTime_(-1),
window_(-1),
windowName_(""),
windowType_(windowType::NONE),
windowTimes_(),
windowFieldNames_(),
allowRestart_(true)
{}
@ -77,8 +97,15 @@ Foam::functionObjects::fieldAverageItem::fieldAverageItem
prime2Mean_(faItem.prime2Mean_),
prime2MeanFieldName_(faItem.prime2MeanFieldName_),
base_(faItem.base_),
totalIter_(faItem.totalIter_),
totalTime_(faItem.totalTime_),
window_(faItem.window_),
windowName_(faItem.windowName_)
windowName_(faItem.windowName_),
windowType_(faItem.windowType_),
windowTimes_(faItem.windowTimes_),
windowFieldNames_(faItem.windowFieldNames_),
allowRestart_(faItem.allowRestart_)
{}
@ -88,6 +115,112 @@ 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::clear
(
const objectRegistry& obr,
bool fullClean
)
{
if (mean_ && obr.found(meanFieldName_))
{
obr.checkOut(*obr[meanFieldName_]);
}
if (prime2Mean_ && obr.found(prime2MeanFieldName_))
{
obr.checkOut(*obr[prime2MeanFieldName_]);
}
for (const word& fieldName : windowFieldNames_)
{
if (obr.found(fieldName))
{
obr.checkOut(*obr[fieldName]);
}
}
if (totalTime_ < 0 || fullClean)
{
totalIter_ = 0;
totalTime_ = 0;
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 * * * * * * * * * * * * * //
void Foam::functionObjects::fieldAverageItem::operator=
@ -111,8 +244,14 @@ void Foam::functionObjects::fieldAverageItem::operator=
prime2Mean_ = rhs.prime2Mean_;
prime2MeanFieldName_ = rhs.prime2MeanFieldName_;
base_ = rhs.base_;
totalIter_ = rhs.totalIter_;
totalTime_ = rhs.totalTime_;
window_ = rhs.window_;
windowName_ = rhs.windowName_;
windowType_ = rhs.windowType_;
windowTimes_ = rhs.windowTimes_;
windowFieldNames_ = rhs.windowFieldNames_;
allowRestart_ = rhs.allowRestart_;
}

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -35,12 +35,21 @@ Description
base time; // iteration
window 200; // optional averaging window
windowName w1; // optional window name (default = "")
windowType approximate; // window type
allowRestart yes; // optional, used for windowType 'exact'
}
\endverbatim
The averaging window corresponds to the averaging interval (iters or 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
fieldAverageItem.C
fieldAverageItemIO.C
@ -52,6 +61,7 @@ SourceFiles
#include "Enum.H"
#include "Switch.H"
#include "FIFOStack.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -61,6 +71,7 @@ namespace Foam
// Forward declaration of classes
class Istream;
class Ostream;
class objectRegistry;
namespace functionObjects
{
@ -88,13 +99,22 @@ public:
//- Prime-squared average
static const word EXT_PRIME2MEAN;
//- Enumeration defining the averaging base type
enum baseType
enum class baseType
{
ITER,
TIME
};
//- Enumeration defining the averaging window type
enum class windowType
{
NONE,
APPROXIMATE,
EXACT
};
private:
@ -124,12 +144,33 @@ private:
//- Averaging base type
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'
scalar window_;
//- Averaging window name - defaults to 'window'
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_;
//- Switch to write all necessary files for clean restart
bool allowRestart_;
public:
@ -154,86 +195,96 @@ public:
// Access
//- Return const access to the active flag
bool active() const
{
return active_;
}
inline bool active() const;
//- Return non-const access to the active flag
bool& active()
{
return active_;
}
inline bool& active();
//- Return const access to the field name
const word& fieldName() const
{
return fieldName_;
}
inline const word& fieldName() const;
//- Return const access to the mean flag
bool mean() const
{
return mean_;
}
inline bool mean() const;
//- Return non-const access to the mean flag
bool& mean()
{
return mean_;
}
inline bool& mean();
//- Return const access to the mean field name
const word& meanFieldName() const
{
return meanFieldName_;
}
inline const word& meanFieldName() const;
//- Return const access to the prime-squared mean flag
bool prime2Mean() const
{
return prime2Mean_;
}
inline bool prime2Mean() const;
//- Return non-const access to the prime-squared mean flag
bool& prime2Mean()
{
return prime2Mean_;
}
inline bool& prime2Mean();
//- Return const access to the prime-squared mean field name
const word& prime2MeanFieldName() const
{
return prime2MeanFieldName_;
}
inline const word& prime2MeanFieldName() const;
//- Return averaging base type name
const word base() const
{
return baseTypeNames_[base_];
}
inline const word& base() const;
//- Return true if base is ITER
bool iterBase() const
{
return base_ == ITER;
}
//- Return the total number of iterations item has been evolved
inline label totalIter() const;
//- Return true if base is time
bool timeBase() const
{
return base_ == TIME;
}
//- Return the total time item has been evolved
inline scalar totalTime() const;
scalar window() const
{
return window_;
}
//- Return the window length (iterations or seconds)
inline scalar window() const;
const word& windowName() const
{
return windowName_;
}
//- Return the (optional) window name
inline const word& windowName() const;
//- 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 allow restart flag
inline bool allowRestart() 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;
//- Return true if we wish to store window fields
inline bool storeWindowFields() const;
//- Return true if we wish to write window fields
inline bool writeWindowFields() const;
//- Add field to window
void addToWindow(const word& fieldName, const scalar deltaT);
//- Evolve and update
void evolve(const objectRegistry& obr);
//- Clear out all mean fields and (optionally) supporting data
void clear(const objectRegistry& obr, const bool fullClean);
//- 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
@ -257,8 +308,12 @@ public:
&& a.prime2Mean_ == b.prime2Mean_
&& a.prime2MeanFieldName_ == b.prime2MeanFieldName_
&& a.base_ == b.base_
&& a.totalIter_ == b.totalIter_
&& a.totalTime_ == b.totalTime_
&& a.window_ == b.window_
&& a.windowName_ == b.windowName_;
&& a.windowName_ == b.windowName_
&& a.windowType_ == b.windowType_
&& a.allowRestart_ == b.allowRestart_;
}
friend bool operator!=
@ -285,6 +340,16 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "fieldAverageItemI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "fieldAverageItemTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,230 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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_;
}
bool Foam::functionObjects::fieldAverageItem::allowRestart() const
{
return allowRestart_;
}
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;
}
bool Foam::functionObjects::fieldAverageItem::storeWindowFields() const
{
return windowType_ == windowType::EXACT;
}
bool Foam::functionObjects::fieldAverageItem::writeWindowFields() const
{
return (allowRestart_ && window_ > 0);
}
// ************************************************************************* //

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -33,31 +33,22 @@ Foam::functionObjects::fieldAverageItem::fieldAverageItem(Istream& is)
:
active_(false),
fieldName_("unknown"),
mean_(0),
mean_(false),
meanFieldName_("unknown"),
prime2Mean_(0),
prime2Mean_(false),
prime2MeanFieldName_("unknown"),
base_(ITER),
window_(-1.0)
base_(baseType::ITER),
totalIter_(0),
totalTime_(-1),
window_(-1.0),
windowName_(""),
windowType_(windowType::NONE),
windowTimes_(),
windowFieldNames_(),
allowRestart_(true)
{
is.check(FUNCTION_NAME);
const dictionaryEntry entry(dictionary::null, is);
fieldName_ = entry.keyword();
mean_ = readBool(entry.lookup("mean"));
prime2Mean_ = readBool(entry.lookup("prime2Mean"));
base_ = baseTypeNames_.lookup("base", entry);
window_ = entry.lookupOrDefault<scalar>("window", -1.0);
windowName_ = entry.lookupOrDefault<word>("windowName", "");
meanFieldName_ = fieldName_ + EXT_MEAN;
prime2MeanFieldName_ = fieldName_ + EXT_PRIME2MEAN;
if ((window_ > 0) && (windowName_ != ""))
{
meanFieldName_ = meanFieldName_ + "_" + windowName_;
prime2MeanFieldName_ = prime2MeanFieldName_ + "_" + windowName_;
}
is >> *this;
}
@ -79,13 +70,61 @@ Foam::Istream& Foam::functionObjects::operator>>
faItem.prime2Mean_ = readBool(entry.lookup("prime2Mean"));
faItem.base_ = faItem.baseTypeNames_.lookup("base", entry);
faItem.window_ = entry.lookupOrDefault<scalar>("window", -1.0);
faItem.windowName_ = entry.lookupOrDefault<word>("windowName", "");
if (faItem.window_ > 0)
{
faItem.windowType_ =
faItem.windowTypeNames_.lookup("windowType", entry);
if (faItem.windowType_ != fieldAverageItem::windowType::NONE)
{
if
(
faItem.base_ == fieldAverageItem::baseType::ITER
&& label(faItem.window_) < 1
)
{
FatalIOErrorInFunction(entry)
<< "Window must be 1 or more for base type "
<< faItem.baseTypeNames_[fieldAverageItem::baseType::ITER]
<< exit(FatalIOError);
}
faItem.windowName_ = entry.lookupOrDefault<word>("windowName", "");
if (faItem.windowType_ == fieldAverageItem::windowType::EXACT)
{
faItem.allowRestart_ = readBool(entry.lookup("allowRestart"));
if (!faItem.allowRestart_)
{
WarningInFunction
<< faItem.windowTypeNames_[faItem.windowType_]
<< " windowing for field " << faItem.fieldName_
<< " will not write intermediate files and restart will"
<< " not be possible. To enable, please set"
<< " 'allowRestart' to 'yes'"
<< endl;
}
}
}
else
{
// Deactivate windowing
faItem.window_ = -1;
}
}
else
{
// Deactivate windowing
faItem.window_ = -1;
}
faItem.meanFieldName_ = faItem.fieldName_ + fieldAverageItem::EXT_MEAN;
faItem.prime2MeanFieldName_ =
faItem.fieldName_ + fieldAverageItem::EXT_PRIME2MEAN;
if ((faItem.window_ > 0) && (faItem.windowName_ != ""))
if ((faItem.window_ > 0) && (!faItem.windowName_.empty()))
{
faItem.meanFieldName_ =
faItem.meanFieldName_ + "_" + faItem.windowName_;
@ -93,6 +132,7 @@ Foam::Istream& Foam::functionObjects::operator>>
faItem.prime2MeanFieldName_ =
faItem.prime2MeanFieldName_ + "_" + faItem.windowName_;
}
return is;
}
@ -105,28 +145,34 @@ Foam::Ostream& Foam::functionObjects::operator<<
{
os.check(FUNCTION_NAME);
os << faItem.fieldName_ << nl << token::BEGIN_BLOCK << nl;
os.writeKeyword("mean") << faItem.mean_ << token::END_STATEMENT << nl;
os.writeKeyword("prime2Mean") << faItem.prime2Mean_
<< token::END_STATEMENT << nl;
os.writeKeyword("base") << faItem.baseTypeNames_[faItem.base_]
<< token::END_STATEMENT << nl;
os.beginBlock(faItem.fieldName_);
os.writeEntry("mean", faItem.mean_);
os.writeEntry("prime2Mean", faItem.prime2Mean_);
os.writeEntry("base", faItem.baseTypeNames_[faItem.base_]);
if (faItem.window_ > 0)
{
os.writeKeyword("window") << faItem.window_
<< token::END_STATEMENT << nl;
os.writeEntry("window", faItem.window_);
if (faItem.windowName_ != "")
if (!faItem.windowName_.empty())
{
os.writeKeyword("windowName") << faItem.windowName_
<< token::END_STATEMENT << nl;
os.writeEntry("windowName", faItem.windowName_);
}
os.writeEntry
(
"windowType",
faItem.windowTypeNames_[faItem.windowType_]
);
os.writeEntry("allowRestart", faItem.allowRestart_);
}
os << token::END_BLOCK << nl;
os.endBlock() << flush;
os.check(FUNCTION_NAME);
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
\\ / O peration |
\\ / 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
This file is part of OpenFOAM.
@ -32,13 +32,22 @@ License
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
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
faItems_[fieldi].active() = true;
const word& fieldName = item.fieldName();
const word& fieldName = faItems_[fieldi].fieldName();
const word& meanFieldName = faItems_[fieldi].meanFieldName();
if (!foundObject<Type>(fieldName))
{
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;
@ -50,7 +59,7 @@ void Foam::functionObjects::fieldAverage::addMeanFieldType(const label fieldi)
<< " since an object with that name already exists."
<< " Disabling averaging for field." << endl;
faItems_[fieldi].mean() = false;
item.mean() = false;
}
else
{
@ -66,9 +75,9 @@ void Foam::functionObjects::fieldAverage::addMeanFieldType(const label fieldi)
meanFieldName,
obr().time().timeName(obr().time().startTime().value()),
obr(),
restartOnOutput_
? IOobject::NO_READ
: IOobject::READ_IF_PRESENT,
restartOnOutput_ ?
IOobject::NO_READ
: IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE
),
1*baseField
@ -79,41 +88,109 @@ void Foam::functionObjects::fieldAverage::addMeanFieldType(const label fieldi)
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, fvsPatchField, surfaceMesh> SurfaceFieldType;
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<Type>(true))
{
addMeanFieldType<VolFieldType>(fieldi);
DebugInfo << "Read and store: " << name << endl;
obr().store(new Type(io, fieldPtr->mesh()));
}
else if (foundObject<SurfaceFieldType>(fieldName))
else
{
addMeanFieldType<SurfaceFieldType>(fieldi);
}
else if (foundObject<SurfFieldType>(fieldName))
{
addMeanFieldType<SurfFieldType>(fieldi);
WarningInFunction
<< "Unable to read window " << Type::typeName << " " << name
<< ". Averaging restart behaviour may be compromised"
<< endl;
}
}
}
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>
void Foam::functionObjects::fieldAverage::addPrime2MeanFieldType
(
const label fieldi
fieldAverageItem& item
)
{
const word& fieldName = faItems_[fieldi].fieldName();
const word& meanFieldName = faItems_[fieldi].meanFieldName();
const word& prime2MeanFieldName = faItems_[fieldi].prime2MeanFieldName();
const word& fieldName = item.fieldName();
if (!foundObject<Type1>(fieldName))
{
return;
}
const word& meanFieldName = item.meanFieldName();
const word& prime2MeanFieldName = item.prime2MeanFieldName();
Log << " Reading/initialising field " << prime2MeanFieldName << nl;
@ -125,7 +202,7 @@ void Foam::functionObjects::fieldAverage::addPrime2MeanFieldType
<< " since an object with that name already exists."
<< " Disabling averaging for field." << endl;
faItems_[fieldi].prime2Mean() = false;
item.prime2Mean() = false;
}
else
{
@ -142,9 +219,9 @@ void Foam::functionObjects::fieldAverage::addPrime2MeanFieldType
prime2MeanFieldName,
obr().time().timeName(obr().time().startTime().value()),
obr(),
restartOnOutput_
? IOobject::NO_READ
: IOobject::READ_IF_PRESENT,
restartOnOutput_?
IOobject::NO_READ
: IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE
),
sqr(baseField) - sqr(meanField)
@ -155,7 +232,10 @@ void Foam::functionObjects::fieldAverage::addPrime2MeanFieldType
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, fvsPatchField, surfaceMesh> SurfaceFieldType1;
@ -165,79 +245,79 @@ void Foam::functionObjects::fieldAverage::addPrime2MeanField(const label fieldi)
typedef GeometricField<Type2, fvsPatchField, surfaceMesh> SurfaceFieldType2;
typedef DimensionedField<Type2, surfGeoMesh> SurfFieldType2;
if (faItems_[fieldi].prime2Mean())
if (item.prime2Mean())
{
const word& fieldName = faItems_[fieldi].fieldName();
if (!faItems_[fieldi].mean())
if (!item.mean())
{
FatalErrorInFunction
<< "To calculate the prime-squared average, the "
<< "mean average must also be selected for field "
<< fieldName << nl << exit(FatalError);
<< item.fieldName() << nl << exit(FatalError);
}
if (foundObject<VolFieldType1>(fieldName))
{
addPrime2MeanFieldType<VolFieldType1, VolFieldType2>(fieldi);
}
else if (foundObject<SurfaceFieldType1>(fieldName))
{
addPrime2MeanFieldType<SurfaceFieldType1, SurfaceFieldType2>
(
fieldi
);
}
else if (foundObject<SurfFieldType1>(fieldName))
{
addPrime2MeanFieldType<SurfFieldType1, SurfFieldType2>
(
fieldi
);
}
addPrime2MeanFieldType<VolFieldType1, VolFieldType2>(item);
addPrime2MeanFieldType<SurfaceFieldType1, SurfaceFieldType2>(item);
addPrime2MeanFieldType<SurfFieldType1, SurfFieldType2>(item);
}
}
template<class Type>
void Foam::functionObjects::fieldAverage::calculateMeanFieldType
void Foam::functionObjects::fieldAverage::storeWindowFieldType
(
const label fieldi
) const
fieldAverageItem& item
)
{
const word& fieldName = faItems_[fieldi].fieldName();
if (foundObject<Type>(fieldName))
const word& fieldName = item.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();
scalar Dt = totalTime_[fieldi];
DebugInfo << "Create and store: " << windowFieldName << endl;
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.storeWindowFields())
{
dt = 1;
Dt = scalar(totalIter_[fieldi]);
storeWindowFieldType<VolFieldType>(item);
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 +329,11 @@ void Foam::functionObjects::fieldAverage::calculateMeanFields() const
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
forAll(faItems_, i)
for (const fieldAverageItem& item : faItems_)
{
if (faItems_[i].mean())
{
calculateMeanFieldType<VolFieldType>(i);
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);
item.calculateMeanField<VolFieldType>(obr());
item.calculateMeanField<SurfaceFieldType>(obr());
item.calculateMeanField<SurfFieldType>(obr());
}
}
@ -318,21 +349,14 @@ void Foam::functionObjects::fieldAverage::calculatePrime2MeanFields() const
typedef GeometricField<Type2, fvsPatchField, surfaceMesh> SurfaceFieldType2;
typedef DimensionedField<Type2, surfGeoMesh> SurfFieldType2;
forAll(faItems_, i)
for (const fieldAverageItem& item : faItems_)
{
if (faItems_[i].prime2Mean())
{
calculatePrime2MeanFieldType<VolFieldType1, VolFieldType2>(i);
calculatePrime2MeanFieldType<SurfaceFieldType1, SurfaceFieldType2>
(
i
);
calculatePrime2MeanFieldType<SurfFieldType1, SurfFieldType2>
(
i
);
}
item.calculatePrime2MeanField<VolFieldType1, VolFieldType2>(obr());
item.calculatePrime2MeanField<SurfaceFieldType1, SurfaceFieldType2>
(
obr()
);
item.calculatePrime2MeanField<SurfFieldType1, SurfFieldType2>(obr());
}
}
@ -340,21 +364,21 @@ void Foam::functionObjects::fieldAverage::calculatePrime2MeanFields() const
template<class Type1, class Type2>
void Foam::functionObjects::fieldAverage::addMeanSqrToPrime2MeanType
(
const label fieldi
const fieldAverageItem& item
) const
{
const word& fieldName = faItems_[fieldi].fieldName();
const word& fieldName = item.fieldName();
if (foundObject<Type1>(fieldName))
if (!foundObject<Type1>(fieldName))
{
const Type1& meanField =
lookupObject<Type1>(faItems_[fieldi].meanFieldName());
Type2& prime2MeanField =
lookupObjectRef<Type2>(faItems_[fieldi].prime2MeanFieldName());
prime2MeanField += sqr(meanField);
return;
}
const Type1& meanField = lookupObject<Type1>(item.meanFieldName());
Type2& prime2MeanField = lookupObjectRef<Type2>(item.prime2MeanFieldName());
prime2MeanField += sqr(meanField);
}
@ -369,13 +393,16 @@ void Foam::functionObjects::fieldAverage::addMeanSqrToPrime2Mean() const
typedef GeometricField<Type2, fvsPatchField, surfaceMesh> SurfaceFieldType2;
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<SurfaceFieldType1, SurfaceFieldType2>(i);
addMeanSqrToPrime2MeanType<SurfFieldType1, SurfFieldType2>(i);
addMeanSqrToPrime2MeanType<VolFieldType1, VolFieldType2>(item);
addMeanSqrToPrime2MeanType<SurfaceFieldType1, SurfaceFieldType2>
(
item
);
addMeanSqrToPrime2MeanType<SurfFieldType1, SurfFieldType2>(item);
}
}
}
@ -402,22 +429,35 @@ void Foam::functionObjects::fieldAverage::writeFields() const
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
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<SurfaceFieldType>(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<SurfaceFieldType>(fieldName);
writeFieldType<SurfFieldType>(fieldName);
}
if (item.writeWindowFields())
{
FIFOStack<word> fieldNames = item.windowFieldNames();
forAllConstIters(fieldNames, fieldNameIter)
{
const word& fieldName = fieldNameIter();
writeFieldType<VolFieldType>(fieldName);
writeFieldType<SurfaceFieldType>(fieldName);
writeFieldType<SurfFieldType>(fieldName);
}
}
}
}