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-2023 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 {
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  forAll(boundaryPoint, pointi)
298  {
299  if (boundaryPoint[pointi])
300  {
301  const labelList& pCells = mesh_.pointCells(pointi);
302  forAll(pCells, i)
303  {
304  label celli = pCells[i];
305  if (!removeCell[celli])
306  {
307  removeCell[celli] = true;
308  }
309  }
310  }
311  }
312  }
313 
314  // Info<< "removeCell after:" << count(removeCell) << endl;
315  // generateField("removeCell_after", removeCell)().write();
316 
317 
318  // Unmark removeCell
319  forAll(removeCell, celli)
320  {
321  if (removeCell[celli])
322  {
323  selectedCell[celli] = false;
324  }
325  }
326 }
327 
328 
329 void Foam::regionToCell::combine(topoSet& set, const bool add) const
330 {
331  // Note: wip. Select cells first
332  boolList selectedCell(mesh_.nCells(), true);
333 
334  if (setName_.size() && setName_ != "none")
335  {
336  Info<< " Loading subset " << setName_ << " to delimit search region."
337  << endl;
338  cellSet subSet(mesh_, setName_);
339 
340  selectedCell = false;
341  forAllConstIter(cellSet, subSet, iter)
342  {
343  selectedCell[iter.key()] = true;
344  }
345  }
346 
347 
348  unselectOutsideRegions(selectedCell);
349 
350  if (nErode_ > 0)
351  {
352  erode(selectedCell);
353  }
354 
355 
356  forAll(selectedCell, celli)
357  {
358  if (selectedCell[celli])
359  {
360  addOrDelete(set, celli, add);
361  }
362  }
363 }
364 
365 
366 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
367 
369 (
370  const polyMesh& mesh,
371  const word& setName,
372  const pointField& insidePoints,
373  const label nErode
374 )
375 :
376  topoSetSource(mesh),
377  setName_(setName),
378  insidePoints_(insidePoints),
379  nErode_(nErode)
380 {}
381 
382 
384 (
385  const polyMesh& mesh,
386  const dictionary& dict
387 )
388 :
389  topoSetSource(mesh),
390  setName_(dict.lookupOrDefault<word>("set", "none")),
391  insidePoints_
392  (
393  dict.found("insidePoint")
394  ? pointField(1, dict.lookup<point>("insidePoint"))
395  : dict.lookup("insidePoints")
396  ),
397  nErode_(dict.lookupOrDefault("nErode", 0))
398 {}
399 
400 
401 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
402 
404 {}
405 
406 
407 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
408 
410 (
411  const topoSetSource::setAction action,
412  topoSet& set
413 ) const
414 {
415  if ((action == topoSetSource::NEW) || (action == topoSetSource::ADD))
416  {
417  Info<< " Adding all cells of connected region containing points "
418  << insidePoints_ << " ..." << endl;
419 
420  combine(set, true);
421  }
422  else if (action == topoSetSource::DELETE)
423  {
424  Info<< " Removing all cells of connected region containing points "
425  << insidePoints_ << " ..." << endl;
426 
427  combine(set, false);
428  }
429 }
430 
431 
432 // ************************************************************************* //
bool found
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
Macros for easy insertion into run-time selection tables.
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:160
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1387
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:403
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1393
label nInternalFaces() const
TopoSetSource. Select cells belonging to topological connected region (that contains given points)
Definition: regionToCell.H:68
virtual void applyToSet(const topoSetSource::setAction action, topoSet &) const
Definition: regionToCell.C:410
regionToCell(const polyMesh &mesh, const word &setName, const pointField &insidePoints, const label nErode)
Construct from components.
Definition: regionToCell.C:369
virtual ~regionToCell()
Destructor.
Definition: regionToCell.C:403
static void syncPointList(const polyMesh &, List< T > &, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronise values on all mesh points.
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData)
Swap to obtain neighbour cell values for all boundary faces.
Base class of a source for a topoSet.
Definition: topoSetSource.H:64
setAction
Enumeration defining the valid actions.
Definition: topoSetSource.H:83
const polyMesh & mesh_
Definition: topoSetSource.H:99
General set of labels of mesh quantity (points, cells, faces).
Definition: topoSet.H:65
A class for handling words, derived from string.
Definition: word.H:62
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
label patchi
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
List< label > labelList
A List of labels.
Definition: labelList.H:56
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
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
messageStream Info
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
defineTypeNameAndDebug(combustionModel, 0)
error FatalError
treeBoundBox combine(const treeBoundBox &a, const treeBoundBox &b)
Definition: patchToPatch.C:78
UList< label > labelUList
Definition: UList.H:65
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
labelList f(nPoints)
nErode
Definition: regionToCell.H:37
insidePoints((1 2 3))
dictionary dict