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>())
242  << " cells." << endl;
243 }
244 
245 
246 void Foam::regionToCell::erode
247 (
248  boolList& selectedCell
249 ) const
250 {
251  //Info<< "Entering shrinkRegions:" << count(selectedCell) << endl;
252  //generateField("selectedCell_before", selectedCell)().write();
253 
254  // Now erode and see which regions get disconnected
255  boolList shrunkSelectedCell(selectedCell);
256 
257  for (label iter = 0; iter < nErode_; iter++)
258  {
259  shrinkRegions(shrunkSelectedCell);
260  }
261 
262  //Info<< "After shrinking:" << count(shrunkSelectedCell) << endl;
263  //generateField("shrunkSelectedCell", shrunkSelectedCell)().write();
264 
265 
266  // Determine faces on the edge of shrunkSelectedCell
267  boolList blockedFace(mesh_.nFaces(), false);
268  markRegionFaces(shrunkSelectedCell, blockedFace);
269 
270  // Find disconnected regions
271  regionSplit cellRegion(mesh_, blockedFace);
272 
273  // Determine regions containing insidePoints
274  boolList keepRegion(findRegions(verbose_, cellRegion));
275 
276 
277  // Extract cells in regions that are not to be kept.
278  boolList removeCell(mesh_.nCells(), false);
279  forAll(cellRegion, celli)
280  {
281  if (shrunkSelectedCell[celli] && !keepRegion[cellRegion[celli]])
282  {
283  removeCell[celli] = true;
284  }
285  }
286 
287  //Info<< "removeCell before:" << count(removeCell) << endl;
288  //generateField("removeCell_before", removeCell)().write();
289 
290 
291  // Grow removeCell
292  for (label iter = 0; iter < nErode_; iter++)
293  {
294  // Grow selected cell in regions that are not for keeping
295  boolList boundaryPoint(mesh_.nPoints(), false);
296  forAll(removeCell, celli)
297  {
298  if (removeCell[celli])
299  {
300  const labelList& cPoints = mesh_.cellPoints(celli);
301  forAll(cPoints, i)
302  {
303  boundaryPoint[cPoints[i]] = true;
304  }
305  }
306  }
307  syncTools::syncPointList(mesh_, boundaryPoint, orEqOp<bool>(), false);
308 
309  // Select all cells using these points
310 
311  label nChanged = 0;
312  forAll(boundaryPoint, pointi)
313  {
314  if (boundaryPoint[pointi])
315  {
316  const labelList& pCells = mesh_.pointCells(pointi);
317  forAll(pCells, i)
318  {
319  label celli = pCells[i];
320  if (!removeCell[celli])
321  {
322  removeCell[celli] = true;
323  nChanged++;
324  }
325  }
326  }
327  }
328  }
329 
330  //Info<< "removeCell after:" << count(removeCell) << endl;
331  //generateField("removeCell_after", removeCell)().write();
332 
333 
334  // Unmark removeCell
335  forAll(removeCell, celli)
336  {
337  if (removeCell[celli])
338  {
339  selectedCell[celli] = false;
340  }
341  }
342 }
343 
344 
345 void Foam::regionToCell::combine(topoSet& set, const bool add) const
346 {
347  // Note: wip. Select cells first
348  boolList selectedCell(mesh_.nCells(), true);
349 
350  if (setName_.size() && setName_ != "none")
351  {
352  Info<< " Loading subset " << setName_
353  << " to delimit search region."
354  << endl;
355 
356  cellSet subSet(mesh_, setName_);
357 
358  selectedCell = false;
359  for (const label celli : subSet)
360  {
361  selectedCell[celli] = true;
362  }
363  }
364 
365 
366  unselectOutsideRegions(selectedCell);
367 
368  if (nErode_ > 0)
369  {
370  erode(selectedCell);
371  }
372 
373 
374  forAll(selectedCell, celli)
375  {
376  if (selectedCell[celli])
377  {
378  addOrDelete(set, celli, add);
379  }
380  }
381 }
382 
383 
384 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
385 
387 (
388  const polyMesh& mesh,
389  const word& setName,
390  const pointField& insidePoints,
391  const label nErode
392 )
393 :
394  topoSetCellSource(mesh),
395  setName_(setName),
396  insidePoints_(insidePoints),
397  nErode_(nErode)
398 {}
399 
400 
402 (
403  const polyMesh& mesh,
404  const dictionary& dict
405 )
406 :
408  setName_(dict.getOrDefault<word>("set", "none")),
409  insidePoints_
410  (
411  dict.getCompat<pointField>("insidePoints", {{ "insidePoint", 0 }})
412  ),
413  nErode_(dict.getCheckOrDefault<label>("nErode", 0, labelMinMax::ge(0)))
414 {}
415 
416 
418 (
419  const polyMesh& mesh,
420  Istream& is
421 )
422 :
423  topoSetCellSource(mesh),
424  setName_(checkIs(is)),
425  insidePoints_(checkIs(is)),
426  nErode_(readLabel(checkIs(is)))
427 {}
428 
429 
430 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
431 
433 (
434  const topoSetSource::setAction action,
435  topoSet& set
436 ) const
437 {
438  if (action == topoSetSource::ADD || action == topoSetSource::NEW)
439  {
440  if (verbose_)
441  {
442  Info<< " Adding all cells of connected region "
443  << "containing points "
444  << insidePoints_ << " ..." << endl;
445  }
446 
447  combine(set, true);
448  }
449  else if (action == topoSetSource::SUBTRACT)
450  {
451  if (verbose_)
452  {
453  Info<< " Removing all cells of connected region "
454  << "containing points "
455  << insidePoints_ << " ..." << endl;
456  }
457 
458  combine(set, false);
459  }
460 }
461 
462 
463 // ************************************************************************* //
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:584
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:120
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1110
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:487
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)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:688
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:80
regionToCell(const polyMesh &mesh, const word &setName, const pointField &insidePoints, const label nErode)
Construct from components.
Definition: regionToCell.C:380
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
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
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:1104
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
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
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:73
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:426
nErode
Definition: regionsToCell.H:36
Namespace for OpenFOAM.