fvMeshSubset.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
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
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Description
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.
28 
29 \*---------------------------------------------------------------------------*/
30 
31 #include "fvMeshSubset.H"
32 #include "boolList.H"
33 #include "Pstream.H"
34 #include "internalPolyPatch.H"
35 #include "demandDrivenData.H"
36 #include "cyclicPolyPatch.H"
37 #include "processorPolyPatch.H"
38 #include "removeCells.H"
39 #include "polyTopoChange.H"
40 #include "polyTopoChangeMap.H"
41 
42 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
43 
44 namespace Foam
45 {
47 }
48 
49 
50 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
51 
52 bool Foam::fvMeshSubset::checkCellSubset() const
53 {
54  if (fvMeshSubsetPtr_.empty())
55  {
57  << "void setCellSubset(const labelHashSet& cellsToSubset)" << endl
58  << "before attempting to access subset data"
59  << abort(FatalError);
60 
61  return false;
62  }
63  else
64  {
65  return true;
66  }
67 }
68 
69 
70 void Foam::fvMeshSubset::markPoints
71 (
72  const labelList& curPoints,
73  Map<label>& pointMap
74 )
75 {
76  forAll(curPoints, pointi)
77  {
78  // Note: insert will only insert if not yet there.
79  pointMap.insert(curPoints[pointi], 0);
80  }
81 }
82 
83 
84 void Foam::fvMeshSubset::markPoints
85 (
86  const labelList& curPoints,
87  labelList& pointMap
88 )
89 {
90  forAll(curPoints, pointi)
91  {
92  pointMap[curPoints[pointi]] = 0;
93  }
94 }
95 
96 
97 void Foam::fvMeshSubset::doCoupledPatches
98 (
99  const bool syncPar,
100  Map<label>& facesToSubset,
101  labelList& nCellsUsingFace
102 ) const
103 {
104  // Synchronise facesToSubset on both sides of coupled patches.
105  // Marks faces that become 'uncoupled' with 3.
106 
107  const polyBoundaryMesh& oldPatches = baseMesh().poly().boundary();
108 
109  label nUncoupled = 0;
110 
111  if (syncPar && Pstream::parRun())
112  {
113  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
114 
115  // Send face usage across processor patches
116  forAll(oldPatches, oldPatchi)
117  {
118  const polyPatch& pp = oldPatches[oldPatchi];
119 
120  if (isA<processorPolyPatch>(pp))
121  {
122  const processorPolyPatch& procPatch =
123  refCast<const processorPolyPatch>(pp);
124 
125  UOPstream toNeighbour(procPatch.neighbProcNo(), pBufs);
126 
127  if (!facesToSubset.empty())
128  {
129  DynamicList<label> patchFacesToSubset;
130  forAll(pp, i)
131  {
132  if
133  (
134  facesToSubset.found(pp.start()+i)
135  && facesToSubset[pp.start()+i] == 1
136  )
137  {
138  patchFacesToSubset.append(i);
139  }
140  }
141  toNeighbour << patchFacesToSubset;
142  }
143  else if (!nCellsUsingFace.empty())
144  {
145  toNeighbour <<
146  SubList<label>(nCellsUsingFace, pp.size(), pp.start());
147  }
148  else
149  {
150  toNeighbour << labelList();
151  }
152  }
153  }
154 
155  pBufs.finishedSends();
156 
157  // Receive face usage count and check for faces that become uncoupled.
158  forAll(oldPatches, oldPatchi)
159  {
160  const polyPatch& pp = oldPatches[oldPatchi];
161 
162  if (isA<processorPolyPatch>(pp))
163  {
164  const processorPolyPatch& procPatch =
165  refCast<const processorPolyPatch>(pp);
166 
167  UIPstream fromNeighbour(procPatch.neighbProcNo(), pBufs);
168 
169  const labelList nbrList(fromNeighbour);
170 
171  // Combine with this side.
172 
173  if (!facesToSubset.empty())
174  {
175  const labelHashSet nbrPatchFacesToSubset(nbrList);
176 
177  forAll(pp, i)
178  {
179  if
180  (
181  facesToSubset.found(pp.start()+i)
182  && facesToSubset[pp.start()+i] == 1
183  && !nbrPatchFacesToSubset.found(i)
184  )
185  {
186  // Face's neighbour is no longer there. Mark face
187  // off as coupled
188  facesToSubset[pp.start()+i] = 3;
189  nUncoupled++;
190  }
191  }
192  }
193  else if (!nCellsUsingFace.empty())
194  {
195  const labelList& nbrCellsUsingFace(nbrList);
196 
197  // Combine with this side.
198 
199  forAll(pp, i)
200  {
201  if
202  (
203  nCellsUsingFace[pp.start()+i] == 1
204  && nbrCellsUsingFace[i] == 0
205  )
206  {
207  // Face's neighbour is no longer there. Mark face
208  // off as coupled
209  nCellsUsingFace[pp.start()+i] = 3;
210  nUncoupled++;
211  }
212  }
213  }
214  }
215  }
216  }
217 
218  // Do same for cyclics.
219  forAll(oldPatches, oldPatchi)
220  {
221  const polyPatch& pp = oldPatches[oldPatchi];
222 
223  if (isA<cyclicPolyPatch>(pp))
224  {
225  const cyclicPolyPatch& cycPatch =
226  refCast<const cyclicPolyPatch>(pp);
227 
228  if (!facesToSubset.empty())
229  {
230  forAll(cycPatch, i)
231  {
232  const label thisFacei = cycPatch.start() + i;
233  const label otherFacei =
234  cycPatch.transformGlobalFace(thisFacei);
235 
236  if
237  (
238  facesToSubset.found(thisFacei)
239  && facesToSubset[thisFacei] == 1
240  && !facesToSubset.found(otherFacei)
241  )
242  {
243  facesToSubset[thisFacei] = 3;
244  nUncoupled++;
245  }
246  }
247  }
248  else if (!nCellsUsingFace.empty())
249  {
250  forAll(cycPatch, i)
251  {
252  const label thisFacei = cycPatch.start() + i;
253  const label otherFacei =
254  cycPatch.transformGlobalFace(thisFacei);
255 
256  if
257  (
258  nCellsUsingFace[thisFacei] == 1
259  && nCellsUsingFace[otherFacei] == 0
260  )
261  {
262  nCellsUsingFace[thisFacei] = 3;
263  nUncoupled++;
264  }
265  }
266  }
267  }
268  }
269 
270  if (syncPar)
271  {
272  reduce(nUncoupled, sumOp<label>());
273  }
274 
275  if (debug && nUncoupled > 0)
276  {
277  Info<< "Uncoupled " << nUncoupled << " faces on coupled patches. "
278  << "(processorPolyPatch, cyclicPolyPatch)" << endl;
279  }
280 }
281 
282 
283 Foam::labelList Foam::fvMeshSubset::subset
284 (
285  const label nElems,
286  const labelList& selectedElements,
287  const labelList& subsetMap
288 )
289 {
290  // Mark selected elements.
291  boolList selected(nElems, false);
292  forAll(selectedElements, i)
293  {
294  selected[selectedElements[i]] = true;
295  }
296 
297  // Count subset of selected elements
298  label n = 0;
299  forAll(subsetMap, i)
300  {
301  if (selected[subsetMap[i]])
302  {
303  n++;
304  }
305  }
306 
307  // Collect selected elements
308  labelList subsettedElements(n);
309  n = 0;
310 
311  forAll(subsetMap, i)
312  {
313  if (selected[subsetMap[i]])
314  {
315  subsettedElements[n++] = i;
316  }
317  }
318 
319  return subsettedElements;
320 }
321 
322 
323 void Foam::fvMeshSubset::subsetZones()
324 {
325  // Keep all zones, even if zero size.
326 
327  const pointZoneList& pointZones = baseMesh().pointZones();
328 
329  // PointZones
330  List<pointZone*> pZonePtrs(pointZones.size());
331 
332  forAll(pointZones, i)
333  {
334  const pointZone& pz = pointZones[i];
335 
336  pZonePtrs[i] = new pointZone
337  (
338  pz.name(),
339  subset(baseMesh().nPoints(), pz, pointMap()),
340  fvMeshSubsetPtr_().pointZones()
341  );
342  }
343 
344 
345  // FaceZones
346  const faceZoneList& faceZones = baseMesh().faceZones();
347 
348  // Do we need to remove zones where the side we're interested in
349  // no longer exists? Guess not.
350  List<faceZone*> fZonePtrs(faceZones.size());
351 
352  forAll(faceZones, i)
353  {
354  const faceZone& fz = faceZones[i];
355 
356  // Expand faceZone to full mesh
357  // +1 : part of faceZone, flipped
358  // -1 : ,, , unflipped
359  // 0 : not part of faceZone
360  labelList zone(baseMesh().nFaces(), 0);
361 
362  if (fz.oriented())
363  {
364  const boolList& flipMap = fz.flipMap();
365  forAll(fz, j)
366  {
367  if (flipMap[j])
368  {
369  zone[fz[j]] = 1;
370  }
371  else
372  {
373  zone[fz[j]] = -1;
374  }
375  }
376  }
377  else
378  {
379  forAll(fz, j)
380  {
381  zone[fz[j]] = -1;
382  }
383  }
384 
385  // Select faces
386  label nSub = 0;
387  forAll(faceMap(), j)
388  {
389  if (zone[faceMap()[j]] != 0)
390  {
391  nSub++;
392  }
393  }
394  labelList subAddressing(nSub);
395  boolList subFlipStatus(nSub);
396  nSub = 0;
397  forAll(faceMap(), subFacei)
398  {
399  const label meshFacei = faceMap()[subFacei];
400  if (zone[meshFacei] != 0)
401  {
402  subAddressing[nSub] = subFacei;
403  const label subOwner = subMesh().faceOwner()[subFacei];
404  const label baseOwner = baseMesh().faceOwner()[meshFacei];
405  // If subowner is the same cell as the base keep the flip status
406  const bool sameOwner = (cellMap()[subOwner] == baseOwner);
407  const bool flip = (zone[meshFacei] == 1);
408  subFlipStatus[nSub] = (sameOwner == flip);
409 
410  nSub++;
411  }
412  }
413 
414  if (fz.oriented())
415  {
416  fZonePtrs[i] = new faceZone
417  (
418  fz.name(),
419  subAddressing,
420  subFlipStatus,
421  fvMeshSubsetPtr_().faceZones()
422  );
423  }
424  else
425  {
426  fZonePtrs[i] = new faceZone
427  (
428  fz.name(),
429  subAddressing,
430  fvMeshSubsetPtr_().faceZones()
431  );
432  }
433  }
434 
435  // CellZones
436  const cellZoneList& cellZones = baseMesh().cellZones();
437 
438  List<cellZone*> cZonePtrs(cellZones.size());
439 
440  forAll(cellZones, i)
441  {
442  const cellZone& cz = cellZones[i];
443 
444  cZonePtrs[i] = new cellZone
445  (
446  cz.name(),
447  subset(baseMesh().nCells(), cz, cellMap()),
448  fvMeshSubsetPtr_().cellZones()
449  );
450  }
451 
452 
453  // Add the zones
454  fvMeshSubsetPtr_().addZones(pZonePtrs, fZonePtrs, cZonePtrs);
455 }
456 
457 
458 Foam::labelList Foam::fvMeshSubset::getCellsToRemove
459 (
460  const labelList& region,
461  const label currentRegion
462 ) const
463 {
464  // Count
465  label nKeep = 0;
466  forAll(region, cellI)
467  {
468  if (region[cellI] == currentRegion)
469  {
470  nKeep++;
471  }
472  }
473 
474  // Collect cells to remove
475  label nRemove = baseMesh().nCells() - nKeep;
476  labelList cellsToRemove(nRemove);
477 
478  nRemove = 0;
479  forAll(region, cellI)
480  {
481  if (region[cellI] != currentRegion)
482  {
483  cellsToRemove[nRemove++] = cellI;
484  }
485  }
486 
487  return cellsToRemove;
488 }
489 
490 
491 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
492 
494 :
495  baseMesh_(baseMesh),
496  fvMeshSubsetPtr_(nullptr),
497  pointMap_(0),
498  faceMap_(0),
499  cellMap_(0),
500  patchMap_(0),
501  faceFlipMapPtr_()
502 {}
503 
504 
505 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
506 
508 {}
509 
510 
511 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
512 
514 (
515  const labelHashSet& globalCellMap,
516  const label patchID,
517  const bool syncPar
518 )
519 {
520  // Initial check on patches before doing anything time consuming.
521  const polyBoundaryMesh& oldPatches = baseMesh().poly().boundary();
522  const cellList& oldCells = baseMesh().cells();
523  const faceList& oldFaces = baseMesh().faces();
524  const pointField& oldPoints = baseMesh().points();
525  const labelList& oldOwner = baseMesh().faceOwner();
526  const labelList& oldNeighbour = baseMesh().faceNeighbour();
527 
528  label wantedPatchID = patchID;
529 
530  if (wantedPatchID == -1)
531  {
532  // No explicit patch specified. Put in oldInternalFaces patch.
533  // Check if patch with this name already exists.
534  wantedPatchID = oldPatches.findIndex("oldInternalFaces");
535  }
536  else if (wantedPatchID < 0 || wantedPatchID >= oldPatches.size())
537  {
539  << "Non-existing patch index " << wantedPatchID << endl
540  << "Should be between 0 and " << oldPatches.size()-1
541  << abort(FatalError);
542  }
543 
544 
545  // Clear demand driven data
546  faceFlipMapPtr_.clear();
547 
548 
549  cellMap_ = globalCellMap.toc();
550 
551  // Sort the cell map in the ascending order
552  sort(cellMap_);
553 
554  // Approximate sizing parameters for face and point lists
555  const label avgNFacesPerCell = 6;
556  const label avgNPointsPerFace = 4;
557 
558 
559  const label nCellsInSet = cellMap_.size();
560 
561  // Mark all used faces
562 
563  Map<label> facesToSubset(avgNFacesPerCell*nCellsInSet);
564 
565  forAll(cellMap_, celli)
566  {
567  // Mark all faces from the cell
568  const labelList& curFaces = oldCells[cellMap_[celli]];
569 
570  forAll(curFaces, facei)
571  {
572  if (!facesToSubset.found(curFaces[facei]))
573  {
574  facesToSubset.insert(curFaces[facei], 1);
575  }
576  else
577  {
578  facesToSubset[curFaces[facei]]++;
579  }
580  }
581  }
582 
583  // Handle coupled faces. Modifies patch faces to be uncoupled to 3.
584  labelList empty;
585  doCoupledPatches(syncPar, facesToSubset, empty);
586 
587  // Mark all used points and make a global-to-local face map
588  Map<label> globalFaceMap(facesToSubset.size());
589 
590  // Make a global-to-local point map
591  Map<label> globalPointMap(avgNPointsPerFace*facesToSubset.size());
592 
593  // This is done in two goes, so that the boundary faces are last
594  // in the list. Because of this, I need to create the face map
595  // along the way rather than just grab the table of contents.
596  labelList facesToc = facesToSubset.toc();
597  sort(facesToc);
598  faceMap_.setSize(facesToc.size());
599 
600  // 1. Get all faces that will be internal to the submesh.
601  forAll(facesToc, facei)
602  {
603  if (facesToSubset[facesToc[facei]] == 2)
604  {
605  // Mark face and increment number of points in set
606  faceMap_[globalFaceMap.size()] = facesToc[facei];
607  globalFaceMap.insert(facesToc[facei], globalFaceMap.size());
608 
609  // Mark all points from the face
610  markPoints(oldFaces[facesToc[facei]], globalPointMap);
611  }
612  }
613 
614  // These are all the internal faces in the mesh.
615  const label nInternalFaces = globalFaceMap.size();
616 
617 
618  // Where to insert old internal faces.
619  label oldPatchStart = labelMax;
620  if (wantedPatchID != -1)
621  {
622  oldPatchStart = oldPatches[wantedPatchID].start();
623  }
624 
625 
626  label facei = 0;
627 
628  // 2. Boundary faces up to where we want to insert old internal faces
629  for (; facei< facesToc.size(); facei++)
630  {
631  if (facesToc[facei] >= oldPatchStart)
632  {
633  break;
634  }
635  if
636  (
637  !baseMesh().isInternalFace(facesToc[facei])
638  && facesToSubset[facesToc[facei]] == 1
639  )
640  {
641  // Mark face and increment number of points in set
642  faceMap_[globalFaceMap.size()] = facesToc[facei];
643  globalFaceMap.insert(facesToc[facei], globalFaceMap.size());
644 
645  // Mark all points from the face
646  markPoints(oldFaces[facesToc[facei]], globalPointMap);
647  }
648  }
649 
650  // 3. old internal faces and uncoupled faces
651  forAll(facesToc, intFacei)
652  {
653  if
654  (
655  (
656  baseMesh().isInternalFace(facesToc[intFacei])
657  && facesToSubset[facesToc[intFacei]] == 1
658  )
659  || (
660  !baseMesh().isInternalFace(facesToc[intFacei])
661  && facesToSubset[facesToc[intFacei]] == 3
662  )
663  )
664  {
665  // Mark face and increment number of points in set
666  faceMap_[globalFaceMap.size()] = facesToc[intFacei];
667  globalFaceMap.insert(facesToc[intFacei], globalFaceMap.size());
668 
669  // Mark all points from the face
670  markPoints(oldFaces[facesToc[intFacei]], globalPointMap);
671  }
672  }
673 
674  // 4. Remaining boundary faces
675  for (; facei< facesToc.size(); facei++)
676  {
677  if
678  (
679  !baseMesh().isInternalFace(facesToc[facei])
680  && facesToSubset[facesToc[facei]] == 1
681  )
682  {
683  // Mark face and increment number of points in set
684  faceMap_[globalFaceMap.size()] = facesToc[facei];
685  globalFaceMap.insert(facesToc[facei], globalFaceMap.size());
686 
687  // Mark all points from the face
688  markPoints(oldFaces[facesToc[facei]], globalPointMap);
689  }
690  }
691 
692 
693 
694  // Grab the points map
695  pointMap_ = globalPointMap.toc();
696  sort(pointMap_);
697 
698  forAll(pointMap_, pointi)
699  {
700  globalPointMap[pointMap_[pointi]] = pointi;
701  }
702 
703  // Make a new mesh
704  pointField newPoints(globalPointMap.size());
705 
706  label nNewPoints = 0;
707 
708  forAll(pointMap_, pointi)
709  {
710  newPoints[nNewPoints] = oldPoints[pointMap_[pointi]];
711  nNewPoints++;
712  }
713 
714  faceList newFaces(globalFaceMap.size());
715 
716  label nNewFaces = 0;
717 
718  // Make internal faces
719  for (label facei = 0; facei < nInternalFaces; facei++)
720  {
721  const face& oldF = oldFaces[faceMap_[facei]];
722 
723  face newF(oldF.size());
724 
725  forAll(newF, i)
726  {
727  newF[i] = globalPointMap[oldF[i]];
728  }
729 
730  newFaces[nNewFaces] = newF;
731  nNewFaces++;
732  }
733 
734  // Make boundary faces
735 
736  label nbSize = oldPatches.size();
737  label oldInternalPatchID = -1;
738 
739  if (wantedPatchID == -1)
740  {
741  // Create 'oldInternalFaces' patch at the end
742  // and put all exposed internal faces in there.
743  oldInternalPatchID = nbSize;
744  nbSize++;
745 
746  }
747  else
748  {
749  oldInternalPatchID = wantedPatchID;
750  }
751 
752 
753  // Grad size and start of each patch on the fly. Because of the
754  // structure of the underlying mesh, the patches will appear in the
755  // ascending order
756  labelList boundaryPatchSizes(nbSize, 0);
757 
758  // Assign boundary faces. Visited in order of faceMap_.
759  for (label facei = nInternalFaces; facei < faceMap_.size(); facei++)
760  {
761  const label oldFacei = faceMap_[facei];
762 
763  face oldF = oldFaces[oldFacei];
764 
765  // Turn the faces as necessary to point outwards
766  if (baseMesh().isInternalFace(oldFacei))
767  {
768  // Internal face. Possibly turned the wrong way round
769  if
770  (
771  !globalCellMap.found(oldOwner[oldFacei])
772  && globalCellMap.found(oldNeighbour[oldFacei])
773  )
774  {
775  oldF = oldFaces[oldFacei].reverseFace();
776  }
777 
778  // Update count for patch
779  boundaryPatchSizes[oldInternalPatchID]++;
780  }
781  else if (facesToSubset[oldFacei] == 3)
782  {
783  // Uncoupled face. Increment the old patch.
784  boundaryPatchSizes[oldInternalPatchID]++;
785  }
786  else
787  {
788  // Boundary face. Increment the appropriate patch
789  const label patchOfFace = oldPatches.whichPatch(oldFacei);
790 
791  // Update count for patch
792  boundaryPatchSizes[patchOfFace]++;
793  }
794 
795  face newF(oldF.size());
796 
797  forAll(newF, i)
798  {
799  newF[i] = globalPointMap[oldF[i]];
800  }
801 
802  newFaces[nNewFaces] = newF;
803  nNewFaces++;
804  }
805 
806 
807 
808  // Create cells
809  cellList newCells(nCellsInSet);
810 
811  label nNewCells = 0;
812 
813  forAll(cellMap_, celli)
814  {
815  const labelList& oldC = oldCells[cellMap_[celli]];
816 
817  labelList newC(oldC.size());
818 
819  forAll(newC, i)
820  {
821  newC[i] = globalFaceMap[oldC[i]];
822  }
823 
824  newCells[nNewCells] = cell(newC);
825  nNewCells++;
826  }
827 
828 
829  // Delete any old mesh
830  fvMeshSubsetPtr_.clear();
831 
832  // Make a new mesh
833  fvMeshSubsetPtr_.reset
834  (
835  new fvMesh
836  (
837  IOobject
838  (
839  baseMesh().name() + "SubSet",
840  baseMesh().time().name(),
841  baseMesh().time(),
844  ),
845  move(newPoints),
846  move(newFaces),
847  move(newCells)
848  )
849  );
850 
851 
852  // Add old patches
853  List<polyPatch*> newBoundary(nbSize);
854  patchMap_.setSize(nbSize);
855  label nNewPatches = 0;
856  label patchStart = nInternalFaces;
857 
858 
859  forAll(oldPatches, patchi)
860  {
861  if (boundaryPatchSizes[patchi] > 0)
862  {
863  // Patch still exists. Add it
864  newBoundary[nNewPatches] = oldPatches[patchi].clone
865  (
866  fvMeshSubsetPtr_().poly().boundary(),
867  nNewPatches,
868  boundaryPatchSizes[patchi],
869  patchStart
870  ).ptr();
871 
872  patchStart += boundaryPatchSizes[patchi];
873  patchMap_[nNewPatches] = patchi;
874  nNewPatches++;
875  }
876  }
877 
878  if (wantedPatchID == -1)
879  {
880  // Newly created patch so is at end. Check if any faces in it.
881  if (boundaryPatchSizes[oldInternalPatchID] > 0)
882  {
883  newBoundary[nNewPatches] = new internalPolyPatch
884  (
885  "oldInternalFaces",
886  boundaryPatchSizes[oldInternalPatchID],
887  patchStart,
888  nNewPatches,
889  fvMeshSubsetPtr_().poly().boundary()
890  );
891 
892  // The index for the first patch is -1 as it originates from
893  // the internal faces
894  patchMap_[nNewPatches] = -1;
895  nNewPatches++;
896  }
897  }
898  // else
899  // {
900  // patchMap_[wantedPatchID] = -1;
901  // }
902 
903  // Reset the patch lists
904  newBoundary.setSize(nNewPatches);
905  patchMap_.setSize(nNewPatches);
906 
907  // Add the fvPatches
908  fvMeshSubsetPtr_().addFvPatches(newBoundary);
909 
910  // Subset and add any zones
911  subsetZones();
912 }
913 
914 
916 (
917  const labelList& region,
918  const label currentRegion,
919  const label patchID,
920  const bool syncPar
921 )
922 {
923  const cellList& oldCells = baseMesh().cells();
924  const faceList& oldFaces = baseMesh().faces();
925  const pointField& oldPoints = baseMesh().points();
926  const labelList& oldOwner = baseMesh().faceOwner();
927  const labelList& oldNeighbour = baseMesh().faceNeighbour();
928  const polyBoundaryMesh& oldPatches = baseMesh().poly().boundary();
929  const label oldNInternalFaces = baseMesh().nInternalFaces();
930 
931  // Initial checks
932 
933  if (region.size() != oldCells.size())
934  {
936  << "Size of region " << region.size()
937  << " is not equal to number of cells in mesh " << oldCells.size()
938  << abort(FatalError);
939  }
940 
941 
942  label wantedPatchID = patchID;
943 
944  if (wantedPatchID == -1)
945  {
946  // No explicit patch specified. Put in oldInternalFaces patch.
947  // Check if patch with this name already exists.
948  wantedPatchID = oldPatches.findIndex("oldInternalFaces");
949  }
950  else if (wantedPatchID < 0 || wantedPatchID >= oldPatches.size())
951  {
953  << "Non-existing patch index " << wantedPatchID << endl
954  << "Should be between 0 and " << oldPatches.size()-1
955  << abort(FatalError);
956  }
957 
958  // Clear demand driven data
959  faceFlipMapPtr_.clear();
960 
961  // Get the cells for the current region.
962  cellMap_.setSize(oldCells.size());
963  label nCellsInSet = 0;
964 
965  forAll(region, oldCelli)
966  {
967  if (region[oldCelli] == currentRegion)
968  {
969  cellMap_[nCellsInSet++] = oldCelli;
970  }
971  }
972  cellMap_.setSize(nCellsInSet);
973 
974 
975  // Mark all used faces. Count number of cells using them
976  // 0: face not used anymore
977  // 1: face used by one cell, face becomes/stays boundary face
978  // 2: face still used and remains internal face
979  // 3: face coupled and used by one cell only (so should become normal,
980  // non-coupled patch face)
981  //
982  // Note that this is not really necessary - but means we can size things
983  // correctly. Also makes handling coupled faces much easier.
984 
985  labelList nCellsUsingFace(oldFaces.size(), 0);
986 
987  label nFacesInSet = 0;
988  forAll(oldFaces, oldFacei)
989  {
990  bool faceUsed = false;
991 
992  if (region[oldOwner[oldFacei]] == currentRegion)
993  {
994  nCellsUsingFace[oldFacei]++;
995  faceUsed = true;
996  }
997 
998  if
999  (
1000  baseMesh().isInternalFace(oldFacei)
1001  && (region[oldNeighbour[oldFacei]] == currentRegion)
1002  )
1003  {
1004  nCellsUsingFace[oldFacei]++;
1005  faceUsed = true;
1006  }
1007 
1008  if (faceUsed)
1009  {
1010  nFacesInSet++;
1011  }
1012  }
1013  faceMap_.setSize(nFacesInSet);
1014 
1015  // Handle coupled faces. Modifies patch faces to be uncoupled to 3.
1016  Map<label> empty;
1017  doCoupledPatches(syncPar, empty, nCellsUsingFace);
1018 
1019 
1020  // See which patch to use for exposed internal faces.
1021  label oldInternalPatchID = 0;
1022 
1023  // Insert faces before which patch
1024  label nextPatchID = oldPatches.size();
1025 
1026  // old to new patches
1027  labelList globalPatchMap(oldPatches.size());
1028 
1029  // New patch size
1030  label nbSize = oldPatches.size();
1031 
1032  if (wantedPatchID == -1)
1033  {
1034  // Create 'oldInternalFaces' patch at the end (or before
1035  // processorPatches)
1036  // and put all exposed internal faces in there.
1037 
1038  forAll(oldPatches, patchi)
1039  {
1040  if (isA<processorPolyPatch>(oldPatches[patchi]))
1041  {
1042  nextPatchID = patchi;
1043  break;
1044  }
1045  oldInternalPatchID++;
1046  }
1047 
1048  nbSize++;
1049 
1050  // adapt old to new patches for inserted patch
1051  for (label oldPatchi = 0; oldPatchi < nextPatchID; oldPatchi++)
1052  {
1053  globalPatchMap[oldPatchi] = oldPatchi;
1054  }
1055  for
1056  (
1057  label oldPatchi = nextPatchID;
1058  oldPatchi < oldPatches.size();
1059  oldPatchi++
1060  )
1061  {
1062  globalPatchMap[oldPatchi] = oldPatchi + 1;
1063  }
1064  }
1065  else
1066  {
1067  oldInternalPatchID = wantedPatchID;
1068  nextPatchID = wantedPatchID + 1;
1069 
1070  // old to new patches
1071  globalPatchMap = identityMap(oldPatches.size());
1072  }
1073 
1074  labelList boundaryPatchSizes(nbSize, 0);
1075 
1076 
1077  // Make a global-to-local point map
1078  labelList globalPointMap(oldPoints.size(), -1);
1079 
1080  labelList globalFaceMap(oldFaces.size(), -1);
1081  label facei = 0;
1082 
1083  // 1. Pick up all preserved internal faces.
1084  for (label oldFacei = 0; oldFacei < oldNInternalFaces; oldFacei++)
1085  {
1086  if (nCellsUsingFace[oldFacei] == 2)
1087  {
1088  globalFaceMap[oldFacei] = facei;
1089  faceMap_[facei++] = oldFacei;
1090 
1091  // Mark all points from the face
1092  markPoints(oldFaces[oldFacei], globalPointMap);
1093  }
1094  }
1095 
1096  // These are all the internal faces in the mesh.
1097  label nInternalFaces = facei;
1098 
1099  // 2. Boundary faces up to where we want to insert old internal faces
1100  for
1101  (
1102  label oldPatchi = 0;
1103  oldPatchi < oldPatches.size()
1104  && oldPatchi < nextPatchID;
1105  oldPatchi++
1106  )
1107  {
1108  const polyPatch& oldPatch = oldPatches[oldPatchi];
1109 
1110  label oldFacei = oldPatch.start();
1111 
1112  forAll(oldPatch, i)
1113  {
1114  if (nCellsUsingFace[oldFacei] == 1)
1115  {
1116  // Boundary face is kept.
1117 
1118  // Mark face and increment number of points in set
1119  globalFaceMap[oldFacei] = facei;
1120  faceMap_[facei++] = oldFacei;
1121 
1122  // Mark all points from the face
1123  markPoints(oldFaces[oldFacei], globalPointMap);
1124 
1125  // Increment number of patch faces
1126  boundaryPatchSizes[globalPatchMap[oldPatchi]]++;
1127  }
1128  oldFacei++;
1129  }
1130  }
1131 
1132  // 3a. old internal faces that have become exposed.
1133  for (label oldFacei = 0; oldFacei < oldNInternalFaces; oldFacei++)
1134  {
1135  if (nCellsUsingFace[oldFacei] == 1)
1136  {
1137  globalFaceMap[oldFacei] = facei;
1138  faceMap_[facei++] = oldFacei;
1139 
1140  // Mark all points from the face
1141  markPoints(oldFaces[oldFacei], globalPointMap);
1142 
1143  // Increment number of patch faces
1144  boundaryPatchSizes[oldInternalPatchID]++;
1145  }
1146  }
1147 
1148  // 3b. coupled patch faces that have become uncoupled.
1149  for
1150  (
1151  label oldFacei = oldNInternalFaces;
1152  oldFacei < oldFaces.size();
1153  oldFacei++
1154  )
1155  {
1156  if (nCellsUsingFace[oldFacei] == 3)
1157  {
1158  globalFaceMap[oldFacei] = facei;
1159  faceMap_[facei++] = oldFacei;
1160 
1161  // Mark all points from the face
1162  markPoints(oldFaces[oldFacei], globalPointMap);
1163 
1164  // Increment number of patch faces
1165  boundaryPatchSizes[oldInternalPatchID]++;
1166  }
1167  }
1168 
1169  // 4. Remaining boundary faces
1170  for
1171  (
1172  label oldPatchi = nextPatchID;
1173  oldPatchi < oldPatches.size();
1174  oldPatchi++
1175  )
1176  {
1177  const polyPatch& oldPatch = oldPatches[oldPatchi];
1178 
1179  label oldFacei = oldPatch.start();
1180 
1181  forAll(oldPatch, i)
1182  {
1183  if (nCellsUsingFace[oldFacei] == 1)
1184  {
1185  // Boundary face is kept.
1186 
1187  // Mark face and increment number of points in set
1188  globalFaceMap[oldFacei] = facei;
1189  faceMap_[facei++] = oldFacei;
1190 
1191  // Mark all points from the face
1192  markPoints(oldFaces[oldFacei], globalPointMap);
1193 
1194  // Increment number of patch faces
1195  boundaryPatchSizes[globalPatchMap[oldPatchi]]++;
1196  }
1197  oldFacei++;
1198  }
1199  }
1200 
1201  if (facei != nFacesInSet)
1202  {
1204  << "Problem" << abort(FatalError);
1205  }
1206 
1207 
1208  // Grab the points map
1209  label nPointsInSet = 0;
1210 
1211  forAll(globalPointMap, pointi)
1212  {
1213  if (globalPointMap[pointi] != -1)
1214  {
1215  nPointsInSet++;
1216  }
1217  }
1218  pointMap_.setSize(nPointsInSet);
1219 
1220  nPointsInSet = 0;
1221 
1222  forAll(globalPointMap, pointi)
1223  {
1224  if (globalPointMap[pointi] != -1)
1225  {
1226  pointMap_[nPointsInSet] = pointi;
1227  globalPointMap[pointi] = nPointsInSet;
1228  nPointsInSet++;
1229  }
1230  }
1231 
1232 
1233  // Make a new mesh
1234  pointField newPoints(pointMap_.size());
1235 
1236  label nNewPoints = 0;
1237 
1238  forAll(pointMap_, pointi)
1239  {
1240  newPoints[nNewPoints] = oldPoints[pointMap_[pointi]];
1241  nNewPoints++;
1242  }
1243 
1244  faceList newFaces(faceMap_.size());
1245 
1246  label nNewFaces = 0;
1247 
1248  // Make internal faces
1249  for (label facei = 0; facei < nInternalFaces; facei++)
1250  {
1251  const face& oldF = oldFaces[faceMap_[facei]];
1252 
1253  face newF(oldF.size());
1254 
1255  forAll(newF, i)
1256  {
1257  newF[i] = globalPointMap[oldF[i]];
1258  }
1259 
1260  newFaces[nNewFaces] = newF;
1261  nNewFaces++;
1262  }
1263 
1264 
1265  // Make boundary faces. (different from internal since might need to be
1266  // flipped)
1267  for (label facei = nInternalFaces; facei < faceMap_.size(); facei++)
1268  {
1269  const label oldFacei = faceMap_[facei];
1270 
1271  face oldF = oldFaces[oldFacei];
1272 
1273  // Turn the faces as necessary to point outwards
1274  if (baseMesh().isInternalFace(oldFacei))
1275  {
1276  // Was internal face. Possibly turned the wrong way round
1277  if
1278  (
1279  region[oldOwner[oldFacei]] != currentRegion
1280  && region[oldNeighbour[oldFacei]] == currentRegion
1281  )
1282  {
1283  oldF = oldFaces[oldFacei].reverseFace();
1284  }
1285  }
1286 
1287  // Relabel vertices of the (possibly turned) face.
1288  face newF(oldF.size());
1289 
1290  forAll(newF, i)
1291  {
1292  newF[i] = globalPointMap[oldF[i]];
1293  }
1294 
1295  newFaces[nNewFaces] = newF;
1296  nNewFaces++;
1297  }
1298 
1299 
1300 
1301  // Create cells
1302  cellList newCells(nCellsInSet);
1303 
1304  label nNewCells = 0;
1305 
1306  forAll(cellMap_, celli)
1307  {
1308  const labelList& oldC = oldCells[cellMap_[celli]];
1309 
1310  labelList newC(oldC.size());
1311 
1312  forAll(newC, i)
1313  {
1314  newC[i] = globalFaceMap[oldC[i]];
1315  }
1316 
1317  newCells[nNewCells] = cell(newC);
1318  nNewCells++;
1319  }
1320 
1321 
1322  // Delete any old one
1323  fvMeshSubsetPtr_.clear();
1324 
1325  // Make a new mesh
1326  // Note that mesh gets registered with same name as original mesh. This is
1327  // not proper but cannot be avoided since otherwise surfaceInterpolation
1328  // cannot find its fvSchemes (it will try to read e.g.
1329  // system/region0SubSet/fvSchemes)
1330  // Make a new mesh
1331  fvMeshSubsetPtr_.reset
1332  (
1333  new fvMesh
1334  (
1335  IOobject
1336  (
1337  baseMesh().name(),
1338  baseMesh().time().name(),
1339  baseMesh().time(),
1342  ),
1343  move(newPoints),
1344  move(newFaces),
1345  move(newCells),
1346  syncPar // parallel synchronisation
1347  )
1348  );
1349 
1350  // Add old patches
1351  List<polyPatch*> newBoundary(nbSize);
1352  patchMap_.setSize(nbSize);
1353  label nNewPatches = 0;
1354  label patchStart = nInternalFaces;
1355 
1356 
1357  // For parallel: only remove patch if none of the processors has it.
1358  // This only gets done for patches before the one being inserted
1359  // (so patches < nextPatchID)
1360 
1361  // Get sum of patch sizes. Zero if patch can be deleted.
1362  labelList globalPatchSizes(boundaryPatchSizes);
1363  globalPatchSizes.setSize(nextPatchID);
1364 
1365  if (syncPar && Pstream::parRun())
1366  {
1367  // Get patch names (up to nextPatchID)
1369  patchNames[Pstream::myProcNo()] = oldPatches.names();
1370  patchNames[Pstream::myProcNo()].setSize(nextPatchID);
1373 
1374  // Get patch sizes (up to nextPatchID).
1375  // Note that up to nextPatchID the globalPatchMap is an identity so
1376  // no need to index through that.
1377  Pstream::listCombineGather(globalPatchSizes, plusEqOp<label>());
1378  Pstream::listCombineScatter(globalPatchSizes);
1379 
1380  // Now all processors have all the patchnames.
1381  // Decide: if all processors have the same patch names and size is zero
1382  // everywhere remove the patch.
1383  bool samePatches = true;
1384 
1385  for (label proci = 1; proci < patchNames.size(); proci++)
1386  {
1387  if (patchNames[proci] != patchNames[0])
1388  {
1389  samePatches = false;
1390  break;
1391  }
1392  }
1393 
1394  if (!samePatches)
1395  {
1396  // Patchnames not sync on all processors so disable removal of
1397  // zero sized patches.
1398  globalPatchSizes = labelMax;
1399  }
1400  }
1401 
1402 
1403  // Old patches
1404 
1405  for
1406  (
1407  label oldPatchi = 0;
1408  oldPatchi < oldPatches.size()
1409  && oldPatchi < nextPatchID;
1410  oldPatchi++
1411  )
1412  {
1413  const label newSize = boundaryPatchSizes[globalPatchMap[oldPatchi]];
1414 
1415  // Clone (even if 0 size)
1416  newBoundary[nNewPatches] = oldPatches[oldPatchi].clone
1417  (
1418  fvMeshSubsetPtr_().poly().boundary(),
1419  nNewPatches,
1420  newSize,
1421  patchStart
1422  ).ptr();
1423 
1424  patchStart += newSize;
1425  patchMap_[nNewPatches] = oldPatchi; // compact patchMap
1426  nNewPatches++;
1427  }
1428 
1429  // Inserted patch
1430 
1431  if (wantedPatchID == -1)
1432  {
1433  label oldInternalSize = boundaryPatchSizes[oldInternalPatchID];
1434 
1435  if (syncPar)
1436  {
1437  reduce(oldInternalSize, sumOp<label>());
1438  }
1439 
1440  // Newly created patch so is at end. Check if any faces in it.
1441  if (oldInternalSize > 0)
1442  {
1443  newBoundary[nNewPatches] = new internalPolyPatch
1444  (
1445  "oldInternalFaces",
1446  boundaryPatchSizes[oldInternalPatchID],
1447  patchStart,
1448  nNewPatches,
1449  fvMeshSubsetPtr_().poly().boundary()
1450  );
1451 
1452  // The index for the first patch is -1 as it originates from
1453  // the internal faces
1454  patchStart += boundaryPatchSizes[oldInternalPatchID];
1455  patchMap_[nNewPatches] = -1;
1456  nNewPatches++;
1457  }
1458  }
1459  // else
1460  // {
1461  // patchMap_[wantedPatchID] = -1;
1462  // }
1463 
1464  // Old patches
1465 
1466  for
1467  (
1468  label oldPatchi = nextPatchID;
1469  oldPatchi < oldPatches.size();
1470  oldPatchi++
1471  )
1472  {
1473  const label newSize = boundaryPatchSizes[globalPatchMap[oldPatchi]];
1474 
1475  // Patch still exists. Add it
1476  newBoundary[nNewPatches] = oldPatches[oldPatchi].clone
1477  (
1478  fvMeshSubsetPtr_().poly().boundary(),
1479  nNewPatches,
1480  newSize,
1481  patchStart
1482  ).ptr();
1483 
1484  patchStart += newSize;
1485  patchMap_[nNewPatches] = oldPatchi; // compact patchMap
1486  nNewPatches++;
1487  }
1488 
1489 
1490  // Reset the patch lists
1491  newBoundary.setSize(nNewPatches);
1492  patchMap_.setSize(nNewPatches);
1493 
1494 
1495  // Add the fvPatches
1496  fvMeshSubsetPtr_().addFvPatches(newBoundary, syncPar);
1497 
1498  // Subset and add any zones
1499  subsetZones();
1500 }
1501 
1502 
1504 (
1505  const labelHashSet& globalCellMap,
1506  const label patchID,
1507  const bool syncPar
1508 )
1509 {
1510  labelList region(baseMesh().nCells(), 0);
1511 
1512  forAllConstIter(labelHashSet, globalCellMap, iter)
1513  {
1514  region[iter.key()] = 1;
1515  }
1516  setLargeCellSubset(region, 1, patchID, syncPar);
1517 }
1518 
1519 
1521 (
1522  const labelList& region,
1523  const label currentRegion,
1524  const bool syncCouples
1525 ) const
1526 {
1527  // Collect cells to remove
1528  const labelList cellsToRemove(getCellsToRemove(region, currentRegion));
1529 
1530  return removeCells(baseMesh(), syncCouples).getExposedFaces(cellsToRemove);
1531 }
1532 
1533 
1535 (
1536  const labelList& region,
1537  const label currentRegion,
1538  const labelList& exposedFaces,
1539  const labelList& patchIDs,
1540  const bool syncCouples
1541 )
1542 {
1543  // Collect cells to remove
1544  labelList cellsToRemove(getCellsToRemove(region, currentRegion));
1545 
1546  // Mesh changing engine.
1547  polyTopoChange meshMod(baseMesh());
1548 
1549  removeCells cellRemover(baseMesh(), syncCouples);
1550 
1551  cellRemover.setRefinement
1552  (
1553  cellsToRemove,
1554  exposedFaces,
1555  patchIDs,
1556  meshMod
1557  );
1558 
1559  // Create mesh, return map from old to new mesh.
1560  autoPtr<polyTopoChangeMap> map = meshMod.makeMesh
1561  (
1562  fvMeshSubsetPtr_,
1563  IOobject
1564  (
1565  baseMesh().name(),
1566  baseMesh().time().name(),
1567  baseMesh().time(),
1570  ),
1571  baseMesh(),
1572  syncCouples
1573  );
1574 
1575  pointMap_ = map().pointMap();
1576  faceMap_ = map().faceMap();
1577  cellMap_ = map().cellMap();
1578  patchMap_ = identityMap(baseMesh().poly().boundary().size());
1579 }
1580 
1581 
1583 {
1584  return fvMeshSubsetPtr_.valid();
1585 }
1586 
1587 
1589 {
1590  checkCellSubset();
1591 
1592  return fvMeshSubsetPtr_();
1593 }
1594 
1595 
1597 {
1598  checkCellSubset();
1599 
1600  return fvMeshSubsetPtr_();
1601 }
1602 
1603 
1605 {
1606  checkCellSubset();
1607 
1608  return pointMap_;
1609 }
1610 
1611 
1613 {
1614  checkCellSubset();
1615 
1616  return faceMap_;
1617 }
1618 
1619 
1621 {
1622  if (!faceFlipMapPtr_.valid())
1623  {
1624  const labelList& subToBaseFace = faceMap();
1625  const labelList& subToBaseCell = cellMap();
1626 
1627  faceFlipMapPtr_.reset(new labelList(subToBaseFace.size()));
1628  labelList& faceFlipMap = faceFlipMapPtr_();
1629 
1630  // Only exposed internal faces might be flipped (since we don't do
1631  // any cell renumbering, just compacting)
1632  label subInt = subMesh().nInternalFaces();
1633  const labelList& subOwn = subMesh().faceOwner();
1634  const labelList& own = baseMesh_.faceOwner();
1635 
1636  for (label subFacei = 0; subFacei < subInt; subFacei++)
1637  {
1638  faceFlipMap[subFacei] = subToBaseFace[subFacei] + 1;
1639  }
1640  for (label subFacei = subInt; subFacei < subOwn.size(); subFacei++)
1641  {
1642  const label facei = subToBaseFace[subFacei];
1643  if (subToBaseCell[subOwn[subFacei]] == own[facei])
1644  {
1645  faceFlipMap[subFacei] = facei + 1;
1646  }
1647  else
1648  {
1649  faceFlipMap[subFacei] = -facei - 1;
1650  }
1651  }
1652  }
1653 
1654  return faceFlipMapPtr_();
1655 }
1656 
1657 
1659 {
1660  checkCellSubset();
1661 
1662  return cellMap_;
1663 }
1664 
1665 
1667 {
1668  checkCellSubset();
1669 
1670  return patchMap_;
1671 }
1672 
1673 
1674 // ************************************************************************* //
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:492
List< Key > toc() const
Return the table of contents.
Definition: HashTable.C:227
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:138
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
autoPtr< IOobject > clone() const
Clone.
Definition: IOobject.H:280
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:411
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:60
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:76
Post-processing mesh subset tool. Given the original mesh and the list of selected cells,...
Definition: fvMeshSubset.H:74
const labelList & faceMap() const
Return face map.
void setCellSubset(const labelHashSet &globalCellMap, const label patchID=-1, const bool syncPar=true)
Set the subset. Create "oldInternalFaces" patch for exposed.
Definition: fvMeshSubset.C:514
const labelList & cellMap() const
Return cell map.
fvMeshSubset(const fvMesh &)
Construct given a mesh to subset.
Definition: fvMeshSubset.C:493
bool hasSubMesh() const
Have subMesh?
const labelList & faceFlipMap() const
Return face map with sign to encode flipped faces.
virtual ~fvMeshSubset()
Destructor.
Definition: fvMeshSubset.C:507
void setLargeCellSubset(const labelList &region, const label currentRegion, const label patchID=-1, const bool syncCouples=true)
Set the subset from all cells with region == currentRegion.
Definition: fvMeshSubset.C:916
const fvMesh & subMesh() const
Return reference to subset mesh.
const labelList & patchMap() const
Return patch map.
const labelList & pointMap() const
Return point map.
labelList getExposedFaces(const labelList &region, const label currentRegion, const bool syncCouples=true) const
Get labels of exposed faces.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:98
label size() const
Return fvMesh size.
Definition: fvMesh.H:468
Constraint patch to hold internal faces exposed by sub-setting.
Motion of the mesh specified as a list of pointMeshMovers.
Foam::polyBoundaryMesh.
label findIndex(const word &patchName) const
Find patch index given a name.
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
wordList names() const
Return the list of patch names.
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:71
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:277
Direct mesh changes based on v1.3 polyTopoChange syntax.
autoPtr< polyTopoChangeMap > makeMesh(autoPtr< fvMesh > &newMesh, const IOobject &io, const polyMesh &mesh, const bool syncParallel=true, const bool orderCells=false, const bool orderPoints=false)
Create new mesh with old mesh patches.
Given list of cells to remove insert all the topology changes.
Definition: removeCells.H:60
void setRefinement(const labelList &cellsToRemove, const labelList &facesToExpose, const labelList &patchIDs, polyTopoChange &) const
Play commands into polyTopoChange to remove cells.
Definition: removeCells.C:175
labelList getExposedFaces(const labelList &cellsToRemove) const
Get labels of exposed faces.
Definition: removeCells.C:69
Template functions to aid in the implementation of demand driven data.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
label patchi
label nPoints
const dimensionSet time
Namespace for OpenFOAM.
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
errorManip< error > abort(error &err)
Definition: errorManip.H:131
messageStream Info
const fvMesh & region(const dictionary &dict)
Cast the give dictionary to the corresponding region fvMesh.
Definition: fvMesh.C:1831
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
void sort(UList< T > &)
Definition: UList.C:115
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys.
Definition: HashSet.H:213
error FatalError
static const label labelMax
Definition: label.H:62
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
defineTypeNameAndDebug(atmosphericBoundaryLayer, 0)
ListType subset(const UList< T > &select, const T &value, const ListType &)
Extract elements of List when select is a certain value.
wordList patchNames(nPatches)
faceListList boundary(nPatches)