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-2022 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  forAll(ptc, pointi)
159  {
160  ref.setAction(polyRemovePoint(ptc[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  Map<label> removedPointMap(2*ptc.size());
171 
172  const labelList& meshPoints =
173  mesh.faceZones()[faceZoneID_.index()]().meshPoints();
174 
175  forAll(ptc, pointi)
176  {
177  removedPointMap.insert(ptc[pointi], meshPoints[pointi]);
178  }
179 
180  const labelListList& pf = mesh.pointFaces();
181 
182  const faceList& faces = mesh.faces();
183 
184  // Make a list of faces to be modified using the map to avoid duplicates
185  labelHashSet facesToModify(ptc.size()*primitiveMesh::facesPerPoint_);
186 
187  forAll(ptc, pointi)
188  {
189  const labelList& curFaces = pf[ptc[pointi]];
190 
191  forAll(curFaces, facei)
192  {
193  if (!facesToRemoveMap.found(curFaces[facei]))
194  {
195  facesToModify.insert(curFaces[facei]);
196  }
197  }
198  }
199 
200  labelList ftm = facesToModify.toc();
201 
202  if (debug > 1)
203  {
204  Pout<< "faces to modify: " << ftm << endl;
205  }
206 
207  forAll(ftm, facei)
208  {
209  // For every face to modify, copy the face and re-map the vertices.
210  // It is known all the faces will be changed since they hang off
211  // re-mapped vertices
212  label curFaceID = ftm[facei];
213 
214  face newFace(faces[curFaceID]);
215 
216  forAll(newFace, pointi)
217  {
218  const auto rpmIter = removedPointMap.cfind(newFace[pointi]);
219 
220  if (rpmIter.good())
221  {
222  // Point mapped. Replace it
223  newFace[pointi] = rpmIter();
224  }
225  }
226 
227  if (debug > 1)
228  {
229  Pout<< "face label: " << curFaceID
230  << " old face: " << faces[curFaceID]
231  << " new face: " << newFace << endl;
232  }
233 
234  // Get face zone and its flip
235  label modifiedFaceZone = mesh.faceZones().whichZone(curFaceID);
236  bool modifiedFaceZoneFlip = false;
237 
238  if (modifiedFaceZone >= 0)
239  {
240  const faceZone& fz = mesh.faceZones()[modifiedFaceZone];
241  modifiedFaceZoneFlip = fz.flipMap()[fz.whichFace(curFaceID)];
242  }
243 
244  label newNeighbour = -1;
245 
246  if (curFaceID < mesh.nInternalFaces())
247  {
248  newNeighbour = nei[curFaceID];
249  }
250 
251  // Modify the face
252  ref.setAction
253  (
254  polyModifyFace
255  (
256  newFace, // modified face
257  curFaceID, // label of face being modified
258  own[curFaceID], // owner
259  newNeighbour, // neighbour
260  false, // face flip
261  mesh.boundaryMesh().whichPatch(curFaceID),// patch for face
262  false, // remove from zone
263  modifiedFaceZone, // zone for face
264  modifiedFaceZoneFlip // face flip in zone
265  )
266  );
267  }
268 
269  // Modify the faces in the master layer to point past the removed cells
270 
271  const labelList& mf = mesh.faceZones()[faceZoneID_.index()];
272  const boolList& mfFlip = mesh.faceZones()[faceZoneID_.index()].flipMap();
273 
274  forAll(mf, facei)
275  {
276  // Grab the owner and neighbour of the faces to be collapsed and get rid
277  // of the cell to be removed
278  label masterSideCell = own[mf[facei]];
279 
280  if (masterSideCell == mc[facei])
281  {
282  if (mesh.isInternalFace(mf[facei]))
283  {
284  // Owner cell of the face is being removed.
285  // Grab the neighbour instead
286  masterSideCell = nei[mf[facei]];
287  }
288  else
289  {
290  masterSideCell = -1;
291  }
292  }
293 
294  label slaveSideCell = own[ftc[facei]];
295 
296  if (slaveSideCell == mc[facei])
297  {
298  if (mesh.isInternalFace(ftc[facei]))
299  {
300  // Owner cell of the face is being removed.
301  // Grab the neighbour instead
302  slaveSideCell = nei[ftc[facei]];
303  }
304  else
305  {
306  slaveSideCell = -1;
307  }
308  }
309 
310  // Find out if the face needs to be flipped
311  label newOwner = -1;
312  label newNeighbour = -1;
313  bool flipFace = false;
314  label newPatchID = -1;
315  label newZoneID = -1;
316 
317  // Is any of the faces a boundary face? If so, grab the patch
318  // A boundary-to-boundary collapse is checked for in validCollapse()
319  // and cannot happen here.
320 
321  if (!mesh.isInternalFace(mf[facei]))
322  {
323  // Master is the boundary face: it gets a new owner but no flip
324  newOwner = slaveSideCell;
325  newNeighbour = -1;
326  flipFace = false;
327  newPatchID = mesh.boundaryMesh().whichPatch(mf[facei]);
328  newZoneID = mesh.faceZones().whichZone(mf[facei]);
329  }
330  else if (!mesh.isInternalFace(ftc[facei]))
331  {
332  // Slave is the boundary face: grab its patch
333  newOwner = slaveSideCell;
334  newNeighbour = -1;
335 
336  // Find out if the face flip is necessary
337  if (own[mf[facei]] == slaveSideCell)
338  {
339  flipFace = false;
340  }
341  else
342  {
343  flipFace = true;
344  }
345 
346  newPatchID = mesh.boundaryMesh().whichPatch(ftc[facei]);
347 
348  // The zone of the master face is preserved
349  newZoneID = mesh.faceZones().whichZone(mf[facei]);
350  }
351  else
352  {
353  // Both faces are internal: flip is decided based on which of the
354  // new cells around it has a lower label
355  newOwner = min(masterSideCell, slaveSideCell);
356  newNeighbour = max(masterSideCell, slaveSideCell);
357 
358  if (newOwner == own[mf[facei]] || newNeighbour == nei[mf[facei]])
359  {
360  flipFace = false;
361  }
362  else
363  {
364  flipFace = true;
365  }
366 
367  newPatchID = -1;
368 
369  // The zone of the master face is preserved
370  newZoneID = mesh.faceZones().whichZone(mf[facei]);
371  }
372 
373  // Modify the face and flip if necessary
374  face newFace = faces[mf[facei]];
375  bool zoneFlip = mfFlip[facei];
376 
377  if (flipFace)
378  {
379  newFace.flip();
380  zoneFlip = !zoneFlip;
381  }
382 
383  if (debug > 1)
384  {
385  Pout<< "Modifying face " << mf[facei]
386  << " newFace: " << newFace << nl
387  << " newOwner: " << newOwner
388  << " newNeighbour: " << newNeighbour
389  << " flipFace: " << flipFace
390  << " newPatchID: " << newPatchID
391  << " newZoneID: " << newZoneID << nl
392  << " oldOwn: " << own[mf[facei]];
393  if (newPatchID == -1)
394  {
395  Pout<< " oldNei: " << nei[mf[facei]];
396  }
397  Pout<< endl;
398  }
399 
400  ref.setAction
401  (
402  polyModifyFace
403  (
404  newFace, // modified face
405  mf[facei], // label of face being modified
406  newOwner, // owner
407  newNeighbour, // neighbour
408  flipFace, // flip
409  newPatchID, // patch for face
410  false, // remove from zone
411  newZoneID, // new zone
412  zoneFlip // face flip in zone
413  )
414  );
415  }
416 }
417 
418 
419 // ************************************************************************* //
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:608
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:670
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: ZoneMesh.C:346
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.