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_.size() && setName_ != "none")
381  {
382  Info<< " Loading subset " << setName_ << " to delimit search region."
383  << endl;
384  cellSet subSet(mesh_, setName_);
385 
386  selectedCell = false;
387  for (const label celli : static_cast<const labelHashSet&>(subSet))
388  {
389  selectedCell[celli] = true;
390  }
391  }
392 
393 
394  unselectOutsideRegions(selectedCell);
395 
396  if (nErode_ > 0)
397  {
398  erode(selectedCell);
399  }
400 
401 
402  forAll(selectedCell, cellI)
403  {
404  if (selectedCell[cellI])
405  {
406  addOrDelete(set, cellI, add);
407  }
408  }
409 }
410 
411 
412 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
413 
415 (
416  const polyMesh& mesh,
417  const word& setName,
418  const pointField& insidePoints,
419  const label nErode
420 )
421 :
422  topoSetCellSource(mesh),
423  setName_(setName),
424  insidePoints_(insidePoints),
425  nErode_(nErode)
426 {}
427 
428 
430 (
431  const polyMesh& mesh,
432  const dictionary& dict
433 )
434 :
436  setName_(dict.getOrDefault<word>("set", "none")),
437  insidePoints_
438  (
439  dict.found("insidePoints")
440  ? dict.lookup("insidePoints")
441  : dict.lookup("insidePoint")
442  ),
443  nErode_(dict.getOrDefault<label>("nErode", 0))
444 {}
445 
446 
448 (
449  const polyMesh& mesh,
450  Istream& is
451 )
452 :
454  setName_(checkIs(is)),
455  insidePoints_(checkIs(is)),
456  nErode_(readLabel(checkIs(is)))
457 {}
458 
459 
460 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
461 
463 (
464  const topoSetSource::setAction action,
465  topoSet& set
466 ) const
467 {
468  if (action == topoSetSource::ADD || action == topoSetSource::NEW)
469  {
470  if (verbose_)
471  {
472  Info<< " Adding all cells of connected region "
473  << "containing points "
474  << insidePoints_ << " ..." << endl;
475  }
476 
477  combine(set, true);
478  }
479  else if (action == topoSetSource::SUBTRACT)
480  {
481  if (verbose_)
482  {
483  Info<< " Removing all cells of connected region "
484  << "containing points "
485  << insidePoints_ << " ..." << endl;
486  }
487 
488  combine(set, false);
489  }
490 }
491 
492 
493 // ************************************************************************* //
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:598
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1122
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
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:1074
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
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:608
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.
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData)
Swap to obtain neighbour cell values for all boundary faces.
Subtract elements from current set.
vector point
Point is a vector.
Definition: point.H:37
Class with constructor to add usage string to table.
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
Reduce inplace (cf. MPI Allreduce) using specified communication schedule.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
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
nErode
Definition: regionsToCell.H:36
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)