1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
28 #include "objectMap.H"
29 #include "changeMap.H"
30 #include "coupledInfo.H"
31 #include "multiThreader.H"
32 #include "dynamicTopoFvMesh.H"
34 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
41 // Method to collapse a quad-face in 2D
42 // - Returns a changeMap with a type specifying:
43 // -3: Collapse failed since face was on a noRefinement patch.
44 // -1: Collapse failed since max number of topo-changes was reached.
45 // 0: Collapse could not be performed.
46 // 1: Collapsed to first node.
47 // 2: Collapsed to second node.
48 // 3: Collapse to mid-point.
49 // - overRideCase is used to force a certain collapse configuration.
50 // -1: Use this value to let collapseQuadFace decide a case.
51 // 1: Force collapse to first node.
52 // 2: Force collapse to second node.
53 // 3: Force collapse to mid-point.
54 // - checkOnly performs a feasibility check and returns without modifications.
55 const changeMap dynamicTopoFvMesh::collapseQuadFace
63 // Figure out which thread this is...
64 label tIndex = self();
66 // Prepare the changeMaps
68 List<changeMap> slaveMaps;
69 bool collapsingSlave = false;
73 (status(TOTAL_MODIFICATIONS) > maxModifications_)
74 && (maxModifications_ > -1)
77 // Reached the max allowable topo-changes.
78 stack(tIndex).clear();
83 // Check if edgeRefinements are to be avoided on patch.
84 if (baseMesh_.lengthEstimator().checkRefinementPatch(whichPatch(fIndex)))
91 // Sanity check: Is the index legitimate?
98 "dynamicTopoFvMesh::collapseQuadFace\n"
100 " const label fIndex,\n"
101 " label overRideCase,\n"
106 << " Invalid index: " << fIndex
107 << abort(FatalError);
110 // Define the edges on the face to be collapsed
111 FixedList<edge,4> checkEdge(edge(-1, -1));
112 FixedList<label,4> checkEdgeIndex(-1);
115 getCheckEdges(fIndex, (*this), map, checkEdge, checkEdgeIndex);
117 // Determine the common vertices for the first and second edges
118 label cv0 = checkEdge[1].commonVertex(checkEdge[0]);
119 label cv1 = checkEdge[1].commonVertex(checkEdge[3]);
120 label cv2 = checkEdge[2].commonVertex(checkEdge[0]);
121 label cv3 = checkEdge[2].commonVertex(checkEdge[3]);
123 // If coupled modification is set, and this is a
124 // master face, collapse its slaves first.
125 bool localCouple = false, procCouple = false;
127 if (coupledModification_)
129 const face& fCheck = faces_[fIndex];
131 const label faceEnum = coupleMap::FACE;
132 const label pointEnum = coupleMap::POINT;
134 // Is this a locally coupled edge (either master or slave)?
135 if (locallyCoupledEntity(fIndex, true))
141 if (processorCoupledEntity(fIndex))
147 if (localCouple && !procCouple)
149 // Determine the slave index.
150 label sIndex = -1, pIndex = -1;
152 forAll(patchCoupling_, patchI)
154 if (patchCoupling_(patchI))
156 const coupleMap& cMap = patchCoupling_[patchI].map();
158 if ((sIndex = cMap.findSlave(faceEnum, fIndex)) > -1)
165 // The following bit happens only during the sliver
166 // exudation process, since slave edges are
167 // usually not added to the coupled edge-stack.
168 if ((sIndex = cMap.findMaster(faceEnum, fIndex)) > -1)
172 // Notice that we are collapsing a slave edge first.
173 collapsingSlave = true;
186 "dynamicTopoFvMesh::collapseQuadFace\n"
188 " const label fIndex,\n"
189 " label overRideCase,\n"
194 << "Coupled maps were improperly specified." << nl
195 << " Slave index not found for: " << nl
196 << " Face: " << fIndex << ": " << fCheck << nl
197 << abort(FatalError);
201 // If we've found the slave, size up the list
208 // Save index and patch for posterity
209 slaveMaps[0].index() = sIndex;
210 slaveMaps[0].patchIndex() = pIndex;
215 Pout<< nl << " >> Collapsing slave face: " << sIndex
216 << " for master face: " << fIndex << endl;
220 if (procCouple && !localCouple)
222 // If this is a new entity, bail out for now.
223 // This will be handled at the next time-step.
224 if (fIndex >= nOldFaces_)
230 forAll(procIndices_, pI)
232 // Fetch reference to subMeshes
233 const coupledMesh& sendMesh = sendMeshes_[pI];
234 const coupledMesh& recvMesh = recvMeshes_[pI];
236 const coupleMap& scMap = sendMesh.map();
237 const coupleMap& rcMap = recvMesh.map();
239 // If this face was sent to a lower-ranked
240 // processor, skip it.
251 if (scMap.reverseEntityMap(faceEnum).found(fIndex))
255 Pout<< "Face: " << fIndex
257 << " was sent to proc: "
259 << ", so bailing out."
269 if ((sIndex = rcMap.findSlave(faceEnum, fIndex)) > -1)
271 // Check if a lower-ranked processor is
272 // handling this face
285 Pout<< "Face: " << fIndex
287 << " is handled by proc: "
289 << ", so bailing out."
296 label curIndex = slaveMaps.size();
305 // Save index and patch for posterity
306 slaveMaps[curIndex].index() = sIndex;
307 slaveMaps[curIndex].patchIndex() = pI;
313 rcMap.findSlave(pointEnum, cv0) > -1 &&
314 rcMap.findSlave(pointEnum, cv1) > -1
317 rcMap.findSlave(pointEnum, cv2) > -1 &&
318 rcMap.findSlave(pointEnum, cv3) > -1
322 // An edge-only coupling exists.
324 // Check if a lower-ranked processor is
325 // handling this face
338 Pout<< "Face edge on: " << fIndex
340 << " is handled by proc: "
342 << ", so bailing out."
349 label p0 = rcMap.findSlave(pointEnum, cv0);
350 label p1 = rcMap.findSlave(pointEnum, cv1);
352 label p2 = rcMap.findSlave(pointEnum, cv2);
353 label p3 = rcMap.findSlave(pointEnum, cv3);
356 label edgeCouple = -1;
358 if ((p0 > -1 && p1 > -1) && (p2 == -1 && p3 == -1))
364 sIndex = readLabel(map.lookup("firstEdge"));
367 if ((p0 == -1 && p1 == -1) && (p2 > -1 && p3 > -1))
373 sIndex = readLabel(map.lookup("secondEdge"));
376 label curIndex = slaveMaps.size();
385 // Unfortunately, since no edge maps are
386 // available in 2D, loop through boundary
387 // faces on subMesh and get the right edge
390 const dynamicTopoFvMesh& sMesh = recvMesh.subMesh();
394 label faceI = sMesh.nOldInternalFaces_;
395 faceI < sMesh.faceEdges_.size();
399 const labelList& fEdges = sMesh.faceEdges_[faceI];
401 forAll(fEdges, edgeI)
403 if (sMesh.edges_[fEdges[edgeI]] == cEdge)
405 seIndex = fEdges[edgeI];
418 Pout<< "Face edge on: " << fIndex
420 << " sIndex: " << sIndex
421 << " could not be found."
422 << abort(FatalError);
425 // Save index and patch for posterity
426 // - Negate the index to signify edge coupling
427 slaveMaps[curIndex].index() = -seIndex;
428 slaveMaps[curIndex].patchIndex() = pI;
430 // Save edgeCouple as well, so that
431 // another map comparison is avoided.
432 slaveMaps[curIndex].type() = edgeCouple;
438 // Something's wrong with coupling maps
443 "dynamicTopoFvMesh::collapseQuadFace\n"
445 " const label fIndex,\n"
446 " label overRideCase,\n"
451 << "Coupled maps were improperly specified." << nl
452 << " localCouple: " << localCouple << nl
453 << " procCouple: " << procCouple << nl
454 << " Face: " << fIndex << ": " << fCheck << nl
455 << abort(FatalError);
458 // Temporarily turn off coupledModification
459 unsetCoupledModification();
461 // Test the master face for collapse, and decide on a case
462 changeMap masterMap = collapseQuadFace(fIndex, -1, true, forceOp);
465 setCoupledModification();
467 // Master couldn't perform collapse
468 if (masterMap.type() <= 0)
473 // For edge-only coupling, define the points for checking
474 List<FixedList<point, 2> > slaveMoveNewPoint(slaveMaps.size());
475 List<FixedList<point, 2> > slaveMoveOldPoint(slaveMaps.size());
477 // Now check each of the slaves for collapse feasibility
478 forAll(slaveMaps, slaveI)
480 // Alias for convenience...
481 changeMap& slaveMap = slaveMaps[slaveI];
483 label slaveOverRide = -1;
484 label sIndex = slaveMap.index();
485 label pI = slaveMap.patchIndex();
486 const coupleMap* cMapPtr = NULL;
490 cMapPtr = &(patchCoupling_[pI].map());
495 const dynamicTopoFvMesh& sMesh =
497 recvMeshes_[pI].subMesh()
500 cMapPtr = &(recvMeshes_[pI].map());
506 Pout<< "Checking slave edge: " << mag(sIndex)
507 << "::" << sMesh.edges_[mag(sIndex)]
508 << " on proc: " << procIndices_[pI]
509 << " for master face: " << fIndex
510 << " using collapseCase: " << masterMap.type()
515 Pout<< "Checking slave face: " << sIndex
516 << "::" << sMesh.faces_[sIndex]
517 << " on proc: " << procIndices_[pI]
518 << " for master face: " << fIndex
519 << " using collapseCase: " << masterMap.type()
525 // Define an overRide case for the slave
526 FixedList<edge, 2> mEdge(edge(-1, -1)), sEdge(edge(-1, -1));
530 const Map<label>& rPointMap =
532 cMapPtr->reverseEntityMap(pointEnum)
537 if (slaveMap.type() == 1)
539 mEdge[0][0] = rPointMap[cv0];
540 mEdge[0][1] = rPointMap[cv1];
543 if (slaveMap.type() == 2)
545 mEdge[0][0] = rPointMap[cv2];
546 mEdge[0][1] = rPointMap[cv3];
551 mEdge[0][0] = rPointMap[cv0];
552 mEdge[0][1] = rPointMap[cv1];
554 mEdge[1][0] = rPointMap[cv2];
555 mEdge[1][1] = rPointMap[cv3];
560 const Map<label>& pointMap =
562 cMapPtr->entityMap(pointEnum)
567 if (slaveMap.type() == 1)
569 mEdge[0][0] = pointMap[cv0];
570 mEdge[0][1] = pointMap[cv1];
573 if (slaveMap.type() == 2)
575 mEdge[0][0] = pointMap[cv2];
576 mEdge[0][1] = pointMap[cv3];
581 mEdge[0][0] = pointMap[cv0];
582 mEdge[0][1] = pointMap[cv1];
584 mEdge[1][0] = pointMap[cv2];
585 mEdge[1][1] = pointMap[cv3];
589 // Determine checkEdges for the slave
590 FixedList<edge,4> slaveCheckEdge(edge(-1, -1));
591 FixedList<label,4> slaveCheckEdgeIndex(-1);
604 sEdge[0] = edges_[readLabel(slaveMap.lookup("firstEdge"))];
605 sEdge[1] = edges_[readLabel(slaveMap.lookup("secondEdge"))];
610 const dynamicTopoFvMesh& sMesh =
612 recvMeshes_[pI].subMesh()
617 sEdge[0] = sMesh.edges_[mag(sIndex)];
632 sMesh.edges_[readLabel(slaveMap.lookup("firstEdge"))]
637 sMesh.edges_[readLabel(slaveMap.lookup("secondEdge"))]
642 // Compare edge orientations for edge-only coupling
645 // Perform a topological comparison.
646 switch (masterMap.type())
652 slaveMoveNewPoint[slaveI][0] = points_[cv0];
653 slaveMoveNewPoint[slaveI][1] = points_[cv1];
655 slaveMoveOldPoint[slaveI][0] = oldPoints_[cv0];
656 slaveMoveOldPoint[slaveI][1] = oldPoints_[cv1];
659 if (mEdge[0] == sEdge[0])
664 if (mEdge[1] == sEdge[0])
670 // Write out for for post-processing
671 writeVTK("mFace_" + Foam::name(fIndex), fIndex, 2);
677 "dynamicTopoFvMesh::collapseQuadFace\n"
679 " const label fIndex,\n"
680 " label overRideCase,\n"
685 << "Coupled collapse failed." << nl
687 << checkEdgeIndex[1] << ": "
688 << checkEdge[1] << nl
689 << checkEdgeIndex[2] << ": "
690 << checkEdge[2] << nl
692 << readLabel(slaveMap.lookup("firstEdge")) << ": "
694 << readLabel(slaveMap.lookup("secondEdge")) << ": "
696 << abort(FatalError);
706 slaveMoveNewPoint[slaveI][0] = points_[cv2];
707 slaveMoveNewPoint[slaveI][1] = points_[cv3];
709 slaveMoveOldPoint[slaveI][0] = oldPoints_[cv2];
710 slaveMoveOldPoint[slaveI][1] = oldPoints_[cv3];
713 if (mEdge[1] == sEdge[1])
718 if (mEdge[0] == sEdge[1])
724 // Write out for for post-processing
725 writeVTK("mFace_" + Foam::name(fIndex), fIndex, 2);
731 "dynamicTopoFvMesh::collapseQuadFace\n"
733 " const label fIndex,\n"
734 " label overRideCase,\n"
739 << "Coupled collapse failed." << nl
741 << checkEdgeIndex[1] << ": "
742 << checkEdge[1] << nl
743 << checkEdgeIndex[2] << ": "
744 << checkEdge[2] << nl
746 << readLabel(slaveMap.lookup("firstEdge")) << ": "
748 << readLabel(slaveMap.lookup("secondEdge")) << ": "
750 << abort(FatalError);
760 slaveMoveNewPoint[slaveI][0] =
762 0.5 * (points_[cv0] + points_[cv2])
765 slaveMoveNewPoint[slaveI][1] =
767 0.5 * (points_[cv1] + points_[cv3])
770 slaveMoveOldPoint[slaveI][0] =
772 0.5 * (oldPoints_[cv0] + oldPoints_[cv2])
775 slaveMoveOldPoint[slaveI][1] =
777 0.5 * (oldPoints_[cv1] + oldPoints_[cv3])
791 // Check edge orientation
792 compVal = edge::compare(mEdge[0], sEdge[0]);
794 // Swap components if necessary
799 slaveMoveNewPoint[slaveI][0],
800 slaveMoveNewPoint[slaveI][1]
805 slaveMoveOldPoint[slaveI][0],
806 slaveMoveOldPoint[slaveI][1]
816 "dynamicTopoFvMesh::collapseQuadFace\n"
818 " const label fIndex,\n"
819 " label overRideCase,\n"
824 << "Coupled topo-change for slave failed." << nl
825 << " Dissimilar edges: " << nl
826 << " mEdge: " << mEdge << nl
827 << " sEdge: " << sEdge << nl
828 << " masterMap type: " << masterMap.type() << nl
829 << abort(FatalError);
833 // Temporarily turn off coupledModification
834 unsetCoupledModification();
836 // Test the slave face
841 collapseQuadFace(sIndex, slaveOverRide, true, forceOp)
847 dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
851 // Edge-based coupling
853 // Build a hull of cells and tri-faces
854 // that are connected to the slave edge
855 labelList slaveHullCells;
856 labelList slaveHullTriFaces;
858 meshOps::constructPrismHull
870 bool infeasible = false;
872 // Keep track of resulting cell quality,
873 // if collapse is indeed feasible
874 scalar slaveCollapseQuality(GREAT);
876 // Check whether the collapse is possible.
883 FixedList<label, 2>(-1),
884 FixedList<label, 2>(-1),
886 slaveMoveNewPoint[slaveI],
887 slaveMoveOldPoint[slaveI],
888 slaveCollapseQuality,
908 // Edge-based coupling
911 sMesh.collapseQuadFace
923 setCoupledModification();
925 if (slaveMap.type() <= 0)
927 // Slave couldn't perform collapse.
933 // Save index and patch for posterity
934 slaveMap.index() = sIndex;
935 slaveMap.patchIndex() = pI;
938 // Next collapse each slave face (for real this time...)
939 forAll(slaveMaps, slaveI)
941 // Alias for convenience...
942 changeMap& slaveMap = slaveMaps[slaveI];
944 label sIndex = slaveMap.index();
945 label pI = slaveMap.patchIndex();
946 label slaveOverRide = slaveMap.type();
948 // Temporarily turn off coupledModification
949 unsetCoupledModification();
951 // Collapse the slave
956 collapseQuadFace(sIndex, slaveOverRide, false, forceOp)
961 const coupleMap& cMap = recvMeshes_[pI].map();
962 dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
966 // Edge-based coupling
968 // Fetch the slave edge
969 edge sEdge = sMesh.edges_[mag(sIndex)];
971 // Move points to new location,
972 // and update operation into coupleMap
973 sMesh.points_[sEdge[0]] = slaveMoveNewPoint[slaveI][0];
974 sMesh.points_[sEdge[1]] = slaveMoveNewPoint[slaveI][1];
976 sMesh.oldPoints_[sEdge[0]] = slaveMoveOldPoint[slaveI][0];
977 sMesh.oldPoints_[sEdge[1]] = slaveMoveOldPoint[slaveI][1];
982 coupleMap::MOVE_POINT,
983 slaveMoveNewPoint[slaveI][0],
984 slaveMoveOldPoint[slaveI][0]
990 coupleMap::MOVE_POINT,
991 slaveMoveNewPoint[slaveI][1],
992 slaveMoveOldPoint[slaveI][1]
995 // Force operation to succeed
1000 // Face-based coupling
1003 sMesh.collapseQuadFace
1012 // Push operation into coupleMap
1013 switch (slaveMap.type())
1020 coupleMap::COLLAPSE_FIRST
1031 coupleMap::COLLAPSE_SECOND
1042 coupleMap::COLLAPSE_MIDPOINT
1052 setCoupledModification();
1054 // The final operation has to succeed.
1055 if (slaveMap.type() <= 0)
1061 "dynamicTopoFvMesh::collapseQuadFace\n"
1063 " const label fIndex,\n"
1064 " label overRideCase,\n"
1065 " bool checkOnly,\n"
1069 << "Coupled topo-change for slave failed." << nl
1070 << " Face: " << fIndex << ": " << fCheck << nl
1071 << " Slave index: " << sIndex << nl
1072 << " Patch index: " << pI << nl
1073 << " Type: " << slaveMap.type() << nl
1074 << abort(FatalError);
1077 // Save index and patch for posterity
1078 slaveMap.index() = sIndex;
1079 slaveMap.patchIndex() = pI;
1083 // Build a hull of cells and tri-faces that are connected to each edge
1084 FixedList<labelList, 2> hullCells;
1085 FixedList<labelList, 2> hullTriFaces;
1087 meshOps::constructPrismHull
1099 meshOps::constructPrismHull
1111 // Determine the neighbouring cells
1112 label c0 = owner_[fIndex], c1 = neighbour_[fIndex];
1114 // Define variables for the prism-face calculation
1115 FixedList<label,2> c0BdyIndex(-1), c0IntIndex(-1);
1116 FixedList<label,2> c1BdyIndex(-1), c1IntIndex(-1);
1117 FixedList<face,2> c0BdyFace(face(3)), c0IntFace(face(4));
1118 FixedList<face,2> c1BdyFace(face(3)), c1IntFace(face(4));
1120 // Find the prism-faces
1121 meshOps::findPrismFaces
1136 meshOps::findPrismFaces
1150 // Determine if either edge belongs to a boundary
1151 FixedList<bool, 2> nBoundCurves(false), edgeBoundary(false);
1153 edgeBoundary[0] = (whichEdgePatch(checkEdgeIndex[1]) > -1);
1154 edgeBoundary[1] = (whichEdgePatch(checkEdgeIndex[2]) > -1);
1156 // Decide on collapseCase
1157 label collapseCase = -1;
1159 if (edgeBoundary[0] && !edgeBoundary[1])
1164 if (!edgeBoundary[0] && edgeBoundary[1])
1169 if (edgeBoundary[0] && edgeBoundary[1])
1179 "dynamicTopoFvMesh::collapseQuadFace\n"
1181 " const label fIndex,\n"
1182 " label overRideCase,\n"
1183 " bool checkOnly,\n"
1186 ) << "Collapsing an internal face that "
1187 << "lies on two boundary patches. "
1188 << "Face: " << fIndex << ": " << faces_[fIndex]
1192 // Bail out for now. If proximity based refinement is
1193 // switched on, mesh may be sliced at this point.
1197 // Check if either edge lies on a bounding curve.
1198 if (checkBoundingCurve(checkEdgeIndex[1]))
1200 nBoundCurves[0] = true;
1203 if (checkBoundingCurve(checkEdgeIndex[2]))
1205 nBoundCurves[1] = true;
1208 // Collapse towards a bounding curve
1209 if (nBoundCurves[0] && !nBoundCurves[1])
1214 if (!nBoundCurves[0] && nBoundCurves[1])
1219 if (!nBoundCurves[0] && !nBoundCurves[1])
1221 // No bounding curves. Collapse to mid-point.
1226 // Two bounding curves? This might cause pinching.
1227 // Bail out for now.
1233 // Looks like this is an interior face.
1234 // Collapse case [3] by default
1238 // Perform an override if requested.
1239 if (overRideCase != -1)
1241 collapseCase = overRideCase;
1244 // Configure the new point-positions
1245 FixedList<bool, 2> check(false);
1246 FixedList<FixedList<label, 2>, 2> checkPoints(FixedList<label, 2>(-1));
1247 FixedList<point, 2> newPoint(vector::zero);
1248 FixedList<point, 2> oldPoint(vector::zero);
1250 // Replacement check points
1251 FixedList<label,2> original(-1), replacement(-1);
1253 switch (collapseCase)
1257 // Collapse to the first node
1258 original[0] = cv2; original[1] = cv3;
1259 replacement[0] = cv0; replacement[1] = cv1;
1261 newPoint[0] = points_[replacement[0]];
1262 newPoint[1] = points_[replacement[1]];
1264 oldPoint[0] = oldPoints_[replacement[0]];
1265 oldPoint[1] = oldPoints_[replacement[1]];
1267 // Define check-points
1269 checkPoints[1][0] = original[0];
1270 checkPoints[1][1] = original[1];
1277 // Collapse to the second node
1278 original[0] = cv0; original[1] = cv1;
1279 replacement[0] = cv2; replacement[1] = cv3;
1281 newPoint[0] = points_[replacement[0]];
1282 newPoint[1] = points_[replacement[1]];
1284 oldPoint[0] = oldPoints_[replacement[0]];
1285 oldPoint[1] = oldPoints_[replacement[1]];
1287 // Define check-points
1289 checkPoints[0][0] = original[0];
1290 checkPoints[0][1] = original[1];
1297 // Collapse to the mid-point
1298 original[0] = cv0; original[1] = cv1;
1299 replacement[0] = cv2; replacement[1] = cv3;
1301 // Define new point-positions
1306 points_[original[0]]
1307 + points_[replacement[0]]
1315 points_[original[1]]
1316 + points_[replacement[1]]
1320 // Define old point-positions
1325 oldPoints_[original[0]]
1326 + oldPoints_[replacement[0]]
1334 oldPoints_[original[1]]
1335 + oldPoints_[replacement[1]]
1339 // Define check-points
1341 checkPoints[0][0] = original[0];
1342 checkPoints[0][1] = original[1];
1345 checkPoints[1][0] = replacement[0];
1346 checkPoints[1][1] = replacement[1];
1353 // Don't think this will ever happen.
1358 "dynamicTopoFvMesh::collapseQuadFace\n"
1360 " const label fIndex,\n"
1361 " label overRideCase,\n"
1362 " bool checkOnly,\n"
1366 << "Edge: " << fIndex << ": " << faces_[fIndex]
1367 << ". Couldn't decide on collapseCase."
1368 << abort(FatalError);
1374 // Keep track of resulting cell quality,
1375 // if collapse is indeed feasible
1376 scalar collapseQuality(GREAT);
1378 // Check collapsibility of cells around edges
1379 // with the re-configured point
1380 forAll(check, indexI)
1387 // Check whether the collapse is possible.
1393 hullTriFaces[indexI],
1396 checkPoints[indexI],
1410 // Add a map entry of the replacements as 'addedPoints'
1411 // - Used in coupled mapping
1412 map.addPoint(replacement[0]);
1413 map.addPoint(replacement[1]);
1415 // Are we only performing checks?
1418 map.type() = collapseCase;
1422 Pout<< "Face: " << fIndex
1423 << ":: " << faces_[fIndex] << nl
1424 << " collapseCase determined to be: " << collapseCase << nl
1425 << " Resulting quality: " << collapseQuality << nl
1426 << " edgeBoundary: " << edgeBoundary << nl
1427 << " nBoundCurves: " << nBoundCurves << nl
1428 << " collapsePoints: " << original << nl
1429 << " replacePoints: " << replacement << nl
1438 const labelList& fE = faceEdges_[fIndex];
1441 << "Face: " << fIndex << ": " << faces_[fIndex] << nl
1442 << "faceEdges: " << fE << " is to be collapsed. "
1445 Pout<< " On SubMesh: " << isSubMesh_ << nl;
1446 Pout<< " coupledModification: " << coupledModification_ << nl;
1448 label epIndex = whichPatch(fIndex);
1450 const polyBoundaryMesh& boundary = boundaryMesh();
1456 Pout<< "Internal" << nl;
1459 if (epIndex < boundary.size())
1461 Pout<< boundary[epIndex].name() << nl;
1465 Pout<< " New patch: " << epIndex << endl;
1471 << "~~~~~~~~~~~~~~~~~~~~~~~~~" << nl
1472 << "Hulls before modification" << nl
1473 << "~~~~~~~~~~~~~~~~~~~~~~~~~" << nl;
1477 Pout<< "Cell [0] Boundary faces: " << nl
1478 << " Face: "<< c0BdyIndex[0]
1479 << "::" << c0BdyFace[0] << nl
1480 << " Face: "<< c0BdyIndex[1]
1481 << "::" << c0BdyFace[1] << nl;
1483 Pout<< "Cell [0] Interior faces: " << nl
1484 << " Face: "<< c0IntIndex[0]
1485 << "::" << c0IntFace[0] << nl
1486 << " Face: "<< c0IntIndex[1]
1487 << "::" << c0IntFace[1] << nl;
1491 Pout<< "Cell [1] Boundary faces: " << nl
1492 << " Face: "<< c1BdyIndex[0]
1493 << "::" << c1BdyFace[0] << nl
1494 << " Face: "<< c1BdyIndex[1]
1495 << "::" << c1BdyFace[1] << nl;
1497 Pout<< "Cell [1] Interior faces: " << nl
1498 << " Face: "<< c1IntIndex[0]
1499 << "::" << c1IntFace[0] << nl
1500 << " Face: "<< c1IntIndex[1]
1501 << "::" << c1IntFace[1] << nl;
1505 Pout<< nl << "Cells belonging to first Edge Hull: "
1506 << hullCells[0] << nl;
1508 forAll(hullCells[0],cellI)
1510 const cell& firstCurCell = cells_[hullCells[0][cellI]];
1512 Pout<< "Cell: " << hullCells[0][cellI]
1513 << ": " << firstCurCell << nl;
1515 forAll(firstCurCell,faceI)
1517 Pout<< " Face: " << firstCurCell[faceI]
1518 << " : " << faces_[firstCurCell[faceI]]
1519 << " fE: " << faceEdges_[firstCurCell[faceI]]
1524 const labelList& fE = faceEdges_[firstCurCell[faceI]];
1528 Pout<< " Edge: " << fE[edgeI]
1529 << " : " << edges_[fE[edgeI]]
1536 const labelList& firstEdgeFaces = edgeFaces_[checkEdgeIndex[1]];
1538 Pout<< nl << "First Edge Face Hull: "
1539 << firstEdgeFaces << nl;
1541 forAll(firstEdgeFaces,indexI)
1543 Pout<< " Face: " << firstEdgeFaces[indexI]
1544 << " : " << faces_[firstEdgeFaces[indexI]]
1545 << " fE: " << faceEdges_[firstEdgeFaces[indexI]]
1550 const labelList& fE = faceEdges_[firstEdgeFaces[indexI]];
1554 Pout<< " Edge: " << fE[edgeI]
1555 << " : " << edges_[fE[edgeI]]
1561 Pout<< nl << "Cells belonging to second Edge Hull: "
1562 << hullCells[1] << nl;
1564 forAll(hullCells[1], cellI)
1566 const cell& secondCurCell = cells_[hullCells[1][cellI]];
1568 Pout<< "Cell: " << hullCells[1][cellI]
1569 << ": " << secondCurCell << nl;
1571 forAll(secondCurCell, faceI)
1573 Pout<< " Face: " << secondCurCell[faceI]
1574 << " : " << faces_[secondCurCell[faceI]]
1575 << " fE: " << faceEdges_[secondCurCell[faceI]]
1580 const labelList& fE = faceEdges_[secondCurCell[faceI]];
1584 Pout<< " Edge: " << fE[edgeI]
1585 << " : " << edges_[fE[edgeI]]
1592 const labelList& secondEdgeFaces = edgeFaces_[checkEdgeIndex[2]];
1594 Pout<< nl << "Second Edge Face Hull: "
1595 << secondEdgeFaces << nl;
1597 forAll(secondEdgeFaces, indexI)
1599 Pout<< " Face: " << secondEdgeFaces[indexI]
1600 << " : " << faces_[secondEdgeFaces[indexI]]
1601 << " fE: " << faceEdges_[secondEdgeFaces[indexI]]
1606 const labelList& fE = faceEdges_[secondEdgeFaces[indexI]];
1610 Pout<< " Edge: " << fE[edgeI]
1611 << " : " << edges_[fE[edgeI]]
1617 // Write out VTK files prior to change
1620 labelHashSet vtkCells;
1622 forAll(hullCells[0], cellI)
1624 if (!vtkCells.found(hullCells[0][cellI]))
1626 vtkCells.insert(hullCells[0][cellI]);
1630 forAll(hullCells[1], cellI)
1632 if (!vtkCells.found(hullCells[1][cellI]))
1634 vtkCells.insert(hullCells[1][cellI]);
1649 // Edges / Quad-faces to throw or keep during collapse
1650 FixedList<label,2> ends(-1);
1651 FixedList<label,2> faceToKeep(-1), faceToThrow(-1);
1652 FixedList<label,4> edgeToKeep(-1), edgeToThrow(-1);
1654 // Maintain a list of modified faces for mapping
1655 dynamicLabelList modifiedFaces(10);
1657 // Case 2 & 3 use identical connectivity,
1658 // but different point locations
1659 if (collapseCase == 2 || collapseCase == 3)
1661 const labelList& firstEdgeFaces = edgeFaces_[checkEdgeIndex[1]];
1663 // Collapse to the second node...
1664 forAll(firstEdgeFaces,faceI)
1666 // Replace point indices on faces.
1667 meshOps::replaceLabel
1671 faces_[firstEdgeFaces[faceI]]
1674 meshOps::replaceLabel
1678 faces_[firstEdgeFaces[faceI]]
1681 // Add an entry for mapping
1682 if (findIndex(modifiedFaces, firstEdgeFaces[faceI]) == -1)
1684 modifiedFaces.append(firstEdgeFaces[faceI]);
1687 // Determine the quad-face in cell[0] & cell[1]
1688 // that belongs to firstEdgeFaces
1689 if (firstEdgeFaces[faceI] == c0IntIndex[0])
1691 faceToKeep[0] = c0IntIndex[1];
1692 faceToThrow[0] = c0IntIndex[0];
1695 if (firstEdgeFaces[faceI] == c0IntIndex[1])
1697 faceToKeep[0] = c0IntIndex[0];
1698 faceToThrow[0] = c0IntIndex[1];
1703 if (firstEdgeFaces[faceI] == c1IntIndex[0])
1705 faceToKeep[1] = c1IntIndex[1];
1706 faceToThrow[1] = c1IntIndex[0];
1709 if (firstEdgeFaces[faceI] == c1IntIndex[1])
1711 faceToKeep[1] = c1IntIndex[0];
1712 faceToThrow[1] = c1IntIndex[1];
1717 // Find common edges between quad / tri faces...
1718 meshOps::findCommonEdge
1726 meshOps::findCommonEdge
1734 meshOps::findCommonEdge
1742 meshOps::findCommonEdge
1750 // Size down edgeFaces for the ends.
1751 meshOps::findCommonEdge
1759 meshOps::sizeDownList
1767 meshOps::findCommonEdge
1775 meshOps::findCommonEdge
1783 meshOps::findCommonEdge
1791 meshOps::findCommonEdge
1799 // Size down edgeFaces for the ends.
1800 meshOps::findCommonEdge
1808 meshOps::sizeDownList
1815 // Correct edgeFaces for triangular faces...
1816 forAll(edgeToThrow, indexI)
1818 if (edgeToThrow[indexI] == -1)
1823 const labelList& eF = edgeFaces_[edgeToThrow[indexI]];
1825 label origTriFace = -1, retTriFace = -1;
1827 // Find the original triangular face index
1830 if (eF[faceI] == c0BdyIndex[0])
1832 origTriFace = c0BdyIndex[0];
1836 if (eF[faceI] == c0BdyIndex[1])
1838 origTriFace = c0BdyIndex[1];
1842 if (eF[faceI] == c1BdyIndex[0])
1844 origTriFace = c1BdyIndex[0];
1848 if (eF[faceI] == c1BdyIndex[1])
1850 origTriFace = c1BdyIndex[1];
1855 // Find the retained triangular face index
1860 (eF[faceI] != origTriFace) &&
1861 (eF[faceI] != faceToThrow[0]) &&
1862 (eF[faceI] != faceToThrow[1])
1865 retTriFace = eF[faceI];
1870 // Finally replace the face index
1871 if (retTriFace == -1)
1873 // Couldn't find a retained face.
1874 // This must be a boundary edge, so size-down instead.
1875 meshOps::sizeDownList
1878 edgeFaces_[edgeToKeep[indexI]]
1883 meshOps::replaceLabel
1887 edgeFaces_[edgeToKeep[indexI]]
1890 meshOps::replaceLabel
1892 edgeToThrow[indexI],
1894 faceEdges_[retTriFace]
1899 // Correct faceEdges / edgeFaces for quad-faces...
1900 forAll(firstEdgeFaces,faceI)
1902 meshOps::replaceLabel
1906 faceEdges_[firstEdgeFaces[faceI]]
1909 // Renumber the edges on this face
1910 const labelList& fE = faceEdges_[firstEdgeFaces[faceI]];
1914 if (edges_[fE[edgeI]].start() == cv0)
1916 edges_[fE[edgeI]].start() = cv2;
1919 if (edges_[fE[edgeI]].end() == cv0)
1921 edges_[fE[edgeI]].end() = cv2;
1924 if (edges_[fE[edgeI]].start() == cv1)
1926 edges_[fE[edgeI]].start() = cv3;
1929 if (edges_[fE[edgeI]].end() == cv1)
1931 edges_[fE[edgeI]].end() = cv3;
1935 // Size-up edgeFaces for the replacement
1938 (firstEdgeFaces[faceI] != faceToThrow[0]) &&
1939 (firstEdgeFaces[faceI] != faceToThrow[1]) &&
1940 (firstEdgeFaces[faceI] != fIndex)
1945 firstEdgeFaces[faceI],
1946 edgeFaces_[checkEdgeIndex[2]]
1951 // Remove the current face from the replacement edge
1952 meshOps::sizeDownList
1955 edgeFaces_[checkEdgeIndex[2]]
1958 // Replace point labels on all triangular boundary faces.
1959 forAll(hullCells[0],cellI)
1961 const cell& cellToCheck = cells_[hullCells[0][cellI]];
1963 forAll(cellToCheck,faceI)
1965 face& faceToCheck = faces_[cellToCheck[faceI]];
1967 if (faceToCheck.size() == 3)
1969 forAll(faceToCheck,pointI)
1971 if (faceToCheck[pointI] == cv0)
1973 faceToCheck[pointI] = cv2;
1976 if (faceToCheck[pointI] == cv1)
1978 faceToCheck[pointI] = cv3;
1985 // Now that we're done with all edges, remove them.
1986 removeEdge(checkEdgeIndex[0]);
1987 removeEdge(checkEdgeIndex[1]);
1988 removeEdge(checkEdgeIndex[3]);
1991 map.removeEdge(checkEdgeIndex[0]);
1992 map.removeEdge(checkEdgeIndex[1]);
1993 map.removeEdge(checkEdgeIndex[2]);
1995 forAll(edgeToThrow, indexI)
1997 if (edgeToThrow[indexI] == -1)
2002 removeEdge(edgeToThrow[indexI]);
2005 map.removeEdge(edgeToThrow[indexI]);
2008 // Delete the two points...
2013 map.removePoint(cv0);
2014 map.removePoint(cv1);
2018 const labelList& secondEdgeFaces = edgeFaces_[checkEdgeIndex[2]];
2020 // Collapse to the first node
2021 forAll(secondEdgeFaces,faceI)
2023 // Replace point indices on faces.
2024 meshOps::replaceLabel
2028 faces_[secondEdgeFaces[faceI]]
2031 meshOps::replaceLabel
2035 faces_[secondEdgeFaces[faceI]]
2038 // Add an entry for mapping
2039 if (findIndex(modifiedFaces, secondEdgeFaces[faceI]) == -1)
2041 modifiedFaces.append(secondEdgeFaces[faceI]);
2044 // Determine the quad-face(s) in cell[0] & cell[1]
2045 // that belongs to secondEdgeFaces
2046 if (secondEdgeFaces[faceI] == c0IntIndex[0])
2048 faceToKeep[0] = c0IntIndex[1];
2049 faceToThrow[0] = c0IntIndex[0];
2052 if (secondEdgeFaces[faceI] == c0IntIndex[1])
2054 faceToKeep[0] = c0IntIndex[0];
2055 faceToThrow[0] = c0IntIndex[1];
2060 if (secondEdgeFaces[faceI] == c1IntIndex[0])
2062 faceToKeep[1] = c1IntIndex[1];
2063 faceToThrow[1] = c1IntIndex[0];
2066 if (secondEdgeFaces[faceI] == c1IntIndex[1])
2068 faceToKeep[1] = c1IntIndex[0];
2069 faceToThrow[1] = c1IntIndex[1];
2074 // Find common edges between quad / tri faces...
2075 meshOps::findCommonEdge
2083 meshOps::findCommonEdge
2091 meshOps::findCommonEdge
2099 meshOps::findCommonEdge
2107 // Size down edgeFaces for the ends.
2108 meshOps::findCommonEdge
2116 meshOps::sizeDownList
2124 meshOps::findCommonEdge
2132 meshOps::findCommonEdge
2140 meshOps::findCommonEdge
2148 meshOps::findCommonEdge
2156 // Size down edgeFaces for the ends.
2157 meshOps::findCommonEdge
2165 meshOps::sizeDownList
2172 // Correct edgeFaces for triangular faces...
2173 forAll(edgeToThrow, indexI)
2175 if (edgeToThrow[indexI] == -1)
2180 const labelList& eF = edgeFaces_[edgeToThrow[indexI]];
2182 label origTriFace = -1, retTriFace = -1;
2184 // Find the original triangular face index
2187 if (eF[faceI] == c0BdyIndex[0])
2189 origTriFace = c0BdyIndex[0];
2193 if (eF[faceI] == c0BdyIndex[1])
2195 origTriFace = c0BdyIndex[1];
2199 if (eF[faceI] == c1BdyIndex[0])
2201 origTriFace = c1BdyIndex[0];
2205 if (eF[faceI] == c1BdyIndex[1])
2207 origTriFace = c1BdyIndex[1];
2212 // Find the retained triangular face index
2217 (eF[faceI] != origTriFace) &&
2218 (eF[faceI] != faceToThrow[0]) &&
2219 (eF[faceI] != faceToThrow[1])
2222 retTriFace = eF[faceI];
2227 // Finally replace the face/edge indices
2228 if (retTriFace == -1)
2230 // Couldn't find a retained face.
2231 // This must be a boundary edge, so size-down instead.
2232 meshOps::sizeDownList
2235 edgeFaces_[edgeToKeep[indexI]]
2240 meshOps::replaceLabel
2244 edgeFaces_[edgeToKeep[indexI]]
2247 meshOps::replaceLabel
2249 edgeToThrow[indexI],
2251 faceEdges_[retTriFace]
2256 // Correct faceEdges / edgeFaces for quad-faces...
2257 forAll(secondEdgeFaces,faceI)
2259 meshOps::replaceLabel
2263 faceEdges_[secondEdgeFaces[faceI]]
2266 // Renumber the edges on this face
2267 const labelList& fE = faceEdges_[secondEdgeFaces[faceI]];
2271 if (edges_[fE[edgeI]].start() == cv2)
2273 edges_[fE[edgeI]].start() = cv0;
2276 if (edges_[fE[edgeI]].end() == cv2)
2278 edges_[fE[edgeI]].end() = cv0;
2281 if (edges_[fE[edgeI]].start() == cv3)
2283 edges_[fE[edgeI]].start() = cv1;
2286 if (edges_[fE[edgeI]].end() == cv3)
2288 edges_[fE[edgeI]].end() = cv1;
2292 // Size-up edgeFaces for the replacement
2295 (secondEdgeFaces[faceI] != faceToThrow[0]) &&
2296 (secondEdgeFaces[faceI] != faceToThrow[1]) &&
2297 (secondEdgeFaces[faceI] != fIndex)
2302 secondEdgeFaces[faceI],
2303 edgeFaces_[checkEdgeIndex[1]]
2308 // Remove the current face from the replacement edge
2309 meshOps::sizeDownList
2312 edgeFaces_[checkEdgeIndex[1]]
2315 // Replace point labels on all triangular boundary faces.
2316 forAll(hullCells[1], cellI)
2318 const cell& cellToCheck = cells_[hullCells[1][cellI]];
2320 forAll(cellToCheck, faceI)
2322 face& faceToCheck = faces_[cellToCheck[faceI]];
2324 if (faceToCheck.size() == 3)
2326 forAll(faceToCheck, pointI)
2328 if (faceToCheck[pointI] == cv2)
2330 faceToCheck[pointI] = cv0;
2333 if (faceToCheck[pointI] == cv3)
2335 faceToCheck[pointI] = cv1;
2342 // Now that we're done with all edges, remove them.
2343 removeEdge(checkEdgeIndex[0]);
2344 removeEdge(checkEdgeIndex[2]);
2345 removeEdge(checkEdgeIndex[3]);
2348 map.removeEdge(checkEdgeIndex[0]);
2349 map.removeEdge(checkEdgeIndex[2]);
2350 map.removeEdge(checkEdgeIndex[3]);
2352 forAll(edgeToThrow, indexI)
2354 if (edgeToThrow[indexI] == -1)
2359 removeEdge(edgeToThrow[indexI]);
2362 map.removeEdge(edgeToThrow[indexI]);
2365 // Delete the two points...
2370 map.removePoint(cv2);
2371 map.removePoint(cv3);
2377 << "~~~~~~~~~~~~~~~~~~~~~~~~" << nl
2378 << "Hulls after modification" << nl
2379 << "~~~~~~~~~~~~~~~~~~~~~~~~" << nl;
2381 Pout<< nl << "Cells belonging to first Edge Hull: "
2382 << hullCells[0] << nl;
2384 forAll(hullCells[0], cellI)
2386 const cell& firstCurCell = cells_[hullCells[0][cellI]];
2388 Pout<< "Cell: " << hullCells[0][cellI]
2389 << ": " << firstCurCell << nl;
2391 forAll(firstCurCell, faceI)
2393 Pout<< " Face: " << firstCurCell[faceI]
2394 << " : " << faces_[firstCurCell[faceI]]
2395 << " fE: " << faceEdges_[firstCurCell[faceI]]
2400 const labelList& firstEdgeFaces = edgeFaces_[checkEdgeIndex[1]];
2402 Pout<< nl << "First Edge Face Hull: " << firstEdgeFaces << nl;
2404 forAll(firstEdgeFaces, indexI)
2406 Pout<< " Face: " << firstEdgeFaces[indexI]
2407 << " : " << faces_[firstEdgeFaces[indexI]]
2408 << " fE: " << faceEdges_[firstEdgeFaces[indexI]]
2412 Pout<< nl << "Cells belonging to second Edge Hull: "
2413 << hullCells[1] << nl;
2415 forAll(hullCells[1], cellI)
2417 const cell& secondCurCell = cells_[hullCells[1][cellI]];
2419 Pout<< "Cell: " << hullCells[1][cellI]
2420 << ": " << secondCurCell << nl;
2422 forAll(secondCurCell, faceI)
2424 Pout<< " Face: " << secondCurCell[faceI]
2425 << " : " << faces_[secondCurCell[faceI]]
2426 << " fE: " << faceEdges_[secondCurCell[faceI]]
2431 const labelList& secondEdgeFaces = edgeFaces_[checkEdgeIndex[2]];
2433 Pout<< nl << "Second Edge Face Hull: " << secondEdgeFaces << nl;
2435 forAll(secondEdgeFaces, indexI)
2437 Pout<< " Face : " << secondEdgeFaces[indexI]
2438 << " : " << faces_[secondEdgeFaces[indexI]]
2439 << " fE: " << faceEdges_[secondEdgeFaces[indexI]]
2443 Pout<< "Retained face: "
2444 << faceToKeep[0] << ": "
2445 << " owner: " << owner_[faceToKeep[0]]
2446 << " neighbour: " << neighbour_[faceToKeep[0]]
2449 Pout<< "Discarded face: "
2450 << faceToThrow[0] << ": "
2451 << " owner: " << owner_[faceToThrow[0]]
2452 << " neighbour: " << neighbour_[faceToThrow[0]]
2457 Pout<< "Retained face: "
2458 << faceToKeep[1] << ": "
2459 << " owner: " << owner_[faceToKeep[1]]
2460 << " neighbour: " << neighbour_[faceToKeep[1]]
2463 Pout<< "Discarded face: "
2464 << faceToThrow[1] << ": "
2465 << " owner: " << owner_[faceToThrow[1]]
2466 << " neighbour: " << neighbour_[faceToThrow[1]]
2473 // Ensure proper orientation for the two retained faces
2474 FixedList<label,2> cellCheck(0);
2476 if (owner_[faceToThrow[0]] == c0)
2478 cellCheck[0] = neighbour_[faceToThrow[0]];
2480 if (owner_[faceToKeep[0]] == c0)
2484 (neighbour_[faceToThrow[0]] > neighbour_[faceToKeep[0]])
2485 && (neighbour_[faceToKeep[0]] != -1)
2488 // This face is to be flipped
2489 faces_[faceToKeep[0]] =
2491 faces_[faceToKeep[0]].reverseFace()
2494 owner_[faceToKeep[0]] = neighbour_[faceToKeep[0]];
2495 neighbour_[faceToKeep[0]] = neighbour_[faceToThrow[0]];
2497 setFlip(faceToKeep[0]);
2501 if (neighbour_[faceToThrow[0]] != -1)
2503 // Keep orientation intact, and update the owner
2504 owner_[faceToKeep[0]] = neighbour_[faceToThrow[0]];
2508 // This face will need to be flipped and converted
2509 // to a boundary face. Flip it now, so that conversion
2511 faces_[faceToKeep[0]] =
2513 faces_[faceToKeep[0]].reverseFace()
2516 owner_[faceToKeep[0]] = neighbour_[faceToKeep[0]];
2517 neighbour_[faceToKeep[0]] = -1;
2519 setFlip(faceToKeep[0]);
2525 // Keep orientation intact, and update the neighbour
2526 neighbour_[faceToKeep[0]] = neighbour_[faceToThrow[0]];
2531 cellCheck[0] = owner_[faceToThrow[0]];
2533 if (neighbour_[faceToKeep[0]] == c0)
2535 if (owner_[faceToThrow[0]] < owner_[faceToKeep[0]])
2537 // This face is to be flipped
2538 faces_[faceToKeep[0]] =
2540 faces_[faceToKeep[0]].reverseFace()
2543 neighbour_[faceToKeep[0]] = owner_[faceToKeep[0]];
2544 owner_[faceToKeep[0]] = owner_[faceToThrow[0]];
2546 setFlip(faceToKeep[0]);
2550 // Keep orientation intact, and update the neighbour
2551 neighbour_[faceToKeep[0]] = owner_[faceToThrow[0]];
2556 // Keep orientation intact, and update the owner
2557 owner_[faceToKeep[0]] = owner_[faceToThrow[0]];
2563 if (owner_[faceToThrow[1]] == c1)
2565 cellCheck[1] = neighbour_[faceToThrow[1]];
2567 if (owner_[faceToKeep[1]] == c1)
2571 (neighbour_[faceToThrow[1]] > neighbour_[faceToKeep[1]])
2572 && (neighbour_[faceToKeep[1]] != -1)
2575 // This face is to be flipped
2576 faces_[faceToKeep[1]] =
2578 faces_[faceToKeep[1]].reverseFace()
2581 owner_[faceToKeep[1]] = neighbour_[faceToKeep[1]];
2582 neighbour_[faceToKeep[1]] = neighbour_[faceToThrow[1]];
2584 setFlip(faceToKeep[1]);
2588 if (neighbour_[faceToThrow[1]] != -1)
2590 // Keep orientation intact, and update the owner
2591 owner_[faceToKeep[1]] = neighbour_[faceToThrow[1]];
2595 // This face will need to be flipped and converted
2596 // to a boundary face. Flip it now, so that conversion
2598 faces_[faceToKeep[1]] =
2600 faces_[faceToKeep[1]].reverseFace()
2603 owner_[faceToKeep[1]] = neighbour_[faceToKeep[1]];
2604 neighbour_[faceToKeep[1]] = -1;
2606 setFlip(faceToKeep[1]);
2612 // Keep orientation intact, and update the neighbour
2613 neighbour_[faceToKeep[1]] = neighbour_[faceToThrow[1]];
2618 cellCheck[1] = owner_[faceToThrow[1]];
2620 if (neighbour_[faceToKeep[1]] == c1)
2622 if (owner_[faceToThrow[1]] < owner_[faceToKeep[1]])
2624 // This face is to be flipped
2625 faces_[faceToKeep[1]] =
2627 faces_[faceToKeep[1]].reverseFace()
2630 neighbour_[faceToKeep[1]] = owner_[faceToKeep[1]];
2631 owner_[faceToKeep[1]] = owner_[faceToThrow[1]];
2633 setFlip(faceToKeep[1]);
2637 // Keep orientation intact, and update the neighbour
2638 neighbour_[faceToKeep[1]] = owner_[faceToThrow[1]];
2643 // Keep orientation intact, and update the owner
2644 owner_[faceToKeep[1]] = owner_[faceToThrow[1]];
2649 // Remove orphaned faces
2650 if (owner_[faceToKeep[0]] == -1)
2652 const face& keepFace = faces_[faceToKeep[0]];
2653 const labelList& rmFE = faceEdges_[faceToKeep[0]];
2655 labelList keepPoints(keepFace.size(), 0);
2659 label eIndex = rmFE[edgeI];
2660 labelList& eFaces = edgeFaces_[eIndex];
2661 const edge& checkEdge = edges_[eIndex];
2665 (eFaces.size() == 1) &&
2666 (eFaces[0] == faceToKeep[0])
2669 // This edge has to be removed entirely.
2673 map.removeEdge(eIndex);
2678 keepPoints[keepFace.which(checkEdge[0])] = 1;
2679 keepPoints[keepFace.which(checkEdge[1])] = 1;
2681 // Size-down edgeFaces
2682 meshOps::sizeDownList
2690 // Check if processor patches are being
2691 // converted into physical ones
2693 label kfPatch = whichPatch(faceToKeep[0]);
2694 label rfPatch = whichPatch(faceToThrow[0]);
2698 (getNeighbourProcessor(kfPatch) == -1) &&
2699 ((neiProc = getNeighbourProcessor(rfPatch)) > -1)
2704 // If this is a subMesh, and faceToKeep is on
2705 // a physical boundary, make a 'special' entry
2706 // for coupled mapping purposes.
2710 labelList(1, (-2 - kfPatch))
2715 // This is a wierd overhanging cell on the master
2716 // processor which is being removed entirely.
2717 // Since the processor patch face is being converted
2718 // to a physical one, the slave processor needs to
2719 // be notified of the change.
2720 forAll(procIndices_, pI)
2722 if (procIndices_[pI] == neiProc)
2724 // Find slave index from the face map
2725 const coupleMap& cMap = recvMeshes_[pI].map();
2736 if (replaceFace == -1)
2738 // Something is wrong here.
2739 Pout<< " Could not find slave face for: " << nl
2740 << " Master face: " << faceToThrow[0]
2741 << " :: " << faces_[faceToThrow[0]] << nl
2742 << " on proc: " << procIndices_[pI] << nl
2743 << " on converting to patch: " << kfPatch
2744 << abort(FatalError);
2750 coupleMap::CONVERT_PHYSICAL,
2760 // Remove unused points
2761 forAll(keepPoints, pointI)
2763 if (keepPoints[pointI] == 0)
2765 removePoint(keepFace[pointI]);
2766 map.removePoint(keepFace[pointI]);
2771 removeFace(faceToKeep[0]);
2774 map.removeFace(faceToKeep[0]);
2779 (neighbour_[faceToKeep[0]] == -1)
2780 && (whichPatch(faceToKeep[0]) < 0)
2783 // Obtain a copy before adding the new face,
2784 // since the reference might become invalid during list resizing.
2785 face newFace = faces_[faceToKeep[0]];
2786 label newOwn = owner_[faceToKeep[0]];
2787 labelList newFaceEdges = faceEdges_[faceToKeep[0]];
2789 // This face is being converted from interior to boundary. Remove
2790 // from the interior list and add as a boundary face to the end.
2791 // Edges don't have to change, since they're all on the boundary anyway.
2792 label newFaceIndex =
2796 whichPatch(faceToThrow[0]),
2804 // Add an entry for mapping
2805 modifiedFaces.append(newFaceIndex);
2808 map.addFace(newFaceIndex, labelList(1, faceToThrow[0]));
2810 meshOps::replaceLabel
2817 // Correct edgeFaces with the new face label.
2818 forAll(newFaceEdges, edgeI)
2820 meshOps::replaceLabel
2824 edgeFaces_[newFaceEdges[edgeI]]
2828 // Renumber the neighbour so that this face is removed correctly.
2829 neighbour_[faceToKeep[0]] = 0;
2830 removeFace(faceToKeep[0]);
2833 map.removeFace(faceToKeep[0]);
2836 // Remove the unwanted faces in the cell(s) adjacent to this face,
2837 // and correct the cells that contain discarded faces
2838 const cell& cell_0 = cells_[c0];
2840 forAll(cell_0,faceI)
2842 if (cell_0[faceI] != fIndex && cell_0[faceI] != faceToKeep[0])
2844 removeFace(cell_0[faceI]);
2847 map.removeFace(cell_0[faceI]);
2851 if (cellCheck[0] != -1)
2853 meshOps::replaceLabel
2857 cells_[cellCheck[0]]
2869 // Increment the surface-collapse counter
2870 status(SURFACE_COLLAPSES)++;
2874 // Remove orphaned faces
2875 if (owner_[faceToKeep[1]] == -1)
2877 const face& keepFace = faces_[faceToKeep[1]];
2878 const labelList& rmFE = faceEdges_[faceToKeep[1]];
2880 labelList keepPoints(keepFace.size(), 0);
2884 label eIndex = rmFE[edgeI];
2885 labelList& eFaces = edgeFaces_[eIndex];
2886 const edge& checkEdge = edges_[eIndex];
2890 (eFaces.size() == 1) &&
2891 (eFaces[0] == faceToKeep[1])
2894 // This edge has to be removed entirely.
2898 map.removeEdge(eIndex);
2903 keepPoints[keepFace.which(checkEdge[0])] = 1;
2904 keepPoints[keepFace.which(checkEdge[1])] = 1;
2906 // Size-down edgeFaces
2907 meshOps::sizeDownList
2915 // Check if processor patches are being
2916 // converted into physical ones
2918 label kfPatch = whichPatch(faceToKeep[1]);
2919 label rfPatch = whichPatch(faceToThrow[1]);
2923 (getNeighbourProcessor(kfPatch) == -1) &&
2924 ((neiProc = getNeighbourProcessor(rfPatch)) > -1)
2929 // If this is a subMesh, and faceToKeep is on
2930 // a physical boundary, make a 'special' entry
2931 // for coupled mapping purposes.
2935 labelList(1, (-2 - kfPatch))
2940 // This is a wierd overhanging cell on the master
2941 // processor which is being removed entirely.
2942 // Since the processor patch face is being converted
2943 // to a physical one, the slave processor needs to
2944 // be notified of the change.
2945 forAll(procIndices_, pI)
2947 if (procIndices_[pI] == neiProc)
2949 // Find slave index from the face map
2950 const coupleMap& cMap = recvMeshes_[pI].map();
2961 if (replaceFace == -1)
2963 // Something is wrong here.
2964 Pout<< " Could not find slave face for: " << nl
2965 << " Master face: " << faceToThrow[1]
2966 << " :: " << faces_[faceToThrow[1]] << nl
2967 << " on proc: " << procIndices_[pI] << nl
2968 << " on converting to patch: " << kfPatch
2969 << abort(FatalError);
2975 coupleMap::CONVERT_PHYSICAL,
2985 // Remove unused points
2986 forAll(keepPoints, pointI)
2988 if (keepPoints[pointI] == 0)
2990 removePoint(keepFace[pointI]);
2991 map.removePoint(keepFace[pointI]);
2996 removeFace(faceToKeep[1]);
2999 map.removeFace(faceToKeep[1]);
3004 (neighbour_[faceToKeep[1]] == -1)
3005 && (whichPatch(faceToKeep[1]) < 0)
3008 // Obtain a copy before adding the new face,
3009 // since the reference might become invalid during list resizing.
3010 face newFace = faces_[faceToKeep[1]];
3011 label newOwn = owner_[faceToKeep[1]];
3012 labelList newFaceEdges = faceEdges_[faceToKeep[1]];
3014 // This face is being converted from interior to boundary. Remove
3015 // from the interior list and add as a boundary face to the end.
3016 // Edges don't have to change, since they're on the boundary anyway.
3017 label newFaceIndex =
3021 whichPatch(faceToThrow[1]),
3029 // Add an entry for mapping
3030 modifiedFaces.append(newFaceIndex);
3033 map.addFace(newFaceIndex, labelList(1, faceToThrow[1]));
3035 meshOps::replaceLabel
3042 // Correct edgeFaces with the new face label.
3043 forAll(newFaceEdges, edgeI)
3045 meshOps::replaceLabel
3049 edgeFaces_[newFaceEdges[edgeI]]
3053 // Renumber the neighbour so that this face is removed correctly.
3054 neighbour_[faceToKeep[1]] = 0;
3055 removeFace(faceToKeep[1]);
3058 map.removeFace(faceToKeep[1]);
3061 const cell& cell_1 = cells_[c1];
3063 forAll(cell_1, faceI)
3065 if (cell_1[faceI] != fIndex && cell_1[faceI] != faceToKeep[1])
3067 removeFace(cell_1[faceI]);
3070 map.removeFace(cell_1[faceI]);
3074 if (cellCheck[1] != -1)
3076 meshOps::replaceLabel
3080 cells_[cellCheck[1]]
3091 // Move old / new points
3092 oldPoints_[replacement[0]] = oldPoint[0];
3093 oldPoints_[replacement[1]] = oldPoint[1];
3095 points_[replacement[0]] = newPoint[0];
3096 points_[replacement[1]] = newPoint[1];
3098 // Finally remove the face
3102 map.removeFace(fIndex);
3104 // Write out VTK files after change
3107 labelHashSet vtkCells;
3109 forAll(hullCells[0], cellI)
3111 if (hullCells[0][cellI] == c0 || hullCells[0][cellI] == c1)
3116 if (!vtkCells.found(hullCells[0][cellI]))
3118 vtkCells.insert(hullCells[0][cellI]);
3122 forAll(hullCells[1], cellI)
3124 if (hullCells[1][cellI] == c0 || hullCells[1][cellI] == c1)
3129 if (!vtkCells.found(hullCells[1][cellI]))
3131 vtkCells.insert(hullCells[1][cellI]);
3144 // Fill-in candidate mapping information
3145 labelList mC(2, -1);
3146 mC[0] = c0, mC[1] = c1;
3148 // Now that all old / new cells possess correct connectivity,
3149 // compute mapping information.
3150 forAll(hullCells, indexI)
3152 forAll(hullCells[indexI], cellI)
3154 label mcIndex = hullCells[indexI][cellI];
3156 // Skip collapsed cells
3157 if (mcIndex == c0 || mcIndex == c1)
3162 // Set the mapping for this cell
3163 setCellMapping(mcIndex, mC);
3167 // Set face mapping information for modified faces
3168 forAll(modifiedFaces, faceI)
3170 const label mfIndex = modifiedFaces[faceI];
3172 // Exclude deleted faces
3173 if (faces_[mfIndex].empty())
3178 // Decide between default / weighted mapping
3179 // based on boundary information
3180 label fPatch = whichPatch(mfIndex);
3184 setFaceMapping(mfIndex);
3188 // Fill-in candidate mapping information
3189 labelList faceCandidates;
3191 const labelList& fEdges = faceEdges_[mfIndex];
3193 forAll(fEdges, edgeI)
3195 if (whichEdgePatch(fEdges[edgeI]) == fPatch)
3197 // Loop through associated edgeFaces
3198 const labelList& eFaces = edgeFaces_[fEdges[edgeI]];
3200 forAll(eFaces, faceI)
3204 (eFaces[faceI] != mfIndex) &&
3205 (whichPatch(eFaces[faceI]) == fPatch)
3208 faceCandidates.setSize
3210 faceCandidates.size() + 1,
3218 if (faceCandidates.empty())
3220 // Add the face itself
3221 faceCandidates.setSize(1, mfIndex);
3224 // Set the mapping for this face
3225 setFaceMapping(mfIndex, faceCandidates);
3229 // If modification is coupled, update mapping info.
3230 if (coupledModification_)
3232 // Check if the collapse points are present
3233 // on a processor not involved in the current
3234 // operation, and update if necessary
3235 if (procCouple && !localCouple)
3237 forAll(procIndices_, pI)
3239 bool involved = false;
3241 forAll(slaveMaps, slaveI)
3243 // Alias for convenience...
3244 const changeMap& slaveMap = slaveMaps[slaveI];
3246 if (slaveMap.patchIndex() == pI && slaveMap.index() >= 0)
3248 // Involved in this operation. Break out.
3259 // Check coupleMaps for point coupling
3260 const label pointEnum = coupleMap::POINT;
3262 const coupledMesh& recvMesh = recvMeshes_[pI];
3263 const coupleMap& cMap = recvMesh.map();
3265 // Obtain non-const references
3266 Map<label>& pointMap = cMap.entityMap(pointEnum);
3267 Map<label>& rPointMap = cMap.reverseEntityMap(pointEnum);
3269 label sI0 = -1, sI1 = -1;
3271 if (collapsingSlave)
3273 if ((sI0 = cMap.findMaster(pointEnum, original[0])) > -1)
3275 if (rPointMap.found(replacement[0]))
3277 rPointMap[replacement[0]] = sI0;
3281 rPointMap.insert(replacement[0], sI0);
3284 pointMap[sI0] = replacement[0];
3287 if ((sI1 = cMap.findMaster(pointEnum, original[1])) > -1)
3289 if (rPointMap.found(replacement[1]))
3291 rPointMap[replacement[1]] = sI1;
3295 rPointMap.insert(replacement[1], sI1);
3298 pointMap[sI1] = replacement[1];
3303 if ((sI0 = cMap.findSlave(pointEnum, original[0])) > -1)
3305 if (pointMap.found(replacement[0]))
3307 pointMap[replacement[0]] = sI0;
3311 pointMap.insert(replacement[0], sI0);
3314 rPointMap[sI0] = replacement[0];
3317 if ((sI1 = cMap.findSlave(pointEnum, original[1])) > -1)
3319 if (pointMap.found(replacement[1]))
3321 pointMap[replacement[1]] = sI1;
3325 pointMap.insert(replacement[1], sI1);
3328 rPointMap[sI1] = replacement[1];
3332 if (sI0 > -1 && sI1 > -1 && debug > 2)
3334 Pout<< " Found " << original[0] << " and " << original[1]
3335 << " on proc: " << procIndices_[pI]
3341 forAll(slaveMaps, slaveI)
3343 // Alias for convenience...
3344 const changeMap& slaveMap = slaveMaps[slaveI];
3346 // Skip updates for edge-based coupling
3347 if (slaveMap.index() < 0)
3352 label pI = slaveMap.patchIndex();
3354 // Fetch the appropriate coupleMap
3355 const coupleMap* cMapPtr = NULL;
3357 if (localCouple && !procCouple)
3359 cMapPtr = &(patchCoupling_[pI].map());
3362 if (procCouple && !localCouple)
3364 cMapPtr = &(recvMeshes_[pI].map());
3367 // Configure the slave replacement points.
3368 // - collapseQuadFace stores this as 'addedPoints'
3369 label scP0 = slaveMap.removedPointList()[0];
3370 label scP1 = slaveMap.removedPointList()[1];
3372 label srP0 = slaveMap.addedPointList()[0].index();
3373 label srP1 = slaveMap.addedPointList()[1].index();
3375 // Alias for convenience
3376 const coupleMap& cMap = *cMapPtr;
3378 // Remove the point entries.
3379 const label pointEnum = coupleMap::POINT;
3381 // Obtain references
3382 Map<label>& pointMap = cMap.entityMap(pointEnum);
3383 Map<label>& rPointMap = cMap.reverseEntityMap(pointEnum);
3385 if (collapsingSlave)
3387 if (rPointMap[replacement[0]] == scP0)
3389 pointMap[srP0] = replacement[0];
3390 rPointMap[replacement[0]] = srP0;
3393 if (rPointMap[replacement[0]] == scP1)
3395 pointMap[srP1] = replacement[0];
3396 rPointMap[replacement[0]] = srP1;
3399 if (rPointMap[original[0]] == scP0)
3401 pointMap.erase(scP0);
3404 if (rPointMap[original[0]] == scP1)
3406 pointMap.erase(scP1);
3409 rPointMap.erase(original[0]);
3413 if (pointMap[replacement[0]] == scP0)
3415 rPointMap[srP0] = replacement[0];
3416 pointMap[replacement[0]] = srP0;
3419 if (pointMap[replacement[0]] == scP1)
3421 rPointMap[srP1] = replacement[0];
3422 pointMap[replacement[0]] = srP1;
3425 if (pointMap[original[0]] == scP0)
3427 rPointMap.erase(scP0);
3430 if (pointMap[original[0]] == scP1)
3432 rPointMap.erase(scP1);
3435 pointMap.erase(original[0]);
3438 if (collapsingSlave)
3440 if (rPointMap[replacement[1]] == scP0)
3442 pointMap[srP0] = replacement[1];
3443 rPointMap[replacement[1]] = srP0;
3446 if (rPointMap[replacement[1]] == scP1)
3448 pointMap[srP1] = replacement[1];
3449 rPointMap[replacement[1]] = srP1;
3452 if (rPointMap[original[1]] == scP0)
3454 pointMap.erase(scP0);
3457 if (rPointMap[original[1]] == scP1)
3459 pointMap.erase(scP1);
3462 rPointMap.erase(original[1]);
3466 if (pointMap[replacement[1]] == scP0)
3468 rPointMap[srP0] = replacement[1];
3469 pointMap[replacement[1]] = srP0;
3472 if (pointMap[replacement[1]] == scP1)
3474 rPointMap[srP1] = replacement[1];
3475 pointMap[replacement[1]] = srP1;
3478 if (pointMap[original[1]] == scP0)
3480 rPointMap.erase(scP0);
3483 if (pointMap[original[1]] == scP1)
3485 rPointMap.erase(scP1);
3488 pointMap.erase(original[1]);
3491 // Remove the face entries
3492 const label faceEnum = coupleMap::FACE;
3494 // Obtain references
3495 Map<label>& faceMap = cMap.entityMap(faceEnum);
3496 Map<label>& rFaceMap = cMap.reverseEntityMap(faceEnum);
3498 if (collapsingSlave)
3500 faceMap.erase(faceMap[fIndex]);
3501 rFaceMap.erase(fIndex);
3505 rFaceMap.erase(faceMap[fIndex]);
3506 faceMap.erase(fIndex);
3509 // Configure a comparison face
3512 // If any interior faces in the master map were
3513 // converted to boundaries, account for it
3514 const List<objectMap>& madF = map.addedFaceList();
3518 label mfIndex = madF[faceI].index();
3519 const face& mFace = faces_[mfIndex];
3521 // Select appropriate mesh
3522 const dynamicTopoFvMesh* meshPtr = NULL;
3524 // Fetch the appropriate coupleMap
3525 const coupleMap* crMapPtr = NULL;
3528 label ofPatch = whichPatch(fIndex);
3529 label mfPatch = whichPatch(mfIndex);
3531 if (localCouple && !procCouple)
3533 // Local coupling. Use this mesh itself
3535 crMapPtr = &(patchCoupling_[pI].map());
3538 if (procCouple && !localCouple)
3540 // Occasionally, this face might talk to
3541 // a processor other than the slave
3542 if (ofPatch == mfPatch)
3544 meshPtr = &(recvMeshes_[pI].subMesh());
3545 crMapPtr = &(recvMeshes_[pI].map());
3549 label neiProcNo = getNeighbourProcessor(mfPatch);
3551 if (neiProcNo == -1)
3553 // Not a processor patch. No mapping required.
3558 // Find an appropriate subMesh
3559 label prI = findIndex(procIndices_, neiProcNo);
3561 meshPtr = &(recvMeshes_[prI].subMesh());
3562 crMapPtr = &(recvMeshes_[prI].map());
3567 bool matchedFace = false;
3569 // Alias for convenience
3570 const coupleMap& crMap = *crMapPtr;
3571 const dynamicTopoFvMesh& sMesh = *meshPtr;
3573 // Obtain references
3574 Map<label>& pMap = crMap.entityMap(pointEnum);
3575 Map<label>& fMap = crMap.entityMap(faceEnum);
3576 Map<label>& rfMap = crMap.reverseEntityMap(faceEnum);
3578 // Configure the face
3579 forAll(cFace, pointI)
3583 pMap.found(mFace[pointI]) ?
3584 pMap[mFace[pointI]] : -1
3588 // Loop through all boundary faces on the subMesh
3591 label faceJ = sMesh.nOldInternalFaces_;
3592 faceJ < sMesh.faces_.size();
3596 const face& sFace = sMesh.faces_[faceJ];
3598 if (face::compare(sFace, cFace))
3602 Pout<< " Found face: " << faceJ
3604 << " with mfIndex: " << mfIndex
3610 if (collapsingSlave)
3612 if (fMap.found(faceJ))
3614 fMap[faceJ] = mfIndex;
3618 fMap.insert(faceJ, mfIndex);
3621 if (rfMap.found(mfIndex))
3623 rfMap[mfIndex] = faceJ;
3627 rfMap.insert(mfIndex, faceJ);
3632 if (rfMap.found(faceJ))
3634 rfMap[faceJ] = mfIndex;
3638 rfMap.insert(faceJ, mfIndex);
3641 if (fMap.found(mfIndex))
3643 fMap[mfIndex] = faceJ;
3647 fMap.insert(mfIndex, faceJ);
3659 // Write out for post-processing
3660 writeVTK("masterFace_" + Foam::name(mfIndex), mfIndex, 2);
3666 "dynamicTopoFvMesh::collapseQuadFace\n"
3668 " const label fIndex,\n"
3669 " label overRideCase,\n"
3670 " bool checkOnly,\n"
3674 << " Master face: " << mfIndex
3675 << ": " << mFace << " could not be matched." << nl
3676 << " cFace: " << cFace << nl
3677 << abort(FatalError);
3681 // If any interior faces in the slave map were
3682 // converted to boundaries, account for it
3683 const List<objectMap>& sadF = slaveMap.addedFaceList();
3687 label sIndex = slaveMap.index();
3688 label sfIndex = sadF[faceI].index();
3690 // Select appropriate mesh
3691 const dynamicTopoFvMesh* meshPtr = NULL;
3693 if (localCouple && !procCouple)
3695 // Local coupling. Use this mesh itself
3699 if (procCouple && !localCouple)
3701 meshPtr = &(recvMeshes_[pI].subMesh());
3704 // Alias for convenience
3705 const dynamicTopoFvMesh& sMesh = *meshPtr;
3707 label ofPatch = sMesh.whichPatch(sIndex);
3708 label sfPatch = sMesh.whichPatch(sfIndex);
3710 // Skip dissimilar patches
3711 if (ofPatch != sfPatch && localCouple)
3716 const face& sFace = sMesh.faces_[sfIndex];
3720 // Slave face was removed. Update map.
3721 Map<label>::iterator sit = rFaceMap.find(sfIndex);
3725 if (sit != rFaceMap.end())
3728 faceMap.erase(sit());
3729 rFaceMap.erase(sit);
3732 // Check if this is a special entry
3735 sadF[faceI].masterObjects().size() ?
3736 sadF[faceI].masterObjects()[0] : 0
3739 // Check if a patch conversion is necessary
3740 label newPatch = -1;
3742 // Back out the physical patch ID
3743 if (mo < 0 && mfIndex > -1)
3745 newPatch = Foam::mag(mo + 2);
3752 // Obtain a copy before adding the new face,
3753 // since the reference might become
3754 // invalid during list resizing.
3755 face newFace = faces_[mfIndex];
3756 label newOwn = owner_[mfIndex];
3757 labelList newFaceEdges = faceEdges_[mfIndex];
3759 label newFaceIndex =
3771 meshOps::replaceLabel
3778 // Correct edgeFaces with the new face label.
3779 forAll(newFaceEdges, edgeI)
3781 meshOps::replaceLabel
3785 edgeFaces_[newFaceEdges[edgeI]]
3789 // Finally remove the face
3790 removeFace(mfIndex);
3793 map.removeFace(mfIndex);
3794 map.addFace(newFaceIndex, labelList(1, mfIndex));
3800 forAll(cFace, pointI)
3804 rPointMap.found(sFace[pointI]) ?
3805 rPointMap[sFace[pointI]] : -1
3810 bool matchedFace = false;
3812 // Loop through all boundary faces on this mesh
3815 label faceJ = nOldInternalFaces_;
3816 faceJ < faces_.size();
3820 const face& mFace = faces_[faceJ];
3822 if (face::compare(mFace, cFace))
3826 Pout<< " Found face: " << faceJ
3828 << " with sfIndex: " << sfIndex
3834 if (collapsingSlave)
3836 if (rFaceMap.found(faceJ))
3838 rFaceMap[faceJ] = sfIndex;
3842 rFaceMap.insert(faceJ, sfIndex);
3845 if (faceMap.found(sfIndex))
3847 faceMap[sfIndex] = faceJ;
3851 faceMap.insert(sfIndex, faceJ);
3856 if (faceMap.found(faceJ))
3858 faceMap[faceJ] = sfIndex;
3862 faceMap.insert(faceJ, sfIndex);
3865 if (rFaceMap.found(sfIndex))
3867 rFaceMap[sfIndex] = faceJ;
3871 rFaceMap.insert(sfIndex, faceJ);
3887 "dynamicTopoFvMesh::collapseQuadFace\n"
3889 " const label fIndex,\n"
3890 " label overRideCase,\n"
3891 " bool checkOnly,\n"
3895 << " Slave face: " << sfIndex
3896 << ": " << sFace << " could not be matched." << nl
3897 << " cFace: " << cFace << nl
3898 << abort(FatalError);
3905 topoChangeFlag_ = true;
3907 // Increment the counter
3908 status(TOTAL_COLLAPSES)++;
3910 // Increment the number of modifications
3911 status(TOTAL_MODIFICATIONS)++;
3913 // Return a succesful collapse
3914 map.type() = collapseCase;
3920 // Method for the collapse of an edge in 3D
3921 // - Returns a changeMap with a type specifying:
3922 // -3: Collapse failed since edge was on a noRefinement patch.
3923 // -1: Collapse failed since max number of topo-changes was reached.
3924 // 0: Collapse could not be performed.
3925 // 1: Collapsed to first node.
3926 // 2: Collapsed to second node.
3927 // 3: Collapsed to mid-point (default).
3928 // - overRideCase is used to force a certain collapse configuration.
3929 // -1: Use this value to let collapseEdge decide a case.
3930 // 1: Force collapse to first node.
3931 // 2: Force collapse to second node.
3932 // 3: Force collapse to mid-point.
3933 // - checkOnly performs a feasibility check and returns without modifications.
3934 // - forceOp to force the collapse.
3935 const changeMap dynamicTopoFvMesh::collapseEdge
3943 // Edge collapse performs the following operations:
3944 // [1] Checks if either vertex of the edge is on a boundary
3945 // [2] Checks whether cells attached to deleted vertices will be valid
3946 // after the edge-collapse operation
3947 // [3] Deletes all cells surrounding this edge
3948 // [4] Deletes all faces surrounding this edge
3949 // [5] Deletes all faces surrounding the deleted vertex attached
3950 // to the cells in [3]
3951 // [6] Checks the orientation of faces connected to the retained
3953 // [7] Remove one of the vertices of the edge
3954 // Update faceEdges and edgeFaces information
3956 // For 2D meshes, perform face-collapse
3959 return collapseQuadFace(eIndex, overRideCase, checkOnly);
3962 // Figure out which thread this is...
3963 label tIndex = self();
3965 // Prepare the changeMaps
3967 List<changeMap> slaveMaps;
3968 bool collapsingSlave = false;
3972 (status(TOTAL_MODIFICATIONS) > maxModifications_)
3973 && (maxModifications_ > -1)
3976 // Reached the max allowable topo-changes.
3977 stack(tIndex).clear();
3982 // Check if edgeRefinements are to be avoided on patch.
3983 const labelList& eF = edgeFaces_[eIndex];
3987 label fPatch = whichPatch(eF[fI]);
3989 if (baseMesh_.lengthEstimator().checkRefinementPatch(fPatch))
3997 // Sanity check: Is the index legitimate?
4003 "const changeMap dynamicTopoFvMesh::collapseEdge\n"
4005 " const label eIndex,\n"
4006 " label overRideCase,\n"
4007 " bool checkOnly,\n"
4011 << " Invalid index: " << eIndex
4012 << abort(FatalError);
4015 // If coupled modification is set, and this is a
4016 // master edge, collapse its slaves as well.
4017 bool localCouple = false, procCouple = false;
4019 if (coupledModification_)
4021 const edge& eCheck = edges_[eIndex];
4023 const label edgeEnum = coupleMap::EDGE;
4024 const label pointEnum = coupleMap::POINT;
4026 // Is this a locally coupled edge (either master or slave)?
4027 if (locallyCoupledEntity(eIndex, true))
4033 if (processorCoupledEntity(eIndex))
4036 localCouple = false;
4039 if (localCouple && !procCouple)
4041 // Determine the slave index.
4042 label sIndex = -1, pIndex = -1;
4044 forAll(patchCoupling_, patchI)
4046 if (patchCoupling_(patchI))
4048 const coupleMap& cMap = patchCoupling_[patchI].map();
4050 if ((sIndex = cMap.findSlave(edgeEnum, eIndex)) > -1)
4057 // The following bit happens only during the sliver
4058 // exudation process, since slave edges are
4059 // usually not added to the coupled edge-stack.
4060 if ((sIndex = cMap.findMaster(edgeEnum, eIndex)) > -1)
4064 // Notice that we are collapsing a slave edge first.
4065 collapsingSlave = true;
4077 "const changeMap dynamicTopoFvMesh::collapseEdge\n"
4079 " const label eIndex,\n"
4080 " label overRideCase,\n"
4081 " bool checkOnly,\n"
4085 << "Coupled maps were improperly specified." << nl
4086 << " Slave index not found for: " << nl
4087 << " Edge: " << eIndex << ": " << eCheck << nl
4088 << abort(FatalError);
4092 // If we've found the slave, size up the list
4099 // Save index and patch for posterity
4100 slaveMaps[0].index() = sIndex;
4101 slaveMaps[0].patchIndex() = pIndex;
4106 Pout<< nl << " >> Collapsing slave edge: " << sIndex
4107 << " for master edge: " << eIndex << endl;
4111 if (procCouple && !localCouple)
4113 // If this is a new entity, bail out for now.
4114 // This will be handled at the next time-step.
4115 if (eIndex >= nOldEdges_)
4121 forAll(procIndices_, pI)
4123 // Fetch reference to subMeshes
4124 const coupledMesh& sendMesh = sendMeshes_[pI];
4125 const coupledMesh& recvMesh = recvMeshes_[pI];
4127 const coupleMap& scMap = sendMesh.map();
4128 const coupleMap& rcMap = recvMesh.map();
4130 // If this edge was sent to a lower-ranked
4131 // processor, skip it.
4142 if (scMap.reverseEntityMap(edgeEnum).found(eIndex))
4146 Pout<< "Edge: " << eIndex
4148 << " was sent to proc: "
4150 << ", so bailing out."
4160 if ((sIndex = rcMap.findSlave(edgeEnum, eIndex)) > -1)
4162 // Check if a lower-ranked processor is
4163 // handling this edge
4176 Pout<< "Edge: " << eIndex
4178 << " is handled by proc: "
4180 << ", so bailing out."
4187 label curIndex = slaveMaps.size();
4196 // Save index and patch for posterity
4197 slaveMaps[curIndex].index() = sIndex;
4198 slaveMaps[curIndex].patchIndex() = pI;
4203 (rcMap.findSlave(pointEnum, eCheck[0]) > -1) ||
4204 (rcMap.findSlave(pointEnum, eCheck[1]) > -1)
4207 // A point-only coupling exists.
4209 // Check if a lower-ranked processor is
4210 // handling this edge
4223 Pout<< "Edge point on: " << eIndex
4225 << " is handled by proc: "
4227 << ", so bailing out."
4234 label p0Index = rcMap.findSlave(pointEnum, eCheck[0]);
4235 label p1Index = rcMap.findSlave(pointEnum, eCheck[1]);
4237 if (p0Index > -1 && p1Index == -1)
4242 if (p0Index == -1 && p1Index > -1)
4247 label curIndex = slaveMaps.size();
4256 // Save index and patch for posterity
4257 // - Negate the index to signify point coupling
4258 slaveMaps[curIndex].index() = -sIndex;
4259 slaveMaps[curIndex].patchIndex() = pI;
4265 // Something's wrong with coupling maps
4269 "const changeMap dynamicTopoFvMesh::collapseEdge\n"
4271 " const label eIndex,\n"
4272 " label overRideCase,\n"
4273 " bool checkOnly,\n"
4277 << "Coupled maps were improperly specified." << nl
4278 << " localCouple: " << localCouple << nl
4279 << " procCouple: " << procCouple << nl
4280 << " Edge: " << eIndex << ": " << eCheck << nl
4281 << abort(FatalError);
4284 // Temporarily turn off coupledModification
4285 unsetCoupledModification();
4287 // Test the master edge for collapse, and decide on a case
4288 changeMap masterMap = collapseEdge(eIndex, -1, true, forceOp);
4291 setCoupledModification();
4293 // Master couldn't perform collapse
4294 if (masterMap.type() <= 0)
4299 // For point-only coupling, define the points for checking
4300 pointField slaveMoveNewPoint(slaveMaps.size(), vector::zero);
4301 pointField slaveMoveOldPoint(slaveMaps.size(), vector::zero);
4303 // Now check each of the slaves for collapse feasibility
4304 forAll(slaveMaps, slaveI)
4306 // Alias for convenience...
4307 changeMap& slaveMap = slaveMaps[slaveI];
4309 label slaveOverRide = -1;
4310 label sIndex = slaveMap.index();
4311 label pI = slaveMap.patchIndex();
4313 // If the edge is mapped onto itself, skip check
4314 // (occurs for cyclic edges)
4315 if ((sIndex == eIndex) && localCouple)
4320 const coupleMap* cMapPtr = NULL;
4322 edge mEdge(eCheck), sEdge(-1, -1);
4326 sEdge = edges_[sIndex];
4328 cMapPtr = &(patchCoupling_[pI].map());
4333 const dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
4335 cMapPtr = &(recvMeshes_[pI].map());
4341 Pout<< "Checking slave point: " << mag(sIndex)
4342 << "::" << sMesh.points_[mag(sIndex)]
4343 << " on proc: " << procIndices_[pI]
4344 << " for master edge: " << eIndex
4345 << " using collapseCase: " << masterMap.type()
4351 sEdge = sMesh.edges_[sIndex];
4355 Pout<< "Checking slave edge: " << sIndex
4356 << "::" << sMesh.edges_[sIndex]
4357 << " on proc: " << procIndices_[pI]
4358 << " for master edge: " << eIndex
4359 << " using collapseCase: " << masterMap.type()
4365 const Map<label>& pointMap = cMapPtr->entityMap(pointEnum);
4367 // Perform a topological comparison.
4368 switch (masterMap.type())
4374 slaveMoveNewPoint[slaveI] = points_[mEdge[0]];
4375 slaveMoveOldPoint[slaveI] = oldPoints_[mEdge[0]];
4378 if (pointMap[mEdge[0]] == sEdge[0])
4383 if (pointMap[mEdge[1]] == sEdge[0])
4389 // Write out for for post-processing
4390 writeVTK("mEdge_" + Foam::name(eIndex), eIndex, 1);
4395 "const changeMap dynamicTopoFvMesh"
4398 " const label eIndex,\n"
4399 " label overRideCase,\n"
4400 " bool checkOnly,\n"
4404 << "Coupled collapse failed." << nl
4405 << "Master: " << eIndex << " : " << mEdge << nl
4406 << "Slave: " << sIndex << " : " << sEdge << nl
4407 << abort(FatalError);
4417 slaveMoveNewPoint[slaveI] = points_[mEdge[1]];
4418 slaveMoveOldPoint[slaveI] = oldPoints_[mEdge[1]];
4421 if (pointMap[mEdge[1]] == sEdge[1])
4426 if (pointMap[mEdge[0]] == sEdge[1])
4432 // Write out for for post-processing
4433 writeVTK("mEdge_" + Foam::name(eIndex), eIndex, 1);
4438 "const changeMap dynamicTopoFvMesh"
4441 " const label eIndex,\n"
4442 " label overRideCase,\n"
4443 " bool checkOnly,\n"
4447 << "Coupled collapse failed." << nl
4448 << "Master: " << eIndex << " : " << mEdge << nl
4449 << "Slave: " << sIndex << " : " << sEdge << nl
4450 << abort(FatalError);
4460 slaveMoveNewPoint[slaveI] =
4462 0.5 * (points_[mEdge[0]] + points_[mEdge[1]])
4465 slaveMoveOldPoint[slaveI] =
4467 0.5 * (oldPoints_[mEdge[0]] + oldPoints_[mEdge[1]])
4479 // Temporarily turn off coupledModification
4480 unsetCoupledModification();
4482 // Test the slave edge
4485 slaveMap = collapseEdge(sIndex, slaveOverRide, true, forceOp);
4490 dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
4494 // Point-based coupling
4495 scalar slaveCollapseQuality(GREAT);
4496 dynamicLabelList cellsChecked(10);
4498 // Check cells connected to coupled point
4499 const labelList& pEdges = sMesh.pointEdges_[mag(sIndex)];
4501 bool infeasible = false;
4503 forAll(pEdges, edgeI)
4505 const labelList& eFaces =
4507 sMesh.edgeFaces_[pEdges[edgeI]]
4510 // Build a list of cells to check
4511 forAll(eFaces, faceI)
4513 label own = sMesh.owner_[eFaces[faceI]];
4514 label nei = sMesh.neighbour_[eFaces[faceI]];
4517 if (findIndex(cellsChecked, own) == -1)
4519 // Check if point movement is feasible
4524 slaveMoveNewPoint[slaveI],
4525 slaveMoveOldPoint[slaveI],
4529 slaveCollapseQuality,
4544 // Check neighbour cell
4545 if (findIndex(cellsChecked, nei) == -1)
4547 // Check if point movement is feasible
4552 slaveMoveNewPoint[slaveI],
4553 slaveMoveOldPoint[slaveI],
4557 slaveCollapseQuality,
4576 slaveMap.type() = 0;
4580 slaveMap.type() = 1;
4585 // Edge-based coupling
4600 setCoupledModification();
4602 if (slaveMap.type() <= 0)
4604 // Slave couldn't perform collapse.
4610 // Save index and patch for posterity
4611 slaveMap.index() = sIndex;
4612 slaveMap.patchIndex() = pI;
4615 // Next collapse each slave edge (for real this time...)
4616 forAll(slaveMaps, slaveI)
4618 // Alias for convenience...
4619 changeMap& slaveMap = slaveMaps[slaveI];
4621 label sIndex = slaveMap.index();
4622 label pI = slaveMap.patchIndex();
4624 // If the edge is mapped onto itself, skip modification
4625 // (occurs for cyclic edges)
4626 if ((sIndex == eIndex) && localCouple)
4631 label slaveOverRide = slaveMap.type();
4633 // Temporarily turn off coupledModification
4634 unsetCoupledModification();
4636 // Collapse the slave
4639 slaveMap = collapseEdge(sIndex, slaveOverRide, false, forceOp);
4643 const coupleMap& cMap = recvMeshes_[pI].map();
4644 dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
4648 // Point based coupling
4650 // Move points to new location,
4651 // and update operation into coupleMap
4652 sMesh.points_[mag(sIndex)] = slaveMoveNewPoint[slaveI];
4653 sMesh.oldPoints_[mag(sIndex)] = slaveMoveOldPoint[slaveI];
4658 coupleMap::MOVE_POINT,
4659 slaveMoveNewPoint[slaveI],
4660 slaveMoveOldPoint[slaveI]
4663 // Force operation to succeed
4664 slaveMap.type() = 1;
4668 // Edge-based coupling
4680 // Push operation into coupleMap
4681 switch (slaveMap.type())
4688 coupleMap::COLLAPSE_FIRST
4699 coupleMap::COLLAPSE_SECOND
4710 coupleMap::COLLAPSE_MIDPOINT
4720 setCoupledModification();
4722 // The final operation has to succeed.
4723 if (slaveMap.type() <= 0)
4728 "const changeMap dynamicTopoFvMesh::collapseEdge\n"
4730 " const label eIndex,\n"
4731 " label overRideCase,\n"
4732 " bool checkOnly,\n"
4736 << "Coupled topo-change for slave failed." << nl
4737 << " Edge: " << eIndex << ": " << eCheck << nl
4738 << " Slave index: " << sIndex << nl
4739 << " Patch index: " << pI << nl
4740 << " Type: " << slaveMap.type() << nl
4741 << abort(FatalError);
4744 // Save index and patch for posterity
4745 slaveMap.index() = sIndex;
4746 slaveMap.patchIndex() = pI;
4750 // Build hullVertices for this edge
4751 labelList vertexHull;
4752 buildVertexHull(eIndex, vertexHull);
4756 label replaceIndex = -1, m = vertexHull.size();
4758 // Size up the hull lists
4759 labelList cellHull(m, -1);
4760 labelList faceHull(m, -1);
4761 labelList edgeHull(m, -1);
4762 labelListList ringEntities(4, labelList(m, -1));
4764 // Construct a hull around this edge
4765 meshOps::constructHull
4782 // Check whether points of the edge lies on a boundary
4783 const FixedList<bool,2> edgeBoundary = checkEdgeBoundary(eIndex);
4784 FixedList<label, 2> nBoundCurves(0), nProcCurves(0), checkPoints(-1);
4786 // Decide on collapseCase
4787 label collapseCase = -1;
4789 if (edgeBoundary[0] && !edgeBoundary[1])
4794 if (!edgeBoundary[0] && edgeBoundary[1])
4799 if (edgeBoundary[0] && edgeBoundary[1])
4801 // If this is an interior edge with two boundary points.
4802 // Bail out for now. If proximity based refinement is
4803 // switched on, mesh may be sliced at this point.
4804 label edgePatch = whichEdgePatch(eIndex);
4806 if (edgePatch == -1)
4811 // Check if either point lies on a bounding curve
4812 // Used to ensure that collapses happen towards bounding curves.
4813 // If the edge itself is on a bounding curve, collapse is valid.
4814 const edge& edgeCheck = edges_[eIndex];
4816 forAll(edgeCheck, pointI)
4818 const labelList& pEdges = pointEdges_[edgeCheck[pointI]];
4820 forAll(pEdges, edgeI)
4828 &(nProcCurves[pointI])
4832 nBoundCurves[pointI]++;
4837 // Check for procCurves first
4838 if (!coupledModification_ && !isSubMesh_)
4841 if (nProcCurves[0] && nProcCurves[1])
4846 if (nProcCurves[0] && !nProcCurves[1])
4848 if (nBoundCurves[1])
4859 if (!nProcCurves[0] && nProcCurves[1])
4861 if (nBoundCurves[0])
4873 // If still undecided, choose based on bounding curves
4874 if (collapseCase == -1)
4876 // Pick the point which is connected to more bounding curves
4877 if (nBoundCurves[0] > nBoundCurves[1])
4882 if (nBoundCurves[1] > nBoundCurves[0])
4888 // Bounding edge: collapseEdge can collapse this edge
4895 // Looks like this is an interior edge.
4896 // Collapse case [3] by default
4900 // Perform an override if requested.
4901 if (overRideCase != -1)
4903 collapseCase = overRideCase;
4906 // Configure the new point-position
4907 point newPoint = vector::zero;
4908 point oldPoint = vector::zero;
4910 label collapsePoint = -1, replacePoint = -1;
4912 switch (collapseCase)
4916 // Collapse to the first node
4917 replacePoint = edges_[eIndex][0];
4918 collapsePoint = edges_[eIndex][1];
4920 newPoint = points_[replacePoint];
4921 oldPoint = oldPoints_[replacePoint];
4923 checkPoints[0] = collapsePoint;
4930 // Collapse to the second node
4931 replacePoint = edges_[eIndex][1];
4932 collapsePoint = edges_[eIndex][0];
4934 newPoint = points_[replacePoint];
4935 oldPoint = oldPoints_[replacePoint];
4937 checkPoints[0] = collapsePoint;
4944 // Collapse to the mid-point
4945 replacePoint = edges_[eIndex][1];
4946 collapsePoint = edges_[eIndex][0];
4952 points_[replacePoint]
4953 + points_[collapsePoint]
4961 oldPoints_[replacePoint]
4962 + oldPoints_[collapsePoint]
4966 checkPoints[0] = replacePoint;
4967 checkPoints[1] = collapsePoint;
4974 // Don't think this will ever happen.
4978 "const changeMap dynamicTopoFvMesh::collapseEdge\n"
4980 " const label eIndex,\n"
4981 " label overRideCase,\n"
4982 " bool checkOnly,\n"
4986 << "Edge: " << eIndex << ": " << edges_[eIndex]
4987 << ". Couldn't decide on collapseCase."
4988 << abort(FatalError);
4994 // Loop through edges and check for feasibility of collapse
4995 // Also, keep track of resulting cell quality,
4996 // if collapse is indeed feasible
4997 scalar collapseQuality(GREAT);
4998 dynamicLabelList cellsChecked(10);
5000 // Add all hull cells as 'checked',
5001 // and therefore, feasible
5002 forAll(cellHull, cellI)
5004 if (cellHull[cellI] == -1)
5009 cellsChecked.append(cellHull[cellI]);
5012 // Check collapsibility of cells around edges
5013 // with the re-configured point
5014 forAll(checkPoints, pointI)
5016 if (checkPoints[pointI] == -1)
5021 const labelList& checkPointEdges = pointEdges_[checkPoints[pointI]];
5023 forAll(checkPointEdges, edgeI)
5025 const labelList& eFaces = edgeFaces_[checkPointEdges[edgeI]];
5027 // Build a list of cells to check
5028 forAll(eFaces, faceI)
5030 label own = owner_[eFaces[faceI]];
5031 label nei = neighbour_[eFaces[faceI]];
5034 if (findIndex(cellsChecked, own) == -1)
5036 // Check if a collapse is feasible
5043 checkPoints[pointI],
5061 // Check neighbour cell
5062 if (findIndex(cellsChecked, nei) == -1)
5064 // Check if a collapse is feasible
5071 checkPoints[pointI],
5087 // Add a map entry of the replacePoint as an 'addedPoint'
5088 // - Used in coupled mapping
5089 map.addPoint(replacePoint);
5091 // Are we only performing checks?
5094 // Return a succesful collapse possibility
5095 map.type() = collapseCase;
5097 // Make note of the removed point
5098 map.removePoint(collapsePoint);
5102 Pout<< nl << "Edge: " << eIndex
5103 << ":: " << edges_[eIndex] << nl
5104 << " collapseCase determined to be: " << collapseCase << nl
5105 << " Resulting quality: " << collapseQuality << nl
5106 << " collapsePoint: " << collapsePoint << nl
5107 << " nBoundCurves: " << nBoundCurves << nl
5108 << " nProcCurves: " << nProcCurves << nl
5115 // Define indices on the hull for removal / replacement
5116 label removeEdgeIndex = -1, replaceEdgeIndex = -1;
5117 label removeFaceIndex = -1, replaceFaceIndex = -1;
5119 if (replacePoint == edges_[eIndex][0])
5121 replaceEdgeIndex = 0;
5122 replaceFaceIndex = 1;
5123 removeEdgeIndex = 2;
5124 removeFaceIndex = 3;
5127 if (replacePoint == edges_[eIndex][1])
5129 removeEdgeIndex = 0;
5130 removeFaceIndex = 1;
5131 replaceEdgeIndex = 2;
5132 replaceFaceIndex = 3;
5136 // Don't think this will ever happen.
5140 "const changeMap dynamicTopoFvMesh::collapseEdge\n"
5142 " const label eIndex,\n"
5143 " label overRideCase,\n"
5144 " bool checkOnly,\n"
5148 << "Edge: " << eIndex << ": " << edges_[eIndex]
5149 << ". Couldn't decide on removal / replacement indices."
5150 << abort(FatalError);
5156 << "Edge: " << eIndex << ": " << edges_[eIndex]
5157 << " is to be collapsed. " << nl;
5159 Pout<< " On SubMesh: " << isSubMesh_ << nl;
5160 Pout<< " coupledModification: " << coupledModification_ << nl;
5162 label epIndex = whichEdgePatch(eIndex);
5164 const polyBoundaryMesh& boundary = boundaryMesh();
5170 Pout<< "Internal" << nl;
5173 if (epIndex < boundary.size())
5175 Pout<< boundary[epIndex].name() << nl;
5179 Pout<< " New patch: " << epIndex << endl;
5182 Pout<< " nBoundCurves: " << nBoundCurves << nl
5183 << " nProcCurves: " << nProcCurves << nl
5184 << " collapseCase: " << collapseCase << nl
5185 << " Resulting quality: " << collapseQuality << endl;
5189 Pout<< " Edges: " << edgeHull << nl
5190 << " Faces: " << faceHull << nl
5191 << " Cells: " << cellHull << nl
5192 << " replacePoint: " << replacePoint << nl
5193 << " collapsePoint: " << collapsePoint << nl
5194 << " checkPoints: " << checkPoints << nl;
5196 Pout<< " ringEntities (removed faces): " << nl;
5198 forAll(ringEntities[removeFaceIndex], faceI)
5200 label fIndex = ringEntities[removeFaceIndex][faceI];
5207 Pout<< fIndex << ": " << faces_[fIndex] << nl;
5210 Pout<< " ringEntities (removed edges): " << nl;
5212 forAll(ringEntities[removeEdgeIndex], edgeI)
5214 label ieIndex = ringEntities[removeEdgeIndex][edgeI];
5221 Pout<< ieIndex << ": " << edges_[ieIndex] << nl;
5224 Pout<< " ringEntities (replacement faces): " << nl;
5226 forAll(ringEntities[replaceFaceIndex], faceI)
5228 label fIndex = ringEntities[replaceFaceIndex][faceI];
5235 Pout<< fIndex << ": " << faces_[fIndex] << nl;
5238 Pout<< " ringEntities (replacement edges): " << nl;
5240 forAll(ringEntities[replaceEdgeIndex], edgeI)
5242 label ieIndex = ringEntities[replaceEdgeIndex][edgeI];
5249 Pout<< ieIndex << ": " << edges_[ieIndex] << nl;
5252 labelList& collapsePointEdges = pointEdges_[collapsePoint];
5254 Pout<< " pointEdges (collapsePoint): ";
5256 forAll(collapsePointEdges, edgeI)
5258 Pout<< collapsePointEdges[edgeI] << " ";
5263 // Write out VTK files prior to change
5264 // - Using old-points for convenience in post-processing
5270 + '(' + Foam::name(collapsePoint)
5271 + ',' + Foam::name(replacePoint) + ')'
5280 if (whichEdgePatch(eIndex) > -1)
5282 // Update number of surface collapses, if necessary.
5283 status(SURFACE_COLLAPSES)++;
5286 // Maintain a list of modified faces for mapping
5287 dynamicLabelList modifiedFaces(10);
5289 // Renumber all hull faces and edges
5290 forAll(faceHull, indexI)
5292 // Loop through all faces of the edge to be removed
5293 // and reassign them to the replacement edge
5294 label edgeToRemove = ringEntities[removeEdgeIndex][indexI];
5295 label faceToRemove = ringEntities[removeFaceIndex][indexI];
5296 label cellToRemove = cellHull[indexI];
5297 label replaceEdge = ringEntities[replaceEdgeIndex][indexI];
5298 label replaceFace = ringEntities[replaceFaceIndex][indexI];
5300 label replacePatch = whichEdgePatch(replaceEdge);
5301 label removePatch = whichEdgePatch(edgeToRemove);
5303 // Check if a patch conversion is necessary
5304 if (replacePatch == -1 && removePatch > -1)
5308 Pout<< " Edge: " << replaceEdge
5309 << " :: " << edges_[replaceEdge]
5310 << " is interior, but edge: " << edgeToRemove
5311 << " :: " << edges_[edgeToRemove]
5312 << " is on a boundary patch."
5316 // Convert patch for edge
5317 edge newEdge = edges_[replaceEdge];
5318 labelList newEdgeFaces = edgeFaces_[replaceEdge];
5320 // Insert the new edge
5321 label newEdgeIndex =
5331 // Replace faceEdges for all
5333 forAll(newEdgeFaces, faceI)
5335 meshOps::replaceLabel
5339 faceEdges_[newEdgeFaces[faceI]]
5344 removeEdge(replaceEdge);
5347 map.removeEdge(replaceEdge);
5348 map.addEdge(newEdgeIndex, labelList(1, replaceEdge));
5350 // Replace index and patch
5351 replaceEdge = newEdgeIndex;
5353 // Modify ringEntities
5354 ringEntities[replaceEdgeIndex][indexI] = newEdgeIndex;
5357 const labelList& rmvEdgeFaces = edgeFaces_[edgeToRemove];
5359 forAll(rmvEdgeFaces, faceI)
5361 // Replace edge labels for faces
5362 meshOps::replaceLabel
5366 faceEdges_[rmvEdgeFaces[faceI]]
5369 // Loop through faces associated with this edge,
5370 // and renumber them as well.
5371 const face& faceToCheck = faces_[rmvEdgeFaces[faceI]];
5373 if ((replaceIndex = faceToCheck.which(collapsePoint)) > -1)
5375 // Renumber the face...
5376 faces_[rmvEdgeFaces[faceI]][replaceIndex] = replacePoint;
5378 // Add an entry for mapping
5379 if (findIndex(modifiedFaces, rmvEdgeFaces[faceI]) == -1)
5381 modifiedFaces.append(rmvEdgeFaces[faceI]);
5385 // Hull faces should be removed for the replacement edge
5386 if (rmvEdgeFaces[faceI] == faceHull[indexI])
5388 meshOps::sizeDownList
5391 edgeFaces_[replaceEdge]
5399 // Need to avoid ring faces as well.
5400 forAll(ringEntities[removeFaceIndex], faceII)
5405 == ringEntities[removeFaceIndex][faceII]
5413 // Size-up the replacement edge list if the face hasn't been found.
5414 // These faces are connected to the edge slated for
5415 // removal, but do not belong to the hull.
5420 rmvEdgeFaces[faceI],
5421 edgeFaces_[replaceEdge]
5426 if (cellToRemove == -1)
5431 // Size down edgeFaces for the ring edges
5432 meshOps::sizeDownList
5435 edgeFaces_[edgeHull[indexI]]
5438 // Ensure proper orientation of retained faces
5439 if (owner_[faceToRemove] == cellToRemove)
5441 if (owner_[replaceFace] == cellToRemove)
5445 (neighbour_[faceToRemove] > neighbour_[replaceFace])
5446 && (neighbour_[replaceFace] != -1)
5449 // This face is to be flipped
5450 faces_[replaceFace] = faces_[replaceFace].reverseFace();
5451 owner_[replaceFace] = neighbour_[replaceFace];
5452 neighbour_[replaceFace] = neighbour_[faceToRemove];
5454 setFlip(replaceFace);
5459 (neighbour_[faceToRemove] == -1) &&
5460 (neighbour_[replaceFace] != -1)
5463 // This interior face would need to be converted
5464 // to a boundary one, and flipped as well.
5465 face newFace = faces_[replaceFace].reverseFace();
5466 label newOwner = neighbour_[replaceFace];
5467 label newNeighbour = neighbour_[faceToRemove];
5468 labelList newFE = faceEdges_[replaceFace];
5470 label newFaceIndex =
5474 whichPatch(faceToRemove),
5482 // Set this face aside for mapping
5483 modifiedFaces.append(newFaceIndex);
5486 map.addFace(newFaceIndex, labelList(1, faceToRemove));
5488 // Ensure that all edges of this face are
5490 forAll(newFE, edgeI)
5492 if (whichEdgePatch(newFE[edgeI]) == -1)
5494 edge newEdge = edges_[newFE[edgeI]];
5495 labelList newEF = edgeFaces_[newFE[edgeI]];
5497 // Need patch information for the new edge.
5498 // Find the corresponding edge in ringEntities.
5499 // Note that hullEdges doesn't need to be checked,
5500 // since they are common to both faces.
5505 ringEntities[replaceEdgeIndex],
5514 ringEntities[removeEdgeIndex][i]
5518 // Insert the new edge
5519 label newEdgeIndex =
5529 // Replace faceEdges for all
5531 forAll(newEF, faceI)
5533 meshOps::replaceLabel
5537 faceEdges_[newEF[faceI]]
5542 removeEdge(newFE[edgeI]);
5545 map.removeEdge(newFE[edgeI]);
5550 labelList(1, newFE[edgeI])
5553 // Replace faceEdges with new edge index
5554 newFE[edgeI] = newEdgeIndex;
5556 // Modify ringEntities
5557 ringEntities[replaceEdgeIndex][i] = newEdgeIndex;
5561 // Add the new faceEdges
5562 faceEdges_[newFaceIndex] = newFE;
5564 // Replace edgeFaces with the new face index
5565 const labelList& newFEdges = faceEdges_[newFaceIndex];
5567 forAll(newFEdges, edgeI)
5569 meshOps::replaceLabel
5573 edgeFaces_[newFEdges[edgeI]]
5578 removeFace(replaceFace);
5581 map.removeFace(replaceFace);
5583 // Replace label for the new owner
5584 meshOps::replaceLabel
5591 // Modify ringEntities and replaceFace
5592 replaceFace = newFaceIndex;
5593 ringEntities[replaceFaceIndex][indexI] = newFaceIndex;
5598 (neighbour_[faceToRemove] == -1) &&
5599 (neighbour_[replaceFace] == -1)
5602 // Wierd overhanging cell. Since replaceFace
5603 // would be an orphan if this continued, remove
5604 // the face entirely.
5605 labelList rmFE = faceEdges_[replaceFace];
5611 (edgeFaces_[rmFE[edgeI]].size() == 1) &&
5612 (edgeFaces_[rmFE[edgeI]][0] == replaceFace)
5615 // This edge has to be removed entirely.
5616 removeEdge(rmFE[edgeI]);
5619 map.removeEdge(rmFE[edgeI]);
5625 ringEntities[replaceEdgeIndex],
5632 // Modify ringEntities
5633 ringEntities[replaceEdgeIndex][i] = -1;
5638 // Size-down edgeFaces
5639 meshOps::sizeDownList
5642 edgeFaces_[rmFE[edgeI]]
5647 // If this is a subMesh, and replaceFace is on
5648 // a physical boundary, make a 'special' entry
5649 // for coupled mapping purposes.
5652 label kfPatch = whichPatch(replaceFace);
5653 label rfPatch = whichPatch(faceToRemove);
5657 (getNeighbourProcessor(rfPatch) > -1) &&
5658 (getNeighbourProcessor(kfPatch) == -1)
5664 labelList(1, (-2 - kfPatch))
5670 removeFace(replaceFace);
5673 map.removeFace(replaceFace);
5675 // Modify ringEntities and replaceFace
5677 ringEntities[replaceFaceIndex][indexI] = -1;
5681 // Keep orientation intact, and update the owner
5682 owner_[replaceFace] = neighbour_[faceToRemove];
5686 if (neighbour_[faceToRemove] == -1)
5688 // This interior face would need to be converted
5689 // to a boundary one, but with orientation intact.
5690 face newFace = faces_[replaceFace];
5691 label newOwner = owner_[replaceFace];
5692 label newNeighbour = neighbour_[faceToRemove];
5693 labelList newFE = faceEdges_[replaceFace];
5695 label newFaceIndex =
5699 whichPatch(faceToRemove),
5707 // Set this face aside for mapping
5708 modifiedFaces.append(newFaceIndex);
5711 map.addFace(newFaceIndex, labelList(1, faceToRemove));
5713 // Ensure that all edges of this face are
5715 forAll(newFE, edgeI)
5717 if (whichEdgePatch(newFE[edgeI]) == -1)
5719 edge newEdge = edges_[newFE[edgeI]];
5720 labelList newEF = edgeFaces_[newFE[edgeI]];
5722 // Need patch information for the new edge.
5723 // Find the corresponding edge in ringEntities.
5724 // Note that hullEdges doesn't need to be checked,
5725 // since they are common to both faces.
5730 ringEntities[replaceEdgeIndex],
5739 ringEntities[removeEdgeIndex][i]
5743 // Insert the new edge
5744 label newEdgeIndex =
5754 // Replace faceEdges for all
5756 forAll(newEF, faceI)
5758 meshOps::replaceLabel
5762 faceEdges_[newEF[faceI]]
5767 removeEdge(newFE[edgeI]);
5770 map.removeEdge(newFE[edgeI]);
5775 labelList(1, newFE[edgeI])
5778 // Replace faceEdges with new edge index
5779 newFE[edgeI] = newEdgeIndex;
5781 // Modify ringEntities
5782 ringEntities[replaceEdgeIndex][i] = newEdgeIndex;
5786 // Add the new faceEdges
5787 faceEdges_[newFaceIndex] = newFE;
5789 // Replace edgeFaces with the new face index
5790 const labelList& newFEdges = faceEdges_[newFaceIndex];
5792 forAll(newFEdges, edgeI)
5794 meshOps::replaceLabel
5798 edgeFaces_[newFEdges[edgeI]]
5803 removeFace(replaceFace);
5806 map.removeFace(replaceFace);
5808 // Replace label for the new owner
5809 meshOps::replaceLabel
5816 // Modify ringEntities and replaceFace
5817 replaceFace = newFaceIndex;
5818 ringEntities[replaceFaceIndex][indexI] = newFaceIndex;
5822 // Keep orientation intact, and update the neighbour
5823 neighbour_[replaceFace] = neighbour_[faceToRemove];
5827 if (neighbour_[faceToRemove] != -1)
5829 meshOps::replaceLabel
5833 cells_[neighbour_[faceToRemove]]
5839 if (neighbour_[replaceFace] == cellToRemove)
5841 if (owner_[faceToRemove] < owner_[replaceFace])
5843 // This face is to be flipped
5844 faces_[replaceFace] = faces_[replaceFace].reverseFace();
5845 neighbour_[replaceFace] = owner_[replaceFace];
5846 owner_[replaceFace] = owner_[faceToRemove];
5848 setFlip(replaceFace);
5852 // Keep orientation intact, and update the neighbour
5853 neighbour_[replaceFace] = owner_[faceToRemove];
5858 // Keep orientation intact, and update the owner
5859 owner_[replaceFace] = owner_[faceToRemove];
5863 meshOps::replaceLabel
5867 cells_[owner_[faceToRemove]]
5872 // Remove all hull entities
5873 forAll(faceHull, indexI)
5875 label edgeToRemove = ringEntities[removeEdgeIndex][indexI];
5876 label faceToRemove = ringEntities[removeFaceIndex][indexI];
5877 label cellToRemove = cellHull[indexI];
5879 if (cellToRemove != -1)
5881 // Remove faceToRemove and associated faceEdges
5882 removeFace(faceToRemove);
5885 map.removeFace(faceToRemove);
5887 // Remove the hull cell
5888 removeCell(cellToRemove);
5891 map.removeCell(cellToRemove);
5894 // Remove the hull edge and associated edgeFaces
5895 removeEdge(edgeToRemove);
5898 map.removeEdge(edgeToRemove);
5900 // Remove the hull face
5901 removeFace(faceHull[indexI]);
5904 map.removeFace(faceHull[indexI]);
5907 // Loop through pointEdges for the collapsePoint,
5908 // and replace all occurrences with replacePoint.
5909 // Size-up pointEdges for the replacePoint as well.
5910 const labelList& pEdges = pointEdges_[collapsePoint];
5912 forAll(pEdges, edgeI)
5915 label edgeIndex = pEdges[edgeI];
5917 if (edgeIndex != eIndex)
5919 if (edges_[edgeIndex][0] == collapsePoint)
5921 edges_[edgeIndex][0] = replacePoint;
5926 pointEdges_[replacePoint]
5930 if (edges_[edgeIndex][1] == collapsePoint)
5932 edges_[edgeIndex][1] = replacePoint;
5937 pointEdges_[replacePoint]
5942 // Looks like pointEdges is inconsistent
5946 "const changeMap dynamicTopoFvMesh::collapseEdge\n"
5948 " const label eIndex,\n"
5949 " label overRideCase,\n"
5950 " bool checkOnly,\n"
5954 << "pointEdges is inconsistent." << nl
5955 << "Point: " << collapsePoint << nl
5956 << "pointEdges: " << pEdges << nl
5957 << abort(FatalError);
5960 // Loop through faces associated with this edge,
5961 // and renumber them as well.
5962 const labelList& eFaces = edgeFaces_[edgeIndex];
5964 forAll(eFaces, faceI)
5966 const face& faceToCheck = faces_[eFaces[faceI]];
5968 if ((replaceIndex = faceToCheck.which(collapsePoint)) > -1)
5970 // Renumber the face...
5971 faces_[eFaces[faceI]][replaceIndex] = replacePoint;
5973 // Set this face aside for mapping
5974 if (findIndex(modifiedFaces, eFaces[faceI]) == -1)
5976 modifiedFaces.append(eFaces[faceI]);
5983 // Set old / new points
5984 oldPoints_[replacePoint] = oldPoint;
5985 points_[replacePoint] = newPoint;
5987 // Remove the collapse point
5988 removePoint(collapsePoint);
5991 map.removePoint(collapsePoint);
5997 map.removeEdge(eIndex);
5999 // Check for duplicate edges connected to the replacePoint
6000 const labelList& rpEdges = pointEdges_[replacePoint];
6002 dynamicLabelList mergeFaces(10);
6004 forAll(rpEdges, edgeI)
6006 const edge& eCheckI = edges_[rpEdges[edgeI]];
6007 const label vCheckI = eCheckI.otherVertex(replacePoint);
6009 for (label edgeJ = edgeI + 1; edgeJ < rpEdges.size(); edgeJ++)
6011 const edge& eCheckJ = edges_[rpEdges[edgeJ]];
6012 const label vCheckJ = eCheckJ.otherVertex(replacePoint);
6014 if (vCheckJ == vCheckI)
6016 labelPair efCheck(rpEdges[edgeI], rpEdges[edgeJ]);
6018 forAll(efCheck, edgeI)
6020 const labelList& eF = edgeFaces_[efCheck[edgeI]];
6024 label patch = whichPatch(eF[faceI]);
6031 if (findIndex(mergeFaces, eF[faceI]) == -1)
6033 mergeFaces.append(eF[faceI]);
6040 Pout<< " Found duplicate: " << eCheckI << nl
6041 << " Merge faces: " << mergeFaces << nl
6048 // Merge faces if necessary
6049 if (mergeFaces.size())
6051 mergeBoundaryFaces(mergeFaces);
6054 // Check and remove edges with an empty edgeFaces list
6055 const labelList& replaceEdges = ringEntities[replaceEdgeIndex];
6057 forAll(replaceEdges, edgeI)
6059 label replaceEdge = replaceEdges[edgeI];
6061 // If the ring edge was removed, don't bother.
6062 if (replaceEdge > -1)
6064 // Account for merged edges as well
6065 if (edgeFaces_[replaceEdge].empty())
6067 // Is this edge truly removed? If not, remove it.
6068 if (edges_[replaceEdge] != edge(-1, -1))
6072 Pout<< " Edge: " << replaceEdge
6073 << " :: " << edges_[replaceEdge]
6074 << " has empty edgeFaces."
6079 removeEdge(replaceEdge);
6082 map.removeEdge(replaceEdge);
6088 // Create a list of candidates for mapping
6089 // using the list of checked cells
6090 labelList mC(cellsChecked.size());
6092 // For cell-mapping, exclude all hull-cells
6093 forAll(cellsChecked, indexI)
6095 mC[indexI] = cellsChecked[indexI];
6097 if (cells_[cellsChecked[indexI]].empty())
6099 cellsChecked[indexI] = -1;
6102 if (findIndex(cellHull, cellsChecked[indexI]) > 0)
6104 cellsChecked[indexI] = -1;
6108 // Write out VTK files after change
6109 // - Using old-points for convenience in post-processing
6115 + '(' + Foam::name(collapsePoint)
6116 + ',' + Foam::name(replacePoint) + ')'
6123 // Now that all old / new cells possess correct connectivity,
6124 // compute mapping information.
6125 forAll(cellsChecked, cellI)
6127 if (cellsChecked[cellI] < 0)
6132 // Set the mapping for this cell
6133 setCellMapping(cellsChecked[cellI], mC);
6136 // Set face mapping information for modified faces
6137 forAll(modifiedFaces, faceI)
6139 const label mfIndex = modifiedFaces[faceI];
6141 // Exclude deleted faces
6142 if (faces_[mfIndex].empty())
6147 // Decide between default / weighted mapping
6148 // based on boundary information
6149 label fPatch = whichPatch(mfIndex);
6153 setFaceMapping(mfIndex);
6157 // Fill-in candidate mapping information
6158 labelList faceCandidates;
6160 const labelList& fEdges = faceEdges_[mfIndex];
6162 forAll(fEdges, edgeI)
6164 if (whichEdgePatch(fEdges[edgeI]) == fPatch)
6166 // Loop through associated edgeFaces
6167 const labelList& eFaces = edgeFaces_[fEdges[edgeI]];
6169 forAll(eFaces, faceI)
6173 (eFaces[faceI] != mfIndex) &&
6174 (whichPatch(eFaces[faceI]) == fPatch)
6177 faceCandidates.setSize
6179 faceCandidates.size() + 1,
6187 if (faceCandidates.empty())
6189 // Add the face itself
6190 faceCandidates.setSize(1, mfIndex);
6193 // Set the mapping for this face
6194 setFaceMapping(mfIndex, faceCandidates);
6198 // If modification is coupled, update mapping info.
6199 if (coupledModification_)
6201 // Build a list of boundary edges / faces for mapping
6202 dynamicLabelList checkEdges(10), checkFaces(10);
6204 const labelList& pEdges = pointEdges_[replacePoint];
6206 forAll(pEdges, edgeI)
6208 const labelList& eFaces = edgeFaces_[pEdges[edgeI]];
6210 forAll(eFaces, faceI)
6212 label fPatch = whichPatch(eFaces[faceI]);
6214 if (localCouple && !procCouple)
6216 if (!locallyCoupledEntity(eFaces[faceI], true, false, true))
6221 // Check for cyclics
6222 if (boundaryMesh()[fPatch].type() == "cyclic")
6224 // Check if this is a master face
6225 const coupleMap& cM = patchCoupling_[fPatch].map();
6226 const Map<label>& fM = cM.entityMap(coupleMap::FACE);
6228 // Only add master faces
6229 // (belonging to the first half)
6230 if (!fM.found(eFaces[faceI]))
6237 if (procCouple && !localCouple)
6239 if (getNeighbourProcessor(fPatch) == -1)
6245 // Add face and its edges for checking
6246 if (findIndex(checkFaces, eFaces[faceI]) == -1)
6249 checkFaces.append(eFaces[faceI]);
6251 const labelList& fEdges = faceEdges_[eFaces[faceI]];
6253 forAll(fEdges, edgeJ)
6255 if (findIndex(checkEdges, fEdges[edgeJ]) == -1)
6257 checkEdges.append(fEdges[edgeJ]);
6264 // Prepare a checklist
6265 boolList matchedFaces(checkFaces.size(), false);
6266 boolList matchedEdges(checkEdges.size(), false);
6268 // Output check entities
6273 "checkEdges_" + Foam::name(eIndex),
6274 checkEdges, 1, false, true
6279 "checkFaces_" + Foam::name(eIndex),
6280 checkFaces, 2, false, true
6284 if (localCouple && !procCouple)
6286 // Alias for convenience...
6287 const changeMap& slaveMap = slaveMaps[0];
6289 const label pI = slaveMap.patchIndex();
6290 const coupleMap& cMap = patchCoupling_[pI].map();
6292 // Obtain references
6293 Map<label>& pointMap = cMap.entityMap(coupleMap::POINT);
6294 Map<label>& rPointMap = cMap.reverseEntityMap(coupleMap::POINT);
6296 const labelList& rpList = slaveMap.removedPointList();
6297 const List<objectMap>& apList = slaveMap.addedPointList();
6299 // Configure the slave replacement point.
6300 // - collapseEdge stores this as an 'addedPoint'
6301 label scPoint = -1, srPoint = -1;
6303 if ((slaveMap.index() == eIndex) && localCouple)
6305 // Cyclic edge at axis
6306 scPoint = collapsePoint;
6307 srPoint = replacePoint;
6311 scPoint = rpList[0];
6312 srPoint = apList[0].index();
6315 if (collapsingSlave)
6317 if (rPointMap[replacePoint] == scPoint)
6319 pointMap[srPoint] = replacePoint;
6320 rPointMap[replacePoint] = srPoint;
6325 if (pointMap[replacePoint] == scPoint)
6327 rPointMap[srPoint] = replacePoint;
6328 pointMap[replacePoint] = srPoint;
6333 const label faceEnum = coupleMap::FACE;
6335 // Obtain references
6336 Map<label>& faceMap = cMap.entityMap(faceEnum);
6337 Map<label>& rFaceMap = cMap.reverseEntityMap(faceEnum);
6339 forAll(checkFaces, faceI)
6341 label mfIndex = checkFaces[faceI];
6342 label mfPatch = whichPatch(mfIndex);
6344 const face& mF = faces_[mfIndex];
6348 pointMap.found(mF[0]) ? pointMap[mF[0]] : -1,
6349 pointMap.found(mF[1]) ? pointMap[mF[1]] : -1,
6350 pointMap.found(mF[2]) ? pointMap[mF[2]] : -1
6353 if (cF[0] == -1 || cF[1] == -1 || cF[2] == -1)
6358 + Foam::name(mfIndex),
6363 Pout<< " Failed to configure face for: "
6364 << mfIndex << " :: " << faces_[mfIndex]
6365 << " using comparison face: " << cF
6366 << abort(FatalError);
6369 // Fetch edges connected to first slave point
6370 const labelList& spEdges = pointEdges_[cF[0]];
6372 forAll(spEdges, edgeJ)
6374 label seIndex = spEdges[edgeJ];
6376 if (whichEdgePatch(seIndex) == -1)
6381 const labelList& seFaces = edgeFaces_[seIndex];
6383 forAll(seFaces, faceJ)
6385 label sfIndex = seFaces[faceJ];
6387 if (whichPatch(sfIndex) == -1)
6392 const face& sF = faces_[sfIndex];
6398 triFace(sF[0], sF[1], sF[2]), cF
6404 word pN(boundaryMesh()[mfPatch].name());
6406 Pout<< " Found face: " << sfIndex
6408 << " with mfIndex: " << mfIndex
6409 << " :: " << faces_[mfIndex]
6414 if (rFaceMap.found(sfIndex))
6416 rFaceMap[sfIndex] = mfIndex;
6420 rFaceMap.insert(sfIndex, mfIndex);
6423 if (faceMap.found(mfIndex))
6425 faceMap[mfIndex] = sfIndex;
6429 faceMap.insert(mfIndex, sfIndex);
6432 matchedFaces[faceI] = true;
6438 if (matchedFaces[faceI])
6444 if (!matchedFaces[faceI])
6449 + Foam::name(mfIndex),
6450 labelList(cF), 0, false, true
6453 Pout<< " Failed to match face: "
6454 << mfIndex << " :: " << faces_[mfIndex]
6455 << " using comparison face: " << cF
6456 << abort(FatalError);
6461 const label edgeEnum = coupleMap::EDGE;
6463 // Obtain references
6464 Map<label>& edgeMap = cMap.entityMap(edgeEnum);
6465 Map<label>& rEdgeMap = cMap.reverseEntityMap(edgeEnum);
6467 forAll(checkEdges, edgeI)
6469 label meIndex = checkEdges[edgeI];
6471 const edge& mE = edges_[meIndex];
6475 pointMap.found(mE[0]) ? pointMap[mE[0]] : -1,
6476 pointMap.found(mE[1]) ? pointMap[mE[1]] : -1
6479 if (cE[0] == -1 || cE[1] == -1)
6484 + Foam::name(meIndex),
6489 Pout<< " Failed to configure edge for: "
6490 << meIndex << " :: " << edges_[meIndex]
6491 << " using comparison edge: " << cE
6492 << abort(FatalError);
6495 // Fetch edges connected to first slave point
6496 const labelList& spEdges = pointEdges_[cE[0]];
6498 forAll(spEdges, edgeJ)
6500 label seIndex = spEdges[edgeJ];
6502 const edge& sE = edges_[seIndex];
6508 Pout<< " Found edge: " << seIndex
6510 << " with meIndex: " << meIndex
6511 << " :: " << edges_[meIndex]
6515 // Update reverse map
6516 if (rEdgeMap.found(seIndex))
6518 rEdgeMap[seIndex] = meIndex;
6522 rEdgeMap.insert(seIndex, meIndex);
6526 if (edgeMap.found(meIndex))
6528 edgeMap[meIndex] = seIndex;
6532 edgeMap.insert(meIndex, seIndex);
6535 matchedEdges[edgeI] = true;
6541 if (!matchedEdges[edgeI])
6546 + Foam::name(meIndex),
6547 labelList(cE), 0, false, true
6550 Pout<< " Failed to match edge: "
6551 << meIndex << " :: " << edges_[meIndex]
6552 << " using comparison edge: " << cE
6553 << abort(FatalError);
6558 if (procCouple && !localCouple)
6560 // Update point mapping
6561 forAll(procIndices_, pI)
6563 const coupleMap& cMap = recvMeshes_[pI].map();
6565 // Obtain references
6566 Map<label>& pointMap = cMap.entityMap(coupleMap::POINT);
6567 Map<label>& rPointMap = cMap.reverseEntityMap(coupleMap::POINT);
6569 const changeMap* slaveMapPtr = NULL;
6570 const label pointEnum = coupleMap::POINT;
6572 forAll(slaveMaps, slaveI)
6574 const changeMap& slaveMap = slaveMaps[slaveI];
6576 if (slaveMap.patchIndex() == pI)
6578 if (slaveMap.index() < 0)
6583 if (collapsingSlave)
6585 sI = cMap.findMaster(pointEnum, collapsePoint);
6589 if (rPointMap.found(replacePoint))
6591 rPointMap[replacePoint] = sI;
6595 rPointMap.insert(replacePoint, sI);
6598 pointMap[sI] = replacePoint;
6603 sI = cMap.findSlave(pointEnum, collapsePoint);
6607 if (pointMap.found(replacePoint))
6609 pointMap[replacePoint] = sI;
6613 pointMap.insert(replacePoint, sI);
6616 rPointMap[sI] = replacePoint;
6620 if (sI > -1 && debug > 2)
6622 Pout<< " Found point: " << collapsePoint
6623 << " on proc: " << procIndices_[pI]
6629 // Edge-coupling. Fetch address for later.
6630 slaveMapPtr = &slaveMap;
6638 // Alias for convenience...
6639 const changeMap& slaveMap = *slaveMapPtr;
6641 const labelList& rpList = slaveMap.removedPointList();
6642 const List<objectMap>& apList = slaveMap.addedPointList();
6644 // Configure the slave replacement point.
6645 // - collapseEdge stores this as an 'addedPoint'
6646 label scPoint = rpList[0];
6647 label srPoint = apList[0].index();
6649 if (collapsingSlave)
6651 if (rPointMap[replacePoint] == scPoint)
6653 pointMap[srPoint] = replacePoint;
6654 rPointMap[replacePoint] = srPoint;
6657 pointMap.erase(rPointMap[collapsePoint]);
6658 rPointMap.erase(collapsePoint);
6662 if (pointMap[replacePoint] == scPoint)
6664 rPointMap[srPoint] = replacePoint;
6665 pointMap[replacePoint] = srPoint;
6668 rPointMap.erase(pointMap[collapsePoint]);
6669 pointMap.erase(collapsePoint);
6672 // If any other points were removed, update map
6673 for (label pointI = 1; pointI < rpList.size(); pointI++)
6675 if (collapsingSlave)
6677 if (pointMap.found(rpList[pointI]))
6679 rPointMap.erase(pointMap[rpList[pointI]]);
6680 pointMap.erase(rpList[pointI]);
6685 if (rPointMap.found(rpList[pointI]))
6689 Pout<< " Found removed point: "
6691 << " on proc: " << procIndices_[pI]
6692 << " for point on this proc: "
6693 << rPointMap[rpList[pointI]]
6697 pointMap.erase(rPointMap[rpList[pointI]]);
6698 rPointMap.erase(rpList[pointI]);
6705 // Update face mapping
6706 forAll(procIndices_, pI)
6708 const coupleMap& cMap = recvMeshes_[pI].map();
6709 const dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
6711 // Obtain point maps
6712 Map<label>& pointMap = cMap.entityMap(coupleMap::POINT);
6715 const label faceEnum = coupleMap::FACE;
6717 // Obtain references
6718 Map<label>& faceMap = cMap.entityMap(faceEnum);
6719 Map<label>& rFaceMap = cMap.reverseEntityMap(faceEnum);
6721 const changeMap* slaveMapPtr = NULL;
6723 forAll(slaveMaps, slaveI)
6725 const changeMap& slaveMap = slaveMaps[slaveI];
6727 if (slaveMap.patchIndex() == pI)
6729 if (slaveMap.index() < 0)
6735 // Edge-coupling. Fetch address for later.
6736 slaveMapPtr = &slaveMap;
6741 forAll(checkFaces, faceI)
6743 label mfIndex = checkFaces[faceI];
6745 const face& mF = faces_[mfIndex];
6747 // Skip checks if a conversion occurred,
6748 // and this face was removed as a result
6754 label mfPatch = whichPatch(mfIndex);
6755 label neiProc = getNeighbourProcessor(mfPatch);
6759 pointMap.found(mF[0]) ? pointMap[mF[0]] : -1,
6760 pointMap.found(mF[1]) ? pointMap[mF[1]] : -1,
6761 pointMap.found(mF[2]) ? pointMap[mF[2]] : -1
6764 // Check if a patch conversion is necessary
6765 label newPatch = -1;
6766 bool requireConversion = false, physConvert = false;
6768 // Skip mapping if all points were not found
6769 if (cF[0] == -1 || cF[1] == -1 || cF[2] == -1)
6771 // Is this actually a non-processor patch?
6782 // Has this face been converted to a physical boundary?
6783 if (faceMap.found(mfIndex) && slaveMapPtr)
6785 // Alias for convenience...
6786 const changeMap& sMap = *slaveMapPtr;
6787 const labelList& rfList = sMap.removedFaceList();
6788 const List<objectMap>& afList = sMap.addedFaceList();
6790 // Was the face removed by the slave?
6791 label sfIndex = faceMap[mfIndex];
6793 if (findIndex(rfList, sfIndex) > -1)
6797 Pout<< " Found removed face: " << sfIndex
6798 << " with mfIndex: " << mfIndex
6799 << " :: " << faces_[mfIndex]
6800 << " on proc: " << procIndices_[pI]
6805 rFaceMap.erase(sfIndex);
6806 faceMap.erase(mfIndex);
6809 // Check added faces for special entries
6810 forAll(afList, indexI)
6812 const objectMap& af = afList[indexI];
6816 af.masterObjects().size() ?
6817 af.masterObjects()[0] : 0
6820 // Back out the physical patch ID
6821 if ((af.index() == sfIndex) && (mo < 0))
6823 newPatch = Foam::mag(mo + 2);
6824 requireConversion = true;
6830 // Was an appropriate physical patch found?
6831 if (physConvert && !requireConversion)
6836 // Are we talking to a different processor?
6837 if (neiProc != procIndices_[pI])
6839 // This face needs to be converted
6840 const polyBoundaryMesh& boundary = boundaryMesh();
6842 forAll(boundary, pi)
6844 if (getNeighbourProcessor(pi) == procIndices_[pI])
6847 requireConversion = true;
6853 if (requireConversion)
6855 // Obtain a copy before adding the new face,
6856 // since the reference might become
6857 // invalid during list resizing.
6858 face newFace = faces_[mfIndex];
6859 label newOwn = owner_[mfIndex];
6860 labelList newFaceEdges = faceEdges_[mfIndex];
6862 label newFaceIndex =
6874 meshOps::replaceLabel
6881 // Correct edgeFaces with the new face label.
6882 forAll(newFaceEdges, edgeI)
6884 meshOps::replaceLabel
6888 edgeFaces_[newFaceEdges[edgeI]]
6892 // Finally remove the face
6893 removeFace(mfIndex);
6896 map.removeFace(mfIndex);
6897 map.addFace(newFaceIndex, labelList(1, mfIndex));
6899 // Replace index and patch
6900 mfIndex = newFaceIndex;
6903 // If conversion was to a physical patch,
6904 // skip the remaining face mapping steps
6905 if (getNeighbourProcessor(newPatch) == -1)
6911 Pout<< " Conversion required... "
6912 << " Face: " << newFace << " : "
6913 << newFace.centre(points_)
6914 << abort(FatalError);
6916 // Push a patch-conversion operation
6920 coupleMap::CONVERT_PATCH,
6921 newFace.centre(points_),
6922 newFace.centre(oldPoints_)
6926 // Fetch edges connected to first slave point
6927 const labelList& spEdges = sMesh.pointEdges_[cF[0]];
6929 forAll(spEdges, edgeJ)
6931 label seIndex = spEdges[edgeJ];
6933 if (sMesh.whichEdgePatch(seIndex) == -1)
6938 const labelList& seFaces = sMesh.edgeFaces_[seIndex];
6940 forAll(seFaces, faceJ)
6942 label sfIndex = seFaces[faceJ];
6944 if (sMesh.whichPatch(sfIndex) == -1)
6949 const face& sF = sMesh.faces_[sfIndex];
6955 triFace(sF[0], sF[1], sF[2]), cF
6961 word pN(boundaryMesh()[mfPatch].name());
6963 Pout<< " Found face: " << sfIndex
6965 << " with mfIndex: " << mfIndex
6966 << " :: " << faces_[mfIndex]
6967 << " on proc: " << procIndices_[pI]
6972 if (rFaceMap.found(sfIndex))
6974 rFaceMap[sfIndex] = mfIndex;
6978 rFaceMap.insert(sfIndex, mfIndex);
6981 if (faceMap.found(mfIndex))
6983 faceMap[mfIndex] = sfIndex;
6987 faceMap.insert(mfIndex, sfIndex);
6990 matchedFaces[faceI] = true;
6996 if (matchedFaces[faceI])
7002 if ((debug > 4) && !matchedFaces[faceI])
7007 + Foam::name(mfIndex),
7008 labelList(cF), 0, false, true
7011 Pout<< " Failed to match face: "
7012 << mfIndex << " :: " << faces_[mfIndex]
7013 << " using comparison face: " << cF
7014 << " on proc: " << procIndices_[pI]
7020 // Update edge mapping
7021 forAll(procIndices_, pI)
7023 const coupleMap& cMap = recvMeshes_[pI].map();
7024 const dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
7026 // Obtain point maps
7027 Map<label>& pointMap = cMap.entityMap(coupleMap::POINT);
7030 const label edgeEnum = coupleMap::EDGE;
7032 // Obtain references
7033 Map<label>& edgeMap = cMap.entityMap(edgeEnum);
7034 Map<label>& rEdgeMap = cMap.reverseEntityMap(edgeEnum);
7036 const changeMap* slaveMapPtr = NULL;
7038 forAll(slaveMaps, slaveI)
7040 const changeMap& slaveMap = slaveMaps[slaveI];
7042 if (slaveMap.patchIndex() == pI)
7044 if (slaveMap.index() < 0)
7050 // Edge-coupling. Fetch address for later.
7051 slaveMapPtr = &slaveMap;
7056 forAll(checkEdges, edgeI)
7058 label meIndex = checkEdges[edgeI];
7060 const edge& mE = edges_[meIndex];
7062 // Skip checks if a conversion occurred,
7063 // and this edge was removed as a result
7064 if (edgeFaces_[meIndex].empty())
7069 label mePatch = whichEdgePatch(meIndex);
7070 label neiProc = getNeighbourProcessor(mePatch);
7074 pointMap.found(mE[0]) ? pointMap[mE[0]] : -1,
7075 pointMap.found(mE[1]) ? pointMap[mE[1]] : -1
7078 // Check if a patch conversion is necessary
7079 label newPatch = -1;
7080 bool requireConversion = true, physConvert = false;
7082 // Skip mapping if all points were not found
7083 if (cE[0] == -1 || cE[1] == -1)
7085 // Is this actually a non-processor patch?
7096 // Has this edge been converted to a physical boundary?
7097 const labelList& meFaces = edgeFaces_[meIndex];
7099 forAll(meFaces, faceI)
7101 label mfPatch = whichPatch(meFaces[faceI]);
7108 if (getNeighbourProcessor(mfPatch) == -1)
7110 // Store physical patch for conversion
7115 requireConversion = false;
7119 // Was an appropriate physical patch found?
7120 if (physConvert && !requireConversion)
7125 if (requireConversion)
7127 edge newEdge = edges_[meIndex];
7128 labelList newEdgeFaces = edgeFaces_[meIndex];
7130 // Insert the new edge
7131 label newEdgeIndex =
7141 // Replace faceEdges for all
7143 forAll(newEdgeFaces, faceI)
7145 meshOps::replaceLabel
7149 faceEdges_[newEdgeFaces[faceI]]
7154 removeEdge(meIndex);
7157 map.removeEdge(meIndex);
7158 map.addEdge(newEdgeIndex, labelList(1, meIndex));
7160 // Replace index and patch
7161 meIndex = newEdgeIndex;
7164 // If conversion was to a physical patch,
7165 // skip the remaining face mapping steps
7166 if (getNeighbourProcessor(newPatch) == -1)
7172 // Fetch edges connected to first slave point
7173 const labelList& spEdges = sMesh.pointEdges_[cE[0]];
7175 forAll(spEdges, edgeJ)
7177 label seIndex = spEdges[edgeJ];
7179 const edge& sE = sMesh.edges_[seIndex];
7185 Pout<< " Found edge: " << seIndex
7187 << " with meIndex: " << meIndex
7188 << " :: " << edges_[meIndex]
7189 << " on proc: " << procIndices_[pI]
7193 // Update reverse map
7194 if (rEdgeMap.found(seIndex))
7196 rEdgeMap[seIndex] = meIndex;
7200 rEdgeMap.insert(seIndex, meIndex);
7204 if (edgeMap.found(meIndex))
7206 edgeMap[meIndex] = seIndex;
7210 edgeMap.insert(meIndex, seIndex);
7213 matchedEdges[edgeI] = true;
7219 if (!matchedEdges[edgeI])
7221 // Check if a coupling existed before
7222 if (edgeMap.found(meIndex) && slaveMapPtr)
7224 // Alias for convenience...
7225 const changeMap& sMap = *slaveMapPtr;
7226 const labelList& reList = sMap.removedEdgeList();
7228 // Was the edge removed by the slave?
7229 if (findIndex(reList, edgeMap[meIndex]) > -1)
7233 Pout<< " Found removed edge: "
7235 << " with meIndex: " << meIndex
7236 << " :: " << edges_[meIndex]
7237 << " on proc: " << procIndices_[pI]
7242 rEdgeMap.erase(edgeMap[meIndex]);
7243 edgeMap.erase(meIndex);
7245 matchedEdges[edgeI] = true;
7250 if ((debug > 4) && !matchedEdges[edgeI])
7255 + Foam::name(meIndex),
7256 labelList(cE), 0, false, true
7259 Pout<< " Failed to match edge: "
7260 << meIndex << " :: " << edges_[meIndex]
7261 << " using comparison edge: " << cE
7262 << " on proc: " << procIndices_[pI]
7269 // Ensure that all entities were matched
7270 label nFailFace = 0, nFailEdge = 0;
7272 forAll(matchedFaces, faceI)
7274 if (!matchedFaces[faceI])
7280 forAll(matchedEdges, edgeI)
7282 if (!matchedEdges[edgeI])
7288 if (nFailFace || nFailEdge)
7290 Pout<< " Failed to match all entities. " << nl
7291 << " Faces: " << nFailFace << nl
7292 << " Edges: " << nFailEdge << nl
7293 << abort(FatalError);
7298 topoChangeFlag_ = true;
7300 // Increment the counter
7301 status(TOTAL_COLLAPSES)++;
7303 // Increment the number of modifications
7304 status(TOTAL_MODIFICATIONS)++;
7306 // Return a succesful collapse
7307 map.type() = collapseCase;
7313 // Remove cell layer above specified patch
7314 const changeMap dynamicTopoFvMesh::removeCellLayer
7321 labelHashSet edgesToRemove, facesToRemove;
7322 Map<labelPair> pointsToRemove, edgesToKeep;
7324 dynamicLabelList patchFaces(patchSizes_[patchID]);
7325 DynamicList<labelPair> cellsToRemove(patchSizes_[patchID]);
7326 DynamicList<labelPair> hFacesToRemove(patchSizes_[patchID]);
7328 for (label faceI = nOldInternalFaces_; faceI < faces_.size(); faceI++)
7330 label pIndex = whichPatch(faceI);
7332 if (pIndex != patchID)
7338 label cIndex = owner_[faceI];
7340 // Add face to the list
7341 patchFaces.append(faceI);
7343 // Fetch appropriate face / cell
7344 const face& bFace = faces_[faceI];
7345 const cell& ownCell = cells_[cIndex];
7347 // Get the opposing face from the cell
7348 oppositeFace oFace = ownCell.opposingFace(faceI, faces_);
7352 // Something's wrong here.
7355 "const changeMap dynamicTopoFvMesh::removeCellLayer"
7356 "(const label patchID)"
7358 << " Face: " << faceI << " :: " << bFace << nl
7359 << " has no opposing face in cell: "
7360 << cIndex << " :: " << ownCell << nl
7361 << abort(FatalError);
7364 // Fetch cell on the other-side of the opposite face
7365 label otherCellIndex =
7367 (owner_[oFace.oppositeIndex()] == cIndex) ?
7368 neighbour_[oFace.oppositeIndex()] :
7369 owner_[oFace.oppositeIndex()]
7372 if (otherCellIndex == -1)
7374 // Opposite face is on a boundary, and layer
7375 // removal would be invalid if we continued.
7381 // Fetch reference to other cell
7382 const cell& otherCell = cells_[otherCellIndex];
7384 // Find opposite face on the other cell
7385 oppositeFace otFace =
7387 otherCell.opposingFace
7389 oFace.oppositeIndex(),
7394 if (!otFace.found())
7396 // Something's wrong here.
7399 "const changeMap dynamicTopoFvMesh::removeCellLayer"
7400 "(const label patchID)"
7402 << " Face: " << oFace.oppositeIndex()
7403 << " :: " << oFace << nl
7404 << " has no opposing face in cell: "
7405 << otherCellIndex << " :: " << otherCell << nl
7406 << abort(FatalError);
7409 // All edges on the boundary face are to be retained
7410 const labelList& fEdges = faceEdges_[faceI];
7411 const labelList& ofEdges = faceEdges_[oFace.oppositeIndex()];
7412 const labelList& otfEdges = faceEdges_[otFace.oppositeIndex()];
7414 forAll(fEdges, edgeI)
7416 label eIndex = fEdges[edgeI];
7418 if (!edgesToKeep.found(eIndex))
7420 // Find equivalent edge on opposite face
7421 label oeIndex = -1, oteIndex = -1;
7422 const edge& bEdge = edges_[eIndex];
7424 // Build edges for comparison
7425 label startLoc = bFace.which(bEdge[0]);
7426 label endLoc = bFace.which(bEdge[1]);
7428 edge cEdge(oFace[startLoc], oFace[endLoc]);
7429 edge ctEdge(otFace[startLoc], otFace[endLoc]);
7431 forAll(ofEdges, edgeJ)
7433 const edge& ofEdge = edges_[ofEdges[edgeJ]];
7435 if (cEdge == ofEdge)
7437 oeIndex = ofEdges[edgeJ];
7442 forAll(otfEdges, edgeJ)
7444 const edge& otfEdge = edges_[otfEdges[edgeJ]];
7446 if (ctEdge == otfEdge)
7448 oteIndex = otfEdges[edgeJ];
7453 if (oeIndex < 0 || oteIndex < 0)
7457 "const changeMap dynamicTopoFvMesh::removeCellLayer"
7458 "(const label patchID)"
7460 << " Could not find comparison edge: " << nl
7461 << " cEdge: " << cEdge
7462 << " oeIndex: " << oeIndex << nl
7463 << " ctEdge: " << ctEdge
7464 << " oteIndex: " << oteIndex << nl
7465 << " for edge: " << bEdge
7466 << abort(FatalError);
7470 edgesToKeep.insert(eIndex, labelPair(oeIndex, oteIndex));
7474 // Add information to removal lists
7475 cellsToRemove.append
7484 hFacesToRemove.append
7488 oFace.oppositeIndex(),
7489 otFace.oppositeIndex()
7493 // Mark points for removal
7494 forAll(oFace, pointI)
7496 label pIndex = oFace[pointI];
7498 if (!pointsToRemove.found(pIndex))
7501 pointsToRemove.insert
7504 labelPair(bFace[pointI], otFace[pointI])
7509 // Loop through cell faces and mark
7510 // faces / edges for removal
7511 forAll(ownCell, faceJ)
7513 label fIndex = ownCell[faceJ];
7515 if (fIndex == faceI || fIndex == oFace.oppositeIndex())
7520 if (!facesToRemove.found(fIndex))
7522 facesToRemove.insert(fIndex);
7525 const labelList& checkEdges = faceEdges_[fIndex];
7527 forAll(checkEdges, edgeI)
7529 label eIndex = checkEdges[edgeI];
7531 if (edgesToKeep.found(eIndex))
7536 if (!edgesToRemove.found(eIndex))
7538 edgesToRemove.insert(eIndex);
7544 // Correct edgeFaces / faceEdges for retained edges
7545 forAllConstIter(Map<labelPair>, edgesToKeep, eIter)
7547 const labelList& rmeFaces = edgeFaces_[eIter().first()];
7549 forAll(rmeFaces, faceI)
7551 labelList& fE = faceEdges_[rmeFaces[faceI]];
7553 bool foundRp = (findIndex(fE, eIter.key()) > -1);
7554 bool foundRn = (findIndex(fE, eIter().second()) > -1);
7558 // Size-down edgeFaces for replacement
7559 meshOps::sizeDownList
7562 edgeFaces_[eIter.key()]
7568 // Size-up edgeFaces for replacement
7572 edgeFaces_[eIter.key()]
7575 // Replace edge index
7576 meshOps::replaceLabel
7586 // Remove unwanted faces
7587 forAllConstIter(labelHashSet, facesToRemove, fIter)
7590 removeFace(fIter.key());
7593 map.removeFace(fIter.key());
7596 // Remove unwanted edges
7597 forAllConstIter(labelHashSet, edgesToRemove, eIter)
7600 removeEdge(eIter.key());
7603 map.removeEdge(eIter.key());
7606 // Remove unwanted points
7607 forAllConstIter(Map<labelPair>, pointsToRemove, pIter)
7609 // Update pointEdges information first
7612 const labelList& pEdges = pointEdges_[pIter.key()];
7614 // Configure edge for comparison
7621 label replaceEdge = -1;
7623 forAll(pEdges, edgeI)
7625 const edge& checkEdge = edges_[pEdges[edgeI]];
7627 if (checkEdge == cEdge)
7629 replaceEdge = pEdges[edgeI];
7634 if (replaceEdge == -1)
7638 "const changeMap dynamicTopoFvMesh::removeCellLayer"
7639 "(const label patchID)"
7641 << " Could not find comparison edge: " << nl
7642 << " cEdge: " << cEdge
7643 << " for point: " << pIter.key() << nl
7644 << " pointEdges: " << pEdges
7645 << abort(FatalError);
7648 // Size-up pointEdges
7652 pointEdges_[pIter().first()]
7657 removePoint(pIter.key());
7660 map.removePoint(pIter.key());
7663 // Track modified faces for mapping
7664 labelHashSet modifiedFaces;
7667 forAll(cellsToRemove, indexI)
7669 // Replace face label on the other cell
7670 meshOps::replaceLabel
7672 hFacesToRemove[indexI].first(),
7674 cells_[cellsToRemove[indexI].second()]
7677 // Set owner information
7678 owner_[patchFaces[indexI]] = cellsToRemove[indexI].second();
7680 // Replace points on faces / edges
7681 const cell& otherCell = cells_[cellsToRemove[indexI].second()];
7683 forAll(otherCell, faceI)
7685 face& faceToCheck = faces_[otherCell[faceI]];
7687 bool modified = false;
7689 forAll(faceToCheck, pointI)
7691 if (pointsToRemove.found(faceToCheck[pointI]))
7693 faceToCheck[pointI] =
7695 pointsToRemove[faceToCheck[pointI]].first()
7703 if (modified && !modifiedFaces.found(otherCell[faceI]))
7705 modifiedFaces.insert(otherCell[faceI]);
7708 const labelList& fEdges = faceEdges_[otherCell[faceI]];
7710 forAll(fEdges, edgeI)
7712 edge& edgeToCheck = edges_[fEdges[edgeI]];
7714 if (pointsToRemove.found(edgeToCheck[0]))
7718 pointsToRemove[edgeToCheck[0]].first()
7722 if (pointsToRemove.found(edgeToCheck[1]))
7726 pointsToRemove[edgeToCheck[1]].first()
7732 // Remove horizontal interior face
7733 removeFace(hFacesToRemove[indexI].first());
7736 map.removeFace(hFacesToRemove[indexI].first());
7739 removeCell(cellsToRemove[indexI].first());
7742 map.removeCell(cellsToRemove[indexI].first());
7745 // Now that all old / new cells possess correct connectivity,
7746 // compute mapping information.
7747 forAll(cellsToRemove, indexI)
7749 // Set mapping for the modified cell
7752 cellsToRemove[indexI].second(),
7753 labelList(cellsToRemove[indexI])
7757 // Set face mapping information for modified faces
7758 forAllConstIter(labelHashSet, modifiedFaces, fIter)
7760 // Decide between default / weighted mapping
7761 // based on boundary information
7762 label fPatch = whichPatch(fIter.key());
7766 // Default mapping for interior faces
7767 setFaceMapping(fIter.key());
7771 // Map boundary face from itself
7772 setFaceMapping(fIter.key(), labelList(1, fIter.key()));
7777 topoChangeFlag_ = true;
7779 // Specify that the operation was successful
7782 // Return the changeMap
7787 // Merge a set of boundary faces into internal
7788 const changeMap dynamicTopoFvMesh::mergeBoundaryFaces
7790 const labelList& mergeFaces
7797 Pout << "Merging faces: " << mergeFaces << endl;
7800 List<labelPair> mergePairs(0);
7802 forAll(mergeFaces, faceI)
7804 const face& fI = faces_[mergeFaces[faceI]];
7806 for (label faceJ = faceI + 1; faceJ < mergeFaces.size(); faceJ++)
7808 const face& fJ = faces_[mergeFaces[faceJ]];
7812 if (fI.size() == fJ.size() && fI.size() == 3)
7818 triFace(fI[0], fI[1], fI[2]),
7819 triFace(fJ[0], fJ[1], fJ[2])
7827 if (face::compare(fI, fJ))
7836 labelPair(mergeFaces[faceI], mergeFaces[faceJ]),
7847 Pout<< " mergePairs: " << mergePairs << endl;
7850 dynamicLabelList checkEdges(10);
7852 forAll(mergePairs, pairI)
7854 label firstFace = mergePairs[pairI].first();
7855 label secondFace = mergePairs[pairI].second();
7857 // Obtain owners for both faces, and compare their labels
7858 label newOwner = -1, newNeighbour = -1;
7859 label removedFace = -1, retainedFace = -1;
7861 if (owner_[firstFace] < owner_[secondFace])
7863 // Retain the first face
7864 removedFace = secondFace;
7865 retainedFace = firstFace;
7867 newOwner = owner_[firstFace];
7868 newNeighbour = owner_[secondFace];
7872 // Retain the second face
7873 removedFace = firstFace;
7874 retainedFace = secondFace;
7876 newOwner = owner_[secondFace];
7877 newNeighbour = owner_[firstFace];
7880 // Insert a new interior face
7881 label newFaceIndex =
7886 face(faces_[retainedFace]),
7889 labelList(faceEdges_[retainedFace])
7894 map.addFace(newFaceIndex);
7896 // Replace cell with the new face label
7897 meshOps::replaceLabel
7901 cells_[owner_[removedFace]]
7904 meshOps::replaceLabel
7908 cells_[owner_[retainedFace]]
7911 const labelList& fEdges = faceEdges_[newFaceIndex];
7912 const labelList& rfEdges = faceEdges_[removedFace];
7914 // Check for common edges on the removed face
7915 forAll(rfEdges, edgeI)
7917 label reIndex = rfEdges[edgeI];
7919 if (findIndex(fEdges, reIndex) == -1)
7921 // Find the equivalent edge
7922 const edge& rEdge = edges_[reIndex];
7923 const labelList& reFaces = edgeFaces_[reIndex];
7927 forAll(fEdges, edgeJ)
7929 if (edges_[fEdges[edgeJ]] == rEdge)
7931 keIndex = fEdges[edgeJ];
7938 Pout<< " Could not find edge for: "
7939 << reIndex << " :: " << rEdge
7940 << abort(FatalError);
7943 // Add edgeFaces from this edge
7944 forAll(reFaces, faceI)
7946 if (reFaces[faceI] == removedFace)
7957 meshOps::replaceLabel
7961 faceEdges_[reFaces[faceI]]
7965 // Remove the old edge
7966 removeEdge(reIndex);
7969 map.removeEdge(reIndex);
7973 // Replace edgeFaces with the new face label
7974 forAll(fEdges, edgeI)
7976 label eIndex = fEdges[edgeI];
7978 if (findIndex(edgeFaces_[eIndex], removedFace) > -1)
7980 meshOps::sizeDownList
7987 if (findIndex(edgeFaces_[eIndex], retainedFace) > -1)
7989 meshOps::sizeDownList
7996 // Size-up list with the new face index
8003 if (findIndex(checkEdges, eIndex) == -1)
8005 checkEdges.append(eIndex);
8009 // Remove the boundary faces
8010 removeFace(removedFace);
8011 removeFace(retainedFace);
8014 map.removeFace(removedFace);
8015 map.removeFace(retainedFace);
8018 forAll(checkEdges, edgeI)
8020 bool allInterior = true;
8021 label eIndex = checkEdges[edgeI];
8023 const labelList& eFaces = edgeFaces_[eIndex];
8025 forAll(eFaces, faceI)
8027 if (whichPatch(eFaces[faceI]) > -1)
8029 allInterior = false;
8036 // This edge needs to be converted to an interior one
8037 label newEdgeIndex =
8042 edge(edges_[eIndex]),
8043 labelList(edgeFaces_[eIndex])
8048 map.addEdge(newEdgeIndex, labelList(1, eIndex));
8050 // Update faceEdges information for all connected faces
8051 const labelList& neFaces = edgeFaces_[newEdgeIndex];
8053 forAll(neFaces, faceI)
8055 meshOps::replaceLabel
8059 faceEdges_[neFaces[faceI]]
8063 // Remove the old boundary edge
8067 map.removeEdge(eIndex);
8070 checkEdges[edgeI] = newEdgeIndex;
8076 Pout<< "Merge complete." << nl << endl;
8079 // Return a succesful merge
8086 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
8088 } // End namespace Foam
8090 // ************************************************************************* //