regionsToCell.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) 2016-2020 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "regionsToCell.H"
29 #include "regionSplit.H"
30 #include "emptyPolyPatch.H"
31 #include "cellSet.H"
32 #include "syncTools.H"
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39  defineTypeNameAndDebug(regionsToCell, 0);
40  addToRunTimeSelectionTable(topoSetSource, regionsToCell, word);
41  addToRunTimeSelectionTable(topoSetSource, regionsToCell, istream);
42  addToRunTimeSelectionTable(topoSetCellSource, regionsToCell, word);
43  addToRunTimeSelectionTable(topoSetCellSource, regionsToCell, istream);
45  (
46  topoSetCellSource,
47  regionsToCell,
48  word,
49  regions
50  );
52  (
53  topoSetCellSource,
54  regionsToCell,
55  istream,
56  regions
57  );
58 }
59 
60 
61 Foam::topoSetSource::addToUsageTable Foam::regionsToCell::usage_
62 (
63  regionsToCell::typeName,
64  "\n Usage: regionsToCell subCellSet (pt0 .. ptn) nErode\n\n"
65  " Select all cells in the connected region containing"
66  " points (pt0..ptn).\n"
67 );
68 
69 
70 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
71 
72 void Foam::regionsToCell::markRegionFaces
73 (
74  const boolList& selectedCell,
75  boolList& regionFace
76 ) const
77 {
78  // Internal faces
79  const labelList& faceOwner = mesh_.faceOwner();
80  const labelList& faceNeighbour = mesh_.faceNeighbour();
81  forAll(faceNeighbour, faceI)
82  {
83  if
84  (
85  selectedCell[faceOwner[faceI]]
86  != selectedCell[faceNeighbour[faceI]]
87  )
88  {
89  regionFace[faceI] = true;
90  }
91  }
92 
93  // Swap neighbour selectedCell state
94  boolList nbrSelected;
95  syncTools::swapBoundaryCellList(mesh_, selectedCell, nbrSelected);
96 
97  // Boundary faces
98  const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
99  forAll(pbm, patchI)
100  {
101  const polyPatch& pp = pbm[patchI];
102  const labelUList& faceCells = pp.faceCells();
103  forAll(faceCells, i)
104  {
105  label faceI = pp.start()+i;
106  label bFaceI = faceI-mesh_.nInternalFaces();
107  if
108  (
109  selectedCell[faceCells[i]]
110  != selectedCell[nbrSelected[bFaceI]]
111  )
112  {
113  regionFace[faceI] = true;
114  }
115  }
116  }
117 }
118 
119 
120 Foam::boolList Foam::regionsToCell::findRegions
121 (
122  const bool verbose,
123  const boolList& selectedCell,
124  const regionSplit& cellRegion
125 ) const
126 {
127  boolList keepRegion(cellRegion.nRegions(), false);
128 
129  for (const point& insidePt : insidePoints_)
130  {
131  // Find the region containing the insidePoint
132 
133  //label cellI = mesh_.findCell(insidePt);
134  label cellI = -1;
135  forAll(selectedCell, index)
136  {
137  if
138  (
139  selectedCell[index]
140  && mesh_.pointInCell(insidePt, index, polyMesh::CELL_TETS)
141  )
142  {
143  cellI = index;
144  break;
145  }
146  }
147 
148  label keepRegionI = -1;
149  label keepProcI = -1;
150  if (cellI != -1)
151  {
152  keepRegionI = cellRegion[cellI];
153  keepProcI = Pstream::myProcNo();
154  }
155  reduce(keepRegionI, maxOp<label>());
156  keepRegion[keepRegionI] = true;
157 
158  reduce(keepProcI, maxOp<label>());
159 
160  if (keepProcI == -1)
161  {
163  << "Did not find " << insidePt
164  << " in mesh." << " Mesh bounds are " << mesh_.bounds()
165  << exit(FatalError);
166  }
167 
168  if (verbose)
169  {
170  Info<< " Found location " << insidePt
171  << " in cell " << cellI << " on processor " << keepProcI
172  << " in global region " << keepRegionI
173  << " out of " << cellRegion.nRegions() << " regions." << endl;
174  }
175  }
176 
177  return keepRegion;
178 }
179 
180 
181 void Foam::regionsToCell::unselectOutsideRegions
182 (
183  boolList& selectedCell
184 ) const
185 {
186  // Determine faces on the edge of selectedCell
187  boolList blockedFace(mesh_.nFaces(), false);
188  markRegionFaces(selectedCell, blockedFace);
189 
190  // Determine regions
191  regionSplit cellRegion(mesh_, blockedFace);
192 
193  // Determine regions containing insidePoints_
194  boolList keepRegion(findRegions(verbose_, selectedCell, cellRegion));
195 
196  // Go back to bool per cell
197  forAll(cellRegion, cellI)
198  {
199  if (!keepRegion[cellRegion[cellI]])
200  {
201  selectedCell[cellI] = false;
202  }
203  }
204 }
205 
206 
207 void Foam::regionsToCell::shrinkRegions
208 (
209  boolList& selectedCell
210 ) const
211 {
212  // Select points on unselected cells and boundary
213  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
214 
215  boolList boundaryPoint(mesh_.nPoints(), false);
216 
217  const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
218 
219  for (const polyPatch& pp : pbm)
220  {
221  if (!pp.coupled() && !isA<emptyPolyPatch>(pp))
222  {
223  forAll(pp, i)
224  {
225  const face& f = pp[i];
226  forAll(f, fp)
227  {
228  boundaryPoint[f[fp]] = true;
229  }
230  }
231  }
232  }
233 
234  forAll(selectedCell, cellI)
235  {
236  if (!selectedCell[cellI])
237  {
238  const labelList& cPoints = mesh_.cellPoints(cellI);
239  forAll(cPoints, i)
240  {
241  boundaryPoint[cPoints[i]] = true;
242  }
243  }
244  }
245 
246  syncTools::syncPointList(mesh_, boundaryPoint, orEqOp<bool>(), false);
247 
248 
249  // Select all cells using these points
250  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
251 
252  label nChanged = 0;
253  forAll(boundaryPoint, pointI)
254  {
255  if (boundaryPoint[pointI])
256  {
257  const labelList& pCells = mesh_.pointCells(pointI);
258  forAll(pCells, i)
259  {
260  label cellI = pCells[i];
261  if (selectedCell[cellI])
262  {
263  selectedCell[cellI] = false;
264  ++nChanged;
265  }
266  }
267  }
268  }
269  Info<< " Eroded "
270  << returnReduce(nChanged, sumOp<label>()) << " cells." << endl;
271 }
272 
273 
274 void Foam::regionsToCell::erode
275 (
276  boolList& selectedCell
277 ) const
278 {
279  //Info<< "Entering shrinkRegions:" << count(selectedCell) << endl;
280  //generateField("selectedCell_before", selectedCell)().write();
281 
282  // Now erode and see which regions get disconnected
283  boolList shrunkSelectedCell(selectedCell);
284 
285  for (label iter = 0; iter < nErode_; iter++)
286  {
287  shrinkRegions(shrunkSelectedCell);
288  }
289 
290  //Info<< "After shrinking:" << count(shrunkSelectedCell) << endl;
291  //generateField("shrunkSelectedCell", shrunkSelectedCell)().write();
292 
293 
294 
295  // Determine faces on the edge of shrunkSelectedCell
296  boolList blockedFace(mesh_.nFaces(), false);
297  markRegionFaces(shrunkSelectedCell, blockedFace);
298 
299  // Find disconnected regions
300  regionSplit cellRegion(mesh_, blockedFace);
301 
302  // Determine regions containing insidePoints
303  boolList keepRegion(findRegions(verbose_, shrunkSelectedCell, cellRegion));
304 
305 
306  // Extract cells in regions that are not to be kept.
307  boolList removeCell(mesh_.nCells(), false);
308  forAll(cellRegion, cellI)
309  {
310  if (shrunkSelectedCell[cellI] && !keepRegion[cellRegion[cellI]])
311  {
312  removeCell[cellI] = true;
313  }
314  }
315 
316  //Info<< "removeCell before:" << count(removeCell) << endl;
317  //generateField("removeCell_before", removeCell)().write();
318 
319 
320 
321  // Grow removeCell
322  for (label iter = 0; iter < nErode_; iter++)
323  {
324  // Grow selected cell in regions that are not for keeping
325  boolList boundaryPoint(mesh_.nPoints(), false);
326  forAll(removeCell, cellI)
327  {
328  if (removeCell[cellI])
329  {
330  const labelList& cPoints = mesh_.cellPoints(cellI);
331  forAll(cPoints, i)
332  {
333  boundaryPoint[cPoints[i]] = true;
334  }
335  }
336  }
337  syncTools::syncPointList(mesh_, boundaryPoint, orEqOp<bool>(), false);
338 
339  // Select all cells using these points
340 
341  // label nChanged = 0;
342  forAll(boundaryPoint, pointI)
343  {
344  if (boundaryPoint[pointI])
345  {
346  const labelList& pCells = mesh_.pointCells(pointI);
347  forAll(pCells, i)
348  {
349  label cellI = pCells[i];
350  if (!removeCell[cellI])
351  {
352  removeCell[cellI] = true;
353  // ++nChanged;
354  }
355  }
356  }
357  }
358  }
359 
360  //Info<< "removeCell after:" << count(removeCell) << endl;
361  //generateField("removeCell_after", removeCell)().write();
362 
363 
364  // Unmark removeCell
365  forAll(removeCell, cellI)
366  {
367  if (removeCell[cellI])
368  {
369  selectedCell[cellI] = false;
370  }
371  }
372 }
373 
374 
375 void Foam::regionsToCell::combine(topoSet& set, const bool add) const
376 {
377  // Note: wip. Select cells first
378  boolList selectedCell(mesh_.nCells(), true);
379 
380  if (!setName_.empty() && setName_ != "none")
381  {
382  Info<< " Loading subset " << setName_
383  << " to delimit search region." << nl;
384 
385  cellSet loadedSet(mesh_, setName_, IOobject::NO_REGISTER);
386  const labelHashSet& cellLabels = loadedSet;
387 
388  selectedCell = false;
389  for (const label celli : cellLabels)
390  {
391  selectedCell[celli] = true;
392  }
393  }
394 
395 
396  unselectOutsideRegions(selectedCell);
397 
398  if (nErode_ > 0)
399  {
400  erode(selectedCell);
401  }
402 
403 
404  forAll(selectedCell, cellI)
405  {
406  if (selectedCell[cellI])
407  {
408  addOrDelete(set, cellI, add);
409  }
410  }
411 }
412 
413 
414 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
415 
417 (
418  const polyMesh& mesh,
419  const word& setName,
420  const pointField& insidePoints,
421  const label nErode
422 )
423 :
424  topoSetCellSource(mesh),
425  setName_(setName),
426  insidePoints_(insidePoints),
427  nErode_(nErode)
428 {}
429 
430 
432 (
433  const polyMesh& mesh,
434  const dictionary& dict
435 )
436 :
438  setName_(dict.getOrDefault<word>("set", "none")),
439  insidePoints_
440  (
441  dict.found("insidePoints")
442  ? dict.lookup("insidePoints")
443  : dict.lookup("insidePoint")
444  ),
445  nErode_(dict.getOrDefault<label>("nErode", 0))
446 {}
447 
448 
450 (
451  const polyMesh& mesh,
452  Istream& is
453 )
454 :
456  setName_(checkIs(is)),
457  insidePoints_(checkIs(is)),
458  nErode_(readLabel(checkIs(is)))
459 {}
460 
461 
462 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
463 
465 (
466  const topoSetSource::setAction action,
467  topoSet& set
468 ) const
469 {
470  if (action == topoSetSource::ADD || action == topoSetSource::NEW)
471  {
472  if (verbose_)
473  {
474  Info<< " Adding all cells of connected region "
475  << "containing points "
476  << insidePoints_ << " ..." << endl;
477  }
478 
479  combine(set, true);
480  }
481  else if (action == topoSetSource::SUBTRACT)
482  {
483  if (verbose_)
484  {
485  Info<< " Removing all cells of connected region "
486  << "containing points "
487  << insidePoints_ << " ..." << endl;
488  }
489 
490  combine(set, false);
491  }
492 }
493 
494 
495 // ************************************************************************* //
const polyBoundaryMesh & pbm
virtual void applyToSet(const topoSetSource::setAction action, topoSet &set) const
Apply specified action to the topoSet.
dictionary dict
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:608
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1122
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData, const bool parRun=UPstream::parRun())
Extract and swap to obtain neighbour cell values for all boundary faces.
Create a new set and ADD elements to it.
Add elements to current set.
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:63
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1086
The topoSetCellSource is a intermediate class for handling topoSet sources for selecting cells...
Lookup type of boundary radiation properties.
Definition: lookup.H:57
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
Macros for easy insertion into run-time selection tables.
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
addNamedToRunTimeSelectionTable(topoSetCellSource, badQualityToCell, word, badQuality)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
AccessType combine(const UList< T > &lists, AccessOp aop=accessOp< T >())
Combines sub-lists into a single list.
Definition: ListListOps.C:62
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
dynamicFvMesh & mesh
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:609
A class for handling words, derived from Foam::string.
Definition: word.H:63
setAction
Enumeration defining various actions.
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1116
label nInternalFaces() const noexcept
Number of internal faces.
static void syncPointList(const polyMesh &mesh, List< T > &pointValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
const polyMesh & mesh_
Reference to the mesh.
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
General set of labels of mesh quantity (points, cells, faces).
Definition: topoSet.H:59
regionsToCell(const polyMesh &mesh, const word &setName, const pointField &insidePoints, const label nErode)
Construct from components.
Subtract elements from current set.
vector point
Point is a vector.
Definition: point.H:37
Class with constructor to add usage string to table.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:75
List< label > labelList
A List of labels.
Definition: List.H:62
insidePoints((1 2 3))
List< bool > boolList
A List of bools.
Definition: List.H:60
bool found
Do not request registration (bool: false)
void reduce(T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce) using linear/tree communication schedule.
nErode
Definition: regionsToCell.H:36
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)