regionToCell.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "regionToCell.H"
27 #include "regionSplit.H"
28 #include "emptyPolyPatch.H"
29 #include "cellSet.H"
30 #include "syncTools.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37  defineTypeNameAndDebug(regionToCell, 0);
38  addToRunTimeSelectionTable(topoSetSource, regionToCell, word);
39  addToRunTimeSelectionTable(topoSetSource, regionToCell, istream);
40 }
41 
42 
43 Foam::topoSetSource::addToUsageTable Foam::regionToCell::usage_
44 (
45  regionToCell::typeName,
46  "\n Usage: regionToCell subCellSet (pt0 .. ptn)\n\n"
47  " Select all cells in the connected region containing"
48  " points (pt0..ptn).\n"
49 );
50 
51 
52 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
53 
54 void Foam::regionToCell::markRegionFaces
55 (
56  const boolList& selectedCell,
57  boolList& regionFace
58 ) const
59 {
60  // Internal faces
61  const labelList& faceOwner = mesh_.faceOwner();
62  const labelList& faceNeighbour = mesh_.faceNeighbour();
63  forAll(faceNeighbour, facei)
64  {
65  if
66  (
67  selectedCell[faceOwner[facei]]
68  != selectedCell[faceNeighbour[facei]]
69  )
70  {
71  regionFace[facei] = true;
72  }
73  }
74 
75  // Swap neighbour selectedCell state
76  boolList nbrSelected;
77  syncTools::swapBoundaryCellList(mesh_, selectedCell, nbrSelected);
78 
79  // Boundary faces
80  const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
81  forAll(pbm, patchi)
82  {
83  const polyPatch& pp = pbm[patchi];
84  const labelUList& faceCells = pp.faceCells();
85  forAll(faceCells, i)
86  {
87  label facei = pp.start()+i;
88  label bFacei = facei-mesh_.nInternalFaces();
89  if
90  (
91  selectedCell[faceCells[i]]
92  != selectedCell[nbrSelected[bFacei]]
93  )
94  {
95  regionFace[facei] = true;
96  }
97  }
98  }
99 }
100 
101 
102 Foam::boolList Foam::regionToCell::findRegions
103 (
104  const bool verbose,
105  const regionSplit& cellRegion
106 ) const
107 {
108  boolList keepRegion(cellRegion.nRegions(), false);
109 
110  forAll(insidePoints_, i)
111  {
112  // Find the region containing the insidePoint
113 
114  label celli = mesh_.findCell(insidePoints_[i]);
115 
116  label keepRegionI = -1;
117  label keepProci = -1;
118  if (celli != -1)
119  {
120  keepRegionI = cellRegion[celli];
121  keepProci = Pstream::myProcNo();
122  }
123  reduce(keepRegionI, maxOp<label>());
124  keepRegion[keepRegionI] = true;
125 
126  reduce(keepProci, maxOp<label>());
127 
128  if (keepProci == -1)
129  {
131  << "Did not find " << insidePoints_[i]
132  << " in mesh." << " Mesh bounds are " << mesh_.bounds()
133  << exit(FatalError);
134  }
135 
136  if (verbose)
137  {
138  Info<< " Found location " << insidePoints_[i]
139  << " in cell " << celli << " on processor " << keepProci
140  << " in global region " << keepRegionI
141  << " out of " << cellRegion.nRegions() << " regions." << endl;
142  }
143  }
144 
145  return keepRegion;
146 }
147 
148 
149 void Foam::regionToCell::unselectOutsideRegions
150 (
151  boolList& selectedCell
152 ) const
153 {
154  // Determine faces on the edge of selectedCell
155  boolList blockedFace(mesh_.nFaces(), false);
156  markRegionFaces(selectedCell, blockedFace);
157 
158  // Determine regions
159  regionSplit cellRegion(mesh_, blockedFace);
160 
161  // Determine regions containing insidePoints_
162  boolList keepRegion(findRegions(true, cellRegion));
163 
164  // Go back to bool per cell
165  forAll(cellRegion, celli)
166  {
167  if (!keepRegion[cellRegion[celli]])
168  {
169  selectedCell[celli] = false;
170  }
171  }
172 }
173 
174 
175 void Foam::regionToCell::shrinkRegions
176 (
177  boolList& selectedCell
178 ) const
179 {
180  // Select points on unselected cells and boundary
181  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
182 
183  boolList boundaryPoint(mesh_.nPoints(), false);
184 
185  const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
186 
187  forAll(pbm, patchi)
188  {
189  const polyPatch& pp = pbm[patchi];
190 
191  if (!pp.coupled() && !isA<emptyPolyPatch>(pp))
192  {
193  forAll(pp, i)
194  {
195  const face& f = pp[i];
196  forAll(f, fp)
197  {
198  boundaryPoint[f[fp]] = true;
199  }
200  }
201  }
202  }
203 
204  forAll(selectedCell, celli)
205  {
206  if (!selectedCell[celli])
207  {
208  const labelList& cPoints = mesh_.cellPoints(celli);
209  forAll(cPoints, i)
210  {
211  boundaryPoint[cPoints[i]] = true;
212  }
213  }
214  }
215 
216  syncTools::syncPointList(mesh_, boundaryPoint, orEqOp<bool>(), false);
217 
218 
219  // Select all cells using these points
220  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
221 
222  label nChanged = 0;
223  forAll(boundaryPoint, pointi)
224  {
225  if (boundaryPoint[pointi])
226  {
227  const labelList& pCells = mesh_.pointCells(pointi);
228  forAll(pCells, i)
229  {
230  label celli = pCells[i];
231  if (selectedCell[celli])
232  {
233  selectedCell[celli] = false;
234  nChanged++;
235  }
236  }
237  }
238  }
239  Info<< " Eroded " << returnReduce(nChanged, sumOp<label>())
240  << " cells." << endl;
241 }
242 
243 
244 void Foam::regionToCell::erode
245 (
246  boolList& selectedCell
247 ) const
248 {
249  // Info<< "Entering shrinkRegions:" << count(selectedCell) << endl;
250  // generateField("selectedCell_before", selectedCell)().write();
251 
252  // Now erode and see which regions get disconnected
253  boolList shrunkSelectedCell(selectedCell);
254 
255  for (label iter = 0; iter < nErode_; iter++)
256  {
257  shrinkRegions(shrunkSelectedCell);
258  }
259 
260  // Info<< "After shrinking:" << count(shrunkSelectedCell) << endl;
261  // generateField("shrunkSelectedCell", shrunkSelectedCell)().write();
262 
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(true, 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 
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_ << " to delimit search region."
353  << endl;
354  cellSet subSet(mesh_, setName_);
355 
356  selectedCell = false;
357  forAllConstIter(cellSet, subSet, iter)
358  {
359  selectedCell[iter.key()] = true;
360  }
361  }
362 
363 
364  unselectOutsideRegions(selectedCell);
365 
366  if (nErode_ > 0)
367  {
368  erode(selectedCell);
369  }
370 
371 
372  forAll(selectedCell, celli)
373  {
374  if (selectedCell[celli])
375  {
376  addOrDelete(set, celli, add);
377  }
378  }
379 }
380 
381 
382 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
383 
385 (
386  const polyMesh& mesh,
387  const word& setName,
388  const pointField& insidePoints,
389  const label nErode
390 )
391 :
392  topoSetSource(mesh),
393  setName_(setName),
394  insidePoints_(insidePoints),
395  nErode_(nErode)
396 {}
397 
398 
400 (
401  const polyMesh& mesh,
402  const dictionary& dict
403 )
404 :
405  topoSetSource(mesh),
406  setName_(dict.lookupOrDefault<word>("set", "none")),
407  insidePoints_
408  (
409  dict.found("insidePoints")
410  ? dict.lookup("insidePoints")
411  : dict.lookup("insidePoint")
412  ),
413  nErode_(dict.lookupOrDefault("nErode", 0))
414 {}
415 
416 
418 (
419  const polyMesh& mesh,
420  Istream& is
421 )
422 :
423  topoSetSource(mesh),
424  setName_(checkIs(is)),
425  insidePoints_(checkIs(is)),
426  nErode_(0)
427 {}
428 
429 
430 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
431 
433 {}
434 
435 
436 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
437 
439 (
440  const topoSetSource::setAction action,
441  topoSet& set
442 ) const
443 {
444  if ((action == topoSetSource::NEW) || (action == topoSetSource::ADD))
445  {
446  Info<< " Adding all cells of connected region containing points "
447  << insidePoints_ << " ..." << endl;
448 
449  combine(set, true);
450  }
451  else if (action == topoSetSource::DELETE)
452  {
453  Info<< " Removing all cells of connected region containing points "
454  << insidePoints_ << " ..." << endl;
455 
456  combine(set, false);
457  }
458 }
459 
460 
461 // ************************************************************************* //
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:431
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:60
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:427
virtual void applyToSet(const topoSetSource::setAction action, topoSet &) const
Definition: regionToCell.C:439
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
AccessType combine(const List< T > &, AccessOp aop=accessOp< T >())
Combines sublists into one big list.
Definition: ListListOps.C:34
virtual ~regionToCell()
Destructor.
Definition: regionToCell.C:432
Macros for easy insertion into run-time selection tables.
UList< label > labelUList
Definition: UList.H:64
regionToCell(const polyMesh &mesh, const word &setName, const pointField &insidePoints, const label nErode)
Construct from components.
Definition: regionToCell.C:385
Base class of a source for a topoSet.
Definition: topoSetSource.H:63
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
A class for handling words, derived from string.
Definition: word.H:59
setAction
Enumeration defining the valid actions.
Definition: topoSetSource.H:82
List< label > labelList
A List of labels.
Definition: labelList.H:56
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
General set of labels of mesh quantity (points, cells, faces).
Definition: topoSet.H:61
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData)
Swap to obtain neighbour cell values for all boundary faces.
label patchi
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
Class with constructor to add usage string to table.
static void syncPointList(const polyMesh &, List< T > &, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
messageStream Info
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
Namespace for OpenFOAM.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:576