From 8d90b165182c77f7246cb144aa640ca014a5f373 Mon Sep 17 00:00:00 2001 From: Andrew Heather <> Date: Mon, 23 May 2022 20:25:05 +0100 Subject: [PATCH] ENH: multiFieldValue - extended to operate on general function objects - Previously, the multiFieldValue function object was limited to operate on lists of fieldValue function objects. - Any function objects that generate results can now be used, e.g. pressureAverage { type multiFieldValue; libs (fieldFunctionObjects); operation average; functions { inlet { type surfaceFieldValue; operation areaAverage; regionType patch; name inlet; fields (p); writeFields no; writeToFile no; log no; resultFields (areaAverage(inlet,p)); } outlet { type surfaceFieldValue; operation areaAverage; regionType patch; name outlet; fields (p); writeFields no; writeToFile no; log no; } average { type valueAverage; functionObject testSample1; fields (average(p)); writeToFile no; log no; } } } TUT: cavity: add an example for the multiFieldValue function object --- src/functionObjects/field/Make/files | 3 +- .../multiFieldValue/multiFieldValue.C | 208 ++++++++++-------- .../multiFieldValue/multiFieldValue.H | 73 +++--- .../multiFieldValueTemplates.C | 8 +- .../pisoFoam/RAS/cavity/Allclean | 2 + .../pisoFoam/RAS/cavity/Allrun-parallel | 17 ++ .../RAS/cavity/system/FOmultiFieldValue | 129 +++++++++++ .../pisoFoam/RAS/cavity/system/controlDict | 3 +- 8 files changed, 316 insertions(+), 127 deletions(-) rename src/functionObjects/field/{fieldValues => }/multiFieldValue/multiFieldValue.C (56%) rename src/functionObjects/field/{fieldValues => }/multiFieldValue/multiFieldValue.H (77%) rename src/functionObjects/field/{fieldValues => }/multiFieldValue/multiFieldValueTemplates.C (94%) create mode 100644 tutorials/incompressible/pisoFoam/RAS/cavity/system/FOmultiFieldValue diff --git a/src/functionObjects/field/Make/files b/src/functionObjects/field/Make/files index 290a84dfe3b..c285367b665 100644 --- a/src/functionObjects/field/Make/files +++ b/src/functionObjects/field/Make/files @@ -20,7 +20,6 @@ fieldValues/fieldValue/fieldValue.C fieldValues/fieldValue/fieldValueNew.C fieldValues/volFieldValue/volFieldValue.C fieldValues/surfaceFieldValue/surfaceFieldValue.C -fieldValues/multiFieldValue/multiFieldValue.C heatTransferCoeff/heatTransferCoeff.C heatTransferCoeff/heatTransferCoeffModels/heatTransferCoeffModel/heatTransferCoeffModel.C @@ -31,6 +30,8 @@ heatTransferCoeff/heatTransferCoeffModels/ReynoldsAnalogy/ReynoldsAnalogy.C limitFields/limitFields.C +multiFieldValue/multiFieldValue.C + nearWallFields/nearWallFields.C nearWallFields/findCellParticle.C nearWallFields/findCellParticleCloud.C diff --git a/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.C b/src/functionObjects/field/multiFieldValue/multiFieldValue.C similarity index 56% rename from src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.C rename to src/functionObjects/field/multiFieldValue/multiFieldValue.C index 251a9a47da7..45cf5bb8d15 100644 --- a/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.C +++ b/src/functionObjects/field/multiFieldValue/multiFieldValue.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2012-2016 OpenFOAM Foundation - Copyright (C) 2015-2021 OpenCFD Ltd. + Copyright (C) 2015-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -63,48 +63,36 @@ Foam::functionObjects::fieldValues::multiFieldValue::operationTypeNames_ void Foam::functionObjects::fieldValues::multiFieldValue::writeFileHeader ( + const wordList& foNames, + const List<wordList>& entries, + const List<wordList>& types, Ostream& os ) const { - const wordList& fields0 = functions_[0].fields(); + const word groupPrefix("Group"); - DynamicList<word> commonFields(fields0.size()); - - for (const word& fieldName : fields0) + forAll(entries, i) { - bool common = true; + writeCommented(os, groupPrefix + Foam::name(i)); + os << nl; - for (label functioni=1; functioni < functions_.size(); ++functioni) + forAll(entries[i], functioni) { - if (!functions_[functioni].fields().found(fieldName)) - { - common = false; - break; - } - } - - if (common) - { - commonFields.append(fieldName); + writeCommented + ( + os, + " - " + foNames[functioni] + ":" + entries[i][functioni] + ); + os << nl; } } - forAll(functions_, functioni) - { - writeHeaderValue - ( - os, - "Source" + Foam::name(functioni), - functions_[functioni].name() - ); - } - writeHeaderValue(os, "Operation", operationTypeNames_[operation_]); writeCommented(os, "Time"); - for (const word& fieldName : commonFields) + forAll(entries, entryi) { - os << tab << fieldName; + writeTabbed(os, groupPrefix + Foam::name(entryi)); } os << endl; @@ -125,10 +113,7 @@ Foam::functionObjects::fieldValues::multiFieldValue::multiFieldValue operation_(opSubtract), functions_() { - if (read(dict)) - { - writeFileHeader(file()); - } + read(dict); } @@ -139,52 +124,73 @@ bool Foam::functionObjects::fieldValues::multiFieldValue::read const dictionary& dict ) { - if (stateFunctionObject::read(dict) && writeFile::read(dict)) + if (!stateFunctionObject::read(dict) || !writeFile::read(dict)) { - const dictionary& functionsDict = dict.subDict("functions"); - functions_.resize(functionsDict.size()); + return false; + } - if (functions_.empty()) - { - WarningInFunction - << "No functions specified" - << endl; - return false; - } + operation_ = operationTypeNames_.get("operation", dict); + + const dictionary& functionsDict = dict.subDict("functions"); + functions_.resize(functionsDict.size()); + + if (functions_.empty()) + { + WarningInFunction + << "No functions specified" + << endl; + return false; + } + + resultFields_.resize(functions_.size()); - label functioni = 0; - for (const entry& dEntry : functionsDict) + label functioni = 0; + for (const entry& dEntry : functionsDict) + { + if (!dEntry.isDict()) { - if (!dEntry.isDict()) - { - FatalIOErrorInFunction(dict) - << "Functions must be specified in dictionary format" - << exit(FatalIOError); - } + FatalIOErrorInFunction(dict) + << "Functions must be specified in dictionary format" + << exit(FatalIOError); + } - const dictionary& localDict = dEntry.dict(); + const dictionary& localDict = dEntry.dict(); - functions_.set + functions_.set + ( + functioni, + functionObject::New ( - functioni, - fieldValue::New - ( - IOobject::scopedName(name(), localDict.dictName()), - time(), - localDict, - false - ) - ); + IOobject::scopedName(name(), localDict.dictName()), + time(), + localDict + ).ptr() + ); - ++functioni; - } + // Deactivate logging for child function objects + //functions_[functioni].log = false; - operation_ = operationTypeNames_.get("operation", dict); + // Get result field names; not specified implies all + resultFields_[functioni] = + localDict.getOrDefault<wordList>("resultFields", wordList()); - return true; + Info<< type() << ' ' << name() << ':' << nl; + if (resultFields_[functioni].size()) + { + Info<< " " << functions_[functioni].name() + << " " << resultFields_[functioni]; + } + else + { + Info<< " " << functions_[functioni].name() + << " - using all available entries"; + } + Info<< nl << endl; + + ++functioni; } - return false; + return true; } @@ -201,19 +207,25 @@ bool Foam::functionObjects::fieldValues::multiFieldValue::write() wordList entries0; label nEntries = -1; - wordList names(nFunction); + wordList foNames(nFunction); List<wordList> entries; List<wordList> types; forAll(functions_, functioni) { auto& f = functions_[functioni]; - names[functioni] = f.name(); + foNames[functioni] = f.name(); - // Note: results are not available until the call to write() + // Note: replicating functionObjectList execute() and write() + // - results may be written on either + f.execute(); f.write(); - const wordList e(objectResultEntries(f.name())); + wordList e = resultFields_[functioni]; + if (e.empty()) + { + e = objectResultEntries(f.name()); + } if (functioni == 0) { @@ -237,54 +249,72 @@ bool Foam::functionObjects::fieldValues::multiFieldValue::write() << "Inconsistent number of result entries" << nl << " " << f0Name << " entries:" << entries0 << nl << " " << f.name() << " entries:" << e - << abort(FatalError); + << exit(FatalError); } forAll(e, entryi) { entries[entryi][functioni] = e[entryi]; types[entryi][functioni] = objectResultType(f.name(), e[entryi]); + + if (types[entryi][functioni] == word::null) + { + FatalErrorInFunction + << "Unable to find function object result" << nl + << " function object : " << f.name() << nl + << " result name : " << e[entryi] << nl + << " available results : " + << objectResultEntries(f.name()) + << exit(FatalError); + } } } + if (!writtenHeader_) + { + writeFileHeader(foNames, entries, types, file()); + writtenHeader_ = true; + } + writeCurrentTime(file()); - forAll(entries, entryi) + forAll(entries, i) { - const wordList& entriesi = entries[entryi]; - const word& t0 = types[entryi][0]; - const wordList& typesi = types[entryi]; - forAll(typesi, functioni) + const wordList& entryi = entries[i]; + const word& expectedType = types[i][0]; + const wordList& foTypes = types[i]; + + forAll(foTypes, functioni) { - const word& t = typesi[functioni]; + const word& foType = foTypes[functioni]; - if (t != t0) + if (foType != expectedType) { FatalErrorInFunction << "Inconsistent function result types" << nl << " " << functions_[0].name() - << " result type:" << t0 << nl + << " result type:" << expectedType << nl << " " << functions_[functioni].name() - << " result type:" << typesi[functioni] - << abort(FatalError); + << " result type:" << foType + << exit(FatalError); } } const bool ok ( - applyOperation<scalar>(t0, names, entriesi) - || applyOperation<vector>(t0, names, entriesi) - || applyOperation<sphericalTensor>(t0, names, entriesi) - || applyOperation<symmTensor>(t0, names, entriesi) - || applyOperation<tensor>(t0, names, entriesi) + applyOperation<scalar>(expectedType, foNames, entryi) + || applyOperation<vector>(expectedType, foNames, entryi) + || applyOperation<sphericalTensor>(expectedType, foNames, entryi) + || applyOperation<symmTensor>(expectedType, foNames, entryi) + || applyOperation<tensor>(expectedType, foNames, entryi) ); if (!ok) { Log << "Operation not applied between functions:" << nl - << flatOutput(names, FlatOutput::BareComma{}) << nl + << flatOutput(foNames, FlatOutput::BareComma{}) << nl << "with result names:" << nl - << flatOutput(entriesi, FlatOutput::BareComma{}) + << flatOutput(entryi, FlatOutput::BareComma{}) << endl; } } diff --git a/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.H b/src/functionObjects/field/multiFieldValue/multiFieldValue.H similarity index 77% rename from src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.H rename to src/functionObjects/field/multiFieldValue/multiFieldValue.H index d6b73499eb2..02a939ff125 100644 --- a/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.H +++ b/src/functionObjects/field/multiFieldValue/multiFieldValue.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2021 OpenCFD Ltd. + Copyright (C) 2021-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -30,10 +30,9 @@ Group grpFieldFunctionObjects Description - Computes a selected operation between multiple \c fieldValue function - objects. + Computes a selected operation between multiple function objects. - The operation is applied to all results of each \c fieldValue object. + The operation is applied to all results of each object. Note Each object must generate the same number and type of results. @@ -43,11 +42,9 @@ Usage \verbatim multiFieldValue1 { - // Mandatory entries (unmodifiable) - type multiFieldValue; - libs (fieldFunctionObjects); - - // Mandatory entries (runtime modifiable) + // Mandatory entries + type multiFieldValue; + libs (fieldFunctionObjects); operation average; // List of fieldValue function objects as dictionaries @@ -56,10 +53,14 @@ Usage region1 { ... + // Optional + resultFields (field1 field2); } region2 { ... + // Optional + resultFields (field1 field2); } ... @@ -67,41 +68,41 @@ Usage regionN { ... + // Optional + resultFields (field1 field2); } } - // Optional (inherited) entries + // Inherited entries ... } \endverbatim where the entries mean: \table - Property | Description | Type | Req'd | Dflt - type | Type name: multiFieldValue | word | yes | - - libs | Library name: fieldFunctionObjects | word | yes | - - operation | Operation type to apply to values | word | yes | - - functions | List of fieldValue function objects | dict | yes | - + Property | Description | Type | Reqd | Deflt + type | Type name: multiFieldValue | word | yes | - + libs | Library name: fieldFunctionObjects | word | yes | - + operation | Operation type to apply to values | word | yes | - + functions | List of function objects | dict | yes | - \endtable Options for the \c operation entry: \plaintable - add | add - subtract | subtract - min | minimum - max | maximum - average | average + sum | Sum of values + add | Add values (same as sum) + subtract | Subtract values from first entry + min | Minimum value + max | Maximum value + average | Average value \endplaintable - The inherited entries are elaborated in: - - \link fieldValue.H \endlink - - Usage by the \c postProcess utility is not available. + The \c resultFields entry can be used to set the name of the function object + result fields to process. If omitted, all available values are employed. -See also - - Foam::functionObject - - Foam::functionObjects::fieldValue - - ExtendedCodeGuide::functionObjects::field::multiFieldValue + The inherited entries are elaborated in: + - \link stateFunctionObject.H \endlink + - \link writeFile.H \endlink SourceFiles multiFieldValue.C @@ -114,7 +115,6 @@ SourceFiles #include "stateFunctionObject.H" #include "writeFile.H" -#include "fieldValue.H" #include "Enum.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -161,8 +161,11 @@ private: //- Operation to apply to values operationType operation_; - //- List of fieldValue function objects - PtrList<fieldValue> functions_; + //- List of function objects + PtrList<functionObject> functions_; + + //- List of result fields per function object + List<wordList> resultFields_; // Private Member Functions @@ -183,7 +186,13 @@ protected: // Protected Member Functions //- Output file header information - virtual void writeFileHeader(Ostream& os) const; + virtual void writeFileHeader + ( + const wordList& foNames, + const List<wordList>& entries, + const List<wordList>& types, + Ostream& os + ) const; public: diff --git a/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValueTemplates.C b/src/functionObjects/field/multiFieldValue/multiFieldValueTemplates.C similarity index 94% rename from src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValueTemplates.C rename to src/functionObjects/field/multiFieldValue/multiFieldValueTemplates.C index 714cb1c48b6..5f6c99c084e 100644 --- a/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValueTemplates.C +++ b/src/functionObjects/field/multiFieldValue/multiFieldValueTemplates.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2012-2016 OpenFOAM Foundation - Copyright (C) 2015-2021 OpenCFD Ltd. + Copyright (C) 2015-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -34,7 +34,7 @@ template<class Type> bool Foam::functionObjects::fieldValues::multiFieldValue::applyOperation ( const word& resultType, - const wordList& names, + const wordList& foNames, const wordList& entryNames ) { @@ -45,10 +45,10 @@ bool Foam::functionObjects::fieldValues::multiFieldValue::applyOperation Type result = Zero; - Field<Type> values(names.size()); + Field<Type> values(foNames.size()); forAll(values, i) { - values[i] = this->getObjectResult<Type>(names[i], entryNames[i]); + values[i] = this->getObjectResult<Type>(foNames[i], entryNames[i]); } const word& opName = operationTypeNames_[operation_]; diff --git a/tutorials/incompressible/pisoFoam/RAS/cavity/Allclean b/tutorials/incompressible/pisoFoam/RAS/cavity/Allclean index fb1f3847301..a89ac03ac12 100755 --- a/tutorials/incompressible/pisoFoam/RAS/cavity/Allclean +++ b/tutorials/incompressible/pisoFoam/RAS/cavity/Allclean @@ -5,4 +5,6 @@ cd "${0%/*}" || exit # Run from this directory cleanCase0 +rm -rf procs.old + #------------------------------------------------------------------------------ diff --git a/tutorials/incompressible/pisoFoam/RAS/cavity/Allrun-parallel b/tutorials/incompressible/pisoFoam/RAS/cavity/Allrun-parallel index f128afc39ba..cbbadfe17df 100755 --- a/tutorials/incompressible/pisoFoam/RAS/cavity/Allrun-parallel +++ b/tutorials/incompressible/pisoFoam/RAS/cavity/Allrun-parallel @@ -13,4 +13,21 @@ runParallel topoSet runParallel $(getApplication) +runApplication reconstructPar + + +latestTime=$(foamListTimes -latestTime) + +mv -f "$latestTime" "$latestTime".bak + +mkdir procs.old + +mv -f processor* procs.old + +runParallel -s "decompose" redistributePar -decompose -time 9.5 + +runParallel -s 2 $(getApplication) + +runParallel -s "reconstruct" redistributePar -reconstruct -latestTime + #------------------------------------------------------------------------------ diff --git a/tutorials/incompressible/pisoFoam/RAS/cavity/system/FOmultiFieldValue b/tutorials/incompressible/pisoFoam/RAS/cavity/system/FOmultiFieldValue new file mode 100644 index 00000000000..43d98042bfc --- /dev/null +++ b/tutorials/incompressible/pisoFoam/RAS/cavity/system/FOmultiFieldValue @@ -0,0 +1,129 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v2112 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ + +sampleEpsilon1 +{ + type sets; + libs (sampling); + interpolationScheme cellPointFace; + setFormat raw; + fields ( epsilon ); + + sets + ( + cloud + { + type cloud; + axis xyz; + points + ( + (0.0025 0.05 0.005) + ); + } + ); +} + + +multiFieldValue_add +{ + // Mandatory entries + type multiFieldValue; + libs (fieldFunctionObjects); + + operation add; + + functions + { + movingWallEpsilon + { + type surfaceFieldValue; + operation areaAverage; + regionType patch; + name movingWall; + fields (epsilon); + + writeFields no; + writeToFile no; + log no; + resultFields (areaAverage(movingWall,epsilon)); + } + fixedWallsEpsilon + { + type surfaceFieldValue; + operation areaAverage; + regionType patch; + name fixedWalls; + fields (epsilon); + + writeFields no; + writeToFile no; + log yes; + } + averageEpsilon + { + type valueAverage; + functionObject sampleEpsilon1; + fields (average(epsilon)); + writeToFile no; + log no; + } + } + + // Inherited entries + writePrecision 10; + writeToFile true; + useUserTime true; + + region region0; + enabled true; + log true; + timeStart 0; + timeEnd 1000; + executeControl timeStep; + executeInterval 1; + writeControl writeTime; + writeInterval -1; +} + + +multiFieldValue_sum +{ + ${multiFieldValue_add} + operation sum; +} + + +multiFieldValue_subtract +{ + ${multiFieldValue_add} + operation subtract; +} + + +multiFieldValue_min +{ + ${multiFieldValue_add} + operation min; +} + + +multiFieldValue_max +{ + ${multiFieldValue_add} + operation max; +} + + +multiFieldValue_average +{ + ${multiFieldValue_add} + operation average; +} + + +// ************************************************************************* // diff --git a/tutorials/incompressible/pisoFoam/RAS/cavity/system/controlDict b/tutorials/incompressible/pisoFoam/RAS/cavity/system/controlDict index 44799398a52..03b72d8ef56 100644 --- a/tutorials/incompressible/pisoFoam/RAS/cavity/system/controlDict +++ b/tutorials/incompressible/pisoFoam/RAS/cavity/system/controlDict @@ -16,7 +16,7 @@ FoamFile application pisoFoam; -startFrom startTime; +startFrom latestTime; startTime 0; @@ -68,6 +68,7 @@ functions #include "FOlog" #include "FOmag" #include "FOmagSqr" + #include "FOmultiFieldValue" #include "FOmultiply" #include "FOmomentum" #include "FOnearWallFields" -- GitLab