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-2020 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"
35
36// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37
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>())
242 << " cells." << endl;
243}
244
245
246void Foam::regionToCell::erode
247(
248 boolList& selectedCell
249) const
250{
251 //Info<< "Entering shrinkRegions:" << count(selectedCell) << endl;
252 //generateField("selectedCell_before", selectedCell)().write();
253
254 // Now erode and see which regions get disconnected
255 boolList shrunkSelectedCell(selectedCell);
256
257 for (label iter = 0; iter < nErode_; iter++)
258 {
259 shrinkRegions(shrunkSelectedCell);
260 }
261
262 //Info<< "After shrinking:" << count(shrunkSelectedCell) << endl;
263 //generateField("shrunkSelectedCell", shrunkSelectedCell)().write();
264
265
266 // Determine faces on the edge of shrunkSelectedCell
267 boolList blockedFace(mesh_.nFaces(), false);
268 markRegionFaces(shrunkSelectedCell, blockedFace);
269
270 // Find disconnected regions
271 regionSplit cellRegion(mesh_, blockedFace);
272
273 // Determine regions containing insidePoints
274 boolList keepRegion(findRegions(verbose_, cellRegion));
275
276
277 // Extract cells in regions that are not to be kept.
278 boolList removeCell(mesh_.nCells(), false);
279 forAll(cellRegion, celli)
280 {
281 if (shrunkSelectedCell[celli] && !keepRegion[cellRegion[celli]])
282 {
283 removeCell[celli] = true;
284 }
285 }
286
287 //Info<< "removeCell before:" << count(removeCell) << endl;
288 //generateField("removeCell_before", removeCell)().write();
289
290
291 // Grow removeCell
292 for (label iter = 0; iter < nErode_; iter++)
293 {
294 // Grow selected cell in regions that are not for keeping
295 boolList boundaryPoint(mesh_.nPoints(), false);
296 forAll(removeCell, celli)
297 {
298 if (removeCell[celli])
299 {
300 const labelList& cPoints = mesh_.cellPoints(celli);
301 forAll(cPoints, i)
302 {
303 boundaryPoint[cPoints[i]] = true;
304 }
305 }
306 }
307 syncTools::syncPointList(mesh_, boundaryPoint, orEqOp<bool>(), false);
308
309 // Select all cells using these points
310
311 label nChanged = 0;
312 forAll(boundaryPoint, pointi)
313 {
314 if (boundaryPoint[pointi])
315 {
316 const labelList& pCells = mesh_.pointCells(pointi);
317 forAll(pCells, i)
318 {
319 label celli = pCells[i];
320 if (!removeCell[celli])
321 {
322 removeCell[celli] = true;
323 nChanged++;
324 }
325 }
326 }
327 }
328 }
329
330 //Info<< "removeCell after:" << count(removeCell) << endl;
331 //generateField("removeCell_after", removeCell)().write();
332
333
334 // Unmark removeCell
335 forAll(removeCell, celli)
336 {
337 if (removeCell[celli])
338 {
339 selectedCell[celli] = false;
340 }
341 }
342}
343
344
345void Foam::regionToCell::combine(topoSet& set, const bool add) const
346{
347 // Note: wip. Select cells first
348 boolList selectedCell(mesh_.nCells(), true);
349
350 if (setName_.size() && setName_ != "none")
351 {
352 Info<< " Loading subset " << setName_
353 << " to delimit search region."
354 << endl;
355
356 cellSet subSet(mesh_, setName_);
357
358 selectedCell = false;
359 for (const label celli : subSet)
360 {
361 selectedCell[celli] = true;
362 }
363 }
364
365
366 unselectOutsideRegions(selectedCell);
367
368 if (nErode_ > 0)
369 {
370 erode(selectedCell);
371 }
372
373
374 forAll(selectedCell, celli)
375 {
376 if (selectedCell[celli])
377 {
378 addOrDelete(set, celli, add);
379 }
380 }
381}
382
383
384// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
385
387(
388 const polyMesh& mesh,
389 const word& setName,
391 const label nErode
392)
393:
395 setName_(setName),
396 insidePoints_(insidePoints),
397 nErode_(nErode)
398{}
399
400
402(
403 const polyMesh& mesh,
404 const dictionary& dict
405)
406:
408 setName_(dict.getOrDefault<word>("set", "none")),
409 insidePoints_
410 (
411 dict.getCompat<pointField>("insidePoints", {{ "insidePoint", 0 }})
412 ),
413 nErode_(dict.getCheckOrDefault<label>("nErode", 0, labelMinMax::ge(0)))
414{}
415
416
418(
419 const polyMesh& mesh,
420 Istream& is
421)
422:
424 setName_(checkIs(is)),
425 insidePoints_(checkIs(is)),
426 nErode_(readLabel(checkIs(is)))
427{}
428
429
430// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
431
433(
434 const topoSetSource::setAction action,
435 topoSet& set
436) const
437{
438 if (action == topoSetSource::ADD || action == topoSetSource::NEW)
439 {
440 if (verbose_)
441 {
442 Info<< " Adding all cells of connected region "
443 << "containing points "
444 << insidePoints_ << " ..." << endl;
445 }
446
447 combine(set, true);
448 }
449 else if (action == topoSetSource::SUBTRACT)
450 {
451 if (verbose_)
452 {
453 Info<< " Removing all cells of connected region "
454 << "containing points "
455 << insidePoints_ << " ..." << endl;
456 }
457
458 combine(set, false);
459 }
460}
461
462
463// ************************************************************************* //
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:64
static MinMax< T > ge(const T &minVal)
A semi-infinite range from minVal to the type max.
Definition: MinMaxI.H:31
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
T getCheckOrDefault(const word &keyword, const T &deflt, const Predicate &pred, enum keyType::option matchOpt=keyType::REGEX) const
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1121
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:456
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1127
label nInternalFaces() const noexcept
Number of internal faces.
int myProcNo() const noexcept
Return processor number.
A topoSetCellSource to select cells belonging to a topologically connected region (that contains give...
Definition: regionToCell.H:179
virtual void applyToSet(const topoSetSource::setAction action, topoSet &set) const
Apply specified action to the topoSet.
Definition: regionToCell.C:433
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData)
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.
Class with constructor to add usage string to table.
Base class of a source for a topoSet.
Definition: topoSetSource.H:68
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.
const polyMesh & mesh_
Reference to the mesh.
General set of labels of mesh quantity (points, cells, faces).
Definition: topoSet.H:67
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Namespace for OpenFOAM.
List< label > labelList
A List of labels.
Definition: List.H:66
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:66
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
List< bool > boolList
A List of bools.
Definition: List.H:64
error FatalError
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
UList< label > labelUList
A UList of labels.
Definition: UList.H:85
labelList f(nPoints)
nErode
Definition: regionsToCell.H:39
insidePoints((1 2 3))
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333