/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2015-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- 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::fieldValues::surfaceFieldValue Group grpFieldFunctionObjects Description Provides a 'face regionType' variant of the fieldValues function object. Given a list of user-specified fields and a selection of mesh (or general surface) faces, a number of operations can be performed, such as sums, 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) Usage Examples of function object specification: \verbatim movingWallPatch { type surfaceFieldValue; libs (fieldFunctionObjects); log true; writeControl writeTime; writeFields false; regionType patch; name movingWall; operation areaAverage; fields (p phi U); } surfaceFieldValue1 { type surfaceFieldValue; libs (fieldFunctionObjects); log true; writeControl writeTime; writeFields true; surfaceFormat none; regionType faceZone; name f0; operation sum; weightField alpha1; fields (p phi U); } \endverbatim Where the entries comprise: \table Property | Description | Required | Default type | Type name: surfaceFieldValue | yes | log | Write data to standard output | no | no regionType | Face regionType: see below | yes | name | Name for regionType | yes | operation | Operation to perform | yes | postOperation | Post-operation to perform | no | none fields | List of fields to operate on | yes | weightField | Name of field to apply weighting | no | scaleFactor | Output value scaling factor | no | 1 writeArea | Write the surface area | no | writeFields | Write the region field values | yes | surfaceFormat | Output value format | no | none \endtable Where \c regionType is defined by \plaintable faceZone | The \b name entry to specify the faceZone patch | The \b name entry to specify the patch functionObjectSurface | The \b name entry to specify a polySurface sampledSurface | A \b sampledSurfaceDict sub-dictionary and \b name \endplaintable The \c operation is one of: \plaintable none | no operation min | minimum max | maximum sum | sum sumMag | sum of component magnitudes sumDirection | sum values that are positive in given direction sumDirectionBalance | sum of balance of values in given direction average | ensemble average areaAverage | area-weighted average areaIntegrate | area integral CoV | coefficient of variation: standard deviation/mean areaNormalAverage | area-weighted average in face normal direction areaNormalIntegrate | area-weighted integral in face normal directon uniformity | uniformity index weightedSum | weighted sum weightedAverage | weighted average weightedAreaAverage | weighted area average weightedAreaIntegrate | weighted area integral weightedUniformity | weighted uniformity index absWeightedSum | sum using absolute weighting absWeightedAverage | average using absolute weighting absWeightedAreaAverage | area average using absolute weighting absWeightedAreaIntegrate | area integral using absolute weighting absWeightedUniformity | uniformity index using absolute weighting \endplaintable The \c postOperation is one of: \plaintable none | No additional operation after calculation mag | Component-wise \c mag() after normal operation sqrt | Component-wise \c sqrt() after normal operation \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 - Using \c functionObjectSurface: - The keyword %subRegion should not be used to select surfaces. Instead specify the regionType 'functionObjectSurface' and provide the name. - 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 Uniformity \f[ UI(\phi) = 1 - \frac{1}{2 \overline{\phi} A} \int{\left| W \phi \cdot \hat{n} - \bar{W} \bar{\phi}\right| d\vec{A}} \,,\; \bar{\phi} = \frac{\int{W \phi \cdot d\vec{A}}}{\int{W \cdot d\vec{A}}} \f] A velocity uniformity index is calculated with no weighting (W=1) and \f$ \phi = \vec{U} \f$. A scalar concentration uniformity index is calculated with either \f$ \rho \vec{U} \f$ or \f$ \vec{U} \f$ for weighting and \f$ \phi = conc \f$. See also Foam::fieldValues Foam::functionObject SourceFiles surfaceFieldValue.C surfaceFieldValueTemplates.C \*---------------------------------------------------------------------------*/ #ifndef functionObjects_surfaceFieldValue_H #define functionObjects_surfaceFieldValue_H #include "fieldValue.H" #include "Enum.H" #include "surfaceMesh.H" #include "polySurface.H" #include "fvsPatchField.H" #include "volFieldsFwd.H" #include "polySurfaceFieldsFwd.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { // Forward Declarations class sampledSurface; class surfaceWriter; namespace functionObjects { namespace fieldValues { /*---------------------------------------------------------------------------*\ Class surfaceFieldValue Declaration \*---------------------------------------------------------------------------*/ class surfaceFieldValue : public fieldValue { public: // Public Data Types //- Region type enumeration enum regionTypes { stFaceZone = 0x01, //!< Calculate on a faceZone stPatch = 0x02, //!< Calculate on a patch stObject = 0x11, //!< Calculate with function object surface stSampled = 0x12 //!< Sample onto surface and calculate }; //- Region type names static const Enum regionTypeNames_; //- Bitmask values for operation variants enum operationVariant { typeBase = 0, //!< Base operation typeScalar = 0x100, //!< Operation returns a scalar typeWeighted = 0x200, //!< Operation using weighting typeAbsolute = 0x400, //!< Operation using mag (eg, for weighting) }; //- Operation type enumeration enum operationType { // Normal operations opNone = 0, //!< No operation opMin, //!< Minimum value opMax, //!< Maximum value opSum, //!< Sum of values opSumMag, //!< Sum of component magnitudes opSumDirection, //!< Sum in a given direction //! Sum of balance of values in given direction opSumDirectionBalance, opAverage, //!< Ensemble average opAreaAverage, //!< Area average opAreaIntegrate, //!< Area integral opCoV, //!< Coefficient of variation // Scalar return values //! Area average in normal direction (output is always scalar) opAreaNormalAverage = typeScalar, //! Area integral in normal direction (output is always scalar) opAreaNormalIntegrate, //! Uniformity index (output is always scalar) opUniformity, // Weighted variants //! Weighted sum opWeightedSum = (opSum | typeWeighted), //! Weighted average opWeightedAverage = (opAverage | typeWeighted), //! Weighted area average opWeightedAreaAverage = (opAreaAverage | typeWeighted), //! Weighted area integral opWeightedAreaIntegrate = (opAreaIntegrate | typeWeighted), //! Weighted uniformity index opWeightedUniformity = (opUniformity | typeWeighted), // Variants using absolute weighting //! Sum using abs weighting opAbsWeightedSum = (opWeightedSum | typeAbsolute), //! Average using abs weighting opAbsWeightedAverage = (opWeightedAverage | typeAbsolute), //! Area average using abs weighting opAbsWeightedAreaAverage = (opWeightedAreaAverage | typeAbsolute), //! Area integral using abs weighting opAbsWeightedAreaIntegrate = (opWeightedAreaIntegrate | typeAbsolute), //! Uniformity index using abs weighting opAbsWeightedUniformity = (opWeightedUniformity | typeAbsolute), }; //- Operation type names static const Enum operationTypeNames_; //- Post-operation type enumeration enum postOperationType { postOpNone, //!< No additional operation after calculation postOpMag, //!< Component-wise mag after normal operation postOpSqrt //!< Component-wise sqrt after normal operation }; //- Operation type names static const Enum postOperationTypeNames_; private: // Private Member Functions //- Set faces to evaluate based on a face zone void setFaceZoneFaces(); //- Set faces to evaluate based on a patch void setPatchFaces(); //- Combine mesh faces and points from multiple processors void combineMeshGeometry ( faceList& faces, pointField& points ) const; //- Combine surface faces and points from multiple processors void combineSurfaceGeometry ( faceList& faces, pointField& points ) const; //- Calculate and return total area of the surfaceFieldValue: sum(magSf) scalar totalArea() const; protected: // Protected Data //- Region type regionTypes regionType_; //- Operation to apply to values operationType operation_; //- Optional post-evaluation operation postOperationType postOperation_; //- Weight field name - optional word weightFieldName_; //- Track if the surface needs an update bool needsUpdate_; //- Optionally write the area of the surfaceFieldValue bool writeArea_; //- Total area of the surfaceFieldValue scalar totalArea_; //- Global number of faces label nFaces_; // If operating on mesh faces (faceZone, patch) //- Local list of face IDs labelList faceId_; //- Local list of patch ID per face labelList facePatchId_; //- List representing the face flip map // (false: use as-is, true: negate) boolList faceFlip_; //- The sampledSurface (when operating on sampledSurface) autoPtr sampledPtr_; //- Surface writer autoPtr surfaceWriterPtr_; // Protected Member Functions //- The volume mesh or surface registry being used const objectRegistry& obr() const; //- Can the surface definition sample surface-fields? inline bool withSurfaceFields() const; //- Can use mesh topological merge? inline bool withTopologicalMerge() const; //- Return the local list of face IDs inline const labelList& faceId() const; //- Return the local list of patch ID per face inline const labelList& facePatch() const; //- Return the local true/false list representing the face flip map inline const boolList& faceFlip() const; //- True if the operation needs a surface Sf bool usesSf() const; //- True if the operation variant uses mag inline bool usesMag() const; //- True if the operation variant uses a weight-field inline bool usesWeight() const; //- True if operation variant uses a weight-field that is available. // Checks for availability on any processor. template inline bool canWeight(const Field& weightField) const; //- Update the surface and surface information as required. // Do nothing (and return false) if no update was required bool update(); //- Return true if the field name is known and a valid type template bool validField(const word& fieldName) const; //- Return field values by looking up field name template tmp> getFieldValues ( const word& fieldName, const bool mandatory = false ) const; //- Apply the 'operation' to the values. Operation must preserve Type. template Type processSameTypeValues ( const Field& values, const vectorField& Sf, const Field& weightField ) const; //- Apply the 'operation' to the values. Wrapper around // processSameTypeValues. See also template specialisation below. template Type processValues ( const Field& values, const vectorField& Sf, const Field& weightField ) const; //- Filter a surface field according to faceIds template tmp> filterField ( const GeometricField& field ) const; //- Filter a volume field according to faceIds template tmp> filterField ( const GeometricField& field ) const; //- Weighting factor. // Possibly applies mag() depending on the operation type. template tmp weightingFactor ( const Field& weightField ) const; //- Weighting factor, weight field with the area. // Possibly applies mag() depending on the operation type. // Reverts to mag(Sf) if the weight field is not available. template tmp weightingFactor ( const Field& weightField, const vectorField& Sf ) const; //- Templated helper function to output field values template label writeAll ( const vectorField& Sf, const Field& weightField, const pointField& points, const faceList& faces ); //- Templated helper function to output field values template bool writeValues ( const word& fieldName, const vectorField& Sf, const Field& weightField, const pointField& points, const faceList& faces ); //- Output file header information virtual void writeFileHeader(Ostream& os) const; public: //- Declare type-name, virtual type (with debug switch) TypeName("surfaceFieldValue"); // Constructors //- Construct from name, Time and dictionary surfaceFieldValue ( const word& name, const Time& runTime, const dictionary& dict ); //- Construct from name, objectRegistry and dictionary surfaceFieldValue ( const word& name, const objectRegistry& obr, const dictionary& dict ); //- Destructor virtual ~surfaceFieldValue() = default; // Member Functions //- Return the region type inline regionTypes regionType() const; //- Return the output directory inline fileName outputDir() const; //- Read from dictionary virtual bool read(const dictionary& dict); //- Calculate and write virtual bool write(); //- Update for changes of mesh virtual void updateMesh(const mapPolyMesh& mpm); //- Update for changes of mesh virtual void movePoints(const polyMesh& mesh); }; //- Specialisation for scalar fields template<> scalar surfaceFieldValue::processValues ( const Field& values, const vectorField& Sf, const scalarField& weightField ) const; //- Specialisation for vector fields template<> vector surfaceFieldValue::processValues ( const Field& values, const vectorField& Sf, const scalarField& weightField ) const; //- Specialisation for scalar - pass through template<> tmp surfaceFieldValue::weightingFactor ( const Field& weightField ) const; //- Specialisation for scalar - scalar * Area template<> tmp surfaceFieldValue::weightingFactor ( const Field& weightField, const vectorField& Sf ) const; //- Specialisation for vector - vector (dot) Area template<> tmp surfaceFieldValue::weightingFactor ( const Field& weightField, const vectorField& Sf ) const; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace fieldValues } // End namespace functionObjects } // End namespace Foam // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // #include "surfaceFieldValueI.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // #ifdef NoRepository #include "surfaceFieldValueTemplates.C" #endif // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // #endif // ************************************************************************* //