functionObjects: surfaceFieldValue, volFieldValue: Various improvements

A number of changes have been made to the surfaceFieldValue and
volFieldValue function objects to improve their usability and
performance, and to extend them so that similar duplicate functionality
elsewhere in OpenFOAM can be removed.

Weighted operations have been removed. Weighting for averages and sums
is now triggered simply by the existence of the "weightField" or
"weightFields" entry. Multiple weight fields are now supported in both
functions.

The distinction between oriented and non-oriented fields has been
removed from surfaceFieldValue. There is now just a single list of
fields which are operated on. Instead of oriented fields, an
"orientedSum" operation has been added, which should be used for
flowRate calculations and other similar operations on fluxes.

Operations minMag and maxMag have been added to both functions, to
calculate the minimum and maximum field magnitudes respectively. The min
and max operations are performed component-wise, as was the case
previously.

In volFieldValue, minMag and maxMag (and min and mag operations when
applied to scalar fields) will report the location, cell and processor
of the maximum or minimum value. There is also a "writeLocation" option
which if set will write this location information into the output file.
The fieldMinMax function has been made obsolete by this change, and has
therefore been removed.

surfaceFieldValue now operates in parallel without accumulating the
entire surface on the master processor for calculation of the operation.
Collecting the entire surface on the master processor is now only done
if the surface itself is to be written out.
This commit is contained in:
Will Bainbridge
2021-07-08 10:51:34 +01:00
parent e00316c7be
commit 056cc20f34
28 changed files with 781 additions and 1302 deletions

View File

@ -8,8 +8,7 @@
#includeEtc "caseDicts/postProcessing/surfaceFieldValue/faceZone.cfg"
fields ();
orientedFields (phi);
operation sum;
fields (phi);
operation orientedSum;
// ************************************************************************* //

View File

@ -1,17 +0,0 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Version: dev
\\/ M anipulation |
-------------------------------------------------------------------------------
Description
Writes out the maximum face value for one or more fields.
\*---------------------------------------------------------------------------*/
#includeEtc "caseDicts/postProcessing/minMax/faceMinMax.cfg"
fields (U p);
// ************************************************************************* //

View File

@ -1,17 +0,0 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Version: dev
\\/ M anipulation |
-------------------------------------------------------------------------------
Description
Writes out the minimum face value for one or more fields.
\*---------------------------------------------------------------------------*/
#includeEtc "caseDicts/postProcessing/minMax/faceMin.cfg"
fields (U p);
// ************************************************************************* //

View File

@ -1,12 +0,0 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Version: dev
\\/ M anipulation |
\*---------------------------------------------------------------------------*/
#includeEtc "caseDicts/postProcessing/minMax/faceMinMax.cfg"
operation min;
// ************************************************************************* //

View File

@ -1,20 +0,0 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Version: dev
\\/ M anipulation |
\*---------------------------------------------------------------------------*/
type surfaceFieldValue;
libs ("libfieldFunctionObjects.so");
writeControl timeStep;
writeInterval 1;
writeFields false;
regionType all;
operation max;
// ************************************************************************* //

View File

@ -1,17 +0,0 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Version: dev
\\/ M anipulation |
\*---------------------------------------------------------------------------*/
type fieldMinMax;
libs ("libfieldFunctionObjects.so");
writeControl timeStep;
writeInterval 1;
mode magnitude;
// ************************************************************************* //

View File

@ -1,18 +0,0 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Version: dev
\\/ M anipulation |
-------------------------------------------------------------------------------
Description
Writes out the minimum and maximum values, by component for non-scalar
fields, and the locations where they occur.
\*---------------------------------------------------------------------------*/
#includeEtc "caseDicts/postProcessing/minMax/minMaxComponents.cfg"
fields (U p);
// ************************************************************************* //

View File

@ -1,12 +0,0 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Version: dev
\\/ M anipulation |
\*---------------------------------------------------------------------------*/
#includeEtc "caseDicts/postProcessing/minMax/fieldMinMax.cfg"
mode component;
// ************************************************************************* //

View File

@ -1,18 +0,0 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Version: dev
\\/ M anipulation |
-------------------------------------------------------------------------------
Description
Writes out the minimum and maximum values, by magnitude for non-scalar
fields, and the locations where they occur.
\*---------------------------------------------------------------------------*/
#includeEtc "caseDicts/postProcessing/minMax/fieldMinMax.cfg"
fields (U p);
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2016-2020 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2016-2021 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -55,15 +55,7 @@ Description
#includeFunc mag(p)
\endverbatim
Other dictionary entries may also be specified using named arguments, for
example the \c name of the \c faceZone in the \c flowRateFaceZone \c
functionObject configuration set and the \c orientedFields entry which
defaults to \c phi may also be overridden as required, e.g.
\verbatim
#includeFunc flowRateFaceZone(name=fZone1)
#includeFunc flowRateFaceZone(orientedFields=(phiAlpha),name=fZone1)
\endverbatim
Other dictionary entries may also be specified using named arguments.
See also
Foam::functionObjectList

View File

@ -3,7 +3,6 @@ fieldAverage/fieldAverageItem/fieldAverageItem.C
fieldAverage/fieldAverageItem/fieldAverageItemIO.C
fieldCoordinateSystemTransform/fieldCoordinateSystemTransform.C
fieldMinMax/fieldMinMax.C
fieldValues/fieldValue/fieldValue.C
fieldValues/fieldValue/fieldValueNew.C

View File

