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-2022 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 {
46  defineTypeNameAndDebug(fvMeshSubset, 0);
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 meshPointZones& 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  i,
341  fvMeshSubsetPtr_().pointZones()
342  );
343  }
344 
345 
346  // FaceZones
347  const meshFaceZones& faceZones = baseMesh().faceZones();
348 
349  // Do we need to remove zones where the side we're interested in
350  // no longer exists? Guess not.
351  List<faceZone*> fZonePtrs(faceZones.size());
352 
353  forAll(faceZones, i)
354  {
355  const faceZone& fz = faceZones[i];
356 
357  // Expand faceZone to full mesh
358  // +1 : part of faceZone, flipped
359  // -1 : ,, , unflipped
360  // 0 : not part of faceZone
361  labelList zone(baseMesh().nFaces(), 0);
362  forAll(fz, j)
363  {
364  if (fz.flipMap()[j])
365  {
366  zone[fz[j]] = 1;
367  }
368  else
369  {
370  zone[fz[j]] = -1;
371  }
372  }
373 
374  // Select faces
375  label nSub = 0;
376  forAll(faceMap(), j)
377  {
378  if (zone[faceMap()[j]] != 0)
379  {
380  nSub++;
381  }
382  }
383  labelList subAddressing(nSub);
384  boolList subFlipStatus(nSub);
385  nSub = 0;
386  forAll(faceMap(), subFacei)
387  {
388  const label meshFacei = faceMap()[subFacei];
389  if (zone[meshFacei] != 0)
390  {
391  subAddressing[nSub] = subFacei;
392  const label subOwner = subMesh().faceOwner()[subFacei];
393  const label baseOwner = baseMesh().faceOwner()[meshFacei];
394  // If subowner is the same cell as the base keep the flip status
395  const bool sameOwner = (cellMap()[subOwner] == baseOwner);
396  const bool flip = (zone[meshFacei] == 1);
397  subFlipStatus[nSub] = (sameOwner == flip);
398 
399  nSub++;
400  }
401  }
402 
403  fZonePtrs[i] = new faceZone
404  (
405  fz.name(),
406  subAddressing,
407  subFlipStatus,
408  i,
409  fvMeshSubsetPtr_().faceZones()
410  );
411  }
412 
413  // CellZones
414  const meshCellZones& cellZones = baseMesh().cellZones();
415 
416  List<cellZone*> cZonePtrs(cellZones.size());
417 
418  forAll(cellZones, i)
419  {
420  const cellZone& cz = cellZones[i];
421 
422  cZonePtrs[i] = new cellZone
423  (
424  cz.name(),
425  subset(baseMesh().nCells(), cz, cellMap()),
426  i,
427  fvMeshSubsetPtr_().cellZones()
428  );
429  }
430 
431 
432  // Add the zones
433  fvMeshSubsetPtr_().addZones(pZonePtrs, fZonePtrs, cZonePtrs);
434 }
435 
436 
437 Foam::labelList Foam::fvMeshSubset::getCellsToRemove
438 (
439  const labelList& region,
440  const label currentRegion
441 ) const
442 {
443  // Count
444  label nKeep = 0;
445  forAll(region, cellI)
446  {
447  if (region[cellI] == currentRegion)
448  {
449  nKeep++;
450  }
451  }
452 
453  // Collect cells to remove
454  label nRemove = baseMesh().nCells() - nKeep;
455  labelList cellsToRemove(nRemove);
456 
457  nRemove = 0;
458  forAll(region, cellI)
459  {
460  if (region[cellI] != currentRegion)
461  {
462  cellsToRemove[nRemove++] = cellI;
463  }
464  }
465 
466  return cellsToRemove;
467 }
468 
469 
470 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
471 
473 :
474  baseMesh_(baseMesh),
475  fvMeshSubsetPtr_(nullptr),
476  pointMap_(0),
477  faceMap_(0),
478  cellMap_(0),
479  patchMap_(0),
480  faceFlipMapPtr_()
481 {}
482 
483 
484 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
485 
487 {}
488 
489 
490 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
491 
493 (
494  const labelHashSet& globalCellMap,
495  const label patchID,
496  const bool syncPar
497 )
498 {
499  // Initial check on patches before doing anything time consuming.
500  const polyBoundaryMesh& oldPatches = baseMesh().boundaryMesh();
501  const cellList& oldCells = baseMesh().cells();
502  const faceList& oldFaces = baseMesh().faces();
503  const pointField& oldPoints = baseMesh().points();
504  const labelList& oldOwner = baseMesh().faceOwner();
505  const labelList& oldNeighbour = baseMesh().faceNeighbour();
506 
507  label wantedPatchID = patchID;
508 
509  if (wantedPatchID == -1)
510  {
511  // No explicit patch specified. Put in oldInternalFaces patch.
512  // Check if patch with this name already exists.
513  wantedPatchID = oldPatches.findPatchID("oldInternalFaces");
514  }
515  else if (wantedPatchID < 0 || wantedPatchID >= oldPatches.size())
516  {
518  << "Non-existing patch index " << wantedPatchID << endl
519  << "Should be between 0 and " << oldPatches.size()-1
520  << abort(FatalError);
521  }
522 
523 
524  // Clear demand driven data
525  faceFlipMapPtr_.clear();
526 
527 
528  cellMap_ = globalCellMap.toc();
529 
530  // Sort the cell map in the ascending order
531  sort(cellMap_);
532 
533  // Approximate sizing parameters for face and point lists
534  const label avgNFacesPerCell = 6;
535  const label avgNPointsPerFace = 4;
536 
537 
538  const label nCellsInSet = cellMap_.size();
539 
540  // Mark all used faces
541 
542  Map<label> facesToSubset(avgNFacesPerCell*nCellsInSet);
543 
544  forAll(cellMap_, celli)
545  {
546  // Mark all faces from the cell
547  const labelList& curFaces = oldCells[cellMap_[celli]];
548 
549  forAll(curFaces, facei)
550  {
551  if (!facesToSubset.found(curFaces[facei]))
552  {
553  facesToSubset.insert(curFaces[facei], 1);
554  }
555  else
556  {
557  facesToSubset[curFaces[facei]]++;
558  }
559  }
560  }
561 
562  // Handle coupled faces. Modifies patch faces to be uncoupled to 3.
563  labelList empty;
564  doCoupledPatches(syncPar, facesToSubset, empty);
565 
566  // Mark all used points and make a global-to-local face map
567  Map<label> globalFaceMap(facesToSubset.size());
568 
569  // Make a global-to-local point map
570  Map<label> globalPointMap(avgNPointsPerFace*facesToSubset.size());
571 
572  // This is done in two goes, so that the boundary faces are last
573  // in the list. Because of this, I need to create the face map
574  // along the way rather than just grab the table of contents.
575  labelList facesToc = facesToSubset.toc();
576  sort(facesToc);
577  faceMap_.setSize(facesToc.size());
578 
579  // 1. Get all faces that will be internal to the submesh.
580  forAll(facesToc, facei)
581  {
582  if (facesToSubset[facesToc[facei]] == 2)
583  {
584  // Mark face and increment number of points in set
585  faceMap_[globalFaceMap.size()] = facesToc[facei];
586  globalFaceMap.insert(facesToc[facei], globalFaceMap.size());
587 
588  // Mark all points from the face
589  markPoints(oldFaces[facesToc[facei]], globalPointMap);
590  }
591  }
592 
593  // These are all the internal faces in the mesh.
594  const label nInternalFaces = globalFaceMap.size();
595 
596 
597  // Where to insert old internal faces.
598  label oldPatchStart = labelMax;
599  if (wantedPatchID != -1)
600  {
601  oldPatchStart = oldPatches[wantedPatchID].start();
602  }
603 
604 
605  label facei = 0;
606 
607  // 2. Boundary faces up to where we want to insert old internal faces
608  for (; facei< facesToc.size(); facei++)
609  {
610  if (facesToc[facei] >= oldPatchStart)
611  {
612  break;
613  }
614  if
615  (
616  !baseMesh().isInternalFace(facesToc[facei])
617  && facesToSubset[facesToc[facei]] == 1
618  )
619  {
620  // Mark face and increment number of points in set
621  faceMap_[globalFaceMap.size()] = facesToc[facei];
622  globalFaceMap.insert(facesToc[facei], globalFaceMap.size());
623 
624  // Mark all points from the face
625  markPoints(oldFaces[facesToc[facei]], globalPointMap);
626  }
627  }
628 
629  // 3. old internal faces and uncoupled faces
630  forAll(facesToc, intFacei)
631  {
632  if
633  (
634  (
635  baseMesh().isInternalFace(facesToc[intFacei])
636  && facesToSubset[facesToc[intFacei]] == 1
637  )
638  || (
639  !baseMesh().isInternalFace(facesToc[intFacei])
640  && facesToSubset[facesToc[intFacei]] == 3
641  )
642  )
643  {
644  // Mark face and increment number of points in set
645  faceMap_[globalFaceMap.size()] = facesToc[intFacei];
646  globalFaceMap.insert(facesToc[intFacei], globalFaceMap.size());
647 
648  // Mark all points from the face
649  markPoints(oldFaces[facesToc[intFacei]], globalPointMap);
650  }
651  }
652 
653  // 4. Remaining boundary faces
654  for (; facei< facesToc.size(); facei++)
655  {
656  if
657  (
658  !baseMesh().isInternalFace(facesToc[facei])
659  && facesToSubset[facesToc[facei]] == 1
660  )
661  {
662  // Mark face and increment number of points in set
663  faceMap_[globalFaceMap.size()] = facesToc[facei];
664  globalFaceMap.insert(facesToc[facei], globalFaceMap.size());
665 
666  // Mark all points from the face
667  markPoints(oldFaces[facesToc[facei]], globalPointMap);
668  }
669  }
670 
671 
672 
673  // Grab the points map
674  pointMap_ = globalPointMap.toc();
675  sort(pointMap_);
676 
677  forAll(pointMap_, pointi)
678  {
679  globalPointMap[pointMap_[pointi]] = pointi;
680  }
681 
682  // Make a new mesh
683  pointField newPoints(globalPointMap.size());
684 
685  label nNewPoints = 0;
686 
687  forAll(pointMap_, pointi)
688  {
689  newPoints[nNewPoints] = oldPoints[pointMap_[pointi]];
690  nNewPoints++;
691  }
692 
693  faceList newFaces(globalFaceMap.size());
694 
695  label nNewFaces = 0;
696 
697  // Make internal faces
698  for (label facei = 0; facei < nInternalFaces; facei++)
699  {
700  const face& oldF = oldFaces[faceMap_[facei]];
701 
702  face newF(oldF.size());
703 
704  forAll(newF, i)
705  {
706  newF[i] = globalPointMap[oldF[i]];
707  }
708 
709  newFaces[nNewFaces] = newF;
710  nNewFaces++;
711  }
712 
713  // Make boundary faces
714 
715  label nbSize = oldPatches.size();
716  label oldInternalPatchID = -1;
717 
718  if (wantedPatchID == -1)
719  {
720  // Create 'oldInternalFaces' patch at the end
721  // and put all exposed internal faces in there.
722  oldInternalPatchID = nbSize;
723  nbSize++;
724 
725  }
726  else
727  {
728  oldInternalPatchID = wantedPatchID;
729  }
730 
731 
732  // Grad size and start of each patch on the fly. Because of the
733  // structure of the underlying mesh, the patches will appear in the
734  // ascending order
735  labelList boundaryPatchSizes(nbSize, 0);
736 
737  // Assign boundary faces. Visited in order of faceMap_.
738  for (label facei = nInternalFaces; facei < faceMap_.size(); facei++)
739  {
740  const label oldFacei = faceMap_[facei];
741 
742  face oldF = oldFaces[oldFacei];
743 
744  // Turn the faces as necessary to point outwards
745  if (baseMesh().isInternalFace(oldFacei))
746  {
747  // Internal face. Possibly turned the wrong way round
748  if
749  (
750  !globalCellMap.found(oldOwner[oldFacei])
751  && globalCellMap.found(oldNeighbour[oldFacei])
752  )
753  {
754  oldF = oldFaces[oldFacei].reverseFace();
755  }
756 
757  // Update count for patch
758  boundaryPatchSizes[oldInternalPatchID]++;
759  }
760  else if (facesToSubset[oldFacei] == 3)
761  {
762  // Uncoupled face. Increment the old patch.
763  boundaryPatchSizes[oldInternalPatchID]++;
764  }
765  else
766  {
767  // Boundary face. Increment the appropriate patch
768  const label patchOfFace = oldPatches.whichPatch(oldFacei);
769 
770  // Update count for patch
771  boundaryPatchSizes[patchOfFace]++;
772  }
773 
774  face newF(oldF.size());
775 
776  forAll(newF, i)
777  {
778  newF[i] = globalPointMap[oldF[i]];
779  }
780 
781  newFaces[nNewFaces] = newF;
782  nNewFaces++;
783  }
784 
785 
786 
787  // Create cells
788  cellList newCells(nCellsInSet);
789 
790  label nNewCells = 0;
791 
792  forAll(cellMap_, celli)
793  {
794  const labelList& oldC = oldCells[cellMap_[celli]];
795 
796  labelList newC(oldC.size());
797 
798  forAll(newC, i)
799  {
800  newC[i] = globalFaceMap[oldC[i]];
801  }
802 
803  newCells[nNewCells] = cell(newC);
804  nNewCells++;
805  }
806 
807 
808  // Delete any old mesh
809  fvMeshSubsetPtr_.clear();
810  // Make a new mesh
811  fvMeshSubsetPtr_.reset
812  (
813  new fvMesh
814  (
815  IOobject
816  (
817  baseMesh().name() + "SubSet",
818  baseMesh().time().timeName(),
819  baseMesh().time(),
822  ),
823  move(newPoints),
824  move(newFaces),
825  move(newCells)
826  )
827  );
828 
829 
830  // Add old patches
831  List<polyPatch*> newBoundary(nbSize);
832  patchMap_.setSize(nbSize);
833  label nNewPatches = 0;
834  label patchStart = nInternalFaces;
835 
836 
837  forAll(oldPatches, patchi)
838  {
839  if (boundaryPatchSizes[patchi] > 0)
840  {
841  // Patch still exists. Add it
842  newBoundary[nNewPatches] = oldPatches[patchi].clone
843  (
844  fvMeshSubsetPtr_().boundaryMesh(),
845  nNewPatches,
846  boundaryPatchSizes[patchi],
847  patchStart
848  ).ptr();
849 
850  patchStart += boundaryPatchSizes[patchi];
851  patchMap_[nNewPatches] = patchi;
852  nNewPatches++;
853  }
854  }
855 
856  if (wantedPatchID == -1)
857  {
858  // Newly created patch so is at end. Check if any faces in it.
859  if (boundaryPatchSizes[oldInternalPatchID] > 0)
860  {
861  newBoundary[nNewPatches] = new internalPolyPatch
862  (
863  "oldInternalFaces",
864  boundaryPatchSizes[oldInternalPatchID],
865  patchStart,
866  nNewPatches,
867  fvMeshSubsetPtr_().boundaryMesh(),
868  internalPolyPatch::typeName
869  );
870 
871  // The index for the first patch is -1 as it originates from
872  // the internal faces
873  patchMap_[nNewPatches] = -1;
874  nNewPatches++;
875  }
876  }
877  // else
878  // {
879  // patchMap_[wantedPatchID] = -1;
880  // }
881 
882  // Reset the patch lists
883  newBoundary.setSize(nNewPatches);
884  patchMap_.setSize(nNewPatches);
885 
886  // Add the fvPatches
887  fvMeshSubsetPtr_().addFvPatches(newBoundary);
888 
889  // Subset and add any zones
890  subsetZones();
891 }
892 
893 
895 (
896  const labelList& region,
897  const label currentRegion,
898  const label patchID,
899  const bool syncPar
900 )
901 {
902  const cellList& oldCells = baseMesh().cells();
903  const faceList& oldFaces = baseMesh().faces();
904  const pointField& oldPoints = baseMesh().points();
905  const labelList& oldOwner = baseMesh().faceOwner();
906  const labelList& oldNeighbour = baseMesh().faceNeighbour();
907  const polyBoundaryMesh& oldPatches = baseMesh().boundaryMesh();
908  const label oldNInternalFaces = baseMesh().nInternalFaces();
909 
910  // Initial checks
911 
912  if (region.size() != oldCells.size())
913  {
915  << "Size of region " << region.size()
916  << " is not equal to number of cells in mesh " << oldCells.size()
917  << abort(FatalError);
918  }
919 
920 
921  label wantedPatchID = patchID;
922 
923  if (wantedPatchID == -1)
924  {
925  // No explicit patch specified. Put in oldInternalFaces patch.
926  // Check if patch with this name already exists.
927  wantedPatchID = oldPatches.findPatchID("oldInternalFaces");
928  }
929  else if (wantedPatchID < 0 || wantedPatchID >= oldPatches.size())
930  {
932  << "Non-existing patch index " << wantedPatchID << endl
933  << "Should be between 0 and " << oldPatches.size()-1
934  << abort(FatalError);
935  }
936 
937  // Clear demand driven data
938  faceFlipMapPtr_.clear();
939 
940  // Get the cells for the current region.
941  cellMap_.setSize(oldCells.size());
942  label nCellsInSet = 0;
943 
944  forAll(region, oldCelli)
945  {
946  if (region[oldCelli] == currentRegion)
947  {
948  cellMap_[nCellsInSet++] = oldCelli;
949  }
950  }
951  cellMap_.setSize(nCellsInSet);
952 
953 
954  // Mark all used faces. Count number of cells using them
955  // 0: face not used anymore
956  // 1: face used by one cell, face becomes/stays boundary face
957  // 2: face still used and remains internal face
958  // 3: face coupled and used by one cell only (so should become normal,
959  // non-coupled patch face)
960  //
961  // Note that this is not really necessary - but means we can size things
962  // correctly. Also makes handling coupled faces much easier.
963 
964  labelList nCellsUsingFace(oldFaces.size(), 0);
965 
966  label nFacesInSet = 0;
967  forAll(oldFaces, oldFacei)
968  {
969  bool faceUsed = false;
970 
971  if (region[oldOwner[oldFacei]] == currentRegion)
972  {
973  nCellsUsingFace[oldFacei]++;
974  faceUsed = true;
975  }
976 
977  if
978  (
979  baseMesh().isInternalFace(oldFacei)
980  && (region[oldNeighbour[oldFacei]] == currentRegion)
981  )
982  {
983  nCellsUsingFace[oldFacei]++;
984  faceUsed = true;
985  }
986 
987  if (faceUsed)
988  {
989  nFacesInSet++;
990  }
991  }
992  faceMap_.setSize(nFacesInSet);
993 
994  // Handle coupled faces. Modifies patch faces to be uncoupled to 3.
995  Map<label> empty;
996  doCoupledPatches(syncPar, empty, nCellsUsingFace);
997 
998 
999  // See which patch to use for exposed internal faces.
1000  label oldInternalPatchID = 0;
1001 
1002  // Insert faces before which patch
1003  label nextPatchID = oldPatches.size();
1004 
1005  // old to new patches
1006  labelList globalPatchMap(oldPatches.size());
1007 
1008  // New patch size
1009  label nbSize = oldPatches.size();
1010 
1011  if (wantedPatchID == -1)
1012  {
1013  // Create 'oldInternalFaces' patch at the end (or before
1014  // processorPatches)
1015  // and put all exposed internal faces in there.
1016 
1017  forAll(oldPatches, patchi)
1018  {
1019  if (isA<processorPolyPatch>(oldPatches[patchi]))
1020  {
1021  nextPatchID = patchi;
1022  break;
1023  }
1024  oldInternalPatchID++;
1025  }
1026 
1027  nbSize++;
1028 
1029  // adapt old to new patches for inserted patch
1030  for (label oldPatchi = 0; oldPatchi < nextPatchID; oldPatchi++)
1031  {
1032  globalPatchMap[oldPatchi] = oldPatchi;
1033  }
1034  for
1035  (
1036  label oldPatchi = nextPatchID;
1037  oldPatchi < oldPatches.size();
1038  oldPatchi++
1039  )
1040  {
1041  globalPatchMap[oldPatchi] = oldPatchi + 1;
1042  }
1043  }
1044  else
1045  {
1046  oldInternalPatchID = wantedPatchID;
1047  nextPatchID = wantedPatchID + 1;
1048 
1049  // old to new patches
1050  globalPatchMap = identity(oldPatches.size());
1051  }
1052 
1053  labelList boundaryPatchSizes(nbSize, 0);
1054 
1055 
1056  // Make a global-to-local point map
1057  labelList globalPointMap(oldPoints.size(), -1);
1058 
1059  labelList globalFaceMap(oldFaces.size(), -1);
1060  label facei = 0;
1061 
1062  // 1. Pick up all preserved internal faces.
1063  for (label oldFacei = 0; oldFacei < oldNInternalFaces; oldFacei++)
1064  {
1065  if (nCellsUsingFace[oldFacei] == 2)
1066  {
1067  globalFaceMap[oldFacei] = facei;
1068  faceMap_[facei++] = oldFacei;
1069 
1070  // Mark all points from the face
1071  markPoints(oldFaces[oldFacei], globalPointMap);
1072  }
1073  }
1074 
1075  // These are all the internal faces in the mesh.
1076  label nInternalFaces = facei;
1077 
1078  // 2. Boundary faces up to where we want to insert old internal faces
1079  for
1080  (
1081  label oldPatchi = 0;
1082  oldPatchi < oldPatches.size()
1083  && oldPatchi < nextPatchID;
1084  oldPatchi++
1085  )
1086  {
1087  const polyPatch& oldPatch = oldPatches[oldPatchi];
1088 
1089  label oldFacei = oldPatch.start();
1090 
1091  forAll(oldPatch, i)
1092  {
1093  if (nCellsUsingFace[oldFacei] == 1)
1094  {
1095  // Boundary face is kept.
1096 
1097  // Mark face and increment number of points in set
1098  globalFaceMap[oldFacei] = facei;
1099  faceMap_[facei++] = oldFacei;
1100 
1101  // Mark all points from the face
1102  markPoints(oldFaces[oldFacei], globalPointMap);
1103 
1104  // Increment number of patch faces
1105  boundaryPatchSizes[globalPatchMap[oldPatchi]]++;
1106  }
1107  oldFacei++;
1108  }
1109  }
1110 
1111  // 3a. old internal faces that have become exposed.
1112  for (label oldFacei = 0; oldFacei < oldNInternalFaces; oldFacei++)
1113  {
1114  if (nCellsUsingFace[oldFacei] == 1)
1115  {
1116  globalFaceMap[oldFacei] = facei;
1117  faceMap_[facei++] = oldFacei;
1118 
1119  // Mark all points from the face
1120  markPoints(oldFaces[oldFacei], globalPointMap);
1121 
1122  // Increment number of patch faces
1123  boundaryPatchSizes[oldInternalPatchID]++;
1124  }
1125  }
1126 
1127  // 3b. coupled patch faces that have become uncoupled.
1128  for
1129  (
1130  label oldFacei = oldNInternalFaces;
1131  oldFacei < oldFaces.size();
1132  oldFacei++
1133  )
1134  {
1135  if (nCellsUsingFace[oldFacei] == 3)
1136  {
1137  globalFaceMap[oldFacei] = facei;
1138  faceMap_[facei++] = oldFacei;
1139 
1140  // Mark all points from the face
1141  markPoints(oldFaces[oldFacei], globalPointMap);
1142 
1143  // Increment number of patch faces
1144  boundaryPatchSizes[oldInternalPatchID]++;
1145  }
1146  }
1147 
1148  // 4. Remaining boundary faces
1149  for
1150  (
1151  label oldPatchi = nextPatchID;
1152  oldPatchi < oldPatches.size();
1153  oldPatchi++
1154  )
1155  {
1156  const polyPatch& oldPatch = oldPatches[oldPatchi];
1157 
1158  label oldFacei = oldPatch.start();
1159 
1160  forAll(oldPatch, i)
1161  {
1162  if (nCellsUsingFace[oldFacei] == 1)
1163  {
1164  // Boundary face is kept.
1165 
1166  // Mark face and increment number of points in set
1167  globalFaceMap[oldFacei] = facei;
1168  faceMap_[facei++] = oldFacei;
1169 
1170  // Mark all points from the face
1171  markPoints(oldFaces[oldFacei], globalPointMap);
1172 
1173  // Increment number of patch faces
1174  boundaryPatchSizes[globalPatchMap[oldPatchi]]++;
1175  }
1176  oldFacei++;
1177  }
1178  }
1179 
1180  if (facei != nFacesInSet)
1181  {
1183  << "Problem" << abort(FatalError);
1184  }
1185 
1186 
1187  // Grab the points map
1188  label nPointsInSet = 0;
1189 
1190  forAll(globalPointMap, pointi)
1191  {
1192  if (globalPointMap[pointi] != -1)
1193  {
1194  nPointsInSet++;
1195  }
1196  }
1197  pointMap_.setSize(nPointsInSet);
1198 
1199  nPointsInSet = 0;
1200 
1201  forAll(globalPointMap, pointi)
1202  {
1203  if (globalPointMap[pointi] != -1)
1204  {
1205  pointMap_[nPointsInSet] = pointi;
1206  globalPointMap[pointi] = nPointsInSet;
1207  nPointsInSet++;
1208  }
1209  }
1210 
1211 
1212  // Make a new mesh
1213  pointField newPoints(pointMap_.size());
1214 
1215  label nNewPoints = 0;
1216 
1217  forAll(pointMap_, pointi)
1218  {
1219  newPoints[nNewPoints] = oldPoints[pointMap_[pointi]];
1220  nNewPoints++;
1221  }
1222 
1223  faceList newFaces(faceMap_.size());
1224 
1225  label nNewFaces = 0;
1226 
1227  // Make internal faces
1228  for (label facei = 0; facei < nInternalFaces; facei++)
1229  {
1230  const face& oldF = oldFaces[faceMap_[facei]];
1231 
1232  face newF(oldF.size());
1233 
1234  forAll(newF, i)
1235  {
1236  newF[i] = globalPointMap[oldF[i]];
1237  }
1238 
1239  newFaces[nNewFaces] = newF;
1240  nNewFaces++;
1241  }
1242 
1243 
1244  // Make boundary faces. (different from internal since might need to be
1245  // flipped)
1246  for (label facei = nInternalFaces; facei < faceMap_.size(); facei++)
1247  {
1248  const label oldFacei = faceMap_[facei];
1249 
1250  face oldF = oldFaces[oldFacei];
1251 
1252  // Turn the faces as necessary to point outwards
1253  if (baseMesh().isInternalFace(oldFacei))
1254  {
1255  // Was internal face. Possibly turned the wrong way round
1256  if
1257  (
1258  region[oldOwner[oldFacei]] != currentRegion
1259  && region[oldNeighbour[oldFacei]] == currentRegion
1260  )
1261  {
1262  oldF = oldFaces[oldFacei].reverseFace();
1263  }
1264  }
1265 
1266  // Relabel vertices of the (possibly turned) face.
1267  face newF(oldF.size());
1268 
1269  forAll(newF, i)
1270  {
1271  newF[i] = globalPointMap[oldF[i]];
1272  }
1273 
1274  newFaces[nNewFaces] = newF;
1275  nNewFaces++;
1276  }
1277 
1278 
1279 
1280  // Create cells
1281  cellList newCells(nCellsInSet);
1282 
1283  label nNewCells = 0;
1284 
1285  forAll(cellMap_, celli)
1286  {
1287  const labelList& oldC = oldCells[cellMap_[celli]];
1288 
1289  labelList newC(oldC.size());
1290 
1291  forAll(newC, i)
1292  {
1293  newC[i] = globalFaceMap[oldC[i]];
1294  }
1295 
1296  newCells[nNewCells] = cell(newC);
1297  nNewCells++;
1298  }
1299 
1300 
1301  // Delete any old one
1302  fvMeshSubsetPtr_.clear();
1303 
1304  // Make a new mesh
1305  // Note that mesh gets registered with same name as original mesh. This is
1306  // not proper but cannot be avoided since otherwise surfaceInterpolation
1307  // cannot find its fvSchemes (it will try to read e.g.
1308  // system/region0SubSet/fvSchemes)
1309  // Make a new mesh
1310  fvMeshSubsetPtr_.reset
1311  (
1312  new fvMesh
1313  (
1314  IOobject
1315  (
1316  baseMesh().name(),
1317  baseMesh().time().timeName(),
1318  baseMesh().time(),
1321  ),
1322  move(newPoints),
1323  move(newFaces),
1324  move(newCells),
1325  syncPar // parallel synchronisation
1326  )
1327  );
1328 
1329  // Add old patches
1330  List<polyPatch*> newBoundary(nbSize);
1331  patchMap_.setSize(nbSize);
1332  label nNewPatches = 0;
1333  label patchStart = nInternalFaces;
1334 
1335 
1336  // For parallel: only remove patch if none of the processors has it.
1337  // This only gets done for patches before the one being inserted
1338  // (so patches < nextPatchID)
1339 
1340  // Get sum of patch sizes. Zero if patch can be deleted.
1341  labelList globalPatchSizes(boundaryPatchSizes);
1342  globalPatchSizes.setSize(nextPatchID);
1343 
1344  if (syncPar && Pstream::parRun())
1345  {
1346  // Get patch names (up to nextPatchID)
1348  patchNames[Pstream::myProcNo()] = oldPatches.names();
1349  patchNames[Pstream::myProcNo()].setSize(nextPatchID);
1350  Pstream::gatherList(patchNames);
1351  Pstream::scatterList(patchNames);
1352 
1353  // Get patch sizes (up to nextPatchID).
1354  // Note that up to nextPatchID the globalPatchMap is an identity so
1355  // no need to index through that.
1356  Pstream::listCombineGather(globalPatchSizes, plusEqOp<label>());
1357  Pstream::listCombineScatter(globalPatchSizes);
1358 
1359  // Now all processors have all the patchnames.
1360  // Decide: if all processors have the same patch names and size is zero
1361  // everywhere remove the patch.
1362  bool samePatches = true;
1363 
1364  for (label proci = 1; proci < patchNames.size(); proci++)
1365  {
1366  if (patchNames[proci] != patchNames[0])
1367  {
1368  samePatches = false;
1369  break;
1370  }
1371  }
1372 
1373  if (!samePatches)
1374  {
1375  // Patchnames not sync on all processors so disable removal of
1376  // zero sized patches.
1377  globalPatchSizes = labelMax;
1378  }
1379  }
1380 
1381 
1382  // Old patches
1383 
1384  for
1385  (
1386  label oldPatchi = 0;
1387  oldPatchi < oldPatches.size()
1388  && oldPatchi < nextPatchID;
1389  oldPatchi++
1390  )
1391  {
1392  const label newSize = boundaryPatchSizes[globalPatchMap[oldPatchi]];
1393 
1394  // Clone (even if 0 size)
1395  newBoundary[nNewPatches] = oldPatches[oldPatchi].clone
1396  (
1397  fvMeshSubsetPtr_().boundaryMesh(),
1398  nNewPatches,
1399  newSize,
1400  patchStart
1401  ).ptr();
1402 
1403  patchStart += newSize;
1404  patchMap_[nNewPatches] = oldPatchi; // compact patchMap
1405  nNewPatches++;
1406  }
1407 
1408  // Inserted patch
1409 
1410  if (wantedPatchID == -1)
1411  {
1412  label oldInternalSize = boundaryPatchSizes[oldInternalPatchID];
1413 
1414  if (syncPar)
1415  {
1416  reduce(oldInternalSize, sumOp<label>());
1417  }
1418 
1419  // Newly created patch so is at end. Check if any faces in it.
1420  if (oldInternalSize > 0)
1421  {
1422  newBoundary[nNewPatches] = new internalPolyPatch
1423  (
1424  "oldInternalFaces",
1425  boundaryPatchSizes[oldInternalPatchID],
1426  patchStart,
1427  nNewPatches,
1428  fvMeshSubsetPtr_().boundaryMesh(),
1429  internalPolyPatch::typeName
1430  );
1431 
1432  // The index for the first patch is -1 as it originates from
1433  // the internal faces
1434  patchStart += boundaryPatchSizes[oldInternalPatchID];
1435  patchMap_[nNewPatches] = -1;
1436  nNewPatches++;
1437  }
1438  }
1439  // else
1440  // {
1441  // patchMap_[wantedPatchID] = -1;
1442  // }
1443 
1444  // Old patches
1445 
1446  for
1447  (
1448  label oldPatchi = nextPatchID;
1449  oldPatchi < oldPatches.size();
1450  oldPatchi++
1451  )
1452  {
1453  const label newSize = boundaryPatchSizes[globalPatchMap[oldPatchi]];
1454 
1455  // Patch still exists. Add it
1456  newBoundary[nNewPatches] = oldPatches[oldPatchi].clone
1457  (
1458  fvMeshSubsetPtr_().boundaryMesh(),
1459  nNewPatches,
1460  newSize,
1461  patchStart
1462  ).ptr();
1463 
1464  patchStart += newSize;
1465  patchMap_[nNewPatches] = oldPatchi; // compact patchMap
1466  nNewPatches++;
1467  }
1468 
1469 
1470  // Reset the patch lists
1471  newBoundary.setSize(nNewPatches);
1472  patchMap_.setSize(nNewPatches);
1473 
1474 
1475  // Add the fvPatches
1476  fvMeshSubsetPtr_().addFvPatches(newBoundary, syncPar);
1477 
1478  // Subset and add any zones
1479  subsetZones();
1480 }
1481 
1482 
1485  const labelHashSet& globalCellMap,
1486  const label patchID,
1487  const bool syncPar
1488 )
1489 {
1490  labelList region(baseMesh().nCells(), 0);
1491 
1492  forAllConstIter(labelHashSet, globalCellMap, iter)
1493  {
1494  region[iter.key()] = 1;
1495  }
1496  setLargeCellSubset(region, 1, patchID, syncPar);
1497 }
1498 
1499 
1502  const labelList& region,
1503  const label currentRegion,
1504  const bool syncCouples
1505 ) const
1506 {
1507  // Collect cells to remove
1508  const labelList cellsToRemove(getCellsToRemove(region, currentRegion));
1509 
1510  return removeCells(baseMesh(), syncCouples).getExposedFaces(cellsToRemove);
1511 }
1512 
1513 
1516  const labelList& region,
1517  const label currentRegion,
1518  const labelList& exposedFaces,
1519  const labelList& patchIDs,
1520  const bool syncCouples
1521 )
1522 {
1523  // Collect cells to remove
1524  labelList cellsToRemove(getCellsToRemove(region, currentRegion));
1525 
1526  // Mesh changing engine.
1527  polyTopoChange meshMod(baseMesh());
1528 
1529  removeCells cellRemover(baseMesh(), syncCouples);
1530 
1531  cellRemover.setRefinement
1532  (
1533  cellsToRemove,
1534  exposedFaces,
1535  patchIDs,
1536  meshMod
1537  );
1538 
1539  // Create mesh, return map from old to new mesh.
1540  autoPtr<polyTopoChangeMap> map = meshMod.makeMesh
1541  (
1542  fvMeshSubsetPtr_,
1543  IOobject
1544  (
1545  baseMesh().name(),
1546  baseMesh().time().timeName(),
1547  baseMesh().time(),
1550  ),
1551  baseMesh(),
1552  syncCouples
1553  );
1554 
1555  pointMap_ = map().pointMap();
1556  faceMap_ = map().faceMap();
1557  cellMap_ = map().cellMap();
1558  patchMap_ = identity(baseMesh().boundaryMesh().size());
1559 }
1560 
1561 
1563 {
1564  return fvMeshSubsetPtr_.valid();
1565 }
1566 
1567 
1569 {
1570  checkCellSubset();
1571 
1572  return fvMeshSubsetPtr_();
1573 }
1574 
1575 
1577 {
1578  checkCellSubset();
1579 
1580  return fvMeshSubsetPtr_();
1581 }
1582 
1583 
1585 {
1586  checkCellSubset();
1587 
1588  return pointMap_;
1589 }
1590 
1591 
1593 {
1594  checkCellSubset();
1595 
1596  return faceMap_;
1597 }
1598 
1599 
1601 {
1602  if (!faceFlipMapPtr_.valid())
1603  {
1604  const labelList& subToBaseFace = faceMap();
1605  const labelList& subToBaseCell = cellMap();
1606 
1607  faceFlipMapPtr_.reset(new labelList(subToBaseFace.size()));
1608  labelList& faceFlipMap = faceFlipMapPtr_();
1609 
1610  // Only exposed internal faces might be flipped (since we don't do
1611  // any cell renumbering, just compacting)
1612  label subInt = subMesh().nInternalFaces();
1613  const labelList& subOwn = subMesh().faceOwner();
1614  const labelList& own = baseMesh_.faceOwner();
1615 
1616  for (label subFacei = 0; subFacei < subInt; subFacei++)
1617  {
1618  faceFlipMap[subFacei] = subToBaseFace[subFacei] + 1;
1619  }
1620  for (label subFacei = subInt; subFacei < subOwn.size(); subFacei++)
1621  {
1622  const label facei = subToBaseFace[subFacei];
1623  if (subToBaseCell[subOwn[subFacei]] == own[facei])
1624  {
1625  faceFlipMap[subFacei] = facei + 1;
1626  }
1627  else
1628  {
1629  faceFlipMap[subFacei] = -facei - 1;
1630  }
1631  }
1632  }
1633 
1634  return faceFlipMapPtr_();
1635 }
1636 
1637 
1639 {
1640  checkCellSubset();
1641 
1642  return cellMap_;
1643 }
1644 
1645 
1647 {
1648  checkCellSubset();
1649 
1650  return patchMap_;
1651 }
1652 
1653 
1654 // ************************************************************************* //
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:453
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:288
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
FvWallInfoData< WallInfo, label > label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
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
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
label nInternalFaces() const
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1243
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
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
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.
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:472
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
const labelList & faceMap() const
Return face map.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1211
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:1237
virtual ~fvMeshSubset()
Destructor.
Definition: fvMeshSubset.C:486
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:1224
MeshZones< pointZone, polyMesh > meshPointZones
A MeshZones with the type pointZone.
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:493
defineTypeNameAndDebug(combustionModel, 0)
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:57
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:95
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:306
ListType subset(const UList< T > &select, const T &value, const ListType &)
Extract elements of List when select is a certain value.
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:98
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:895
const fvMesh & baseMesh() const
Original mesh.
Definition: fvMeshSubset.H:222
Namespace for OpenFOAM.
bool hasSubMesh() const
Have subMesh?