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 "objectMap.H"
27 #include "coupledInfo.H"
28 #include "dynamicTopoFvMesh.H"
30 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
35 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
37 // Reorder points after a topology change
38 void dynamicTopoFvMesh::reOrderPoints
41 pointField& preMotionPoints,
42 labelListList& pointZoneMap,
46 // *** Point renumbering *** //
47 // If points were deleted during topology change, the numerical order ceases
48 // to be continuous. Loop through all points and renumber sequentially.
54 Info<< "Thread: " << self() << ": ";
57 Info<< "ReOrdering points..." << flush;
60 // Allocate for the mapping information
61 pointMap_.setSize(nPoints_, -1);
63 label pointInOrder = 0;
65 addedPointRenumbering_.clear();
67 for (label pointI = 0; pointI < nOldPoints_; pointI++)
69 // Check if this is a deleted point
70 if (reversePointMap_[pointI] == -1)
75 // Update the point info
76 points[pointInOrder] = points_[pointI];
77 preMotionPoints[pointInOrder] = oldPoints_[pointI];
80 pointMap_[pointInOrder] = pointI;
81 reversePointMap_[pointI] = pointInOrder;
87 for (label pointI = nOldPoints_; pointI < points_.size(); pointI++)
89 // Was this point removed after addition?
90 if (deletedPoints_.found(pointI))
95 // Update the point info
96 points[pointInOrder] = points_[pointI];
97 preMotionPoints[pointInOrder] = oldPoints_[pointI];
99 // Put inserted points in a seperate hashSet
100 addedPointRenumbering_.insert(pointI, pointInOrder);
102 // Update the counter
106 // Now that we're done preparing the point maps, unlock the point mutex
109 entityMutex_[0].unlock();
112 // Final check to ensure everything went okay
113 if (pointInOrder != nPoints_)
115 FatalErrorIn("dynamicTopoFvMesh::reOrderPoints()") << nl
116 << " Algorithm did not visit every point in the mesh."
117 << " Something's messed up." << nl
118 << abort(FatalError);
121 // Renumber all maps.
122 forAll(pointsFromPoints_, indexI)
124 objectMap& thisMap = pointsFromPoints_[indexI];
126 if (thisMap.index() < nOldPoints_)
128 thisMap.index() = reversePointMap_[thisMap.index()];
132 thisMap.index() = addedPointRenumbering_[thisMap.index()];
136 // Prepare the pointZoneMap
137 pointZoneMesh& pointZones = polyMesh::pointZones();
139 labelListList newPointZoneAddr(pointZones.size());
140 labelList nPointsInZone(pointZones.size(), 0);
142 // Prepare zone maps.
143 forAll(pointZones, pzI)
145 // Get the list of old points
146 const labelList& oldAddr = pointZones[pzI];
148 label& curNPoints = nPointsInZone[pzI];
150 // First count the actual number of points in each zone.
151 forAll(oldAddr, pointI)
153 // Was this zone point deleted? Don't count it.
154 if (reversePointMap_[oldAddr[pointI]] != -1)
160 // Check for added points as well
161 forAllIter(Map<label>, addedPointZones_, pIter)
170 labelList& newAddr = newPointZoneAddr[pzI];
172 // Set the sizes first
173 newAddr.setSize(curNPoints);
174 pointZoneMap[pzI].setSize(curNPoints, -1);
176 // Add existing zone points which have been renumbered.
177 forAll(oldAddr, pointI)
179 if (reversePointMap_[oldAddr[pointI]] != -1)
181 pointZoneMap[pzI][pIndex] = oldAddr[pointI];
182 newAddr[pIndex] = reversePointMap_[oldAddr[pointI]];
187 // Next, add the newly added zone points.
188 forAllIter(Map<label>, addedPointZones_, pIter)
192 newAddr[pIndex++] = addedPointRenumbering_[pIter.key()];
196 // Finally, assign addressing to this zone.
197 pointZones[pzI] = newPointZoneAddr[pzI];
201 pointZones.updateMesh();
203 // Loop through all local coupling maps, and renumber points.
204 forAll(patchCoupling_, patchI)
206 if (!patchCoupling_(patchI))
211 const coupleMap& cMap = patchCoupling_[patchI].map();
214 Map<label>& mtsMap = cMap.entityMap(coupleMap::POINT);
216 Map<label> newMtsMap, newStmMap;
218 forAllIter(Map<label>, mtsMap, pIter)
220 label newMaster = -1, newSlave = -1;
222 if (pIter.key() < nOldPoints_)
224 newMaster = reversePointMap_[pIter.key()];
228 newMaster = addedPointRenumbering_[pIter.key()];
231 if (pIter() < nOldPoints_)
233 newSlave = reversePointMap_[pIter()];
237 newSlave = addedPointRenumbering_[pIter()];
241 newMtsMap.insert(newMaster, newSlave);
242 newStmMap.insert(newSlave, newMaster);
245 // Overwrite the old maps.
246 cMap.transferMaps(coupleMap::POINT, newMtsMap, newStmMap);
249 // Clear local point copies
255 oldPoints_ = preMotionPoints;
259 Info<< "Done." << endl;
264 // Static equivalent for multi-threading
265 void dynamicTopoFvMesh::reOrderPointsThread
270 // Recast the argument
271 meshHandler *thread = static_cast<meshHandler*>(argument);
273 dynamicTopoFvMesh& mesh = thread->reference();
275 // Lock the point mutex first
276 mesh.entityMutex(0).lock();
278 // Signal the calling thread
279 thread->sendSignal(meshHandler::START);
281 // Recast the pointers for the reOrderPoints argument
284 *(static_cast<pointField*>(thread->operator()(0)))
287 pointField& preMotionPoints =
289 *(static_cast<pointField*>(thread->operator()(1)))
292 labelListList& pointZoneMap =
294 *(static_cast<labelListList*>(thread->operator()(2)))
297 // Reorder the points
298 mesh.reOrderPoints(points, preMotionPoints, pointZoneMap, true);
302 // Reorder edges after a topology change
303 void dynamicTopoFvMesh::reOrderEdges
306 labelListList& edgeFaces,
307 labelListList& faceEdges,
311 // *** Edge renumbering *** //
312 // If edges were deleted during topology change, the numerical order ceases
313 // to be continuous. Edges are added to respective internal/boundary patches
319 Info<< "Thread: " << self() << ": ";
322 Info<< "ReOrdering edges..." << flush;
325 // Allocate for mapping information
326 edgeMap_.setSize(nEdges_, -1);
328 label edgeInOrder = 0, allEdges = edges_.size();
329 edgeList oldEdges(allEdges);
330 labelListList oldEdgeFaces(allEdges);
332 addedEdgeRenumbering_.clear();
334 // Transfer old edge-based lists, and clear them
335 forAll(edges_, edgeI)
337 oldEdges[edgeI] = edges_[edgeI];
338 oldEdgeFaces[edgeI].transfer(edgeFaces_[edgeI]);
341 edges_.setSize(nEdges_); edgeFaces_.setSize(nEdges_);
343 // Keep track of inserted boundary edge indices
344 labelList boundaryPatchIndices(edgePatchStarts_);
346 // Loop through all edges and add them
347 forAll(oldEdges, edgeI)
349 // Ensure that we're adding valid edges
350 if (oldEdgeFaces[edgeI].empty())
355 // Determine which patch this edge belongs to
356 label patch = whichEdgePatch(edgeI);
359 edge& thisEdge = oldEdges[edgeI];
360 labelList& thisEF = oldEdgeFaces[edgeI];
364 label bEdgeIndex = boundaryPatchIndices[patch]++;
367 if (edgeI < nOldEdges_)
369 edgeMap_[bEdgeIndex] = edgeI;
370 reverseEdgeMap_[edgeI] = bEdgeIndex;
374 edgeMap_[bEdgeIndex] = -1;
375 addedEdgeRenumbering_.insert(edgeI, bEdgeIndex);
378 // Insert entities into local lists...
379 edges_[bEdgeIndex] = thisEdge;
380 edgeFaces_[bEdgeIndex] = thisEF;
382 // Insert entities into mesh-reset lists
383 edges[bEdgeIndex] = thisEdge;
384 edgeFaces[bEdgeIndex].transfer(thisEF);
388 // Renumber internal edges and add normally.
389 if (edgeI < nOldEdges_)
391 edgeMap_[edgeInOrder] = edgeI;
392 reverseEdgeMap_[edgeI] = edgeInOrder;
396 addedEdgeRenumbering_.insert(edgeI, edgeInOrder);
399 // Insert entities into local lists...
400 edges_[edgeInOrder] = thisEdge;
401 edgeFaces_[edgeInOrder] = thisEF;
403 // Insert entities into mesh-reset lists
404 edges[edgeInOrder] = thisEdge;
405 edgeFaces[edgeInOrder].transfer(thisEF);
411 // Now that we're done with edges, unlock it
414 entityMutex_[1].unlock();
417 // Final check to ensure everything went okay
418 if (edgeInOrder != nInternalEdges_)
420 FatalErrorIn("dynamicTopoFvMesh::reOrderEdges()") << nl
421 << " Algorithm did not visit every internal edge in the mesh."
422 << " Something's messed up." << nl
423 << abort(FatalError);
426 // Renumber all edges with updated point information
431 entityMutex_[0].lock();
434 forAll(edges_, edgeI)
437 edge& thisEdge = edges_[edgeI];
438 edge& thisREdge = edges[edgeI];
441 if (thisEdge[0] < nOldPoints_)
443 pIndex = reversePointMap_[thisEdge[0]];
447 pIndex = addedPointRenumbering_[thisEdge[0]];
450 thisEdge[0] = pIndex;
451 thisREdge[0] = pIndex;
453 if (thisEdge[1] < nOldPoints_)
455 pIndex = reversePointMap_[thisEdge[1]];
459 pIndex = addedPointRenumbering_[thisEdge[1]];
462 thisEdge[1] = pIndex;
463 thisREdge[1] = pIndex;
468 entityMutex_[0].unlock();
471 // Renumber all faceEdges
476 entityMutex_[2].lock();
479 forAll(faceEdges_, faceI)
482 labelList& fEdges = faceEdges_[faceI];
483 labelList& rfEdges = faceEdges[faceI];
485 forAll(fEdges, edgeI)
487 if (fEdges[edgeI] < nOldEdges_)
489 eIndex = reverseEdgeMap_[fEdges[edgeI]];
493 eIndex = addedEdgeRenumbering_[fEdges[edgeI]];
496 fEdges[edgeI] = eIndex;
497 rfEdges[edgeI] = eIndex;
501 // Renumber all edgeFaces
504 forAll(edgeFaces_, edgeI)
507 labelList& eFaces = edgeFaces_[edgeI];
508 labelList& reFaces = edgeFaces[edgeI];
510 // Renumber edgeFaces
511 forAll(eFaces, faceI)
513 if (eFaces[faceI] < nOldFaces_)
515 fIndex = reverseFaceMap_[eFaces[faceI]];
519 fIndex = addedFaceRenumbering_[eFaces[faceI]];
522 eFaces[faceI] = fIndex;
523 reFaces[faceI] = fIndex;
529 entityMutex_[2].unlock();
534 // Invert edges to obtain pointEdges
535 pointEdges_ = invertManyToMany<edge, labelList>(nPoints_, edges_);
537 // Loop through all local coupling maps, and renumber edges.
538 forAll(patchCoupling_, patchI)
540 if (!patchCoupling_(patchI))
546 const coupleMap& cMap = patchCoupling_[patchI].map();
547 const Map<label>& mtsMap = cMap.entityMap(coupleMap::EDGE);
549 Map<label> newMtsMap, newStmMap;
551 forAllConstIter(Map<label>, mtsMap, mIter)
553 label newMaster = -1, newSlave = -1;
555 if (mIter.key() < nOldEdges_)
557 newMaster = reverseEdgeMap_[mIter.key()];
561 newMaster = addedEdgeRenumbering_[mIter.key()];
564 if (mIter() < nOldEdges_)
566 newSlave = reverseEdgeMap_[mIter()];
570 newSlave = addedEdgeRenumbering_[mIter()];
574 newMtsMap.insert(newMaster, newSlave);
575 newStmMap.insert(newSlave, newMaster);
578 // Overwrite the old maps.
579 cMap.transferMaps(coupleMap::EDGE, newMtsMap, newStmMap);
585 Info<< "Done." << endl;
590 // Static equivalent for multi-threading
591 void dynamicTopoFvMesh::reOrderEdgesThread
596 // Recast the argument
597 meshHandler *thread = static_cast<meshHandler*>(argument);
599 dynamicTopoFvMesh& mesh = thread->reference();
601 // Lock the edge mutex first
602 mesh.entityMutex(1).lock();
604 // Signal the calling thread
605 thread->sendSignal(meshHandler::START);
607 // Recast the pointers for the argument
610 *(static_cast<edgeList*>(thread->operator()(0)))
613 labelListList& edgeFaces =
615 *(static_cast<labelListList*>(thread->operator()(1)))
618 labelListList& faceEdges =
620 *(static_cast<labelListList*>(thread->operator()(2)))
624 mesh.reOrderEdges(edges, edgeFaces, faceEdges, true);
626 // Signal the calling thread
627 thread->sendSignal(meshHandler::STOP);
631 // Reorder faces in upper-triangular order after a topology change
632 void dynamicTopoFvMesh::reOrderFaces
636 labelList& neighbour,
637 labelListList& faceEdges,
638 labelListList& faceZoneFaceMap,
642 // *** Face renumbering *** //
643 // Faces have to be renumbered if any were added/deleted/modified
644 // Boundary faces are added to respective patches.
645 // Internal faces, however, have to be added in upper-triangular ordering;
646 // i.e., in the increasing order of neighbours
652 Info<< "Thread: " << self() << ": ";
655 Info<< "ReOrdering faces..." << flush;
658 // Allocate for mapping information
659 faceMap_.setSize(nFaces_, -1);
661 label faceInOrder = 0, allFaces = faces_.size();
662 faceList oldFaces(allFaces);
663 labelList oldOwner(allFaces), oldNeighbour(allFaces), visited(allFaces,0);
664 labelListList oldFaceEdges(allFaces);
666 addedFaceRenumbering_.clear();
668 // Track reverse renumbering for added faces.
669 // - Required during coupled patch re-ordering.
670 Map<label> addedFaceReverseRenumbering;
672 // Make a copy of the old face-based lists, and clear them
673 forAll(faces_, faceI)
675 oldFaces[faceI].transfer(faces_[faceI]);
676 oldOwner[faceI] = owner_[faceI];
677 oldNeighbour[faceI] = neighbour_[faceI];
678 oldFaceEdges[faceI].transfer(faceEdges_[faceI]);
681 // Renumber all faces with updated point information
686 entityMutex_[0].lock();
689 forAll(oldFaces, faceI)
691 face& thisFace = oldFaces[faceI];
693 forAll(thisFace, pointI)
695 if (thisFace[pointI] < nOldPoints_)
697 pIndex = reversePointMap_[thisFace[pointI]];
701 pIndex = addedPointRenumbering_[thisFace[pointI]];
704 thisFace[pointI] = pIndex;
710 entityMutex_[0].unlock();
713 // Wait for the cell mutex to become available
716 entityMutex_[3].lock();
719 faces_.setSize(nFaces_);
720 owner_.setSize(nFaces_);
721 neighbour_.setSize(nFaces_);
722 faceEdges_.setSize(nFaces_);
724 // Mark the internal faces with -2 so that they are inserted first
725 forAll(cells_, cellI)
727 const cell& curFaces = cells_[cellI];
729 forAll(curFaces, faceI)
731 visited[curFaces[faceI]]--;
735 // Keep track of inserted boundary face indices
736 labelList boundaryPatchIndices(patchStarts_);
738 // Handle boundaries first. If any coupled interfaces need to be
739 // updated, they can be reshuffled after interior faces are done.
740 for (label faceI = nOldInternalFaces_; faceI < allFaces; faceI++)
742 if (visited[faceI] == -1)
744 label patchID = whichPatch(faceI);
745 label bFaceIndex = boundaryPatchIndices[patchID]++;
748 if (faceI < nOldFaces_)
750 faceMap_[bFaceIndex] = faceI;
751 reverseFaceMap_[faceI] = bFaceIndex;
755 faceMap_[bFaceIndex] = -1;
756 addedFaceRenumbering_.insert(faceI, bFaceIndex);
757 addedFaceReverseRenumbering.insert(bFaceIndex, faceI);
761 label ownerRenumber =
763 oldOwner[faceI] < nOldCells_
764 ? reverseCellMap_[oldOwner[faceI]]
765 : addedCellRenumbering_[oldOwner[faceI]]
768 // Insert entities into local lists...
769 owner_[bFaceIndex] = ownerRenumber;
770 neighbour_[bFaceIndex] = -1;
771 faces_[bFaceIndex] = oldFaces[faceI];
772 faceEdges_[bFaceIndex] = oldFaceEdges[faceI];
774 // Insert entities into mesh-reset lists...
775 owner[bFaceIndex] = ownerRenumber;
776 faces[bFaceIndex].transfer(oldFaces[faceI]);
777 faceEdges[bFaceIndex].transfer(oldFaceEdges[faceI]);
779 // Mark this face as visited
784 // Prepare centres and anchors for coupled interfaces
785 List<pointField> centres(nPatches_), anchors(nPatches_);
787 // Now that points and boundary faces are up-to-date,
788 // send and receive centres and anchor points for coupled patches
789 initCoupledBoundaryOrdering
795 // Upper-triangular ordering of internal faces:
797 // Insertion cannot be done in one go as the faces need to be
798 // added into the list in the increasing order of neighbour
799 // cells. Therefore, all neighbours will be detected first
800 // and then added in the correct order.
801 forAll(cells_, cellI)
803 // Record the neighbour cell
804 const cell& curFaces = cells_[cellI];
806 labelList neiCells(curFaces.size(), -1);
808 label nNeighbours = 0;
810 forAll(curFaces, faceI)
812 if (visited[curFaces[faceI]] == -2)
814 // Face is internal and gets reordered
817 oldOwner[curFaces[faceI]] < nOldCells_
818 ? reverseCellMap_[oldOwner[curFaces[faceI]]]
819 : addedCellRenumbering_[oldOwner[curFaces[faceI]]]
824 oldNeighbour[curFaces[faceI]] < nOldCells_
825 ? reverseCellMap_[oldNeighbour[curFaces[faceI]]]
826 : addedCellRenumbering_[oldNeighbour[curFaces[faceI]]]
829 label smallerIndex = own < nei ? own : nei;
830 label largerIndex = own > nei ? own : nei;
832 if (cellI == smallerIndex)
834 neiCells[faceI] = largerIndex;
840 // Add internal faces in the increasing order of neighbours
841 for (label neiSearch = 0; neiSearch < nNeighbours; neiSearch++)
843 // Find the lowest neighbour which is still valid
845 label minNei = nCells_;
847 forAll(neiCells, ncI)
849 if (neiCells[ncI] > -1 && neiCells[ncI] < minNei)
852 minNei = neiCells[ncI];
858 // Face is internal and gets reordered
859 if (curFaces[nextNei] < nOldFaces_)
861 faceMap_[faceInOrder] = curFaces[nextNei];
862 reverseFaceMap_[curFaces[nextNei]] = faceInOrder;
866 addedFaceRenumbering_.insert
873 // Renumber owner/neighbour
874 label oldOwn = oldOwner[curFaces[nextNei]];
875 label oldNei = oldNeighbour[curFaces[nextNei]];
877 label ownerRenumber =
880 ? reverseCellMap_[oldOwn] : addedCellRenumbering_[oldOwn]
883 label neighbourRenumber =
886 ? reverseCellMap_[oldNei] : addedCellRenumbering_[oldNei]
889 // Cell-reordering may cause flipped faces.. Correct them.
890 face& faceRenumber = oldFaces[curFaces[nextNei]];
892 if (neighbourRenumber < ownerRenumber)
894 faceRenumber = faceRenumber.reverseFace();
896 if (!bandWidthReduction_)
898 FatalErrorIn("dynamicTopoFvMesh::reOrderFaces()")
900 << " Found an improperly ordered face."
901 << " Something's messed up." << nl
902 << abort(FatalError);
905 setFlip(curFaces[nextNei]);
908 // Insert entities into local lists...
909 faces_[faceInOrder] = faceRenumber;
910 owner_[faceInOrder] = cellI;
911 neighbour_[faceInOrder] = minNei;
912 faceEdges_[faceInOrder] =
914 oldFaceEdges[curFaces[nextNei]]
917 // Insert entities into mesh-reset lists
918 faces[faceInOrder].transfer(faceRenumber);
919 owner[faceInOrder] = cellI;
920 neighbour[faceInOrder] = minNei;
921 faceEdges[faceInOrder].transfer
923 oldFaceEdges[curFaces[nextNei]]
926 // Stop the neighbour from being used again
927 neiCells[nextNei] = -1;
929 // Mark this face as visited
930 visited[curFaces[nextNei]] = 0;
936 FatalErrorIn("dynamicTopoFvMesh::reOrderFaces()") << nl
937 << "Error in internal face insertion" << nl
938 << abort(FatalError);
943 // Prepare faceMaps and rotations for coupled interfaces
944 labelListList patchMaps(nPatches_), rotations(nPatches_);
946 // Now compute patchMaps for coupled interfaces
949 syncCoupledBoundaryOrdering
960 forAll(patchMaps, pI)
962 const labelList& patchMap = patchMaps[pI];
966 // Faces in this patch need to be shuffled
967 label pStart = patchStarts_[pI];
971 label oldPos = fI + pStart;
972 label newPos = patchMap[fI] + pStart;
974 // Rotate the face in-place
975 const face& oldFace = faces_[oldPos];
977 // Copy the old face, and rotate if necessary
978 face newFace(oldFace);
979 label nPos = rotations[pI][fI];
985 label nfpI = (fpI + nPos) % oldFace.size();
989 nfpI += oldFace.size();
992 newFace[nfpI] = oldFace[fpI];
996 // Map to new locations, using the
997 // 'old' lists as temporaries.
998 // - All boundary neighbours are '-1',
999 // so use that as a faceMap temporary
1000 oldNeighbour[newPos] = faceMap_[oldPos];
1002 // Check if this face was added
1003 if (faceMap_[oldPos] == -1)
1005 // Fetch the index for the new face
1006 label addedIndex = addedFaceReverseRenumbering[oldPos];
1008 // Renumber for the added index
1009 addedFaceRenumbering_[addedIndex] = newPos;
1013 // Fetch the index for the existing face
1014 label existIndex = faceMap_[oldPos];
1016 // Renumber the reverse map
1017 reverseFaceMap_[existIndex] = newPos;
1020 oldOwner[newPos] = owner_[oldPos];
1021 oldFaces[newPos].transfer(newFace);
1022 oldFaceEdges[newPos].transfer(faceEdges_[oldPos]);
1025 // Now copy / transfer back to original lists
1026 forAll(patchMap, fI)
1028 label index = (fI + pStart);
1030 faceMap_[index] = oldNeighbour[index];
1032 owner_[index] = oldOwner[index];
1033 faces_[index] = oldFaces[index];
1034 faceEdges_[index] = oldFaceEdges[index];
1036 owner[index] = oldOwner[index];
1037 faces[index].transfer(oldFaces[index]);
1038 faceEdges[index].transfer(oldFaceEdges[index]);
1044 // Now that we're done with faces, unlock it
1047 entityMutex_[2].unlock();
1050 // Renumber all maps.
1051 forAll(facesFromPoints_, indexI)
1053 objectMap& thisMap = facesFromPoints_[indexI];
1055 if (thisMap.index() < nOldFaces_)
1057 thisMap.index() = reverseFaceMap_[thisMap.index()];
1061 thisMap.index() = addedFaceRenumbering_[thisMap.index()];
1065 forAll(facesFromEdges_, indexI)
1067 objectMap& thisMap = facesFromEdges_[indexI];
1069 if (thisMap.index() < nOldFaces_)
1071 thisMap.index() = reverseFaceMap_[thisMap.index()];
1075 thisMap.index() = addedFaceRenumbering_[thisMap.index()];
1079 forAll(facesFromFaces_, indexI)
1081 objectMap& thisMap = facesFromFaces_[indexI];
1083 if (thisMap.index() < nOldFaces_)
1085 thisMap.index() = reverseFaceMap_[thisMap.index()];
1089 thisMap.index() = addedFaceRenumbering_[thisMap.index()];
1093 // Renumber all flipFaces
1094 labelHashSet flipFaces;
1096 forAllIter(labelHashSet, flipFaces_, fIter)
1098 if (fIter.key() < nOldFaces_)
1100 flipFaces.insert(reverseFaceMap_[fIter.key()]);
1104 // Added faces cannot be flipped.
1105 FatalErrorIn("dynamicTopoFvMesh::reOrderFaces()") << nl
1106 << " Face: " << fIter.key()
1107 << " is new, and shouldn't be flipped." << nl
1108 << " nOldFaces: " << nOldFaces_
1109 << abort(FatalError);
1113 flipFaces_.transfer(flipFaces);
1115 // Renumber all cells with updated face information
1116 forAll(cells_, cellI)
1118 cell& cellFaces = cells_[cellI];
1120 forAll(cellFaces, faceI)
1122 if (cellFaces[faceI] < nOldFaces_)
1124 cellFaces[faceI] = reverseFaceMap_[cellFaces[faceI]];
1128 cellFaces[faceI] = addedFaceRenumbering_[cellFaces[faceI]];
1133 // Now that we're done with cells, unlock it
1136 entityMutex_[3].unlock();
1139 // Final check to ensure everything went okay
1142 if (sum(visited) != 0)
1144 FatalErrorIn("dynamicTopoFvMesh::reOrderFaces()") << nl
1145 << " Algorithm did not visit every face in the mesh."
1146 << " Something's messed up." << nl
1147 << abort(FatalError);
1151 // Prepare the faceZoneMap
1152 faceZoneMesh& faceZones = polyMesh::faceZones();
1154 labelListList newFaceZoneAddr(faceZones.size());
1155 boolListList faceZoneFlipMap(faceZones.size());
1156 labelList nFacesInZone(faceZones.size(), 0);
1158 // Prepare zone maps.
1159 forAll(faceZones, fzI)
1161 // Get the list of old faces
1162 const labelList& oldAddr = faceZones[fzI];
1164 label& curNFaces = nFacesInZone[fzI];
1166 // First count the actual number of faces in each zone.
1167 forAll(oldAddr, faceI)
1169 // Was this zone face deleted? Don't count it.
1170 if (reverseFaceMap_[oldAddr[faceI]] != -1)
1176 // Check for added faces as well
1177 forAllIter(Map<label>, addedFaceZones_, fIter)
1186 labelList& newAddr = newFaceZoneAddr[fzI];
1188 // Set the sizes first
1189 newAddr.setSize(curNFaces);
1190 faceZoneFaceMap[fzI].setSize(curNFaces, -1);
1191 faceZoneFlipMap[fzI].setSize(curNFaces, false);
1193 // Add existing zone faces which have been renumbered.
1194 forAll(oldAddr, faceI)
1196 if (reverseFaceMap_[oldAddr[faceI]] != -1)
1198 faceZoneFaceMap[fzI][fIndex] = oldAddr[faceI];
1199 newAddr[fIndex] = reverseFaceMap_[oldAddr[faceI]];
1204 // Next, add the newly added zone faces.
1205 forAllIter(Map<label>, addedFaceZones_, fIter)
1209 newAddr[fIndex++] = addedFaceRenumbering_[fIter.key()];
1213 // Finally, reset addressing for this zone.
1214 faceZones[fzI].resetAddressing
1216 newFaceZoneAddr[fzI],
1217 faceZoneFlipMap[fzI]
1222 faceZones.updateMesh();
1224 // Loop through all local coupling maps, and renumber faces.
1225 forAll(patchCoupling_, patchI)
1227 if (!patchCoupling_(patchI))
1232 // Obtain references
1233 const coupleMap& cMap = patchCoupling_[patchI].map();
1234 const Map<label>& mtsMap = cMap.entityMap(coupleMap::FACE);
1236 Map<label> newMtsMap, newStmMap;
1238 forAllConstIter(Map<label>, mtsMap, mIter)
1240 label newMaster = -1, newSlave = -1;
1242 if (mIter.key() < nOldFaces_)
1244 newMaster = reverseFaceMap_[mIter.key()];
1248 newMaster = addedFaceRenumbering_[mIter.key()];
1251 if (mIter() < nOldFaces_)
1253 newSlave = reverseFaceMap_[mIter()];
1257 newSlave = addedFaceRenumbering_[mIter()];
1261 newMtsMap.insert(newMaster, newSlave);
1262 newStmMap.insert(newSlave, newMaster);
1265 // Overwrite the old maps.
1266 cMap.transferMaps(coupleMap::FACE, newMtsMap, newStmMap);
1271 Info<< "Done." << endl;
1276 // Static equivalent for multi-threading
1277 void dynamicTopoFvMesh::reOrderFacesThread
1282 // Recast the argument
1283 meshHandler *thread = static_cast<meshHandler*>(argument);
1285 dynamicTopoFvMesh& mesh = thread->reference();
1287 // Lock the face mutex first
1288 mesh.entityMutex(2).lock();
1290 // Signal the calling thread
1291 thread->sendSignal(meshHandler::START);
1293 // Recast the pointers for the argument
1296 *(static_cast<faceList*>(thread->operator()(0)))
1301 *(static_cast<labelList*>(thread->operator()(1)))
1304 labelList& neighbour =
1306 *(static_cast<labelList*>(thread->operator()(2)))
1309 labelListList& faceEdges =
1311 *(static_cast<labelListList*>(thread->operator()(3)))
1314 labelListList& faceZoneFaceMap =
1316 *(static_cast<labelListList*>(thread->operator()(4)))
1319 // Reorder the faces
1332 // Reorder & renumber cells with bandwidth reduction after a topology change
1333 void dynamicTopoFvMesh::reOrderCells
1335 labelListList& cellZoneMap,
1339 // *** Cell renumbering *** //
1340 // If cells were deleted during topology change, the numerical order ceases
1341 // to be continuous. Also, cells are always added at the end of the list by
1342 // virtue of the append method. Thus, cells would now have to be
1343 // reordered so that bandwidth is reduced and renumbered to be sequential.
1349 Info<< "Thread: " << self() << ": ";
1352 Info<< "ReOrdering cells..." << flush;
1355 // Allocate for mapping information
1356 cellMap_.setSize(nCells_, -1);
1358 label cellInOrder = 0;
1360 addedCellRenumbering_.clear();
1362 // Make a copy of the old cell-based lists, and clear them
1363 label allCells = cells_.size();
1365 cellList oldCells(allCells);
1367 forAll(cells_, cellI)
1369 oldCells[cellI].transfer(cells_[cellI]);
1372 cells_.setSize(nCells_);
1374 if (bandWidthReduction_)
1377 SLList<label> nextCell;
1378 labelList ncc(allCells, 0), visited(allCells, 0);
1379 labelListList cellCellAddr(allCells);
1381 // Build a cell-cell addressing list
1382 forAll(owner_, faceI)
1384 if ((neighbour_[faceI] > -1) && (owner_[faceI] > -1))
1386 ncc[owner_[faceI]]++;
1387 ncc[neighbour_[faceI]]++;
1391 forAll(cellCellAddr, cellI)
1393 cellCellAddr[cellI].setSize(ncc[cellI]);
1395 // Mark off deleted cells as "visited"
1396 if (ncc[cellI] == 0)
1404 forAll(owner_, faceI)
1406 if ((owner_[faceI] > -1) && (neighbour_[faceI] > -1))
1408 cellCellAddr[owner_[faceI]][ncc[owner_[faceI]]++] =
1413 cellCellAddr[neighbour_[faceI]][ncc[neighbour_[faceI]]++] =
1420 // Let's get to the "business bit" of the band-compression
1421 forAll(visited, cellI)
1423 // Find the first cell that has not been visited yet
1424 if (visited[cellI] == 0)
1426 // Use this cell as a start
1427 currentCell = cellI;
1429 nextCell.append(currentCell);
1431 // Loop through the nextCell list. Add the first cell
1432 // into the cell order if it has not already been visited
1433 // and ask for its neighbours. If the neighbour in question
1434 // has not been visited, add it to the end of the nextCell list
1435 while (nextCell.size() > 0)
1437 currentCell = nextCell.removeHead();
1439 if (visited[currentCell] == 0)
1441 // Mark as visited and update cell mapping info
1442 visited[currentCell] = 1;
1444 if (currentCell < nOldCells_)
1446 cellMap_[cellInOrder] = currentCell;
1447 reverseCellMap_[currentCell] = cellInOrder;
1451 addedCellRenumbering_.insert
1458 // Insert entities into local lists...
1459 cells_[cellInOrder].transfer(oldCells[currentCell]);
1463 // Find if the neighbours have been visited
1464 const labelList& neighbours = cellCellAddr[currentCell];
1466 forAll(neighbours, nI)
1468 if (visited[neighbours[nI]] == 0)
1470 // Not visited, add to the list
1471 nextCell.append(neighbours[nI]);
1481 if (sum(visited) != allCells)
1483 FatalErrorIn("dynamicTopoFvMesh::reOrderCells()") << nl
1484 << " Algorithm did not visit every cell in the mesh."
1485 << " Something's messed up." << nl
1486 << abort(FatalError);
1492 // No bandwidth reduction. Fill-in sequentially.
1493 for (label cellI = 0; cellI < nOldCells_; cellI++)
1495 // Check if this is a deleted cell
1496 if (reverseCellMap_[cellI] == -1)
1501 // Update the cell info
1502 cells_[cellInOrder].transfer(oldCells[cellI]);
1505 cellMap_[cellInOrder] = cellI;
1506 reverseCellMap_[cellI] = cellInOrder;
1508 // Update the counter
1512 for (label cellI = nOldCells_; cellI < allCells; cellI++)
1514 // Was this cell removed after addition?
1515 if (deletedCells_.found(cellI))
1520 // Update the cell info
1521 cells_[cellInOrder].transfer(oldCells[cellI]);
1523 // Put inserted cells in a seperate hashSet
1524 addedCellRenumbering_.insert(cellI, cellInOrder);
1526 // Update the counter
1530 // Final check to ensure everything went okay
1531 if (cellInOrder != nCells_)
1533 FatalErrorIn("dynamicTopoFvMesh::reOrderCells()") << nl
1534 << " Algorithm did not visit every cell in the mesh."
1535 << " Something's messed up." << nl
1536 << abort(FatalError);
1540 // Now that we're done preparing the cell maps, unlock the cell mutex
1543 entityMutex_[3].unlock();
1546 // Renumber all maps.
1547 forAll(cellsFromPoints_, cellI)
1549 objectMap& thisMap = cellsFromPoints_[cellI];
1551 if (thisMap.index() < nOldCells_)
1553 thisMap.index() = reverseCellMap_[thisMap.index()];
1557 thisMap.index() = addedCellRenumbering_[thisMap.index()];
1561 forAll(cellsFromEdges_, cellI)
1563 objectMap& thisMap = cellsFromEdges_[cellI];
1565 if (thisMap.index() < nOldCells_)
1567 thisMap.index() = reverseCellMap_[thisMap.index()];
1571 thisMap.index() = addedCellRenumbering_[thisMap.index()];
1575 forAll(cellsFromFaces_, cellI)
1577 objectMap& thisMap = cellsFromFaces_[cellI];
1579 if (thisMap.index() < nOldCells_)
1581 thisMap.index() = reverseCellMap_[thisMap.index()];
1585 thisMap.index() = addedCellRenumbering_[thisMap.index()];
1589 forAll(cellsFromCells_, cellI)
1591 objectMap& thisMap = cellsFromCells_[cellI];
1593 if (thisMap.index() < nOldCells_)
1595 thisMap.index() = reverseCellMap_[thisMap.index()];
1599 thisMap.index() = addedCellRenumbering_[thisMap.index()];
1603 // Prepare the cellZoneMap
1604 cellZoneMesh& cellZones = polyMesh::cellZones();
1606 labelListList newCellZoneAddr(cellZones.size());
1607 labelList nCellsInZone(cellZones.size(), 0);
1609 // Prepare zone maps.
1610 forAll(cellZones, czI)
1612 // Get the list of old cells
1613 const labelList& oldAddr = cellZones[czI];
1615 label& curNCells = nCellsInZone[czI];
1617 // First count the actual number of cells in each zone.
1618 forAll(oldAddr, cellI)
1620 // Was this zone cell deleted? Don't count it.
1621 if (reverseCellMap_[oldAddr[cellI]] != -1)
1627 // Check for added cells as well
1628 forAllIter(Map<label>, addedCellZones_, cIter)
1637 labelList& newAddr = newCellZoneAddr[czI];
1639 // Set the sizes first
1640 newAddr.setSize(curNCells);
1641 cellZoneMap[czI].setSize(curNCells, -1);
1643 // Add existing zone cells which have been renumbered.
1644 forAll(oldAddr, cellI)
1646 if (reverseCellMap_[oldAddr[cellI]] != -1)
1648 cellZoneMap[czI][cIndex] = oldAddr[cellI];
1649 newAddr[cIndex] = reverseCellMap_[oldAddr[cellI]];
1654 // Next, add the newly added zone cells.
1655 forAllIter(Map<label>, addedCellZones_, cIter)
1659 newAddr[cIndex++] = addedCellRenumbering_[cIter.key()];
1663 // Finally, assign addressing to this zone.
1664 cellZones[czI] = newCellZoneAddr[czI];
1668 cellZones.updateMesh();
1672 Info<< "Done." << endl;
1677 // Static equivalent for multi-threading
1678 void dynamicTopoFvMesh::reOrderCellsThread
1683 // Recast the argument
1684 meshHandler *thread = static_cast<meshHandler*>(argument);
1686 dynamicTopoFvMesh& mesh = thread->reference();
1688 // Lock the cell mutex first
1689 mesh.entityMutex(3).lock();
1691 // Signal the calling thread
1692 thread->sendSignal(meshHandler::START);
1694 // Recast the pointers for the argument
1695 labelListList& cellZoneMap =
1697 *(static_cast<labelListList*>(thread->operator()(0)))
1700 // Reorder the cells
1701 mesh.reOrderCells(cellZoneMap, true);
1705 // Reorder the faces in upper-triangular order, and generate mapping information
1706 void dynamicTopoFvMesh::reOrderMesh
1709 pointField& preMotionPoints,
1713 labelList& neighbour,
1714 labelListList& faceEdges,
1715 labelListList& edgeFaces,
1716 labelListList& pointZoneMap,
1717 labelListList& faceZoneFaceMap,
1718 labelListList& cellZoneMap
1723 // Buffered print-out of mesh-stats
1724 if (Pstream::parRun())
1726 if (Pstream::master())
1728 for (label i = Pstream::nProcs() - 1; i >= 1; i--)
1731 meshOps::pWrite(i, i);
1733 // Wait for response from slave
1735 meshOps::pRead(i, j);
1742 meshOps::pRead(Pstream::masterNo(), i);
1747 << "=================" << nl
1748 << " Mesh reOrdering " << nl
1749 << "=================" << nl
1750 << " Mesh Info [n]:" << nl
1751 << " Points: " << nOldPoints_ << nl
1752 << " Edges: " << nOldEdges_ << nl
1753 << " Faces: " << nOldFaces_ << nl
1754 << " Cells: " << nOldCells_ << nl
1755 << " Internal Edges: " << nOldInternalEdges_ << nl
1756 << " Internal Faces: " << nOldInternalFaces_ << nl
1757 << " nPatches: " << nPatches_ << nl;
1761 Pout<< " Patch Starts [Face]: " << oldPatchStarts_ << nl
1762 << " Patch Sizes [Face]: " << oldPatchSizes_ << nl
1763 << " Patch Starts [Edge]: " << oldEdgePatchStarts_ << nl
1764 << " Patch Sizes [Edge]: " << oldEdgePatchSizes_ << nl;
1767 Pout<< "=================" << nl
1768 << " Mesh Info [n+1]:" << nl
1769 << " Points: " << nPoints_ << nl
1770 << " Edges: " << nEdges_ << nl
1771 << " Faces: " << nFaces_ << nl
1772 << " Cells: " << nCells_ << nl
1773 << " Internal Edges: " << nInternalEdges_ << nl
1774 << " Internal Faces: " << nInternalFaces_ << nl
1775 << " nPatches: " << nPatches_ << nl;
1779 Pout<< " Patch Starts [Face]: " << patchStarts_ << nl
1780 << " Patch Sizes: [Face]: " << patchSizes_ << nl
1781 << " Patch Starts [Edge]: " << edgePatchStarts_ << nl
1782 << " Patch Sizes: [Edge]: " << edgePatchSizes_ << nl;
1785 Pout<< "=================" << endl;
1788 if (Pstream::parRun() && !Pstream::master())
1790 meshOps::pWrite(Pstream::masterNo(), Pstream::myProcNo());
1793 bool checkPoint = false;
1794 reduce(checkPoint, andOp<bool>());
1796 // Check connectivity structures for consistency
1797 // before entering the reOrdering phase.
1798 checkConnectivity();
1801 if (threader_->multiThreaded() && !Pstream::parRun())
1803 // Initialize multi-threaded reOrdering
1804 threadedMeshReOrdering
1821 // Reorder the points
1822 reOrderPoints(points, preMotionPoints, pointZoneMap);
1824 // Reorder the cells
1825 reOrderCells(cellZoneMap);
1827 // Reorder the faces
1828 reOrderFaces(faces, owner, neighbour, faceEdges, faceZoneFaceMap);
1830 // Reorder the edges
1831 reOrderEdges(edges, edgeFaces, faceEdges);
1836 // Invoke reOrdering with multiple threads
1837 void dynamicTopoFvMesh::threadedMeshReOrdering
1840 pointField& preMotionPoints,
1844 labelList& neighbour,
1845 labelListList& faceEdges,
1846 labelListList& edgeFaces,
1847 labelListList& pointZoneMap,
1848 labelListList& faceZoneFaceMap,
1849 labelListList& cellZoneMap
1852 // For reOrdering, one handler for each reOrdering method
1853 PtrList<meshHandler> reOrderPtr(4);
1855 // Initialize reOrdering handlers
1856 forAll(reOrderPtr, memberI)
1861 new meshHandler(*this, threader())
1865 // Set argument sizes for individual members
1867 // Points take three arguments
1868 // (Two pointFields and one labelListList)
1869 reOrderPtr[0].setSize(3);
1871 // Prepare pointers for point reOrdering
1872 reOrderPtr[0].set(0, &points);
1873 reOrderPtr[0].set(1, &preMotionPoints);
1874 reOrderPtr[0].set(2, &pointZoneMap);
1876 // Edges take three arguments
1877 // (One edgeList and two labelListLists)
1878 reOrderPtr[1].setSize(3);
1880 // Prepare pointers for edge reOrdering
1881 reOrderPtr[1].set(0, &edges);
1882 reOrderPtr[1].set(1, &edgeFaces);
1883 reOrderPtr[1].set(2, &faceEdges);
1885 // Faces take five arguments
1886 // (One faceList, two labelLists, and two labelListLists)
1887 reOrderPtr[2].setSize(5);
1889 // Prepare pointers for face reOrdering
1890 reOrderPtr[2].set(0, &faces);
1891 reOrderPtr[2].set(1, &owner);
1892 reOrderPtr[2].set(2, &neighbour);
1893 reOrderPtr[2].set(3, &faceEdges);
1894 reOrderPtr[2].set(4, &faceZoneFaceMap);
1896 // Cells take one argument
1897 // (One labelListList)
1898 reOrderPtr[3].setSize(1);
1900 // Prepare pointers for cell reOrdering
1901 reOrderPtr[3].set(0, &cellZoneMap);
1903 // Set the thread scheduling sequence
1904 labelList reOrderSeq(4, -1);
1906 // Points, cells, faces and edges (in that order)
1912 // Lock all slave threads first
1913 forAll(reOrderSeq, i)
1915 reOrderPtr[reOrderSeq[i]].lock(meshHandler::START);
1916 reOrderPtr[reOrderSeq[i]].unsetPredicate(meshHandler::START);
1919 // Submit points to the work queue
1920 threader_->addToWorkQueue
1922 &reOrderPointsThread,
1926 // Wait for a signal from this thread before moving on.
1927 reOrderPtr[0].waitForSignal(meshHandler::START);
1929 // Submit cells to the work queue
1930 threader_->addToWorkQueue
1932 &reOrderCellsThread,
1936 // Wait for a signal from this thread before moving on.
1937 reOrderPtr[3].waitForSignal(meshHandler::START);
1939 // Submit faces to the work queue
1940 threader_->addToWorkQueue
1942 &reOrderFacesThread,
1946 // Wait for a signal from this thread before moving on.
1947 reOrderPtr[2].waitForSignal(meshHandler::START);
1949 // Lock the edge stop-mutex
1950 reOrderPtr[1].lock(meshHandler::STOP);
1951 reOrderPtr[1].unsetPredicate(meshHandler::STOP);
1953 // Submit edges to the work queue
1954 threader_->addToWorkQueue
1956 &reOrderEdgesThread,
1960 // Wait for a signal from this thread before moving on.
1961 reOrderPtr[1].waitForSignal(meshHandler::START);
1963 // Wait for edges to be reOrdered before moving on.
1964 reOrderPtr[1].waitForSignal(meshHandler::STOP);
1967 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1969 } // End namespace Foam
1971 // ************************************************************************* //