1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
29 #include "objectMap.H"
30 #include "changeMap.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 const changeMap dynamicTopoFvMesh::bisectQuadFace
49 const changeMap& masterMap,
54 // Quad-face bisection performs the following operations:
55 // [1] Add two points at the middle of the face
56 // [2] Create a new internal face for each bisected cell
57 // [3] Modify existing face and create a new half-face
58 // [4] Modify triangular boundary faces, and create new ones as well
59 // [5] Create edges for new faces
60 // Update faceEdges and edgeFaces information
62 // Figure out which thread this is...
63 label tIndex = self();
65 // Prepare the changeMaps
66 changeMap map, slaveMap;
70 (statistics_[0] > maxModifications_) &&
71 (maxModifications_ > -1)
74 // Reached the max allowable topo-changes.
75 stack(tIndex).clear();
80 // Check if edgeRefinements are to be avoided on patch.
81 if (lengthEstimator().checkRefinementPatch(whichPatch(fIndex)))
86 // Sanity check: Is the index legitimate?
92 "const changeMap dynamicTopoFvMesh::bisectQuadFace\n"
94 " const label fIndex,\n"
95 " const changeMap& masterMap,\n"
99 << " Invalid index: " << fIndex << nl
100 << " nFaces: " << nFaces_
101 << abort(FatalError);
105 label replaceFace = -1, retainFace = -1;
106 face tmpQuadFace(4), tmpTriFace(3);
107 labelList tmpQFEdges(4, -1), tmpTFEdges(3, -1);
108 FixedList<label,7> newFaceIndex(-1), newEdgeIndex(-1);
109 FixedList<edge,4> commonEdges;
110 FixedList<label,4> cornerEdgeIndex(-1), commonEdgeIndex(-1);
111 FixedList<label,4> commonFaceIndex(-1);
112 FixedList<label,2> newPointIndex(-1), newCellIndex(-1);
113 FixedList<label,4> otherEdgeIndex(-1), otherEdgePoint(-1);
114 FixedList<label,4> otherPointIndex(-1), nextToOtherPoint(-1);
115 FixedList<label,2> c0BdyIndex, c0IntIndex, c1BdyIndex, c1IntIndex;
116 FixedList<face,2> c0BdyFace, c0IntFace, c1BdyFace, c1IntFace;
118 // Get the two cells on either side...
119 label c0 = owner_[fIndex], c1 = neighbour_[fIndex];
121 // Keep track of old / new cells
122 FixedList<cell, 2> oldCells(cell(5));
123 FixedList<cell, 2> newCells(cell(5));
125 // Find the prism faces for cell[0].
126 oldCells[0] = cells_[c0];
128 meshOps::findPrismFaces
141 // Check for resulting quality
142 if (checkBisection(fIndex, c0BdyIndex[0], forceOp))
150 // Find the prism faces for cell[1].
151 meshOps::findPrismFaces
164 // Check for resulting quality
165 if (checkBisection(fIndex, c1BdyIndex[0], forceOp))
174 Info << nl << nl << "Face: " << fIndex
175 << ": " << faces_[fIndex] << " is to be bisected. " << endl;
177 label epIndex = whichPatch(fIndex);
183 Info << "Internal" << endl;
187 Info << boundaryMesh()[epIndex].name() << endl;
192 Info << "Cell[0]: " << c0 << ": " << oldCells[0] << endl;
194 forAll(oldCells[0], faceI)
196 const labelList& fE = faceEdges_[oldCells[0][faceI]];
198 Info << oldCells[0][faceI] << ": "
199 << faces_[oldCells[0][faceI]]
205 const labelList& eF = edgeFaces_[fE[edgeI]];
207 Info << '\t' << fE[edgeI]
208 << ": " << edges_[fE[edgeI]]
215 // Write out VTK files prior to change
218 labelList cellHull(2, -1);
220 cellHull[0] = owner_[fIndex];
221 cellHull[1] = neighbour_[fIndex];
232 // Find the common-edge between the triangular boundary faces
233 // and the face under consideration.
234 meshOps::findCommonEdge
242 meshOps::findCommonEdge
250 commonEdges[0] = edges_[commonEdgeIndex[0]];
251 commonEdges[1] = edges_[commonEdgeIndex[1]];
253 // Are we performing only checks?
260 // Find the isolated point on both boundary faces of cell[0]
261 meshOps::findIsolatedPoint
269 meshOps::findIsolatedPoint
277 // For convenience...
278 otherEdgePoint[0] = commonEdges[0].otherVertex(nextToOtherPoint[0]);
279 otherEdgePoint[1] = commonEdges[1].otherVertex(nextToOtherPoint[1]);
283 // Set mapping for this point
284 mP[0] = commonEdges[0][0];
285 mP[1] = commonEdges[0][1];
287 // Add two new points to the end of the list
292 0.5 * (points_[mP[0]] + points_[mP[1]]),
293 0.5 * (oldPoints_[mP[0]] + oldPoints_[mP[1]]),
298 // Set mapping for this point
299 mP[0] = commonEdges[1][0];
300 mP[1] = commonEdges[1][1];
306 0.5 * (points_[mP[0]] + points_[mP[1]]),
307 0.5 * (oldPoints_[mP[0]] + oldPoints_[mP[1]]),
313 map.addPoint(newPointIndex[0]);
314 map.addPoint(newPointIndex[1]);
317 // Add a new prism cell to the end of the list.
318 // Currently invalid, but will be updated later.
319 newCellIndex[0] = insertCell(newCells[0], lengthScale_[c0]);
321 // Modify the two existing triangle boundary faces
323 // Zeroth boundary face - Owner = c[0] & Neighbour [-1] (unchanged)
324 meshOps::replaceLabel
331 // First boundary face - Owner = newCell[0], Neighbour = -1
332 meshOps::replaceLabel
340 faces_[c0BdyIndex[0]] = c0BdyFace[0];
341 faces_[c0BdyIndex[1]] = c0BdyFace[1];
343 owner_[c0BdyIndex[1]] = newCellIndex[0];
345 meshOps::replaceLabel
352 // Detect edges other than commonEdges
353 const labelList& fEdges = faceEdges_[fIndex];
355 forAll(fEdges, edgeI)
359 fEdges[edgeI] != commonEdgeIndex[0] &&
360 fEdges[edgeI] != commonEdgeIndex[1]
363 // Obtain a reference to this edge
364 const edge& eThis = edges_[fEdges[edgeI]];
368 eThis[0] == nextToOtherPoint[0]
369 || eThis[1] == nextToOtherPoint[0]
372 otherEdgeIndex[0] = fEdges[edgeI];
376 otherEdgeIndex[1] = fEdges[edgeI];
381 // Modify point-labels on the quad face under consideration
382 meshOps::replaceLabel
389 meshOps::replaceLabel
396 // Add this face to the map.
397 // Although this face isn't technically 'added', it's
398 // required for coupled patch mapping.
403 Info << "Modified face: " << fIndex
404 << ": " << faces_[fIndex] << endl;
408 Info << "Common edges: " << nl
409 << commonEdgeIndex[0] << ": " << commonEdges[0] << nl
410 << commonEdgeIndex[1] << ": " << commonEdges[1]
415 // Find the quad face that contains otherEdgeIndex[1]
418 const labelList& e1 = faceEdges_[c0IntIndex[0]];
422 if (e1[edgeI] == otherEdgeIndex[1])
424 meshOps::replaceLabel
431 replaceFace = c0IntIndex[0];
432 retainFace = c0IntIndex[1];
440 // The edge was not found before
441 meshOps::replaceLabel
448 replaceFace = c0IntIndex[1];
449 retainFace = c0IntIndex[0];
452 // Check if face reversal is necessary for the replacement
453 if (owner_[replaceFace] == c0)
455 if (neighbour_[replaceFace] == -1)
458 owner_[replaceFace] = newCellIndex[0];
462 // This face has to be reversed
463 faces_[replaceFace] = faces_[replaceFace].reverseFace();
464 owner_[replaceFace] = neighbour_[replaceFace];
465 neighbour_[replaceFace] = newCellIndex[0];
467 setFlip(replaceFace);
472 // Keep owner, but change neighbour
473 neighbour_[replaceFace] = newCellIndex[0];
476 // Define the faces for the new cell
477 newCells[0][0] = c0BdyIndex[1];
478 newCells[0][1] = replaceFace;
480 // Define the set of new faces and insert...
482 // New interior face; Owner = cell[0] & Neighbour = newCell[0]
483 tmpQuadFace[0] = otherPointIndex[0];
484 tmpQuadFace[1] = newPointIndex[0];
485 tmpQuadFace[2] = newPointIndex[1];
486 tmpQuadFace[3] = otherPointIndex[1];
499 // Add a faceEdges entry as well
500 faceEdges_.append(tmpQFEdges);
502 // Find the common edge between quad/quad faces...
503 meshOps::findCommonEdge
511 // ... and size-up edgeFaces for the edge
515 edgeFaces_[otherEdgeIndex[2]]
518 meshOps::replaceLabel
525 meshOps::replaceLabel
532 // remove2DSliver requires this face index for removal
533 map.addFace(newFaceIndex[0]);
535 // Second boundary face; Owner = newCell[0] & Neighbour = [-1]
536 tmpTriFace[0] = otherPointIndex[0];
537 tmpTriFace[1] = newPointIndex[0];
538 tmpTriFace[2] = otherEdgePoint[0];
544 whichPatch(c0BdyIndex[0]),
551 // Add a faceEdges entry as well
552 faceEdges_.append(tmpTFEdges);
554 meshOps::replaceLabel
561 // Third boundary face; Owner = c[0] & Neighbour = [-1]
562 tmpTriFace[0] = otherPointIndex[1];
563 tmpTriFace[1] = newPointIndex[1];
564 tmpTriFace[2] = otherEdgePoint[1];
570 whichPatch(c0BdyIndex[1]),
577 // Add a faceEdges entry as well
578 faceEdges_.append(tmpTFEdges);
580 meshOps::replaceLabel
587 // Create / modify edges...
588 labelList tmpTriEdgeFaces(3, -1);
590 // The edge bisecting the zeroth boundary triangular face
591 tmpTriEdgeFaces[0] = c0BdyIndex[0];
592 tmpTriEdgeFaces[1] = newFaceIndex[0];
593 tmpTriEdgeFaces[2] = newFaceIndex[1];
599 whichEdgePatch(commonEdgeIndex[0]),
600 edge(newPointIndex[0], otherPointIndex[0]),
605 // Find the common edge between the quad/tri faces...
606 meshOps::findCommonEdge
614 // ...and correct faceEdges / edgeFaces
615 meshOps::replaceLabel
619 faceEdges_[c0BdyIndex[0]]
622 meshOps::replaceLabel
626 edgeFaces_[cornerEdgeIndex[0]]
629 // The edge bisecting the first boundary triangular face
630 tmpTriEdgeFaces[0] = c0BdyIndex[1];
631 tmpTriEdgeFaces[1] = newFaceIndex[0];
632 tmpTriEdgeFaces[2] = newFaceIndex[2];
638 whichEdgePatch(commonEdgeIndex[1]),
639 edge(newPointIndex[1], otherPointIndex[1]),
644 // Find the common edge between the quad/tri faces...
645 meshOps::findCommonEdge
653 // ...and correct faceEdges / edgeFaces
654 meshOps::replaceLabel
658 faceEdges_[c0BdyIndex[1]]
661 meshOps::replaceLabel
665 edgeFaces_[cornerEdgeIndex[1]]
670 // The quad boundary face resulting from bisection;
671 // Owner = newCell[0] & Neighbour = [-1]
672 tmpQuadFace[0] = newPointIndex[1];
673 tmpQuadFace[1] = nextToOtherPoint[1];
674 tmpQuadFace[2] = otherEdgePoint[0];
675 tmpQuadFace[3] = newPointIndex[0];
688 // Add this face to the map.
689 map.addFace(newFaceIndex[3]);
691 // Add a faceEdges entry as well
692 faceEdges_.append(tmpQFEdges);
694 // Correct edgeFaces for otherEdgeIndex[1]
695 meshOps::replaceLabel
699 edgeFaces_[otherEdgeIndex[1]]
702 meshOps::replaceLabel
709 labelList tmpBiEdgeFaces(2, -1);
711 // The edge bisecting the face
712 tmpTriEdgeFaces[0] = newFaceIndex[3];
713 tmpTriEdgeFaces[1] = newFaceIndex[0];
714 tmpTriEdgeFaces[2] = fIndex;
720 whichEdgePatch(otherEdgeIndex[0]),
721 edge(newPointIndex[0], newPointIndex[1]),
726 // Replace an edge on the bisected face
727 meshOps::replaceLabel
734 // Create / replace side edges created from face bisection
735 tmpBiEdgeFaces[0] = newFaceIndex[1];
736 tmpBiEdgeFaces[1] = newFaceIndex[3];
742 whichEdgePatch(commonEdgeIndex[0]),
743 edge(newPointIndex[0], otherEdgePoint[0]),
748 tmpBiEdgeFaces[0] = c0BdyIndex[1];
749 tmpBiEdgeFaces[1] = newFaceIndex[3];
755 whichEdgePatch(commonEdgeIndex[1]),
756 edge(newPointIndex[1], nextToOtherPoint[1]),
761 // Now that edges are defined, configure faceEdges
764 // The quad interior face; Owner = cell[0] & Neighbour = newCell[0]
765 tmpQFEdges[0] = newEdgeIndex[0];
766 tmpQFEdges[1] = newEdgeIndex[1];
767 tmpQFEdges[2] = otherEdgeIndex[2];
768 tmpQFEdges[3] = newEdgeIndex[2];
769 faceEdges_[newFaceIndex[0]] = tmpQFEdges;
771 // Second boundary face; Owner = newCell[0] & Neighbour = [-1]
772 tmpTFEdges[0] = newEdgeIndex[3];
773 tmpTFEdges[1] = cornerEdgeIndex[0];
774 tmpTFEdges[2] = newEdgeIndex[1];
775 faceEdges_[newFaceIndex[1]] = tmpTFEdges;
777 // Third boundary face; Owner = c[0] & Neighbour = [-1]
778 tmpTFEdges[0] = newEdgeIndex[2];
779 tmpTFEdges[1] = cornerEdgeIndex[1];
780 tmpTFEdges[2] = commonEdgeIndex[1];
781 faceEdges_[newFaceIndex[2]] = tmpTFEdges;
783 // The quad face from bisection:
784 tmpQFEdges[0] = otherEdgeIndex[1];
785 tmpQFEdges[1] = newEdgeIndex[3];
786 tmpQFEdges[2] = newEdgeIndex[0];
787 tmpQFEdges[3] = newEdgeIndex[4];
788 faceEdges_[newFaceIndex[3]] = tmpQFEdges;
790 meshOps::replaceLabel
794 faceEdges_[c0BdyIndex[1]]
797 meshOps::replaceLabel
801 edgeFaces_[commonEdgeIndex[1]]
806 Info << "Modified Cell[0]: "
807 << c0 << ": " << oldCells[0] << endl;
809 forAll(oldCells[0], faceI)
811 const labelList& fE = faceEdges_[oldCells[0][faceI]];
813 Info << oldCells[0][faceI]
814 << ": " << faces_[oldCells[0][faceI]]
820 const labelList& eF = edgeFaces_[fE[edgeI]];
822 Info << '\t' << fE[edgeI]
823 << ": " << edges_[fE[edgeI]]
829 Info << "New Cell[0]: " << newCellIndex[0]
830 << ": " << newCells[0] << endl;
832 forAll(newCells[0], faceI)
834 const labelList& fE = faceEdges_[newCells[0][faceI]];
836 Info << newCells[0][faceI]
837 << ": " << faces_[newCells[0][faceI]]
843 const labelList& eF = edgeFaces_[fE[edgeI]];
845 Info << '\t' << fE[edgeI]
846 << ": " << edges_[fE[edgeI]]
855 oldCells[1] = cells_[c1];
857 newCellIndex[1] = insertCell(newCells[1], lengthScale_[c1]);
861 Info << "Cell[1]: " << c1 << ": " << oldCells[1] << endl;
863 forAll(oldCells[1], faceI)
865 const labelList& fE = faceEdges_[oldCells[1][faceI]];
867 Info << oldCells[1][faceI] << ": "
868 << faces_[oldCells[1][faceI]]
874 const labelList& eF = edgeFaces_[fE[edgeI]];
876 Info << '\t' << fE[edgeI]
877 << ": " << edges_[fE[edgeI]]
884 // Find the interior face that contains otherEdgeIndex[1]
887 const labelList& e2 = faceEdges_[c1IntIndex[0]];
891 if (e2[edgeI] == otherEdgeIndex[1])
893 meshOps::replaceLabel
900 replaceFace = c1IntIndex[0];
901 retainFace = c1IntIndex[1];
909 // The edge was not found before
910 meshOps::replaceLabel
917 replaceFace = c1IntIndex[1];
918 retainFace = c1IntIndex[0];
921 // Check if face reversal is necessary for the replacement
922 if (owner_[replaceFace] == c1)
924 if (neighbour_[replaceFace] == -1)
927 owner_[replaceFace] = newCellIndex[1];
931 // This face has to be reversed
932 faces_[replaceFace] = faces_[replaceFace].reverseFace();
933 owner_[replaceFace] = neighbour_[replaceFace];
934 neighbour_[replaceFace] = newCellIndex[1];
936 setFlip(replaceFace);
941 // Keep owner, but change neighbour
942 neighbour_[replaceFace] = newCellIndex[1];
945 // Define attributes for the new prism cell
946 newCells[1][0] = replaceFace;
948 // The quad interior face resulting from bisection;
949 // Owner = newCell[0] & Neighbour = newCell[1]
950 tmpQuadFace[0] = newPointIndex[1];
951 tmpQuadFace[1] = nextToOtherPoint[1];
952 tmpQuadFace[2] = otherEdgePoint[0];
953 tmpQuadFace[3] = newPointIndex[0];
966 // Add a faceEdges entry as well
967 faceEdges_.append(tmpQFEdges);
969 // Correct edgeFaces for otherEdgeIndex[1]
970 meshOps::replaceLabel
974 edgeFaces_[otherEdgeIndex[1]]
977 meshOps::replaceLabel
984 meshOps::replaceLabel
991 newCells[1][1] = newFaceIndex[3];
993 // Check for common edges among the two boundary faces
994 // Find the isolated point on both boundary faces of cell[1]
997 meshOps::findCommonEdge
1006 meshOps::findCommonEdge
1014 commonFaceIndex[2] = c1BdyIndex[0];
1015 commonFaceIndex[3] = c1BdyIndex[1];
1019 meshOps::findCommonEdge
1027 meshOps::findCommonEdge
1035 commonFaceIndex[2] = c1BdyIndex[1];
1036 commonFaceIndex[3] = c1BdyIndex[0];
1039 commonEdges[2] = edges_[commonEdgeIndex[2]];
1040 commonEdges[3] = edges_[commonEdgeIndex[3]];
1044 Info << "Common edges: " << nl
1045 << commonEdgeIndex[2] << ": " << commonEdges[2] << nl
1046 << commonEdgeIndex[3] << ": " << commonEdges[3]
1050 meshOps::findIsolatedPoint
1052 faces_[commonFaceIndex[2]],
1058 meshOps::findIsolatedPoint
1060 faces_[commonFaceIndex[3]],
1066 // For convenience...
1067 otherEdgePoint[2] = commonEdges[2].otherVertex(nextToOtherPoint[2]);
1068 otherEdgePoint[3] = commonEdges[3].otherVertex(nextToOtherPoint[3]);
1070 // Modify the two existing triangle boundary faces
1072 // Zeroth boundary face - Owner = newCell[1], Neighbour = -1
1073 meshOps::replaceLabel
1077 faces_[commonFaceIndex[2]]
1080 owner_[commonFaceIndex[2]] = newCellIndex[1];
1082 meshOps::replaceLabel
1089 newCells[1][2] = commonFaceIndex[2];
1091 // First boundary face - Owner = c[1] & Neighbour [-1] (unchanged)
1092 meshOps::replaceLabel
1096 faces_[commonFaceIndex[3]]
1099 // New interior face; Owner = cell[1] & Neighbour = newCell[1]
1100 tmpQuadFace[0] = newPointIndex[0];
1101 tmpQuadFace[1] = otherPointIndex[2];
1102 tmpQuadFace[2] = otherPointIndex[3];
1103 tmpQuadFace[3] = newPointIndex[1];
1116 // Add a faceEdges entry as well
1117 faceEdges_.append(tmpQFEdges);
1119 // remove2DSliver requires this face index for removal
1120 map.addFace(newFaceIndex[4]);
1122 // Find the common edge between quad/quad faces...
1123 meshOps::findCommonEdge
1131 // ... and size-up edgeFaces for the edge
1135 edgeFaces_[otherEdgeIndex[3]]
1138 meshOps::replaceLabel
1145 meshOps::replaceLabel
1152 // Second boundary face; Owner = cell[1] & Neighbour [-1]
1153 tmpTriFace[0] = otherPointIndex[2];
1154 tmpTriFace[1] = newPointIndex[0];
1155 tmpTriFace[2] = otherEdgePoint[2];
1161 whichPatch(commonFaceIndex[2]),
1168 // Add a faceEdges entry as well
1169 faceEdges_.append(tmpTFEdges);
1171 meshOps::replaceLabel
1178 // Third boundary face; Owner = newCell[1] & Neighbour [-1]
1179 tmpTriFace[0] = otherPointIndex[3];
1180 tmpTriFace[1] = newPointIndex[1];
1181 tmpTriFace[2] = otherEdgePoint[3];
1187 whichPatch(commonFaceIndex[3]),
1194 // Add a faceEdges entry as well
1195 faceEdges_.append(tmpTFEdges);
1197 meshOps::replaceLabel
1204 // Create / modify edges...
1205 labelList tmpQuadEdgeFaces(4, -1);
1207 // The internal edge bisecting the face
1208 tmpQuadEdgeFaces[0] = fIndex;
1209 tmpQuadEdgeFaces[1] = newFaceIndex[0];
1210 tmpQuadEdgeFaces[2] = newFaceIndex[3];
1211 tmpQuadEdgeFaces[3] = newFaceIndex[4];
1218 edge(newPointIndex[0], newPointIndex[1]),
1223 // Replace an edge on the bisected face
1224 meshOps::replaceLabel
1231 // Create / replace side edges created from face bisection
1232 tmpTriEdgeFaces[0] = commonFaceIndex[2];
1233 tmpTriEdgeFaces[1] = newFaceIndex[3];
1234 tmpTriEdgeFaces[2] = newFaceIndex[1];
1240 whichEdgePatch(commonEdgeIndex[2]),
1241 edge(newPointIndex[0], nextToOtherPoint[2]),
1246 tmpTriEdgeFaces[0] = c0BdyIndex[1];
1247 tmpTriEdgeFaces[1] = newFaceIndex[3];
1248 tmpTriEdgeFaces[2] = newFaceIndex[6];
1254 whichEdgePatch(commonEdgeIndex[3]),
1255 edge(newPointIndex[1], otherEdgePoint[3]),
1260 // The edge bisecting the second boundary triangular face
1261 tmpTriEdgeFaces[0] = commonFaceIndex[2];
1262 tmpTriEdgeFaces[1] = newFaceIndex[4];
1263 tmpTriEdgeFaces[2] = newFaceIndex[5];
1269 whichEdgePatch(commonEdgeIndex[2]),
1270 edge(newPointIndex[0], otherPointIndex[2]),
1275 // Find the common edge between the quad/tri faces...
1276 meshOps::findCommonEdge
1284 // ...and correct faceEdges / edgeFaces
1285 meshOps::replaceLabel
1289 faceEdges_[commonFaceIndex[2]]
1292 meshOps::replaceLabel
1296 edgeFaces_[cornerEdgeIndex[2]]
1299 // The edge bisecting the third boundary triangular face
1300 tmpTriEdgeFaces[0] = commonFaceIndex[3];
1301 tmpTriEdgeFaces[1] = newFaceIndex[4];
1302 tmpTriEdgeFaces[2] = newFaceIndex[6];
1308 whichEdgePatch(commonEdgeIndex[3]),
1309 edge(newPointIndex[1], otherPointIndex[3]),
1314 // Find the common edge between the quad/tri faces...
1315 meshOps::findCommonEdge
1323 // ...and correct faceEdges / edgeFaces
1324 meshOps::replaceLabel
1328 faceEdges_[commonFaceIndex[3]]
1331 meshOps::replaceLabel
1335 edgeFaces_[cornerEdgeIndex[3]]
1338 // Now that edges are defined, configure faceEdges
1339 // for all new faces
1341 // The quad interior face; Owner = c[0] & Neighbour = newCell[0]
1342 tmpQFEdges[0] = newEdgeIndex[0];
1343 tmpQFEdges[1] = newEdgeIndex[1];
1344 tmpQFEdges[2] = otherEdgeIndex[2];
1345 tmpQFEdges[3] = newEdgeIndex[2];
1346 faceEdges_[newFaceIndex[0]] = tmpQFEdges;
1348 // Second boundary face; Owner = newCell[0] & Neighbour = [-1]
1349 tmpTFEdges[0] = newEdgeIndex[3];
1350 tmpTFEdges[1] = cornerEdgeIndex[0];
1351 tmpTFEdges[2] = newEdgeIndex[1];
1352 faceEdges_[newFaceIndex[1]] = tmpTFEdges;
1354 // Third boundary face; Owner = c[0] & Neighbour = [-1]
1355 tmpTFEdges[0] = newEdgeIndex[2];
1356 tmpTFEdges[1] = cornerEdgeIndex[1];
1357 tmpTFEdges[2] = commonEdgeIndex[3];
1358 faceEdges_[newFaceIndex[2]] = tmpTFEdges;
1360 // The quad face from bisection:
1361 tmpQFEdges[0] = otherEdgeIndex[1];
1362 tmpQFEdges[1] = newEdgeIndex[3];
1363 tmpQFEdges[2] = newEdgeIndex[0];
1364 tmpQFEdges[3] = newEdgeIndex[4];
1365 faceEdges_[newFaceIndex[3]] = tmpQFEdges;
1367 // The quad interior face; Owner = c[1] & Neighbour = newCell[1]
1368 tmpQFEdges[0] = newEdgeIndex[0];
1369 tmpQFEdges[1] = newEdgeIndex[5];
1370 tmpQFEdges[2] = otherEdgeIndex[3];
1371 tmpQFEdges[3] = newEdgeIndex[6];
1372 faceEdges_[newFaceIndex[4]] = tmpQFEdges;
1374 // Second boundary face; Owner = c[1] & Neighbour = [-1]
1375 tmpTFEdges[0] = commonEdgeIndex[2];
1376 tmpTFEdges[1] = cornerEdgeIndex[2];
1377 tmpTFEdges[2] = newEdgeIndex[5];
1378 faceEdges_[newFaceIndex[5]] = tmpTFEdges;
1380 // Third boundary face; Owner = newCell[1] & Neighbour = [-1]
1381 tmpTFEdges[0] = newEdgeIndex[4];
1382 tmpTFEdges[1] = cornerEdgeIndex[3];
1383 tmpTFEdges[2] = newEdgeIndex[6];
1384 faceEdges_[newFaceIndex[6]] = tmpTFEdges;
1386 meshOps::replaceLabel
1390 faceEdges_[c0BdyIndex[1]]
1393 meshOps::replaceLabel
1397 edgeFaces_[commonEdgeIndex[1]]
1400 meshOps::replaceLabel
1404 faceEdges_[commonFaceIndex[2]]
1407 meshOps::replaceLabel
1411 edgeFaces_[commonEdgeIndex[2]]
1416 Info << nl << "Modified Cell[0]: "
1417 << c0 << ": " << oldCells[0] << endl;
1419 forAll(oldCells[0], faceI)
1421 const labelList& fE = faceEdges_[oldCells[0][faceI]];
1423 Info << oldCells[0][faceI]
1424 << ": " << faces_[oldCells[0][faceI]]
1430 const labelList& eF = edgeFaces_[fE[edgeI]];
1432 Info << '\t' << fE[edgeI]
1433 << ": " << edges_[fE[edgeI]]
1439 Info << "New Cell[0]: "
1440 << newCellIndex[0] << ": " << newCells[0] << endl;
1442 forAll(newCells[0], faceI)
1444 const labelList& fE = faceEdges_[newCells[0][faceI]];
1446 Info << newCells[0][faceI] << ": "
1447 << faces_[newCells[0][faceI]]
1453 const labelList& eF = edgeFaces_[fE[edgeI]];
1455 Info << '\t' << fE[edgeI]
1456 << ": " << edges_[fE[edgeI]]
1462 Info << nl << "Modified Cell[1]: "
1463 << c1 << ": " << oldCells[1] << endl;
1465 forAll(oldCells[1], faceI)
1467 const labelList& fE = faceEdges_[oldCells[1][faceI]];
1469 Info << oldCells[1][faceI] << ": "
1470 << faces_[oldCells[1][faceI]]
1476 const labelList& eF = edgeFaces_[fE[edgeI]];
1478 Info << '\t' << fE[edgeI]
1479 << ": " << edges_[fE[edgeI]]
1485 Info << "New Cell[1]: "
1486 << newCellIndex[1] << ": " << newCells[1] << endl;
1488 forAll(newCells[1], faceI)
1490 const labelList& fE = faceEdges_[newCells[1][faceI]];
1492 Info << newCells[1][faceI] << ": "
1493 << faces_[newCells[1][faceI]]
1499 const labelList& eF = edgeFaces_[fE[edgeI]];
1501 Info << '\t' << fE[edgeI]
1502 << ": " << edges_[fE[edgeI]]
1509 // Update the cell list.
1510 cells_[c1] = oldCells[1];
1511 cells_[newCellIndex[1]] = newCells[1];
1514 // Update the cell list.
1515 cells_[c0] = oldCells[0];
1516 cells_[newCellIndex[0]] = newCells[0];
1518 // Modify point labels for common edges
1519 if (edges_[commonEdgeIndex[0]].start() == otherEdgePoint[0])
1521 edges_[commonEdgeIndex[0]].start() = newPointIndex[0];
1525 edges_[commonEdgeIndex[0]].end() = newPointIndex[0];
1528 if (edges_[commonEdgeIndex[1]].start() == nextToOtherPoint[1])
1530 edges_[commonEdgeIndex[1]].start() = newPointIndex[1];
1534 edges_[commonEdgeIndex[1]].end() = newPointIndex[1];
1537 // Write out VTK files after change
1540 labelList cellHull(4, -1);
1542 cellHull[0] = owner_[fIndex];
1543 cellHull[1] = neighbour_[fIndex];
1544 cellHull[2] = owner_[newFaceIndex[3]];
1545 cellHull[3] = neighbour_[newFaceIndex[3]];
1555 // Fill-in mapping information
1556 FixedList<label, 4> mapCells(-1);
1559 mapCells[1] = newCellIndex[0];
1564 mapCells[3] = newCellIndex[1];
1567 labelList mC(1, c0);
1569 forAll(mapCells, cellI)
1571 if (mapCells[cellI] == -1)
1576 // Set the mapping for this cell
1577 setCellMapping(mapCells[cellI], mC);
1580 // Set fill-in mapping information for the modified face.
1583 // Set the mapping for this face
1584 setFaceMapping(fIndex, labelList(1, fIndex));
1588 // Internal face. Default mapping.
1589 setFaceMapping(fIndex);
1592 forAll(newFaceIndex, faceI)
1594 if (newFaceIndex[faceI] == -1)
1599 // Check for boundary faces
1600 if (neighbour_[newFaceIndex[faceI]] == -1)
1602 // Boundary face. Compute mapping.
1605 if (faces_[newFaceIndex[faceI]].size() == 4)
1607 // Quad-face on boundary
1608 mC.setSize(1, fIndex);
1611 if (faces_[newFaceIndex[faceI]].size() == 3)
1613 label triFacePatch = whichPatch(newFaceIndex[faceI]);
1615 // Fetch face-normals
1616 vector tfNorm, f0Norm, f1Norm;
1618 tfNorm = faces_[newFaceIndex[faceI]].normal(oldPoints_);
1619 f0Norm = faces_[c0BdyIndex[0]].normal(oldPoints_);
1620 f1Norm = faces_[c0BdyIndex[1]].normal(oldPoints_);
1622 // Tri-face on boundary. Perform normal checks
1623 // also, because of empty patches.
1626 (whichPatch(c0BdyIndex[0]) == triFacePatch) &&
1627 ((tfNorm & f0Norm) > 0.0)
1630 mC.setSize(1, c0BdyIndex[0]);
1635 (whichPatch(c0BdyIndex[1]) == triFacePatch) &&
1636 ((tfNorm & f1Norm) > 0.0)
1639 mC.setSize(1, c0BdyIndex[1]);
1646 "const changeMap dynamicTopoFvMesh::bisectQuadFace\n"
1648 " const label fIndex,\n"
1649 " const changeMap& masterMap,\n"
1653 << " Unable to find patch for face: "
1654 << newFaceIndex[faceI] << ":: "
1655 << faces_[newFaceIndex[faceI]] << nl
1656 << " Patch: " << triFacePatch << nl
1657 << abort(FatalError);
1661 // Set the mapping for this face
1662 setFaceMapping(newFaceIndex[faceI], mC);
1666 // Internal quad-faces get default mapping.
1667 setFaceMapping(newFaceIndex[faceI]);
1672 topoChangeFlag_ = true;
1674 // Increment the counter
1677 // Increment surface-counter
1683 // Increment the number of modifications
1686 // Specify that the operation was successful
1689 // Return the changeMap
1693 // Method for the bisection of an edge in 3D
1694 // - Returns a changeMap with a type specifying:
1695 // 1: Bisection was successful
1696 // -1: Bisection failed since max number of topo-changes was reached.
1697 // -2: Bisection failed since resulting quality would be unacceptable.
1698 // - AddedPoints contain the index of the newly added point.
1699 const changeMap dynamicTopoFvMesh::bisectEdge
1706 // Edge bisection performs the following operations:
1707 // [1] Add a point at middle of the edge
1708 // [2] Bisect all faces surrounding this edge
1709 // [3] Bisect all cells surrounding this edge
1710 // [4] Create internal/external edges for each bisected face
1711 // [5] Create internal faces for each bisected cell
1712 // Update faceEdges, edgeFaces and edgePoints information
1714 // For 2D meshes, perform face-bisection
1717 return bisectQuadFace(eIndex, changeMap(), checkOnly);
1720 // Figure out which thread this is...
1721 label tIndex = self();
1723 // Prepare the changeMaps
1724 changeMap map, slaveMap;
1728 (statistics_[0] > maxModifications_) &&
1729 (maxModifications_ > -1)
1732 // Reached the max allowable topo-changes.
1733 stack(tIndex).clear();
1738 // Check if edgeRefinements are to be avoided on patch.
1739 if (lengthEstimator().checkRefinementPatch(whichEdgePatch(eIndex)))
1744 // Sanity check: Is the index legitimate?
1750 "const changeMap dynamicTopoFvMesh::bisectEdge\n"
1752 " const label eIndex,\n"
1753 " bool checkOnly,\n"
1757 << " Invalid index: " << eIndex
1758 << " nEdges: " << nEdges_
1759 << abort(FatalError);
1762 // Before we bisect this edge, check whether the operation will
1763 // yield an acceptable cell-quality.
1766 if ((minQ = computeBisectionQuality(eIndex)) < sliverThreshold_)
1768 // Check if the quality is actually valid before forcing it.
1769 if (forceOp && (minQ < 0.0))
1774 "const changeMap dynamicTopoFvMesh::bisectEdge\n"
1776 " const label eIndex,\n"
1777 " bool checkOnly,\n"
1781 << " Forcing bisection on edge: " << eIndex
1782 << " will yield an invalid cell."
1783 << abort(FatalError);
1793 // Are we performing only checks?
1800 // Update number of surface bisections, if necessary.
1801 if (whichEdgePatch(eIndex) > -1)
1808 labelList tmpEdgeFaces(3,-1);
1809 labelList tmpIntEdgeFaces(4,-1);
1810 labelList tmpEdgePoints(3,-1);
1811 labelList tmpIntEdgePoints(4,-1);
1812 labelList tmpFaceEdges(3,-1);
1814 // Make a copy of existing entities
1815 const labelList vertexHull = edgePoints_[eIndex];
1816 label m = vertexHull.size();
1818 // Size up the hull lists
1819 labelList cellHull(m, -1);
1820 labelList faceHull(m, -1);
1821 labelList edgeHull(m, -1);
1822 labelListList ringEntities(4, labelList(m, -1));
1824 // Construct a hull around this edge
1825 meshOps::constructHull
1845 << "Edge: " << eIndex
1846 << ": " << edges_[eIndex]
1847 << " is to be bisected. " << endl;
1849 label epIndex = whichEdgePatch(eIndex);
1855 Info << "Internal" << endl;
1859 Info << boundaryMesh()[epIndex].name() << endl;
1862 // Write out VTK files prior to change
1874 labelList mP(2, -1);
1876 // Set mapping for this point
1877 mP[0] = edges_[eIndex][0];
1878 mP[1] = edges_[eIndex][1];
1880 // Add a new point to the end of the list
1881 label newPointIndex =
1885 0.5 * (points_[mP[0]] + points_[mP[1]]),
1886 0.5 * (oldPoints_[mP[0]] + oldPoints_[mP[1]]),
1891 // Add this point to the map.
1892 map.addPoint(newPointIndex);
1894 // New edges can lie on a bounding curve between
1895 // coupled and non-coupled faces. Preferentially
1896 // add edges to coupled-patches, if they exist.
1897 // This makes it convenient for coupled patch matching.
1901 nePatch = whichEdgePatch(eIndex);
1904 // Add a new edge to the end of the list
1905 label newEdgeIndex =
1910 edge(newPointIndex,edges_[eIndex][1]),
1911 labelList(faceHull.size(),-1),
1916 // Add this edge to the map.
1917 map.addEdge(newEdgeIndex);
1919 // Remove the existing edge from the pointEdges list
1920 // of the modified point, and add it to the new point
1921 meshOps::sizeDownList(eIndex, pointEdges_[edges_[eIndex][1]]);
1922 meshOps::sizeUpList(eIndex, pointEdges_[newPointIndex]);
1924 // Modify the existing edge
1925 edges_[eIndex][1] = newPointIndex;
1927 // Add this edge to the map.
1928 // Although this edge isn't technically 'added', it's
1929 // required for coupled patch mapping.
1930 map.addEdge(eIndex);
1932 // Keep track of added entities
1933 labelList addedCellIndices(cellHull.size(),-1);
1934 labelList addedFaceIndices(faceHull.size(),-1);
1935 labelList addedEdgeIndices(faceHull.size(),-1);
1936 labelList addedIntFaceIndices(faceHull.size(),-1);
1938 // Now loop through the hull and bisect individual entities
1939 forAll(vertexHull, indexI)
1941 // Modify the existing face
1942 meshOps::replaceLabel
1944 edges_[newEdgeIndex][1],
1946 faces_[faceHull[indexI]]
1949 // Modify edgePoints for the edge
1950 meshOps::replaceLabel
1952 edges_[newEdgeIndex][1],
1954 edgePoints_[ringEntities[0][indexI]]
1957 // Obtain circular indices
1958 label nextI = vertexHull.fcIndex(indexI);
1959 label prevI = vertexHull.rcIndex(indexI);
1961 // Check if this is an interior/boundary face
1962 if (cellHull[indexI] != -1)
1964 // Create a new cell. Add it for now, but update later.
1967 addedCellIndices[indexI] =
1969 insertCell(newCell, lengthScale_[cellHull[indexI]])
1972 // Add this cell to the map.
1973 map.addCell(addedCellIndices[indexI]);
1975 // Configure the interior face
1976 tmpTriFace[0] = vertexHull[nextI];
1977 tmpTriFace[1] = vertexHull[indexI];
1978 tmpTriFace[2] = newPointIndex;
1981 addedIntFaceIndices[indexI] =
1988 addedCellIndices[indexI]
1992 // Add a faceEdges entry as well
1993 faceEdges_.append(tmpFaceEdges);
1995 // Add this face to the map.
1996 map.addFace(addedIntFaceIndices[indexI]);
1998 // Add to the new cell
1999 newCell[0] = addedIntFaceIndices[indexI];
2001 // Modify the existing ring face connected to newEdge[1]
2002 label replaceFace = ringEntities[3][indexI];
2004 // Check if face reversal is necessary
2005 if (owner_[replaceFace] == cellHull[indexI])
2007 if (neighbour_[replaceFace] == -1)
2010 owner_[replaceFace] = addedCellIndices[indexI];
2014 // This face has to be reversed
2015 faces_[replaceFace] = faces_[replaceFace].reverseFace();
2016 owner_[replaceFace] = neighbour_[replaceFace];
2017 neighbour_[replaceFace] = addedCellIndices[indexI];
2019 setFlip(replaceFace);
2024 // Keep owner, but change neighbour
2025 neighbour_[replaceFace] = addedCellIndices[indexI];
2028 // Modify the edge on the ring.
2029 // Add the new interior face to edgeFaces.
2032 addedIntFaceIndices[indexI],
2033 edgeFaces_[edgeHull[indexI]]
2036 // Insert the new point to edgePoints for the ring edge
2037 meshOps::insertLabel
2041 edges_[newEdgeIndex][1],
2042 edgePoints_[edgeHull[indexI]]
2045 // Add this edge to faceEdges for the new interior face
2046 faceEdges_[addedIntFaceIndices[indexI]][0] = edgeHull[indexI];
2048 // Replace face labels
2049 meshOps::replaceLabel
2052 addedIntFaceIndices[indexI],
2053 cells_[cellHull[indexI]]
2056 // Add to the new cell
2057 newCell[1] = replaceFace;
2059 // Check if this is a boundary face
2060 if (cellHull[prevI] == -1)
2062 // Configure the boundary face
2063 tmpTriFace[0] = newPointIndex;
2064 tmpTriFace[1] = edges_[newEdgeIndex][1];
2065 tmpTriFace[2] = vertexHull[indexI];
2068 addedFaceIndices[indexI] =
2072 whichPatch(faceHull[indexI]),
2074 addedCellIndices[indexI],
2079 // Add this face to the map.
2080 map.addFace(addedFaceIndices[indexI]);
2082 // Configure edgeFaces
2083 tmpEdgeFaces[0] = faceHull[indexI];
2084 tmpEdgeFaces[1] = addedIntFaceIndices[indexI];
2085 tmpEdgeFaces[2] = addedFaceIndices[indexI];
2087 // Configure edgePoints
2088 tmpEdgePoints[0] = edges_[eIndex][0];
2089 tmpEdgePoints[1] = vertexHull[nextI];
2090 tmpEdgePoints[2] = edges_[newEdgeIndex][1];
2093 addedEdgeIndices[indexI] =
2097 whichPatch(faceHull[indexI]),
2098 edge(newPointIndex,vertexHull[indexI]),
2104 // Add this edge to the map.
2105 map.addEdge(addedEdgeIndices[indexI]);
2107 // Add this edge to the interior-face faceEdges entry
2108 faceEdges_[addedIntFaceIndices[indexI]][1] =
2110 addedEdgeIndices[indexI]
2113 // Configure faceEdges for this boundary face
2114 tmpFaceEdges[0] = addedEdgeIndices[indexI];
2115 tmpFaceEdges[1] = newEdgeIndex;
2116 tmpFaceEdges[2] = ringEntities[2][indexI];
2118 // Modify faceEdges for the hull face
2119 meshOps::replaceLabel
2121 ringEntities[2][indexI],
2122 addedEdgeIndices[indexI],
2123 faceEdges_[faceHull[indexI]]
2126 // Modify edgeFaces for the edge connected to newEdge[1]
2127 meshOps::replaceLabel
2130 addedFaceIndices[indexI],
2131 edgeFaces_[ringEntities[2][indexI]]
2134 // Modify edgePoints for the edge connected to newEdge[1]
2135 meshOps::replaceLabel
2139 edgePoints_[ringEntities[2][indexI]]
2142 // Add the faceEdges entry
2143 faceEdges_.append(tmpFaceEdges);
2145 // Add an entry to edgeFaces
2146 edgeFaces_[newEdgeIndex][indexI] = addedFaceIndices[indexI];
2148 // Add an entry for this cell
2149 newCell[2] = addedFaceIndices[indexI];
2152 // Check if a cell was added before this
2153 if (addedCellIndices[prevI] != -1)
2155 // Configure the interior face
2156 tmpTriFace[0] = vertexHull[indexI];
2157 tmpTriFace[1] = edges_[newEdgeIndex][1];
2158 tmpTriFace[2] = newPointIndex;
2161 addedFaceIndices[indexI] =
2167 addedCellIndices[prevI],
2168 addedCellIndices[indexI]
2172 // Add this face to the map.
2173 map.addFace(addedFaceIndices[indexI]);
2175 // Configure edgeFaces
2176 tmpIntEdgeFaces[0] = faceHull[indexI];
2177 tmpIntEdgeFaces[1] = addedIntFaceIndices[indexI];
2178 tmpIntEdgeFaces[2] = addedFaceIndices[indexI];
2179 tmpIntEdgeFaces[3] = addedIntFaceIndices[prevI];
2181 // Configure edgePoints
2182 tmpIntEdgePoints[0] = edges_[eIndex][0];
2183 tmpIntEdgePoints[1] = vertexHull[nextI];
2184 tmpIntEdgePoints[2] = edges_[newEdgeIndex][1];
2185 tmpIntEdgePoints[3] = vertexHull[prevI];
2187 // Add an internal edge
2188 addedEdgeIndices[indexI] =
2193 edge(newPointIndex,vertexHull[indexI]),
2199 // Add this edge to the map.
2200 map.addEdge(addedEdgeIndices[indexI]);
2202 // Add this edge to the interior-face faceEdges entry..
2203 faceEdges_[addedIntFaceIndices[indexI]][1] =
2205 addedEdgeIndices[indexI]
2208 // ... and to the previous interior face as well
2209 faceEdges_[addedIntFaceIndices[prevI]][2] =
2211 addedEdgeIndices[indexI]
2214 // Configure faceEdges for this split interior face
2215 tmpFaceEdges[0] = addedEdgeIndices[indexI];
2216 tmpFaceEdges[1] = newEdgeIndex;
2217 tmpFaceEdges[2] = ringEntities[2][indexI];
2219 // Modify faceEdges for the hull face
2220 meshOps::replaceLabel
2222 ringEntities[2][indexI],
2223 addedEdgeIndices[indexI],
2224 faceEdges_[faceHull[indexI]]
2227 // Modify edgeFaces for the edge connected to newEdge[1]
2228 meshOps::replaceLabel
2231 addedFaceIndices[indexI],
2232 edgeFaces_[ringEntities[2][indexI]]
2235 // Modify edgePoints for the edge connected to newEdge[1]
2236 meshOps::replaceLabel
2240 edgePoints_[ringEntities[2][indexI]]
2243 // Add the faceEdges entry
2244 faceEdges_.append(tmpFaceEdges);
2246 // Add an entry to edgeFaces
2247 edgeFaces_[newEdgeIndex][indexI] = addedFaceIndices[indexI];
2249 // Add an entry for this cell
2250 newCell[2] = addedFaceIndices[indexI];
2252 // Make the final entry for the previous cell
2253 cells_[addedCellIndices[prevI]][3] = addedFaceIndices[indexI];
2256 // Do the first interior face at the end
2257 if (indexI == vertexHull.size() - 1)
2259 // Configure the interior face
2260 tmpTriFace[0] = newPointIndex;
2261 tmpTriFace[1] = edges_[newEdgeIndex][1];
2262 tmpTriFace[2] = vertexHull[0];
2265 addedFaceIndices[0] =
2271 addedCellIndices[0],
2272 addedCellIndices[indexI]
2276 // Add this face to the map.
2277 map.addFace(addedFaceIndices[0]);
2279 // Configure edgeFaces
2280 tmpIntEdgeFaces[0] = faceHull[0];
2281 tmpIntEdgeFaces[1] = addedIntFaceIndices[0];
2282 tmpIntEdgeFaces[2] = addedFaceIndices[0];
2283 tmpIntEdgeFaces[3] = addedIntFaceIndices[indexI];
2285 // Configure edgePoints
2286 tmpIntEdgePoints[0] = edges_[eIndex][0];
2287 tmpIntEdgePoints[1] = vertexHull[1];
2288 tmpIntEdgePoints[2] = edges_[newEdgeIndex][1];
2289 tmpIntEdgePoints[3] = vertexHull[indexI];
2291 // Add an internal edge
2292 addedEdgeIndices[0] =
2297 edge(newPointIndex,vertexHull[0]),
2303 // Add this edge to the map.
2304 map.addEdge(addedEdgeIndices[0]);
2306 // Add this edge to the interior-face faceEdges entry..
2307 faceEdges_[addedIntFaceIndices[0]][1] =
2312 // ... and to the previous interior face as well
2313 faceEdges_[addedIntFaceIndices[indexI]][2] =
2318 // Configure faceEdges for the first split face
2319 tmpFaceEdges[0] = addedEdgeIndices[0];
2320 tmpFaceEdges[1] = newEdgeIndex;
2321 tmpFaceEdges[2] = ringEntities[2][0];
2323 // Modify faceEdges for the hull face
2324 meshOps::replaceLabel
2327 addedEdgeIndices[0],
2328 faceEdges_[faceHull[0]]
2331 // Modify edgeFaces for the edge connected to newEdge[1]
2332 meshOps::replaceLabel
2335 addedFaceIndices[0],
2336 edgeFaces_[ringEntities[2][0]]
2339 // Modify edgePoints for the edge connected to newEdge[1]
2340 meshOps::replaceLabel
2344 edgePoints_[ringEntities[2][0]]
2347 // Add the faceEdges entry
2348 faceEdges_.append(tmpFaceEdges);
2350 // Add an entry to edgeFaces
2351 edgeFaces_[newEdgeIndex][0] = addedFaceIndices[0];
2353 // Add an entry for this cell
2354 newCell[3] = addedFaceIndices[0];
2356 // Make the final entry for the first cell
2357 cells_[addedCellIndices[0]][2] = addedFaceIndices[0];
2360 // Update the cell list with the new cell.
2361 cells_[addedCellIndices[indexI]] = newCell;
2365 // Configure the final boundary face
2366 tmpTriFace[0] = vertexHull[indexI];
2367 tmpTriFace[1] = edges_[newEdgeIndex][1];
2368 tmpTriFace[2] = newPointIndex;
2371 addedFaceIndices[indexI] =
2375 whichPatch(faceHull[indexI]),
2377 addedCellIndices[prevI],
2382 // Add this face to the map.
2383 map.addFace(addedFaceIndices[indexI]);
2385 // Configure edgeFaces
2386 tmpEdgeFaces[0] = addedFaceIndices[indexI];
2387 tmpEdgeFaces[1] = addedIntFaceIndices[prevI];
2388 tmpEdgeFaces[2] = faceHull[indexI];
2390 // Configure edgePoints
2391 tmpEdgePoints[0] = edges_[newEdgeIndex][1];
2392 tmpEdgePoints[1] = vertexHull[prevI];
2393 tmpEdgePoints[2] = edges_[eIndex][0];
2396 addedEdgeIndices[indexI] =
2400 whichPatch(faceHull[indexI]),
2401 edge(newPointIndex,vertexHull[indexI]),
2407 // Add this edge to the map.
2408 map.addEdge(addedEdgeIndices[indexI]);
2410 // Add a faceEdges entry to the previous interior face
2411 faceEdges_[addedIntFaceIndices[prevI]][2] =
2413 addedEdgeIndices[indexI]
2416 // Configure faceEdges for the final boundary face
2417 tmpFaceEdges[0] = addedEdgeIndices[indexI];
2418 tmpFaceEdges[1] = newEdgeIndex;
2419 tmpFaceEdges[2] = ringEntities[2][indexI];
2421 // Modify faceEdges for the hull face
2422 meshOps::replaceLabel
2424 ringEntities[2][indexI],
2425 addedEdgeIndices[indexI],
2426 faceEdges_[faceHull[indexI]]
2429 // Modify edgeFaces for the edge connected to newEdge[1]
2430 meshOps::replaceLabel
2433 addedFaceIndices[indexI],
2434 edgeFaces_[ringEntities[2][indexI]]
2437 // Modify edgePoints for the edge connected to newEdge[1]
2438 meshOps::replaceLabel
2442 edgePoints_[ringEntities[2][indexI]]
2445 // Add the faceEdges entry
2446 faceEdges_.append(tmpFaceEdges);
2448 // Add an entry to edgeFaces
2449 edgeFaces_[newEdgeIndex][indexI] = addedFaceIndices[indexI];
2451 // Make the final entry for the previous cell
2452 cells_[addedCellIndices[prevI]][3] = addedFaceIndices[indexI];
2456 // Now that all old / new cells possess correct connectivity,
2457 // compute mapping information.
2458 forAll(cellHull, indexI)
2460 if (cellHull[indexI] == -1)
2465 // Set mapping for both new and modified cells.
2466 FixedList<label, 2> cmIndex;
2468 cmIndex[0] = cellHull[indexI];
2469 cmIndex[1] = addedCellIndices[indexI];
2471 // Fill-in candidate mapping information
2472 labelList mC(1, cellHull[indexI]);
2474 forAll(cmIndex, cmI)
2476 // Set the mapping for this cell
2477 setCellMapping(cmIndex[cmI], mC);
2481 // Set mapping information for old / new faces
2482 forAll(faceHull, indexI)
2484 // Interior faces get default mapping
2485 if (addedIntFaceIndices[indexI] > -1)
2487 setFaceMapping(addedIntFaceIndices[indexI]);
2490 // Decide between default / weighted mapping
2491 // based on boundary information
2492 if (whichPatch(faceHull[indexI]) == -1)
2494 // Interior faces get default mapping
2495 setFaceMapping(faceHull[indexI]);
2496 setFaceMapping(addedFaceIndices[indexI]);
2500 // Compute mapping weights for boundary faces
2501 FixedList<label, 2> fmIndex;
2503 fmIndex[0] = faceHull[indexI];
2504 fmIndex[1] = addedFaceIndices[indexI];
2506 // Fill-in candidate mapping information
2507 labelList mF(1, faceHull[indexI]);
2509 forAll(fmIndex, fmI)
2511 // Set the mapping for this face
2512 setFaceMapping(fmIndex[fmI], mF);
2519 label bPatch = whichEdgePatch(eIndex);
2523 Info << "Patch: Internal" << endl;
2527 Info << "Patch: " << boundaryMesh()[bPatch].name() << endl;
2530 Info << "EdgePoints: " << vertexHull << endl;
2531 Info << "Edges: " << edgeHull << endl;
2532 Info << "Faces: " << faceHull << endl;
2533 Info << "Cells: " << cellHull << endl;
2535 Info << "Modified cells: " << endl;
2537 forAll(cellHull, cellI)
2539 if (cellHull[cellI] == -1)
2544 Info << cellHull[cellI] << ":: "
2545 << cells_[cellHull[cellI]]
2549 Info << "Added cells: " << endl;
2551 forAll(addedCellIndices, cellI)
2553 if (addedCellIndices[cellI] == -1)
2558 Info << addedCellIndices[cellI] << ":: "
2559 << cells_[addedCellIndices[cellI]] << nl
2560 << "lengthScale: " << lengthScale_[addedCellIndices[cellI]]
2564 Info << "Modified faces: " << endl;
2566 forAll(faceHull, faceI)
2568 Info << faceHull[faceI] << ":: "
2569 << faces_[faceHull[faceI]] << ": "
2570 << owner_[faceHull[faceI]] << ": "
2571 << neighbour_[faceHull[faceI]] << " "
2572 << "faceEdges:: " << faceEdges_[faceHull[faceI]]
2576 Info << "Added faces: " << endl;
2578 forAll(addedFaceIndices, faceI)
2580 Info << addedFaceIndices[faceI] << ":: "
2581 << faces_[addedFaceIndices[faceI]] << ": "
2582 << owner_[addedFaceIndices[faceI]] << ": "
2583 << neighbour_[addedFaceIndices[faceI]] << " "
2584 << "faceEdges:: " << faceEdges_[addedFaceIndices[faceI]]
2588 forAll(addedIntFaceIndices, faceI)
2590 if (addedIntFaceIndices[faceI] == -1)
2595 Info << addedIntFaceIndices[faceI] << ":: "
2596 << faces_[addedIntFaceIndices[faceI]] << ": "
2597 << owner_[addedIntFaceIndices[faceI]] << ": "
2598 << neighbour_[addedIntFaceIndices[faceI]] << " "
2600 << faceEdges_[addedIntFaceIndices[faceI]]
2604 Info << "New edge:: " << newEdgeIndex
2605 << ": " << edges_[newEdgeIndex] << nl
2606 << " edgeFaces:: " << edgeFaces_[newEdgeIndex] << nl
2607 << " edgePoints:: " << edgePoints_[newEdgeIndex]
2610 Info << "Added edges: " << endl;
2612 forAll(addedEdgeIndices, edgeI)
2614 Info << addedEdgeIndices[edgeI]
2615 << ":: " << edges_[addedEdgeIndices[edgeI]] << nl
2616 << " edgeFaces:: " << edgeFaces_[addedEdgeIndices[edgeI]] << nl
2617 << " edgePoints:: " << edgePoints_[addedEdgeIndices[edgeI]]
2621 Info << "New Point:: " << newPointIndex << endl;
2622 Info << "pointEdges:: " << pointEdges_[newPointIndex] << endl;
2624 // Write out VTK files after change
2627 labelList newHull(cellHull.size() + addedCellIndices.size(), 0);
2629 // Combine both lists into one.
2632 newHull[i] = cellHull[i];
2635 label start = cellHull.size();
2637 for(label i = start; i < newHull.size(); i++)
2639 newHull[i] = addedCellIndices[i - start];
2652 topoChangeFlag_ = true;
2654 // Increment the counter
2657 // Increment the number of modifications
2660 // Specify that the operation was successful
2663 // Return the changeMap
2667 // Method for the trisection of a face in 3D
2668 // - Returns a changeMap with a type specifying:
2669 // 1: Trisection was successful
2670 // -1: Trisection failed since max number of topo-changes was reached.
2671 // -2: Trisection failed since resulting quality would be really bad.
2672 // - AddedPoint is the index of the newly added point.
2673 const changeMap dynamicTopoFvMesh::trisectFace
2680 // Face trisection performs the following operations:
2681 // [1] Add a point at middle of the face
2682 // [2] Remove the face and add three new faces in place.
2683 // [3] Add three cells for each trisected cell (remove the originals).
2684 // [4] Create one internal edge for each trisected cell.
2685 // [5] Create three edges for the trisected face.
2686 // [6] Create three internal faces for each trisected cell.
2687 // Update faceEdges, edgeFaces and edgePoints information.
2689 // Figure out which thread this is...
2690 label tIndex = self();
2692 // Prepare the changeMaps
2693 changeMap map, slaveMap;
2697 (statistics_[0] > maxModifications_) &&
2698 (maxModifications_ > -1)
2701 // Reached the max allowable topo-changes.
2702 stack(tIndex).clear();
2707 // Sanity check: Is the index legitimate?
2712 "const changeMap dynamicTopoFvMesh::trisectFace\n"
2714 " const label fIndex,\n"
2715 " bool checkOnly,\n"
2719 << " Invalid index: " << fIndex
2720 << abort(FatalError);
2723 // Before we trisect this face, check whether the operation will
2724 // yield an acceptable cell-quality.
2727 if ((minQ = computeTrisectionQuality(fIndex)) < sliverThreshold_)
2729 // Check if the quality is actually valid before forcing it.
2730 if (forceOp && (minQ < 0.0))
2734 "const changeMap dynamicTopoFvMesh::trisectFace\n"
2736 " const label fIndex,\n"
2737 " bool checkOnly,\n"
2741 << " Forcing trisection on face: " << fIndex
2742 << " will yield an invalid cell."
2743 << abort(FatalError);
2753 // Are we performing only checks?
2760 // Update number of surface bisections, if necessary.
2761 if (whichPatch(fIndex) > -1)
2768 labelList newTriEdgeFaces(3), newTriEdgePoints(3);
2769 labelList newQuadEdgeFaces(4), newQuadEdgePoints(4);
2771 FixedList<label,2> apexPoint(-1);
2772 FixedList<face, 3> checkFace(face(3));
2773 FixedList<label,5> newEdgeIndex(-1);
2774 FixedList<label,9> newFaceIndex(-1);
2775 FixedList<label,6> newCellIndex(-1);
2776 FixedList<cell, 6> newTetCell(cell(4));
2777 FixedList<labelList, 9> newFaceEdges(labelList(3));
2779 // Counters for entities
2780 FixedList<label, 9> nE(0);
2781 FixedList<label, 6> nF(0);
2783 // Determine the two cells to be removed
2784 FixedList<label,2> cellsForRemoval;
2785 cellsForRemoval[0] = owner_[fIndex];
2786 cellsForRemoval[1] = neighbour_[fIndex];
2791 << "Face: " << fIndex
2792 << ": " << faces_[fIndex]
2793 << " is to be trisected. " << endl;
2795 // Write out VTK files prior to change
2800 if (neighbour_[fIndex] == -1)
2802 vtkCells.setSize(1);
2803 vtkCells[0] = owner_[fIndex];
2807 vtkCells.setSize(2);
2808 vtkCells[0] = owner_[fIndex];
2809 vtkCells[1] = neighbour_[fIndex];
2821 labelList mP(3, -1);
2823 // Fill in mapping information
2824 mP[0] = faces_[fIndex][0];
2825 mP[1] = faces_[fIndex][1];
2826 mP[2] = faces_[fIndex][2];
2828 // Add a new point to the end of the list
2829 scalar oT = (1.0/3.0);
2831 label newPointIndex =
2835 oT * (points_[mP[0]] + points_[mP[1]] + points_[mP[2]]),
2836 oT * (oldPoints_[mP[0]] + oldPoints_[mP[1]] + oldPoints_[mP[2]]),
2841 // Add this point to the map.
2842 map.addPoint(newPointIndex);
2844 // Add three new cells to the end of the cell list
2845 for (label i = 0; i < 3; i++)
2847 scalar parentScale = -1.0;
2849 if (edgeRefinement_)
2851 parentScale = lengthScale_[cellsForRemoval[0]];
2854 newCellIndex[i] = insertCell(newTetCell[i], parentScale);
2856 // Add cells to the map
2857 map.addCell(newCellIndex[i]);
2860 // Find the apex point for this cell
2863 meshOps::tetApexPoint
2872 // Insert three new internal faces
2874 // First face: Owner: newCellIndex[0], Neighbour: newCellIndex[1]
2875 tmpTriFace[0] = newPointIndex;
2876 tmpTriFace[1] = faces_[fIndex][0];
2877 tmpTriFace[2] = apexPoint[0];
2890 // Second face: Owner: newCellIndex[1], Neighbour: newCellIndex[2]
2891 tmpTriFace[0] = newPointIndex;
2892 tmpTriFace[1] = faces_[fIndex][1];
2893 tmpTriFace[2] = apexPoint[0];
2906 // Third face: Owner: newCellIndex[0], Neighbour: newCellIndex[2]
2907 tmpTriFace[0] = newPointIndex;
2908 tmpTriFace[1] = apexPoint[0];
2909 tmpTriFace[2] = faces_[fIndex][2];
2922 // Add an entry to edgeFaces
2923 newTriEdgeFaces[0] = newFaceIndex[0];
2924 newTriEdgeFaces[1] = newFaceIndex[1];
2925 newTriEdgeFaces[2] = newFaceIndex[2];
2927 // Add an entry for edgePoints as well
2928 newTriEdgePoints[0] = faces_[fIndex][0];
2929 newTriEdgePoints[1] = faces_[fIndex][1];
2930 newTriEdgePoints[2] = faces_[fIndex][2];
2932 // Add a new internal edge to the mesh
2948 // Configure faceEdges with the new internal edge
2949 newFaceEdges[0][nE[0]++] = newEdgeIndex[0];
2950 newFaceEdges[1][nE[1]++] = newEdgeIndex[0];
2951 newFaceEdges[2][nE[2]++] = newEdgeIndex[0];
2953 // Add the newly created faces to cells
2954 newTetCell[0][nF[0]++] = newFaceIndex[0];
2955 newTetCell[0][nF[0]++] = newFaceIndex[2];
2956 newTetCell[1][nF[1]++] = newFaceIndex[0];
2957 newTetCell[1][nF[1]++] = newFaceIndex[1];
2958 newTetCell[2][nF[2]++] = newFaceIndex[1];
2959 newTetCell[2][nF[2]++] = newFaceIndex[2];
2961 // Define the three faces to check for orientation:
2962 checkFace[0][0] = faces_[fIndex][2];
2963 checkFace[0][1] = apexPoint[0];
2964 checkFace[0][2] = faces_[fIndex][0];
2966 checkFace[1][0] = faces_[fIndex][0];
2967 checkFace[1][1] = apexPoint[0];
2968 checkFace[1][2] = faces_[fIndex][1];
2970 checkFace[2][0] = faces_[fIndex][1];
2971 checkFace[2][1] = apexPoint[0];
2972 checkFace[2][2] = faces_[fIndex][2];
2974 // Check the orientation of faces on the first cell.
2975 forAll(cells_[owner_[fIndex]], faceI)
2977 label faceIndex = cells_[owner_[fIndex]][faceI];
2979 if (faceIndex == fIndex)
2984 const face& faceToCheck = faces_[faceIndex];
2985 label cellIndex = cellsForRemoval[0];
2986 label newIndex = -1;
2988 // Check against faces.
2989 if (triFace::compare(triFace(faceToCheck), triFace(checkFace[0])))
2991 newIndex = newCellIndex[0];
2992 newTetCell[0][nF[0]++] = faceIndex;
2995 if (triFace::compare(triFace(faceToCheck), triFace(checkFace[1])))
2997 newIndex = newCellIndex[1];
2998 newTetCell[1][nF[1]++] = faceIndex;
3001 if (triFace::compare(triFace(faceToCheck), triFace(checkFace[2])))
3003 newIndex = newCellIndex[2];
3004 newTetCell[2][nF[2]++] = faceIndex;
3008 // Something's terribly wrong.
3011 "const changeMap dynamicTopoFvMesh::trisectFace\n"
3013 " const label fIndex,\n"
3014 " bool checkOnly,\n"
3018 << "Failed to determine a face match."
3019 << abort(FatalError);
3022 // Check if a face-flip is necessary
3023 if (owner_[faceIndex] == cellIndex)
3025 if (neighbour_[faceIndex] == -1)
3028 owner_[faceIndex] = newIndex;
3033 faces_[faceIndex] = faceToCheck.reverseFace();
3034 owner_[faceIndex] = neighbour_[faceIndex];
3035 neighbour_[faceIndex] = newIndex;
3042 // Flip is unnecessary. Just update neighbour
3043 neighbour_[faceIndex] = newIndex;
3047 if (cellsForRemoval[1] == -1)
3049 // Boundary face. Determine its patch.
3050 label facePatch = whichPatch(fIndex);
3052 // Add three new boundary faces.
3054 // Fourth face: Owner: newCellIndex[0], Neighbour: -1
3055 tmpTriFace[0] = newPointIndex;
3056 tmpTriFace[1] = faces_[fIndex][2];
3057 tmpTriFace[2] = faces_[fIndex][0];
3070 // Fifth face: Owner: newCellIndex[1], Neighbour: -1
3071 tmpTriFace[0] = newPointIndex;
3072 tmpTriFace[1] = faces_[fIndex][0];
3073 tmpTriFace[2] = faces_[fIndex][1];
3086 // Sixth face: Owner: newCellIndex[2], Neighbour: -1
3087 tmpTriFace[0] = newPointIndex;
3088 tmpTriFace[1] = faces_[fIndex][1];
3089 tmpTriFace[2] = faces_[fIndex][2];
3102 // Add the newly created faces to cells
3103 newTetCell[0][nF[0]++] = newFaceIndex[3];
3104 newTetCell[1][nF[1]++] = newFaceIndex[4];
3105 newTetCell[2][nF[2]++] = newFaceIndex[5];
3107 // Configure edgeFaces and edgePoints for three new boundary edges.
3108 newTriEdgeFaces[0] = newFaceIndex[4];
3109 newTriEdgeFaces[1] = newFaceIndex[0];
3110 newTriEdgeFaces[2] = newFaceIndex[3];
3112 newTriEdgePoints[0] = faces_[fIndex][1];
3113 newTriEdgePoints[1] = apexPoint[0];
3114 newTriEdgePoints[2] = faces_[fIndex][2];
3131 newTriEdgeFaces[0] = newFaceIndex[5];
3132 newTriEdgeFaces[1] = newFaceIndex[1];
3133 newTriEdgeFaces[2] = newFaceIndex[4];
3135 newTriEdgePoints[0] = faces_[fIndex][2];
3136 newTriEdgePoints[1] = apexPoint[0];
3137 newTriEdgePoints[2] = faces_[fIndex][0];
3154 newTriEdgeFaces[0] = newFaceIndex[3];
3155 newTriEdgeFaces[1] = newFaceIndex[2];
3156 newTriEdgeFaces[2] = newFaceIndex[5];
3158 newTriEdgePoints[0] = faces_[fIndex][0];
3159 newTriEdgePoints[1] = apexPoint[0];
3160 newTriEdgePoints[2] = faces_[fIndex][1];
3177 // Configure faceEdges with the three new edges.
3178 newFaceEdges[0][nE[0]++] = newEdgeIndex[1];
3179 newFaceEdges[1][nE[1]++] = newEdgeIndex[2];
3180 newFaceEdges[2][nE[2]++] = newEdgeIndex[3];
3182 newFaceEdges[3][nE[3]++] = newEdgeIndex[1];
3183 newFaceEdges[3][nE[3]++] = newEdgeIndex[3];
3184 newFaceEdges[4][nE[4]++] = newEdgeIndex[1];
3185 newFaceEdges[4][nE[4]++] = newEdgeIndex[2];
3186 newFaceEdges[5][nE[5]++] = newEdgeIndex[2];
3187 newFaceEdges[5][nE[5]++] = newEdgeIndex[3];
3189 // Define the six edges to check while building faceEdges:
3190 FixedList<edge,6> check;
3192 check[0][0] = apexPoint[0]; check[0][1] = faces_[fIndex][0];
3193 check[1][0] = apexPoint[0]; check[1][1] = faces_[fIndex][1];
3194 check[2][0] = apexPoint[0]; check[2][1] = faces_[fIndex][2];
3196 check[3][0] = faces_[fIndex][2]; check[3][1] = faces_[fIndex][0];
3197 check[4][0] = faces_[fIndex][0]; check[4][1] = faces_[fIndex][1];
3198 check[5][0] = faces_[fIndex][1]; check[5][1] = faces_[fIndex][2];
3200 // Build a list of cellEdges
3201 labelHashSet cellEdges;
3203 forAll(cells_[owner_[fIndex]], faceI)
3205 const labelList& fEdges =
3207 faceEdges_[cells_[owner_[fIndex]][faceI]]
3210 forAll(fEdges, edgeI)
3212 if (!cellEdges.found(fEdges[edgeI]))
3214 cellEdges.insert(fEdges[edgeI]);
3219 // Loop through cellEdges, and perform appropriate actions.
3220 forAllIter(labelHashSet, cellEdges, eIter)
3222 const edge& edgeToCheck = edges_[eIter.key()];
3224 // Check against the specified edges.
3225 if (edgeToCheck == check[0])
3227 meshOps::insertLabel
3232 edgePoints_[eIter.key()]
3235 meshOps::sizeUpList(newFaceIndex[0], edgeFaces_[eIter.key()]);
3236 newFaceEdges[0][nE[0]++] = eIter.key();
3239 if (edgeToCheck == check[1])
3241 meshOps::insertLabel
3246 edgePoints_[eIter.key()]
3249 meshOps::sizeUpList(newFaceIndex[1], edgeFaces_[eIter.key()]);
3250 newFaceEdges[1][nE[1]++] = eIter.key();
3253 if (edgeToCheck == check[2])
3255 meshOps::insertLabel
3260 edgePoints_[eIter.key()]
3263 meshOps::sizeUpList(newFaceIndex[2], edgeFaces_[eIter.key()]);
3264 newFaceEdges[2][nE[2]++] = eIter.key();
3267 if (edgeToCheck == check[3])
3269 meshOps::replaceLabel
3273 edgePoints_[eIter.key()]
3276 meshOps::replaceLabel
3280 edgeFaces_[eIter.key()]
3283 newFaceEdges[3][nE[3]++] = eIter.key();
3286 if (edgeToCheck == check[4])
3288 meshOps::replaceLabel
3292 edgePoints_[eIter.key()]
3295 meshOps::replaceLabel
3299 edgeFaces_[eIter.key()]
3302 newFaceEdges[4][nE[4]++] = eIter.key();
3305 if (edgeToCheck == check[5])
3307 meshOps::replaceLabel
3311 edgePoints_[eIter.key()]
3314 meshOps::replaceLabel
3318 edgeFaces_[eIter.key()]
3321 newFaceEdges[5][nE[5]++] = eIter.key();
3325 // Now that faceEdges has been configured, append them to the list.
3326 for (label i = 0; i < 6; i++)
3328 faceEdges_.append(newFaceEdges[i]);
3330 // Add faces to the map.
3331 map.addFace(newFaceIndex[i]);
3336 // Add three new cells to the end of the cell list
3337 for (label i = 3; i < 6; i++)
3339 scalar parentScale = -1.0;
3341 if (edgeRefinement_)
3343 parentScale = lengthScale_[cellsForRemoval[1]];
3346 newCellIndex[i] = insertCell(newTetCell[i], parentScale);
3349 map.addCell(newCellIndex[i]);
3352 // Find the apex point for this cell
3355 meshOps::tetApexPoint
3364 // Add six new interior faces.
3366 // Fourth face: Owner: newCellIndex[0], Neighbour: newCellIndex[3]
3367 tmpTriFace[0] = newPointIndex;
3368 tmpTriFace[1] = faces_[fIndex][2];
3369 tmpTriFace[2] = faces_[fIndex][0];
3382 // Fifth face: Owner: newCellIndex[1], Neighbour: newCellIndex[4]
3383 tmpTriFace[0] = newPointIndex;
3384 tmpTriFace[1] = faces_[fIndex][0];
3385 tmpTriFace[2] = faces_[fIndex][1];
3398 // Sixth face: Owner: newCellIndex[2], Neighbour: newCellIndex[5]
3399 tmpTriFace[0] = newPointIndex;
3400 tmpTriFace[1] = faces_[fIndex][1];
3401 tmpTriFace[2] = faces_[fIndex][2];
3414 // Seventh face: Owner: newCellIndex[3], Neighbour: newCellIndex[4]
3415 tmpTriFace[0] = newPointIndex;
3416 tmpTriFace[1] = apexPoint[1];
3417 tmpTriFace[2] = faces_[fIndex][0];
3430 // Eighth face: Owner: newCellIndex[4], Neighbour: newCellIndex[5]
3431 tmpTriFace[0] = newPointIndex;
3432 tmpTriFace[1] = apexPoint[1];
3433 tmpTriFace[2] = faces_[fIndex][1];
3446 // Ninth face: Owner: newCellIndex[3], Neighbour: newCellIndex[5]
3447 tmpTriFace[0] = newPointIndex;
3448 tmpTriFace[1] = faces_[fIndex][2];
3449 tmpTriFace[2] = apexPoint[1];
3462 // Add the newly created faces to cells
3463 newTetCell[3][nF[3]++] = newFaceIndex[6];
3464 newTetCell[3][nF[3]++] = newFaceIndex[8];
3465 newTetCell[4][nF[4]++] = newFaceIndex[6];
3466 newTetCell[4][nF[4]++] = newFaceIndex[7];
3467 newTetCell[5][nF[5]++] = newFaceIndex[7];
3468 newTetCell[5][nF[5]++] = newFaceIndex[8];
3470 newTetCell[0][nF[0]++] = newFaceIndex[3];
3471 newTetCell[1][nF[1]++] = newFaceIndex[4];
3472 newTetCell[2][nF[2]++] = newFaceIndex[5];
3474 newTetCell[3][nF[3]++] = newFaceIndex[3];
3475 newTetCell[4][nF[4]++] = newFaceIndex[4];
3476 newTetCell[5][nF[5]++] = newFaceIndex[5];
3478 // Define the three faces to check for orientation:
3479 checkFace[0][0] = faces_[fIndex][2];
3480 checkFace[0][1] = apexPoint[1];
3481 checkFace[0][2] = faces_[fIndex][0];
3483 checkFace[1][0] = faces_[fIndex][0];
3484 checkFace[1][1] = apexPoint[1];
3485 checkFace[1][2] = faces_[fIndex][1];
3487 checkFace[2][0] = faces_[fIndex][1];
3488 checkFace[2][1] = apexPoint[1];
3489 checkFace[2][2] = faces_[fIndex][2];
3491 // Check the orientation of faces on the second cell.
3492 forAll(cells_[neighbour_[fIndex]], faceI)
3494 label faceIndex = cells_[neighbour_[fIndex]][faceI];
3496 if (faceIndex == fIndex)
3501 const face& faceToCheck = faces_[faceIndex];
3502 label cellIndex = cellsForRemoval[1];
3503 label newIndex = -1;
3505 // Check against faces.
3506 if (triFace::compare(triFace(faceToCheck), triFace(checkFace[0])))
3508 newIndex = newCellIndex[3];
3509 newTetCell[3][nF[3]++] = faceIndex;
3512 if (triFace::compare(triFace(faceToCheck), triFace(checkFace[1])))
3514 newIndex = newCellIndex[4];
3515 newTetCell[4][nF[4]++] = faceIndex;
3518 if (triFace::compare(triFace(faceToCheck), triFace(checkFace[2])))
3520 newIndex = newCellIndex[5];
3521 newTetCell[5][nF[5]++] = faceIndex;
3525 // Something's terribly wrong.
3528 "const changeMap dynamicTopoFvMesh::trisectFace\n"
3530 " const label fIndex,\n"
3531 " bool checkOnly,\n"
3535 << "Failed to determine a face match."
3536 << abort(FatalError);
3539 // Check if a face-flip is necessary
3540 if (owner_[faceIndex] == cellIndex)
3542 if (neighbour_[faceIndex] == -1)
3545 owner_[faceIndex] = newIndex;
3550 faces_[faceIndex] = faceToCheck.reverseFace();
3551 owner_[faceIndex] = neighbour_[faceIndex];
3552 neighbour_[faceIndex] = newIndex;
3559 // Flip is unnecessary. Just update neighbour
3560 neighbour_[faceIndex] = newIndex;
3564 // Configure edgeFaces and edgePoints for four new interior edges.
3565 newQuadEdgeFaces[0] = newFaceIndex[4];
3566 newQuadEdgeFaces[1] = newFaceIndex[0];
3567 newQuadEdgeFaces[2] = newFaceIndex[3];
3568 newQuadEdgeFaces[3] = newFaceIndex[6];
3570 newQuadEdgePoints[0] = faces_[fIndex][1];
3571 newQuadEdgePoints[1] = apexPoint[0];
3572 newQuadEdgePoints[2] = faces_[fIndex][2];
3573 newQuadEdgePoints[3] = apexPoint[1];
3590 newQuadEdgeFaces[0] = newFaceIndex[5];
3591 newQuadEdgeFaces[1] = newFaceIndex[1];
3592 newQuadEdgeFaces[2] = newFaceIndex[4];
3593 newQuadEdgeFaces[3] = newFaceIndex[7];
3595 newQuadEdgePoints[0] = faces_[fIndex][2];
3596 newQuadEdgePoints[1] = apexPoint[0];
3597 newQuadEdgePoints[2] = faces_[fIndex][0];
3598 newQuadEdgePoints[3] = apexPoint[1];
3615 newQuadEdgeFaces[0] = newFaceIndex[3];
3616 newQuadEdgeFaces[1] = newFaceIndex[2];
3617 newQuadEdgeFaces[2] = newFaceIndex[5];
3618 newQuadEdgeFaces[3] = newFaceIndex[8];
3620 newQuadEdgePoints[0] = faces_[fIndex][0];
3621 newQuadEdgePoints[1] = apexPoint[0];
3622 newQuadEdgePoints[2] = faces_[fIndex][1];
3623 newQuadEdgePoints[3] = apexPoint[1];
3640 newTriEdgeFaces[0] = newFaceIndex[6];
3641 newTriEdgeFaces[1] = newFaceIndex[7];
3642 newTriEdgeFaces[2] = newFaceIndex[8];
3644 newTriEdgePoints[0] = faces_[fIndex][0];
3645 newTriEdgePoints[1] = faces_[fIndex][1];
3646 newTriEdgePoints[2] = faces_[fIndex][2];
3663 // Configure faceEdges with the new internal edges
3664 newFaceEdges[0][nE[0]++] = newEdgeIndex[1];
3665 newFaceEdges[1][nE[1]++] = newEdgeIndex[2];
3666 newFaceEdges[2][nE[2]++] = newEdgeIndex[3];
3668 newFaceEdges[3][nE[3]++] = newEdgeIndex[1];
3669 newFaceEdges[3][nE[3]++] = newEdgeIndex[3];
3670 newFaceEdges[4][nE[4]++] = newEdgeIndex[1];
3671 newFaceEdges[4][nE[4]++] = newEdgeIndex[2];
3672 newFaceEdges[5][nE[5]++] = newEdgeIndex[2];
3673 newFaceEdges[5][nE[5]++] = newEdgeIndex[3];
3675 newFaceEdges[6][nE[6]++] = newEdgeIndex[1];
3676 newFaceEdges[7][nE[7]++] = newEdgeIndex[2];
3677 newFaceEdges[8][nE[8]++] = newEdgeIndex[3];
3679 newFaceEdges[6][nE[6]++] = newEdgeIndex[4];
3680 newFaceEdges[7][nE[7]++] = newEdgeIndex[4];
3681 newFaceEdges[8][nE[8]++] = newEdgeIndex[4];
3683 // Define the nine edges to check while building faceEdges:
3684 FixedList<edge,9> check;
3686 check[0][0] = apexPoint[0]; check[0][1] = faces_[fIndex][0];
3687 check[1][0] = apexPoint[0]; check[1][1] = faces_[fIndex][1];
3688 check[2][0] = apexPoint[0]; check[2][1] = faces_[fIndex][2];
3690 check[3][0] = faces_[fIndex][2]; check[3][1] = faces_[fIndex][0];
3691 check[4][0] = faces_[fIndex][0]; check[4][1] = faces_[fIndex][1];
3692 check[5][0] = faces_[fIndex][1]; check[5][1] = faces_[fIndex][2];
3694 check[6][0] = apexPoint[1]; check[6][1] = faces_[fIndex][0];
3695 check[7][0] = apexPoint[1]; check[7][1] = faces_[fIndex][1];
3696 check[8][0] = apexPoint[1]; check[8][1] = faces_[fIndex][2];
3698 // Build a list of cellEdges
3699 labelHashSet cellEdges;
3701 forAll(cells_[owner_[fIndex]], faceI)
3703 const labelList& fEdges =
3705 faceEdges_[cells_[owner_[fIndex]][faceI]]
3708 forAll(fEdges, edgeI)
3710 if (!cellEdges.found(fEdges[edgeI]))
3712 cellEdges.insert(fEdges[edgeI]);
3717 forAll(cells_[neighbour_[fIndex]], faceI)
3719 const labelList& fEdges =
3721 faceEdges_[cells_[neighbour_[fIndex]][faceI]]
3724 forAll(fEdges, edgeI)
3726 if (!cellEdges.found(fEdges[edgeI]))
3728 cellEdges.insert(fEdges[edgeI]);
3733 // Loop through cellEdges, and perform appropriate actions.
3734 forAllIter(labelHashSet, cellEdges, eIter)
3736 const edge& edgeToCheck = edges_[eIter.key()];
3738 // Check against the specified edges.
3739 if (edgeToCheck == check[0])
3741 meshOps::insertLabel
3746 edgePoints_[eIter.key()]
3749 meshOps::sizeUpList(newFaceIndex[0], edgeFaces_[eIter.key()]);
3750 newFaceEdges[0][nE[0]++] = eIter.key();
3753 if (edgeToCheck == check[1])
3755 meshOps::insertLabel
3760 edgePoints_[eIter.key()]
3763 meshOps::sizeUpList(newFaceIndex[1], edgeFaces_[eIter.key()]);
3764 newFaceEdges[1][nE[1]++] = eIter.key();
3767 if (edgeToCheck == check[2])
3769 meshOps::insertLabel
3774 edgePoints_[eIter.key()]
3777 meshOps::sizeUpList(newFaceIndex[2], edgeFaces_[eIter.key()]);
3778 newFaceEdges[2][nE[2]++] = eIter.key();
3781 if (edgeToCheck == check[3])
3783 meshOps::replaceLabel
3787 edgePoints_[eIter.key()]
3790 meshOps::replaceLabel
3794 edgeFaces_[eIter.key()]
3797 newFaceEdges[3][nE[3]++] = eIter.key();
3800 if (edgeToCheck == check[4])
3802 meshOps::replaceLabel
3806 edgePoints_[eIter.key()]
3809 meshOps::replaceLabel
3813 edgeFaces_[eIter.key()]
3816 newFaceEdges[4][nE[4]++] = eIter.key();
3819 if (edgeToCheck == check[5])
3821 meshOps::replaceLabel
3825 edgePoints_[eIter.key()]
3828 meshOps::replaceLabel
3832 edgeFaces_[eIter.key()]
3835 newFaceEdges[5][nE[5]++] = eIter.key();
3838 if (edgeToCheck == check[6])
3840 meshOps::insertLabel
3845 edgePoints_[eIter.key()]
3848 meshOps::sizeUpList(newFaceIndex[6], edgeFaces_[eIter.key()]);
3849 newFaceEdges[6][nE[6]++] = eIter.key();
3852 if (edgeToCheck == check[7])
3854 meshOps::insertLabel
3859 edgePoints_[eIter.key()]
3862 meshOps::sizeUpList(newFaceIndex[7], edgeFaces_[eIter.key()]);
3863 newFaceEdges[7][nE[7]++] = eIter.key();
3866 if (edgeToCheck == check[8])
3868 meshOps::insertLabel
3873 edgePoints_[eIter.key()]
3876 meshOps::sizeUpList(newFaceIndex[8], edgeFaces_[eIter.key()]);
3877 newFaceEdges[8][nE[8]++] = eIter.key();
3881 // Now that faceEdges has been configured, append them to the list.
3882 for (label i = 0; i < 9; i++)
3884 faceEdges_.append(newFaceEdges[i]);
3886 // Add faces to the map.
3887 map.addFace(newFaceIndex[i]);
3891 // Added edges are those connected to the new point
3892 const labelList& pointEdges = pointEdges_[newPointIndex];
3894 forAll(pointEdges, edgeI)
3896 map.addEdge(pointEdges[edgeI]);
3899 // Now generate mapping info and remove entities.
3900 forAll(cellsForRemoval, cellI)
3902 label cIndex = cellsForRemoval[cellI];
3909 // Fill-in mapping information
3910 labelList mC(1, cellsForRemoval[cellI]);
3914 for (label i = 0; i < 3; i++)
3916 // Update the cell list with newly configured cells.
3917 cells_[newCellIndex[i]] = newTetCell[i];
3919 setCellMapping(newCellIndex[i], mC);
3924 for (label i = 3; i < 6; i++)
3926 // Update the cell list with newly configured cells.
3927 cells_[newCellIndex[i]] = newTetCell[i];
3929 setCellMapping(newCellIndex[i], mC);
3936 // Set default mapping for interior faces.
3937 for (label i = 0; i < 3; i++)
3939 setFaceMapping(newFaceIndex[i]);
3942 if (cellsForRemoval[1] == -1)
3944 // Set mapping for boundary faces.
3945 for (label i = 3; i < 6; i++)
3947 setFaceMapping(newFaceIndex[i], labelList(1, fIndex));
3952 // Set default mapping for interior faces.
3953 for (label i = 3; i < 9; i++)
3955 setFaceMapping(newFaceIndex[i]);
3959 // Now finally remove the face...
3964 Info << "New Point:: " << newPointIndex << endl;
3966 const labelList& pEdges = pointEdges_[newPointIndex];
3968 Info << "pointEdges:: " << pEdges << endl;
3970 Info << "Added edges: " << endl;
3971 forAll(pEdges, edgeI)
3973 Info << pEdges[edgeI]
3974 << ":: " << edges_[pEdges[edgeI]] << nl
3975 << " edgeFaces:: " << edgeFaces_[pEdges[edgeI]] << nl
3976 << " edgePoints:: " << edgePoints_[pEdges[edgeI]]
3980 Info << "Added faces: " << endl;
3981 forAll(newFaceIndex, faceI)
3983 if (newFaceIndex[faceI] == -1)
3988 Info << newFaceIndex[faceI] << ":: "
3989 << faces_[newFaceIndex[faceI]]
3993 Info << "Added cells: " << endl;
3994 forAll(newCellIndex, cellI)
3996 if (newCellIndex[cellI] == -1)
4001 Info << newCellIndex[cellI] << ":: "
4002 << cells_[newCellIndex[cellI]]
4006 // Write out VTK files after change
4011 if (cellsForRemoval[1] == -1)
4013 vtkCells.setSize(3);
4015 // Fill in cell indices
4016 vtkCells[0] = newCellIndex[0];
4017 vtkCells[1] = newCellIndex[1];
4018 vtkCells[2] = newCellIndex[2];
4022 vtkCells.setSize(6);
4024 // Fill in cell indices
4025 forAll(newCellIndex, indexI)
4027 vtkCells[indexI] = newCellIndex[indexI];
4041 topoChangeFlag_ = true;
4043 // Increment the counter
4046 // Increment the number of modifications
4049 // Specify that the operation was successful
4052 // Return the changeMap
4057 // Utility method to compute the quality of a
4058 // vertex hull around an edge after bisection.
4059 scalar dynamicTopoFvMesh::computeBisectionQuality
4064 scalar minQuality = GREAT, minVolume = GREAT;
4065 scalar cQuality = 0.0, oldVolume = 0.0;
4067 // Obtain a reference to this edge and corresponding edgePoints
4068 const edge& edgeToCheck = edges_[eIndex];
4069 const labelList& hullVertices = edgePoints_[eIndex];
4071 // Obtain point references
4072 const point& a = points_[edgeToCheck[0]];
4073 const point& c = points_[edgeToCheck[1]];
4075 const point& aOld = oldPoints_[edgeToCheck[0]];
4076 const point& cOld = oldPoints_[edgeToCheck[1]];
4078 // Compute the mid-point of the edge
4079 point midPoint = 0.5*(a + c);
4080 point oldPoint = 0.5*(aOld + cOld);
4082 if (whichEdgePatch(eIndex) < 0)
4085 forAll(hullVertices, indexI)
4087 label prevIndex = hullVertices.rcIndex(indexI);
4089 // Pick vertices off the list
4090 const point& b = points_[hullVertices[prevIndex]];
4091 const point& d = points_[hullVertices[indexI]];
4093 const point& bOld = oldPoints_[hullVertices[prevIndex]];
4094 const point& dOld = oldPoints_[hullVertices[indexI]];
4096 // Compute the quality of the upper half.
4097 cQuality = tetMetric_(a, b, midPoint, d);
4099 // Compute old volume of the upper half.
4100 oldVolume = tetPointRef(aOld, bOld, oldPoint, dOld).mag();
4102 // Check if the volume / quality is worse
4103 minQuality = Foam::min(cQuality, minQuality);
4104 minVolume = Foam::min(oldVolume, minVolume);
4106 // Compute the quality of the lower half.
4107 cQuality = tetMetric_(midPoint, b, c, d);
4109 // Compute old volume of the lower half.
4110 oldVolume = tetPointRef(oldPoint, bOld, cOld, dOld).mag();
4112 // Check if the quality is worse
4113 minQuality = Foam::min(cQuality, minQuality);
4114 minVolume = Foam::min(oldVolume, minVolume);
4120 for(label indexI = 1; indexI < hullVertices.size(); indexI++)
4122 // Pick vertices off the list
4123 const point& b = points_[hullVertices[indexI-1]];
4124 const point& d = points_[hullVertices[indexI]];
4126 const point& bOld = oldPoints_[hullVertices[indexI-1]];
4127 const point& dOld = oldPoints_[hullVertices[indexI]];
4129 // Compute the quality of the upper half.
4130 cQuality = tetMetric_(a, b, midPoint, d);
4132 // Compute old volume of the upper half.
4133 oldVolume = tetPointRef(aOld, bOld, oldPoint, dOld).mag();
4135 // Check if the quality is worse
4136 minQuality = Foam::min(cQuality, minQuality);
4137 minVolume = Foam::min(oldVolume, minVolume);
4139 // Compute the quality of the lower half.
4140 cQuality = tetMetric_(midPoint, b, c, d);
4142 // Compute old volume of the lower half.
4143 oldVolume = tetPointRef(oldPoint, bOld, cOld, dOld).mag();
4145 // Check if the quality is worse
4146 minQuality = Foam::min(cQuality, minQuality);
4147 minVolume = Foam::min(oldVolume, minVolume);
4151 // Ensure that the mesh is valid
4152 if (minQuality < sliverThreshold_)
4154 if (debug > 3 && minQuality < 0.0)
4156 // Write out cells for post processing.
4157 labelHashSet iCells;
4159 const labelList& eFaces = edgeFaces_[eIndex];
4161 forAll(eFaces, faceI)
4163 if (!iCells.found(owner_[eFaces[faceI]]))
4165 iCells.insert(owner_[eFaces[faceI]]);
4168 if (!iCells.found(neighbour_[eFaces[faceI]]))
4170 iCells.insert(neighbour_[eFaces[faceI]]);
4174 writeVTK(Foam::name(eIndex) + "_iCells", iCells.toc());
4181 "scalar dynamicTopoFvMesh::computeBisectionQuality"
4182 "(const label eIndex) const"
4184 << "Bisecting edge will fall below the "
4185 << "sliver threshold of: " << sliverThreshold_ << nl
4186 << "Edge: " << eIndex << ": " << edgeToCheck << nl
4187 << "EdgePoints: " << hullVertices << nl
4188 << "Minimum Quality: " << minQuality << nl
4189 << "Mid point: " << midPoint
4194 // If a negative old-volume was encountered,
4195 // return an invalid quality.
4196 if (minVolume < 0.0)
4205 // Utility method to compute the quality of cells
4206 // around a face after trisection.
4207 scalar dynamicTopoFvMesh::computeTrisectionQuality
4212 scalar minQuality = GREAT;
4213 scalar cQuality = 0.0;
4217 // Fetch the midPoint
4218 midPoint = faces_[fIndex].centre(points_);
4220 FixedList<label,2> apexPoint(-1);
4222 // Find the apex point
4225 meshOps::tetApexPoint
4234 const face& faceToCheck = faces_[fIndex];
4236 forAll(faceToCheck, pointI)
4238 // Pick vertices off the list
4239 const point& b = points_[faceToCheck[pointI]];
4240 const point& c = points_[apexPoint[0]];
4241 const point& d = points_[faceToCheck[faceToCheck.fcIndex(pointI)]];
4243 // Compute the quality of the upper half.
4244 cQuality = tetMetric_(midPoint, b, c, d);
4246 // Check if the quality is worse
4247 minQuality = Foam::min(cQuality, minQuality);
4250 if (whichPatch(fIndex) == -1)
4254 meshOps::tetApexPoint
4263 forAll(faceToCheck, pointI)
4265 // Pick vertices off the list
4266 const point& b = points_[faceToCheck[pointI]];
4267 const point& c = points_[apexPoint[1]];
4268 const point& d = points_[faceToCheck[faceToCheck.rcIndex(pointI)]];
4270 // Compute the quality of the upper half.
4271 cQuality = tetMetric_(midPoint, b, c, d);
4273 // Check if the quality is worse
4274 minQuality = Foam::min(cQuality, minQuality);
4282 // Split a set of internal faces into boundary faces
4283 // - Add boundary faces and edges to the patch specified by 'patchIndex'
4284 // - Cell color should specify a binary value dictating either side
4285 // of the split face.
4286 void dynamicTopoFvMesh::splitInternalFaces
4288 const label patchIndex,
4289 const labelList& internalFaces,
4290 const Map<bool>& cellColors
4293 Map<label> mirrorPointLabels;
4294 FixedList<Map<label>, 2> mirrorEdgeLabels, mirrorFaceLabels;
4296 // First loop through the list and accumulate a list of
4297 // points and edges that need to be duplicated.
4298 forAll(internalFaces, faceI)
4300 const face& faceToCheck = faces_[internalFaces[faceI]];
4302 forAll(faceToCheck, pointI)
4304 if (!mirrorPointLabels.found(faceToCheck[pointI]))
4306 mirrorPointLabels.insert(faceToCheck[pointI], -1);
4310 const labelList& fEdges = faceEdges_[internalFaces[faceI]];
4312 forAll(fEdges, edgeI)
4314 if (!mirrorEdgeLabels[0].found(fEdges[edgeI]))
4316 mirrorEdgeLabels[0].insert(fEdges[edgeI], -1);
4321 // Now for every point in the list, add a new one.
4322 // Add a mapping entry as well.
4323 forAllIter(Map<label>, mirrorPointLabels, pIter)
4325 // Obtain a copy of the point before adding it,
4326 // since the reference might become invalid during list resizing.
4327 point newPoint = points_[pIter.key()];
4328 point oldPoint = oldPoints_[pIter.key()];
4330 pIter() = insertPoint(newPoint, oldPoint, labelList(1, pIter.key()));
4334 const labelList& pEdges = pointEdges_[pIter.key()];
4336 labelHashSet edgesToRemove;
4338 forAll(pEdges, edgeI)
4340 const labelList& eFaces = edgeFaces_[pEdges[edgeI]];
4342 bool allTrue = true;
4344 forAll(eFaces, faceI)
4346 label own = owner_[eFaces[faceI]];
4347 label nei = neighbour_[eFaces[faceI]];
4349 // Check if an owner/neighbour cell is false
4350 if (!cellColors[own])
4358 if (!cellColors[nei])
4368 // Mark this edge label to be discarded later
4369 edgesToRemove.insert(pEdges[edgeI]);
4373 // It is dangerous to use the pointEdges references,
4374 // so call it using array-lookup instead.
4375 forAllIter(labelHashSet, edgesToRemove, hsIter)
4377 // Add the edge to the mirror point list
4381 pointEdges_[pIter()]
4384 // Remove the edge from the original point list
4385 meshOps::sizeDownList
4388 pointEdges_[pIter.key()]
4397 labelList mPoints(mirrorPointLabels.size());
4401 forAllIter(Map<label>, mirrorPointLabels, pIter)
4405 "pEdges_o_" + Foam::name(pIter.key()) + '_',
4406 pointEdges_[pIter.key()],
4412 "pEdges_m_" + Foam::name(pIter()) + '_',
4413 pointEdges_[pIter()],
4417 mPoints[i++] = pIter();
4423 mirrorPointLabels.toc(),
4436 // For every internal face, add a new one.
4437 // - Stick to the rule:
4438 // [1] Every cell marked false keeps the existing entities.
4439 // [2] Every cell marked true gets new points/edges/faces.
4440 // - If faces are improperly oriented, reverse them.
4441 forAll(internalFaces, faceI)
4443 FixedList<face, 2> newFace;
4444 FixedList<label, 2> newFaceIndex(-1);
4445 FixedList<label, 2> newOwner(-1);
4447 label oldOwn = owner_[internalFaces[faceI]];
4448 label oldNei = neighbour_[internalFaces[faceI]];
4450 if (cellColors[oldOwn] && !cellColors[oldNei])
4452 // The owner gets a new boundary face.
4453 // Note that orientation is already correct.
4454 newFace[0] = faces_[internalFaces[faceI]];
4456 // The neighbour needs to have its face reversed
4457 // and moved to the boundary patch, thereby getting
4458 // deleted in the process.
4459 newFace[1] = newFace[0].reverseFace();
4461 newOwner[0] = oldOwn;
4462 newOwner[1] = oldNei;
4465 if (!cellColors[oldOwn] && cellColors[oldNei])
4467 // The neighbour gets a new boundary face.
4468 // The face is oriented in the opposite sense, however.
4469 newFace[0] = faces_[internalFaces[faceI]].reverseFace();
4471 // The owner keeps the existing face and orientation.
4472 // But it also needs to be moved to the boundary.
4473 newFace[1] = faces_[internalFaces[faceI]];
4475 newOwner[0] = oldNei;
4476 newOwner[1] = oldOwn;
4480 // Something's wrong here.
4483 "dynamicTopoFvMesh::splitInternalFaces\n"
4485 " const label patchIndex,\n"
4486 " const labelList& internalFaces,\n"
4487 " const Map<bool>& cellColors\n"
4491 << internalFaces[faceI]
4492 << " has cells which are improperly marked: " << nl
4493 << oldOwn << ":: " << cellColors[oldOwn] << nl
4494 << oldNei << ":: " << cellColors[oldNei]
4495 << abort(FatalError);
4498 // Renumber point labels for the first new face.
4499 forAll(newFace[0], pointI)
4501 newFace[0][pointI] = mirrorPointLabels[newFace[0][pointI]];
4504 // Insert the new boundary faces.
4505 forAll(newFace, indexI)
4507 newFaceIndex[indexI] =
4518 // Make an identical faceEdges entry.
4519 // This will be renumbered once new edges are added.
4520 labelList newFaceEdges(faceEdges_[internalFaces[faceI]]);
4522 faceEdges_.append(newFaceEdges);
4524 // Replace face labels on cells
4525 meshOps::replaceLabel
4527 internalFaces[faceI],
4528 newFaceIndex[indexI],
4529 cells_[newOwner[indexI]]
4532 // Make face mapping entries for posterity.
4533 mirrorFaceLabels[indexI].insert
4535 internalFaces[faceI],
4536 newFaceIndex[indexI]
4541 // For every edge in the list, add a new one.
4542 // We'll deal with correcting edgeFaces and edgePoints later.
4543 forAllIter(Map<label>, mirrorEdgeLabels[0], eIter)
4545 // Obtain copies for the append method
4546 edge origEdge = edges_[eIter.key()];
4547 labelList newEdgeFaces(edgeFaces_[eIter.key()]);
4556 mirrorPointLabels[origEdge[0]],
4557 mirrorPointLabels[origEdge[1]]
4564 // Is the original edge an internal one?
4565 // If it is, we need to move it to the boundary.
4566 if (whichEdgePatch(eIter.key()) == -1)
4568 label rplEdgeIndex =
4579 // Map the new entry.
4580 mirrorEdgeLabels[1].insert(eIter.key(), rplEdgeIndex);
4584 // This is already a boundary edge.
4585 // Make an identical map.
4586 mirrorEdgeLabels[1].insert(eIter.key(), eIter.key());
4590 // Correct edgeFaces for all new edges
4591 forAll(mirrorEdgeLabels, indexI)
4593 forAllIter(Map<label>, mirrorEdgeLabels[indexI], eIter)
4595 labelList& eFaces = edgeFaces_[eIter()];
4597 labelHashSet facesToRemove;
4599 forAll(eFaces, faceI)
4601 bool remove = false;
4603 label own = owner_[eFaces[faceI]];
4604 label nei = neighbour_[eFaces[faceI]];
4608 (!cellColors[own] && !indexI) ||
4609 ( cellColors[own] && indexI)
4619 (!cellColors[nei] && !indexI) ||
4620 ( cellColors[nei] && indexI)
4627 if (mirrorFaceLabels[indexI].found(eFaces[faceI]))
4629 // Perform a replacement instead of a removal.
4630 eFaces[faceI] = mirrorFaceLabels[indexI][eFaces[faceI]];
4637 facesToRemove.insert(eFaces[faceI]);
4641 // Now successively size down edgeFaces.
4642 // It is dangerous to use the eFaces reference,
4643 // so call it using array-lookup.
4644 forAllIter(labelHashSet, facesToRemove, hsIter)
4646 meshOps::sizeDownList(hsIter.key(), edgeFaces_[eIter()]);
4651 // Renumber faceEdges for all faces connected to new edges
4652 forAll(mirrorEdgeLabels, indexI)
4654 forAllIter(Map<label>, mirrorEdgeLabels[indexI], eIter)
4656 const labelList& eFaces = edgeFaces_[eIter()];
4658 forAll(eFaces, faceI)
4660 labelList& fEdges = faceEdges_[eFaces[faceI]];
4662 forAll(fEdges, edgeI)
4664 if (mirrorEdgeLabels[indexI].found(fEdges[edgeI]))
4668 mirrorEdgeLabels[indexI][fEdges[edgeI]]
4678 // Renumber edges and faces
4679 forAllIter(Map<label>, mirrorEdgeLabels[0], eIter)
4681 const labelList& eFaces = edgeFaces_[eIter()];
4683 // Two levels of indirection to ensure
4684 // that all entities we renumbered.
4685 // A flip-side for the lack of a pointEdges list in 2D.
4686 forAll(eFaces, faceI)
4688 const labelList& fEdges = faceEdges_[eFaces[faceI]];
4690 forAll(fEdges, edgeI)
4692 // Renumber this edge.
4693 edge& edgeToCheck = edges_[fEdges[edgeI]];
4695 forAll(edgeToCheck, pointI)
4697 if (mirrorPointLabels.found(edgeToCheck[pointI]))
4699 edgeToCheck[pointI] =
4701 mirrorPointLabels[edgeToCheck[pointI]]
4706 // Also renumber faces connected to this edge.
4707 const labelList& efFaces = edgeFaces_[fEdges[edgeI]];
4709 forAll(efFaces, faceJ)
4711 face& faceToCheck = faces_[efFaces[faceJ]];
4713 forAll(faceToCheck, pointI)
4717 mirrorPointLabels.found(faceToCheck[pointI])
4720 faceToCheck[pointI] =
4722 mirrorPointLabels[faceToCheck[pointI]]
4733 // Point renumbering of entities connected to mirror points
4734 forAllIter(Map<label>, mirrorPointLabels, pIter)
4736 const labelList& pEdges = pointEdges_[pIter()];
4738 forAll(pEdges, edgeI)
4740 // Renumber this edge.
4741 edge& edgeToCheck = edges_[pEdges[edgeI]];
4743 forAll(edgeToCheck, pointI)
4745 if (edgeToCheck[pointI] == pIter.key())
4747 edgeToCheck[pointI] = pIter();
4751 // Also renumber faces connected to this edge.
4752 const labelList& eFaces = edgeFaces_[pEdges[edgeI]];
4754 forAll(eFaces, faceI)
4756 face& faceToCheck = faces_[eFaces[faceI]];
4758 forAll(faceToCheck, pointI)
4760 if (faceToCheck[pointI] == pIter.key())
4762 faceToCheck[pointI] = pIter();
4769 // Scan edges connected to mirror points,
4770 // and correct any edgePoints entries for
4771 // edges connected to the other vertex.
4772 forAllIter(Map<label>, mirrorPointLabels, pIter)
4774 const labelList& pEdges = pointEdges_[pIter()];
4776 forAll(pEdges, edgeI)
4778 label otherVertex = edges_[pEdges[edgeI]].otherVertex(pIter());
4780 // Scan edgePoints for edges connected to this point
4781 const labelList& opEdges = pointEdges_[otherVertex];
4783 forAll(opEdges, edgeJ)
4785 labelList& ePoints = edgePoints_[opEdges[edgeJ]];
4787 forAll(ePoints, pointI)
4789 if (mirrorPointLabels.found(ePoints[pointI]))
4791 // Replace this point with the mirror point
4794 mirrorPointLabels[ePoints[pointI]]
4802 // Build edgePoints for new edges
4803 forAll(mirrorEdgeLabels, indexI)
4805 forAllIter(Map<label>, mirrorEdgeLabels[indexI], eIter)
4807 buildEdgePoints(eIter());
4812 // Now that we're done with the internal faces, remove them.
4813 forAll(internalFaces, faceI)
4815 removeFace(internalFaces[faceI]);
4818 // Remove old internal edges as well.
4819 forAllIter(Map<label>, mirrorEdgeLabels[1], eIter)
4821 if (eIter.key() != eIter())
4823 removeEdge(eIter.key());
4828 topoChangeFlag_ = true;
4831 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
4833 } // End namespace Foam
4835 // ************************************************************************* //