regionToCell.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-2016 OpenFOAM Foundation
9  Copyright (C) 2015-2020 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 "regionToCell.H"
30 #include "regionSplit.H"
31 #include "emptyPolyPatch.H"
32 #include "cellSet.H"
33 #include "syncTools.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40  defineTypeNameAndDebug(regionToCell, 0);
41  addToRunTimeSelectionTable(topoSetSource, regionToCell, word);
42  addToRunTimeSelectionTable(topoSetSource, regionToCell, istream);
43  addToRunTimeSelectionTable(topoSetCellSource, regionToCell, word);
44  addToRunTimeSelectionTable(topoSetCellSource, regionToCell, istream);
45 }
46 
47 
48 Foam::topoSetSource::addToUsageTable Foam::regionToCell::usage_
49 (
50  regionToCell::typeName,
51  "\n Usage: regionToCell subCellSet (pt0 .. ptn) nErode\n\n"
52  " Select all cells in the connected region containing"
53  " points (pt0..ptn).\n"
54 );
55 
56 
57 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
58 
59 void Foam::regionToCell::markRegionFaces
60 (
61  const boolList& selectedCell,
62  boolList& regionFace
63 ) const
64 {
65  // Internal faces
66  const labelList& faceOwner = mesh_.faceOwner();
67  const labelList& faceNeighbour = mesh_.faceNeighbour();
68  forAll(faceNeighbour, facei)
69  {
70  if
71  (
72  selectedCell[faceOwner[facei]]
73  != selectedCell[faceNeighbour[facei]]
74  )
75  {
76  regionFace[facei] = true;
77  }
78  }
79 
80  // Swap neighbour selectedCell state
81  boolList nbrSelected;
82  syncTools::swapBoundaryCellList(mesh_, selectedCell, nbrSelected);
83 
84  // Boundary faces
85  const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
86  forAll(pbm, patchi)
87  {
88  const polyPatch& pp = pbm[patchi];
89  const labelUList& faceCells = pp.faceCells();
90  forAll(faceCells, i)
91  {
92  label facei = pp.start()+i;
93  label bFacei = facei-mesh_.nInternalFaces();
94  if (selectedCell[faceCells[i]] != nbrSelected[bFacei])
95  {
96  regionFace[facei] = true;
97  }
98  }
99  }
100 }
101 
102 
103 Foam::boolList Foam::regionToCell::findRegions
104 (
105  const bool verbose,
106  const regionSplit& cellRegion
107 ) const
108 {
109  boolList keepRegion(cellRegion.nRegions(), false);
110 
111  forAll(insidePoints_, i)
112  {
113  // Find the region containing the insidePoint
114 
115  label celli = mesh_.findCell(insidePoints_[i]);
116 
117  label keepRegionI = -1;
118  label keepProci = -1;
119  if (celli != -1)
120  {
121  keepRegionI = cellRegion[celli];
122  keepProci = Pstream::myProcNo();
123  }
124  reduce(keepRegionI, maxOp<label>());
125  keepRegion[keepRegionI] = true;
126 
127  reduce(keepProci, maxOp<label>());
128 
129  if (keepProci == -1)
130  {
132  << "Did not find " << insidePoints_[i]
133  << " in mesh." << " Mesh bounds are " << mesh_.bounds()
134  << exit(FatalError);
135  }
136 
137  if (verbose)
138  {
139  Info<< " Found location " << insidePoints_[i]
140  << " in cell " << celli << " on processor " << keepProci
141  << " in global region " << keepRegionI
142  << " out of " << cellRegion.nRegions() << " regions." << endl;
143  }
144  }
145 
146  return keepRegion;
147 }
148 
149 
150 void Foam::regionToCell::unselectOutsideRegions
151 (
152  boolList& selectedCell
153 ) const
154 {
155  // Determine faces on the edge of selectedCell
156  boolList blockedFace(mesh_.nFaces(), false);
157  markRegionFaces(selectedCell, blockedFace);
158 
159  // Determine regions
160  regionSplit cellRegion(mesh_, blockedFace);
161 
162  // Determine regions containing insidePoints_
163  boolList keepRegion(findRegions(verbose_, cellRegion));
164 
165  // Go back to bool per cell
166  forAll(cellRegion, celli)
167  {
168  if (!keepRegion[cellRegion[celli]])
169  {
170  selectedCell[celli] = false;
171  }
172  }
173 }
174 
175 
176 void Foam::regionToCell::shrinkRegions
177 (
178  boolList& selectedCell
179 ) const
180 {
181  // Select points on unselected cells and boundary
182  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
183 
184  boolList boundaryPoint(mesh_.nPoints(), false);
185 
186  const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
187 
188  forAll(pbm, patchi)
189  {
190  const polyPatch& pp = pbm[patchi];
191 
192  if (!pp.coupled() && !isA<emptyPolyPatch>(pp))
193  {
194  forAll(pp, i)
195  {
196  const face& f = pp[i];
197  forAll(f, fp)
198  {
199  boundaryPoint[f[fp]] = true;
200  }
201  }
202  }
203  }
204 
205  forAll(selectedCell, celli)
206  {
207  if (!selectedCell[celli])
208  {
209  const labelList& cPoints = mesh_.cellPoints(celli);
210  forAll(cPoints, i)
211  {
212  boundaryPoint[cPoints[i]] = true;
213  }
214  }
215  }
216 
217  syncTools::syncPointList(mesh_, boundaryPoint, orEqOp<bool>(), false);
218 
219 
220  // Select all cells using these points
221  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
222 
223  label nChanged = 0;
224  forAll(boundaryPoint, pointi)
225  {
226  if (boundaryPoint[pointi])
227  {
228  const labelList& pCells = mesh_.pointCells(pointi);
229  forAll(pCells, i)
230  {
231  label celli = pCells[i];
232  if (selectedCell[celli])
233  {
234  selectedCell[celli] = false;
235  ++nChanged;
236  }
237  }
238  }
239  }
240  Info<< " Eroded "
241  << returnReduce(nChanged, sumOp<label>()) << " cells." << endl;
242 }
243 
244 
245 void Foam::regionToCell::erode
246 (
247  boolList& selectedCell
248 ) const
249 {
250  //Info<< "Entering shrinkRegions:" << count(selectedCell) << endl;
251  //generateField("selectedCell_before", selectedCell)().write();
252 
253  // Now erode and see which regions get disconnected
254  boolList shrunkSelectedCell(selectedCell);
255 
256  for (label iter = 0; iter < nErode_; iter++)
257  {
258  shrinkRegions(shrunkSelectedCell);
259  }
260 
261  //Info<< "After shrinking:" << count(shrunkSelectedCell) << endl;
262  //generateField("shrunkSelectedCell", shrunkSelectedCell)().write();
263 
264 
265  // Determine faces on the edge of shrunkSelectedCell
266  boolList blockedFace(mesh_.nFaces(), false);
267  markRegionFaces(shrunkSelectedCell, blockedFace);
268 
269  // Find disconnected regions
270  regionSplit cellRegion(mesh_, blockedFace);
271 
272  // Determine regions containing insidePoints
273  boolList keepRegion(findRegions(verbose_, cellRegion));
274 
275 
276  // Extract cells in regions that are not to be kept.
277  boolList removeCell(mesh_.nCells(), false);
278  forAll(cellRegion, celli)
279  {
280  if (shrunkSelectedCell[celli] && !keepRegion[cellRegion[celli]])
281  {
282  removeCell[celli] = true;
283  }
284  }
285 
286  //Info<< "removeCell before:" << count(removeCell) << endl;
287  //generateField("removeCell_before", removeCell)().write();
288 
289 
290  // Grow removeCell
291  for (label iter = 0; iter < nErode_; iter++)
292  {
293  // Grow selected cell in regions that are not for keeping
294  boolList boundaryPoint(mesh_.nPoints(), false);
295  forAll(removeCell, celli)
296  {
297  if (removeCell[celli])
298  {
299  const labelList& cPoints = mesh_.cellPoints(celli);
300  forAll(cPoints, i)
301  {
302  boundaryPoint[cPoints[i]] = true;
303  }
304  }
305  }
306  syncTools::syncPointList(mesh_, boundaryPoint, orEqOp<bool>(), false);
307 
308  // Select all cells using these points
309 
310  // label nChanged = 0;
311  forAll(boundaryPoint, pointi)
312  {
313  if (boundaryPoint[pointi])
314  {
315  const labelList& pCells = mesh_.pointCells(pointi);
316  forAll(pCells, i)
317  {
318  label celli = pCells[i];
319  if (!removeCell[celli])
320  {
321  removeCell[celli] = true;
322  // ++nChanged;
323  }
324  }
325  }
326  }
327  }
328 
329  //Info<< "removeCell after:" << count(removeCell) << endl;
330  //generateField("removeCell_after", removeCell)().write();
331 
332 
333  // Unmark removeCell
334  forAll(removeCell, celli)
335  {
336  if (removeCell[celli])
337  {
338  selectedCell[celli] = false;
339  }
340  }
341 }
342 
343 
344 void Foam::regionToCell::combine(topoSet& set, const bool add) const
345 {
346  // Note: wip. Select cells first
347  boolList selectedCell(mesh_.nCells(), true);
348 
349  if (setName_.size() && setName_ != "none")
350  {
351  Info<< " Loading subset " << setName_
352  << " to delimit search region."
353  << endl;
354 
355  cellSet subSet(mesh_, setName_);
356 
357  selectedCell = false;
358  for (const label celli : subSet)
359  {
360  selectedCell[celli] = true;
361  }
362  }
363 
364 
365  unselectOutsideRegions(selectedCell);
366 
367  if (nErode_ > 0)
368  {
369  erode(selectedCell);
370  }
371 
372 
373  forAll(selectedCell, celli)
374  {
375  if (selectedCell[celli])
376  {
377  addOrDelete(set, celli, add);
378  }
379  }
380 }
381 
382 
383 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
384 
386 (
387  const polyMesh& mesh,
388  const word& setName,
389  const pointField& insidePoints,
390  const label nErode
391 )
392 :
393  topoSetCellSource(mesh),
394  setName_(setName),
395  insidePoints_(insidePoints),
396  nErode_(nErode)
397 {}
398 
399 
401 (
402  const polyMesh& mesh,
403  const dictionary& dict
404 )
405 :
407  setName_(dict.getOrDefault<word>("set", "none")),
408  insidePoints_
409  (
410  dict.getCompat<pointField>("insidePoints", {{ "insidePoint", 0 }})
411  ),
412  nErode_(dict.getCheckOrDefault<label>("nErode", 0, labelMinMax::ge(0)))
413 {}
414 
415 
417 (
418  const polyMesh& mesh,
419  Istream& is
420 )
421 :
422  topoSetCellSource(mesh),
423  setName_(checkIs(is)),
424  insidePoints_(checkIs(is)),
425  nErode_(readLabel(checkIs(is)))
426 {}
427 
428 
429 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
430 
432 (
433  const topoSetSource::setAction action,
434  topoSet& set
435 ) const
436 {
437  if (action == topoSetSource::ADD || action == topoSetSource::NEW)
438  {
439  if (verbose_)
440  {
441  Info<< " Adding all cells of connected region "
442  << "containing points "
443  << insidePoints_ << " ..." << endl;
444  }
445 
446  combine(set, true);
447  }
448  else if (action == topoSetSource::SUBTRACT)
449  {
450  if (verbose_)
451  {
452  Info<< " Removing all cells of connected region "
453  << "containing points "
454  << insidePoints_ << " ..." << endl;
455  }
456 
457  combine(set, false);
458  }
459 }
460 
461 
462 // ************************************************************************* //
const polyBoundaryMesh & pbm
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.
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...
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
regionToCell(const polyMesh &mesh, const word &setName, const pointField &insidePoints, const label nErode)
Construct from components.
Definition: regionToCell.C:379
#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
static MinMax< T > ge(const T &minVal)
A semi-infinite range from minVal to the type max.
Definition: MinMaxI.H:24
T getCheckOrDefault(const word &keyword, const T &deflt, const Predicate &pred, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
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
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.
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
virtual void applyToSet(const topoSetSource::setAction action, topoSet &set) const
Apply specified action to the topoSet.
Definition: regionToCell.C:425
nErode
Definition: regionsToCell.H:36
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)