@ -1,169 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "fieldMinMax.H"
#include "fieldTypes.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
defineTypeNameAndDebug(fieldMinMax, 0);
addToRunTimeSelectionTable(functionObject, fieldMinMax, dictionary);
}
}
template<>
const char* Foam::NamedEnum
<
Foam::functionObjects::fieldMinMax::modeType,
2
>::names[] = {"magnitude", "component"};
const Foam::NamedEnum
<
Foam::functionObjects::fieldMinMax::modeType,
2
> Foam::functionObjects::fieldMinMax::modeTypeNames_;
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::functionObjects::fieldMinMax::writeFileHeader(const label i)
{
OFstream& file = this->file();
writeHeader(file, "Field minima and maxima");
writeCommented(file, "Time");
if (location_)
{
writeTabbed(file, "field");
writeTabbed(file, "min");
writeTabbed(file, "location(min)");
if (Pstream::parRun())
{
writeTabbed(file, "processor");
}
writeTabbed(file, "max");
writeTabbed(file, "location(max)");
if (Pstream::parRun())
{
writeTabbed(file, "processor");
}
}
else
{
forAll(fieldSet_, fieldi)
{
writeTabbed(file, "min(" + fieldSet_[fieldi] + ')');
writeTabbed(file, "max(" + fieldSet_[fieldi] + ')');
}
}
file<< endl;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::fieldMinMax::fieldMinMax
(
const word& name,
const Time& runTime,
const dictionary& dict
)
:
fvMeshFunctionObject(name, runTime, dict),
logFiles(obr_, name),
location_(true),
mode_(modeType::mag),
fieldSet_()
{
read(dict);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::functionObjects::fieldMinMax::~fieldMinMax()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::functionObjects::fieldMinMax::read(const dictionary& dict)
{
fvMeshFunctionObject::read(dict);
location_ = dict.lookupOrDefault<Switch>("location", true);
mode_ = modeTypeNames_[dict.lookupOrDefault<word>("mode", "magnitude")];
dict.lookup("fields") >> fieldSet_;
resetName(typeName);
return true;
}
bool Foam::functionObjects::fieldMinMax::execute()
{
return true;
}
bool Foam::functionObjects::fieldMinMax::write()
{
logFiles::write();
if (Pstream::master() && !location_) writeTime(file());
Log << type() << " " << name() << " write:" << nl;
forAll(fieldSet_, fieldi)
{
calcMinMaxFields<scalar>(fieldSet_[fieldi], modeType::cmpt);
calcMinMaxFields<vector>(fieldSet_[fieldi], mode_);
calcMinMaxFields<sphericalTensor>(fieldSet_[fieldi], mode_);
calcMinMaxFields<symmTensor>(fieldSet_[fieldi], mode_);
calcMinMaxFields<tensor>(fieldSet_[fieldi], mode_);
}
if (Pstream::master() && !location_) file() << endl;
Log << endl;
return true;
}
// ************************************************************************* //

View File

@ -1,209 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2020 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::functionObjects::fieldMinMax
Description
Calculates the value and location of scalar minimum and maximum for a list
of user-specified fields.
For variables with a rank greater than zero, either the min/max of a
component value or the magnitude is reported. When operating in parallel,
the processor owning the value is also given.
Example of function object specification:
\verbatim
fieldMinMax1
{
type fieldMinMax;
libs ("libfieldFunctionObjects.so");
...
log yes;
location yes;
mode magnitude;
fields
(
U
p
);
}
\endverbatim
Usage
\table
Property | Description | Required | Default value
type | type name: fieldMinMax | yes |
log | write min/max data to standard output | no | no
location | write location of the min/max value | no | yes
mode | calculation mode: magnitude or component | no | magnitude
\endtable
Output data is written to the file \<timeDir\>/fieldMinMax.dat
See also
Foam::functionObjects::fvMeshFunctionObject
Foam::functionObjects::logFiles
SourceFiles
fieldMinMax.C
\*---------------------------------------------------------------------------*/
#ifndef functionObjects_fieldMinMax_H
#define functionObjects_fieldMinMax_H
#include "fvMeshFunctionObject.H"
#include "logFiles.H"
#include "vector.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
/*---------------------------------------------------------------------------*\
Class fieldMinMax Declaration
\*---------------------------------------------------------------------------*/
class fieldMinMax
:
public fvMeshFunctionObject,
public logFiles
{
public:
enum class modeType
{
mag,
cmpt
};
protected:
// Protected data
//- Mode type names
static const NamedEnum<modeType, 2> modeTypeNames_;
//- Switch to write location of min/max values
Switch location_;
//- Mode for min/max - only applicable for ranks > 0
modeType mode_;
//- Fields to assess min/max
wordList fieldSet_;
// Protected Member Functions
//- Helper function to write the output
template<class Type>
void output
(
const word& fieldName,
const word& outputName,
const label minCell,
const label maxCell,
const vector& minC,
const vector& maxC,
const label minProci,
const label maxProci,
const Type& minValue,
const Type& maxValue
);
//- Calculate the field min/max
template<class Type>
void calcMinMaxFields
(
const word& fieldName,
const modeType& mode
);
//- Output file header information
virtual void writeFileHeader(const label i);
public:
//- Runtime type information
TypeName("fieldMinMax");
// Constructors
//- Construct from Time and dictionary
fieldMinMax
(
const word& name,
const Time& runTime,
const dictionary& dict
);
//- Disallow default bitwise copy construction
fieldMinMax(const fieldMinMax&) = delete;
//- Destructor
virtual ~fieldMinMax();
// Member Functions
//- Read the field min/max data
virtual bool read(const dictionary&);
//- Execute, currently does nothing
virtual bool execute();
//- Write the fieldMinMax
virtual bool write();
// Member Operators
//- Disallow default bitwise assignment
void operator=(const fieldMinMax&) = delete;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace functionObjects
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "fieldMinMaxTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,305 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "fieldMinMax.H"
#include "volFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
void Foam::functionObjects::fieldMinMax::output
(
const word& fieldName,
const word& outputName,
const label minCell,
const label maxCell,
const vector& minC,
const vector& maxC,
const label minProci,
const label maxProci,
const Type& minValue,
const Type& maxValue
)
{
OFstream& file = this->file();
if (location_)
{
writeTime(file());
writeTabbed(file, fieldName);
file<< tab << minValue
<< tab << minC;
if (Pstream::parRun())
{
file<< tab << minProci;
}
file<< tab << maxValue
<< tab << maxC;
if (Pstream::parRun())
{
file<< tab << maxProci;
}
file<< endl;
Log << " min(" << outputName << ") = " << minValue
<< " in cell " << minCell
<< " at location " << minC;
if (Pstream::parRun())
{
Log << " on processor " << minProci;
}
Log << nl << " max(" << outputName << ") = " << maxValue
<< " in cell " << maxCell
<< " at location " << maxC;
if (Pstream::parRun())
{
Log << " on processor " << maxProci;
}
}
else
{
file<< tab << minValue << tab << maxValue;
Log << " min/max(" << outputName << ") = "
<< minValue << ' ' << maxValue;
}
Log << endl;
}
template<class Type>
void Foam::functionObjects::fieldMinMax::calcMinMaxFields
(
const word& fieldName,
const modeType& mode
)
{
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
if (obr_.foundObject<fieldType>(fieldName))
{
const label proci = Pstream::myProcNo();
const fieldType& field = obr_.lookupObject<fieldType>(fieldName);
const volVectorField::Boundary& CfBoundary =
mesh_.C().boundaryField();
switch (mode)
{
case modeType::mag:
{
const volScalarField magField(mag(field));
const volScalarField::Boundary& magFieldBoundary =
magField.boundaryField();
scalarList minVs(Pstream::nProcs());
labelList minCells(Pstream::nProcs());
List<vector> minCs(Pstream::nProcs());
label minProci = findMin(magField);
minVs[proci] = magField[minProci];
minCells[proci] = minProci;
minCs[proci] = mesh_.C()[minProci];
scalarList maxVs(Pstream::nProcs());
labelList maxCells(Pstream::nProcs());
List<vector> maxCs(Pstream::nProcs());
label maxProci = findMax(magField);
maxVs[proci] = magField[maxProci];
maxCells[proci] = maxProci;
maxCs[proci] = mesh_.C()[maxProci];
forAll(magFieldBoundary, patchi)
{
const scalarField& mfp = magFieldBoundary[patchi];
if (mfp.size())
{
const vectorField& Cfp = CfBoundary[patchi];
const labelList& faceCells =
magFieldBoundary[patchi].patch().faceCells();
label minPI = findMin(mfp);
if (mfp[minPI] < minVs[proci])
{
minVs[proci] = mfp[minPI];
minCells[proci] = faceCells[minPI];
minCs[proci] = Cfp[minPI];
}
label maxPI = findMax(mfp);
if (mfp[maxPI] > maxVs[proci])
{
maxVs[proci] = mfp[maxPI];
maxCells[proci] = faceCells[maxPI];
maxCs[proci] = Cfp[maxPI];
}
}
}
Pstream::gatherList(minVs);
Pstream::gatherList(minCells);
Pstream::gatherList(minCs);
Pstream::gatherList(maxVs);
Pstream::gatherList(maxCells);
Pstream::gatherList(maxCs);
if (Pstream::master())
{
const label minI = findMin(minVs);
const scalar minValue = minVs[minI];
const label minCell = minCells[minI];
const vector& minC = minCs[minI];
const label maxI = findMax(maxVs);
const scalar maxValue = maxVs[maxI];
const label maxCell = maxCells[maxI];
const vector& maxC = maxCs[maxI];
output
(
fieldName,
word("mag(" + fieldName + ")"),
minCell,
maxCell,
minC,
maxC,
minI,
maxI,
minValue,
maxValue
);
}
break;
}
case modeType::cmpt:
{
const typename fieldType::Boundary&
fieldBoundary = field.boundaryField();
List<Type> minVs(Pstream::nProcs());
labelList minCells(Pstream::nProcs());
List<vector> minCs(Pstream::nProcs());
label minProci = findMin(field);
minVs[proci] = field[minProci];
minCells[proci] = minProci;
minCs[proci] = mesh_.C()[minProci];
List<Type> maxVs(Pstream::nProcs());
labelList maxCells(Pstream::nProcs());
List<vector> maxCs(Pstream::nProcs());
label maxProci = findMax(field);
maxVs[proci] = field[maxProci];
maxCells[proci] = maxProci;
maxCs[proci] = mesh_.C()[maxProci];
forAll(fieldBoundary, patchi)
{
const Field<Type>& fp = fieldBoundary[patchi];
if (fp.size())
{
const vectorField& Cfp = CfBoundary[patchi];
const labelList& faceCells =
fieldBoundary[patchi].patch().faceCells();
label minPI = findMin(fp);
if (fp[minPI] < minVs[proci])
{
minVs[proci] = fp[minPI];
minCells[proci] = faceCells[minPI];
minCs[proci] = Cfp[minPI];
}
label maxPI = findMax(fp);
if (fp[maxPI] > maxVs[proci])
{
maxVs[proci] = fp[maxPI];
maxCells[proci] = faceCells[maxPI];
maxCs[proci] = Cfp[maxPI];
}
}
}
Pstream::gatherList(minVs);
Pstream::gatherList(minCells);
Pstream::gatherList(minCs);
Pstream::gatherList(maxVs);
Pstream::gatherList(maxCells);
Pstream::gatherList(maxCs);
if (Pstream::master())
{
label minI = findMin(minVs);
Type minValue = minVs[minI];
const label minCell = minCells[minI];
const vector& minC = minCs[minI];
label maxI = findMax(maxVs);
Type maxValue = maxVs[maxI];
const label maxCell = maxCells[maxI];
const vector& maxC = maxCs[maxI];
output
(
fieldName,
fieldName,
minCell,
maxCell,
minC,
maxC,
minI,
maxI,
minValue,
maxValue
);
}
break;
}
default:
{
FatalErrorInFunction
<< "Unknown min/max mode: " << modeTypeNames_[mode_]
<< exit(FatalError);
}
}
}
}
// ************************************************************************* //

View File

@ -63,23 +63,22 @@ template<>
const char* Foam::NamedEnum
<
Foam::functionObjects::fieldValues::surfaceFieldValue::operationType,
17
16
>::names[] =
{
"none",
"sum",
"weightedSum",
"sumMag",
"sumDirection",
"sumDirectionBalance",
"orientedSum",
"average",
"weightedAverage",
"areaAverage",
"weightedAreaAverage",
"areaIntegrate",
"weightedAreaIntegrate",
"min",
"max",
"minMag",
"maxMag",
"CoV",
"areaNormalAverage",
"areaNormalIntegrate"
@ -94,7 +93,7 @@ const Foam::NamedEnum
const Foam::NamedEnum
<
Foam::functionObjects::fieldValues::surfaceFieldValue::operationType,
17
16
> Foam::functionObjects::fieldValues::surfaceFieldValue::operationTypeNames_;
@ -366,7 +365,7 @@ combineSurfaceGeometry
pointField& points
) const
{
if (surfacePtr_.valid())
if (regionType_ == regionTypes::sampledSurface)
{
const sampledSurface& s = surfacePtr_();
@ -402,18 +401,14 @@ combineSurfaceGeometry
Foam::scalar
Foam::functionObjects::fieldValues::surfaceFieldValue::totalArea() const
{
scalar totalArea;
if (surfacePtr_.valid())
if (regionType_ == regionTypes::sampledSurface)
{
totalArea = gSum(surfacePtr_().magSf());
return gSum(surfacePtr_().magSf());
}
else
{
totalArea = gSum(filterField(mesh_.magSf(), false));
return gSum(filterField(mesh_.magSf()));
}
return totalArea;
}
@ -462,7 +457,7 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::initialise
<< " Region has no faces" << exit(FatalError);
}
if (surfacePtr_.valid())
if (regionType_ == regionTypes::sampledSurface)
{
surfacePtr_().update();
}
@ -475,42 +470,18 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::initialise
<< " total area = " << totalArea_
<< nl;
if (dict.readIfPresent("orientedWeightField", weightFieldName_))
if (dict.readIfPresent("weightFields", weightFieldNames_))
{
Info<< " orientedWeightField = " << weightFieldName_ << nl;
orientWeightField_ = true;
Info<< name() << " " << operationTypeNames_[operation_]
<< " weight fields " << weightFieldNames_;
}
else if (dict.found("weightField"))
{
weightFieldNames_.setSize(1);
dict.lookup("weightField") >> weightFieldNames_[0];
if (regionType_ == regionTypes::sampledSurface)
{
FatalIOErrorInFunction(dict)
<< "Cannot use orientedWeightField for a sampledSurface"
<< exit(FatalIOError);
}
if (dict.found("weightField"))
{
FatalIOErrorInFunction(dict)
<< "Either provide weightField or orientedWeightField"
<< exit(FatalIOError);
}
}
else if (dict.readIfPresent("weightField", weightFieldName_))
{
Info<< " weightField = " << weightFieldName_ << nl;
if (regionType_ == regionTypes::sampledSurface)
{
FatalIOErrorInFunction(dict)
<< "Cannot use weightField for a sampledSurface"
<< exit(FatalIOError);
}
}
List<word> orientedFields;
if (dict.readIfPresent("orientedFields", orientedFields))
{
orientedFieldsStart_ = fields_.size();
fields_.append(orientedFields);
Info<< name() << " " << operationTypeNames_[operation_]
<< " weight field " << weightFieldNames_[0];
}
if (dict.readIfPresent("scaleFactor", scaleFactor_))
@ -567,8 +538,9 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::writeFileHeader
bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
(
const Field<scalar>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf,
const scalarField& weightField,
scalar& result
) const
{
@ -576,21 +548,28 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
{
case operationType::sumDirection:
{
vector n(dict_.lookup("direction"));
result = sum(pos0(values*(Sf & n))*mag(values));
const vector n(dict_.lookup("direction"));
result = gSum(weights*pos0(values*(Sf & n))*mag(values));
return true;
}
case operationType::sumDirectionBalance:
{
vector n(dict_.lookup("direction"));
const vector n(dict_.lookup("direction"));
const scalarField nv(values*(Sf & n));
result = sum(pos0(nv)*mag(values) - neg(nv)*mag(values));
result = gSum(weights*(pos0(nv)*mag(values) - neg(nv)*mag(values)));
return true;
}
default:
{
// Fall through to same-type operations
return processValuesTypeType(values, Sf, weightField, result);
return processValuesTypeType
(
values,
signs,
weights,
Sf,
result
);
}
}
}
@ -599,8 +578,9 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
(
const Field<vector>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf,
const scalarField& weightField,
scalar& result
) const
{
@ -608,12 +588,12 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
{
case operationType::areaNormalAverage:
{
result = sum(values & Sf)/sum(mag(Sf));
result = gSum(weights*values & Sf)/gSum(mag(weights*Sf));
return true;
}
case operationType::areaNormalIntegrate:
{
result = sum(values & Sf);
result = gSum(weights*values & Sf);
return true;
}
default:
@ -627,8 +607,9 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
(
const Field<vector>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf,
const scalarField& weightField,
vector& result
) const
{
@ -636,24 +617,29 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
{
case operationType::sumDirection:
{
vector n(dict_.lookup("direction"));
n /= mag(n) + rootVSmall;
const vector n = normalised(dict_.lookup<vector>("direction"));
const scalarField nv(n & values);
result = sum(pos0(nv)*n*(nv));
result = gSum(weights*pos0(nv)*n*(nv));
return true;
}
case operationType::sumDirectionBalance:
{
vector n(dict_.lookup("direction"));
n /= mag(n) + rootVSmall;
const vector n = normalised(dict_.lookup<vector>("direction"));
const scalarField nv(n & values);
result = sum(pos0(nv)*n*(nv));
result = gSum(weights*pos0(nv)*n*(nv));
return true;
}
default:
{
// Fall through to same-type operations
return processValuesTypeType(values, Sf, weightField, result);
return processValuesTypeType
(
values,
signs,
weights,
Sf,
result
);
}
}
}
@ -672,10 +658,8 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::surfaceFieldValue
surfaceWriterPtr_(nullptr),
regionType_(regionTypeNames_.read(dict.lookup("regionType"))),
operation_(operationTypeNames_.read(dict.lookup("operation"))),
weightFieldName_("none"),
orientWeightField_(false),
orientedFieldsStart_(labelMax),
scaleFactor_(1.0),
weightFieldNames_(),
scaleFactor_(1),
writeArea_(dict.lookupOrDefault("writeArea", false)),
nFaces_(0),
faceId_(),
@ -696,10 +680,8 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::surfaceFieldValue
surfaceWriterPtr_(nullptr),
regionType_(regionTypeNames_.read(dict.lookup("regionType"))),
operation_(operationTypeNames_.read(dict.lookup("operation"))),
weightFieldName_("none"),
orientWeightField_(false),
orientedFieldsStart_(labelMax),
scaleFactor_(1.0),
weightFieldNames_(),
scaleFactor_(1),
writeArea_(dict.lookupOrDefault("writeArea", false)),
nFaces_(0),
faceId_(),
@ -737,7 +719,7 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::write()
fieldValue::write();
}
if (surfacePtr_.valid())
if (regionType_ == regionTypes::sampledSurface)
{
surfacePtr_().update();
}
@ -758,12 +740,12 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::write()
}
// Write the surface geometry
if (surfaceWriterPtr_.valid())
if (writeFields_)
{
faceList faces;
pointField points;
if (surfacePtr_.valid())
if (regionType_ == regionTypes::sampledSurface)
{
combineSurfaceGeometry(faces, points);
}
@ -784,21 +766,24 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::write()
}
}
// Construct weight field. Note: zero size means weight = 1
scalarField weightField;
if (weightFieldName_ != "none")
{
weightField =
getFieldValues<scalar>
// Construct the sign and weight fields and the surface normals
const scalarField signs
(
weightFieldName_,
true,
orientWeightField_
regionType_ == regionTypes::sampledSurface
? scalarField(surfacePtr_().Sf().size(), 1)
: List<scalar>(faceSign_)
);
scalarField weights(signs.size(), 1);
forAll(weightFieldNames_, i)
{
weights *= getFieldValues<scalar>(weightFieldNames_[i]);
}
// Combine onto master
combineFields(weightField);
const vectorField Sf
(
regionType_ == regionTypes::sampledSurface
? surfacePtr_().Sf()
: (signs*filterField(mesh_.Sf()))()
);
// Process the fields
forAll(fields_, i)
@ -806,12 +791,18 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::write()
const word& fieldName = fields_[i];
bool ok = false;
bool orient = i >= orientedFieldsStart_;
ok = ok || writeValues<scalar>(fieldName, weightField, orient);
ok = ok || writeValues<vector>(fieldName, weightField, orient);
ok = ok || writeValues<sphericalTensor>(fieldName, weightField, orient);
ok = ok || writeValues<symmTensor>(fieldName, weightField, orient);
ok = ok || writeValues<tensor>(fieldName, weightField, orient);
#define writeValuesFieldType(fieldType, none) \
ok = \
ok \
|| writeValues<fieldType> \
( \
fieldName, \
signs, \
weights, \
Sf \
);
FOR_ALL_FIELD_TYPES(writeValuesFieldType);
#undef writeValuesFieldType
if (!ok)
{

View File

@ -32,7 +32,7 @@ Description
averages and integrations.
For example, to calculate the volumetric or mass flux across a patch,
apply the 'sum' operator to the flux field (typically \c phi)
apply the 'orientedSum' operator to the flux field (typically \c phi)
Examples of function object specification:
\verbatim
@ -96,10 +96,9 @@ Usage
name | name of face regionType if required | no |
operation | operation to perform | yes |
weightField | name of field to apply weighting | no |
orientedWeightField | name of oriented field to apply weighting | no |
weightFields | Names of fields to apply weighting | no |
scaleFactor | scale factor | no | 1
fields | list of fields to operate on | yes |
orientedFields | list of oriented fields to operate on | no |
\endtable
Where \c regionType is defined by
@ -113,41 +112,38 @@ Usage
\plaintable
none | no operation
sum | sum
weightedSum | weighted sum
sumMag | sum of component magnitudes
sumDirection | sum values which are positive in given direction
sumDirectionBalance | sum of balance of values in given direction
orientedSum | sum with face orientations
average | ensemble average
weightedAverage | weighted average
areaAverage | area weighted average
weightedAreaAverage | weighted area average
areaIntegrate | area integral
weightedAreaIntegrate | weighted area integral
min | minimum
max | maximum
minMag | minimum magnitude
maxMag | maximum magnitude
CoV | coefficient of variation: standard deviation/mean
areaNormalAverage | area weighted average in face normal direction
areaNormalIntegrate | area weighted integral in face normal directon
areaNormalIntegrate | area weighted integral in face normal direction
\endplaintable
Note
- The values reported by the areaNormalAverage and areaNormalIntegrate
operations are written as the first component of a field with the same
rank as the input field.
- faces on empty patches get ignored
- if the field is a volField the \c faceZone can only consist of boundary
- Faces on empty patches get ignored.
- The `oriented' operations will flip the sign of the field so that all the
normals point in a consistent direction. This is only of relevance when
summing mesh-oriented fields, such as the flux, on faceZones.
- If the field is a volField then a \c faceZone can only consist of
boundary faces, because only these faces have a value associated with
them. No cell-to-face interpolation is performed.
- If the field is a surfaceField then the region cannot be a \c
sampledSurface
- If a sampledSurface has interpolation set to false then the surface
face values will be taken directly from the cell that contains the
surface face centre
- If a \c sampledSurface has interpolation set to true then the field
will be interpolated to the vertices, then averaged onto the surface
faces
- the `oriented' entries relate to mesh-oriented fields, such as the
flux, phi. These fields will be oriented according to the face normals.
- using \c sampledSurface:
- not available for surface fields
- if interpolate=true they use \c interpolationCellPoint
otherwise they use cell values
- each triangle in \c sampledSurface is logically only in one cell
so interpolation will be wrong when triangles are larger than
cells. This can only happen for sampling on a \c triSurfaceMesh
- take care when using isoSurfaces - these might have duplicate
triangles and so integration might be wrong
See also
Foam::fieldValues
@ -208,25 +204,24 @@ public:
{
none,
sum,
weightedSum,
sumMag,
sumDirection,
sumDirectionBalance,
orientedSum,
average,
weightedAverage,
areaAverage,
weightedAreaAverage,
areaIntegrate,
weightedAreaIntegrate,
min,
max,
minMag,
maxMag,
CoV,
areaNormalAverage,
areaNormalIntegrate
};
//- Operation type names
static const NamedEnum<operationType, 17> operationTypeNames_;
static const NamedEnum<operationType, 16> operationTypeNames_;
private:
@ -273,14 +268,8 @@ protected:
//- Operation to apply to values
operationType operation_;
//- Weight field name - optional
word weightFieldName_;
//- Flag to indicate if flipMap should be applied to the weight field
bool orientWeightField_;
//- Start index of fields that require application of flipMap
label orientedFieldsStart_;
//- Weight field names - optional
wordList weightFieldNames_;
//- Scale factor - optional
scalar scaleFactor_;
@ -325,12 +314,7 @@ protected:
//- Return field values by looking up field name
template<class Type>
tmp<Field<Type>> getFieldValues
(
const word& fieldName,
const bool mustGet = false,
const bool applyOrientation = false
) const;
tmp<Field<Type>> getFieldValues(const word& fieldName) const;
//- Apply the operation to the values, and return true if successful.
// Does nothing unless overloaded below.
@ -338,8 +322,9 @@ protected:
bool processValues
(
const Field<Type>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf,
const scalarField& weightField,
ResultType& result
) const;
@ -349,19 +334,32 @@ protected:
bool processValues
(
const Field<Type>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf,
const scalarField& weightField,
Type& result
) const;
//- Apply Type -> scalar operation to the values
template<class Type>
bool processValues
(
const Field<Type>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf,
scalar& result
) const;
//- Apply scalar -> scalar operation to the values. Tries to apply
// scalar -> scalar specific operations, otherwise calls
// processValuesTypeType.
bool processValues
(
const Field<scalar>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf,
const scalarField& weightField,
scalar& result
) const;
@ -369,8 +367,9 @@ protected:
bool processValues
(
const Field<vector>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf,
const scalarField& weightField,
scalar& result
) const;
@ -380,8 +379,9 @@ protected:
bool processValues
(
const Field<vector>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf,
const scalarField& weightField,
vector& result
) const;
@ -390,8 +390,9 @@ protected:
bool processValuesTypeType
(
const Field<Type>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf,
const scalarField& weightField,
Type& result
) const;
@ -450,8 +451,9 @@ public:
bool writeValues
(
const word& fieldName,
const scalarField& weightField,
const bool orient
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf
);
//- Templated helper function to output field values
@ -459,8 +461,9 @@ public:
bool writeValues
(
const word& fieldName,
const scalarField& weightField,
const Field<Type>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf
);
@ -468,16 +471,14 @@ public:
template<class Type>
tmp<Field<Type>> filterField
(
const GeometricField<Type, fvsPatchField, surfaceMesh>& field,
const bool applyOrientation
const GeometricField<Type, fvsPatchField, surfaceMesh>& field
) const;
//- Filter a volume field according to faceIds
template<class Type>
tmp<Field<Type>> filterField
(
const GeometricField<Type, fvPatchField, volMesh>& field,
const bool applyOrientation
const GeometricField<Type, fvPatchField, volMesh>& field
) const;
//- Read from dictionary

View File

@ -62,42 +62,29 @@ template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::functionObjects::fieldValues::surfaceFieldValue::getFieldValues
(
const word& fieldName,
const bool mustGet,
const bool applyOrientation
const word& fieldName
) const
{
typedef GeometricField<Type, fvsPatchField, surfaceMesh> sf;
typedef GeometricField<Type, fvPatchField, volMesh> vf;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> sf;
if
(
regionType_ != regionTypes::sampledSurface
&& obr_.foundObject<sf>(fieldName)
)
if (regionType_ == regionTypes::sampledSurface)
{
return filterField(obr_.lookupObject<sf>(fieldName), applyOrientation);
}
else if (obr_.foundObject<vf>(fieldName))
if (obr_.foundObject<vf>(fieldName))
{
const vf& fld = obr_.lookupObject<vf>(fieldName);
if (surfacePtr_.valid())
{
if (surfacePtr_().interpolate())
{
// Interpolate the field to the surface points
const interpolationCellPoint<Type> interp(fld);
tmp<Field<Type>> tintFld(surfacePtr_().interpolate(interp));
const Field<Type>& intFld = tintFld();
// Average
// Average the interpolated field onto the surface faces
const faceList& faces = surfacePtr_().faces();
tmp<Field<Type>> tavg
(
new Field<Type>(faces.size(), Zero)
);
tmp<Field<Type>> tavg(new Field<Type>(faces.size(), Zero));
Field<Type>& avg = tavg.ref();
forAll(faces, facei)
{
const face& f = faces[facei];
@ -115,20 +102,34 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::getFieldValues
return surfacePtr_().sample(fld);
}
}
else if (obr_.foundObject<sf>(fieldName))
{
FatalErrorInFunction
<< "Surface field " << fieldName
<< " cannot be sampled onto surface " << surfacePtr_().name()
<< ". Only vol fields can be sampled onto surfaces."
<< abort(FatalError);
}
}
else
{
return filterField(fld, applyOrientation);
if (obr_.foundObject<vf>(fieldName))
{
const vf& fld = obr_.lookupObject<vf>(fieldName);
return filterField(fld);
}
else if (obr_.foundObject<sf>(fieldName))
{
const sf& fld = obr_.lookupObject<sf>(fieldName);
return filterField(fld);
}
}
if (mustGet)
{
FatalErrorInFunction
<< "Field " << fieldName << " not found in database"
<< abort(FatalError);
}
return tmp<Field<Type>>(new Field<Type>(0));
return tmp<Field<Type>>(nullptr);
}
@ -136,8 +137,9 @@ template<class Type, class ResultType>
bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
(
const Field<Type>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf,
const scalarField& weightField,
ResultType& result
) const
{
@ -149,12 +151,43 @@ template<class Type>
bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
(
const Field<Type>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf,
const scalarField& weightField,
Type& result
) const
{
return processValuesTypeType(values, Sf, weightField, result);
return processValuesTypeType(values, signs, weights, Sf, result);
}
template<class Type>
bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
(
const Field<Type>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf,
scalar& result
) const
{
switch (operation_)
{
case operationType::minMag:
{
result = gMin(mag(values));
return true;
}
case operationType::maxMag:
{
result = gMax(mag(values));
return true;
}
default:
{
return false;
}
}
}
@ -163,8 +196,9 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::
processValuesTypeType
(
const Field<Type>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf,
const scalarField& weightField,
Type& result
) const
{
@ -172,104 +206,55 @@ processValuesTypeType
{
case operationType::sum:
{
result = sum(values);
return true;
}
case operationType::weightedSum:
{
if (weightField.size())
{
result = sum(weightField*values);
}
else
{
result = sum(values);
}
result = gSum(weights*values);
return true;
}
case operationType::sumMag:
{
result = sum(cmptMag(values));
result = gSum(weights*cmptMag(values));
return true;
}
case operationType::orientedSum:
{
result = gSum(signs*weights*values);
return true;
}
case operationType::average:
{
result = sum(values)/values.size();
return true;
}
case operationType::weightedAverage:
{
if (weightField.size())
{
result =
sum(weightField*values)
/stabilise(sum(weightField), vSmall);
}
else
{
result = sum(values)/values.size();
}
gSum(weights*values)
/stabilise(gSum(weights), vSmall);
return true;
}
case operationType::areaAverage:
{
const scalarField magSf(mag(Sf));
result = sum(magSf*values)/sum(magSf);
return true;
}
case operationType::weightedAreaAverage:
{
const scalarField magSf(mag(Sf));
if (weightField.size())
{
result =
sum(weightField*magSf*values)
/stabilise(sum(magSf*weightField), vSmall);
}
else
{
result = sum(magSf*values)/sum(magSf);
}
gSum(weights*magSf*values)
/stabilise(gSum(weights*magSf), vSmall);
return true;
}
case operationType::areaIntegrate:
{
const scalarField magSf(mag(Sf));
result = sum(magSf*values);
return true;
}
case operationType::weightedAreaIntegrate:
{
const scalarField magSf(mag(Sf));
if (weightField.size())
{
result = sum(weightField*magSf*values);
}
else
{
result = sum(magSf*values);
}
result = gSum(weights*magSf*values);
return true;
}
case operationType::min:
{
result = min(values);
result = gMin(values);
return true;
}
case operationType::max:
{
result = max(values);
result = gMax(values);
return true;
}
case operationType::CoV:
{
const scalarField magSf(mag(Sf));
Type meanValue = sum(values*magSf)/sum(magSf);
Type meanValue = gSum(values*magSf)/gSum(magSf);
const label nComp = pTraits<Type>::nComponents;
@ -279,7 +264,7 @@ processValuesTypeType
scalar mean = component(meanValue, d);
scalar& res = setComponent(result, d);
res = sqrt(sum(magSf*sqr(vals - mean))/sum(magSf))/mean;
res = sqrt(gSum(magSf*sqr(vals - mean))/gSum(magSf))/mean;
}
return true;
@ -302,39 +287,25 @@ template<class Type>
bool Foam::functionObjects::fieldValues::surfaceFieldValue::writeValues
(
const word& fieldName,
const scalarField& weightField,
const bool orient
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf
)
{
const bool ok = validField<Type>(fieldName);
if (ok)
{
Field<Type> values(getFieldValues<Type>(fieldName, true, orient));
vectorField Sf;
if (surfacePtr_.valid())
{
// Get oriented Sf
Sf = surfacePtr_().Sf();
}
else
{
// Get oriented Sf
Sf = filterField(mesh_.Sf(), true);
}
// Combine onto master
combineFields(values);
combineFields(Sf);
// Get the values
Field<Type> values(getFieldValues<Type>(fieldName));
// Write raw values on surface if specified
if (surfaceWriterPtr_.valid())
if (writeFields_)
{
faceList faces;
pointField points;
if (surfacePtr_.valid())
if (regionType_ == regionTypes::sampledSurface)
{
combineSurfaceGeometry(faces, points);
}
@ -343,6 +314,9 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::writeValues
combineMeshGeometry(faces, points);
}
Field<Type> writeValues(weights*values);
combineFields(writeValues);
if (Pstream::master())
{
surfaceWriterPtr_->write
@ -352,32 +326,35 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::writeValues
points,
faces,
fieldName,
values,
writeValues,
false
);
}
}
// Do the operation
if (operation_ != operationType::none)
{
// Apply scale factor
values *= scaleFactor_;
if (Pstream::master())
{
if
(
!writeValues<Type, scalar>
(fieldName, weightField, values, Sf)
&& !writeValues<Type, vector>
(fieldName, weightField, values, Sf)
&& !writeValues<Type, sphericalTensor>
(fieldName, weightField, values, Sf)
&& !writeValues<Type, symmTensor>
(fieldName, weightField, values, Sf)
&& !writeValues<Type, tensor>
(fieldName, weightField, values, Sf)
)
bool ok = false;
#define writeValuesFieldType(fieldType, none) \
ok = \
ok \
|| writeValues<Type, fieldType> \
( \
fieldName, \
values, \
signs, \
weights, \
Sf \
);
FOR_ALL_FIELD_TYPES(writeValuesFieldType);
#undef writeValuesFieldType
if (!ok)
{
FatalErrorInFunction
<< "Operation " << operationTypeNames_[operation_]
@ -387,7 +364,6 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::writeValues
}
}
}
}
return ok;
}
@ -397,23 +373,27 @@ template<class Type, class ResultType>
bool Foam::functionObjects::fieldValues::surfaceFieldValue::writeValues
(
const word& fieldName,
const scalarField& weightField,
const Field<Type>& values,
const scalarField& signs,
const scalarField& weights,
const vectorField& Sf
)
{
ResultType result;
if (processValues(values, Sf, weightField, result))
if (processValues(values, signs, weights, Sf, result))
{
// Add to result dictionary, over-writing any previous entry
resultDict_.add(fieldName, result, true);
if (Pstream::master())
{
file() << tab << result;
Log << " " << operationTypeNames_[operation_]
<< "(" << regionName_ << ") of " << fieldName
<< " = " << result << endl;
}
return true;
}
@ -426,8 +406,7 @@ template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::functionObjects::fieldValues::surfaceFieldValue::filterField
(
const GeometricField<Type, fvPatchField, volMesh>& field,
const bool applyOrientation
const GeometricField<Type, fvPatchField, volMesh>& field
) const
{
tmp<Field<Type>> tvalues(new Field<Type>(faceId_.size()));
@ -435,8 +414,9 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::filterField
forAll(values, i)
{
label facei = faceId_[i];
label patchi = facePatchId_[i];
const label facei = faceId_[i];
const label patchi = facePatchId_[i];
if (patchi >= 0)
{
values[i] = field.boundaryField()[patchi][facei];
@ -452,14 +432,6 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::filterField
}
}
if (applyOrientation)
{
forAll(values, i)
{
values[i] *= faceSign_[i];
}
}
return tvalues;
}
@ -468,8 +440,7 @@ template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::functionObjects::fieldValues::surfaceFieldValue::filterField
(
const GeometricField<Type, fvsPatchField, surfaceMesh>& field,
const bool applyOrientation
const GeometricField<Type, fvsPatchField, surfaceMesh>& field
) const
{
tmp<Field<Type>> tvalues(new Field<Type>(faceId_.size()));
@ -477,8 +448,9 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::filterField
forAll(values, i)
{
label facei = faceId_[i];
label patchi = facePatchId_[i];
const label facei = faceId_[i];
const label patchi = facePatchId_[i];
if (patchi >= 0)
{
values[i] = field.boundaryField()[patchi][facei];
@ -489,14 +461,6 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::filterField
}
}
if (applyOrientation)
{
forAll(values, i)
{
values[i] *= faceSign_[i];
}
}
return tvalues;
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2020 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -48,28 +48,26 @@ const char*
Foam::NamedEnum
<
Foam::functionObjects::fieldValues::volFieldValue::operationType,
13
11
>::names[] =
{
"none",
"sum",
"weightedSum",
"sumMag",
"average",
"weightedAverage",
"volAverage",
"weightedVolAverage",
"volIntegrate",
"weightedVolIntegrate",
"min",
"max",
"minMag",
"maxMag",
"CoV"
};
const Foam::NamedEnum
<
Foam::functionObjects::fieldValues::volFieldValue::operationType,
13
11
> Foam::functionObjects::fieldValues::volFieldValue::operationTypeNames_;
@ -80,6 +78,8 @@ void Foam::functionObjects::fieldValues::volFieldValue::initialise
const dictionary& dict
)
{
dict.readIfPresent<Switch>("writeLocation", writeLocation_);
if (dict.readIfPresent("weightFields", weightFieldNames_))
{
Info<< name() << " " << operationTypeNames_[operation_]
@ -94,10 +94,57 @@ void Foam::functionObjects::fieldValues::volFieldValue::initialise
<< " weight field " << weightFieldNames_[0];
}
if (dict.readIfPresent("scaleFactor", scaleFactor_))
{
Info<< " scale factor = " << scaleFactor_ << nl;
}
Info<< nl << endl;
}
template<class Type>
void Foam::functionObjects::fieldValues::volFieldValue::
writeFileHeaderLocation()
{
switch (operation_)
{
case operationType::minMag:
case operationType::maxMag:
file() << tab << "location" << tab << "cell";
if (Pstream::parRun())
{
file() << tab << "processor";
}
break;
default:
break;
}
}
template<>
void Foam::functionObjects::fieldValues::volFieldValue::
writeFileHeaderLocation<Foam::scalar>()
{
switch (operation_)
{
case operationType::min:
case operationType::max:
case operationType::minMag:
case operationType::maxMag:
file() << tab << "location" << tab << "cell";
if (Pstream::parRun())
{
file() << tab << "processor";
}
break;
default:
break;
}
}
void Foam::functionObjects::fieldValues::volFieldValue::writeFileHeader
(
const label i
@ -117,12 +164,54 @@ void Foam::functionObjects::fieldValues::volFieldValue::writeFileHeader
}
file() << fields_[fieldi] << ")";
if (writeLocation_)
{
#define writeFileHeaderLocationFieldType(fieldType, none) \
if (validField<fieldType>(fields_[fieldi])) \
{ \
writeFileHeaderLocation<fieldType>(); \
}
FOR_ALL_FIELD_TYPES(writeFileHeaderLocationFieldType)
#undef writeHeaderLocationFieldType
}
}
file() << endl;
}
bool Foam::functionObjects::fieldValues::volFieldValue::processValues
(
const Field<scalar>& values,
const scalarField& weights,
const scalarField& V,
Result<scalar>& result
) const
{
switch (operation_)
{
case operationType::min:
case operationType::minMag:
{
opMag(values, result, lessOp<scalar>());
return true;
}
case operationType::max:
case operationType::maxMag:
{
opMag(values, result, greaterOp<scalar>());
return true;
}
default:
{
// Fall through to same-type operations
return processValuesTypeType(values, weights, V, result);
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::fieldValues::volFieldValue::volFieldValue
@ -134,7 +223,9 @@ Foam::functionObjects::fieldValues::volFieldValue::volFieldValue
:
fieldValue(name, runTime, dict, typeName),
volRegion(fieldValue::mesh_, dict),
operation_(operationTypeNames_.read(dict.lookup("operation")))
writeLocation_(false),
operation_(operationTypeNames_.read(dict.lookup("operation"))),
scaleFactor_(1)
{
read(dict);
}
@ -149,7 +240,9 @@ Foam::functionObjects::fieldValues::volFieldValue::volFieldValue
:
fieldValue(name, obr, dict, typeName),
volRegion(fieldValue::mesh_, dict),
operation_(operationTypeNames_.read(dict.lookup("operation")))
writeLocation_(false),
operation_(operationTypeNames_.read(dict.lookup("operation"))),
scaleFactor_(1)
{
read(dict);
}
@ -186,22 +279,35 @@ bool Foam::functionObjects::fieldValues::volFieldValue::write()
writeTime(file());
}
// Construct the weight field and the volumes
scalarField weights
(
isNull(cellIDs()) ? fieldValue::mesh_.nCells() : cellIDs().size(),
1
);
forAll(weightFieldNames_, i)
{
weights *= getFieldValues<scalar>(weightFieldNames_[i]);
}
const scalarField V(filterField(fieldValue::mesh_.V()));
forAll(fields_, i)
{
const word& fieldName = fields_[i];
bool processed = false;
bool ok = false;
#define processType(fieldType, none) \
processed = processed || writeValues<fieldType>(fieldName);
FOR_ALL_FIELD_TYPES(processType)
#define writeValuesFieldType(fieldType, none) \
ok = ok || writeValues<fieldType>(fieldName, weights, V);
FOR_ALL_FIELD_TYPES(writeValuesFieldType)
#undef writeValuesFieldType
if (!processed)
if (!ok)
{
cannotFindObject(fieldName);
}
}
if (Pstream::master())
if (operation_ != operationType::none && Pstream::master())
{
file() << endl;
}

View File

@ -61,6 +61,7 @@ Usage
type | Type name: volFieldValue | yes |
log | Write data to standard output | no | no
writeFields | Write the region field values | yes |
writeLocation| Write the location (if available) | no | no
regionType | volRegion type: see below | yes |
name | Name of volRegion if required | no |
operation | Operation to perform | yes |
@ -79,16 +80,14 @@ Usage
\plaintable
none | No operation
sum | Sum
weightedSum | Weighted sum
sumMag | Sum of component magnitudes
average | Ensemble average
weightedAverage | Weighted average
volAverage | Volume weighted average
weightedVolAverage | Weighted volume average
volIntegrate | Volume integral
weightedVolIntegrate | Weighted volume integral
min | Minimum
max | Maximum
minMag | Minimum magnitude
maxMag | Maximum magnitude
CoV | Coefficient of variation: standard deviation/mean
\endplaintable
@ -136,33 +135,44 @@ public:
{
none,
sum,
weightedSum,
sumMag,
average,
weightedAverage,
volAverage,
weightedVolAverage,
volIntegrate,
weightedVolIntegrate,
min,
max,
minMag,
maxMag,
CoV
};
//- Operation type names
static const NamedEnum<operationType, 13> operationTypeNames_;
static const NamedEnum<operationType, 11> operationTypeNames_;
// Public classes
//- Forward declare the result structure
template<class Type>
struct Result;
protected:
// Protected data
//- Write the location if available for this operation - optional
Switch writeLocation_;
//- Operation to apply to values
operationType operation_;
//- Weight field names - only used for weighted modes
//- Weight field names
wordList weightFieldNames_;
//- Scale factor - optional
scalar scaleFactor_;
// Protected Member Functions
@ -175,21 +185,74 @@ protected:
//- Insert field values into values list
template<class Type>
tmp<Field<Type>> setFieldValues
(
const word& fieldName,
const bool mustGet = false
) const;
tmp<Field<Type>> getFieldValues(const word& fieldName) const;
//- Apply the 'operation' to the values
template<class Type>
Type processValues
//- Apply a comparison operation (min/max) to the field magnitude,
// returning the limiting value, its index and processor index
template<class Type, class Op>
void opMag
(
const Field<Type>& values,
const scalarField& V,
const scalarField& weightField
Result<scalar>& result,
const Op& op
) const;
//- Apply the operation to the values, and return true if successful.
// Does nothing unless overloaded below.
template<class Type, class ResultType>
bool processValues
(
const Field<Type>& values,
const scalarField& weights,
const scalarField& V,
Result<ResultType>& result
) const;
//- Apply Type -> Type operation to the values. Calls
// processValuesTypeType.
template<class Type>
bool processValues
(
const Field<Type>& values,
const scalarField& weights,
const scalarField& V,
Result<Type>& result
) const;
//- Apply Type -> scalar operation to the values
template<class Type>
bool processValues
(
const Field<Type>& values,
const scalarField& weights,
const scalarField& V,
Result<scalar>& result
) const;
//- Apply scalar -> scalar operation to the values. Calls
// processValuesTypeType.
bool processValues
(
const Field<scalar>& values,
const scalarField& weights,
const scalarField& V,
Result<scalar>& result
) const;
//- Apply a Type -> Type operation to the values
template<class Type>
bool processValuesTypeType
(
const Field<Type>& values,
const scalarField& weights,
const scalarField& V,
Result<Type>& result
) const;
//- Output file header location information for a given type
template<class Type>
void writeFileHeaderLocation();
//- Output file header information
virtual void writeFileHeader(const label i);
@ -227,7 +290,22 @@ public:
//- Templated helper function to output field values
template<class Type>
bool writeValues(const word& fieldName);
bool writeValues
(
const word& fieldName,
const scalarField& weights,
const scalarField& V
);
//- Templated helper function to output field values
template<class Type, class ResultType>
bool writeValues
(
const word& fieldName,
const Field<Type>& values,
const scalarField& weights,
const scalarField& V
);
//- Filter a field according to cellIds
template<class Type>
@ -241,6 +319,46 @@ public:
};
template<>
void volFieldValue::writeFileHeaderLocation<scalar>();
/*---------------------------------------------------------------------------*\
Class volFieldValue::Result Declaration
\*---------------------------------------------------------------------------*/
template<class Type>
struct volFieldValue::Result
{
Type value;
label celli;
label proci;
point cc;
};
template<class Type>
inline Istream& operator>>
(
Istream& is,
volFieldValue::Result<Type>& result
)
{
return is >> result.value >> result.celli >> result.proci >> result.cc;
}
template<class Type>
inline Ostream& operator<<
(
Ostream& os,
const volFieldValue::Result<Type>& result
)
{
return os << result.value << result.celli << result.proci << result.cc;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fieldValues

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2020 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -47,10 +47,9 @@ bool Foam::functionObjects::fieldValues::volFieldValue::validField
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::functionObjects::fieldValues::volFieldValue::setFieldValues
Foam::functionObjects::fieldValues::volFieldValue::getFieldValues
(
const word& fieldName,
const bool mustGet
const word& fieldName
) const
{
typedef GeometricField<Type, fvPatchField, volMesh> vf;
@ -60,83 +59,149 @@ Foam::functionObjects::fieldValues::volFieldValue::setFieldValues
return filterField(obr_.lookupObject<vf>(fieldName));
}
if (mustGet)
{
FatalErrorInFunction
<< "Field " << fieldName << " not found in database"
<< abort(FatalError);
return tmp<Field<Type>>(nullptr);
}
return tmp<Field<Type>>(new Field<Type>(0.0));
template<class Type, class Op>
void Foam::functionObjects::fieldValues::volFieldValue::opMag
(
const Field<Type>& values,
Result<scalar>& result,
const Op& op
) const
{
const scalarField magValues(mag(values));
label i = 0;
forAll(magValues, j)
{
if (op(magValues[j], magValues[i]))
{
i = j;
}
}
result.value = magValues[i];
result.celli = isNull(cellIDs()) ? i : cellIDs()[i];
result.proci = Pstream::parRun() ? Pstream::myProcNo() : -1;
result.cc = fieldValue::mesh_.C()[result.celli];
reduce
(
result,
[&op](const Result<scalar>& a, const Result<scalar>& b)
{
return op(a.value, b.value) ? a : b;
}
);
}
template<class Type, class ResultType>
bool Foam::functionObjects::fieldValues::volFieldValue::processValues
(
const Field<Type>& values,
const scalarField& weights,
const scalarField& V,
Result<ResultType>& result
) const
{
return false;
}
template<class Type>
Type Foam::functionObjects::fieldValues::volFieldValue::processValues
bool Foam::functionObjects::fieldValues::volFieldValue::processValues
(
const Field<Type>& values,
const scalarField& weights,
const scalarField& V,
const scalarField& weightField
Result<Type>& result
) const
{
return processValuesTypeType(values, weights, V, result);
}
template<class Type>
bool Foam::functionObjects::fieldValues::volFieldValue::processValues
(
const Field<Type>& values,
const scalarField& weights,
const scalarField& V,
Result<scalar>& result
) const
{
switch (operation_)
{
case operationType::minMag:
{
opMag(values, result, lessOp<scalar>());
return true;
}
case operationType::maxMag:
{
opMag(values, result, greaterOp<scalar>());
return true;
}
default:
{
return false;
}
}
}
template<class Type>
bool Foam::functionObjects::fieldValues::volFieldValue::processValuesTypeType
(
const Field<Type>& values,
const scalarField& weights,
const scalarField& V,
Result<Type>& result
) const
{
Type result = Zero;
switch (operation_)
{
case operationType::sum:
{
result = gSum(values);
break;
}
case operationType::weightedSum:
{
result = gSum(weightField*values);
break;
result.value = gSum(weights*values);
return true;
}
case operationType::sumMag:
{
result = gSum(cmptMag(values));
break;
result.value = gSum(cmptMag(values));
return true;
}
case operationType::average:
{
result = gSum(values)/nCells();
break;
}
case operationType::weightedAverage:
{
result = gSum(weightField*values)/max(gSum(weightField), vSmall);
break;
result.value = gSum(weights*values)/max(gSum(weights), vSmall);
return true;
}
case operationType::volAverage:
{
result = gSum(V*values)/this->V();
break;
}
case operationType::weightedVolAverage:
{
result =
gSum(weightField*V*values)/max(gSum(weightField*V), vSmall);
break;
result.value = gSum(weights*V*values)/max(gSum(weights*V), vSmall);
return true;
}
case operationType::volIntegrate:
{
result = gSum(V*values);
break;
}
case operationType::weightedVolIntegrate:
{
result = gSum(weightField*V*values);
break;
result.value = gSum(weights*V*values);
return true;
}
case operationType::min:
{
result = gMin(values);
break;
result.value = gMin(values);
return true;
}
case operationType::max:
{
result = gMax(values);
break;
result.value = gMax(values);
return true;
}
case operationType::CoV:
{
@ -148,18 +213,22 @@ Type Foam::functionObjects::fieldValues::volFieldValue::processValues
{
scalarField vals(values.component(d));
scalar mean = component(meanValue, d);
scalar& res = setComponent(result, d);
scalar& res = setComponent(result.value, d);
res = sqrt(gSum(V*sqr(vals - mean))/this->V())/mean;
}
break;
return true;
}
case operationType::none:
{}
{
return true;
}
default:
{
return false;
}
}
return result;
}
@ -168,36 +237,19 @@ Type Foam::functionObjects::fieldValues::volFieldValue::processValues
template<class Type>
bool Foam::functionObjects::fieldValues::volFieldValue::writeValues
(
const word& fieldName
const word& fieldName,
const scalarField& weights,
const scalarField& V
)
{
const bool ok = validField<Type>(fieldName);
if (ok)
{
Field<Type> values(setFieldValues<Type>(fieldName));
scalarField V(filterField(fieldValue::mesh_.V()));
scalarField weightField(values.size(), 1.0);
forAll(weightFieldNames_, i)
{
weightField *= setFieldValues<scalar>(weightFieldNames_[i], true);
}
Type result = processValues(values, V, weightField);
if (Pstream::master())
{
// Add to result dictionary, over-writing any previous entry
resultDict_.add(fieldName, result, true);
file()<< tab << result;
Log << " " << operationTypeNames_[operation_]
<< "(" << volRegion::regionName_ << ") of " << fieldName
<< " = " << result << endl;
}
// Get the values
Field<Type> values(getFieldValues<Type>(fieldName));
// Write raw values if specified
if (writeFields_)
{
IOField<Type>
@ -211,15 +263,98 @@ bool Foam::functionObjects::fieldValues::volFieldValue::writeValues
IOobject::NO_READ,
IOobject::NO_WRITE
),
(weightField*values).ref()
(weights*values).ref()
).write();
}
// Do the operation
if (operation_ != operationType::none)
{
// Apply scale factor
values *= scaleFactor_;
bool ok = false;
#define writeValuesFieldType(fieldType, none) \
ok = \
ok \
|| writeValues<Type, fieldType> \
( \
fieldName, \
values, \
weights, \
V \
);
FOR_ALL_FIELD_TYPES(writeValuesFieldType);
#undef writeValuesFieldType
if (!ok)
{
FatalErrorInFunction
<< "Operation " << operationTypeNames_[operation_]
<< " not available for values of type "
<< pTraits<Type>::typeName
<< exit(FatalError);
}
}
}
return ok;
}
template<class Type, class ResultType>
bool Foam::functionObjects::fieldValues::volFieldValue::writeValues
(
const word& fieldName,
const Field<Type>& values,
const scalarField& weights,
const scalarField& V
)
{
Result<ResultType> result({Zero, -1, -1, point::uniform(NaN)});
if (processValues(values, weights, V, result))
{
// Add to result dictionary, over-writing any previous entry
resultDict_.add(fieldName, result.value, true);
if (Pstream::master())
{
file() << tab << result.value;
Log << " " << operationTypeNames_[operation_]
<< "(" << volRegion::regionName_ << ") of " << fieldName
<< " = " << result.value;
if (result.celli != -1)
{
Log << " at location " << result.cc;
if (writeLocation_) file() << tab << result.cc;
}
if (result.celli != -1)
{
Log << " in cell " << result.celli;
if (writeLocation_) file() << tab << result.celli;
}
if (result.proci != -1)
{
Log << " on processor " << result.proci;
if (writeLocation_) file() << tab << result.proci;
}
Log << endl;
}
return true;
}
return false;
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::functionObjects::fieldValues::volFieldValue::filterField

View File

@ -61,7 +61,7 @@ functions
writeFields no;
regionType patch;
name outlet;
operation weightedAverage;
operation average;
weightField phi;
fields

View File

@ -56,7 +56,7 @@ functions
writeFields no;
regionType patch;
name outlet;
operation weightedAverage;
operation average;
weightField phi;
fields
(

View File

@ -57,7 +57,7 @@ functions
writeFields no;
regionType patch;
name outlet;
operation weightedAverage;
operation average;
weightField phi;
fields
(

View File

@ -82,7 +82,7 @@ functions
writeFields false;
regionType patch;
name outlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.gas;
fields ( h.gas );
}
@ -94,7 +94,7 @@ functions
writeFields false;
regionType patch;
name outlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.liquid;
fields ( h.liquid );
}
@ -106,7 +106,7 @@ functions
writeFields false;
regionType patch;
name inlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.gas;
fields ( h.gas );
}
@ -118,7 +118,7 @@ functions
writeFields false;
regionType patch;
name inlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.liquid;
fields ( h.liquid );
}

View File

@ -82,7 +82,7 @@ functions
writeFields false;
regionType patch;
name outlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.gas;
fields ( h.gas );
}
@ -94,7 +94,7 @@ functions
writeFields false;
regionType patch;
name outlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.liquid;
fields ( h.liquid );
}
@ -106,7 +106,7 @@ functions
writeFields false;
regionType patch;
name inlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.gas;
fields ( h.gas );
}
@ -118,7 +118,7 @@ functions
writeFields false;
regionType patch;
name inlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.liquid;
fields ( h.liquid );
}

View File

@ -121,7 +121,7 @@ functions
writeFields false;
regionType patch;
name outlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.gas;
fields ( h.gas );
}
@ -133,7 +133,7 @@ functions
writeFields false;
regionType patch;
name outlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.liquid;
fields ( h.liquid );
}
@ -145,7 +145,7 @@ functions
writeFields false;
regionType patch;
name inlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.gas;
fields ( h.gas );
}
@ -157,7 +157,7 @@ functions
writeFields false;
regionType patch;
name inlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.liquid;
fields ( h.liquid );
}

