regionToCell.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2015-2024 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "regionToCell.H"
30 #include "regionSplit.H"
31 #include "emptyPolyPatch.H"
32 #include "cellSet.H"
33 #include "syncTools.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40  defineTypeNameAndDebug(regionToCell, 0);
41  addToRunTimeSelectionTable(topoSetSource, regionToCell, word);
42  addToRunTimeSelectionTable(topoSetSource, regionToCell, istream);
43  addToRunTimeSelectionTable(topoSetCellSource, regionToCell, word);
44  addToRunTimeSelectionTable(topoSetCellSource, regionToCell, istream);
45 }
46 
47 
48 Foam::topoSetSource::addToUsageTable Foam::regionToCell::usage_
49 (
50  regionToCell::typeName,
51  "\n Usage: regionToCell subCellSet (pt0 .. ptn) nErode\n\n"
52  " Select all cells in the connected region containing"
53  " points (pt0..ptn).\n"
54 );
55 
56 
57 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
58 
59 void Foam::regionToCell::markRegionFaces
60 (
61  const boolList& selectedCell,
62  boolList& regionFace
63 ) const
64 {
65  // Internal faces
66  const labelList& faceOwner = mesh_.faceOwner();
67  const labelList& faceNeighbour = mesh_.faceNeighbour();
68  forAll(faceNeighbour, facei)
69  {
70  if
71  (
72  selectedCell[faceOwner[facei]]
73  != selectedCell[faceNeighbour[facei]]
74  )
75  {
76  regionFace[facei] = true;
77  }
78  }
79 
80  // Swap neighbour selectedCell state
81  boolList nbrSelected;
82  syncTools::swapBoundaryCellList(mesh_, selectedCell, nbrSelected);
83 
84  // Boundary faces
85  const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
86  forAll(pbm, patchi)
87  {
88  const polyPatch& pp = pbm[patchi];
89  const labelUList& faceCells = pp.faceCells();
90  forAll(faceCells, i)
91  {
92  label facei = pp.start()+i;
93  label bFacei = facei-mesh_.nInternalFaces();
94  if (selectedCell[faceCells[i]] != nbrSelected[bFacei])
95  {
96  regionFace[facei] = true;
97  }
98  }
99  }
100 }
101 
102 
103 Foam::boolList Foam::regionToCell::findRegions
104 (
105  const bool verbose,
106  const regionSplit& cellRegion
107 ) const
108 {
109  boolList keepRegion(cellRegion.nRegions(), false);
110 
111  forAll(insidePoints_, i)
112  {
113  // Find the region containing the insidePoint
114 
115  label celli = mesh_.findCell(insidePoints_[i]);
116 
117  label keepRegionI = -1;
118  label keepProci = -1;
119  if (celli != -1)
120  {
121  keepRegionI = cellRegion[celli];
122  keepProci = Pstream::myProcNo();
123  }
124  reduce(keepRegionI, maxOp<label>());
125  keepRegion[keepRegionI] = true;
126 
127  reduce(keepProci, maxOp<label>());
128 
129  if (keepProci == -1)
130  {
132  << "Did not find " << insidePoints_[i]
133  << " in mesh." << " Mesh bounds are " << mesh_.bounds()
134  << exit(FatalError);
135  }
136 
137  if (verbose)
138  {
139  Info<< " Found location " << insidePoints_[i]
140  << " in cell " << celli << " on processor " << keepProci
141  << " in global region " << keepRegionI
142  << " out of " << cellRegion.nRegions() << " regions." << endl;
143  }
144  }
145 
146  return keepRegion;
147 }
148 
149 
150 void Foam::regionToCell::unselectOutsideRegions
151 (
152  boolList& selectedCell
153 ) const
154 {
155  // Determine faces on the edge of selectedCell
156  boolList blockedFace(mesh_.nFaces(), false);
157  markRegionFaces(selectedCell, blockedFace);
158 
159  // Determine regions
160  regionSplit cellRegion(mesh_, blockedFace);
161 
162  // Determine regions containing insidePoints_
163  boolList keepRegion(findRegions(verbose_, cellRegion));
164 
165  // Go back to bool per cell
166  forAll(cellRegion, celli)
167  {
168  if (!keepRegion[cellRegion[celli]])
169  {
170  selectedCell[celli] = false;
171  }
172  }
173 }
174 
175 
176 void Foam::regionToCell::shrinkRegions
177 (
178  boolList& selectedCell
179 ) const
180 {
181  // Select points on unselected cells and boundary
182  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
183 
184  boolList boundaryPoint(mesh_.nPoints(), false);
185 
186  const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
187 
188  forAll(pbm, patchi)
189  {
190  const polyPatch& pp = pbm[patchi];
191 
192  if (!pp.coupled() && !isA<emptyPolyPatch>(pp))
193  {
194  forAll(pp, i)
195  {
196  const face& f = pp[i];
197  forAll(f, fp)
198  {
199  boundaryPoint[f[fp]] = true;
200  }
201  }
202  }
203  }
204 
205  forAll(selectedCell, celli)
206  {
207  if (!selectedCell[celli])
208  {
209  const labelList& cPoints = mesh_.cellPoints(celli);
210  forAll(cPoints, i)
211  {
212  boundaryPoint[cPoints[i]] = true;
213  }
214  }
215  }
216 
217  syncTools::syncPointList(mesh_, boundaryPoint, orEqOp<bool>(), false);
218 
219 
220  // Select all cells using these points
221  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
222 
223  label nChanged = 0;
224  forAll(boundaryPoint, pointi)
225  {
226  if (boundaryPoint[pointi])
227  {
228  const labelList& pCells = mesh_.pointCells(pointi);
229  forAll(pCells, i)
230  {
231  label celli = pCells[i];
232  if (selectedCell[celli])
233  {
234  selectedCell[celli] = false;
235  ++nChanged;
236  }
237  }
238  }
239  }
240  Info<< " Eroded "
241  << returnReduce(nChanged, sumOp<label>()) << " cells." << endl;
242 }
243 
244 
245 void Foam::regionToCell::erode
246 (
247  boolList& selectedCell
248 ) const
249 {
250  //Info<< "Entering shrinkRegions:" << count(selectedCell) << endl;
251  //generateField("selectedCell_before", selectedCell)().write();
252 
253  // Now erode and see which regions get disconnected
254  boolList shrunkSelectedCell(selectedCell);
255 
256  for (label iter = 0; iter < nErode_; iter++)
257  {
258  shrinkRegions(shrunkSelectedCell);
259  }
260 
261  //Info<< "After shrinking:" << count(shrunkSelectedCell) << endl;
262  //generateField("shrunkSelectedCell", shrunkSelectedCell)().write();
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(verbose_, 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  // Grow removeCell
291  for (label iter = 0; iter < nErode_; iter++)
292  {
293  // Grow selected cell in regions that are not for keeping
294  boolList boundaryPoint(mesh_.nPoints(), false);
295  forAll(removeCell, celli)
296  {
297  if (removeCell[celli])
298  {
299  const labelList& cPoints = mesh_.cellPoints(celli);
300  forAll(cPoints, i)
301  {
302  boundaryPoint[cPoints[i]] = true;
303  }
304  }
305  }
306  syncTools::syncPointList(mesh_, boundaryPoint, orEqOp<bool>(), false);
307 
308  // Select all cells using these points
309 
310  // label nChanged = 0;
311  forAll(boundaryPoint, pointi)
312  {
313  if (boundaryPoint[pointi])
314  {
315  const labelList& pCells = mesh_.pointCells(pointi);
316  forAll(pCells, i)
317  {
318  label celli = pCells[i];
319  if (!removeCell[celli])
320  {
321  removeCell[celli] = true;
322  // ++nChanged;
323  }
324  }
325  }
326  }
327  }
328 
329  //Info<< "removeCell after:" << count(removeCell) << endl;
330  //generateField("removeCell_after", removeCell)().write();
331 
332 
333  // Unmark removeCell
334  forAll(removeCell, celli)
335  {
336  if (removeCell[celli])
337  {
338  selectedCell[celli] = false;
339  }
340  }
341 }
342 
343 
344 void Foam::regionToCell::combine(topoSet& set, const bool add) const
345 {
346  // Note: wip. Select cells first
347  boolList selectedCell(mesh_.nCells(), true);
348 
349  if (!setName_.empty() && setName_ != "none")
350  {
351  if (isZone_)
352  {
353  Info<< " Using cellZone " << setName_
354  << " to delimit search region." << nl;
355 
356  selectedCell = false;
357  for (const label celli : mesh_.cellZones()[setName_])
358  {
359  selectedCell[celli] = true;
360  }
361  }
362  else
363  {
364  Info<< " Loading cellSet " << setName_
365  << " to delimit search region." << nl;
366 
367  cellSet subSet(mesh_, setName_, IOobject::NO_REGISTER);
368 
369  selectedCell = false;
370  for (const label celli : subSet)
371  {
372  selectedCell[celli] = true;
373  }
374  }
375  }
376 
377 
378  unselectOutsideRegions(selectedCell);
379 
380  if (nErode_ > 0)
381  {
382  erode(selectedCell);
383  }
384 
385 
386  forAll(selectedCell, celli)
387  {
388  if (selectedCell[celli])
389  {
390  addOrDelete(set, celli, add);
391  }
392  }
393 }
394 
395 
396 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
397 
399 (
400  const polyMesh& mesh,
401  const word& setName,
402  const pointField& insidePoints,
403  const label nErode
404 )
405 :
406  topoSetCellSource(mesh),
407  setName_(setName),
408  isZone_(false),
409  insidePoints_(insidePoints),
410  nErode_(nErode)
411 {}
412 
413 
415 (
416  const polyMesh& mesh,
417  const dictionary& dict
418 )
419 :
421  setName_(),
422  isZone_(false),
423  insidePoints_
424  (
425  dict.getCompat<pointField>("insidePoints", {{ "insidePoint", 0 }})
426  ),
427  nErode_(dict.getCheckOrDefault<label>("nErode", 0, labelMinMax::ge(0)))
428 {
429  // A single "set" or "zone" only
430  if (!dict.readIfPresent("set", setName_))
431  {
432  // Optional entry
433  if (dict.readIfPresent("zone", setName_))
434  {
435  isZone_ = true;
436  }
437  }
438 }
439 
440 
442 (
443  const polyMesh& mesh,
444  Istream& is
445 )
446 :
447  topoSetCellSource(mesh),
448  setName_(checkIs(is)),
449  isZone_(false),
450  insidePoints_(checkIs(is)),
451  nErode_(readLabel(checkIs(is)))
452 {}
453 
454 
455 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
456 
458 (
459  const topoSetSource::setAction action,
460  topoSet& set
461 ) const
462 {
463  if (action == topoSetSource::ADD || action == topoSetSource::NEW)
464  {
465  if (verbose_)
466  {
467  Info<< " Adding all cells of connected region "
468  << "containing points "
469  << insidePoints_ << " ..." << endl;
470  }
471 
472  combine(set, true);
473  }
474  else if (action == topoSetSource::SUBTRACT)
475  {
476  if (verbose_)
477  {
478  Info<< " Removing all cells of connected region "
479  << "containing points "
480  << insidePoints_ << " ..." << endl;
481  }
482 
483  combine(set, false);
484  }
485 }
486 
487 
488 // ************************************************************************* //
const polyBoundaryMesh & pbm
dictionary dict
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:608
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1122
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData, const bool parRun=UPstream::parRun())
Extract and swap to obtain neighbour cell values for all boundary faces.
Create a new set and ADD elements to it.
Add elements to current set.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:63
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1086
The topoSetCellSource is a intermediate class for handling topoSet sources for selecting cells...
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
Macros for easy insertion into run-time selection tables.
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
regionToCell(const polyMesh &mesh, const word &setName, const pointField &insidePoints, const label nErode)
Construct from components.
Definition: regionToCell.C:392
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
AccessType combine(const UList< T > &lists, AccessOp aop=accessOp< T >())
Combines sub-lists into a single list.
Definition: ListListOps.C:62
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
dynamicFvMesh & mesh
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:609
static MinMax< T > ge(const T &minVal)
A semi-infinite range from minVal to the type max.
Definition: MinMaxI.H:24
T getCheckOrDefault(const word &keyword, const T &deflt, const Predicate &pred, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
setAction
Enumeration defining various actions.
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1116
label nInternalFaces() const noexcept
Number of internal faces.
static void syncPointList(const polyMesh &mesh, List< T > &pointValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
const polyMesh & mesh_
Reference to the mesh.
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
General set of labels of mesh quantity (points, cells, faces).
Definition: topoSet.H:59
Subtract elements from current set.
Class with constructor to add usage string to table.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:75
List< label > labelList
A List of labels.
Definition: List.H:62
insidePoints((1 2 3))
List< bool > boolList
A List of bools.
Definition: List.H:60
virtual void applyToSet(const topoSetSource::setAction action, topoSet &set) const
Apply specified action to the topoSet.
Definition: regionToCell.C:451
Do not request registration (bool: false)
void reduce(T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce) using linear/tree communication schedule.
nErode
Definition: regionsToCell.H:36
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)