From 056cc20f341301c9a289fd0f4db34102fff0c63f Mon Sep 17 00:00:00 2001 From: Will Bainbridge Date: Thu, 8 Jul 2021 10:51:34 +0100 Subject: [PATCH] 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. --- .../flowRate/flowRateFaceZone.cfg | 5 +- etc/caseDicts/postProcessing/minMax/faceMax | 17 - etc/caseDicts/postProcessing/minMax/faceMin | 17 - .../postProcessing/minMax/faceMin.cfg | 12 - .../postProcessing/minMax/faceMinMax.cfg | 20 -- .../postProcessing/minMax/fieldMinMax.cfg | 17 - .../postProcessing/minMax/minMaxComponents | 18 - .../minMax/minMaxComponents.cfg | 12 - .../postProcessing/minMax/minMaxMagnitude | 18 - .../includeFuncEntry/includeFuncEntry.H | 12 +- src/functionObjects/field/Make/files | 1 - .../field/fieldMinMax/fieldMinMax.C | 169 ---------- .../field/fieldMinMax/fieldMinMax.H | 209 ------------ .../field/fieldMinMax/fieldMinMaxTemplates.C | 305 ----------------- .../surfaceFieldValue/surfaceFieldValue.C | 179 +++++----- .../surfaceFieldValue/surfaceFieldValue.H | 115 +++---- .../surfaceFieldValueTemplates.C | 314 ++++++++---------- .../fieldValues/volFieldValue/volFieldValue.C | 138 +++++++- .../fieldValues/volFieldValue/volFieldValue.H | 160 +++++++-- .../volFieldValue/volFieldValueTemplates.C | 287 +++++++++++----- .../verticalChannel/system/controlDict | 2 +- .../verticalChannelLTS/system/controlDict | 2 +- .../verticalChannelSteady/system/controlDict | 2 +- .../RAS/wallBoiling/system/controlDict.orig | 8 +- .../wallBoilingIATE/system/controlDict.orig | 8 +- .../system/controlDict.orig | 8 +- .../system/controlDict.orig | 12 +- .../laminar/steamInjection/system/controlDict | 16 +- 28 files changed, 781 insertions(+), 1302 deletions(-) delete mode 100644 etc/caseDicts/postProcessing/minMax/faceMax delete mode 100644 etc/caseDicts/postProcessing/minMax/faceMin delete mode 100644 etc/caseDicts/postProcessing/minMax/faceMin.cfg delete mode 100644 etc/caseDicts/postProcessing/minMax/faceMinMax.cfg delete mode 100644 etc/caseDicts/postProcessing/minMax/fieldMinMax.cfg delete mode 100644 etc/caseDicts/postProcessing/minMax/minMaxComponents delete mode 100644 etc/caseDicts/postProcessing/minMax/minMaxComponents.cfg delete mode 100644 etc/caseDicts/postProcessing/minMax/minMaxMagnitude delete mode 100644 src/functionObjects/field/fieldMinMax/fieldMinMax.C delete mode 100644 src/functionObjects/field/fieldMinMax/fieldMinMax.H delete mode 100644 src/functionObjects/field/fieldMinMax/fieldMinMaxTemplates.C diff --git a/etc/caseDicts/postProcessing/flowRate/flowRateFaceZone.cfg b/etc/caseDicts/postProcessing/flowRate/flowRateFaceZone.cfg index bf97ae5288..e1042bab1b 100644 --- a/etc/caseDicts/postProcessing/flowRate/flowRateFaceZone.cfg +++ b/etc/caseDicts/postProcessing/flowRate/flowRateFaceZone.cfg @@ -8,8 +8,7 @@ #includeEtc "caseDicts/postProcessing/surfaceFieldValue/faceZone.cfg" -fields (); -orientedFields (phi); -operation sum; +fields (phi); +operation orientedSum; // ************************************************************************* // diff --git a/etc/caseDicts/postProcessing/minMax/faceMax b/etc/caseDicts/postProcessing/minMax/faceMax deleted file mode 100644 index 7853585663..0000000000 --- a/etc/caseDicts/postProcessing/minMax/faceMax +++ /dev/null @@ -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); - -// ************************************************************************* // diff --git a/etc/caseDicts/postProcessing/minMax/faceMin b/etc/caseDicts/postProcessing/minMax/faceMin deleted file mode 100644 index 18b3037006..0000000000 --- a/etc/caseDicts/postProcessing/minMax/faceMin +++ /dev/null @@ -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); - -// ************************************************************************* // diff --git a/etc/caseDicts/postProcessing/minMax/faceMin.cfg b/etc/caseDicts/postProcessing/minMax/faceMin.cfg deleted file mode 100644 index 655a03f6ae..0000000000 --- a/etc/caseDicts/postProcessing/minMax/faceMin.cfg +++ /dev/null @@ -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; - -// ************************************************************************* // diff --git a/etc/caseDicts/postProcessing/minMax/faceMinMax.cfg b/etc/caseDicts/postProcessing/minMax/faceMinMax.cfg deleted file mode 100644 index 7a46cadbc4..0000000000 --- a/etc/caseDicts/postProcessing/minMax/faceMinMax.cfg +++ /dev/null @@ -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; - -// ************************************************************************* // diff --git a/etc/caseDicts/postProcessing/minMax/fieldMinMax.cfg b/etc/caseDicts/postProcessing/minMax/fieldMinMax.cfg deleted file mode 100644 index 32c2dc9a2b..0000000000 --- a/etc/caseDicts/postProcessing/minMax/fieldMinMax.cfg +++ /dev/null @@ -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; - -// ************************************************************************* // diff --git a/etc/caseDicts/postProcessing/minMax/minMaxComponents b/etc/caseDicts/postProcessing/minMax/minMaxComponents deleted file mode 100644 index c9a740b675..0000000000 --- a/etc/caseDicts/postProcessing/minMax/minMaxComponents +++ /dev/null @@ -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); - -// ************************************************************************* // diff --git a/etc/caseDicts/postProcessing/minMax/minMaxComponents.cfg b/etc/caseDicts/postProcessing/minMax/minMaxComponents.cfg deleted file mode 100644 index 0ff18c233e..0000000000 --- a/etc/caseDicts/postProcessing/minMax/minMaxComponents.cfg +++ /dev/null @@ -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; - -// ************************************************************************* // diff --git a/etc/caseDicts/postProcessing/minMax/minMaxMagnitude b/etc/caseDicts/postProcessing/minMax/minMaxMagnitude deleted file mode 100644 index 7878b1489b..0000000000 --- a/etc/caseDicts/postProcessing/minMax/minMaxMagnitude +++ /dev/null @@ -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); - -// ************************************************************************* // diff --git a/src/OpenFOAM/db/dictionary/functionEntries/includeFuncEntry/includeFuncEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/includeFuncEntry/includeFuncEntry.H index fb4b5ec552..dcf4652736 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/includeFuncEntry/includeFuncEntry.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/includeFuncEntry/includeFuncEntry.H @@ -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 diff --git a/src/functionObjects/field/Make/files b/src/functionObjects/field/Make/files index 603111a869..69f939e24a 100644 --- a/src/functionObjects/field/Make/files +++ b/src/functionObjects/field/Make/files @@ -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 diff --git a/src/functionObjects/field/fieldMinMax/fieldMinMax.C b/src/functionObjects/field/fieldMinMax/fieldMinMax.C deleted file mode 100644 index d31fca1f53..0000000000 --- a/src/functionObjects/field/fieldMinMax/fieldMinMax.C +++ /dev/null @@ -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 . - -\*---------------------------------------------------------------------------*/ - -#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("location", true); - - mode_ = modeTypeNames_[dict.lookupOrDefault("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(fieldSet_[fieldi], modeType::cmpt); - calcMinMaxFields(fieldSet_[fieldi], mode_); - calcMinMaxFields(fieldSet_[fieldi], mode_); - calcMinMaxFields(fieldSet_[fieldi], mode_); - calcMinMaxFields(fieldSet_[fieldi], mode_); - } - - if (Pstream::master() && !location_) file() << endl; - Log << endl; - - return true; -} - - - -// ************************************************************************* // diff --git a/src/functionObjects/field/fieldMinMax/fieldMinMax.H b/src/functionObjects/field/fieldMinMax/fieldMinMax.H deleted file mode 100644 index 4e454316dd..0000000000 --- a/src/functionObjects/field/fieldMinMax/fieldMinMax.H +++ /dev/null @@ -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 . - -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 \/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 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 - 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 - 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 - -// ************************************************************************* // diff --git a/src/functionObjects/field/fieldMinMax/fieldMinMaxTemplates.C b/src/functionObjects/field/fieldMinMax/fieldMinMaxTemplates.C deleted file mode 100644 index bbb07f6a7a..0000000000 --- a/src/functionObjects/field/fieldMinMax/fieldMinMaxTemplates.C +++ /dev/null @@ -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 . - -\*---------------------------------------------------------------------------*/ - -#include "fieldMinMax.H" -#include "volFields.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -template -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 -void Foam::functionObjects::fieldMinMax::calcMinMaxFields -( - const word& fieldName, - const modeType& mode -) -{ - typedef GeometricField fieldType; - - if (obr_.foundObject(fieldName)) - { - const label proci = Pstream::myProcNo(); - - const fieldType& field = obr_.lookupObject(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 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 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 minVs(Pstream::nProcs()); - labelList minCells(Pstream::nProcs()); - List minCs(Pstream::nProcs()); - label minProci = findMin(field); - minVs[proci] = field[minProci]; - minCells[proci] = minProci; - minCs[proci] = mesh_.C()[minProci]; - - List maxVs(Pstream::nProcs()); - labelList maxCells(Pstream::nProcs()); - List maxCs(Pstream::nProcs()); - label maxProci = findMax(field); - maxVs[proci] = field[maxProci]; - maxCells[proci] = maxProci; - maxCs[proci] = mesh_.C()[maxProci]; - - forAll(fieldBoundary, patchi) - { - const Field& 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); - } - } - } -} - - -// ************************************************************************* // diff --git a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C index 3c2e8ebb1c..066d235952 100644 --- a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C +++ b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C @@ -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; - - 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); - } + Info<< name() << " " << operationTypeNames_[operation_] + << " weight fields " << weightFieldNames_; } - else if (dict.readIfPresent("weightField", weightFieldName_)) + else if (dict.found("weightField")) { - Info<< " weightField = " << weightFieldName_ << nl; + weightFieldNames_.setSize(1); + dict.lookup("weightField") >> weightFieldNames_[0]; - if (regionType_ == regionTypes::sampledSurface) - { - FatalIOErrorInFunction(dict) - << "Cannot use weightField for a sampledSurface" - << exit(FatalIOError); - } - } - - List 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& 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& 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& 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("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("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") + // Construct the sign and weight fields and the surface normals + const scalarField signs + ( + regionType_ == regionTypes::sampledSurface + ? scalarField(surfacePtr_().Sf().size(), 1) + : List(faceSign_) + ); + scalarField weights(signs.size(), 1); + forAll(weightFieldNames_, i) { - weightField = - getFieldValues - ( - weightFieldName_, - true, - orientWeightField_ - ); + weights *= getFieldValues(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(fieldName, weightField, orient); - ok = ok || writeValues(fieldName, weightField, orient); - ok = ok || writeValues(fieldName, weightField, orient); - ok = ok || writeValues(fieldName, weightField, orient); - ok = ok || writeValues(fieldName, weightField, orient); + #define writeValuesFieldType(fieldType, none) \ + ok = \ + ok \ + || writeValues \ + ( \ + fieldName, \ + signs, \ + weights, \ + Sf \ + ); + FOR_ALL_FIELD_TYPES(writeValuesFieldType); + #undef writeValuesFieldType if (!ok) { diff --git a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H index 8f7f9c64c7..9d74556dfb 100644 --- a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H +++ b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H @@ -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 + areaNormalAverage | area weighted average in face normal direction + 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 operationTypeNames_; + static const NamedEnum 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 - tmp> getFieldValues - ( - const word& fieldName, - const bool mustGet = false, - const bool applyOrientation = false - ) const; + tmp> 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& 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& values, + const scalarField& signs, + const scalarField& weights, const vectorField& Sf, - const scalarField& weightField, Type& result ) const; + //- Apply Type -> scalar operation to the values + template + bool processValues + ( + const Field& 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& 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& 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& 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& 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& values, + const scalarField& signs, + const scalarField& weights, const vectorField& Sf ); @@ -468,16 +471,14 @@ public: template tmp> filterField ( - const GeometricField& field, - const bool applyOrientation + const GeometricField& field ) const; //- Filter a volume field according to faceIds template tmp> filterField ( - const GeometricField& field, - const bool applyOrientation + const GeometricField& field ) const; //- Read from dictionary diff --git a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValueTemplates.C b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValueTemplates.C index 365428da15..843ac7f006 100644 --- a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValueTemplates.C +++ b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValueTemplates.C @@ -62,42 +62,29 @@ template Foam::tmp> Foam::functionObjects::fieldValues::surfaceFieldValue::getFieldValues ( - const word& fieldName, - const bool mustGet, - const bool applyOrientation + const word& fieldName ) const { - typedef GeometricField sf; typedef GeometricField vf; + typedef GeometricField sf; - if - ( - regionType_ != regionTypes::sampledSurface - && obr_.foundObject(fieldName) - ) + if (regionType_ == regionTypes::sampledSurface) { - return filterField(obr_.lookupObject(fieldName), applyOrientation); - } - else if (obr_.foundObject(fieldName)) - { - const vf& fld = obr_.lookupObject(fieldName); - - if (surfacePtr_.valid()) + if (obr_.foundObject(fieldName)) { + const vf& fld = obr_.lookupObject(fieldName); + if (surfacePtr_().interpolate()) { + // Interpolate the field to the surface points const interpolationCellPoint interp(fld); tmp> tintFld(surfacePtr_().interpolate(interp)); const Field& intFld = tintFld(); - // Average + // Average the interpolated field onto the surface faces const faceList& faces = surfacePtr_().faces(); - tmp> tavg - ( - new Field(faces.size(), Zero) - ); + tmp> tavg(new Field(faces.size(), Zero)); Field& 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 + else if (obr_.foundObject(fieldName)) { - return filterField(fld, applyOrientation); + FatalErrorInFunction + << "Surface field " << fieldName + << " cannot be sampled onto surface " << surfacePtr_().name() + << ". Only vol fields can be sampled onto surfaces." + << abort(FatalError); + } + } + else + { + if (obr_.foundObject(fieldName)) + { + const vf& fld = obr_.lookupObject(fieldName); + return filterField(fld); + } + else if (obr_.foundObject(fieldName)) + { + const sf& fld = obr_.lookupObject(fieldName); + return filterField(fld); } } - if (mustGet) - { - FatalErrorInFunction - << "Field " << fieldName << " not found in database" - << abort(FatalError); - } + FatalErrorInFunction + << "Field " << fieldName << " not found in database" + << abort(FatalError); - return tmp>(new Field(0)); + return tmp>(nullptr); } @@ -136,8 +137,9 @@ template bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues ( const Field& values, + const scalarField& signs, + const scalarField& weights, const vectorField& Sf, - const scalarField& weightField, ResultType& result ) const { @@ -149,12 +151,43 @@ template bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues ( const Field& 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 +bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues +( + const Field& 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& 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(); - } + result = + 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); - } + result = + 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::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 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(fieldName); if (ok) { - Field values(getFieldValues(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 values(getFieldValues(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 writeValues(weights*values); + combineFields(writeValues); + if (Pstream::master()) { surfaceWriterPtr_->write @@ -352,39 +326,41 @@ 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()) + bool ok = false; + + #define writeValuesFieldType(fieldType, none) \ + ok = \ + ok \ + || writeValues \ + ( \ + fieldName, \ + values, \ + signs, \ + weights, \ + Sf \ + ); + FOR_ALL_FIELD_TYPES(writeValuesFieldType); + #undef writeValuesFieldType + + if (!ok) { - if - ( - !writeValues - (fieldName, weightField, values, Sf) - && !writeValues - (fieldName, weightField, values, Sf) - && !writeValues - (fieldName, weightField, values, Sf) - && !writeValues - (fieldName, weightField, values, Sf) - && !writeValues - (fieldName, weightField, values, Sf) - ) - { - FatalErrorInFunction - << "Operation " << operationTypeNames_[operation_] - << " not available for values of type " - << pTraits::typeName - << exit(FatalError); - } + FatalErrorInFunction + << "Operation " << operationTypeNames_[operation_] + << " not available for values of type " + << pTraits::typeName + << exit(FatalError); } } } @@ -397,23 +373,27 @@ template bool Foam::functionObjects::fieldValues::surfaceFieldValue::writeValues ( const word& fieldName, - const scalarField& weightField, const Field& 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); - file() << tab << result; + if (Pstream::master()) + { + file() << tab << result; - Log << " " << operationTypeNames_[operation_] - << "(" << regionName_ << ") of " << fieldName - << " = " << result << endl; + Log << " " << operationTypeNames_[operation_] + << "(" << regionName_ << ") of " << fieldName + << " = " << result << endl; + } return true; } @@ -426,8 +406,7 @@ template Foam::tmp> Foam::functionObjects::fieldValues::surfaceFieldValue::filterField ( - const GeometricField& field, - const bool applyOrientation + const GeometricField& field ) const { tmp> tvalues(new Field(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 Foam::tmp> Foam::functionObjects::fieldValues::surfaceFieldValue::filterField ( - const GeometricField& field, - const bool applyOrientation + const GeometricField& field ) const { tmp> tvalues(new Field(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; } diff --git a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.C b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.C index c1b7cfac3f..030219b40d 100644 --- a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.C +++ b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.C @@ -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("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 +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() +{ + 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(fields_[fieldi])) \ + { \ + writeFileHeaderLocation(); \ + } + FOR_ALL_FIELD_TYPES(writeFileHeaderLocationFieldType) + #undef writeHeaderLocationFieldType + } } file() << endl; } +bool Foam::functionObjects::fieldValues::volFieldValue::processValues +( + const Field& values, + const scalarField& weights, + const scalarField& V, + Result& result +) const +{ + switch (operation_) + { + case operationType::min: + case operationType::minMag: + { + opMag(values, result, lessOp()); + return true; + } + case operationType::max: + case operationType::maxMag: + { + opMag(values, result, greaterOp()); + 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,24 +279,37 @@ 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(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(fieldName); - FOR_ALL_FIELD_TYPES(processType) + #define writeValuesFieldType(fieldType, none) \ + ok = ok || writeValues(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; + file() << endl; } Log << endl; diff --git a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.H b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.H index b7c4688bbe..c55c111856 100644 --- a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.H +++ b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.H @@ -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 operationTypeNames_; + static const NamedEnum operationTypeNames_; + + + // Public classes + + //- Forward declare the result structure + template + 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 - tmp> setFieldValues - ( - const word& fieldName, - const bool mustGet = false - ) const; + tmp> getFieldValues(const word& fieldName) const; - //- Apply the 'operation' to the values - template - Type processValues + //- Apply a comparison operation (min/max) to the field magnitude, + // returning the limiting value, its index and processor index + template + void opMag ( const Field& values, - const scalarField& V, - const scalarField& weightField + Result& result, + const Op& op ) const; + //- Apply the operation to the values, and return true if successful. + // Does nothing unless overloaded below. + template + bool processValues + ( + const Field& values, + const scalarField& weights, + const scalarField& V, + Result& result + ) const; + + //- Apply Type -> Type operation to the values. Calls + // processValuesTypeType. + template + bool processValues + ( + const Field& values, + const scalarField& weights, + const scalarField& V, + Result& result + ) const; + + //- Apply Type -> scalar operation to the values + template + bool processValues + ( + const Field& values, + const scalarField& weights, + const scalarField& V, + Result& result + ) const; + + //- Apply scalar -> scalar operation to the values. Calls + // processValuesTypeType. + bool processValues + ( + const Field& values, + const scalarField& weights, + const scalarField& V, + Result& result + ) const; + + //- Apply a Type -> Type operation to the values + template + bool processValuesTypeType + ( + const Field& values, + const scalarField& weights, + const scalarField& V, + Result& result + ) const; + + //- Output file header location information for a given type + template + 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 - bool writeValues(const word& fieldName); + bool writeValues + ( + const word& fieldName, + const scalarField& weights, + const scalarField& V + ); + + //- Templated helper function to output field values + template + bool writeValues + ( + const word& fieldName, + const Field& values, + const scalarField& weights, + const scalarField& V + ); //- Filter a field according to cellIds template @@ -241,6 +319,46 @@ public: }; +template<> +void volFieldValue::writeFileHeaderLocation(); + + +/*---------------------------------------------------------------------------*\ + Class volFieldValue::Result Declaration +\*---------------------------------------------------------------------------*/ + +template +struct volFieldValue::Result +{ + Type value; + label celli; + label proci; + point cc; +}; + + +template +inline Istream& operator>> +( + Istream& is, + volFieldValue::Result& result +) +{ + return is >> result.value >> result.celli >> result.proci >> result.cc; +} + + +template +inline Ostream& operator<< +( + Ostream& os, + const volFieldValue::Result& result +) +{ + return os << result.value << result.celli << result.proci << result.cc; +} + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace fieldValues diff --git a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValueTemplates.C b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValueTemplates.C index e45094a6a7..c3488a3d69 100644 --- a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValueTemplates.C +++ b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValueTemplates.C @@ -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 Foam::tmp> -Foam::functionObjects::fieldValues::volFieldValue::setFieldValues +Foam::functionObjects::fieldValues::volFieldValue::getFieldValues ( - const word& fieldName, - const bool mustGet + const word& fieldName ) const { typedef GeometricField vf; @@ -60,83 +59,149 @@ Foam::functionObjects::fieldValues::volFieldValue::setFieldValues return filterField(obr_.lookupObject(fieldName)); } - if (mustGet) + FatalErrorInFunction + << "Field " << fieldName << " not found in database" + << abort(FatalError); + + return tmp>(nullptr); +} + + +template +void Foam::functionObjects::fieldValues::volFieldValue::opMag +( + const Field& values, + Result& result, + const Op& op +) const +{ + const scalarField magValues(mag(values)); + + label i = 0; + forAll(magValues, j) { - FatalErrorInFunction - << "Field " << fieldName << " not found in database" - << abort(FatalError); + if (op(magValues[j], magValues[i])) + { + i = j; + } } - return tmp>(new Field(0.0)); + 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& a, const Result& b) + { + return op(a.value, b.value) ? a : b; + } + ); +} + + +template +bool Foam::functionObjects::fieldValues::volFieldValue::processValues +( + const Field& values, + const scalarField& weights, + const scalarField& V, + Result& result +) const +{ + return false; } template -Type Foam::functionObjects::fieldValues::volFieldValue::processValues +bool Foam::functionObjects::fieldValues::volFieldValue::processValues ( const Field& values, + const scalarField& weights, const scalarField& V, - const scalarField& weightField + Result& result +) const +{ + return processValuesTypeType(values, weights, V, result); +} + + +template +bool Foam::functionObjects::fieldValues::volFieldValue::processValues +( + const Field& values, + const scalarField& weights, + const scalarField& V, + Result& result +) const +{ + switch (operation_) + { + case operationType::minMag: + { + opMag(values, result, lessOp()); + return true; + } + case operationType::maxMag: + { + opMag(values, result, greaterOp()); + return true; + } + default: + { + return false; + } + } +} + + +template +bool Foam::functionObjects::fieldValues::volFieldValue::processValuesTypeType +( + const Field& values, + const scalarField& weights, + const scalarField& V, + Result& 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 bool Foam::functionObjects::fieldValues::volFieldValue::writeValues ( - const word& fieldName + const word& fieldName, + const scalarField& weights, + const scalarField& V ) { const bool ok = validField(fieldName); if (ok) { - Field values(setFieldValues(fieldName)); - scalarField V(filterField(fieldValue::mesh_.V())); - scalarField weightField(values.size(), 1.0); - - forAll(weightFieldNames_, i) - { - weightField *= setFieldValues(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 values(getFieldValues(fieldName)); + // Write raw values if specified if (writeFields_) { IOField @@ -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 \ + ( \ + fieldName, \ + values, \ + weights, \ + V \ + ); + FOR_ALL_FIELD_TYPES(writeValuesFieldType); + #undef writeValuesFieldType + + if (!ok) + { + FatalErrorInFunction + << "Operation " << operationTypeNames_[operation_] + << " not available for values of type " + << pTraits::typeName + << exit(FatalError); + } + } } return ok; } +template +bool Foam::functionObjects::fieldValues::volFieldValue::writeValues +( + const word& fieldName, + const Field& values, + const scalarField& weights, + const scalarField& V +) +{ + Result 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 Foam::tmp> Foam::functionObjects::fieldValues::volFieldValue::filterField diff --git a/tutorials/combustion/reactingFoam/Lagrangian/verticalChannel/system/controlDict b/tutorials/combustion/reactingFoam/Lagrangian/verticalChannel/system/controlDict index 28227b237c..3614ab47a7 100644 --- a/tutorials/combustion/reactingFoam/Lagrangian/verticalChannel/system/controlDict +++ b/tutorials/combustion/reactingFoam/Lagrangian/verticalChannel/system/controlDict @@ -61,7 +61,7 @@ functions writeFields no; regionType patch; name outlet; - operation weightedAverage; + operation average; weightField phi; fields diff --git a/tutorials/combustion/reactingFoam/Lagrangian/verticalChannelLTS/system/controlDict b/tutorials/combustion/reactingFoam/Lagrangian/verticalChannelLTS/system/controlDict index e01be16367..eac100c93f 100644 --- a/tutorials/combustion/reactingFoam/Lagrangian/verticalChannelLTS/system/controlDict +++ b/tutorials/combustion/reactingFoam/Lagrangian/verticalChannelLTS/system/controlDict @@ -56,7 +56,7 @@ functions writeFields no; regionType patch; name outlet; - operation weightedAverage; + operation average; weightField phi; fields ( diff --git a/tutorials/combustion/reactingFoam/Lagrangian/verticalChannelSteady/system/controlDict b/tutorials/combustion/reactingFoam/Lagrangian/verticalChannelSteady/system/controlDict index a2d74b8fda..a7b2a3287d 100644 --- a/tutorials/combustion/reactingFoam/Lagrangian/verticalChannelSteady/system/controlDict +++ b/tutorials/combustion/reactingFoam/Lagrangian/verticalChannelSteady/system/controlDict @@ -57,7 +57,7 @@ functions writeFields no; regionType patch; name outlet; - operation weightedAverage; + operation average; weightField phi; fields ( diff --git a/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoiling/system/controlDict.orig b/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoiling/system/controlDict.orig index 329d0afcd9..5860578930 100644 --- a/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoiling/system/controlDict.orig +++ b/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoiling/system/controlDict.orig @@ -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 ); } diff --git a/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoilingIATE/system/controlDict.orig b/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoilingIATE/system/controlDict.orig index fed019172b..1b5e3ce561 100644 --- a/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoilingIATE/system/controlDict.orig +++ b/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoilingIATE/system/controlDict.orig @@ -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 ); } diff --git a/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoilingPolydisperse/system/controlDict.orig b/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoilingPolydisperse/system/controlDict.orig index 69ffcf3ce6..4e40d83b8c 100644 --- a/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoilingPolydisperse/system/controlDict.orig +++ b/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoilingPolydisperse/system/controlDict.orig @@ -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 ); } diff --git a/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoilingPolydisperseTwoGroups/system/controlDict.orig b/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoilingPolydisperseTwoGroups/system/controlDict.orig index fc635cdfaa..d8f23c6f1b 100644 --- a/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoilingPolydisperseTwoGroups/system/controlDict.orig +++ b/tutorials/multiphase/multiphaseEulerFoam/RAS/wallBoilingPolydisperseTwoGroups/system/controlDict.orig @@ -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 ); } diff --git a/tutorials/multiphase/multiphaseEulerFoam/laminar/steamInjection/system/controlDict b/tutorials/multiphase/multiphaseEulerFoam/laminar/steamInjection/system/controlDict index 0d6499ccae..092bf02bc6 100644 --- a/tutorials/multiphase/multiphaseEulerFoam/laminar/steamInjection/system/controlDict +++ b/tutorials/multiphase/multiphaseEulerFoam/laminar/steamInjection/system/controlDict @@ -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) }