1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
28 #include "objectRegistry.H"
30 #include "objectMap.H"
31 #include "changeMap.H"
32 #include "multiThreader.H"
33 #include "coupledInfo.H"
34 #include "dynamicTopoFvMesh.H"
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
43 // Method for the bisection of a quad-face in 2D
44 // - Returns a changeMap with a type specifying:
45 // 1: Bisection was successful
46 // -1: Bisection failed since max number of topo-changes was reached.
47 // -2: Bisection failed since resulting quality would be unacceptable.
48 // -3: Bisection failed since edge was on a noRefinement patch.
49 const changeMap dynamicTopoFvMesh::bisectQuadFace
52 const changeMap& masterMap,
57 // Quad-face bisection performs the following operations:
58 // [1] Add two points at the middle of the face
59 // [2] Create a new internal face for each bisected cell
60 // [3] Modify existing face and create a new half-face
61 // [4] Modify triangular boundary faces, and create new ones as well
62 // [5] Create edges for new faces
63 // Update faceEdges and edgeFaces information
65 // Figure out which thread this is...
66 label tIndex = self();
68 // Prepare the changeMaps
70 List<changeMap> slaveMaps;
71 bool bisectingSlave = false;
75 (statistics_[0] > maxModifications_) &&
76 (maxModifications_ > -1)
79 // Reached the max allowable topo-changes.
80 stack(tIndex).clear();
85 // Check if edgeRefinements are to be avoided on patch.
86 if (baseMesh_.lengthEstimator().checkRefinementPatch(whichPatch(fIndex)))
93 // Sanity check: Is the index legitimate?
99 "const changeMap dynamicTopoFvMesh::bisectQuadFace\n"
101 " const label fIndex,\n"
102 " const changeMap& masterMap,\n"
107 << " Invalid index: " << fIndex << nl
108 << " nFaces: " << nFaces_
109 << abort(FatalError);
113 label replaceFace = -1, retainFace = -1;
114 face tmpQuadFace(4), tmpTriFace(3);
115 labelList tmpQFEdges(4, -1), tmpTFEdges(3, -1);
116 FixedList<label,7> newFaceIndex(-1), newEdgeIndex(-1);
117 FixedList<edge,4> commonEdges(edge(-1, -1));
118 FixedList<label,4> cornerEdgeIndex(-1), commonEdgeIndex(-1);
119 FixedList<label,4> commonFaceIndex(-1);
120 FixedList<label,2> newPointIndex(-1), newCellIndex(-1);
121 FixedList<label,4> otherEdgeIndex(-1), otherEdgePoint(-1);
122 FixedList<label,4> otherPointIndex(-1), nextToOtherPoint(-1);
123 FixedList<label,2> c0BdyIndex(-1), c0IntIndex(-1);
124 FixedList<label,2> c1BdyIndex(-1), c1IntIndex(-1);
125 FixedList<face,2> c0BdyFace(face(3)), c0IntFace(face(4));
126 FixedList<face,2> c1BdyFace(face(3)), c1IntFace(face(4));
128 // Get the two cells on either side...
129 label c0 = owner_[fIndex], c1 = neighbour_[fIndex];
131 // Keep track of old / new cells
132 FixedList<cell, 2> oldCells(cell(5));
133 FixedList<cell, 2> newCells(cell(5));
135 // Find the prism faces for cell[0].
136 oldCells[0] = cells_[c0];
138 meshOps::findPrismFaces
151 // Check for resulting quality
152 if (checkBisection(fIndex, c0BdyIndex[0], forceOp))
160 // Find the prism faces for cell[1].
161 meshOps::findPrismFaces
174 // Check for resulting quality
175 if (checkBisection(fIndex, c1BdyIndex[0], forceOp))
182 // Find the common-edge between the triangular boundary faces
183 // and the face under consideration.
184 meshOps::findCommonEdge
192 meshOps::findCommonEdge
200 commonEdges[0] = edges_[commonEdgeIndex[0]];
201 commonEdges[1] = edges_[commonEdgeIndex[1]];
203 // If coupled modification is set, and this is a
204 // master edge, bisect its slaves as well.
205 bool localCouple = false, procCouple = false;
207 if (coupledModification_)
209 const label faceEnum = coupleMap::FACE;
210 const label pointEnum = coupleMap::POINT;
212 // Is this a locally coupled face (either master or slave)?
213 if (locallyCoupledEntity(fIndex, true))
219 if (processorCoupledEntity(fIndex))
225 if (localCouple && !procCouple)
227 // Determine the slave index.
228 label sIndex = -1, pIndex = -1;
230 forAll(patchCoupling_, patchI)
232 if (patchCoupling_(patchI))
234 const coupleMap& cMap = patchCoupling_[patchI].map();
236 if ((sIndex = cMap.findSlave(faceEnum, fIndex)) > -1)
243 // The following bit happens only during the sliver
244 // exudation process, since slave faces are
245 // usually not added to the coupled face-stack.
246 if ((sIndex = cMap.findMaster(faceEnum, fIndex)) > -1)
250 // Notice that we are collapsing a slave face first.
251 bisectingSlave = true;
263 "const changeMap dynamicTopoFvMesh::bisectQuadFace\n"
265 " const label fIndex,\n"
266 " const changeMap& masterMap,\n"
271 << "Coupled maps were improperly specified." << nl
272 << " Slave index not found for: " << nl
273 << " Face: " << fIndex << ": " << faces_[fIndex] << nl
274 << abort(FatalError);
278 // If we've found the slave, size up the list
285 // Save index and patch for posterity
286 slaveMaps[0].index() = sIndex;
287 slaveMaps[0].patchIndex() = pIndex;
292 Pout<< nl << " >> Bisecting slave face: " << sIndex
293 << " for master face: " << fIndex << endl;
297 if (procCouple && !localCouple)
299 // If this is a new entity, bail out for now.
300 // This will be handled at the next time-step.
301 if (fIndex >= nOldFaces_)
307 forAll(procIndices_, pI)
309 // Fetch reference to subMesh
310 const coupledInfo& recvMesh = recvMeshes_[pI];
311 const coupleMap& cMap = recvMesh.map();
315 if ((sIndex = cMap.findSlave(faceEnum, fIndex)) > -1)
319 Pout<< "Checking slave face: " << sIndex
320 << " on proc: " << procIndices_[pI]
321 << " for master face: " << fIndex
325 // Check if a lower-ranked processor is
326 // handling this edge
327 if (procIndices_[pI] < Pstream::myProcNo())
331 Pout<< "Face: " << fIndex
332 << " is handled by proc: "
334 << ", so bailing out."
341 label curIndex = slaveMaps.size();
350 // Save index and patch for posterity
351 slaveMaps[curIndex].index() = sIndex;
352 slaveMaps[curIndex].patchIndex() = pI;
354 // Only one slave coupling is possible, so bail out
361 // Something's wrong with coupling maps
365 "const changeMap dynamicTopoFvMesh::bisectQuadFace\n"
367 " const label fIndex,\n"
368 " const changeMap& masterMap,\n"
373 << "Coupled maps were improperly specified." << nl
374 << " localCouple: " << localCouple << nl
375 << " procCouple: " << procCouple << nl
376 << " Face: " << fIndex << ": " << faces_[fIndex] << nl
377 << abort(FatalError);
380 // Alias for convenience...
381 changeMap& slaveMap = slaveMaps[0];
383 label sIndex = slaveMap.index();
384 label pI = slaveMap.patchIndex();
385 const coupleMap* cMapPtr = NULL;
387 // Temporarily turn off coupledModification
388 unsetCoupledModification();
392 cMapPtr = &(patchCoupling_[pI].map());
394 // First check the slave for bisection feasibility.
395 slaveMap = bisectQuadFace(sIndex, changeMap(), true, forceOp);
400 cMapPtr = &(recvMeshes_[pI].map());
402 coupledInfo& recvMesh = recvMeshes_[pI];
404 // First check the slave for bisection feasibility.
407 recvMesh.subMesh().bisectQuadFace
418 setCoupledModification();
420 if (slaveMap.type() <= 0)
422 // Slave couldn't perform bisection.
428 // Save index and patch for posterity
429 slaveMap.index() = sIndex;
430 slaveMap.patchIndex() = pI;
432 // Alias for convenience..
433 const coupleMap& cMap = *cMapPtr;
435 // Temporarily turn off coupledModification
436 unsetCoupledModification();
438 // First check the master for bisection feasibility.
439 changeMap masterMap = bisectQuadFace(fIndex, changeMap(), true);
442 setCoupledModification();
444 // Master couldn't perform bisection
445 if (masterMap.type() <= 0)
450 // Fill the masterMap with points that
451 // we seek maps for...
452 FixedList<labelList, 2> slaveEdges(labelList(2, -1));
454 forAll(slaveEdges, edgeI)
456 labelList& slaveEdge = slaveEdges[edgeI];
458 // Renumber to slave indices
459 forAll(slaveEdge, pointI)
466 commonEdges[edgeI][pointI]
471 masterMap.addPoint(-1, slaveEdge);
474 // Temporarily turn off coupledModification
475 unsetCoupledModification();
479 // Bisect the local slave.
480 slaveMap = bisectQuadFace(sIndex, masterMap, false, forceOp);
484 coupledInfo& recvMesh = recvMeshes_[pI];
486 // Bisect the slave face
489 recvMesh.subMesh().bisectQuadFace
499 // Turn coupledModification back on.
500 setCoupledModification();
502 // The final operation has to succeed.
503 if (slaveMap.type() <= 0)
508 "const changeMap dynamicTopoFvMesh::bisectQuadFace\n"
510 " const label fIndex,\n"
511 " const changeMap& masterMap,\n"
516 << "Coupled topo-change for slave failed."
517 << " Master face: " << fIndex << nl
518 << " Slave face: " << sIndex << nl
519 << " Patch index: " << pI << nl
520 << " Type: " << slaveMap.type() << nl
521 << abort(FatalError);
524 // Save index and patch for posterity
525 slaveMap.index() = sIndex;
526 slaveMap.patchIndex() = pI;
529 // Are we performing only checks?
539 << "Face: " << fIndex
540 << ": " << faces_[fIndex]
541 << " is to be bisected. " << endl;
545 Pout<< " On SubMesh: " << Switch::asText(isSubMesh_) << nl;
546 Pout<< " coupledModification: " << coupledModification_ << nl;
548 const polyBoundaryMesh& boundary = boundaryMesh();
550 label epIndex = whichPatch(fIndex);
556 Pout<< "Internal" << endl;
559 if (epIndex < boundary.size())
561 Pout<< boundary[epIndex].name() << endl;
565 Pout<< " New patch: " << epIndex << endl;
568 Pout<< "Cell[0]: " << c0 << ": " << oldCells[0] << endl;
570 forAll(oldCells[0], faceI)
572 const labelList& fE = faceEdges_[oldCells[0][faceI]];
574 Pout<< oldCells[0][faceI] << ": "
575 << faces_[oldCells[0][faceI]]
581 const labelList& eF = edgeFaces_[fE[edgeI]];
583 Pout<< '\t' << fE[edgeI]
584 << ": " << edges_[fE[edgeI]]
591 // Write out VTK files prior to change
594 labelList cellHull(2, -1);
596 cellHull[0] = owner_[fIndex];
597 cellHull[1] = neighbour_[fIndex];
608 // Find the isolated point on both boundary faces of cell[0]
609 meshOps::findIsolatedPoint
617 meshOps::findIsolatedPoint
625 // For convenience...
626 otherEdgePoint[0] = commonEdges[0].otherVertex(nextToOtherPoint[0]);
627 otherEdgePoint[1] = commonEdges[1].otherVertex(nextToOtherPoint[1]);
631 // Set mapping for this point
632 mP[0] = commonEdges[0][0];
633 mP[1] = commonEdges[0][1];
635 // Add two new points to the end of the list
640 0.5 * (points_[mP[0]] + points_[mP[1]]),
641 0.5 * (oldPoints_[mP[0]] + oldPoints_[mP[1]]),
646 // Set mapping for this point
647 mP[0] = commonEdges[1][0];
648 mP[1] = commonEdges[1][1];
654 0.5 * (points_[mP[0]] + points_[mP[1]]),
655 0.5 * (oldPoints_[mP[0]] + oldPoints_[mP[1]]),
660 // Add the points to the map. Since this might require master mapping,
661 // first check to see if a slave is being bisected.
662 if (masterMap.addedPointList().size())
664 const List<objectMap>& pMap =
666 masterMap.addedPointList()
671 pMap[0].masterObjects()[0],
672 pMap[0].masterObjects()[1]
677 pMap[1].masterObjects()[0],
678 pMap[1].masterObjects()[1]
681 if (firstEdge == commonEdges[0] && secondEdge == commonEdges[1])
683 // Update in conventional order
684 map.addPoint(newPointIndex[0]);
685 map.addPoint(newPointIndex[1]);
688 if (firstEdge == commonEdges[1] && secondEdge == commonEdges[0])
690 // Update in reverse order
691 map.addPoint(newPointIndex[1]);
692 map.addPoint(newPointIndex[0]);
701 "dynamicTopoFvMesh::bisectQuadFace\n"
703 " const label fIndex,\n"
704 " const changeMap& masterMap,\n"
709 << "Coupled topo-change for slave failed."
710 << " firstEdge: " << firstEdge << nl
711 << " secondEdge: " << secondEdge << nl
712 << " commonEdges[0]: " << commonEdges[0] << nl
713 << " commonEdges[1]: " << commonEdges[1] << nl
714 << abort(FatalError);
719 map.addPoint(newPointIndex[0]);
720 map.addPoint(newPointIndex[1]);
723 // Add a new prism cell to the end of the list.
724 // Currently invalid, but will be updated later.
725 newCellIndex[0] = insertCell(newCells[0], lengthScale_[c0]);
727 // Add this cell to the map.
728 map.addCell(newCellIndex[0]);
730 // Modify the two existing triangle boundary faces
732 // Zeroth boundary face - Owner = c[0] & Neighbour [-1] (unchanged)
733 meshOps::replaceLabel
740 // First boundary face - Owner = newCell[0], Neighbour = -1
741 meshOps::replaceLabel
749 faces_[c0BdyIndex[0]] = c0BdyFace[0];
750 faces_[c0BdyIndex[1]] = c0BdyFace[1];
752 owner_[c0BdyIndex[1]] = newCellIndex[0];
754 meshOps::replaceLabel
761 // Detect edges other than commonEdges
762 const labelList& fEdges = faceEdges_[fIndex];
764 forAll(fEdges, edgeI)
768 fEdges[edgeI] != commonEdgeIndex[0] &&
769 fEdges[edgeI] != commonEdgeIndex[1]
772 // Obtain a reference to this edge
773 const edge& eThis = edges_[fEdges[edgeI]];
777 eThis[0] == nextToOtherPoint[0]
778 || eThis[1] == nextToOtherPoint[0]
781 otherEdgeIndex[0] = fEdges[edgeI];
785 otherEdgeIndex[1] = fEdges[edgeI];
790 // Modify point-labels on the quad face under consideration
791 meshOps::replaceLabel
798 meshOps::replaceLabel
805 // Add this face to the map.
806 // Although this face isn't technically 'added', it's
807 // required for coupled patch mapping.
812 Pout<< "Modified face: " << fIndex
813 << ": " << faces_[fIndex] << endl;
817 Pout<< "Common edges: " << nl
818 << commonEdgeIndex[0] << ": " << commonEdges[0] << nl
819 << commonEdgeIndex[1] << ": " << commonEdges[1]
824 // Find the quad face that contains otherEdgeIndex[1]
827 const labelList& e1 = faceEdges_[c0IntIndex[0]];
831 if (e1[edgeI] == otherEdgeIndex[1])
833 meshOps::replaceLabel
840 replaceFace = c0IntIndex[0];
841 retainFace = c0IntIndex[1];
849 // The edge was not found before
850 meshOps::replaceLabel
857 replaceFace = c0IntIndex[1];
858 retainFace = c0IntIndex[0];
861 // Check if face reversal is necessary for the replacement
862 if (owner_[replaceFace] == c0)
864 if (neighbour_[replaceFace] == -1)
867 owner_[replaceFace] = newCellIndex[0];
871 // This face has to be reversed
872 faces_[replaceFace] = faces_[replaceFace].reverseFace();
873 owner_[replaceFace] = neighbour_[replaceFace];
874 neighbour_[replaceFace] = newCellIndex[0];
876 setFlip(replaceFace);
881 // Keep owner, but change neighbour
882 neighbour_[replaceFace] = newCellIndex[0];
885 // Define the faces for the new cell
886 newCells[0][0] = c0BdyIndex[1];
887 newCells[0][1] = replaceFace;
889 // Define the set of new faces and insert...
891 // New interior face; Owner = cell[0] & Neighbour = newCell[0]
892 tmpQuadFace[0] = otherPointIndex[0];
893 tmpQuadFace[1] = newPointIndex[0];
894 tmpQuadFace[2] = newPointIndex[1];
895 tmpQuadFace[3] = otherPointIndex[1];
908 // Add a faceEdges entry as well
909 faceEdges_.append(tmpQFEdges);
911 // Add this face to the map.
912 map.addFace(newFaceIndex[0]);
914 // Find the common edge between quad/quad faces...
915 meshOps::findCommonEdge
923 // ... and size-up edgeFaces for the edge
927 edgeFaces_[otherEdgeIndex[2]]
930 meshOps::replaceLabel
937 meshOps::replaceLabel
944 // Second boundary face; Owner = newCell[0] & Neighbour = [-1]
945 tmpTriFace[0] = otherPointIndex[0];
946 tmpTriFace[1] = newPointIndex[0];
947 tmpTriFace[2] = otherEdgePoint[0];
953 whichPatch(c0BdyIndex[0]),
960 // Add a faceEdges entry as well
961 faceEdges_.append(tmpTFEdges);
963 // Add this face to the map.
964 map.addFace(newFaceIndex[1]);
966 meshOps::replaceLabel
973 // Third boundary face; Owner = c[0] & Neighbour = [-1]
974 tmpTriFace[0] = otherPointIndex[1];
975 tmpTriFace[1] = newPointIndex[1];
976 tmpTriFace[2] = otherEdgePoint[1];
982 whichPatch(c0BdyIndex[1]),
989 // Add a faceEdges entry as well
990 faceEdges_.append(tmpTFEdges);
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];
1109 // Add a faceEdges entry as well
1110 faceEdges_.append(tmpQFEdges);
1112 // Add this face to the map.
1113 map.addFace(newFaceIndex[3]);
1115 // Correct edgeFaces for otherEdgeIndex[1]
1116 meshOps::replaceLabel
1120 edgeFaces_[otherEdgeIndex[1]]
1123 meshOps::replaceLabel
1130 labelList tmpBiEdgeFaces(2, -1);
1132 // The edge bisecting the face
1133 tmpTriEdgeFaces[0] = newFaceIndex[3];
1134 tmpTriEdgeFaces[1] = newFaceIndex[0];
1135 tmpTriEdgeFaces[2] = fIndex;
1141 whichEdgePatch(otherEdgeIndex[0]),
1142 edge(newPointIndex[0], newPointIndex[1]),
1147 // Add this edge to the map.
1148 map.addEdge(newEdgeIndex[0]);
1150 // Replace an edge on the bisected face
1151 meshOps::replaceLabel
1158 // Create / replace side edges created from face bisection
1159 tmpBiEdgeFaces[0] = newFaceIndex[1];
1160 tmpBiEdgeFaces[1] = newFaceIndex[3];
1166 whichEdgePatch(commonEdgeIndex[0]),
1167 edge(newPointIndex[0], otherEdgePoint[0]),
1172 // Add this edge to the map.
1173 map.addEdge(newEdgeIndex[3]);
1175 tmpBiEdgeFaces[0] = c0BdyIndex[1];
1176 tmpBiEdgeFaces[1] = newFaceIndex[3];
1182 whichEdgePatch(commonEdgeIndex[1]),
1183 edge(newPointIndex[1], nextToOtherPoint[1]),
1188 // Add this edge to the map.
1189 map.addEdge(newEdgeIndex[4]);
1191 // Now that edges are defined, configure faceEdges
1192 // for all new faces
1194 // The quad interior face; Owner = cell[0] & Neighbour = newCell[0]
1195 tmpQFEdges[0] = newEdgeIndex[0];
1196 tmpQFEdges[1] = newEdgeIndex[1];
1197 tmpQFEdges[2] = otherEdgeIndex[2];
1198 tmpQFEdges[3] = newEdgeIndex[2];
1199 faceEdges_[newFaceIndex[0]] = tmpQFEdges;
1201 // Second boundary face; Owner = newCell[0] & Neighbour = [-1]
1202 tmpTFEdges[0] = newEdgeIndex[3];
1203 tmpTFEdges[1] = cornerEdgeIndex[0];
1204 tmpTFEdges[2] = newEdgeIndex[1];
1205 faceEdges_[newFaceIndex[1]] = tmpTFEdges;
1207 // Third boundary face; Owner = c[0] & Neighbour = [-1]
1208 tmpTFEdges[0] = newEdgeIndex[2];
1209 tmpTFEdges[1] = cornerEdgeIndex[1];
1210 tmpTFEdges[2] = commonEdgeIndex[1];
1211 faceEdges_[newFaceIndex[2]] = tmpTFEdges;
1213 // The quad face from bisection:
1214 tmpQFEdges[0] = otherEdgeIndex[1];
1215 tmpQFEdges[1] = newEdgeIndex[3];
1216 tmpQFEdges[2] = newEdgeIndex[0];
1217 tmpQFEdges[3] = newEdgeIndex[4];
1218 faceEdges_[newFaceIndex[3]] = tmpQFEdges;
1220 meshOps::replaceLabel
1224 faceEdges_[c0BdyIndex[1]]
1227 meshOps::replaceLabel
1231 edgeFaces_[commonEdgeIndex[1]]
1236 Pout<< "Modified Cell[0]: "
1237 << c0 << ": " << oldCells[0] << endl;
1239 forAll(oldCells[0], faceI)
1241 const labelList& fE = faceEdges_[oldCells[0][faceI]];
1243 Pout<< oldCells[0][faceI]
1244 << ": " << faces_[oldCells[0][faceI]]
1250 const labelList& eF = edgeFaces_[fE[edgeI]];
1252 Pout<< '\t' << fE[edgeI]
1253 << ": " << edges_[fE[edgeI]]
1259 Pout<< "New Cell[0]: " << newCellIndex[0]
1260 << ": " << newCells[0] << endl;
1262 forAll(newCells[0], faceI)
1264 const labelList& fE = faceEdges_[newCells[0][faceI]];
1266 Pout<< newCells[0][faceI]
1267 << ": " << faces_[newCells[0][faceI]]
1273 const labelList& eF = edgeFaces_[fE[edgeI]];
1275 Pout<< '\t' << fE[edgeI]
1276 << ": " << edges_[fE[edgeI]]
1285 oldCells[1] = cells_[c1];
1287 // Add a new prism cell to the end of the list.
1288 // Currently invalid, but will be updated later.
1289 newCellIndex[1] = insertCell(newCells[1], lengthScale_[c1]);
1291 // Add this cell to the map.
1292 map.addCell(newCellIndex[1]);
1296 Pout<< "Cell[1]: " << c1 << ": " << oldCells[1] << endl;
1298 forAll(oldCells[1], faceI)
1300 const labelList& fE = faceEdges_[oldCells[1][faceI]];
1302 Pout<< oldCells[1][faceI] << ": "
1303 << faces_[oldCells[1][faceI]]
1309 const labelList& eF = edgeFaces_[fE[edgeI]];
1311 Pout<< '\t' << fE[edgeI]
1312 << ": " << edges_[fE[edgeI]]
1319 // Find the interior face that contains otherEdgeIndex[1]
1322 const labelList& e2 = faceEdges_[c1IntIndex[0]];
1326 if (e2[edgeI] == otherEdgeIndex[1])
1328 meshOps::replaceLabel
1335 replaceFace = c1IntIndex[0];
1336 retainFace = c1IntIndex[1];
1344 // The edge was not found before
1345 meshOps::replaceLabel
1352 replaceFace = c1IntIndex[1];
1353 retainFace = c1IntIndex[0];
1356 // Check if face reversal is necessary for the replacement
1357 if (owner_[replaceFace] == c1)
1359 if (neighbour_[replaceFace] == -1)
1362 owner_[replaceFace] = newCellIndex[1];
1366 // This face has to be reversed
1367 faces_[replaceFace] = faces_[replaceFace].reverseFace();
1368 owner_[replaceFace] = neighbour_[replaceFace];
1369 neighbour_[replaceFace] = newCellIndex[1];
1371 setFlip(replaceFace);
1376 // Keep owner, but change neighbour
1377 neighbour_[replaceFace] = newCellIndex[1];
1380 // Define attributes for the new prism cell
1381 newCells[1][0] = replaceFace;
1383 // The quad interior face resulting from bisection;
1384 // Owner = newCell[0] & Neighbour = newCell[1]
1385 tmpQuadFace[0] = newPointIndex[1];
1386 tmpQuadFace[1] = nextToOtherPoint[1];
1387 tmpQuadFace[2] = otherEdgePoint[0];
1388 tmpQuadFace[3] = newPointIndex[0];
1401 // Add a faceEdges entry as well
1402 faceEdges_.append(tmpQFEdges);
1404 // Add this face to the map.
1405 map.addFace(newFaceIndex[3]);
1407 // Correct edgeFaces for otherEdgeIndex[1]
1408 meshOps::replaceLabel
1412 edgeFaces_[otherEdgeIndex[1]]
1415 meshOps::replaceLabel
1422 meshOps::replaceLabel
1429 newCells[1][1] = newFaceIndex[3];
1431 // Check for common edges among the two boundary faces
1432 // Find the isolated point on both boundary faces of cell[1]
1435 meshOps::findCommonEdge
1444 meshOps::findCommonEdge
1452 commonFaceIndex[2] = c1BdyIndex[0];
1453 commonFaceIndex[3] = c1BdyIndex[1];
1457 meshOps::findCommonEdge
1465 meshOps::findCommonEdge
1473 commonFaceIndex[2] = c1BdyIndex[1];
1474 commonFaceIndex[3] = c1BdyIndex[0];
1477 commonEdges[2] = edges_[commonEdgeIndex[2]];
1478 commonEdges[3] = edges_[commonEdgeIndex[3]];
1482 Pout<< "Common edges: " << nl
1483 << commonEdgeIndex[2] << ": " << commonEdges[2] << nl
1484 << commonEdgeIndex[3] << ": " << commonEdges[3]
1488 meshOps::findIsolatedPoint
1490 faces_[commonFaceIndex[2]],
1496 meshOps::findIsolatedPoint
1498 faces_[commonFaceIndex[3]],
1504 // For convenience...
1505 otherEdgePoint[2] = commonEdges[2].otherVertex(nextToOtherPoint[2]);
1506 otherEdgePoint[3] = commonEdges[3].otherVertex(nextToOtherPoint[3]);
1508 // Modify the two existing triangle boundary faces
1510 // Zeroth boundary face - Owner = newCell[1], Neighbour = -1
1511 meshOps::replaceLabel
1515 faces_[commonFaceIndex[2]]
1518 owner_[commonFaceIndex[2]] = newCellIndex[1];
1520 meshOps::replaceLabel
1527 newCells[1][2] = commonFaceIndex[2];
1529 // First boundary face - Owner = c[1] & Neighbour [-1] (unchanged)
1530 meshOps::replaceLabel
1534 faces_[commonFaceIndex[3]]
1537 // New interior face; Owner = cell[1] & Neighbour = newCell[1]
1538 tmpQuadFace[0] = newPointIndex[0];
1539 tmpQuadFace[1] = otherPointIndex[2];
1540 tmpQuadFace[2] = otherPointIndex[3];
1541 tmpQuadFace[3] = newPointIndex[1];
1554 // Add a faceEdges entry as well
1555 faceEdges_.append(tmpQFEdges);
1557 // Add this face to the map.
1558 map.addFace(newFaceIndex[4]);
1560 // Find the common edge between quad/quad faces...
1561 meshOps::findCommonEdge
1569 // ... and size-up edgeFaces for the edge
1573 edgeFaces_[otherEdgeIndex[3]]
1576 meshOps::replaceLabel
1583 meshOps::replaceLabel
1590 // Second boundary face; Owner = cell[1] & Neighbour [-1]
1591 tmpTriFace[0] = otherPointIndex[2];
1592 tmpTriFace[1] = newPointIndex[0];
1593 tmpTriFace[2] = otherEdgePoint[2];
1599 whichPatch(commonFaceIndex[2]),
1606 // Add a faceEdges entry as well
1607 faceEdges_.append(tmpTFEdges);
1609 // Add this face to the map.
1610 map.addFace(newFaceIndex[5]);
1612 meshOps::replaceLabel
1619 // Third boundary face; Owner = newCell[1] & Neighbour [-1]
1620 tmpTriFace[0] = otherPointIndex[3];
1621 tmpTriFace[1] = newPointIndex[1];
1622 tmpTriFace[2] = otherEdgePoint[3];
1628 whichPatch(commonFaceIndex[3]),
1635 // Add a faceEdges entry as well
1636 faceEdges_.append(tmpTFEdges);
1638 // Add this face to the map.
1639 map.addFace(newFaceIndex[6]);
1641 meshOps::replaceLabel
1648 // Create / modify edges...
1649 labelList tmpQuadEdgeFaces(4, -1);
1651 // The internal edge bisecting the face
1652 tmpQuadEdgeFaces[0] = fIndex;
1653 tmpQuadEdgeFaces[1] = newFaceIndex[0];
1654 tmpQuadEdgeFaces[2] = newFaceIndex[3];
1655 tmpQuadEdgeFaces[3] = newFaceIndex[4];
1662 edge(newPointIndex[0], newPointIndex[1]),
1667 // Add this edge to the map.
1668 map.addEdge(newEdgeIndex[0]);
1670 // Replace an edge on the bisected face
1671 meshOps::replaceLabel
1678 // Create / replace side edges created from face bisection
1679 tmpTriEdgeFaces[0] = commonFaceIndex[2];
1680 tmpTriEdgeFaces[1] = newFaceIndex[3];
1681 tmpTriEdgeFaces[2] = newFaceIndex[1];
1687 whichEdgePatch(commonEdgeIndex[2]),
1688 edge(newPointIndex[0], nextToOtherPoint[2]),
1693 // Add this edge to the map.
1694 map.addEdge(newEdgeIndex[3]);
1696 tmpTriEdgeFaces[0] = c0BdyIndex[1];
1697 tmpTriEdgeFaces[1] = newFaceIndex[3];
1698 tmpTriEdgeFaces[2] = newFaceIndex[6];
1704 whichEdgePatch(commonEdgeIndex[3]),
1705 edge(newPointIndex[1], otherEdgePoint[3]),
1710 // Add this edge to the map.
1711 map.addEdge(newEdgeIndex[4]);
1713 // The edge bisecting the second boundary triangular face
1714 tmpTriEdgeFaces[0] = commonFaceIndex[2];
1715 tmpTriEdgeFaces[1] = newFaceIndex[4];
1716 tmpTriEdgeFaces[2] = newFaceIndex[5];
1722 whichEdgePatch(commonEdgeIndex[2]),
1723 edge(newPointIndex[0], otherPointIndex[2]),
1728 // Add this edge to the map.
1729 map.addEdge(newEdgeIndex[5]);
1731 // Find the common edge between the quad/tri faces...
1732 meshOps::findCommonEdge
1740 // ...and correct faceEdges / edgeFaces
1741 meshOps::replaceLabel
1745 faceEdges_[commonFaceIndex[2]]
1748 meshOps::replaceLabel
1752 edgeFaces_[cornerEdgeIndex[2]]
1755 // The edge bisecting the third boundary triangular face
1756 tmpTriEdgeFaces[0] = commonFaceIndex[3];
1757 tmpTriEdgeFaces[1] = newFaceIndex[4];
1758 tmpTriEdgeFaces[2] = newFaceIndex[6];
1764 whichEdgePatch(commonEdgeIndex[3]),
1765 edge(newPointIndex[1], otherPointIndex[3]),
1770 // Add this edge to the map.
1771 map.addEdge(newEdgeIndex[6]);
1773 // Find the common edge between the quad/tri faces...
1774 meshOps::findCommonEdge
1782 // ...and correct faceEdges / edgeFaces
1783 meshOps::replaceLabel
1787 faceEdges_[commonFaceIndex[3]]
1790 meshOps::replaceLabel
1794 edgeFaces_[cornerEdgeIndex[3]]
1797 // Now that edges are defined, configure faceEdges
1798 // for all new faces
1800 // The quad interior face; Owner = c[0] & Neighbour = newCell[0]
1801 tmpQFEdges[0] = newEdgeIndex[0];
1802 tmpQFEdges[1] = newEdgeIndex[1];
1803 tmpQFEdges[2] = otherEdgeIndex[2];
1804 tmpQFEdges[3] = newEdgeIndex[2];
1805 faceEdges_[newFaceIndex[0]] = tmpQFEdges;
1807 // Second boundary face; Owner = newCell[0] & Neighbour = [-1]
1808 tmpTFEdges[0] = newEdgeIndex[3];
1809 tmpTFEdges[1] = cornerEdgeIndex[0];
1810 tmpTFEdges[2] = newEdgeIndex[1];
1811 faceEdges_[newFaceIndex[1]] = tmpTFEdges;
1813 // Third boundary face; Owner = c[0] & Neighbour = [-1]
1814 tmpTFEdges[0] = newEdgeIndex[2];
1815 tmpTFEdges[1] = cornerEdgeIndex[1];
1816 tmpTFEdges[2] = commonEdgeIndex[3];
1817 faceEdges_[newFaceIndex[2]] = tmpTFEdges;
1819 // The quad face from bisection:
1820 tmpQFEdges[0] = otherEdgeIndex[1];
1821 tmpQFEdges[1] = newEdgeIndex[3];
1822 tmpQFEdges[2] = newEdgeIndex[0];
1823 tmpQFEdges[3] = newEdgeIndex[4];
1824 faceEdges_[newFaceIndex[3]] = tmpQFEdges;
1826 // The quad interior face; Owner = c[1] & Neighbour = newCell[1]
1827 tmpQFEdges[0] = newEdgeIndex[0];
1828 tmpQFEdges[1] = newEdgeIndex[5];
1829 tmpQFEdges[2] = otherEdgeIndex[3];
1830 tmpQFEdges[3] = newEdgeIndex[6];
1831 faceEdges_[newFaceIndex[4]] = tmpQFEdges;
1833 // Second boundary face; Owner = c[1] & Neighbour = [-1]
1834 tmpTFEdges[0] = commonEdgeIndex[2];
1835 tmpTFEdges[1] = cornerEdgeIndex[2];
1836 tmpTFEdges[2] = newEdgeIndex[5];
1837 faceEdges_[newFaceIndex[5]] = tmpTFEdges;
1839 // Third boundary face; Owner = newCell[1] & Neighbour = [-1]
1840 tmpTFEdges[0] = newEdgeIndex[4];
1841 tmpTFEdges[1] = cornerEdgeIndex[3];
1842 tmpTFEdges[2] = newEdgeIndex[6];
1843 faceEdges_[newFaceIndex[6]] = tmpTFEdges;
1845 meshOps::replaceLabel
1849 faceEdges_[c0BdyIndex[1]]
1852 meshOps::replaceLabel
1856 edgeFaces_[commonEdgeIndex[1]]
1859 meshOps::replaceLabel
1863 faceEdges_[commonFaceIndex[2]]
1866 meshOps::replaceLabel
1870 edgeFaces_[commonEdgeIndex[2]]
1875 Pout<< nl << "Modified Cell[0]: "
1876 << c0 << ": " << oldCells[0] << endl;
1878 forAll(oldCells[0], faceI)
1880 const labelList& fE = faceEdges_[oldCells[0][faceI]];
1882 Pout<< oldCells[0][faceI]
1883 << ": " << faces_[oldCells[0][faceI]]
1889 const labelList& eF = edgeFaces_[fE[edgeI]];
1891 Pout<< '\t' << fE[edgeI]
1892 << ": " << edges_[fE[edgeI]]
1898 Pout<< "New Cell[0]: "
1899 << newCellIndex[0] << ": " << newCells[0] << endl;
1901 forAll(newCells[0], faceI)
1903 const labelList& fE = faceEdges_[newCells[0][faceI]];
1905 Pout<< newCells[0][faceI] << ": "
1906 << faces_[newCells[0][faceI]]
1912 const labelList& eF = edgeFaces_[fE[edgeI]];
1914 Pout<< '\t' << fE[edgeI]
1915 << ": " << edges_[fE[edgeI]]
1921 Pout<< nl << "Modified Cell[1]: "
1922 << c1 << ": " << oldCells[1] << endl;
1924 forAll(oldCells[1], faceI)
1926 const labelList& fE = faceEdges_[oldCells[1][faceI]];
1928 Pout<< oldCells[1][faceI] << ": "
1929 << faces_[oldCells[1][faceI]]
1935 const labelList& eF = edgeFaces_[fE[edgeI]];
1937 Pout<< '\t' << fE[edgeI]
1938 << ": " << edges_[fE[edgeI]]
1944 Pout<< "New Cell[1]: "
1945 << newCellIndex[1] << ": " << newCells[1] << endl;
1947 forAll(newCells[1], faceI)
1949 const labelList& fE = faceEdges_[newCells[1][faceI]];
1951 Pout<< newCells[1][faceI] << ": "
1952 << faces_[newCells[1][faceI]]
1958 const labelList& eF = edgeFaces_[fE[edgeI]];
1960 Pout<< '\t' << fE[edgeI]
1961 << ": " << edges_[fE[edgeI]]
1968 // Update the cell list.
1969 cells_[c1] = oldCells[1];
1970 cells_[newCellIndex[1]] = newCells[1];
1973 // Update the cell list.
1974 cells_[c0] = oldCells[0];
1975 cells_[newCellIndex[0]] = newCells[0];
1977 // Modify point labels for common edges
1978 if (edges_[commonEdgeIndex[0]].start() == otherEdgePoint[0])
1980 edges_[commonEdgeIndex[0]].start() = newPointIndex[0];
1984 edges_[commonEdgeIndex[0]].end() = newPointIndex[0];
1987 if (edges_[commonEdgeIndex[1]].start() == nextToOtherPoint[1])
1989 edges_[commonEdgeIndex[1]].start() = newPointIndex[1];
1993 edges_[commonEdgeIndex[1]].end() = newPointIndex[1];
1996 if (coupledModification_)
1998 // Alias for convenience...
1999 const changeMap& slaveMap = slaveMaps[0];
2001 const label pI = slaveMap.patchIndex();
2003 // Fetch the appropriate coupleMap
2004 const coupleMap* cMapPtr = NULL;
2006 if (localCouple && !procCouple)
2008 cMapPtr = &(patchCoupling_[pI].map());
2011 if (procCouple && !localCouple)
2013 cMapPtr = &(recvMeshes_[pI].map());
2016 // Alias for convenience
2017 const coupleMap& cMap = *cMapPtr;
2019 // Add the new points to the coupling map
2020 const List<objectMap>& apList = slaveMap.addedPointList();
2024 // Update reverse pointMap
2071 // Update reverse pointMap
2087 // Create a master/slave entry for the new face on the patch.
2088 FixedList<bool, 2> foundMatch(false);
2089 FixedList<label, 2> checkFaces(-1);
2091 // Fill in the faces to check for...
2092 checkFaces[0] = fIndex;
2093 checkFaces[1] = newFaceIndex[3];
2095 const List<objectMap>& afList = slaveMap.addedFaceList();
2097 forAll (checkFaces, indexI)
2099 const face& mFace = faces_[checkFaces[indexI]];
2101 label sFaceIndex = -1;
2105 const face* facePtr = NULL;
2107 if (localCouple && !procCouple)
2109 facePtr = &(faces_[afList[sfI].index()]);
2112 if (procCouple && !localCouple)
2114 const dynamicTopoFvMesh& mesh = recvMeshes_[pI].subMesh();
2116 facePtr = &(mesh.faces_[afList[sfI].index()]);
2119 const face& tFace = *facePtr;
2120 FixedList<bool, 4> cP(false);
2122 forAll(mFace, pointI)
2124 const Map<label>& pointMap =
2126 cMap.entityMap(coupleMap::POINT)
2129 if (tFace.which(pointMap[mFace[pointI]]) > -1)
2135 if (cP[0] && cP[1] && cP[2] && cP[3])
2137 sFaceIndex = afList[sfI].index();
2138 foundMatch[indexI] = true;
2143 if (foundMatch[indexI])
2184 "dynamicTopoFvMesh::bisectQuadFace\n"
2186 " const label fIndex,\n"
2187 " const changeMap& masterMap,\n"
2188 " bool checkOnly,\n"
2192 << "Failed to build coupled maps." << nl
2193 << " masterFace: " << mFace << nl
2194 << " Added slave faces: " << afList << nl
2195 << abort(FatalError);
2199 // Push operation into coupleMap
2203 coupleMap::BISECTION
2207 // Write out VTK files after change
2210 labelList cellHull(4, -1);
2212 cellHull[0] = owner_[fIndex];
2213 cellHull[1] = neighbour_[fIndex];
2214 cellHull[2] = owner_[newFaceIndex[3]];
2215 cellHull[3] = neighbour_[newFaceIndex[3]];
2225 // Fill-in mapping information
2226 FixedList<label, 4> mapCells(-1);
2229 mapCells[1] = newCellIndex[0];
2234 mapCells[3] = newCellIndex[1];
2237 labelList mC(1, c0);
2239 forAll(mapCells, cellI)
2241 if (mapCells[cellI] == -1)
2246 // Set the mapping for this cell
2247 setCellMapping(mapCells[cellI], mC);
2250 // Set fill-in mapping information for the modified face.
2253 // Set the mapping for this face
2254 setFaceMapping(fIndex, labelList(1, fIndex));
2258 // Internal face. Default mapping.
2259 setFaceMapping(fIndex);
2262 forAll(newFaceIndex, faceI)
2264 if (newFaceIndex[faceI] == -1)
2269 // Check for boundary faces
2270 if (neighbour_[newFaceIndex[faceI]] == -1)
2272 // Boundary face. Compute mapping.
2275 if (faces_[newFaceIndex[faceI]].size() == 4)
2277 // Quad-face on boundary
2278 mC.setSize(1, fIndex);
2281 if (faces_[newFaceIndex[faceI]].size() == 3)
2283 label triFacePatch = whichPatch(newFaceIndex[faceI]);
2285 // Fetch face-normals
2286 vector tfNorm, f0Norm, f1Norm;
2288 tfNorm = faces_[newFaceIndex[faceI]].normal(oldPoints_);
2289 f0Norm = faces_[c0BdyIndex[0]].normal(oldPoints_);
2290 f1Norm = faces_[c0BdyIndex[1]].normal(oldPoints_);
2292 // Tri-face on boundary. Perform normal checks
2293 // also, because of empty patches.
2296 (whichPatch(c0BdyIndex[0]) == triFacePatch) &&
2297 ((tfNorm & f0Norm) > 0.0)
2300 mC.setSize(1, c0BdyIndex[0]);
2305 (whichPatch(c0BdyIndex[1]) == triFacePatch) &&
2306 ((tfNorm & f1Norm) > 0.0)
2309 mC.setSize(1, c0BdyIndex[1]);
2316 "const changeMap dynamicTopoFvMesh::bisectQuadFace\n"
2318 " const label fIndex,\n"
2319 " const changeMap& masterMap,\n"
2323 << " Unable to find patch for face: "
2324 << newFaceIndex[faceI] << ":: "
2325 << faces_[newFaceIndex[faceI]] << nl
2326 << " Patch: " << triFacePatch << nl
2327 << abort(FatalError);
2331 // Set the mapping for this face
2332 setFaceMapping(newFaceIndex[faceI], mC);
2336 // Internal quad-faces get default mapping.
2337 setFaceMapping(newFaceIndex[faceI]);
2342 topoChangeFlag_ = true;
2344 // Increment the counter
2347 // Increment surface-counter
2350 // Do not update stats for processor patches
2351 if (!processorCoupledEntity(fIndex))
2357 // Increment the number of modifications
2360 // Specify that the operation was successful
2363 // Return the changeMap
2368 // Method for the bisection of an edge in 3D
2369 // - Returns a changeMap with a type specifying:
2370 // 1: Bisection was successful
2371 // -1: Bisection failed since max number of topo-changes was reached.
2372 // -2: Bisection failed since resulting quality would be unacceptable.
2373 // -3: Bisection failed since edge was on a noRefinement patch.
2374 // - AddedPoints contain the index of the newly added point.
2375 const changeMap dynamicTopoFvMesh::bisectEdge
2382 // Edge bisection performs the following operations:
2383 // [1] Add a point at middle of the edge
2384 // [2] Bisect all faces surrounding this edge
2385 // [3] Bisect all cells surrounding this edge
2386 // [4] Create internal/external edges for each bisected face
2387 // [5] Create internal faces for each bisected cell
2388 // Update faceEdges and edgeFaces information
2390 // For 2D meshes, perform face-bisection
2393 return bisectQuadFace(eIndex, changeMap(), checkOnly);
2396 // Figure out which thread this is...
2397 label tIndex = self();
2399 // Prepare the changeMaps
2401 List<changeMap> slaveMaps;
2402 bool bisectingSlave = false;
2406 (statistics_[0] > maxModifications_) &&
2407 (maxModifications_ > -1)
2410 // Reached the max allowable topo-changes.
2411 stack(tIndex).clear();
2416 // Check if edgeRefinements are to be avoided on patch.
2417 const labelList& eF = edgeFaces_[eIndex];
2421 label fPatch = whichPatch(eF[fI]);
2423 if (baseMesh_.lengthEstimator().checkRefinementPatch(fPatch))
2431 // Sanity check: Is the index legitimate?
2437 "const changeMap dynamicTopoFvMesh::bisectEdge\n"
2439 " const label eIndex,\n"
2440 " bool checkOnly,\n"
2444 << " Invalid index: " << eIndex
2445 << abort(FatalError);
2448 // If coupled modification is set, and this is a
2449 // master edge, bisect its slaves as well.
2450 bool localCouple = false, procCouple = false;
2452 if (coupledModification_)
2454 const edge& eCheck = edges_[eIndex];
2456 const label edgeEnum = coupleMap::EDGE;
2458 // Is this a locally coupled edge (either master or slave)?
2459 if (locallyCoupledEntity(eIndex, true))
2465 if (processorCoupledEntity(eIndex))
2468 localCouple = false;
2471 if (localCouple && !procCouple)
2473 // Determine the slave index.
2474 label sIndex = -1, pIndex = -1;
2476 forAll(patchCoupling_, patchI)
2478 if (patchCoupling_(patchI))
2480 const coupleMap& cMap = patchCoupling_[patchI].map();
2482 if ((sIndex = cMap.findSlave(edgeEnum, eIndex)) > -1)
2489 // The following bit happens only during the sliver
2490 // exudation process, since slave edges are
2491 // usually not added to the coupled edge-stack.
2492 if ((sIndex = cMap.findMaster(edgeEnum, eIndex)) > -1)
2496 // Notice that we are bisecting a slave edge first.
2497 bisectingSlave = true;
2509 "const changeMap dynamicTopoFvMesh::bisectEdge\n"
2511 " const label eIndex,\n"
2512 " bool checkOnly,\n"
2516 << "Coupled maps were improperly specified." << nl
2517 << " Slave index not found for: " << nl
2518 << " Edge: " << eIndex << ": " << edges_[eIndex] << nl
2519 << abort(FatalError);
2523 // If we've found the slave, size up the list
2530 // Save index and patch for posterity
2531 slaveMaps[0].index() = sIndex;
2532 slaveMaps[0].patchIndex() = pIndex;
2537 Pout<< nl << " >> Bisecting slave edge: " << sIndex
2538 << " for master edge: " << eIndex << endl;
2542 if (procCouple && !localCouple)
2544 // If this is a new entity, bail out for now.
2545 // This will be handled at the next time-step.
2546 if (eIndex >= nOldEdges_)
2552 forAll(procIndices_, pI)
2554 // Fetch reference to subMeshes
2555 const coupledInfo& sendMesh = sendMeshes_[pI];
2556 const coupledInfo& recvMesh = recvMeshes_[pI];
2558 const coupleMap& scMap = sendMesh.map();
2559 const coupleMap& rcMap = recvMesh.map();
2561 // If this edge was sent to a lower-ranked
2562 // processor, skip it.
2563 if (procIndices_[pI] < Pstream::myProcNo())
2565 if (scMap.reverseEntityMap(edgeEnum).found(eIndex))
2569 Pout<< "Edge: " << eIndex
2571 << " was sent to proc: "
2573 << ", so bailing out."
2583 if ((sIndex = rcMap.findSlave(edgeEnum, eIndex)) > -1)
2587 Pout<< "Checking slave edge: " << sIndex
2588 << " on proc: " << procIndices_[pI]
2589 << " for master edge: " << eIndex
2593 // Check if a lower-ranked processor is
2594 // handling this edge
2595 if (procIndices_[pI] < Pstream::myProcNo())
2599 Pout<< "Edge: " << eIndex
2600 << " is handled by proc: "
2602 << ", so bailing out."
2609 label curIndex = slaveMaps.size();
2618 // Save index and patch for posterity
2619 slaveMaps[curIndex].index() = sIndex;
2620 slaveMaps[curIndex].patchIndex() = pI;
2626 // Something's wrong with coupling maps
2630 "const changeMap dynamicTopoFvMesh::bisectEdge\n"
2632 " const label eIndex,\n"
2633 " bool checkOnly,\n"
2637 << "Coupled maps were improperly specified." << nl
2638 << " localCouple: " << localCouple << nl
2639 << " procCouple: " << procCouple << nl
2640 << " Edge: " << eIndex << ": " << edges_[eIndex] << nl
2641 << abort(FatalError);
2644 // Temporarily turn off coupledModification
2645 unsetCoupledModification();
2647 // First check the master for bisection feasibility.
2648 changeMap masterMap = bisectEdge(eIndex, true, forceOp);
2651 setCoupledModification();
2653 // Master couldn't perform bisection
2654 if (masterMap.type() <= 0)
2659 // Now check each of the slaves for bisection feasibility
2660 forAll(slaveMaps, slaveI)
2662 // Alias for convenience...
2663 changeMap& slaveMap = slaveMaps[slaveI];
2665 label sIndex = slaveMap.index();
2666 label pI = slaveMap.patchIndex();
2668 // If the edge is mapped onto itself, skip check
2669 // (occurs for cyclic edges)
2670 if ((sIndex == eIndex) && localCouple)
2675 // Temporarily turn off coupledModification
2676 unsetCoupledModification();
2678 // Test the slave edge
2681 slaveMap = bisectEdge(sIndex, true, forceOp);
2686 dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
2690 Pout<< "Checking slave edge: " << sIndex
2691 << "::" << sMesh.edges_[sIndex]
2692 << " on proc: " << procIndices_[pI]
2693 << " for master edge: " << eIndex
2697 slaveMap = sMesh.bisectEdge(sIndex, true, forceOp);
2701 setCoupledModification();
2703 if (slaveMap.type() <= 0)
2705 // Slave couldn't perform bisection.
2711 // Save index and patch for posterity
2712 slaveMap.index() = sIndex;
2713 slaveMap.patchIndex() = pI;
2716 // Next bisect each slave edge..
2717 forAll(slaveMaps, slaveI)
2719 // Alias for convenience...
2720 changeMap& slaveMap = slaveMaps[slaveI];
2722 label sIndex = slaveMap.index();
2723 label pI = slaveMap.patchIndex();
2725 // If the edge is mapped onto itself, skip modification
2726 // (occurs for cyclic edges)
2727 if ((sIndex == eIndex) && localCouple)
2732 // Temporarily turn off coupledModification
2733 unsetCoupledModification();
2735 // Bisect the slave edge
2738 slaveMap = bisectEdge(sIndex, false, forceOp);
2742 dynamicTopoFvMesh& sMesh = recvMeshes_[pI].subMesh();
2744 slaveMap = sMesh.bisectEdge(sIndex, false, forceOp);
2748 setCoupledModification();
2750 // The final operation has to succeed.
2751 if (slaveMap.type() <= 0)
2756 "const changeMap dynamicTopoFvMesh::bisectEdge\n"
2758 " const label eIndex,\n"
2759 " bool checkOnly,\n"
2763 << "Coupled topo-change for slave failed." << nl
2764 << " Edge: " << eIndex << ": " << edges_[eIndex] << nl
2765 << " Slave index: " << sIndex << nl
2766 << " Patch index: " << pI << nl
2767 << " Type: " << slaveMap.type() << nl
2768 << abort(FatalError);
2771 // Save index and patch for posterity
2772 slaveMap.index() = sIndex;
2773 slaveMap.patchIndex() = pI;
2777 // Before we bisect this edge, check whether the operation will
2778 // yield an acceptable cell-quality.
2781 if ((minQ = computeBisectionQuality(eIndex)) < sliverThreshold_)
2783 // Check if the quality is actually valid before forcing it.
2784 if (forceOp && (minQ < 0.0))
2789 "const changeMap dynamicTopoFvMesh::bisectEdge\n"
2791 " const label eIndex,\n"
2792 " bool checkOnly,\n"
2796 << " Forcing bisection on edge: " << eIndex
2797 << " will yield an invalid cell."
2798 << abort(FatalError);
2808 // Are we performing only checks?
2811 if (debug > 3 && isSubMesh_)
2813 Pout<< " Slave edge: " << eIndex
2814 << " can be bisected."
2822 // Update number of surface bisections, if necessary.
2823 if (whichEdgePatch(eIndex) > -1)
2825 // Do not update stats for processor patches
2826 if (!processorCoupledEntity(eIndex))
2834 edge origEdge(edges_[eIndex]);
2835 labelList tmpEdgeFaces(3,-1);
2836 labelList tmpIntEdgeFaces(4,-1);
2837 labelList tmpFaceEdges(3,-1);
2839 // Build vertexHull for this edge
2840 labelList vertexHull;
2841 buildVertexHull(eIndex, vertexHull);
2843 // Size up the hull lists
2844 label m = vertexHull.size();
2845 labelList cellHull(m, -1);
2846 labelList faceHull(m, -1);
2847 labelList edgeHull(m, -1);
2848 labelListList ringEntities(4, labelList(m, -1));
2850 // Construct a hull around this edge
2851 meshOps::constructHull
2871 << "Edge: " << eIndex
2873 << " is to be bisected. " << endl;
2875 Pout<< " On SubMesh: " << Switch::asText(isSubMesh_) << nl;
2876 Pout<< " coupledModification: " << coupledModification_ << nl;
2878 label epIndex = whichEdgePatch(eIndex);
2880 const polyBoundaryMesh& boundary = boundaryMesh();
2886 Pout<< "Internal" << endl;
2889 if (epIndex < boundary.size())
2891 Pout<< boundary[epIndex].name() << endl;
2895 Pout<< " New patch: " << epIndex << endl;
2898 // Write out VTK files prior to change
2899 // - Using old-points for convenience in post-processing
2905 + '(' + Foam::name(origEdge[0])
2906 + ',' + Foam::name(origEdge[1]) + ')'
2914 labelList mP(2, -1);
2916 // Set mapping for this point
2917 mP[0] = edges_[eIndex][0];
2918 mP[1] = edges_[eIndex][1];
2920 // Add a new point to the end of the list
2921 label newPointIndex =
2925 0.5 * (points_[mP[0]] + points_[mP[1]]),
2926 0.5 * (oldPoints_[mP[0]] + oldPoints_[mP[1]]),
2931 // Add this point to the map.
2932 map.addPoint(newPointIndex);
2934 // New edges can lie on a bounding curve between
2935 // coupled and non-coupled faces. Preferentially
2936 // add edges to coupled-patches, if they exist.
2937 // This makes it convenient for coupled patch matching.
2940 if (locallyCoupledEntity(eIndex, true))
2942 nePatch = locallyCoupledEdgePatch(eIndex);
2946 nePatch = whichEdgePatch(eIndex);
2949 // Add a new edge to the end of the list
2950 label newEdgeIndex =
2955 edge(newPointIndex,edges_[eIndex][1]),
2956 labelList(faceHull.size(),-1)
2960 // Add this edge to the map.
2961 map.addEdge(newEdgeIndex);
2963 // Remove the existing edge from the pointEdges list
2964 // of the modified point, and add it to the new point
2965 meshOps::sizeDownList(eIndex, pointEdges_[edges_[eIndex][1]]);
2966 meshOps::sizeUpList(eIndex, pointEdges_[newPointIndex]);
2968 // Modify the existing edge
2969 edges_[eIndex][1] = newPointIndex;
2971 // Add this edge to the map.
2972 // Although this edge isn't technically 'added', it's
2973 // required for coupled patch mapping.
2974 map.addEdge(eIndex);
2976 // Keep track of added entities
2977 labelList addedCellIndices(cellHull.size(),-1);
2978 labelList addedFaceIndices(faceHull.size(),-1);
2979 labelList addedEdgeIndices(faceHull.size(),-1);
2980 labelList addedIntFaceIndices(faceHull.size(),-1);
2982 // Now loop through the hull and bisect individual entities
2983 forAll(vertexHull, indexI)
2985 // Modify the existing face
2986 meshOps::replaceLabel
2988 edges_[newEdgeIndex][1],
2990 faces_[faceHull[indexI]]
2993 // Obtain circular indices
2994 label nextI = vertexHull.fcIndex(indexI);
2995 label prevI = vertexHull.rcIndex(indexI);
2997 // Check if this is an interior/boundary face
2998 if (cellHull[indexI] != -1)
3000 // Create a new cell. Add it for now, but update later.
3003 addedCellIndices[indexI] =
3008 lengthScale_[cellHull[indexI]]
3012 // Add this cell to the map.
3013 map.addCell(addedCellIndices[indexI]);
3015 // Configure the interior face
3016 tmpTriFace[0] = vertexHull[nextI];
3017 tmpTriFace[1] = vertexHull[indexI];
3018 tmpTriFace[2] = newPointIndex;
3021 addedIntFaceIndices[indexI] =
3028 addedCellIndices[indexI]
3032 // Add a faceEdges entry as well
3033 faceEdges_.append(tmpFaceEdges);
3035 // Add this face to the map.
3036 map.addFace(addedIntFaceIndices[indexI]);
3038 // Add to the new cell
3039 newCell[0] = addedIntFaceIndices[indexI];
3041 // Modify the existing ring face connected to newEdge[1]
3042 label replaceFace = ringEntities[3][indexI];
3044 // Check if face reversal is necessary
3045 if (owner_[replaceFace] == cellHull[indexI])
3047 if (neighbour_[replaceFace] == -1)
3050 owner_[replaceFace] = addedCellIndices[indexI];
3054 // This face has to be reversed
3055 faces_[replaceFace] = faces_[replaceFace].reverseFace();
3056 owner_[replaceFace] = neighbour_[replaceFace];
3057 neighbour_[replaceFace] = addedCellIndices[indexI];
3059 setFlip(replaceFace);
3064 // Keep owner, but change neighbour
3065 neighbour_[replaceFace] = addedCellIndices[indexI];
3068 // Modify the edge on the ring.
3069 // Add the new interior face to edgeFaces.
3072 addedIntFaceIndices[indexI],
3073 edgeFaces_[edgeHull[indexI]]
3076 // Add this edge to faceEdges for the new interior face
3077 faceEdges_[addedIntFaceIndices[indexI]][0] = edgeHull[indexI];
3079 // Replace face labels
3080 meshOps::replaceLabel
3083 addedIntFaceIndices[indexI],
3084 cells_[cellHull[indexI]]
3087 // Add to the new cell
3088 newCell[1] = replaceFace;
3090 // Check if this is a boundary face
3091 if (cellHull[prevI] == -1)
3093 // Configure the boundary face
3094 tmpTriFace[0] = newPointIndex;
3095 tmpTriFace[1] = edges_[newEdgeIndex][1];
3096 tmpTriFace[2] = vertexHull[indexI];
3099 addedFaceIndices[indexI] =
3103 whichPatch(faceHull[indexI]),
3105 addedCellIndices[indexI],
3110 // Add this face to the map.
3111 map.addFace(addedFaceIndices[indexI]);
3113 // Configure edgeFaces
3114 tmpEdgeFaces[0] = faceHull[indexI];
3115 tmpEdgeFaces[1] = addedIntFaceIndices[indexI];
3116 tmpEdgeFaces[2] = addedFaceIndices[indexI];
3119 addedEdgeIndices[indexI] =
3123 whichPatch(faceHull[indexI]),
3124 edge(newPointIndex,vertexHull[indexI]),
3129 // Add this edge to the map.
3130 map.addEdge(addedEdgeIndices[indexI]);
3132 // Add this edge to the interior-face faceEdges entry
3133 faceEdges_[addedIntFaceIndices[indexI]][1] =
3135 addedEdgeIndices[indexI]
3138 // Configure faceEdges for this boundary face
3139 tmpFaceEdges[0] = addedEdgeIndices[indexI];
3140 tmpFaceEdges[1] = newEdgeIndex;
3141 tmpFaceEdges[2] = ringEntities[2][indexI];
3143 // Modify faceEdges for the hull face
3144 meshOps::replaceLabel
3146 ringEntities[2][indexI],
3147 addedEdgeIndices[indexI],
3148 faceEdges_[faceHull[indexI]]
3151 // Modify edgeFaces for the edge connected to newEdge[1]
3152 meshOps::replaceLabel
3155 addedFaceIndices[indexI],
3156 edgeFaces_[ringEntities[2][indexI]]
3159 // Add the faceEdges entry
3160 faceEdges_.append(tmpFaceEdges);
3162 // Add an entry to edgeFaces
3163 edgeFaces_[newEdgeIndex][indexI] = addedFaceIndices[indexI];
3165 // Add an entry for this cell
3166 newCell[2] = addedFaceIndices[indexI];
3169 // Check if a cell was added before this
3170 if (addedCellIndices[prevI] != -1)
3172 // Configure the interior face
3173 tmpTriFace[0] = vertexHull[indexI];
3174 tmpTriFace[1] = edges_[newEdgeIndex][1];
3175 tmpTriFace[2] = newPointIndex;
3178 addedFaceIndices[indexI] =
3184 addedCellIndices[prevI],
3185 addedCellIndices[indexI]
3189 // Add this face to the map.
3190 map.addFace(addedFaceIndices[indexI]);
3192 // Configure edgeFaces
3193 tmpIntEdgeFaces[0] = faceHull[indexI];
3194 tmpIntEdgeFaces[1] = addedIntFaceIndices[indexI];
3195 tmpIntEdgeFaces[2] = addedFaceIndices[indexI];
3196 tmpIntEdgeFaces[3] = addedIntFaceIndices[prevI];
3198 // Add an internal edge
3199 addedEdgeIndices[indexI] =
3204 edge(newPointIndex,vertexHull[indexI]),
3209 // Add this edge to the map.
3210 map.addEdge(addedEdgeIndices[indexI]);
3212 // Add this edge to the interior-face faceEdges entry..
3213 faceEdges_[addedIntFaceIndices[indexI]][1] =
3215 addedEdgeIndices[indexI]
3218 // ... and to the previous interior face as well
3219 faceEdges_[addedIntFaceIndices[prevI]][2] =
3221 addedEdgeIndices[indexI]
3224 // Configure faceEdges for this split interior face
3225 tmpFaceEdges[0] = addedEdgeIndices[indexI];
3226 tmpFaceEdges[1] = newEdgeIndex;
3227 tmpFaceEdges[2] = ringEntities[2][indexI];
3229 // Modify faceEdges for the hull face
3230 meshOps::replaceLabel
3232 ringEntities[2][indexI],
3233 addedEdgeIndices[indexI],
3234 faceEdges_[faceHull[indexI]]
3237 // Modify edgeFaces for the edge connected to newEdge[1]
3238 meshOps::replaceLabel
3241 addedFaceIndices[indexI],
3242 edgeFaces_[ringEntities[2][indexI]]
3245 // Add the faceEdges entry
3246 faceEdges_.append(tmpFaceEdges);
3248 // Add an entry to edgeFaces
3249 edgeFaces_[newEdgeIndex][indexI] = addedFaceIndices[indexI];
3251 // Add an entry for this cell
3252 newCell[2] = addedFaceIndices[indexI];
3254 // Make the final entry for the previous cell
3255 cells_[addedCellIndices[prevI]][3] = addedFaceIndices[indexI];
3258 // Do the first interior face at the end
3259 if (indexI == vertexHull.size() - 1)
3261 // Configure the interior face
3262 tmpTriFace[0] = newPointIndex;
3263 tmpTriFace[1] = edges_[newEdgeIndex][1];
3264 tmpTriFace[2] = vertexHull[0];
3267 addedFaceIndices[0] =
3273 addedCellIndices[0],
3274 addedCellIndices[indexI]
3278 // Add this face to the map.
3279 map.addFace(addedFaceIndices[0]);
3281 // Configure edgeFaces
3282 tmpIntEdgeFaces[0] = faceHull[0];
3283 tmpIntEdgeFaces[1] = addedIntFaceIndices[0];
3284 tmpIntEdgeFaces[2] = addedFaceIndices[0];
3285 tmpIntEdgeFaces[3] = addedIntFaceIndices[indexI];
3287 // Add an internal edge
3288 addedEdgeIndices[0] =
3293 edge(newPointIndex,vertexHull[0]),
3298 // Add this edge to the map.
3299 map.addEdge(addedEdgeIndices[0]);
3301 // Add this edge to the interior-face faceEdges entry..
3302 faceEdges_[addedIntFaceIndices[0]][1] =
3307 // ... and to the previous interior face as well
3308 faceEdges_[addedIntFaceIndices[indexI]][2] =
3313 // Configure faceEdges for the first split face
3314 tmpFaceEdges[0] = addedEdgeIndices[0];
3315 tmpFaceEdges[1] = newEdgeIndex;
3316 tmpFaceEdges[2] = ringEntities[2][0];
3318 // Modify faceEdges for the hull face
3319 meshOps::replaceLabel
3322 addedEdgeIndices[0],
3323 faceEdges_[faceHull[0]]
3326 // Modify edgeFaces for the edge connected to newEdge[1]
3327 meshOps::replaceLabel
3330 addedFaceIndices[0],
3331 edgeFaces_[ringEntities[2][0]]
3334 // Add the faceEdges entry
3335 faceEdges_.append(tmpFaceEdges);
3337 // Add an entry to edgeFaces
3338 edgeFaces_[newEdgeIndex][0] = addedFaceIndices[0];
3340 // Add an entry for this cell
3341 newCell[3] = addedFaceIndices[0];
3343 // Make the final entry for the first cell
3344 cells_[addedCellIndices[0]][2] = addedFaceIndices[0];
3347 // Update the cell list with the new cell.
3348 cells_[addedCellIndices[indexI]] = newCell;
3352 // Configure the final boundary face
3353 tmpTriFace[0] = vertexHull[indexI];
3354 tmpTriFace[1] = edges_[newEdgeIndex][1];
3355 tmpTriFace[2] = newPointIndex;
3358 addedFaceIndices[indexI] =
3362 whichPatch(faceHull[indexI]),
3364 addedCellIndices[prevI],
3369 // Add this face to the map.
3370 map.addFace(addedFaceIndices[indexI]);
3372 // Configure edgeFaces
3373 tmpEdgeFaces[0] = addedFaceIndices[indexI];
3374 tmpEdgeFaces[1] = addedIntFaceIndices[prevI];
3375 tmpEdgeFaces[2] = faceHull[indexI];
3378 addedEdgeIndices[indexI] =
3382 whichPatch(faceHull[indexI]),
3383 edge(newPointIndex,vertexHull[indexI]),
3388 // Add this edge to the map.
3389 map.addEdge(addedEdgeIndices[indexI]);
3391 // Add a faceEdges entry to the previous interior face
3392 faceEdges_[addedIntFaceIndices[prevI]][2] =
3394 addedEdgeIndices[indexI]
3397 // Configure faceEdges for the final boundary face
3398 tmpFaceEdges[0] = addedEdgeIndices[indexI];
3399 tmpFaceEdges[1] = newEdgeIndex;
3400 tmpFaceEdges[2] = ringEntities[2][indexI];
3402 // Modify faceEdges for the hull face
3403 meshOps::replaceLabel
3405 ringEntities[2][indexI],
3406 addedEdgeIndices[indexI],
3407 faceEdges_[faceHull[indexI]]
3410 // Modify edgeFaces for the edge connected to newEdge[1]
3411 meshOps::replaceLabel
3414 addedFaceIndices[indexI],
3415 edgeFaces_[ringEntities[2][indexI]]
3418 // Add the faceEdges entry
3419 faceEdges_.append(tmpFaceEdges);
3421 // Add an entry to edgeFaces
3422 edgeFaces_[newEdgeIndex][indexI] = addedFaceIndices[indexI];
3424 // Make the final entry for the previous cell
3425 cells_[addedCellIndices[prevI]][3] = addedFaceIndices[indexI];
3429 // Now that all old / new cells possess correct connectivity,
3430 // compute mapping information.
3431 forAll(cellHull, indexI)
3433 if (cellHull[indexI] == -1)
3438 // Set mapping for both new and modified cells.
3439 FixedList<label, 2> cmIndex;
3441 cmIndex[0] = cellHull[indexI];
3442 cmIndex[1] = addedCellIndices[indexI];
3444 // Fill-in candidate mapping information
3445 labelList mC(1, cellHull[indexI]);
3447 forAll(cmIndex, cmI)
3449 // Set the mapping for this cell
3450 setCellMapping(cmIndex[cmI], mC);
3454 // Set mapping information for old / new faces
3455 forAll(faceHull, indexI)
3457 // Interior faces get default mapping
3458 if (addedIntFaceIndices[indexI] > -1)
3460 setFaceMapping(addedIntFaceIndices[indexI]);
3463 // Decide between default / weighted mapping
3464 // based on boundary information
3465 if (whichPatch(faceHull[indexI]) == -1)
3467 // Interior faces get default mapping
3468 setFaceMapping(faceHull[indexI]);
3469 setFaceMapping(addedFaceIndices[indexI]);
3473 // Compute mapping weights for boundary faces
3474 FixedList<label, 2> fmIndex;
3476 fmIndex[0] = faceHull[indexI];
3477 fmIndex[1] = addedFaceIndices[indexI];
3479 // Fill-in candidate mapping information
3480 labelList mF(1, faceHull[indexI]);
3482 forAll(fmIndex, fmI)
3484 // Set the mapping for this face
3485 setFaceMapping(fmIndex[fmI], mF);
3490 // If modification is coupled, update mapping info.
3491 if (coupledModification_)
3493 // Build a list of boundary edges / faces for mapping
3494 DynamicList<label> checkEdges(8), checkFaces(4);
3496 const labelList& oeFaces = edgeFaces_[eIndex];
3497 const labelList& neFaces = edgeFaces_[newEdgeIndex];
3499 forAll(oeFaces, faceI)
3501 FixedList<label, 2> check(-1);
3503 check[0] = oeFaces[faceI];
3504 check[1] = neFaces[faceI];
3506 forAll(check, indexI)
3508 label cPatch = whichPatch(check[indexI]);
3510 if (localCouple && !procCouple)
3512 if (!locallyCoupledEntity(check[indexI], true, false, true))
3517 // Check for cyclics
3518 if (boundaryMesh()[cPatch].type() == "cyclic")
3520 // Check if this is a master face
3521 const coupleMap& cM = patchCoupling_[cPatch].map();
3522 const Map<label>& fM = cM.entityMap(coupleMap::FACE);
3524 // Only add master faces
3525 // (belonging to the first half)
3526 // - Only check[0] will be present,
3527 // so check for that alone
3528 if (!fM.found(check[0]))
3535 if (procCouple && !localCouple)
3537 if (getNeighbourProcessor(cPatch) == -1)
3543 // Add face and its edges for checking
3544 if (findIndex(checkFaces, check[indexI]) == -1)
3547 checkFaces.append(check[indexI]);
3549 const labelList& fEdges = faceEdges_[check[indexI]];
3551 forAll(fEdges, edgeI)
3553 if (findIndex(checkEdges, fEdges[edgeI]) == -1)
3555 checkEdges.append(fEdges[edgeI]);
3562 // Output check entities
3567 "checkEdges_" + Foam::name(eIndex),
3568 checkEdges, 1, false, true
3573 "checkFaces_" + Foam::name(eIndex),
3574 checkFaces, 2, false, true
3578 forAll(slaveMaps, slaveI)
3580 // Alias for convenience...
3581 const changeMap& slaveMap = slaveMaps[slaveI];
3583 const label pI = slaveMap.patchIndex();
3585 // Fetch the appropriate coupleMap / mesh
3586 const coupleMap* cMapPtr = NULL;
3587 const dynamicTopoFvMesh* sMeshPtr = NULL;
3589 if (localCouple && !procCouple)
3591 cMapPtr = &(patchCoupling_[pI].map());
3595 if (procCouple && !localCouple)
3597 cMapPtr = &(recvMeshes_[pI].map());
3598 sMeshPtr = &(recvMeshes_[pI].subMesh());
3601 // Alias for convenience
3602 const coupleMap& cMap = *cMapPtr;
3603 const dynamicTopoFvMesh& sMesh = *sMeshPtr;
3605 // Add the new points to the coupling map
3606 const List<objectMap>& apList = slaveMap.addedPointList();
3608 // Fetch the slave point
3609 label slavePoint = -1;
3611 if ((slaveMap.index() == eIndex) && localCouple)
3613 // Cyclic edge at axis
3614 slavePoint = newPointIndex;
3618 slavePoint = apList[0].index();
3624 // Update reverse pointMap
3650 // Update reverse pointMap
3661 Pout<< " Adding point: " << slavePoint
3662 << " for point: " << newPointIndex
3666 // Obtain point maps
3667 const Map<label>& pointMap = cMap.entityMap(coupleMap::POINT);
3669 // Update face mapping
3670 const label faceEnum = coupleMap::FACE;
3672 // Obtain references
3673 Map<label>& faceMap = cMap.entityMap(faceEnum);
3674 Map<label>& rFaceMap = cMap.reverseEntityMap(faceEnum);
3676 forAll(checkFaces, faceI)
3678 label mfIndex = checkFaces[faceI];
3680 const face& mF = faces_[mfIndex];
3682 label mfPatch = whichPatch(mfIndex);
3684 // Check for processor match
3685 label neiProc = getNeighbourProcessor(mfPatch);
3687 if (procCouple && !localCouple)
3689 if (neiProc != procIndices_[pI])
3697 pointMap.found(mF[0]) ? pointMap[mF[0]] : -1,
3698 pointMap.found(mF[1]) ? pointMap[mF[1]] : -1,
3699 pointMap.found(mF[2]) ? pointMap[mF[2]] : -1
3702 // Skip mapping if all points were not found
3703 if (cF[0] == -1 || cF[1] == -1 || cF[2] == -1)
3708 bool matchedFace = false;
3710 // Fetch edges connected to the slave point
3711 const labelList& spEdges = sMesh.pointEdges_[slavePoint];
3713 forAll(spEdges, edgeI)
3715 label seIndex = spEdges[edgeI];
3717 if (sMesh.whichEdgePatch(seIndex) == -1)
3722 const labelList& seFaces = sMesh.edgeFaces_[seIndex];
3724 forAll(seFaces, faceI)
3726 label sfIndex = seFaces[faceI];
3728 if (sMesh.whichPatch(sfIndex) == -1)
3733 const face& sF = sMesh.faces_[sfIndex];
3739 triFace(sF[0], sF[1], sF[2]), cF
3745 word pN(boundaryMesh()[mfPatch].name());
3747 Pout<< " Found face: " << sfIndex
3749 << " with mfIndex: " << mfIndex
3755 if (rFaceMap.found(sfIndex))
3757 rFaceMap[sfIndex] = mfIndex;
3761 rFaceMap.insert(sfIndex, mfIndex);
3764 if (faceMap.found(mfIndex))
3766 faceMap[mfIndex] = sfIndex;
3770 faceMap.insert(mfIndex, sfIndex);
3790 + Foam::name(mfIndex),
3796 "checkFaces_" + Foam::name(eIndex),
3797 checkFaces, 2, false, true
3800 Pout<< " Failed to match face: "
3801 << mfIndex << " :: " << mF
3802 << " masterPatch: " << mfPatch
3803 << " using comparison face: " << cF
3804 << abort(FatalError);
3808 // Update edge mapping
3809 const label edgeEnum = coupleMap::EDGE;
3811 // Obtain references
3812 Map<label>& edgeMap = cMap.entityMap(edgeEnum);
3813 Map<label>& rEdgeMap = cMap.reverseEntityMap(edgeEnum);
3815 forAll(checkEdges, edgeI)
3817 label meIndex = checkEdges[edgeI];
3819 const edge& mE = edges_[meIndex];
3821 label mePatch = whichPatch(meIndex);
3822 label neiProc = getNeighbourProcessor(mePatch);
3826 pointMap.found(mE[0]) ? pointMap[mE[0]] : -1,
3827 pointMap.found(mE[1]) ? pointMap[mE[1]] : -1
3830 // Skip mapping if all points were not found
3831 if (cE[0] == -1 || cE[1] == -1)
3836 bool matchedEdge = false;
3838 // Fetch edges connected to the slave point
3839 const labelList& spEdges = sMesh.pointEdges_[cE[0]];
3841 forAll(spEdges, edgeI)
3843 label seIndex = spEdges[edgeI];
3845 const edge& sE = sMesh.edges_[seIndex];
3851 Pout<< " Found edge: " << seIndex
3853 << " with meIndex: " << meIndex
3858 // Update reverse map
3859 if (rEdgeMap.found(seIndex))
3861 rEdgeMap[seIndex] = meIndex;
3865 rEdgeMap.insert(seIndex, meIndex);
3869 if (edgeMap.found(meIndex))
3871 edgeMap[meIndex] = seIndex;
3875 edgeMap.insert(meIndex, seIndex);
3886 if (procCouple && !localCouple)
3888 // Rare occassion where both points
3889 // of the edge lie on processor, but
3890 // not the edge itself.
3891 if (neiProc != procIndices_[pI])
3895 Pout<< " Edge: " << meIndex
3897 << " with comparison: " << cE
3898 << " has points on processor: " << neiProc
3899 << " but no edge. Marking as matched."
3913 + Foam::name(meIndex),
3919 "checkEdges_" + Foam::name(eIndex),
3920 checkEdges, 1, false, true
3923 Pout<< " Failed to match edge: "
3924 << meIndex << " :: " << mE
3925 << " using comparison edge: " << cE
3926 << abort(FatalError);
3930 // Push operation into coupleMap
3931 if (procCouple && !localCouple)
3936 coupleMap::BISECTION
3944 label bPatch = whichEdgePatch(eIndex);
3946 const polyBoundaryMesh& boundary = boundaryMesh();
3950 Pout<< "Patch: Internal" << nl;
3953 if (bPatch < boundary.size())
3955 Pout<< "Patch: " << boundary[bPatch].name() << nl;
3959 Pout<< " New patch: " << bPatch << endl;
3962 Pout<< "vertexHull: " << vertexHull << nl
3963 << "Edges: " << edgeHull << nl
3964 << "Faces: " << faceHull << nl
3965 << "Cells: " << cellHull << nl;
3967 Pout<< "Modified cells: " << nl;
3969 forAll(cellHull, cellI)
3971 if (cellHull[cellI] == -1)
3976 Pout<< cellHull[cellI] << ":: "
3977 << cells_[cellHull[cellI]]
3981 Pout<< nl << "Added cells: " << nl;
3983 forAll(addedCellIndices, cellI)
3985 if (addedCellIndices[cellI] == -1)
3990 Pout<< addedCellIndices[cellI] << ":: "
3991 << cells_[addedCellIndices[cellI]] << nl
3992 << "lengthScale: " << lengthScale_[addedCellIndices[cellI]]
3996 Pout<< nl << "Modified faces: " << nl;
3998 forAll(faceHull, faceI)
4000 Pout<< faceHull[faceI] << ":: "
4001 << faces_[faceHull[faceI]] << ": "
4002 << owner_[faceHull[faceI]] << ": "
4003 << neighbour_[faceHull[faceI]] << " "
4004 << "faceEdges:: " << faceEdges_[faceHull[faceI]]
4008 Pout<< nl << "Added faces: " << nl;
4010 forAll(addedFaceIndices, faceI)
4012 Pout<< addedFaceIndices[faceI] << ":: "
4013 << faces_[addedFaceIndices[faceI]] << ": "
4014 << owner_[addedFaceIndices[faceI]] << ": "
4015 << neighbour_[addedFaceIndices[faceI]] << " "
4016 << "faceEdges:: " << faceEdges_[addedFaceIndices[faceI]]
4020 forAll(addedIntFaceIndices, faceI)
4022 if (addedIntFaceIndices[faceI] == -1)
4027 Pout<< addedIntFaceIndices[faceI] << ":: "
4028 << faces_[addedIntFaceIndices[faceI]] << ": "
4029 << owner_[addedIntFaceIndices[faceI]] << ": "
4030 << neighbour_[addedIntFaceIndices[faceI]] << " "
4031 << "faceEdges:: " << faceEdges_[addedIntFaceIndices[faceI]]
4035 Pout<< nl << "New edge:: " << newEdgeIndex
4036 << ": " << edges_[newEdgeIndex] << nl
4037 << " edgeFaces:: " << edgeFaces_[newEdgeIndex]
4040 Pout<< nl << "Added edges: " << nl;
4042 forAll(addedEdgeIndices, edgeI)
4044 Pout<< addedEdgeIndices[edgeI]
4045 << ":: " << edges_[addedEdgeIndices[edgeI]] << nl
4046 << " edgeFaces:: " << edgeFaces_[addedEdgeIndices[edgeI]]
4050 Pout<< "New Point:: " << newPointIndex << nl
4051 << "pointEdges:: " << pointEdges_[newPointIndex] << nl;
4056 // Write out VTK files after change
4059 labelList newHull(cellHull.size() + addedCellIndices.size(), 0);
4061 // Combine both lists into one.
4064 newHull[i] = cellHull[i];
4067 label start = cellHull.size();
4069 for(label i = start; i < newHull.size(); i++)
4071 newHull[i] = addedCellIndices[i - start];
4074 // Write out VTK files after change
4075 // - Using old-points for convenience in post-processing
4079 + '(' + Foam::name(origEdge[0])
4080 + ',' + Foam::name(origEdge[1]) + ')'
4089 topoChangeFlag_ = true;
4091 // Increment the counter
4094 // Increment the number of modifications
4097 // Specify that the operation was successful
4100 // Return the changeMap
4105 // Method for the trisection of a face in 3D
4106 // - Returns a changeMap with a type specifying:
4107 // 1: Trisection was successful
4108 // -1: Trisection failed since max number of topo-changes was reached.
4109 // -2: Trisection failed since resulting quality would be really bad.
4110 // - AddedPoint is the index of the newly added point.
4111 const changeMap dynamicTopoFvMesh::trisectFace
4118 // Face trisection performs the following operations:
4119 // [1] Add a point at middle of the face
4120 // [2] Remove the face and add three new faces in place.
4121 // [3] Add three cells for each trisected cell (remove the originals).
4122 // [4] Create one internal edge for each trisected cell.
4123 // [5] Create three edges for the trisected face.
4124 // [6] Create three internal faces for each trisected cell.
4125 // Update faceEdges and edgeFaces information.
4127 // Figure out which thread this is...
4128 label tIndex = self(), pIndex = -1;
4130 // Prepare the changeMaps
4131 changeMap map, slaveMap;
4132 bool trisectingSlave = false;
4136 (statistics_[0] > maxModifications_) &&
4137 (maxModifications_ > -1)
4140 // Reached the max allowable topo-changes.
4141 stack(tIndex).clear();
4146 // Sanity check: Is the index legitimate?
4151 "const changeMap dynamicTopoFvMesh::trisectFace\n"
4153 " const label fIndex,\n"
4154 " bool checkOnly,\n"
4158 << " Invalid index: " << fIndex
4159 << abort(FatalError);
4162 if (coupledModification_)
4164 // Is this a locally coupled face (either master or slave)?
4165 if (locallyCoupledEntity(fIndex, true))
4169 // Loop through master/slave maps
4170 // and determine the coupled edge index.
4171 forAll(patchCoupling_, patchI)
4173 if (!patchCoupling_(patchI))
4178 const label faceEnum = coupleMap::FACE;
4179 const coupleMap& cMap = patchCoupling_[patchI].map();
4181 if ((sIndex = cMap.findSlave(faceEnum, fIndex)) > -1)
4183 // Keep this index for master/slave mapping.
4189 // The following bit happens only during the sliver
4190 // exudation process.
4191 if ((sIndex = cMap.findMaster(faceEnum, fIndex)) > -1)
4193 // Keep this index for master/slave mapping.
4196 // Notice that we are trisecting a slave edge.
4197 trisectingSlave = true;
4207 "const changeMap dynamicTopoFvMesh::trisectFace\n"
4209 " const label fIndex,\n"
4210 " bool checkOnly,\n"
4214 << "Coupled maps were improperly specified." << nl
4215 << " Slave index not found for: " << nl
4216 << " Face: " << fIndex << nl
4217 << abort(FatalError);
4222 Pout<< nl << "Trisecting slave face: " << sIndex
4223 << " for master face: " << fIndex << endl;
4226 // Temporarily turn off coupledModification.
4227 unsetCoupledModification();
4229 // First check the slave for trisection feasibility.
4230 slaveMap = trisectFace(sIndex, true, forceOp);
4232 if (slaveMap.type() == 1)
4234 // Can the master be trisected as well?
4235 changeMap masterMap = trisectFace(fIndex, true, forceOp);
4237 // Master couldn't perform trisection
4238 if (masterMap.type() != 1)
4240 setCoupledModification();
4245 // Trisect the slave face
4246 slaveMap = trisectFace(sIndex, false, forceOp);
4248 // The final operation has to succeed.
4249 if (slaveMap.type() <= 0)
4253 "const changeMap dynamicTopoFvMesh::trisectFace\n"
4255 " const label fIndex,\n"
4256 " bool checkOnly,\n"
4260 << "Coupled topo-change for slave failed." << nl
4261 << " Type: " << slaveMap.type()
4262 << abort(FatalError);
4267 // Slave couldn't perform trisection.
4268 setCoupledModification();
4276 setCoupledModification();
4279 if (processorCoupledEntity(fIndex))
4281 // Trisect face on the patchSubMesh.
4286 // Before we trisect this face, check whether the operation will
4287 // yield an acceptable cell-quality.
4290 if ((minQ = computeTrisectionQuality(fIndex)) < sliverThreshold_)
4292 // Check if the quality is actually valid before forcing it.
4293 if (forceOp && (minQ < 0.0))
4297 "const changeMap dynamicTopoFvMesh::trisectFace\n"
4299 " const label fIndex,\n"
4300 " bool checkOnly,\n"
4304 << " Forcing trisection on face: " << fIndex
4305 << " will yield an invalid cell."
4306 << abort(FatalError);
4316 // Are we performing only checks?
4323 // Update number of surface bisections, if necessary.
4324 if (whichPatch(fIndex) > -1)
4331 labelList newTriEdgeFaces(3);
4332 labelList newQuadEdgeFaces(4);
4334 FixedList<label,2> apexPoint(-1);
4335 FixedList<face, 3> checkFace(face(3));
4336 FixedList<label,5> newEdgeIndex(-1);
4337 FixedList<label,9> newFaceIndex(-1);
4338 FixedList<label,6> newCellIndex(-1);
4339 FixedList<cell, 6> newTetCell(cell(4));
4340 FixedList<labelList, 9> newFaceEdges(labelList(3));
4342 // Counters for entities
4343 FixedList<label, 9> nE(0);
4344 FixedList<label, 6> nF(0);
4346 // Determine the two cells to be removed
4347 FixedList<label,2> cellsForRemoval;
4348 cellsForRemoval[0] = owner_[fIndex];
4349 cellsForRemoval[1] = neighbour_[fIndex];
4354 << "Face: " << fIndex
4355 << ": " << faces_[fIndex]
4356 << " is to be trisected. " << endl;
4358 // Write out VTK files prior to change
4363 if (neighbour_[fIndex] == -1)
4365 vtkCells.setSize(1);
4366 vtkCells[0] = owner_[fIndex];
4370 vtkCells.setSize(2);
4371 vtkCells[0] = owner_[fIndex];
4372 vtkCells[1] = neighbour_[fIndex];
4384 labelList mP(3, -1);
4386 // Fill in mapping information
4387 mP[0] = faces_[fIndex][0];
4388 mP[1] = faces_[fIndex][1];
4389 mP[2] = faces_[fIndex][2];
4391 // Add a new point to the end of the list
4392 scalar oT = (1.0/3.0);
4394 label newPointIndex =
4398 oT * (points_[mP[0]] + points_[mP[1]] + points_[mP[2]]),
4399 oT * (oldPoints_[mP[0]] + oldPoints_[mP[1]] + oldPoints_[mP[2]]),
4404 // Add this point to the map.
4405 map.addPoint(newPointIndex);
4407 // Add three new cells to the end of the cell list
4408 for (label i = 0; i < 3; i++)
4410 scalar parentScale = -1.0;
4412 if (edgeRefinement_)
4414 parentScale = lengthScale_[cellsForRemoval[0]];
4417 newCellIndex[i] = insertCell(newTetCell[i], parentScale);
4419 // Add cells to the map
4420 map.addCell(newCellIndex[i]);
4423 // Find the apex point for this cell
4426 meshOps::tetApexPoint
4435 // Insert three new internal faces
4437 // First face: Owner: newCellIndex[0], Neighbour: newCellIndex[1]
4438 tmpTriFace[0] = newPointIndex;
4439 tmpTriFace[1] = faces_[fIndex][0];
4440 tmpTriFace[2] = apexPoint[0];
4453 // Second face: Owner: newCellIndex[1], Neighbour: newCellIndex[2]
4454 tmpTriFace[0] = newPointIndex;
4455 tmpTriFace[1] = faces_[fIndex][1];
4456 tmpTriFace[2] = apexPoint[0];
4469 // Third face: Owner: newCellIndex[0], Neighbour: newCellIndex[2]
4470 tmpTriFace[0] = newPointIndex;
4471 tmpTriFace[1] = apexPoint[0];
4472 tmpTriFace[2] = faces_[fIndex][2];
4485 // Add an entry to edgeFaces
4486 newTriEdgeFaces[0] = newFaceIndex[0];
4487 newTriEdgeFaces[1] = newFaceIndex[1];
4488 newTriEdgeFaces[2] = newFaceIndex[2];
4490 // Add a new internal edge to the mesh
4505 // Configure faceEdges with the new internal edge
4506 newFaceEdges[0][nE[0]++] = newEdgeIndex[0];
4507 newFaceEdges[1][nE[1]++] = newEdgeIndex[0];
4508 newFaceEdges[2][nE[2]++] = newEdgeIndex[0];
4510 // Add the newly created faces to cells
4511 newTetCell[0][nF[0]++] = newFaceIndex[0];
4512 newTetCell[0][nF[0]++] = newFaceIndex[2];
4513 newTetCell[1][nF[1]++] = newFaceIndex[0];
4514 newTetCell[1][nF[1]++] = newFaceIndex[1];
4515 newTetCell[2][nF[2]++] = newFaceIndex[1];
4516 newTetCell[2][nF[2]++] = newFaceIndex[2];
4518 // Define the three faces to check for orientation:
4519 checkFace[0][0] = faces_[fIndex][2];
4520 checkFace[0][1] = apexPoint[0];
4521 checkFace[0][2] = faces_[fIndex][0];
4523 checkFace[1][0] = faces_[fIndex][0];
4524 checkFace[1][1] = apexPoint[0];
4525 checkFace[1][2] = faces_[fIndex][1];
4527 checkFace[2][0] = faces_[fIndex][1];
4528 checkFace[2][1] = apexPoint[0];
4529 checkFace[2][2] = faces_[fIndex][2];
4531 // Check the orientation of faces on the first cell.
4532 forAll(cells_[owner_[fIndex]], faceI)
4534 label faceIndex = cells_[owner_[fIndex]][faceI];
4536 if (faceIndex == fIndex)
4541 const face& faceToCheck = faces_[faceIndex];
4542 label cellIndex = cellsForRemoval[0];
4543 label newIndex = -1;
4545 // Check against faces.
4546 if (triFace::compare(triFace(faceToCheck), triFace(checkFace[0])))
4548 newIndex = newCellIndex[0];
4549 newTetCell[0][nF[0]++] = faceIndex;
4552 if (triFace::compare(triFace(faceToCheck), triFace(checkFace[1])))
4554 newIndex = newCellIndex[1];
4555 newTetCell[1][nF[1]++] = faceIndex;
4558 if (triFace::compare(triFace(faceToCheck), triFace(checkFace[2])))
4560 newIndex = newCellIndex[2];
4561 newTetCell[2][nF[2]++] = faceIndex;
4565 // Something's terribly wrong.
4568 "const changeMap dynamicTopoFvMesh::trisectFace\n"
4570 " const label fIndex,\n"
4571 " bool checkOnly,\n"
4575 << "Failed to determine a face match."
4576 << abort(FatalError);
4579 // Check if a face-flip is necessary
4580 if (owner_[faceIndex] == cellIndex)
4582 if (neighbour_[faceIndex] == -1)
4585 owner_[faceIndex] = newIndex;
4590 faces_[faceIndex] = faceToCheck.reverseFace();
4591 owner_[faceIndex] = neighbour_[faceIndex];
4592 neighbour_[faceIndex] = newIndex;
4599 // Flip is unnecessary. Just update neighbour
4600 neighbour_[faceIndex] = newIndex;
4604 if (cellsForRemoval[1] == -1)
4606 // Boundary face. Determine its patch.
4607 label facePatch = whichPatch(fIndex);
4609 // Add three new boundary faces.
4611 // Fourth face: Owner: newCellIndex[0], Neighbour: -1
4612 tmpTriFace[0] = newPointIndex;
4613 tmpTriFace[1] = faces_[fIndex][2];
4614 tmpTriFace[2] = faces_[fIndex][0];
4627 // Fifth face: Owner: newCellIndex[1], Neighbour: -1
4628 tmpTriFace[0] = newPointIndex;
4629 tmpTriFace[1] = faces_[fIndex][0];
4630 tmpTriFace[2] = faces_[fIndex][1];
4643 // Sixth face: Owner: newCellIndex[2], Neighbour: -1
4644 tmpTriFace[0] = newPointIndex;
4645 tmpTriFace[1] = faces_[fIndex][1];
4646 tmpTriFace[2] = faces_[fIndex][2];
4659 // Add the newly created faces to cells
4660 newTetCell[0][nF[0]++] = newFaceIndex[3];
4661 newTetCell[1][nF[1]++] = newFaceIndex[4];
4662 newTetCell[2][nF[2]++] = newFaceIndex[5];
4664 // Configure edgeFaces for three new boundary edges.
4665 newTriEdgeFaces[0] = newFaceIndex[4];
4666 newTriEdgeFaces[1] = newFaceIndex[0];
4667 newTriEdgeFaces[2] = newFaceIndex[3];
4683 newTriEdgeFaces[0] = newFaceIndex[5];
4684 newTriEdgeFaces[1] = newFaceIndex[1];
4685 newTriEdgeFaces[2] = newFaceIndex[4];
4701 newTriEdgeFaces[0] = newFaceIndex[3];
4702 newTriEdgeFaces[1] = newFaceIndex[2];
4703 newTriEdgeFaces[2] = newFaceIndex[5];
4719 // Configure faceEdges with the three new edges.
4720 newFaceEdges[0][nE[0]++] = newEdgeIndex[1];
4721 newFaceEdges[1][nE[1]++] = newEdgeIndex[2];
4722 newFaceEdges[2][nE[2]++] = newEdgeIndex[3];
4724 newFaceEdges[3][nE[3]++] = newEdgeIndex[1];
4725 newFaceEdges[3][nE[3]++] = newEdgeIndex[3];
4726 newFaceEdges[4][nE[4]++] = newEdgeIndex[1];
4727 newFaceEdges[4][nE[4]++] = newEdgeIndex[2];
4728 newFaceEdges[5][nE[5]++] = newEdgeIndex[2];
4729 newFaceEdges[5][nE[5]++] = newEdgeIndex[3];
4731 // Define the six edges to check while building faceEdges:
4732 FixedList<edge,6> check;
4734 check[0][0] = apexPoint[0]; check[0][1] = faces_[fIndex][0];
4735 check[1][0] = apexPoint[0]; check[1][1] = faces_[fIndex][1];
4736 check[2][0] = apexPoint[0]; check[2][1] = faces_[fIndex][2];
4738 check[3][0] = faces_[fIndex][2]; check[3][1] = faces_[fIndex][0];
4739 check[4][0] = faces_[fIndex][0]; check[4][1] = faces_[fIndex][1];
4740 check[5][0] = faces_[fIndex][1]; check[5][1] = faces_[fIndex][2];
4742 // Build a list of cellEdges
4743 DynamicList<label> cellEdges(6);
4745 forAll(cells_[owner_[fIndex]], faceI)
4747 const labelList& fEdges =
4749 faceEdges_[cells_[owner_[fIndex]][faceI]]
4752 forAll(fEdges, edgeI)
4754 if (findIndex(cellEdges, fEdges[edgeI]) == -1)
4756 cellEdges.append(fEdges[edgeI]);
4761 // Loop through cellEdges, and perform appropriate actions.
4762 forAll(cellEdges, edgeI)
4764 const label ceIndex = cellEdges[edgeI];
4765 const edge& edgeToCheck = edges_[ceIndex];
4767 // Check against the specified edges.
4768 if (edgeToCheck == check[0])
4770 meshOps::sizeUpList(newFaceIndex[0], edgeFaces_[ceIndex]);
4771 newFaceEdges[0][nE[0]++] = ceIndex;
4774 if (edgeToCheck == check[1])
4776 meshOps::sizeUpList(newFaceIndex[1], edgeFaces_[ceIndex]);
4777 newFaceEdges[1][nE[1]++] = ceIndex;
4780 if (edgeToCheck == check[2])
4782 meshOps::sizeUpList(newFaceIndex[2], edgeFaces_[ceIndex]);
4783 newFaceEdges[2][nE[2]++] = ceIndex;
4786 if (edgeToCheck == check[3])
4788 meshOps::replaceLabel
4795 newFaceEdges[3][nE[3]++] = ceIndex;
4798 if (edgeToCheck == check[4])
4800 meshOps::replaceLabel
4807 newFaceEdges[4][nE[4]++] = ceIndex;
4810 if (edgeToCheck == check[5])
4812 meshOps::replaceLabel
4819 newFaceEdges[5][nE[5]++] = ceIndex;
4823 // Now that faceEdges has been configured, append them to the list.
4824 for (label i = 0; i < 6; i++)
4826 faceEdges_.append(newFaceEdges[i]);
4828 // Add faces to the map.
4829 map.addFace(newFaceIndex[i]);
4832 // If modification is coupled, generate mapping info.
4833 if (coupledModification_)
4835 // Create a master/slave entry for the new edges/faces on the patch.
4836 if (locallyCoupledEntity(fIndex, true))
4838 if (patchCoupling_(pIndex))
4840 // Add the new point to the coupling map
4841 const coupleMap& cMap = patchCoupling_[pIndex].map();
4843 if (trisectingSlave)
4849 slaveMap.addedPointList()[0].index()
4855 slaveMap.addedPointList()[0].index(),
4865 slaveMap.addedPointList()[0].index()
4871 slaveMap.addedPointList()[0].index(),
4877 const List<objectMap>& ameList = map.addedEdgeList();
4878 const List<objectMap>& aseList = slaveMap.addedEdgeList();
4880 // Compare with all check entries.
4881 forAll(ameList, meI)
4883 label epIndex = whichEdgePatch(ameList[meI].index());
4885 if (epIndex != pIndex && !trisectingSlave)
4890 if (patchCoupling_(pIndex))
4892 const coupleMap& cM = patchCoupling_[pIndex].map();
4894 if (trisectingSlave && epIndex != cM.slaveIndex())
4904 const coupleMap& cMap = patchCoupling_[pIndex].map();
4906 // Configure an edge for comparison.
4909 const edge& mE = edges_[ameList[meI].index()];
4911 if (trisectingSlave)
4913 cE[0] = cMap.reverseEntityMap(coupleMap::POINT)[mE[0]];
4914 cE[1] = cMap.reverseEntityMap(coupleMap::POINT)[mE[1]];
4918 cE[0] = cMap.entityMap(coupleMap::POINT)[mE[0]];
4919 cE[1] = cMap.entityMap(coupleMap::POINT)[mE[1]];
4922 bool matched = false;
4924 forAll(aseList, seI)
4926 const edge& sE = edges_[aseList[seI].index()];
4930 if (trisectingSlave)
4935 ameList[meI].index(),
4936 aseList[seI].index()
4942 aseList[seI].index(),
4943 ameList[meI].index()
4951 ameList[meI].index(),
4952 aseList[seI].index()
4958 aseList[seI].index(),
4959 ameList[meI].index()
4971 Pout<< "masterEdges: " << nl
4974 Pout<< "slaveEdges: " << nl
4977 forAll(ameList, meI)
4979 Pout<< ameList[meI].index() << ": "
4980 << edges_[ameList[meI].index()]
4984 forAll(aseList, seI)
4986 Pout<< aseList[seI].index() << ": "
4987 << edges_[aseList[seI].index()]
4993 "const changeMap dynamicTopoFvMesh::trisectFace\n"
4995 " const label fIndex,\n"
4996 " bool checkOnly,\n"
5000 << "Failed to build coupled edge maps."
5001 << abort(FatalError);
5005 // Add a mapping entry for three new faces as well.
5008 const List<objectMap>& amfList = map.addedFaceList();
5009 const List<objectMap>& asfList = slaveMap.addedFaceList();
5011 forAll(amfList, mfI)
5013 label fpIndex = whichPatch(amfList[mfI].index());
5015 if (fpIndex != pIndex && !trisectingSlave)
5020 if (patchCoupling_(pIndex))
5022 const coupleMap& cM = patchCoupling_[pIndex].map();
5024 if (trisectingSlave && fpIndex != cM.slaveIndex())
5034 const coupleMap& cMap = patchCoupling_[pIndex].map();
5036 // Configure a face for comparison.
5037 const face& mF = faces_[amfList[mfI].index()];
5041 if (trisectingSlave)
5045 cMap.reverseEntityMap(coupleMap::POINT)[mF[pI]]
5052 cMap.entityMap(coupleMap::POINT)[mF[pI]]
5057 bool matched = false;
5059 forAll(asfList, sfI)
5061 const face& sF = faces_[asfList[sfI].index()];
5063 if (triFace::compare(triFace(cF), triFace(sF)))
5065 if (trisectingSlave)
5070 amfList[mfI].index(),
5071 asfList[sfI].index()
5077 asfList[sfI].index(),
5078 amfList[mfI].index()
5086 amfList[mfI].index(),
5087 asfList[sfI].index()
5093 asfList[sfI].index(),
5094 amfList[mfI].index()
5106 Pout<< "masterFaces: " << nl
5109 Pout<< "slaveFaces: " << nl
5112 forAll(amfList, mfI)
5114 Pout<< amfList[mfI].index() << ": "
5115 << faces_[amfList[mfI].index()]
5119 forAll(asfList, sfI)
5121 Pout<< asfList[sfI].index() << ": "
5122 << faces_[asfList[sfI].index()]
5128 "const changeMap dynamicTopoFvMesh::trisectFace\n"
5130 " const label fIndex,\n"
5131 " bool checkOnly,\n"
5135 << "Failed to build coupled face maps."
5136 << abort(FatalError);
5141 if (processorCoupledEntity(fIndex))
5143 // Look for matching slave edges on the patchSubMesh.
5150 // Add three new cells to the end of the cell list
5151 for (label i = 3; i < 6; i++)
5153 scalar parentScale = -1.0;
5155 if (edgeRefinement_)
5157 parentScale = lengthScale_[cellsForRemoval[1]];
5160 newCellIndex[i] = insertCell(newTetCell[i], parentScale);
5163 map.addCell(newCellIndex[i]);
5166 // Find the apex point for this cell
5169 meshOps::tetApexPoint
5178 // Add six new interior faces.
5180 // Fourth face: Owner: newCellIndex[0], Neighbour: newCellIndex[3]
5181 tmpTriFace[0] = newPointIndex;
5182 tmpTriFace[1] = faces_[fIndex][2];
5183 tmpTriFace[2] = faces_[fIndex][0];
5196 // Fifth face: Owner: newCellIndex[1], Neighbour: newCellIndex[4]
5197 tmpTriFace[0] = newPointIndex;
5198 tmpTriFace[1] = faces_[fIndex][0];
5199 tmpTriFace[2] = faces_[fIndex][1];
5212 // Sixth face: Owner: newCellIndex[2], Neighbour: newCellIndex[5]
5213 tmpTriFace[0] = newPointIndex;
5214 tmpTriFace[1] = faces_[fIndex][1];
5215 tmpTriFace[2] = faces_[fIndex][2];
5228 // Seventh face: Owner: newCellIndex[3], Neighbour: newCellIndex[4]
5229 tmpTriFace[0] = newPointIndex;
5230 tmpTriFace[1] = apexPoint[1];
5231 tmpTriFace[2] = faces_[fIndex][0];
5244 // Eighth face: Owner: newCellIndex[4], Neighbour: newCellIndex[5]
5245 tmpTriFace[0] = newPointIndex;
5246 tmpTriFace[1] = apexPoint[1];
5247 tmpTriFace[2] = faces_[fIndex][1];
5260 // Ninth face: Owner: newCellIndex[3], Neighbour: newCellIndex[5]
5261 tmpTriFace[0] = newPointIndex;
5262 tmpTriFace[1] = faces_[fIndex][2];
5263 tmpTriFace[2] = apexPoint[1];
5276 // Add the newly created faces to cells
5277 newTetCell[3][nF[3]++] = newFaceIndex[6];
5278 newTetCell[3][nF[3]++] = newFaceIndex[8];
5279 newTetCell[4][nF[4]++] = newFaceIndex[6];
5280 newTetCell[4][nF[4]++] = newFaceIndex[7];
5281 newTetCell[5][nF[5]++] = newFaceIndex[7];
5282 newTetCell[5][nF[5]++] = newFaceIndex[8];
5284 newTetCell[0][nF[0]++] = newFaceIndex[3];
5285 newTetCell[1][nF[1]++] = newFaceIndex[4];
5286 newTetCell[2][nF[2]++] = newFaceIndex[5];
5288 newTetCell[3][nF[3]++] = newFaceIndex[3];
5289 newTetCell[4][nF[4]++] = newFaceIndex[4];
5290 newTetCell[5][nF[5]++] = newFaceIndex[5];
5292 // Define the three faces to check for orientation:
5293 checkFace[0][0] = faces_[fIndex][2];
5294 checkFace[0][1] = apexPoint[1];
5295 checkFace[0][2] = faces_[fIndex][0];
5297 checkFace[1][0] = faces_[fIndex][0];
5298 checkFace[1][1] = apexPoint[1];
5299 checkFace[1][2] = faces_[fIndex][1];
5301 checkFace[2][0] = faces_[fIndex][1];
5302 checkFace[2][1] = apexPoint[1];
5303 checkFace[2][2] = faces_[fIndex][2];
5305 // Check the orientation of faces on the second cell.
5306 forAll(cells_[neighbour_[fIndex]], faceI)
5308 label faceIndex = cells_[neighbour_[fIndex]][faceI];
5310 if (faceIndex == fIndex)
5315 const face& faceToCheck = faces_[faceIndex];
5316 label cellIndex = cellsForRemoval[1];
5317 label newIndex = -1;
5319 // Check against faces.
5320 if (triFace::compare(triFace(faceToCheck), triFace(checkFace[0])))
5322 newIndex = newCellIndex[3];
5323 newTetCell[3][nF[3]++] = faceIndex;
5326 if (triFace::compare(triFace(faceToCheck), triFace(checkFace[1])))
5328 newIndex = newCellIndex[4];
5329 newTetCell[4][nF[4]++] = faceIndex;
5332 if (triFace::compare(triFace(faceToCheck), triFace(checkFace[2])))
5334 newIndex = newCellIndex[5];
5335 newTetCell[5][nF[5]++] = faceIndex;
5339 // Something's terribly wrong.
5342 "const changeMap dynamicTopoFvMesh::trisectFace\n"
5344 " const label fIndex,\n"
5345 " bool checkOnly,\n"
5349 << "Failed to determine a face match."
5350 << abort(FatalError);
5353 // Check if a face-flip is necessary
5354 if (owner_[faceIndex] == cellIndex)
5356 if (neighbour_[faceIndex] == -1)
5359 owner_[faceIndex] = newIndex;
5364 faces_[faceIndex] = faceToCheck.reverseFace();
5365 owner_[faceIndex] = neighbour_[faceIndex];
5366 neighbour_[faceIndex] = newIndex;
5373 // Flip is unnecessary. Just update neighbour
5374 neighbour_[faceIndex] = newIndex;
5378 // Configure edgeFaces for four new interior edges.
5379 newQuadEdgeFaces[0] = newFaceIndex[4];
5380 newQuadEdgeFaces[1] = newFaceIndex[0];
5381 newQuadEdgeFaces[2] = newFaceIndex[3];
5382 newQuadEdgeFaces[3] = newFaceIndex[6];
5398 newQuadEdgeFaces[0] = newFaceIndex[5];
5399 newQuadEdgeFaces[1] = newFaceIndex[1];
5400 newQuadEdgeFaces[2] = newFaceIndex[4];
5401 newQuadEdgeFaces[3] = newFaceIndex[7];
5417 newQuadEdgeFaces[0] = newFaceIndex[3];
5418 newQuadEdgeFaces[1] = newFaceIndex[2];
5419 newQuadEdgeFaces[2] = newFaceIndex[5];
5420 newQuadEdgeFaces[3] = newFaceIndex[8];
5436 newTriEdgeFaces[0] = newFaceIndex[6];
5437 newTriEdgeFaces[1] = newFaceIndex[7];
5438 newTriEdgeFaces[2] = newFaceIndex[8];
5454 // Configure faceEdges with the new internal edges
5455 newFaceEdges[0][nE[0]++] = newEdgeIndex[1];
5456 newFaceEdges[1][nE[1]++] = newEdgeIndex[2];
5457 newFaceEdges[2][nE[2]++] = newEdgeIndex[3];
5459 newFaceEdges[3][nE[3]++] = newEdgeIndex[1];
5460 newFaceEdges[3][nE[3]++] = newEdgeIndex[3];
5461 newFaceEdges[4][nE[4]++] = newEdgeIndex[1];
5462 newFaceEdges[4][nE[4]++] = newEdgeIndex[2];
5463 newFaceEdges[5][nE[5]++] = newEdgeIndex[2];
5464 newFaceEdges[5][nE[5]++] = newEdgeIndex[3];
5466 newFaceEdges[6][nE[6]++] = newEdgeIndex[1];
5467 newFaceEdges[7][nE[7]++] = newEdgeIndex[2];
5468 newFaceEdges[8][nE[8]++] = newEdgeIndex[3];
5470 newFaceEdges[6][nE[6]++] = newEdgeIndex[4];
5471 newFaceEdges[7][nE[7]++] = newEdgeIndex[4];
5472 newFaceEdges[8][nE[8]++] = newEdgeIndex[4];
5474 // Define the nine edges to check while building faceEdges:
5475 FixedList<edge,9> check;
5477 check[0][0] = apexPoint[0]; check[0][1] = faces_[fIndex][0];
5478 check[1][0] = apexPoint[0]; check[1][1] = faces_[fIndex][1];
5479 check[2][0] = apexPoint[0]; check[2][1] = faces_[fIndex][2];
5481 check[3][0] = faces_[fIndex][2]; check[3][1] = faces_[fIndex][0];
5482 check[4][0] = faces_[fIndex][0]; check[4][1] = faces_[fIndex][1];
5483 check[5][0] = faces_[fIndex][1]; check[5][1] = faces_[fIndex][2];
5485 check[6][0] = apexPoint[1]; check[6][1] = faces_[fIndex][0];
5486 check[7][0] = apexPoint[1]; check[7][1] = faces_[fIndex][1];
5487 check[8][0] = apexPoint[1]; check[8][1] = faces_[fIndex][2];
5489 // Build a list of cellEdges
5490 DynamicList<label> cellEdges(12);
5492 forAll(cells_[owner_[fIndex]], faceI)
5494 const labelList& fEdges =
5496 faceEdges_[cells_[owner_[fIndex]][faceI]]
5499 forAll(fEdges, edgeI)
5501 if (findIndex(cellEdges, fEdges[edgeI]) == -1)
5503 cellEdges.append(fEdges[edgeI]);
5508 forAll(cells_[neighbour_[fIndex]], faceI)
5510 const labelList& fEdges =
5512 faceEdges_[cells_[neighbour_[fIndex]][faceI]]
5515 forAll(fEdges, edgeI)
5517 if (findIndex(cellEdges, fEdges[edgeI]) == -1)
5519 cellEdges.append(fEdges[edgeI]);
5524 // Loop through cellEdges, and perform appropriate actions.
5525 forAll(cellEdges, edgeI)
5527 const label ceIndex = cellEdges[edgeI];
5528 const edge& edgeToCheck = edges_[ceIndex];
5530 // Check against the specified edges.
5531 if (edgeToCheck == check[0])
5533 meshOps::sizeUpList(newFaceIndex[0], edgeFaces_[ceIndex]);
5534 newFaceEdges[0][nE[0]++] = ceIndex;
5537 if (edgeToCheck == check[1])
5539 meshOps::sizeUpList(newFaceIndex[1], edgeFaces_[ceIndex]);
5540 newFaceEdges[1][nE[1]++] = ceIndex;
5543 if (edgeToCheck == check[2])
5545 meshOps::sizeUpList(newFaceIndex[2], edgeFaces_[ceIndex]);
5546 newFaceEdges[2][nE[2]++] = ceIndex;
5549 if (edgeToCheck == check[3])
5551 meshOps::replaceLabel
5558 newFaceEdges[3][nE[3]++] = ceIndex;
5561 if (edgeToCheck == check[4])
5563 meshOps::replaceLabel
5570 newFaceEdges[4][nE[4]++] = ceIndex;
5573 if (edgeToCheck == check[5])
5575 meshOps::replaceLabel
5582 newFaceEdges[5][nE[5]++] = ceIndex;
5585 if (edgeToCheck == check[6])
5587 meshOps::sizeUpList(newFaceIndex[6], edgeFaces_[ceIndex]);
5588 newFaceEdges[6][nE[6]++] = ceIndex;
5591 if (edgeToCheck == check[7])
5593 meshOps::sizeUpList(newFaceIndex[7], edgeFaces_[ceIndex]);
5594 newFaceEdges[7][nE[7]++] = ceIndex;
5597 if (edgeToCheck == check[8])
5599 meshOps::sizeUpList(newFaceIndex[8], edgeFaces_[ceIndex]);
5600 newFaceEdges[8][nE[8]++] = ceIndex;
5604 // Now that faceEdges has been configured, append them to the list.
5605 for (label i = 0; i < 9; i++)
5607 faceEdges_.append(newFaceEdges[i]);
5609 // Add faces to the map.
5610 map.addFace(newFaceIndex[i]);
5614 // Added edges are those connected to the new point
5615 const labelList& pointEdges = pointEdges_[newPointIndex];
5617 forAll(pointEdges, edgeI)
5619 map.addEdge(pointEdges[edgeI]);
5622 // Now generate mapping info and remove entities.
5623 forAll(cellsForRemoval, cellI)
5625 label cIndex = cellsForRemoval[cellI];
5632 // Fill-in mapping information
5633 labelList mC(1, cellsForRemoval[cellI]);
5637 for (label i = 0; i < 3; i++)
5639 // Update the cell list with newly configured cells.
5640 cells_[newCellIndex[i]] = newTetCell[i];
5642 setCellMapping(newCellIndex[i], mC);
5647 for (label i = 3; i < 6; i++)
5649 // Update the cell list with newly configured cells.
5650 cells_[newCellIndex[i]] = newTetCell[i];
5652 setCellMapping(newCellIndex[i], mC);
5659 // Set default mapping for interior faces.
5660 for (label i = 0; i < 3; i++)
5662 setFaceMapping(newFaceIndex[i]);
5665 if (cellsForRemoval[1] == -1)
5667 // Set mapping for boundary faces.
5668 for (label i = 3; i < 6; i++)
5670 setFaceMapping(newFaceIndex[i], labelList(1, fIndex));
5675 // Set default mapping for interior faces.
5676 for (label i = 3; i < 9; i++)
5678 setFaceMapping(newFaceIndex[i]);
5682 // Now finally remove the face...
5687 Pout<< "New Point:: " << newPointIndex << endl;
5689 const labelList& pEdges = pointEdges_[newPointIndex];
5691 Pout<< "pointEdges:: " << pEdges << endl;
5693 Pout<< "Added edges: " << endl;
5695 forAll(pEdges, edgeI)
5697 Pout<< pEdges[edgeI]
5698 << ":: " << edges_[pEdges[edgeI]] << nl
5699 << " edgeFaces:: " << edgeFaces_[pEdges[edgeI]] << nl
5703 Pout<< "Added faces: " << endl;
5705 forAll(newFaceIndex, faceI)
5707 if (newFaceIndex[faceI] == -1)
5712 Pout<< newFaceIndex[faceI] << ":: "
5713 << faces_[newFaceIndex[faceI]]
5717 Pout<< "Added cells: " << endl;
5719 forAll(newCellIndex, cellI)
5721 if (newCellIndex[cellI] == -1)
5726 Pout<< newCellIndex[cellI] << ":: "
5727 << cells_[newCellIndex[cellI]]
5731 // Write out VTK files after change
5736 if (cellsForRemoval[1] == -1)
5738 vtkCells.setSize(3);
5740 // Fill in cell indices
5741 vtkCells[0] = newCellIndex[0];
5742 vtkCells[1] = newCellIndex[1];
5743 vtkCells[2] = newCellIndex[2];
5747 vtkCells.setSize(6);
5749 // Fill in cell indices
5750 forAll(newCellIndex, indexI)
5752 vtkCells[indexI] = newCellIndex[indexI];
5766 topoChangeFlag_ = true;
5768 // Increment the counter
5771 // Increment the number of modifications
5774 // Specify that the operation was successful
5777 // Return the changeMap
5782 // Utility method to compute the quality of a
5783 // vertex hull around an edge after bisection.
5784 scalar dynamicTopoFvMesh::computeBisectionQuality
5789 scalar minQuality = GREAT, minVolume = GREAT;
5790 scalar cQuality = 0.0, oldVolume = 0.0;
5792 // Obtain a reference to this edge
5793 const edge& edgeToCheck = edges_[eIndex];
5795 // Obtain point references
5796 const point& a = points_[edgeToCheck[0]];
5797 const point& c = points_[edgeToCheck[1]];
5799 const point& aOld = oldPoints_[edgeToCheck[0]];
5800 const point& cOld = oldPoints_[edgeToCheck[1]];
5802 // Compute the mid-point of the edge
5803 point midPoint = 0.5 * (a + c);
5804 point oldPoint = 0.5 * (aOld + cOld);
5806 DynamicList<label> eCells(10);
5808 const labelList& eFaces = edgeFaces_[eIndex];
5810 // Accumulate cells connected to this edge
5811 forAll(eFaces, faceI)
5813 label own = owner_[eFaces[faceI]];
5814 label nei = neighbour_[eFaces[faceI]];
5816 if (findIndex(eCells, own) == -1)
5826 if (findIndex(eCells, nei) == -1)
5832 // Loop through all cells and compute quality
5833 forAll(eCells, cellI)
5835 label cellIndex = eCells[cellI];
5837 const cell& checkCell = cells_[cellIndex];
5839 // Find two faces that don't contain the edge
5840 forAll(checkCell, faceI)
5842 const face& checkFace = faces_[checkCell[faceI]];
5846 (findIndex(checkFace, edgeToCheck[0]) == -1) &&
5847 (findIndex(checkFace, edgeToCheck[1]) == -1)
5850 // Check orientation
5851 if (owner_[checkCell[faceI]] == cellIndex)
5857 points_[checkFace[2]],
5858 points_[checkFace[1]],
5859 points_[checkFace[0]],
5868 oldPoints_[checkFace[2]],
5869 oldPoints_[checkFace[1]],
5870 oldPoints_[checkFace[0]],
5881 points_[checkFace[0]],
5882 points_[checkFace[1]],
5883 points_[checkFace[2]],
5892 oldPoints_[checkFace[0]],
5893 oldPoints_[checkFace[1]],
5894 oldPoints_[checkFace[2]],
5900 // Check if the quality is worse
5901 minQuality = Foam::min(cQuality, minQuality);
5902 minVolume = Foam::min(oldVolume, minVolume);
5907 // Ensure that the mesh is valid
5908 if (minQuality < sliverThreshold_)
5910 if (debug > 3 && minQuality < 0.0)
5912 writeVTK(Foam::name(eIndex) + "_iCells", eCells);
5919 "scalar dynamicTopoFvMesh::computeBisectionQuality"
5920 "(const label eIndex) const"
5922 << " Bisecting edge will fall below the"
5923 << " sliver threshold of: " << sliverThreshold_ << nl
5924 << " Edge: " << eIndex << ": " << edgeToCheck << nl
5925 << " Minimum Quality: " << minQuality << nl
5926 << " Minimum Volume: " << minVolume << nl
5927 << " Mid point: " << midPoint << nl
5928 << " Old point: " << oldPoint << nl
5933 // If a negative old-volume was encountered,
5934 // return an invalid quality.
5935 if (minVolume < 0.0)
5944 // Utility method to compute the quality of cells
5945 // around a face after trisection.
5946 scalar dynamicTopoFvMesh::computeTrisectionQuality
5951 scalar minQuality = GREAT;
5952 scalar cQuality = 0.0;
5956 // Fetch the midPoint
5957 midPoint = faces_[fIndex].centre(points_);
5959 FixedList<label,2> apexPoint(-1);
5961 // Find the apex point
5964 meshOps::tetApexPoint
5973 const face& faceToCheck = faces_[fIndex];
5975 forAll(faceToCheck, pointI)
5977 // Pick vertices off the list
5978 const point& b = points_[faceToCheck[pointI]];
5979 const point& c = points_[apexPoint[0]];
5980 const point& d = points_[faceToCheck[faceToCheck.fcIndex(pointI)]];
5982 // Compute the quality of the upper half.
5983 cQuality = tetMetric_(midPoint, b, c, d);
5985 // Check if the quality is worse
5986 minQuality = Foam::min(cQuality, minQuality);
5989 if (whichPatch(fIndex) == -1)
5993 meshOps::tetApexPoint
6002 forAll(faceToCheck, pointI)
6004 // Pick vertices off the list
6005 const point& b = points_[faceToCheck[pointI]];
6006 const point& c = points_[apexPoint[1]];
6007 const point& d = points_[faceToCheck[faceToCheck.rcIndex(pointI)]];
6009 // Compute the quality of the upper half.
6010 cQuality = tetMetric_(midPoint, b, c, d);
6012 // Check if the quality is worse
6013 minQuality = Foam::min(cQuality, minQuality);
6021 // Slice the mesh at a particular location
6022 void dynamicTopoFvMesh::sliceMesh
6024 const labelPair& pointPair
6030 << "Pair: " << pointPair
6031 << " is to be used for mesh slicing. " << endl;
6034 label patchIndex = -1;
6036 vector gCentre = vector::zero;
6037 FixedList<vector, 2> fC(vector::zero);
6041 patchIndex = whichPatch(pointPair.first());
6043 // Fetch face centres
6044 fC[0] = faces_[pointPair.first()].centre(points_);
6045 fC[1] = faces_[pointPair.second()].centre(points_);
6049 // Find the patch that the edge-vertex is connected to.
6050 const labelList& pEdges = pointEdges_[pointPair.first()];
6052 forAll(pEdges, edgeI)
6054 if ((patchIndex = whichEdgePatch(pEdges[edgeI])) > -1)
6060 fC[0] = points_[pointPair.first()];
6061 fC[1] = points_[pointPair.second()];
6064 linePointRef lpr(fC[0], fC[1]);
6066 // Specify the centre.
6067 gCentre = lpr.centre();
6069 // Specify a search distance
6072 // Is this edge in the vicinity of a previous slice-point?
6073 if (lengthEstimator().checkOldSlices(gCentre))
6078 << "Pair: " << pointPair
6079 << " is too close to another slice point. "
6083 // Too close to another slice-point. Bail out.
6087 // Choose a box around the centre and scan all
6088 // surface entities that fall into this region.
6091 gCentre - vector(dx, dx, dx),
6092 gCentre + vector(dx, dx, dx)
6095 vector p = vector::zero, N = vector::zero;
6096 Map<vector> checkPoints, surfFaces;
6097 Map<edge> checkEdges;
6101 // Assign plane point / normal
6104 vector gNorm = faces_[pointPair.first()].normal(points_);
6106 gNorm /= (mag(gNorm) + VSMALL);
6108 // Since this is 2D, assume XY-plane here.
6109 N = (gNorm ^ vector(0.0, 0.0, 1.0));
6113 // Prepare surface points / edges for Dijkstra's algorithm
6114 for (label edgeI = nOldInternalEdges_; edgeI < nEdges_; edgeI++)
6116 if (edgeFaces_[edgeI].empty())
6121 if (whichEdgePatch(edgeI) == patchIndex)
6123 const edge& surfaceEdge = edges_[edgeI];
6127 (bBox.contains(points_[surfaceEdge[0]])) &&
6128 (bBox.contains(points_[surfaceEdge[1]]))
6131 checkEdges.insert(edgeI, surfaceEdge);
6133 if (!checkPoints.found(surfaceEdge[0]))
6138 points_[surfaceEdge[0]]
6142 if (!checkPoints.found(surfaceEdge[1]))
6147 points_[surfaceEdge[1]]
6151 // Add surface faces as well.
6152 const labelList& eFaces = edgeFaces_[edgeI];
6154 forAll(eFaces, faceI)
6158 (neighbour_[eFaces[faceI]] == -1) &&
6159 (!surfFaces.found(eFaces[faceI]))
6164 faces_[eFaces[faceI]].normal(points_)
6167 surfFaces.insert(eFaces[faceI], surfNorm);
6177 << " Point [0]: " << points_[pointPair.first()] << nl
6178 << " Point [1]: " << points_[pointPair.second()] << endl;
6182 writeVTK("slicePoints", checkPoints.toc(), 0);
6183 writeVTK("sliceEdges", checkEdges.toc(), 1);
6187 // Find the shortest path using Dijkstra's algorithm.
6188 Map<label> shortestPath;
6202 // First normalize all face-normals
6203 forAllIter(Map<vector>, surfFaces, sIter)
6205 sIter() /= (mag(sIter()) + VSMALL);
6210 // Next, take cross-products with every other
6211 // vector in the list, and accumulate.
6212 forAllIter(Map<vector>, surfFaces, sIterI)
6214 forAllIter(Map<vector>, surfFaces, sIterJ)
6216 if (sIterI.key() != sIterJ.key())
6218 vector n = (sIterI() ^ sIterJ());
6220 n /= (mag(n) + VSMALL);
6222 // Reverse the vector if necessary
6233 N /= (mag(N) + VSMALL);
6235 // Obtain point position
6240 // Probably a membrane-type configuration.
6241 labelHashSet checkCells;
6243 // Prepare a bounding cylinder with radius dx.
6244 forAllIter(Map<vector>, surfFaces, sIter)
6246 const face& thisFace = faces_[sIter.key()];
6248 if (thisFace.which(pointPair.first()) > -1)
6254 // Normalize and reverse.
6255 N /= -(mag(N) + VSMALL);
6257 vector a0 = points_[pointPair.first()];
6258 vector a1 = points_[pointPair.second()];
6259 scalar dist = mag(a1 - a0);
6261 forAll(cells_, cellI)
6263 if (cells_[cellI].empty())
6269 vector x = vector::zero;
6271 meshOps::cellCentreAndVolume
6282 vector rx = (x - a0);
6283 vector ra = (rx & N)*N;
6285 // Check if point falls off cylinder ends.
6286 if (mag(ra) > dist || mag(ra) < 0.0)
6291 vector r = (rx - ra);
6293 // Check if the magnitude of 'r' is within radius.
6296 checkCells.insert(cellI);
6300 labelList cList = checkCells.toc();
6304 Pout<< "Dijkstra's algorithm could not find a path." << endl;
6308 writeVTK("checkCells", cList, 3);
6312 changeMap sliceMap =
6319 + Foam::name(pointPair.first()) + '_'
6320 + Foam::name(pointPair.second())
6326 checkConnectivity(10);
6329 // Accumulate a list of projection points
6330 labelHashSet pPoints;
6332 const List<objectMap>& afList = sliceMap.addedFaceList();
6334 forAll(afList, faceI)
6336 const face& thisFace = faces_[afList[faceI].index()];
6338 forAll(thisFace, pointI)
6340 if (!pPoints.found(thisFace[pointI]))
6342 pPoints.insert(thisFace[pointI]);
6347 // Now project points in a series of intermediate steps.
6349 // Add an entry to sliceBoxes.
6350 lengthEstimator().appendBox(bBox);
6359 << " Plane point: " << p << nl
6360 << " Plane normal: " << N << endl;
6363 // Mark cells and interior faces that fall
6364 // within the bounding box.
6365 labelHashSet checkCells, checkFaces, splitFaces;
6366 Map<bool> cellColors;
6368 forAll(faces_, faceI)
6370 if (faces_[faceI].empty())
6375 if (twoDMesh_ && faces_[faceI].size() == 3)
6380 vector fCentre = faces_[faceI].centre(points_);
6382 FixedList<label, 2> cellsToCheck(-1);
6383 cellsToCheck[0] = owner_[faceI];
6384 cellsToCheck[1] = neighbour_[faceI];
6386 if (bBox.contains(fCentre) && cellsToCheck[1] != -1)
6388 // Add this internal face to the list.
6389 checkFaces.insert(faceI);
6391 scalar volume = 0.0;
6392 vector centre = vector::zero;
6394 forAll(cellsToCheck, cellI)
6396 if (!checkCells.found(cellsToCheck[cellI]))
6398 meshOps::cellCentreAndVolume
6400 cellsToCheck[cellI],
6409 checkCells.insert(cellsToCheck[cellI]);
6411 if (((centre - p) & N) > 0.0)
6413 cellColors.insert(cellsToCheck[cellI], true);
6417 cellColors.insert(cellsToCheck[cellI], false);
6424 // Prepare a list of internal faces for mesh splitting.
6425 forAllIter(labelHashSet, checkFaces, fIter)
6429 cellColors[owner_[fIter.key()]]
6430 != cellColors[neighbour_[fIter.key()]]
6433 splitFaces.insert(fIter.key());
6436 // Loop through all points (and associated pointEdges)
6437 // for this face, and check if connected cells are also
6438 // present in the checkCells/cellColors list
6441 const labelList& fEdges = faceEdges_[fIter.key()];
6443 forAll(fEdges, edgeI)
6445 const labelList& eFaces = edgeFaces_[fEdges[edgeI]];
6447 forAll(eFaces, faceI)
6449 label own = owner_[eFaces[faceI]];
6450 label nei = neighbour_[eFaces[faceI]];
6452 if (!checkCells.found(own))
6454 scalar volume = 0.0;
6455 vector centre = vector::zero;
6457 meshOps::cellCentreAndVolume
6468 checkCells.insert(own);
6470 if (((centre - p) & N) > 0.0)
6472 cellColors.insert(own, true);
6476 cellColors.insert(own, false);
6480 if (!checkCells.found(nei) && nei != -1)
6482 scalar volume = 0.0;
6483 vector centre = vector::zero;
6485 meshOps::cellCentreAndVolume
6496 checkCells.insert(nei);
6498 if (((centre - p) & N) > 0.0)
6500 cellColors.insert(nei, true);
6504 cellColors.insert(nei, false);
6512 const face& faceToCheck = faces_[fIter.key()];
6514 forAll(faceToCheck, pointI)
6516 const labelList& pEdges = pointEdges_[faceToCheck[pointI]];
6518 forAll(pEdges, edgeI)
6520 const labelList& eFaces = edgeFaces_[pEdges[edgeI]];
6522 forAll(eFaces, faceI)
6524 label own = owner_[eFaces[faceI]];
6525 label nei = neighbour_[eFaces[faceI]];
6527 if (!checkCells.found(own))
6529 scalar volume = 0.0;
6530 vector centre = vector::zero;
6532 meshOps::cellCentreAndVolume
6543 checkCells.insert(own);
6545 if (((centre - p) & N) > 0.0)
6547 cellColors.insert(own, true);
6551 cellColors.insert(own, false);
6555 if (!checkCells.found(nei) && nei != -1)
6557 scalar volume = 0.0;
6558 vector centre = vector::zero;
6560 meshOps::cellCentreAndVolume
6571 checkCells.insert(nei);
6573 if (((centre - p) & N) > 0.0)
6575 cellColors.insert(nei, true);
6579 cellColors.insert(nei, false);
6590 writeVTK("splitFaces", splitFaces.toc(), 2);
6591 writeVTK("checkCells", checkCells.toc(), 3);
6594 // Pass this info into the splitInternalFaces routine.
6602 // Add an entry to sliceBoxes.
6603 lengthEstimator().appendBox(bBox);
6607 // Add cell layer above specified patch
6608 const changeMap dynamicTopoFvMesh::addCellLayer
6615 // Maps for added entities
6616 Map<label> addedPoints;
6617 Map<label> addedHEdges, addedVEdges, currentVEdges;
6618 Map<label> addedHFaces, addedVFaces, currentVFaces;
6619 Map<labelPair> addedCells;
6621 // Allocate a list of patch faces
6622 DynamicList<label> patchFaces(patchSizes_[patchID]);
6624 // Loop through all patch faces and create a cell for each
6625 for (label faceI = nOldInternalFaces_; faceI < faces_.size(); faceI++)
6627 label pIndex = whichPatch(faceI);
6629 if (pIndex != patchID)
6634 // Add face to the list
6635 patchFaces.append(faceI);
6638 label cIndex = owner_[faceI];
6639 scalar newLengthScale = -1.0;
6640 const cell& ownCell = cells_[cIndex];
6642 if (edgeRefinement_)
6644 newLengthScale = lengthScale_[cIndex];
6647 label newCellIndex =
6651 cell(ownCell.size()),
6657 map.addCell(newCellIndex, labelList(1, cIndex));
6658 addedCells.insert(cIndex, labelPair(newCellIndex, 0));
6661 FixedList<label, 2> mP(-1);
6663 forAll(patchFaces, indexI)
6665 label faceI = patchFaces[indexI];
6666 label cIndex = owner_[faceI];
6668 // Fetch appropriate face / cell
6669 // - Make copies, since holding references
6670 // to data within this loop is unsafe.
6671 const face bFace = faces_[faceI];
6672 const cell ownCell = cells_[cIndex];
6674 // Configure a new face for insertion
6675 face newHFace(bFace);
6676 labelList newHFaceEdges(bFace.size(), -1);
6678 // Get the opposing face from the cell
6679 oppositeFace oFace = ownCell.opposingFace(faceI, faces_);
6683 // Something's wrong here.
6686 "const changeMap dynamicTopoFvMesh::addCellLayer"
6687 "(const label patchID)"
6689 << " Face: " << faceI << " :: " << bFace << nl
6690 << " has no opposing face in cell: "
6691 << cIndex << " :: " << ownCell << nl
6692 << abort(FatalError);
6696 forAll(bFace, pointI)
6698 label pIndex = bFace[pointI];
6700 // Skip if we've added this already
6701 if (addedPoints.found(pIndex))
6706 // Set master points
6708 mP[1] = oFace[pointI];
6710 label newPointIndex =
6714 0.5 * (points_[mP[0]] + points_[mP[1]]),
6721 map.addPoint(newPointIndex, mP);
6722 addedPoints.insert(pIndex, newPointIndex);
6725 // Fetch faceEdges from opposite faces.
6726 // - Make copies, since holding references is unsafe
6727 const labelList bfEdges = faceEdges_[faceI];
6728 const labelList ofEdges = faceEdges_[oFace.oppositeIndex()];
6730 // Create edges for each edge of the new horizontal face
6731 forAll(bfEdges, edgeI)
6733 label beIndex = bfEdges[edgeI];
6735 // Skip if we've added this already
6736 if (addedHEdges.found(beIndex))
6738 // Update face edges for the new horizontal face
6739 newHFaceEdges[edgeI] = addedHEdges[beIndex];
6744 // Configure the new edge
6746 const edge bEdge = edges_[beIndex];
6748 // Build an edge for comparison
6751 oFace[bFace.which(bEdge[0])],
6752 oFace[bFace.which(bEdge[1])]
6755 forAll(ofEdges, edgeJ)
6757 const edge& ofEdge = edges_[ofEdges[edgeJ]];
6759 if (cEdge == ofEdge)
6761 oeIndex = ofEdges[edgeJ];
6770 "const changeMap dynamicTopoFvMesh::addCellLayer"
6771 "(const label patchID)"
6773 << " Could not find comparison edge: " << cEdge
6774 << " for edge: " << bEdge
6775 << abort(FatalError);
6778 // Fetch patch information
6779 label hEdgePatch = whichEdgePatch(oeIndex);
6784 addedPoints[bEdge[0]],
6785 addedPoints[bEdge[1]]
6788 // Insert a new edge with empty edgeFaces
6789 label newHEdgeIndex =
6800 map.addEdge(newHEdgeIndex);
6801 addedHEdges.insert(beIndex, newHEdgeIndex);
6803 // Update face edges for the new horizontal face
6804 newHFaceEdges[edgeI] = newHEdgeIndex;
6806 // Add a new vertical face for this edge
6807 label vFaceIndex = -1;
6809 // Find a vertical face that contains both edges
6810 const labelList& beFaces = edgeFaces_[beIndex];
6812 forAll(beFaces, faceJ)
6814 const labelList& testEdges = faceEdges_[beFaces[faceJ]];
6818 (findIndex(testEdges, beIndex) > -1) &&
6819 (findIndex(testEdges, oeIndex) > -1)
6822 vFaceIndex = beFaces[faceJ];
6831 "const changeMap dynamicTopoFvMesh::addCellLayer"
6832 "(const label patchID)"
6834 << " Could not find an appropriate vertical face"
6835 << " containing edges: " << oeIndex
6836 << " and " << beIndex
6837 << abort(FatalError);
6840 // Find two vertical edges on this face
6841 const labelList& vfEdges = faceEdges_[vFaceIndex];
6843 forAll(vfEdges, edgeJ)
6845 const edge& vfEdge = edges_[vfEdges[edgeJ]];
6849 if (vfEdge == edge(bEdge[i], cEdge[i]))
6851 // Skip if we've added this already
6852 if (addedVEdges.found(bEdge[i]))
6857 label veIndex = vfEdges[edgeJ];
6859 // Fetch edge patch information
6860 label vEdgePatch = whichEdgePatch(veIndex);
6866 addedPoints[bEdge[i]]
6869 // Insert a new edge with empty edgeFaces
6870 label newVEdgeIndex =
6881 map.addEdge(newVEdgeIndex);
6882 addedVEdges.insert(bEdge[i], newVEdgeIndex);
6884 // Note edge indices for later renumbering
6885 currentVEdges.insert(bEdge[i], veIndex);
6890 // Configure the new vertical face
6891 face newVFace(faces_[vFaceIndex]);
6892 label newOwner = -1, newNeighbour = -1;
6894 label oldOwner = owner_[vFaceIndex];
6895 label oldNeighbour = neighbour_[vFaceIndex];
6897 // Fetch owner / neighbour
6898 newOwner = addedCells[oldOwner].first();
6900 if (oldNeighbour > -1)
6902 newNeighbour = addedCells[oldNeighbour].first();
6905 // Replace point indices on the new face
6908 meshOps::replaceLabel
6911 addedPoints[bEdge[i]],
6916 // Note face indices for later renumbering
6917 currentVFaces.insert(beIndex, vFaceIndex);
6919 // Check if reversal is necessary
6920 if ((newNeighbour < newOwner) && (newNeighbour > -1))
6923 newVFace = newVFace.reverseFace();
6926 Foam::Swap(newOwner, newNeighbour);
6927 Foam::Swap(oldOwner, oldNeighbour);
6930 // Configure faceEdges for the new vertical face
6931 labelList newVFaceEdges(4, -1);
6933 newVFaceEdges[0] = beIndex;
6934 newVFaceEdges[1] = newHEdgeIndex;
6935 newVFaceEdges[2] = addedVEdges[bEdge[0]];
6936 newVFaceEdges[3] = addedVEdges[bEdge[1]];
6938 // Add the new vertical face
6939 label newVFaceIndex =
6943 whichPatch(vFaceIndex),
6950 // Add a faceEdges entry
6951 faceEdges_.append(newVFaceEdges);
6954 map.addFace(newVFaceIndex, labelList(1, vFaceIndex));
6955 addedVFaces.insert(beIndex, newVFaceIndex);
6957 // Update face count on the new cells
6958 cells_[newOwner][addedCells[oldOwner].second()++] =
6963 if (newNeighbour > -1)
6965 cells_[newNeighbour][addedCells[oldNeighbour].second()++] =
6971 // Size up edgeFaces for each edge
6972 forAll(newVFaceEdges, edgeJ)
6974 label vfeIndex = newVFaceEdges[edgeJ];
6979 edgeFaces_[vfeIndex]
6984 // Add a new interior face, with identical orientation
6985 forAll(newHFace, pointI)
6987 newHFace[pointI] = addedPoints[newHFace[pointI]];
6990 // Add the new horizontal face
6991 label newHFaceIndex =
6998 addedCells[cIndex].first()
7002 // Add a faceEdges entry
7003 faceEdges_.append(newHFaceEdges);
7006 map.addFace(newHFaceIndex, labelList(1, faceI));
7007 addedHFaces.insert(faceI, newHFaceIndex);
7009 // Replace index on the old cell
7010 meshOps::replaceLabel
7017 // Update face count on the new cell
7018 label newCellIndex = addedCells[cIndex].first();
7020 // Modify owner for the existing boundary face
7021 owner_[faceI] = newCellIndex;
7023 cells_[newCellIndex][addedCells[cIndex].second()++] = faceI;
7024 cells_[newCellIndex][addedCells[cIndex].second()++] = newHFaceIndex;
7026 // Size up edgeFaces for each edge
7027 forAll(newHFaceEdges, edgeI)
7029 label hfeIndex = newHFaceEdges[edgeI];
7034 edgeFaces_[hfeIndex]
7039 // Renumber vertical edges
7040 forAllConstIter(Map<label>, currentVEdges, eIter)
7042 // Fetch reference to edge
7043 edge& curEdge = edges_[eIter()];
7045 if (curEdge[0] == eIter.key())
7047 curEdge[0] = addedPoints[eIter.key()];
7050 if (curEdge[1] == eIter.key())
7052 curEdge[1] = addedPoints[eIter.key()];
7055 // Size down pointEdges
7058 meshOps::sizeDownList
7061 pointEdges_[eIter.key()]
7067 pointEdges_[addedPoints[eIter.key()]]
7072 // Renumber vertical faces
7073 forAllConstIter(Map<label>, currentVFaces, fIter)
7075 // Fetch reference to existing edge
7076 const edge& bEdge = edges_[fIter.key()];
7078 // Replace point indices on vertical face
7081 meshOps::replaceLabel
7084 addedPoints[bEdge[i]],
7089 // Replace edge on the existing vertical face
7090 meshOps::replaceLabel
7093 addedHEdges[fIter.key()],
7097 // Remove old face on existing boundary edge
7098 meshOps::sizeDownList
7101 edgeFaces_[fIter.key()]
7104 // Add old face to new horizontal edge
7108 edgeFaces_[addedHEdges[fIter.key()]]
7112 // Now that all old / new cells possess correct connectivity,
7113 // compute mapping information.
7114 const List<objectMap>& afList = map.addedFaceList();
7116 forAll(afList, indexI)
7118 label parent = afList[indexI].masterObjects()[0];
7120 if (whichPatch(afList[indexI].index()) == -1)
7122 // Interior faces get default mapping
7123 if (whichPatch(parent) == -1)
7125 setFaceMapping(parent);
7128 setFaceMapping(afList[indexI].index());
7133 topoChangeFlag_ = true;
7135 // Specify that the operation was successful
7138 // Return the changeMap
7143 // Split a set of internal faces into boundary faces
7144 // - Add boundary faces and edges to the patch specified by 'patchIndex'
7145 // - Cell color should specify a binary value dictating either side
7146 // of the split face.
7147 void dynamicTopoFvMesh::splitInternalFaces
7149 const label patchIndex,
7150 const labelList& internalFaces,
7151 const Map<bool>& cellColors
7154 Map<label> mirrorPointLabels;
7155 FixedList<Map<label>, 2> mirrorEdgeLabels, mirrorFaceLabels;
7157 // First loop through the list and accumulate a list of
7158 // points and edges that need to be duplicated.
7159 forAll(internalFaces, faceI)
7161 const face& faceToCheck = faces_[internalFaces[faceI]];
7163 forAll(faceToCheck, pointI)
7165 if (!mirrorPointLabels.found(faceToCheck[pointI]))
7167 mirrorPointLabels.insert(faceToCheck[pointI], -1);
7171 const labelList& fEdges = faceEdges_[internalFaces[faceI]];
7173 forAll(fEdges, edgeI)
7175 if (!mirrorEdgeLabels[0].found(fEdges[edgeI]))
7177 mirrorEdgeLabels[0].insert(fEdges[edgeI], -1);
7182 // Now for every point in the list, add a new one.
7183 // Add a mapping entry as well.
7184 forAllIter(Map<label>, mirrorPointLabels, pIter)
7186 // Obtain a copy of the point before adding it,
7187 // since the reference might become invalid during list resizing.
7188 point newPoint = points_[pIter.key()];
7189 point oldPoint = oldPoints_[pIter.key()];
7191 pIter() = insertPoint(newPoint, oldPoint, labelList(1, pIter.key()));
7195 const labelList& pEdges = pointEdges_[pIter.key()];
7197 labelHashSet edgesToRemove;
7199 forAll(pEdges, edgeI)
7201 const labelList& eFaces = edgeFaces_[pEdges[edgeI]];
7203 bool allTrue = true;
7205 forAll(eFaces, faceI)
7207 label own = owner_[eFaces[faceI]];
7208 label nei = neighbour_[eFaces[faceI]];
7210 // Check if an owner/neighbour cell is false
7211 if (!cellColors[own])
7219 if (!cellColors[nei])
7229 // Mark this edge label to be discarded later
7230 edgesToRemove.insert(pEdges[edgeI]);
7234 // It is dangerous to use the pointEdges references,
7235 // so call it using array-lookup instead.
7236 forAllIter(labelHashSet, edgesToRemove, hsIter)
7238 // Add the edge to the mirror point list
7242 pointEdges_[pIter()]
7245 // Remove the edge from the original point list
7246 meshOps::sizeDownList
7249 pointEdges_[pIter.key()]
7258 labelList mPoints(mirrorPointLabels.size());
7262 forAllIter(Map<label>, mirrorPointLabels, pIter)
7266 "pEdges_o_" + Foam::name(pIter.key()) + '_',
7267 pointEdges_[pIter.key()],
7273 "pEdges_m_" + Foam::name(pIter()) + '_',
7274 pointEdges_[pIter()],
7278 mPoints[i++] = pIter();
7284 mirrorPointLabels.toc(),
7297 // For every internal face, add a new one.
7298 // - Stick to the rule:
7299 // [1] Every cell marked false keeps the existing entities.
7300 // [2] Every cell marked true gets new points/edges/faces.
7301 // - If faces are improperly oriented, reverse them.
7302 forAll(internalFaces, faceI)
7304 FixedList<face, 2> newFace;
7305 FixedList<label, 2> newFaceIndex(-1);
7306 FixedList<label, 2> newOwner(-1);
7308 label oldOwn = owner_[internalFaces[faceI]];
7309 label oldNei = neighbour_[internalFaces[faceI]];
7311 if (cellColors[oldOwn] && !cellColors[oldNei])
7313 // The owner gets a new boundary face.
7314 // Note that orientation is already correct.
7315 newFace[0] = faces_[internalFaces[faceI]];
7317 // The neighbour needs to have its face reversed
7318 // and moved to the boundary patch, thereby getting
7319 // deleted in the process.
7320 newFace[1] = newFace[0].reverseFace();
7322 newOwner[0] = oldOwn;
7323 newOwner[1] = oldNei;
7326 if (!cellColors[oldOwn] && cellColors[oldNei])
7328 // The neighbour gets a new boundary face.
7329 // The face is oriented in the opposite sense, however.
7330 newFace[0] = faces_[internalFaces[faceI]].reverseFace();
7332 // The owner keeps the existing face and orientation.
7333 // But it also needs to be moved to the boundary.
7334 newFace[1] = faces_[internalFaces[faceI]];
7336 newOwner[0] = oldNei;
7337 newOwner[1] = oldOwn;
7341 // Something's wrong here.
7344 "dynamicTopoFvMesh::splitInternalFaces\n"
7346 " const label patchIndex,\n"
7347 " const labelList& internalFaces,\n"
7348 " const Map<bool>& cellColors\n"
7352 << internalFaces[faceI]
7353 << " has cells which are improperly marked: " << nl
7354 << oldOwn << ":: " << cellColors[oldOwn] << nl
7355 << oldNei << ":: " << cellColors[oldNei]
7356 << abort(FatalError);
7359 // Renumber point labels for the first new face.
7360 forAll(newFace[0], pointI)
7362 newFace[0][pointI] = mirrorPointLabels[newFace[0][pointI]];
7365 // Insert the new boundary faces.
7366 forAll(newFace, indexI)
7368 newFaceIndex[indexI] =
7379 // Make an identical faceEdges entry.
7380 // This will be renumbered once new edges are added.
7381 labelList newFaceEdges(faceEdges_[internalFaces[faceI]]);
7383 faceEdges_.append(newFaceEdges);
7385 // Replace face labels on cells
7386 meshOps::replaceLabel
7388 internalFaces[faceI],
7389 newFaceIndex[indexI],
7390 cells_[newOwner[indexI]]
7393 // Make face mapping entries for posterity.
7394 mirrorFaceLabels[indexI].insert
7396 internalFaces[faceI],
7397 newFaceIndex[indexI]
7402 // For every edge in the list, add a new one.
7403 // We'll deal with correcting edgeFaces later.
7404 forAllIter(Map<label>, mirrorEdgeLabels[0], eIter)
7406 // Obtain copies for the append method
7407 edge origEdge = edges_[eIter.key()];
7408 labelList newEdgeFaces(edgeFaces_[eIter.key()]);
7417 mirrorPointLabels[origEdge[0]],
7418 mirrorPointLabels[origEdge[1]]
7424 // Is the original edge an internal one?
7425 // If it is, we need to move it to the boundary.
7426 if (whichEdgePatch(eIter.key()) == -1)
7428 label rplEdgeIndex =
7438 // Map the new entry.
7439 mirrorEdgeLabels[1].insert(eIter.key(), rplEdgeIndex);
7443 // This is already a boundary edge.
7444 // Make an identical map.
7445 mirrorEdgeLabels[1].insert(eIter.key(), eIter.key());
7449 // Correct edgeFaces for all new edges
7450 forAll(mirrorEdgeLabels, indexI)
7452 forAllIter(Map<label>, mirrorEdgeLabels[indexI], eIter)
7454 labelList& eFaces = edgeFaces_[eIter()];
7456 labelHashSet facesToRemove;
7458 forAll(eFaces, faceI)
7460 bool remove = false;
7462 label own = owner_[eFaces[faceI]];
7463 label nei = neighbour_[eFaces[faceI]];
7467 (!cellColors[own] && !indexI) ||
7468 ( cellColors[own] && indexI)
7478 (!cellColors[nei] && !indexI) ||
7479 ( cellColors[nei] && indexI)
7486 if (mirrorFaceLabels[indexI].found(eFaces[faceI]))
7488 // Perform a replacement instead of a removal.
7489 eFaces[faceI] = mirrorFaceLabels[indexI][eFaces[faceI]];
7496 facesToRemove.insert(eFaces[faceI]);
7500 // Now successively size down edgeFaces.
7501 // It is dangerous to use the eFaces reference,
7502 // so call it using array-lookup.
7503 forAllIter(labelHashSet, facesToRemove, hsIter)
7505 meshOps::sizeDownList(hsIter.key(), edgeFaces_[eIter()]);
7510 // Renumber faceEdges for all faces connected to new edges
7511 forAll(mirrorEdgeLabels, indexI)
7513 forAllIter(Map<label>, mirrorEdgeLabels[indexI], eIter)
7515 const labelList& eFaces = edgeFaces_[eIter()];
7517 forAll(eFaces, faceI)
7519 labelList& fEdges = faceEdges_[eFaces[faceI]];
7521 forAll(fEdges, edgeI)
7523 if (mirrorEdgeLabels[indexI].found(fEdges[edgeI]))
7527 mirrorEdgeLabels[indexI][fEdges[edgeI]]
7537 // Renumber edges and faces
7538 forAllIter(Map<label>, mirrorEdgeLabels[0], eIter)
7540 const labelList& eFaces = edgeFaces_[eIter()];
7542 // Two levels of indirection to ensure
7543 // that all entities we renumbered.
7544 // A flip-side for the lack of a pointEdges list in 2D.
7545 forAll(eFaces, faceI)
7547 const labelList& fEdges = faceEdges_[eFaces[faceI]];
7549 forAll(fEdges, edgeI)
7551 // Renumber this edge.
7552 edge& edgeToCheck = edges_[fEdges[edgeI]];
7554 forAll(edgeToCheck, pointI)
7556 if (mirrorPointLabels.found(edgeToCheck[pointI]))
7558 edgeToCheck[pointI] =
7560 mirrorPointLabels[edgeToCheck[pointI]]
7565 // Also renumber faces connected to this edge.
7566 const labelList& efFaces = edgeFaces_[fEdges[edgeI]];
7568 forAll(efFaces, faceJ)
7570 face& faceToCheck = faces_[efFaces[faceJ]];
7572 forAll(faceToCheck, pointI)
7576 mirrorPointLabels.found(faceToCheck[pointI])
7579 faceToCheck[pointI] =
7581 mirrorPointLabels[faceToCheck[pointI]]
7592 // Point renumbering of entities connected to mirror points
7593 forAllIter(Map<label>, mirrorPointLabels, pIter)
7595 const labelList& pEdges = pointEdges_[pIter()];
7597 forAll(pEdges, edgeI)
7599 // Renumber this edge.
7600 edge& edgeToCheck = edges_[pEdges[edgeI]];
7602 forAll(edgeToCheck, pointI)
7604 if (edgeToCheck[pointI] == pIter.key())
7606 edgeToCheck[pointI] = pIter();
7610 // Also renumber faces connected to this edge.
7611 const labelList& eFaces = edgeFaces_[pEdges[edgeI]];
7613 forAll(eFaces, faceI)
7615 face& faceToCheck = faces_[eFaces[faceI]];
7617 forAll(faceToCheck, pointI)
7619 if (faceToCheck[pointI] == pIter.key())
7621 faceToCheck[pointI] = pIter();
7629 // Now that we're done with the internal faces, remove them.
7630 forAll(internalFaces, faceI)
7632 removeFace(internalFaces[faceI]);
7635 // Remove old internal edges as well.
7636 forAllIter(Map<label>, mirrorEdgeLabels[1], eIter)
7638 if (eIter.key() != eIter())
7640 removeEdge(eIter.key());
7645 topoChangeFlag_ = true;
7648 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
7650 } // End namespace Foam
7652 // ************************************************************************* //