1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "attachDetach.H"
28 #include "primitiveMesh.H"
29 #include "polyTopoChange.H"
30 #include "polyTopoChanger.H"
31 #include "polyAddPoint.H"
32 #include "polyModifyFace.H"
33 #include "polyAddFace.H"
35 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37 void Foam::attachDetach::detachInterface
43 // 1. Create new points for points of the master face zone
44 // 2. Modify all faces of the master zone, by putting them into the master
45 // patch (look for orientation) and their renumbered mirror images
46 // into the slave patch
47 // 3. Create a point renumbering list, giving a new point index for original
48 // points in the face patch
49 // 4. Grab all faces in cells on the master side and renumber them
50 // using the point renumbering list. Exclude the ones that belong to
51 // the master face zone
53 // Note on point creation:
54 // In order to take into account the issues related to partial
55 // blocking in an attach/detach mesh modifier, special treatment
56 // is required for the duplication of points on the edge of the
57 // face zone. Points which are shared only by internal edges need
58 // not to be duplicated, as this would propagate the discontinuity
59 // in the mesh beyond the face zone. Therefore, before creating
60 // the new points, check the external edge loop. For each edge
61 // check if the edge is internal (i.e. does not belong to a
62 // patch); if so, exclude both of its points from duplication.
66 Pout<< "void attachDetach::detachInterface("
67 << "polyTopoChange& ref) const "
68 << " for object " << name() << " : "
69 << "Detaching interface" << endl;
72 const polyMesh& mesh = topoChanger().mesh();
73 const faceZoneMesh& zoneMesh = mesh.faceZones();
75 // Check that zone is in increasing order (needed since adding faces
76 // in same order - otherwise polyTopoChange face ordering will mess up
80 const labelList& faceLabels = zoneMesh[faceZoneID_.index()];
81 if (faceLabels.size() > 0)
83 for (label i = 1; i < faceLabels.size(); i++)
85 if (faceLabels[i] <= faceLabels[i-1])
89 "attachDetach::detachInterface"
90 "(polyTopoChange&) const"
91 ) << "faceZone " << zoneMesh[faceZoneID_.index()].name()
92 << " does not have mesh face labels in"
93 << " increasing order." << endl
94 << "Face label " << faceLabels[i]
95 << " at position " << i
96 << " is smaller than the previous value "
106 const primitiveFacePatch& masterFaceLayer = zoneMesh[faceZoneID_.index()]();
107 const pointField& points = mesh.points();
108 const labelListList& meshEdgeFaces = mesh.edgeFaces();
110 const labelList& mp = masterFaceLayer.meshPoints();
111 const edgeList& zoneLocalEdges = masterFaceLayer.edges();
113 const labelList& meshEdges = zoneMesh[faceZoneID_.index()].meshEdges();
117 labelList addedPoints(mp.size(), -1);
119 // Go through boundary edges of the master patch. If all the faces from
120 // this patch are internal, mark the points in the addedPoints lookup
121 // with their original labels to stop duplication
122 label nIntEdges = masterFaceLayer.nInternalEdges();
124 for (label curEdgeID = nIntEdges; curEdgeID < meshEdges.size(); curEdgeID++)
126 const labelList& curFaces = meshEdgeFaces[meshEdges[curEdgeID]];
128 bool edgeIsInternal = true;
130 forAll (curFaces, faceI)
132 if (!mesh.isInternalFace(curFaces[faceI]))
134 // The edge belongs to a boundary face
135 edgeIsInternal = false;
142 const edge& e = zoneLocalEdges[curEdgeID];
144 // Reset the point creation
145 addedPoints[e.start()] = mp[e.start()];
146 addedPoints[e.end()] = mp[e.end()];
149 // Pout << "addedPoints before point creation: " << addedPoints << endl;
151 // Create new points for face zone
152 forAll (addedPoints, pointI)
154 if (addedPoints[pointI] < 0)
156 addedPoints[pointI] =
161 points[mp[pointI]], // point
162 mp[pointI], // master point
164 true // supports a cell
167 //Pout<< "Adding point " << addedPoints[pointI]
168 // << " coord1:" << points[mp[pointI]]
169 // << " coord2:" << masterFaceLayer.localPoints()[pointI]
170 // << " for original point " << mp[pointI] << endl;
174 // Modify faces in the master zone and duplicate for the slave zone
176 const labelList& mf = zoneMesh[faceZoneID_.index()];
177 const boolList& mfFlip = zoneMesh[faceZoneID_.index()].flipMap();
178 const faceList& zoneFaces = masterFaceLayer.localFaces();
180 const faceList& faces = mesh.faces();
181 const labelList& own = mesh.faceOwner();
182 const labelList& nei = mesh.faceNeighbour();
186 const label curFaceID = mf[faceI];
188 // Build the face for the slave patch by renumbering
189 const face oldFace = zoneFaces[faceI].reverseFace();
191 face newFace(oldFace.size());
193 forAll (oldFace, pointI)
195 newFace[pointI] = addedPoints[oldFace[pointI]];
200 // Face needs to be flipped for the master patch
205 faces[curFaceID].reverseFace(), // modified face
206 curFaceID, // label of face being modified
207 nei[curFaceID], // owner
210 masterPatchID_.index(), // patch for face
211 false, // remove from zone
212 faceZoneID_.index(), // zone for face
213 !mfFlip[faceI] // face flip in zone
217 // Add renumbered face into the slave patch
224 own[curFaceID], // owner
228 curFaceID, // master face
230 slavePatchID_.index(), // patch to add the face to
236 // pointField newPts(ref.points());
237 //Pout<< "Flip. Modifying face: " << ref.faces()[curFaceID]
238 // << " fc:" << ref.faces()[curFaceID].centre(newPts)
239 // << " next to cell: " << nei[curFaceID]
240 // << " and adding face: " << newFace
241 // << " fc:" << ref.faces()[addedFaceI].centre(newPts)
242 // << " next to cell: " << own[curFaceID] << endl;
252 faces[curFaceID], // modified face
253 curFaceID, // label of face being modified
254 own[curFaceID], // owner
257 masterPatchID_.index(), // patch for face
258 false, // remove from zone
259 faceZoneID_.index(), // zone for face
260 mfFlip[faceI] // face flip in zone
264 // Add renumbered face into the slave patch
271 nei[curFaceID], // owner
275 curFaceID, // master face
277 slavePatchID_.index(), // patch to add the face to
279 false // face flip in zone
283 // pointField newPts(ref.points());
284 //Pout<< "No flip. Modifying face: " << ref.faces()[curFaceID]
285 // << " fc:" << ref.faces()[curFaceID].centre(newPts)
286 // << " next to cell: " << own[curFaceID]
287 // << " and adding face: " << newFace
288 // << " fc:" << ref.faces()[addedFaceI].centre(newPts)
289 // << " next to cell: " << nei[curFaceID] << endl;
294 // Modify the remaining faces of the master cells to reconnect to the new
297 // Algorithm: Go through all the cells of the master zone and make
298 // a map of faces to avoid duplicates. Do not insert the faces in
299 // the master patch (as they have already been dealt with). Make
300 // a master layer point renumbering map, which for every point in
301 // the master layer gives its new label. Loop through all faces in
302 // the map and attempt to renumber them using the master layer
303 // point renumbering map. Once the face is renumbered, compare it
304 // with the original face; if they are the same, the face has not
305 // changed; if not, modify the face but keep all of its old
306 // attributes (apart from the vertex numbers).
308 // Create the map of faces in the master cell layer
309 const labelList& mc =
310 mesh.faceZones()[faceZoneID_.index()].masterCells();
312 labelHashSet masterCellFaceMap(6*mc.size());
314 const cellList& cells = mesh.cells();
318 const labelList& curFaces = cells[mc[cellI]];
320 forAll (curFaces, faceI)
322 // Check if the face belongs to the master patch; if not add it
323 if (zoneMesh.whichZone(curFaces[faceI]) != faceZoneID_.index())
325 masterCellFaceMap.insert(curFaces[faceI]);
330 // Extend the map to include first neighbours of the master cells to
331 // deal with multiple corners.
332 { // Protection and memory management
333 // Make a map of master cells for quick reject
334 labelHashSet mcMap(2*mc.size());
338 mcMap.insert(mc[mcI]);
341 // Go through all the faces in the masterCellFaceMap. If the
342 // cells around them are not already used, add all of their
344 const labelList mcf = masterCellFaceMap.toc();
349 const label ownCell = own[mcf[mcfI]];
351 if (!mcMap.found(ownCell))
353 // Cell not found. Add its faces to the map
354 const cell& curFaces = cells[ownCell];
356 forAll (curFaces, faceI)
358 masterCellFaceMap.insert(curFaces[faceI]);
362 // Do the neighbour side if face is internal
363 if (mesh.isInternalFace(mcf[mcfI]))
365 const label neiCell = nei[mcf[mcfI]];
367 if (!mcMap.found(neiCell))
369 // Cell not found. Add its faces to the map
370 const cell& curFaces = cells[neiCell];
372 forAll (curFaces, faceI)
374 masterCellFaceMap.insert(curFaces[faceI]);
381 // Create the master layer point map
382 Map<label> masterLayerPointMap(2*mp.size());
386 masterLayerPointMap.insert
393 // Grab the list of faces of the master layer
394 const labelList masterCellFaces = masterCellFaceMap.toc();
396 forAll (masterCellFaces, faceI)
398 // Attempt to renumber the face using the masterLayerPointMap.
399 // Missing point remain the same
401 const label curFaceID = masterCellFaces[faceI];
403 const face& oldFace = faces[curFaceID];
405 face newFace(oldFace.size());
407 bool changed = false;
409 forAll (oldFace, pointI)
411 if (masterLayerPointMap.found(oldFace[pointI]))
415 newFace[pointI] = masterLayerPointMap.find(oldFace[pointI])();
419 newFace[pointI] = oldFace[pointI];
423 // If the face has changed, create a modification entry
426 if (mesh.isInternalFace(curFaceID))
433 curFaceID, // master face
434 own[curFaceID], // owner
435 nei[curFaceID], // neighbour
437 -1, // patch for face
438 false, // remove from zone
440 false // face zone flip
443 // Pout << "modifying stick-out face. Internal Old face: " << oldFace << " new face: " << newFace << " own: " << own[curFaceID] << " nei: " << nei[curFaceID] << endl;
452 curFaceID, // master face
453 own[curFaceID], // owner
456 mesh.boundaryMesh().whichPatch(curFaceID), // patch
457 false, // remove from zone
459 false // face zone flip
462 // Pout << "modifying stick-out face. Boundary Old face: " << oldFace << " new face: " << newFace << " own: " << own[curFaceID] << " patch: " << mesh.boundaryMesh().whichPatch(curFaceID) << endl;
469 Pout<< "void attachDetach::detachInterface("
470 << "polyTopoChange& ref) const "
471 << " for object " << name() << " : "
472 << "Finished detaching interface" << endl;
477 // ************************************************************************* //