43 namespace functionObjects
61 { regionTypes::stFaceZone,
"faceZone" },
62 { regionTypes::stPatch,
"patch" },
63 { regionTypes::stObject,
"functionObjectSurface" },
64 { regionTypes::stSampled,
"sampledSurface" },
75 { operationType::opNone,
"none" },
76 { operationType::opMin,
"min" },
77 { operationType::opMax,
"max" },
78 { operationType::opSum,
"sum" },
79 { operationType::opSumMag,
"sumMag" },
80 { operationType::opSumDirection,
"sumDirection" },
81 { operationType::opSumDirectionBalance,
"sumDirectionBalance" },
82 { operationType::opAverage,
"average" },
83 { operationType::opAreaAverage,
"areaAverage" },
84 { operationType::opAreaIntegrate,
"areaIntegrate" },
85 { operationType::opCoV,
"CoV" },
86 { operationType::opAreaNormalAverage,
"areaNormalAverage" },
87 { operationType::opAreaNormalIntegrate,
"areaNormalIntegrate" },
88 { operationType::opUniformity,
"uniformity" },
91 { operationType::opWeightedSum,
"weightedSum" },
92 { operationType::opWeightedAverage,
"weightedAverage" },
93 { operationType::opWeightedAreaAverage,
"weightedAreaAverage" },
94 { operationType::opWeightedAreaIntegrate,
"weightedAreaIntegrate" },
95 { operationType::opWeightedUniformity,
"weightedUniformity" },
98 { operationType::opAbsWeightedSum,
"absWeightedSum" },
99 { operationType::opAbsWeightedAverage,
"absWeightedAverage" },
100 { operationType::opAbsWeightedAreaAverage,
"absWeightedAreaAverage" },
101 { operationType::opAbsWeightedAreaIntegrate,
"absWeightedAreaIntegrate" },
102 { operationType::opAbsWeightedUniformity,
"absWeightedUniformity" },
111 { postOperationType::postOpNone,
"none" },
112 { postOperationType::postOpMag,
"mag" },
113 { postOperationType::postOpSqrt,
"sqrt" },
131 void Foam::functionObjects::fieldValues::surfaceFieldValue::setFaceZoneFaces()
136 mesh_.faceZones().indices(selectionNames_)
141 for (
const label zoneId : zoneIds)
143 numFaces += mesh_.faceZones()[zoneId].size();
150 << regionTypeNames_[regionType_] <<
'(' << regionName_ <<
"):" <<
nl
151 <<
" No matching face zone(s): "
153 <<
" Known face zones: "
164 << regionTypeNames_[regionType_] <<
'(' << regionName_ <<
"):" <<
nl
165 <<
" The faceZone specification: "
167 <<
" resulted in 0 faces" <<
nl
172 faceId_.resize(numFaces);
173 facePatchId_.resize(numFaces);
174 faceFlip_.resize(numFaces);
178 for (
const label zoneId : zoneIds)
180 const faceZone& fZone = mesh_.faceZones()[zoneId];
184 const label meshFacei = fZone[i];
185 const bool isFlip = fZone.flipMap()[i];
189 label facePatchId = -1;
192 if (!mesh_.isInternalFace(meshFacei))
194 facePatchId = mesh_.boundaryMesh().whichPatch(meshFacei);
195 const polyPatch& pp = mesh_.boundaryMesh()[facePatchId];
196 const auto* cpp = isA<coupledPolyPatch>(pp);
200 faceId = (cpp->owner() ? pp.whichFace(meshFacei) : -1);
202 else if (!isA<emptyPolyPatch>(pp))
204 faceId = pp.whichFace(meshFacei);
215 faceId_[numFaces] =
faceId;
216 facePatchId_[numFaces] = facePatchId;
217 faceFlip_[numFaces] = isFlip;
225 faceId_.resize(numFaces);
226 facePatchId_.resize(numFaces);
227 faceFlip_.resize(numFaces);
232 void Foam::functionObjects::fieldValues::surfaceFieldValue::setPatchFaces()
242 mesh_.boundaryMesh().patchSet
249 DynamicList<label> bad;
250 for (
const label patchi : selected)
252 const polyPatch& pp = mesh_.boundaryMesh()[patchi];
254 if (isA<emptyPolyPatch>(pp))
260 numFaces += pp.size();
266 label nGood = (selected.size() - bad.size());
270 os <<
"Cannot sample an empty patch" <<
nl;
272 for (
const label patchi : bad)
275 << mesh_.boundaryMesh()[patchi].name() <<
nl;
280 os <<
"No non-empty patches selected" <<
endl
285 os <<
"Selected " << nGood <<
" non-empty patches" <<
nl;
290 for (
const label patchi : selected)
292 if (!bad.found(patchi))
308 << regionTypeNames_[regionType_] <<
'(' << regionName_ <<
"):" <<
nl
309 <<
" No matching patch name(s): "
311 <<
" Known patch names:" <<
nl
312 << mesh_.boundaryMesh().names() <<
nl
322 << regionTypeNames_[regionType_] <<
'(' << regionName_ <<
"):" <<
nl
323 <<
" The patch specification: "
325 <<
" resulted in 0 faces" <<
nl
330 faceId_.resize(numFaces);
331 facePatchId_.resize(numFaces);
332 faceFlip_.resize(numFaces);
338 const polyPatch& pp = mesh_.boundaryMesh()[patchi];
339 const label len = pp.size();
341 SubList<label>(faceId_, len, numFaces) =
identity(len);
342 SubList<label>(facePatchId_, len, numFaces) = patchi;
343 SubList<bool>(faceFlip_, len, numFaces) =
false;
350 void Foam::functionObjects::fieldValues::surfaceFieldValue::combineMeshGeometry
360 IndirectList<face> selectedFaces(mesh_.faces(),
labelList(faceId_));
361 labelList& meshFaceIds = selectedFaces.addressing();
365 const label patchi = facePatchId_[i];
368 meshFaceIds[i] += mesh_.boundaryMesh()[patchi].start();
387 nFaces += allFaces[proci].size();
391 faces.resize(nFaces);
401 faces[nFaces++] = offsetOp<face>()(
f,
nPoints);
418 for (
const face&
f : allFaces[proci])
420 faces[nFaces++] = offsetOp<face>()(
f,
nPoints);
446 <<
" down to " << newPoints.size() <<
" points" <<
endl;
449 points.transfer(newPoints);
450 for (face&
f : faces)
458 void Foam::functionObjects::fieldValues::surfaceFieldValue::
459 combineSurfaceGeometry
465 if (stObject == regionType_)
467 const polySurface&
s = dynamicCast<const polySurface>(obr());
472 const scalar mergeDim = 1
e-10*boundBox(
s.points(),
true).mag();
491 else if (sampledPtr_)
493 const sampledSurface&
s = *sampledPtr_;
498 const scalar mergeDim = 1
e-10*mesh_.bounds().mag();
521 Foam::functionObjects::fieldValues::surfaceFieldValue::totalArea()
const
523 scalar totalArea = 0;
525 if (stObject == regionType_)
527 const polySurface&
s = dynamicCast<const polySurface>(obr());
529 totalArea =
gSum(
s.magSf());
531 else if (sampledPtr_)
533 totalArea =
gSum(sampledPtr_->magSf());
537 totalArea =
gSum(filterField(mesh_.magSf()));
570 sampledPtr_->update();
592 const polySurface&
s = dynamicCast<const polySurface>(obr());
598 nFaces_ =
returnReduce(sampledPtr_->faces().size(), sumOp<label>());
609 << regionTypeNames_[regionType_] <<
'(' << regionName_ <<
"):" <<
nl
613 totalArea_ = totalArea();
615 Log <<
" total faces = " << nFaces_ <<
nl
616 <<
" total area = " << totalArea_ <<
nl
619 writeFileHeader(file());
621 needsUpdate_ =
false;
631 if (canWriteHeader() && (operation_ != opNone))
633 writeCommented(
os,
"Region type : ");
634 os << regionTypeNames_[regionType_] <<
' ' << regionName_ <<
nl;
636 writeHeaderValue(
os,
"Faces", nFaces_);
637 writeHeaderValue(
os,
"Area", totalArea_);
638 writeHeaderValue(
os,
"Scale factor", scaleFactor_);
640 if (weightFieldNames_.size())
650 writeCommented(
os,
"Time");
658 for (
const word& fieldName : fields_)
660 os <<
tab << operationTypeNames_[operation_]
661 <<
'(' << fieldName <<
')';
667 writtenHeader_ =
true;
687 case opSumDirectionBalance:
696 case opWeightedUniformity:
697 case opAbsWeightedUniformity:
699 const scalar areaTotal =
gSum(
mag(Sf));
704 if (is_weightedOp() && canWeight(weightField))
710 weightingFactor(weightField, is_magOp())
714 mean =
gSum(weight()*areaVal()) / areaTotal;
717 numer =
gSum(
mag(weight*areaVal - (mean *
mag(Sf))));
724 mean =
gSum(areaVal()) / areaTotal;
727 numer =
gSum(
mag(areaVal - (mean *
mag(Sf))));
731 const scalar ui = 1 - numer/(2*
mag(mean*areaTotal) + ROOTVSMALL);
733 return min(
max(ui, 0), 1);
739 return processSameTypeValues(
values, Sf, weightField);
763 case opSumDirectionBalance:
770 case opAreaNormalAverage:
775 case opAreaNormalIntegrate:
782 case opWeightedUniformity:
783 case opAbsWeightedUniformity:
785 const scalar areaTotal =
gSum(
mag(Sf));
786 tmp<scalarField> areaVal(
values & Sf);
790 if (is_weightedOp() && canWeight(weightField))
794 tmp<scalarField> weight
796 weightingFactor(weightField, is_magOp())
800 mean =
gSum(weight()*areaVal()) / areaTotal;
803 numer =
gSum(
mag(weight*areaVal - (mean *
mag(Sf))));
810 mean =
gSum(areaVal()) / areaTotal;
813 numer =
gSum(
mag(areaVal - (mean *
mag(Sf))));
817 const scalar ui = 1 - numer/(2*
mag(mean*areaTotal) + ROOTVSMALL);
825 return processSameTypeValues(
values, Sf, weightField);
843 return mag(weightField);
871 return mag(weightField);
899 return mag(weightField *
mag(Sf));
902 return (weightField *
mag(Sf));
924 const label len = weightField.size();
927 auto& result = tresult.ref();
929 for (label facei=0; facei < len; ++facei)
932 result[facei] = (weightField[facei] & unitNormal);
937 for (scalar& val : result)
967 return mag(weightField & Sf);
970 return (weightField & Sf);
984 regionType_(regionTypeNames_.
get(
"regionType",
dict)),
985 operation_(operationTypeNames_.
get(
"operation",
dict)),
988 postOperationTypeNames_.getOrDefault
992 postOperationType::postOpNone,
1018 regionType_(regionTypeNames_.
get(
"regionType",
dict)),
1019 operation_(operationTypeNames_.
get(
"operation",
dict)),
1022 postOperationTypeNames_.getOrDefault
1026 postOperationType::postOpNone,
1033 weightFieldNames_(),
1060 needsUpdate_ =
true;
1061 writeArea_ =
dict.getOrDefault(
"writeArea",
false);
1062 weightFieldNames_.clear();
1069 facePatchId_.clear();
1071 sampledPtr_.reset(
nullptr);
1072 surfaceWriterPtr_.reset(
nullptr);
1079 regionName_.clear();
1080 selectionNames_.clear();
1083 dict.readIfPresent(
"names", selectionNames_);
1085 for (
const auto& item : selectionNames_)
1087 if (item.isLiteral())
1104 if (selectionNames_.empty())
1106 selectionNames_.resize(1);
1107 selectionNames_.first() = regionName_;
1114 if (stSampled == regionType_)
1120 dict.subDict(
"sampledSurfaceDict")
1124 sampledPtr_->isPointData(
false);
1130 if (postOperation_ != postOpNone)
1132 Info<< postOperationTypeNames_[postOperation_] <<
'('
1133 << operationTypeNames_[operation_] <<
')' <<
nl;
1137 Info<< operationTypeNames_[operation_] <<
nl;
1140 if (is_weightedOp())
1144 bool missing =
true;
1145 if (
dict.readIfPresent(
"weightFields", weightFieldNames_))
1151 weightFieldNames_.resize(1);
1153 if (
dict.readIfPresent(
"weightField", weightFieldNames_.first()))
1156 if (
"none" == weightFieldNames_.first())
1159 weightFieldNames_.clear();
1168 <<
"The '" << operationTypeNames_[operation_]
1169 <<
"' operation is missing a weightField." <<
nl
1170 <<
"Either provide the weightField, "
1171 <<
"use weightField 'none' to suppress weighting," <<
nl
1172 <<
"or use a different operation."
1176 Info<<
" weight field = ";
1177 if (weightFieldNames_.empty())
1187 if (stSampled == regionType_ && sampledPtr_)
1189 Info<<
" sampled surface: ";
1190 sampledPtr_->print(
Info, 0);
1196 const word formatName(
dict.get<word>(
"surfaceFormat"));
1198 surfaceWriterPtr_.reset
1203 dict.subOrEmptyDict(
"formatOptions").subOrEmptyDict(formatName)
1208 surfaceWriterPtr_->nFields(fields_.size());
1212 surfaceWriterPtr_->verbose(
true);
1215 if (surfaceWriterPtr_->enabled())
1217 Info<<
" surfaceFormat = " << formatName <<
nl;
1221 surfaceWriterPtr_->clear();
1233 if (needsUpdate_ || operation_ != opNone)
1240 if (operation_ != opNone)
1242 writeCurrentTime(file());
1247 totalArea_ = totalArea();
1248 Log <<
" total area = " << totalArea_ <<
endl;
1252 file() <<
tab << totalArea_;
1260 if (stObject == regionType_)
1262 const polySurface&
s = dynamicCast<const polySurface>(obr());
1265 else if (sampledPtr_)
1267 Sf = sampledPtr_->Sf();
1271 Sf = filterField(mesh_.Sf());
1279 if (surfaceWriterPtr_)
1281 if (withTopologicalMerge())
1283 combineMeshGeometry(faces,
points);
1287 combineSurfaceGeometry(faces,
points);
1301 for (
const word& weightName : weightFieldNames_)
1303 if (validField<scalar>(weightName))
1305 tmp<scalarField> tfld = getFieldValues<scalar>(weightName,
true);
1307 if (scalarWeights.empty())
1309 scalarWeights = tfld;
1313 scalarWeights *= tfld;
1316 else if (validField<vector>(weightName))
1318 tmp<vectorField> tfld = getFieldValues<vector>(weightName,
true);
1320 if (vectorWeights.empty())
1322 vectorWeights = tfld;
1327 <<
"weightField " << weightName
1328 <<
" - only one vector weight field allowed. " <<
nl
1333 else if (weightName !=
"none")
1341 <<
"weightField " << weightName
1342 <<
" not found or an unsupported type" <<
nl
1349 if (
returnReduce(!vectorWeights.empty(), orOp<bool>()))
1351 if (scalarWeights.size())
1353 vectorWeights *= scalarWeights;
1356 writeAll(Sf, vectorWeights,
points, faces);
1360 writeAll(Sf, scalarWeights,
points, faces);
1364 if (operation_ != opNone)
1380 needsUpdate_ =
true;
1389 needsUpdate_ =
true;