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];
197 if (isA<coupledPolyPatch>(pp))
199 if (refCast<const coupledPolyPatch>(pp).owner())
201 faceId = pp.whichFace(meshFacei);
208 else if (!isA<emptyPolyPatch>(pp))
210 faceId = meshFacei - pp.start();
221 faceId_[numFaces] =
faceId;
222 facePatchId_[numFaces] = facePatchId;
223 faceFlip_[numFaces] = isFlip;
231 faceId_.resize(numFaces);
232 facePatchId_.resize(numFaces);
233 faceFlip_.resize(numFaces);
238 void Foam::functionObjects::fieldValues::surfaceFieldValue::setPatchFaces()
248 mesh_.boundaryMesh().patchSet
255 DynamicList<label> bad;
256 for (
const label patchi : selected)
258 const polyPatch& pp = mesh_.boundaryMesh()[patchi];
260 if (isA<emptyPolyPatch>(pp))
266 numFaces += pp.size();
272 label nGood = (selected.size() - bad.size());
276 os <<
"Cannot sample an empty patch" <<
nl;
278 for (
const label patchi : bad)
281 << mesh_.boundaryMesh()[patchi].
name() <<
nl;
286 os <<
"No non-empty patches selected" <<
endl
291 os <<
"Selected " << nGood <<
" non-empty patches" <<
nl;
296 for (
const label patchi : selected)
298 if (!bad.found(patchi))
314 << regionTypeNames_[regionType_] <<
'(' << regionName_ <<
"):" <<
nl
315 <<
" No matching patch name(s): "
317 <<
" Known patch names:" <<
nl
318 << mesh_.boundaryMesh().names() <<
nl
328 << regionTypeNames_[regionType_] <<
'(' << regionName_ <<
"):" <<
nl
329 <<
" The patch specification: "
331 <<
" resulted in 0 faces" <<
nl
336 faceId_.resize(numFaces);
337 facePatchId_.resize(numFaces);
338 faceFlip_.resize(numFaces);
344 const polyPatch& pp = mesh_.boundaryMesh()[patchi];
345 const label len = pp.size();
347 SubList<label>(faceId_, len, numFaces) =
identity(len);
348 SubList<label>(facePatchId_, len, numFaces) = patchi;
349 SubList<bool>(faceFlip_, len, numFaces) =
false;
356 void Foam::functionObjects::fieldValues::surfaceFieldValue::combineMeshGeometry
366 IndirectList<face> selectedFaces(mesh_.faces(),
labelList(faceId_));
367 labelList& meshFaceIds = selectedFaces.addressing();
371 const label patchi = facePatchId_[i];
374 meshFaceIds[i] += mesh_.boundaryMesh()[patchi].start();
393 nFaces += allFaces[proci].size();
397 faces.resize(nFaces);
407 faces[nFaces++] = offsetOp<face>()(
f,
nPoints);
424 for (
const face&
f : allFaces[proci])
426 faces[nFaces++] = offsetOp<face>()(
f,
nPoints);
452 <<
" down to " << newPoints.size() <<
" points" <<
endl;
455 points.transfer(newPoints);
456 for (face&
f : faces)
464 void Foam::functionObjects::fieldValues::surfaceFieldValue::
465 combineSurfaceGeometry
471 if (stObject == regionType_)
473 const polySurface&
s = dynamicCast<const polySurface>(obr());
478 const scalar mergeDim = 1
e-10*boundBox(
s.points(),
true).
mag();
497 else if (sampledPtr_)
499 const sampledSurface&
s = *sampledPtr_;
504 const scalar mergeDim = 1
e-10*mesh_.bounds().mag();
527 Foam::functionObjects::fieldValues::surfaceFieldValue::totalArea()
const
529 scalar totalArea = 0;
531 if (stObject == regionType_)
533 const polySurface&
s = dynamicCast<const polySurface>(obr());
535 totalArea =
gSum(
s.magSf());
537 else if (sampledPtr_)
539 totalArea =
gSum(sampledPtr_->magSf());
543 totalArea =
gSum(filterField(mesh_.magSf()));
578 sampledPtr_->update();
600 const polySurface&
s = dynamicCast<const polySurface>(obr());
617 << regionTypeNames_[regionType_] <<
'(' << regionName_ <<
"):" <<
nl
621 totalArea_ = totalArea();
623 Log <<
" total faces = " << nFaces_ <<
nl
624 <<
" total area = " << totalArea_ <<
nl
627 writeFileHeader(file());
629 needsUpdate_ =
false;
639 if (canWriteHeader() && (operation_ != opNone))
641 writeCommented(os,
"Region type : ");
642 os << regionTypeNames_[regionType_] <<
' ' << regionName_ <<
nl;
644 writeHeaderValue(os,
"Faces", nFaces_);
645 writeHeaderValue(os,
"Area", totalArea_);
646 writeHeaderValue(os,
"Scale factor", scaleFactor_);
648 if (weightFieldNames_.size())
658 writeCommented(os,
"Time");
666 for (
const word& fieldName : fields_)
668 os <<
tab << operationTypeNames_[operation_]
669 <<
'(' << fieldName <<
')';
675 writtenHeader_ =
true;
695 case opSumDirectionBalance:
704 case opWeightedUniformity:
705 case opAbsWeightedUniformity:
707 const scalar areaTotal =
gSum(
mag(Sf));
712 if (canWeight(weightField))
719 mean =
gSum(weight()*areaVal()) / areaTotal;
722 numer =
gSum(
mag(weight*areaVal - (mean *
mag(Sf))));
729 mean =
gSum(areaVal()) / areaTotal;
732 numer =
gSum(
mag(areaVal - (mean *
mag(Sf))));
736 const scalar ui = 1 - numer/(2*
mag(mean*areaTotal) + ROOTVSMALL);
738 return min(
max(ui, 0), 1);
744 return processSameTypeValues(
values, Sf, weightField);
768 case opSumDirectionBalance:
775 case opAreaNormalAverage:
780 case opAreaNormalIntegrate:
787 case opWeightedUniformity:
788 case opAbsWeightedUniformity:
790 const scalar areaTotal =
gSum(
mag(Sf));
795 if (canWeight(weightField))
802 mean =
gSum(weight()*areaVal()) / areaTotal;
805 numer =
gSum(
mag(weight*areaVal - (mean *
mag(Sf))));
812 mean =
gSum(areaVal()) / areaTotal;
815 numer =
gSum(
mag(areaVal - (mean *
mag(Sf))));
819 const scalar ui = 1 - numer/(2*
mag(mean*areaTotal) + ROOTVSMALL);
827 return processSameTypeValues(
values, Sf, weightField);
842 return mag(weightField);
867 return mag(weightField *
mag(Sf));
870 return (weightField *
mag(Sf));
891 return mag(weightField & Sf);
894 return (weightField & Sf);
908 regionType_(regionTypeNames_.get(
"regionType",
dict)),
909 operation_(operationTypeNames_.get(
"operation",
dict)),
912 postOperationTypeNames_.getOrDefault
916 postOperationType::postOpNone,
942 regionType_(regionTypeNames_.get(
"regionType",
dict)),
943 operation_(operationTypeNames_.get(
"operation",
dict)),
946 postOperationTypeNames_.getOrDefault
950 postOperationType::postOpNone,
978 writeArea_ =
dict.getOrDefault(
"writeArea",
false);
979 weightFieldNames_.clear();
984 facePatchId_.clear();
986 sampledPtr_.reset(
nullptr);
987 surfaceWriterPtr_.reset(
nullptr);
995 selectionNames_.clear();
998 dict.readIfPresent(
"names", selectionNames_);
1000 for (
const auto& item : selectionNames_)
1002 if (item.isLiteral())
1019 if (selectionNames_.empty())
1021 selectionNames_.resize(1);
1022 selectionNames_.first() = regionName_;
1029 if (stSampled == regionType_)
1035 dict.subDict(
"sampledSurfaceDict")
1042 if (postOperation_ != postOpNone)
1044 Info<< postOperationTypeNames_[postOperation_] <<
'('
1045 << operationTypeNames_[operation_] <<
')' <<
nl;
1049 Info<< operationTypeNames_[operation_] <<
nl;
1054 if (stSampled == regionType_)
1057 <<
"Cannot use weighted operation '"
1058 << operationTypeNames_[operation_]
1059 <<
"' for sampledSurface"
1065 bool missing =
true;
1066 if (
dict.readIfPresent(
"weightFields", weightFieldNames_))
1072 weightFieldNames_.resize(1);
1074 if (
dict.readIfPresent(
"weightField", weightFieldNames_.first()))
1077 if (
"none" == weightFieldNames_.first())
1080 weightFieldNames_.clear();
1089 <<
"The '" << operationTypeNames_[operation_]
1090 <<
"' operation is missing a weightField." <<
nl
1091 <<
"Either provide the weightField, "
1092 <<
"use weightField 'none' to suppress weighting," <<
nl
1093 <<
"or use a different operation."
1097 Info<<
" weight field = ";
1098 if (weightFieldNames_.empty())
1110 if (
dict.readIfPresent(
"orientedFields", orientedFields))
1112 fields_.
append(orientedFields);
1115 <<
"The 'orientedFields' option is deprecated. These fields can "
1116 <<
"and have been added to the standard 'fields' list."
1122 const word formatName(
dict.get<
word>(
"surfaceFormat"));
1124 surfaceWriterPtr_.reset
1129 dict.subOrEmptyDict(
"formatOptions").subOrEmptyDict(formatName)
1135 surfaceWriterPtr_->verbose(
true);
1138 if (surfaceWriterPtr_->enabled())
1140 Info<<
" surfaceFormat = " << formatName <<
nl;
1144 surfaceWriterPtr_->clear();
1156 if (needsUpdate_ || operation_ != opNone)
1163 if (operation_ != opNone)
1165 writeCurrentTime(file());
1170 totalArea_ = totalArea();
1171 Log <<
" total area = " << totalArea_ <<
endl;
1175 file() <<
tab << totalArea_;
1183 if (stObject == regionType_)
1185 const polySurface&
s = dynamicCast<const polySurface>(obr());
1188 else if (sampledPtr_)
1190 Sf = sampledPtr_->Sf();
1194 Sf = filterField(mesh_.Sf());
1202 if (surfaceWriterPtr_)
1204 if (withTopologicalMerge())
1206 combineMeshGeometry(faces,
points);
1210 combineSurfaceGeometry(faces,
points);
1224 for (
const word& weightName : weightFieldNames_)
1226 if (validField<scalar>(weightName))
1230 if (scalarWeights.empty())
1232 scalarWeights = tfld;
1236 scalarWeights *= tfld;
1239 else if (validField<vector>(weightName))
1243 if (vectorWeights.empty())
1245 vectorWeights = tfld;
1250 <<
"weightField " << weightName
1251 <<
" - only one vector weight field allowed. " <<
nl
1256 else if (weightName !=
"none")
1264 <<
"weightField " << weightName
1265 <<
" not found or an unsupported type" <<
nl
1272 if (vectorWeights.size())
1274 if (scalarWeights.size())
1276 vectorWeights *= scalarWeights;
1279 writeAll(Sf, vectorWeights,
points, faces);
1283 writeAll(Sf, scalarWeights,
points, faces);
1287 if (operation_ != opNone)
1303 needsUpdate_ =
true;
1312 needsUpdate_ =
true;