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