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 }
40 
41 
42 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
43 
44 void Foam::regionToCell::markRegionFaces
45 (
46  const boolList& selectedCell,
47  boolList& regionFace
48 ) const
49 {
50  // Internal faces
51  const labelList& faceOwner = mesh_.faceOwner();
52  const labelList& faceNeighbour = mesh_.faceNeighbour();
53  forAll(faceNeighbour, facei)
54  {
55  if
56  (
57  selectedCell[faceOwner[facei]]
58  != selectedCell[faceNeighbour[facei]]
59  )
60  {
61  regionFace[facei] = true;
62  }
63  }
64 
65  // Swap neighbour selectedCell state
66  boolList nbrSelected;
67  syncTools::swapBoundaryCellList(mesh_, selectedCell, nbrSelected);
68 
69  // Boundary faces
70  const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
71  forAll(pbm, patchi)
72  {
73  const polyPatch& pp = pbm[patchi];
74  const labelUList& faceCells = pp.faceCells();
75  forAll(faceCells, i)
76  {
77  label facei = pp.start()+i;
78  label bFacei = facei-mesh_.nInternalFaces();
79  if (selectedCell[faceCells[i]] != nbrSelected[bFacei])
80  {
81  regionFace[facei] = true;
82  }
83  }
84  }
85 }
86 
87 
88 Foam::boolList Foam::regionToCell::findRegions
89 (
90  const bool verbose,
91  const regionSplit& cellRegion
92 ) const
93 {
94  boolList keepRegion(cellRegion.nRegions(), false);
95 
96  forAll(insidePoints_, i)
97  {
98  // Find the region containing the insidePoint
99 
100  label celli = mesh_.findCell(insidePoints_[i]);
101 
102  label keepRegionI = -1;
103  label keepProci = -1;
104  if (celli != -1)
105  {
106  keepRegionI = cellRegion[celli];
107  keepProci = Pstream::myProcNo();
108  }
109  reduce(keepRegionI, maxOp<label>());
110  keepRegion[keepRegionI] = true;
111 
112  reduce(keepProci, maxOp<label>());
113 
114  if (keepProci == -1)
115  {
117  << "Did not find " << insidePoints_[i]
118  << " in mesh." << " Mesh bounds are " << mesh_.bounds()
119  << exit(FatalError);
120  }
121 
122  if (verbose)
123  {
124  Info<< " Found location " << insidePoints_[i]
125  << " in cell " << celli << " on processor " << keepProci
126  << " in global region " << keepRegionI
127  << " out of " << cellRegion.nRegions() << " regions." << endl;
128  }
129  }
130 
131  return keepRegion;
132 }
133 
134 
135 void Foam::regionToCell::unselectOutsideRegions
136 (
137  boolList& selectedCell
138 ) const
139 {
140  // Determine faces on the edge of selectedCell
141  boolList blockedFace(mesh_.nFaces(), false);
142  markRegionFaces(selectedCell, blockedFace);
143 
144  // Determine regions
145  regionSplit cellRegion(mesh_, blockedFace);
146 
147  // Determine regions containing insidePoints_
148  boolList keepRegion(findRegions(true, cellRegion));
149 
150  // Go back to bool per cell
151  forAll(cellRegion, celli)
152  {
153  if (!keepRegion[cellRegion[celli]])
154  {
155  selectedCell[celli] = false;
156  }
157  }
158 }
159 
160 
161 void Foam::regionToCell::shrinkRegions
162 (
163  boolList& selectedCell
164 ) const
165 {
166  // Select points on unselected cells and boundary
167  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
168 
169  boolList boundaryPoint(mesh_.nPoints(), false);
170 
171  const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
172 
173  forAll(pbm, patchi)
174  {
175  const polyPatch& pp = pbm[patchi];
176 
177  if (!pp.coupled() && !isA<emptyPolyPatch>(pp))
178  {
179  forAll(pp, i)
180  {
181  const face& f = pp[i];
182  forAll(f, fp)
183  {
184  boundaryPoint[f[fp]] = true;
185  }
186  }
187  }
188  }
189 
190  forAll(selectedCell, celli)
191  {
192  if (!selectedCell[celli])
193  {
194  const labelList& cPoints = mesh_.cellPoints(celli);
195  forAll(cPoints, i)
196  {
197  boundaryPoint[cPoints[i]] = true;
198  }
199  }
200  }
201 
202  syncTools::syncPointList(mesh_, boundaryPoint, orEqOp<bool>(), false);
203 
204 
205  // Select all cells using these points
206  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
207 
208  label nChanged = 0;
209  forAll(boundaryPoint, pointi)
210  {
211  if (boundaryPoint[pointi])
212  {
213  const labelList& pCells = mesh_.pointCells(pointi);
214  forAll(pCells, i)
215  {
216  label celli = pCells[i];
217  if (selectedCell[celli])
218  {
219  selectedCell[celli] = false;
220  nChanged++;
221  }
222  }
223  }
224  }
225  Info<< " Eroded " << returnReduce(nChanged, sumOp<label>())
226  << " cells." << endl;
227 }
228 
229 
230 void Foam::regionToCell::erode
231 (
232  boolList& selectedCell
233 ) const
234 {
235  // Info<< "Entering shrinkRegions:" << count(selectedCell) << endl;
236  // generateField("selectedCell_before", selectedCell)().write();
237 
238  // Now erode and see which regions get disconnected
239  boolList shrunkSelectedCell(selectedCell);
240 
241  for (label iter = 0; iter < nErode_; iter++)
242  {
243  shrinkRegions(shrunkSelectedCell);
244  }
245 
246  // Info<< "After shrinking:" << count(shrunkSelectedCell) << endl;
247  // generateField("shrunkSelectedCell", shrunkSelectedCell)().write();
248 
249 
250 
251  // Determine faces on the edge of shrunkSelectedCell
252  boolList blockedFace(mesh_.nFaces(), false);
253  markRegionFaces(shrunkSelectedCell, blockedFace);
254 
255  // Find disconnected regions
256  regionSplit cellRegion(mesh_, blockedFace);
257 
258  // Determine regions containing insidePoints
259  boolList keepRegion(findRegions(true, cellRegion));
260 
261 
262  // Extract cells in regions that are not to be kept.
263  boolList removeCell(mesh_.nCells(), false);
264  forAll(cellRegion, celli)
265  {
266  if (shrunkSelectedCell[celli] && !keepRegion[cellRegion[celli]])
267  {
268  removeCell[celli] = true;
269  }
270  }
271 
272  // Info<< "removeCell before:" << count(removeCell) << endl;
273  // generateField("removeCell_before", removeCell)().write();
274 
275 
276 
277  // Grow removeCell
278  for (label iter = 0; iter < nErode_; iter++)
279  {
280  // Grow selected cell in regions that are not for keeping
281  boolList boundaryPoint(mesh_.nPoints(), false);
282  forAll(removeCell, celli)
283  {
284  if (removeCell[celli])
285  {
286  const labelList& cPoints = mesh_.cellPoints(celli);
287  forAll(cPoints, i)
288  {
289  boundaryPoint[cPoints[i]] = true;
290  }
291  }
292  }
293  syncTools::syncPointList(mesh_, boundaryPoint, orEqOp<bool>(), false);
294 
295  // Select all cells using these points
296 
297  label nChanged = 0;
298  forAll(boundaryPoint, pointi)
299  {
300  if (boundaryPoint[pointi])
301  {
302  const labelList& pCells = mesh_.pointCells(pointi);
303  forAll(pCells, i)
304  {
305  label celli = pCells[i];
306  if (!removeCell[celli])
307  {
308  removeCell[celli] = true;
309  nChanged++;
310  }
311  }
312  }
313  }
314  }
315 
316  // Info<< "removeCell after:" << count(removeCell) << endl;
317  // generateField("removeCell_after", removeCell)().write();
318 
319 
320  // Unmark removeCell
321  forAll(removeCell, celli)
322  {
323  if (removeCell[celli])
324  {
325  selectedCell[celli] = false;
326  }
327  }
328 }
329 
330 
331 void Foam::regionToCell::combine(topoSet& set, const bool add) const
332 {
333  // Note: wip. Select cells first
334  boolList selectedCell(mesh_.nCells(), true);
335 
336  if (setName_.size() && setName_ != "none")
337  {
338  Info<< " Loading subset " << setName_ << " to delimit search region."
339  << endl;
340  cellSet subSet(mesh_, setName_);
341 
342  selectedCell = false;
343  forAllConstIter(cellSet, subSet, iter)
344  {
345  selectedCell[iter.key()] = true;
346  }
347  }
348 
349 
350  unselectOutsideRegions(selectedCell);
351 
352  if (nErode_ > 0)
353  {
354  erode(selectedCell);
355  }
356 
357 
358  forAll(selectedCell, celli)
359  {
360  if (selectedCell[celli])
361  {
362  addOrDelete(set, celli, add);
363  }
364  }
365 }
366 
367 
368 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
369 
371 (
372  const polyMesh& mesh,
373  const word& setName,
374  const pointField& insidePoints,
375  const label nErode
376 )
377 :
378  topoSetSource(mesh),
379  setName_(setName),
380  insidePoints_(insidePoints),
381  nErode_(nErode)
382 {}
383 
384 
386 (
387  const polyMesh& mesh,
388  const dictionary& dict
389 )
390 :
391  topoSetSource(mesh),
392  setName_(dict.lookupOrDefault<word>("set", "none")),
393  insidePoints_
394  (
395  dict.found("insidePoint")
396  ? pointField(1, dict.lookup<point>("insidePoint"))
397  : dict.lookup("insidePoints")
398  ),
399  nErode_(dict.lookupOrDefault("nErode", 0))
400 {}
401 
402 
403 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
404 
406 {}
407 
408 
409 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
410 
412 (
413  const topoSetSource::setAction action,
414  topoSet& set
415 ) const
416 {
417  if ((action == topoSetSource::NEW) || (action == topoSetSource::ADD))
418  {
419  Info<< " Adding all cells of connected region containing points "
420  << insidePoints_ << " ..." << endl;
421 
422  combine(set, true);
423  }
424  else if (action == topoSetSource::DELETE)
425  {
426  Info<< " Removing all cells of connected region containing points "
427  << insidePoints_ << " ..." << endl;
428 
429  combine(set, false);
430  }
431 }
432 
433 
434 // ************************************************************************* //
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:663
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
FvWallInfoData< WallInfo, label > label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
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:306
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
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
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:412
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
virtual ~regionToCell()
Destructor.
Definition: regionToCell.C:405
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:371
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
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,.
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:76
Namespace for OpenFOAM.
treeBoundBox combine(const treeBoundBox &a, const treeBoundBox &b)
Definition: patchToPatch.C:77
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:864