removeCells.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-2018 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 "removeCells.H"
30#include "bitSet.H"
31#include "polyMesh.H"
32#include "polyTopoChange.H"
33#include "polyRemoveCell.H"
34#include "polyRemoveFace.H"
35#include "polyModifyFace.H"
36#include "polyRemovePoint.H"
37#include "syncTools.H"
38
39// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40
41namespace Foam
42{
44}
45
46// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
47
48namespace
49{
50
51// Increase count (usage) of elements of list
52inline void incrCount(const Foam::labelUList& list, Foam::labelList& counter)
53{
54 for (auto idx : list)
55 {
56 ++counter[idx];
57 }
58}
59
60// Decrease count (usage) of elements of list
61inline void decrCount(const Foam::labelUList& list, Foam::labelList& counter)
62{
63 for (auto idx : list)
64 {
65 --counter[idx];
66 }
67}
68
69} // End anonymous namespace
70
71
72// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
73
74Foam::removeCells::removeCells(const polyMesh& mesh, const bool syncPar)
75:
76 mesh_(mesh),
77 syncPar_(syncPar)
78{}
79
80
81// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
82
84(
85 const bitSet& removedCell
86) const
87{
88 const labelList& faceOwner = mesh_.faceOwner();
89 const labelList& faceNeighbour = mesh_.faceNeighbour();
90
91 // Count cells using face.
92 labelList nCellsUsingFace(mesh_.nFaces(), Zero);
93
94 for (label facei = 0; facei < mesh_.nInternalFaces(); ++facei)
95 {
96 const label own = faceOwner[facei];
97 const label nei = faceNeighbour[facei];
98
99 if (!removedCell[own])
100 {
101 ++nCellsUsingFace[facei];
102 }
103 if (!removedCell[nei])
104 {
105 ++nCellsUsingFace[facei];
106 }
107 }
108
109 for (label facei = mesh_.nInternalFaces(); facei < mesh_.nFaces(); ++facei)
110 {
111 const label own = faceOwner[facei];
112
113 if (!removedCell[own])
114 {
115 ++nCellsUsingFace[facei];
116 }
117 }
118
119 // Coupled faces: add number of cells using face across couple.
120 {
121 // Note cyclics done always, parallel bits only done if syncPar_
122
123 SubList<label> bndValues
124 (
125 nCellsUsingFace,
126 mesh_.nBoundaryFaces(),
127 mesh_.nInternalFaces()
128 );
129
131 (
132 mesh_,
133 bndValues,
136 syncPar_
137 );
138 }
139
140 // Now nCellsUsingFace:
141 // 0 : internal face whose both cells get deleted
142 // boundary face whose all cells get deleted
143 // 1 : internal face that gets exposed
144 // unaffected (uncoupled) boundary face
145 // coupled boundary face that gets exposed ('uncoupled')
146 // 2 : unaffected internal face
147 // unaffected coupled boundary face
148
149 DynamicList<label> exposedFaces(mesh_.nFaces()/10);
150
151 for (label facei = 0; facei < mesh_.nInternalFaces(); ++facei)
152 {
153 if (nCellsUsingFace[facei] == 1)
154 {
155 exposedFaces.append(facei);
156 }
157 }
158
159 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
160
161 for (const polyPatch& pp : patches)
162 {
163 if (pp.coupled())
164 {
165 label facei = pp.start();
166
167 forAll(pp, i)
168 {
169 const label own = faceOwner[facei];
170
171 if (nCellsUsingFace[facei] == 1 && !removedCell[own])
172 {
173 // My owner not removed but other side is so has to become
174 // normal, uncoupled, boundary face
175 exposedFaces.append(facei);
176 }
177
178 ++facei;
179 }
180 }
181 }
182
183 return exposedFaces.shrink();
184}
185
186
188(
189 const bitSet& removedCell,
190 const labelUList& exposedFaceLabels,
191 const labelUList& exposedPatchIDs,
192 polyTopoChange& meshMod
193) const
194{
195 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
196
197 if (exposedFaceLabels.size() != exposedPatchIDs.size())
198 {
200 << "Size of exposedFaceLabels " << exposedFaceLabels.size()
201 << " differs from size of exposedPatchIDs "
202 << exposedPatchIDs.size()
203 << abort(FatalError);
204 }
205
206 // List of new patchIDs
207 labelList newPatchID(mesh_.nFaces(), -1);
208
209 forAll(exposedFaceLabels, i)
210 {
211 const label facei = exposedFaceLabels[i];
212 const label patchi = exposedPatchIDs[i];
213
214 if (patchi < 0 || patchi >= patches.size())
215 {
217 << "Invalid patch " << patchi
218 << " for exposed face " << facei << nl
219 << "Valid patches 0.." << patches.size()-1
220 << abort(FatalError);
221 }
222
223 if (patches[patchi].coupled())
224 {
226 << "Trying to put exposed face " << facei
227 << " into a coupled patch : " << patches[patchi].name()
228 << nl
229 << "This is illegal."
230 << abort(FatalError);
231 }
232
233 newPatchID[facei] = patchi;
234 }
235
236
237 // Walk all the cells mentioned for removal
238 for (const label celli : removedCell)
239 {
240 //Pout<< "Removing cell " << celli
241 // << " cc:" << mesh_.cellCentres()[celli] << endl;
242
243 meshMod.setAction(polyRemoveCell(celli));
244 }
245
246
247 // Remove faces that are no longer used. Modify faces that
248 // are used by one cell only.
249
250 const faceList& faces = mesh_.faces();
251 const labelList& faceOwner = mesh_.faceOwner();
252 const labelList& faceNeighbour = mesh_.faceNeighbour();
253 const faceZoneMesh& faceZones = mesh_.faceZones();
254
255 // Count starting number of faces using each point.
256 // Update whenever removing a face.
257 labelList nFacesUsingPoint(mesh_.nPoints(), Zero);
258
259 for (const face& f : faces)
260 {
261 incrCount(f, nFacesUsingPoint);
262 }
263
264
265 for (label facei = 0; facei < mesh_.nInternalFaces(); ++facei)
266 {
267 const face& f = faces[facei];
268 const label own = faceOwner[facei];
269 const label nei = faceNeighbour[facei];
270
271 if (removedCell[own])
272 {
273 if (removedCell[nei])
274 {
275 // Face no longer used
276 //Pout<< "Removing internal face " << facei
277 // << " fc:" << mesh_.faceCentres()[facei] << endl;
278
279 meshMod.setAction(polyRemoveFace(facei));
280 decrCount(f, nFacesUsingPoint);
281 }
282 else
283 {
284 if (newPatchID[facei] == -1)
285 {
287 << "No patchID provided for exposed face " << facei
288 << " on cell " << nei << nl
289 << "Did you provide patch IDs for all exposed faces?"
290 << abort(FatalError);
291 }
292
293 // nei is remaining cell. Facei becomes external cell
294
295 const label zoneID = faceZones.whichZone(facei);
296 bool zoneFlip = false;
297
298 if (zoneID >= 0)
299 {
300 const faceZone& fZone = faceZones[zoneID];
301 // Note: we reverse the owner/neighbour of the face
302 // so should also select the other side of the zone
303 zoneFlip = !fZone.flipMap()[fZone.whichFace(facei)];
304 }
305
306 //Pout<< "Putting exposed internal face " << facei
307 // << " fc:" << mesh_.faceCentres()[facei]
308 // << " into patch " << newPatchID[facei] << endl;
309
310 meshMod.setAction
311 (
313 (
314 f.reverseFace(), // modified face
315 facei, // label of face being modified
316 nei, // owner
317 -1, // neighbour
318 true, // face flip
319 newPatchID[facei], // patch for face
320 false, // remove from zone
321 zoneID, // zone for face
322 zoneFlip // face flip in zone
323 )
324 );
325 }
326 }
327 else if (removedCell[nei])
328 {
329 if (newPatchID[facei] == -1)
330 {
332 << "No patchID provided for exposed face " << facei
333 << " on cell " << own << nl
334 << "Did you provide patch IDs for all exposed faces?"
335 << abort(FatalError);
336 }
337
338 //Pout<< "Putting exposed internal face " << facei
339 // << " fc:" << mesh_.faceCentres()[facei]
340 // << " into patch " << newPatchID[facei] << endl;
341
342 // own is remaining cell. Facei becomes external cell.
343 const label zoneID = faceZones.whichZone(facei);
344 bool zoneFlip = false;
345
346 if (zoneID >= 0)
347 {
348 const faceZone& fZone = faceZones[zoneID];
349 zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
350 }
351
352 meshMod.setAction
353 (
355 (
356 f, // modified face
357 facei, // label of face being modified
358 own, // owner
359 -1, // neighbour
360 false, // face flip
361 newPatchID[facei], // patch for face
362 false, // remove from zone
363 zoneID, // zone for face
364 zoneFlip // face flip in zone
365 )
366 );
367 }
368 }
369
370 for (const polyPatch& pp : patches)
371 {
372 if (pp.coupled())
373 {
374 label facei = pp.start();
375
376 forAll(pp, i)
377 {
378 if (newPatchID[facei] != -1)
379 {
380 //Pout<< "Putting uncoupled coupled face " << facei
381 // << " fc:" << mesh_.faceCentres()[facei]
382 // << " into patch " << newPatchID[facei] << endl;
383
384 const label zoneID = faceZones.whichZone(facei);
385 bool zoneFlip = false;
386
387 if (zoneID >= 0)
388 {
389 const faceZone& fZone = faceZones[zoneID];
390 zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
391 }
392
393 meshMod.setAction
394 (
396 (
397 faces[facei], // modified face
398 facei, // label of face
399 faceOwner[facei], // owner
400 -1, // neighbour
401 false, // face flip
402 newPatchID[facei], // patch for face
403 false, // remove from zone
404 zoneID, // zone for face
405 zoneFlip // face flip in zone
406 )
407 );
408 }
409 else if (removedCell[faceOwner[facei]])
410 {
411 // Face no longer used
412 //Pout<< "Removing boundary face " << facei
413 // << " fc:" << mesh_.faceCentres()[facei]
414 // << endl;
415
416 meshMod.setAction(polyRemoveFace(facei));
417 decrCount(faces[facei], nFacesUsingPoint);
418 }
419
420 ++facei;
421 }
422 }
423 else
424 {
425 label facei = pp.start();
426
427 forAll(pp, i)
428 {
429 if (newPatchID[facei] != -1)
430 {
432 << "new patchID provided for boundary face " << facei
433 << " even though it is not on a coupled face."
434 << abort(FatalError);
435 }
436
437 if (removedCell[faceOwner[facei]])
438 {
439 // Face no longer used
440 //Pout<< "Removing boundary face " << facei
441 // << " fc:" << mesh_.faceCentres()[facei]
442 // << endl;
443
444 meshMod.setAction(polyRemoveFace(facei));
445 decrCount(faces[facei], nFacesUsingPoint);
446 }
447
448 ++facei;
449 }
450 }
451 }
452
453
454 // Remove points that are no longer used.
455 // Loop rewritten to not use pointFaces.
456
457 forAll(nFacesUsingPoint, pointi)
458 {
459 if (nFacesUsingPoint[pointi] == 0)
460 {
461 //Pout<< "Removing unused point " << pointi
462 // << " at:" << mesh_.points()[pointi] << endl;
463
464 meshMod.setAction(polyRemovePoint(pointi));
465 }
466 else if (nFacesUsingPoint[pointi] == 1)
467 {
469 << "point " << pointi << " at coordinate "
470 << mesh_.points()[pointi]
471 << " is only used by 1 face after removing cells."
472 << " This probably results in an illegal mesh."
473 << endl;
474 }
475 }
476}
477
478
480(
481 const labelUList& cellsToRemove
482) const
483{
484 bitSet removeCell(mesh_.nCells(), cellsToRemove);
485
486 return getExposedFaces(removeCell);
487}
488
489
491(
492 const labelUList& cellsToRemove,
493 const labelUList& exposedFaceLabels,
494 const labelUList& exposedPatchIDs,
495 polyTopoChange& meshMod
496) const
497{
498 bitSet removedCell(mesh_.nCells(), cellsToRemove);
499
500 setRefinement
501 (
502 removedCell,
503 exposedFaceLabels,
504 exposedPatchIDs,
505 meshMod
506 );
507}
508
509
510// ************************************************************************* //
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:72
DynamicList< T, SizeMin > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:434
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:503
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:65
A List obtained as a section of another List.
Definition: SubList.H:70
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:106
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: ZoneMesh.C:288
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:66
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:67
label whichFace(const label globalCellID) const
Helper function to re-direct to zone::localID(...)
Definition: faceZone.C:372
const boolList & flipMap() const noexcept
Return face flip map.
Definition: faceZone.H:272
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Default transformation behaviour.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
label start() const noexcept
The start label of boundary faces in the polyMesh face list.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
Class describing modification of a face.
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:75
Class containing data for cell removal.
Class containing data for face removal.
Class containing data for point removal.
Direct mesh changes based on v1.3 polyTopoChange syntax.
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
Given list of cells to remove, insert all the topology changes.
Definition: removeCells.H:64
labelList getExposedFaces(const bitSet &removedCell) const
Get labels of faces exposed after cells removal.
Definition: removeCells.C:84
void setRefinement(const bitSet &removedCell, const labelUList &facesToExpose, const labelUList &patchIDs, polyTopoChange &) const
Play commands into polyTopoChange to remove cells.
Definition: removeCells.C:188
static void syncBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop, const TransformOp &top, const bool parRun=Pstream::parRun())
Synchronize values on boundary faces only.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
const polyBoundaryMesh & patches
bool coupled(solutionDict.getOrDefault("coupledEnergyField", false))
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
const labelIOList & zoneID
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for OpenFOAM.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
errorManip< error > abort(error &err)
Definition: errorManip.H:144
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
error FatalError
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
labelList f(nPoints)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333