fvMeshSubset.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "fvMeshSubset.H"
30 #include "boolList.H"
31 #include "BitOps.H"
32 #include "pointIndList.H"
33 #include "Pstream.H"
34 #include "emptyPolyPatch.H"
35 #include "cyclicPolyPatch.H"
36 #include "removeCells.H"
37 #include "polyTopoChange.H"
38 #include "mapPolyMesh.H"
39 
40 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
41 
42 namespace
43 {
44 
45 // Mark faces/points (with 0) in labelList
46 inline void markUsed
47 (
48  const Foam::labelUList& locations,
49  Foam::labelList& map
50 )
51 {
52  for (auto idx : locations)
53  {
54  map[idx] = 0;
55  }
56 }
57 
58 } // End anonymous namespace
59 
60 
61 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
62 
64 
65 
66 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
67 
68 bool Foam::fvMeshSubset::checkCellSubset() const
69 {
70  if (!fvMeshSubsetPtr_)
71  {
73  << "setCellSubset()" << nl
74  << "before attempting to access subset data"
75  << abort(FatalError);
76 
77  return false;
78  }
79 
80  return true;
81 }
82 
83 
84 void Foam::fvMeshSubset::calcFaceFlipMap() const
85 {
86  const labelList& subToBaseFace = faceMap();
87  const labelList& subToBaseCell = cellMap();
88 
89  faceFlipMapPtr_.reset(new labelList(subToBaseFace.size()));
90  auto& faceFlipMap = *faceFlipMapPtr_;
91 
92  // Only exposed internal faces might be flipped (since we don't do
93  // any cell renumbering, just compacting)
94  const label subInt = subMesh().nInternalFaces();
95 
96  const labelList& subOwn = subMesh().faceOwner();
97  const labelList& own = baseMesh_.faceOwner();
98 
99  for (label subFaceI = 0; subFaceI < subInt; ++subFaceI)
100  {
101  faceFlipMap[subFaceI] = subToBaseFace[subFaceI]+1;
102  }
103  for (label subFaceI = subInt; subFaceI < subOwn.size(); ++subFaceI)
104  {
105  const label faceI = subToBaseFace[subFaceI];
106  if (subToBaseCell[subOwn[subFaceI]] == own[faceI])
107  {
108  faceFlipMap[subFaceI] = faceI+1;
109  }
110  else
111  {
112  faceFlipMap[subFaceI] = -faceI-1;
113  }
114  }
115 }
116 
117 
118 void Foam::fvMeshSubset::doCoupledPatches
119 (
120  const bool syncPar,
121  labelList& nCellsUsingFace
122 ) const
123 {
124  // Synchronize facesToSubset on both sides of coupled patches.
125  // Marks faces that become 'uncoupled' with 3.
126 
127  const polyBoundaryMesh& oldPatches = baseMesh().boundaryMesh();
128 
129  label nUncoupled = 0;
130 
131  if (syncPar && Pstream::parRun())
132  {
133  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
134 
135  // Send face usage across processor patches
136  for (const polyPatch& pp : oldPatches)
137  {
138  const auto* procPatch = isA<processorPolyPatch>(pp);
139 
140  if (procPatch)
141  {
142  const label nbrProci = procPatch->neighbProcNo();
143 
144  UOPstream toNeighbour(nbrProci, pBufs);
145 
146  if (!nCellsUsingFace.empty())
147  {
148  toNeighbour <<
149  SubList<label>(nCellsUsingFace, pp.size(), pp.start());
150  }
151  else
152  {
153  toNeighbour << labelList();
154  }
155  }
156  }
157 
158  pBufs.finishedSends();
159 
160  // Receive face usage count and check for faces that become uncoupled.
161  for (const polyPatch& pp : oldPatches)
162  {
163  const auto* procPatch = isA<processorPolyPatch>(pp);
164 
165  if (procPatch)
166  {
167  const label nbrProci = procPatch->neighbProcNo();
168 
169  UIPstream fromNeighbour(nbrProci, pBufs);
170 
171  const labelList nbrList(fromNeighbour);
172 
173  // Combine with this side.
174 
175  if (!nCellsUsingFace.empty())
176  {
177  const labelList& nbrCellsUsingFace(nbrList);
178 
179  // Combine with this side.
180 
181  forAll(pp, i)
182  {
183  if
184  (
185  nCellsUsingFace[pp.start()+i] == 1
186  && nbrCellsUsingFace[i] == 0
187  )
188  {
189  // Face's neighbour is no longer there. Mark face
190  // off as coupled
191  nCellsUsingFace[pp.start()+i] = 3;
192  ++nUncoupled;
193  }
194  }
195  }
196  }
197  }
198  }
199 
200  // Do same for cyclics.
201  for (const polyPatch& pp : oldPatches)
202  {
203  const cyclicPolyPatch* cpp = isA<cyclicPolyPatch>(pp);
204 
205  if (cpp && !nCellsUsingFace.empty())
206  {
207  const auto& cycPatch = *cpp;
208 
209  forAll(cycPatch, i)
210  {
211  label thisFacei = cycPatch.start() + i;
212  label otherFacei = cycPatch.transformGlobalFace(thisFacei);
213 
214  if
215  (
216  nCellsUsingFace[thisFacei] == 1
217  && nCellsUsingFace[otherFacei] == 0
218  )
219  {
220  nCellsUsingFace[thisFacei] = 3;
221  ++nUncoupled;
222  }
223  }
224  }
225  }
226 
227  if (syncPar)
228  {
229  reduce(nUncoupled, sumOp<label>());
230  }
231 
232  if (nUncoupled > 0)
233  {
234  Info<< "Uncoupled " << nUncoupled << " faces on coupled patches. "
235  << "(processorPolyPatch, cyclicPolyPatch)" << endl;
236  }
237 }
238 
239 
240 void Foam::fvMeshSubset::removeCellsImpl
241 (
242  const bitSet& cellsToRemove,
243  const labelList& exposedFaces,
244  const labelList& patchIDs,
245  const bool syncCouples
246 )
247 {
248  // Mesh changing engine.
249  polyTopoChange meshMod(baseMesh());
250 
251  removeCells cellRemover(baseMesh(), syncCouples);
252 
253  cellRemover.setRefinement
254  (
255  cellsToRemove,
256  exposedFaces,
257  patchIDs,
258  meshMod
259  );
260 
261  // Create mesh, return map from old to new mesh.
262  autoPtr<mapPolyMesh> map = meshMod.makeMesh
263  (
264  fvMeshSubsetPtr_,
265  IOobject
266  (
267  baseMesh().name(),
268  baseMesh().time().timeName(),
269  baseMesh().time(),
270  IOobject::READ_IF_PRESENT, // read fv* if present
272  ),
273  baseMesh(),
274  syncCouples
275  );
276 
277  pointMap_ = map().pointMap();
278  faceMap_ = map().faceMap();
279  cellMap_ = map().cellMap();
280  patchMap_ = identity(baseMesh().boundaryMesh().size());
281 }
282 
283 
284 Foam::labelList Foam::fvMeshSubset::subsetSubset
285 (
286  const label nElems,
287  const labelUList& selectedElements,
288  const labelUList& subsetMap
289 )
290 {
291  // Mark selected elements.
292  const bitSet selected(nElems, selectedElements);
293 
294  // Count subset of selected elements
295  label n = 0;
296  forAll(subsetMap, i)
297  {
298  if (selected[subsetMap[i]])
299  {
300  ++n;
301  }
302  }
303 
304  // Collect selected elements
305  labelList subsettedElements(n);
306  n = 0;
307 
308  forAll(subsetMap, i)
309  {
310  if (selected[subsetMap[i]])
311  {
312  subsettedElements[n] = i;
313  ++n;
314  }
315  }
316 
317  return subsettedElements;
318 }
319 
320 
321 void Foam::fvMeshSubset::subsetZones()
322 {
323  // Keep all zones, even if zero size.
324 
325  // PointZones
326 
327  const pointZoneMesh& pointZones = baseMesh().pointZones();
328 
329  List<pointZone*> pZonePtrs(pointZones.size());
330 
331  forAll(pointZones, zonei)
332  {
333  const pointZone& pz = pointZones[zonei];
334 
335  pZonePtrs[zonei] = new pointZone
336  (
337  pz.name(),
338  subsetSubset(baseMesh().nPoints(), pz, pointMap()),
339  zonei,
340  fvMeshSubsetPtr_().pointZones()
341  );
342  }
343 
344 
345  // FaceZones
346  // Do we need to remove zones where the side we're interested in
347  // no longer exists? Guess not.
348 
349  const faceZoneMesh& faceZones = baseMesh().faceZones();
350 
351  List<faceZone*> fZonePtrs(faceZones.size());
352 
353  forAll(faceZones, zonei)
354  {
355  const faceZone& fz = faceZones[zonei];
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(), Zero);
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[zonei] = new faceZone
404  (
405  fz.name(),
406  subAddressing,
407  subFlipStatus,
408  zonei,
409  fvMeshSubsetPtr_().faceZones()
410  );
411  }
412 
413  // Cell Zones
414 
415  const cellZoneMesh& cellZones = baseMesh().cellZones();
416 
417  List<cellZone*> cZonePtrs(cellZones.size());
418 
419  forAll(cellZones, zonei)
420  {
421  const cellZone& cz = cellZones[zonei];
422 
423  cZonePtrs[zonei] = new cellZone
424  (
425  cz.name(),
426  subsetSubset(baseMesh().nCells(), cz, cellMap()),
427  zonei,
428  fvMeshSubsetPtr_().cellZones()
429  );
430  }
431 
432 
433  // Add the zones
434  fvMeshSubsetPtr_().addZones(pZonePtrs, fZonePtrs, cZonePtrs);
435 }
436 
437 
438 Foam::bitSet Foam::fvMeshSubset::getCellsToRemove
439 (
440  const bitSet& selectedCells
441 ) const
442 {
443  // Work on a copy
444  bitSet cellsToRemove(selectedCells);
445 
446  // Ensure we have the full range
447  cellsToRemove.resize(baseMesh().nCells(), false);
448 
449  // Invert the selection
450  cellsToRemove.flip();
451 
452  return cellsToRemove;
453 }
454 
455 
456 Foam::bitSet Foam::fvMeshSubset::getCellsToRemove
457 (
458  const label regioni,
459  const labelUList& regions
460 ) const
461 {
462  return BitSetOps::create
463  (
464  baseMesh().nCells(),
465  regioni,
466  regions,
467  false // on=false: invert return cells to remove
468  );
469 }
470 
471 
472 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
473 
474 Foam::fvMeshSubset::fvMeshSubset(const fvMesh& baseMesh)
475 :
476  baseMesh_(baseMesh),
477  fvMeshSubsetPtr_(nullptr),
478  faceFlipMapPtr_(nullptr),
479  pointMap_(),
480  faceMap_(),
481  cellMap_(),
482  patchMap_()
483 {}
484 
485 
486 Foam::fvMeshSubset::fvMeshSubset
487 (
488  const fvMesh& baseMesh,
489  const bitSet& selectedCells,
490  const label patchID,
491  const bool syncCouples
492 )
493 :
494  fvMeshSubset(baseMesh)
495 {
496  setCellSubset(selectedCells, patchID, syncCouples);
497 }
498 
499 
500 Foam::fvMeshSubset::fvMeshSubset
501 (
502  const fvMesh& baseMesh,
503  const labelHashSet& selectedCells,
504  const label patchID,
505  const bool syncCouples
506 )
507 :
508  fvMeshSubset(baseMesh)
509 {
510  setCellSubset(selectedCells, patchID, syncCouples);
511 }
512 
513 
514 Foam::fvMeshSubset::fvMeshSubset
515 (
516  const fvMesh& baseMesh,
517  const labelUList& selectedCells,
518  const label patchID,
519  const bool syncCouples
520 )
521 :
522  fvMeshSubset(baseMesh)
523 {
524  setCellSubset(selectedCells, patchID, syncCouples);
525 }
526 
527 
528 Foam::fvMeshSubset::fvMeshSubset
529 (
530  const fvMesh& baseMesh,
531  const label regioni,
532  const labelUList& regions,
533  const label patchID,
534  const bool syncCouples
535 )
536 :
537  fvMeshSubset(baseMesh)
538 {
539  setCellSubset(regioni, regions, patchID, syncCouples);
540 }
541 
542 
543 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
544 
546 {
547  fvMeshSubsetPtr_.reset(nullptr);
548  faceFlipMapPtr_.reset(nullptr);
549 
550  pointMap_.clear();
551  faceMap_.clear();
552  cellMap_.clear();
553  patchMap_.clear();
554 }
555 
556 
558 (
559  const bitSet& selectedCells,
560  const label patchID,
561  const bool syncPar
562 )
563 {
564  const cellList& oldCells = baseMesh().cells();
565  const faceList& oldFaces = baseMesh().faces();
566  const pointField& oldPoints = baseMesh().points();
567  const labelList& oldOwner = baseMesh().faceOwner();
568  const labelList& oldNeighbour = baseMesh().faceNeighbour();
569  const polyBoundaryMesh& oldPatches = baseMesh().boundaryMesh();
570  const label oldNInternalFaces = baseMesh().nInternalFaces();
571 
572  // Initial check on patches before doing anything time consuming.
573 
574  label wantedPatchID = patchID;
575 
576  if (wantedPatchID == -1)
577  {
578  // No explicit patch specified. Put in oldInternalFaces patch.
579  // Check if patch with this name already exists.
580  wantedPatchID = oldPatches.findPatchID(exposedPatchName);
581  }
582  else if (wantedPatchID < 0 || wantedPatchID >= oldPatches.size())
583  {
585  << "Non-existing patch index " << wantedPatchID << endl
586  << "Should be between 0 and " << oldPatches.size()-1
587  << abort(FatalError);
588  }
589 
590  // Clear all old maps and pointers
591  clear();
592 
593  // The selected cells - sorted in ascending order
594  cellMap_ = selectedCells.sortedToc();
595 
596  // The selectedCells should normally be in the [0,nCells) range,
597  // but it is better not to trust that.
598  {
599  label len = cellMap_.size();
600  for
601  (
602  label i = len-1;
603  i >= 0 && (cellMap_[i] >= oldCells.size());
604  --i
605  )
606  {
607  len = i;
608  }
609  cellMap_.resize(len);
610  }
611 
612 
613  // Mark all used faces. Count number of cells using them
614  // 0: face not used anymore
615  // 1: face used by one cell, face becomes/stays boundary face
616  // 2: face still used and remains internal face
617  // 3: face coupled and used by one cell only (so should become normal,
618  // non-coupled patch face)
619  //
620  // Note that this is not really necessary - but means we can size things
621  // correctly. Also makes handling coupled faces much easier.
622 
623  labelList nCellsUsingFace(oldFaces.size(), Zero);
624 
625  label nFacesInSet = 0;
626  forAll(oldFaces, oldFacei)
627  {
628  bool faceUsed = false;
629 
630  if (selectedCells.test(oldOwner[oldFacei]))
631  {
632  ++nCellsUsingFace[oldFacei];
633  faceUsed = true;
634  }
635 
636  if
637  (
638  baseMesh().isInternalFace(oldFacei)
639  && selectedCells.test(oldNeighbour[oldFacei])
640  )
641  {
642  ++nCellsUsingFace[oldFacei];
643  faceUsed = true;
644  }
645 
646  if (faceUsed)
647  {
648  ++nFacesInSet;
649  }
650  }
651  faceMap_.setSize(nFacesInSet);
652 
653  // Handle coupled faces. Modifies patch faces to be uncoupled to 3.
654  doCoupledPatches(syncPar, nCellsUsingFace);
655 
656 
657  // See which patch to use for exposed internal faces.
658  label oldInternalPatchID = 0;
659 
660  // Insert faces before which patch
661  label nextPatchID = oldPatches.size();
662 
663  // old to new patches
664  labelList globalPatchMap(oldPatches.size());
665 
666  // New patch size
667  label nbSize = oldPatches.size();
668 
669  if (wantedPatchID == -1)
670  {
671  // Create 'oldInternalFaces' patch at the end (or before
672  // processorPatches)
673  // and put all exposed internal faces in there.
674 
675  forAll(oldPatches, patchi)
676  {
677  if (isA<processorPolyPatch>(oldPatches[patchi]))
678  {
679  nextPatchID = patchi;
680  break;
681  }
682  ++oldInternalPatchID;
683  }
684 
685  ++nbSize;
686 
687  // adapt old to new patches for inserted patch
688  for (label oldPatchi = 0; oldPatchi < nextPatchID; oldPatchi++)
689  {
690  globalPatchMap[oldPatchi] = oldPatchi;
691  }
692  for
693  (
694  label oldPatchi = nextPatchID;
695  oldPatchi < oldPatches.size();
696  oldPatchi++
697  )
698  {
699  globalPatchMap[oldPatchi] = oldPatchi+1;
700  }
701  }
702  else
703  {
704  oldInternalPatchID = wantedPatchID;
705  nextPatchID = wantedPatchID+1;
706 
707  // old to new patches
708  globalPatchMap = identity(oldPatches.size());
709  }
710 
711  labelList boundaryPatchSizes(nbSize, Zero);
712 
713 
714  // Make a global-to-local point map
715  labelList globalPointMap(oldPoints.size(), -1);
716  labelList globalFaceMap(oldFaces.size(), -1);
717 
718  label facei = 0;
719 
720  // 1. Pick up all preserved internal faces.
721  for (label oldFacei = 0; oldFacei < oldNInternalFaces; ++oldFacei)
722  {
723  if (nCellsUsingFace[oldFacei] == 2)
724  {
725  globalFaceMap[oldFacei] = facei;
726  faceMap_[facei++] = oldFacei;
727 
728  // Mark all points from the face
729  markUsed(oldFaces[oldFacei], globalPointMap);
730  }
731  }
732 
733  // These are all the internal faces in the mesh.
734  const label nInternalFaces = facei;
735 
736  // 2. Boundary faces up to where we want to insert old internal faces
737  for
738  (
739  label oldPatchi = 0;
740  oldPatchi < oldPatches.size()
741  && oldPatchi < nextPatchID;
742  oldPatchi++
743  )
744  {
745  const polyPatch& oldPatch = oldPatches[oldPatchi];
746 
747  label oldFacei = oldPatch.start();
748 
749  forAll(oldPatch, i)
750  {
751  if (nCellsUsingFace[oldFacei] == 1)
752  {
753  // Boundary face is kept.
754 
755  // Mark face and increment number of points in set
756  globalFaceMap[oldFacei] = facei;
757  faceMap_[facei++] = oldFacei;
758 
759  // Mark all points from the face
760  markUsed(oldFaces[oldFacei], globalPointMap);
761 
762  // Increment number of patch faces
763  ++boundaryPatchSizes[globalPatchMap[oldPatchi]];
764  }
765  ++oldFacei;
766  }
767  }
768 
769  // 3a. old internal faces that have become exposed.
770  for (label oldFacei = 0; oldFacei < oldNInternalFaces; ++oldFacei)
771  {
772  if (nCellsUsingFace[oldFacei] == 1)
773  {
774  globalFaceMap[oldFacei] = facei;
775  faceMap_[facei++] = oldFacei;
776 
777  // Mark all points from the face
778  markUsed(oldFaces[oldFacei], globalPointMap);
779 
780  // Increment number of patch faces
781  ++boundaryPatchSizes[oldInternalPatchID];
782  }
783  }
784 
785  // 3b. coupled patch faces that have become uncoupled.
786  for
787  (
788  label oldFacei = oldNInternalFaces;
789  oldFacei < oldFaces.size();
790  oldFacei++
791  )
792  {
793  if (nCellsUsingFace[oldFacei] == 3)
794  {
795  globalFaceMap[oldFacei] = facei;
796  faceMap_[facei++] = oldFacei;
797 
798  // Mark all points from the face
799  markUsed(oldFaces[oldFacei], globalPointMap);
800 
801  // Increment number of patch faces
802  ++boundaryPatchSizes[oldInternalPatchID];
803  }
804  }
805 
806  // 4. Remaining boundary faces
807  for
808  (
809  label oldPatchi = nextPatchID;
810  oldPatchi < oldPatches.size();
811  oldPatchi++
812  )
813  {
814  const polyPatch& oldPatch = oldPatches[oldPatchi];
815 
816  label oldFacei = oldPatch.start();
817 
818  forAll(oldPatch, i)
819  {
820  if (nCellsUsingFace[oldFacei] == 1)
821  {
822  // Boundary face is kept.
823 
824  // Mark face and increment number of points in set
825  globalFaceMap[oldFacei] = facei;
826  faceMap_[facei++] = oldFacei;
827 
828  // Mark all points from the face
829  markUsed(oldFaces[oldFacei], globalPointMap);
830 
831  // Increment number of patch faces
832  ++boundaryPatchSizes[globalPatchMap[oldPatchi]];
833  }
834  ++oldFacei;
835  }
836  }
837 
838  if (facei != nFacesInSet)
839  {
841  << "Problem" << abort(FatalError);
842  }
843 
844 
845  // Grab the points map
846  label nPointsInSet = 0;
847 
848  forAll(globalPointMap, pointi)
849  {
850  if (globalPointMap[pointi] != -1)
851  {
852  ++nPointsInSet;
853  }
854  }
855  pointMap_.setSize(nPointsInSet);
856 
857  nPointsInSet = 0;
858 
859  forAll(globalPointMap, pointi)
860  {
861  if (globalPointMap[pointi] != -1)
862  {
863  pointMap_[nPointsInSet] = pointi;
864  globalPointMap[pointi] = nPointsInSet;
865  ++nPointsInSet;
866  }
867  }
868 
869 
870  //Pout<< "Number of points,faces,cells in new mesh : "
871  // << pointMap_.size() << ' '
872  // << faceMap_.size() << ' '
873  // << cellMap_.size() << nl;
874 
875 
876  // Make a new mesh
877 
878  //
879  // Create new points
880  //
881  pointField newPoints(pointUIndList(oldPoints, pointMap_));
882 
883 
884  //
885  // Create new faces
886  //
887 
888  faceList newFaces(faceMap_.size());
889  {
890  auto iter = newFaces.begin();
891  const auto& renumbering = globalPointMap;
892 
893  // Internal faces
894  for (label facei = 0; facei < nInternalFaces; ++facei)
895  {
896  face& newItem = *iter;
897  ++iter;
898 
899  const face& oldItem = oldFaces[faceMap_[facei]];
900 
901  // Copy relabelled
902  newItem.resize(oldItem.size());
903 
904  forAll(oldItem, i)
905  {
906  newItem[i] = renumbering[oldItem[i]];
907  }
908  }
909 
910  // Boundary faces - may need to be flipped
911  for (label facei = nInternalFaces; facei < faceMap_.size(); ++facei)
912  {
913  const label oldFacei = faceMap_[facei];
914 
915  face& newItem = *iter;
916  ++iter;
917 
918  const face oldItem =
919  (
920  (
921  baseMesh().isInternalFace(oldFacei)
922  && selectedCells.test(oldNeighbour[oldFacei])
923  && !selectedCells.test(oldOwner[oldFacei])
924  )
925  // Face flipped to point outwards
926  ? oldFaces[oldFacei].reverseFace()
927  : oldFaces[oldFacei]
928  );
929 
930  // Copy relabelled
931  newItem.resize(oldItem.size());
932 
933  forAll(oldItem, i)
934  {
935  newItem[i] = renumbering[oldItem[i]];
936  }
937  }
938  }
939 
940 
941  //
942  // Create new cells
943  //
944 
945  cellList newCells(cellMap_.size());
946  {
947  auto iter = newCells.begin();
948  const auto& renumbering = globalFaceMap;
949 
950  for (const label oldCelli : cellMap_)
951  {
952  cell& newItem = *iter;
953  ++iter;
954 
955  const labelList& oldItem = oldCells[oldCelli];
956 
957  // Copy relabelled
958  newItem.resize(oldItem.size());
959 
960  forAll(oldItem, i)
961  {
962  newItem[i] = renumbering[oldItem[i]];
963  }
964  }
965  }
966 
967 
968  // Make a new mesh
969  //
970  // Note that mesh gets registered with same name as original mesh.
971  // This is not proper but cannot be avoided since otherwise
972  // surfaceInterpolation cannot find its fvSchemes.
973  // It will try to read, for example. "system/region0SubSet/fvSchemes"
974  //
975  fvMeshSubsetPtr_ = autoPtr<fvMesh>::New
976  (
977  IOobject
978  (
979  baseMesh().name(),
980  baseMesh().time().timeName(),
981  baseMesh().time(),
982  IOobject::NO_READ, // do not read any dictionaries
984  ),
985  baseMesh(), // get dictionaries from base mesh
986  std::move(newPoints),
987  std::move(newFaces),
988  std::move(newCells),
989  syncPar // parallel synchronisation
990  );
991 
992 
993  // Add old patches
994  List<polyPatch*> newBoundary(nbSize);
995  patchMap_.setSize(nbSize);
996  label nNewPatches = 0;
997  label patchStart = nInternalFaces;
998 
999 
1000  // For parallel: only remove patch if none of the processors has it.
1001  // This only gets done for patches before the one being inserted
1002  // (so patches < nextPatchID)
1003 
1004  // Get sum of patch sizes. Zero if patch can be deleted.
1005  labelList globalPatchSizes(boundaryPatchSizes);
1006  globalPatchSizes.setSize(nextPatchID);
1007 
1008  if (syncPar && Pstream::parRun())
1009  {
1010  // Get patch names (up to nextPatchID)
1012  patchNames[Pstream::myProcNo()] = oldPatches.names();
1013  patchNames[Pstream::myProcNo()].setSize(nextPatchID);
1016 
1017  // Get patch sizes (up to nextPatchID).
1018  // Note that up to nextPatchID the globalPatchMap is an identity so
1019  // no need to index through that.
1020  Pstream::listCombineGather(globalPatchSizes, plusEqOp<label>());
1021  Pstream::listCombineScatter(globalPatchSizes);
1022 
1023  // Now all processors have all the patchnames.
1024  // Decide: if all processors have the same patch names and size is zero
1025  // everywhere remove the patch.
1026  bool samePatches = true;
1027 
1028  for (label proci = 1; proci < patchNames.size(); ++proci)
1029  {
1030  if (patchNames[proci] != patchNames[0])
1031  {
1032  samePatches = false;
1033  break;
1034  }
1035  }
1036 
1037  if (!samePatches)
1038  {
1039  // Patchnames not sync on all processors so disable removal of
1040  // zero sized patches.
1041  globalPatchSizes = labelMax;
1042  }
1043  }
1044 
1045 
1046  // Old patches
1047 
1048  for
1049  (
1050  label oldPatchi = 0;
1051  oldPatchi < oldPatches.size()
1052  && oldPatchi < nextPatchID;
1053  oldPatchi++
1054  )
1055  {
1056  const label newSize = boundaryPatchSizes[globalPatchMap[oldPatchi]];
1057 
1058  if (oldInternalPatchID != oldPatchi)
1059  {
1060  // Pure subset of patch faces (no internal faces added to this
1061  // patch). Can use mapping.
1062  labelList map(newSize);
1063  for (label patchFacei = 0; patchFacei < newSize; patchFacei++)
1064  {
1065  const label facei = patchStart+patchFacei;
1066  const label oldFacei = faceMap_[facei];
1067  map[patchFacei] = oldPatches[oldPatchi].whichFace(oldFacei);
1068  }
1069 
1070  newBoundary[nNewPatches] = oldPatches[oldPatchi].clone
1071  (
1072  fvMeshSubsetPtr_().boundaryMesh(),
1073  nNewPatches,
1074  map,
1075  patchStart
1076  ).ptr();
1077  }
1078  else
1079  {
1080  // Clone (even if 0 size)
1081  newBoundary[nNewPatches] = oldPatches[oldPatchi].clone
1082  (
1083  fvMeshSubsetPtr_().boundaryMesh(),
1084  nNewPatches,
1085  newSize,
1086  patchStart
1087  ).ptr();
1088  }
1089 
1090  patchStart += newSize;
1091  patchMap_[nNewPatches] = oldPatchi; // compact patchMap
1092  ++nNewPatches;
1093  }
1094 
1095  // Inserted patch
1096 
1097  if (wantedPatchID == -1)
1098  {
1099  label oldInternalSize = boundaryPatchSizes[oldInternalPatchID];
1100 
1101  if (syncPar)
1102  {
1103  reduce(oldInternalSize, sumOp<label>());
1104  }
1105 
1106  // Newly created patch so is at end. Check if any faces in it.
1107  if (oldInternalSize > 0)
1108  {
1109  newBoundary[nNewPatches] = new emptyPolyPatch
1110  (
1111  exposedPatchName,
1112  boundaryPatchSizes[oldInternalPatchID],
1113  patchStart,
1114  nNewPatches,
1115  fvMeshSubsetPtr_().boundaryMesh(),
1116  emptyPolyPatch::typeName
1117  );
1118 
1119  //Pout<< " " << exposedPatchName << " : "
1120  // << boundaryPatchSizes[oldInternalPatchID] << endl;
1121 
1122  // The index for the first patch is -1 as it originates from
1123  // the internal faces
1124  patchStart += boundaryPatchSizes[oldInternalPatchID];
1125  patchMap_[nNewPatches] = -1;
1126  ++nNewPatches;
1127  }
1128  }
1129 
1130  // Old patches
1131 
1132  for
1133  (
1134  label oldPatchi = nextPatchID;
1135  oldPatchi < oldPatches.size();
1136  oldPatchi++
1137  )
1138  {
1139  const label newSize = boundaryPatchSizes[globalPatchMap[oldPatchi]];
1140 
1141  if (oldInternalPatchID != oldPatchi)
1142  {
1143  // Pure subset of patch faces (no internal faces added to this
1144  // patch). Can use mapping.
1145  labelList map(newSize);
1146  for (label patchFacei = 0; patchFacei < newSize; patchFacei++)
1147  {
1148  const label facei = patchStart+patchFacei;
1149  const label oldFacei = faceMap_[facei];
1150  map[patchFacei] = oldPatches[oldPatchi].whichFace(oldFacei);
1151  }
1152 
1153  newBoundary[nNewPatches] = oldPatches[oldPatchi].clone
1154  (
1155  fvMeshSubsetPtr_().boundaryMesh(),
1156  nNewPatches,
1157  map,
1158  patchStart
1159  ).ptr();
1160  }
1161  else
1162  {
1163  // Patch still exists. Add it
1164  newBoundary[nNewPatches] = oldPatches[oldPatchi].clone
1165  (
1166  fvMeshSubsetPtr_().boundaryMesh(),
1167  nNewPatches,
1168  newSize,
1169  patchStart
1170  ).ptr();
1171  }
1172 
1173  //Pout<< " " << oldPatches[oldPatchi].name() << " : "
1174  // << newSize << endl;
1175 
1176  patchStart += newSize;
1177  patchMap_[nNewPatches] = oldPatchi; // compact patchMap
1178  ++nNewPatches;
1179  }
1180 
1181 
1182  // Reset the patch lists
1183  newBoundary.setSize(nNewPatches);
1184  patchMap_.setSize(nNewPatches);
1185 
1186 
1187  // Add the fvPatches
1188  fvMeshSubsetPtr_().addFvPatches(newBoundary, syncPar);
1189 
1190  // Subset and add any zones
1191  subsetZones();
1192 }
1193 
1194 
1197  const labelUList& selectedCells,
1198  const label patchID,
1199  const bool syncPar
1200 )
1201 {
1202  setCellSubset
1203  (
1204  BitSetOps::create(baseMesh().nCells(), selectedCells),
1205  patchID,
1206  syncPar
1207  );
1208 }
1209 
1210 
1213  const labelHashSet& selectedCells,
1214  const label patchID,
1215  const bool syncPar
1216 )
1217 {
1218  setCellSubset
1219  (
1220  BitSetOps::create(baseMesh().nCells(), selectedCells),
1221  patchID,
1222  syncPar
1223  );
1224 }
1225 
1226 
1229  const label regioni,
1230  const labelUList& regions,
1231  const label patchID,
1232  const bool syncPar
1233 )
1234 {
1235  setCellSubset
1236  (
1237  BitSetOps::create(baseMesh().nCells(), regioni, regions),
1238  patchID,
1239  syncPar
1240  );
1241 }
1242 
1243 
1246  const bitSet& selectedCells,
1247  const bool syncCouples
1248 ) const
1249 {
1250  return
1251  removeCells(baseMesh(), syncCouples)
1252  .getExposedFaces(getCellsToRemove(selectedCells));
1253 }
1254 
1255 
1258  const label regioni,
1259  const labelUList& regions,
1260  const bool syncCouples
1261 ) const
1262 {
1263  return
1264  removeCells(baseMesh(), syncCouples)
1265  .getExposedFaces(getCellsToRemove(regioni, regions));
1266 }
1267 
1268 
1271  const bitSet& selectedCells,
1272  const labelList& exposedFaces,
1273  const labelList& patchIDs,
1274  const bool syncCouples
1275 )
1276 {
1277  removeCellsImpl
1278  (
1279  getCellsToRemove(selectedCells),
1280  exposedFaces,
1281  patchIDs,
1282  syncCouples
1283  );
1284 }
1285 
1286 
1289  const label selectRegion,
1290  const labelList& regions,
1291  const labelList& exposedFaces,
1292  const labelList& patchIDs,
1293  const bool syncCouples
1294 )
1295 {
1296  removeCellsImpl
1297  (
1298  getCellsToRemove(selectRegion, regions),
1299  exposedFaces,
1300  patchIDs,
1301  syncCouples
1302  );
1303 }
1304 
1305 
1306 // ************************************************************************* //
Foam::IOobject::NO_WRITE
Definition: IOobject.H:195
Foam::autoPtr::New
static autoPtr< T > New(Args &&... args)
Construct autoPtr of T with forwarding arguments.
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
BitOps.H
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1069
Foam::BitSetOps::create
bitSet create(const label n, const labelHashSet &locations, const bool on=true)
Create a bitSet with length n with the specified on locations.
Definition: BitOps.C:123
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeTopological.C:94
boolList.H
Foam::labelMax
constexpr label labelMax
Definition: label.H:61
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
Foam::List::resize
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:63
cyclicPolyPatch.H
Foam::fvMeshSubset
Given the original mesh and the list of selected cells, it creates the mesh consisting only of the de...
Definition: fvMeshSubset.H:73
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::removeCells
Given list of cells to remove, insert all the topology changes.
Definition: removeCells.H:63
pointIndList.H
fvMeshSubset.H
Foam::Pstream::scatterList
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
Definition: gatherScatterList.C:215
mapPolyMesh.H
polyTopoChange.H
Foam::primitiveMesh::cells
const cellList & cells() const
Definition: primitiveMeshCells.C:138
Foam::fvMeshSubset::exposedPatchName
static word exposedPatchName
Name for exposed internal faces (default: oldInternalFaces)
Definition: fvMeshSubset.H:161
Foam::fvMeshSubset::setCellSubset
void setCellSubset(const bitSet &selectedCells, const label patchID=-1, const bool syncPar=true)
Define cell subset based on the selectedCells.
Definition: fvMeshSubset.C:558
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:65
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:444
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
removeCells.H
Foam::cellZoneMesh
ZoneMesh< cellZone, polyMesh > cellZoneMesh
A ZoneMesh with the type cellZone.
Definition: cellZoneMeshFwd.H:44
Foam::bitSet::test
bool test(const label pos) const
Test value at specified position, never auto-vivify entries.
Definition: bitSetI.H:520
Foam::HashSet< label, Hash< label > >
Foam::pointZoneMesh
ZoneMesh< pointZone, polyMesh > pointZoneMesh
A ZoneMesh with the type pointZone.
Definition: pointZoneMeshFwd.H:44
Foam::polyBoundaryMesh::names
wordList names() const
Return a list of patch names.
Definition: polyBoundaryMesh.C:555
Foam::sumOp
Definition: ops.H:213
Foam::fvMeshSubset::clear
void clear()
Reset maps and subsetting.
Definition: fvMeshSubset.C:545
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::faceZoneMesh
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with the type faceZone.
Definition: faceZoneMeshFwd.H:44
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:51
Foam::pointUIndList
UIndirectList< point > pointUIndList
A UIndirectList of points.
Definition: pointIndList.H:53
Foam::Field< vector >
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
Foam::polyMesh::cellZones
const cellZoneMesh & cellZones() const noexcept
Return cell zone mesh.
Definition: polyMesh.H:492
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
patchID
label patchID
Definition: boundaryProcessorFaPatchPoints.H:5
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1107
Foam::IOobject::READ_IF_PRESENT
Definition: IOobject.H:187
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:486
patchNames
wordList patchNames(nPatches)
Foam::polyBoundaryMesh::findPatchID
label findPatchID(const word &patchName, const bool allowNotFound=true) const
Find patch index given a name, return -1 if not found.
Definition: polyBoundaryMesh.C:765
timeName
word timeName
Definition: getTimeIndex.H:3
Foam::FatalError
error FatalError
Foam::PtrList::clone
PtrList< T > clone(Args &&... args) const
Make a copy by cloning each of the list elements.
Pstream.H
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:85
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:361
emptyPolyPatch.H
Foam::Pstream::listCombineGather
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
Definition: combineGatherScatter.C:290
Foam::emptyPolyPatch
Empty front and back plane patch. Used for 2-D geometries.
Definition: emptyPolyPatch.H:50
Foam::primitiveMesh::isInternalFace
bool isInternalFace(const label faceIndex) const noexcept
Return true if given face label is internal to the mesh.
Definition: primitiveMeshI.H:103
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1094
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::Pstream::gatherList
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
Definition: gatherScatterList.C:52
Foam::UPstream::commsTypes::nonBlocking
Foam::fvMeshSubset::getExposedFaces
labelList getExposedFaces(const bitSet &selectedCells, const bool syncCouples=true) const
Get labels of exposed faces.
Definition: fvMeshSubset.C:1245
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:463
clear
patchWriters clear()
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::primitiveMesh::nInternalFaces
label nInternalFaces() const noexcept
Number of internal faces.
Definition: primitiveMeshI.H:78
Foam::UPstream::parRun
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:63
Foam::UList< label >
Foam::identity
labelList identity(const label len, label start=0)
Create identity map of the given length with (map[i] == i)
Definition: labelList.C:38
Foam::polyMesh::pointZones
const pointZoneMesh & pointZones() const noexcept
Return point zone mesh.
Definition: polyMesh.H:480
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::boundaryMesh
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface....
Definition: boundaryMesh.H:62
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
Foam::plusEqOp
Definition: ops.H:72
Foam::Pstream::listCombineScatter
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
Definition: combineGatherScatter.C:432
Foam::labelUList
UList< label > labelUList
A UList of labels.
Definition: UList.H:85
Foam::IOobject::NO_READ
Definition: IOobject.H:188
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:54
Foam::bitSet::sortedToc
labelList sortedToc() const
The indices of the on bits as a sorted labelList.
Definition: bitSetI.H:532
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1113
Foam::UPstream::nProcs
static label nProcs(const label communicator=worldComm)
Number of processes in parallel run, and 1 for serial run.
Definition: UPstream.H:445
Foam::removeCells::getExposedFaces
labelList getExposedFaces(const bitSet &removedCell) const
Get labels of faces exposed after cells removal.
Definition: removeCells.C:97