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
25 \*---------------------------------------------------------------------------*/
27 #include "layerAdditionRemoval.H"
29 #include "primitiveMesh.H"
30 #include "polyTopoChange.H"
31 #include "polyTopoChanger.H"
33 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
35 void Foam::layerAdditionRemoval::addCellLayer
40 // Insert the layer addition instructions into the topological change
43 // 1. For every point in the master zone add a new point
44 // 2. For every face in the master zone add a cell
45 // 3. Go through all the edges of the master zone. For all internal edges,
46 // add a face with the correct orientation and make it internal.
47 // For all boundary edges, find the patch it belongs to and add the face
49 // 4. Create a set of new faces on the patch image and assign them to be
50 // between the old master cells and the newly created cells
51 // 5. Modify all the faces in the patch such that they are located
52 // between the old slave cells and newly created cells
56 Pout<< "void layerAdditionRemoval::addCellLayer("
57 << "polyTopoChange& ref) const for object " << name() << " : "
58 << "Adding cell layer" << endl;
63 const polyMesh& mesh = topoChanger().mesh();
64 const primitiveFacePatch& masterFaceLayer =
65 mesh.faceZones()[faceZoneID_.index()]();
67 const pointField& points = mesh.points();
68 const labelList& mp = masterFaceLayer.meshPoints();
70 // Calculation of point normals, using point pairing
72 vectorField extrusionDir(mp.size());
74 if (setLayerPairing())
78 Pout<< "void layerAdditionRemoval::addCellLayer("
79 << "polyTopoChange& ref) const "
80 << " for object " << name() << " : "
81 << "Using edges for point insertion" << endl;
84 // Detected a valid layer. Grab the point and face collapse mapping
85 const labelList& ptc = pointsPairing();
87 forAll (extrusionDir, mpI)
89 extrusionDir[mpI] = points[ptc[mpI]] - points[mp[mpI]];
96 Pout<< "void layerAdditionRemoval::addCellLayer("
97 << "polyTopoChange& ref) const "
98 << " for object " << name() << " : "
99 << "A valid layer could not be found in front of "
100 << "the addition face layer. Using face-based "
101 << "point normals for point addition"
105 extrusionDir = minLayerThickness_*masterFaceLayer.pointNormals();
108 // Add the new points
109 labelList addedPoints(mp.size());
113 // Add the point nominal thickness away from the master zone point
114 // and grab the label
115 addedPoints[pointI] =
120 points[mp[pointI]] // point
121 // + addDelta_*maxLayerThickness_*extrusionDir[pointI],
122 + addDelta_*extrusionDir[pointI],
123 mp[pointI], // master point
124 -1, // zone for point
125 true // supports a cell
130 // Pout << "mp: " << mp << " addedPoints: " << addedPoints << endl;
133 const labelList& mc =
134 mesh.faceZones()[faceZoneID_.index()].masterCells();
135 const labelList& sc =
136 mesh.faceZones()[faceZoneID_.index()].slaveCells();
137 // Pout << "mc: " << mc << " sc: " << sc << endl;
138 const labelList& mf = mesh.faceZones()[faceZoneID_.index()];
139 const boolList& mfFlip = mesh.faceZones()[faceZoneID_.index()].flipMap();
141 const labelList& own = mesh.faceOwner();
142 const labelList& nei = mesh.faceNeighbour();
144 labelList addedCells(mf.size());
155 mf[faceI], // master face
162 // Create the new faces
164 // Grab the local faces from the master zone
165 const faceList& zoneFaces = masterFaceLayer.localFaces();
167 // Create the new faces by copying the master zone. All the added
168 // faces need to point into the newly created cells, which means
169 // all the faces from the master layer are flipped. The flux flip
170 // is determined from the original master layer face and the face
171 // owner: if the master cell is equal to the face owner the flux
172 // remains the same; otherwise it is flipped
174 forAll (zoneFaces, faceI)
176 const face oldFace = zoneFaces[faceI].reverseFace();
178 face newFace(oldFace.size());
180 forAll (oldFace, pointI)
182 newFace[pointI] = addedPoints[oldFace[pointI]];
185 bool flipFaceFlux = false;
187 // Flip the face as necessary
188 if (mesh.isInternalFace(mf[faceI]))
190 if (mc[faceI] == nei[mf[faceI]])
197 // Boundary face. Flip it
208 addedCells[faceI], // neighbour
211 mf[faceI], // master face for addition
212 flipFaceFlux, // flux flip
213 -1, // patch for face
215 false // face zone flip
219 // Pout << "adding face: " << newFace << " own: " << mc[faceI] << " nei: " << addedCells[faceI] << endl;
222 // Modify the faces from the master zone for the new neighbour
224 const faceList& faces = mesh.faces();
225 // Pout << "mfFlip: " << mfFlip << endl;
228 const label curfaceID = mf[faceI];
230 // If the face is internal, modify its owner to be the newly
231 // created cell. No flip is necessary
232 if (!mesh.isInternalFace(curfaceID))
238 faces[curfaceID], // modified face
239 curfaceID, // label of face being modified
240 addedCells[faceI], // owner
243 mesh.boundaryMesh().whichPatch(curfaceID),// patch for face
244 false, // remove from zone
245 faceZoneID_.index(), // zone for face
246 mfFlip[faceI] // face flip in zone
249 // Pout << "Modifying a boundary face. Face: " << curfaceID << " flip: " << mfFlip[faceI] << endl;
251 // If slave cell is owner, the face remains the same (but with
252 // a new neighbour - the newly created cell). Otherwise, the
254 else if (sc[faceI] == own[curfaceID])
256 // Orientation is good, just change neighbour
261 faces[curfaceID], // modified face
262 curfaceID, // label of face being modified
263 own[curfaceID], // owner
264 addedCells[faceI], // neighbour
266 mesh.boundaryMesh().whichPatch(curfaceID),// patch for face
267 false, // remove from zone
268 faceZoneID_.index(), // zone for face
269 mfFlip[faceI] // face flip in zone
273 // Pout << "modify face, no flip " << curfaceID << " own: " << own[curfaceID] << " nei: " << addedCells[faceI] << endl;
277 // Change in orientation; flip face
282 faces[curfaceID].reverseFace(), // modified face
283 curfaceID, // label of face being modified
284 nei[curfaceID], // owner
285 addedCells[faceI], // neighbour
287 mesh.boundaryMesh().whichPatch(curfaceID), // patch for face
288 false, // remove from zone
289 faceZoneID_.index(), // zone for face
290 !mfFlip[faceI] // face flip in zone
293 // Pout << "modify face, with flip " << curfaceID << " own: " << own[curfaceID] << " nei: " << addedCells[faceI] << endl;
297 // Create new faces from edges
299 const edgeList& zoneLocalEdges = masterFaceLayer.edges();
301 const labelListList& edgeFaces = masterFaceLayer.edgeFaces();
303 label nInternalEdges = masterFaceLayer.nInternalEdges();
305 const labelList& meshEdges =
306 mesh.faceZones()[faceZoneID_.index()].meshEdges();
308 // Do all internal edges
309 for (label curEdgeID = 0; curEdgeID < nInternalEdges; curEdgeID++)
313 newFace[0] = mp[zoneLocalEdges[curEdgeID].start()];
314 newFace[1] = mp[zoneLocalEdges[curEdgeID].end()];
315 newFace[2] = addedPoints[zoneLocalEdges[curEdgeID].end()];
316 newFace[3] = addedPoints[zoneLocalEdges[curEdgeID].start()];
323 addedCells[edgeFaces[curEdgeID][0]], // owner
324 addedCells[edgeFaces[curEdgeID][1]], // neighbour
326 meshEdges[curEdgeID], // master edge
329 -1, // patch for face
331 false // face zone flip
335 // Pout << "Add internal face off edge: " << newFace << " own: " << addedCells[edgeFaces[curEdgeID][0]] << " nei: " << addedCells[edgeFaces[curEdgeID][1]] << endl;
338 // Prepare creation of faces from boundary edges.
340 // A tricky part of the algorithm is finding the patch into which the
341 // newly created face will be added. For this purpose, take the edge
342 // and grab all the faces coming from it. From the set of faces
343 // eliminate the internal faces and find the boundary face from the rest.
344 // If there is more than one boundary face (excluding the ones in
345 // the master zone), the patch with the lower label is selected.
347 const labelListList& meshEdgeFaces = mesh.edgeFaces();
349 const faceZoneMesh& zoneMesh = mesh.faceZones();
351 // Do all boundary edges
355 label curEdgeID = nInternalEdges;
356 curEdgeID < zoneLocalEdges.size();
361 newFace[0] = mp[zoneLocalEdges[curEdgeID].start()];
362 newFace[1] = mp[zoneLocalEdges[curEdgeID].end()];
363 newFace[2] = addedPoints[zoneLocalEdges[curEdgeID].end()];
364 newFace[3] = addedPoints[zoneLocalEdges[curEdgeID].start()];
366 // Determine the patch for insertion
367 const labelList& curFaces = meshEdgeFaces[meshEdges[curEdgeID]];
372 forAll (curFaces, faceI)
374 const label cf = curFaces[faceI];
376 if (!mesh.isInternalFace(cf))
378 // Face not internal. Check if it is in the zone
379 if (zoneMesh.whichZone(cf) != faceZoneID_.index())
381 // Found the face in a boundary patch which is not in zone
382 patchID = mesh.boundaryMesh().whichPatch(cf);
383 zoneID = mesh.faceZones().whichZone(cf);
394 "void Foam::layerAdditionRemoval::setRefinement("
395 "polyTopoChange& ref)"
396 ) << "Cannot find patch for edge " << meshEdges[curEdgeID]
397 << ". Edge: " << mesh.edges()[meshEdges[curEdgeID]]
398 << abort(FatalError);
406 addedCells[edgeFaces[curEdgeID][0]], // owner
409 meshEdges[curEdgeID], // master edge
412 patchID, // patch for face
414 false // zone face flip
417 // Pout << "add boundary face: " << newFace << " into patch " << patchID << " own: " << addedCells[edgeFaces[curEdgeID][0]] << endl;
420 // Modify the remaining faces of the master cells to reconnect to the new
422 // Algorithm: Go through all the cells of the master zone and make
423 // a map of faces to avoid duplicates. Do not insert the faces in
424 // the master patch (as they have already been dealt with). Make
425 // a master layer point renumbering map, which for every point in
426 // the master layer gives its new label. Loop through all faces in
427 // the map and attempt to renumber them using the master layer
428 // point renumbering map. Once the face is renumbered, compare it
429 // with the original face; if they are the same, the face has not
430 // changed; if not, modify the face but keep all of its old
431 // attributes (apart from the vertex numbers).
433 // Create the map of faces in the master cell layer
434 labelHashSet masterCellFaceMap(primitiveMesh::facesPerCell_*mc.size());
436 const cellList& cells = mesh.cells();
440 const labelList& curFaces = cells[mc[cellI]];
442 forAll (curFaces, faceI)
444 // Check if the face belongs to the master zone; if not add it
445 if (zoneMesh.whichZone(curFaces[faceI]) != faceZoneID_.index())
447 masterCellFaceMap.insert(curFaces[faceI]);
452 // Create the master layer point map
453 Map<label> masterLayerPointMap(2*mp.size());
457 masterLayerPointMap.insert
464 // Grab the list of faces of the master layer
465 const labelList masterCellFaces = masterCellFaceMap.toc();
467 forAll (masterCellFaces, faceI)
469 // Attempt to renumber the face using the masterLayerPointMap.
470 // Missing point remain the same
472 const label curFaceID = masterCellFaces[faceI];
474 const face& oldFace = faces[curFaceID];
476 face newFace(oldFace.size());
478 bool changed = false;
480 forAll (oldFace, pointI)
482 if (masterLayerPointMap.found(oldFace[pointI]))
486 newFace[pointI] = masterLayerPointMap.find(oldFace[pointI])();
490 newFace[pointI] = oldFace[pointI];
494 // If the face has changed, create a modification entry
497 // Get face zone and its flip
498 label modifiedFaceZone = mesh.faceZones().whichZone(curFaceID);
499 bool modifiedFaceZoneFlip = false;
501 if (modifiedFaceZone >= 0)
503 modifiedFaceZoneFlip =
504 mesh.faceZones()[modifiedFaceZone].flipMap()
506 mesh.faceZones()[modifiedFaceZone].whichFace(curFaceID)
510 if (mesh.isInternalFace(curFaceID))
516 newFace, // modified face
517 curFaceID, // label of face being modified
518 own[curFaceID], // owner
519 nei[curFaceID], // neighbour
521 -1, // patch for face
522 false, // remove from zone
523 modifiedFaceZone, // zone for face
524 modifiedFaceZoneFlip // face flip in zone
527 // Pout << "modifying stick-out face. Internal Old face: " << oldFace << " new face: " << newFace << " own: " << own[curFaceID] << " nei: " << nei[curFaceID] << endl;
535 newFace, // modified face
536 curFaceID, // label of face being modified
537 own[curFaceID], // owner
540 mesh.boundaryMesh().whichPatch(curFaceID), // patch for face
541 false, // remove from zone
542 modifiedFaceZone, // zone for face
543 modifiedFaceZoneFlip // face flip in zone
546 // Pout << "modifying stick-out face. Boundary Old face: " << oldFace << " new face: " << newFace << " own: " << own[curFaceID] << " patch: " << mesh.boundaryMesh().whichPatch(curFaceID) << endl;
553 Pout<< "void layerAdditionRemoval::addCellLayer("
554 << "polyTopoChange& ref) const "
555 << " for object " << name() << " : "
556 << "Finished adding cell layer" << endl;
561 // ************************************************************************* //