59 scalar faceAreaLimit = SMALL;
63 if (
mag(fAreas[facei]) > faceAreaLimit)
65 checkFaces.append(facei);
71 motionSmoother::checkMesh
99 for (
const label facei : badFaces)
106 syncTools::syncPointList
135 const label edgeI = faceEdges[eI];
136 const edge&
e = edges[edgeI];
156 edgeLabels[
count++] = edgeI;
160 if (
count != edgeLabels.size())
162 edgeLabels.setSize(
count);
169 void Foam::edgeCollapser::collapseToEdge
174 const vector& collapseAxis,
182 Map<point>& collapsePointToLocation
191 DynamicList<label> maxPriorityPts(
max(dNeg.size(), dPos.size()));
195 const label facePointi = facePtsNeg[fPtI];
196 const label facePtPriority = pointPriority[facePointi];
198 if (facePtPriority > maxPriority)
200 maxPriority = facePtPriority;
201 maxPriorityPts.clear();
202 maxPriorityPts.append(facePointi);
204 else if (facePtPriority == maxPriority)
206 maxPriorityPts.append(facePointi);
210 if (!maxPriorityPts.empty())
214 forAll(maxPriorityPts, ptI)
216 averagePt += pts[maxPriorityPts[ptI]];
219 collapseToPtA = averagePt/maxPriorityPts.size();
224 maxPriorityPts.clear();
226 labelList faceEdgesNeg = edgesFromPoints(facei, facePtsNeg);
232 collapsePointToLocation.set(facePtsNeg[pI], collapseToPtA);
242 const label facePointi = facePtsPos[fPtI];
243 const label facePtPriority = pointPriority[facePointi];
245 if (facePtPriority > maxPriority)
247 maxPriority = facePtPriority;
248 maxPriorityPts.clear();
249 maxPriorityPts.append(facePointi);
251 else if (facePtPriority == maxPriority)
253 maxPriorityPts.append(facePointi);
257 if (!maxPriorityPts.empty())
261 forAll(maxPriorityPts, ptI)
263 averagePt += pts[maxPriorityPts[ptI]];
266 collapseToPtB = averagePt/maxPriorityPts.size();
270 labelList faceEdgesPos = edgesFromPoints(facei, facePtsPos);
276 collapsePointToLocation.set(facePtsPos[pI], collapseToPtB);
281 void Foam::edgeCollapser::collapseToPoint
289 Map<point>& collapsePointToLocation
292 const face&
f = mesh_.faces()[facei];
297 DynamicList<label> maxPriorityPts(
f.size());
301 const label facePointi = facePts[fPtI];
302 const label facePtPriority = pointPriority[facePointi];
304 if (facePtPriority > maxPriority)
306 maxPriority = facePtPriority;
307 maxPriorityPts.clear();
308 maxPriorityPts.append(facePointi);
310 else if (facePtPriority == maxPriority)
312 maxPriorityPts.append(facePointi);
316 if (!maxPriorityPts.empty())
320 forAll(maxPriorityPts, ptI)
322 averagePt += pts[maxPriorityPts[ptI]];
325 collapseToPt = averagePt/maxPriorityPts.
size();
368 const labelList& faceEdges = mesh_.faceEdges()[facei];
374 collapsePointToLocation.set(
f[pI], collapseToPt);
379 void Foam::edgeCollapser::faceCollapseAxisAndAspectRatio
396 scalar magJ =
mag(J);
411 detJ =
max(
det(J), SMALL);
418 collapseAxis =
f.edges()[
f.longestEdge(pts)].unitVec(pts);
428 if (
mag(eVals.y() - eVals.x()) < 100*SMALL)
435 collapseAxis =
f.edges()[
f.longestEdge(pts)].unitVec(pts);
463 const polyBoundaryMesh&
patches = mesh_.boundaryMesh();
465 const labelList& cellOwner = mesh_.faceOwner();
466 const labelList& cellNeighbour = mesh_.faceNeighbour();
468 const label nBoundaryFaces = mesh_.nBoundaryFaces();
471 for (label intFacei = 0; intFacei < mesh_.nInternalFaces(); ++intFacei)
473 const scalar cellOwnerVol =
max(0.0, V[cellOwner[intFacei]]);
474 const scalar cellNeighbourVol =
max(0.0, V[cellNeighbour[intFacei]]);
476 scalar targetFaceSizeA =
Foam::cbrt(cellOwnerVol);
477 scalar targetFaceSizeB =
Foam::cbrt(cellNeighbourVol);
479 targetFaceSizes[intFacei] = 0.5*(targetFaceSizeA + targetFaceSizeB);
489 label bFacei =
patch.start() - mesh_.nInternalFaces();
499 neiCellVolumes[bFacei++] =
max(0.0, V[faceCells[facei]]);
508 const label extFacei = patchFacei +
patch.start();
509 const scalar cellOwnerVol =
max(0.0, V[cellOwner[extFacei]]);
511 targetFaceSizes[extFacei] =
Foam::cbrt(cellOwnerVol);
522 label bFacei =
patch.start() - mesh_.nInternalFaces();
528 const label localFacei = patchFacei +
patch.start();
529 const scalar cellOwnerVol =
max(0.0, V[cellOwner[localFacei]]);
530 const scalar cellNeighbourVol = neiCellVolumes[bFacei++];
532 scalar targetFaceSizeA =
Foam::cbrt(cellOwnerVol);
533 scalar targetFaceSizeB =
Foam::cbrt(cellNeighbourVol);
535 targetFaceSizes[localFacei]
536 = 0.5*(targetFaceSizeA + targetFaceSizeB);
542 return targetFaceSizes;
551 const scalar targetFaceSize,
553 Map<point>& collapsePointToLocation,
557 const scalar collapseSizeLimitCoeff = faceFilterFactor[facei];
565 const scalar fA =
f.mag(pts);
568 scalar aspectRatio = 1.0;
570 faceCollapseAxisAndAspectRatio(
f, fC, collapseAxis, aspectRatio);
581 d[fPtI] = (collapseAxis & (pt - fC));
589 oldToNew =
invert(oldToNew.size(), oldToNew);
598 scalar dShift = -0.5*(d.first() + d.last());
628 SubList<scalar> dNeg(d, middle, 0);
629 SubList<label> facePtsNeg(facePts, middle, 0);
632 SubList<scalar> dPos(d, d.size() - middle, middle);
633 SubList<label> facePtsPos(facePts, d.size() - middle, middle);
645 if (dNeg.size() == 0 || dPos.size() == 0)
648 <<
"All points on one side of face centre, not collapsing."
656 collapseType typeOfCollapse = noCollapse;
658 if (
magSqr(collapseAxis) < VSMALL)
662 else if (fA < aspectRatio*
sqr(targetFaceSize*collapseSizeLimitCoeff))
666 allowEarlyCollapseToPoint_
667 && (d.last() - d.first())
669 *allowEarlyCollapseCoeff_*maxCollapseFaceToPointSideLengthCoeff_
676 (dNeg.last() < guardFraction_*dNeg.first())
677 && (dPos.first() > guardFraction_*dPos.last())
680 typeOfCollapse = toEdge;
684 (d.last() - d.first())
686 *maxCollapseFaceToPointSideLengthCoeff_
705 collapsePointToLocation
708 else if (typeOfCollapse == toEdge)
723 collapsePointToLocation
727 return typeOfCollapse;
731 Foam::label Foam::edgeCollapser::edgeMaster
737 label masterPoint = -1;
739 const label e0 =
e.start();
740 const label e1 =
e.end();
742 const label e0Priority = pointPriority[e0];
743 const label e1Priority = pointPriority[e1];
745 if (e0Priority > e1Priority)
749 else if (e0Priority < e1Priority)
753 else if (e0Priority == e1Priority)
789 void Foam::edgeCollapser::checkBoundaryPointMergeEdges
792 const label otherPointi,
794 Map<point>& collapsePointToLocation
799 const label e0Priority = pointPriority[pointi];
800 const label e1Priority = pointPriority[otherPointi];
802 if (e0Priority > e1Priority)
804 collapsePointToLocation.set
810 else if (e0Priority < e1Priority)
812 collapsePointToLocation.set
820 collapsePointToLocation.set
837 Foam::label Foam::edgeCollapser::breakStringsAtEdges
839 const bitSet& markedEdges,
841 List<pointEdgeCollapse>& allPointInfo
844 const edgeList& edges = mesh_.edges();
847 label nUncollapsed = 0;
851 if (markedEdges.test(eI))
853 const edge&
e = edges[eI];
855 const label startCollapseIndex
856 = allPointInfo[
e.start()].collapseIndex();
858 if (startCollapseIndex != -1 && startCollapseIndex != -2)
860 const label endCollapseIndex
861 = allPointInfo[
e.end()].collapseIndex();
866 && startCollapseIndex == endCollapseIndex
869 const labelList& ptEdgesStart = pointEdges[
e.start()];
871 forAll(ptEdgesStart, ptEdgeI)
873 const label edgeI = ptEdgesStart[ptEdgeI];
875 const label nbrPointi
876 = edges[edgeI].otherVertex(
e.start());
878 = allPointInfo[nbrPointi].collapseIndex();
882 nbrIndex == startCollapseIndex
899 void Foam::edgeCollapser::determineDuplicatePointsOnFace
902 bitSet& markedPoints,
905 List<pointEdgeCollapse>& allPointInfo
908 uniqueCollapses.clear();
909 duplicateCollapses.clear();
913 label index = allPointInfo[
f[fpI]].collapseIndex();
916 if (index != allPointInfo[
f.prevLabel(fpI)].collapseIndex())
918 if (!uniqueCollapses.insert(index))
921 duplicateCollapses.insert(index);
930 label index = allPointInfo[
f[fpI]].collapseIndex();
931 if (duplicateCollapses.found(index))
933 markedPoints.set(
f[fpI]);
939 Foam::label Foam::edgeCollapser::countEdgesOnFace
942 List<pointEdgeCollapse>& allPointInfo
949 const label pointi =
f[fpI];
950 const label
newPointi = allPointInfo[pointi].collapseIndex();
958 const label prevPointi =
f[
f.fcIndex(fpI)];
959 const label prevNewPointi
960 = allPointInfo[prevPointi].collapseIndex();
973 bool Foam::edgeCollapser::isFaceCollapsed
976 List<pointEdgeCollapse>& allPointInfo
979 label nEdges = countEdgesOnFace(
f, allPointInfo);
997 Foam::label Foam::edgeCollapser::syncCollapse
999 const globalIndex& globalPoints,
1002 const Map<point>& collapsePointToLocation,
1003 List<pointEdgeCollapse>& allPointInfo
1006 const edgeList& edges = mesh_.edges();
1008 label nCollapsed = 0;
1010 DynamicList<label> initPoints(mesh_.nPoints());
1011 DynamicList<pointEdgeCollapse> initPointInfo(mesh_.nPoints());
1013 allPointInfo.
clear();
1014 allPointInfo.setSize(mesh_.nPoints());
1017 List<pointEdgeCollapse> allEdgeInfo
1020 pointEdgeCollapse(
Zero, -1, -1)
1028 const edge&
e = edges[edgeI];
1030 label masterPointi =
e.start();
1033 if (pointPriority[
e.end()] > pointPriority[
e.start()])
1035 masterPointi =
e.end();
1038 label masterPointPriority = pointPriority[masterPointi];
1040 label index = globalPoints.toGlobal(masterPointi);
1042 if (!collapsePointToLocation.found(masterPointi))
1044 const label otherVertex =
e.otherVertex(masterPointi);
1046 if (!collapsePointToLocation.found(otherVertex))
1049 << masterPointi <<
" on edge " << edgeI <<
" " <<
e
1050 <<
" is not marked for collapse."
1055 masterPointi = otherVertex;
1056 masterPointPriority = pointPriority[masterPointi];
1057 index = globalPoints.toGlobal(masterPointi);
1061 const point& collapsePoint = collapsePointToLocation[masterPointi];
1063 const pointEdgeCollapse pec
1072 allEdgeInfo[edgeI] = pointEdgeCollapse
1079 initPointInfo.append(pec);
1080 initPoints.append(
e.start());
1082 initPointInfo.append(pec);
1083 initPoints.append(
e.end());
1089 PointEdgeWave<pointEdgeCollapse> collapsePropagator
1096 mesh_.globalData().nTotalPoints()
1103 void Foam::edgeCollapser::filterFace
1105 const Map<DynamicList<label>>& collapseStrings,
1106 const List<pointEdgeCollapse>& allPointInfo,
1116 label pointi =
f[fp];
1118 label collapseIndex = allPointInfo[pointi].collapseIndex();
1121 if (collapseStrings.found(collapseIndex))
1123 const label localPointi = collapseStrings[collapseIndex][0];
1125 if (!SubList<label>(
f, newFp).found(localPointi))
1127 f[newFp++] = localPointi;
1130 else if (collapseIndex == -1)
1133 <<
"Point " << pointi <<
" was not visited by PointEdgeWave"
1138 f[newFp++] = pointi;
1149 const label size = newFp;
1153 for (label fp = 2; fp < size; fp++)
1158 label pointi =
f[fp];
1161 const label index = SubList<label>(
f, fp).find(pointi);
1166 <<
"Removing consecutive duplicate vertex in face "
1170 else if (index == fp2)
1173 <<
"Removing non-consecutive duplicate vertex in face "
1178 else if (index != -1)
1181 <<
"Pinched face " <<
f <<
endl;
1182 f[newFp++] = pointi;
1186 f[newFp++] = pointi;
1200 maxCollapseFaceToPointSideLengthCoeff_(0),
1201 allowEarlyCollapseToPoint_(false),
1202 allowEarlyCollapseCoeff_(0)
1206 Foam::edgeCollapser::edgeCollapser
1217 maxCollapseFaceToPointSideLengthCoeff_
1221 allowEarlyCollapseToPoint_
1225 allowEarlyCollapseCoeff_
1232 Info<<
"Edge Collapser Settings:" <<
nl
1233 <<
" Guard Fraction = " << guardFraction_ <<
nl
1234 <<
" Max collapse face to point side length = "
1235 << maxCollapseFaceToPointSideLengthCoeff_ <<
nl
1236 <<
" " << (allowEarlyCollapseToPoint_ ?
"Allow" :
"Do not allow")
1237 <<
" early collapse to point" <<
nl
1238 <<
" Early collapse coeff = " << allowEarlyCollapseCoeff_
1253 const labelList& faceOwner = mesh_.faceOwner();
1254 const labelList& faceNeighbour = mesh_.faceNeighbour();
1296 bool meshChanged =
false;
1298 bitSet removedPoints(mesh_.nPoints());
1306 forAll(allPointInfo, pointi)
1308 label collapseIndex = allPointInfo[pointi].collapseIndex();
1310 if (collapseIndex != -1 && collapseIndex != -2)
1312 ++(nPerIndex(collapseIndex, 0));
1317 collapseStrings.
resize(2*nPerIndex.size());
1324 forAll(allPointInfo, pointi)
1326 const label collapseIndex = allPointInfo[pointi].collapseIndex();
1328 if (collapseIndex != -1 && collapseIndex != -2)
1330 collapseStrings[collapseIndex].
append(pointi);
1362 bitSet cellRemoved(mesh_.nCells(),
false);
1364 label nUnvisited = 0;
1365 label nUncollapsed = 0;
1366 label nCollapsed = 0;
1386 label
nPoints = allPointInfo.size();
1395 <<
indent <<
"Not visited : " << nUnvisited <<
nl
1396 <<
indent <<
"Not collapsed : " << nUncollapsed <<
nl
1397 <<
indent <<
"Collapsed : " << nCollapsed <<
nl
1405 filterFace(collapseStrings, allPointInfo, newFaces[facei]);
1409 label nCellCollapsed = 0;
1413 if (!cellRemoved.test(celli))
1417 label nFaces = cFaces.size();
1421 label facei = cFaces[i];
1423 if (newFaces[facei].size() < 3)
1429 Pout<<
"Cell:" << celli
1430 <<
" uses faces:" << cFaces
1431 <<
" of which too many are marked for removal:"
1438 if (newFaces[cFaces[j]].size() < 3)
1440 Pout<<
' '<< cFaces[j];
1445 cellRemoved.set(celli);
1460 Info<<
indent <<
"Collapsing " << nCellCollapsed <<
" cells" <<
endl;
1462 if (nCellCollapsed == 0)
1471 bitSet doneFace(mesh_.nFaces(),
false);
1475 bitSet usedPoint(mesh_.nPoints(),
false);
1477 forAll(cellRemoved, celli)
1479 if (cellRemoved.test(celli))
1488 const face&
f = newFaces[facei];
1496 doneFace.set(facei);
1506 forAll(usedPoint, pointi)
1508 if (!usedPoint.test(pointi))
1510 removedPoints.set(pointi);
1518 forAll(allPointInfo, pointi)
1520 const label collapseIndex = allPointInfo[pointi].collapseIndex();
1521 const point& collapsePoint = allPointInfo[pointi].collapsePoint();
1525 !removedPoints.test(pointi)
1526 && collapseIndex != -1
1527 && collapseIndex != -2
1545 forAll(allPointInfo, pointi)
1547 if (removedPoints.test(pointi))
1549 const labelList& changedFaces = pointFaces[pointi];
1551 forAll(changedFaces, changedFacei)
1553 label facei = changedFaces[changedFacei];
1555 if (doneFace.set(facei))
1562 bool zoneFlip =
false;
1572 label own = faceOwner[facei];
1576 if (mesh_.isInternalFace(facei))
1578 nei = faceNeighbour[facei];
1614 const bool allowCellCollapse
1619 const faceList faces = mesh_.faces();
1620 const edgeList& edges = mesh_.edges();
1630 label nUncollapsed = 0;
1648 collapsePointToLocation,
1654 bitSet isCollapsedFace(mesh_.nFaces());
1655 bitSet markedPoints(mesh_.nPoints());
1659 const face&
f = faces[facei];
1661 isCollapsedFace[facei] = isFaceCollapsed(
f, allPointInfo);
1663 if (!isCollapsedFace.test(facei))
1665 determineDuplicatePointsOnFace
1686 forAll(markedPoints, pointi)
1688 if (markedPoints.test(pointi))
1690 const label index = allPointInfo[pointi].collapseIndex();
1692 const labelList& ptEdges = pointEdges[pointi];
1696 const label edgeI = ptEdges[ptEdgeI];
1697 const label nbrPointi = edges[edgeI].otherVertex(pointi);
1698 const label nbrIndex
1699 = allPointInfo[nbrPointi].collapseIndex();
1710 bitSet markedEdges(mesh_.nEdges());
1712 if (!allowCellCollapse)
1719 label nFaces = cFaces.size();
1723 label facei = cFaces[fI];
1725 if (isCollapsedFace.test(facei))
1735 label facei = cFaces[fI];
1737 const labelList& fEdges = faceEdges[facei];
1742 label edgeI = fEdges[fEdgeI];
1749 markedEdges.
set(edgeI);
1753 isCollapsedFace.unset(facei);
1761 <<
"Cell " << celli <<
" " << cFaces <<
nl
1762 <<
"is " << nFaces <<
", "
1763 <<
"but cell collapse has been disabled."
1777 nUncollapsed += breakStringsAtEdges
1786 Info<<
" Uncollapsed edges = " << nUncollapsed <<
" / "
1789 if (nUncollapsed == 0)
1809 const edgeList& edges = mesh_.edges();
1811 label nCollapsed = 0;
1815 const edge&
e = edges[edgeI];
1819 if (
e.mag(
points) < minEdgeLen[edgeI])
1823 label masterPointi = edgeMaster(pointPriority,
e);
1825 if (masterPointi == -1)
1830 collapsePointToLocation.set(
e.start(),
average);
1836 collapsePointToLocation.set(masterPointi, collapsePt);
1850 const scalar maxCos,
1856 const edgeList& edges = mesh_.edges();
1865 label nTotRemove = pointRemover.
countPointUsage(maxCos, pointCanBeDeleted);
1869 label nCollapsed = 0;
1873 forAll(pointEdges, pointi)
1875 if (pointCanBeDeleted[pointi])
1877 const labelList& pEdges = pointEdges[pointi];
1879 if (pEdges.size() == 2)
1883 label e0 = pEdges[0];
1884 label e1 = pEdges[1];
1889 scalar e0length =
mag
1894 scalar e1length =
mag
1899 if (e0length <= e1length)
1903 checkBoundaryPointMergeEdges
1906 edges[e0].otherVertex(pointi),
1908 collapsePointToLocation
1915 checkBoundaryPointMergeEdges
1918 edges[e1].otherVertex(pointi),
1920 collapsePointToLocation
1943 const faceList& faces = mesh_.faces();
1945 const scalarField targetFaceSizes = calcTargetFaceSizes();
1948 label nCollapseToPoint = 0;
1949 label nCollapseToEdge = 0;
1953 const face&
f = faces[fI];
1955 if (faceFilterFactor[fI] <= 0)
1965 targetFaceSizes[fI],
1967 collapsePointToLocation,
1971 if (flagCollapseFace == noCollapse)
1975 else if (flagCollapseFace ==
toPoint)
1979 else if (flagCollapseFace == toEdge)
1986 <<
"Face is marked to be collapsed to " << flagCollapseFace
1987 <<
". Currently can only collapse to point/edge."
1992 return labelPair(nCollapseToPoint, nCollapseToEdge);
2005 const faceList& faces = mesh_.faces();
2007 const scalarField targetFaceSizes = calcTargetFaceSizes();
2010 label nCollapseToPoint = 0;
2011 label nCollapseToEdge = 0;
2020 const face&
f = faces[fI];
2022 if (faceFilterFactor[fI] <= 0)
2032 targetFaceSizes[fI],
2034 collapsePointToLocation,
2038 if (flagCollapseFace == noCollapse)
2042 else if (flagCollapseFace ==
toPoint)
2046 else if (flagCollapseFace == toEdge)
2053 <<
"Face is marked to be collapsed to " << flagCollapseFace
2054 <<
". Currently can only collapse to point/edge."
2059 return labelPair(nCollapseToPoint, nCollapseToEdge);