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 -------------------------------------------------------------------------------
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 "layerAdditionRemoval.H"
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 
42 bool 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 
84 void Foam::layerAdditionRemoval::removeCellLayer
85 (
86  polyTopoChange& ref
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  (
249  polyModifyFace
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  (
397  polyModifyFace
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 // ************************************************************************* //
List< cell > cellList
List of cell.
Definition: cellListFwd.H:39
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1122
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
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
const cellList & cells() const
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
static const unsigned facesPerPoint_
Estimated number of faces per point.
bool isInternalFace(const label faceIndex) const noexcept
Return true if given face label is internal to the mesh.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
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:39
static const unsigned facesPerCell_
Estimated number of faces per cell.
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
const cellShapeList & cells
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:609
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1116
label nInternalFaces() const noexcept
Number of internal faces.
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1103
label whichPatch(const label meshFacei) const
Return patch index for a given mesh face index. Uses binary search.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
label index() const
The index of the first matching items, -1 if no matches.
Definition: DynamicID.H:139
rDeltaT ref()
int debug
Static debugging option.
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:671
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: ZoneMesh.C:406
const polyTopoChanger & topoChanger() const
Return reference to morph engine.
const word & name() const
Return name of this modifier.
const labelListList & pointFaces() const
List< label > labelList
A List of labels.
Definition: List.H:62
const polyMesh & mesh() const
Return the mesh reference.
bool returnReduceOr(const bool value, const label comm=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
List< bool > boolList
A List of bools.
Definition: List.H:60
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.