1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
28 #include "objectMap.H"
29 #include "changeMap.H"
30 #include "coupledInfo.H"
31 #include "multiThreader.H"
32 #include "dynamicTopoFvMesh.H"
34 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
41 // Method for the bisection of a quad-face in 2D
42 // - Returns a changeMap with a type specifying:
43 // 1: Bisection was successful
44 // -1: Bisection failed since max number of topo-changes was reached.
45 // -2: Bisection failed since resulting quality would be unacceptable.
46 // -3: Bisection failed since edge was on a noRefinement patch.
47 const changeMap dynamicTopoFvMesh::bisectQuadFace
50 const changeMap& masterMap,
55 // Quad-face bisection performs the following operations:
56 // [1] Add two points at the middle of the face
57 // [2] Create a new internal face for each bisected cell
58 // [3] Modify existing face and create a new half-face
59 // [4] Modify triangular boundary faces, and create new ones as well
60 // [5] Create edges for new faces
61 // Update faceEdges and edgeFaces information
63 // Figure out which thread this is...
64 label tIndex = self();
66 // Prepare the changeMaps
68 List<changeMap> slaveMaps;
69 bool bisectingSlave = false;
73 (status(TOTAL_MODIFICATIONS) > maxModifications_) &&
74 (maxModifications_ > -1)
77 // Reached the max allowable topo-changes.
78 stack(tIndex).clear();
83 // Check if edgeRefinements are to be avoided on patch.
84 if (baseMesh_.lengthEstimator().checkRefinementPatch(whichPatch(fIndex)))
91 // Sanity check: Is the index legitimate?
97 "const changeMap dynamicTopoFvMesh::bisectQuadFace\n"
99 " const label fIndex,\n"
100 " const changeMap& masterMap,\n"
105 << " Invalid index: " << fIndex << nl
106 << " nFaces: " << nFaces_
107 << abort(FatalError);
111 label replaceFace = -1, retainFace = -1;
112 face tmpQuadFace(4), tmpTriFace(3);
113 labelList tmpQFEdges(4, -1), tmpTFEdges(3, -1);
114 FixedList<label,7> newFaceIndex(-1), newEdgeIndex(-1);
115 FixedList<edge,4> commonEdges(edge(-1, -1));
116 FixedList<label,4> cornerEdgeIndex(-1), commonEdgeIndex(-1);
117 FixedList<label,4> commonFaceIndex(-1);
118 FixedList<label,2> newPointIndex(-1), newCellIndex(-1);
119 FixedList<label,4> otherEdgeIndex(-1), otherEdgePoint(-1);
120 FixedList<label,4> otherPointIndex(-1), nextToOtherPoint(-1);
121 FixedList<label,2> c0BdyIndex(-1), c0IntIndex(-1);
122 FixedList<label,2> c1BdyIndex(-1), c1IntIndex(-1);
123 FixedList<face,2> c0BdyFace(face(3)), c0IntFace(face(4));
124 FixedList<face,2> c1BdyFace(face(3)), c1IntFace(face(4));
126 // Get the two cells on either side...
127 label c0 = owner_[fIndex], c1 = neighbour_[fIndex];
129 // Keep track of old / new cells
130 FixedList<cell, 2> oldCells(cell(5));
131 FixedList<cell, 2> newCells(cell(5));
133 // Find the prism faces for cell[0].
134 oldCells[0] = cells_[c0];
136 meshOps::findPrismFaces
149 // Check for resulting quality
150 if (checkBisection(fIndex, c0BdyIndex[0], forceOp))
158 // Find the prism faces for cell[1].
159 meshOps::findPrismFaces
172 // Check for resulting quality
173 if (checkBisection(fIndex, c1BdyIndex[0], forceOp))
180 // Find the common-edge between the triangular boundary faces
181 // and the face under consideration.
182 meshOps::findCommonEdge
190 meshOps::findCommonEdge
198 commonEdges[0] = edges_[commonEdgeIndex[0]];
199 commonEdges[1] = edges_[commonEdgeIndex[1]];
201 // If coupled modification is set, and this is a
202 // master edge, bisect its slaves as well.
203 bool localCouple = false, procCouple = false;
205 if (coupledModification_)
207 const label faceEnum = coupleMap::FACE;
208 const label pointEnum = coupleMap::POINT;
210 // Is this a locally coupled face (either master or slave)?
211 if (locallyCoupledEntity(fIndex, true))
217 if (processorCoupledEntity(fIndex))
223 if (localCouple && !procCouple)
225 // Determine the slave index.
226 label sIndex = -1, pIndex = -1;
228 forAll(patchCoupling_, patchI)
230 if (patchCoupling_(patchI))
232 const coupleMap& cMap = patchCoupling_[patchI].map();
234 if ((sIndex = cMap.findSlave(faceEnum, fIndex)) > -1)
241 // The following bit happens only during the sliver
242 // exudation process, since slave faces are
243 // usually not added to the coupled face-stack.
244 if ((sIndex = cMap.findMaster(faceEnum, fIndex)) > -1)
248 // Notice that we are collapsing a slave face first.
249 bisectingSlave = true;
261 "const changeMap dynamicTopoFvMesh::bisectQuadFace\n"
263 " const label fIndex,\n"
264 " const changeMap& masterMap,\n"
269 << "Coupled maps were improperly specified." << nl
270 << " Slave index not found for: " << nl
271 << " Face: " << fIndex << ": " << faces_[fIndex] << nl
272 << abort(FatalError);
276 // If we've found the slave, size up the list
283 // Save index and patch for posterity
284 slaveMaps[0].index() = sIndex;
285 slaveMaps[0].patchIndex() = pIndex;
290 Pout<< nl << " >> Bisecting slave face: " << sIndex
291 << " for master face: " << fIndex << endl;
295 if (procCouple && !localCouple)
297 // If this is a new entity, bail out for now.
298 // This will be handled at the next time-step.
299 if (fIndex >= nOldFaces_)
305 forAll(procIndices_, pI)
307 // Fetch reference to subMesh
308 const coupledMesh& recvMesh = recvMeshes_[pI];
309 const coupleMap& cMap = recvMesh.map();
313 if ((sIndex = cMap.findSlave(faceEnum, fIndex)) > -1)
317 Pout<< "Checking slave face: " << sIndex
318 << " on proc: " << procIndices_[pI]
319 << " for master face: " << fIndex
323 // Check if a lower-ranked processor is
324 // handling this edge
337 Pout<< "Face: " << fIndex
338 << " is handled by proc: "
340 << ", so bailing out."
347 label curIndex = slaveMaps.size();
356 // Save index and patch for posterity
357 slaveMaps[curIndex].index() = sIndex;
358 slaveMaps[curIndex].patchIndex() = pI;
360 // Only one slave coupling is possible, so bail out
367 // Something's wrong with coupling maps
371 "const changeMap dynamicTopoFvMesh::bisectQuadFace\n"
373 " const label fIndex,\n"
374 " const changeMap& masterMap,\n"
379 << "Coupled maps were improperly specified." << nl
380 << " localCouple: " << localCouple << nl
381 << " procCouple: " << procCouple << nl
382 << " Face: " << fIndex << ": " << faces_[fIndex] << nl
383 << abort(FatalError);
386 // Alias for convenience...
387 changeMap& slaveMap = slaveMaps[0];
389 label sIndex = slaveMap.index();
390 label pI = slaveMap.patchIndex();
391 const coupleMap* cMapPtr = NULL;
393 // Temporarily turn off coupledModification
394 unsetCoupledModification();
398 cMapPtr = &(patchCoupling_[pI].map());
400 // First check the slave for bisection feasibility.
401 slaveMap = bisectQuadFace(sIndex, changeMap(), true, forceOp);
406 cMapPtr = &(recvMeshes_[pI].map());
408 coupledMesh& recvMesh = recvMeshes_[pI];
410 // First check the slave for bisection feasibility.
413 recvMesh.subMesh().bisectQuadFace
424 setCoupledModification();
426 if (slaveMap.type() <= 0)
428 // Slave couldn't perform bisection.
434 // Save index and patch for posterity
435 slaveMap.index() = sIndex;
436 slaveMap.patchIndex() = pI;
438 // Alias for convenience..
439 const coupleMap& cMap = *cMapPtr;
441 // Temporarily turn off coupledModification
442 unsetCoupledModification();
444 // First check the master for bisection feasibility.
445 changeMap masterMap = bisectQuadFace(fIndex, changeMap(), true);
448 setCoupledModification();
450 // Master couldn't perform bisection
451 if (masterMap.type() <= 0)
456 // Fill the masterMap with points that
457 // we seek maps for...
458 FixedList<labelList, 2> slaveEdges(labelList(2, -1));
460 forAll(slaveEdges, edgeI)
462 labelList& slaveEdge = slaveEdges[edgeI];
464 // Renumber to slave indices
465 forAll(slaveEdge, pointI)
472 commonEdges[edgeI][pointI]
477 masterMap.addPoint(-1, slaveEdge);
480 // Temporarily turn off coupledModification
481 unsetCoupledModification();
485 // Bisect the local slave.
486 slaveMap = bisectQuadFace(sIndex, masterMap, false, forceOp);
490 coupledMesh& recvMesh = recvMeshes_[pI];
492 // Bisect the slave face
495 recvMesh.subMesh().bisectQuadFace
505 // Turn coupledModification back on.
506 setCoupledModification();
508 // The final operation has to succeed.
509 if (slaveMap.type() <= 0)
514 "const changeMap dynamicTopoFvMesh::bisectQuadFace\n"
516 " const label fIndex,\n"
517 " const changeMap& masterMap,\n"
522 << "Coupled topo-change for slave failed."
523 << " Master face: " << fIndex << nl
524 << " Slave face: " << sIndex << nl
525 << " Patch index: " << pI << nl
526 << " Type: " << slaveMap.type() << nl
527 << abort(FatalError);
530 // Save index and patch for posterity
531 slaveMap.index() = sIndex;
532 slaveMap.patchIndex() = pI;
535 // Are we performing only checks?
545 << "Face: " << fIndex
546 << ": " << faces_[fIndex]
547 << " is to be bisected. " << endl;
551 Pout<< " On SubMesh: " << isSubMesh_ << nl;
552 Pout<< " coupledModification: " << coupledModification_ << nl;
554 const polyBoundaryMesh& boundary = boundaryMesh();
556 label epIndex = whichPatch(fIndex);
562 Pout<< "Internal" << endl;
565 if (epIndex < boundary.size())
567 Pout<< boundary[epIndex].name() << endl;
571 Pout<< " New patch: " << epIndex << endl;
574 Pout<< "Cell[0]: " << c0 << ": " << oldCells[0] << endl;
576 forAll(oldCells[0], faceI)
578 const labelList& fE = faceEdges_[oldCells[0][faceI]];
580 Pout<< oldCells[0][faceI] << ": "
581 << faces_[oldCells[0][faceI]]
587 const labelList& eF = edgeFaces_[fE[edgeI]];
589 Pout<< '\t' << fE[edgeI]
590 << ": " << edges_[fE[edgeI]]
597 // Write out VTK files prior to change
600 labelList cellHull(2, -1);
602 cellHull[0] = owner_[fIndex];
603 cellHull[1] = neighbour_[fIndex];
614 // Find the isolated point on both boundary faces of cell[0]
615 meshOps::findIsolatedPoint
623 meshOps::findIsolatedPoint
631 // For convenience...
632 otherEdgePoint[0] = commonEdges[0].otherVertex(nextToOtherPoint[0]);
633 otherEdgePoint[1] = commonEdges[1].otherVertex(nextToOtherPoint[1]);
637 // Set mapping for this point
638 mP[0] = commonEdges[0][0];
639 mP[1] = commonEdges[0][1];
641 // Add two new points to the end of the list
646 0.5 * (points_[mP[0]] + points_[mP[1]]),
647 0.5 * (oldPoints_[mP[0]] + oldPoints_[mP[1]]),
652 // Set mapping for this point
653 mP[0] = commonEdges[1][0];
654 mP[1] = commonEdges[1][1];
660 0.5 * (points_[mP[0]] + points_[mP[1]]),
661 0.5 * (oldPoints_[mP[0]] + oldPoints_[mP[1]]),
666 // Add the points to the map. Since this might require master mapping,
667 // first check to see if a slave is being bisected.
668 if (masterMap.addedPointList().size())
670 const List<objectMap>& pMap =
672 masterMap.addedPointList()
677 pMap[0].masterObjects()[0],
678 pMap[0].masterObjects()[1]
683 pMap[1].masterObjects()[0],
684 pMap[1].masterObjects()[1]
687 if (firstEdge == commonEdges[0] && secondEdge == commonEdges[1])
689 // Update in conventional order
690 map.addPoint(newPointIndex[0]);
691 map.addPoint(newPointIndex[1]);
694 if (firstEdge == commonEdges[1] && secondEdge == commonEdges[0])
696 // Update in reverse order
697 map.addPoint(newPointIndex[1]);
698 map.addPoint(newPointIndex[0]);
707 "dynamicTopoFvMesh::bisectQuadFace\n"
709 " const label fIndex,\n"
710 " const changeMap& masterMap,\n"
715 << "Coupled topo-change for slave failed."
716 << " firstEdge: " << firstEdge << nl
717 << " secondEdge: " << secondEdge << nl
718 << " commonEdges[0]: " << commonEdges[0] << nl
719 << " commonEdges[1]: " << commonEdges[1] << nl
720 << abort(FatalError);
725 map.addPoint(newPointIndex[0]);
726 map.addPoint(newPointIndex[1]);
729 // Add a new prism cell to the end of the list.
730 // Currently invalid, but will be updated later.
731 newCellIndex[0] = insertCell(newCells[0], lengthScale_[c0]);
733 // Add this cell to the map.
734 map.addCell(newCellIndex[0]);
736 // Modify the two existing triangle boundary faces
738 // Zeroth boundary face - Owner = c[0] & Neighbour [-1] (unchanged)
739 meshOps::replaceLabel
746 // First boundary face - Owner = newCell[0], Neighbour = -1
747 meshOps::replaceLabel
755 faces_[c0BdyIndex[0]] = c0BdyFace[0];
756 faces_[c0BdyIndex[1]] = c0BdyFace[1];
758 owner_[c0BdyIndex[1]] = newCellIndex[0];
760 meshOps::replaceLabel
767 // Detect edges other than commonEdges
768 const labelList& fEdges = faceEdges_[fIndex];
770 forAll(fEdges, edgeI)
774 fEdges[edgeI] != commonEdgeIndex[0] &&
775 fEdges[edgeI] != commonEdgeIndex[1]
778 // Obtain a reference to this edge
779 const edge& eThis = edges_[fEdges[edgeI]];
783 eThis[0] == nextToOtherPoint[0]
784 || eThis[1] == nextToOtherPoint[0]
787 otherEdgeIndex[0] = fEdges[edgeI];
791 otherEdgeIndex[1] = fEdges[edgeI];
796 // Modify point-labels on the quad face under consideration
797 meshOps::replaceLabel
804 meshOps::replaceLabel
811 // Add this face to the map.
812 // Although this face isn't technically 'added', it's
813 // required for coupled patch mapping.
818 Pout<< "Modified face: " << fIndex
819 << ": " << faces_[fIndex] << endl;
823 Pout<< "Common edges: " << nl
824 << commonEdgeIndex[0] << ": " << commonEdges[0] << nl
825 << commonEdgeIndex[1] << ": " << commonEdges[1]
830 // Find the quad face that contains otherEdgeIndex[1]
833 const labelList& e1 = faceEdges_[c0IntIndex[0]];
837 if (e1[edgeI] == otherEdgeIndex[1])
839 meshOps::replaceLabel
846 replaceFace = c0IntIndex[0];
847 retainFace = c0IntIndex[1];
855 // The edge was not found before
856 meshOps::replaceLabel
863 replaceFace = c0IntIndex[1];
864 retainFace = c0IntIndex[0];
867 // Check if face reversal is necessary for the replacement
868 if (owner_[replaceFace] == c0)
870 if (neighbour_[replaceFace] == -1)
873 owner_[replaceFace] = newCellIndex[0];
877 // This face has to be reversed
878 faces_[replaceFace] = faces_[replaceFace].reverseFace();
879 owner_[replaceFace] = neighbour_[replaceFace];
880 neighbour_[replaceFace] = newCellIndex[0];
882 setFlip(replaceFace);
887 // Keep owner, but change neighbour
888 neighbour_[replaceFace] = newCellIndex[0];
891 // Define the faces for the new cell
892 newCells[0][0] = c0BdyIndex[1];
893 newCells[0][1] = replaceFace;
895 // Define the set of new faces and insert...
897 // New interior face; Owner = cell[0] & Neighbour = newCell[0]
898 tmpQuadFace[0] = otherPointIndex[0];
899 tmpQuadFace[1] = newPointIndex[0];
900 tmpQuadFace[2] = newPointIndex[1];
901 tmpQuadFace[3] = otherPointIndex[1];
915 // Add this face to the map.
916 map.addFace(newFaceIndex[0]);
918 // Find the common edge between quad/quad faces...
919 meshOps::findCommonEdge
927 // ... and size-up edgeFaces for the edge
931 edgeFaces_[otherEdgeIndex[2]]
934 meshOps::replaceLabel
941 meshOps::replaceLabel
948 // Second boundary face; Owner = newCell[0] & Neighbour = [-1]
949 tmpTriFace[0] = otherPointIndex[0];
950 tmpTriFace[1] = newPointIndex[0];
951 tmpTriFace[2] = otherEdgePoint[0];
957 whichPatch(c0BdyIndex[0]),
965 // Add this face to the map.
966 map.addFace(newFaceIndex[1]);
968 meshOps::replaceLabel
975 // Third boundary face; Owner = c[0] & Neighbour = [-1]
976 tmpTriFace[0] = otherPointIndex[1];
977 tmpTriFace[1] = newPointIndex[1];
978 tmpTriFace[2] = otherEdgePoint[1];
984 whichPatch(c0BdyIndex[1]),
992 // Add this face to the map.
993 map.addFace(newFaceIndex[2]);
995 meshOps::replaceLabel
1002 // Create / modify edges...
1003 labelList tmpTriEdgeFaces(3, -1);
1005 // The edge bisecting the zeroth boundary triangular face
1006 tmpTriEdgeFaces[0] = c0BdyIndex[0];
1007 tmpTriEdgeFaces[1] = newFaceIndex[0];
1008 tmpTriEdgeFaces[2] = newFaceIndex[1];
1014 whichEdgePatch(commonEdgeIndex[0]),
1015 edge(newPointIndex[0], otherPointIndex[0]),
1020 // Add this edge to the map.
1021 map.addEdge(newEdgeIndex[1]);
1023 // Find the common edge between the quad/tri faces...
1024 meshOps::findCommonEdge
1032 // ...and correct faceEdges / edgeFaces
1033 meshOps::replaceLabel
1037 faceEdges_[c0BdyIndex[0]]
1040 meshOps::replaceLabel
1044 edgeFaces_[cornerEdgeIndex[0]]
1047 // The edge bisecting the first boundary triangular face
1048 tmpTriEdgeFaces[0] = c0BdyIndex[1];
1049 tmpTriEdgeFaces[1] = newFaceIndex[0];
1050 tmpTriEdgeFaces[2] = newFaceIndex[2];
1056 whichEdgePatch(commonEdgeIndex[1]),
1057 edge(newPointIndex[1], otherPointIndex[1]),
1062 // Add this edge to the map.
1063 map.addEdge(newEdgeIndex[2]);
1065 // Find the common edge between the quad/tri faces...
1066 meshOps::findCommonEdge
1074 // ...and correct faceEdges / edgeFaces
1075 meshOps::replaceLabel
1079 faceEdges_[c0BdyIndex[1]]
1082 meshOps::replaceLabel
1086 edgeFaces_[cornerEdgeIndex[1]]
1091 // The quad boundary face resulting from bisection;
1092 // Owner = newCell[0] & Neighbour = [-1]
1093 tmpQuadFace[0] = newPointIndex[1];
1094 tmpQuadFace[1] = nextToOtherPoint[1];
1095 tmpQuadFace[2] = otherEdgePoint[0];
1096 tmpQuadFace[3] = newPointIndex[0];
1110 // Add this face to the map.
1111 map.addFace(newFaceIndex[3]);
1113 // Correct edgeFaces for otherEdgeIndex[1]
1114 meshOps::replaceLabel
1118 edgeFaces_[otherEdgeIndex[1]]
1121 meshOps::replaceLabel
1128 labelList tmpBiEdgeFaces(2, -1);
1130 // The edge bisecting the face
1131 tmpTriEdgeFaces[0] = newFaceIndex[3];
1132 tmpTriEdgeFaces[1] = newFaceIndex[0];
1133 tmpTriEdgeFaces[2] = fIndex;
1139 whichEdgePatch(otherEdgeIndex[0]),
1140 edge(newPointIndex[0], newPointIndex[1]),
1145 // Add this edge to the map.
1146 map.addEdge(newEdgeIndex[0]);
1148 // Replace an edge on the bisected face
1149 meshOps::replaceLabel
1156 // Create / replace side edges created from face bisection
1157 tmpBiEdgeFaces[0] = newFaceIndex[1];
1158 tmpBiEdgeFaces[1] = newFaceIndex[3];
1164 whichEdgePatch(commonEdgeIndex[0]),
1165 edge(newPointIndex[0], otherEdgePoint[0]),
1170 // Add this edge to the map.
1171 map.addEdge(newEdgeIndex[3]);
1173 tmpBiEdgeFaces[0] = c0BdyIndex[1];
1174 tmpBiEdgeFaces[1] = newFaceIndex[3];
1180 whichEdgePatch(commonEdgeIndex[1]),
1181 edge(newPointIndex[1], nextToOtherPoint[1]),
1186 // Add this edge to the map.
1187 map.addEdge(newEdgeIndex[4]);
1189 // Now that edges are defined, configure faceEdges
1190 // for all new faces
1192 // The quad interior face; Owner = cell[0] & Neighbour = newCell[0]
1193 tmpQFEdges[0] = newEdgeIndex[0];
1194 tmpQFEdges[1] = newEdgeIndex[1];
1195 tmpQFEdges[2] = otherEdgeIndex[2];
1196 tmpQFEdges[3] = newEdgeIndex[2];
1197 faceEdges_[newFaceIndex[0]] = tmpQFEdges;
1199 // Second boundary face; Owner = newCell[0] & Neighbour = [-1]
1200 tmpTFEdges[0] = newEdgeIndex[3];
1201 tmpTFEdges[1] = cornerEdgeIndex[0];
1202 tmpTFEdges[2] = newEdgeIndex[1];
1203 faceEdges_[newFaceIndex[1]] = tmpTFEdges;
1205 // Third boundary face; Owner = c[0] & Neighbour = [-1]
1206 tmpTFEdges[0] = newEdgeIndex[2];
1207 tmpTFEdges[1] = cornerEdgeIndex[1];
1208 tmpTFEdges[2] = commonEdgeIndex[1];
1209 faceEdges_[newFaceIndex[2]] = tmpTFEdges;
1211 // The quad face from bisection:
1212 tmpQFEdges[0] = otherEdgeIndex[1];
1213 tmpQFEdges[1] = newEdgeIndex[3];
1214 tmpQFEdges[2] = newEdgeIndex[0];
1215 tmpQFEdges[3] = newEdgeIndex[4];
1216 faceEdges_[newFaceIndex[3]] = tmpQFEdges;
1218 meshOps::replaceLabel
1222 faceEdges_[c0BdyIndex[1]]
1225 meshOps::replaceLabel
1229 edgeFaces_[commonEdgeIndex[1]]
1234 Pout<< "Modified Cell[0]: "
1235 << c0 << ": " << oldCells[0] << endl;
1237 forAll(oldCells[0], faceI)
1239 const labelList& fE = faceEdges_[oldCells[0][faceI]];
1241 Pout<< oldCells[0][faceI]
1242 << ": " << faces_[oldCells[0][faceI]]
1248 const labelList& eF = edgeFaces_[fE[edgeI]];
1250 Pout<< '\t' << fE[edgeI]
1251 << ": " << edges_[fE[edgeI]]
1257 Pout<< "New Cell[0]: " << newCellIndex[0]
1258 << ": " << newCells[0] << endl;
1260 forAll(newCells[0], faceI)
1262 const labelList& fE = faceEdges_[newCells[0][faceI]];
1264 Pout<< newCells[0][faceI]
1265 << ": " << faces_[newCells[0][faceI]]
1271 const labelList& eF = edgeFaces_[fE[edgeI]];
1273 Pout<< '\t' << fE[edgeI]
1274 << ": " << edges_[fE[edgeI]]
1283 oldCells[1] = cells_[c1];
1285 // Add a new prism cell to the end of the list.
1286 // Currently invalid, but will be updated later.
1287 newCellIndex[1] = insertCell(newCells[1], lengthScale_[c1]);
1289 // Add this cell to the map.
1290 map.addCell(newCellIndex[1]);
1294 Pout<< "Cell[1]: " << c1 << ": " << oldCells[1] << endl;
1296 forAll(oldCells[1], faceI)
1298 const labelList& fE = faceEdges_[oldCells[1][faceI]];
1300 Pout<< oldCells[1][faceI] << ": "
1301 << faces_[oldCells[1][faceI]]
1307 const labelList& eF = edgeFaces_[fE[edgeI]];
1309 Pout<< '\t' << fE[edgeI]
1310 << ": " << edges_[fE[edgeI]]
1317 // Find the interior face that contains otherEdgeIndex[1]
1320 const labelList& e2 = faceEdges_[c1IntIndex[0]];
1324 if (e2[edgeI] == otherEdgeIndex[1])
1326 meshOps::replaceLabel
1333 replaceFace = c1IntIndex[0];
1334 retainFace = c1IntIndex[1];
1342 // The edge was not found before
1343 meshOps::replaceLabel
1350 replaceFace = c1IntIndex[1];
1351 retainFace = c1IntIndex[0];
1354 // Check if face reversal is necessary for the replacement
1355 if (owner_[replaceFace] == c1)
1357 if (neighbour_[replaceFace] == -1)
1360 owner_[replaceFace] = newCellIndex[1];
1364 // This face has to be reversed
1365 faces_[replaceFace] = faces_[replaceFace].reverseFace();
1366 owner_[replaceFace] = neighbour_[replaceFace];
1367 neighbour_[replaceFace] = newCellIndex[1];
1369 setFlip(replaceFace);
1374 // Keep owner, but change neighbour
1375 neighbour_[replaceFace] = newCellIndex[1];
1378 // Define attributes for the new prism cell
1379 newCells[1][0] = replaceFace;
1381 // The quad interior face resulting from bisection;
1382 // Owner = newCell[0] & Neighbour = newCell[1]
1383 tmpQuadFace[0] = newPointIndex[1];
1384 tmpQuadFace[1] = nextToOtherPoint[1];
1385 tmpQuadFace[2] = otherEdgePoint[0];
1386 tmpQuadFace[3] = newPointIndex[0];
1400 // Add this face to the map.
1401 map.addFace(newFaceIndex[3]);
1403 // Correct edgeFaces for otherEdgeIndex[1]
1404 meshOps::replaceLabel
1408 edgeFaces_[otherEdgeIndex[1]]
1411 meshOps::replaceLabel
1418 meshOps::replaceLabel
1425 newCells[1][1] = newFaceIndex[3];
1427 // Check for common edges among the two boundary faces
1428 // Find the isolated point on both boundary faces of cell[1]
1431 meshOps::findCommonEdge
1440 meshOps::findCommonEdge
1448 commonFaceIndex[2] = c1BdyIndex[0];
1449 commonFaceIndex[3] = c1BdyIndex[1];
1453 meshOps::findCommonEdge
1461 meshOps::findCommonEdge
1469 commonFaceIndex[2] = c1BdyIndex[1];
1470 commonFaceIndex[3] = c1BdyIndex[0];
1473 commonEdges[2] = edges_[commonEdgeIndex[2]];
1474 commonEdges[3] = edges_[commonEdgeIndex[3]];
1478 Pout<< "Common edges: " << nl
1479 << commonEdgeIndex[2] << ": " << commonEdges[2] << nl
1480 << commonEdgeIndex[3] << ": " << commonEdges[3]
1484 meshOps::findIsolatedPoint
1486 faces_[commonFaceIndex[2]],
1492 meshOps::findIsolatedPoint
1494 faces_[commonFaceIndex[3]],
1500 // For convenience...
1501 otherEdgePoint[2] = commonEdges[2].otherVertex(nextToOtherPoint[2]);
1502 otherEdgePoint[3] = commonEdges[3].otherVertex(nextToOtherPoint[3]);
1504 // Modify the two existing triangle boundary faces
1506 // Zeroth boundary face - Owner = newCell[1], Neighbour = -1
1507 meshOps::replaceLabel
1511 faces_[commonFaceIndex[2]]
1514 owner_[commonFaceIndex[2]] = newCellIndex[1];
1516 meshOps::replaceLabel
1523 newCells[1][2] = commonFaceIndex[2];
1525 // First boundary face - Owner = c[1] & Neighbour [-1] (unchanged)
1526 meshOps::replaceLabel
1530 faces_[commonFaceIndex[3]]
1533 // New interior face; Owner = cell[1] & Neighbour = newCell[1]
1534 tmpQuadFace[0] = newPointIndex[0];
1535 tmpQuadFace[1] = otherPointIndex[2];
1536 tmpQuadFace[2] = otherPointIndex[3];
1537 tmpQuadFace[3] = newPointIndex[1];
1551 // Add this face to the map.
1552 map.addFace(newFaceIndex[4]);
1554 // Find the common edge between quad/quad faces...
1555 meshOps::findCommonEdge
1563 // ... and size-up edgeFaces for the edge
1567 edgeFaces_[otherEdgeIndex[3]]
1570 meshOps::replaceLabel
1577 meshOps::replaceLabel
1584 // Second boundary face; Owner = cell[1] & Neighbour [-1]
1585 tmpTriFace[0] = otherPointIndex[2];
1586 tmpTriFace[1] = newPointIndex[0];
1587 tmpTriFace[2] = otherEdgePoint[2];
1593 whichPatch(commonFaceIndex[2]),
1601 // Add this face to the map.
1602 map.addFace(newFaceIndex[5]);
1604 meshOps::replaceLabel
1611 // Third boundary face; Owner = newCell[1] & Neighbour [-1]
1612 tmpTriFace[0] = otherPointIndex[3];
1613 tmpTriFace[1] = newPointIndex[1];
1614 tmpTriFace[2] = otherEdgePoint[3];
1620 whichPatch(commonFaceIndex[3]),
1628 // Add this face to the map.
1629 map.addFace(newFaceIndex[6]);
1631 meshOps::replaceLabel
1638 // Create / modify edges...
1639 labelList tmpQuadEdgeFaces(4, -1);
1641 // The internal edge bisecting the face
1642 tmpQuadEdgeFaces[0] = fIndex;
1643 tmpQuadEdgeFaces[1] = newFaceIndex[0];
1644 tmpQuadEdgeFaces[2] = newFaceIndex[3];
1645 tmpQuadEdgeFaces[3] = newFaceIndex[4];
1652 edge(newPointIndex[0], newPointIndex[1]),
1657 // Add this edge to the map.
1658 map.addEdge(newEdgeIndex[0]);
1660 // Replace an edge on the bisected face
1661 meshOps::replaceLabel
1668 // Create / replace side edges created from face bisection
1669 tmpTriEdgeFaces[0] = commonFaceIndex[2];
1670 tmpTriEdgeFaces[1] = newFaceIndex[3];
1671 tmpTriEdgeFaces[2] = newFaceIndex[1];
1677 whichEdgePatch(commonEdgeIndex[2]),
1678 edge(newPointIndex[0], nextToOtherPoint[2]),
1683 // Add this edge to the map.
1684 map.addEdge(newEdgeIndex[3]);
1686 tmpTriEdgeFaces[0] = c0BdyIndex[1];
1687 tmpTriEdgeFaces[1] = newFaceIndex[3];
1688 tmpTriEdgeFaces[2] = newFaceIndex[6];
1694 whichEdgePatch(commonEdgeIndex[3]),
1695 edge(newPointIndex[1], otherEdgePoint[3]),
1700 // Add this edge to the map.
1701 map.addEdge(newEdgeIndex[4]);
1703 // The edge bisecting the second boundary triangular face
1704 tmpTriEdgeFaces[0] = commonFaceIndex[2];
1705 tmpTriEdgeFaces[1] = newFaceIndex[4];
1706 tmpTriEdgeFaces[2] = newFaceIndex[5];
1712 whichEdgePatch(commonEdgeIndex[2]),
1713 edge(newPointIndex[0], otherPointIndex[2]),
1718 // Add this edge to the map.
1719 map.addEdge(newEdgeIndex[5]);
1721 // Find the common edge between the quad/tri faces...
1722 meshOps::findCommonEdge
1730 // ...and correct faceEdges / edgeFaces
1731 meshOps::replaceLabel
1735 faceEdges_[commonFaceIndex[2]]
1738 meshOps::replaceLabel
1742 edgeFaces_[cornerEdgeIndex[2]]
1745 // The edge bisecting the third boundary triangular face
1746 tmpTriEdgeFaces[0] = commonFaceIndex[3];
1747 tmpTriEdgeFaces[1] = newFaceIndex[4];
1748 tmpTriEdgeFaces[2] = newFaceIndex[6];
1754 whichEdgePatch(commonEdgeIndex[3]),
1755 edge(newPointIndex[1], otherPointIndex[3]),
1760 // Add this edge to the map.
1761 map.addEdge(newEdgeIndex[6]);
1763 // Find the common edge between the quad/tri faces...
1764 meshOps::findCommonEdge
1772 // ...and correct faceEdges / edgeFaces
1773 meshOps::replaceLabel
1777 faceEdges_[commonFaceIndex[3]]
1780 meshOps::replaceLabel
1784 edgeFaces_[cornerEdgeIndex[3]]
1787 // Now that edges are defined, configure faceEdges
1788 // for all new faces
1790 // The quad interior face; Owner = c[0] & Neighbour = newCell[0]
1791 tmpQFEdges[0] = newEdgeIndex[0];
1792 tmpQFEdges[1] = newEdgeIndex[1];
1793 tmpQFEdges[2] = otherEdgeIndex[2];
1794 tmpQFEdges[3] = newEdgeIndex[2];
1795 faceEdges_[newFaceIndex[0]] = tmpQFEdges;
1797 // Second boundary face; Owner = newCell[0] & Neighbour = [-1]
1798 tmpTFEdges[0] = newEdgeIndex[3];
1799 tmpTFEdges[1] = cornerEdgeIndex[0];
1800 tmpTFEdges[2] = newEdgeIndex[1];
1801 faceEdges_[newFaceIndex[1]] = tmpTFEdges;
1803 // Third boundary face; Owner = c[0] & Neighbour = [-1]
1804 tmpTFEdges[0] = newEdgeIndex[2];
1805 tmpTFEdges[1] = cornerEdgeIndex[1];
1806 tmpTFEdges[2] = commonEdgeIndex[3];
1807 faceEdges_[newFaceIndex[2]] = tmpTFEdges;
1809 // The quad face from bisection:
1810 tmpQFEdges[0] = otherEdgeIndex[1];
1811 tmpQFEdges[1] = newEdgeIndex[3];
1812 tmpQFEdges[2] = newEdgeIndex[0];
1813 tmpQFEdges[3] = newEdgeIndex[4];
1814 faceEdges_[newFaceIndex[3]] = tmpQFEdges;
1816 // The quad interior face; Owner = c[1] & Neighbour = newCell[1]
1817 tmpQFEdges[0] = newEdgeIndex[0];
1818 tmpQFEdges[1] = newEdgeIndex[5];
1819 tmpQFEdges[2] = otherEdgeIndex[3];
1820 tmpQFEdges[3] = newEdgeIndex[6];
1821 faceEdges_[newFaceIndex[4]] = tmpQFEdges;
1823 // Second boundary face; Owner = c[1] & Neighbour = [-1]
1824 tmpTFEdges[0] = commonEdgeIndex[2];
1825 tmpTFEdges[1] = cornerEdgeIndex[2];
1826 tmpTFEdges[2] = newEdgeIndex[5];
1827 faceEdges_[newFaceIndex[5]] = tmpTFEdges;
1829 // Third boundary face; Owner = newCell[1] & Neighbour = [-1]
1830 tmpTFEdges[0] = newEdgeIndex[4];
1831 tmpTFEdges[1] = cornerEdgeIndex[3];
1832 tmpTFEdges[2] = newEdgeIndex[6];
1833 faceEdges_[newFaceIndex[6]] = tmpTFEdges;
1835 meshOps::replaceLabel
1839 faceEdges_[c0BdyIndex[1]]
1842 meshOps::replaceLabel
1846 edgeFaces_[commonEdgeIndex[1]]
1849 meshOps::replaceLabel
1853 faceEdges_[commonFaceIndex[2]]
1856 meshOps::replaceLabel
1860 edgeFaces_[commonEdgeIndex[2]]
1865 Pout<< nl << "Modified Cell[0]: "
1866 << c0 << ": " << oldCells[0] << endl;
1868 forAll(oldCells[0], faceI)
1870 const labelList& fE = faceEdges_[oldCells[0][faceI]];
1872 Pout<< oldCells[0][faceI]
1873 << ": " << faces_[oldCells[0][faceI]]
1879 const labelList& eF = edgeFaces_[fE[edgeI]];
1881 Pout<< '\t' << fE[edgeI]
1882 << ": " << edges_[fE[edgeI]]
1888 Pout<< "New Cell[0]: "
1889 << newCellIndex[0] << ": " << newCells[0] << endl;
1891 forAll(newCells[0], faceI)
1893 const labelList& fE = faceEdges_[newCells[0][faceI]];
1895 Pout<< newCells[0][faceI] << ": "
1896 << faces_[newCells[0][faceI]]
1902 const labelList& eF = edgeFaces_[fE[edgeI]];
1904 Pout<< '\t' << fE[edgeI]
1905 << ": " << edges_[fE[edgeI]]
1911 Pout<< nl << "Modified Cell[1]: "
1912 << c1 << ": " << oldCells[1] << endl;
1914 forAll(oldCells[1], faceI)
1916 const labelList& fE = faceEdges_[oldCells[1][faceI]];
1918 Pout<< oldCells[1][faceI] << ": "
1919 << faces_[oldCells[1][faceI]]
1925 const labelList& eF = edgeFaces_[fE[edgeI]];
1927 Pout<< '\t' << fE[edgeI]
1928 << ": " << edges_[fE[edgeI]]
1934 Pout<< "New Cell[1]: "
1935 << newCellIndex[1] << ": " << newCells[1] << endl;
1937 forAll(newCells[1], faceI)
1939 const labelList& fE = faceEdges_[newCells[1][faceI]];
1941 Pout<< newCells[1][faceI] << ": "
1942 << faces_[newCells[1][faceI]]
1948 const labelList& eF = edgeFaces_[fE[edgeI]];
1950 Pout<< '\t' << fE[edgeI]
1951 << ": " << edges_[fE[edgeI]]
1958 // Update the cell list.
1959 cells_[c1] = oldCells[1];
1960 cells_[newCellIndex[1]] = newCells[1];
1963 // Update the cell list.
1964 cells_[c0] = oldCells[0];
1965 cells_[newCellIndex[0]] = newCells[0];
1967 // Modify point labels for common edges
1968 if (edges_[commonEdgeIndex[0]].start() == otherEdgePoint[0])
1970 edges_[commonEdgeIndex[0]].start() = newPointIndex[0];
1974 edges_[commonEdgeIndex[0]].end() = newPointIndex[0];
1977 if (edges_[commonEdgeIndex[1]].start() == nextToOtherPoint[1])
1979 edges_[commonEdgeIndex[1]].start() = newPointIndex[1];
1983 edges_[commonEdgeIndex[1]].end() = newPointIndex[1];
1986 if (coupledModification_)
1988 // Alias for convenience...
1989 const changeMap& slaveMap = slaveMaps[0];
1991 const label pI = slaveMap.patchIndex();
1993 // Fetch the appropriate coupleMap
1994 const coupleMap* cMapPtr = NULL;
1996 if (localCouple && !procCouple)
1998 cMapPtr = &(patchCoupling_[pI].map());
2001 if (procCouple && !localCouple)
2003 cMapPtr = &(recvMeshes_[pI].map());
2006 // Alias for convenience
2007 const coupleMap& cMap = *cMapPtr;
2009 // Add the new points to the coupling map
2010 const List<objectMap>& apList = slaveMap.addedPointList();
2014 // Update reverse pointMap
2061 // Update reverse pointMap
2077 // Create a master/slave entry for the new face on the patch.
2078 FixedList<bool, 2> foundMatch(false);
2079 FixedList<label, 2> checkFaces(-1);
2081 // Fill in the faces to check for...
2082 checkFaces[0] = fIndex;
2083 checkFaces[1] = newFaceIndex[3];
2085 const List<objectMap>& afList = slaveMap.addedFaceList();
2087 forAll (checkFaces, indexI)
2089 const face& mFace = faces_[checkFaces[indexI]];
2091 label sFaceIndex = -1;
2095 const face* facePtr = NULL;
2097 if (localCouple && !procCouple)
2099 facePtr = &(faces_[afList[sfI].index()]);
2102 if (procCouple && !localCouple)
2104 const dynamicTopoFvMesh& mesh = recvMeshes_[pI].subMesh();
2106 facePtr = &(mesh.faces_[afList[sfI].index()]);
2109 const face& tFace = *facePtr;
2110 FixedList<bool, 4> cP(false);
2112 forAll(mFace, pointI)
2114 const Map<label>& pointMap =
2116 cMap.entityMap(coupleMap::POINT)
2119 if (tFace.which(pointMap[mFace[pointI]]) > -1)
2125 if (cP[0] && cP[1] && cP[2] && cP[3])
2127 sFaceIndex = afList[sfI].index();
2128 foundMatch[indexI] = true;
2133 if (foundMatch[indexI])
2174 "dynamicTopoFvMesh::bisectQuadFace\n"
2176 " const label fIndex,\n"
2177 " const changeMap& masterMap,\n"
2178 " bool checkOnly,\n"
2182 << "Failed to build coupled maps." << nl
2183 << " masterFace: " << mFace << nl
2184 << " Added slave faces: " << afList << nl
2185 << abort(FatalError);
2189 // Push operation into coupleMap
2193 coupleMap::BISECTION
2197 // Write out VTK files after change
2200 labelList cellHull(4, -1);
2202 cellHull[0] = owner_[fIndex];
2203 cellHull[1] = neighbour_[fIndex];
2204 cellHull[2] = owner_[newFaceIndex[3]];
2205 cellHull[3] = neighbour_[newFaceIndex[3]];
2215 // Fill-in mapping information
2216 FixedList<label, 4> mapCells(-1);
2219 mapCells[1] = newCellIndex[0];
2224 mapCells[3] = newCellIndex[1];
2227 labelList mC(1, c0);
2229 forAll(mapCells, cellI)
2231 if (mapCells[cellI] == -1)
2236 // Set the mapping for this cell
2237 setCellMapping(mapCells[cellI], mC);
2240 // Set fill-in mapping information for the modified face.
2243 // Set the mapping for this face
2244 setFaceMapping(fIndex, labelList(1, fIndex));
2248 // Internal face. Default mapping.
2249 setFaceMapping(fIndex);
2252 forAll(newFaceIndex, faceI)
2254 if (newFaceIndex[faceI] == -1)
2259 // Check for boundary faces
2260 if (neighbour_[newFaceIndex[faceI]] == -1)
2262 // Boundary face. Compute mapping.
2265 if (faces_[newFaceIndex[faceI]].size() == 4)
2267 // Quad-face on boundary
2268 mC.setSize(1, fIndex);
2271 if (faces_[newFaceIndex[faceI]].size() == 3)
2273 label triFacePatch = whichPatch(newFaceIndex[faceI]);
2275 // Fetch face-normals
2276 vector tfNorm, f0Norm, f1Norm;
2278 tfNorm = faces_[newFaceIndex[faceI]].normal(oldPoints_);
2279 f0Norm = faces_[c0BdyIndex[0]].normal(oldPoints_);
2280 f1Norm = faces_[c0BdyIndex[1]].normal(oldPoints_);
2282 // Tri-face on boundary. Perform normal checks
2283 // also, because of empty patches.
2286 (whichPatch(c0BdyIndex[0]) == triFacePatch) &&
2287 ((tfNorm & f0Norm) > 0.0)
2290 mC.setSize(1, c0BdyIndex[0]);
2295 (whichPatch(c0BdyIndex[1]) == triFacePatch) &&
2296 ((tfNorm & f1Norm) > 0.0)
2299 mC.setSize(1, c0BdyIndex[1]);
2306 "const changeMap dynamicTopoFvMesh::bisectQuadFace\n"
2308 " const label fIndex,\n"
2309 " const changeMap& masterMap,\n"
2313 << " Unable to find patch for face: "
2314 << newFaceIndex[faceI] << ":: "
2315 << faces_[newFaceIndex[faceI]] << nl
2316 << " Patch: " << triFacePatch << nl
2317 << abort(FatalError);
2321 // Set the mapping for this face
2322 setFaceMapping(newFaceIndex[faceI], mC);
2326 // Internal quad-faces get default mapping.
2327 setFaceMapping(newFaceIndex[faceI]);
2332 topoChangeFlag_ = true;
2334 // Increment the counter
2335 status(TOTAL_BISECTIONS)++;
2337 // Increment surface-counter
2340 // Do not update stats for processor patches
2341 if (!processorCoupledEntity(fIndex))
2343 status(SURFACE_BISECTIONS)++;
2347 // Increment the number of modifications
2348 status(TOTAL_MODIFICATIONS)++;
2350 // Specify that the operation was successful
2353 // Return the changeMap
2358 // Method for the bisection of an edge in 3D
2359 // - Returns a changeMap with a type specifying:
2360 // 1: Bisection was successful
2361 // -1: Bisection failed since max number of topo-changes was reached.
2362 // -2: Bisection failed since resulting quality would be unacceptable.
2363 // -3: Bisection failed since edge was on a noRefinement patch.
2364 // - AddedPoints contain the index of the newly added point.
2365 const changeMap dynamicTopoFvMesh::bisectEdge
2372 // Edge bisection performs the following operations:
2373 // [1] Add a point at middle of the edge
2374 // [2] Bisect all faces surrounding this edge
2375 // [3] Bisect all cells surrounding this edge
2376 // [4] Create internal/external edges for each bisected face
2377 // [5] Create internal faces for each bisected cell
2378 // Update faceEdges and edgeFaces information
2380 // For 2D meshes, perform face-bisection
2383 return bisectQuadFace(eIndex, changeMap(), checkOnly);
2386 // Figure out which thread this is...
2387 label tIndex = self();
2389 // Prepare the changeMaps
2391 List<changeMap> slaveMaps;
2392 bool bisectingSlave = false;
2396 (status(TOTAL_MODIFICATIONS) > maxModifications_) &&
2397 (maxModifications_ > -1)
2400 // Reached the max allowable topo-changes.
2401 stack(tIndex).clear();
2406 // Check if edgeRefinements are to be avoided on patch.
2407 const labelList& eF = edgeFaces_[eIndex];
2411 label fPatch = whichPatch(eF[fI]);
2413 if (baseMesh_.lengthEstimator().checkRefinementPatch(fPatch))
2421 // Sanity check: Is the index legitimate?
2427 "const changeMap dynamicTopoFvMesh::bisectEdge\n"
2429 " const label eIndex,\n"
2430 " bool checkOnly,\n"
2434 << " Invalid index: " << eIndex
2435 << abort(FatalError);
2438 // If coupled modification is set, and this is a
2439 // master edge, bisect its slaves as well.
2440 bool localCouple = false, procCouple = false;
2442 if (coupledModification_)
2444 const edge& eCheck = edges_[eIndex];
2446 const label edgeEnum = coupleMap::EDGE;
2448 // Is this a locally coupled edge (either master or slave)?
2449 if (locallyCoupledEntity(eIndex, true))
2455 if (processorCoupledEntity(eIndex))
2458 localCouple = false;
2461 if (localCouple && !procCouple)
2463 // Determine the slave index.
2464 label sIndex = -1, pIndex = -1;
2466 forAll(patchCoupling_, patchI)
2468 if (patchCoupling_(patchI))
2470 const coupleMap& cMap = patchCoupling_[patchI].map();
2472 if ((sIndex = cMap.findSlave(edgeEnum, eIndex)) > -1)
2479 // The following bit happens only during the sliver
2480 // exudation process, since slave edges are
2481 // usually not added to the coupled edge-stack.
2482 if ((sIndex = cMap.findMaster(edgeEnum, eIndex)) > -1)
2486 // Notice that we are bisecting a slave edge first.
2487 bisectingSlave = true;
2499 "const changeMap dynamicTopoFvMesh::bisectEdge\n"
2501 " const label eIndex,\n"
2502 " bool checkOnly,\n"
2506 << "Coupled maps were improperly specified." << nl
2507 << " Slave index not found for: " << nl
2508 << " Edge: " << eIndex << ": " << edges_[eIndex] << nl
2509 << abort(FatalError);
2513 // If we've found the slave, size up the list
2520 // Save index and patch for posterity
2521 slaveMaps[0].index() = sIndex;
2522 slaveMaps[0].patchIndex() = pIndex;
2527 Pout<< nl << " >> Bisecting slave edge: " << sIndex
2528 << " for master edge: " << eIndex << endl;
2532 if (procCouple && !localCouple)
2534 // If this is a new entity, bail out for now.
2535 // This will be handled at the next time-step.
2536 if (eIndex >= nOldEdges_)
2542 forAll(procIndices_, pI)
2544 // Fetch reference to subMeshes
2545 const coupledMesh& sendMesh = sendMeshes_[pI];
2546 const coupledMesh& recvMesh = recvMeshes_[pI];
2548 const coupleMap& scMap = sendMesh.map();
2549 const coupleMap& rcMap = recvMesh.map();
2551 // If this edge was sent to a lower-ranked
2552 // processor, skip it.
2563 if (scMap.reverseEntityMap(edgeEnum).found(eIndex))
2567 Pout<< "Edge: " << eIndex
2569 << " was sent to proc: "
2571 << ", so bailing out."
2581 if ((sIndex = rcMap.findSlave(edgeEnum, eIndex)) > -1)
2585 Pout<< "Checking slave edge: " << sIndex
2586 << " on proc: " << procIndices_[pI]
2587 << " for master edge: " << eIndex
2591 // Check if a lower-ranked processor is
2592 // handling this edge
2605 Pout<< "Edge: " << eIndex
2606 << " is handled by proc: "
2608 << ", so bailing out."
2615 label curIndex = slaveMaps.size();
2624 // Save index and patch for posterity
2625 slaveMaps[curIndex].index() = sIndex;
2626 slaveMaps[curIndex].patchIndex() = pI;
2632 // Something's wrong with coupling maps
2636 "const changeMap dynamicTopoFvMesh::bisectEdge\n"
2638 " const label eIndex,\n"
2639 " bool checkOnly,\n"
2643 << "Coupled maps were improperly specified." << nl
2644 << " localCouple: " << localCouple << nl
2645 << " procCouple: " << procCouple << nl
2646 << " Edge: " << eIndex << ": " << edges_[eIndex] << nl
2647 << abort(FatalError);
2650 // Temporarily turn off coupledModification
2651 unsetCoupledModification();
2653 // First check the master for bisection feasibility.
2654 changeMap masterMap = bisectEdge(eIndex, true, forceOp);
2657 setCoupledModification();
2659 // Master couldn't perform bisection
2660 if (masterMap.type() <= 0)
2665 // Now check each of the slaves for bisection feasibility
2666 forAll(slaveMaps, slaveI)
2668 // Alias for convenience...
2669 changeMap& slaveMap = slaveMaps[slaveI];
2671 label sIndex = slaveMap.index();
2672 label pI = slaveMap.patchIndex();
2674 // If the edge is mapped onto itself, skip check
2675 // (occurs for cyclic edges)
2676 if ((sIndex == eIndex) && localCouple)
2681 // Temporarily turn off coupledModification
2682 unsetCoupledModification();
2684 // Test the slave edge
2687 slaveMap = bisectEdge(sIndex, true, forceOp);
2692 dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
2696 Pout<< "Checking slave edge: " << sIndex
2697 << "::" << sMesh.edges_[sIndex]
2698 << " on proc: " << procIndices_[pI]
2699 << " for master edge: " << eIndex
2703 slaveMap = sMesh.bisectEdge(sIndex, true, forceOp);
2707 setCoupledModification();
2709 if (slaveMap.type() <= 0)
2711 // Slave couldn't perform bisection.
2717 // Save index and patch for posterity
2718 slaveMap.index() = sIndex;
2719 slaveMap.patchIndex() = pI;
2722 // Next bisect each slave edge..
2723 forAll(slaveMaps, slaveI)
2725 // Alias for convenience...
2726 changeMap& slaveMap = slaveMaps[slaveI];
2728 label sIndex = slaveMap.index();
2729 label pI = slaveMap.patchIndex();
2731 // If the edge is mapped onto itself, skip modification
2732 // (occurs for cyclic edges)
2733 if ((sIndex == eIndex) && localCouple)
2738 // Temporarily turn off coupledModification
2739 unsetCoupledModification();
2741 // Bisect the slave edge
2744 slaveMap = bisectEdge(sIndex, false, forceOp);
2748 dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
2750 slaveMap = sMesh.bisectEdge(sIndex, false, forceOp);
2754 setCoupledModification();
2756 // The final operation has to succeed.
2757 if (slaveMap.type() <= 0)
2762 "const changeMap dynamicTopoFvMesh::bisectEdge\n"
2764 " const label eIndex,\n"
2765 " bool checkOnly,\n"
2769 << "Coupled topo-change for slave failed." << nl
2770 << " Edge: " << eIndex << ": " << edges_[eIndex] << nl
2771 << " Slave index: " << sIndex << nl
2772 << " Patch index: " << pI << nl
2773 << " Type: " << slaveMap.type() << nl
2774 << abort(FatalError);
2777 // Save index and patch for posterity
2778 slaveMap.index() = sIndex;
2779 slaveMap.patchIndex() = pI;
2783 // Before we bisect this edge, check whether the operation will
2784 // yield an acceptable cell-quality.
2787 if ((minQ = computeBisectionQuality(eIndex)) < sliverThreshold_)
2789 // Check if the quality is actually valid before forcing it.
2790 if (forceOp && (minQ < 0.0))
2795 "const changeMap dynamicTopoFvMesh::bisectEdge\n"
2797 " const label eIndex,\n"
2798 " bool checkOnly,\n"
2802 << " Forcing bisection on edge: " << eIndex
2803 << " will yield an invalid cell."
2804 << abort(FatalError);
2814 // Are we performing only checks?
2817 if (debug > 3 && isSubMesh_)
2819 Pout<< " Slave edge: " << eIndex
2820 << " can be bisected."
2828 // Update number of surface bisections, if necessary.
2829 if (whichEdgePatch(eIndex) > -1)
2831 // Do not update stats for processor patches
2832 if (!processorCoupledEntity(eIndex))
2834 status(SURFACE_BISECTIONS)++;
2840 edge origEdge(edges_[eIndex]);
2841 labelList tmpEdgeFaces(3,-1);
2842 labelList tmpIntEdgeFaces(4,-1);
2843 labelList tmpFaceEdges(3,-1);
2845 // Build vertexHull for this edge
2846 labelList vertexHull;
2847 buildVertexHull(eIndex, vertexHull);
2849 // Size up the hull lists
2850 label m = vertexHull.size();
2851 labelList cellHull(m, -1);
2852 labelList faceHull(m, -1);
2853 labelList edgeHull(m, -1);
2854 labelListList ringEntities(4, labelList(m, -1));
2856 // Construct a hull around this edge
2857 meshOps::constructHull
2877 << "Edge: " << eIndex
2879 << " is to be bisected. " << endl;
2881 Pout<< " On SubMesh: " << isSubMesh_ << nl;
2882 Pout<< " coupledModification: " << coupledModification_ << nl;
2884 label epIndex = whichEdgePatch(eIndex);
2886 const polyBoundaryMesh& boundary = boundaryMesh();
2892 Pout<< "Internal" << endl;
2895 if (epIndex < boundary.size())
2897 Pout<< boundary[epIndex].name() << endl;
2901 Pout<< " New patch: " << epIndex << endl;
2904 // Write out VTK files prior to change
2905 // - Using old-points for convenience in post-processing
2911 + '(' + Foam::name(origEdge[0])
2912 + ',' + Foam::name(origEdge[1]) + ')'
2920 labelList mP(2, -1);
2922 // Set mapping for this point
2923 mP[0] = edges_[eIndex][0];
2924 mP[1] = edges_[eIndex][1];
2926 // Add a new point to the end of the list
2927 label newPointIndex =
2931 0.5 * (points_[mP[0]] + points_[mP[1]]),
2932 0.5 * (oldPoints_[mP[0]] + oldPoints_[mP[1]]),
2937 // Add this point to the map.
2938 map.addPoint(newPointIndex);
2940 // New edges can lie on a bounding curve between
2941 // coupled and non-coupled faces. Preferentially
2942 // add edges to coupled-patches, if they exist.
2943 // This makes it convenient for coupled patch matching.
2946 if (locallyCoupledEntity(eIndex, true))
2948 nePatch = locallyCoupledEdgePatch(eIndex);
2952 nePatch = whichEdgePatch(eIndex);
2955 // Add a new edge to the end of the list
2956 label newEdgeIndex =
2961 edge(newPointIndex,edges_[eIndex][1]),
2962 labelList(faceHull.size(),-1)
2966 // Add this edge to the map.
2967 map.addEdge(newEdgeIndex);
2969 // Remove the existing edge from the pointEdges list
2970 // of the modified point, and add it to the new point
2971 meshOps::sizeDownList(eIndex, pointEdges_[edges_[eIndex][1]]);
2972 meshOps::sizeUpList(eIndex, pointEdges_[newPointIndex]);
2974 // Modify the existing edge
2975 edges_[eIndex][1] = newPointIndex;
2977 // Add this edge to the map.
2978 // Although this edge isn't technically 'added', it's
2979 // required for coupled patch mapping.
2980 map.addEdge(eIndex);
2982 // Keep track of added entities
2983 labelList addedCellIndices(cellHull.size(),-1);
2984 labelList addedFaceIndices(faceHull.size(),-1);
2985 labelList addedEdgeIndices(faceHull.size(),-1);
2986 labelList addedIntFaceIndices(faceHull.size(),-1);
2988 // Now loop through the hull and bisect individual entities
2989 forAll(vertexHull, indexI)
2991 // Modify the existing face
2992 meshOps::replaceLabel
2994 edges_[newEdgeIndex][1],
2996 faces_[faceHull[indexI]]
2999 // Obtain circular indices
3000 label nextI = vertexHull.fcIndex(indexI);
3001 label prevI = vertexHull.rcIndex(indexI);
3003 // Check if this is an interior/boundary face
3004 if (cellHull[indexI] != -1)
3006 // Create a new cell. Add it for now, but update later.
3009 addedCellIndices[indexI] =
3014 lengthScale_[cellHull[indexI]]
3018 // Add this cell to the map.
3019 map.addCell(addedCellIndices[indexI]);
3021 // Configure the interior face
3022 tmpTriFace[0] = vertexHull[nextI];
3023 tmpTriFace[1] = vertexHull[indexI];
3024 tmpTriFace[2] = newPointIndex;
3027 addedIntFaceIndices[indexI] =
3034 addedCellIndices[indexI],
3039 // Add this face to the map.
3040 map.addFace(addedIntFaceIndices[indexI]);
3042 // Add to the new cell
3043 newCell[0] = addedIntFaceIndices[indexI];
3045 // Modify the existing ring face connected to newEdge[1]
3046 label replaceFace = ringEntities[3][indexI];
3048 // Check if face reversal is necessary
3049 if (owner_[replaceFace] == cellHull[indexI])
3051 if (neighbour_[replaceFace] == -1)
3054 owner_[replaceFace] = addedCellIndices[indexI];
3058 // This face has to be reversed
3059 faces_[replaceFace] = faces_[replaceFace].reverseFace();
3060 owner_[replaceFace] = neighbour_[replaceFace];
3061 neighbour_[replaceFace] = addedCellIndices[indexI];
3063 setFlip(replaceFace);
3068 // Keep owner, but change neighbour
3069 neighbour_[replaceFace] = addedCellIndices[indexI];
3072 // Modify the edge on the ring.
3073 // Add the new interior face to edgeFaces.
3076 addedIntFaceIndices[indexI],
3077 edgeFaces_[edgeHull[indexI]]
3080 // Add this edge to faceEdges for the new interior face
3081 faceEdges_[addedIntFaceIndices[indexI]][0] = edgeHull[indexI];
3083 // Replace face labels
3084 meshOps::replaceLabel
3087 addedIntFaceIndices[indexI],
3088 cells_[cellHull[indexI]]
3091 // Add to the new cell
3092 newCell[1] = replaceFace;
3094 // Check if this is a boundary face
3095 if (cellHull[prevI] == -1)
3097 // Configure the boundary face
3098 tmpTriFace[0] = newPointIndex;
3099 tmpTriFace[1] = edges_[newEdgeIndex][1];
3100 tmpTriFace[2] = vertexHull[indexI];
3103 addedFaceIndices[indexI] =
3107 whichPatch(faceHull[indexI]),
3109 addedCellIndices[indexI],
3115 // Add this face to the map.
3116 map.addFace(addedFaceIndices[indexI]);
3118 // Configure edgeFaces
3119 tmpEdgeFaces[0] = faceHull[indexI];
3120 tmpEdgeFaces[1] = addedIntFaceIndices[indexI];
3121 tmpEdgeFaces[2] = addedFaceIndices[indexI];
3124 addedEdgeIndices[indexI] =
3128 whichPatch(faceHull[indexI]),
3129 edge(newPointIndex,vertexHull[indexI]),
3134 // Add this edge to the map.
3135 map.addEdge(addedEdgeIndices[indexI]);
3137 // Add this edge to the interior-face faceEdges entry
3138 faceEdges_[addedIntFaceIndices[indexI]][1] =
3140 addedEdgeIndices[indexI]
3143 // Configure faceEdges for this boundary face
3144 tmpFaceEdges[0] = addedEdgeIndices[indexI];
3145 tmpFaceEdges[1] = newEdgeIndex;
3146 tmpFaceEdges[2] = ringEntities[2][indexI];
3148 // Modify faceEdges for the hull face
3149 meshOps::replaceLabel
3151 ringEntities[2][indexI],
3152 addedEdgeIndices[indexI],
3153 faceEdges_[faceHull[indexI]]
3156 // Modify edgeFaces for the edge connected to newEdge[1]
3157 meshOps::replaceLabel
3160 addedFaceIndices[indexI],
3161 edgeFaces_[ringEntities[2][indexI]]
3164 // Add the faceEdges entry
3165 faceEdges_[addedFaceIndices[indexI]] = tmpFaceEdges;
3167 // Add an entry to edgeFaces
3168 edgeFaces_[newEdgeIndex][indexI] = addedFaceIndices[indexI];
3170 // Add an entry for this cell
3171 newCell[2] = addedFaceIndices[indexI];
3174 // Check if a cell was added before this
3175 if (addedCellIndices[prevI] != -1)
3177 // Configure the interior face
3178 tmpTriFace[0] = vertexHull[indexI];
3179 tmpTriFace[1] = edges_[newEdgeIndex][1];
3180 tmpTriFace[2] = newPointIndex;
3183 addedFaceIndices[indexI] =
3189 addedCellIndices[prevI],
3190 addedCellIndices[indexI],
3195 // Add this face to the map.
3196 map.addFace(addedFaceIndices[indexI]);
3198 // Configure edgeFaces
3199 tmpIntEdgeFaces[0] = faceHull[indexI];
3200 tmpIntEdgeFaces[1] = addedIntFaceIndices[indexI];
3201 tmpIntEdgeFaces[2] = addedFaceIndices[indexI];
3202 tmpIntEdgeFaces[3] = addedIntFaceIndices[prevI];
3204 // Add an internal edge
3205 addedEdgeIndices[indexI] =
3210 edge(newPointIndex,vertexHull[indexI]),
3215 // Add this edge to the map.
3216 map.addEdge(addedEdgeIndices[indexI]);
3218 // Add this edge to the interior-face faceEdges entry..
3219 faceEdges_[addedIntFaceIndices[indexI]][1] =
3221 addedEdgeIndices[indexI]
3224 // ... and to the previous interior face as well
3225 faceEdges_[addedIntFaceIndices[prevI]][2] =
3227 addedEdgeIndices[indexI]
3230 // Configure faceEdges for this split interior face
3231 tmpFaceEdges[0] = addedEdgeIndices[indexI];
3232 tmpFaceEdges[1] = newEdgeIndex;
3233 tmpFaceEdges[2] = ringEntities[2][indexI];
3235 // Modify faceEdges for the hull face
3236 meshOps::replaceLabel
3238 ringEntities[2][indexI],
3239 addedEdgeIndices[indexI],
3240 faceEdges_[faceHull[indexI]]
3243 // Modify edgeFaces for the edge connected to newEdge[1]
3244 meshOps::replaceLabel
3247 addedFaceIndices[indexI],
3248 edgeFaces_[ringEntities[2][indexI]]
3251 // Add the faceEdges entry
3252 faceEdges_[addedFaceIndices[indexI]] = tmpFaceEdges;
3254 // Add an entry to edgeFaces
3255 edgeFaces_[newEdgeIndex][indexI] = addedFaceIndices[indexI];
3257 // Add an entry for this cell
3258 newCell[2] = addedFaceIndices[indexI];
3260 // Make the final entry for the previous cell
3261 cells_[addedCellIndices[prevI]][3] = addedFaceIndices[indexI];
3264 // Do the first interior face at the end
3265 if (indexI == vertexHull.size() - 1)
3267 // Configure the interior face
3268 tmpTriFace[0] = newPointIndex;
3269 tmpTriFace[1] = edges_[newEdgeIndex][1];
3270 tmpTriFace[2] = vertexHull[0];
3273 addedFaceIndices[0] =
3279 addedCellIndices[0],
3280 addedCellIndices[indexI],
3285 // Add this face to the map.
3286 map.addFace(addedFaceIndices[0]);
3288 // Configure edgeFaces
3289 tmpIntEdgeFaces[0] = faceHull[0];
3290 tmpIntEdgeFaces[1] = addedIntFaceIndices[0];
3291 tmpIntEdgeFaces[2] = addedFaceIndices[0];
3292 tmpIntEdgeFaces[3] = addedIntFaceIndices[indexI];
3294 // Add an internal edge
3295 addedEdgeIndices[0] =
3300 edge(newPointIndex,vertexHull[0]),
3305 // Add this edge to the map.
3306 map.addEdge(addedEdgeIndices[0]);
3308 // Add this edge to the interior-face faceEdges entry..
3309 faceEdges_[addedIntFaceIndices[0]][1] =
3314 // ... and to the previous interior face as well
3315 faceEdges_[addedIntFaceIndices[indexI]][2] =
3320 // Configure faceEdges for the first split face
3321 tmpFaceEdges[0] = addedEdgeIndices[0];
3322 tmpFaceEdges[1] = newEdgeIndex;
3323 tmpFaceEdges[2] = ringEntities[2][0];
3325 // Modify faceEdges for the hull face
3326 meshOps::replaceLabel
3329 addedEdgeIndices[0],
3330 faceEdges_[faceHull[0]]
3333 // Modify edgeFaces for the edge connected to newEdge[1]
3334 meshOps::replaceLabel
3337 addedFaceIndices[0],
3338 edgeFaces_[ringEntities[2][0]]
3341 // Add the faceEdges entry
3342 faceEdges_[addedFaceIndices[0]] = tmpFaceEdges;
3344 // Add an entry to edgeFaces
3345 edgeFaces_[newEdgeIndex][0] = addedFaceIndices[0];
3347 // Add an entry for this cell
3348 newCell[3] = addedFaceIndices[0];
3350 // Make the final entry for the first cell
3351 cells_[addedCellIndices[0]][2] = addedFaceIndices[0];
3354 // Update the cell list with the new cell.
3355 cells_[addedCellIndices[indexI]] = newCell;
3359 // Configure the final boundary face
3360 tmpTriFace[0] = vertexHull[indexI];
3361 tmpTriFace[1] = edges_[newEdgeIndex][1];
3362 tmpTriFace[2] = newPointIndex;
3365 addedFaceIndices[indexI] =
3369 whichPatch(faceHull[indexI]),
3371 addedCellIndices[prevI],
3377 // Add this face to the map.
3378 map.addFace(addedFaceIndices[indexI]);
3380 // Configure edgeFaces
3381 tmpEdgeFaces[0] = addedFaceIndices[indexI];
3382 tmpEdgeFaces[1] = addedIntFaceIndices[prevI];
3383 tmpEdgeFaces[2] = faceHull[indexI];
3386 addedEdgeIndices[indexI] =
3390 whichPatch(faceHull[indexI]),
3391 edge(newPointIndex,vertexHull[indexI]),
3396 // Add this edge to the map.
3397 map.addEdge(addedEdgeIndices[indexI]);
3399 // Add a faceEdges entry to the previous interior face
3400 faceEdges_[addedIntFaceIndices[prevI]][2] =
3402 addedEdgeIndices[indexI]
3405 // Configure faceEdges for the final boundary face
3406 tmpFaceEdges[0] = addedEdgeIndices[indexI];
3407 tmpFaceEdges[1] = newEdgeIndex;
3408 tmpFaceEdges[2] = ringEntities[2][indexI];
3410 // Modify faceEdges for the hull face
3411 meshOps::replaceLabel
3413 ringEntities[2][indexI],
3414 addedEdgeIndices[indexI],
3415 faceEdges_[faceHull[indexI]]
3418 // Modify edgeFaces for the edge connected to newEdge[1]
3419 meshOps::replaceLabel
3422 addedFaceIndices[indexI],
3423 edgeFaces_[ringEntities[2][indexI]]
3426 // Add the faceEdges entry
3427 faceEdges_[addedFaceIndices[indexI]] = tmpFaceEdges;
3429 // Add an entry to edgeFaces
3430 edgeFaces_[newEdgeIndex][indexI] = addedFaceIndices[indexI];
3432 // Make the final entry for the previous cell
3433 cells_[addedCellIndices[prevI]][3] = addedFaceIndices[indexI];
3437 // Now that all old / new cells possess correct connectivity,
3438 // compute mapping information.
3439 forAll(cellHull, indexI)
3441 if (cellHull[indexI] == -1)
3446 // Set mapping for both new and modified cells.
3447 FixedList<label, 2> cmIndex;
3449 cmIndex[0] = cellHull[indexI];
3450 cmIndex[1] = addedCellIndices[indexI];
3452 // Fill-in candidate mapping information
3453 labelList mC(1, cellHull[indexI]);
3455 forAll(cmIndex, cmI)
3457 // Set the mapping for this cell
3458 setCellMapping(cmIndex[cmI], mC);
3462 // Set mapping information for old / new faces
3463 forAll(faceHull, indexI)
3465 // Interior faces get default mapping
3466 if (addedIntFaceIndices[indexI] > -1)
3468 setFaceMapping(addedIntFaceIndices[indexI]);
3471 // Decide between default / weighted mapping
3472 // based on boundary information
3473 if (whichPatch(faceHull[indexI]) == -1)
3475 // Interior faces get default mapping
3476 setFaceMapping(faceHull[indexI]);
3477 setFaceMapping(addedFaceIndices[indexI]);
3481 // Compute mapping weights for boundary faces
3482 FixedList<label, 2> fmIndex;
3484 fmIndex[0] = faceHull[indexI];
3485 fmIndex[1] = addedFaceIndices[indexI];
3487 // Fill-in candidate mapping information
3488 labelList mF(1, faceHull[indexI]);
3490 forAll(fmIndex, fmI)
3492 // Set the mapping for this face
3493 setFaceMapping(fmIndex[fmI], mF);
3498 // If modification is coupled, update mapping info.
3499 if (coupledModification_)
3501 // Build a list of boundary edges / faces for mapping
3502 dynamicLabelList checkEdges(8), checkFaces(4);
3504 const labelList& oeFaces = edgeFaces_[eIndex];
3505 const labelList& neFaces = edgeFaces_[newEdgeIndex];
3507 forAll(oeFaces, faceI)
3509 FixedList<label, 2> check(-1);
3511 check[0] = oeFaces[faceI];
3512 check[1] = neFaces[faceI];
3514 forAll(check, indexI)
3516 label cPatch = whichPatch(check[indexI]);
3518 if (localCouple && !procCouple)
3520 if (!locallyCoupledEntity(check[indexI], true, false, true))
3525 // Check for cyclics
3526 if (boundaryMesh()[cPatch].type() == "cyclic")
3528 // Check if this is a master face
3529 const coupleMap& cM = patchCoupling_[cPatch].map();
3530 const Map<label>& fM = cM.entityMap(coupleMap::FACE);
3532 // Only add master faces
3533 // (belonging to the first half)
3534 // - Only check[0] will be present,
3535 // so check for that alone
3536 if (!fM.found(check[0]))
3543 if (procCouple && !localCouple)
3545 if (getNeighbourProcessor(cPatch) == -1)
3551 // Add face and its edges for checking
3552 if (findIndex(checkFaces, check[indexI]) == -1)
3555 checkFaces.append(check[indexI]);
3557 const labelList& fEdges = faceEdges_[check[indexI]];
3559 forAll(fEdges, edgeI)
3561 if (findIndex(checkEdges, fEdges[edgeI]) == -1)
3563 checkEdges.append(fEdges[edgeI]);
3570 // Prepare a checklist
3571 boolList matchedFaces(checkFaces.size(), false);
3572 boolList matchedEdges(checkEdges.size(), false);
3574 // Output check entities
3579 "checkEdges_" + Foam::name(eIndex),
3580 checkEdges, 1, false, true
3585 "checkFaces_" + Foam::name(eIndex),
3586 checkFaces, 2, false, true
3590 forAll(slaveMaps, slaveI)
3592 // Alias for convenience...
3593 const changeMap& slaveMap = slaveMaps[slaveI];
3595 const label pI = slaveMap.patchIndex();
3597 // Fetch the appropriate coupleMap / mesh
3598 const coupleMap* cMapPtr = NULL;
3599 const dynamicTopoFvMesh* sMeshPtr = NULL;
3601 if (localCouple && !procCouple)
3603 cMapPtr = &(patchCoupling_[pI].map());
3607 if (procCouple && !localCouple)
3609 cMapPtr = &(recvMeshes_[pI].map());
3610 sMeshPtr = &(recvMeshes_[pI].subMesh());
3613 // Alias for convenience
3614 const coupleMap& cMap = *cMapPtr;
3615 const dynamicTopoFvMesh& sMesh = *sMeshPtr;
3617 // Add the new points to the coupling map
3618 const List<objectMap>& apList = slaveMap.addedPointList();
3620 // Fetch the slave point
3621 label slavePoint = -1;
3623 if ((slaveMap.index() == eIndex) && localCouple)
3625 // Cyclic edge at axis
3626 slavePoint = newPointIndex;
3630 slavePoint = apList[0].index();
3636 // Update reverse pointMap
3662 // Update reverse pointMap
3673 Pout<< " Adding point: " << slavePoint
3674 << " for point: " << newPointIndex
3678 // Obtain point maps
3679 const Map<label>& pointMap = cMap.entityMap(coupleMap::POINT);
3681 // Update face mapping
3682 const label faceEnum = coupleMap::FACE;
3684 // Obtain references
3685 Map<label>& faceMap = cMap.entityMap(faceEnum);
3686 Map<label>& rFaceMap = cMap.reverseEntityMap(faceEnum);
3688 forAll(checkFaces, faceI)
3690 label mfIndex = checkFaces[faceI];
3692 const face& mF = faces_[mfIndex];
3694 label mfPatch = whichPatch(mfIndex);
3696 // Check for processor match
3697 label neiProc = getNeighbourProcessor(mfPatch);
3699 if (procCouple && !localCouple)
3701 if (neiProc != procIndices_[pI])
3709 pointMap.found(mF[0]) ? pointMap[mF[0]] : -1,
3710 pointMap.found(mF[1]) ? pointMap[mF[1]] : -1,
3711 pointMap.found(mF[2]) ? pointMap[mF[2]] : -1
3714 // Skip mapping if all points were not found
3715 if (cF[0] == -1 || cF[1] == -1 || cF[2] == -1)
3720 // Fetch edges connected to the slave point
3721 const labelList& spEdges = sMesh.pointEdges_[slavePoint];
3723 forAll(spEdges, edgeI)
3725 label seIndex = spEdges[edgeI];
3727 if (sMesh.whichEdgePatch(seIndex) == -1)
3732 const labelList& seFaces = sMesh.edgeFaces_[seIndex];
3734 forAll(seFaces, faceJ)
3736 label sfIndex = seFaces[faceJ];
3738 if (sMesh.whichPatch(sfIndex) == -1)
3743 const face& sF = sMesh.faces_[sfIndex];
3749 triFace(sF[0], sF[1], sF[2]), cF
3755 word pN(boundaryMesh()[mfPatch].name());
3757 Pout<< " Found face: " << sfIndex
3759 << " with mfIndex: " << mfIndex
3765 if (rFaceMap.found(sfIndex))
3767 rFaceMap[sfIndex] = mfIndex;
3771 rFaceMap.insert(sfIndex, mfIndex);
3774 if (faceMap.found(mfIndex))
3776 faceMap[mfIndex] = sfIndex;
3780 faceMap.insert(mfIndex, sfIndex);
3783 matchedFaces[faceI] = true;
3789 if (matchedFaces[faceI])
3795 if ((debug > 4) && !matchedFaces[faceI])
3800 + Foam::name(mfIndex),
3801 labelList(cF), 0, false, true
3806 "checkFaces_" + Foam::name(eIndex),
3807 checkFaces, 2, false, true
3810 Pout<< " Failed to match face: "
3811 << mfIndex << " :: " << mF
3812 << " masterPatch: " << mfPatch
3813 << " using comparison face: " << cF
3814 << " on proc: " << procIndices_[pI]
3819 // Update edge mapping
3820 const label edgeEnum = coupleMap::EDGE;
3822 // Obtain references
3823 Map<label>& edgeMap = cMap.entityMap(edgeEnum);
3824 Map<label>& rEdgeMap = cMap.reverseEntityMap(edgeEnum);
3826 forAll(checkEdges, edgeI)
3828 label meIndex = checkEdges[edgeI];
3830 const edge& mE = edges_[meIndex];
3832 label mePatch = whichEdgePatch(meIndex);
3833 label neiProc = getNeighbourProcessor(mePatch);
3837 pointMap.found(mE[0]) ? pointMap[mE[0]] : -1,
3838 pointMap.found(mE[1]) ? pointMap[mE[1]] : -1
3841 // Skip mapping if all points were not found
3842 if (cE[0] == -1 || cE[1] == -1)
3847 // Fetch edges connected to the slave point
3848 const labelList& spEdges = sMesh.pointEdges_[cE[0]];
3850 forAll(spEdges, edgeJ)
3852 label seIndex = spEdges[edgeJ];
3854 const edge& sE = sMesh.edges_[seIndex];
3860 Pout<< " Found edge: " << seIndex
3862 << " with meIndex: " << meIndex
3864 << " on proc: " << procIndices_[pI]
3868 // Update reverse map
3869 if (rEdgeMap.found(seIndex))
3871 rEdgeMap[seIndex] = meIndex;
3875 rEdgeMap.insert(seIndex, meIndex);
3879 if (edgeMap.found(meIndex))
3881 edgeMap[meIndex] = seIndex;
3885 edgeMap.insert(meIndex, seIndex);
3888 matchedEdges[edgeI] = true;
3894 if (!matchedEdges[edgeI])
3896 if (procCouple && !localCouple)
3898 // Rare occassion where both points
3899 // of the edge lie on processor, but
3900 // not the edge itself.
3901 if (neiProc != procIndices_[pI])
3905 Pout<< " Edge: " << meIndex
3907 << " with comparison: " << cE
3908 << " has points on processor: " << neiProc
3909 << " but no edge. Marking as matched."
3913 matchedEdges[edgeI] = true;
3918 if ((debug > 4) && !matchedEdges[edgeI])
3923 + Foam::name(meIndex),
3924 labelList(cE), 0, false, true
3929 "checkEdges_" + Foam::name(eIndex),
3930 checkEdges, 1, false, true
3933 Pout<< " Failed to match edge: "
3934 << meIndex << " :: " << mE
3935 << " using comparison edge: " << cE
3936 << " on proc: " << procIndices_[pI]
3941 // Push operation into coupleMap
3942 if (procCouple && !localCouple)
3947 coupleMap::BISECTION
3952 // Ensure that all entities were matched
3953 label nFailFace = 0, nFailEdge = 0;
3955 forAll(matchedFaces, faceI)
3957 if (!matchedFaces[faceI])
3963 forAll(matchedEdges, edgeI)
3965 if (!matchedEdges[edgeI])
3971 if (nFailFace || nFailEdge)
3973 Pout<< " Failed to match all entities. " << nl
3974 << " Faces: " << nFailFace << nl
3975 << " Edges: " << nFailEdge << nl
3976 << abort(FatalError);
3982 label bPatch = whichEdgePatch(eIndex);
3984 const polyBoundaryMesh& boundary = boundaryMesh();
3988 Pout<< "Patch: Internal" << nl;
3991 if (bPatch < boundary.size())
3993 Pout<< "Patch: " << boundary[bPatch].name() << nl;
3997 Pout<< " New patch: " << bPatch << endl;
4000 Pout<< "vertexHull: " << vertexHull << nl
4001 << "Edges: " << edgeHull << nl
4002 << "Faces: " << faceHull << nl
4003 << "Cells: " << cellHull << nl;
4005 Pout<< "Modified cells: " << nl;
4007 forAll(cellHull, cellI)
4009 if (cellHull[cellI] == -1)
4014 Pout<< cellHull[cellI] << ":: "
4015 << cells_[cellHull[cellI]]
4019 Pout<< nl << "Added cells: " << nl;
4021 forAll(addedCellIndices, cellI)
4023 if (addedCellIndices[cellI] == -1)
4028 Pout<< addedCellIndices[cellI] << ":: "
4029 << cells_[addedCellIndices[cellI]] << nl
4030 << "lengthScale: " << lengthScale_[addedCellIndices[cellI]]
4034 Pout<< nl << "Modified faces: " << nl;
4036 forAll(faceHull, faceI)
4038 Pout<< faceHull[faceI] << ":: "
4039 << faces_[faceHull[faceI]] << ": "
4040 << owner_[faceHull[faceI]] << ": "
4041 << neighbour_[faceHull[faceI]] << " "
4042 << "faceEdges:: " << faceEdges_[faceHull[faceI]]
4046 Pout<< nl << "Added faces: " << nl;
4048 forAll(addedFaceIndices, faceI)
4050 Pout<< addedFaceIndices[faceI] << ":: "
4051 << faces_[addedFaceIndices[faceI]] << ": "
4052 << owner_[addedFaceIndices[faceI]] << ": "
4053 << neighbour_[addedFaceIndices[faceI]] << " "
4054 << "faceEdges:: " << faceEdges_[addedFaceIndices[faceI]]
4058 forAll(addedIntFaceIndices, faceI)
4060 if (addedIntFaceIndices[faceI] == -1)
4065 Pout<< addedIntFaceIndices[faceI] << ":: "
4066 << faces_[addedIntFaceIndices[faceI]] << ": "
4067 << owner_[addedIntFaceIndices[faceI]] << ": "
4068 << neighbour_[addedIntFaceIndices[faceI]] << " "
4069 << "faceEdges:: " << faceEdges_[addedIntFaceIndices[faceI]]
4073 Pout<< nl << "New edge:: " << newEdgeIndex
4074 << ": " << edges_[newEdgeIndex] << nl
4075 << " edgeFaces:: " << edgeFaces_[newEdgeIndex]
4078 Pout<< nl << "Added edges: " << nl;
4080 forAll(addedEdgeIndices, edgeI)
4082 Pout<< addedEdgeIndices[edgeI]
4083 << ":: " << edges_[addedEdgeIndices[edgeI]] << nl
4084 << " edgeFaces:: " << edgeFaces_[addedEdgeIndices[edgeI]]
4088 Pout<< "New Point:: " << newPointIndex << nl
4089 << "pointEdges:: " << pointEdges_[newPointIndex] << nl;
4094 // Write out VTK files after change
4097 labelList newHull(cellHull.size() + addedCellIndices.size(), 0);
4099 // Combine both lists into one.
4102 newHull[i] = cellHull[i];
4105 label start = cellHull.size();
4107 for(label i = start; i < newHull.size(); i++)
4109 newHull[i] = addedCellIndices[i - start];
4112 // Write out VTK files after change
4113 // - Using old-points for convenience in post-processing
4117 + '(' + Foam::name(origEdge[0])
4118 + ',' + Foam::name(origEdge[1]) + ')'
4127 topoChangeFlag_ = true;
4129 // Increment the counter
4130 status(TOTAL_BISECTIONS)++;
4132 // Increment the number of modifications
4133 status(TOTAL_MODIFICATIONS)++;
4135 // Specify that the operation was successful
4138 // Return the changeMap
4143 // Utility method to compute the quality of a
4144 // vertex hull around an edge after bisection.
4145 scalar dynamicTopoFvMesh::computeBisectionQuality
4150 scalar minQuality = GREAT, minVolume = GREAT;
4151 scalar cQuality = 0.0, oldVolume = 0.0;
4153 // Obtain a reference to this edge
4154 const edge& edgeToCheck = edges_[eIndex];
4156 // Obtain point references
4157 const point& a = points_[edgeToCheck[0]];
4158 const point& c = points_[edgeToCheck[1]];
4160 const point& aOld = oldPoints_[edgeToCheck[0]];
4161 const point& cOld = oldPoints_[edgeToCheck[1]];
4163 // Compute the mid-point of the edge
4164 point midPoint = 0.5 * (a + c);
4165 point oldPoint = 0.5 * (aOld + cOld);
4167 dynamicLabelList eCells(10);
4169 const labelList& eFaces = edgeFaces_[eIndex];
4171 // Accumulate cells connected to this edge
4172 forAll(eFaces, faceI)
4174 label own = owner_[eFaces[faceI]];
4175 label nei = neighbour_[eFaces[faceI]];
4177 if (findIndex(eCells, own) == -1)
4187 if (findIndex(eCells, nei) == -1)
4193 // Loop through all cells and compute quality
4194 forAll(eCells, cellI)
4196 label cellIndex = eCells[cellI];
4198 const cell& checkCell = cells_[cellIndex];
4200 // Find two faces that don't contain the edge
4201 forAll(checkCell, faceI)
4203 const face& checkFace = faces_[checkCell[faceI]];
4205 bool check0 = (findIndex(checkFace, edgeToCheck[0]) == -1);
4206 bool check1 = (findIndex(checkFace, edgeToCheck[1]) == -1);
4208 if ((check0 && !check1) || (!check0 && check1))
4210 // Check orientation
4211 if (owner_[checkCell[faceI]] == cellIndex)
4217 points_[checkFace[2]],
4218 points_[checkFace[1]],
4219 points_[checkFace[0]],
4228 oldPoints_[checkFace[2]],
4229 oldPoints_[checkFace[1]],
4230 oldPoints_[checkFace[0]],
4241 points_[checkFace[0]],
4242 points_[checkFace[1]],
4243 points_[checkFace[2]],
4252 oldPoints_[checkFace[0]],
4253 oldPoints_[checkFace[1]],
4254 oldPoints_[checkFace[2]],
4260 // Check if the quality is worse
4261 minQuality = Foam::min(cQuality, minQuality);
4262 minVolume = Foam::min(oldVolume, minVolume);
4267 // Ensure that the mesh is valid
4268 if (minQuality < sliverThreshold_)
4270 if (debug > 3 && minQuality < 0.0)
4272 writeVTK(Foam::name(eIndex) + "_iCells", eCells);
4279 "scalar dynamicTopoFvMesh::computeBisectionQuality"
4280 "(const label eIndex) const"
4282 << " Bisecting edge will fall below the"
4283 << " sliver threshold of: " << sliverThreshold_ << nl
4284 << " Edge: " << eIndex << ": " << edgeToCheck << nl
4285 << " Minimum Quality: " << minQuality << nl
4286 << " Minimum Volume: " << minVolume << nl
4287 << " Mid point: " << midPoint << nl
4288 << " Old point: " << oldPoint << nl
4293 // If a negative old-volume was encountered,
4294 // return an invalid quality.
4295 if (minVolume < 0.0)
4304 // Slice the mesh at a particular location
4305 void dynamicTopoFvMesh::sliceMesh
4307 const labelPair& pointPair
4313 << "Pair: " << pointPair
4314 << " is to be used for mesh slicing. " << endl;
4317 label patchIndex = -1;
4319 vector gCentre = vector::zero;
4320 FixedList<vector, 2> fC(vector::zero);
4324 patchIndex = whichPatch(pointPair.first());
4326 // Fetch face centres
4327 fC[0] = faces_[pointPair.first()].centre(points_);
4328 fC[1] = faces_[pointPair.second()].centre(points_);
4332 // Find the patch that the edge-vertex is connected to.
4333 const labelList& pEdges = pointEdges_[pointPair.first()];
4335 forAll(pEdges, edgeI)
4337 if ((patchIndex = whichEdgePatch(pEdges[edgeI])) > -1)
4343 fC[0] = points_[pointPair.first()];
4344 fC[1] = points_[pointPair.second()];
4347 linePointRef lpr(fC[0], fC[1]);
4349 // Specify the centre.
4350 gCentre = lpr.centre();
4352 // Specify a search distance
4355 // Is this edge in the vicinity of a previous slice-point?
4356 if (lengthEstimator().checkOldSlices(gCentre))
4361 << "Pair: " << pointPair
4362 << " is too close to another slice point. "
4366 // Too close to another slice-point. Bail out.
4370 // Choose a box around the centre and scan all
4371 // surface entities that fall into this region.
4374 gCentre - vector(dx, dx, dx),
4375 gCentre + vector(dx, dx, dx)
4378 vector p = vector::zero, N = vector::zero;
4379 Map<vector> checkPoints, surfFaces;
4380 Map<edge> checkEdges;
4384 // Assign plane point / normal
4387 vector gNorm = faces_[pointPair.first()].normal(points_);
4389 gNorm /= (mag(gNorm) + VSMALL);
4391 // Since this is 2D, assume XY-plane here.
4392 N = (gNorm ^ vector(0.0, 0.0, 1.0));
4396 // Prepare surface points / edges for Dijkstra's algorithm
4397 for (label edgeI = nOldInternalEdges_; edgeI < nEdges_; edgeI++)
4399 if (edgeFaces_[edgeI].empty())
4404 if (whichEdgePatch(edgeI) == patchIndex)
4406 const edge& surfaceEdge = edges_[edgeI];
4410 (bBox.contains(points_[surfaceEdge[0]])) &&
4411 (bBox.contains(points_[surfaceEdge[1]]))
4414 checkEdges.insert(edgeI, surfaceEdge);
4416 if (!checkPoints.found(surfaceEdge[0]))
4421 points_[surfaceEdge[0]]
4425 if (!checkPoints.found(surfaceEdge[1]))
4430 points_[surfaceEdge[1]]
4434 // Add surface faces as well.
4435 const labelList& eFaces = edgeFaces_[edgeI];
4437 forAll(eFaces, faceI)
4441 (neighbour_[eFaces[faceI]] == -1) &&
4442 (!surfFaces.found(eFaces[faceI]))
4447 faces_[eFaces[faceI]].normal(points_)
4450 surfFaces.insert(eFaces[faceI], surfNorm);
4460 << " Point [0]: " << points_[pointPair.first()] << nl
4461 << " Point [1]: " << points_[pointPair.second()] << endl;
4465 writeVTK("slicePoints", checkPoints.toc(), 0);
4466 writeVTK("sliceEdges", checkEdges.toc(), 1);
4470 // Find the shortest path using Dijkstra's algorithm.
4471 Map<label> shortestPath;
4485 // First normalize all face-normals
4486 forAllIter(Map<vector>, surfFaces, sIter)
4488 sIter() /= (mag(sIter()) + VSMALL);
4493 // Next, take cross-products with every other
4494 // vector in the list, and accumulate.
4495 forAllIter(Map<vector>, surfFaces, sIterI)
4497 forAllIter(Map<vector>, surfFaces, sIterJ)
4499 if (sIterI.key() != sIterJ.key())
4501 vector n = (sIterI() ^ sIterJ());
4503 n /= (mag(n) + VSMALL);
4505 // Reverse the vector if necessary
4516 N /= (mag(N) + VSMALL);
4518 // Obtain point position
4523 // Probably a membrane-type configuration.
4524 labelHashSet checkCells;
4526 // Prepare a bounding cylinder with radius dx.
4527 forAllIter(Map<vector>, surfFaces, sIter)
4529 const face& thisFace = faces_[sIter.key()];
4531 if (thisFace.which(pointPair.first()) > -1)
4537 // Normalize and reverse.
4538 N /= -(mag(N) + VSMALL);
4540 vector a0 = points_[pointPair.first()];
4541 vector a1 = points_[pointPair.second()];
4542 scalar dist = mag(a1 - a0);
4544 forAll(cells_, cellI)
4546 if (cells_[cellI].empty())
4552 vector x = vector::zero;
4554 meshOps::cellCentreAndVolume
4565 vector rx = (x - a0);
4566 vector ra = (rx & N)*N;
4568 // Check if point falls off cylinder ends.
4569 if (mag(ra) > dist || mag(ra) < 0.0)
4574 vector r = (rx - ra);
4576 // Check if the magnitude of 'r' is within radius.
4579 checkCells.insert(cellI);
4583 labelList cList = checkCells.toc();
4587 Pout<< "Dijkstra's algorithm could not find a path." << endl;
4591 writeVTK("checkCells", cList, 3);
4595 changeMap sliceMap =
4602 + Foam::name(pointPair.first()) + '_'
4603 + Foam::name(pointPair.second())
4609 checkConnectivity(10);
4612 // Accumulate a list of projection points
4613 labelHashSet pPoints;
4615 const List<objectMap>& afList = sliceMap.addedFaceList();
4617 forAll(afList, faceI)
4619 const face& thisFace = faces_[afList[faceI].index()];
4621 forAll(thisFace, pointI)
4623 if (!pPoints.found(thisFace[pointI]))
4625 pPoints.insert(thisFace[pointI]);
4630 // Now project points in a series of intermediate steps.
4632 // Add an entry to sliceBoxes.
4633 lengthEstimator().appendBox(bBox);
4642 << " Plane point: " << p << nl
4643 << " Plane normal: " << N << endl;
4646 // Mark cells and interior faces that fall
4647 // within the bounding box.
4648 labelHashSet checkCells, checkFaces, splitFaces;
4649 Map<bool> cellColors;
4651 forAll(faces_, faceI)
4653 if (faces_[faceI].empty())
4658 if (is2D() && faces_[faceI].size() == 3)
4663 vector fCentre = faces_[faceI].centre(points_);
4665 FixedList<label, 2> cellsToCheck(-1);
4666 cellsToCheck[0] = owner_[faceI];
4667 cellsToCheck[1] = neighbour_[faceI];
4669 if (bBox.contains(fCentre) && cellsToCheck[1] != -1)
4671 // Add this internal face to the list.
4672 checkFaces.insert(faceI);
4674 scalar volume = 0.0;
4675 vector centre = vector::zero;
4677 forAll(cellsToCheck, cellI)
4679 if (!checkCells.found(cellsToCheck[cellI]))
4681 meshOps::cellCentreAndVolume
4683 cellsToCheck[cellI],
4692 checkCells.insert(cellsToCheck[cellI]);
4694 if (((centre - p) & N) > 0.0)
4696 cellColors.insert(cellsToCheck[cellI], true);
4700 cellColors.insert(cellsToCheck[cellI], false);
4707 // Prepare a list of internal faces for mesh splitting.
4708 forAllIter(labelHashSet, checkFaces, fIter)
4712 cellColors[owner_[fIter.key()]]
4713 != cellColors[neighbour_[fIter.key()]]
4716 splitFaces.insert(fIter.key());
4719 // Loop through all points (and associated pointEdges)
4720 // for this face, and check if connected cells are also
4721 // present in the checkCells/cellColors list
4724 const labelList& fEdges = faceEdges_[fIter.key()];
4726 forAll(fEdges, edgeI)
4728 const labelList& eFaces = edgeFaces_[fEdges[edgeI]];
4730 forAll(eFaces, faceI)
4732 label own = owner_[eFaces[faceI]];
4733 label nei = neighbour_[eFaces[faceI]];
4735 if (!checkCells.found(own))
4737 scalar volume = 0.0;
4738 vector centre = vector::zero;
4740 meshOps::cellCentreAndVolume
4751 checkCells.insert(own);
4753 if (((centre - p) & N) > 0.0)
4755 cellColors.insert(own, true);
4759 cellColors.insert(own, false);
4763 if (!checkCells.found(nei) && nei != -1)
4765 scalar volume = 0.0;
4766 vector centre = vector::zero;
4768 meshOps::cellCentreAndVolume
4779 checkCells.insert(nei);
4781 if (((centre - p) & N) > 0.0)
4783 cellColors.insert(nei, true);
4787 cellColors.insert(nei, false);
4795 const face& faceToCheck = faces_[fIter.key()];
4797 forAll(faceToCheck, pointI)
4799 const labelList& pEdges = pointEdges_[faceToCheck[pointI]];
4801 forAll(pEdges, edgeI)
4803 const labelList& eFaces = edgeFaces_[pEdges[edgeI]];
4805 forAll(eFaces, faceI)
4807 label own = owner_[eFaces[faceI]];
4808 label nei = neighbour_[eFaces[faceI]];
4810 if (!checkCells.found(own))
4812 scalar volume = 0.0;
4813 vector centre = vector::zero;
4815 meshOps::cellCentreAndVolume
4826 checkCells.insert(own);
4828 if (((centre - p) & N) > 0.0)
4830 cellColors.insert(own, true);
4834 cellColors.insert(own, false);
4838 if (!checkCells.found(nei) && nei != -1)
4840 scalar volume = 0.0;
4841 vector centre = vector::zero;
4843 meshOps::cellCentreAndVolume
4854 checkCells.insert(nei);
4856 if (((centre - p) & N) > 0.0)
4858 cellColors.insert(nei, true);
4862 cellColors.insert(nei, false);
4873 writeVTK("splitFaces", splitFaces.toc(), 2);
4874 writeVTK("checkCells", checkCells.toc(), 3);
4877 // Pass this info into the splitInternalFaces routine.
4885 // Add an entry to sliceBoxes.
4886 lengthEstimator().appendBox(bBox);
4890 // Add cell layer above specified patch
4891 const changeMap dynamicTopoFvMesh::addCellLayer
4898 // Maps for added entities
4899 Map<label> addedPoints;
4900 Map<label> addedHEdges, addedVEdges, currentVEdges;
4901 Map<label> addedHFaces, addedVFaces, currentVFaces;
4902 Map<labelPair> addedCells;
4904 // Allocate a list of patch faces
4905 dynamicLabelList patchFaces(patchSizes_[patchID]);
4907 // Loop through all patch faces and create a cell for each
4908 for (label faceI = nOldInternalFaces_; faceI < faces_.size(); faceI++)
4910 label pIndex = whichPatch(faceI);
4912 if (pIndex != patchID)
4917 // Add face to the list
4918 patchFaces.append(faceI);
4921 label cIndex = owner_[faceI];
4922 scalar newLengthScale = -1.0;
4923 const cell& ownCell = cells_[cIndex];
4925 if (edgeRefinement_)
4927 newLengthScale = lengthScale_[cIndex];
4930 label newCellIndex =
4934 cell(ownCell.size()),
4940 map.addCell(newCellIndex, labelList(1, cIndex));
4941 addedCells.insert(cIndex, labelPair(newCellIndex, 0));
4944 labelList mP(2, -1);
4946 forAll(patchFaces, indexI)
4948 label faceI = patchFaces[indexI];
4949 label cIndex = owner_[faceI];
4951 // Fetch appropriate face / cell
4952 // - Make copies, since holding references
4953 // to data within this loop is unsafe.
4954 const face bFace = faces_[faceI];
4955 const cell ownCell = cells_[cIndex];
4957 // Configure a new face for insertion
4958 face newHFace(bFace);
4959 labelList newHFaceEdges(bFace.size(), -1);
4961 // Get the opposing face from the cell
4962 oppositeFace oFace = ownCell.opposingFace(faceI, faces_);
4966 // Something's wrong here.
4969 "const changeMap dynamicTopoFvMesh::addCellLayer"
4970 "(const label patchID)"
4972 << " Face: " << faceI << " :: " << bFace << nl
4973 << " has no opposing face in cell: "
4974 << cIndex << " :: " << ownCell << nl
4975 << abort(FatalError);
4979 forAll(bFace, pointI)
4981 label pIndex = bFace[pointI];
4983 // Skip if we've added this already
4984 if (addedPoints.found(pIndex))
4989 // Set master points
4991 mP[1] = oFace[pointI];
4993 label newPointIndex =
4997 0.5 * (points_[mP[0]] + points_[mP[1]]),
5004 map.addPoint(newPointIndex, mP);
5005 addedPoints.insert(pIndex, newPointIndex);
5008 // Fetch faceEdges from opposite faces.
5009 // - Make copies, since holding references is unsafe
5010 const labelList bfEdges = faceEdges_[faceI];
5011 const labelList ofEdges = faceEdges_[oFace.oppositeIndex()];
5013 // Create edges for each edge of the new horizontal face
5014 forAll(bfEdges, edgeI)
5016 label beIndex = bfEdges[edgeI];
5018 // Skip if we've added this already
5019 if (addedHEdges.found(beIndex))
5021 // Update face edges for the new horizontal face
5022 newHFaceEdges[edgeI] = addedHEdges[beIndex];
5027 // Configure the new edge
5029 const edge bEdge = edges_[beIndex];
5031 // Build an edge for comparison
5034 oFace[bFace.which(bEdge[0])],
5035 oFace[bFace.which(bEdge[1])]
5038 forAll(ofEdges, edgeJ)
5040 const edge& ofEdge = edges_[ofEdges[edgeJ]];
5042 if (cEdge == ofEdge)
5044 oeIndex = ofEdges[edgeJ];
5053 "const changeMap dynamicTopoFvMesh::addCellLayer"
5054 "(const label patchID)"
5056 << " Could not find comparison edge: " << cEdge
5057 << " for edge: " << bEdge
5058 << abort(FatalError);
5061 // Fetch patch information
5062 label hEdgePatch = whichEdgePatch(oeIndex);
5067 addedPoints[bEdge[0]],
5068 addedPoints[bEdge[1]]
5071 // Insert a new edge with empty edgeFaces
5072 label newHEdgeIndex =
5083 map.addEdge(newHEdgeIndex);
5084 addedHEdges.insert(beIndex, newHEdgeIndex);
5086 // Update face edges for the new horizontal face
5087 newHFaceEdges[edgeI] = newHEdgeIndex;
5089 // Add a new vertical face for this edge
5090 label vFaceIndex = -1;
5092 // Find a vertical face that contains both edges
5093 const labelList& beFaces = edgeFaces_[beIndex];
5095 forAll(beFaces, faceJ)
5097 const labelList& testEdges = faceEdges_[beFaces[faceJ]];
5101 (findIndex(testEdges, beIndex) > -1) &&
5102 (findIndex(testEdges, oeIndex) > -1)
5105 vFaceIndex = beFaces[faceJ];
5114 "const changeMap dynamicTopoFvMesh::addCellLayer"
5115 "(const label patchID)"
5117 << " Could not find an appropriate vertical face"
5118 << " containing edges: " << oeIndex
5119 << " and " << beIndex
5120 << abort(FatalError);
5123 // Find two vertical edges on this face
5124 const labelList& vfEdges = faceEdges_[vFaceIndex];
5126 forAll(vfEdges, edgeJ)
5128 const edge& vfEdge = edges_[vfEdges[edgeJ]];
5132 if (vfEdge == edge(bEdge[i], cEdge[i]))
5134 // Skip if we've added this already
5135 if (addedVEdges.found(bEdge[i]))
5140 label veIndex = vfEdges[edgeJ];
5142 // Fetch edge patch information
5143 label vEdgePatch = whichEdgePatch(veIndex);
5149 addedPoints[bEdge[i]]
5152 // Insert a new edge with empty edgeFaces
5153 label newVEdgeIndex =
5164 map.addEdge(newVEdgeIndex);
5165 addedVEdges.insert(bEdge[i], newVEdgeIndex);
5167 // Note edge indices for later renumbering
5168 currentVEdges.insert(bEdge[i], veIndex);
5173 // Configure the new vertical face
5174 face newVFace(faces_[vFaceIndex]);
5175 label newOwner = -1, newNeighbour = -1;
5177 label oldOwner = owner_[vFaceIndex];
5178 label oldNeighbour = neighbour_[vFaceIndex];
5180 // Fetch owner / neighbour
5181 newOwner = addedCells[oldOwner].first();
5183 if (oldNeighbour > -1)
5185 newNeighbour = addedCells[oldNeighbour].first();
5188 // Replace point indices on the new face
5191 meshOps::replaceLabel
5194 addedPoints[bEdge[i]],
5199 // Note face indices for later renumbering
5200 currentVFaces.insert(beIndex, vFaceIndex);
5202 // Check if reversal is necessary
5203 if ((newNeighbour < newOwner) && (newNeighbour > -1))
5206 newVFace = newVFace.reverseFace();
5209 Foam::Swap(newOwner, newNeighbour);
5210 Foam::Swap(oldOwner, oldNeighbour);
5213 // Configure faceEdges for the new vertical face
5214 labelList newVFaceEdges(4, -1);
5216 newVFaceEdges[0] = beIndex;
5217 newVFaceEdges[1] = newHEdgeIndex;
5218 newVFaceEdges[2] = addedVEdges[bEdge[0]];
5219 newVFaceEdges[3] = addedVEdges[bEdge[1]];
5221 // Add the new vertical face
5222 label newVFaceIndex =
5226 whichPatch(vFaceIndex),
5235 map.addFace(newVFaceIndex, labelList(1, vFaceIndex));
5236 addedVFaces.insert(beIndex, newVFaceIndex);
5238 // Update face count on the new cells
5239 cells_[newOwner][addedCells[oldOwner].second()++] =
5244 if (newNeighbour > -1)
5246 cells_[newNeighbour][addedCells[oldNeighbour].second()++] =
5252 // Size up edgeFaces for each edge
5253 forAll(newVFaceEdges, edgeJ)
5255 label vfeIndex = newVFaceEdges[edgeJ];
5260 edgeFaces_[vfeIndex]
5265 // Add a new interior face, with identical orientation
5266 forAll(newHFace, pointI)
5268 newHFace[pointI] = addedPoints[newHFace[pointI]];
5271 // Add the new horizontal face
5272 label newHFaceIndex =
5279 addedCells[cIndex].first(),
5285 map.addFace(newHFaceIndex, labelList(1, faceI));
5286 addedHFaces.insert(faceI, newHFaceIndex);
5288 // Replace index on the old cell
5289 meshOps::replaceLabel
5296 // Update face count on the new cell
5297 label newCellIndex = addedCells[cIndex].first();
5299 // Modify owner for the existing boundary face
5300 owner_[faceI] = newCellIndex;
5302 cells_[newCellIndex][addedCells[cIndex].second()++] = faceI;
5303 cells_[newCellIndex][addedCells[cIndex].second()++] = newHFaceIndex;
5305 // Size up edgeFaces for each edge
5306 forAll(newHFaceEdges, edgeI)
5308 label hfeIndex = newHFaceEdges[edgeI];
5313 edgeFaces_[hfeIndex]
5318 // Renumber vertical edges
5319 forAllConstIter(Map<label>, currentVEdges, eIter)
5321 // Fetch reference to edge
5322 edge& curEdge = edges_[eIter()];
5324 if (curEdge[0] == eIter.key())
5326 curEdge[0] = addedPoints[eIter.key()];
5329 if (curEdge[1] == eIter.key())
5331 curEdge[1] = addedPoints[eIter.key()];
5334 // Size down pointEdges
5337 meshOps::sizeDownList
5340 pointEdges_[eIter.key()]
5346 pointEdges_[addedPoints[eIter.key()]]
5351 // Renumber vertical faces
5352 forAllConstIter(Map<label>, currentVFaces, fIter)
5354 // Fetch reference to existing edge
5355 const edge& bEdge = edges_[fIter.key()];
5357 // Replace point indices on vertical face
5360 meshOps::replaceLabel
5363 addedPoints[bEdge[i]],
5368 // Replace edge on the existing vertical face
5369 meshOps::replaceLabel
5372 addedHEdges[fIter.key()],
5376 // Remove old face on existing boundary edge
5377 meshOps::sizeDownList
5380 edgeFaces_[fIter.key()]
5383 // Add old face to new horizontal edge
5387 edgeFaces_[addedHEdges[fIter.key()]]
5391 // Now that all old / new cells possess correct connectivity,
5392 // compute mapping information.
5393 const List<objectMap>& afList = map.addedFaceList();
5395 forAll(afList, indexI)
5397 label parent = afList[indexI].masterObjects()[0];
5399 if (whichPatch(afList[indexI].index()) == -1)
5401 // Interior faces get default mapping
5402 if (whichPatch(parent) == -1)
5404 setFaceMapping(parent);
5407 setFaceMapping(afList[indexI].index());
5412 topoChangeFlag_ = true;
5414 // Specify that the operation was successful
5417 // Return the changeMap
5422 // Split a set of internal faces into boundary faces
5423 // - Add boundary faces and edges to the patch specified by 'patchIndex'
5424 // - Cell color should specify a binary value dictating either side
5425 // of the split face.
5426 void dynamicTopoFvMesh::splitInternalFaces
5428 const label patchIndex,
5429 const labelList& internalFaces,
5430 const Map<bool>& cellColors
5433 Map<label> mirrorPointLabels;
5434 FixedList<Map<label>, 2> mirrorEdgeLabels, mirrorFaceLabels;
5436 // First loop through the list and accumulate a list of
5437 // points and edges that need to be duplicated.
5438 forAll(internalFaces, faceI)
5440 const face& faceToCheck = faces_[internalFaces[faceI]];
5442 forAll(faceToCheck, pointI)
5444 if (!mirrorPointLabels.found(faceToCheck[pointI]))
5446 mirrorPointLabels.insert(faceToCheck[pointI], -1);
5450 const labelList& fEdges = faceEdges_[internalFaces[faceI]];
5452 forAll(fEdges, edgeI)
5454 if (!mirrorEdgeLabels[0].found(fEdges[edgeI]))
5456 mirrorEdgeLabels[0].insert(fEdges[edgeI], -1);
5461 // Now for every point in the list, add a new one.
5462 // Add a mapping entry as well.
5463 forAllIter(Map<label>, mirrorPointLabels, pIter)
5465 // Obtain a copy of the point before adding it,
5466 // since the reference might become invalid during list resizing.
5467 point newPoint = points_[pIter.key()];
5468 point oldPoint = oldPoints_[pIter.key()];
5470 pIter() = insertPoint(newPoint, oldPoint, labelList(1, pIter.key()));
5474 const labelList& pEdges = pointEdges_[pIter.key()];
5476 labelHashSet edgesToRemove;
5478 forAll(pEdges, edgeI)
5480 const labelList& eFaces = edgeFaces_[pEdges[edgeI]];
5482 bool allTrue = true;
5484 forAll(eFaces, faceI)
5486 label own = owner_[eFaces[faceI]];
5487 label nei = neighbour_[eFaces[faceI]];
5489 // Check if an owner/neighbour cell is false
5490 if (!cellColors[own])
5498 if (!cellColors[nei])
5508 // Mark this edge label to be discarded later
5509 edgesToRemove.insert(pEdges[edgeI]);
5513 // It is dangerous to use the pointEdges references,
5514 // so call it using array-lookup instead.
5515 forAllIter(labelHashSet, edgesToRemove, hsIter)
5517 // Add the edge to the mirror point list
5521 pointEdges_[pIter()]
5524 // Remove the edge from the original point list
5525 meshOps::sizeDownList
5528 pointEdges_[pIter.key()]
5537 labelList mPoints(mirrorPointLabels.size());
5541 forAllIter(Map<label>, mirrorPointLabels, pIter)
5545 "pEdges_o_" + Foam::name(pIter.key()) + '_',
5546 pointEdges_[pIter.key()],
5552 "pEdges_m_" + Foam::name(pIter()) + '_',
5553 pointEdges_[pIter()],
5557 mPoints[i++] = pIter();
5563 mirrorPointLabels.toc(),
5576 // For every internal face, add a new one.
5577 // - Stick to the rule:
5578 // [1] Every cell marked false keeps the existing entities.
5579 // [2] Every cell marked true gets new points/edges/faces.
5580 // - If faces are improperly oriented, reverse them.
5581 forAll(internalFaces, faceI)
5583 FixedList<face, 2> newFace;
5584 FixedList<label, 2> newFaceIndex(-1);
5585 FixedList<label, 2> newOwner(-1);
5587 label oldOwn = owner_[internalFaces[faceI]];
5588 label oldNei = neighbour_[internalFaces[faceI]];
5590 if (cellColors[oldOwn] && !cellColors[oldNei])
5592 // The owner gets a new boundary face.
5593 // Note that orientation is already correct.
5594 newFace[0] = faces_[internalFaces[faceI]];
5596 // The neighbour needs to have its face reversed
5597 // and moved to the boundary patch, thereby getting
5598 // deleted in the process.
5599 newFace[1] = newFace[0].reverseFace();
5601 newOwner[0] = oldOwn;
5602 newOwner[1] = oldNei;
5605 if (!cellColors[oldOwn] && cellColors[oldNei])
5607 // The neighbour gets a new boundary face.
5608 // The face is oriented in the opposite sense, however.
5609 newFace[0] = faces_[internalFaces[faceI]].reverseFace();
5611 // The owner keeps the existing face and orientation.
5612 // But it also needs to be moved to the boundary.
5613 newFace[1] = faces_[internalFaces[faceI]];
5615 newOwner[0] = oldNei;
5616 newOwner[1] = oldOwn;
5620 // Something's wrong here.
5623 "dynamicTopoFvMesh::splitInternalFaces\n"
5625 " const label patchIndex,\n"
5626 " const labelList& internalFaces,\n"
5627 " const Map<bool>& cellColors\n"
5631 << internalFaces[faceI]
5632 << " has cells which are improperly marked: " << nl
5633 << oldOwn << ":: " << cellColors[oldOwn] << nl
5634 << oldNei << ":: " << cellColors[oldNei]
5635 << abort(FatalError);
5638 // Renumber point labels for the first new face.
5639 forAll(newFace[0], pointI)
5641 newFace[0][pointI] = mirrorPointLabels[newFace[0][pointI]];
5644 // Insert the new boundary faces.
5645 forAll(newFace, indexI)
5647 // Make an identical faceEdges entry.
5648 // This will be renumbered once new edges are added.
5649 labelList newFaceEdges(faceEdges_[internalFaces[faceI]]);
5651 newFaceIndex[indexI] =
5663 // Replace face labels on cells
5664 meshOps::replaceLabel
5666 internalFaces[faceI],
5667 newFaceIndex[indexI],
5668 cells_[newOwner[indexI]]
5671 // Make face mapping entries for posterity.
5672 mirrorFaceLabels[indexI].insert
5674 internalFaces[faceI],
5675 newFaceIndex[indexI]
5680 // For every edge in the list, add a new one.
5681 // We'll deal with correcting edgeFaces later.
5682 forAllIter(Map<label>, mirrorEdgeLabels[0], eIter)
5684 // Obtain copies for the append method
5685 edge origEdge = edges_[eIter.key()];
5686 labelList newEdgeFaces(edgeFaces_[eIter.key()]);
5695 mirrorPointLabels[origEdge[0]],
5696 mirrorPointLabels[origEdge[1]]
5702 // Is the original edge an internal one?
5703 // If it is, we need to move it to the boundary.
5704 if (whichEdgePatch(eIter.key()) == -1)
5706 label rplEdgeIndex =
5716 // Map the new entry.
5717 mirrorEdgeLabels[1].insert(eIter.key(), rplEdgeIndex);
5721 // This is already a boundary edge.
5722 // Make an identical map.
5723 mirrorEdgeLabels[1].insert(eIter.key(), eIter.key());
5727 // Correct edgeFaces for all new edges
5728 forAll(mirrorEdgeLabels, indexI)
5730 forAllIter(Map<label>, mirrorEdgeLabels[indexI], eIter)
5732 labelList& eFaces = edgeFaces_[eIter()];
5734 labelHashSet facesToRemove;
5736 forAll(eFaces, faceI)
5738 bool remove = false;
5740 label own = owner_[eFaces[faceI]];
5741 label nei = neighbour_[eFaces[faceI]];
5745 (!cellColors[own] && !indexI) ||
5746 ( cellColors[own] && indexI)
5756 (!cellColors[nei] && !indexI) ||
5757 ( cellColors[nei] && indexI)
5764 if (mirrorFaceLabels[indexI].found(eFaces[faceI]))
5766 // Perform a replacement instead of a removal.
5767 eFaces[faceI] = mirrorFaceLabels[indexI][eFaces[faceI]];
5774 facesToRemove.insert(eFaces[faceI]);
5778 // Now successively size down edgeFaces.
5779 // It is dangerous to use the eFaces reference,
5780 // so call it using array-lookup.
5781 forAllIter(labelHashSet, facesToRemove, hsIter)
5783 meshOps::sizeDownList(hsIter.key(), edgeFaces_[eIter()]);
5788 // Renumber faceEdges for all faces connected to new edges
5789 forAll(mirrorEdgeLabels, indexI)
5791 forAllIter(Map<label>, mirrorEdgeLabels[indexI], eIter)
5793 const labelList& eFaces = edgeFaces_[eIter()];
5795 forAll(eFaces, faceI)
5797 labelList& fEdges = faceEdges_[eFaces[faceI]];
5799 forAll(fEdges, edgeI)
5801 if (mirrorEdgeLabels[indexI].found(fEdges[edgeI]))
5805 mirrorEdgeLabels[indexI][fEdges[edgeI]]
5815 // Renumber edges and faces
5816 forAllIter(Map<label>, mirrorEdgeLabels[0], eIter)
5818 const labelList& eFaces = edgeFaces_[eIter()];
5820 // Two levels of indirection to ensure
5821 // that all entities we renumbered.
5822 // A flip-side for the lack of a pointEdges list in 2D.
5823 forAll(eFaces, faceI)
5825 const labelList& fEdges = faceEdges_[eFaces[faceI]];
5827 forAll(fEdges, edgeI)
5829 // Renumber this edge.
5830 edge& edgeToCheck = edges_[fEdges[edgeI]];
5832 forAll(edgeToCheck, pointI)
5834 if (mirrorPointLabels.found(edgeToCheck[pointI]))
5836 edgeToCheck[pointI] =
5838 mirrorPointLabels[edgeToCheck[pointI]]
5843 // Also renumber faces connected to this edge.
5844 const labelList& efFaces = edgeFaces_[fEdges[edgeI]];
5846 forAll(efFaces, faceJ)
5848 face& faceToCheck = faces_[efFaces[faceJ]];
5850 forAll(faceToCheck, pointI)
5854 mirrorPointLabels.found(faceToCheck[pointI])
5857 faceToCheck[pointI] =
5859 mirrorPointLabels[faceToCheck[pointI]]
5870 // Point renumbering of entities connected to mirror points
5871 forAllIter(Map<label>, mirrorPointLabels, pIter)
5873 const labelList& pEdges = pointEdges_[pIter()];
5875 forAll(pEdges, edgeI)
5877 // Renumber this edge.
5878 edge& edgeToCheck = edges_[pEdges[edgeI]];
5880 forAll(edgeToCheck, pointI)
5882 if (edgeToCheck[pointI] == pIter.key())
5884 edgeToCheck[pointI] = pIter();
5888 // Also renumber faces connected to this edge.
5889 const labelList& eFaces = edgeFaces_[pEdges[edgeI]];
5891 forAll(eFaces, faceI)
5893 face& faceToCheck = faces_[eFaces[faceI]];
5895 forAll(faceToCheck, pointI)
5897 if (faceToCheck[pointI] == pIter.key())
5899 faceToCheck[pointI] = pIter();
5907 // Now that we're done with the internal faces, remove them.
5908 forAll(internalFaces, faceI)
5910 removeFace(internalFaces[faceI]);
5913 // Remove old internal edges as well.
5914 forAllIter(Map<label>, mirrorEdgeLabels[1], eIter)
5916 if (eIter.key() != eIter())
5918 removeEdge(eIter.key());
5923 topoChangeFlag_ = true;
5926 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
5928 } // End namespace Foam
5930 // ************************************************************************* //