1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM 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 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
28 #include "objectRegistry.H"
30 #include "objectMap.H"
31 #include "changeMap.H"
32 #include "multiThreader.H"
33 #include "coupledInfo.H"
34 #include "dynamicTopoFvMesh.H"
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
43 // Method to collapse a quad-face in 2D
44 // - Returns a changeMap with a type specifying:
45 // -3: Collapse failed since face was on a noRefinement patch.
46 // -1: Collapse failed since max number of topo-changes was reached.
47 // 0: Collapse could not be performed.
48 // 1: Collapsed to first node.
49 // 2: Collapsed to second node.
50 // 3: Collapse to mid-point.
51 // - overRideCase is used to force a certain collapse configuration.
52 // -1: Use this value to let collapseQuadFace decide a case.
53 // 1: Force collapse to first node.
54 // 2: Force collapse to second node.
55 // 3: Force collapse to mid-point.
56 // - checkOnly performs a feasibility check and returns without modifications.
57 const changeMap dynamicTopoFvMesh::collapseQuadFace
65 // Figure out which thread this is...
66 label tIndex = self();
68 // Prepare the changeMaps
70 List<changeMap> slaveMaps;
71 bool collapsingSlave = false;
75 (statistics_[0] > maxModifications_)
76 && (maxModifications_ > -1)
79 // Reached the max allowable topo-changes.
80 stack(tIndex).clear();
85 // Check if edgeRefinements are to be avoided on patch.
86 if (baseMesh_.lengthEstimator().checkRefinementPatch(whichPatch(fIndex)))
93 // Sanity check: Is the index legitimate?
100 "dynamicTopoFvMesh::collapseQuadFace\n"
102 " const label fIndex,\n"
103 " label overRideCase,\n"
108 << " Invalid index: " << fIndex
109 << abort(FatalError);
112 // Define the edges on the face to be collapsed
113 FixedList<edge,4> checkEdge(edge(-1, -1));
114 FixedList<label,4> checkEdgeIndex(-1);
117 getCheckEdges(fIndex, (*this), map, checkEdge, checkEdgeIndex);
119 // Determine the common vertices for the first and second edges
120 label cv0 = checkEdge[1].commonVertex(checkEdge[0]);
121 label cv1 = checkEdge[1].commonVertex(checkEdge[3]);
122 label cv2 = checkEdge[2].commonVertex(checkEdge[0]);
123 label cv3 = checkEdge[2].commonVertex(checkEdge[3]);
125 // If coupled modification is set, and this is a
126 // master face, collapse its slaves first.
127 bool localCouple = false, procCouple = false;
129 if (coupledModification_)
131 const face& fCheck = faces_[fIndex];
133 const label faceEnum = coupleMap::FACE;
134 const label pointEnum = coupleMap::POINT;
136 // Is this a locally coupled edge (either master or slave)?
137 if (locallyCoupledEntity(fIndex, true))
143 if (processorCoupledEntity(fIndex))
149 if (localCouple && !procCouple)
151 // Determine the slave index.
152 label sIndex = -1, pIndex = -1;
154 forAll(patchCoupling_, patchI)
156 if (patchCoupling_(patchI))
158 const coupleMap& cMap = patchCoupling_[patchI].map();
160 if ((sIndex = cMap.findSlave(faceEnum, fIndex)) > -1)
167 // The following bit happens only during the sliver
168 // exudation process, since slave edges are
169 // usually not added to the coupled edge-stack.
170 if ((sIndex = cMap.findMaster(faceEnum, fIndex)) > -1)
174 // Notice that we are collapsing a slave edge first.
175 collapsingSlave = true;
188 "dynamicTopoFvMesh::collapseQuadFace\n"
190 " const label fIndex,\n"
191 " label overRideCase,\n"
196 << "Coupled maps were improperly specified." << nl
197 << " Slave index not found for: " << nl
198 << " Face: " << fIndex << ": " << fCheck << nl
199 << abort(FatalError);
203 // If we've found the slave, size up the list
210 // Save index and patch for posterity
211 slaveMaps[0].index() = sIndex;
212 slaveMaps[0].patchIndex() = pIndex;
217 Pout<< nl << " >> Collapsing slave face: " << sIndex
218 << " for master face: " << fIndex << endl;
222 if (procCouple && !localCouple)
224 // If this is a new entity, bail out for now.
225 // This will be handled at the next time-step.
226 if (fIndex >= nOldFaces_)
232 forAll(procIndices_, pI)
234 // Fetch reference to subMeshes
235 const coupledInfo& sendMesh = sendMeshes_[pI];
236 const coupledInfo& recvMesh = recvMeshes_[pI];
238 const coupleMap& scMap = sendMesh.map();
239 const coupleMap& rcMap = recvMesh.map();
241 // If this face was sent to a lower-ranked
242 // processor, skip it.
243 if (procIndices_[pI] < Pstream::myProcNo())
245 if (scMap.reverseEntityMap(faceEnum).found(fIndex))
249 Pout<< "Face: " << fIndex
251 << " was sent to proc: "
253 << ", so bailing out."
263 if ((sIndex = rcMap.findSlave(faceEnum, fIndex)) > -1)
265 // Check if a lower-ranked processor is
266 // handling this face
267 if (procIndices_[pI] < Pstream::myProcNo())
271 Pout<< "Face: " << fIndex
273 << " is handled by proc: "
275 << ", so bailing out."
282 label curIndex = slaveMaps.size();
291 // Save index and patch for posterity
292 slaveMaps[curIndex].index() = sIndex;
293 slaveMaps[curIndex].patchIndex() = pI;
299 rcMap.findSlave(pointEnum, cv0) > -1 &&
300 rcMap.findSlave(pointEnum, cv1) > -1
303 rcMap.findSlave(pointEnum, cv2) > -1 &&
304 rcMap.findSlave(pointEnum, cv3) > -1
308 // An edge-only coupling exists.
310 // Check if a lower-ranked processor is
311 // handling this face
312 if (procIndices_[pI] < Pstream::myProcNo())
316 Pout<< "Face edge on: " << fIndex
318 << " is handled by proc: "
320 << ", so bailing out."
327 label p0 = rcMap.findSlave(pointEnum, cv0);
328 label p1 = rcMap.findSlave(pointEnum, cv1);
330 label p2 = rcMap.findSlave(pointEnum, cv2);
331 label p3 = rcMap.findSlave(pointEnum, cv3);
334 label edgeCouple = -1;
336 if ((p0 > -1 && p1 > -1) && (p2 == -1 && p3 == -1))
342 sIndex = readLabel(map.lookup("firstEdge"));
345 if ((p0 == -1 && p1 == -1) && (p2 > -1 && p3 > -1))
351 sIndex = readLabel(map.lookup("secondEdge"));
354 label curIndex = slaveMaps.size();
363 // Unfortunately, since no edge maps are
364 // available in 2D, loop through boundary
365 // faces on subMesh and get the right edge
368 const dynamicTopoFvMesh& sMesh = recvMesh.subMesh();
372 label faceI = sMesh.nOldInternalFaces_;
373 faceI < sMesh.faceEdges_.size();
377 const labelList& fEdges = sMesh.faceEdges_[faceI];
379 forAll(fEdges, edgeI)
381 if (sMesh.edges_[fEdges[edgeI]] == cEdge)
383 seIndex = fEdges[edgeI];
396 Pout<< "Face edge on: " << fIndex
398 << " sIndex: " << sIndex
399 << " could not be found."
400 << abort(FatalError);
403 // Save index and patch for posterity
404 // - Negate the index to signify edge coupling
405 slaveMaps[curIndex].index() = -seIndex;
406 slaveMaps[curIndex].patchIndex() = pI;
408 // Save edgeCouple as well, so that
409 // another map comparison is avoided.
410 slaveMaps[curIndex].type() = edgeCouple;
416 // Something's wrong with coupling maps
421 "dynamicTopoFvMesh::collapseQuadFace\n"
423 " const label fIndex,\n"
424 " label overRideCase,\n"
429 << "Coupled maps were improperly specified." << nl
430 << " localCouple: " << localCouple << nl
431 << " procCouple: " << procCouple << nl
432 << " Face: " << fIndex << ": " << fCheck << nl
433 << abort(FatalError);
436 // Temporarily turn off coupledModification
437 unsetCoupledModification();
439 // Test the master face for collapse, and decide on a case
440 changeMap masterMap = collapseQuadFace(fIndex, -1, true, forceOp);
443 setCoupledModification();
445 // Master couldn't perform collapse
446 if (masterMap.type() <= 0)
451 // For edge-only coupling, define the points for checking
452 List<FixedList<point, 2> > slaveMoveNewPoint(slaveMaps.size());
453 List<FixedList<point, 2> > slaveMoveOldPoint(slaveMaps.size());
455 // Now check each of the slaves for collapse feasibility
456 forAll(slaveMaps, slaveI)
458 // Alias for convenience...
459 changeMap& slaveMap = slaveMaps[slaveI];
461 label slaveOverRide = -1;
462 label sIndex = slaveMap.index();
463 label pI = slaveMap.patchIndex();
464 const coupleMap* cMapPtr = NULL;
468 cMapPtr = &(patchCoupling_[pI].map());
473 const dynamicTopoFvMesh& sMesh =
475 recvMeshes_[pI].subMesh()
478 cMapPtr = &(recvMeshes_[pI].map());
484 Pout<< "Checking slave edge: " << mag(sIndex)
485 << "::" << sMesh.edges_[mag(sIndex)]
486 << " on proc: " << procIndices_[pI]
487 << " for master face: " << fIndex
488 << " using collapseCase: " << masterMap.type()
493 Pout<< "Checking slave face: " << sIndex
494 << "::" << sMesh.faces_[sIndex]
495 << " on proc: " << procIndices_[pI]
496 << " for master face: " << fIndex
497 << " using collapseCase: " << masterMap.type()
503 // Define an overRide case for the slave
504 FixedList<edge, 2> mEdge(edge(-1, -1)), sEdge(edge(-1, -1));
508 const Map<label>& rPointMap =
510 cMapPtr->reverseEntityMap(pointEnum)
515 if (slaveMap.type() == 1)
517 mEdge[0][0] = rPointMap[cv0];
518 mEdge[0][1] = rPointMap[cv1];
521 if (slaveMap.type() == 2)
523 mEdge[0][0] = rPointMap[cv2];
524 mEdge[0][1] = rPointMap[cv3];
529 mEdge[0][0] = rPointMap[cv0];
530 mEdge[0][1] = rPointMap[cv1];
532 mEdge[1][0] = rPointMap[cv2];
533 mEdge[1][1] = rPointMap[cv3];
538 const Map<label>& pointMap =
540 cMapPtr->entityMap(pointEnum)
545 if (slaveMap.type() == 1)
547 mEdge[0][0] = pointMap[cv0];
548 mEdge[0][1] = pointMap[cv1];
551 if (slaveMap.type() == 2)
553 mEdge[0][0] = pointMap[cv2];
554 mEdge[0][1] = pointMap[cv3];
559 mEdge[0][0] = pointMap[cv0];
560 mEdge[0][1] = pointMap[cv1];
562 mEdge[1][0] = pointMap[cv2];
563 mEdge[1][1] = pointMap[cv3];
567 // Determine checkEdges for the slave
568 FixedList<edge,4> slaveCheckEdge(edge(-1, -1));
569 FixedList<label,4> slaveCheckEdgeIndex(-1);
582 sEdge[0] = edges_[readLabel(slaveMap.lookup("firstEdge"))];
583 sEdge[1] = edges_[readLabel(slaveMap.lookup("secondEdge"))];
588 const dynamicTopoFvMesh& sMesh =
590 recvMeshes_[pI].subMesh()
595 sEdge[0] = sMesh.edges_[mag(sIndex)];
610 sMesh.edges_[readLabel(slaveMap.lookup("firstEdge"))]
615 sMesh.edges_[readLabel(slaveMap.lookup("secondEdge"))]
620 // Compare edge orientations for edge-only coupling
623 // Perform a topological comparison.
624 switch (masterMap.type())
630 slaveMoveNewPoint[slaveI][0] = points_[cv0];
631 slaveMoveNewPoint[slaveI][1] = points_[cv1];
633 slaveMoveOldPoint[slaveI][0] = oldPoints_[cv0];
634 slaveMoveOldPoint[slaveI][1] = oldPoints_[cv1];
637 if (mEdge[0] == sEdge[0])
642 if (mEdge[1] == sEdge[0])
648 // Write out for for post-processing
649 writeVTK("mFace_" + Foam::name(fIndex), fIndex, 2);
655 "dynamicTopoFvMesh::collapseQuadFace\n"
657 " const label fIndex,\n"
658 " label overRideCase,\n"
663 << "Coupled collapse failed." << nl
665 << checkEdgeIndex[1] << ": "
666 << checkEdge[1] << nl
667 << checkEdgeIndex[2] << ": "
668 << checkEdge[2] << nl
670 << readLabel(slaveMap.lookup("firstEdge")) << ": "
672 << readLabel(slaveMap.lookup("secondEdge")) << ": "
674 << abort(FatalError);
684 slaveMoveNewPoint[slaveI][0] = points_[cv2];
685 slaveMoveNewPoint[slaveI][1] = points_[cv3];
687 slaveMoveOldPoint[slaveI][0] = oldPoints_[cv2];
688 slaveMoveOldPoint[slaveI][1] = oldPoints_[cv3];
691 if (mEdge[1] == sEdge[1])
696 if (mEdge[0] == sEdge[1])
702 // Write out for for post-processing
703 writeVTK("mFace_" + Foam::name(fIndex), fIndex, 2);
709 "dynamicTopoFvMesh::collapseQuadFace\n"
711 " const label fIndex,\n"
712 " label overRideCase,\n"
717 << "Coupled collapse failed." << nl
719 << checkEdgeIndex[1] << ": "
720 << checkEdge[1] << nl
721 << checkEdgeIndex[2] << ": "
722 << checkEdge[2] << nl
724 << readLabel(slaveMap.lookup("firstEdge")) << ": "
726 << readLabel(slaveMap.lookup("secondEdge")) << ": "
728 << abort(FatalError);
738 slaveMoveNewPoint[slaveI][0] =
740 0.5 * (points_[cv0] + points_[cv2])
743 slaveMoveNewPoint[slaveI][1] =
745 0.5 * (points_[cv1] + points_[cv3])
748 slaveMoveOldPoint[slaveI][0] =
750 0.5 * (oldPoints_[cv0] + oldPoints_[cv2])
753 slaveMoveOldPoint[slaveI][1] =
755 0.5 * (oldPoints_[cv1] + oldPoints_[cv3])
769 // Check edge orientation
770 compVal = edge::compare(mEdge[0], sEdge[0]);
772 // Swap components if necessary
777 slaveMoveNewPoint[slaveI][0],
778 slaveMoveNewPoint[slaveI][1]
783 slaveMoveOldPoint[slaveI][0],
784 slaveMoveOldPoint[slaveI][1]
794 "dynamicTopoFvMesh::collapseQuadFace\n"
796 " const label fIndex,\n"
797 " label overRideCase,\n"
802 << "Coupled topo-change for slave failed." << nl
803 << " Dissimilar edges: " << nl
804 << " mEdge: " << mEdge << nl
805 << " sEdge: " << sEdge << nl
806 << " masterMap type: " << masterMap.type() << nl
807 << abort(FatalError);
811 // Temporarily turn off coupledModification
812 unsetCoupledModification();
814 // Test the slave face
819 collapseQuadFace(sIndex, slaveOverRide, true, forceOp)
825 dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
829 // Edge-based coupling
831 // Build a hull of cells and tri-faces
832 // that are connected to the slave edge
833 labelList slaveHullCells;
834 labelList slaveHullTriFaces;
836 meshOps::constructPrismHull
848 bool infeasible = false;
850 // Keep track of resulting cell quality,
851 // if collapse is indeed feasible
852 scalar slaveCollapseQuality(GREAT);
854 // Check whether the collapse is possible.
861 FixedList<label, 2>(-1),
862 FixedList<label, 2>(-1),
864 slaveMoveNewPoint[slaveI],
865 slaveMoveOldPoint[slaveI],
866 slaveCollapseQuality,
886 // Edge-based coupling
889 sMesh.collapseQuadFace
901 setCoupledModification();
903 if (slaveMap.type() <= 0)
905 // Slave couldn't perform collapse.
911 // Save index and patch for posterity
912 slaveMap.index() = sIndex;
913 slaveMap.patchIndex() = pI;
916 // Next collapse each slave face (for real this time...)
917 forAll(slaveMaps, slaveI)
919 // Alias for convenience...
920 changeMap& slaveMap = slaveMaps[slaveI];
922 label sIndex = slaveMap.index();
923 label pI = slaveMap.patchIndex();
924 label slaveOverRide = slaveMap.type();
926 // Temporarily turn off coupledModification
927 unsetCoupledModification();
929 // Collapse the slave
934 collapseQuadFace(sIndex, slaveOverRide, false, forceOp)
939 dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
943 // Edge-based coupling
944 const coupleMap& cMap = recvMeshes_[pI].map();
946 // Fetch the slave edge
947 edge sEdge = sMesh.edges_[mag(sIndex)];
949 // Move points to new location,
950 // and update operation into coupleMap
951 sMesh.points_[sEdge[0]] = slaveMoveNewPoint[slaveI][0];
952 sMesh.points_[sEdge[1]] = slaveMoveNewPoint[slaveI][1];
954 sMesh.oldPoints_[sEdge[0]] = slaveMoveOldPoint[slaveI][0];
955 sMesh.oldPoints_[sEdge[1]] = slaveMoveOldPoint[slaveI][1];
960 coupleMap::MOVE_POINT,
961 slaveMoveNewPoint[slaveI][0],
962 slaveMoveOldPoint[slaveI][0]
968 coupleMap::MOVE_POINT,
969 slaveMoveNewPoint[slaveI][1],
970 slaveMoveOldPoint[slaveI][1]
973 // Force operation to succeed
978 // Face-based coupling
981 sMesh.collapseQuadFace
993 setCoupledModification();
995 // The final operation has to succeed.
996 if (slaveMap.type() <= 0)
1002 "dynamicTopoFvMesh::collapseQuadFace\n"
1004 " const label fIndex,\n"
1005 " label overRideCase,\n"
1006 " bool checkOnly,\n"
1010 << "Coupled topo-change for slave failed." << nl
1011 << " Face: " << fIndex << ": " << fCheck << nl
1012 << " Slave index: " << sIndex << nl
1013 << " Patch index: " << pI << nl
1014 << " Type: " << slaveMap.type() << nl
1015 << abort(FatalError);
1018 // Save index and patch for posterity
1019 slaveMap.index() = sIndex;
1020 slaveMap.patchIndex() = pI;
1024 // Build a hull of cells and tri-faces that are connected to each edge
1025 FixedList<labelList, 2> hullCells;
1026 FixedList<labelList, 2> hullTriFaces;
1028 meshOps::constructPrismHull
1040 meshOps::constructPrismHull
1052 // Determine the neighbouring cells
1053 label c0 = owner_[fIndex], c1 = neighbour_[fIndex];
1055 // Define variables for the prism-face calculation
1056 FixedList<label,2> c0BdyIndex(-1), c0IntIndex(-1);
1057 FixedList<label,2> c1BdyIndex(-1), c1IntIndex(-1);
1058 FixedList<face,2> c0BdyFace(face(3)), c0IntFace(face(4));
1059 FixedList<face,2> c1BdyFace(face(3)), c1IntFace(face(4));
1061 // Find the prism-faces
1062 meshOps::findPrismFaces
1077 meshOps::findPrismFaces
1091 // Determine if either edge belongs to a boundary
1092 FixedList<bool, 2> nBoundCurves(false), edgeBoundary(false);
1094 edgeBoundary[0] = (whichEdgePatch(checkEdgeIndex[1]) > -1);
1095 edgeBoundary[1] = (whichEdgePatch(checkEdgeIndex[2]) > -1);
1097 // Decide on collapseCase
1098 label collapseCase = -1;
1100 if (edgeBoundary[0] && !edgeBoundary[1])
1105 if (!edgeBoundary[0] && edgeBoundary[1])
1110 if (edgeBoundary[0] && edgeBoundary[1])
1120 "dynamicTopoFvMesh::collapseQuadFace\n"
1122 " const label fIndex,\n"
1123 " label overRideCase,\n"
1124 " bool checkOnly,\n"
1127 ) << "Collapsing an internal face that "
1128 << "lies on two boundary patches. "
1129 << "Face: " << fIndex << ": " << faces_[fIndex]
1133 // Bail out for now. If proximity based refinement is
1134 // switched on, mesh may be sliced at this point.
1138 // Check if either edge lies on a bounding curve.
1139 if (checkBoundingCurve(checkEdgeIndex[1]))
1141 nBoundCurves[0] = true;
1144 if (checkBoundingCurve(checkEdgeIndex[2]))
1146 nBoundCurves[1] = true;
1149 // Collapse towards a bounding curve
1150 if (nBoundCurves[0] && !nBoundCurves[1])
1155 if (!nBoundCurves[0] && nBoundCurves[1])
1160 if (!nBoundCurves[0] && !nBoundCurves[1])
1162 // No bounding curves. Collapse to mid-point.
1167 // Two bounding curves? This might cause pinching.
1168 // Bail out for now.
1174 // Looks like this is an interior face.
1175 // Collapse case [3] by default
1179 // Perform an override if requested.
1180 if (overRideCase != -1)
1182 collapseCase = overRideCase;
1185 // Configure the new point-positions
1186 FixedList<bool, 2> check(false);
1187 FixedList<FixedList<label, 2>, 2> checkPoints(FixedList<label, 2>(-1));
1188 FixedList<point, 2> newPoint(vector::zero);
1189 FixedList<point, 2> oldPoint(vector::zero);
1191 // Replacement check points
1192 FixedList<label,2> original(-1), replacement(-1);
1194 switch (collapseCase)
1198 // Collapse to the first node
1199 original[0] = cv2; original[1] = cv3;
1200 replacement[0] = cv0; replacement[1] = cv1;
1202 newPoint[0] = points_[replacement[0]];
1203 newPoint[1] = points_[replacement[1]];
1205 oldPoint[0] = oldPoints_[replacement[0]];
1206 oldPoint[1] = oldPoints_[replacement[1]];
1208 // Define check-points
1210 checkPoints[1][0] = original[0];
1211 checkPoints[1][1] = original[1];
1218 // Collapse to the second node
1219 original[0] = cv0; original[1] = cv1;
1220 replacement[0] = cv2; replacement[1] = cv3;
1222 newPoint[0] = points_[replacement[0]];
1223 newPoint[1] = points_[replacement[1]];
1225 oldPoint[0] = oldPoints_[replacement[0]];
1226 oldPoint[1] = oldPoints_[replacement[1]];
1228 // Define check-points
1230 checkPoints[0][0] = original[0];
1231 checkPoints[0][1] = original[1];
1238 // Collapse to the mid-point
1239 original[0] = cv0; original[1] = cv1;
1240 replacement[0] = cv2; replacement[1] = cv3;
1242 // Define new point-positions
1247 points_[original[0]]
1248 + points_[replacement[0]]
1256 points_[original[1]]
1257 + points_[replacement[1]]
1261 // Define old point-positions
1266 oldPoints_[original[0]]
1267 + oldPoints_[replacement[0]]
1275 oldPoints_[original[1]]
1276 + oldPoints_[replacement[1]]
1280 // Define check-points
1282 checkPoints[0][0] = original[0];
1283 checkPoints[0][1] = original[1];
1286 checkPoints[1][0] = replacement[0];
1287 checkPoints[1][1] = replacement[1];
1294 // Don't think this will ever happen.
1299 "dynamicTopoFvMesh::collapseQuadFace\n"
1301 " const label fIndex,\n"
1302 " label overRideCase,\n"
1303 " bool checkOnly,\n"
1307 << "Edge: " << fIndex << ": " << faces_[fIndex]
1308 << ". Couldn't decide on collapseCase."
1309 << abort(FatalError);
1315 // Keep track of resulting cell quality,
1316 // if collapse is indeed feasible
1317 scalar collapseQuality(GREAT);
1319 // Check collapsibility of cells around edges
1320 // with the re-configured point
1321 forAll(check, indexI)
1328 // Check whether the collapse is possible.
1334 hullTriFaces[indexI],
1337 checkPoints[indexI],
1351 // Add a map entry of the replacements as 'addedPoints'
1352 // - Used in coupled mapping
1353 map.addPoint(replacement[0]);
1354 map.addPoint(replacement[1]);
1356 // Are we only performing checks?
1359 map.type() = collapseCase;
1363 Pout<< "Face: " << fIndex
1364 << ":: " << faces_[fIndex] << nl
1365 << " collapseCase determined to be: " << collapseCase << nl
1366 << " Resulting quality: " << collapseQuality << nl
1367 << " edgeBoundary: " << edgeBoundary << nl
1368 << " nBoundCurves: " << nBoundCurves << nl
1369 << " collapsePoints: " << original << nl
1370 << " replacePoints: " << replacement << nl
1379 const labelList& fE = faceEdges_[fIndex];
1382 << "Face: " << fIndex << ": " << faces_[fIndex] << nl
1383 << "faceEdges: " << fE << " is to be collapsed. "
1386 Pout<< " On SubMesh: " << Switch::asText(isSubMesh_) << nl;
1387 Pout<< " coupledModification: " << coupledModification_ << nl;
1389 label epIndex = whichPatch(fIndex);
1391 const polyBoundaryMesh& boundary = boundaryMesh();
1397 Pout<< "Internal" << nl;
1400 if (epIndex < boundary.size())
1402 Pout<< boundary[epIndex].name() << nl;
1406 Pout<< " New patch: " << epIndex << endl;
1412 << "~~~~~~~~~~~~~~~~~~~~~~~~~" << nl
1413 << "Hulls before modification" << nl
1414 << "~~~~~~~~~~~~~~~~~~~~~~~~~" << nl;
1418 Pout<< "Cell [0] Boundary faces: " << nl
1419 << " Face: "<< c0BdyIndex[0]
1420 << "::" << c0BdyFace[0] << nl
1421 << " Face: "<< c0BdyIndex[1]
1422 << "::" << c0BdyFace[1] << nl;
1424 Pout<< "Cell [0] Interior faces: " << nl
1425 << " Face: "<< c0IntIndex[0]
1426 << "::" << c0IntFace[0] << nl
1427 << " Face: "<< c0IntIndex[1]
1428 << "::" << c0IntFace[1] << nl;
1432 Pout<< "Cell [1] Boundary faces: " << nl
1433 << " Face: "<< c1BdyIndex[0]
1434 << "::" << c1BdyFace[0] << nl
1435 << " Face: "<< c1BdyIndex[1]
1436 << "::" << c1BdyFace[1] << nl;
1438 Pout<< "Cell [1] Interior faces: " << nl
1439 << " Face: "<< c1IntIndex[0]
1440 << "::" << c1IntFace[0] << nl
1441 << " Face: "<< c1IntIndex[1]
1442 << "::" << c1IntFace[1] << nl;
1446 Pout<< nl << "Cells belonging to first Edge Hull: "
1447 << hullCells[0] << nl;
1449 forAll(hullCells[0],cellI)
1451 const cell& firstCurCell = cells_[hullCells[0][cellI]];
1453 Pout<< "Cell: " << hullCells[0][cellI]
1454 << ": " << firstCurCell << nl;
1456 forAll(firstCurCell,faceI)
1458 Pout<< " Face: " << firstCurCell[faceI]
1459 << " : " << faces_[firstCurCell[faceI]]
1460 << " fE: " << faceEdges_[firstCurCell[faceI]]
1465 const labelList& fE = faceEdges_[firstCurCell[faceI]];
1469 Pout<< " Edge: " << fE[edgeI]
1470 << " : " << edges_[fE[edgeI]]
1477 const labelList& firstEdgeFaces = edgeFaces_[checkEdgeIndex[1]];
1479 Pout<< nl << "First Edge Face Hull: "
1480 << firstEdgeFaces << nl;
1482 forAll(firstEdgeFaces,indexI)
1484 Pout<< " Face: " << firstEdgeFaces[indexI]
1485 << " : " << faces_[firstEdgeFaces[indexI]]
1486 << " fE: " << faceEdges_[firstEdgeFaces[indexI]]
1491 const labelList& fE = faceEdges_[firstEdgeFaces[indexI]];
1495 Pout<< " Edge: " << fE[edgeI]
1496 << " : " << edges_[fE[edgeI]]
1502 Pout<< nl << "Cells belonging to second Edge Hull: "
1503 << hullCells[1] << nl;
1505 forAll(hullCells[1], cellI)
1507 const cell& secondCurCell = cells_[hullCells[1][cellI]];
1509 Pout<< "Cell: " << hullCells[1][cellI]
1510 << ": " << secondCurCell << nl;
1512 forAll(secondCurCell, faceI)
1514 Pout<< " Face: " << secondCurCell[faceI]
1515 << " : " << faces_[secondCurCell[faceI]]
1516 << " fE: " << faceEdges_[secondCurCell[faceI]]
1521 const labelList& fE = faceEdges_[secondCurCell[faceI]];
1525 Pout<< " Edge: " << fE[edgeI]
1526 << " : " << edges_[fE[edgeI]]
1533 const labelList& secondEdgeFaces = edgeFaces_[checkEdgeIndex[2]];
1535 Pout<< nl << "Second Edge Face Hull: "
1536 << secondEdgeFaces << nl;
1538 forAll(secondEdgeFaces, indexI)
1540 Pout<< " Face: " << secondEdgeFaces[indexI]
1541 << " : " << faces_[secondEdgeFaces[indexI]]
1542 << " fE: " << faceEdges_[secondEdgeFaces[indexI]]
1547 const labelList& fE = faceEdges_[secondEdgeFaces[indexI]];
1551 Pout<< " Edge: " << fE[edgeI]
1552 << " : " << edges_[fE[edgeI]]
1558 // Write out VTK files prior to change
1561 labelHashSet vtkCells;
1563 forAll(hullCells[0], cellI)
1565 if (!vtkCells.found(hullCells[0][cellI]))
1567 vtkCells.insert(hullCells[0][cellI]);
1571 forAll(hullCells[1], cellI)
1573 if (!vtkCells.found(hullCells[1][cellI]))
1575 vtkCells.insert(hullCells[1][cellI]);
1589 // Edges / Quad-faces to throw or keep during collapse
1590 FixedList<label,2> ends(-1);
1591 FixedList<label,2> faceToKeep(-1), faceToThrow(-1);
1592 FixedList<label,4> edgeToKeep(-1), edgeToThrow(-1);
1594 // Maintain a list of modified faces for mapping
1595 DynamicList<label> modifiedFaces(10);
1597 // Case 2 & 3 use identical connectivity,
1598 // but different point locations
1599 if (collapseCase == 2 || collapseCase == 3)
1601 const labelList& firstEdgeFaces = edgeFaces_[checkEdgeIndex[1]];
1603 // Collapse to the second node...
1604 forAll(firstEdgeFaces,faceI)
1606 // Replace point indices on faces.
1607 meshOps::replaceLabel
1611 faces_[firstEdgeFaces[faceI]]
1614 meshOps::replaceLabel
1618 faces_[firstEdgeFaces[faceI]]
1621 // Add an entry for mapping
1622 if (findIndex(modifiedFaces, firstEdgeFaces[faceI]) == -1)
1624 modifiedFaces.append(firstEdgeFaces[faceI]);
1627 // Determine the quad-face in cell[0] & cell[1]
1628 // that belongs to firstEdgeFaces
1629 if (firstEdgeFaces[faceI] == c0IntIndex[0])
1631 faceToKeep[0] = c0IntIndex[1];
1632 faceToThrow[0] = c0IntIndex[0];
1635 if (firstEdgeFaces[faceI] == c0IntIndex[1])
1637 faceToKeep[0] = c0IntIndex[0];
1638 faceToThrow[0] = c0IntIndex[1];
1643 if (firstEdgeFaces[faceI] == c1IntIndex[0])
1645 faceToKeep[1] = c1IntIndex[1];
1646 faceToThrow[1] = c1IntIndex[0];
1649 if (firstEdgeFaces[faceI] == c1IntIndex[1])
1651 faceToKeep[1] = c1IntIndex[0];
1652 faceToThrow[1] = c1IntIndex[1];
1657 // Find common edges between quad / tri faces...
1658 meshOps::findCommonEdge
1666 meshOps::findCommonEdge
1674 meshOps::findCommonEdge
1682 meshOps::findCommonEdge
1690 // Size down edgeFaces for the ends.
1691 meshOps::findCommonEdge
1699 meshOps::sizeDownList
1707 meshOps::findCommonEdge
1715 meshOps::findCommonEdge
1723 meshOps::findCommonEdge
1731 meshOps::findCommonEdge
1739 // Size down edgeFaces for the ends.
1740 meshOps::findCommonEdge
1748 meshOps::sizeDownList
1755 // Correct edgeFaces for triangular faces...
1756 forAll(edgeToThrow, indexI)
1758 if (edgeToThrow[indexI] == -1)
1763 const labelList& eF = edgeFaces_[edgeToThrow[indexI]];
1765 label origTriFace = -1, retTriFace = -1;
1767 // Find the original triangular face index
1770 if (eF[faceI] == c0BdyIndex[0])
1772 origTriFace = c0BdyIndex[0];
1776 if (eF[faceI] == c0BdyIndex[1])
1778 origTriFace = c0BdyIndex[1];
1782 if (eF[faceI] == c1BdyIndex[0])
1784 origTriFace = c1BdyIndex[0];
1788 if (eF[faceI] == c1BdyIndex[1])
1790 origTriFace = c1BdyIndex[1];
1795 // Find the retained triangular face index
1800 (eF[faceI] != origTriFace) &&
1801 (eF[faceI] != faceToThrow[0]) &&
1802 (eF[faceI] != faceToThrow[1])
1805 retTriFace = eF[faceI];
1810 // Finally replace the face index
1811 if (retTriFace == -1)
1813 // Couldn't find a retained face.
1814 // This must be a boundary edge, so size-down instead.
1815 meshOps::sizeDownList
1818 edgeFaces_[edgeToKeep[indexI]]
1823 meshOps::replaceLabel
1827 edgeFaces_[edgeToKeep[indexI]]
1830 meshOps::replaceLabel
1832 edgeToThrow[indexI],
1834 faceEdges_[retTriFace]
1839 // Correct faceEdges / edgeFaces for quad-faces...
1840 forAll(firstEdgeFaces,faceI)
1842 meshOps::replaceLabel
1846 faceEdges_[firstEdgeFaces[faceI]]
1849 // Renumber the edges on this face
1850 const labelList& fE = faceEdges_[firstEdgeFaces[faceI]];
1854 if (edges_[fE[edgeI]].start() == cv0)
1856 edges_[fE[edgeI]].start() = cv2;
1859 if (edges_[fE[edgeI]].end() == cv0)
1861 edges_[fE[edgeI]].end() = cv2;
1864 if (edges_[fE[edgeI]].start() == cv1)
1866 edges_[fE[edgeI]].start() = cv3;
1869 if (edges_[fE[edgeI]].end() == cv1)
1871 edges_[fE[edgeI]].end() = cv3;
1875 // Size-up edgeFaces for the replacement
1878 (firstEdgeFaces[faceI] != faceToThrow[0]) &&
1879 (firstEdgeFaces[faceI] != faceToThrow[1]) &&
1880 (firstEdgeFaces[faceI] != fIndex)
1885 firstEdgeFaces[faceI],
1886 edgeFaces_[checkEdgeIndex[2]]
1891 // Remove the current face from the replacement edge
1892 meshOps::sizeDownList
1895 edgeFaces_[checkEdgeIndex[2]]
1898 // Replace point labels on all triangular boundary faces.
1899 forAll(hullCells[0],cellI)
1901 const cell& cellToCheck = cells_[hullCells[0][cellI]];
1903 forAll(cellToCheck,faceI)
1905 face& faceToCheck = faces_[cellToCheck[faceI]];
1907 if (faceToCheck.size() == 3)
1909 forAll(faceToCheck,pointI)
1911 if (faceToCheck[pointI] == cv0)
1913 faceToCheck[pointI] = cv2;
1916 if (faceToCheck[pointI] == cv1)
1918 faceToCheck[pointI] = cv3;
1925 // Now that we're done with all edges, remove them.
1926 removeEdge(checkEdgeIndex[0]);
1927 removeEdge(checkEdgeIndex[1]);
1928 removeEdge(checkEdgeIndex[3]);
1931 map.removeEdge(checkEdgeIndex[0]);
1932 map.removeEdge(checkEdgeIndex[1]);
1933 map.removeEdge(checkEdgeIndex[2]);
1935 forAll(edgeToThrow, indexI)
1937 if (edgeToThrow[indexI] == -1)
1942 removeEdge(edgeToThrow[indexI]);
1945 map.removeEdge(edgeToThrow[indexI]);
1948 // Delete the two points...
1953 map.removePoint(cv0);
1954 map.removePoint(cv1);
1958 const labelList& secondEdgeFaces = edgeFaces_[checkEdgeIndex[2]];
1960 // Collapse to the first node
1961 forAll(secondEdgeFaces,faceI)
1963 // Replace point indices on faces.
1964 meshOps::replaceLabel
1968 faces_[secondEdgeFaces[faceI]]
1971 meshOps::replaceLabel
1975 faces_[secondEdgeFaces[faceI]]
1978 // Add an entry for mapping
1979 if (findIndex(modifiedFaces, secondEdgeFaces[faceI]) == -1)
1981 modifiedFaces.append(secondEdgeFaces[faceI]);
1984 // Determine the quad-face(s) in cell[0] & cell[1]
1985 // that belongs to secondEdgeFaces
1986 if (secondEdgeFaces[faceI] == c0IntIndex[0])
1988 faceToKeep[0] = c0IntIndex[1];
1989 faceToThrow[0] = c0IntIndex[0];
1992 if (secondEdgeFaces[faceI] == c0IntIndex[1])
1994 faceToKeep[0] = c0IntIndex[0];
1995 faceToThrow[0] = c0IntIndex[1];
2000 if (secondEdgeFaces[faceI] == c1IntIndex[0])
2002 faceToKeep[1] = c1IntIndex[1];
2003 faceToThrow[1] = c1IntIndex[0];
2006 if (secondEdgeFaces[faceI] == c1IntIndex[1])
2008 faceToKeep[1] = c1IntIndex[0];
2009 faceToThrow[1] = c1IntIndex[1];
2014 // Find common edges between quad / tri faces...
2015 meshOps::findCommonEdge
2023 meshOps::findCommonEdge
2031 meshOps::findCommonEdge
2039 meshOps::findCommonEdge
2047 // Size down edgeFaces for the ends.
2048 meshOps::findCommonEdge
2056 meshOps::sizeDownList
2064 meshOps::findCommonEdge
2072 meshOps::findCommonEdge
2080 meshOps::findCommonEdge
2088 meshOps::findCommonEdge
2096 // Size down edgeFaces for the ends.
2097 meshOps::findCommonEdge
2105 meshOps::sizeDownList
2112 // Correct edgeFaces for triangular faces...
2113 forAll(edgeToThrow, indexI)
2115 if (edgeToThrow[indexI] == -1)
2120 const labelList& eF = edgeFaces_[edgeToThrow[indexI]];
2122 label origTriFace = -1, retTriFace = -1;
2124 // Find the original triangular face index
2127 if (eF[faceI] == c0BdyIndex[0])
2129 origTriFace = c0BdyIndex[0];
2133 if (eF[faceI] == c0BdyIndex[1])
2135 origTriFace = c0BdyIndex[1];
2139 if (eF[faceI] == c1BdyIndex[0])
2141 origTriFace = c1BdyIndex[0];
2145 if (eF[faceI] == c1BdyIndex[1])
2147 origTriFace = c1BdyIndex[1];
2152 // Find the retained triangular face index
2157 (eF[faceI] != origTriFace) &&
2158 (eF[faceI] != faceToThrow[0]) &&
2159 (eF[faceI] != faceToThrow[1])
2162 retTriFace = eF[faceI];
2167 // Finally replace the face/edge indices
2168 if (retTriFace == -1)
2170 // Couldn't find a retained face.
2171 // This must be a boundary edge, so size-down instead.
2172 meshOps::sizeDownList
2175 edgeFaces_[edgeToKeep[indexI]]
2180 meshOps::replaceLabel
2184 edgeFaces_[edgeToKeep[indexI]]
2187 meshOps::replaceLabel
2189 edgeToThrow[indexI],
2191 faceEdges_[retTriFace]
2196 // Correct faceEdges / edgeFaces for quad-faces...
2197 forAll(secondEdgeFaces,faceI)
2199 meshOps::replaceLabel
2203 faceEdges_[secondEdgeFaces[faceI]]
2206 // Renumber the edges on this face
2207 const labelList& fE = faceEdges_[secondEdgeFaces[faceI]];
2211 if (edges_[fE[edgeI]].start() == cv2)
2213 edges_[fE[edgeI]].start() = cv0;
2216 if (edges_[fE[edgeI]].end() == cv2)
2218 edges_[fE[edgeI]].end() = cv0;
2221 if (edges_[fE[edgeI]].start() == cv3)
2223 edges_[fE[edgeI]].start() = cv1;
2226 if (edges_[fE[edgeI]].end() == cv3)
2228 edges_[fE[edgeI]].end() = cv1;
2232 // Size-up edgeFaces for the replacement
2235 (secondEdgeFaces[faceI] != faceToThrow[0]) &&
2236 (secondEdgeFaces[faceI] != faceToThrow[1]) &&
2237 (secondEdgeFaces[faceI] != fIndex)
2242 secondEdgeFaces[faceI],
2243 edgeFaces_[checkEdgeIndex[1]]
2248 // Remove the current face from the replacement edge
2249 meshOps::sizeDownList
2252 edgeFaces_[checkEdgeIndex[1]]
2255 // Replace point labels on all triangular boundary faces.
2256 forAll(hullCells[1], cellI)
2258 const cell& cellToCheck = cells_[hullCells[1][cellI]];
2260 forAll(cellToCheck, faceI)
2262 face& faceToCheck = faces_[cellToCheck[faceI]];
2264 if (faceToCheck.size() == 3)
2266 forAll(faceToCheck, pointI)
2268 if (faceToCheck[pointI] == cv2)
2270 faceToCheck[pointI] = cv0;
2273 if (faceToCheck[pointI] == cv3)
2275 faceToCheck[pointI] = cv1;
2282 // Now that we're done with all edges, remove them.
2283 removeEdge(checkEdgeIndex[0]);
2284 removeEdge(checkEdgeIndex[2]);
2285 removeEdge(checkEdgeIndex[3]);
2288 map.removeEdge(checkEdgeIndex[0]);
2289 map.removeEdge(checkEdgeIndex[2]);
2290 map.removeEdge(checkEdgeIndex[3]);
2292 forAll(edgeToThrow, indexI)
2294 if (edgeToThrow[indexI] == -1)
2299 removeEdge(edgeToThrow[indexI]);
2302 map.removeEdge(edgeToThrow[indexI]);
2305 // Delete the two points...
2310 map.removePoint(cv2);
2311 map.removePoint(cv3);
2317 << "~~~~~~~~~~~~~~~~~~~~~~~~" << nl
2318 << "Hulls after modification" << nl
2319 << "~~~~~~~~~~~~~~~~~~~~~~~~" << nl;
2321 Pout<< nl << "Cells belonging to first Edge Hull: "
2322 << hullCells[0] << nl;
2324 forAll(hullCells[0], cellI)
2326 const cell& firstCurCell = cells_[hullCells[0][cellI]];
2328 Pout<< "Cell: " << hullCells[0][cellI]
2329 << ": " << firstCurCell << nl;
2331 forAll(firstCurCell, faceI)
2333 Pout<< " Face: " << firstCurCell[faceI]
2334 << " : " << faces_[firstCurCell[faceI]]
2335 << " fE: " << faceEdges_[firstCurCell[faceI]]
2340 const labelList& firstEdgeFaces = edgeFaces_[checkEdgeIndex[1]];
2342 Pout<< nl << "First Edge Face Hull: " << firstEdgeFaces << nl;
2344 forAll(firstEdgeFaces, indexI)
2346 Pout<< " Face: " << firstEdgeFaces[indexI]
2347 << " : " << faces_[firstEdgeFaces[indexI]]
2348 << " fE: " << faceEdges_[firstEdgeFaces[indexI]]
2352 Pout<< nl << "Cells belonging to second Edge Hull: "
2353 << hullCells[1] << nl;
2355 forAll(hullCells[1], cellI)
2357 const cell& secondCurCell = cells_[hullCells[1][cellI]];
2359 Pout<< "Cell: " << hullCells[1][cellI]
2360 << ": " << secondCurCell << nl;
2362 forAll(secondCurCell, faceI)
2364 Pout<< " Face: " << secondCurCell[faceI]
2365 << " : " << faces_[secondCurCell[faceI]]
2366 << " fE: " << faceEdges_[secondCurCell[faceI]]
2371 const labelList& secondEdgeFaces = edgeFaces_[checkEdgeIndex[2]];
2373 Pout<< nl << "Second Edge Face Hull: " << secondEdgeFaces << nl;
2375 forAll(secondEdgeFaces, indexI)
2377 Pout<< " Face : " << secondEdgeFaces[indexI]
2378 << " : " << faces_[secondEdgeFaces[indexI]]
2379 << " fE: " << faceEdges_[secondEdgeFaces[indexI]]
2383 Pout<< "Retained face: "
2384 << faceToKeep[0] << ": "
2385 << " owner: " << owner_[faceToKeep[0]]
2386 << " neighbour: " << neighbour_[faceToKeep[0]]
2389 Pout<< "Discarded face: "
2390 << faceToThrow[0] << ": "
2391 << " owner: " << owner_[faceToThrow[0]]
2392 << " neighbour: " << neighbour_[faceToThrow[0]]
2397 Pout<< "Retained face: "
2398 << faceToKeep[1] << ": "
2399 << " owner: " << owner_[faceToKeep[1]]
2400 << " neighbour: " << neighbour_[faceToKeep[1]]
2403 Pout<< "Discarded face: "
2404 << faceToThrow[1] << ": "
2405 << " owner: " << owner_[faceToThrow[1]]
2406 << " neighbour: " << neighbour_[faceToThrow[1]]
2413 // Ensure proper orientation for the two retained faces
2414 FixedList<label,2> cellCheck(0);
2416 if (owner_[faceToThrow[0]] == c0)
2418 cellCheck[0] = neighbour_[faceToThrow[0]];
2420 if (owner_[faceToKeep[0]] == c0)
2424 (neighbour_[faceToThrow[0]] > neighbour_[faceToKeep[0]])
2425 && (neighbour_[faceToKeep[0]] != -1)
2428 // This face is to be flipped
2429 faces_[faceToKeep[0]] =
2431 faces_[faceToKeep[0]].reverseFace()
2434 owner_[faceToKeep[0]] = neighbour_[faceToKeep[0]];
2435 neighbour_[faceToKeep[0]] = neighbour_[faceToThrow[0]];
2437 setFlip(faceToKeep[0]);
2441 if (neighbour_[faceToThrow[0]] != -1)
2443 // Keep orientation intact, and update the owner
2444 owner_[faceToKeep[0]] = neighbour_[faceToThrow[0]];
2448 // This face will need to be flipped and converted
2449 // to a boundary face. Flip it now, so that conversion
2451 faces_[faceToKeep[0]] =
2453 faces_[faceToKeep[0]].reverseFace()
2456 owner_[faceToKeep[0]] = neighbour_[faceToKeep[0]];
2457 neighbour_[faceToKeep[0]] = -1;
2459 setFlip(faceToKeep[0]);
2465 // Keep orientation intact, and update the neighbour
2466 neighbour_[faceToKeep[0]] = neighbour_[faceToThrow[0]];
2471 cellCheck[0] = owner_[faceToThrow[0]];
2473 if (neighbour_[faceToKeep[0]] == c0)
2475 if (owner_[faceToThrow[0]] < owner_[faceToKeep[0]])
2477 // This face is to be flipped
2478 faces_[faceToKeep[0]] =
2480 faces_[faceToKeep[0]].reverseFace()
2483 neighbour_[faceToKeep[0]] = owner_[faceToKeep[0]];
2484 owner_[faceToKeep[0]] = owner_[faceToThrow[0]];
2486 setFlip(faceToKeep[0]);
2490 // Keep orientation intact, and update the neighbour
2491 neighbour_[faceToKeep[0]] = owner_[faceToThrow[0]];
2496 // Keep orientation intact, and update the owner
2497 owner_[faceToKeep[0]] = owner_[faceToThrow[0]];
2503 if (owner_[faceToThrow[1]] == c1)
2505 cellCheck[1] = neighbour_[faceToThrow[1]];
2507 if (owner_[faceToKeep[1]] == c1)
2511 (neighbour_[faceToThrow[1]] > neighbour_[faceToKeep[1]])
2512 && (neighbour_[faceToKeep[1]] != -1)
2515 // This face is to be flipped
2516 faces_[faceToKeep[1]] =
2518 faces_[faceToKeep[1]].reverseFace()
2521 owner_[faceToKeep[1]] = neighbour_[faceToKeep[1]];
2522 neighbour_[faceToKeep[1]] = neighbour_[faceToThrow[1]];
2524 setFlip(faceToKeep[1]);
2528 if (neighbour_[faceToThrow[1]] != -1)
2530 // Keep orientation intact, and update the owner
2531 owner_[faceToKeep[1]] = neighbour_[faceToThrow[1]];
2535 // This face will need to be flipped and converted
2536 // to a boundary face. Flip it now, so that conversion
2538 faces_[faceToKeep[1]] =
2540 faces_[faceToKeep[1]].reverseFace()
2543 owner_[faceToKeep[1]] = neighbour_[faceToKeep[1]];
2544 neighbour_[faceToKeep[1]] = -1;
2546 setFlip(faceToKeep[1]);
2552 // Keep orientation intact, and update the neighbour
2553 neighbour_[faceToKeep[1]] = neighbour_[faceToThrow[1]];
2558 cellCheck[1] = owner_[faceToThrow[1]];
2560 if (neighbour_[faceToKeep[1]] == c1)
2562 if (owner_[faceToThrow[1]] < owner_[faceToKeep[1]])
2564 // This face is to be flipped
2565 faces_[faceToKeep[1]] =
2567 faces_[faceToKeep[1]].reverseFace()
2570 neighbour_[faceToKeep[1]] = owner_[faceToKeep[1]];
2571 owner_[faceToKeep[1]] = owner_[faceToThrow[1]];
2573 setFlip(faceToKeep[1]);
2577 // Keep orientation intact, and update the neighbour
2578 neighbour_[faceToKeep[1]] = owner_[faceToThrow[1]];
2583 // Keep orientation intact, and update the owner
2584 owner_[faceToKeep[1]] = owner_[faceToThrow[1]];
2589 // Remove orphaned faces
2590 if (owner_[faceToKeep[0]] == -1)
2592 removeFace(faceToKeep[0]);
2595 map.removeFace(faceToKeep[0]);
2600 (neighbour_[faceToKeep[0]] == -1)
2601 && (whichPatch(faceToKeep[0]) < 0)
2604 // Obtain a copy before adding the new face,
2605 // since the reference might become invalid during list resizing.
2606 face newFace = faces_[faceToKeep[0]];
2607 label newOwn = owner_[faceToKeep[0]];
2608 labelList newFaceEdges = faceEdges_[faceToKeep[0]];
2610 // This face is being converted from interior to boundary. Remove
2611 // from the interior list and add as a boundary face to the end.
2612 label newFaceIndex =
2616 whichPatch(faceToThrow[0]),
2623 // Add an entry for mapping
2624 modifiedFaces.append(newFaceIndex);
2627 map.addFace(newFaceIndex, labelList(1, faceToThrow[0]));
2629 // Add a faceEdges entry as well.
2630 // Edges don't have to change, since they're
2631 // all on the boundary anyway.
2632 faceEdges_.append(newFaceEdges);
2634 meshOps::replaceLabel
2641 // Correct edgeFaces with the new face label.
2642 forAll(newFaceEdges, edgeI)
2644 meshOps::replaceLabel
2648 edgeFaces_[newFaceEdges[edgeI]]
2652 // Renumber the neighbour so that this face is removed correctly.
2653 neighbour_[faceToKeep[0]] = 0;
2654 removeFace(faceToKeep[0]);
2657 map.removeFace(faceToKeep[0]);
2660 // Remove the unwanted faces in the cell(s) adjacent to this face,
2661 // and correct the cells that contain discarded faces
2662 const cell& cell_0 = cells_[c0];
2664 forAll(cell_0,faceI)
2666 if (cell_0[faceI] != fIndex && cell_0[faceI] != faceToKeep[0])
2668 removeFace(cell_0[faceI]);
2671 map.removeFace(cell_0[faceI]);
2675 if (cellCheck[0] != -1)
2677 meshOps::replaceLabel
2681 cells_[cellCheck[0]]
2693 // Increment the surface-collapse counter
2698 // Remove orphaned faces
2699 if (owner_[faceToKeep[1]] == -1)
2701 removeFace(faceToKeep[1]);
2704 map.removeFace(faceToKeep[1]);
2709 (neighbour_[faceToKeep[1]] == -1)
2710 && (whichPatch(faceToKeep[1]) < 0)
2713 // Obtain a copy before adding the new face,
2714 // since the reference might become invalid during list resizing.
2715 face newFace = faces_[faceToKeep[1]];
2716 label newOwn = owner_[faceToKeep[1]];
2717 labelList newFaceEdges = faceEdges_[faceToKeep[1]];
2719 // This face is being converted from interior to boundary. Remove
2720 // from the interior list and add as a boundary face to the end.
2721 label newFaceIndex =
2725 whichPatch(faceToThrow[1]),
2732 // Add an entry for mapping
2733 modifiedFaces.append(newFaceIndex);
2736 map.addFace(newFaceIndex, labelList(1, faceToThrow[1]));
2738 // Add a faceEdges entry as well.
2739 // Edges don't have to change, since they're
2740 // all on the boundary anyway.
2741 faceEdges_.append(newFaceEdges);
2743 meshOps::replaceLabel
2750 // Correct edgeFaces with the new face label.
2751 forAll(newFaceEdges, edgeI)
2753 meshOps::replaceLabel
2757 edgeFaces_[newFaceEdges[edgeI]]
2761 // Renumber the neighbour so that this face is removed correctly.
2762 neighbour_[faceToKeep[1]] = 0;
2763 removeFace(faceToKeep[1]);
2766 map.removeFace(faceToKeep[1]);
2769 const cell& cell_1 = cells_[c1];
2771 forAll(cell_1, faceI)
2773 if (cell_1[faceI] != fIndex && cell_1[faceI] != faceToKeep[1])
2775 removeFace(cell_1[faceI]);
2778 map.removeFace(cell_1[faceI]);
2782 if (cellCheck[1] != -1)
2784 meshOps::replaceLabel
2788 cells_[cellCheck[1]]
2799 // Move old / new points
2800 oldPoints_[replacement[0]] = oldPoint[0];
2801 oldPoints_[replacement[1]] = oldPoint[1];
2803 points_[replacement[0]] = newPoint[0];
2804 points_[replacement[1]] = newPoint[1];
2806 // Finally remove the face
2810 map.removeFace(fIndex);
2812 // Write out VTK files after change
2815 labelHashSet vtkCells;
2817 forAll(hullCells[0], cellI)
2819 if (hullCells[0][cellI] == c0 || hullCells[0][cellI] == c1)
2824 if (!vtkCells.found(hullCells[0][cellI]))
2826 vtkCells.insert(hullCells[0][cellI]);
2830 forAll(hullCells[1], cellI)
2832 if (hullCells[1][cellI] == c0 || hullCells[1][cellI] == c1)
2837 if (!vtkCells.found(hullCells[1][cellI]))
2839 vtkCells.insert(hullCells[1][cellI]);
2851 // Fill-in candidate mapping information
2852 labelList mC(2, -1);
2853 mC[0] = c0, mC[1] = c1;
2855 // Now that all old / new cells possess correct connectivity,
2856 // compute mapping information.
2857 forAll(hullCells, indexI)
2859 forAll(hullCells[indexI], cellI)
2861 label mcIndex = hullCells[indexI][cellI];
2863 // Skip collapsed cells
2864 if (mcIndex == c0 || mcIndex == c1)
2869 // Set the mapping for this cell
2870 setCellMapping(mcIndex, mC);
2874 // Set face mapping information for modified faces
2875 forAll(modifiedFaces, faceI)
2877 const label mfIndex = modifiedFaces[faceI];
2879 // Exclude deleted faces
2880 if (faces_[mfIndex].empty())
2885 // Decide between default / weighted mapping
2886 // based on boundary information
2887 label fPatch = whichPatch(mfIndex);
2891 setFaceMapping(mfIndex);
2895 // Fill-in candidate mapping information
2896 labelList faceCandidates;
2898 const labelList& fEdges = faceEdges_[mfIndex];
2900 forAll(fEdges, edgeI)
2902 if (whichEdgePatch(fEdges[edgeI]) == fPatch)
2904 // Loop through associated edgeFaces
2905 const labelList& eFaces = edgeFaces_[fEdges[edgeI]];
2907 forAll(eFaces, faceI)
2911 (eFaces[faceI] != mfIndex) &&
2912 (whichPatch(eFaces[faceI]) == fPatch)
2915 faceCandidates.setSize
2917 faceCandidates.size() + 1,
2925 // Set the mapping for this face
2926 setFaceMapping(mfIndex, faceCandidates);
2930 // If modification is coupled, update mapping info.
2931 if (coupledModification_)
2933 // Check if the collapse points are present
2934 // on a processor not involved in the current
2935 // operation, and update if necessary
2936 if (procCouple && !localCouple)
2938 forAll(procIndices_, pI)
2940 bool involved = false;
2942 forAll(slaveMaps, slaveI)
2944 // Alias for convenience...
2945 const changeMap& slaveMap = slaveMaps[slaveI];
2947 if (slaveMap.patchIndex() == pI && slaveMap.index() >= 0)
2949 // Involved in this operation. Break out.
2960 // Check coupleMaps for point coupling
2961 const label pointEnum = coupleMap::POINT;
2963 const coupledInfo& recvMesh = recvMeshes_[pI];
2964 const coupleMap& cMap = recvMesh.map();
2966 // Obtain non-const references
2967 Map<label>& pointMap = cMap.entityMap(pointEnum);
2968 Map<label>& rPointMap = cMap.reverseEntityMap(pointEnum);
2970 label sI0 = -1, sI1 = -1;
2972 if (collapsingSlave)
2974 if ((sI0 = cMap.findMaster(pointEnum, original[0])) > -1)
2976 if (rPointMap.found(replacement[0]))
2978 rPointMap[replacement[0]] = sI0;
2982 rPointMap.insert(replacement[0], sI0);
2985 pointMap[sI0] = replacement[0];
2988 if ((sI1 = cMap.findMaster(pointEnum, original[1])) > -1)
2990 if (rPointMap.found(replacement[1]))
2992 rPointMap[replacement[1]] = sI1;
2996 rPointMap.insert(replacement[1], sI1);
2999 pointMap[sI1] = replacement[1];
3004 if ((sI0 = cMap.findSlave(pointEnum, original[0])) > -1)
3006 if (pointMap.found(replacement[0]))
3008 pointMap[replacement[0]] = sI0;
3012 pointMap.insert(replacement[0], sI0);
3015 rPointMap[sI0] = replacement[0];
3018 if ((sI1 = cMap.findSlave(pointEnum, original[1])) > -1)
3020 if (pointMap.found(replacement[1]))
3022 pointMap[replacement[1]] = sI1;
3026 pointMap.insert(replacement[1], sI1);
3029 rPointMap[sI1] = replacement[1];
3033 if (sI0 > -1 && sI1 > -1 && debug > 2)
3035 Pout<< " Found " << original[0] << " and " << original[1]
3036 << " on proc: " << procIndices_[pI]
3042 forAll(slaveMaps, slaveI)
3044 // Alias for convenience...
3045 const changeMap& slaveMap = slaveMaps[slaveI];
3047 // Skip updates for edge-based coupling
3048 if (slaveMap.index() < 0)
3053 label pI = slaveMap.patchIndex();
3055 // Fetch the appropriate coupleMap
3056 const coupleMap* cMapPtr = NULL;
3058 if (localCouple && !procCouple)
3060 cMapPtr = &(patchCoupling_[pI].map());
3063 if (procCouple && !localCouple)
3065 cMapPtr = &(recvMeshes_[pI].map());
3068 // Configure the slave replacement points.
3069 // - collapseQuadFace stores this as 'addedPoints'
3070 label scP0 = slaveMap.removedPointList()[0];
3071 label scP1 = slaveMap.removedPointList()[1];
3073 label srP0 = slaveMap.addedPointList()[0].index();
3074 label srP1 = slaveMap.addedPointList()[1].index();
3076 // Alias for convenience
3077 const coupleMap& cMap = *cMapPtr;
3079 // Remove the point entries.
3080 const label pointEnum = coupleMap::POINT;
3082 // Obtain references
3083 Map<label>& pointMap = cMap.entityMap(pointEnum);
3084 Map<label>& rPointMap = cMap.reverseEntityMap(pointEnum);
3086 if (collapsingSlave)
3088 if (rPointMap[replacement[0]] == scP0)
3090 pointMap[srP0] = replacement[0];
3091 rPointMap[replacement[0]] = srP0;
3094 if (rPointMap[replacement[0]] == scP1)
3096 pointMap[srP1] = replacement[0];
3097 rPointMap[replacement[0]] = srP1;
3100 pointMap.erase(rPointMap[original[0]]);
3101 rPointMap.erase(original[0]);
3105 if (pointMap[replacement[0]] == scP0)
3107 rPointMap[srP0] = replacement[0];
3108 pointMap[replacement[0]] = srP0;
3111 if (pointMap[replacement[0]] == scP1)
3113 rPointMap[srP1] = replacement[0];
3114 pointMap[replacement[0]] = srP1;
3117 rPointMap.erase(pointMap[original[0]]);
3118 pointMap.erase(original[0]);
3121 if (collapsingSlave)
3123 if (rPointMap[replacement[1]] == scP0)
3125 pointMap[srP0] = replacement[1];
3126 rPointMap[replacement[1]] = srP0;
3129 if (rPointMap[replacement[1]] == scP1)
3131 pointMap[srP1] = replacement[1];
3132 rPointMap[replacement[1]] = srP1;
3135 pointMap.erase(rPointMap[original[1]]);
3136 rPointMap.erase(original[1]);
3140 if (pointMap[replacement[1]] == scP0)
3142 rPointMap[srP0] = replacement[1];
3143 pointMap[replacement[1]] = srP0;
3146 if (pointMap[replacement[1]] == scP1)
3148 rPointMap[srP1] = replacement[1];
3149 pointMap[replacement[1]] = srP1;
3152 rPointMap.erase(pointMap[original[1]]);
3153 pointMap.erase(original[1]);
3156 // Remove the face entries
3157 const label faceEnum = coupleMap::FACE;
3159 // Obtain references
3160 Map<label>& faceMap = cMap.entityMap(faceEnum);
3161 Map<label>& rFaceMap = cMap.reverseEntityMap(faceEnum);
3163 if (collapsingSlave)
3165 faceMap.erase(faceMap[fIndex]);
3166 rFaceMap.erase(fIndex);
3170 rFaceMap.erase(faceMap[fIndex]);
3171 faceMap.erase(fIndex);
3174 // Configure a comparison face
3177 // If any interior faces in the master map were
3178 // converted to boundaries, account for it
3179 const List<objectMap>& madF = map.addedFaceList();
3183 label mfIndex = madF[faceI].index();
3184 const face& mFace = faces_[mfIndex];
3186 // Select appropriate mesh
3187 const dynamicTopoFvMesh* meshPtr = NULL;
3189 // Fetch the appropriate coupleMap
3190 const coupleMap* crMapPtr = NULL;
3193 label ofPatch = whichPatch(fIndex);
3194 label mfPatch = whichPatch(mfIndex);
3196 if (localCouple && !procCouple)
3198 // Local coupling. Use this mesh itself
3200 crMapPtr = &(patchCoupling_[pI].map());
3203 if (procCouple && !localCouple)
3205 // Occasionally, this face might talk to
3206 // a processor other than the slave
3207 if (ofPatch == mfPatch)
3209 meshPtr = &(recvMeshes_[pI].subMesh());
3210 crMapPtr = &(recvMeshes_[pI].map());
3214 label neiProcNo = getNeighbourProcessor(mfPatch);
3216 if (neiProcNo == -1)
3218 // Not a processor patch. No mapping required.
3223 // Find an appropriate subMesh
3224 label prI = findIndex(procIndices_, neiProcNo);
3226 meshPtr = &(recvMeshes_[prI].subMesh());
3227 crMapPtr = &(recvMeshes_[prI].map());
3232 bool matchedFace = false;
3234 // Alias for convenience
3235 const coupleMap& crMap = *crMapPtr;
3236 const dynamicTopoFvMesh& sMesh = *meshPtr;
3238 // Obtain references
3239 Map<label>& pMap = crMap.entityMap(pointEnum);
3240 Map<label>& fMap = crMap.entityMap(faceEnum);
3241 Map<label>& rfMap = crMap.reverseEntityMap(faceEnum);
3243 // Configure the face
3244 forAll(cFace, pointI)
3248 pMap.found(mFace[pointI]) ?
3249 pMap[mFace[pointI]] : -1
3253 // Loop through all boundary faces on the subMesh
3256 label faceJ = sMesh.nOldInternalFaces_;
3257 faceJ < sMesh.faces_.size();
3261 const face& sFace = sMesh.faces_[faceJ];
3263 if (face::compare(sFace, cFace))
3267 Pout<< " Found face: " << faceJ
3269 << " with mfIndex: " << mfIndex
3275 if (collapsingSlave)
3277 if (fMap.found(faceJ))
3279 fMap[faceJ] = mfIndex;
3283 fMap.insert(faceJ, mfIndex);
3286 if (rfMap.found(mfIndex))
3288 rfMap[mfIndex] = faceJ;
3292 rfMap.insert(mfIndex, faceJ);
3297 if (rfMap.found(faceJ))
3299 rfMap[faceJ] = mfIndex;
3303 rfMap.insert(faceJ, mfIndex);
3306 if (fMap.found(mfIndex))
3308 fMap[mfIndex] = faceJ;
3312 fMap.insert(mfIndex, faceJ);
3324 // Write out for post-processing
3325 writeVTK("masterFace_" + Foam::name(mfIndex), mfIndex, 2);
3331 "dynamicTopoFvMesh::collapseQuadFace\n"
3333 " const label fIndex,\n"
3334 " label overRideCase,\n"
3335 " bool checkOnly,\n"
3339 << " Master face: " << mfIndex
3340 << ": " << mFace << " could not be matched." << nl
3341 << " cFace: " << cFace << nl
3342 << abort(FatalError);
3346 // If any interior faces in the slave map were
3347 // converted to boundaries, account for it
3348 const List<objectMap>& sadF = slaveMap.addedFaceList();
3352 label sIndex = slaveMap.index();
3353 label sfIndex = sadF[faceI].index();
3355 // Select appropriate mesh
3356 const dynamicTopoFvMesh* meshPtr = NULL;
3358 if (localCouple && !procCouple)
3360 // Local coupling. Use this mesh itself
3364 if (procCouple && !localCouple)
3366 meshPtr = &(recvMeshes_[pI].subMesh());
3369 // Alias for convenience
3370 const dynamicTopoFvMesh& sMesh = *meshPtr;
3372 label ofPatch = sMesh.whichPatch(sIndex);
3373 label sfPatch = sMesh.whichPatch(sfIndex);
3375 // Skip dissimilar patches
3376 if (ofPatch != sfPatch)
3381 const face& sFace = sMesh.faces_[sfIndex];
3383 forAll(cFace, pointI)
3387 rPointMap.found(sFace[pointI]) ?
3388 rPointMap[sFace[pointI]] : -1
3392 bool matchedFace = false;
3394 // Loop through all boundary faces on this mesh
3397 label faceJ = nOldInternalFaces_;
3398 faceJ < faces_.size();
3402 const face& mFace = faces_[faceJ];
3404 if (face::compare(mFace, cFace))
3408 Pout<< " Found face: " << faceJ
3410 << " with sfIndex: " << sfIndex
3416 if (collapsingSlave)
3418 if (rFaceMap.found(faceJ))
3420 rFaceMap[faceJ] = sfIndex;
3424 rFaceMap.insert(faceJ, sfIndex);
3427 if (faceMap.found(sfIndex))
3429 faceMap[sfIndex] = faceJ;
3433 faceMap.insert(sfIndex, faceJ);
3438 if (faceMap.found(faceJ))
3440 faceMap[faceJ] = sfIndex;
3444 faceMap.insert(faceJ, sfIndex);
3447 if (rFaceMap.found(sfIndex))
3449 rFaceMap[sfIndex] = faceJ;
3453 rFaceMap.insert(sfIndex, faceJ);
3469 "dynamicTopoFvMesh::collapseQuadFace\n"
3471 " const label fIndex,\n"
3472 " label overRideCase,\n"
3473 " bool checkOnly,\n"
3477 << " Slave face: " << sfIndex
3478 << ": " << sFace << " could not be matched." << nl
3479 << " cFace: " << cFace << nl
3480 << abort(FatalError);
3484 // Push operation into coupleMap
3485 switch (slaveMap.type())
3492 coupleMap::COLLAPSE_FIRST
3503 coupleMap::COLLAPSE_SECOND
3514 coupleMap::COLLAPSE_MIDPOINT
3524 topoChangeFlag_ = true;
3526 // Increment the counter
3529 // Increment the number of modifications
3532 // Return a succesful collapse
3533 map.type() = collapseCase;
3539 // Method for the collapse of an edge in 3D
3540 // - Returns a changeMap with a type specifying:
3541 // -3: Collapse failed since edge was on a noRefinement patch.
3542 // -1: Collapse failed since max number of topo-changes was reached.
3543 // 0: Collapse could not be performed.
3544 // 1: Collapsed to first node.
3545 // 2: Collapsed to second node.
3546 // 3: Collapsed to mid-point (default).
3547 // - overRideCase is used to force a certain collapse configuration.
3548 // -1: Use this value to let collapseEdge decide a case.
3549 // 1: Force collapse to first node.
3550 // 2: Force collapse to second node.
3551 // 3: Force collapse to mid-point.
3552 // - checkOnly performs a feasibility check and returns without modifications.
3553 // - forceOp to force the collapse.
3554 const changeMap dynamicTopoFvMesh::collapseEdge
3562 // Edge collapse performs the following operations:
3563 // [1] Checks if either vertex of the edge is on a boundary
3564 // [2] Checks whether cells attached to deleted vertices will be valid
3565 // after the edge-collapse operation
3566 // [3] Deletes all cells surrounding this edge
3567 // [4] Deletes all faces surrounding this edge
3568 // [5] Deletes all faces surrounding the deleted vertex attached
3569 // to the cells in [3]
3570 // [6] Checks the orientation of faces connected to the retained
3572 // [7] Remove one of the vertices of the edge
3573 // Update faceEdges and edgeFaces information
3575 // For 2D meshes, perform face-collapse
3578 return collapseQuadFace(eIndex, overRideCase, checkOnly);
3581 // Figure out which thread this is...
3582 label tIndex = self();
3584 // Prepare the changeMaps
3586 List<changeMap> slaveMaps;
3587 bool collapsingSlave = false;
3591 (statistics_[0] > maxModifications_)
3592 && (maxModifications_ > -1)
3595 // Reached the max allowable topo-changes.
3596 stack(tIndex).clear();
3601 // Check if edgeRefinements are to be avoided on patch.
3602 const labelList& eF = edgeFaces_[eIndex];
3606 label fPatch = whichPatch(eF[fI]);
3608 if (baseMesh_.lengthEstimator().checkRefinementPatch(fPatch))
3616 // Sanity check: Is the index legitimate?
3622 "const changeMap dynamicTopoFvMesh::collapseEdge\n"
3624 " const label eIndex,\n"
3625 " label overRideCase,\n"
3626 " bool checkOnly,\n"
3630 << " Invalid index: " << eIndex
3631 << abort(FatalError);
3634 // If coupled modification is set, and this is a
3635 // master edge, collapse its slaves as well.
3636 bool localCouple = false, procCouple = false;
3638 if (coupledModification_)
3640 const edge& eCheck = edges_[eIndex];
3642 const label edgeEnum = coupleMap::EDGE;
3643 const label pointEnum = coupleMap::POINT;
3645 // Is this a locally coupled edge (either master or slave)?
3646 if (locallyCoupledEntity(eIndex, true))
3652 if (processorCoupledEntity(eIndex))
3655 localCouple = false;
3658 if (localCouple && !procCouple)
3660 // Determine the slave index.
3661 label sIndex = -1, pIndex = -1;
3663 forAll(patchCoupling_, patchI)
3665 if (patchCoupling_(patchI))
3667 const coupleMap& cMap = patchCoupling_[patchI].map();
3669 if ((sIndex = cMap.findSlave(edgeEnum, eIndex)) > -1)
3676 // The following bit happens only during the sliver
3677 // exudation process, since slave edges are
3678 // usually not added to the coupled edge-stack.
3679 if ((sIndex = cMap.findMaster(edgeEnum, eIndex)) > -1)
3683 // Notice that we are collapsing a slave edge first.
3684 collapsingSlave = true;
3696 "const changeMap dynamicTopoFvMesh::collapseEdge\n"
3698 " const label eIndex,\n"
3699 " label overRideCase,\n"
3700 " bool checkOnly,\n"
3704 << "Coupled maps were improperly specified." << nl
3705 << " Slave index not found for: " << nl
3706 << " Edge: " << eIndex << ": " << eCheck << nl
3707 << abort(FatalError);
3711 // If we've found the slave, size up the list
3718 // Save index and patch for posterity
3719 slaveMaps[0].index() = sIndex;
3720 slaveMaps[0].patchIndex() = pIndex;
3725 Pout<< nl << " >> Collapsing slave edge: " << sIndex
3726 << " for master edge: " << eIndex << endl;
3730 if (procCouple && !localCouple)
3732 // If this is a new entity, bail out for now.
3733 // This will be handled at the next time-step.
3734 if (eIndex >= nOldEdges_)
3740 forAll(procIndices_, pI)
3742 // Fetch reference to subMeshes
3743 const coupledInfo& sendMesh = sendMeshes_[pI];
3744 const coupledInfo& recvMesh = recvMeshes_[pI];
3746 const coupleMap& scMap = sendMesh.map();
3747 const coupleMap& rcMap = recvMesh.map();
3749 // If this edge was sent to a lower-ranked
3750 // processor, skip it.
3751 if (procIndices_[pI] < Pstream::myProcNo())
3753 if (scMap.reverseEntityMap(edgeEnum).found(eIndex))
3757 Pout<< "Edge: " << eIndex
3759 << " was sent to proc: "
3761 << ", so bailing out."
3771 if ((sIndex = rcMap.findSlave(edgeEnum, eIndex)) > -1)
3773 // Check if a lower-ranked processor is
3774 // handling this edge
3775 if (procIndices_[pI] < Pstream::myProcNo())
3779 Pout<< "Edge: " << eIndex
3781 << " is handled by proc: "
3783 << ", so bailing out."
3790 label curIndex = slaveMaps.size();
3799 // Save index and patch for posterity
3800 slaveMaps[curIndex].index() = sIndex;
3801 slaveMaps[curIndex].patchIndex() = pI;
3806 (rcMap.findSlave(pointEnum, eCheck[0]) > -1) ||
3807 (rcMap.findSlave(pointEnum, eCheck[1]) > -1)
3810 // A point-only coupling exists.
3812 // Check if a lower-ranked processor is
3813 // handling this edge
3814 if (procIndices_[pI] < Pstream::myProcNo())
3818 Pout<< "Edge point on: " << eIndex
3820 << " is handled by proc: "
3822 << ", so bailing out."
3829 label p0Index = rcMap.findSlave(pointEnum, eCheck[0]);
3830 label p1Index = rcMap.findSlave(pointEnum, eCheck[1]);
3832 if (p0Index > -1 && p1Index == -1)
3837 if (p0Index == -1 && p1Index > -1)
3842 label curIndex = slaveMaps.size();
3851 // Save index and patch for posterity
3852 // - Negate the index to signify point coupling
3853 slaveMaps[curIndex].index() = -sIndex;
3854 slaveMaps[curIndex].patchIndex() = pI;
3860 // Something's wrong with coupling maps
3864 "const changeMap dynamicTopoFvMesh::collapseEdge\n"
3866 " const label eIndex,\n"
3867 " label overRideCase,\n"
3868 " bool checkOnly,\n"
3872 << "Coupled maps were improperly specified." << nl
3873 << " localCouple: " << localCouple << nl
3874 << " procCouple: " << procCouple << nl
3875 << " Edge: " << eIndex << ": " << eCheck << nl
3876 << abort(FatalError);
3879 // Temporarily turn off coupledModification
3880 unsetCoupledModification();
3882 // Test the master edge for collapse, and decide on a case
3883 changeMap masterMap = collapseEdge(eIndex, -1, true, forceOp);
3886 setCoupledModification();
3888 // Master couldn't perform collapse
3889 if (masterMap.type() <= 0)
3894 // For point-only coupling, define the points for checking
3895 pointField slaveMoveNewPoint(slaveMaps.size(), vector::zero);
3896 pointField slaveMoveOldPoint(slaveMaps.size(), vector::zero);
3898 // Now check each of the slaves for collapse feasibility
3899 forAll(slaveMaps, slaveI)
3901 // Alias for convenience...
3902 changeMap& slaveMap = slaveMaps[slaveI];
3904 label slaveOverRide = -1;
3905 label sIndex = slaveMap.index();
3906 label pI = slaveMap.patchIndex();
3908 // If the edge is mapped onto itself, skip check
3909 // (occurs for cyclic edges)
3910 if ((sIndex == eIndex) && localCouple)
3915 const coupleMap* cMapPtr = NULL;
3917 edge mEdge(eCheck), sEdge(-1, -1);
3921 sEdge = edges_[sIndex];
3923 cMapPtr = &(patchCoupling_[pI].map());
3928 const dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
3930 cMapPtr = &(recvMeshes_[pI].map());
3936 Pout<< "Checking slave point: " << mag(sIndex)
3937 << "::" << sMesh.points_[mag(sIndex)]
3938 << " on proc: " << procIndices_[pI]
3939 << " for master edge: " << eIndex
3940 << " using collapseCase: " << masterMap.type()
3946 sEdge = sMesh.edges_[sIndex];
3950 Pout<< "Checking slave edge: " << sIndex
3951 << "::" << sMesh.edges_[sIndex]
3952 << " on proc: " << procIndices_[pI]
3953 << " for master edge: " << eIndex
3954 << " using collapseCase: " << masterMap.type()
3960 const Map<label>& pointMap = cMapPtr->entityMap(pointEnum);
3962 // Perform a topological comparison.
3963 switch (masterMap.type())
3969 slaveMoveNewPoint[slaveI] = points_[mEdge[0]];
3970 slaveMoveOldPoint[slaveI] = oldPoints_[mEdge[0]];
3973 if (pointMap[mEdge[0]] == sEdge[0])
3978 if (pointMap[mEdge[1]] == sEdge[0])
3984 // Write out for for post-processing
3985 writeVTK("mEdge_" + Foam::name(eIndex), eIndex, 1);
3990 "const changeMap dynamicTopoFvMesh"
3993 " const label eIndex,\n"
3994 " label overRideCase,\n"
3995 " bool checkOnly,\n"
3999 << "Coupled collapse failed." << nl
4000 << "Master: " << eIndex << " : " << mEdge << nl
4001 << "Slave: " << sIndex << " : " << sEdge << nl
4002 << abort(FatalError);
4012 slaveMoveNewPoint[slaveI] = points_[mEdge[1]];
4013 slaveMoveOldPoint[slaveI] = oldPoints_[mEdge[1]];
4016 if (pointMap[mEdge[1]] == sEdge[1])
4021 if (pointMap[mEdge[0]] == sEdge[1])
4027 // Write out for for post-processing
4028 writeVTK("mEdge_" + Foam::name(eIndex), eIndex, 1);
4033 "const changeMap dynamicTopoFvMesh"
4036 " const label eIndex,\n"
4037 " label overRideCase,\n"
4038 " bool checkOnly,\n"
4042 << "Coupled collapse failed." << nl
4043 << "Master: " << eIndex << " : " << mEdge << nl
4044 << "Slave: " << sIndex << " : " << sEdge << nl
4045 << abort(FatalError);
4055 slaveMoveNewPoint[slaveI] =
4057 0.5 * (points_[mEdge[0]] + points_[mEdge[1]])
4060 slaveMoveOldPoint[slaveI] =
4062 0.5 * (oldPoints_[mEdge[0]] + oldPoints_[mEdge[1]])
4074 // Temporarily turn off coupledModification
4075 unsetCoupledModification();
4077 // Test the slave edge
4080 slaveMap = collapseEdge(sIndex, slaveOverRide, true, forceOp);
4085 dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
4089 // Point-based coupling
4090 scalar slaveCollapseQuality(GREAT);
4091 DynamicList<label> cellsChecked(10);
4093 // Check cells connected to coupled point
4094 const labelList& pEdges = sMesh.pointEdges_[mag(sIndex)];
4096 bool infeasible = false;
4098 forAll(pEdges, edgeI)
4100 const labelList& eFaces =
4102 sMesh.edgeFaces_[pEdges[edgeI]]
4105 // Build a list of cells to check
4106 forAll(eFaces, faceI)
4108 label own = sMesh.owner_[eFaces[faceI]];
4109 label nei = sMesh.neighbour_[eFaces[faceI]];
4112 if (findIndex(cellsChecked, own) == -1)
4114 // Check if point movement is feasible
4119 slaveMoveNewPoint[slaveI],
4120 slaveMoveOldPoint[slaveI],
4124 slaveCollapseQuality,
4139 // Check neighbour cell
4140 if (findIndex(cellsChecked, nei) == -1)
4142 // Check if point movement is feasible
4147 slaveMoveNewPoint[slaveI],
4148 slaveMoveOldPoint[slaveI],
4152 slaveCollapseQuality,
4171 slaveMap.type() = 0;
4175 slaveMap.type() = 1;
4180 // Edge-based coupling
4195 setCoupledModification();
4197 if (slaveMap.type() <= 0)
4199 // Slave couldn't perform collapse.
4205 // Save index and patch for posterity
4206 slaveMap.index() = sIndex;
4207 slaveMap.patchIndex() = pI;
4210 // Next collapse each slave edge (for real this time...)
4211 forAll(slaveMaps, slaveI)
4213 // Alias for convenience...
4214 changeMap& slaveMap = slaveMaps[slaveI];
4216 label sIndex = slaveMap.index();
4217 label pI = slaveMap.patchIndex();
4219 // If the edge is mapped onto itself, skip modification
4220 // (occurs for cyclic edges)
4221 if ((sIndex == eIndex) && localCouple)
4226 label slaveOverRide = slaveMap.type();
4228 // Temporarily turn off coupledModification
4229 unsetCoupledModification();
4231 // Collapse the slave
4234 slaveMap = collapseEdge(sIndex, slaveOverRide, false, forceOp);
4238 const coupleMap& cMap = recvMeshes_[pI].map();
4239 dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
4243 // Point based coupling
4245 // Move points to new location,
4246 // and update operation into coupleMap
4247 sMesh.points_[mag(sIndex)] = slaveMoveNewPoint[slaveI];
4248 sMesh.oldPoints_[mag(sIndex)] = slaveMoveOldPoint[slaveI];
4253 coupleMap::MOVE_POINT,
4254 slaveMoveNewPoint[slaveI],
4255 slaveMoveOldPoint[slaveI]
4258 // Force operation to succeed
4259 slaveMap.type() = 1;
4263 // Edge-based coupling
4275 // Push operation into coupleMap
4276 switch (slaveMap.type())
4283 coupleMap::COLLAPSE_FIRST
4294 coupleMap::COLLAPSE_SECOND
4305 coupleMap::COLLAPSE_MIDPOINT
4315 setCoupledModification();
4317 // The final operation has to succeed.
4318 if (slaveMap.type() <= 0)
4323 "const changeMap dynamicTopoFvMesh::collapseEdge\n"
4325 " const label eIndex,\n"
4326 " label overRideCase,\n"
4327 " bool checkOnly,\n"
4331 << "Coupled topo-change for slave failed." << nl
4332 << " Edge: " << eIndex << ": " << eCheck << nl
4333 << " Slave index: " << sIndex << nl
4334 << " Patch index: " << pI << nl
4335 << " Type: " << slaveMap.type() << nl
4336 << abort(FatalError);
4339 // Save index and patch for posterity
4340 slaveMap.index() = sIndex;
4341 slaveMap.patchIndex() = pI;
4345 // Build hullVertices for this edge
4346 labelList vertexHull;
4347 buildVertexHull(eIndex, vertexHull);
4351 label replaceIndex = -1, m = vertexHull.size();
4353 // Size up the hull lists
4354 labelList cellHull(m, -1);
4355 labelList faceHull(m, -1);
4356 labelList edgeHull(m, -1);
4357 labelListList ringEntities(4, labelList(m, -1));
4359 // Construct a hull around this edge
4360 meshOps::constructHull
4377 // Check whether points of the edge lies on a boundary
4378 const FixedList<bool,2> edgeBoundary = checkEdgeBoundary(eIndex);
4379 FixedList<label, 2> nBoundCurves(0), nProcCurves(0), checkPoints(-1);
4381 // Decide on collapseCase
4382 label collapseCase = -1;
4384 if (edgeBoundary[0] && !edgeBoundary[1])
4389 if (!edgeBoundary[0] && edgeBoundary[1])
4394 if (edgeBoundary[0] && edgeBoundary[1])
4396 // If this is an interior edge with two boundary points.
4397 // Bail out for now. If proximity based refinement is
4398 // switched on, mesh may be sliced at this point.
4399 label edgePatch = whichEdgePatch(eIndex);
4401 if (edgePatch == -1)
4406 // Check if either point lies on a bounding curve
4407 // Used to ensure that collapses happen towards bounding curves.
4408 // If the edge itself is on a bounding curve, collapse is valid.
4409 const edge& edgeCheck = edges_[eIndex];
4411 forAll(edgeCheck, pointI)
4413 const labelList& pEdges = pointEdges_[edgeCheck[pointI]];
4415 forAll(pEdges, edgeI)
4423 &(nProcCurves[pointI])
4427 nBoundCurves[pointI]++;
4432 // Check for procCurves first
4433 if (!coupledModification_ && !isSubMesh_)
4436 if (nProcCurves[0] && nProcCurves[1])
4441 if (nProcCurves[0] && !nProcCurves[1])
4443 if (nBoundCurves[1])
4454 if (!nProcCurves[0] && nProcCurves[1])
4456 if (nBoundCurves[0])
4468 // If still undecided, choose based on bounding curves
4469 if (collapseCase == -1)
4471 // Pick the point which is connected to more bounding curves
4472 if (nBoundCurves[0] > nBoundCurves[1])
4477 if (nBoundCurves[1] > nBoundCurves[0])
4483 // Bounding edge: collapseEdge can collapse this edge
4490 // Looks like this is an interior edge.
4491 // Collapse case [3] by default
4495 // Perform an override if requested.
4496 if (overRideCase != -1)
4498 collapseCase = overRideCase;
4501 // Configure the new point-position
4502 point newPoint = vector::zero;
4503 point oldPoint = vector::zero;
4505 label collapsePoint = -1, replacePoint = -1;
4507 switch (collapseCase)
4511 // Collapse to the first node
4512 replacePoint = edges_[eIndex][0];
4513 collapsePoint = edges_[eIndex][1];
4515 newPoint = points_[replacePoint];
4516 oldPoint = oldPoints_[replacePoint];
4518 checkPoints[0] = collapsePoint;
4525 // Collapse to the second node
4526 replacePoint = edges_[eIndex][1];
4527 collapsePoint = edges_[eIndex][0];
4529 newPoint = points_[replacePoint];
4530 oldPoint = oldPoints_[replacePoint];
4532 checkPoints[0] = collapsePoint;
4539 // Collapse to the mid-point
4540 replacePoint = edges_[eIndex][1];
4541 collapsePoint = edges_[eIndex][0];
4547 points_[replacePoint]
4548 + points_[collapsePoint]
4556 oldPoints_[replacePoint]
4557 + oldPoints_[collapsePoint]
4561 checkPoints[0] = replacePoint;
4562 checkPoints[1] = collapsePoint;
4569 // Don't think this will ever happen.
4573 "const changeMap dynamicTopoFvMesh::collapseEdge\n"
4575 " const label eIndex,\n"
4576 " label overRideCase,\n"
4577 " bool checkOnly,\n"
4581 << "Edge: " << eIndex << ": " << edges_[eIndex]
4582 << ". Couldn't decide on collapseCase."
4583 << abort(FatalError);
4589 // Loop through edges and check for feasibility of collapse
4590 // Also, keep track of resulting cell quality,
4591 // if collapse is indeed feasible
4592 scalar collapseQuality(GREAT);
4593 DynamicList<label> cellsChecked(10);
4595 // Add all hull cells as 'checked',
4596 // and therefore, feasible
4597 forAll(cellHull, cellI)
4599 if (cellHull[cellI] == -1)
4604 cellsChecked.append(cellHull[cellI]);
4607 // Check collapsibility of cells around edges
4608 // with the re-configured point
4609 forAll(checkPoints, pointI)
4611 if (checkPoints[pointI] == -1)
4616 const labelList& checkPointEdges = pointEdges_[checkPoints[pointI]];
4618 forAll(checkPointEdges, edgeI)
4620 const labelList& eFaces = edgeFaces_[checkPointEdges[edgeI]];
4622 // Build a list of cells to check
4623 forAll(eFaces, faceI)
4625 label own = owner_[eFaces[faceI]];
4626 label nei = neighbour_[eFaces[faceI]];
4629 if (findIndex(cellsChecked, own) == -1)
4631 // Check if a collapse is feasible
4638 checkPoints[pointI],
4656 // Check neighbour cell
4657 if (findIndex(cellsChecked, nei) == -1)
4659 // Check if a collapse is feasible
4666 checkPoints[pointI],
4682 // Add a map entry of the replacePoint as an 'addedPoint'
4683 // - Used in coupled mapping
4684 map.addPoint(replacePoint);
4686 // Are we only performing checks?
4689 // Return a succesful collapse possibility
4690 map.type() = collapseCase;
4692 // Make note of the removed point
4693 map.removePoint(collapsePoint);
4697 Pout<< nl << "Edge: " << eIndex
4698 << ":: " << edges_[eIndex] << nl
4699 << " collapseCase determined to be: " << collapseCase << nl
4700 << " Resulting quality: " << collapseQuality << nl
4701 << " collapsePoint: " << collapsePoint << nl
4702 << " nBoundCurves: " << nBoundCurves << nl
4703 << " nProcCurves: " << nProcCurves << nl
4710 // Define indices on the hull for removal / replacement
4711 label removeEdgeIndex = -1, replaceEdgeIndex = -1;
4712 label removeFaceIndex = -1, replaceFaceIndex = -1;
4714 if (replacePoint == edges_[eIndex][0])
4716 replaceEdgeIndex = 0;
4717 replaceFaceIndex = 1;
4718 removeEdgeIndex = 2;
4719 removeFaceIndex = 3;
4722 if (replacePoint == edges_[eIndex][1])
4724 removeEdgeIndex = 0;
4725 removeFaceIndex = 1;
4726 replaceEdgeIndex = 2;
4727 replaceFaceIndex = 3;
4731 // Don't think this will ever happen.
4735 "const changeMap dynamicTopoFvMesh::collapseEdge\n"
4737 " const label eIndex,\n"
4738 " label overRideCase,\n"
4739 " bool checkOnly,\n"
4743 << "Edge: " << eIndex << ": " << edges_[eIndex]
4744 << ". Couldn't decide on removal / replacement indices."
4745 << abort(FatalError);
4751 << "Edge: " << eIndex << ": " << edges_[eIndex]
4752 << " is to be collapsed. " << nl;
4754 Pout<< " On SubMesh: " << Switch::asText(isSubMesh_) << nl;
4755 Pout<< " coupledModification: " << coupledModification_ << nl;
4757 label epIndex = whichEdgePatch(eIndex);
4759 const polyBoundaryMesh& boundary = boundaryMesh();
4765 Pout<< "Internal" << nl;
4768 if (epIndex < boundary.size())
4770 Pout<< boundary[epIndex].name() << nl;
4774 Pout<< " New patch: " << epIndex << endl;
4777 Pout<< " nBoundCurves: " << nBoundCurves << nl
4778 << " nProcCurves: " << nProcCurves << nl
4779 << " collapseCase: " << collapseCase << nl
4780 << " Resulting quality: " << collapseQuality << endl;
4784 Pout<< " Edges: " << edgeHull << nl
4785 << " Faces: " << faceHull << nl
4786 << " Cells: " << cellHull << nl
4787 << " replacePoint: " << replacePoint << nl
4788 << " collapsePoint: " << collapsePoint << nl
4789 << " checkPoints: " << checkPoints << nl;
4791 Pout<< " ringEntities (removed faces): " << nl;
4793 forAll(ringEntities[removeFaceIndex], faceI)
4795 label fIndex = ringEntities[removeFaceIndex][faceI];
4802 Pout<< fIndex << ": " << faces_[fIndex] << nl;
4805 Pout<< " ringEntities (removed edges): " << nl;
4807 forAll(ringEntities[removeEdgeIndex], edgeI)
4809 label ieIndex = ringEntities[removeEdgeIndex][edgeI];
4816 Pout<< ieIndex << ": " << edges_[ieIndex] << nl;
4819 Pout<< " ringEntities (replacement faces): " << nl;
4821 forAll(ringEntities[replaceFaceIndex], faceI)
4823 label fIndex = ringEntities[replaceFaceIndex][faceI];
4830 Pout<< fIndex << ": " << faces_[fIndex] << nl;
4833 Pout<< " ringEntities (replacement edges): " << nl;
4835 forAll(ringEntities[replaceEdgeIndex], edgeI)
4837 label ieIndex = ringEntities[replaceEdgeIndex][edgeI];
4844 Pout<< ieIndex << ": " << edges_[ieIndex] << nl;
4847 labelList& collapsePointEdges = pointEdges_[collapsePoint];
4849 Pout<< " pointEdges (collapsePoint): ";
4851 forAll(collapsePointEdges, edgeI)
4853 Pout<< collapsePointEdges[edgeI] << " ";
4858 // Write out VTK files prior to change
4859 // - Using old-points for convenience in post-processing
4865 + '(' + Foam::name(collapsePoint)
4866 + ',' + Foam::name(replacePoint) + ')'
4875 if (whichEdgePatch(eIndex) > -1)
4877 // Update number of surface collapses, if necessary.
4881 // Maintain a list of modified faces for mapping
4882 DynamicList<label> modifiedFaces(10);
4884 // Renumber all hull faces and edges
4885 forAll(faceHull, indexI)
4887 // Loop through all faces of the edge to be removed
4888 // and reassign them to the replacement edge
4889 label edgeToRemove = ringEntities[removeEdgeIndex][indexI];
4890 label faceToRemove = ringEntities[removeFaceIndex][indexI];
4891 label cellToRemove = cellHull[indexI];
4892 label replaceEdge = ringEntities[replaceEdgeIndex][indexI];
4893 label replaceFace = ringEntities[replaceFaceIndex][indexI];
4895 label replacePatch = whichEdgePatch(replaceEdge);
4896 label removePatch = whichEdgePatch(edgeToRemove);
4898 // Check if a patch conversion is necessary
4899 if (replacePatch == -1 && removePatch > -1)
4903 Pout<< " Edge: " << replaceEdge
4904 << " :: " << edges_[replaceEdge]
4905 << " is interior, but edge: " << edgeToRemove
4906 << " :: " << edges_[edgeToRemove]
4907 << " is on a boundary patch."
4911 // Convert patch for edge
4912 edge newEdge = edges_[replaceEdge];
4913 labelList newEdgeFaces = edgeFaces_[replaceEdge];
4915 // Insert the new edge
4916 label newEdgeIndex =
4926 // Replace faceEdges for all
4928 forAll(newEdgeFaces, faceI)
4930 meshOps::replaceLabel
4934 faceEdges_[newEdgeFaces[faceI]]
4939 removeEdge(replaceEdge);
4942 map.removeEdge(replaceEdge);
4943 map.addEdge(newEdgeIndex, labelList(1, replaceEdge));
4945 // Replace index and patch
4946 replaceEdge = newEdgeIndex;
4948 // Modify ringEntities
4949 ringEntities[replaceEdgeIndex][indexI] = newEdgeIndex;
4952 const labelList& rmvEdgeFaces = edgeFaces_[edgeToRemove];
4954 forAll(rmvEdgeFaces, faceI)
4956 // Replace edge labels for faces
4957 meshOps::replaceLabel
4961 faceEdges_[rmvEdgeFaces[faceI]]
4964 // Loop through faces associated with this edge,
4965 // and renumber them as well.
4966 const face& faceToCheck = faces_[rmvEdgeFaces[faceI]];
4968 if ((replaceIndex = faceToCheck.which(collapsePoint)) > -1)
4970 // Renumber the face...
4971 faces_[rmvEdgeFaces[faceI]][replaceIndex] = replacePoint;
4973 // Add an entry for mapping
4974 if (findIndex(modifiedFaces, rmvEdgeFaces[faceI]) == -1)
4976 modifiedFaces.append(rmvEdgeFaces[faceI]);
4980 // Hull faces should be removed for the replacement edge
4981 if (rmvEdgeFaces[faceI] == faceHull[indexI])
4983 meshOps::sizeDownList
4986 edgeFaces_[replaceEdge]
4994 // Need to avoid ring faces as well.
4995 forAll(ringEntities[removeFaceIndex], faceII)
5000 == ringEntities[removeFaceIndex][faceII]
5008 // Size-up the replacement edge list if the face hasn't been found.
5009 // These faces are connected to the edge slated for
5010 // removal, but do not belong to the hull.
5015 rmvEdgeFaces[faceI],
5016 edgeFaces_[replaceEdge]
5021 if (cellToRemove == -1)
5026 // Size down edgeFaces for the ring edges
5027 meshOps::sizeDownList
5030 edgeFaces_[edgeHull[indexI]]
5033 // Ensure proper orientation of retained faces
5034 if (owner_[faceToRemove] == cellToRemove)
5036 if (owner_[replaceFace] == cellToRemove)
5040 (neighbour_[faceToRemove] > neighbour_[replaceFace])
5041 && (neighbour_[replaceFace] != -1)
5044 // This face is to be flipped
5045 faces_[replaceFace] = faces_[replaceFace].reverseFace();
5046 owner_[replaceFace] = neighbour_[replaceFace];
5047 neighbour_[replaceFace] = neighbour_[faceToRemove];
5049 setFlip(replaceFace);
5054 (neighbour_[faceToRemove] == -1) &&
5055 (neighbour_[replaceFace] != -1)
5058 // This interior face would need to be converted
5059 // to a boundary one, and flipped as well.
5060 face newFace = faces_[replaceFace].reverseFace();
5061 label newOwner = neighbour_[replaceFace];
5062 label newNeighbour = neighbour_[faceToRemove];
5063 labelList newFE = faceEdges_[replaceFace];
5065 label newFaceIndex =
5069 whichPatch(faceToRemove),
5076 // Set this face aside for mapping
5077 modifiedFaces.append(newFaceIndex);
5080 map.addFace(newFaceIndex, labelList(1, faceToRemove));
5082 // Ensure that all edges of this face are
5084 forAll(newFE, edgeI)
5086 if (whichEdgePatch(newFE[edgeI]) == -1)
5088 edge newEdge = edges_[newFE[edgeI]];
5089 labelList newEF = edgeFaces_[newFE[edgeI]];
5091 // Need patch information for the new edge.
5092 // Find the corresponding edge in ringEntities.
5093 // Note that hullEdges doesn't need to be checked,
5094 // since they are common to both faces.
5099 ringEntities[replaceEdgeIndex],
5108 ringEntities[removeEdgeIndex][i]
5112 // Insert the new edge
5113 label newEdgeIndex =
5123 // Replace faceEdges for all
5125 forAll(newEF, faceI)
5127 meshOps::replaceLabel
5131 faceEdges_[newEF[faceI]]
5136 removeEdge(newFE[edgeI]);
5139 map.removeEdge(newFE[edgeI]);
5144 labelList(1, newFE[edgeI])
5147 // Replace faceEdges with new edge index
5148 newFE[edgeI] = newEdgeIndex;
5150 // Modify ringEntities
5151 ringEntities[replaceEdgeIndex][i] = newEdgeIndex;
5155 // Add the new faceEdges
5156 faceEdges_.append(newFE);
5158 // Replace edgeFaces with the new face index
5159 const labelList& newFEdges = faceEdges_[newFaceIndex];
5161 forAll(newFEdges, edgeI)
5163 meshOps::replaceLabel
5167 edgeFaces_[newFEdges[edgeI]]
5172 removeFace(replaceFace);
5175 map.removeFace(replaceFace);
5177 // Replace label for the new owner
5178 meshOps::replaceLabel
5185 // Modify ringEntities and replaceFace
5186 replaceFace = newFaceIndex;
5187 ringEntities[replaceFaceIndex][indexI] = newFaceIndex;
5192 (neighbour_[faceToRemove] == -1) &&
5193 (neighbour_[replaceFace] == -1)
5196 // Wierd overhanging cell. Since replaceFace
5197 // would be an orphan if this continued, remove
5198 // the face entirely.
5199 labelList rmFE = faceEdges_[replaceFace];
5205 (edgeFaces_[rmFE[edgeI]].size() == 1) &&
5206 (edgeFaces_[rmFE[edgeI]][0] == replaceFace)
5209 // This edge has to be removed entirely.
5210 removeEdge(rmFE[edgeI]);
5213 map.removeEdge(rmFE[edgeI]);
5219 ringEntities[replaceEdgeIndex],
5226 // Modify ringEntities
5227 ringEntities[replaceEdgeIndex][i] = -1;
5232 // Size-down edgeFaces
5233 meshOps::sizeDownList
5236 edgeFaces_[rmFE[edgeI]]
5241 // If this is a subMesh, and replaceFace is on
5242 // a physical boundary, make a 'special' entry
5243 // for coupled mapping purposes.
5246 label kfPatch = whichPatch(replaceFace);
5247 label rfPatch = whichPatch(faceToRemove);
5251 (getNeighbourProcessor(rfPatch) > -1) &&
5252 (getNeighbourProcessor(kfPatch) == -1)
5258 labelList(1, (-2 - kfPatch))
5264 removeFace(replaceFace);
5267 map.removeFace(replaceFace);
5269 // Modify ringEntities and replaceFace
5271 ringEntities[replaceFaceIndex][indexI] = -1;
5275 // Keep orientation intact, and update the owner
5276 owner_[replaceFace] = neighbour_[faceToRemove];
5280 if (neighbour_[faceToRemove] == -1)
5282 // This interior face would need to be converted
5283 // to a boundary one, but with orientation intact.
5284 face newFace = faces_[replaceFace];
5285 label newOwner = owner_[replaceFace];
5286 label newNeighbour = neighbour_[faceToRemove];
5287 labelList newFE = faceEdges_[replaceFace];
5289 label newFaceIndex =
5293 whichPatch(faceToRemove),
5300 // Set this face aside for mapping
5301 modifiedFaces.append(newFaceIndex);
5304 map.addFace(newFaceIndex, labelList(1, faceToRemove));
5306 // Ensure that all edges of this face are
5308 forAll(newFE, edgeI)
5310 if (whichEdgePatch(newFE[edgeI]) == -1)
5312 edge newEdge = edges_[newFE[edgeI]];
5313 labelList newEF = edgeFaces_[newFE[edgeI]];
5315 // Need patch information for the new edge.
5316 // Find the corresponding edge in ringEntities.
5317 // Note that hullEdges doesn't need to be checked,
5318 // since they are common to both faces.
5323 ringEntities[replaceEdgeIndex],
5332 ringEntities[removeEdgeIndex][i]
5336 // Insert the new edge
5337 label newEdgeIndex =
5347 // Replace faceEdges for all
5349 forAll(newEF, faceI)
5351 meshOps::replaceLabel
5355 faceEdges_[newEF[faceI]]
5360 removeEdge(newFE[edgeI]);
5363 map.removeEdge(newFE[edgeI]);
5368 labelList(1, newFE[edgeI])
5371 // Replace faceEdges with new edge index
5372 newFE[edgeI] = newEdgeIndex;
5374 // Modify ringEntities
5375 ringEntities[replaceEdgeIndex][i] = newEdgeIndex;
5379 // Add the new faceEdges
5380 faceEdges_.append(newFE);
5382 // Replace edgeFaces with the new face index
5383 const labelList& newFEdges = faceEdges_[newFaceIndex];
5385 forAll(newFEdges, edgeI)
5387 meshOps::replaceLabel
5391 edgeFaces_[newFEdges[edgeI]]
5396 removeFace(replaceFace);
5399 map.removeFace(replaceFace);
5401 // Replace label for the new owner
5402 meshOps::replaceLabel
5409 // Modify ringEntities and replaceFace
5410 replaceFace = newFaceIndex;
5411 ringEntities[replaceFaceIndex][indexI] = newFaceIndex;
5415 // Keep orientation intact, and update the neighbour
5416 neighbour_[replaceFace] = neighbour_[faceToRemove];
5420 if (neighbour_[faceToRemove] != -1)
5422 meshOps::replaceLabel
5426 cells_[neighbour_[faceToRemove]]
5432 if (neighbour_[replaceFace] == cellToRemove)
5434 if (owner_[faceToRemove] < owner_[replaceFace])
5436 // This face is to be flipped
5437 faces_[replaceFace] = faces_[replaceFace].reverseFace();
5438 neighbour_[replaceFace] = owner_[replaceFace];
5439 owner_[replaceFace] = owner_[faceToRemove];
5441 setFlip(replaceFace);
5445 // Keep orientation intact, and update the neighbour
5446 neighbour_[replaceFace] = owner_[faceToRemove];
5451 // Keep orientation intact, and update the owner
5452 owner_[replaceFace] = owner_[faceToRemove];
5456 meshOps::replaceLabel
5460 cells_[owner_[faceToRemove]]
5465 // Remove all hull entities
5466 forAll(faceHull, indexI)
5468 label edgeToRemove = ringEntities[removeEdgeIndex][indexI];
5469 label faceToRemove = ringEntities[removeFaceIndex][indexI];
5470 label cellToRemove = cellHull[indexI];
5472 if (cellToRemove != -1)
5474 // Remove faceToRemove and associated faceEdges
5475 removeFace(faceToRemove);
5478 map.removeFace(faceToRemove);
5480 // Remove the hull cell
5481 removeCell(cellToRemove);
5484 map.removeCell(cellToRemove);
5487 // Remove the hull edge and associated edgeFaces
5488 removeEdge(edgeToRemove);
5491 map.removeEdge(edgeToRemove);
5493 // Remove the hull face
5494 removeFace(faceHull[indexI]);
5497 map.removeFace(faceHull[indexI]);
5500 // Loop through pointEdges for the collapsePoint,
5501 // and replace all occurrences with replacePoint.
5502 // Size-up pointEdges for the replacePoint as well.
5503 const labelList& pEdges = pointEdges_[collapsePoint];
5505 forAll(pEdges, edgeI)
5508 label edgeIndex = pEdges[edgeI];
5510 if (edgeIndex != eIndex)
5512 if (edges_[edgeIndex][0] == collapsePoint)
5514 edges_[edgeIndex][0] = replacePoint;
5519 pointEdges_[replacePoint]
5523 if (edges_[edgeIndex][1] == collapsePoint)
5525 edges_[edgeIndex][1] = replacePoint;
5530 pointEdges_[replacePoint]
5535 // Looks like pointEdges is inconsistent
5539 "const changeMap dynamicTopoFvMesh::collapseEdge\n"
5541 " const label eIndex,\n"
5542 " label overRideCase,\n"
5543 " bool checkOnly,\n"
5547 << "pointEdges is inconsistent." << nl
5548 << "Point: " << collapsePoint << nl
5549 << "pointEdges: " << pEdges << nl
5550 << abort(FatalError);
5553 // Loop through faces associated with this edge,
5554 // and renumber them as well.
5555 const labelList& eFaces = edgeFaces_[edgeIndex];
5557 forAll(eFaces, faceI)
5559 const face& faceToCheck = faces_[eFaces[faceI]];
5561 if ((replaceIndex = faceToCheck.which(collapsePoint)) > -1)
5563 // Renumber the face...
5564 faces_[eFaces[faceI]][replaceIndex] = replacePoint;
5566 // Set this face aside for mapping
5567 if (findIndex(modifiedFaces, eFaces[faceI]) == -1)
5569 modifiedFaces.append(eFaces[faceI]);
5576 // Set old / new points
5577 oldPoints_[replacePoint] = oldPoint;
5578 points_[replacePoint] = newPoint;
5580 // Remove the collapse point
5581 removePoint(collapsePoint);
5584 map.removePoint(collapsePoint);
5590 map.removeEdge(eIndex);
5592 // Check for duplicate edges connected to the replacePoint
5593 const labelList& rpEdges = pointEdges_[replacePoint];
5595 DynamicList<label> mergeFaces(10);
5597 forAll(rpEdges, edgeI)
5599 const edge& eCheckI = edges_[rpEdges[edgeI]];
5600 const label vCheckI = eCheckI.otherVertex(replacePoint);
5602 for (label edgeJ = edgeI + 1; edgeJ < rpEdges.size(); edgeJ++)
5604 const edge& eCheckJ = edges_[rpEdges[edgeJ]];
5605 const label vCheckJ = eCheckJ.otherVertex(replacePoint);
5607 if (vCheckJ == vCheckI)
5609 labelPair efCheck(rpEdges[edgeI], rpEdges[edgeJ]);
5611 forAll(efCheck, edgeI)
5613 const labelList& eF = edgeFaces_[efCheck[edgeI]];
5617 label patch = whichPatch(eF[faceI]);
5624 if (findIndex(mergeFaces, eF[faceI]) == -1)
5626 mergeFaces.append(eF[faceI]);
5633 Pout<< " Found duplicate: " << eCheckI << nl
5634 << " Merge faces: " << mergeFaces << nl
5641 // Merge faces if necessary
5642 if (mergeFaces.size())
5644 mergeBoundaryFaces(mergeFaces);
5647 // Check and remove edges with an empty edgeFaces list
5648 const labelList& replaceEdges = ringEntities[replaceEdgeIndex];
5650 forAll(replaceEdges, edgeI)
5652 label replaceEdge = replaceEdges[edgeI];
5654 // If the ring edge was removed, don't bother.
5655 if (replaceEdge > -1)
5657 // Account for merged edges as well
5658 if (edgeFaces_[replaceEdge].empty())
5660 // Is this edge truly removed? If not, remove it.
5661 if (edges_[replaceEdge] != edge(-1, -1))
5665 Pout<< " Edge: " << replaceEdge
5666 << " :: " << edges_[replaceEdge]
5667 << " has empty edgeFaces."
5672 removeEdge(replaceEdge);
5675 map.removeEdge(replaceEdge);
5681 // For cell-mapping, exclude all hull-cells
5682 forAll(cellsChecked, indexI)
5684 if (cells_[cellsChecked[indexI]].empty())
5686 cellsChecked[indexI] = -1;
5689 if (findIndex(cellHull, cellsChecked[indexI]) > 0)
5691 cellsChecked[indexI] = -1;
5695 // Write out VTK files after change
5696 // - Using old-points for convenience in post-processing
5702 + '(' + Foam::name(collapsePoint)
5703 + ',' + Foam::name(replacePoint) + ')'
5710 // Now that all old / new cells possess correct connectivity,
5711 // compute mapping information.
5712 forAll(cellsChecked, cellI)
5714 if (cellsChecked[cellI] < 0)
5719 // Fill-in candidate mapping information
5720 labelList mC(1, cellsChecked[cellI]);
5722 // Set the mapping for this cell
5723 setCellMapping(cellsChecked[cellI], mC);
5726 // Set face mapping information for modified faces
5727 forAll(modifiedFaces, faceI)
5729 const label mfIndex = modifiedFaces[faceI];
5731 // Exclude deleted faces
5732 if (faces_[mfIndex].empty())
5737 // Decide between default / weighted mapping
5738 // based on boundary information
5739 label fPatch = whichPatch(mfIndex);
5743 setFaceMapping(mfIndex);
5747 // Fill-in candidate mapping information
5748 labelList faceCandidates;
5750 const labelList& fEdges = faceEdges_[mfIndex];
5752 forAll(fEdges, edgeI)
5754 if (whichEdgePatch(fEdges[edgeI]) == fPatch)
5756 // Loop through associated edgeFaces
5757 const labelList& eFaces = edgeFaces_[fEdges[edgeI]];
5759 forAll(eFaces, faceI)
5763 (eFaces[faceI] != mfIndex) &&
5764 (whichPatch(eFaces[faceI]) == fPatch)
5767 faceCandidates.setSize
5769 faceCandidates.size() + 1,
5777 // Set the mapping for this face
5778 setFaceMapping(mfIndex, faceCandidates);
5782 // If modification is coupled, update mapping info.
5783 if (coupledModification_)
5785 // Build a list of boundary edges / faces for mapping
5786 DynamicList<label> checkEdges(10), checkFaces(10);
5788 const labelList& pEdges = pointEdges_[replacePoint];
5790 forAll(pEdges, edgeI)
5792 const labelList& eFaces = edgeFaces_[pEdges[edgeI]];
5794 forAll(eFaces, faceI)
5796 label fPatch = whichPatch(eFaces[faceI]);
5798 if (localCouple && !procCouple)
5800 if (!locallyCoupledEntity(eFaces[faceI], true, false, true))
5805 // Check for cyclics
5806 if (boundaryMesh()[fPatch].type() == "cyclic")
5808 // Check if this is a master face
5809 const coupleMap& cM = patchCoupling_[fPatch].map();
5810 const Map<label>& fM = cM.entityMap(coupleMap::FACE);
5812 // Only add master faces
5813 // (belonging to the first half)
5814 if (!fM.found(eFaces[faceI]))
5821 if (procCouple && !localCouple)
5823 if (getNeighbourProcessor(fPatch) == -1)
5829 // Add face and its edges for checking
5830 if (findIndex(checkFaces, eFaces[faceI]) == -1)
5833 checkFaces.append(eFaces[faceI]);
5835 const labelList& fEdges = faceEdges_[eFaces[faceI]];
5837 forAll(fEdges, edgeJ)
5839 if (findIndex(checkEdges, fEdges[edgeJ]) == -1)
5841 checkEdges.append(fEdges[edgeJ]);
5848 // Output check entities
5853 "checkEdges_" + Foam::name(eIndex),
5854 checkEdges, 1, false, true
5859 "checkFaces_" + Foam::name(eIndex),
5860 checkFaces, 2, false, true
5864 if (localCouple && !procCouple)
5866 // Alias for convenience...
5867 const changeMap& slaveMap = slaveMaps[0];
5869 const label pI = slaveMap.patchIndex();
5870 const coupleMap& cMap = patchCoupling_[pI].map();
5872 // Obtain references
5873 Map<label>& pointMap = cMap.entityMap(coupleMap::POINT);
5874 Map<label>& rPointMap = cMap.reverseEntityMap(coupleMap::POINT);
5876 const labelList& rpList = slaveMap.removedPointList();
5877 const List<objectMap>& apList = slaveMap.addedPointList();
5879 // Configure the slave replacement point.
5880 // - collapseEdge stores this as an 'addedPoint'
5881 label scPoint = -1, srPoint = -1;
5883 if ((slaveMap.index() == eIndex) && localCouple)
5885 // Cyclic edge at axis
5886 scPoint = collapsePoint;
5887 srPoint = replacePoint;
5891 scPoint = rpList[0];
5892 srPoint = apList[0].index();
5895 if (collapsingSlave)
5897 if (rPointMap[replacePoint] == scPoint)
5899 pointMap[srPoint] = replacePoint;
5900 rPointMap[replacePoint] = srPoint;
5905 if (pointMap[replacePoint] == scPoint)
5907 rPointMap[srPoint] = replacePoint;
5908 pointMap[replacePoint] = srPoint;
5913 const label faceEnum = coupleMap::FACE;
5915 // Obtain references
5916 Map<label>& faceMap = cMap.entityMap(faceEnum);
5917 Map<label>& rFaceMap = cMap.reverseEntityMap(faceEnum);
5919 forAll(checkFaces, faceI)
5921 label mfIndex = checkFaces[faceI];
5922 label mfPatch = whichPatch(mfIndex);
5924 const face& mF = faces_[mfIndex];
5928 pointMap.found(mF[0]) ? pointMap[mF[0]] : -1,
5929 pointMap.found(mF[1]) ? pointMap[mF[1]] : -1,
5930 pointMap.found(mF[2]) ? pointMap[mF[2]] : -1
5933 if (cF[0] == -1 || cF[1] == -1 || cF[2] == -1)
5938 + Foam::name(mfIndex),
5943 Pout<< " Failed to configure face for: "
5944 << mfIndex << " :: " << faces_[mfIndex]
5945 << " using comparison face: " << cF
5946 << abort(FatalError);
5949 bool matchedFace = false;
5951 // Fetch edges connected to first slave point
5952 const labelList& spEdges = pointEdges_[cF[0]];
5954 forAll(spEdges, edgeJ)
5956 label seIndex = spEdges[edgeJ];
5958 if (whichEdgePatch(seIndex) == -1)
5963 const labelList& seFaces = edgeFaces_[seIndex];
5965 forAll(seFaces, faceI)
5967 label sfIndex = seFaces[faceI];
5969 if (whichPatch(sfIndex) == -1)
5974 const face& sF = faces_[sfIndex];
5980 triFace(sF[0], sF[1], sF[2]), cF
5986 word pN(boundaryMesh()[mfPatch].name());
5988 Pout<< " Found face: " << sfIndex
5990 << " with mfIndex: " << mfIndex
5991 << " :: " << faces_[mfIndex]
5996 if (rFaceMap.found(sfIndex))
5998 rFaceMap[sfIndex] = mfIndex;
6002 rFaceMap.insert(sfIndex, mfIndex);
6005 if (faceMap.found(mfIndex))
6007 faceMap[mfIndex] = sfIndex;
6011 faceMap.insert(mfIndex, sfIndex);
6031 + Foam::name(mfIndex),
6035 Pout<< " Failed to match face: "
6036 << mfIndex << " :: " << faces_[mfIndex]
6037 << " using comparison face: " << cF
6038 << abort(FatalError);
6043 const label edgeEnum = coupleMap::EDGE;
6045 // Obtain references
6046 Map<label>& edgeMap = cMap.entityMap(edgeEnum);
6047 Map<label>& rEdgeMap = cMap.reverseEntityMap(edgeEnum);
6049 forAll(checkEdges, edgeI)
6051 label meIndex = checkEdges[edgeI];
6053 const edge& mE = edges_[meIndex];
6057 pointMap.found(mE[0]) ? pointMap[mE[0]] : -1,
6058 pointMap.found(mE[1]) ? pointMap[mE[1]] : -1
6061 if (cE[0] == -1 || cE[1] == -1)
6066 + Foam::name(meIndex),
6071 Pout<< " Failed to configure edge for: "
6072 << meIndex << " :: " << edges_[meIndex]
6073 << " using comparison edge: " << cE
6074 << abort(FatalError);
6077 bool matchedEdge = false;
6079 // Fetch edges connected to first slave point
6080 const labelList& spEdges = pointEdges_[cE[0]];
6082 forAll(spEdges, edgeJ)
6084 label seIndex = spEdges[edgeJ];
6086 const edge& sE = edges_[seIndex];
6092 Pout<< " Found edge: " << seIndex
6094 << " with meIndex: " << meIndex
6095 << " :: " << edges_[meIndex]
6099 // Update reverse map
6100 if (rEdgeMap.found(seIndex))
6102 rEdgeMap[seIndex] = meIndex;
6106 rEdgeMap.insert(seIndex, meIndex);
6110 if (edgeMap.found(meIndex))
6112 edgeMap[meIndex] = seIndex;
6116 edgeMap.insert(meIndex, seIndex);
6130 + Foam::name(meIndex),
6134 Pout<< " Failed to match edge: "
6135 << meIndex << " :: " << edges_[meIndex]
6136 << " using comparison edge: " << cE
6137 << abort(FatalError);
6142 if (procCouple && !localCouple)
6144 // Update point mapping
6145 forAll(procIndices_, pI)
6147 const coupleMap& cMap = recvMeshes_[pI].map();
6149 // Obtain references
6150 Map<label>& pointMap = cMap.entityMap(coupleMap::POINT);
6151 Map<label>& rPointMap = cMap.reverseEntityMap(coupleMap::POINT);
6153 const changeMap* slaveMapPtr = NULL;
6154 const label pointEnum = coupleMap::POINT;
6156 forAll(slaveMaps, slaveI)
6158 const changeMap& slaveMap = slaveMaps[slaveI];
6160 if (slaveMap.patchIndex() == pI)
6162 if (slaveMap.index() < 0)
6167 if (collapsingSlave)
6169 sI = cMap.findMaster(pointEnum, collapsePoint);
6173 if (rPointMap.found(replacePoint))
6175 rPointMap[replacePoint] = sI;
6179 rPointMap.insert(replacePoint, sI);
6182 pointMap[sI] = replacePoint;
6187 sI = cMap.findSlave(pointEnum, collapsePoint);
6191 if (pointMap.found(replacePoint))
6193 pointMap[replacePoint] = sI;
6197 pointMap.insert(replacePoint, sI);
6200 rPointMap[sI] = replacePoint;
6204 if (sI > -1 && debug > 2)
6206 Pout<< " Found point: " << collapsePoint
6207 << " on proc: " << procIndices_[pI]
6213 // Edge-coupling. Fetch address for later.
6214 slaveMapPtr = &slaveMap;
6222 // Alias for convenience...
6223 const changeMap& slaveMap = *slaveMapPtr;
6225 const labelList& rpList = slaveMap.removedPointList();
6226 const List<objectMap>& apList = slaveMap.addedPointList();
6228 // Configure the slave replacement point.
6229 // - collapseEdge stores this as an 'addedPoint'
6230 label scPoint = rpList[0];
6231 label srPoint = apList[0].index();
6233 if (collapsingSlave)
6235 if (rPointMap[replacePoint] == scPoint)
6237 pointMap[srPoint] = replacePoint;
6238 rPointMap[replacePoint] = srPoint;
6241 pointMap.erase(rPointMap[collapsePoint]);
6242 rPointMap.erase(collapsePoint);
6246 if (pointMap[replacePoint] == scPoint)
6248 rPointMap[srPoint] = replacePoint;
6249 pointMap[replacePoint] = srPoint;
6252 rPointMap.erase(pointMap[collapsePoint]);
6253 pointMap.erase(collapsePoint);
6256 // If any other points were removed, update map
6257 for (label pointI = 1; pointI < rpList.size(); pointI++)
6259 if (collapsingSlave)
6261 if (pointMap.found(rpList[pointI]))
6263 rPointMap.erase(pointMap[rpList[pointI]]);
6264 pointMap.erase(rpList[pointI]);
6269 if (rPointMap.found(rpList[pointI]))
6273 Pout<< " Found removed point: "
6275 << " on proc: " << procIndices_[pI]
6276 << " for point on this proc: "
6277 << rPointMap[rpList[pointI]]
6281 pointMap.erase(rPointMap[rpList[pointI]]);
6282 rPointMap.erase(rpList[pointI]);
6289 // Update face mapping
6290 forAll(procIndices_, pI)
6292 const coupleMap& cMap = recvMeshes_[pI].map();
6293 const dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
6295 // Obtain point maps
6296 Map<label>& pointMap = cMap.entityMap(coupleMap::POINT);
6299 const label faceEnum = coupleMap::FACE;
6301 // Obtain references
6302 Map<label>& faceMap = cMap.entityMap(faceEnum);
6303 Map<label>& rFaceMap = cMap.reverseEntityMap(faceEnum);
6305 const changeMap* slaveMapPtr = NULL;
6307 forAll(slaveMaps, slaveI)
6309 const changeMap& slaveMap = slaveMaps[slaveI];
6311 if (slaveMap.patchIndex() == pI)
6313 if (slaveMap.index() < 0)
6319 // Edge-coupling. Fetch address for later.
6320 slaveMapPtr = &slaveMap;
6325 forAll(checkFaces, faceI)
6327 label mfIndex = checkFaces[faceI];
6329 const face& mF = faces_[mfIndex];
6331 // Skip checks if a conversion occurred,
6332 // and this face was removed as a result
6338 label mfPatch = whichPatch(mfIndex);
6339 label neiProc = getNeighbourProcessor(mfPatch);
6343 pointMap.found(mF[0]) ? pointMap[mF[0]] : -1,
6344 pointMap.found(mF[1]) ? pointMap[mF[1]] : -1,
6345 pointMap.found(mF[2]) ? pointMap[mF[2]] : -1
6348 // Check if a patch conversion is necessary
6349 label newPatch = -1;
6350 bool requireConversion = false, physConvert = false;
6352 // Skip mapping if all points were not found
6353 if (cF[0] == -1 || cF[1] == -1 || cF[2] == -1)
6355 // Is this actually a non-processor patch?
6366 // Has this face been converted to a physical boundary?
6367 if (faceMap.found(mfIndex) && slaveMapPtr)
6369 // Alias for convenience...
6370 const changeMap& sMap = *slaveMapPtr;
6371 const labelList& rfList = sMap.removedFaceList();
6372 const List<objectMap>& afList = sMap.addedFaceList();
6374 // Was the face removed by the slave?
6375 label sfIndex = faceMap[mfIndex];
6377 if (findIndex(rfList, sfIndex) > -1)
6381 Pout<< " Found removed face: " << sfIndex
6382 << " with mfIndex: " << mfIndex
6383 << " :: " << faces_[mfIndex]
6384 << " on proc: " << procIndices_[pI]
6389 rFaceMap.erase(sfIndex);
6390 faceMap.erase(mfIndex);
6393 // Check added faces for special entries
6394 forAll(afList, indexI)
6396 const objectMap& af = afList[indexI];
6400 af.masterObjects().size() ?
6401 af.masterObjects()[0] : 0
6404 // Back out the physical patch ID
6405 if ((af.index() == sfIndex) && (mo < 0))
6407 newPatch = Foam::mag(mo + 2);
6408 requireConversion = true;
6414 // Was an appropriate physical patch found?
6415 if (physConvert && !requireConversion)
6420 // Are we talking to a different processor?
6421 if (neiProc != procIndices_[pI])
6423 // This face needs to be converted
6424 const polyBoundaryMesh& boundary = boundaryMesh();
6426 forAll(boundary, pi)
6428 if (getNeighbourProcessor(pi) == procIndices_[pI])
6431 requireConversion = true;
6437 if (requireConversion)
6439 // Obtain a copy before adding the new face,
6440 // since the reference might become
6441 // invalid during list resizing.
6442 face newFace = faces_[mfIndex];
6443 label newOwn = owner_[mfIndex];
6444 labelList newFaceEdges = faceEdges_[mfIndex];
6446 label newFaceIndex =
6457 faceEdges_.append(newFaceEdges);
6459 meshOps::replaceLabel
6466 // Correct edgeFaces with the new face label.
6467 forAll(newFaceEdges, edgeI)
6469 meshOps::replaceLabel
6473 edgeFaces_[newFaceEdges[edgeI]]
6477 // Finally remove the face
6478 removeFace(mfIndex);
6481 map.removeFace(mfIndex);
6482 map.addFace(newFaceIndex, labelList(1, mfIndex));
6484 // Replace index and patch
6485 mfIndex = newFaceIndex;
6488 // If conversion was to a physical patch,
6489 // skip the remaining face mapping steps
6490 if (getNeighbourProcessor(newPatch) == -1)
6496 Pout<< " Conversion required... "
6497 << " Face: " << newFace << " : "
6498 << newFace.centre(points_)
6499 << abort(FatalError);
6501 // Push a patch-conversion operation
6505 coupleMap::CONVERT_PATCH,
6506 newFace.centre(points_),
6507 newFace.centre(oldPoints_)
6511 bool matchedFace = false;
6513 // Fetch edges connected to first slave point
6514 const labelList& spEdges = sMesh.pointEdges_[cF[0]];
6516 forAll(spEdges, edgeJ)
6518 label seIndex = spEdges[edgeJ];
6520 if (sMesh.whichEdgePatch(seIndex) == -1)
6525 const labelList& seFaces = sMesh.edgeFaces_[seIndex];
6527 forAll(seFaces, faceI)
6529 label sfIndex = seFaces[faceI];
6531 if (sMesh.whichPatch(sfIndex) == -1)
6536 const face& sF = sMesh.faces_[sfIndex];
6542 triFace(sF[0], sF[1], sF[2]), cF
6548 word pN(boundaryMesh()[mfPatch].name());
6550 Pout<< " Found face: " << sfIndex
6552 << " with mfIndex: " << mfIndex
6553 << " :: " << faces_[mfIndex]
6554 << " on proc: " << procIndices_[pI]
6559 if (rFaceMap.found(sfIndex))
6561 rFaceMap[sfIndex] = mfIndex;
6565 rFaceMap.insert(sfIndex, mfIndex);
6568 if (faceMap.found(mfIndex))
6570 faceMap[mfIndex] = sfIndex;
6574 faceMap.insert(mfIndex, sfIndex);
6594 + Foam::name(mfIndex),
6598 Pout<< " Failed to match face: "
6599 << mfIndex << " :: " << faces_[mfIndex]
6600 << " using comparison face: " << cF
6601 << " on proc: " << procIndices_[pI]
6602 << abort(FatalError);
6607 // Update edge mapping
6608 forAll(procIndices_, pI)
6610 const coupleMap& cMap = recvMeshes_[pI].map();
6611 const dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
6613 // Obtain point maps
6614 Map<label>& pointMap = cMap.entityMap(coupleMap::POINT);
6617 const label edgeEnum = coupleMap::EDGE;
6619 // Obtain references
6620 Map<label>& edgeMap = cMap.entityMap(edgeEnum);
6621 Map<label>& rEdgeMap = cMap.reverseEntityMap(edgeEnum);
6623 const changeMap* slaveMapPtr = NULL;
6625 forAll(slaveMaps, slaveI)
6627 const changeMap& slaveMap = slaveMaps[slaveI];
6629 if (slaveMap.patchIndex() == pI)
6631 if (slaveMap.index() < 0)
6637 // Edge-coupling. Fetch address for later.
6638 slaveMapPtr = &slaveMap;
6643 forAll(checkEdges, edgeI)
6645 label meIndex = checkEdges[edgeI];
6647 const edge& mE = edges_[meIndex];
6649 // Skip checks if a conversion occurred,
6650 // and this edge was removed as a result
6651 if (edgeFaces_[meIndex].empty())
6656 label mePatch = whichEdgePatch(meIndex);
6657 label neiProc = getNeighbourProcessor(mePatch);
6661 pointMap.found(mE[0]) ? pointMap[mE[0]] : -1,
6662 pointMap.found(mE[1]) ? pointMap[mE[1]] : -1
6665 // Check if a patch conversion is necessary
6666 label newPatch = -1;
6667 bool requireConversion = true, physConvert = false;
6669 // Skip mapping if all points were not found
6670 if (cE[0] == -1 || cE[1] == -1)
6672 // Is this actually a non-processor patch?
6683 // Has this edge been converted to a physical boundary?
6684 const labelList& meFaces = edgeFaces_[meIndex];
6686 forAll(meFaces, faceI)
6688 label mfPatch = whichPatch(meFaces[faceI]);
6695 if (getNeighbourProcessor(mfPatch) == -1)
6697 // Store physical patch for conversion
6702 requireConversion = false;
6706 // Was an appropriate physical patch found?
6707 if (physConvert && !requireConversion)
6712 if (requireConversion)
6714 edge newEdge = edges_[meIndex];
6715 labelList newEdgeFaces = edgeFaces_[meIndex];
6717 // Insert the new edge
6718 label newEdgeIndex =
6728 // Replace faceEdges for all
6730 forAll(newEdgeFaces, faceI)
6732 meshOps::replaceLabel
6736 faceEdges_[newEdgeFaces[faceI]]
6741 removeEdge(meIndex);
6744 map.removeEdge(meIndex);
6745 map.addEdge(newEdgeIndex, labelList(1, meIndex));
6747 // Replace index and patch
6748 meIndex = newEdgeIndex;
6751 // If conversion was to a physical patch,
6752 // skip the remaining face mapping steps
6753 if (getNeighbourProcessor(newPatch) == -1)
6759 bool matchedEdge = false;
6761 // Fetch edges connected to first slave point
6762 const labelList& spEdges = sMesh.pointEdges_[cE[0]];
6764 forAll(spEdges, edgeJ)
6766 label seIndex = spEdges[edgeJ];
6768 const edge& sE = sMesh.edges_[seIndex];
6774 Pout<< " Found edge: " << seIndex
6776 << " with meIndex: " << meIndex
6777 << " :: " << edges_[meIndex]
6778 << " on proc: " << procIndices_[pI]
6782 // Update reverse map
6783 if (rEdgeMap.found(seIndex))
6785 rEdgeMap[seIndex] = meIndex;
6789 rEdgeMap.insert(seIndex, meIndex);
6793 if (edgeMap.found(meIndex))
6795 edgeMap[meIndex] = seIndex;
6799 edgeMap.insert(meIndex, seIndex);
6810 // Check if a coupling existed before
6811 if (edgeMap.found(meIndex) && slaveMapPtr)
6813 // Alias for convenience...
6814 const changeMap& sMap = *slaveMapPtr;
6815 const labelList& reList = sMap.removedEdgeList();
6817 // Was the edge removed by the slave?
6818 if (findIndex(reList, edgeMap[meIndex]) > -1)
6822 Pout<< " Found removed edge: "
6824 << " with meIndex: " << meIndex
6825 << " :: " << edges_[meIndex]
6826 << " on proc: " << procIndices_[pI]
6831 rEdgeMap.erase(edgeMap[meIndex]);
6832 edgeMap.erase(meIndex);
6844 + Foam::name(meIndex),
6848 Pout<< " Failed to match edge: "
6849 << meIndex << " :: " << edges_[meIndex]
6850 << " using comparison edge: " << cE
6851 << " on proc: " << procIndices_[pI]
6852 << abort(FatalError);
6860 topoChangeFlag_ = true;
6862 // Increment the counter
6865 // Increment the number of modifications
6868 // Return a succesful collapse
6869 map.type() = collapseCase;
6875 // Remove cell layer above specified patch
6876 const changeMap dynamicTopoFvMesh::removeCellLayer
6883 labelHashSet edgesToRemove, facesToRemove;
6884 Map<labelPair> pointsToRemove, edgesToKeep;
6886 DynamicList<label> patchFaces(patchSizes_[patchID]);
6887 DynamicList<labelPair> cellsToRemove(patchSizes_[patchID]);
6888 DynamicList<labelPair> hFacesToRemove(patchSizes_[patchID]);
6890 for (label faceI = nOldInternalFaces_; faceI < faces_.size(); faceI++)
6892 label pIndex = whichPatch(faceI);
6894 if (pIndex != patchID)
6900 label cIndex = owner_[faceI];
6902 // Add face to the list
6903 patchFaces.append(faceI);
6905 // Fetch appropriate face / cell
6906 const face& bFace = faces_[faceI];
6907 const cell& ownCell = cells_[cIndex];
6909 // Get the opposing face from the cell
6910 oppositeFace oFace = ownCell.opposingFace(faceI, faces_);
6914 // Something's wrong here.
6917 "const changeMap dynamicTopoFvMesh::removeCellLayer"
6918 "(const label patchID)"
6920 << " Face: " << faceI << " :: " << bFace << nl
6921 << " has no opposing face in cell: "
6922 << cIndex << " :: " << ownCell << nl
6923 << abort(FatalError);
6926 // Fetch cell on the other-side of the opposite face
6927 label otherCellIndex =
6929 (owner_[oFace.oppositeIndex()] == cIndex) ?
6930 neighbour_[oFace.oppositeIndex()] :
6931 owner_[oFace.oppositeIndex()]
6934 if (otherCellIndex == -1)
6936 // Opposite face is on a boundary, and layer
6937 // removal would be invalid if we continued.
6943 // Fetch reference to other cell
6944 const cell& otherCell = cells_[otherCellIndex];
6946 // Find opposite face on the other cell
6947 oppositeFace otFace =
6949 otherCell.opposingFace
6951 oFace.oppositeIndex(),
6956 if (!otFace.found())
6958 // Something's wrong here.
6961 "const changeMap dynamicTopoFvMesh::removeCellLayer"
6962 "(const label patchID)"
6964 << " Face: " << oFace.oppositeIndex()
6965 << " :: " << oFace << nl
6966 << " has no opposing face in cell: "
6967 << otherCellIndex << " :: " << otherCell << nl
6968 << abort(FatalError);
6971 // All edges on the boundary face are to be retained
6972 const labelList& fEdges = faceEdges_[faceI];
6973 const labelList& ofEdges = faceEdges_[oFace.oppositeIndex()];
6974 const labelList& otfEdges = faceEdges_[otFace.oppositeIndex()];
6976 forAll(fEdges, edgeI)
6978 label eIndex = fEdges[edgeI];
6980 if (!edgesToKeep.found(eIndex))
6982 // Find equivalent edge on opposite face
6983 label oeIndex = -1, oteIndex = -1;
6984 const edge& bEdge = edges_[eIndex];
6986 // Build edges for comparison
6987 label startLoc = bFace.which(bEdge[0]);
6988 label endLoc = bFace.which(bEdge[1]);
6990 edge cEdge(oFace[startLoc], oFace[endLoc]);
6991 edge ctEdge(otFace[startLoc], otFace[endLoc]);
6993 forAll(ofEdges, edgeJ)
6995 const edge& ofEdge = edges_[ofEdges[edgeJ]];
6997 if (cEdge == ofEdge)
6999 oeIndex = ofEdges[edgeJ];
7004 forAll(otfEdges, edgeJ)
7006 const edge& otfEdge = edges_[otfEdges[edgeJ]];
7008 if (ctEdge == otfEdge)
7010 oteIndex = otfEdges[edgeJ];
7015 if (oeIndex < 0 || oteIndex < 0)
7019 "const changeMap dynamicTopoFvMesh::removeCellLayer"
7020 "(const label patchID)"
7022 << " Could not find comparison edge: " << nl
7023 << " cEdge: " << cEdge
7024 << " oeIndex: " << oeIndex << nl
7025 << " ctEdge: " << ctEdge
7026 << " oteIndex: " << oteIndex << nl
7027 << " for edge: " << bEdge
7028 << abort(FatalError);
7032 edgesToKeep.insert(eIndex, labelPair(oeIndex, oteIndex));
7036 // Add information to removal lists
7037 cellsToRemove.append
7046 hFacesToRemove.append
7050 oFace.oppositeIndex(),
7051 otFace.oppositeIndex()
7055 // Mark points for removal
7056 forAll(oFace, pointI)
7058 label pIndex = oFace[pointI];
7060 if (!pointsToRemove.found(pIndex))
7063 pointsToRemove.insert
7066 labelPair(bFace[pointI], otFace[pointI])
7071 // Loop through cell faces and mark
7072 // faces / edges for removal
7073 forAll(ownCell, faceJ)
7075 label fIndex = ownCell[faceJ];
7077 if (fIndex == faceI || fIndex == oFace.oppositeIndex())
7082 if (!facesToRemove.found(fIndex))
7084 facesToRemove.insert(fIndex);
7087 const labelList& checkEdges = faceEdges_[fIndex];
7089 forAll(checkEdges, edgeI)
7091 label eIndex = checkEdges[edgeI];
7093 if (edgesToKeep.found(eIndex))
7098 if (!edgesToRemove.found(eIndex))
7100 edgesToRemove.insert(eIndex);
7106 // Correct edgeFaces / faceEdges for retained edges
7107 forAllConstIter(Map<labelPair>, edgesToKeep, eIter)
7109 const labelList& rmeFaces = edgeFaces_[eIter().first()];
7111 forAll(rmeFaces, faceI)
7113 labelList& fE = faceEdges_[rmeFaces[faceI]];
7115 bool foundRp = (findIndex(fE, eIter.key()) > -1);
7116 bool foundRn = (findIndex(fE, eIter().second()) > -1);
7120 // Size-down edgeFaces for replacement
7121 meshOps::sizeDownList
7124 edgeFaces_[eIter.key()]
7130 // Size-up edgeFaces for replacement
7134 edgeFaces_[eIter.key()]
7137 // Replace edge index
7138 meshOps::replaceLabel
7148 // Remove unwanted faces
7149 forAllConstIter(labelHashSet, facesToRemove, fIter)
7152 removeFace(fIter.key());
7155 map.removeFace(fIter.key());
7158 // Remove unwanted edges
7159 forAllConstIter(labelHashSet, edgesToRemove, eIter)
7162 removeEdge(eIter.key());
7165 map.removeEdge(eIter.key());
7168 // Remove unwanted points
7169 forAllConstIter(Map<labelPair>, pointsToRemove, pIter)
7171 // Update pointEdges information first
7174 const labelList& pEdges = pointEdges_[pIter.key()];
7176 // Configure edge for comparison
7183 label replaceEdge = -1;
7185 forAll(pEdges, edgeI)
7187 const edge& checkEdge = edges_[pEdges[edgeI]];
7189 if (checkEdge == cEdge)
7191 replaceEdge = pEdges[edgeI];
7196 if (replaceEdge == -1)
7200 "const changeMap dynamicTopoFvMesh::removeCellLayer"
7201 "(const label patchID)"
7203 << " Could not find comparison edge: " << nl
7204 << " cEdge: " << cEdge
7205 << " for point: " << pIter.key() << nl
7206 << " pointEdges: " << pEdges
7207 << abort(FatalError);
7210 // Size-up pointEdges
7214 pointEdges_[pIter().first()]
7219 removePoint(pIter.key());
7222 map.removePoint(pIter.key());
7225 // Track modified faces for mapping
7226 labelHashSet modifiedFaces;
7229 forAll(cellsToRemove, indexI)
7231 // Replace face label on the other cell
7232 meshOps::replaceLabel
7234 hFacesToRemove[indexI].first(),
7236 cells_[cellsToRemove[indexI].second()]
7239 // Set owner information
7240 owner_[patchFaces[indexI]] = cellsToRemove[indexI].second();
7242 // Replace points on faces / edges
7243 const cell& otherCell = cells_[cellsToRemove[indexI].second()];
7245 forAll(otherCell, faceI)
7247 face& faceToCheck = faces_[otherCell[faceI]];
7249 bool modified = false;
7251 forAll(faceToCheck, pointI)
7253 if (pointsToRemove.found(faceToCheck[pointI]))
7255 faceToCheck[pointI] =
7257 pointsToRemove[faceToCheck[pointI]].first()
7265 if (modified && !modifiedFaces.found(otherCell[faceI]))
7267 modifiedFaces.insert(otherCell[faceI]);
7270 const labelList& fEdges = faceEdges_[otherCell[faceI]];
7272 forAll(fEdges, edgeI)
7274 edge& edgeToCheck = edges_[fEdges[edgeI]];
7276 if (pointsToRemove.found(edgeToCheck[0]))
7280 pointsToRemove[edgeToCheck[0]].first()
7284 if (pointsToRemove.found(edgeToCheck[1]))
7288 pointsToRemove[edgeToCheck[1]].first()
7294 // Remove horizontal interior face
7295 removeFace(hFacesToRemove[indexI].first());
7298 map.removeFace(hFacesToRemove[indexI].first());
7301 removeCell(cellsToRemove[indexI].first());
7304 map.removeCell(cellsToRemove[indexI].first());
7307 // Now that all old / new cells possess correct connectivity,
7308 // compute mapping information.
7309 forAll(cellsToRemove, indexI)
7311 // Set mapping for the modified cell
7314 cellsToRemove[indexI].second(),
7315 cellsToRemove[indexI]
7319 // Set face mapping information for modified faces
7320 forAllConstIter(labelHashSet, modifiedFaces, fIter)
7322 // Decide between default / weighted mapping
7323 // based on boundary information
7324 label fPatch = whichPatch(fIter.key());
7328 // Default mapping for interior faces
7329 setFaceMapping(fIter.key());
7333 // Map boundary face from itself
7334 setFaceMapping(fIter.key(), labelList(1, fIter.key()));
7339 topoChangeFlag_ = true;
7341 // Specify that the operation was successful
7344 // Return the changeMap
7349 // Merge a set of boundary faces into internal
7350 const changeMap dynamicTopoFvMesh::mergeBoundaryFaces
7352 const labelList& mergeFaces
7359 Pout << "Merging faces: " << mergeFaces << endl;
7362 List<labelPair> mergePairs(0);
7364 forAll(mergeFaces, faceI)
7366 const face& fI = faces_[mergeFaces[faceI]];
7368 for (label faceJ = faceI + 1; faceJ < mergeFaces.size(); faceJ++)
7370 const face& fJ = faces_[mergeFaces[faceJ]];
7374 if (fI.size() == fJ.size() && fI.size() == 3)
7380 triFace(fI[0], fI[1], fI[2]),
7381 triFace(fJ[0], fJ[1], fJ[2])
7389 if (face::compare(fI, fJ))
7398 labelPair(mergeFaces[faceI], mergeFaces[faceJ]),
7409 Pout<< " mergePairs: " << mergePairs << endl;
7412 DynamicList<label> checkEdges(10);
7414 forAll(mergePairs, pairI)
7416 label firstFace = mergePairs[pairI].first();
7417 label secondFace = mergePairs[pairI].second();
7419 // Obtain owners for both faces, and compare their labels
7420 label newOwner = -1, newNeighbour = -1;
7421 label removedFace = -1, retainedFace = -1;
7423 if (owner_[firstFace] < owner_[secondFace])
7425 // Retain the first face
7426 removedFace = secondFace;
7427 retainedFace = firstFace;
7429 newOwner = owner_[firstFace];
7430 newNeighbour = owner_[secondFace];
7434 // Retain the second face
7435 removedFace = firstFace;
7436 retainedFace = secondFace;
7438 newOwner = owner_[secondFace];
7439 newNeighbour = owner_[firstFace];
7442 // Insert a new interior face
7443 label newFaceIndex =
7448 face(faces_[retainedFace]),
7454 // Add the faceEdges entry
7455 faceEdges_.append(labelList(faceEdges_[retainedFace]));
7458 map.addFace(newFaceIndex);
7460 // Replace cell with the new face label
7461 meshOps::replaceLabel
7465 cells_[owner_[removedFace]]
7468 meshOps::replaceLabel
7472 cells_[owner_[retainedFace]]
7475 const labelList& fEdges = faceEdges_[newFaceIndex];
7476 const labelList& rfEdges = faceEdges_[removedFace];
7478 // Check for common edges on the removed face
7479 forAll(rfEdges, edgeI)
7481 label reIndex = rfEdges[edgeI];
7483 if (findIndex(fEdges, reIndex) == -1)
7485 // Find the equivalent edge
7486 const edge& rEdge = edges_[reIndex];
7487 const labelList& reFaces = edgeFaces_[reIndex];
7491 forAll(fEdges, edgeJ)
7493 if (edges_[fEdges[edgeJ]] == rEdge)
7495 keIndex = fEdges[edgeJ];
7502 Pout<< " Could not find edge for: "
7503 << reIndex << " :: " << rEdge
7504 << abort(FatalError);
7507 // Add edgeFaces from this edge
7508 forAll(reFaces, faceI)
7510 if (reFaces[faceI] == removedFace)
7521 meshOps::replaceLabel
7525 faceEdges_[reFaces[faceI]]
7529 // Remove the old edge
7530 removeEdge(reIndex);
7533 map.removeEdge(reIndex);
7537 // Replace edgeFaces with the new face label
7538 forAll(fEdges, edgeI)
7540 label eIndex = fEdges[edgeI];
7542 if (findIndex(edgeFaces_[eIndex], removedFace) > -1)
7544 meshOps::sizeDownList
7551 if (findIndex(edgeFaces_[eIndex], retainedFace) > -1)
7553 meshOps::sizeDownList
7560 // Size-up list with the new face index
7567 if (findIndex(checkEdges, eIndex) == -1)
7569 checkEdges.append(eIndex);
7573 // Remove the boundary faces
7574 removeFace(removedFace);
7575 removeFace(retainedFace);
7578 map.removeFace(removedFace);
7579 map.removeFace(retainedFace);
7582 forAll(checkEdges, edgeI)
7584 bool allInterior = true;
7585 label eIndex = checkEdges[edgeI];
7587 const labelList& eFaces = edgeFaces_[eIndex];
7589 forAll(eFaces, faceI)
7591 if (whichPatch(eFaces[faceI]) > -1)
7593 allInterior = false;
7600 // This edge needs to be converted to an interior one
7601 label newEdgeIndex =
7606 edge(edges_[eIndex]),
7607 labelList(edgeFaces_[eIndex])
7612 map.addEdge(newEdgeIndex, labelList(1, eIndex));
7614 // Update faceEdges information for all connected faces
7615 const labelList& neFaces = edgeFaces_[newEdgeIndex];
7617 forAll(neFaces, faceI)
7619 meshOps::replaceLabel
7623 faceEdges_[neFaces[faceI]]
7627 // Remove the old boundary edge
7631 map.removeEdge(eIndex);
7634 checkEdges[edgeI] = newEdgeIndex;
7640 Pout<< "Merge complete." << nl << endl;
7643 // Return a succesful merge
7650 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
7652 } // End namespace Foam
7654 // ************************************************************************* //