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/>.
25 Post-processing mesh subset tool. Given the original mesh and the
26 list of selected cells, it creates the mesh consisting only of the
27 desired cells, with the mapping list for points, faces, and cells.
29 MJ 23/03/05 on coupled faces change the patch of the face to the
30 oldInternalFaces patch.
32 \*---------------------------------------------------------------------------*/
34 #include "fvMeshSubset.H"
37 #include "emptyPolyPatch.H"
38 #include "demandDrivenData.H"
39 #include "cyclicPolyPatch.H"
41 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
48 bool Foam::fvMeshSubset::checkCellSubset() const
50 if (!fvMeshSubsetPtr_)
52 FatalErrorIn("bool fvMeshSubset::checkCellSubset() const")
53 << "Mesh subset not set. Please set the cell map using "
54 << "void setCellSubset(const labelHashSet& cellsToSubset)" << endl
55 << "before attempting to access subset data"
67 void Foam::fvMeshSubset::markPoints
69 const labelList& curPoints,
73 forAll (curPoints, pointI)
75 // Note: insert will only insert if not yet there.
76 pointMap.insert(curPoints[pointI], 0);
81 void Foam::fvMeshSubset::markPoints
83 const labelList& curPoints,
87 forAll (curPoints, pointI)
89 pointMap[curPoints[pointI]] = 0;
94 // Synchronize nCellsUsingFace on both sides of coupled patches. Marks
95 // faces that become 'uncoupled' with 3.
96 void Foam::fvMeshSubset::doCoupledPatches
99 labelList& nCellsUsingFace
102 const polyBoundaryMesh& oldPatches = baseMesh().boundaryMesh();
104 label nUncoupled = 0;
106 if (syncPar && Pstream::parRun())
108 // Send face usage across processor patches
109 forAll (oldPatches, oldPatchI)
111 const polyPatch& pp = oldPatches[oldPatchI];
113 if (isA<processorPolyPatch>(pp))
115 const processorPolyPatch& procPatch =
116 refCast<const processorPolyPatch>(pp);
121 procPatch.neighbProcNo()
125 << SubList<label>(nCellsUsingFace, pp.size(), pp.start());
130 // Receive face usage count and check for faces that become uncoupled.
131 forAll (oldPatches, oldPatchI)
133 const polyPatch& pp = oldPatches[oldPatchI];
135 if (isA<processorPolyPatch>(pp))
137 const processorPolyPatch& procPatch =
138 refCast<const processorPolyPatch>(pp);
140 IPstream fromNeighbour
143 procPatch.neighbProcNo()
146 labelList nbrCellsUsingFace(fromNeighbour);
148 // Combine with this side.
154 nCellsUsingFace[pp.start()+i] == 1
155 && nbrCellsUsingFace[i] == 0
158 // Face's neighbour is no longer there. Mark face off
160 nCellsUsingFace[pp.start()+i] = 3;
168 // Do same for cyclics.
169 forAll (oldPatches, oldPatchI)
171 const polyPatch& pp = oldPatches[oldPatchI];
173 if (isA<cyclicPolyPatch>(pp))
175 const cyclicPolyPatch& cycPatch =
176 refCast<const cyclicPolyPatch>(pp);
180 label thisFaceI = cycPatch.start() + i;
181 label otherFaceI = cycPatch.transformGlobalFace(thisFaceI);
185 nCellsUsingFace[thisFaceI] == 1
186 && nCellsUsingFace[otherFaceI] == 0
189 nCellsUsingFace[thisFaceI] = 3;
198 reduce(nUncoupled, sumOp<label>());
203 Info<< "Uncoupled " << nUncoupled << " faces on coupled patches. "
204 << "(processorPolyPatch, cyclicPolyPatch)" << nl
205 << "You might need to run couplePatches to restore the patch face"
206 << " ordering." << nl << endl;
211 labelList Foam::fvMeshSubset::subset
214 const labelList& selectedElements,
215 const labelList& subsetMap
218 // Mark selected elements.
219 boolList selected(nElems, false);
220 forAll (selectedElements, i)
222 selected[selectedElements[i]] = true;
225 // Count subset of selected elements
227 forAll (subsetMap, i)
229 if (selected[subsetMap[i]])
235 // Collect selected elements
236 labelList subsettedElements(n);
241 if (selected[subsetMap[i]])
243 subsettedElements[n++] = i;
247 return subsettedElements;
251 void Foam::fvMeshSubset::subsetZones()
253 // Keep all zones, even if zero size.
255 const pointZoneMesh& pointZones = baseMesh().pointZones();
258 List<pointZone*> pZonePtrs(pointZones.size());
260 forAll(pointZones, i)
262 const pointZone& pz = pointZones[i];
264 pZonePtrs[i] = new pointZone
267 subset(baseMesh().allPoints().size(), pz, pointMap()),
269 fvMeshSubsetPtr_->pointZones()
276 const faceZoneMesh& faceZones = baseMesh().faceZones();
279 // Do we need to remove zones where the side we're interested in
280 // no longer exists? Guess not.
281 List<faceZone*> fZonePtrs(faceZones.size());
285 const faceZone& fz = faceZones[i];
287 // Create list of mesh faces part of the new zone
288 labelList subAddressing
292 baseMesh().allFaces().size(),
298 // Flipmap for all mesh faces
299 boolList fullFlipStatus(baseMesh().allFaces().size(), false);
302 fullFlipStatus[fz[j]] = fz.flipMap()[j];
305 boolList subFlipStatus(subAddressing.size(), false);
306 forAll(subAddressing, j)
308 subFlipStatus[j] = fullFlipStatus[faceMap()[subAddressing[j]]];
311 fZonePtrs[i] = new faceZone
317 fvMeshSubsetPtr_->faceZones()
322 const cellZoneMesh& cellZones = baseMesh().cellZones();
324 List<cellZone*> cZonePtrs(cellZones.size());
328 const cellZone& cz = cellZones[i];
330 cZonePtrs[i] = new cellZone
333 subset(baseMesh().nCells(), cz, cellMap()),
335 fvMeshSubsetPtr_->cellZones()
341 fvMeshSubsetPtr_->addZones(pZonePtrs, fZonePtrs, cZonePtrs);
345 void Foam::fvMeshSubset::makeFvDictionaries()
347 // Try accessing dictionaries
352 this->name() + "Subset",
353 baseMesh().time().timeName(),
360 IOdictionary fvSchemes
372 if (!fvSchemes.headerOk())
374 Info << "Cannot read " << fvSchemes.path()
375 << ". Copy from base" << endl;
377 IOdictionary fvSchemesBase
382 baseMesh().time().system(),
389 fvSchemes = fvSchemesBase;
390 fvSchemes.regIOobject::write();
393 IOdictionary fvSolution
405 if (!fvSolution.headerOk())
407 Info << "Cannot read " << fvSolution.path()
408 << ". Copy from base" << endl;
410 IOdictionary fvSolutionBase
415 baseMesh().time().system(),
422 fvSolution = fvSolutionBase;
423 fvSolution.regIOobject::write();
428 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
430 // Construct from components
431 Foam::fvMeshSubset::fvMeshSubset
434 const fvMesh& baseMesh
439 fvMeshSubsetPtr_(NULL),
440 pointMeshSubsetPtr_(NULL),
448 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
450 Foam::fvMeshSubset::~fvMeshSubset()
452 deleteDemandDrivenData(fvMeshSubsetPtr_);
453 deleteDemandDrivenData(pointMeshSubsetPtr_);
457 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
459 void Foam::fvMeshSubset::setCellSubset
461 const labelHashSet& globalCellMap,
465 // Initial check on patches before doing anything time consuming.
466 const polyBoundaryMesh& oldPatches = baseMesh().boundaryMesh();
467 const cellList& oldCells = baseMesh().cells();
468 const faceList& oldFaces = baseMesh().allFaces();
469 const pointField& oldPoints = baseMesh().points();
470 const labelList& oldOwner = baseMesh().faceOwner();
471 const labelList& oldNeighbour = baseMesh().faceNeighbour();
473 label wantedPatchID = patchID;
475 if (wantedPatchID == -1)
477 // No explicit patch specified. Put in oldInternalFaces patch.
478 // Check if patch with this name already exists.
479 wantedPatchID = oldPatches.findPatchID("oldInternalFaces");
481 else if (wantedPatchID < 0 || wantedPatchID >= oldPatches.size())
485 "fvMeshSubset::setCellSubset(const labelHashSet&"
486 ", const label patchID)"
487 ) << "Non-existing patch index " << wantedPatchID << endl
488 << "Should be between 0 and " << oldPatches.size()-1
489 << abort(FatalError);
493 cellMap_ = globalCellMap.toc();
495 // Sort the cell map in the ascending order
498 label nCellsInSet = cellMap_.size();
500 // Mark all used faces
502 Map<label> facesToSubset(primitiveMesh::facesPerCell_*nCellsInSet);
504 forAll (cellMap_, cellI)
506 // Mark all faces from the cell
507 const labelList& curFaces = oldCells[cellMap_[cellI]];
509 forAll (curFaces, faceI)
511 if (!facesToSubset.found(curFaces[faceI]))
513 facesToSubset.insert(curFaces[faceI], 1);
517 facesToSubset[curFaces[faceI]]++;
522 // Mark all used points and make a global-to-local face map
523 Map<label> globalFaceMap(facesToSubset.size());
525 // Make a global-to-local point map
526 Map<label> globalPointMap
528 primitiveMesh::pointsPerFace_*facesToSubset.size()
531 // This is done in two goes, so that the boundary faces are last
532 // in the list. Because of this, I need to create the face map
533 // along the way rather than just grab the table of contents.
534 labelList facesToc = facesToSubset.toc();
536 faceMap_.setSize(facesToc.size());
538 // 1. Get all faces that will be internal to the submesh.
539 forAll (facesToc, faceI)
541 if (facesToSubset[facesToc[faceI]] == 2)
543 // Mark face and increment number of points in set
544 faceMap_[globalFaceMap.size()] = facesToc[faceI];
545 globalFaceMap.insert(facesToc[faceI], globalFaceMap.size());
547 // Mark all points from the face
548 markPoints(oldFaces[facesToc[faceI]], globalPointMap);
552 // These are all the internal faces in the mesh.
553 label nInternalFaces = globalFaceMap.size();
556 // Where to insert old internal faces.
557 label oldPatchStart = labelMax;
558 if (wantedPatchID != -1)
560 oldPatchStart = oldPatches[wantedPatchID].start();
566 // 2. Boundary faces up to where we want to insert old internal faces
567 for (; faceI< facesToc.size(); faceI++)
569 if (facesToc[faceI] >= oldPatchStart)
575 !baseMesh().isInternalFace(facesToc[faceI])
576 && facesToSubset[facesToc[faceI]] == 1
579 // Mark face and increment number of points in set
580 faceMap_[globalFaceMap.size()] = facesToc[faceI];
581 globalFaceMap.insert(facesToc[faceI], globalFaceMap.size());
583 // Mark all points from the face
584 markPoints(oldFaces[facesToc[faceI]], globalPointMap);
588 // 3. old internal faces
589 forAll(facesToc, intFaceI)
593 baseMesh().isInternalFace(facesToc[intFaceI])
594 && facesToSubset[facesToc[intFaceI]] == 1
597 // Mark face and increment number of points in set
598 faceMap_[globalFaceMap.size()] = facesToc[intFaceI];
599 globalFaceMap.insert(facesToc[intFaceI], globalFaceMap.size());
601 // Mark all points from the face
602 markPoints(oldFaces[facesToc[intFaceI]], globalPointMap);
606 // 4. Remaining boundary faces
607 for (; faceI< facesToc.size(); faceI++)
611 !baseMesh().isInternalFace(facesToc[faceI])
612 && facesToSubset[facesToc[faceI]] == 1
615 // Mark face and increment number of points in set
616 faceMap_[globalFaceMap.size()] = facesToc[faceI];
617 globalFaceMap.insert(facesToc[faceI], globalFaceMap.size());
619 // Mark all points from the face
620 markPoints(oldFaces[facesToc[faceI]], globalPointMap);
626 // Grab the points map
627 pointMap_ = globalPointMap.toc();
630 forAll (pointMap_, pointI)
632 globalPointMap[pointMap_[pointI]] = pointI;
637 Pout<< "Number of cells in new mesh: " << nCellsInSet << nl
638 << "Number of faces in new mesh: " << globalFaceMap.size() << nl
639 << "Number of points in new mesh: " << globalPointMap.size()
644 pointField newPoints(globalPointMap.size());
646 label nNewPoints = 0;
648 forAll (pointMap_, pointI)
650 newPoints[nNewPoints] = oldPoints[pointMap_[pointI]];
654 faceList newFaces(globalFaceMap.size());
658 // Make internal faces
659 for (label faceI = 0; faceI < nInternalFaces; faceI++)
661 const face& oldF = oldFaces[faceMap_[faceI]];
663 face newF(oldF.size());
667 newF[i] = globalPointMap[oldF[i]];
670 newFaces[nNewFaces] = newF;
674 // Make boundary faces
676 label nbSize = oldPatches.size();
677 label oldInternalPatchID = -1;
679 if (wantedPatchID == -1)
681 // Create 'oldInternalFaces' patch at the end
682 // and put all exposed internal faces in there.
683 oldInternalPatchID = nbSize;
689 oldInternalPatchID = wantedPatchID;
693 // Grad size and start of each patch on the fly. Because of the
694 // structure of the underlying mesh, the patches will appear in the
696 labelList boundaryPatchSizes(nbSize, 0);
698 // Assign boundary faces. Visited in order of faceMap_.
699 for (label faceI = nInternalFaces; faceI < faceMap_.size(); faceI++)
701 label oldFaceI = faceMap_[faceI];
703 face oldF = oldFaces[oldFaceI];
705 // Turn the faces as necessary to point outwards
706 if (baseMesh().isInternalFace(oldFaceI))
708 // Internal face. Possibly turned the wrong way round
711 !globalCellMap.found(oldOwner[oldFaceI])
712 && globalCellMap.found(oldNeighbour[oldFaceI])
715 oldF = oldFaces[oldFaceI].reverseFace();
718 // Update count for patch
719 boundaryPatchSizes[oldInternalPatchID]++;
723 // Boundary face. Increment the appropriate patch
724 label patchOfFace = oldPatches.whichPatch(oldFaceI);
726 // Update count for patch
727 boundaryPatchSizes[patchOfFace]++;
730 face newF(oldF.size());
734 newF[i] = globalPointMap[oldF[i]];
737 newFaces[nNewFaces] = newF;
744 cellList newCells(nCellsInSet);
748 forAll (cellMap_, cellI)
750 const labelList& oldC = oldCells[cellMap_[cellI]];
752 labelList newC(oldC.size());
756 newC[i] = globalFaceMap[oldC[i]];
759 newCells[nNewCells] = cell(newC);
765 fvMeshSubsetPtr_ = new fvMesh
769 this->name() + "Subset",
770 baseMesh().time().timeName(),
781 deleteDemandDrivenData(pointMeshSubsetPtr_);
785 List<polyPatch*> newBoundary(nbSize);
786 patchMap_.setSize(nbSize);
787 label nNewPatches = 0;
788 label patchStart = nInternalFaces;
790 forAll(oldPatches, patchI)
792 if (boundaryPatchSizes[patchI] > 0)
794 // Patch still exists. Add it
795 newBoundary[nNewPatches] = oldPatches[patchI].clone
797 fvMeshSubsetPtr_->boundaryMesh(),
799 boundaryPatchSizes[patchI],
803 patchStart += boundaryPatchSizes[patchI];
804 patchMap_[nNewPatches] = patchI;
809 if (wantedPatchID == -1)
811 // Newly created patch so is at end. Check if any faces in it.
812 if (boundaryPatchSizes[oldInternalPatchID] > 0)
814 newBoundary[nNewPatches] = new polyPatch
817 boundaryPatchSizes[oldInternalPatchID],
820 fvMeshSubsetPtr_->boundaryMesh()
823 // The index for the first patch is -1 as it originates from
824 // the internal faces
825 patchMap_[nNewPatches] = -1;
830 // Reset the patch lists
831 newBoundary.setSize(nNewPatches);
832 patchMap_.setSize(nNewPatches);
835 fvMeshSubsetPtr_->addFvPatches(newBoundary);
837 // Subset and add any zones
842 void Foam::fvMeshSubset::setLargeCellSubset
844 const labelList& region,
845 const label currentRegion,
850 const cellList& oldCells = baseMesh().cells();
851 const faceList& oldFaces = baseMesh().faces();
852 const pointField& oldPoints = baseMesh().points();
853 const labelList& oldOwner = baseMesh().faceOwner();
854 const labelList& oldNeighbour = baseMesh().faceNeighbour();
855 const polyBoundaryMesh& oldPatches = baseMesh().boundaryMesh();
856 const label oldNInternalFaces = baseMesh().nInternalFaces();
860 if (region.size() != oldCells.size())
864 "fvMeshSubset::setCellSubset(const labelList&"
865 ", const label, const label, const bool)"
866 ) << "Size of region " << region.size()
867 << " is not equal to number of cells in mesh " << oldCells.size()
868 << abort(FatalError);
872 label wantedPatchID = patchID;
874 if (wantedPatchID == -1)
876 // No explicit patch specified. Put in oldInternalFaces patch.
877 // Check if patch with this name already exists.
878 wantedPatchID = oldPatches.findPatchID("oldInternalFaces");
880 else if (wantedPatchID < 0 || wantedPatchID >= oldPatches.size())
884 "fvMeshSubset::setCellSubset(const labelList&"
885 ", const label, const label, const bool)"
886 ) << "Non-existing patch index " << wantedPatchID << endl
887 << "Should be between 0 and " << oldPatches.size()-1
888 << abort(FatalError);
892 // Get the cells for the current region.
893 cellMap_.setSize(oldCells.size());
894 label nCellsInSet = 0;
896 forAll (region, oldCellI)
898 if (region[oldCellI] == currentRegion)
900 cellMap_[nCellsInSet++] = oldCellI;
903 cellMap_.setSize(nCellsInSet);
906 // Mark all used faces. Count number of cells using them
907 // 0: face not used anymore
908 // 1: face used by one cell, face becomes/stays boundary face
909 // 2: face still used and remains internal face
910 // 3: face coupled and used by one cell only (so should become normal,
911 // non-coupled patch face)
913 // Note that this is not really nessecary - but means we can size things
914 // correctly. Also makes handling coupled faces much easier.
916 labelList nCellsUsingFace(oldFaces.size(), 0);
918 label nFacesInSet = 0;
919 forAll (oldFaces, oldFaceI)
921 bool faceUsed = false;
923 if (region[oldOwner[oldFaceI]] == currentRegion)
925 nCellsUsingFace[oldFaceI]++;
931 baseMesh().isInternalFace(oldFaceI)
932 && (region[oldNeighbour[oldFaceI]] == currentRegion)
935 nCellsUsingFace[oldFaceI]++;
944 faceMap_.setSize(nFacesInSet);
946 // Handle coupled faces. Modifies patch faces to be uncoupled to 3.
947 doCoupledPatches(syncPar, nCellsUsingFace);
950 // See which patch to use for exposed internal faces.
951 label oldInternalPatchID = 0;
953 // Insert faces before which patch
954 label nextPatchID = oldPatches.size();
956 // old to new patches
957 labelList globalPatchMap(oldPatches.size());
960 label nbSize = oldPatches.size();
962 if (wantedPatchID == -1)
964 // Create 'oldInternalFaces' patch at the end (or before
966 // and put all exposed internal faces in there.
968 forAll(oldPatches, patchI)
970 if (isA<processorPolyPatch>(oldPatches[patchI]))
972 nextPatchID = patchI;
975 oldInternalPatchID++;
980 // adapt old to new patches for inserted patch
981 for (label oldPatchI = 0; oldPatchI < nextPatchID; oldPatchI++)
983 globalPatchMap[oldPatchI] = oldPatchI;
987 label oldPatchI = nextPatchID;
988 oldPatchI < oldPatches.size();
992 globalPatchMap[oldPatchI] = oldPatchI+1;
997 oldInternalPatchID = wantedPatchID;
998 nextPatchID = wantedPatchID+1;
1000 // old to new patches
1001 globalPatchMap = identity(oldPatches.size());
1004 labelList boundaryPatchSizes(nbSize, 0);
1007 // Make a global-to-local point map
1008 labelList globalPointMap(oldPoints.size(), -1);
1010 labelList globalFaceMap(oldFaces.size(), -1);
1013 // 1. Pick up all preserved internal faces.
1014 for (label oldFaceI = 0; oldFaceI < oldNInternalFaces; oldFaceI++)
1016 if (nCellsUsingFace[oldFaceI] == 2)
1018 globalFaceMap[oldFaceI] = faceI;
1019 faceMap_[faceI++] = oldFaceI;
1021 // Mark all points from the face
1022 markPoints(oldFaces[oldFaceI], globalPointMap);
1026 // These are all the internal faces in the mesh.
1027 label nInternalFaces = faceI;
1029 // 2. Boundary faces up to where we want to insert old internal faces
1032 label oldPatchI = 0;
1033 oldPatchI < oldPatches.size()
1034 && oldPatchI < nextPatchID;
1038 const polyPatch& oldPatch = oldPatches[oldPatchI];
1040 label oldFaceI = oldPatch.start();
1042 forAll (oldPatch, i)
1044 if (nCellsUsingFace[oldFaceI] == 1)
1046 // Boundary face is kept.
1048 // Mark face and increment number of points in set
1049 globalFaceMap[oldFaceI] = faceI;
1050 faceMap_[faceI++] = oldFaceI;
1052 // Mark all points from the face
1053 markPoints(oldFaces[oldFaceI], globalPointMap);
1055 // Increment number of patch faces
1056 boundaryPatchSizes[globalPatchMap[oldPatchI]]++;
1062 // 3a. old internal faces that have become exposed.
1063 for (label oldFaceI = 0; oldFaceI < oldNInternalFaces; oldFaceI++)
1065 if (nCellsUsingFace[oldFaceI] == 1)
1067 globalFaceMap[oldFaceI] = faceI;
1068 faceMap_[faceI++] = oldFaceI;
1070 // Mark all points from the face
1071 markPoints(oldFaces[oldFaceI], globalPointMap);
1073 // Increment number of patch faces
1074 boundaryPatchSizes[oldInternalPatchID]++;
1078 // 3b. coupled patch faces that have become uncoupled.
1081 label oldFaceI = oldNInternalFaces;
1082 oldFaceI < oldFaces.size();
1086 if (nCellsUsingFace[oldFaceI] == 3)
1088 globalFaceMap[oldFaceI] = faceI;
1089 faceMap_[faceI++] = oldFaceI;
1091 // Mark all points from the face
1092 markPoints(oldFaces[oldFaceI], globalPointMap);
1094 // Increment number of patch faces
1095 boundaryPatchSizes[oldInternalPatchID]++;
1099 // 4. Remaining boundary faces
1102 label oldPatchI = nextPatchID;
1103 oldPatchI < oldPatches.size();
1107 const polyPatch& oldPatch = oldPatches[oldPatchI];
1109 label oldFaceI = oldPatch.start();
1111 forAll (oldPatch, i)
1113 if (nCellsUsingFace[oldFaceI] == 1)
1115 // Boundary face is kept.
1117 // Mark face and increment number of points in set
1118 globalFaceMap[oldFaceI] = faceI;
1119 faceMap_[faceI++] = oldFaceI;
1121 // Mark all points from the face
1122 markPoints(oldFaces[oldFaceI], globalPointMap);
1124 // Increment number of patch faces
1125 boundaryPatchSizes[globalPatchMap[oldPatchI]]++;
1131 if (faceI != nFacesInSet)
1135 "fvMeshSubset::setCellSubset(const labelList&"
1136 ", const label, const label, const bool)"
1137 ) << "Problem" << abort(FatalError);
1141 // Grab the points map
1142 label nPointsInSet = 0;
1144 forAll(globalPointMap, pointI)
1146 if (globalPointMap[pointI] != -1)
1151 pointMap_.setSize(nPointsInSet);
1155 forAll(globalPointMap, pointI)
1157 if (globalPointMap[pointI] != -1)
1159 pointMap_[nPointsInSet] = pointI;
1160 globalPointMap[pointI] = nPointsInSet;
1165 Pout<< "Number of cells in new mesh : " << cellMap_.size() << endl;
1166 Pout<< "Number of faces in new mesh : " << faceMap_.size() << endl;
1167 Pout<< "Number of points in new mesh: " << pointMap_.size() << endl;
1170 pointField newPoints(pointMap_.size());
1172 label nNewPoints = 0;
1174 forAll (pointMap_, pointI)
1176 newPoints[nNewPoints] = oldPoints[pointMap_[pointI]];
1180 faceList newFaces(faceMap_.size());
1182 label nNewFaces = 0;
1184 // Make internal faces
1185 for (label faceI = 0; faceI < nInternalFaces; faceI++)
1187 const face& oldF = oldFaces[faceMap_[faceI]];
1189 face newF(oldF.size());
1193 newF[i] = globalPointMap[oldF[i]];
1196 newFaces[nNewFaces] = newF;
1201 // Make boundary faces. (different from internal since might need to be
1203 for (label faceI = nInternalFaces; faceI < faceMap_.size(); faceI++)
1205 label oldFaceI = faceMap_[faceI];
1207 face oldF = oldFaces[oldFaceI];
1209 // Turn the faces as necessary to point outwards
1210 if (baseMesh().isInternalFace(oldFaceI))
1212 // Was internal face. Possibly turned the wrong way round
1215 region[oldOwner[oldFaceI]] != currentRegion
1216 && region[oldNeighbour[oldFaceI]] == currentRegion
1219 oldF = oldFaces[oldFaceI].reverseFace();
1223 // Relabel vertices of the (possibly turned) face.
1224 face newF(oldF.size());
1228 newF[i] = globalPointMap[oldF[i]];
1231 newFaces[nNewFaces] = newF;
1238 cellList newCells(nCellsInSet);
1240 label nNewCells = 0;
1242 forAll (cellMap_, cellI)
1244 const labelList& oldC = oldCells[cellMap_[cellI]];
1246 labelList newC(oldC.size());
1250 newC[i] = globalFaceMap[oldC[i]];
1253 newCells[nNewCells] = cell(newC);
1259 makeFvDictionaries();
1261 fvMeshSubsetPtr_ = new fvMesh
1265 this->name() + "Subset",
1266 baseMesh().time().timeName(),
1271 xferMove(newPoints),
1274 syncPar // parallel synchronisation
1278 deleteDemandDrivenData(pointMeshSubsetPtr_);
1281 List<polyPatch*> newBoundary(nbSize);
1282 patchMap_.setSize(nbSize);
1283 label nNewPatches = 0;
1284 label patchStart = nInternalFaces;
1287 // For parallel: only remove patch if none of the processors has it.
1288 // This only gets done for patches before the one being inserted
1289 // (so patches < nextPatchID)
1291 // Get sum of patch sizes. Zero if patch can be deleted.
1292 labelList globalPatchSizes(boundaryPatchSizes);
1293 globalPatchSizes.setSize(nextPatchID);
1295 if (syncPar && Pstream::parRun())
1297 // Get patch names (up to nextPatchID)
1298 List<wordList> patchNames(Pstream::nProcs());
1299 patchNames[Pstream::myProcNo()] = oldPatches.names();
1300 patchNames[Pstream::myProcNo()].setSize(nextPatchID);
1301 Pstream::gatherList(patchNames);
1302 Pstream::scatterList(patchNames);
1304 // Get patch sizes (up to nextPatchID).
1305 // Note that up to nextPatchID the globalPatchMap is an identity so
1306 // no need to index through that.
1307 Pstream::listCombineGather(globalPatchSizes, plusEqOp<label>());
1308 Pstream::listCombineScatter(globalPatchSizes);
1310 // Now all processors have all the patchnames.
1311 // Decide: if all processors have the same patch names and size is zero
1312 // everywhere remove the patch.
1313 bool samePatches = true;
1315 for (label procI = 1; procI < patchNames.size(); procI++)
1317 if (patchNames[procI] != patchNames[0])
1319 samePatches = false;
1326 // Patchnames not sync on all processors so disable removal of
1327 // zero sized patches.
1328 globalPatchSizes = labelMax;
1337 label oldPatchI = 0;
1338 oldPatchI < oldPatches.size()
1339 && oldPatchI < nextPatchID;
1343 label newSize = boundaryPatchSizes[globalPatchMap[oldPatchI]];
1345 // Clone (even if 0 size)
1346 newBoundary[nNewPatches] = oldPatches[oldPatchI].clone
1348 fvMeshSubsetPtr_->boundaryMesh(),
1354 patchStart += newSize;
1355 patchMap_[nNewPatches] = oldPatchI; // compact patchMap
1361 if (wantedPatchID == -1)
1363 label oldInternalSize = boundaryPatchSizes[oldInternalPatchID];
1367 reduce(oldInternalSize, sumOp<label>());
1370 // Newly created patch so is at end. Check if any faces in it.
1371 if (oldInternalSize > 0)
1373 newBoundary[nNewPatches] = new polyPatch
1376 boundaryPatchSizes[oldInternalPatchID],
1379 fvMeshSubsetPtr_->boundaryMesh()
1382 Pout<< " oldInternalFaces : "
1383 << boundaryPatchSizes[oldInternalPatchID] << endl;
1385 // The index for the first patch is -1 as it originates from
1386 // the internal faces
1387 patchStart += boundaryPatchSizes[oldInternalPatchID];
1388 patchMap_[nNewPatches] = -1;
1397 label oldPatchI = nextPatchID;
1398 oldPatchI < oldPatches.size();
1402 label newSize = boundaryPatchSizes[globalPatchMap[oldPatchI]];
1404 // Patch still exists. Add it
1405 newBoundary[nNewPatches] = oldPatches[oldPatchI].clone
1407 fvMeshSubsetPtr_->boundaryMesh(),
1413 //Pout<< " " << oldPatches[oldPatchI].name() << " : "
1414 // << newSize << endl;
1416 patchStart += newSize;
1417 patchMap_[nNewPatches] = oldPatchI; // compact patchMap
1422 // Reset the patch lists
1423 newBoundary.setSize(nNewPatches);
1424 patchMap_.setSize(nNewPatches);
1427 // Add the fvPatches
1428 fvMeshSubsetPtr_->addFvPatches(newBoundary, syncPar);
1430 // Subset and add any zones
1435 void Foam::fvMeshSubset::setLargeCellSubset
1437 const labelHashSet& globalCellMap,
1438 const label patchID,
1442 labelList region(baseMesh().nCells(), 0);
1444 forAllConstIter (labelHashSet, globalCellMap, iter)
1446 region[iter.key()] = 1;
1448 setLargeCellSubset(region, 1, patchID, syncPar);
1452 const fvMesh& Foam::fvMeshSubset::subMesh() const
1456 return *fvMeshSubsetPtr_;
1460 fvMesh& Foam::fvMeshSubset::subMesh()
1464 return *fvMeshSubsetPtr_;
1468 const pointMesh& Foam::fvMeshSubset::subPointMesh() const
1470 if (!pointMeshSubsetPtr_)
1472 pointMeshSubsetPtr_ = new pointMesh(subMesh());
1475 return *pointMeshSubsetPtr_;
1479 pointMesh& Foam::fvMeshSubset::subPointMesh()
1481 if (!pointMeshSubsetPtr_)
1483 pointMeshSubsetPtr_ = new pointMesh(subMesh());
1486 return *pointMeshSubsetPtr_;
1490 const labelList& Foam::fvMeshSubset::pointMap() const
1498 const labelList& Foam::fvMeshSubset::faceMap() const
1506 const labelList& Foam::fvMeshSubset::cellMap() const
1514 const labelList& Foam::fvMeshSubset::patchMap() const
1522 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1524 } // End namespace Foam
1526 // ************************************************************************* //