Loading...
Searching...
No Matches
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-------------------------------------------------------------------------------
11License
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"
36// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38namespace Foam
39{
45}
46
47
48Foam::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
59void 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
103Foam::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
150void 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
176void 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
245void 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
344void 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);
392 }
393}
394
395
396// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
397
399(
400 const polyMesh& mesh,
401 const word& setName,
403 const label nErode
404)
405:
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_))
435 isZone_ = true;
436 }
437 }
438}
439
440
442(
443 const polyMesh& mesh,
444 Istream& is
445)
446:
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// ************************************************************************* //
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
const polyBoundaryMesh & pbm
@ NO_REGISTER
Do not request registration (bool: false).
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition Istream.H:60
static MinMax< label > ge(const label &minVal)
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
Definition UPstream.H:1706
A collection of cell labels.
Definition cellSet.H:50
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
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...
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...
A face is a list of labels corresponding to mesh vertices.
Definition face.H:71
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
virtual const labelList & faceOwner() const
Return face owner.
Definition polyMesh.C:1101
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition polyMesh.C:1107
A patch is a list of labels that address the faces in the global face list.
Definition polyPatch.H:73
This class separates the mesh into distinct unconnected regions, each of which is then given a label ...
A topoSetCellSource to select cells belonging to a topologically connected region (that contains give...
regionToCell(const polyMesh &mesh, const word &setName, const pointField &insidePoints, const label nErode)
Construct from components.
virtual void applyToSet(const topoSetSource::setAction action, topoSet &set) const
Apply specified action to the topoSet.
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.
static void syncPointList(const polyMesh &mesh, List< T > &pointValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
The topoSetCellSource is a intermediate class for handling topoSet sources for selecting cells.
topoSetCellSource(const polyMesh &mesh)
Construct from mesh.
Class with constructor to add usage string to table.
Base class of a source for a topoSet.
setAction
Enumeration defining various actions.
@ SUBTRACT
Subtract elements from current set.
@ ADD
Add elements to current set.
@ NEW
Create a new set and ADD elements to it.
bool verbose_
Output verbosity (default: true).
const polyMesh & mesh() const noexcept
Reference to the mesh.
const polyMesh & mesh_
Reference to the mesh.
static Istream & checkIs(Istream &is)
Check state of stream.
General set of labels of mesh quantity (points, cells, faces).
Definition topoSet.H:63
A class for handling words, derived from Foam::string.
Definition word.H:66
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
Namespace for OpenFOAM.
List< label > labelList
A List of labels.
Definition List.H:62
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition label.H:63
messageStream Info
Information stream (stdout output on master, null elsewhere).
T returnReduce(const T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
void add(DimensionedField< scalar, GeoMesh > &result, const dimensioned< scalar > &dt1, const DimensionedField< scalar, GeoMesh > &f2)
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
Definition typeInfo.H:87
void reduce(T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce).
List< bool > boolList
A List of bools.
Definition List.H:60
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
vectorField pointField
pointField is a vectorField.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
UList< label > labelUList
A UList of labels.
Definition UList.H:75
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
labelList f(nPoints)
nErode
insidePoints((1 2 3))
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299