1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 Post-processing mesh subset tool. Given the original mesh and the
27 list of selected cells, it creates the mesh consisting only of the
28 desired cells, with the mapping list for points, faces, and cells.
30 MJ 23/03/05 on coupled faces change the patch of the face to the
31 oldInternalFaces patch.
33 \*---------------------------------------------------------------------------*/
35 #include "fvMeshSubset.H"
38 #include "emptyPolyPatch.H"
39 #include "demandDrivenData.H"
40 #include "cyclicPolyPatch.H"
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
49 bool Foam::fvMeshSubset::checkCellSubset() const
51 if (fvMeshSubsetPtr_.empty())
53 FatalErrorIn("bool fvMeshSubset::checkCellSubset() const")
54 << "Mesh subset not set. Please set the cell map using "
55 << "void setCellSubset(const labelHashSet& cellsToSubset)" << endl
56 << "before attempting to access subset data"
68 void Foam::fvMeshSubset::markPoints
70 const labelList& curPoints,
74 forAll (curPoints, pointI)
76 // Note: insert will only insert if not yet there.
77 pointMap.insert(curPoints[pointI], 0);
82 void Foam::fvMeshSubset::markPoints
84 const labelList& curPoints,
88 forAll (curPoints, pointI)
90 pointMap[curPoints[pointI]] = 0;
95 // Synchronize nCellsUsingFace on both sides of coupled patches. Marks
96 // faces that become 'uncoupled' with 3.
97 void Foam::fvMeshSubset::doCoupledPatches
100 labelList& nCellsUsingFace
103 const polyBoundaryMesh& oldPatches = baseMesh().boundaryMesh();
105 label nUncoupled = 0;
107 if (syncPar && Pstream::parRun())
109 // Send face usage across processor patches
110 forAll (oldPatches, oldPatchI)
112 const polyPatch& pp = oldPatches[oldPatchI];
114 if (typeid(pp) == typeid(processorPolyPatch))
116 const processorPolyPatch& procPatch =
117 refCast<const processorPolyPatch>(pp);
122 procPatch.neighbProcNo()
126 << SubList<label>(nCellsUsingFace, pp.size(), pp.start());
131 // Receive face usage count and check for faces that become uncoupled.
132 forAll (oldPatches, oldPatchI)
134 const polyPatch& pp = oldPatches[oldPatchI];
136 if (typeid(pp) == typeid(processorPolyPatch))
138 const processorPolyPatch& procPatch =
139 refCast<const processorPolyPatch>(pp);
141 IPstream fromNeighbour
144 procPatch.neighbProcNo()
147 labelList nbrCellsUsingFace(fromNeighbour);
149 // Combine with this side.
155 nCellsUsingFace[pp.start()+i] == 1
156 && nbrCellsUsingFace[i] == 0
159 // Face's neighbour is no longer there. Mark face off
161 nCellsUsingFace[pp.start()+i] = 3;
169 // Do same for cyclics.
170 forAll (oldPatches, oldPatchI)
172 const polyPatch& pp = oldPatches[oldPatchI];
174 if (typeid(pp) == typeid(cyclicPolyPatch))
176 const cyclicPolyPatch& cycPatch =
177 refCast<const cyclicPolyPatch>(pp);
181 label thisFaceI = cycPatch.start() + i;
182 label otherFaceI = cycPatch.transformGlobalFace(thisFaceI);
186 nCellsUsingFace[thisFaceI] == 1
187 && nCellsUsingFace[otherFaceI] == 0
190 nCellsUsingFace[thisFaceI] = 3;
199 reduce(nUncoupled, sumOp<label>());
204 Info<< "Uncoupled " << nUncoupled << " faces on coupled patches. "
205 << "(processorPolyPatch, cyclicPolyPatch)" << nl
206 << "You might need to run couplePatches to restore the patch face"
207 << " ordering." << nl << endl;
212 labelList Foam::fvMeshSubset::subset
215 const labelList& selectedElements,
216 const labelList& subsetMap
219 // Mark selected elements.
220 boolList selected(nElems, false);
221 forAll(selectedElements, i)
223 selected[selectedElements[i]] = true;
226 // Count subset of selected elements
230 if (selected[subsetMap[i]])
236 // Collect selected elements
237 labelList subsettedElements(n);
242 if (selected[subsetMap[i]])
244 subsettedElements[n++] = i;
248 return subsettedElements;
252 void Foam::fvMeshSubset::subsetZones()
254 // Keep all zones, even if zero size.
256 const pointZoneMesh& pointZones = baseMesh().pointZones();
259 List<pointZone*> pZonePtrs(pointZones.size());
261 forAll(pointZones, i)
263 const pointZone& pz = pointZones[i];
265 pZonePtrs[i] = new pointZone
268 subset(baseMesh().nPoints(), pz, pointMap()),
270 fvMeshSubsetPtr_().pointZones()
277 const faceZoneMesh& faceZones = baseMesh().faceZones();
280 // Do we need to remove zones where the side we're interested in
281 // no longer exists? Guess not.
282 List<faceZone*> fZonePtrs(faceZones.size());
286 const faceZone& fz = faceZones[i];
288 // Create list of mesh faces part of the new zone
289 labelList subAddressing
299 // Flipmap for all mesh faces
300 boolList fullFlipStatus(baseMesh().nFaces(), false);
303 fullFlipStatus[fz[j]] = fz.flipMap()[j];
306 boolList subFlipStatus(subAddressing.size(), false);
307 forAll(subAddressing, j)
309 subFlipStatus[j] = fullFlipStatus[faceMap()[subAddressing[j]]];
312 fZonePtrs[i] = new faceZone
318 fvMeshSubsetPtr_().faceZones()
323 const cellZoneMesh& cellZones = baseMesh().cellZones();
325 List<cellZone*> cZonePtrs(cellZones.size());
329 const cellZone& cz = cellZones[i];
331 cZonePtrs[i] = new cellZone
334 subset(baseMesh().nCells(), cz, cellMap()),
336 fvMeshSubsetPtr_().cellZones()
342 fvMeshSubsetPtr_().addZones(pZonePtrs, fZonePtrs, cZonePtrs);
346 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
348 // Construct from components
349 Foam::fvMeshSubset::fvMeshSubset(const fvMesh& baseMesh)
352 fvMeshSubsetPtr_(NULL),
360 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
362 void Foam::fvMeshSubset::setCellSubset
364 const labelHashSet& globalCellMap,
368 // Initial check on patches before doing anything time consuming.
369 const polyBoundaryMesh& oldPatches = baseMesh().boundaryMesh();
370 const cellList& oldCells = baseMesh().cells();
371 const faceList& oldFaces = baseMesh().faces();
372 const pointField& oldPoints = baseMesh().points();
373 const labelList& oldOwner = baseMesh().faceOwner();
374 const labelList& oldNeighbour = baseMesh().faceNeighbour();
376 label wantedPatchID = patchID;
378 if (wantedPatchID == -1)
380 // No explicit patch specified. Put in oldInternalFaces patch.
381 // Check if patch with this name already exists.
382 wantedPatchID = oldPatches.findPatchID("oldInternalFaces");
384 else if (wantedPatchID < 0 || wantedPatchID >= oldPatches.size())
388 "fvMeshSubset::setCellSubset(const labelHashSet&"
389 ", const label patchID)"
390 ) << "Non-existing patch index " << wantedPatchID << endl
391 << "Should be between 0 and " << oldPatches.size()-1
392 << abort(FatalError);
396 cellMap_ = globalCellMap.toc();
398 // Sort the cell map in the ascending order
401 // Approximate sizing parameters for face and point lists
402 const label avgNFacesPerCell = 6;
403 const label avgNPointsPerFace = 4;
406 label nCellsInSet = cellMap_.size();
408 // Mark all used faces
410 Map<label> facesToSubset(avgNFacesPerCell*nCellsInSet);
412 forAll (cellMap_, cellI)
414 // Mark all faces from the cell
415 const labelList& curFaces = oldCells[cellMap_[cellI]];
417 forAll (curFaces, faceI)
419 if (!facesToSubset.found(curFaces[faceI]))
421 facesToSubset.insert(curFaces[faceI], 1);
425 facesToSubset[curFaces[faceI]]++;
430 // Mark all used points and make a global-to-local face map
431 Map<label> globalFaceMap(facesToSubset.size());
433 // Make a global-to-local point map
434 Map<label> globalPointMap(avgNPointsPerFace*facesToSubset.size());
436 // This is done in two goes, so that the boundary faces are last
437 // in the list. Because of this, I need to create the face map
438 // along the way rather than just grab the table of contents.
439 labelList facesToc = facesToSubset.toc();
441 faceMap_.setSize(facesToc.size());
443 // 1. Get all faces that will be internal to the submesh.
444 forAll (facesToc, faceI)
446 if (facesToSubset[facesToc[faceI]] == 2)
448 // Mark face and increment number of points in set
449 faceMap_[globalFaceMap.size()] = facesToc[faceI];
450 globalFaceMap.insert(facesToc[faceI], globalFaceMap.size());
452 // Mark all points from the face
453 markPoints(oldFaces[facesToc[faceI]], globalPointMap);
457 // These are all the internal faces in the mesh.
458 label nInternalFaces = globalFaceMap.size();
461 // Where to insert old internal faces.
462 label oldPatchStart = labelMax;
463 if (wantedPatchID != -1)
465 oldPatchStart = oldPatches[wantedPatchID].start();
471 // 2. Boundary faces up to where we want to insert old internal faces
472 for (; faceI< facesToc.size(); faceI++)
474 if (facesToc[faceI] >= oldPatchStart)
480 !baseMesh().isInternalFace(facesToc[faceI])
481 && facesToSubset[facesToc[faceI]] == 1
484 // Mark face and increment number of points in set
485 faceMap_[globalFaceMap.size()] = facesToc[faceI];
486 globalFaceMap.insert(facesToc[faceI], globalFaceMap.size());
488 // Mark all points from the face
489 markPoints(oldFaces[facesToc[faceI]], globalPointMap);
493 // 3. old internal faces
494 forAll(facesToc, intFaceI)
498 baseMesh().isInternalFace(facesToc[intFaceI])
499 && facesToSubset[facesToc[intFaceI]] == 1
502 // Mark face and increment number of points in set
503 faceMap_[globalFaceMap.size()] = facesToc[intFaceI];
504 globalFaceMap.insert(facesToc[intFaceI], globalFaceMap.size());
506 // Mark all points from the face
507 markPoints(oldFaces[facesToc[intFaceI]], globalPointMap);
511 // 4. Remaining boundary faces
512 for (; faceI< facesToc.size(); faceI++)
516 !baseMesh().isInternalFace(facesToc[faceI])
517 && facesToSubset[facesToc[faceI]] == 1
520 // Mark face and increment number of points in set
521 faceMap_[globalFaceMap.size()] = facesToc[faceI];
522 globalFaceMap.insert(facesToc[faceI], globalFaceMap.size());
524 // Mark all points from the face
525 markPoints(oldFaces[facesToc[faceI]], globalPointMap);
531 // Grab the points map
532 pointMap_ = globalPointMap.toc();
535 forAll (pointMap_, pointI)
537 globalPointMap[pointMap_[pointI]] = pointI;
540 Pout << "Number of cells in new mesh: " << nCellsInSet << endl;
541 Pout << "Number of faces in new mesh: " << globalFaceMap.size() << endl;
542 Pout << "Number of points in new mesh: " << globalPointMap.size() << endl;
545 pointField newPoints(globalPointMap.size());
547 label nNewPoints = 0;
549 forAll (pointMap_, pointI)
551 newPoints[nNewPoints] = oldPoints[pointMap_[pointI]];
555 faceList newFaces(globalFaceMap.size());
559 // Make internal faces
560 for (label faceI = 0; faceI < nInternalFaces; faceI++)
562 const face& oldF = oldFaces[faceMap_[faceI]];
564 face newF(oldF.size());
568 newF[i] = globalPointMap[oldF[i]];
571 newFaces[nNewFaces] = newF;
575 // Make boundary faces
577 label nbSize = oldPatches.size();
578 label oldInternalPatchID = -1;
580 if (wantedPatchID == -1)
582 // Create 'oldInternalFaces' patch at the end
583 // and put all exposed internal faces in there.
584 oldInternalPatchID = nbSize;
590 oldInternalPatchID = wantedPatchID;
594 // Grad size and start of each patch on the fly. Because of the
595 // structure of the underlying mesh, the patches will appear in the
597 labelList boundaryPatchSizes(nbSize, 0);
599 // Assign boundary faces. Visited in order of faceMap_.
600 for (label faceI = nInternalFaces; faceI < faceMap_.size(); faceI++)
602 label oldFaceI = faceMap_[faceI];
604 face oldF = oldFaces[oldFaceI];
606 // Turn the faces as necessary to point outwards
607 if (baseMesh().isInternalFace(oldFaceI))
609 // Internal face. Possibly turned the wrong way round
612 !globalCellMap.found(oldOwner[oldFaceI])
613 && globalCellMap.found(oldNeighbour[oldFaceI])
616 oldF = oldFaces[oldFaceI].reverseFace();
619 // Update count for patch
620 boundaryPatchSizes[oldInternalPatchID]++;
624 // Boundary face. Increment the appropriate patch
625 label patchOfFace = oldPatches.whichPatch(oldFaceI);
627 // Update count for patch
628 boundaryPatchSizes[patchOfFace]++;
631 face newF(oldF.size());
635 newF[i] = globalPointMap[oldF[i]];
638 newFaces[nNewFaces] = newF;
645 cellList newCells(nCellsInSet);
649 forAll (cellMap_, cellI)
651 const labelList& oldC = oldCells[cellMap_[cellI]];
653 labelList newC(oldC.size());
657 newC[i] = globalFaceMap[oldC[i]];
660 newCells[nNewCells] = cell(newC);
666 fvMeshSubsetPtr_.reset
672 baseMesh().name() + "SubSet",
673 baseMesh().time().timeName(),
686 List<polyPatch*> newBoundary(nbSize);
687 patchMap_.setSize(nbSize);
688 label nNewPatches = 0;
689 label patchStart = nInternalFaces;
691 forAll(oldPatches, patchI)
693 if (boundaryPatchSizes[patchI] > 0)
695 // Patch still exists. Add it
696 newBoundary[nNewPatches] = oldPatches[patchI].clone
698 fvMeshSubsetPtr_().boundaryMesh(),
700 boundaryPatchSizes[patchI],
704 patchStart += boundaryPatchSizes[patchI];
705 patchMap_[nNewPatches] = patchI;
710 if (wantedPatchID == -1)
712 // Newly created patch so is at end. Check if any faces in it.
713 if (boundaryPatchSizes[oldInternalPatchID] > 0)
715 newBoundary[nNewPatches] = new emptyPolyPatch
718 boundaryPatchSizes[oldInternalPatchID],
721 fvMeshSubsetPtr_().boundaryMesh()
724 // The index for the first patch is -1 as it originates from
725 // the internal faces
726 patchMap_[nNewPatches] = -1;
731 // Reset the patch lists
732 newBoundary.setSize(nNewPatches);
733 patchMap_.setSize(nNewPatches);
736 fvMeshSubsetPtr_().addFvPatches(newBoundary);
738 // Subset and add any zones
743 void Foam::fvMeshSubset::setLargeCellSubset
745 const labelList& region,
746 const label currentRegion,
751 const cellList& oldCells = baseMesh().cells();
752 const faceList& oldFaces = baseMesh().faces();
753 const pointField& oldPoints = baseMesh().points();
754 const labelList& oldOwner = baseMesh().faceOwner();
755 const labelList& oldNeighbour = baseMesh().faceNeighbour();
756 const polyBoundaryMesh& oldPatches = baseMesh().boundaryMesh();
757 const label oldNInternalFaces = baseMesh().nInternalFaces();
761 if (region.size() != oldCells.size())
765 "fvMeshSubset::setCellSubset(const labelList&"
766 ", const label, const label, const bool)"
767 ) << "Size of region " << region.size()
768 << " is not equal to number of cells in mesh " << oldCells.size()
769 << abort(FatalError);
773 label wantedPatchID = patchID;
775 if (wantedPatchID == -1)
777 // No explicit patch specified. Put in oldInternalFaces patch.
778 // Check if patch with this name already exists.
779 wantedPatchID = oldPatches.findPatchID("oldInternalFaces");
781 else if (wantedPatchID < 0 || wantedPatchID >= oldPatches.size())
785 "fvMeshSubset::setCellSubset(const labelList&"
786 ", const label, const label, const bool)"
787 ) << "Non-existing patch index " << wantedPatchID << endl
788 << "Should be between 0 and " << oldPatches.size()-1
789 << abort(FatalError);
793 // Get the cells for the current region.
794 cellMap_.setSize(oldCells.size());
795 label nCellsInSet = 0;
797 forAll (region, oldCellI)
799 if (region[oldCellI] == currentRegion)
801 cellMap_[nCellsInSet++] = oldCellI;
804 cellMap_.setSize(nCellsInSet);
807 // Mark all used faces. Count number of cells using them
808 // 0: face not used anymore
809 // 1: face used by one cell, face becomes/stays boundary face
810 // 2: face still used and remains internal face
811 // 3: face coupled and used by one cell only (so should become normal,
812 // non-coupled patch face)
814 // Note that this is not really nessecary - but means we can size things
815 // correctly. Also makes handling coupled faces much easier.
817 labelList nCellsUsingFace(oldFaces.size(), 0);
819 label nFacesInSet = 0;
820 forAll (oldFaces, oldFaceI)
822 bool faceUsed = false;
824 if (region[oldOwner[oldFaceI]] == currentRegion)
826 nCellsUsingFace[oldFaceI]++;
832 baseMesh().isInternalFace(oldFaceI)
833 && (region[oldNeighbour[oldFaceI]] == currentRegion)
836 nCellsUsingFace[oldFaceI]++;
845 faceMap_.setSize(nFacesInSet);
847 // Handle coupled faces. Modifies patch faces to be uncoupled to 3.
848 doCoupledPatches(syncPar, nCellsUsingFace);
851 // See which patch to use for exposed internal faces.
852 label oldInternalPatchID = 0;
854 // Insert faces before which patch
855 label nextPatchID = oldPatches.size();
857 // old to new patches
858 labelList globalPatchMap(oldPatches.size());
861 label nbSize = oldPatches.size();
863 if (wantedPatchID == -1)
865 // Create 'oldInternalFaces' patch at the end (or before
867 // and put all exposed internal faces in there.
869 forAll(oldPatches, patchI)
871 if (isA<processorPolyPatch>(oldPatches[patchI]))
873 nextPatchID = patchI;
876 oldInternalPatchID++;
881 // adapt old to new patches for inserted patch
882 for (label oldPatchI = 0; oldPatchI < nextPatchID; oldPatchI++)
884 globalPatchMap[oldPatchI] = oldPatchI;
888 label oldPatchI = nextPatchID;
889 oldPatchI < oldPatches.size();
893 globalPatchMap[oldPatchI] = oldPatchI+1;
898 oldInternalPatchID = wantedPatchID;
899 nextPatchID = wantedPatchID+1;
901 // old to new patches
902 globalPatchMap = identity(oldPatches.size());
905 labelList boundaryPatchSizes(nbSize, 0);
908 // Make a global-to-local point map
909 labelList globalPointMap(oldPoints.size(), -1);
911 labelList globalFaceMap(oldFaces.size(), -1);
914 // 1. Pick up all preserved internal faces.
915 for (label oldFaceI = 0; oldFaceI < oldNInternalFaces; oldFaceI++)
917 if (nCellsUsingFace[oldFaceI] == 2)
919 globalFaceMap[oldFaceI] = faceI;
920 faceMap_[faceI++] = oldFaceI;
922 // Mark all points from the face
923 markPoints(oldFaces[oldFaceI], globalPointMap);
927 // These are all the internal faces in the mesh.
928 label nInternalFaces = faceI;
930 // 2. Boundary faces up to where we want to insert old internal faces
934 oldPatchI < oldPatches.size()
935 && oldPatchI < nextPatchID;
939 const polyPatch& oldPatch = oldPatches[oldPatchI];
941 label oldFaceI = oldPatch.start();
945 if (nCellsUsingFace[oldFaceI] == 1)
947 // Boundary face is kept.
949 // Mark face and increment number of points in set
950 globalFaceMap[oldFaceI] = faceI;
951 faceMap_[faceI++] = oldFaceI;
953 // Mark all points from the face
954 markPoints(oldFaces[oldFaceI], globalPointMap);
956 // Increment number of patch faces
957 boundaryPatchSizes[globalPatchMap[oldPatchI]]++;
963 // 3a. old internal faces that have become exposed.
964 for (label oldFaceI = 0; oldFaceI < oldNInternalFaces; oldFaceI++)
966 if (nCellsUsingFace[oldFaceI] == 1)
968 globalFaceMap[oldFaceI] = faceI;
969 faceMap_[faceI++] = oldFaceI;
971 // Mark all points from the face
972 markPoints(oldFaces[oldFaceI], globalPointMap);
974 // Increment number of patch faces
975 boundaryPatchSizes[oldInternalPatchID]++;
979 // 3b. coupled patch faces that have become uncoupled.
982 label oldFaceI = oldNInternalFaces;
983 oldFaceI < oldFaces.size();
987 if (nCellsUsingFace[oldFaceI] == 3)
989 globalFaceMap[oldFaceI] = faceI;
990 faceMap_[faceI++] = oldFaceI;
992 // Mark all points from the face
993 markPoints(oldFaces[oldFaceI], globalPointMap);
995 // Increment number of patch faces
996 boundaryPatchSizes[oldInternalPatchID]++;
1000 // 4. Remaining boundary faces
1003 label oldPatchI = nextPatchID;
1004 oldPatchI < oldPatches.size();
1008 const polyPatch& oldPatch = oldPatches[oldPatchI];
1010 label oldFaceI = oldPatch.start();
1012 forAll (oldPatch, i)
1014 if (nCellsUsingFace[oldFaceI] == 1)
1016 // Boundary face is kept.
1018 // Mark face and increment number of points in set
1019 globalFaceMap[oldFaceI] = faceI;
1020 faceMap_[faceI++] = oldFaceI;
1022 // Mark all points from the face
1023 markPoints(oldFaces[oldFaceI], globalPointMap);
1025 // Increment number of patch faces
1026 boundaryPatchSizes[globalPatchMap[oldPatchI]]++;
1032 if (faceI != nFacesInSet)
1036 "fvMeshSubset::setCellSubset(const labelList&"
1037 ", const label, const label, const bool)"
1038 ) << "Problem" << abort(FatalError);
1042 // Grab the points map
1043 label nPointsInSet = 0;
1045 forAll(globalPointMap, pointI)
1047 if (globalPointMap[pointI] != -1)
1052 pointMap_.setSize(nPointsInSet);
1056 forAll(globalPointMap, pointI)
1058 if (globalPointMap[pointI] != -1)
1060 pointMap_[nPointsInSet] = pointI;
1061 globalPointMap[pointI] = nPointsInSet;
1066 //Pout<< "Number of cells in new mesh : " << cellMap_.size() << endl;
1067 //Pout<< "Number of faces in new mesh : " << faceMap_.size() << endl;
1068 //Pout<< "Number of points in new mesh: " << pointMap_.size() << endl;
1071 pointField newPoints(pointMap_.size());
1073 label nNewPoints = 0;
1075 forAll (pointMap_, pointI)
1077 newPoints[nNewPoints] = oldPoints[pointMap_[pointI]];
1081 faceList newFaces(faceMap_.size());
1083 label nNewFaces = 0;
1085 // Make internal faces
1086 for (label faceI = 0; faceI < nInternalFaces; faceI++)
1088 const face& oldF = oldFaces[faceMap_[faceI]];
1090 face newF(oldF.size());
1094 newF[i] = globalPointMap[oldF[i]];
1097 newFaces[nNewFaces] = newF;
1102 // Make boundary faces. (different from internal since might need to be
1104 for (label faceI = nInternalFaces; faceI < faceMap_.size(); faceI++)
1106 label oldFaceI = faceMap_[faceI];
1108 face oldF = oldFaces[oldFaceI];
1110 // Turn the faces as necessary to point outwards
1111 if (baseMesh().isInternalFace(oldFaceI))
1113 // Was internal face. Possibly turned the wrong way round
1116 region[oldOwner[oldFaceI]] != currentRegion
1117 && region[oldNeighbour[oldFaceI]] == currentRegion
1120 oldF = oldFaces[oldFaceI].reverseFace();
1124 // Relabel vertices of the (possibly turned) face.
1125 face newF(oldF.size());
1129 newF[i] = globalPointMap[oldF[i]];
1132 newFaces[nNewFaces] = newF;
1139 cellList newCells(nCellsInSet);
1141 label nNewCells = 0;
1143 forAll (cellMap_, cellI)
1145 const labelList& oldC = oldCells[cellMap_[cellI]];
1147 labelList newC(oldC.size());
1151 newC[i] = globalFaceMap[oldC[i]];
1154 newCells[nNewCells] = cell(newC);
1160 // Note that mesh gets registered with same name as original mesh. This is
1161 // not proper but cannot be avoided since otherwise surfaceInterpolation
1162 // cannot find its fvSchemes (it will try to read e.g.
1163 // system/region0SubSet/fvSchemes)
1164 fvMeshSubsetPtr_.reset
1171 baseMesh().time().timeName(),
1176 xferMove(newPoints),
1179 syncPar // parallel synchronisation
1184 List<polyPatch*> newBoundary(nbSize);
1185 patchMap_.setSize(nbSize);
1186 label nNewPatches = 0;
1187 label patchStart = nInternalFaces;
1190 // For parallel: only remove patch if none of the processors has it.
1191 // This only gets done for patches before the one being inserted
1192 // (so patches < nextPatchID)
1194 // Get sum of patch sizes. Zero if patch can be deleted.
1195 labelList globalPatchSizes(boundaryPatchSizes);
1196 globalPatchSizes.setSize(nextPatchID);
1198 if (syncPar && Pstream::parRun())
1200 // Get patch names (up to nextPatchID)
1201 List<wordList> patchNames(Pstream::nProcs());
1202 patchNames[Pstream::myProcNo()] = oldPatches.names();
1203 patchNames[Pstream::myProcNo()].setSize(nextPatchID);
1204 Pstream::gatherList(patchNames);
1205 Pstream::scatterList(patchNames);
1207 // Get patch sizes (up to nextPatchID).
1208 // Note that up to nextPatchID the globalPatchMap is an identity so
1209 // no need to index through that.
1210 Pstream::listCombineGather(globalPatchSizes, plusEqOp<label>());
1211 Pstream::listCombineScatter(globalPatchSizes);
1213 // Now all processors have all the patchnames.
1214 // Decide: if all processors have the same patch names and size is zero
1215 // everywhere remove the patch.
1216 bool samePatches = true;
1218 for (label procI = 1; procI < patchNames.size(); procI++)
1220 if (patchNames[procI] != patchNames[0])
1222 samePatches = false;
1229 // Patchnames not sync on all processors so disable removal of
1230 // zero sized patches.
1231 globalPatchSizes = labelMax;
1240 label oldPatchI = 0;
1241 oldPatchI < oldPatches.size()
1242 && oldPatchI < nextPatchID;
1246 label newSize = boundaryPatchSizes[globalPatchMap[oldPatchI]];
1248 // Clone (even if 0 size)
1249 newBoundary[nNewPatches] = oldPatches[oldPatchI].clone
1251 fvMeshSubsetPtr_().boundaryMesh(),
1257 patchStart += newSize;
1258 patchMap_[nNewPatches] = oldPatchI; // compact patchMap
1264 if (wantedPatchID == -1)
1266 label oldInternalSize = boundaryPatchSizes[oldInternalPatchID];
1270 reduce(oldInternalSize, sumOp<label>());
1273 // Newly created patch so is at end. Check if any faces in it.
1274 if (oldInternalSize > 0)
1276 newBoundary[nNewPatches] = new emptyPolyPatch
1279 boundaryPatchSizes[oldInternalPatchID],
1282 fvMeshSubsetPtr_().boundaryMesh()
1285 //Pout<< " oldInternalFaces : "
1286 // << boundaryPatchSizes[oldInternalPatchID] << endl;
1288 // The index for the first patch is -1 as it originates from
1289 // the internal faces
1290 patchStart += boundaryPatchSizes[oldInternalPatchID];
1291 patchMap_[nNewPatches] = -1;
1300 label oldPatchI = nextPatchID;
1301 oldPatchI < oldPatches.size();
1305 label newSize = boundaryPatchSizes[globalPatchMap[oldPatchI]];
1307 // Patch still exists. Add it
1308 newBoundary[nNewPatches] = oldPatches[oldPatchI].clone
1310 fvMeshSubsetPtr_().boundaryMesh(),
1316 //Pout<< " " << oldPatches[oldPatchI].name() << " : "
1317 // << newSize << endl;
1319 patchStart += newSize;
1320 patchMap_[nNewPatches] = oldPatchI; // compact patchMap
1325 // Reset the patch lists
1326 newBoundary.setSize(nNewPatches);
1327 patchMap_.setSize(nNewPatches);
1330 // Add the fvPatches
1331 fvMeshSubsetPtr_().addFvPatches(newBoundary, syncPar);
1333 // Subset and add any zones
1338 void Foam::fvMeshSubset::setLargeCellSubset
1340 const labelHashSet& globalCellMap,
1341 const label patchID,
1345 labelList region(baseMesh().nCells(), 0);
1347 forAllConstIter (labelHashSet, globalCellMap, iter)
1349 region[iter.key()] = 1;
1351 setLargeCellSubset(region, 1, patchID, syncPar);
1355 const fvMesh& Foam::fvMeshSubset::subMesh() const
1359 return fvMeshSubsetPtr_();
1363 fvMesh& Foam::fvMeshSubset::subMesh()
1367 return fvMeshSubsetPtr_();
1371 const labelList& Foam::fvMeshSubset::pointMap() const
1379 const labelList& Foam::fvMeshSubset::faceMap() const
1387 const labelList& Foam::fvMeshSubset::cellMap() const
1395 const labelList& Foam::fvMeshSubset::patchMap() const
1403 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1405 } // End namespace Foam
1407 // ************************************************************************* //