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
This commit is contained in:
Andrew Heather
2022-05-23 20:25:05 +01:00
committed by Sergio Ferraris
parent 34ef9ae342
commit 8d90b16518
8 changed files with 326 additions and 137 deletions

View File

@ -20,7 +20,6 @@ fieldValues/fieldValue/fieldValue.C
fieldValues/fieldValue/fieldValueNew.C fieldValues/fieldValue/fieldValueNew.C
fieldValues/volFieldValue/volFieldValue.C fieldValues/volFieldValue/volFieldValue.C
fieldValues/surfaceFieldValue/surfaceFieldValue.C fieldValues/surfaceFieldValue/surfaceFieldValue.C
fieldValues/multiFieldValue/multiFieldValue.C
heatTransferCoeff/heatTransferCoeff.C heatTransferCoeff/heatTransferCoeff.C
heatTransferCoeff/heatTransferCoeffModels/heatTransferCoeffModel/heatTransferCoeffModel.C heatTransferCoeff/heatTransferCoeffModels/heatTransferCoeffModel/heatTransferCoeffModel.C
@ -31,6 +30,8 @@ heatTransferCoeff/heatTransferCoeffModels/ReynoldsAnalogy/ReynoldsAnalogy.C
limitFields/limitFields.C limitFields/limitFields.C
multiFieldValue/multiFieldValue.C
nearWallFields/nearWallFields.C nearWallFields/nearWallFields.C
nearWallFields/findCellParticle.C nearWallFields/findCellParticle.C
nearWallFields/findCellParticleCloud.C nearWallFields/findCellParticleCloud.C

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2012-2016 OpenFOAM Foundation Copyright (C) 2012-2016 OpenFOAM Foundation
Copyright (C) 2015-2021 OpenCFD Ltd. Copyright (C) 2015-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -63,48 +63,36 @@ Foam::functionObjects::fieldValues::multiFieldValue::operationTypeNames_
void Foam::functionObjects::fieldValues::multiFieldValue::writeFileHeader void Foam::functionObjects::fieldValues::multiFieldValue::writeFileHeader
( (
const wordList& foNames,
const List<wordList>& entries,
const List<wordList>& types,
Ostream& os Ostream& os
) const ) const
{ {
const wordList& fields0 = functions_[0].fields(); const word groupPrefix("Group");
DynamicList<word> commonFields(fields0.size()); forAll(entries, i)
for (const word& fieldName : fields0)
{ {
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)) writeCommented
{ (
common = false; os,
break; " - " + foNames[functioni] + ":" + entries[i][functioni]
} );
os << nl;
} }
if (common)
{
commonFields.append(fieldName);
}
}
forAll(functions_, functioni)
{
writeHeaderValue
(
os,
"Source" + Foam::name(functioni),
functions_[functioni].name()
);
} }
writeHeaderValue(os, "Operation", operationTypeNames_[operation_]); writeHeaderValue(os, "Operation", operationTypeNames_[operation_]);
writeCommented(os, "Time"); writeCommented(os, "Time");
for (const word& fieldName : commonFields) forAll(entries, entryi)
{ {
os << tab << fieldName; writeTabbed(os, groupPrefix + Foam::name(entryi));
} }
os << endl; os << endl;
@ -125,10 +113,7 @@ Foam::functionObjects::fieldValues::multiFieldValue::multiFieldValue
operation_(opSubtract), operation_(opSubtract),
functions_() functions_()
{ {
if (read(dict)) read(dict);
{
writeFileHeader(file());
}
} }
@ -139,52 +124,73 @@ bool Foam::functionObjects::fieldValues::multiFieldValue::read
const dictionary& dict const dictionary& dict
) )
{ {
if (stateFunctionObject::read(dict) && writeFile::read(dict)) if (!stateFunctionObject::read(dict) || !writeFile::read(dict))
{ {
const dictionary& functionsDict = dict.subDict("functions"); return false;
functions_.resize(functionsDict.size());
if (functions_.empty())
{
WarningInFunction
<< "No functions specified"
<< endl;
return false;
}
label functioni = 0;
for (const entry& dEntry : functionsDict)
{
if (!dEntry.isDict())
{
FatalIOErrorInFunction(dict)
<< "Functions must be specified in dictionary format"
<< exit(FatalIOError);
}
const dictionary& localDict = dEntry.dict();
functions_.set
(
functioni,
fieldValue::New
(
IOobject::scopedName(name(), localDict.dictName()),
time(),
localDict,
false
)
);
++functioni;
}
operation_ = operationTypeNames_.get("operation", dict);
return true;
} }
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)
{
if (!dEntry.isDict())
{
FatalIOErrorInFunction(dict)
<< "Functions must be specified in dictionary format"
<< exit(FatalIOError);
}
const dictionary& localDict = dEntry.dict();
functions_.set
(
functioni,
functionObject::New
(
IOobject::scopedName(name(), localDict.dictName()),
time(),
localDict
).ptr()
);
// Deactivate logging for child function objects
//functions_[functioni].log = false;
// Get result field names; not specified implies all
resultFields_[functioni] =
localDict.getOrDefault<wordList>("resultFields", wordList());
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 true;
} }
@ -201,19 +207,25 @@ bool Foam::functionObjects::fieldValues::multiFieldValue::write()
wordList entries0; wordList entries0;
label nEntries = -1; label nEntries = -1;
wordList names(nFunction); wordList foNames(nFunction);
List<wordList> entries; List<wordList> entries;
List<wordList> types; List<wordList> types;
forAll(functions_, functioni) forAll(functions_, functioni)
{ {
auto& f = 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(); f.write();
const wordList e(objectResultEntries(f.name())); wordList e = resultFields_[functioni];
if (e.empty())
{
e = objectResultEntries(f.name());
}
if (functioni == 0) if (functioni == 0)
{ {
@ -237,54 +249,72 @@ bool Foam::functionObjects::fieldValues::multiFieldValue::write()
<< "Inconsistent number of result entries" << nl << "Inconsistent number of result entries" << nl
<< " " << f0Name << " entries:" << entries0 << nl << " " << f0Name << " entries:" << entries0 << nl
<< " " << f.name() << " entries:" << e << " " << f.name() << " entries:" << e
<< abort(FatalError); << exit(FatalError);
} }
forAll(e, entryi) forAll(e, entryi)
{ {
entries[entryi][functioni] = e[entryi]; entries[entryi][functioni] = e[entryi];
types[entryi][functioni] = objectResultType(f.name(), 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()); writeCurrentTime(file());
forAll(entries, entryi) forAll(entries, i)
{ {
const wordList& entriesi = entries[entryi]; const wordList& entryi = entries[i];
const word& t0 = types[entryi][0]; const word& expectedType = types[i][0];
const wordList& typesi = types[entryi]; const wordList& foTypes = types[i];
forAll(typesi, functioni)
{
const word& t = typesi[functioni];
if (t != t0) forAll(foTypes, functioni)
{
const word& foType = foTypes[functioni];
if (foType != expectedType)
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Inconsistent function result types" << nl << "Inconsistent function result types" << nl
<< " " << functions_[0].name() << " " << functions_[0].name()
<< " result type:" << t0 << nl << " result type:" << expectedType << nl
<< " " << functions_[functioni].name() << " " << functions_[functioni].name()
<< " result type:" << typesi[functioni] << " result type:" << foType
<< abort(FatalError); << exit(FatalError);
} }
} }
const bool ok const bool ok
( (
applyOperation<scalar>(t0, names, entriesi) applyOperation<scalar>(expectedType, foNames, entryi)
|| applyOperation<vector>(t0, names, entriesi) || applyOperation<vector>(expectedType, foNames, entryi)
|| applyOperation<sphericalTensor>(t0, names, entriesi) || applyOperation<sphericalTensor>(expectedType, foNames, entryi)
|| applyOperation<symmTensor>(t0, names, entriesi) || applyOperation<symmTensor>(expectedType, foNames, entryi)
|| applyOperation<tensor>(t0, names, entriesi) || applyOperation<tensor>(expectedType, foNames, entryi)
); );
if (!ok) if (!ok)
{ {
Log << "Operation not applied between functions:" << nl Log << "Operation not applied between functions:" << nl
<< flatOutput(names, FlatOutput::BareComma{}) << nl << flatOutput(foNames, FlatOutput::BareComma{}) << nl
<< "with result names:" << nl << "with result names:" << nl
<< flatOutput(entriesi, FlatOutput::BareComma{}) << flatOutput(entryi, FlatOutput::BareComma{})
<< endl; << endl;
} }
} }

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd. Copyright (C) 2021-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -30,10 +30,9 @@ Group
grpFieldFunctionObjects grpFieldFunctionObjects
Description Description
Computes a selected operation between multiple \c fieldValue function Computes a selected operation between multiple function objects.
objects.
The operation is applied to all results of each \c fieldValue object. The operation is applied to all results of each object.
Note Note
Each object must generate the same number and type of results. Each object must generate the same number and type of results.
@ -43,11 +42,9 @@ Usage
\verbatim \verbatim
multiFieldValue1 multiFieldValue1
{ {
// Mandatory entries (unmodifiable) // Mandatory entries
type multiFieldValue; type multiFieldValue;
libs (fieldFunctionObjects); libs (fieldFunctionObjects);
// Mandatory entries (runtime modifiable)
operation average; operation average;
// List of fieldValue function objects as dictionaries // List of fieldValue function objects as dictionaries
@ -56,10 +53,14 @@ Usage
region1 region1
{ {
... ...
// Optional
resultFields (field1 field2);
} }
region2 region2
{ {
... ...
// Optional
resultFields (field1 field2);
} }
... ...
@ -67,41 +68,41 @@ Usage
regionN regionN
{ {
... ...
// Optional
resultFields (field1 field2);
} }
} }
// Optional (inherited) entries // Inherited entries
... ...
} }
\endverbatim \endverbatim
where the entries mean: where the entries mean:
\table \table
Property | Description | Type | Req'd | Dflt Property | Description | Type | Reqd | Deflt
type | Type name: multiFieldValue | word | yes | - type | Type name: multiFieldValue | word | yes | -
libs | Library name: fieldFunctionObjects | word | yes | - libs | Library name: fieldFunctionObjects | word | yes | -
operation | Operation type to apply to values | word | yes | - operation | Operation type to apply to values | word | yes | -
functions | List of fieldValue function objects | dict | yes | - functions | List of function objects | dict | yes | -
\endtable \endtable
Options for the \c operation entry: Options for the \c operation entry:
\plaintable \plaintable
add | add sum | Sum of values
subtract | subtract add | Add values (same as sum)
min | minimum subtract | Subtract values from first entry
max | maximum min | Minimum value
average | average max | Maximum value
average | Average value
\endplaintable \endplaintable
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.
The inherited entries are elaborated in: The inherited entries are elaborated in:
- \link fieldValue.H \endlink - \link stateFunctionObject.H \endlink
- \link writeFile.H \endlink
Usage by the \c postProcess utility is not available.
See also
- Foam::functionObject
- Foam::functionObjects::fieldValue
- ExtendedCodeGuide::functionObjects::field::multiFieldValue
SourceFiles SourceFiles
multiFieldValue.C multiFieldValue.C
@ -114,7 +115,6 @@ SourceFiles
#include "stateFunctionObject.H" #include "stateFunctionObject.H"
#include "writeFile.H" #include "writeFile.H"
#include "fieldValue.H"
#include "Enum.H" #include "Enum.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -161,8 +161,11 @@ private:
//- Operation to apply to values //- Operation to apply to values
operationType operation_; operationType operation_;
//- List of fieldValue function objects //- List of function objects
PtrList<fieldValue> functions_; PtrList<functionObject> functions_;
//- List of result fields per function object
List<wordList> resultFields_;
// Private Member Functions // Private Member Functions
@ -183,7 +186,13 @@ protected:
// Protected Member Functions // Protected Member Functions
//- Output file header information //- 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: public:

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2012-2016 OpenFOAM Foundation Copyright (C) 2012-2016 OpenFOAM Foundation
Copyright (C) 2015-2021 OpenCFD Ltd. Copyright (C) 2015-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -34,7 +34,7 @@ template<class Type>
bool Foam::functionObjects::fieldValues::multiFieldValue::applyOperation bool Foam::functionObjects::fieldValues::multiFieldValue::applyOperation
( (
const word& resultType, const word& resultType,
const wordList& names, const wordList& foNames,
const wordList& entryNames const wordList& entryNames
) )
{ {
@ -45,10 +45,10 @@ bool Foam::functionObjects::fieldValues::multiFieldValue::applyOperation
Type result = Zero; Type result = Zero;
Field<Type> values(names.size()); Field<Type> values(foNames.size());
forAll(values, i) 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_]; const word& opName = operationTypeNames_[operation_];

View File

@ -5,4 +5,6 @@ cd "${0%/*}" || exit # Run from this directory
cleanCase0 cleanCase0
rm -rf procs.old
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -13,4 +13,21 @@ runParallel topoSet
runParallel $(getApplication) 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
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -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;
}
// ************************************************************************* //

View File

@ -16,7 +16,7 @@ FoamFile
application pisoFoam; application pisoFoam;
startFrom startTime; startFrom latestTime;
startTime 0; startTime 0;
@ -68,6 +68,7 @@ functions
#include "FOlog" #include "FOlog"
#include "FOmag" #include "FOmag"
#include "FOmagSqr" #include "FOmagSqr"
#include "FOmultiFieldValue"
#include "FOmultiply" #include "FOmultiply"
#include "FOmomentum" #include "FOmomentum"
#include "FOnearWallFields" #include "FOnearWallFields"