1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "dynamicTopoFvMesh.H"
29 #include "objectMap.H"
30 #include "changeMap.H"
31 #include "triPointRef.H"
32 #include "linePointRef.H"
33 #include "multiThreader.H"
34 #include "coupledInfo.H"
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
43 // Perform a Delaunay test on an internal face
44 // - Returns 'true' if the test failed
45 bool dynamicTopoFvMesh::testDelaunay
50 bool failed = false, procCoupled = false;
51 label eIndex = -1, pointIndex = -1, fLabel = -1;
52 label sIndex = -1, pIndex = -1;
53 FixedList<triFace, 2> triFaces(triFace(-1, -1, -1));
54 FixedList<bool, 2> foundTriFace(false);
56 // If this entity was deleted, skip it.
57 if (faces_[fIndex].empty())
62 // If face is not shared by prism cells, skip it.
63 label own = owner_[fIndex], nei = neighbour_[fIndex];
65 if (cells_[own].size() != 5)
72 if (cells_[nei].size() != 5)
78 // Boundary faces are discarded.
79 if (whichPatch(fIndex) > -1)
81 procCoupled = processorCoupledEntity(fIndex);
89 const labelList& fEdges = faceEdges_[fIndex];
93 // Break out if both triangular faces are found
94 if (foundTriFace[0] && foundTriFace[1])
99 // Obtain edgeFaces for this edge
100 const labelList& eFaces = edgeFaces_[fEdges[edgeI]];
102 forAll(eFaces, faceI)
104 const face& thisFace = faces_[eFaces[faceI]];
106 if (thisFace.size() == 3)
110 // Update the second face.
111 triFaces[1][0] = thisFace[0];
112 triFaces[1][1] = thisFace[1];
113 triFaces[1][2] = thisFace[2];
115 foundTriFace[1] = true;
119 // Update the first face.
120 triFaces[0][0] = thisFace[0];
121 triFaces[0][1] = thisFace[1];
122 triFaces[0][2] = thisFace[2];
124 foundTriFace[0] = true;
125 fLabel = eFaces[faceI];
128 eIndex = fEdges[edgeI];
132 // Stop searching for processor boundary cases
133 foundTriFace[1] = true;
140 const edge& checkEdge = edges_[eIndex];
142 // Configure the comparison edge
147 // If this is a new entity, bail out for now.
148 // This will be handled at the next time-step.
149 if (fIndex >= nOldFaces_)
154 const label faceEnum = coupleMap::FACE;
155 const label pointEnum = coupleMap::POINT;
158 bool foundEdge = false;
160 forAll(procIndices_, pI)
162 // Fetch non-const reference to subMeshes
163 const coupledMesh& recvMesh = recvMeshes_[pI];
165 const coupleMap& cMap = recvMesh.map();
166 const dynamicTopoFvMesh& sMesh = recvMesh.subMesh();
168 if ((sIndex = cMap.findSlave(faceEnum, fIndex)) > -1)
170 // Find equivalent points on the slave
171 cEdge[0] = cMap.findSlave(pointEnum, checkEdge[0]);
172 cEdge[1] = cMap.findSlave(pointEnum, checkEdge[1]);
174 // Find a triangular face containing cEdge
175 const labelList& sfE = sMesh.faceEdges_[sIndex];
179 // Obtain edgeFaces for this edge
180 const labelList& seF = sMesh.edgeFaces_[sfE[edgeI]];
184 const face& tF = sMesh.faces_[seF[faceI]];
190 (findIndex(tF, cEdge[0]) > -1) &&
191 (findIndex(tF, cEdge[1]) > -1)
194 triFaces[1][0] = tF[0];
195 triFaces[1][1] = tF[1];
196 triFaces[1][2] = tF[2];
211 // Store patch index for later
218 if (sIndex == -1 || !foundEdge)
220 // Write out for post-processing
221 writeVTK("coupledDelaunayFace_" + Foam::name(fIndex), fIndex, 2);
225 "bool dynamicTopoFvMesh::testDelaunay"
226 "(const label fIndex) const"
228 << "Coupled maps were improperly specified." << nl
229 << " Slave index not found for: " << nl
230 << " Face: " << fIndex << nl
231 << " checkEdge: " << checkEdge << nl
232 << " cEdge: " << cEdge << nl
233 << abort(FatalError);
242 // Obtain point references for the first face
243 point a = points_[triFaces[0][0]];
245 const face& faceToCheck = faces_[fLabel];
251 points_[faceToCheck[0]],
252 points_[faceToCheck[1]],
253 points_[faceToCheck[2]]
257 scalar rSquared = (a - cCentre) & (a - cCentre);
259 // Find the isolated point on the second face
260 point otherPoint = vector::zero;
262 // Check the first point
263 if (triFaces[1][0] != cEdge[0] && triFaces[1][0] != cEdge[1])
265 pointIndex = triFaces[1][0];
268 // Check the second point
269 if (triFaces[1][1] != cEdge[0] && triFaces[1][1] != cEdge[1])
271 pointIndex = triFaces[1][1];
274 // Check the third point
275 if (triFaces[1][2] != cEdge[0] && triFaces[1][2] != cEdge[1])
277 pointIndex = triFaces[1][2];
282 otherPoint = recvMeshes_[pIndex].subMesh().points_[pointIndex];
286 otherPoint = points_[pointIndex];
289 // ...and determine whether it lies in this circle
290 if (((otherPoint - cCentre) & (otherPoint - cCentre)) < rSquared)
300 // Method for the swapping of a quad-face in 2D
301 // - Returns a changeMap with a type specifying:
302 // 1: Swap sequence was successful
303 // -1: Swap sequence failed
304 const changeMap dynamicTopoFvMesh::swapQuadFace
313 label commonIndex = -1;
314 FixedList<label,4> otherPointIndex(-1), nextToOtherPoint(-1);
315 FixedList<label,2> c0BdyIndex(-1), c0IntIndex(-1);
316 FixedList<label,2> c1BdyIndex(-1), c1IntIndex(-1);
317 FixedList<face,2> c0BdyFace(face(3)), c0IntFace(face(4));
318 FixedList<face,2> c1BdyFace(face(3)), c1IntFace(face(4));
319 FixedList<label,2> commonEdgeIndex(-1);
320 FixedList<edge,2> commonEdges(edge(-1, -1));
321 FixedList<label,4> otherEdgeIndex(-1);
322 FixedList<label,4> commonFaceIndex(-1), cornerEdgeIndex(-1);
323 FixedList<face,4> commonFaces(face(3)), commonIntFaces(face(4));
324 FixedList<label,4> commonIntFaceIndex(-1);
325 FixedList<bool,2> foundTriFace0(false), foundTriFace1(false);
326 FixedList<face,2> triFaces0(face(3)), triFaces1(face(3));
328 if (coupledModification_)
330 if (processorCoupledEntity(fIndex))
332 // When swapping across processors, we need to add the
333 // prism-cell from (as well as delete on) the patchSubMesh
334 const changeMap faceMap = insertCells(fIndex);
336 // Bail out if entity is handled elsewhere
337 if (faceMap.type() == -2)
342 if (faceMap.type() != 1)
346 "const changeMap dynamicTopoFvMesh::swapQuadFace"
347 "(const label fIndex)"
349 << " Could not insert cells around face: " << fIndex
350 << " :: " << faces_[fIndex] << nl
351 << abort(FatalError);
354 // Figure out the new internal face index.
355 // This should not be a coupled face anymore.
356 label newIndex = faceMap.index();
358 // Temporarily turn off coupledModification
359 unsetCoupledModification();
361 // Recursively call this function for the new face
362 map = swapQuadFace(newIndex);
365 setCoupledModification();
371 // Get the two cells on either side...
372 label c0 = owner_[fIndex];
373 label c1 = neighbour_[fIndex];
375 // Prepare two new cells
376 FixedList<cell, 2> newCell(cell(5));
378 // Need to find common faces and edges...
379 // At the end of this loop, commonFaces [0] & [1] share commonEdge[0]
380 // and commonFaces [2] & [3] share commonEdge[1]
381 // Also, commonFaces[0] & [2] are connected to cell[0],
382 // and commonFaces[1] & [3] are connected to cell[1]
383 const labelList& fEdges = faceEdges_[fIndex];
385 forAll(fEdges, edgeI)
387 // Break out if all triangular faces are found
390 foundTriFace0[0] && foundTriFace0[1] &&
391 foundTriFace1[0] && foundTriFace1[1]
397 // Obtain edgeFaces for this edge
398 const labelList& eFaces = edgeFaces_[fEdges[edgeI]];
400 forAll(eFaces, faceI)
402 const face& eFace = faces_[eFaces[faceI]];
404 if (eFace.size() == 3)
406 // Found a triangular face. Determine which cell it belongs to.
407 if (owner_[eFaces[faceI]] == c0)
409 if (foundTriFace0[0])
411 // Update the second face on cell[0].
413 foundTriFace0[1] = true;
415 if (foundTriFace1[1])
417 commonEdgeIndex[1] = fEdges[edgeI];
418 commonEdges[1] = edges_[fEdges[edgeI]];
423 // Update the first face on cell[0].
425 foundTriFace0[0] = true;
427 if (foundTriFace1[0])
429 commonEdgeIndex[0] = fEdges[edgeI];
430 commonEdges[0] = edges_[fEdges[edgeI]];
436 if (foundTriFace1[0])
438 // Update the second face on cell[1].
440 foundTriFace1[1] = true;
442 if (foundTriFace0[1])
444 commonEdgeIndex[1] = fEdges[edgeI];
445 commonEdges[1] = edges_[fEdges[edgeI]];
450 // Update the first face on cell[1].
452 foundTriFace1[0] = true;
454 if (foundTriFace0[0])
456 commonEdgeIndex[0] = fEdges[edgeI];
457 commonEdges[0] = edges_[fEdges[edgeI]];
462 // Store the face and index
463 commonFaces[commonIndex][0] = eFace[0];
464 commonFaces[commonIndex][1] = eFace[1];
465 commonFaces[commonIndex][2] = eFace[2];
467 commonFaceIndex[commonIndex] = eFaces[faceI];
472 // Find the interior/boundary faces.
473 meshOps::findPrismFaces
486 meshOps::findPrismFaces
499 // Find the points that don't lie on shared edges
500 // and the points next to them (for orientation)
501 meshOps::findIsolatedPoint
509 meshOps::findIsolatedPoint
517 meshOps::findIsolatedPoint
525 meshOps::findIsolatedPoint
533 // Ensure that the configuration will be valid
534 // using old point-positions. A simple area-based
535 // calculation should suffice.
536 FixedList<face, 2> triFaceOldPoints(face(3));
538 triFaceOldPoints[0][0] = otherPointIndex[0];
539 triFaceOldPoints[0][1] = nextToOtherPoint[0];
540 triFaceOldPoints[0][2] = otherPointIndex[1];
542 triFaceOldPoints[1][0] = otherPointIndex[1];
543 triFaceOldPoints[1][1] = nextToOtherPoint[1];
544 triFaceOldPoints[1][2] = otherPointIndex[0];
546 // Assume XY plane here
547 vector n = vector(0,0,1);
549 forAll(triFaceOldPoints, faceI)
551 // Assume that centre-plane passes through the origin.
554 xf = triFaceOldPoints[faceI].centre(oldPoints_);
555 nf = triFaceOldPoints[faceI].normal(oldPoints_);
557 if ((((xf & n) * n) & nf) < 0.0)
559 // This will yield an inverted cell. Bail out.
564 // Find the other two edges on the face being flipped
565 forAll(fEdges, edgeI)
569 fEdges[edgeI] != commonEdgeIndex[0] &&
570 fEdges[edgeI] != commonEdgeIndex[1]
573 // Obtain a reference to this edge
574 const edge& eThis = edges_[fEdges[edgeI]];
578 eThis[0] == nextToOtherPoint[0]
579 || eThis[1] == nextToOtherPoint[0]
582 otherEdgeIndex[0] = fEdges[edgeI];
586 otherEdgeIndex[1] = fEdges[edgeI];
591 // At the end of this loop, commonIntFaces [0] & [1] share otherEdges[0]
592 // and commonIntFaces [2] & [3] share the otherEdges[1],
593 // where [0],[2] lie on cell[0] and [1],[3] lie on cell[1]
596 const labelList& e1 = faceEdges_[c0IntIndex[0]];
600 if (e1[edgeI] == otherEdgeIndex[0])
602 commonIntFaces[0] = c0IntFace[0];
603 commonIntFaces[2] = c0IntFace[1];
604 commonIntFaceIndex[0] = c0IntIndex[0];
605 commonIntFaceIndex[2] = c0IntIndex[1];
612 // The edge was not found before
613 commonIntFaces[0] = c0IntFace[1];
614 commonIntFaces[2] = c0IntFace[0];
615 commonIntFaceIndex[0] = c0IntIndex[1];
616 commonIntFaceIndex[2] = c0IntIndex[0];
621 const labelList& e3 = faceEdges_[c1IntIndex[0]];
625 if (e3[edgeI] == otherEdgeIndex[0])
627 commonIntFaces[1] = c1IntFace[0];
628 commonIntFaces[3] = c1IntFace[1];
629 commonIntFaceIndex[1] = c1IntIndex[0];
630 commonIntFaceIndex[3] = c1IntIndex[1];
637 // The edge was not found before
638 commonIntFaces[1] = c1IntFace[1];
639 commonIntFaces[3] = c1IntFace[0];
640 commonIntFaceIndex[1] = c1IntIndex[1];
641 commonIntFaceIndex[3] = c1IntIndex[0];
644 // Find two common edges between quad/quad faces
645 meshOps::findCommonEdge
653 meshOps::findCommonEdge
661 // Find four common edges between quad/tri faces
662 meshOps::findCommonEdge
665 commonIntFaceIndex[1],
670 meshOps::findCommonEdge
673 commonIntFaceIndex[1],
678 meshOps::findCommonEdge
681 commonIntFaceIndex[2],
686 meshOps::findCommonEdge
689 commonIntFaceIndex[2],
694 // Perform a few debug calls before modifications
697 Pout<< nl << nl << "Face: " << fIndex
698 << " needs to be flipped. " << endl;
702 Pout<< " Cell[0]: " << c0 << ": " << cells_[c0] << nl
703 << " Cell[1]: " << c1 << ": " << cells_[c1] << nl;
705 Pout<< " Common Faces: Set 1: "
706 << commonFaceIndex[0] << ": " << commonFaces[0] << ", "
707 << commonFaceIndex[1] << ": " << commonFaces[1] << nl;
709 Pout<< " Common Faces: Set 2: "
710 << commonFaceIndex[2] << ": " << commonFaces[2] << ", "
711 << commonFaceIndex[3] << ": " << commonFaces[3] << nl;
713 Pout<< " Old face: " << faces_[fIndex] << nl
714 << " Old faceEdges: " << faceEdges_[fIndex] << endl;
717 // Write out VTK files before change
720 labelList cellHull(2, -1);
725 writeVTK(Foam::name(fIndex) + "_Swap_0", cellHull);
729 // Modify the five faces belonging to this hull
730 face newFace = faces_[fIndex];
731 labelList newFEdges = faceEdges_[fIndex];
732 FixedList<face, 4> newBdyFace(face(3));
733 FixedList<edge, 2> newEdges;
735 // Assign current faces
736 forAll(newBdyFace, faceI)
738 newBdyFace[faceI] = faces_[commonFaceIndex[faceI]];
741 label c0count=0, c1count=0;
743 // Size down edgeFaces for the original face
744 meshOps::sizeDownList
747 edgeFaces_[otherEdgeIndex[0]]
750 meshOps::sizeDownList
753 edgeFaces_[otherEdgeIndex[1]]
756 // Size up edgeFaces for the face after flipping
760 edgeFaces_[otherEdgeIndex[2]]
766 edgeFaces_[otherEdgeIndex[3]]
769 // Replace edgeFaces and faceEdges for the
770 // four (out of 8 total) corner edges of this hull.
771 meshOps::replaceLabel
775 faceEdges_[commonFaceIndex[1]]
778 meshOps::replaceLabel
782 edgeFaces_[cornerEdgeIndex[0]]
785 meshOps::replaceLabel
789 faceEdges_[commonFaceIndex[3]]
792 meshOps::replaceLabel
796 edgeFaces_[cornerEdgeIndex[1]]
799 meshOps::replaceLabel
803 faceEdges_[commonFaceIndex[0]]
806 meshOps::replaceLabel
810 edgeFaces_[cornerEdgeIndex[2]]
813 meshOps::replaceLabel
817 faceEdges_[commonFaceIndex[2]]
820 meshOps::replaceLabel
824 edgeFaces_[cornerEdgeIndex[3]]
827 // Define parameters for the new flipped face
828 newFace[0] = otherPointIndex[0];
829 newFace[1] = otherPointIndex[1];
830 newFace[2] = otherPointIndex[3];
831 newFace[3] = otherPointIndex[2];
833 newFEdges[0] = otherEdgeIndex[2];
834 newFEdges[1] = commonEdgeIndex[0];
835 newFEdges[2] = otherEdgeIndex[3];
836 newFEdges[3] = commonEdgeIndex[1];
838 newCell[0][c0count++] = fIndex;
839 newCell[1][c1count++] = fIndex;
842 neighbour_[fIndex] = c1;
844 // Both commonEdges need to be renumbered.
845 newEdges[0][0] = otherPointIndex[0];
846 newEdges[0][1] = otherPointIndex[1];
848 newEdges[1][0] = otherPointIndex[3];
849 newEdges[1][1] = otherPointIndex[2];
851 // Four modified boundary faces need to be constructed,
852 // but right-handedness is also important.
853 // Take a cue from the existing boundary-face orientation
855 // Zeroth boundary face - Owner c[0], Neighbour -1
856 newBdyFace[0][0] = otherPointIndex[0];
857 newBdyFace[0][1] = nextToOtherPoint[0];
858 newBdyFace[0][2] = otherPointIndex[1];
859 newCell[0][c0count++] = commonFaceIndex[0];
860 owner_[commonFaceIndex[0]] = c0;
861 neighbour_[commonFaceIndex[0]] = -1;
863 // First boundary face - Owner c[1], Neighbour -1
864 newBdyFace[1][0] = otherPointIndex[1];
865 newBdyFace[1][1] = nextToOtherPoint[1];
866 newBdyFace[1][2] = otherPointIndex[0];
867 newCell[1][c1count++] = commonFaceIndex[1];
868 owner_[commonFaceIndex[1]] = c1;
869 neighbour_[commonFaceIndex[1]] = -1;
871 // Second boundary face - Owner c[0], Neighbour -1
872 newBdyFace[2][0] = otherPointIndex[3];
873 newBdyFace[2][1] = nextToOtherPoint[3];
874 newBdyFace[2][2] = otherPointIndex[2];
875 newCell[0][c0count++] = commonFaceIndex[2];
876 owner_[commonFaceIndex[2]] = c0;
877 neighbour_[commonFaceIndex[2]] = -1;
879 // Third boundary face - Owner c[1], Neighbour -1
880 newBdyFace[3][0] = otherPointIndex[2];
881 newBdyFace[3][1] = nextToOtherPoint[2];
882 newBdyFace[3][2] = otherPointIndex[3];
883 newCell[1][c1count++] = commonFaceIndex[3];
884 owner_[commonFaceIndex[3]] = c1;
885 neighbour_[commonFaceIndex[3]] = -1;
889 Pout<< "New flipped face: " << newFace << nl;
893 forAll(newBdyFace, faceI)
895 Pout<< "New boundary face[" << faceI << "]: "
896 << commonFaceIndex[faceI]
897 << ": " << newBdyFace[faceI] << nl;
904 // Check the orientation of the two quad faces, and modify as necessary
905 label newOwn=0, newNei=0;
907 // The quad face belonging to cell[1] now becomes a part of cell[0]
908 if (neighbour_[commonIntFaceIndex[1]] == -1)
911 // Face doesn't need to be flipped, just update the owner
912 f = commonIntFaces[1];
917 if (owner_[commonIntFaceIndex[1]] == c1)
919 // This face is on the interior, check for previous owner
920 // Upper-triangular ordering has to be maintained, however...
921 if (c0 > neighbour_[commonIntFaceIndex[1]])
924 f = commonIntFaces[1].reverseFace();
925 newOwn = neighbour_[commonIntFaceIndex[1]];
928 setFlip(commonIntFaceIndex[1]);
932 // Flip isn't necessary, just change the owner
933 f = commonIntFaces[1];
935 newNei = neighbour_[commonIntFaceIndex[1]];
939 if (neighbour_[commonIntFaceIndex[1]] == c1)
941 // This face is on the interior, check for previous neighbour
942 // Upper-triangular ordering has to be maintained, however...
943 if (c0 < owner_[commonIntFaceIndex[1]])
946 f = commonIntFaces[1].reverseFace();
948 newNei = owner_[commonIntFaceIndex[1]];
950 setFlip(commonIntFaceIndex[1]);
954 // Flip isn't necessary, just change the neighbour
955 f = commonIntFaces[1];
956 newOwn = owner_[commonIntFaceIndex[1]];
961 faces_[commonIntFaceIndex[1]] = f;
962 newCell[0][c0count++] = commonIntFaceIndex[0];
963 newCell[0][c0count++] = commonIntFaceIndex[1];
964 owner_[commonIntFaceIndex[1]] = newOwn;
965 neighbour_[commonIntFaceIndex[1]] = newNei;
967 // The quad face belonging to cell[0] now becomes a part of cell[1]
968 if (neighbour_[commonIntFaceIndex[2]] == -1)
971 // Face doesn't need to be flipped, just update the owner
972 f = commonIntFaces[2];
977 if (owner_[commonIntFaceIndex[2]] == c0)
979 // This face is on the interior, check for previous owner
980 // Upper-triangular ordering has to be maintained, however...
981 if (c1 > neighbour_[commonIntFaceIndex[2]])
984 f = commonIntFaces[2].reverseFace();
985 newOwn = neighbour_[commonIntFaceIndex[2]];
988 setFlip(commonIntFaceIndex[2]);
992 // Flip isn't necessary, just change the owner
993 f = commonIntFaces[2];
995 newNei = neighbour_[commonIntFaceIndex[2]];
999 if (neighbour_[commonIntFaceIndex[2]] == c0)
1001 // This face is on the interior, check for previous neighbour
1002 // Upper-triangular ordering has to be maintained, however...
1003 if (c1 < owner_[commonIntFaceIndex[2]])
1005 // Flip is necessary
1006 f = commonIntFaces[2].reverseFace();
1008 newNei = owner_[commonIntFaceIndex[2]];
1010 setFlip(commonIntFaceIndex[2]);
1014 // Flip isn't necessary, just change the neighbour
1015 f = commonIntFaces[2];
1016 newOwn = owner_[commonIntFaceIndex[2]];
1021 faces_[commonIntFaceIndex[2]] = f;
1022 newCell[1][c1count++] = commonIntFaceIndex[2];
1023 newCell[1][c1count++] = commonIntFaceIndex[3];
1024 owner_[commonIntFaceIndex[2]] = newOwn;
1025 neighbour_[commonIntFaceIndex[2]] = newNei;
1027 // Now that all entities are properly configured,
1028 // overwrite the entries in connectivity lists.
1029 cells_[c0] = newCell[0];
1030 cells_[c1] = newCell[1];
1032 faces_[fIndex] = newFace;
1033 faceEdges_[fIndex] = newFEdges;
1035 forAll(newBdyFace, faceI)
1037 faces_[commonFaceIndex[faceI]] = newBdyFace[faceI];
1040 edges_[commonEdgeIndex[0]] = newEdges[0];
1041 edges_[commonEdgeIndex[1]] = newEdges[1];
1043 // Fill-in mapping information
1044 labelList mC(2, -1);
1045 mC[0] = c0; mC[1] = c1;
1049 // Set the mapping for this cell
1050 setCellMapping(mC[cellI], mC);
1053 // Interpolate new fluxes for the flipped face.
1054 setFaceMapping(fIndex);
1056 // Write out VTK files after change
1059 labelList cellHull(2, -1);
1073 topoChangeFlag_ = true;
1075 // Increment the counter
1076 status(TOTAL_SWAPS)++;
1078 // Return a successful operation.
1085 // Allocate dynamic programming tables
1086 void dynamicTopoFvMesh::initTables
1089 PtrList<scalarListList>& Q,
1090 PtrList<labelListList>& K,
1091 PtrList<labelListList>& triangulations,
1092 const label checkIndex
1095 label mMax = maxTetsPerEdge_;
1097 // Check if resizing is necessary only for a particular index.
1098 if (checkIndex != -1)
1101 Q[checkIndex].setSize((mMax-2),scalarList(mMax,-1.0));
1102 K[checkIndex].setSize((mMax-2),labelList(mMax,-1));
1103 triangulations[checkIndex].setSize(3,labelList((mMax-2),-1));
1108 // Size all elements by default.
1109 label numIndices = coupledModification_ ? 2 : 1;
1111 m.setSize(numIndices, -1);
1112 Q.setSize(numIndices);
1113 K.setSize(numIndices);
1114 triangulations.setSize(numIndices);
1121 new scalarListList((mMax-2),scalarList(mMax,-1.0))
1127 new labelListList((mMax-2),labelList(mMax,-1))
1133 new labelListList(3,labelList((mMax-2),-1))
1139 // Utility method to fill the dynamic programming tables
1140 // - Returns true if the operation completed successfully.
1141 // - Returns false if tables could not be resized.
1142 bool dynamicTopoFvMesh::fillTables
1147 labelList& hullVertices,
1148 PtrList<scalarListList>& Q,
1149 PtrList<labelListList>& K,
1150 PtrList<labelListList>& triangulations,
1151 const label checkIndex
1154 // Obtain a reference to this edge
1155 const labelList& edgeFaces = edgeFaces_[eIndex];
1157 // If this entity was deleted, skip it.
1158 if (edgeFaces.empty())
1163 // Ensure that edge is surrounded by triangles
1164 forAll(edgeFaces, faceI)
1166 if (faces_[edgeFaces[faceI]].size() != 3)
1172 const edge& edgeToCheck = edges_[eIndex];
1174 if (coupledModification_)
1176 return coupledFillTables(eIndex, minQuality, m, Q, K, triangulations);
1180 m[checkIndex] = hullVertices.size();
1182 // Check if a table-resize is necessary
1183 if (m[checkIndex] > maxTetsPerEdge_)
1185 if (allowTableResize_)
1187 // Resize the tables to account for
1188 // more tets per edge
1189 label& mtpe = const_cast<label&>(maxTetsPerEdge_);
1191 mtpe = m[checkIndex];
1193 // Clear tables for this index.
1194 Q[checkIndex].clear();
1195 K[checkIndex].clear();
1196 triangulations[checkIndex].clear();
1198 // Resize for this index.
1199 initTables(m, Q, K, triangulations, checkIndex);
1203 // Can't resize. Bail out.
1208 // Fill dynamic programming tables
1218 triangulations[checkIndex]
1221 // Print out tables for debugging
1224 printTables(m, Q, K, checkIndex);
1231 // Fill tables given addressing
1232 void dynamicTopoFvMesh::fillTables
1234 const edge& edgeToCheck,
1235 const scalar minQuality,
1237 const labelList& hullVertices,
1238 const UList<point>& points,
1241 labelListList& triangulations
1244 for (label i = (m - 3); i >= 0; i--)
1246 for (label j = i + 2; j < m; j++)
1248 for (label k = i + 1; k < j; k++)
1250 scalar q = (*tetMetric_)
1252 points[hullVertices[i]],
1253 points[hullVertices[k]],
1254 points[hullVertices[j]],
1255 points[edgeToCheck[0]]
1258 // For efficiency, check the bottom triangulation
1259 // only when the top one if less than the hull quality.
1269 points[hullVertices[j]],
1270 points[hullVertices[k]],
1271 points[hullVertices[i]],
1272 points[edgeToCheck[1]]
1280 q = Foam::min(q, Q[k][j]);
1285 q = Foam::min(q, Q[i][k]);
1288 if ((k == i + 1) || (q > Q[i][j]))
1299 // Remove the edge according to the swap sequence.
1300 // - Returns a changeMap with a type specifying:
1301 // 1: Swap sequence was successful
1302 // -1: Swap sequence failed
1303 const changeMap dynamicTopoFvMesh::removeEdgeFlips
1306 const scalar minQuality,
1307 const labelList& vertexHull,
1308 PtrList<scalarListList>& Q,
1309 PtrList<labelListList>& K,
1310 PtrList<labelListList>& triangulations,
1311 const label checkIndex
1314 changeMap map, slaveMap;
1318 Pout<< nl << " Removing edge : " << eIndex << " by flipping."
1319 << " Edge: " << edges_[eIndex]
1320 << " minQuality: " << minQuality
1324 if (coupledModification_)
1326 if (processorCoupledEntity(eIndex))
1328 const changeMap edgeMap = insertCells(eIndex);
1330 // Bail out if entity is handled elsewhere
1331 if (edgeMap.type() == -2)
1336 if (edgeMap.type() != 1)
1341 "const changeMap dynamicTopoFvMesh::removeEdgeFlips\n"
1343 " const label eIndex,\n"
1344 " const scalar minQuality,\n"
1345 " const labelList& vertexHull,\n"
1346 " PtrList<scalarListList>& Q,\n"
1347 " PtrList<labelListList>& K,\n"
1348 " PtrList<labelListList>& triangulations,\n"
1349 " const label checkIndex\n"
1352 << " Could not insert cells around edge: " << eIndex
1353 << " :: " << edges_[eIndex] << nl
1354 << abort(FatalError);
1357 // Temporarily turn off coupledModification
1358 unsetCoupledModification();
1360 // Re-fill tables for the reconfigured edge.
1361 // This should not be a coupled edge anymore.
1362 label newIndex = edgeMap.index();
1364 if (processorCoupledEntity(newIndex))
1366 // Write out edge connectivity
1367 writeEdgeConnectivity(newIndex);
1372 "const changeMap dynamicTopoFvMesh::removeEdgeFlips\n"
1374 " const label eIndex,\n"
1375 " const scalar minQuality,\n"
1376 " const labelList& vertexHull,\n"
1377 " PtrList<scalarListList>& Q,\n"
1378 " PtrList<labelListList>& K,\n"
1379 " PtrList<labelListList>& triangulations,\n"
1380 " const label checkIndex\n"
1383 << " Edge: " << newIndex
1384 << " :: " << edges_[newIndex] << nl
1385 << " is still processor-coupled. "
1386 << abort(FatalError);
1389 const edge& newEdge = edges_[newIndex];
1391 // Build vertexHull for this edge
1392 labelList newVertexHull;
1393 buildVertexHull(newIndex, newVertexHull);
1399 newVertexHull.size(),
1407 // Recursively call this function for the new edge
1422 setCoupledModification();
1428 label m = vertexHull.size();
1429 labelList hullFaces(m, -1);
1430 labelList hullCells(m, -1);
1431 labelList hullEdges(m, -1);
1432 labelListList ringEntities(4, labelList(m, -1));
1434 // Construct the hull
1435 meshOps::constructHull
1452 label numTriangulations = 0, isolatedVertex = -1;
1454 // Extract the appropriate triangulations
1455 extractTriangulation
1461 triangulations[checkIndex]
1464 // Check old-volumes for the configuration.
1467 checkTriangulationVolumes
1471 triangulations[checkIndex]
1475 // Reset all triangulations and bail out
1476 triangulations[checkIndex][0] = -1;
1477 triangulations[checkIndex][1] = -1;
1478 triangulations[checkIndex][2] = -1;
1483 // Determine the final swap triangulation
1490 triangulations[checkIndex]
1494 // Check that the triangulation is valid
1499 const edge& edgeToCheck = edges_[eIndex];
1501 Pout<< " All triangulations: " << nl
1502 << ' ' << triangulations[checkIndex][0] << nl
1503 << ' ' << triangulations[checkIndex][1] << nl
1504 << ' ' << triangulations[checkIndex][2] << nl
1510 "const changeMap dynamicTopoFvMesh::removeEdgeFlips\n"
1512 " const label eIndex,\n"
1513 " const scalar minQuality,\n"
1514 " const labelList& vertexHull,\n"
1515 " PtrList<scalarListList>& Q,\n"
1516 " PtrList<labelListList>& K,\n"
1517 " PtrList<labelListList>& triangulations,\n"
1518 " const label checkIndex\n"
1521 << "Could not determine 3-2 swap triangulation." << nl
1522 << "Edge: " << edgeToCheck << nl
1524 << points_[edgeToCheck[0]] << ","
1525 << points_[edgeToCheck[1]] << nl
1526 << abort(FatalError);
1528 // Reset all triangulations and bail out
1529 triangulations[checkIndex][0] = -1;
1530 triangulations[checkIndex][1] = -1;
1531 triangulations[checkIndex][2] = -1;
1538 Pout<< " Identified tF as: " << tF << nl;
1540 Pout<< " Triangulation: "
1541 << triangulations[checkIndex][0][tF] << " "
1542 << triangulations[checkIndex][1][tF] << " "
1543 << triangulations[checkIndex][2][tF] << " "
1546 Pout<< " All triangulations: " << nl
1547 << ' ' << triangulations[checkIndex][0] << nl
1548 << ' ' << triangulations[checkIndex][1] << nl
1549 << ' ' << triangulations[checkIndex][2] << nl
1553 if (coupledModification_)
1555 if (locallyCoupledEntity(eIndex))
1557 // Flip the slave edge as well.
1560 // Determine the slave index.
1561 forAll(patchCoupling_, patchI)
1563 if (patchCoupling_(patchI))
1565 const label edgeEnum = coupleMap::EDGE;
1566 const coupleMap& cMap = patchCoupling_[patchI].map();
1568 if ((sIndex = cMap.findSlave(edgeEnum, eIndex)) > -1)
1580 "const changeMap dynamicTopoFvMesh::removeEdgeFlips\n"
1582 " const label eIndex,\n"
1583 " const scalar minQuality,\n"
1584 " const labelList& vertexHull,\n"
1585 " PtrList<scalarListList>& Q,\n"
1586 " PtrList<labelListList>& K,\n"
1587 " PtrList<labelListList>& triangulations,\n"
1588 " const label checkIndex\n"
1591 << "Coupled maps were improperly specified." << nl
1592 << " Slave index not found for: " << nl
1593 << " Edge: " << eIndex << nl
1594 << abort(FatalError);
1599 Pout<< nl << "Removing slave edge: " << sIndex
1600 << " for master edge: " << eIndex << endl;
1603 // Build vertexHull for this edge
1604 labelList slaveVertexHull;
1605 buildVertexHull(sIndex, slaveVertexHull);
1607 // Turn off switch temporarily.
1608 unsetCoupledModification();
1610 // Recursively call for the slave edge.
1626 setCoupledModification();
1628 // Bail out if the slave failed.
1629 if (slaveMap.type() == -1)
1631 // Reset all triangulations and bail out
1632 triangulations[checkIndex][0] = -1;
1633 triangulations[checkIndex][1] = -1;
1634 triangulations[checkIndex][2] = -1;
1641 // Perform a series of 2-3 swaps
1644 while (numSwaps < (m-3))
1646 for (label i = 0; i < (m-2); i++)
1648 if ( (i != tF) && (triangulations[checkIndex][0][i] != -1) )
1650 // Check if triangulation is on the boundary
1653 boundaryTriangulation
1657 triangulations[checkIndex]
1670 triangulations[checkIndex],
1677 // Done with this face, so reset it
1678 triangulations[checkIndex][0][i] = -1;
1679 triangulations[checkIndex][1][i] = -1;
1680 triangulations[checkIndex][2][i] = -1;
1689 Pout<< "Triangulations: " << nl;
1691 forAll(triangulations[checkIndex], row)
1693 Pout<< triangulations[checkIndex][row] << nl;
1698 // Should have performed at least one swap
1702 "const changeMap dynamicTopoFvMesh::removeEdgeFlips\n"
1704 " const label eIndex,\n"
1705 " const scalar minQuality,\n"
1706 " const labelList& vertexHull,\n"
1707 " PtrList<scalarListList>& Q,\n"
1708 " PtrList<labelListList>& K,\n"
1709 " PtrList<labelListList>& triangulations,\n"
1710 " const label checkIndex\n"
1713 << "Did not perform any 2-3 swaps" << nl
1714 << abort(FatalError);
1718 // Perform the final 3-2 / 2-2 swap
1726 triangulations[checkIndex],
1733 // Done with this face, so reset it
1734 triangulations[checkIndex][0][tF] = -1;
1735 triangulations[checkIndex][1][tF] = -1;
1736 triangulations[checkIndex][2][tF] = -1;
1738 // Update the coupled map
1739 if (coupledModification_)
1741 // Create a mapping entry for the new edge.
1742 const coupleMap& cMap = patchCoupling_[pIndex].map();
1744 if (locallyCoupledEntity(map.addedEdgeList()[0].index()))
1749 map.addedEdgeList()[0].index(),
1750 slaveMap.addedEdgeList()[0].index()
1756 slaveMap.addedEdgeList()[0].index(),
1757 map.addedEdgeList()[0].index()
1761 // Add a mapping entry for two new faces as well.
1764 const List<objectMap>& amfList = map.addedFaceList();
1765 const List<objectMap>& asfList = slaveMap.addedFaceList();
1767 forAll(amfList, mfI)
1769 // Configure a face for comparison.
1770 const face& mF = faces_[amfList[mfI].index()];
1774 cF[pointI] = cMap.entityMap(coupleMap::POINT)[mF[pointI]];
1777 bool matched = false;
1779 forAll(asfList, sfI)
1781 const face& sF = faces_[asfList[sfI].index()];
1783 if (triFace::compare(triFace(cF), triFace(sF)))
1788 amfList[mfI].index(),
1789 asfList[sfI].index()
1795 asfList[sfI].index(),
1796 amfList[mfI].index()
1807 Pout<< "masterFaces: " << nl
1810 Pout<< "slaveFaces: " << nl
1813 forAll(amfList, mfI)
1815 Pout<< amfList[mfI].index() << ": "
1816 << faces_[amfList[mfI].index()]
1820 forAll(asfList, sfI)
1822 Pout<< asfList[sfI].index() << ": "
1823 << faces_[asfList[sfI].index()]
1832 "const changeMap dynamicTopoFvMesh::removeEdgeFlips\n"
1834 " const label eIndex,\n"
1835 " const scalar minQuality,\n"
1836 " const labelList& vertexHull,\n"
1837 " PtrList<scalarListList>& Q,\n"
1838 " PtrList<labelListList>& K,\n"
1839 " PtrList<labelListList>& triangulations,\n"
1840 " const label checkIndex\n"
1843 << "Failed to build coupled face maps."
1844 << abort(FatalError);
1849 // Finally remove the edge
1853 map.removeEdge(eIndex);
1855 // Increment the counter
1856 status(TOTAL_SWAPS)++;
1859 topoChangeFlag_ = true;
1861 // Return a successful operation.
1866 // Extract triangulations from the programming table
1867 void dynamicTopoFvMesh::extractTriangulation
1871 const labelListList& K,
1872 label& numTriangulations,
1873 labelListList& triangulations
1880 // Fill in the triangulation list
1881 triangulations[0][numTriangulations] = i;
1882 triangulations[1][numTriangulations] = k;
1883 triangulations[2][numTriangulations] = j;
1885 // Increment triangulation count
1886 numTriangulations++;
1888 // Recursively call the function for the two sub-triangulations
1889 extractTriangulation(i,k,K,numTriangulations,triangulations);
1890 extractTriangulation(k,j,K,numTriangulations,triangulations);
1895 // Identify the 3-2 swap from the triangulation sequence
1896 // - Use an edge-plane intersection formula
1897 label dynamicTopoFvMesh::identify32Swap
1900 const labelList& hullVertices,
1901 const labelListList& triangulations,
1905 label m = hullVertices.size();
1906 const edge& edgeToCheck = edges_[eIndex];
1908 // Obtain intersection point.
1909 linePointRef segment
1911 points_[edgeToCheck.start()],
1912 points_[edgeToCheck.end()]
1915 vector intPt = vector::zero;
1917 // Configure a face with triangulation
1918 for (label i = 0; i < (m-2); i++)
1922 meshOps::segmentTriFaceIntersection
1926 points_[hullVertices[triangulations[0][i]]],
1927 points_[hullVertices[triangulations[1][i]]],
1928 points_[hullVertices[triangulations[2][i]]]
1941 if (debug > 1 || output)
1943 Pout<< nl << nl << "Hull Vertices: " << nl;
1945 forAll(hullVertices, vertexI)
1947 Pout<< hullVertices[vertexI] << ": "
1948 << points_[hullVertices[vertexI]]
1955 "label dynamicTopoFvMesh::identify32Swap\n"
1957 " const label eIndex,\n"
1958 " const labelList& hullVertices,\n"
1959 " const labelListList& triangulations,\n"
1963 << "Could not determine 3-2 swap triangulation." << nl
1964 << "Edge: " << edgeToCheck << nl
1966 << segment.start() << "," << segment.end() << nl
1970 // Could not find an intersecting triangulation.
1971 // - If this is a boundary edge, a curved surface-mesh
1972 // was probably the reason why this failed.
1973 // - If so, declare the nearest triangulation instead.
1974 vector eCentre = segment.centre();
1976 scalarField dist(m-2, 0.0);
1978 label mT = -1, ePatch = whichEdgePatch(eIndex);
1979 bool foundTriangulation = false;
1981 for (label i = 0; i < (m-2); i++)
1983 // Compute edge to face-centre distance.
1991 points_[hullVertices[triangulations[0][i]]],
1992 points_[hullVertices[triangulations[1][i]]],
1993 points_[hullVertices[triangulations[2][i]]]
1999 while (!foundTriangulation)
2003 // Check validity for boundary edges
2007 ((triangulations[0][mT] != 0) || (triangulations[2][mT] != m-1))
2010 // This is a 2-3 triangulation. Try again.
2015 foundTriangulation = true;
2019 if (debug > 1 || output)
2021 Pout<< " All distances :" << dist << nl
2022 << " Triangulation index: " << mT
2031 // Routine to check whether the triangulation at the
2032 // index lies on the boundary of the vertex ring.
2033 bool dynamicTopoFvMesh::boundaryTriangulation
2036 label& isolatedVertex,
2037 labelListList& triangulations
2040 label first = 0, second = 0, third = 0;
2042 // Count for occurrences
2043 forAll(triangulations, row)
2045 forAll(triangulations[row], col)
2047 if (triangulations[row][col] == triangulations[0][index])
2052 if (triangulations[row][col] == triangulations[1][index])
2057 if (triangulations[row][col] == triangulations[2][index])
2066 isolatedVertex = triangulations[0][index];
2072 isolatedVertex = triangulations[1][index];
2078 isolatedVertex = triangulations[2][index];
2082 // This isn't a boundary triangulation
2087 // Utility method to compute the minimum quality of a vertex hull
2088 scalar dynamicTopoFvMesh::computeMinQuality
2091 labelList& hullVertices
2094 scalar minQuality = GREAT;
2096 // Obtain a reference to this edge
2097 const edge& edgeToCheck = edges_[eIndex];
2098 const labelList& edgeFaces = edgeFaces_[eIndex];
2100 // If this entity was deleted, skip it.
2101 if (edgeFaces.empty())
2106 // Ensure that edge is surrounded by triangles
2107 forAll(edgeFaces, faceI)
2109 if (faces_[edgeFaces[faceI]].size() != 3)
2115 // Build vertexHull for this edge
2116 buildVertexHull(eIndex, hullVertices);
2118 if (coupledModification_)
2120 if (locallyCoupledEntity(eIndex))
2122 // Compute the minimum quality of the slave edge as well.
2125 // Determine the slave index.
2126 forAll(patchCoupling_, patchI)
2128 if (patchCoupling_(patchI))
2130 const label edgeEnum = coupleMap::EDGE;
2131 const coupleMap& cMap = patchCoupling_[patchI].map();
2133 if ((sIndex = cMap.findSlave(edgeEnum, eIndex)) > -1)
2144 "scalar dynamicTopoFvMesh::computeMinQuality"
2145 "(const label eIndex, labelList& hullVertices) const"
2147 << nl << "Coupled maps were improperly specified." << nl
2148 << " Slave index not found for: " << nl
2149 << " Edge: " << eIndex << nl
2150 << abort(FatalError);
2153 // Build vertexHull for this edge
2154 labelList slaveVertexHull;
2155 buildVertexHull(eIndex, slaveVertexHull);
2157 // Temporarily turn off coupledModification
2158 unsetCoupledModification();
2160 scalar slaveQuality = computeMinQuality(sIndex, slaveVertexHull);
2162 minQuality = Foam::min(slaveQuality, minQuality);
2165 setCoupledModification();
2168 if (processorCoupledEntity(eIndex))
2170 // Don't compute minQuality here, but do it in
2171 // fillTables instead, while calculating hullPoints
2176 // Compute minQuality
2186 (whichEdgePatch(eIndex) < 0)
2192 // Ensure that the mesh is valid
2193 if (minQuality < 0.0)
2195 // Write out faces and cells for post processing.
2196 labelHashSet iFaces, iCells, bFaces;
2198 const labelList& eFaces = edgeFaces_[eIndex];
2200 forAll(eFaces, faceI)
2202 iFaces.insert(eFaces[faceI]);
2204 if (!iCells.found(owner_[eFaces[faceI]]))
2206 iCells.insert(owner_[eFaces[faceI]]);
2209 if (!iCells.found(neighbour_[eFaces[faceI]]))
2211 iCells.insert(neighbour_[eFaces[faceI]]);
2215 writeVTK(Foam::name(eIndex) + "_iCells", iCells.toc());
2216 writeVTK(Foam::name(eIndex) + "_iFaces", iFaces.toc(), 2);
2218 // Write out the boundary patches (for post-processing reference)
2221 label faceI = nOldInternalFaces_;
2222 faceI < faces_.size();
2226 if (faces_[faceI].empty())
2231 label pIndex = whichPatch(faceI);
2235 bFaces.insert(faceI);
2239 writeVTK(Foam::name(eIndex) + "_bFaces", bFaces.toc(), 2);
2243 "scalar dynamicTopoFvMesh::computeMinQuality"
2244 "(const label eIndex, labelList& hullVertices) const"
2246 << "Encountered negative cell-quality!" << nl
2247 << "Edge: " << eIndex << ": " << edgeToCheck << nl
2248 << "vertexHull: " << hullVertices << nl
2249 << "Minimum Quality: " << minQuality
2250 << abort(FatalError);
2257 // Compute minQuality given addressing
2258 scalar dynamicTopoFvMesh::computeMinQuality
2260 const edge& edgeToCheck,
2261 const labelList& hullVertices,
2262 const UList<point>& points,
2266 scalar cQuality = 0.0;
2267 scalar minQuality = GREAT;
2269 // Obtain point references
2270 const point& a = points[edgeToCheck[0]];
2271 const point& c = points[edgeToCheck[1]];
2273 label start = (closedRing ? 0 : 1);
2275 for (label indexJ = start; indexJ < hullVertices.size(); indexJ++)
2277 label indexI = hullVertices.rcIndex(indexJ);
2279 // Pick vertices off the list
2280 const point& b = points[hullVertices[indexI]];
2281 const point& d = points[hullVertices[indexJ]];
2283 // Compute the quality
2284 cQuality = tetMetric_(a, b, c, d);
2286 // Check if the quality is worse
2287 minQuality = Foam::min(cQuality, minQuality);
2294 // Method used to perform a 2-3 swap in 3D
2295 // - Returns a changeMap with a type specifying:
2296 // 1: Swap was successful
2297 // - The index of the triangulated face in map.index()
2298 const changeMap dynamicTopoFvMesh::swap23
2300 const label isolatedVertex,
2302 const label triangulationIndex,
2303 const label numTriangulations,
2304 const labelListList& triangulations,
2305 const labelList& hullVertices,
2306 const labelList& hullFaces,
2307 const labelList& hullCells
2310 // A 2-3 swap performs the following operations:
2311 // [1] Remove face: [ edgeToCheck[0] edgeToCheck[1] isolatedVertex ]
2312 // [2] Remove two cells on either side of removed face
2314 // [4] Add three new faces
2315 // [5] Add three new cells
2316 // Update faceEdges and edgeFaces information
2320 // Obtain a copy of the edge
2321 edge edgeToCheck = edges_[eIndex];
2323 label faceForRemoval = hullFaces[isolatedVertex];
2324 label vertexForRemoval = hullVertices[isolatedVertex];
2326 // Determine the two cells to be removed
2327 FixedList<label,2> cellsForRemoval;
2328 cellsForRemoval[0] = owner_[faceForRemoval];
2329 cellsForRemoval[1] = neighbour_[faceForRemoval];
2333 // Print out arguments
2335 << "== Swapping 2-3 ==" << nl
2336 << "Edge: " << eIndex << ": " << edgeToCheck << endl;
2340 Pout<< " On SubMesh: " << isSubMesh_ << nl;
2341 Pout<< " coupledModification: " << coupledModification_ << nl;
2343 label bPatch = whichEdgePatch(eIndex);
2345 const polyBoundaryMesh& boundary = boundaryMesh();
2349 Pout<< " Patch: Internal" << nl;
2352 if (bPatch < boundary.size())
2354 Pout<< " Patch: " << boundary[bPatch].name() << nl;
2358 Pout<< " New patch: " << bPatch << endl;
2361 Pout<< " Ring: " << hullVertices << nl
2362 << " Faces: " << hullFaces << nl
2363 << " Cells: " << hullCells << nl
2364 << " Triangulation: "
2365 << triangulations[0][triangulationIndex] << " "
2366 << triangulations[1][triangulationIndex] << " "
2367 << triangulations[2][triangulationIndex] << " "
2369 << " Isolated vertex: " << isolatedVertex << endl;
2377 + '(' + Foam::name(edgeToCheck[0])
2378 + ',' + Foam::name(edgeToCheck[1]) + ')'
2380 + Foam::name(numTriangulations) + "_"
2381 + Foam::name(triangulationIndex),
2382 labelList(cellsForRemoval),
2388 // Check if this is an internal face
2389 if (cellsForRemoval[1] == -1)
2391 // Write out for post-processing
2392 Pout<< " isolatedVertex: " << isolatedVertex << nl
2393 << " triangulations: " << triangulations << nl
2394 << " numTriangulations: " << numTriangulations << nl
2395 << " triangulationIndex: " << triangulationIndex << endl;
2397 writeVTK("Edge23_" + Foam::name(eIndex), eIndex, 1);
2398 writeVTK("Cells23_" + Foam::name(eIndex), hullCells, 3);
2400 // Write out identify32Swap output for diagnostics
2401 identify32Swap(eIndex, hullVertices, triangulations, true);
2406 "const changeMap dynamicTopoFvMesh::swap23\n"
2408 " const label isolatedVertex,\n"
2409 " const label eIndex,\n"
2410 " const label triangulationIndex,\n"
2411 " const label numTriangulations,\n"
2412 " const labelListList& triangulations,\n"
2413 " const labelList& hullVertices,\n"
2414 " const labelList& hullFaces,\n"
2415 " const labelList& hullCells\n"
2418 << " Expected an internal face,"
2419 << " but found a boundary one instead." << nl
2420 << " Looks like identify32Swap couldn't correctly identify"
2421 << " the 2-2 swap triangulation." << nl
2422 << abort(FatalError);
2425 // Add three new cells to the end of the cell list
2426 FixedList<label,3> newCellIndex(-1);
2427 FixedList<cell, 3> newTetCell(cell(4));
2429 forAll(newCellIndex, cellI)
2431 scalar avgScale = -1.0;
2433 if (edgeRefinement_)
2439 lengthScale_[cellsForRemoval[0]]
2440 + lengthScale_[cellsForRemoval[1]]
2446 newCellIndex[cellI] = insertCell(newTetCell[cellI], avgScale);
2448 // Add this cell to the map.
2449 map.addCell(newCellIndex[cellI]);
2452 // Obtain point-ordering for the other vertices
2453 // otherVertices[0] is the point before isolatedVertex
2454 // otherVertices[1] is the point after isolatedVertex
2455 FixedList<label,2> otherVertices;
2457 if (triangulations[0][triangulationIndex] == isolatedVertex)
2459 otherVertices[0] = hullVertices[triangulations[2][triangulationIndex]];
2460 otherVertices[1] = hullVertices[triangulations[1][triangulationIndex]];
2463 if (triangulations[1][triangulationIndex] == isolatedVertex)
2465 otherVertices[0] = hullVertices[triangulations[0][triangulationIndex]];
2466 otherVertices[1] = hullVertices[triangulations[2][triangulationIndex]];
2470 otherVertices[0] = hullVertices[triangulations[1][triangulationIndex]];
2471 otherVertices[1] = hullVertices[triangulations[0][triangulationIndex]];
2474 // Insert three new internal faces
2475 FixedList<label,3> newFaceIndex;
2478 // First face: The actual triangulation
2479 tmpTriFace[0] = otherVertices[0];
2480 tmpTriFace[1] = vertexForRemoval;
2481 tmpTriFace[2] = otherVertices[1];
2495 // Add this face to the map.
2496 map.addFace(newFaceIndex[0]);
2498 // Note the triangulation face in index()
2499 map.index() = newFaceIndex[0];
2501 // Second face: Triangle involving edgeToCheck[0]
2502 tmpTriFace[0] = otherVertices[0];
2503 tmpTriFace[1] = edgeToCheck[0];
2504 tmpTriFace[2] = otherVertices[1];
2518 // Add this face to the map.
2519 map.addFace(newFaceIndex[1]);
2521 // Third face: Triangle involving edgeToCheck[1]
2522 tmpTriFace[0] = otherVertices[1];
2523 tmpTriFace[1] = edgeToCheck[1];
2524 tmpTriFace[2] = otherVertices[0];
2538 // Add this face to the map.
2539 map.addFace(newFaceIndex[2]);
2541 // Add an entry to edgeFaces
2542 labelList newEdgeFaces(3);
2543 newEdgeFaces[0] = newFaceIndex[0];
2544 newEdgeFaces[1] = newFaceIndex[1];
2545 newEdgeFaces[2] = newFaceIndex[2];
2547 // Add a new internal edge to the mesh
2548 label newEdgeIndex =
2562 // Add this edge to the map.
2563 map.addEdge(newEdgeIndex);
2565 // Define the six edges to check while building faceEdges:
2566 FixedList<edge,6> check;
2568 check[0][0] = vertexForRemoval; check[0][1] = otherVertices[0];
2569 check[1][0] = vertexForRemoval; check[1][1] = otherVertices[1];
2570 check[2][0] = edgeToCheck[0]; check[2][1] = otherVertices[0];
2571 check[3][0] = edgeToCheck[1]; check[3][1] = otherVertices[0];
2572 check[4][0] = edgeToCheck[0]; check[4][1] = otherVertices[1];
2573 check[5][0] = edgeToCheck[1]; check[5][1] = otherVertices[1];
2575 // Add three new entries to faceEdges
2576 label nE0 = 0, nE1 = 0, nE2 = 0;
2577 FixedList<labelList,3> newFaceEdges(labelList(3));
2579 newFaceEdges[0][nE0++] = newEdgeIndex;
2580 newFaceEdges[1][nE1++] = newEdgeIndex;
2581 newFaceEdges[2][nE2++] = newEdgeIndex;
2583 // Fill-in information for the three new cells,
2584 // and correct info on existing neighbouring cells
2585 label nF0 = 0, nF1 = 0, nF2 = 0;
2586 FixedList<bool,2> foundEdge;
2588 // Add the newly created faces to cells
2589 newTetCell[0][nF0++] = newFaceIndex[0];
2590 newTetCell[0][nF0++] = newFaceIndex[2];
2591 newTetCell[1][nF1++] = newFaceIndex[0];
2592 newTetCell[1][nF1++] = newFaceIndex[1];
2593 newTetCell[2][nF2++] = newFaceIndex[1];
2594 newTetCell[2][nF2++] = newFaceIndex[2];
2596 forAll(cellsForRemoval, cellI)
2598 label cellIndex = cellsForRemoval[cellI];
2600 forAll(cells_[cellIndex], faceI)
2602 label faceIndex = cells_[cellIndex][faceI];
2604 foundEdge[0] = false; foundEdge[1] = false;
2606 // Check if face contains edgeToCheck[0]
2609 (faces_[faceIndex][0] == edgeToCheck[0])
2610 || (faces_[faceIndex][1] == edgeToCheck[0])
2611 || (faces_[faceIndex][2] == edgeToCheck[0])
2614 foundEdge[0] = true;
2617 // Check if face contains edgeToCheck[1]
2620 (faces_[faceIndex][0] == edgeToCheck[1])
2621 || (faces_[faceIndex][1] == edgeToCheck[1])
2622 || (faces_[faceIndex][2] == edgeToCheck[1])
2625 foundEdge[1] = true;
2628 // Face is connected to edgeToCheck[0]
2629 if (foundEdge[0] && !foundEdge[1])
2631 // Check if a face-flip is necessary
2632 if (owner_[faceIndex] == cellIndex)
2634 if (neighbour_[faceIndex] == -1)
2637 owner_[faceIndex] = newCellIndex[1];
2642 faces_[faceIndex] = faces_[faceIndex].reverseFace();
2643 owner_[faceIndex] = neighbour_[faceIndex];
2644 neighbour_[faceIndex] = newCellIndex[1];
2651 // Flip is unnecessary. Just update neighbour
2652 neighbour_[faceIndex] = newCellIndex[1];
2655 // Add this face to the cell
2656 newTetCell[1][nF1++] = faceIndex;
2658 // Update faceEdges and edgeFaces
2659 forAll(faceEdges_[faceIndex], edgeI)
2661 if (edges_[faceEdges_[faceIndex][edgeI]] == check[0])
2663 newFaceEdges[0][nE0++] = faceEdges_[faceIndex][edgeI];
2668 edgeFaces_[faceEdges_[faceIndex][edgeI]]
2672 if (edges_[faceEdges_[faceIndex][edgeI]] == check[1])
2674 newFaceEdges[0][nE0++] = faceEdges_[faceIndex][edgeI];
2679 edgeFaces_[faceEdges_[faceIndex][edgeI]]
2683 if (edges_[faceEdges_[faceIndex][edgeI]] == check[2])
2685 newFaceEdges[1][nE1++] = faceEdges_[faceIndex][edgeI];
2690 edgeFaces_[faceEdges_[faceIndex][edgeI]]
2694 if (edges_[faceEdges_[faceIndex][edgeI]] == check[4])
2696 newFaceEdges[1][nE1++] = faceEdges_[faceIndex][edgeI];
2701 edgeFaces_[faceEdges_[faceIndex][edgeI]]
2707 // Face is connected to edgeToCheck[1]
2708 if (!foundEdge[0] && foundEdge[1])
2710 // Check if a face-flip is necessary
2711 if (owner_[faceIndex] == cellIndex)
2713 if (neighbour_[faceIndex] == -1)
2716 owner_[faceIndex] = newCellIndex[0];
2721 faces_[faceIndex] = faces_[faceIndex].reverseFace();
2722 owner_[faceIndex] = neighbour_[faceIndex];
2723 neighbour_[faceIndex] = newCellIndex[0];
2730 // Flip is unnecessary. Just update neighbour
2731 neighbour_[faceIndex] = newCellIndex[0];
2734 // Add this face to the cell
2735 newTetCell[0][nF0++] = faceIndex;
2737 // Update faceEdges and edgeFaces
2738 const labelList& fEdges = faceEdges_[faceIndex];
2740 forAll(fEdges, edgeI)
2742 if (edges_[fEdges[edgeI]] == check[3])
2744 newFaceEdges[2][nE2++] = fEdges[edgeI];
2749 edgeFaces_[fEdges[edgeI]]
2753 if (edges_[fEdges[edgeI]] == check[5])
2755 newFaceEdges[2][nE2++] = fEdges[edgeI];
2760 edgeFaces_[fEdges[edgeI]]
2766 // Face is connected to both edgeToCheck [0] and [1]
2769 (foundEdge[0] && foundEdge[1]) &&
2770 (faceIndex != faceForRemoval)
2773 // Check if a face-flip is necessary
2774 if (owner_[faceIndex] == cellIndex)
2776 if (neighbour_[faceIndex] == -1)
2779 owner_[faceIndex] = newCellIndex[2];
2784 faces_[faceIndex] = faces_[faceIndex].reverseFace();
2785 owner_[faceIndex] = neighbour_[faceIndex];
2786 neighbour_[faceIndex] = newCellIndex[2];
2793 // Flip is unnecessary. Just update neighbour
2794 neighbour_[faceIndex] = newCellIndex[2];
2797 // Add this face to the cell
2798 newTetCell[2][nF2++] = faceIndex;
2803 // Now update faceEdges for the three new faces
2804 forAll(newFaceEdges, faceI)
2806 faceEdges_[newFaceIndex[faceI]] = newFaceEdges[faceI];
2809 // Update edgeFaces for edges of the removed face
2810 forAll(faceEdges_[faceForRemoval], edgeI)
2812 label edgeIndex = faceEdges_[faceForRemoval][edgeI];
2814 meshOps::sizeDownList
2817 edgeFaces_[edgeIndex]
2822 removeFace(faceForRemoval);
2825 map.removeFace(faceForRemoval);
2827 forAll(cellsForRemoval, cellI)
2829 removeCell(cellsForRemoval[cellI]);
2832 map.removeCell(cellsForRemoval[cellI]);
2835 // Update the cell list with newly configured cells.
2836 forAll(newCellIndex, cellI)
2838 cells_[newCellIndex[cellI]] = newTetCell[cellI];
2842 // Skip mapping for the intermediate cell.
2843 setCellMapping(newCellIndex[cellI], hullCells, false);
2847 // Set the mapping for this cell
2848 setCellMapping(newCellIndex[cellI], hullCells);
2852 // Fill in mapping information for three new faces.
2853 // Since they're all internal, interpolate fluxes by default.
2854 forAll(newFaceIndex, faceI)
2856 setFaceMapping(newFaceIndex[faceI]);
2861 Pout<< "Added edge: " << nl;
2863 Pout<< newEdgeIndex << ":: "
2864 << edges_[newEdgeIndex]
2866 << edgeFaces_[newEdgeIndex]
2869 Pout<< "Added faces: " << nl;
2871 forAll(newFaceIndex, faceI)
2873 Pout<< newFaceIndex[faceI] << ":: "
2874 << faces_[newFaceIndex[faceI]]
2876 << faceEdges_[newFaceIndex[faceI]]
2880 Pout<< "Added cells: " << nl;
2882 forAll(newCellIndex, cellI)
2884 Pout<< newCellIndex[cellI] << ":: "
2885 << cells_[newCellIndex[cellI]]
2896 + '(' + Foam::name(edgeToCheck[0])
2897 + ',' + Foam::name(edgeToCheck[1]) + ')'
2899 + Foam::name(numTriangulations) + "_"
2900 + Foam::name(triangulationIndex),
2901 labelList(newCellIndex),
2907 // Specify that the swap was successful
2910 // Return the changeMap
2915 // Method used to perform a 2-2 / 3-2 swap in 3D
2916 // - Returns a changeMap with a type specifying:
2917 // 1: Swap was successful
2918 // - The index of the triangulated face in map.index()
2919 const changeMap dynamicTopoFvMesh::swap32
2922 const label triangulationIndex,
2923 const label numTriangulations,
2924 const labelListList& triangulations,
2925 const labelList& hullVertices,
2926 const labelList& hullFaces,
2927 const labelList& hullCells
2930 // A 2-2 / 3-2 swap performs the following operations:
2931 // [1] Remove three faces surrounding edgeToCheck
2932 // [2] Remove two (2-2 swap) or three(3-2 swap)
2933 // cells surrounding edgeToCheck
2934 // [3] Add one internal face
2935 // [4] Add two new cells
2936 // [5] If edgeToCheck is on a boundary,
2937 // add two boundary faces and a boundary edge (2-2 swap)
2938 // eIndex is removed later by removeEdgeFlips
2939 // Update faceEdges and edgeFaces information
2943 // Obtain a copy of the edge
2944 edge edgeToCheck = edges_[eIndex];
2946 // Determine the patch this edge belongs to
2947 label edgePatch = whichEdgePatch(eIndex);
2949 // Determine the three faces to be removed
2950 FixedList<label,3> facesForRemoval;
2951 dynamicLabelList cellRemovalList(3);
2953 forAll(facesForRemoval, faceI)
2955 facesForRemoval[faceI] =
2957 hullFaces[triangulations[faceI][triangulationIndex]]
2960 label own = owner_[facesForRemoval[faceI]];
2961 label nei = neighbour_[facesForRemoval[faceI]];
2963 // Check and add cells as well
2964 if (findIndex(cellRemovalList, own) == -1)
2966 cellRemovalList.append(own);
2971 if (findIndex(cellRemovalList, nei) == -1)
2973 cellRemovalList.append(nei);
2980 // Print out arguments
2985 Pout<< "== Swapping 3-2 ==" << nl;
2989 Pout<< "== Swapping 2-2 ==" << nl;
2992 Pout<< " Edge: " << eIndex << ": " << edgeToCheck << endl;
2996 Pout<< " On SubMesh: " << isSubMesh_ << nl;
2997 Pout<< " coupledModification: " << coupledModification_ << nl;
2999 label bPatch = whichEdgePatch(eIndex);
3001 const polyBoundaryMesh& boundary = boundaryMesh();
3005 Pout<< " Patch: Internal" << nl;
3008 if (bPatch < boundary.size())
3010 Pout<< " Patch: " << boundary[bPatch].name() << nl;
3014 Pout<< " New patch: " << bPatch << endl;
3017 Pout<< " Ring: " << hullVertices << nl
3018 << " Faces: " << hullFaces << nl
3019 << " Cells: " << hullCells << nl
3020 << " Triangulation: "
3021 << triangulations[0][triangulationIndex] << " "
3022 << triangulations[1][triangulationIndex] << " "
3023 << triangulations[2][triangulationIndex] << " "
3032 + '(' + Foam::name(edgeToCheck[0])
3033 + ',' + Foam::name(edgeToCheck[1]) + ')'
3035 + Foam::name(numTriangulations) + "_"
3036 + Foam::name(triangulationIndex),
3043 // Add two new cells to the end of the cell list
3044 FixedList<label,2> newCellIndex(-1);
3045 FixedList<cell, 2> newTetCell(cell(4));
3047 forAll(newCellIndex, cellI)
3049 scalar avgScale = 0.0;
3051 if (edgeRefinement_)
3053 forAll(cellRemovalList, indexI)
3055 avgScale += lengthScale_[cellRemovalList[indexI]];
3058 avgScale /= cellRemovalList.size();
3062 newCellIndex[cellI] = insertCell(newTetCell[cellI], avgScale);
3064 // Add this cell to the map.
3065 map.addCell(newCellIndex[cellI]);
3068 // Insert a new internal face
3071 newTriFace[0] = hullVertices[triangulations[0][triangulationIndex]];
3072 newTriFace[1] = hullVertices[triangulations[1][triangulationIndex]];
3073 newTriFace[2] = hullVertices[triangulations[2][triangulationIndex]];
3075 label newFaceIndex =
3087 // Add this face to the map.
3088 map.addFace(newFaceIndex);
3090 // Note the triangulation face in index()
3091 map.index() = newFaceIndex;
3093 // Define the three edges to check while building faceEdges:
3094 FixedList<edge,3> check;
3096 check[0][0] = newTriFace[0]; check[0][1] = newTriFace[1];
3097 check[1][0] = newTriFace[1]; check[1][1] = newTriFace[2];
3098 check[2][0] = newTriFace[2]; check[2][1] = newTriFace[0];
3100 // For 2-2 swaps, two faces are introduced
3101 label nE = 0, nBf = 0;
3102 FixedList<label,2> nBE(0);
3103 FixedList<labelList,2> bdyFaceEdges(labelList(3, -1));
3105 // Fill-in information for the two new cells,
3106 // and correct info on existing neighbouring cells
3107 label nF0 = 0, nF1 = 0;
3108 label otherPoint = -1, nextPoint = -1;
3109 FixedList<bool,2> foundEdge;
3111 // For a 2-2 swap on a boundary edge,
3112 // add two boundary faces and an edge
3113 label newEdgeIndex = -1;
3114 labelList oldBdyFaceIndex(2, -1), newBdyFaceIndex(2, -1);
3118 // Temporary local variables
3119 label facePatch = -1;
3120 edge newEdge(-1, -1);
3121 FixedList<label,2> nBEdge(0);
3122 FixedList<FixedList<label,2>,2> bdyEdges;
3123 FixedList<face,2> newBdyTriFace(face(3));
3125 // Get a cue for face orientation from existing faces
3126 forAll(facesForRemoval, faceI)
3128 if (neighbour_[facesForRemoval[faceI]] == -1)
3130 facePatch = whichPatch(facesForRemoval[faceI]);
3132 // Record this face-index for mapping.
3133 oldBdyFaceIndex[nBf++] = facesForRemoval[faceI];
3135 meshOps::findIsolatedPoint
3137 faces_[facesForRemoval[faceI]],
3143 if (nextPoint == edgeToCheck[0])
3145 newEdge[1] = otherPoint;
3146 newBdyTriFace[0][0] = otherPoint;
3147 newBdyTriFace[0][1] = edgeToCheck[0];
3148 newBdyTriFace[1][2] = otherPoint;
3152 newEdge[0] = otherPoint;
3153 newBdyTriFace[1][0] = otherPoint;
3154 newBdyTriFace[1][1] = edgeToCheck[1];
3155 newBdyTriFace[0][2] = otherPoint;
3158 // Also update faceEdges for the new boundary faces
3159 forAll(faceEdges_[facesForRemoval[faceI]], edgeI)
3163 edges_[faceEdges_[facesForRemoval[faceI]][edgeI]]
3164 == edge(edgeToCheck[0], otherPoint)
3167 bdyFaceEdges[0][nBE[0]++] =
3169 faceEdges_[facesForRemoval[faceI]][edgeI]
3172 bdyEdges[0][nBEdge[0]++] =
3174 faceEdges_[facesForRemoval[faceI]][edgeI]
3180 edges_[faceEdges_[facesForRemoval[faceI]][edgeI]]
3181 == edge(edgeToCheck[1], otherPoint)
3184 bdyFaceEdges[1][nBE[1]++] =
3186 faceEdges_[facesForRemoval[faceI]][edgeI]
3189 bdyEdges[1][nBEdge[1]++] =
3191 faceEdges_[facesForRemoval[faceI]][edgeI]
3198 // Insert the first of two new faces
3199 newBdyFaceIndex[0] =
3211 // Add this face to the map.
3212 map.addFace(newBdyFaceIndex[0]);
3214 // Insert the second of two new faces
3215 newBdyFaceIndex[1] =
3227 // Add this face to the map.
3228 map.addFace(newBdyFaceIndex[1]);
3230 // Update the new cells
3231 newTetCell[0][nF0++] = newBdyFaceIndex[1];
3232 newTetCell[1][nF1++] = newBdyFaceIndex[0];
3234 // Add an edgeFaces entry
3235 labelList newBdyEdgeFaces(3, -1);
3236 newBdyEdgeFaces[0] = newBdyFaceIndex[0];
3237 newBdyEdgeFaces[1] = newFaceIndex;
3238 newBdyEdgeFaces[2] = newBdyFaceIndex[1];
3240 // Find the point other than the new edge
3241 // on the new triangular face
3242 meshOps::findIsolatedPoint
3261 // Add this edge to the map.
3262 map.addEdge(newEdgeIndex);
3264 // Update faceEdges with the new edge
3265 faceEdges_[newFaceIndex][nE++] = newEdgeIndex;
3266 bdyFaceEdges[0][nBE[0]++] = newEdgeIndex;
3267 bdyFaceEdges[1][nBE[1]++] = newEdgeIndex;
3269 // Update edgeFaces with the two new faces
3270 forAll(bdyEdges[0], edgeI)
3275 edgeFaces_[bdyEdges[0][edgeI]]
3281 edgeFaces_[bdyEdges[1][edgeI]]
3285 // Add faceEdges for the two new boundary faces
3286 faceEdges_[newBdyFaceIndex[0]] = bdyFaceEdges[0];
3287 faceEdges_[newBdyFaceIndex[1]] = bdyFaceEdges[1];
3289 // Update the number of surface swaps.
3290 status(SURFACE_SWAPS)++;
3293 newTetCell[0][nF0++] = newFaceIndex;
3294 newTetCell[1][nF1++] = newFaceIndex;
3296 forAll(cellRemovalList, cellI)
3298 label cellIndex = cellRemovalList[cellI];
3300 forAll(cells_[cellIndex], faceI)
3302 label faceIndex = cells_[cellIndex][faceI];
3304 foundEdge[0] = false; foundEdge[1] = false;
3306 // Find the face that contains only
3307 // edgeToCheck[0] or edgeToCheck[1]
3308 forAll(faces_[faceIndex], pointI)
3310 if (faces_[faceIndex][pointI] == edgeToCheck[0])
3312 foundEdge[0] = true;
3315 if (faces_[faceIndex][pointI] == edgeToCheck[1])
3317 foundEdge[1] = true;
3321 // Face is connected to edgeToCheck[0]
3322 if (foundEdge[0] && !foundEdge[1])
3324 // Check if a face-flip is necessary
3325 if (owner_[faceIndex] == cellIndex)
3327 if (neighbour_[faceIndex] == -1)
3330 owner_[faceIndex] = newCellIndex[1];
3335 faces_[faceIndex] = faces_[faceIndex].reverseFace();
3336 owner_[faceIndex] = neighbour_[faceIndex];
3337 neighbour_[faceIndex] = newCellIndex[1];
3344 // Flip is unnecessary. Just update neighbour
3345 neighbour_[faceIndex] = newCellIndex[1];
3348 // Add this face to the cell
3349 newTetCell[1][nF1++] = faceIndex;
3351 // Update faceEdges and edgeFaces
3352 forAll(faceEdges_[faceIndex], edgeI)
3356 (edges_[faceEdges_[faceIndex][edgeI]] == check[0])
3357 || (edges_[faceEdges_[faceIndex][edgeI]] == check[1])
3358 || (edges_[faceEdges_[faceIndex][edgeI]] == check[2])
3361 faceEdges_[newFaceIndex][nE++] =
3363 faceEdges_[faceIndex][edgeI]
3369 edgeFaces_[faceEdges_[faceIndex][edgeI]]
3377 // Face is connected to edgeToCheck[1]
3378 if (!foundEdge[0] && foundEdge[1])
3380 // Check if a face-flip is necessary
3381 if (owner_[faceIndex] == cellIndex)
3383 if (neighbour_[faceIndex] == -1)
3386 owner_[faceIndex] = newCellIndex[0];
3391 faces_[faceIndex] = faces_[faceIndex].reverseFace();
3392 owner_[faceIndex] = neighbour_[faceIndex];
3393 neighbour_[faceIndex] = newCellIndex[0];
3400 // Flip is unnecessary. Just update neighbour
3401 neighbour_[faceIndex] = newCellIndex[0];
3404 // Add this face to the cell
3405 newTetCell[0][nF0++] = faceIndex;
3410 // Remove the faces and update associated edges
3411 forAll(facesForRemoval, faceI)
3414 forAll(faceEdges_[facesForRemoval[faceI]], edgeI)
3416 label edgeIndex = faceEdges_[facesForRemoval[faceI]][edgeI];
3418 if (edgeIndex != eIndex)
3420 meshOps::sizeDownList
3422 facesForRemoval[faceI],
3423 edgeFaces_[edgeIndex]
3428 // Now remove the face...
3429 removeFace(facesForRemoval[faceI]);
3432 map.removeFace(facesForRemoval[faceI]);
3435 forAll(cellRemovalList, cellI)
3437 removeCell(cellRemovalList[cellI]);
3440 map.removeCell(cellRemovalList[cellI]);
3443 // Update the cell list with newly configured cells.
3444 forAll(newCellIndex, cellI)
3446 cells_[newCellIndex[cellI]] = newTetCell[cellI];
3448 // Set the mapping for this cell
3449 setCellMapping(newCellIndex[cellI], hullCells);
3452 // Set fill-in mapping for two new boundary faces
3455 forAll(newBdyFaceIndex, i)
3457 // Set the mapping for this face
3458 setFaceMapping(newBdyFaceIndex[i], oldBdyFaceIndex);
3462 // Fill in mapping information for the new face.
3463 // Since it is internal, interpolate fluxes by default.
3464 setFaceMapping(newFaceIndex);
3470 Pout<< "Added edge: "
3471 << newEdgeIndex << ":: "
3472 << edges_[newEdgeIndex]
3474 << edgeFaces_[newEdgeIndex]
3478 Pout<< "Added face(s): " << nl;
3480 Pout<< newFaceIndex << ":: "
3481 << faces_[newFaceIndex];
3483 Pout<< " faceEdges: "
3484 << faceEdges_[newFaceIndex]
3489 forAll(newBdyFaceIndex, faceI)
3491 Pout<< newBdyFaceIndex[faceI] << ":: "
3492 << faces_[newBdyFaceIndex[faceI]]
3494 << faceEdges_[newBdyFaceIndex[faceI]]
3499 Pout<< "Added cells: " << nl;
3501 forAll(newCellIndex, cellI)
3503 Pout<< newCellIndex[cellI] << ":: "
3504 << cells_[newCellIndex[cellI]]
3515 + '(' + Foam::name(edgeToCheck[0])
3516 + ',' + Foam::name(edgeToCheck[1]) + ')'
3518 + Foam::name(numTriangulations) + "_"
3519 + Foam::name(triangulationIndex),
3520 labelList(newCellIndex),
3526 // Specify that the swap was successful
3529 // Return the changeMap
3533 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
3535 } // End namespace Foam
3537 // ************************************************************************* //