42namespace functionObjects
60 { regionTypes::stFaceZone,
"faceZone" },
61 { regionTypes::stPatch,
"patch" },
62 { regionTypes::stObject,
"functionObjectSurface" },
63 { regionTypes::stSampled,
"sampledSurface" },
74 { operationType::opNone,
"none" },
75 { operationType::opMin,
"min" },
76 { operationType::opMax,
"max" },
77 { operationType::opSum,
"sum" },
78 { operationType::opSumMag,
"sumMag" },
79 { operationType::opSumDirection,
"sumDirection" },
80 { operationType::opSumDirectionBalance,
"sumDirectionBalance" },
81 { operationType::opAverage,
"average" },
82 { operationType::opAreaAverage,
"areaAverage" },
83 { operationType::opAreaIntegrate,
"areaIntegrate" },
84 { operationType::opCoV,
"CoV" },
85 { operationType::opAreaNormalAverage,
"areaNormalAverage" },
86 { operationType::opAreaNormalIntegrate,
"areaNormalIntegrate" },
87 { operationType::opUniformity,
"uniformity" },
90 { operationType::opWeightedSum,
"weightedSum" },
91 { operationType::opWeightedAverage,
"weightedAverage" },
92 { operationType::opWeightedAreaAverage,
"weightedAreaAverage" },
93 { operationType::opWeightedAreaIntegrate,
"weightedAreaIntegrate" },
94 { operationType::opWeightedUniformity,
"weightedUniformity" },
97 { operationType::opAbsWeightedSum,
"absWeightedSum" },
98 { operationType::opAbsWeightedAverage,
"absWeightedAverage" },
99 { operationType::opAbsWeightedAreaAverage,
"absWeightedAreaAverage" },
100 { operationType::opAbsWeightedAreaIntegrate,
"absWeightedAreaIntegrate" },
101 { operationType::opAbsWeightedUniformity,
"absWeightedUniformity" },
110 { postOperationType::postOpNone,
"none" },
111 { postOperationType::postOpMag,
"mag" },
112 { postOperationType::postOpSqrt,
"sqrt" },
130void Foam::functionObjects::fieldValues::surfaceFieldValue::setFaceZoneFaces()
135 mesh_.faceZones().indices(selectionNames_)
140 for (
const label zoneId : zoneIds)
142 numFaces += mesh_.faceZones()[zoneId].size();
149 << regionTypeNames_[regionType_] <<
'(' << regionName_ <<
"):" <<
nl
150 <<
" No matching face zone(s): "
152 <<
" Known face zones: "
163 << regionTypeNames_[regionType_] <<
'(' << regionName_ <<
"):" <<
nl
164 <<
" The faceZone specification: "
166 <<
" resulted in 0 faces" <<
nl
171 faceId_.resize(numFaces);
172 facePatchId_.resize(numFaces);
173 faceFlip_.resize(numFaces);
177 for (
const label zoneId : zoneIds)
179 const faceZone& fZone = mesh_.faceZones()[zoneId];
183 const label meshFacei = fZone[i];
184 const bool isFlip = fZone.flipMap()[i];
188 label facePatchId = -1;
191 if (!mesh_.isInternalFace(meshFacei))
193 facePatchId = mesh_.boundaryMesh().whichPatch(meshFacei);
194 const polyPatch& pp = mesh_.boundaryMesh()[facePatchId];
195 const auto* cpp = isA<coupledPolyPatch>(pp);
199 faceId = (cpp->owner() ? pp.whichFace(meshFacei) : -1);
201 else if (!isA<emptyPolyPatch>(pp))
203 faceId = pp.whichFace(meshFacei);
214 faceId_[numFaces] =
faceId;
215 facePatchId_[numFaces] = facePatchId;
216 faceFlip_[numFaces] = isFlip;
224 faceId_.resize(numFaces);
225 facePatchId_.resize(numFaces);
226 faceFlip_.resize(numFaces);
231void Foam::functionObjects::fieldValues::surfaceFieldValue::setPatchFaces()
241 mesh_.boundaryMesh().patchSet
248 DynamicList<label> bad;
249 for (
const label patchi : selected)
251 const polyPatch& pp = mesh_.boundaryMesh()[patchi];
253 if (isA<emptyPolyPatch>(pp))
259 numFaces += pp.size();
265 label nGood = (selected.size() - bad.size());
269 os <<
"Cannot sample an empty patch" <<
nl;
271 for (
const label patchi : bad)
274 << mesh_.boundaryMesh()[patchi].name() <<
nl;
279 os <<
"No non-empty patches selected" <<
endl
284 os <<
"Selected " << nGood <<
" non-empty patches" <<
nl;
289 for (
const label patchi : selected)
291 if (!bad.found(patchi))
307 << regionTypeNames_[regionType_] <<
'(' << regionName_ <<
"):" <<
nl
308 <<
" No matching patch name(s): "
310 <<
" Known patch names:" <<
nl
311 << mesh_.boundaryMesh().names() <<
nl
321 << regionTypeNames_[regionType_] <<
'(' << regionName_ <<
"):" <<
nl
322 <<
" The patch specification: "
324 <<
" resulted in 0 faces" <<
nl
329 faceId_.resize(numFaces);
330 facePatchId_.resize(numFaces);
331 faceFlip_.resize(numFaces);
337 const polyPatch& pp = mesh_.boundaryMesh()[patchi];
338 const label len = pp.size();
340 SubList<label>(faceId_, len, numFaces) =
identity(len);
341 SubList<label>(facePatchId_, len, numFaces) = patchi;
342 SubList<bool>(faceFlip_, len, numFaces) =
false;
349void Foam::functionObjects::fieldValues::surfaceFieldValue::combineMeshGeometry
360 const label patchi = facePatchId_[i];
363 whichFaces[i] += mesh_.boundaryMesh()[patchi].start();
369 IndirectList<face>(mesh_.faces(), std::move(whichFaces)),
379 autoPtr<globalIndex> globalPoints;
380 autoPtr<globalIndex> globalFaces;
389 uniqueMeshPointLabels,
399 faces = pp.localFaces();
400 points = pp.localPoints();
405void Foam::functionObjects::fieldValues::surfaceFieldValue::
406combineSurfaceGeometry
412 if (stObject == regionType_)
414 const polySurface&
s = dynamicCast<const polySurface>(obr());
419 const scalar mergeDim = 1
e-10*boundBox(
s.points(),
true).mag();
438 else if (sampledPtr_)
440 const sampledSurface&
s = *sampledPtr_;
445 const scalar mergeDim = 1
e-10*mesh_.bounds().mag();
468Foam::functionObjects::fieldValues::surfaceFieldValue::totalArea()
const
470 scalar totalArea = 0;
472 if (stObject == regionType_)
474 const polySurface&
s = dynamicCast<const polySurface>(obr());
476 totalArea =
gSum(
s.magSf());
478 else if (sampledPtr_)
480 totalArea =
gSum(sampledPtr_->magSf());
484 totalArea =
gSum(filterField(mesh_.magSf()));
517 sampledPtr_->update();
539 const polySurface&
s = dynamicCast<const polySurface>(obr());
556 << regionTypeNames_[regionType_] <<
'(' << regionName_ <<
"):" <<
nl
560 totalArea_ = totalArea();
562 Log <<
" total faces = " << nFaces_ <<
nl
563 <<
" total area = " << totalArea_ <<
nl
566 writeFileHeader(file());
568 needsUpdate_ =
false;
578 if (canWriteHeader() && (operation_ != opNone))
580 writeCommented(
os,
"Region type : ");
581 os << regionTypeNames_[regionType_] <<
' ' << regionName_ <<
nl;
583 writeHeaderValue(
os,
"Faces", nFaces_);
584 writeHeaderValue(
os,
"Area", totalArea_);
585 writeHeaderValue(
os,
"Scale factor", scaleFactor_);
587 if (weightFieldNames_.size())
597 writeCommented(
os,
"Time");
605 for (
const word& fieldName : fields_)
607 os <<
tab << operationTypeNames_[operation_]
608 <<
'(' << fieldName <<
')';
614 writtenHeader_ =
true;
634 case opSumDirectionBalance:
643 case opWeightedUniformity:
644 case opAbsWeightedUniformity:
646 const scalar areaTotal =
gSum(
mag(Sf));
651 if (is_weightedOp() && canWeight(weightField))
657 weightingFactor(weightField, is_magOp())
661 mean =
gSum(weight()*areaVal()) / areaTotal;
664 numer =
gSum(
mag(weight*areaVal - (mean *
mag(Sf))));
671 mean =
gSum(areaVal()) / areaTotal;
674 numer =
gSum(
mag(areaVal - (mean *
mag(Sf))));
678 const scalar ui = 1 - numer/(2*
mag(mean*areaTotal) + ROOTVSMALL);
680 return min(
max(ui, 0), 1);
686 return processSameTypeValues(values, Sf, weightField);
710 case opSumDirectionBalance:
717 case opAreaNormalAverage:
719 const scalar val =
gSum(values & Sf)/
gSum(
mag(Sf));
722 case opAreaNormalIntegrate:
724 const scalar val =
gSum(values & Sf);
729 case opWeightedUniformity:
730 case opAbsWeightedUniformity:
732 const scalar areaTotal =
gSum(
mag(Sf));
737 if (is_weightedOp() && canWeight(weightField))
743 weightingFactor(weightField, is_magOp())
747 mean =
gSum(weight()*areaVal()) / areaTotal;
750 numer =
gSum(
mag(weight*areaVal - (mean *
mag(Sf))));
757 mean =
gSum(areaVal()) / areaTotal;
760 numer =
gSum(
mag(areaVal - (mean *
mag(Sf))));
764 const scalar ui = 1 - numer/(2*
mag(mean*areaTotal) + ROOTVSMALL);
772 return processSameTypeValues(values, Sf, weightField);
790 return mag(weightField);
818 return mag(weightField);
846 return mag(weightField *
mag(Sf));
849 return (weightField *
mag(Sf));
871 const label len = weightField.
size();
874 auto& result = tresult.ref();
876 for (label facei=0; facei < len; ++facei)
879 result[facei] = (weightField[facei] & unitNormal);
884 for (scalar& val : result)
914 return mag(weightField & Sf);
917 return (weightField & Sf);
931 regionType_(regionTypeNames_.get(
"regionType",
dict)),
932 operation_(operationTypeNames_.get(
"operation",
dict)),
935 postOperationTypeNames_.getOrDefault
965 regionType_(regionTypeNames_.get(
"regionType",
dict)),
966 operation_(operationTypeNames_.get(
"operation",
dict)),
969 postOperationTypeNames_.getOrDefault
1007 needsUpdate_ =
true;
1008 writeArea_ =
dict.getOrDefault(
"writeArea",
false);
1009 weightFieldNames_.clear();
1016 facePatchId_.clear();
1018 sampledPtr_.reset(
nullptr);
1019 surfaceWriterPtr_.reset(
nullptr);
1026 regionName_.clear();
1027 selectionNames_.clear();
1030 dict.readIfPresent(
"names", selectionNames_);
1032 for (
const auto& item : selectionNames_)
1034 if (item.isLiteral())
1051 if (selectionNames_.empty())
1053 selectionNames_.resize(1);
1054 selectionNames_.first() = regionName_;
1061 if (stSampled == regionType_)
1067 dict.subDict(
"sampledSurfaceDict")
1071 sampledPtr_->isPointData(
false);
1077 if (postOperation_ != postOpNone)
1079 Info<< postOperationTypeNames_[postOperation_] <<
'('
1080 << operationTypeNames_[operation_] <<
')' <<
nl;
1084 Info<< operationTypeNames_[operation_] <<
nl;
1087 if (is_weightedOp())
1091 bool missing =
true;
1092 if (
dict.readIfPresent(
"weightFields", weightFieldNames_))
1098 weightFieldNames_.resize(1);
1100 if (
dict.readIfPresent(
"weightField", weightFieldNames_.first()))
1103 if (
"none" == weightFieldNames_.first())
1106 weightFieldNames_.clear();
1115 <<
"The '" << operationTypeNames_[operation_]
1116 <<
"' operation is missing a weightField." <<
nl
1117 <<
"Either provide the weightField, "
1118 <<
"use weightField 'none' to suppress weighting," <<
nl
1119 <<
"or use a different operation."
1123 Info<<
" weight field = ";
1124 if (weightFieldNames_.empty())
1134 if (stSampled == regionType_ && sampledPtr_)
1136 Info<<
" sampled surface: ";
1137 sampledPtr_->print(
Info, 0);
1143 const word formatName(
dict.get<
word>(
"surfaceFormat"));
1145 surfaceWriterPtr_.reset
1150 dict.subOrEmptyDict(
"formatOptions").subOrEmptyDict(formatName)
1155 surfaceWriterPtr_->nFields(fields_.size());
1159 surfaceWriterPtr_->verbose(
true);
1162 if (surfaceWriterPtr_->enabled())
1164 Info<<
" surfaceFormat = " << formatName <<
nl;
1168 surfaceWriterPtr_->clear();
1180 if (needsUpdate_ || operation_ != opNone)
1187 if (operation_ != opNone)
1189 writeCurrentTime(file());
1194 totalArea_ = totalArea();
1195 Log <<
" total area = " << totalArea_ <<
endl;
1199 file() <<
tab << totalArea_;
1207 if (stObject == regionType_)
1209 const polySurface&
s = dynamicCast<const polySurface>(obr());
1212 else if (sampledPtr_)
1214 Sf = sampledPtr_->Sf();
1218 Sf = filterField(mesh_.Sf());
1226 if (surfaceWriterPtr_)
1228 if (withTopologicalMerge())
1230 combineMeshGeometry(faces,
points);
1234 combineSurfaceGeometry(faces,
points);
1248 for (
const word& weightName : weightFieldNames_)
1250 if (validField<scalar>(weightName))
1254 if (scalarWeights.
empty())
1256 scalarWeights = tfld;
1260 scalarWeights *= tfld;
1263 else if (validField<vector>(weightName))
1267 if (vectorWeights.
empty())
1269 vectorWeights = tfld;
1274 <<
"weightField " << weightName
1275 <<
" - only one vector weight field allowed. " <<
nl
1280 else if (weightName !=
"none")
1288 <<
"weightField " << weightName
1289 <<
" not found or an unsupported type" <<
nl
1298 if (scalarWeights.
size())
1300 vectorWeights *= scalarWeights;
1303 writeAll(Sf, vectorWeights,
points, faces);
1307 writeAll(Sf, scalarWeights,
points, faces);
1311 if (operation_ != opNone)
1327 needsUpdate_ =
true;
1336 needsUpdate_ =
true;
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Generic templated field type.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
virtual bool read()
Re-read model coefficients if they have changed.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
void size(const label n)
Older name for setAddressableSize.
static bool & parRun() noexcept
Test if this a parallel run.
Vector< Cmpt > & normalise(const scalar tol=ROOTVSMALL)
Inplace normalise the vector by its magnitude.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
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...
Intermediate class for handling field value-based function objects.
word regionName_
Name of region (patch, zone, etc.)
const dictionary & dict() const noexcept
Return the reference to the construction dictionary.
virtual bool write()
Write.
A face regionType variant of the fieldValues function object.
static const Enum< regionTypes > regionTypeNames_
Region type names.
regionTypes
Region type enumeration.
@ stObject
Calculate with function object surface.
static tmp< scalarField > weightingFactor(const Field< WeightType > &weightField, const bool useMag)
Weighting factor.
bool usesSf() const noexcept
True if the operation needs a surface Sf.
const objectRegistry & obr() const
The volume mesh or surface registry being used.
postOperationType
Post-operation type enumeration.
virtual bool read(const dictionary &dict)
Read from dictionary.
bool update()
Update the surface and surface information as required.
regionTypes regionType_
Region type.
static const Enum< postOperationType > postOperationTypeNames_
Operation type names.
virtual void writeFileHeader(Ostream &os)
Output file header information.
static tmp< scalarField > areaWeightingFactor(const Field< WeightType > &weightField, const vectorField &Sf, const bool useMag)
Weighting factor, weight field with area factor.
static const Enum< operationType > operationTypeNames_
Operation type names.
virtual bool write()
Calculate and write.
Type processValues(const Field< Type > &values, const vectorField &Sf, const Field< WeightType > &weightField) const
Apply the 'operation' to the values. Wrapper around.
virtual ~surfaceFieldValue()
Destructor.
operationType
Operation type enumeration.
const fvMesh & mesh_
Reference to the fvMesh.
Computes the magnitude of an input field.
objectRegistry & storedObjects()
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
void movePoints()
Update for new mesh geometry.
void updateMesh()
Update for new mesh topology.
Registry of regIOobjects.
const Type & lookupObject(const word &name, const bool recursive=false) const
Mesh consisting of general polyhedral cells.
A surface mesh consisting of general polygon faces and capable of holding fields.
splitCell * master() const
A class for managing temporary objects.
A class for handling words, derived from Foam::string.
#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)
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 WarningInFunction
Report a warning using Foam::Warning.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Type gSum(const FieldField< Field, Type > &f)
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
dimensionedScalar pos0(const dimensionedScalar &ds)
List< label > labelList
A List of labels.
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
messageStream Info
Information stream (stdout output on master, null elsewhere)
vectorField pointField
pointField is a vectorField.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field.
Ostream & endl(Ostream &os)
Add newline and flush stream.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
dimensionedScalar neg(const dimensionedScalar &ds)
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.
List< face > faceList
A List of faces.
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)
constexpr char nl
The newline '\n' character (0x0a)
constexpr char tab
The tab '\t' character(0x09)
#define forAll(list, i)
Loop across all elements in list.
Surround with '\0' and '\0' separate with ','.