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-2021 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 (selectedCell[faceCells[i]] != nbrSelected[bFacei])
90  {
91  regionFace[facei] = true;
92  }
93  }
94  }
95 }
96 
97 
98 Foam::boolList Foam::regionToCell::findRegions
99 (
100  const bool verbose,
101  const regionSplit& cellRegion
102 ) const
103 {
104  boolList keepRegion(cellRegion.nRegions(), false);
105 
106  forAll(insidePoints_, i)
107  {
108  // Find the region containing the insidePoint
109 
110  label celli = mesh_.findCell(insidePoints_[i]);
111 
112  label keepRegionI = -1;
113  label keepProci = -1;
114  if (celli != -1)
115  {
116  keepRegionI = cellRegion[celli];
117  keepProci = Pstream::myProcNo();
118  }
119  reduce(keepRegionI, maxOp<label>());
120  keepRegion[keepRegionI] = true;
121 
122  reduce(keepProci, maxOp<label>());
123 
124  if (keepProci == -1)
125  {
127  << "Did not find " << insidePoints_[i]
128  << " in mesh." << " Mesh bounds are " << mesh_.bounds()
129  << exit(FatalError);
130  }
131 
132  if (verbose)
133  {
134  Info<< " Found location " << insidePoints_[i]
135  << " in cell " << celli << " on processor " << keepProci
136  << " in global region " << keepRegionI
137  << " out of " << cellRegion.nRegions() << " regions." << endl;
138  }
139  }
140 
141  return keepRegion;
142 }
143 
144 
145 void Foam::regionToCell::unselectOutsideRegions
146 (
147  boolList& selectedCell
148 ) const
149 {
150  // Determine faces on the edge of selectedCell
151  boolList blockedFace(mesh_.nFaces(), false);
152  markRegionFaces(selectedCell, blockedFace);
153 
154  // Determine regions
155  regionSplit cellRegion(mesh_, blockedFace);
156 
157  // Determine regions containing insidePoints_
158  boolList keepRegion(findRegions(true, cellRegion));
159 
160  // Go back to bool per cell
161  forAll(cellRegion, celli)
162  {
163  if (!keepRegion[cellRegion[celli]])
164  {
165  selectedCell[celli] = false;
166  }
167  }
168 }
169 
170 
171 void Foam::regionToCell::shrinkRegions
172 (
173  boolList& selectedCell
174 ) const
175 {
176  // Select points on unselected cells and boundary
177  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
178 
179  boolList boundaryPoint(mesh_.nPoints(), false);
180 
181  const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
182 
183  forAll(pbm, patchi)
184  {
185  const polyPatch& pp = pbm[patchi];
186 
187  if (!pp.coupled() && !isA<emptyPolyPatch>(pp))
188  {
189  forAll(pp, i)
190  {
191  const face& f = pp[i];
192  forAll(f, fp)
193  {
194  boundaryPoint[f[fp]] = true;
195  }
196  }
197  }
198  }
199 
200  forAll(selectedCell, celli)
201  {
202  if (!selectedCell[celli])
203  {
204  const labelList& cPoints = mesh_.cellPoints(celli);
205  forAll(cPoints, i)
206  {
207  boundaryPoint[cPoints[i]] = true;
208  }
209  }
210  }
211 
212  syncTools::syncPointList(mesh_, boundaryPoint, orEqOp<bool>(), false);
213 
214 
215  // Select all cells using these points
216  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
217 
218  label nChanged = 0;
219  forAll(boundaryPoint, pointi)
220  {
221  if (boundaryPoint[pointi])
222  {
223  const labelList& pCells = mesh_.pointCells(pointi);
224  forAll(pCells, i)
225  {
226  label celli = pCells[i];
227  if (selectedCell[celli])
228  {
229  selectedCell[celli] = false;
230  nChanged++;
231  }
232  }
233  }
234  }
235  Info<< " Eroded " << returnReduce(nChanged, sumOp<label>())
236  << " cells." << endl;
237 }
238 
239 
240 void Foam::regionToCell::erode
241 (
242  boolList& selectedCell
243 ) const
244 {
245  // Info<< "Entering shrinkRegions:" << count(selectedCell) << endl;
246  // generateField("selectedCell_before", selectedCell)().write();
247 
248  // Now erode and see which regions get disconnected
249  boolList shrunkSelectedCell(selectedCell);
250 
251  for (label iter = 0; iter < nErode_; iter++)
252  {
253  shrinkRegions(shrunkSelectedCell);
254  }
255 
256  // Info<< "After shrinking:" << count(shrunkSelectedCell) << endl;
257  // generateField("shrunkSelectedCell", shrunkSelectedCell)().write();
258 
259 
260 
261  // Determine faces on the edge of shrunkSelectedCell
262  boolList blockedFace(mesh_.nFaces(), false);
263  markRegionFaces(shrunkSelectedCell, blockedFace);
264 
265  // Find disconnected regions
266  regionSplit cellRegion(mesh_, blockedFace);
267 
268  // Determine regions containing insidePoints
269  boolList keepRegion(findRegions(true, cellRegion));
270 
271 
272  // Extract cells in regions that are not to be kept.
273  boolList removeCell(mesh_.nCells(), false);
274  forAll(cellRegion, celli)
275  {
276  if (shrunkSelectedCell[celli] && !keepRegion[cellRegion[celli]])
277  {
278  removeCell[celli] = true;
279  }
280  }
281 
282  // Info<< "removeCell before:" << count(removeCell) << endl;
283  // generateField("removeCell_before", removeCell)().write();
284 
285 
286 
287  // Grow removeCell
288  for (label iter = 0; iter < nErode_; iter++)
289  {
290  // Grow selected cell in regions that are not for keeping
291  boolList boundaryPoint(mesh_.nPoints(), false);
292  forAll(removeCell, celli)
293  {
294  if (removeCell[celli])
295  {
296  const labelList& cPoints = mesh_.cellPoints(celli);
297  forAll(cPoints, i)
298  {
299  boundaryPoint[cPoints[i]] = true;
300  }
301  }
302  }
303  syncTools::syncPointList(mesh_, boundaryPoint, orEqOp<bool>(), false);
304 
305  // Select all cells using these points
306 
307  label nChanged = 0;
308  forAll(boundaryPoint, pointi)
309  {
310  if (boundaryPoint[pointi])
311  {
312  const labelList& pCells = mesh_.pointCells(pointi);
313  forAll(pCells, i)
314  {
315  label celli = pCells[i];
316  if (!removeCell[celli])
317  {
318  removeCell[celli] = true;
319  nChanged++;
320  }
321  }
322  }
323  }
324  }
325 
326  // Info<< "removeCell after:" << count(removeCell) << endl;
327  // generateField("removeCell_after", removeCell)().write();
328 
329 
330  // Unmark removeCell
331  forAll(removeCell, celli)
332  {
333  if (removeCell[celli])
334  {
335  selectedCell[celli] = false;
336  }
337  }
338 }
339 
340 
341 void Foam::regionToCell::combine(topoSet& set, const bool add) const
342 {
343  // Note: wip. Select cells first
344  boolList selectedCell(mesh_.nCells(), true);
345 
346  if (setName_.size() && setName_ != "none")
347  {
348  Info<< " Loading subset " << setName_ << " to delimit search region."
349  << endl;
350  cellSet subSet(mesh_, setName_);
351 
352  selectedCell = false;
353  forAllConstIter(cellSet, subSet, iter)
354  {
355  selectedCell[iter.key()] = true;
356  }
357  }
358 
359 
360  unselectOutsideRegions(selectedCell);
361 
362  if (nErode_ > 0)
363  {
364  erode(selectedCell);
365  }
366 
367 
368  forAll(selectedCell, celli)
369  {
370  if (selectedCell[celli])
371  {
372  addOrDelete(set, celli, add);
373  }
374  }
375 }
376 
377 
378 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
379 
381 (
382  const polyMesh& mesh,
383  const word& setName,
384  const pointField& insidePoints,
385  const label nErode
386 )
387 :
388  topoSetSource(mesh),
389  setName_(setName),
390  insidePoints_(insidePoints),
391  nErode_(nErode)
392 {}
393 
394 
396 (
397  const polyMesh& mesh,
398  const dictionary& dict
399 )
400 :
401  topoSetSource(mesh),
402  setName_(dict.lookupOrDefault<word>("set", "none")),
403  insidePoints_
404  (
405  dict.found("insidePoint")
406  ? pointField(1, dict.lookup<point>("insidePoint"))
407  : dict.lookup("insidePoints")
408  ),
409  nErode_(dict.lookupOrDefault("nErode", 0))
410 {}
411 
412 
414 (
415  const polyMesh& mesh,
416  Istream& is
417 )
418 :
419  topoSetSource(mesh),
420  setName_(checkIs(is)),
421  insidePoints_(checkIs(is)),
422  nErode_(0)
423 {}
424 
425 
426 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
427 
429 {}
430 
431 
432 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
433 
435 (
436  const topoSetSource::setAction action,
437  topoSet& set
438 ) const
439 {
440  if ((action == topoSetSource::NEW) || (action == topoSetSource::ADD))
441  {
442  Info<< " Adding all cells of connected region containing points "
443  << insidePoints_ << " ..." << endl;
444 
445  combine(set, true);
446  }
447  else if (action == topoSetSource::DELETE)
448  {
449  Info<< " Removing all cells of connected region containing points "
450  << insidePoints_ << " ..." << endl;
451 
452  combine(set, false);
453  }
454 }
455 
456 
457 // ************************************************************************* //
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:643
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
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:156
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:323
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
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:429
virtual void applyToSet(const topoSetSource::setAction action, topoSet &) const
Definition: regionToCell.C:435
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
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:428
Macros for easy insertion into run-time selection tables.
UList< label > labelUList
Definition: UList.H:65
regionToCell(const polyMesh &mesh, const word &setName, const pointField &insidePoints, const label nErode)
Construct from components.
Definition: regionToCell.C:381
Base class of a source for a topoSet.
Definition: topoSetSource.H:63
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
stressControl lookup("compactNormalStress") >> compactNormalStress
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)
Synchronise 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:844