1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 Remove a layer of cells and prepare addressing data
28 \*---------------------------------------------------------------------------*/
30 #include "layerAdditionRemoval.H"
32 #include "primitiveMesh.H"
33 #include "polyTopoChange.H"
34 #include "oppositeFace.H"
35 #include "polyTopoChanger.H"
37 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
39 bool Foam::layerAdditionRemoval::validCollapse() const
41 // Check for valid layer collapse
42 // - no boundary-to-boundary collapse
46 Pout << "Checking layer collapse for object " << name() << endl;
49 // Grab the face collapse mapping
50 const polyMesh& mesh = topoChanger().mesh();
52 const labelList& ftc = facesPairing();
53 const labelList& mf = mesh.faceZones()[faceZoneID_.index()];
55 label nBoundaryHits = 0;
61 !mesh.isInternalFace(mf[faceI])
62 && !mesh.isInternalFace(ftc[faceI])
72 Pout<< "Finished checking layer collapse for object "
73 << name() <<". Number of boundary-on-boundary hits: "
74 << nBoundaryHits << endl;
77 if (returnReduce(nBoundaryHits, sumOp<label>()) > 0)
87 void Foam::layerAdditionRemoval::removeCellLayer
92 // Algorithm for layer removal. Second phase: topological change
93 // 2) Go through all the faces of the master cell layer and remove
94 // the ones that are not in the master face zone.
96 // 3) Grab all the faces coming out of points that are collapsed
97 // and select the ones that are not marked for removal. Go
98 // through the remaining faces and replace the point to remove by
99 // the equivalent point in the master face zone.
102 Pout << "Removing the cell layer for object " << name() << endl;
105 const polyMesh& mesh = topoChanger().mesh();
107 const labelList& ptc = pointsPairing();
108 const labelList& ftc = facesPairing();
110 // Remove all the cells from the master layer
111 const labelList& mc =
112 topoChanger().mesh().faceZones()[faceZoneID_.index()].masterCells();
116 ref.setAction(polyRemoveCell(mc[cellI]));
119 // Remove all the faces from the master layer cells which are not in
120 // the master face layer
121 labelHashSet facesToRemoveMap(mc.size()*primitiveMesh::facesPerCell_);
123 const cellList& cells = mesh.cells();
127 const cell& curCell = cells[mc[cellI]];
129 forAll (curCell, faceI)
131 // Check if the face is in the master zone. If not, remove it
134 mesh.faceZones().whichZone(curCell[faceI])
135 != faceZoneID_.index()
138 facesToRemoveMap.insert(curCell[faceI]);
143 forAllConstIter(labelHashSet, facesToRemoveMap, iter)
145 ref.setAction(polyRemoveFace(iter.key()));
148 // Remove all points that will be collapsed
151 ref.setAction(polyRemovePoint(ptc[pointI]));
154 // Grab all faces coming off points to be deleted. If the face
155 // has not been deleted, replace the removed point with the
156 // equivalent from the master layer.
158 // Make a map of all point to be removed, giving the master point label
161 Map<label> removedPointMap(2*ptc.size());
163 const labelList& meshPoints =
164 mesh.faceZones()[faceZoneID_.index()]().meshPoints();
168 removedPointMap.insert(ptc[pointI], meshPoints[pointI]);
171 const labelListList& pf = mesh.pointFaces();
173 const faceList& faces = mesh.faces();
174 const labelList& own = mesh.faceOwner();
175 const labelList& nei = mesh.faceNeighbour();
177 // Make a list of faces to be modified using the map to avoid duplicates
178 labelHashSet facesToModify(ptc.size()*primitiveMesh::facesPerPoint_);
182 const labelList& curFaces = pf[ptc[pointI]];
184 forAll (curFaces, faceI)
186 if (!facesToRemoveMap.found(curFaces[faceI]))
188 facesToModify.insert(curFaces[faceI]);
193 labelList ftm = facesToModify.toc();
195 //Pout << "faces to modify: " << ftm << endl;
199 // For every face to modify, copy the face and re-map the vertices.
200 // It is known all the faces will be changed since they hang off
201 // re-mapped vertices
202 label curFaceID = ftm[faceI];
204 face newFace(faces[curFaceID]);
206 forAll (newFace, pointI)
208 Map<label>::iterator rpmIter =
209 removedPointMap.find(newFace[pointI]);
211 if (rpmIter != removedPointMap.end())
213 // Point mapped. Replace it
214 newFace[pointI] = rpmIter();
218 //Pout<< "face label: " << curFaceID
219 // << " old face: " << faces[curFaceID]
220 // << " new face: " << newFace << endl;
222 // Get face zone and its flip
223 label modifiedFaceZone = mesh.faceZones().whichZone(curFaceID);
224 bool modifiedFaceZoneFlip = false;
226 if (modifiedFaceZone >= 0)
228 modifiedFaceZoneFlip =
229 mesh.faceZones()[modifiedFaceZone].flipMap()
231 mesh.faceZones()[modifiedFaceZone].whichFace(curFaceID)
235 label newNeighbour = -1;
237 if (curFaceID < mesh.nInternalFaces())
239 newNeighbour = nei[curFaceID];
251 newFace, // modified face
252 curFaceID, // label of face being modified
253 own[curFaceID], // owner
254 newNeighbour, // neighbour
256 mesh.boundaryMesh().whichPatch(curFaceID),// patch for face
257 false, // remove from zone
258 modifiedFaceZone, // zone for face
259 modifiedFaceZoneFlip // face flip in zone
264 // Modify the faces in the master layer to point past the removed cells
266 const labelList& mf = mesh.faceZones()[faceZoneID_.index()];
267 const boolList& mfFlip = mesh.faceZones()[faceZoneID_.index()].flipMap();
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]];
275 if (masterSideCell == mc[faceI])
277 // Owner cell of the face is being removed.
278 // Grab the neighbour instead
279 if (mesh.isInternalFace(mf[faceI]))
281 masterSideCell = nei[mf[faceI]];
289 label slaveSideCell = own[ftc[faceI]];
291 if (slaveSideCell == mc[faceI])
293 // Owner cell of the face is being removed.
294 // Grab the neighbour instead
295 if (mesh.isInternalFace(ftc[faceI]))
297 slaveSideCell = nei[ftc[faceI]];
305 // Find out if the face needs to be flipped
307 label newNeighbour = -1;
308 bool flipFace = false;
309 label newPatchID = -1;
310 label newZoneID = -1;
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 cannnot happen here.
316 if (!mesh.isInternalFace(mf[faceI]))
318 // Master is the boundary face: it gets a new owner but no flip
319 newOwner = slaveSideCell;
322 newPatchID = mesh.boundaryMesh().whichPatch(mf[faceI]);
323 newZoneID = mesh.faceZones().whichZone(mf[faceI]);
325 else if (!mesh.isInternalFace(ftc[faceI]))
327 // Slave is the boundary face: grab its patch
328 newOwner = slaveSideCell;
331 // Find out if the face flip is necessary
332 if (own[mf[faceI]] == slaveSideCell)
341 newPatchID = mesh.boundaryMesh().whichPatch(ftc[faceI]);
343 // The zone of the master face is preserved
344 newZoneID = mesh.faceZones().whichZone(mf[faceI]);
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);
353 if (newOwner == own[mf[faceI]] || newNeighbour == nei[mf[faceI]])
364 // The zone of the master face is preserved
365 newZoneID = mesh.faceZones().whichZone(mf[faceI]);
368 // Modify the face and flip if necessary
369 face newFace = faces[mf[faceI]];
370 bool zoneFlip = mfFlip[faceI];
374 newFace = newFace.reverseFace();
375 zoneFlip = !zoneFlip;
378 // Pout<< "Modifying face " << mf[faceI]
379 // << " newFace: " << newFace << nl
380 // << " newOwner: " << newOwner
381 // << " newNeighbour: " << newNeighbour
382 // << " flipFace: " << flipFace
383 // << " newPatchID: " << newPatchID
384 // << " newZoneID: " << newZoneID << nl
385 // << " oldOwn: " << own[mf[faceI]]
386 // << " oldNei: " << nei[mf[faceI]] << endl;
392 newFace, // modified face
393 mf[faceI], // label of face being modified
395 newNeighbour, // neighbour
397 newPatchID, // patch for face
398 false, // remove from zone
399 newZoneID, // new zone
400 zoneFlip // face flip in zone
407 // ************************************************************************* //