FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

detachInterface.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "attachDetach.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 #include <OpenFOAM/primitiveMesh.H>
00029 #include <dynamicMesh/polyTopoChange.H>
00030 #include <dynamicMesh/polyTopoChanger.H>
00031 #include <dynamicMesh/polyAddPoint.H>
00032 #include <dynamicMesh/polyModifyFace.H>
00033 #include <dynamicMesh/polyAddFace.H>
00034 
00035 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00036 
00037 void Foam::attachDetach::detachInterface
00038 (
00039     polyTopoChange& ref
00040 ) const
00041 {
00042     // Algorithm:
00043     // 1. Create new points for points of the master face zone
00044     // 2. Modify all faces of the master zone, by putting them into the master
00045     //    patch (look for orientation) and their renumbered mirror images
00046     //    into the slave patch
00047     // 3. Create a point renumbering list, giving a new point index for original
00048     //    points in the face patch
00049     // 4. Grab all faces in cells on the master side and renumber them 
00050     //    using the point renumbering list.  Exclude the ones that belong to
00051     //    the master face zone
00052     //
00053     // Note on point creation:
00054     // In order to take into account the issues related to partial
00055     // blocking in an attach/detach mesh modifier, special treatment
00056     // is required for the duplication of points on the edge of the
00057     // face zone.  Points which are shared only by internal edges need
00058     // not to be duplicated, as this would propagate the discontinuity
00059     // in the mesh beyond the face zone.  Therefore, before creating
00060     // the new points, check the external edge loop.  For each edge
00061     // check if the edge is internal (i.e. does not belong to a
00062     // patch); if so, exclude both of its points from duplication.
00063 
00064     if (debug)
00065     {
00066         Pout<< "void attachDetach::detachInterface("
00067             << "polyTopoChange& ref) const "
00068             << " for object " << name() << " : "
00069             << "Detaching interface" << endl;
00070     }
00071 
00072     const polyMesh& mesh = topoChanger().mesh();
00073     const faceZoneMesh& zoneMesh = mesh.faceZones();
00074 
00075     // Check that zone is in increasing order (needed since adding faces
00076     // in same order - otherwise polyTopoChange face ordering will mess up
00077     // correspondence)
00078     if (debug)
00079     {
00080         const labelList& faceLabels = zoneMesh[faceZoneID_.index()];
00081         if (faceLabels.size() > 0)
00082         {
00083             for (label i = 1; i < faceLabels.size(); i++)
00084             {
00085                 if (faceLabels[i] <= faceLabels[i-1])
00086                 {
00087                     FatalErrorIn
00088                     (
00089                         "attachDetach::detachInterface"
00090                         "(polyTopoChange&) const"
00091                     )   << "faceZone " << zoneMesh[faceZoneID_.index()].name()
00092                         << " does not have mesh face labels in"
00093                         << " increasing order." << endl
00094                         << "Face label " << faceLabels[i]
00095                         << " at position " << i
00096                         << " is smaller than the previous value "
00097                         << faceLabels[i-1]
00098                         << exit(FatalError);
00099                 }
00100             }
00101         }
00102     }
00103 
00104 
00105 
00106     const primitiveFacePatch& masterFaceLayer = zoneMesh[faceZoneID_.index()]();
00107     const pointField& points = mesh.points();
00108     const labelListList& meshEdgeFaces = mesh.edgeFaces();
00109 
00110     const labelList& mp = masterFaceLayer.meshPoints();
00111     const edgeList& zoneLocalEdges = masterFaceLayer.edges();
00112 
00113     const labelList& meshEdges = zoneMesh[faceZoneID_.index()].meshEdges();
00114 
00115     // Create the points
00116 
00117     labelList addedPoints(mp.size(), -1);
00118 
00119     // Go through boundary edges of the master patch.  If all the faces from
00120     // this patch are internal, mark the points in the addedPoints lookup
00121     // with their original labels to stop duplication
00122     label nIntEdges = masterFaceLayer.nInternalEdges();
00123 
00124     for (label curEdgeID = nIntEdges; curEdgeID < meshEdges.size(); curEdgeID++)
00125     {
00126         const labelList& curFaces = meshEdgeFaces[meshEdges[curEdgeID]];
00127 
00128         bool edgeIsInternal = true;
00129 
00130         forAll (curFaces, faceI)
00131         {
00132             if (!mesh.isInternalFace(curFaces[faceI]))
00133             {
00134                 // The edge belongs to a boundary face
00135                 edgeIsInternal = false;
00136                 break;
00137             }
00138         }
00139 
00140         if (edgeIsInternal)
00141         {
00142             const edge& e = zoneLocalEdges[curEdgeID];
00143 
00144             // Reset the point creation
00145             addedPoints[e.start()] = mp[e.start()];
00146             addedPoints[e.end()] = mp[e.end()];
00147         }
00148     }
00149 // Pout << "addedPoints before point creation: " << addedPoints << endl;
00150 
00151     // Create new points for face zone
00152     forAll (addedPoints, pointI)
00153     {
00154         if (addedPoints[pointI] < 0)
00155         {
00156             addedPoints[pointI] =
00157                 ref.setAction
00158                 (
00159                     polyAddPoint
00160                     (
00161                         points[mp[pointI]],        // point
00162                         mp[pointI],                // master point
00163                         -1,                        // zone ID
00164                         true                       // supports a cell
00165                     )
00166                 );
00167             //Pout<< "Adding point " << addedPoints[pointI]
00168             //    << " coord1:" << points[mp[pointI]]
00169             //    << " coord2:" << masterFaceLayer.localPoints()[pointI]
00170             //    << " for original point " << mp[pointI] << endl;
00171         }
00172     }
00173 
00174     // Modify faces in the master zone and duplicate for the slave zone
00175 
00176     const labelList& mf = zoneMesh[faceZoneID_.index()];
00177     const boolList& mfFlip = zoneMesh[faceZoneID_.index()].flipMap();
00178     const faceList& zoneFaces = masterFaceLayer.localFaces();
00179 
00180     const faceList& faces = mesh.faces();
00181     const labelList& own = mesh.faceOwner();
00182     const labelList& nei = mesh.faceNeighbour();
00183 
00184     forAll (mf, faceI)
00185     {
00186         const label curFaceID = mf[faceI];
00187 
00188         // Build the face for the slave patch by renumbering
00189         const face oldFace = zoneFaces[faceI].reverseFace();
00190 
00191         face newFace(oldFace.size());
00192 
00193         forAll (oldFace, pointI)
00194         {
00195             newFace[pointI] = addedPoints[oldFace[pointI]];
00196         }
00197 
00198         if (mfFlip[faceI])
00199         {
00200             // Face needs to be flipped for the master patch
00201             ref.setAction
00202             (
00203                 polyModifyFace
00204                 (
00205                     faces[curFaceID].reverseFace(), // modified face
00206                     curFaceID,                   // label of face being modified
00207                     nei[curFaceID],                 // owner
00208                     -1,                             // neighbour
00209                     true,                           // face flip
00210                     masterPatchID_.index(),         // patch for face
00211                     false,                          // remove from zone
00212                     faceZoneID_.index(),            // zone for face
00213                     !mfFlip[faceI]                  // face flip in zone
00214                 )
00215             );
00216 
00217             // Add renumbered face into the slave patch
00218             //label addedFaceI =
00219             ref.setAction
00220             (
00221                 polyAddFace
00222                 (
00223                     newFace,                        // face
00224                     own[curFaceID],                 // owner
00225                     -1,                             // neighbour
00226                     -1,                             // master point
00227                     -1,                             // master edge
00228                     curFaceID,                      // master face
00229                     false,                          // flip flux
00230                     slavePatchID_.index(),          // patch to add the face to
00231                     -1,                             // zone for face
00232                     false                           // zone flip
00233                 )
00234             );
00235             //{
00236             //    pointField newPts(ref.points());
00237             //Pout<< "Flip.  Modifying face: " << ref.faces()[curFaceID]
00238             //    << " fc:" <<  ref.faces()[curFaceID].centre(newPts)
00239             //    << " next to cell: " << nei[curFaceID]
00240             //    << " and adding face: " << newFace
00241             //    << " fc:" << ref.faces()[addedFaceI].centre(newPts)
00242             //    << " next to cell: " << own[curFaceID] << endl;
00243             //}
00244         }
00245         else
00246         {
00247             // No flip
00248             ref.setAction
00249             (
00250                 polyModifyFace
00251                 (
00252                     faces[curFaceID],         // modified face
00253                     curFaceID,                // label of face being modified
00254                     own[curFaceID],           // owner
00255                     -1,                       // neighbour
00256                     false,                    // face flip
00257                     masterPatchID_.index(),   // patch for face
00258                     false,                    // remove from zone
00259                     faceZoneID_.index(),      // zone for face
00260                     mfFlip[faceI]             // face flip in zone
00261                 )
00262             );
00263 
00264             // Add renumbered face into the slave patch
00265             //label addedFaceI =
00266             ref.setAction
00267             (
00268                 polyAddFace
00269                 (
00270                     newFace,                        // face
00271                     nei[curFaceID],                 // owner
00272                     -1,                             // neighbour
00273                     -1,                             // master point
00274                     -1,                             // master edge
00275                     curFaceID,                      // master face
00276                     true,                           // flip flux
00277                     slavePatchID_.index(),          // patch to add the face to
00278                     -1,                             // zone for face
00279                     false                           // face flip in zone
00280                 )
00281             );
00282             //{
00283             //    pointField newPts(ref.points());
00284             //Pout<< "No flip.  Modifying face: " << ref.faces()[curFaceID]
00285             //    << " fc:" <<  ref.faces()[curFaceID].centre(newPts)
00286             //    << " next to cell: " << own[curFaceID]
00287             //    << " and adding face: " << newFace
00288             //    << " fc:" << ref.faces()[addedFaceI].centre(newPts)
00289             //    << " next to cell: " << nei[curFaceID] << endl;
00290             //}
00291         }
00292     }
00293 
00294     // Modify the remaining faces of the master cells to reconnect to the new
00295     // layer of faces.
00296 
00297     // Algorithm: Go through all the cells of the master zone and make
00298     // a map of faces to avoid duplicates.  Do not insert the faces in
00299     // the master patch (as they have already been dealt with).  Make
00300     // a master layer point renumbering map, which for every point in
00301     // the master layer gives its new label. Loop through all faces in
00302     // the map and attempt to renumber them using the master layer
00303     // point renumbering map.  Once the face is renumbered, compare it
00304     // with the original face; if they are the same, the face has not
00305     // changed; if not, modify the face but keep all of its old
00306     // attributes (apart from the vertex numbers).
00307 
00308     // Create the map of faces in the master cell layer
00309     const labelList& mc =
00310         mesh.faceZones()[faceZoneID_.index()].masterCells();
00311 
00312     labelHashSet masterCellFaceMap(6*mc.size());
00313 
00314     const cellList& cells = mesh.cells();
00315 
00316     forAll (mc, cellI)
00317     {
00318         const labelList& curFaces = cells[mc[cellI]];
00319 
00320         forAll (curFaces, faceI)
00321         {
00322             // Check if the face belongs to the master patch; if not add it
00323             if (zoneMesh.whichZone(curFaces[faceI]) != faceZoneID_.index())
00324             {
00325                 masterCellFaceMap.insert(curFaces[faceI]);
00326             }
00327         }
00328     }
00329 
00330     // Extend the map to include first neighbours of the master cells to
00331     // deal with multiple corners.
00332     { // Protection and memory management
00333         // Make a map of master cells for quick reject
00334         labelHashSet mcMap(2*mc.size());
00335 
00336         forAll (mc, mcI)
00337         {
00338             mcMap.insert(mc[mcI]);
00339         }
00340 
00341         // Go through all the faces in the masterCellFaceMap.  If the
00342         // cells around them are not already used, add all of their
00343         // faces to the map
00344         const labelList mcf = masterCellFaceMap.toc();
00345 
00346         forAll (mcf, mcfI)
00347         {
00348             // Do the owner side
00349             const label ownCell = own[mcf[mcfI]];
00350 
00351             if (!mcMap.found(ownCell))
00352             {
00353                 // Cell not found. Add its faces to the map
00354                 const cell& curFaces = cells[ownCell];
00355 
00356                 forAll (curFaces, faceI)
00357                 {
00358                     masterCellFaceMap.insert(curFaces[faceI]);
00359                 }
00360             }
00361 
00362             // Do the neighbour side if face is internal
00363             if (mesh.isInternalFace(mcf[mcfI]))
00364             {
00365                 const label neiCell = nei[mcf[mcfI]];
00366 
00367                 if (!mcMap.found(neiCell))
00368                 {
00369                     // Cell not found. Add its faces to the map
00370                     const cell& curFaces = cells[neiCell];
00371 
00372                     forAll (curFaces, faceI)
00373                     {
00374                         masterCellFaceMap.insert(curFaces[faceI]);
00375                     }
00376                 }
00377             }
00378         }
00379     }
00380 
00381     // Create the master layer point map
00382     Map<label> masterLayerPointMap(2*mp.size());
00383 
00384     forAll (mp, pointI)
00385     {
00386         masterLayerPointMap.insert
00387         (
00388             mp[pointI],
00389             addedPoints[pointI]
00390         );
00391     }
00392 
00393     // Grab the list of faces of the master layer
00394     const labelList masterCellFaces = masterCellFaceMap.toc();
00395 
00396     forAll (masterCellFaces, faceI)
00397     {
00398         // Attempt to renumber the face using the masterLayerPointMap.
00399         // Missing point remain the same
00400 
00401         const label curFaceID = masterCellFaces[faceI];
00402 
00403         const face& oldFace = faces[curFaceID];
00404 
00405         face newFace(oldFace.size());
00406 
00407         bool changed = false;
00408 
00409         forAll (oldFace, pointI)
00410         {
00411             if (masterLayerPointMap.found(oldFace[pointI]))
00412             {
00413                 changed = true;
00414 
00415                 newFace[pointI] = masterLayerPointMap.find(oldFace[pointI])();
00416             }
00417             else
00418             {
00419                 newFace[pointI] = oldFace[pointI];
00420             }
00421         }
00422 
00423         // If the face has changed, create a modification entry
00424         if (changed)
00425         {
00426             if (mesh.isInternalFace(curFaceID))
00427             {
00428                 ref.setAction
00429                 (
00430                     polyModifyFace
00431                     (
00432                         newFace,                    // face
00433                         curFaceID,                  // master face
00434                         own[curFaceID],             // owner
00435                         nei[curFaceID],             // neighbour
00436                         false,                      // flip flux
00437                         -1,                         // patch for face
00438                         false,                      // remove from zone
00439                         -1,                         // zone for face
00440                         false                       // face zone flip
00441                     )
00442                 );
00443 // Pout << "modifying stick-out face. Internal Old face: " << oldFace << " new face: " << newFace << " own: " << own[curFaceID] << " nei: " << nei[curFaceID] << endl;
00444             }
00445             else
00446             {
00447                 ref.setAction
00448                 (
00449                     polyModifyFace
00450                     (
00451                         newFace,                     // face
00452                         curFaceID,                   // master face
00453                         own[curFaceID],              // owner
00454                         -1,                          // neighbour
00455                         false,                       // flip flux
00456                         mesh.boundaryMesh().whichPatch(curFaceID), // patch
00457                         false,                        // remove from zone
00458                         -1,                           // zone for face
00459                         false                         // face zone flip
00460                     )
00461                 );   
00462 // Pout << "modifying stick-out face. Boundary Old face: " << oldFace << " new face: " << newFace << " own: " << own[curFaceID] << " patch: " << mesh.boundaryMesh().whichPatch(curFaceID) << endl;
00463             }                                                  
00464         }
00465     }
00466 
00467     if (debug)
00468     {
00469         Pout<< "void attachDetach::detachInterface("
00470             << "polyTopoChange& ref) const "
00471             << " for object " << name() << " : "
00472             << "Finished detaching interface" << endl;
00473     }
00474 }
00475 
00476 
00477 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines