Loading...
Searching...
No Matches
surfaceFieldValue.H
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2017 OpenFOAM Foundation
9 Copyright (C) 2015-2023 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27Class
28 Foam::functionObjects::fieldValues::surfaceFieldValue
29
30Group
31 grpFieldFunctionObjects
32
33Description
34 A \c face regionType variant of the \c fieldValues function object.
35
36 Given a list of user-specified fields and a selection of mesh (or general
37 surface) faces, a number of operations can be performed, such as sums,
38 averages and integrations.
39
40 For example, to calculate the volumetric or mass flux across a patch,
41 apply the \c sum operator to the flux field (typically \c phi).
42
43Usage
44 A minimal example:
45 \verbatim
46 surfaceFieldValuePatchFO
47 {
48 // Mandatory entries
49 type surfaceFieldValue;
50 libs (fieldFunctionObjects);
51 fields <wordList>; // (<field1> <field2> ... <fieldN>);
52 regionType <word>;
53 operation <word>;
54
55 // Optional entries
56 postOperation <word>;
57 writeArea <bool>;
58 empty-surface <word>; // default | warn | ignore | strict
59 names (<patch-name> <patch-regex>);
60 name <patch>;
61 weightField <word>; // alpha1;
62
63 // Conditional entries
64
65 // when regionType = sampledSurface
66 sampledSurfaceDict <dict>;
67
68 // when writeFields = true
69 surfaceFormat <word>; // vtk | raw | none
70
71 // Inherited entries
72 ...
73 }
74
75 where the entries mean:
76 \table
77 Property | Description | Type | Reqd | Deflt
78 type | Type name: surfaceFieldValue | word | yes | -
79 libs | Libraries: fieldFunctionObjects | wordList | yes | -
80 regionType | Face regionType: see below | word | yes | -
81 fields | Names of operand fields | wordList | yes | -
82 name | Name of the regionType | word | yes | -
83 names | Extended selection | word/regex list | no | -
84 operation | Operation type: see below | word | yes | -
85 postOperation | Post-operation type: see below | word | no | none
86 weightField | Name of field to apply weighting | word | maybe |
87 weightFields | Names of fields to apply weighting | wordList | maybe |
88 writeArea | Write the surface area | bool | no | false
89 surfaceFormat | Output value format | word <!--
90 --> | conditional on writeFields | none
91 empty-surface | Error handling for empty surfaces | enum | no | default
92 sampledSurfaceDict | Dict defining the sampledSurface | dict | no | -
93 \endtable
94
95 The inherited entries are elaborated in:
96 - \link fieldValue.H \endlink
97
98 Options for the \c regionType entry:
99 \plaintable
100 faceZone | The \b name entry specifies a faceZone. Supports \b names
101 patch | The \b name entry specifies a patch. Supports \b names
102 functionObjectSurface | The \b name entry specifies a polySurface
103 sampledSurface | A \b sampledSurfaceDict sub-dictionary and \b name
104 \endplaintable
105
106 Options for the \c operation entry:
107 \plaintable
108 none | no operation
109 min | minimum
110 max | maximum
111 sum | sum
112 sumMag | sum of component magnitudes
113 sumDirection | sum values that are positive in given direction
114 sumDirectionBalance | sum of balance of values in given direction
115 average | ensemble average
116 areaAverage | area-weighted average
117 areaIntegrate | area integral
118 CoV | coefficient of variation: standard deviation/mean
119 areaNormalAverage | area-weighted average in face normal direction
120 areaNormalIntegrate | area-weighted integral in face normal directon
121 uniformity | uniformity index
122 weightedSum | weighted sum
123 weightedAverage | weighted average
124 weightedAreaAverage | weighted area average
125 weightedAreaIntegrate | weighted area integral
126 weightedUniformity | weighted uniformity index
127 absWeightedSum | sum using absolute weighting
128 absWeightedAverage | average using absolute weighting
129 absWeightedAreaAverage | area average using absolute weighting
130 absWeightedAreaIntegrate | area integral using absolute weighting
131 absWeightedUniformity | uniformity index using absolute weighting
132 \endplaintable
133
134 Options for the \c postOperation entry:
135 \plaintable
136 none | No additional operation after calculation
137 mag | Component-wise \c mag() after normal operation
138 sqrt | Component-wise \c sqrt() after normal operation
139 \endplaintable
140
141Note
142 - Some types (eg, patch or faceZone) support the selection of multiple
143 entries, which can be specified as list of words or regular expressions
144 by \b names entry.<br>
145 If the \b names enty exists \em and contains a literal that can be used
146 as a suitable value for \b name, the \b name entry becomes optional
147 instead of being mandatory.
148 - The values reported by the \c areaNormalAverage and \c areaNormalIntegrate
149 operations are written as the first component of a field with the same
150 rank as the input field.
151 - Faces on empty patches are ignored.
152 - Using \c functionObjectSurface:
153 - The keyword %subRegion should not be used to select surfaces.
154 Instead specify the regionType 'functionObjectSurface' and provide
155 the name.
156 - Using \c sampledSurface:
157 - surface fields only supported by some surfaces
158 - default uses sampleScheme \c cell
159 - each face in \c sampledSurface is logically only in one cell
160 so sampling will be wrong when they are larger than cells.
161 This can only happen for sampling on a \c triSurfaceMesh
162 - take care when using isoSurfaces - these might have duplicate
163 triangles and so integration might be wrong
164
165 Uniformity:
166 \f[
167 UI(\phi) = 1 - \frac{1}{2 \overline{\phi} A}
168 \int{\left| W \phi \cdot \hat{n} - \bar{W} \bar{\phi}\right| d\vec{A}}
169 \,,\;
170 \bar{\phi} = \frac{\int{W \phi \cdot d\vec{A}}}{\int{W \cdot d\vec{A}}}
171 \f]
172
173 A velocity uniformity index is calculated with no weighting (W=1) and
174 \f$ \phi = \vec{U} \f$.
175
176 A scalar concentration uniformity index is calculated with either
177 \f$ \rho \vec U \f$ or \f$ \vec U \f$ for weighting and
178 \f$ \phi = conc \f$.
179
180SourceFiles
181 surfaceFieldValue.C
182 surfaceFieldValueTemplates.C
183
184\*---------------------------------------------------------------------------*/
185
186#ifndef Foam_functionObjects_surfaceFieldValue_H
187#define Foam_functionObjects_surfaceFieldValue_H
188
189#include "fieldValue.H"
190#include "Enum.H"
191#include "surfaceMesh.H"
192#include "polySurface.H"
193#include "fvsPatchField.H"
194#include "volFieldsFwd.H"
195#include "polySurfaceFieldsFwd.H"
196
197// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
198
199namespace Foam
200{
201
202// Forward Declarations
203class sampledSurface;
204class surfaceWriter;
205
206namespace functionObjects
207{
208namespace fieldValues
209{
210
211/*---------------------------------------------------------------------------*\
212 Class surfaceFieldValue Declaration
213\*---------------------------------------------------------------------------*/
214
215class surfaceFieldValue
216:
217 public fieldValue
218{
219public:
220
221 // Public Data Types
222
223 //- Region type enumeration
224 enum regionTypes
225 {
226 stFaceZone = 0x01,
227 stPatch = 0x02,
228 stObject = 0x11,
229 stSampled = 0x12
230 };
231
232 //- Region type names
233 static const Enum<regionTypes> regionTypeNames_;
234
235 //- Operation type enumeration
236 enum operationType
237 {
238 // Normal operations
239
240 opNone = 0,
241 opMin,
242 opMax,
243 opSum,
244 opSumMag,
245 opSumDirection,
246
248 opSumDirectionBalance,
249
250 opAverage,
251 opAreaAverage,
252 opAreaIntegrate,
253 opCoV,
254
255 // Operations returning scalar - bitmask value
256 typeScalar = 0x100,
257
259 opAreaNormalAverage = (1 | typeScalar),
260
262 opAreaNormalIntegrate,
263
265 opUniformity,
266
267 // Weighted variants
268 // Operations using weighting - bitmask value
269 typeWeighted = 0x200,
270
272 opWeightedSum = (opSum | typeWeighted),
273
275 opWeightedAverage = (opAverage | typeWeighted),
276
278 opWeightedAreaAverage = (opAreaAverage | typeWeighted),
279
281 opWeightedAreaIntegrate = (opAreaIntegrate | typeWeighted),
282
284 opWeightedUniformity = (opUniformity | typeWeighted),
285
286 // Variants using absolute weighting
287 // Operation using mag (eg, for weighting) - bitmask value
288 typeAbsolute = 0x400,
289
291 opAbsWeightedSum = (opWeightedSum | typeAbsolute),
292
294 opAbsWeightedAverage = (opWeightedAverage | typeAbsolute),
295
297 opAbsWeightedAreaAverage = (opWeightedAreaAverage | typeAbsolute),
298
300 opAbsWeightedAreaIntegrate =
301 (opWeightedAreaIntegrate | typeAbsolute),
302
304 opAbsWeightedUniformity =
305 (opWeightedUniformity | typeAbsolute),
306 };
307
308 //- Operation type names
309 static const Enum<operationType> operationTypeNames_;
310
311
312 //- Post-operation type enumeration
313 enum postOperationType
314 {
315 postOpNone,
316 postOpMag,
317 postOpSqrt
318 };
319
320 //- Operation type names
321 static const Enum<postOperationType> postOperationTypeNames_;
322
323
324private:
325
326 // Private Member Functions
327
328 //- Set faces to evaluate based on a face zone
329 void setFaceZoneFaces();
330
331 //- Set faces to evaluate based on a patch
332 void setPatchFaces();
333
334 //- Combine mesh faces and points from multiple processors
335 void combineMeshGeometry
336 (
337 faceList& faces,
338 pointField& points
339 ) const;
340
341 //- Combine surface faces and points from multiple processors
342 void combineSurfaceGeometry
343 (
344 faceList& faces,
345 pointField& points
346 ) const;
347
348 //- Calculate and return total area of the surfaceFieldValue: sum(magSf)
349 scalar totalArea() const;
350
351
352protected:
353
354 // Protected Data
355
356 //- Region type
357 regionTypes regionType_;
358
359 //- Operation to apply to values
360 operationType operation_;
361
362 //- Optional post-evaluation operation
363 postOperationType postOperation_;
364
365 //- Track if the surface needs an update
366 bool needsUpdate_;
367
368 //- Optionally write the area of the surfaceFieldValue
369 bool writeArea_;
370
371 //- Handling of empty surfaces (nFaces = 0). Default is Fatal.
372 error::handlerTypes emptySurfaceError_;
373
374 //- Extended selections
375 wordRes selectionNames_;
376
377 //- Weight field name(s) - optional
378 wordList weightFieldNames_;
379
380 //- Total area of the surfaceFieldValue
381 scalar totalArea_;
382
383 //- Global number of faces
384 label nFaces_;
385
386 //- Number of warnings emitted since the last valid update
387 unsigned nWarnings_;
388
389
390 // If operating on mesh faces (faceZone, patch)
391
392 //- Local list of face IDs
393 labelList faceId_;
394
395 //- Local list of patch ID per face
396 labelList facePatchId_;
397
398 //- List representing the face flip map
399 // (false: use as-is, true: negate)
400 boolList faceFlip_;
401
402
403 // Demand-driven
404
405 //- The sampledSurface (when operating on sampledSurface)
406 autoPtr<sampledSurface> sampledPtr_;
407
408 //- Surface writer
409 autoPtr<surfaceWriter> surfaceWriterPtr_;
410
411
412 // Static Member Functions
413
414 //- Weighting factor.
415 // Possibly applies mag() depending on the operation type.
416 template<class WeightType>
417 static tmp<scalarField> weightingFactor
418 (
419 const Field<WeightType>& weightField,
420 const bool useMag
421 );
422
423 //- Weighting factor, weight field projected onto unit-normal.
424 // Possibly applies mag() depending on the operation type.
425 // Reverts to 'one' if the weight field is unavailable.
426 template<class WeightType>
427 static tmp<scalarField> weightingFactor
428 (
429 const Field<WeightType>& weightField,
430 const vectorField& Sf,
431 const bool useMag
432 );
433
434 //- Weighting factor, weight field with area factor.
435 // Possibly applies mag() depending on the operation type.
436 // Reverts to mag(Sf) if the weight field is unavailable.
437 template<class WeightType>
438 static tmp<scalarField> areaWeightingFactor
439 (
440 const Field<WeightType>& weightField,
441 const vectorField& Sf,
442 const bool useMag
443 );
444
445
446 // Protected Member Functions
447
448 //- The volume mesh or surface registry being used
449 const objectRegistry& obr() const;
450
451 //- Can the surface definition sample surface-fields?
452 inline bool withSurfaceFields() const;
453
454 //- Can use mesh topological merge?
455 inline bool withTopologicalMerge() const noexcept;
456
457 //- Return the local list of face IDs
458 inline const labelList& faceId() const noexcept;
459
460 //- Return the local list of patch ID per face
461 inline const labelList& facePatch() const noexcept;
462
463 //- Return the local true/false list representing the face flip map
464 inline const boolList& faceFlip() const noexcept;
465
466 //- True if the operation needs a surface Sf
467 bool usesSf() const noexcept;
468
469 //- True if the operation variant uses mag
470 inline bool is_magOp() const noexcept;
471
472 //- True if the operation variant uses a weight-field
473 inline bool is_weightedOp() const noexcept;
474
475 //- True if field is non-empty on any processor.
476 template<class WeightType>
477 inline bool canWeight(const Field<WeightType>& fld) const;
478
479 //- Update the surface and surface information as required.
480 // Do nothing (and return false) if no update was required
481 bool update();
482
483 //- Return true if the field name is known and a valid type
484 template<class Type>
485 bool validField(const word& fieldName) const;
486
487 //- Return field values by looking up field name
488 template<class Type>
489 tmp<Field<Type>> getFieldValues
490 (
491 const word& fieldName,
492 const bool mandatory = false
493 ) const;
494
495 //- Apply the 'operation' to the values. Operation must preserve Type.
496 template<class Type, class WeightType>
497 Type processSameTypeValues
498 (
499 const Field<Type>& values,
500 const vectorField& Sf,
501 const Field<WeightType>& weightField
502 ) const;
503
504 //- Apply the 'operation' to the values. Wrapper around
505 // processSameTypeValues. See also template specialisation below.
506 template<class Type, class WeightType>
507 Type processValues
508 (
509 const Field<Type>& values,
510 const vectorField& Sf,
511 const Field<WeightType>& weightField
512 ) const;
513
514
515 //- Filter a surface field according to faceIds
516 template<class Type>
517 tmp<Field<Type>> filterField
518 (
519 const GeometricField<Type, fvsPatchField, surfaceMesh>& field
520 ) const;
521
522 //- Filter a volume field according to faceIds
523 template<class Type>
524 tmp<Field<Type>> filterField
525 (
526 const GeometricField<Type, fvPatchField, volMesh>& field
527 ) const;
528
529 //- Templated helper function to output field values
530 template<class WeightType>
531 label writeAll
532 (
533 const vectorField& Sf,
534 const Field<WeightType>& weightField,
535 const pointField& points,
536 const faceList& faces
537 );
538
539 //- Templated helper function to output field values
540 template<class Type, class WeightType>
541 bool writeValues
542 (
543 const word& fieldName,
544 const vectorField& Sf,
545 const Field<WeightType>& weightField,
546 const pointField& points,
547 const faceList& faces
548 );
549
550
551 //- Output file header information
552 virtual void writeFileHeader(Ostream& os);
553
554
555public:
556
557 //- Declare type-name, virtual type (with debug switch)
558 TypeName("surfaceFieldValue");
559
560
561 // Constructors
562
563 //- Construct from name, Time and dictionary
564 surfaceFieldValue
565 (
566 const word& name,
567 const Time& runTime,
568 const dictionary& dict
569 );
570
571 //- Construct from name, objectRegistry and dictionary
572 surfaceFieldValue
573 (
574 const word& name,
575 const objectRegistry& obr,
576 const dictionary& dict
577 );
578
579 //- No copy construct
580 surfaceFieldValue(const surfaceFieldValue&) = delete;
581
582 //- No copy assignment
583 void operator=(const surfaceFieldValue&) = delete;
584
585
586 //- Destructor
587 virtual ~surfaceFieldValue();
588
589
590 // Member Functions
591
592 //- Return the region type
593 inline regionTypes regionType() const noexcept;
594
595 //- Return the output directory
596 inline fileName outputDir() const;
597
598 //- Read the function-object dictionary
599 virtual bool read(const dictionary& dict);
600
601 //- Write the function-object results
602 virtual bool write();
603
604 //- Update for changes of mesh
605 virtual void updateMesh(const mapPolyMesh& mpm);
606
607 //- Update for changes of mesh
608 virtual void movePoints(const polyMesh& mesh);
609};
610
611
612//- Specialisation for scalar fields
613template<>
614scalar surfaceFieldValue::processValues
615(
616 const Field<scalar>& values,
617 const vectorField& Sf,
618 const scalarField& weightField
619) const;
620
621
622//- Specialisation for vector fields
623template<>
624vector surfaceFieldValue::processValues
625(
626 const Field<vector>& values,
627 const vectorField& Sf,
628 const scalarField& weightField
629) const;
630
631
632//- Specialisation for scalar - pass through
633template<>
634tmp<scalarField> surfaceFieldValue::weightingFactor
635(
636 const Field<scalar>& weightField,
637 const bool useMag
638);
639
640//- Specialisation for scalar - pass through
641template<>
642tmp<scalarField> surfaceFieldValue::weightingFactor
643(
644 const Field<scalar>& weightField,
645 const vectorField& Sf /* unused */,
646 const bool useMag
647);
648
649//- Specialisation for scalar - scalar * Area
650template<>
651tmp<scalarField> surfaceFieldValue::areaWeightingFactor
652(
653 const Field<scalar>& weightField,
654 const vectorField& Sf,
655 const bool useMag
656);
657
658
659//- Specialisation for vector - vector (dot) unit-normal
660template<>
661tmp<scalarField> surfaceFieldValue::weightingFactor
662(
663 const Field<vector>& weightField,
664 const vectorField& Sf,
665 const bool useMag
666);
667
668//- Specialisation for vector - vector (dot) Area
669template<>
670tmp<scalarField> surfaceFieldValue::areaWeightingFactor
671(
672 const Field<vector>& weightField,
673 const vectorField& Sf,
674 const bool useMag
675);
676
677
678// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
679
680} // End namespace fieldValues
681} // End namespace functionObjects
682} // End namespace Foam
683
684// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
685
686#include "surfaceFieldValueI.H"
687
688// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
689
690#ifdef NoRepository
692#endif
693
694// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
695
696#endif
697
698// ************************************************************************* //
Info<< nl;Info<< "Write faMesh in vtk format:"<< nl;{ vtk::uindirectPatchWriter writer(aMesh.patch(), fileName(aMesh.time().globalPath()/vtkBaseFileName));writer.writeGeometry();globalIndex procAddr(aMesh.nFaces());labelList cellIDs;if(UPstream::master()) { cellIDs.resize(procAddr.totalSize());for(const labelRange &range :procAddr.ranges()) { auto slice=cellIDs.slice(range);slice=identity(range);} } writer.beginCellData(4);writer.writeProcIDs();writer.write("cellID", cellIDs);writer.write("area", aMesh.S().field());writer.write("normal", aMesh.faceAreaNormals());writer.beginPointData(1);writer.write("normal", aMesh.pointAreaNormals());Info<< " "<< writer.output().name()<< nl;}{ vtk::lineWriter writer(aMesh.points(), aMesh.edges(), fileName(aMesh.time().globalPath()/(vtkBaseFileName+"-edges")));writer.writeGeometry();writer.beginCellData(4);writer.writeProcIDs();{ Field< scalar > fld(faMeshTools::flattenEdgeField(aMesh.magLe(), true))
An abstract class for surfaces with sampling.
Base class for surface writers.
rDeltaTY field()
mesh update()
dynamicFvMesh & mesh
engineTime & runTime
OBJstream os(runTime.globalPath()/outputName)
auto & name
const pointField & points
label faceId(-1)
Function objects are OpenFOAM utilities to ease workflow configurations and enhance workflows.
Namespace for OpenFOAM.
List< word > wordList
List of word.
Definition fileName.H:60
List< label > labelList
A List of labels.
Definition List.H:62
List< bool > boolList
A List of bools.
Definition List.H:60
runTime write()
dictionary dict
#define TypeName(TypeNameString)
Declare a ClassName() with extra virtual type info.
Definition typeInfo.H:68
Forwards and collection of common volume field types.