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-2025 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().boundaryMesh();
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().boundaryMesh();
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_().boundaryMesh(),
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_().boundaryMesh(),
890  internalPolyPatch::typeName
891  );
892 
893  // The index for the first patch is -1 as it originates from
894  // the internal faces
895  patchMap_[nNewPatches] = -1;
896  nNewPatches++;
897  }
898  }
899  // else
900  // {
901  // patchMap_[wantedPatchID] = -1;
902  // }
903 
904  // Reset the patch lists
905  newBoundary.setSize(nNewPatches);
906  patchMap_.setSize(nNewPatches);
907 
908  // Add the fvPatches
909  fvMeshSubsetPtr_().addFvPatches(newBoundary);
910 
911  // Subset and add any zones
912  subsetZones();
913 }
914 
915 
917 (
918  const labelList& region,
919  const label currentRegion,
920  const label patchID,
921  const bool syncPar
922 )
923 {
924  const cellList& oldCells = baseMesh().cells();
925  const faceList& oldFaces = baseMesh().faces();
926  const pointField& oldPoints = baseMesh().points();
927  const labelList& oldOwner = baseMesh().faceOwner();
928  const labelList& oldNeighbour = baseMesh().faceNeighbour();
929  const polyBoundaryMesh& oldPatches = baseMesh().boundaryMesh();
930  const label oldNInternalFaces = baseMesh().nInternalFaces();
931 
932  // Initial checks
933 
934  if (region.size() != oldCells.size())
935  {
937  << "Size of region " << region.size()
938  << " is not equal to number of cells in mesh " << oldCells.size()
939  << abort(FatalError);
940  }
941 
942 
943  label wantedPatchID = patchID;
944 
945  if (wantedPatchID == -1)
946  {
947  // No explicit patch specified. Put in oldInternalFaces patch.
948  // Check if patch with this name already exists.
949  wantedPatchID = oldPatches.findIndex("oldInternalFaces");
950  }
951  else if (wantedPatchID < 0 || wantedPatchID >= oldPatches.size())
952  {
954  << "Non-existing patch index " << wantedPatchID << endl
955  << "Should be between 0 and " << oldPatches.size()-1
956  << abort(FatalError);
957  }
958 
959  // Clear demand driven data
960  faceFlipMapPtr_.clear();
961 
962  // Get the cells for the current region.
963  cellMap_.setSize(oldCells.size());
964  label nCellsInSet = 0;
965 
966  forAll(region, oldCelli)
967  {
968  if (region[oldCelli] == currentRegion)
969  {
970  cellMap_[nCellsInSet++] = oldCelli;
971  }
972  }
973  cellMap_.setSize(nCellsInSet);
974 
975 
976  // Mark all used faces. Count number of cells using them
977  // 0: face not used anymore
978  // 1: face used by one cell, face becomes/stays boundary face
979  // 2: face still used and remains internal face
980  // 3: face coupled and used by one cell only (so should become normal,
981  // non-coupled patch face)
982  //
983  // Note that this is not really necessary - but means we can size things
984  // correctly. Also makes handling coupled faces much easier.
985 
986  labelList nCellsUsingFace(oldFaces.size(), 0);
987 
988  label nFacesInSet = 0;
989  forAll(oldFaces, oldFacei)
990  {
991  bool faceUsed = false;
992 
993  if (region[oldOwner[oldFacei]] == currentRegion)
994  {
995  nCellsUsingFace[oldFacei]++;
996  faceUsed = true;
997  }
998 
999  if
1000  (
1001  baseMesh().isInternalFace(oldFacei)
1002  && (region[oldNeighbour[oldFacei]] == currentRegion)
1003  )
1004  {
1005  nCellsUsingFace[oldFacei]++;
1006  faceUsed = true;
1007  }
1008 
1009  if (faceUsed)
1010  {
1011  nFacesInSet++;
1012  }
1013  }
1014  faceMap_.setSize(nFacesInSet);
1015 
1016  // Handle coupled faces. Modifies patch faces to be uncoupled to 3.
1017  Map<label> empty;
1018  doCoupledPatches(syncPar, empty, nCellsUsingFace);
1019 
1020 
1021  // See which patch to use for exposed internal faces.
1022  label oldInternalPatchID = 0;
1023 
1024  // Insert faces before which patch
1025  label nextPatchID = oldPatches.size();
1026 
1027  // old to new patches
1028  labelList globalPatchMap(oldPatches.size());
1029 
1030  // New patch size
1031  label nbSize = oldPatches.size();
1032 
1033  if (wantedPatchID == -1)
1034  {
1035  // Create 'oldInternalFaces' patch at the end (or before
1036  // processorPatches)
1037  // and put all exposed internal faces in there.
1038 
1039  forAll(oldPatches, patchi)
1040  {
1041  if (isA<processorPolyPatch>(oldPatches[patchi]))
1042  {
1043  nextPatchID = patchi;
1044  break;
1045  }
1046  oldInternalPatchID++;
1047  }
1048 
1049  nbSize++;
1050 
1051  // adapt old to new patches for inserted patch
1052  for (label oldPatchi = 0; oldPatchi < nextPatchID; oldPatchi++)
1053  {
1054  globalPatchMap[oldPatchi] = oldPatchi;
1055  }
1056  for
1057  (
1058  label oldPatchi = nextPatchID;
1059  oldPatchi < oldPatches.size();
1060  oldPatchi++
1061  )
1062  {
1063  globalPatchMap[oldPatchi] = oldPatchi + 1;
1064  }
1065  }
1066  else
1067  {
1068  oldInternalPatchID = wantedPatchID;
1069  nextPatchID = wantedPatchID + 1;
1070 
1071  // old to new patches
1072  globalPatchMap = identityMap(oldPatches.size());
1073  }
1074 
1075  labelList boundaryPatchSizes(nbSize, 0);
1076 
1077 
1078  // Make a global-to-local point map
1079  labelList globalPointMap(oldPoints.size(), -1);
1080 
1081  labelList globalFaceMap(oldFaces.size(), -1);
1082  label facei = 0;
1083 
1084  // 1. Pick up all preserved internal faces.
1085  for (label oldFacei = 0; oldFacei < oldNInternalFaces; oldFacei++)
1086  {
1087  if (nCellsUsingFace[oldFacei] == 2)
1088  {
1089  globalFaceMap[oldFacei] = facei;
1090  faceMap_[facei++] = oldFacei;
1091 
1092  // Mark all points from the face
1093  markPoints(oldFaces[oldFacei], globalPointMap);
1094  }
1095  }
1096 
1097  // These are all the internal faces in the mesh.
1098  label nInternalFaces = facei;
1099 
1100  // 2. Boundary faces up to where we want to insert old internal faces
1101  for
1102  (
1103  label oldPatchi = 0;
1104  oldPatchi < oldPatches.size()
1105  && oldPatchi < nextPatchID;
1106  oldPatchi++
1107  )
1108  {
1109  const polyPatch& oldPatch = oldPatches[oldPatchi];
1110 
1111  label oldFacei = oldPatch.start();
1112 
1113  forAll(oldPatch, i)
1114  {
1115  if (nCellsUsingFace[oldFacei] == 1)
1116  {
1117  // Boundary face is kept.
1118 
1119  // Mark face and increment number of points in set
1120  globalFaceMap[oldFacei] = facei;
1121  faceMap_[facei++] = oldFacei;
1122 
1123  // Mark all points from the face
1124  markPoints(oldFaces[oldFacei], globalPointMap);
1125 
1126  // Increment number of patch faces
1127  boundaryPatchSizes[globalPatchMap[oldPatchi]]++;
1128  }
1129  oldFacei++;
1130  }
1131  }
1132 
1133  // 3a. old internal faces that have become exposed.
1134  for (label oldFacei = 0; oldFacei < oldNInternalFaces; oldFacei++)
1135  {
1136  if (nCellsUsingFace[oldFacei] == 1)
1137  {
1138  globalFaceMap[oldFacei] = facei;
1139  faceMap_[facei++] = oldFacei;
1140 
1141  // Mark all points from the face
1142  markPoints(oldFaces[oldFacei], globalPointMap);
1143 
1144  // Increment number of patch faces
1145  boundaryPatchSizes[oldInternalPatchID]++;
1146  }
1147  }
1148 
1149  // 3b. coupled patch faces that have become uncoupled.
1150  for
1151  (
1152  label oldFacei = oldNInternalFaces;
1153  oldFacei < oldFaces.size();
1154  oldFacei++
1155  )
1156  {
1157  if (nCellsUsingFace[oldFacei] == 3)
1158  {
1159  globalFaceMap[oldFacei] = facei;
1160  faceMap_[facei++] = oldFacei;
1161 
1162  // Mark all points from the face
1163  markPoints(oldFaces[oldFacei], globalPointMap);
1164 
1165  // Increment number of patch faces
1166  boundaryPatchSizes[oldInternalPatchID]++;
1167  }
1168  }
1169 
1170  // 4. Remaining boundary faces
1171  for
1172  (
1173  label oldPatchi = nextPatchID;
1174  oldPatchi < oldPatches.size();
1175  oldPatchi++
1176  )
1177  {
1178  const polyPatch& oldPatch = oldPatches[oldPatchi];
1179 
1180  label oldFacei = oldPatch.start();
1181 
1182  forAll(oldPatch, i)
1183  {
1184  if (nCellsUsingFace[oldFacei] == 1)
1185  {
1186  // Boundary face is kept.
1187 
1188  // Mark face and increment number of points in set
1189  globalFaceMap[oldFacei] = facei;
1190  faceMap_[facei++] = oldFacei;
1191 
1192  // Mark all points from the face
1193  markPoints(oldFaces[oldFacei], globalPointMap);
1194 
1195  // Increment number of patch faces
1196  boundaryPatchSizes[globalPatchMap[oldPatchi]]++;
1197  }
1198  oldFacei++;
1199  }
1200  }
1201 
1202  if (facei != nFacesInSet)
1203  {
1205  << "Problem" << abort(FatalError);
1206  }
1207 
1208 
1209  // Grab the points map
1210  label nPointsInSet = 0;
1211 
1212  forAll(globalPointMap, pointi)
1213  {
1214  if (globalPointMap[pointi] != -1)
1215  {
1216  nPointsInSet++;
1217  }
1218  }
1219  pointMap_.setSize(nPointsInSet);
1220 
1221  nPointsInSet = 0;
1222 
1223  forAll(globalPointMap, pointi)
1224  {
1225  if (globalPointMap[pointi] != -1)
1226  {
1227  pointMap_[nPointsInSet] = pointi;
1228  globalPointMap[pointi] = nPointsInSet;
1229  nPointsInSet++;
1230  }
1231  }
1232 
1233 
1234  // Make a new mesh
1235  pointField newPoints(pointMap_.size());
1236 
1237  label nNewPoints = 0;
1238 
1239  forAll(pointMap_, pointi)
1240  {
1241  newPoints[nNewPoints] = oldPoints[pointMap_[pointi]];
1242  nNewPoints++;
1243  }
1244 
1245  faceList newFaces(faceMap_.size());
1246 
1247  label nNewFaces = 0;
1248 
1249  // Make internal faces
1250  for (label facei = 0; facei < nInternalFaces; facei++)
1251  {
1252  const face& oldF = oldFaces[faceMap_[facei]];
1253 
1254  face newF(oldF.size());
1255 
1256  forAll(newF, i)
1257  {
1258  newF[i] = globalPointMap[oldF[i]];
1259  }
1260 
1261  newFaces[nNewFaces] = newF;
1262  nNewFaces++;
1263  }
1264 
1265 
1266  // Make boundary faces. (different from internal since might need to be
1267  // flipped)
1268  for (label facei = nInternalFaces; facei < faceMap_.size(); facei++)
1269  {
1270  const label oldFacei = faceMap_[facei];
1271 
1272  face oldF = oldFaces[oldFacei];
1273 
1274  // Turn the faces as necessary to point outwards
1275  if (baseMesh().isInternalFace(oldFacei))
1276  {
1277  // Was internal face. Possibly turned the wrong way round
1278  if
1279  (
1280  region[oldOwner[oldFacei]] != currentRegion
1281  && region[oldNeighbour[oldFacei]] == currentRegion
1282  )
1283  {
1284  oldF = oldFaces[oldFacei].reverseFace();
1285  }
1286  }
1287 
1288  // Relabel vertices of the (possibly turned) face.
1289  face newF(oldF.size());
1290 
1291  forAll(newF, i)
1292  {
1293  newF[i] = globalPointMap[oldF[i]];
1294  }
1295 
1296  newFaces[nNewFaces] = newF;
1297  nNewFaces++;
1298  }
1299 
1300 
1301 
1302  // Create cells
1303  cellList newCells(nCellsInSet);
1304 
1305  label nNewCells = 0;
1306 
1307  forAll(cellMap_, celli)
1308  {
1309  const labelList& oldC = oldCells[cellMap_[celli]];
1310 
1311  labelList newC(oldC.size());
1312 
1313  forAll(newC, i)
1314  {
1315  newC[i] = globalFaceMap[oldC[i]];
1316  }
1317 
1318  newCells[nNewCells] = cell(newC);
1319  nNewCells++;
1320  }
1321 
1322 
1323  // Delete any old one
1324  fvMeshSubsetPtr_.clear();
1325 
1326  // Make a new mesh
1327  // Note that mesh gets registered with same name as original mesh. This is
1328  // not proper but cannot be avoided since otherwise surfaceInterpolation
1329  // cannot find its fvSchemes (it will try to read e.g.
1330  // system/region0SubSet/fvSchemes)
1331  // Make a new mesh
1332  fvMeshSubsetPtr_.reset
1333  (
1334  new fvMesh
1335  (
1336  IOobject
1337  (
1338  baseMesh().name(),
1339  baseMesh().time().name(),
1340  baseMesh().time(),
1343  ),
1344  move(newPoints),
1345  move(newFaces),
1346  move(newCells),
1347  syncPar // parallel synchronisation
1348  )
1349  );
1350 
1351  // Add old patches
1352  List<polyPatch*> newBoundary(nbSize);
1353  patchMap_.setSize(nbSize);
1354  label nNewPatches = 0;
1355  label patchStart = nInternalFaces;
1356 
1357 
1358  // For parallel: only remove patch if none of the processors has it.
1359  // This only gets done for patches before the one being inserted
1360  // (so patches < nextPatchID)
1361 
1362  // Get sum of patch sizes. Zero if patch can be deleted.
1363  labelList globalPatchSizes(boundaryPatchSizes);
1364  globalPatchSizes.setSize(nextPatchID);
1365 
1366  if (syncPar && Pstream::parRun())
1367  {
1368  // Get patch names (up to nextPatchID)
1370  patchNames[Pstream::myProcNo()] = oldPatches.names();
1371  patchNames[Pstream::myProcNo()].setSize(nextPatchID);
1374 
1375  // Get patch sizes (up to nextPatchID).
1376  // Note that up to nextPatchID the globalPatchMap is an identity so
1377  // no need to index through that.
1378  Pstream::listCombineGather(globalPatchSizes, plusEqOp<label>());
1379  Pstream::listCombineScatter(globalPatchSizes);
1380 
1381  // Now all processors have all the patchnames.
1382  // Decide: if all processors have the same patch names and size is zero
1383  // everywhere remove the patch.
1384  bool samePatches = true;
1385 
1386  for (label proci = 1; proci < patchNames.size(); proci++)
1387  {
1388  if (patchNames[proci] != patchNames[0])
1389  {
1390  samePatches = false;
1391  break;
1392  }
1393  }
1394 
1395  if (!samePatches)
1396  {
1397  // Patchnames not sync on all processors so disable removal of
1398  // zero sized patches.
1399  globalPatchSizes = labelMax;
1400  }
1401  }
1402 
1403 
1404  // Old patches
1405 
1406  for
1407  (
1408  label oldPatchi = 0;
1409  oldPatchi < oldPatches.size()
1410  && oldPatchi < nextPatchID;
1411  oldPatchi++
1412  )
1413  {
1414  const label newSize = boundaryPatchSizes[globalPatchMap[oldPatchi]];
1415 
1416  // Clone (even if 0 size)
1417  newBoundary[nNewPatches] = oldPatches[oldPatchi].clone
1418  (
1419  fvMeshSubsetPtr_().boundaryMesh(),
1420  nNewPatches,
1421  newSize,
1422  patchStart
1423  ).ptr();
1424 
1425  patchStart += newSize;
1426  patchMap_[nNewPatches] = oldPatchi; // compact patchMap
1427  nNewPatches++;
1428  }
1429 
1430  // Inserted patch
1431 
1432  if (wantedPatchID == -1)
1433  {
1434  label oldInternalSize = boundaryPatchSizes[oldInternalPatchID];
1435 
1436  if (syncPar)
1437  {
1438  reduce(oldInternalSize, sumOp<label>());
1439  }
1440 
1441  // Newly created patch so is at end. Check if any faces in it.
1442  if (oldInternalSize > 0)
1443  {
1444  newBoundary[nNewPatches] = new internalPolyPatch
1445  (
1446  "oldInternalFaces",
1447  boundaryPatchSizes[oldInternalPatchID],
1448  patchStart,
1449  nNewPatches,
1450  fvMeshSubsetPtr_().boundaryMesh(),
1451  internalPolyPatch::typeName
1452  );
1453 
1454  // The index for the first patch is -1 as it originates from
1455  // the internal faces
1456  patchStart += boundaryPatchSizes[oldInternalPatchID];
1457  patchMap_[nNewPatches] = -1;
1458  nNewPatches++;
1459  }
1460  }
1461  // else
1462  // {
1463  // patchMap_[wantedPatchID] = -1;
1464  // }
1465 
1466  // Old patches
1467 
1468  for
1469  (
1470  label oldPatchi = nextPatchID;
1471  oldPatchi < oldPatches.size();
1472  oldPatchi++
1473  )
1474  {
1475  const label newSize = boundaryPatchSizes[globalPatchMap[oldPatchi]];
1476 
1477  // Patch still exists. Add it
1478  newBoundary[nNewPatches] = oldPatches[oldPatchi].clone
1479  (
1480  fvMeshSubsetPtr_().boundaryMesh(),
1481  nNewPatches,
1482  newSize,
1483  patchStart
1484  ).ptr();
1485 
1486  patchStart += newSize;
1487  patchMap_[nNewPatches] = oldPatchi; // compact patchMap
1488  nNewPatches++;
1489  }
1490 
1491 
1492  // Reset the patch lists
1493  newBoundary.setSize(nNewPatches);
1494  patchMap_.setSize(nNewPatches);
1495 
1496 
1497  // Add the fvPatches
1498  fvMeshSubsetPtr_().addFvPatches(newBoundary, syncPar);
1499 
1500  // Subset and add any zones
1501  subsetZones();
1502 }
1503 
1504 
1506 (
1507  const labelHashSet& globalCellMap,
1508  const label patchID,
1509  const bool syncPar
1510 )
1511 {
1512  labelList region(baseMesh().nCells(), 0);
1513 
1514  forAllConstIter(labelHashSet, globalCellMap, iter)
1515  {
1516  region[iter.key()] = 1;
1517  }
1518  setLargeCellSubset(region, 1, patchID, syncPar);
1519 }
1520 
1521 
1523 (
1524  const labelList& region,
1525  const label currentRegion,
1526  const bool syncCouples
1527 ) const
1528 {
1529  // Collect cells to remove
1530  const labelList cellsToRemove(getCellsToRemove(region, currentRegion));
1531 
1532  return removeCells(baseMesh(), syncCouples).getExposedFaces(cellsToRemove);
1533 }
1534 
1535 
1537 (
1538  const labelList& region,
1539  const label currentRegion,
1540  const labelList& exposedFaces,
1541  const labelList& patchIDs,
1542  const bool syncCouples
1543 )
1544 {
1545  // Collect cells to remove
1546  labelList cellsToRemove(getCellsToRemove(region, currentRegion));
1547 
1548  // Mesh changing engine.
1549  polyTopoChange meshMod(baseMesh());
1550 
1551  removeCells cellRemover(baseMesh(), syncCouples);
1552 
1553  cellRemover.setRefinement
1554  (
1555  cellsToRemove,
1556  exposedFaces,
1557  patchIDs,
1558  meshMod
1559  );
1560 
1561  // Create mesh, return map from old to new mesh.
1562  autoPtr<polyTopoChangeMap> map = meshMod.makeMesh
1563  (
1564  fvMeshSubsetPtr_,
1565  IOobject
1566  (
1567  baseMesh().name(),
1568  baseMesh().time().name(),
1569  baseMesh().time(),
1572  ),
1573  baseMesh(),
1574  syncCouples
1575  );
1576 
1577  pointMap_ = map().pointMap();
1578  faceMap_ = map().faceMap();
1579  cellMap_ = map().cellMap();
1580  patchMap_ = identityMap(baseMesh().boundaryMesh().size());
1581 }
1582 
1583 
1585 {
1586  return fvMeshSubsetPtr_.valid();
1587 }
1588 
1589 
1591 {
1592  checkCellSubset();
1593 
1594  return fvMeshSubsetPtr_();
1595 }
1596 
1597 
1599 {
1600  checkCellSubset();
1601 
1602  return fvMeshSubsetPtr_();
1603 }
1604 
1605 
1607 {
1608  checkCellSubset();
1609 
1610  return pointMap_;
1611 }
1612 
1613 
1615 {
1616  checkCellSubset();
1617 
1618  return faceMap_;
1619 }
1620 
1621 
1623 {
1624  if (!faceFlipMapPtr_.valid())
1625  {
1626  const labelList& subToBaseFace = faceMap();
1627  const labelList& subToBaseCell = cellMap();
1628 
1629  faceFlipMapPtr_.reset(new labelList(subToBaseFace.size()));
1630  labelList& faceFlipMap = faceFlipMapPtr_();
1631 
1632  // Only exposed internal faces might be flipped (since we don't do
1633  // any cell renumbering, just compacting)
1634  label subInt = subMesh().nInternalFaces();
1635  const labelList& subOwn = subMesh().faceOwner();
1636  const labelList& own = baseMesh_.faceOwner();
1637 
1638  for (label subFacei = 0; subFacei < subInt; subFacei++)
1639  {
1640  faceFlipMap[subFacei] = subToBaseFace[subFacei] + 1;
1641  }
1642  for (label subFacei = subInt; subFacei < subOwn.size(); subFacei++)
1643  {
1644  const label facei = subToBaseFace[subFacei];
1645  if (subToBaseCell[subOwn[subFacei]] == own[facei])
1646  {
1647  faceFlipMap[subFacei] = facei + 1;
1648  }
1649  else
1650  {
1651  faceFlipMap[subFacei] = -facei - 1;
1652  }
1653  }
1654  }
1655 
1656  return faceFlipMapPtr_();
1657 }
1658 
1659 
1661 {
1662  checkCellSubset();
1663 
1664  return cellMap_;
1665 }
1666 
1667 
1669 {
1670  checkCellSubset();
1671 
1672  return patchMap_;
1673 }
1674 
1675 
1676 // ************************************************************************* //
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:476
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:917
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:96
Constraint patch to hold internal faces exposed by sub-setting.
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:70
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:280
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
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:258
errorManip< error > abort(error &err)
Definition: errorManip.H:131
messageStream Info
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
defineTypeNameAndDebug(combustionModel, 0)
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
ListType subset(const UList< T > &select, const T &value, const ListType &)
Extract elements of List when select is a certain value.
wordList patchNames(nPatches)