Loading...
Searching...
No Matches
removeCellLayer.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) 2018-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
30#include "polyMesh.H"
31#include "primitiveMesh.H"
32#include "polyTopoChange.H"
33#include "oppositeFace.H"
34#include "polyTopoChanger.H"
35#include "polyRemoveCell.H"
36#include "polyRemoveFace.H"
37#include "polyRemovePoint.H"
38#include "polyModifyFace.H"
39
40// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
41
42bool Foam::layerAdditionRemoval::validCollapse() const
43{
44 // Check for valid layer collapse
45 // - no boundary-to-boundary collapse
46
47 if (debug)
48 {
49 Pout<< "Checking layer collapse for object " << name() << endl;
50 }
51
52 // Grab the face collapse mapping
53 const polyMesh& mesh = topoChanger().mesh();
54
55 const labelList& ftc = facesPairing();
56 const labelList& mf = mesh.faceZones()[faceZoneID_.index()];
57
58 label nBoundaryHits = 0;
59
60 forAll(mf, facei)
61 {
62 if
63 (
64 !mesh.isInternalFace(mf[facei])
65 && !mesh.isInternalFace(ftc[facei])
66 )
67 {
68 nBoundaryHits++;
69 }
70 }
71
72
73 if (debug)
74 {
75 Pout<< "Finished checking layer collapse for object "
76 << name() <<". Number of boundary-on-boundary hits: "
77 << nBoundaryHits << endl;
78 }
79
80 return !returnReduceOr(nBoundaryHits);
81}
82
83
84void Foam::layerAdditionRemoval::removeCellLayer
85(
87) const
88{
89 // Algorithm for layer removal. Second phase: topological change
90 // 2) Go through all the faces of the master cell layer and remove
91 // the ones that are not in the master face zone.
92 //
93 // 3) Grab all the faces coming out of points that are collapsed
94 // and select the ones that are not marked for removal. Go
95 // through the remaining faces and replace the point to remove by
96 // the equivalent point in the master face zone.
97 if (debug)
98 {
99 Pout<< "Removing the cell layer for object " << name() << endl;
100 }
101
102 const polyMesh& mesh = topoChanger().mesh();
103
104 const labelList& own = mesh.faceOwner();
105 const labelList& nei = mesh.faceNeighbour();
106
107 const labelList& ptc = pointsPairing();
108 const labelList& ftc = facesPairing();
109
110 // Remove all the cells from the master layer
111 const labelList& mc =
112 mesh.faceZones()[faceZoneID_.index()].masterCells();
113
114 forAll(mc, facei)
115 {
116 label slaveSideCell = own[ftc[facei]];
117
118 if (mesh.isInternalFace(ftc[facei]) && slaveSideCell == mc[facei])
119 {
120 // Owner cell of the face is being removed.
121 // Grab the neighbour instead
122 slaveSideCell = nei[ftc[facei]];
123 }
124
125 ref.setAction(polyRemoveCell(mc[facei], slaveSideCell));
126 }
127
128 // Remove all the faces from the master layer cells which are not in
129 // the master face layer
130 labelHashSet facesToRemoveMap(mc.size()*primitiveMesh::facesPerCell_);
131
132 const cellList& cells = mesh.cells();
133
134 forAll(mc, celli)
135 {
136 const cell& curCell = cells[mc[celli]];
137
138 forAll(curCell, facei)
139 {
140 // Check if the face is in the master zone. If not, remove it
141 if
142 (
143 mesh.faceZones().whichZone(curCell[facei])
144 != faceZoneID_.index()
145 )
146 {
147 facesToRemoveMap.insert(curCell[facei]);
148 }
149 }
150 }
151
152 for (const label facei : facesToRemoveMap)
153 {
154 ref.setAction(polyRemoveFace(facei));
155 }
156
157 // Remove all points that will be collapsed
158 for (const label pointi : ptc)
159 {
160 ref.setAction(polyRemovePoint(pointi));
161 }
162
163 // Grab all faces coming off points to be deleted. If the face
164 // has not been deleted, replace the removed point with the
165 // equivalent from the master layer.
166
167 // Make a map of all point to be removed, giving the master point label
168 // for each of them
169
170 const labelList& meshPoints =
171 mesh.faceZones()[faceZoneID_.index()].patch().meshPoints();
172
173 Map<label> removedPointMap(ptc, meshPoints);
174
175 const labelListList& pf = mesh.pointFaces();
176
177 const faceList& faces = mesh.faces();
178
179 // Make a list of faces to be modified using the map to avoid duplicates
180 labelHashSet facesToModify(ptc.size()*primitiveMesh::facesPerPoint_);
181
182 forAll(ptc, pointi)
183 {
184 const labelList& curFaces = pf[ptc[pointi]];
185
186 forAll(curFaces, facei)
187 {
188 if (!facesToRemoveMap.found(curFaces[facei]))
189 {
190 facesToModify.insert(curFaces[facei]);
191 }
192 }
193 }
194
195 labelList ftm = facesToModify.toc();
196
197 if (debug > 1)
198 {
199 Pout<< "faces to modify: " << ftm << endl;
200 }
201
202 forAll(ftm, facei)
203 {
204 // For every face to modify, copy the face and re-map the vertices.
205 // It is known all the faces will be changed since they hang off
206 // re-mapped vertices
207 label curFaceID = ftm[facei];
208
209 face newFace(faces[curFaceID]);
210
211 forAll(newFace, pointi)
212 {
213 const auto rpmIter = removedPointMap.cfind(newFace[pointi]);
214
215 if (rpmIter.good())
216 {
217 // Point mapped. Replace it
218 newFace[pointi] = rpmIter();
219 }
220 }
221
222 if (debug > 1)
223 {
224 Pout<< "face label: " << curFaceID
225 << " old face: " << faces[curFaceID]
226 << " new face: " << newFace << endl;
227 }
228
229 // Get face zone and its flip
230 label modifiedFaceZone = mesh.faceZones().whichZone(curFaceID);
231 bool modifiedFaceZoneFlip = false;
232
233 if (modifiedFaceZone >= 0)
234 {
235 const faceZone& fz = mesh.faceZones()[modifiedFaceZone];
236 modifiedFaceZoneFlip = fz.flipMap()[fz.whichFace(curFaceID)];
237 }
238
239 label newNeighbour = -1;
240
241 if (curFaceID < mesh.nInternalFaces())
242 {
243 newNeighbour = nei[curFaceID];
244 }
245
246 // Modify the face
247 ref.setAction
248 (
250 (
251 newFace, // modified face
252 curFaceID, // label of face being modified
253 own[curFaceID], // owner
254 newNeighbour, // neighbour
255 false, // face flip
256 mesh.boundaryMesh().whichPatch(curFaceID),// patch for face
257 false, // remove from zone
258 modifiedFaceZone, // zone for face
259 modifiedFaceZoneFlip // face flip in zone
260 )
261 );
262 }
263
264 // Modify the faces in the master layer to point past the removed cells
265
266 const labelList& mf = mesh.faceZones()[faceZoneID_.index()];
267 const boolList& mfFlip = mesh.faceZones()[faceZoneID_.index()].flipMap();
268
269 forAll(mf, facei)
270 {
271 // Grab the owner and neighbour of the faces to be collapsed and get rid
272 // of the cell to be removed
273 label masterSideCell = own[mf[facei]];
274
275 if (masterSideCell == mc[facei])
276 {
277 if (mesh.isInternalFace(mf[facei]))
278 {
279 // Owner cell of the face is being removed.
280 // Grab the neighbour instead
281 masterSideCell = nei[mf[facei]];
282 }
283 else
284 {
285 masterSideCell = -1;
286 }
287 }
288
289 label slaveSideCell = own[ftc[facei]];
290
291 if (slaveSideCell == mc[facei])
292 {
293 if (mesh.isInternalFace(ftc[facei]))
294 {
295 // Owner cell of the face is being removed.
296 // Grab the neighbour instead
297 slaveSideCell = nei[ftc[facei]];
298 }
299 else
300 {
301 slaveSideCell = -1;
302 }
303 }
304
305 // Find out if the face needs to be flipped
306 label newOwner = -1;
307 label newNeighbour = -1;
308 bool flipFace = false;
309 label newPatchID = -1;
310 label newZoneID = -1;
311
312 // Is any of the faces a boundary face? If so, grab the patch
313 // A boundary-to-boundary collapse is checked for in validCollapse()
314 // and cannot happen here.
315
316 if (!mesh.isInternalFace(mf[facei]))
317 {
318 // Master is the boundary face: it gets a new owner but no flip
319 newOwner = slaveSideCell;
320 newNeighbour = -1;
321 flipFace = false;
322 newPatchID = mesh.boundaryMesh().whichPatch(mf[facei]);
323 newZoneID = mesh.faceZones().whichZone(mf[facei]);
324 }
325 else if (!mesh.isInternalFace(ftc[facei]))
326 {
327 // Slave is the boundary face: grab its patch
328 newOwner = slaveSideCell;
329 newNeighbour = -1;
330
331 // Find out if the face flip is necessary
332 if (own[mf[facei]] == slaveSideCell)
333 {
334 flipFace = false;
335 }
336 else
337 {
338 flipFace = true;
339 }
340
341 newPatchID = mesh.boundaryMesh().whichPatch(ftc[facei]);
342
343 // The zone of the master face is preserved
344 newZoneID = mesh.faceZones().whichZone(mf[facei]);
345 }
346 else
347 {
348 // Both faces are internal: flip is decided based on which of the
349 // new cells around it has a lower label
350 newOwner = min(masterSideCell, slaveSideCell);
351 newNeighbour = max(masterSideCell, slaveSideCell);
352
353 if (newOwner == own[mf[facei]] || newNeighbour == nei[mf[facei]])
354 {
355 flipFace = false;
356 }
357 else
358 {
359 flipFace = true;
360 }
361
362 newPatchID = -1;
363
364 // The zone of the master face is preserved
365 newZoneID = mesh.faceZones().whichZone(mf[facei]);
366 }
367
368 // Modify the face and flip if necessary
369 face newFace = faces[mf[facei]];
370 bool zoneFlip = mfFlip[facei];
371
372 if (flipFace)
373 {
374 newFace.flip();
375 zoneFlip = !zoneFlip;
376 }
377
378 if (debug > 1)
379 {
380 Pout<< "Modifying face " << mf[facei]
381 << " newFace: " << newFace << nl
382 << " newOwner: " << newOwner
383 << " newNeighbour: " << newNeighbour
384 << " flipFace: " << flipFace
385 << " newPatchID: " << newPatchID
386 << " newZoneID: " << newZoneID << nl
387 << " oldOwn: " << own[mf[facei]];
388 if (newPatchID == -1)
389 {
390 Pout<< " oldNei: " << nei[mf[facei]];
391 }
392 Pout<< endl;
393 }
394
395 ref.setAction
396 (
398 (
399 newFace, // modified face
400 mf[facei], // label of face being modified
401 newOwner, // owner
402 newNeighbour, // neighbour
403 flipFace, // flip
404 newPatchID, // patch for face
405 false, // remove from zone
406 newZoneID, // new zone
407 zoneFlip // face flip in zone
408 )
409 );
410 }
411}
412
413
414// ************************************************************************* //
A HashTable to objects of type <T> with a label key.
Definition Map.H:54
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition ZoneMesh.C:410
A cell is defined as a list of faces with extra functionality.
Definition cell.H:56
A subset of mesh faces organised as a primitive patch.
Definition faceZone.H:63
A face is a list of labels corresponding to mesh vertices.
Definition face.H:71
label whichPatch(const label meshFacei) const
Return patch index for a given mesh face index. Uses binary search.
const word & name() const
Return name of this modifier.
const polyTopoChanger & topoChanger() const
Return reference to morph engine.
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition polyMesh.H:609
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition polyMesh.H:671
virtual const faceList & faces() const
Return raw faces.
Definition polyMesh.C:1088
virtual const labelList & faceOwner() const
Return face owner.
Definition polyMesh.C:1101
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition polyMesh.C:1107
Class describing modification of a face.
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.
const polyMesh & mesh() const
Return the mesh reference.
bool isInternalFace(const label faceIndex) const noexcept
Return true if given face label is internal to the mesh.
label nInternalFaces() const noexcept
Number of internal faces.
static const unsigned facesPerPoint_
Estimated number of faces per point.
const labelListList & pointFaces() const
static const unsigned facesPerCell_
Estimated number of faces per cell.
const cellList & cells() const
rDeltaT ref()
dynamicFvMesh & mesh
auto & name
const cellShapeList & cells
Namespace for handling debugging switches.
Definition debug.C:45
bool returnReduceOr(const bool value, const int communicator=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
List< label > labelList
A List of labels.
Definition List.H:62
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition HashSet.H:85
List< face > faceList
List of faces.
Definition faceListFwd.H:41
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
List< cell > cellList
List of cell.
Definition cellListFwd.H:41
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:26
List< bool > boolList
A List of bools.
Definition List.H:60
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299