From 4fc4f49cef9a4b2ceda8804cd8ba68ec273581cd Mon Sep 17 00:00:00 2001 From: Andrew Heather Date: Wed, 9 Aug 2017 16:52:03 +0100 Subject: [PATCH 1/2] 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 --- .../functionObjectList/functionObjectList.C | 3 +- .../field/fieldAverage/fieldAverage.C | 131 +++--- .../field/fieldAverage/fieldAverage.H | 31 +- .../fieldAverageItem/fieldAverageItem.C | 128 +++++- .../fieldAverageItem/fieldAverageItem.H | 172 +++++--- .../fieldAverageItem/fieldAverageItemI.H | 212 ++++++++++ .../fieldAverageItem/fieldAverageItemIO.C | 62 ++- .../fieldAverageItemTemplates.C | 291 ++++++++++++++ .../fieldAverage/fieldAverageTemplates.C | 372 ++++++++++-------- 9 files changed, 1065 insertions(+), 337 deletions(-) create mode 100644 src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemI.H create mode 100644 src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemTemplates.C diff --git a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C index 0082266d5b..56782ea6ee 100644 --- a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C +++ b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C @@ -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; diff --git a/src/functionObjects/field/fieldAverage/fieldAverage.C b/src/functionObjects/field/fieldAverage/fieldAverage.C index be75c66f09..769775639b 100644 --- a/src/functionObjects/field/fieldAverage/fieldAverage.C +++ b/src/functionObjects/field/fieldAverage/fieldAverage.C @@ -44,21 +44,21 @@ namespace functionObjects 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() { - if (!totalIter_.size()) + for (fieldAverageItem& item : faItems_) { - totalIter_.setSize(faItems_.size(), 1); - } - - 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(); - } - } + item.restart(0, false); } resetFields(); @@ -93,28 +77,39 @@ void Foam::functionObjects::fieldAverage::initialize() Log << type() << " " << name() << ":" << nl; // Add mean fields to the field lists - forAll(faItems_, fieldi) + for (fieldAverageItem& item : faItems_) { - addMeanField(fieldi); - addMeanField(fieldi); - addMeanField(fieldi); - addMeanField(fieldi); - addMeanField(fieldi); + addMeanField(item); + addMeanField(item); + addMeanField(item); + addMeanField(item); + addMeanField(item); } // Add prime-squared mean fields to the field lists - forAll(faItems_, fieldi) + for (fieldAverageItem& item : faItems_) { - addPrime2MeanField(fieldi); - addPrime2MeanField(fieldi); + addPrime2MeanField(item); + addPrime2MeanField(item); } - forAll(faItems_, fieldi) + // Add window fields to the field lists + for (const fieldAverageItem& item : faItems_) { - if (!faItems_[fieldi].active()) + restoreWindowFields(item); + restoreWindowFields(item); + restoreWindowFields(item); + restoreWindowFields(item); + restoreWindowFields(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 +128,10 @@ void Foam::functionObjects::fieldAverage::restart() << obr().time().timeOutputValue() << nl << endl; - totalIter_.clear(); - totalTime_.clear(); + for (fieldAverageItem& item : faItems_) + { + item.restart(0, true); + } initialize(); } @@ -180,6 +177,17 @@ void Foam::functionObjects::fieldAverage::calcAverages() Log << type() << " " << name() << " write:" << nl << " Calculating averages" << nl; + forAll(faItems_, fieldi) + { + faItems_[fieldi].evolve(obr()); + } + + storeWindowFields(); + storeWindowFields(); + storeWindowFields(); + storeWindowFields(); + storeWindowFields(); + addMeanSqrToPrime2Mean(); addMeanSqrToPrime2Mean(); @@ -192,12 +200,6 @@ void Foam::functionObjects::fieldAverage::calcAverages() calculatePrime2MeanFields(); calculatePrime2MeanFields(); - forAll(faItems_, fieldi) - { - totalIter_[fieldi]++; - totalTime_[fieldi] += obr().time().deltaTValue(); - } - Log << endl; } @@ -218,28 +220,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,22 +242,20 @@ 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); - - totalIter_[fieldi] = readLabel(fieldDict.lookup("totalIter")); - totalTime_[fieldi] = readScalar(fieldDict.lookup("totalTime")); + item.readState(fieldDict); scalar userTotalTime = - obr().time().timeToUserTime(totalTime_[fieldi]); + obr().time().timeToUserTime(item.totalTime()); Info<< " " << fieldName - << " iters = " << totalIter_[fieldi] + << " iters = " << item.totalIter() << " time = " << userTotalTime << nl; } else @@ -298,8 +287,6 @@ Foam::functionObjects::fieldAverage::fieldAverage restartTime_(GREAT), initialised_(false), faItems_(), - totalIter_(), - totalTime_(), periodIndex_(1) { read(dict); @@ -321,10 +308,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; diff --git a/src/functionObjects/field/fieldAverage/fieldAverage.H b/src/functionObjects/field/fieldAverage/fieldAverage.H index e0de5ee6fb..52a907a405 100644 --- a/src/functionObjects/field/fieldAverage/fieldAverage.H +++ b/src/functionObjects/field/fieldAverage/fieldAverage.H @@ -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" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -208,19 +210,19 @@ protected: //- Add mean average field to database template - void addMeanFieldType(const label fieldi); + void addMeanFieldType(fieldAverageItem& item); //- Add mean average field to database template - void addMeanField(const label fieldi); + void addMeanField(fieldAverageItem& item); //- Add prime-squared average field to database template - void addPrime2MeanFieldType(const label fieldi); + void addPrime2MeanFieldType(fieldAverageItem& item); //- Add prime-squared average field to database template - void addPrime2MeanField(const label fieldi); + void addPrime2MeanField(fieldAverageItem& item); // Calculation functions @@ -228,30 +230,33 @@ protected: //- Main calculation routine virtual void calcAverages(); - //- Calculate mean average fields - template - void calculateMeanFieldType(const label fieldi) const; - //- Calculate mean average fields template void calculateMeanFields() const; - //- Calculate prime-squared average fields - template - void calculatePrime2MeanFieldType(const label fieldi) const; - //- Calculate prime-squared average fields template void calculatePrime2MeanFields() const; //- Add mean-squared field value to prime-squared mean field template - void addMeanSqrToPrime2MeanType(const label fieldi) const; + void addMeanSqrToPrime2MeanType(const fieldAverageItem& item) const; //- Add mean-squared field value to prime-squared mean field template void addMeanSqrToPrime2Mean() const; + template + void storeWindowFieldType(fieldAverageItem& item); + + template + void storeWindowFields(); + + template + void restoreWindowFieldsType(const fieldAverageItem& item); + + template + void restoreWindowFields(const fieldAverageItem& item); // I-O diff --git a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.C b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.C index f42858f1f6..d96261d763 100644 --- a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.C +++ b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.C @@ -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,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 * * * * * * * * * * * * * * // Foam::functionObjects::fieldAverageItem::fieldAverageItem() @@ -59,9 +72,15 @@ Foam::functionObjects::fieldAverageItem::fieldAverageItem() meanFieldName_("unknown"), prime2Mean_(0), prime2MeanFieldName_("unknown"), - base_(ITER), - window_(-1.0), - windowName_("") + base_(baseType::ITER), + totalIter_(0), + totalTime_(-1), + window_(-1), + windowName_(""), + windowType_(windowType::NONE), + + windowTimes_(), + windowFieldNames_() {} @@ -77,8 +96,14 @@ 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_) {} @@ -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 * * * * * * * * * * * * * // void Foam::functionObjects::fieldAverageItem::operator= @@ -111,8 +224,13 @@ 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_; } diff --git a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.H b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.H index d683cafea7..c54bc66866 100644 --- a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.H +++ b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.H @@ -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,19 @@ Description base time; // iteration window 200; // optional averaging window windowName w1; // optional window name (default = "") + windowType approximate; // window type } \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 +59,7 @@ SourceFiles #include "Enum.H" #include "Switch.H" +#include "FIFOStack.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -61,6 +69,7 @@ namespace Foam // Forward declaration of classes class Istream; class Ostream; +class objectRegistry; namespace functionObjects { @@ -88,13 +97,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 +142,30 @@ 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 windowTypeNames_; + + //- List of window times (windowType = EXACT) + FIFOStack windowTimes_; + + //- List of window field names (windowType = EXACT) + FIFOStack windowFieldNames_; + public: @@ -154,86 +190,87 @@ 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& windowTimes() const; + + //- Return the list of window field names (windowType = EXACT) + inline const FIFOStack& 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 + bool calculateMeanField(const objectRegistry& obr) const; + + //- Calculate prime-squared average fields + template + bool calculatePrime2MeanField(const objectRegistry& obr) const; // Member Operators @@ -257,8 +294,11 @@ 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_; } friend bool operator!= @@ -285,6 +325,16 @@ public: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +#include "fieldAverageItemI.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "fieldAverageItemTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + #endif // ************************************************************************* // diff --git a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemI.H b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemI.H new file mode 100644 index 0000000000..b7426dd06e --- /dev/null +++ b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemI.H @@ -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 . + + +\*---------------------------------------------------------------------------*/ + + +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::functionObjects::fieldAverageItem::windowTimes() const +{ + return windowTimes_; +} + + +const Foam::FIFOStack& +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; +} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemIO.C b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemIO.C index a057aba576..faef22d688 100644 --- a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemIO.C +++ b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemIO.C @@ -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. @@ -37,8 +37,15 @@ Foam::functionObjects::fieldAverageItem::fieldAverageItem(Istream& is) meanFieldName_("unknown"), prime2Mean_(0), prime2MeanFieldName_("unknown"), - base_(ITER), - window_(-1.0) + base_(baseType::ITER), + totalIter_(0), + totalTime_(-1), + window_(-1.0), + windowName_(""), + windowType_(windowType::NONE), + + windowTimes_(), + windowFieldNames_() { is.check(FUNCTION_NAME); @@ -49,11 +56,21 @@ Foam::functionObjects::fieldAverageItem::fieldAverageItem(Istream& is) prime2Mean_ = readBool(entry.lookup("prime2Mean")); base_ = baseTypeNames_.lookup("base", entry); window_ = entry.lookupOrDefault("window", -1.0); - windowName_ = entry.lookupOrDefault("windowName", ""); + + if (window_ > 0) + { + windowName_ = entry.lookupOrDefault("windowName", ""); + windowType_ = windowTypeNames_.lookup("windowType", entry); + + if (windowType_ == windowType::NONE) + { + window_ = -1; + } + } meanFieldName_ = fieldName_ + EXT_MEAN; prime2MeanFieldName_ = fieldName_ + EXT_PRIME2MEAN; - if ((window_ > 0) && (windowName_ != "")) + if ((window_ > 0) && (!windowName_.empty())) { meanFieldName_ = meanFieldName_ + "_" + windowName_; prime2MeanFieldName_ = prime2MeanFieldName_ + "_" + windowName_; @@ -79,13 +96,24 @@ Foam::Istream& Foam::functionObjects::operator>> faItem.prime2Mean_ = readBool(entry.lookup("prime2Mean")); faItem.base_ = faItem.baseTypeNames_.lookup("base", entry); faItem.window_ = entry.lookupOrDefault("window", -1.0); - faItem.windowName_ = entry.lookupOrDefault("windowName", ""); + + if (faItem.window_ > 0) + { + faItem.windowName_ = entry.lookupOrDefault("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.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_; @@ -105,7 +133,8 @@ Foam::Ostream& Foam::functionObjects::operator<< { 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("prime2Mean") << faItem.prime2Mean_ << token::END_STATEMENT << nl; @@ -114,19 +143,24 @@ Foam::Ostream& Foam::functionObjects::operator<< 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 << token::END_BLOCK << nl; + os.endBlock() << flush; os.check(FUNCTION_NAME); + return os; } diff --git a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemTemplates.C b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemTemplates.C new file mode 100644 index 0000000000..f7a752b993 --- /dev/null +++ b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemTemplates.C @@ -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 . + +\*---------------------------------------------------------------------------*/ + +#include "objectRegistry.H" +#include "Time.H" + +template +bool Foam::functionObjects::fieldAverageItem::calculateMeanField +( + const objectRegistry& obr +) const +{ + if (!mean_) + { + return false; + } + + const Type* baseFieldPtr = obr.lookupObjectPtr(fieldName_); + + if (!baseFieldPtr) + { + return false; + } + + const Type& baseField = *baseFieldPtr; + Type& meanField = obr.lookupObjectRef(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(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::const_iterator timeIter = + windowTimes_.begin(); + FIFOStack::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(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 +bool Foam::functionObjects::fieldAverageItem::calculatePrime2MeanField +( + const objectRegistry& obr +) const +{ + if (!prime2Mean_) + { + return false; + } + + const Type1* baseFieldPtr = obr.lookupObjectPtr(fieldName_); + + if (!baseFieldPtr) + { + return false; + } + + const Type1& baseField = *baseFieldPtr; + const Type1& meanField = obr.lookupObject(meanFieldName_); + + Type2& prime2MeanField = + obr.lookupObjectRef(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::const_iterator timeIter = + windowTimes_.begin(); + FIFOStack::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(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; +} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/fieldAverage/fieldAverageTemplates.C b/src/functionObjects/field/fieldAverage/fieldAverageTemplates.C index 490325d809..9946d67a21 100644 --- a/src/functionObjects/field/fieldAverage/fieldAverageTemplates.C +++ b/src/functionObjects/field/fieldAverage/fieldAverageTemplates.C @@ -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 -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(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,102 @@ void Foam::functionObjects::fieldAverage::addMeanFieldType(const label fieldi) template -void Foam::functionObjects::fieldAverage::addMeanField(const label fieldi) +void Foam::functionObjects::fieldAverage::addMeanField +( + fieldAverageItem& item +) { typedef GeometricField VolFieldType; typedef GeometricField SurfaceFieldType; typedef DimensionedField SurfFieldType; - if (faItems_[fieldi].mean()) + if (item.mean()) { - const word& fieldName = faItems_[fieldi].fieldName(); + addMeanFieldType(item); + addMeanFieldType(item); + addMeanFieldType(item); + } +} - if (foundObject(fieldName)) + +template +void Foam::functionObjects::fieldAverage::restoreWindowFieldsType +( + const fieldAverageItem& item +) +{ + if (restartOnOutput_) + { + return; + } + + const word& fieldName = item.fieldName(); + + const Type* fieldPtr = lookupObjectPtr(fieldName); + + if (!fieldPtr) + { + return; + } + + const FIFOStack& 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(false)) { - addMeanFieldType(fieldi); - } - else if (foundObject(fieldName)) - { - addMeanFieldType(fieldi); - } - else if (foundObject(fieldName)) - { - addMeanFieldType(fieldi); + DebugInfo << "Read and store: " << name << endl; + obr().store(new Type(io, fieldPtr->mesh())); } } } +template +void Foam::functionObjects::fieldAverage::restoreWindowFields +( + const fieldAverageItem& item +) +{ + typedef GeometricField VolFieldType; + typedef GeometricField SurfaceFieldType; + typedef DimensionedField SurfFieldType; + + if (item.window() > 0) + { + restoreWindowFieldsType(item); + restoreWindowFieldsType(item); + restoreWindowFieldsType(item); + } +} + + template 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(fieldName)) + { + return; + } + + const word& meanFieldName = item.meanFieldName(); + const word& prime2MeanFieldName = item.prime2MeanFieldName(); Log << " Reading/initialising field " << prime2MeanFieldName << nl; @@ -125,7 +195,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 +212,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 +225,10 @@ void Foam::functionObjects::fieldAverage::addPrime2MeanFieldType template -void Foam::functionObjects::fieldAverage::addPrime2MeanField(const label fieldi) +void Foam::functionObjects::fieldAverage::addPrime2MeanField +( + fieldAverageItem& item +) { typedef GeometricField VolFieldType1; typedef GeometricField SurfaceFieldType1; @@ -165,79 +238,80 @@ void Foam::functionObjects::fieldAverage::addPrime2MeanField(const label fieldi) typedef GeometricField SurfaceFieldType2; typedef DimensionedField 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(fieldName)) - { - addPrime2MeanFieldType(fieldi); - } - else if (foundObject(fieldName)) - { - addPrime2MeanFieldType - ( - fieldi - ); - } - else if (foundObject(fieldName)) - { - addPrime2MeanFieldType - ( - fieldi - ); - } + addPrime2MeanFieldType(item); + addPrime2MeanFieldType(item); + addPrime2MeanFieldType(item); } } template -void Foam::functionObjects::fieldAverage::calculateMeanFieldType +void Foam::functionObjects::fieldAverage::storeWindowFieldType ( - const label fieldi -) const + fieldAverageItem& item +) { - const word& fieldName = faItems_[fieldi].fieldName(); + const word& fieldName = item.fieldName(); - if (foundObject(fieldName)) + if (!foundObject(fieldName)) { - const Type& baseField = lookupObject(fieldName); + return; + } - Type& meanField = const_cast + const Type& baseField = lookupObject(fieldName); + + const word windowFieldName = item.windowFieldName(this->name()); + + // Store on registry + obr().store + ( + new Type ( - lookupObject(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 +void Foam::functionObjects::fieldAverage::storeWindowFields() +{ + typedef GeometricField VolFieldType; + typedef GeometricField SurfaceFieldType; + typedef DimensionedField SurfFieldType; + + for (fieldAverageItem& item : faItems_) + { + if (item.window() > 0) { - dt = 1; - Dt = scalar(totalIter_[fieldi]); + storeWindowFieldType(item); + storeWindowFieldType(item); + storeWindowFieldType(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 SurfaceFieldType; typedef DimensionedField SurfFieldType; - forAll(faItems_, i) + for (const fieldAverageItem& item : faItems_) { - if (faItems_[i].mean()) - { - calculateMeanFieldType(i); - calculateMeanFieldType(i); - calculateMeanFieldType(i); - } - } -} - - -template -void Foam::functionObjects::fieldAverage::calculatePrime2MeanFieldType -( - const label fieldi -) const -{ - const word& fieldName = faItems_[fieldi].fieldName(); - - if (foundObject(fieldName)) - { - const Type1& baseField = lookupObject(fieldName); - const Type1& meanField = - lookupObject(faItems_[fieldi].meanFieldName()); - - Type2& prime2MeanField = - lookupObjectRef(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(obr()); + item.calculateMeanField(obr()); + item.calculateMeanField(obr()); } } @@ -318,21 +343,14 @@ void Foam::functionObjects::fieldAverage::calculatePrime2MeanFields() const typedef GeometricField SurfaceFieldType2; typedef DimensionedField SurfFieldType2; - forAll(faItems_, i) + for (const fieldAverageItem& item : faItems_) { - if (faItems_[i].prime2Mean()) - { - calculatePrime2MeanFieldType(i); - calculatePrime2MeanFieldType - ( - i - ); - - calculatePrime2MeanFieldType - ( - i - ); - } + item.calculatePrime2MeanField(obr()); + item.calculatePrime2MeanField + ( + obr() + ); + item.calculatePrime2MeanField(obr()); } } @@ -340,21 +358,21 @@ void Foam::functionObjects::fieldAverage::calculatePrime2MeanFields() const template 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(fieldName)) + if (!foundObject(fieldName)) { - const Type1& meanField = - lookupObject(faItems_[fieldi].meanFieldName()); - - Type2& prime2MeanField = - lookupObjectRef(faItems_[fieldi].prime2MeanFieldName()); - - prime2MeanField += sqr(meanField); + return; } + + const Type1& meanField = lookupObject(item.meanFieldName()); + + Type2& prime2MeanField = lookupObjectRef(item.prime2MeanFieldName()); + + prime2MeanField += sqr(meanField); } @@ -369,13 +387,16 @@ void Foam::functionObjects::fieldAverage::addMeanSqrToPrime2Mean() const typedef GeometricField SurfaceFieldType2; typedef DimensionedField SurfFieldType2; - forAll(faItems_, i) + for (const fieldAverageItem& item : faItems_) { - if (faItems_[i].prime2Mean()) + if (item.prime2Mean()) { - addMeanSqrToPrime2MeanType(i); - addMeanSqrToPrime2MeanType(i); - addMeanSqrToPrime2MeanType(i); + addMeanSqrToPrime2MeanType(item); + addMeanSqrToPrime2MeanType + ( + item + ); + addMeanSqrToPrime2MeanType(item); } } } @@ -402,22 +423,33 @@ void Foam::functionObjects::fieldAverage::writeFields() const typedef GeometricField SurfaceFieldType; typedef DimensionedField 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(fieldName); writeFieldType(fieldName); writeFieldType(fieldName); } - if (faItems_[i].prime2Mean()) + if (item.prime2Mean()) { - const word& fieldName = faItems_[i].prime2MeanFieldName(); + const word& fieldName = item.prime2MeanFieldName(); writeFieldType(fieldName); writeFieldType(fieldName); writeFieldType(fieldName); } + if (item.window() > 0) + { + FIFOStack fieldNames = item.windowFieldNames(); + forAllConstIters(fieldNames, fieldNameIter) + { + const word& fieldName = fieldNameIter(); + writeFieldType(fieldName); + writeFieldType(fieldName); + writeFieldType(fieldName); + } + } } } From f7ff26bd2d26a7d1a54a9d9398b37f23cb3924ee Mon Sep 17 00:00:00 2001 From: Andrew Heather Date: Mon, 30 Oct 2017 13:47:32 +0000 Subject: [PATCH 2/2] ENH: fieldAverage - enable suppressing of intermediate field writing for the exact method Also updated/corrected restart behaviour --- .../field/fieldAverage/fieldAverage.C | 51 ++++------- .../field/fieldAverage/fieldAverage.H | 4 - .../fieldAverageItem/fieldAverageItem.C | 39 ++++++-- .../fieldAverageItem/fieldAverageItem.H | 21 ++++- .../fieldAverageItem/fieldAverageItemI.H | 18 ++++ .../fieldAverageItem/fieldAverageItemIO.C | 88 +++++++++++-------- .../fieldAverage/fieldAverageTemplates.C | 16 +++- 7 files changed, 147 insertions(+), 90 deletions(-) diff --git a/src/functionObjects/field/fieldAverage/fieldAverage.C b/src/functionObjects/field/fieldAverage/fieldAverage.C index 769775639b..7c8aa89d08 100644 --- a/src/functionObjects/field/fieldAverage/fieldAverage.C +++ b/src/functionObjects/field/fieldAverage/fieldAverage.C @@ -42,38 +42,14 @@ namespace functionObjects // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // -void Foam::functionObjects::fieldAverage::resetFields() -{ - for (const fieldAverageItem& item : faItems_) - { - if (item.mean()) - { - if (obr().found(item.meanFieldName())) - { - obr().checkOut(*obr()[item.meanFieldName()]); - } - } - - if (item.prime2Mean()) - { - if (obr().found(item.prime2MeanFieldName())) - { - obr().checkOut(*obr()[item.prime2MeanFieldName()]); - } - } - } -} - - void Foam::functionObjects::fieldAverage::initialize() { for (fieldAverageItem& item : faItems_) { - item.restart(0, false); + // Note: not clearing data needed for restart + item.clear(obr(), false); } - resetFields(); - Log << type() << " " << name() << ":" << nl; // Add mean fields to the field lists @@ -130,7 +106,7 @@ void Foam::functionObjects::fieldAverage::restart() for (fieldAverageItem& item : faItems_) { - item.restart(0, true); + item.clear(obr(), true); } initialize(); @@ -251,12 +227,23 @@ void Foam::functionObjects::fieldAverage::readAveragingProperties() getDict(fieldName, fieldDict); item.readState(fieldDict); - scalar userTotalTime = - obr().time().timeToUserTime(item.totalTime()); + if (item.allowRestart()) + { + scalar userTotalTime = + obr().time().timeToUserTime(item.totalTime()); - Info<< " " << fieldName - << " iters = " << item.totalIter() - << " time = " << userTotalTime << nl; + Info<< " " << fieldName + << ": iters = " << item.totalIter() + << " time = " << userTotalTime << nl; + } + else + { + item.clear(obr(), true); + + Info<< " " << fieldName + << ": starting averaging at time " + << obr().time().timeOutputValue() << endl; + } } else { diff --git a/src/functionObjects/field/fieldAverage/fieldAverage.H b/src/functionObjects/field/fieldAverage/fieldAverage.H index 52a907a405..b169bfa051 100644 --- a/src/functionObjects/field/fieldAverage/fieldAverage.H +++ b/src/functionObjects/field/fieldAverage/fieldAverage.H @@ -197,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(); diff --git a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.C b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.C index d96261d763..74927ea91f 100644 --- a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.C +++ b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.C @@ -68,9 +68,9 @@ Foam::functionObjects::fieldAverageItem::fieldAverageItem() : active_(false), fieldName_("unknown"), - mean_(0), + mean_(false), meanFieldName_("unknown"), - prime2Mean_(0), + prime2Mean_(false), prime2MeanFieldName_("unknown"), base_(baseType::ITER), totalIter_(0), @@ -80,7 +80,8 @@ Foam::functionObjects::fieldAverageItem::fieldAverageItem() windowType_(windowType::NONE), windowTimes_(), - windowFieldNames_() + windowFieldNames_(), + allowRestart_(true) {} @@ -103,7 +104,8 @@ Foam::functionObjects::fieldAverageItem::fieldAverageItem windowType_(faItem.windowType_), windowTimes_(faItem.windowTimes_), - windowFieldNames_(faItem.windowFieldNames_) + windowFieldNames_(faItem.windowFieldNames_), + allowRestart_(faItem.allowRestart_) {} @@ -154,16 +156,34 @@ void Foam::functionObjects::fieldAverageItem::evolve(const objectRegistry& obr) } -void Foam::functionObjects::fieldAverageItem::restart +void Foam::functionObjects::fieldAverageItem::clear ( - const scalar time0, - const bool override + const objectRegistry& obr, + bool fullClean ) { - if (totalTime_ < 0 || override) + 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_ = time0; + totalTime_ = 0; windowTimes_.clear(); windowFieldNames_.clear(); } @@ -231,6 +251,7 @@ void Foam::functionObjects::fieldAverageItem::operator= windowType_ = rhs.windowType_; windowTimes_ = rhs.windowTimes_; windowFieldNames_ = rhs.windowFieldNames_; + allowRestart_ = rhs.allowRestart_; } diff --git a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.H b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.H index c54bc66866..24fecbae7c 100644 --- a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.H +++ b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.H @@ -36,6 +36,8 @@ Description window 200; // optional averaging window windowName w1; // optional window name (default = "") windowType approximate; // window type + + allowRestart yes; // optional, used for windowType 'exact' } \endverbatim @@ -166,6 +168,9 @@ private: //- List of window field names (windowType = EXACT) FIFOStack windowFieldNames_; + //- Switch to write all necessary files for clean restart + bool allowRestart_; + public: @@ -237,6 +242,9 @@ public: //- Return the list of window field names (windowType = EXACT) inline const FIFOStack& windowFieldNames() const; + //- Return the allow restart flag + inline bool allowRestart() const; + //- Return the current time interval inline scalar dt(const scalar deltaT) const; @@ -249,14 +257,20 @@ public: //- 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); - //- Restart - void restart(const scalar time0, const bool override); + //- 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); @@ -298,7 +312,8 @@ public: && a.totalTime_ == b.totalTime_ && a.window_ == b.window_ && a.windowName_ == b.windowName_ - && a.windowType_ == b.windowType_; + && a.windowType_ == b.windowType_ + && a.allowRestart_ == b.allowRestart_; } friend bool operator!= diff --git a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemI.H b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemI.H index b7426dd06e..371a3091e8 100644 --- a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemI.H +++ b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemI.H @@ -124,6 +124,12 @@ Foam::functionObjects::fieldAverageItem::windowFieldNames() const } +bool Foam::functionObjects::fieldAverageItem::allowRestart() const +{ + return allowRestart_; +} + + Foam::scalar Foam::functionObjects::fieldAverageItem::dt ( const scalar deltaT @@ -209,4 +215,16 @@ bool Foam::functionObjects::fieldAverageItem::inWindow(const scalar t) const } +bool Foam::functionObjects::fieldAverageItem::storeWindowFields() const +{ + return windowType_ == windowType::EXACT; +} + + +bool Foam::functionObjects::fieldAverageItem::writeWindowFields() const +{ + return (allowRestart_ && window_ > 0); +} + + // ************************************************************************* // diff --git a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemIO.C b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemIO.C index faef22d688..c1c3e1d19a 100644 --- a/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemIO.C +++ b/src/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItemIO.C @@ -33,9 +33,9 @@ Foam::functionObjects::fieldAverageItem::fieldAverageItem(Istream& is) : active_(false), fieldName_("unknown"), - mean_(0), + mean_(false), meanFieldName_("unknown"), - prime2Mean_(0), + prime2Mean_(false), prime2MeanFieldName_("unknown"), base_(baseType::ITER), totalIter_(0), @@ -45,36 +45,10 @@ Foam::functionObjects::fieldAverageItem::fieldAverageItem(Istream& is) windowType_(windowType::NONE), windowTimes_(), - windowFieldNames_() + 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("window", -1.0); - - if (window_ > 0) - { - windowName_ = entry.lookupOrDefault("windowName", ""); - windowType_ = windowTypeNames_.lookup("windowType", entry); - - if (windowType_ == windowType::NONE) - { - window_ = -1; - } - } - - meanFieldName_ = fieldName_ + EXT_MEAN; - prime2MeanFieldName_ = fieldName_ + EXT_PRIME2MEAN; - if ((window_ > 0) && (!windowName_.empty())) - { - meanFieldName_ = meanFieldName_ + "_" + windowName_; - prime2MeanFieldName_ = prime2MeanFieldName_ + "_" + windowName_; - } + is >> *this; } @@ -99,15 +73,52 @@ Foam::Istream& Foam::functionObjects::operator>> if (faItem.window_ > 0) { - faItem.windowName_ = entry.lookupOrDefault("windowName", ""); faItem.windowType_ = faItem.windowTypeNames_.lookup("windowType", entry); - if (faItem.windowType_ == fieldAverageItem::windowType::NONE) + 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("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_ = @@ -121,6 +132,7 @@ Foam::Istream& Foam::functionObjects::operator>> faItem.prime2MeanFieldName_ = faItem.prime2MeanFieldName_ + "_" + faItem.windowName_; } + return is; } @@ -135,11 +147,9 @@ Foam::Ostream& Foam::functionObjects::operator<< os.beginBlock(faItem.fieldName_); - 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.writeEntry("mean", faItem.mean_); + os.writeEntry("prime2Mean", faItem.prime2Mean_); + os.writeEntry("base", faItem.baseTypeNames_[faItem.base_]); if (faItem.window_ > 0) { @@ -155,6 +165,8 @@ Foam::Ostream& Foam::functionObjects::operator<< "windowType", faItem.windowTypeNames_[faItem.windowType_] ); + + os.writeEntry("allowRestart", faItem.allowRestart_); } os.endBlock() << flush; diff --git a/src/functionObjects/field/fieldAverage/fieldAverageTemplates.C b/src/functionObjects/field/fieldAverage/fieldAverageTemplates.C index 9946d67a21..5f34c9de2a 100644 --- a/src/functionObjects/field/fieldAverage/fieldAverageTemplates.C +++ b/src/functionObjects/field/fieldAverage/fieldAverageTemplates.C @@ -141,11 +141,18 @@ void Foam::functionObjects::fieldAverage::restoreWindowFieldsType IOobject::NO_WRITE ); - if (io.typeHeaderOk(false)) + if (io.typeHeaderOk(true)) { DebugInfo << "Read and store: " << name << endl; obr().store(new Type(io, fieldPtr->mesh())); } + else + { + WarningInFunction + << "Unable to read window " << Type::typeName << " " << name + << ". Averaging restart behaviour may be compromised" + << endl; + } } } @@ -262,7 +269,6 @@ void Foam::functionObjects::fieldAverage::storeWindowFieldType ) { const word& fieldName = item.fieldName(); - if (!foundObject(fieldName)) { return; @@ -306,7 +312,7 @@ void Foam::functionObjects::fieldAverage::storeWindowFields() for (fieldAverageItem& item : faItems_) { - if (item.window() > 0) + if (item.storeWindowFields()) { storeWindowFieldType(item); storeWindowFieldType(item); @@ -432,6 +438,7 @@ void Foam::functionObjects::fieldAverage::writeFields() const writeFieldType(fieldName); writeFieldType(fieldName); } + if (item.prime2Mean()) { const word& fieldName = item.prime2MeanFieldName(); @@ -439,7 +446,8 @@ void Foam::functionObjects::fieldAverage::writeFields() const writeFieldType(fieldName); writeFieldType(fieldName); } - if (item.window() > 0) + + if (item.writeWindowFields()) { FIFOStack fieldNames = item.windowFieldNames(); forAllConstIters(fieldNames, fieldNameIter)