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