View File

@ -121,7 +121,7 @@ functions
writeFields false;
regionType patch;
name outlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.gas;
fields ( h.gas );
}
@ -133,7 +133,7 @@ functions
writeFields false;
regionType patch;
name outlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.gas2;
fields ( h.gas2 );
}
@ -145,7 +145,7 @@ functions
writeFields false;
regionType patch;
name outlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.liquid;
fields ( h.liquid );
}
@ -157,7 +157,7 @@ functions
writeFields false;
regionType patch;
name inlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.gas;
fields ( h.gas );
}
@ -169,7 +169,7 @@ functions
writeFields false;
regionType patch;
name inlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.gas2;
fields ( h.gas2 );
}
@ -181,7 +181,7 @@ functions
writeFields false;
regionType patch;
name inlet;
operation weightedSum;
operation sum;
weightField alphaRhoPhi.liquid;
fields ( h.liquid );
}

View File

@ -52,20 +52,8 @@ maxDeltaT 1e-2;
functions
{
minMax
{
type fieldMinMax;
functionObjectLibs ("libfieldFunctionObjects.so");
fields
(
T.steam
T.water
p
);
location no;
writeControl timeStep;
writeInterval 1;
}
#includeFunc cellMin(T.steam,T.water,p)
#includeFunc cellMax(T.steam,T.water,p)
}