Go to the documentation of this file.
46 namespace functionObjects
59 { modeType::mdFaceZone ,
"faceZone" },
60 { modeType::mdFaceZoneAndDirection,
"faceZoneAndDirection" },
61 { modeType::mdCellZoneAndDirection,
"cellZoneAndDirection" },
62 { modeType::mdSurface,
"functionObjectSurface" },
63 { modeType::mdSurface,
"surface" },
64 { modeType::mdSurfaceAndDirection,
"surfaceAndDirection" },
97 <<
"Unsupported flux field " << fieldName <<
" with dimensions "
99 <<
". Expected either mass flow or volumetric flow rate."
108 const word& surfName,
120 <<
"Unable to find surface " << surfName
121 <<
". Valid surfaces: "
134 const word& surfName,
147 <<
"Unable to find surface " << surfName
148 <<
". Valid surfaces: "
153 const auto&
s = *surfptr;
154 const vector refDir = dir/(
mag(dir) + ROOTVSMALL);
160 boolList& flips = faceFlip[faceFlip.size()-1];
166 const vector&
n =
s.faceNormals()[i];
168 if ((
n & refDir) > tolerance_)
182 const word& faceZoneName,
190 label zonei = mesh_.faceZones().findZoneID(faceZoneName);
194 <<
"Unable to find faceZone " << faceZoneName
196 << mesh_.faceZones().sortedNames() <<
nl
199 const faceZone& fZone = mesh_.faceZones()[zonei];
210 label facei = fZone[i];
211 const bool isFlip = fZone.
flipMap()[i];
214 label facePatchID = -1;
215 if (mesh_.isInternalFace(facei))
222 facePatchID = mesh_.boundaryMesh().whichPatch(facei);
224 const auto* cpp = isA<coupledPolyPatch>(pp);
228 faceID = (cpp->owner() ? pp.
whichFace(facei) : -1);
230 else if (!isA<emptyPolyPatch>(pp))
244 flips.append(isFlip);
245 faceIDs.append(faceID);
246 facePatchIDs.append(facePatchID);
252 facePatchID.
append(facePatchIDs);
259 const word& faceZoneName,
268 const vector refDir = dir/(
mag(dir) + ROOTVSMALL);
270 label zonei = mesh_.faceZones().findZoneID(faceZoneName);
274 <<
"Unable to find faceZone " << faceZoneName
276 << mesh_.faceZones().sortedNames() <<
nl
279 const faceZone& fZone = mesh_.faceZones()[zonei];
295 label facei = fZone[i];
298 label facePatchID = -1;
299 if (mesh_.isInternalFace(facei))
306 facePatchID = mesh_.boundaryMesh().whichPatch(facei);
308 const auto* cpp = isA<coupledPolyPatch>(pp);
312 faceID = (cpp->owner() ? pp.
whichFace(facei) : -1);
314 else if (!isA<emptyPolyPatch>(pp))
328 if (facePatchID != -1)
330 n = Sf.boundaryField()[facePatchID][faceID]
335 n = Sf[faceID]/(magSf[faceID] + ROOTVSMALL);
338 if ((
n & refDir) > tolerance_)
347 faceIDs.append(faceID);
348 facePatchIDs.append(facePatchID);
354 facePatchID.
append(facePatchIDs);
361 const word& cellZoneName,
370 const vector refDir = dir/(
mag(dir) + ROOTVSMALL);
372 const label cellZonei = mesh_.cellZones().findZoneID(cellZoneName);
376 <<
"Unable to find cellZone " << cellZoneName
378 << mesh_.cellZones().sortedNames() <<
nl
382 const label nInternalFaces = mesh_.nInternalFaces();
386 const labelList& cellIDs = mesh_.cellZones()[cellZonei];
388 labelList nbrFaceCellAddr(mesh_.nFaces() - nInternalFaces, -1);
398 label facei = pp.
start() + i;
399 label nbrFacei = facei - nInternalFaces;
400 label own = mesh_.faceOwner()[facei];
401 nbrFaceCellAddr[nbrFacei] = cellAddr[own];
416 for (label facei = 0; facei < nInternalFaces; facei++)
418 const label own = cellAddr[mesh_.faceOwner()[facei]];
419 const label nbr = cellAddr[mesh_.faceNeighbour()[facei]];
421 if (((own != -1) && (nbr == -1)) || ((own == -1) && (nbr != -1)))
423 vector n = mesh_.faces()[facei].unitNormal(mesh_.points());
425 if ((
n & refDir) > tolerance_)
428 faceLocalPatchIDs.append(facei);
429 facePatchIDs.append(-1);
432 else if ((
n & -refDir) > tolerance_)
435 faceLocalPatchIDs.append(facei);
436 facePatchIDs.append(-1);
449 const label facei = pp.
start() + localFacei;
450 const label own = cellAddr[mesh_.faceOwner()[facei]];
451 const label nbr = nbrFaceCellAddr[facei - nInternalFaces];
453 if ((own != -1) && (nbr == -1))
455 vector n = mesh_.faces()[facei].unitNormal(mesh_.points());
457 if ((
n & refDir) > tolerance_)
460 faceLocalPatchIDs.append(localFacei);
461 facePatchIDs.append(patchi);
464 else if ((
n & -refDir) > tolerance_)
467 faceLocalPatchIDs.append(localFacei);
468 facePatchIDs.append(patchi);
486 os.write(faces, mesh_.points(),
false);
497 <<
"initialiseCellZoneAndDirection: "
498 <<
"Starting walk to split patch into faceZones"
507 bool dummyData{
false};
515 for (; oldFaceID <
patch.size(); oldFaceID++)
517 if (!allFaceInfo[oldFaceID].valid<bool>(dummyData))
519 seedFacei = globalFaces.toGlobal(oldFaceID);
530 if (globalFaces.isLocal(seedFacei))
532 const label localFacei = globalFaces.toLocal(seedFacei);
535 for (
const label edgei : fEdges)
537 if (allEdgeInfo[edgei].valid<bool>(dummyData))
540 <<
"Problem in edge face wave: attempted to assign a "
541 <<
"value to an edge that has already been visited. "
542 <<
"Edge info: " << allEdgeInfo[edgei]
546 changedEdges.
append(edgei);
577 forAll(allFaceInfo, facei)
579 if (allFaceInfo[facei].
data() == regioni)
585 Info<<
"*** region:" << regioni
594 const label nRegion = regioni;
601 <<
"Region split failed" <<
nl
610 forAll(allFaceInfo, facei)
612 regioni = allFaceInfo[facei].data();
614 regionFaceIDs[regioni].
append(faceLocalPatchIDs[facei]);
615 regionFacePatchIDs[regioni].
append(facePatchIDs[facei]);
616 regionFaceFlips[regioni].
append(flips[facei]);
620 forAll(regionFaceIDs, regioni)
622 const word zoneName = cellZoneName +
":faceZone" +
Foam::name(regioni);
625 faceID.
append(regionFaceIDs[regioni]);
626 facePatchID.
append(regionFacePatchIDs[regioni]);
627 faceFlip.
append(regionFaceFlips[regioni]);
632 OBJstream os(mesh_.time().path()/zoneName +
".obj");
633 faceList faces(mesh_.faces(), regionFaceIDs[regioni]);
634 os.write(faces, mesh_.points(),
false);
641 <<
" Created " << faceID.size()
642 <<
" separate face zones from cell zone " << cellZoneName <<
nl;
648 << nFaces <<
" faces" <<
nl;
666 storedObjects().lookupObject<
polySurface>(zoneNames_[idx]);
668 sumMagSf =
sum(
s.magSf());
675 const labelList& facePatchIDs = facePatchID_[idx];
679 label facei = faceIDs[i];
681 if (facePatchIDs[i] == -1)
683 sumMagSf += magSf[facei];
687 label patchi = facePatchIDs[i];
699 for (
const word& surfName : zoneNames_)
702 storedObjects().lookupObject<
polySurface>(surfName);
707 << checkFlowType(
phi.dimensions(),
phi.name()) <<
" write:" <<
nl;
714 storedObjects().lookupObject<
polySurface>(zoneNames_[surfi]);
718 checkFlowType(
phi.dimensions(),
phi.name());
720 const boolList& flips = faceFlip_[surfi];
730 scalar phif =
phis[i];
749 phiPos *= scaleFactor_;
750 phiNeg *= scaleFactor_;
752 scalar netFlux = phiPos + phiNeg;
753 scalar absoluteFlux = phiPos - phiNeg;
755 Log <<
" surface " << zoneNames_[surfi] <<
':' <<
nl
756 <<
" positive : " << phiPos <<
nl
757 <<
" negative : " << phiNeg <<
nl
758 <<
" net : " << netFlux <<
nl
759 <<
" absolute : " << absoluteFlux
812 case mdFaceZoneAndDirection:
816 initialiseFaceZoneAndDirection
819 zoneDirections_[zonei],
829 case mdCellZoneAndDirection:
833 initialiseCellZoneAndDirection
836 zoneDirections_[zonei],
860 case mdSurfaceAndDirection:
864 initialiseSurfaceAndDirection
867 zoneDirections_[zonei],
879 zoneNames_.transfer(faceZoneName);
880 faceID_.transfer(faceID);
881 facePatchID_.transfer(facePatchID);
882 faceFlip_.transfer(faceFlips);
890 const word& zoneName = zoneNames_[zonei];
891 areas[zonei] = totalArea(zonei);
895 Info<<
" Surface: " << zoneName
896 <<
", area: " << areas[zonei] <<
nl;
900 Info<<
" Zone: " << zoneName
901 <<
", area: " << areas[zonei] <<
nl;
908 filePtrs_.resize(zoneNames_.size());
912 const word& zoneName = zoneNames_[zonei];
913 filePtrs_.set(zonei, createFile(zoneName));
926 needsUpdate_ =
false;
967 mode_ = modeTypeNames_.get(
"mode",
dict);
968 phiName_ =
dict.getOrDefault<
word>(
"phi",
"phi");
969 scaleFactor_ =
dict.getOrDefault<scalar>(
"scaleFactor", 1);
970 tolerance_ =
dict.getOrDefault<scalar>(
"tolerance", 0.8);
973 zoneDirections_.clear();
981 dict.readEntry(
"faceZones", zoneNames_);
984 case mdFaceZoneAndDirection:
986 dict.readEntry(
"faceZoneAndDirection", nameAndDirection);
989 case mdCellZoneAndDirection:
991 dict.readEntry(
"cellZoneAndDirection", nameAndDirection);
996 dict.readEntry(
"surfaces", zoneNames_);
999 case mdSurfaceAndDirection:
1001 dict.readEntry(
"surfaceAndDirection", nameAndDirection);
1007 <<
"unhandled enumeration " << modeTypeNames_[mode_]
1014 if (nameAndDirection.size())
1016 zoneNames_.resize(nameAndDirection.size());
1017 zoneDirections_.resize(nameAndDirection.size());
1023 zoneNames_[zonei] = nameDirn.first();
1024 zoneDirections_[zonei] = nameDirn.second();
1028 nameAndDirection.clear();
1033 << modeTypeNames_[mode_] <<
") with selection:\n "
1036 return !zoneNames_.empty();
1042 const word& zoneName,
1049 if (isSurfaceMode())
1051 writeHeaderValue(
os,
"Surface", zoneName);
1055 writeHeaderValue(
os,
"Face zone", zoneName);
1057 writeHeaderValue(
os,
"Total area",
area);
1061 case mdFaceZoneAndDirection:
1062 case mdCellZoneAndDirection:
1063 case mdSurfaceAndDirection:
1065 writeHeaderValue(
os,
"Reference direction", refDir);
1072 writeHeaderValue(
os,
"Scale factor", scaleFactor_);
1074 writeCommented(
os,
"Time");
1075 os <<
tab <<
"positive"
1076 <<
tab <<
"negative"
1078 <<
tab <<
"absolute"
1093 if (isSurfaceMode())
1095 return surfaceModeWrite();
1101 << checkFlowType(
phi.dimensions(),
phi.name()) <<
" write:" <<
nl;
1103 forAll(zoneNames_, zonei)
1105 const labelList& faceID = faceID_[zonei];
1106 const labelList& facePatchID = facePatchID_[zonei];
1107 const boolList& faceFlips = faceFlip_[zonei];
1115 label facei = faceID[i];
1116 label patchi = facePatchID[i];
1120 phif =
phi.boundaryField()[patchi][facei];
1145 phiPos *= scaleFactor_;
1146 phiNeg *= scaleFactor_;
1148 scalar netFlux = phiPos + phiNeg;
1149 scalar absoluteFlux = phiPos - phiNeg;
1151 Log <<
" faceZone " << zoneNames_[zonei] <<
':' <<
nl
1152 <<
" positive : " << phiPos <<
nl
1153 <<
" negative : " << phiNeg <<
nl
1154 <<
" net : " << netFlux <<
nl
1155 <<
" absolute : " << absoluteFlux
int debug
Static debugging option.
void initialiseCellZoneAndDirection(const word &cellZoneName, const vector &refDir, DynamicList< word > &names, DynamicList< vector > &dir, DynamicList< labelList > &faceID, DynamicList< labelList > &facePatchID, DynamicList< boolList > &faceFlip) const
Initialise face set from cell zone and direction.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
A class for handling words, derived from Foam::string.
void initialiseFaceZoneAndDirection(const word &faceZoneName, const vector &refDir, DynamicList< word > &names, DynamicList< vector > &dir, DynamicList< labelList > &faceID, DynamicList< labelList > &facePatchID, DynamicList< boolList > &faceFlip) const
Initialise face set from face zone and direction.
const boolList & flipMap() const noexcept
Return face flip map.
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
OFstream that keeps track of vertices.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
A class for managing temporary objects.
static constexpr const zero Zero
Global zero (0)
bool surfaceModeWrite()
Specialized write for surfaces.
bool isSurfaceMode() const
Check if surface mode instead of zone mode.
Wave propagation of information along patch. Every iteration information goes through one layer of fa...
bool read(const char *buf, int32_t &val)
Same as readInt32.
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
A functionObject surface.
List< bool > boolList
A List of bools.
void append(const T &val)
Append an element at the end of the list.
Ostream & endl(Ostream &os)
Add newline and flush stream.
word checkFlowType(const dimensionSet &fieldDims, const word &fieldName) const
Check flowType (mass or volume)
static void writeHeader(Ostream &os, const word &fieldName)
Dimension set for the base types, which can be used to implement rigorous dimension checking for alge...
Set of directions for each cell in the mesh. Either uniform and size=1 or one set of directions per c...
Specialization of Foam::functionObject for an Foam::fvMesh, providing a reference to the Foam::fvMesh...
virtual bool execute()
Execute, currently does nothing.
scalar totalArea(const label idx) const
Calculate the total area for the surface or derived faceZone.
static const Enum< modeType > modeTypeNames_
Face mode names.
#define forAll(list, i)
Loop across all elements in list.
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
virtual bool read(const dictionary &dict)
Read.
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
A surface mesh consisting of general polygon faces and capable of holding fields.
virtual void writeFileHeader(const word &zoneName, const scalar area, const vector &refDir, Ostream &os) const
Output file header information.
const dimensionSet dimArea(sqr(dimLength))
const polyBoundaryMesh & boundaryMesh() const
Return boundaryMesh reference.
A subset of mesh faces organised as a primitive patch.
messageStream Info
Information stream (stdout output on master, null elsewhere)
A patch is a list of labels that address the faces in the global face list.
fluxSummary(const word &name, const Time &runTime, const dictionary &dict)
Construct from Time and dictionary.
void setSize(const label n)
Alias for resize()
void initialiseSurface(const word &surfName, DynamicList< word > &names, DynamicList< vector > &dir, DynamicList< boolList > &faceFlip) const
Initialise for given surface name.
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
void initialiseFaceZone(const word &faceZoneName, DynamicList< word > &names, DynamicList< vector > &dir, DynamicList< labelList > &faceID, DynamicList< labelList > &facePatchID, DynamicList< boolList > &faceFlip) const
Initialise face set from face zone.
A List with indirect addressing.
For use with PatchEdgeFaceWave. Determines topological distance to starting edges....
A surface with prescribed direction.
modeType mode_
Mode for face determination/to generate faces to test.
virtual bool write()
Write the fluxSummary.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
virtual bool read(const dictionary &dict)
Read optional controls.
OBJstream os(runTime.globalPath()/outputName)
void initialiseSurfaceAndDirection(const word &surfName, const vector &refDir, DynamicList< word > &names, DynamicList< vector > &dir, DynamicList< boolList > &faceFlip) const
Initialise for given surface name and direction.
Macros for easy insertion into run-time selection tables.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0)
errorManip< error > abort(error &err)
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
label start() const
Return start label of this patch in the polyMesh face list.
errorManipArg< error, int > exit(error &err, const int errNo=1)
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
#define DebugInfo
Report an information message using Foam::Info.
label whichFace(const label l) const
Return label of face in patch from global face label.
const Type * cfindObject(const word &name, const bool recursive=false) const
Return const pointer to the object of the given Type.
addToRunTimeSelectionTable(functionObject, ObukhovLength, dictionary)
const std::string patch
OpenFOAM patch number as a std::string.
virtual bool read(const dictionary &dict)
Read the field fluxSummary data.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
labelList identity(const label len, label start=0)
Create identity map of the given length with (map[i] == i)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
defineTypeNameAndDebug(ObukhovLength, 0)
static const word null
An empty word.
const wordList area
Standard area field types (scalar, vector, tensor, etc)
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Computes the natural logarithm of an input volScalarField.
Base class for writing single files from the function objects.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
const dimensionSet dimVolume(pow3(dimLength))
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
bool update()
Initialise - after read(), before write()
#define WarningInFunction
Report a warning using Foam::Warning.
Database for solution data, solver performance and other reduced data.
edgeScalarField phis(IOobject("phis", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::NO_WRITE), linearEdgeInterpolate(Us) &aMesh.Le())
const Boundary & boundaryField() const
Return const-reference to the boundary field.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
A list of faces which address into the list of points.
UIndirectList< label > labelUIndList
UIndirectList of labels.