46namespace 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);
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];
201 names.
append(faceZoneName);
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))
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];
281 names.
append(faceZoneName);
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)
335 n = Sf[faceID]/(magSf[faceID] + ROOTVSMALL);
338 if ((
n & refDir) > tolerance_)
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();
388 labelList nbrFaceCellAddr(mesh_.nBoundaryFaces(), -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);
432 else if ((
n & -refDir) > tolerance_)
435 faceLocalPatchIDs.
append(facei);
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);
533 const labelList& fEdges = patch.faceEdges()[localFacei];
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;
647 Info<<
" " << names[i] <<
": "
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
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
void append(const T &val)
Copy append an element to the end of this list.
label capacity() const noexcept
Size of the underlying storage.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
const Boundary & boundaryField() const
Return const-reference to the boundary field.
A List with indirect addressing.
void setSize(const label n)
Alias for resize()
void append(const T &val)
Append an element at the end of the list.
OFstream that keeps track of vertices.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Wave propagation of information along patch. Every iteration information goes through one layer of fa...
A list of faces which address into the list of points.
virtual bool read()
Re-read model coefficients if they have changed.
The TAB Method for Numerical Calculation of Spray Droplet Breakup.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
T * data() noexcept
Return pointer to the underlying array serving as data storage.
void size(const label n)
Older name for setAddressableSize.
Database for solution data, solver performance and other reduced data.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
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...
For use with PatchEdgeFaceWave. Determines topological distance to starting edges....
A subset of mesh faces organised as a primitive patch.
const boolList & flipMap() const noexcept
Return face flip map.
Abstract base-class for Time/database function objects.
Watches for presence of the named trigger file in the case directory and signals a simulation stop (o...
Computes the volumetric- or mass-flux information across selections of face zones.
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.
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.
modeType mode_
Mode for face determination/to generate faces to test.
static const Enum< modeType > modeTypeNames_
Face mode names.
scalar totalArea(const label idx) const
Calculate the total area for the surface or derived faceZone.
virtual void writeFileHeader(const word &zoneName, const scalar area, const vector &refDir, Ostream &os) const
Output file header information.
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.
virtual bool read(const dictionary &dict)
Read the field fluxSummary data.
void initialiseSurface(const word &surfName, DynamicList< word > &names, DynamicList< vector > &dir, DynamicList< boolList > &faceFlip) const
Initialise for given surface name.
word checkFlowType(const dimensionSet &fieldDims, const word &fieldName) const
Check flowType (mass or volume)
bool isSurfaceMode() const
Check if surface mode instead of zone mode.
@ mdSurface
A functionObject surface.
@ mdSurfaceAndDirection
A surface with prescribed direction.
bool update()
Initialise - after read(), before write()
virtual bool execute()
Execute, currently does nothing.
virtual bool write()
Write the fluxSummary.
bool surfaceModeWrite()
Specialized write for surfaces.
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.
Specialization of Foam::functionObject for an Foam::fvMesh, providing a reference to the Foam::fvMesh...
Computes the natural logarithm of an input volScalarField.
Computes the magnitude of an input field.
Base class for writing single files from the function objects.
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
label toGlobal(const label i) const
From local to global index.
label toLocal(const label i) const
From global to local on current processor.
bool isLocal(const label i) const
Is on local processor.
const Type * cfindObject(const word &name, const bool recursive=false) const
Return const pointer to the object of the given Type.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
A patch is a list of labels that address the faces in the global face list.
label whichFace(const label l) const
Return label of face in patch from global face label.
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
label start() const
Return start label of this patch in the polyMesh face list.
const polyBoundaryMesh & boundaryMesh() const
Return boundaryMesh reference.
A surface mesh consisting of general polygon faces and capable of holding fields.
A class for managing temporary objects.
A class for handling words, derived from Foam::string.
static const word null
An empty word.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
OBJstream os(runTime.globalPath()/outputName)
const labelList nFaces(UPstream::listGatherValues< label >(aMesh.nFaces()))
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))
#define DebugInfo
Report an information message using Foam::Info.
#define WarningInFunction
Report a warning using Foam::Warning.
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
const dimensionSet dimArea(sqr(dimLength))
static void writeHeader(Ostream &os, const word &fieldName)
messageStream Info
Information stream (stdout output on master, null elsewhere)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Ostream & endl(Ostream &os)
Add newline and flush stream.
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
List< bool > boolList
A List of bools.
static constexpr const zero Zero
Global zero (0)
const dimensionSet dimVolume(pow3(dimLength))
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field.
errorManipArg< error, int > exit(error &err, const int errNo=1)
UIndirectList< label > labelUIndList
UIndirectList of labels.
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0)
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
constexpr char nl
The newline '\n' character (0x0a)
constexpr char tab
The tab '\t' character(0x09)
Fields (face and point) for polySurface.
edgeScalarField phis(IOobject("phis", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::NO_WRITE), linearEdgeInterpolate(Us) &aMesh.Le())
#define forAll(list, i)
Loop across all elements in list.