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

addCellLayer.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 "layerAdditionRemoval.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/polyAddCell.H>
00033 #include <dynamicMesh/polyAddFace.H>
00034 #include <dynamicMesh/polyModifyFace.H>
00035 
00036 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00037 
00038 //- Calculate the offset to the next layer
00039 Foam::tmp<Foam::vectorField> Foam::layerAdditionRemoval::extrusionDir() const
00040 {
00041     const polyMesh& mesh = topoChanger().mesh();
00042     const primitiveFacePatch& masterFaceLayer =
00043         mesh.faceZones()[faceZoneID_.index()]();
00044 
00045     const pointField& points = mesh.points();
00046     const labelList& mp = masterFaceLayer.meshPoints();
00047 
00048     tmp<vectorField> textrusionDir(new vectorField(mp.size()));
00049     vectorField& extrusionDir = textrusionDir();
00050 
00051     if (setLayerPairing())
00052     {
00053         if (debug)
00054         {
00055             Pout<< "void layerAdditionRemoval::extrusionDir() const "
00056                 << " for object " << name() << " : "
00057                 << "Using edges for point insertion" << endl;
00058         }
00059 
00060         // Detected a valid layer.  Grab the point and face collapse mapping
00061         const labelList& ptc = pointsPairing();
00062 
00063         forAll (extrusionDir, mpI)
00064         {
00065             extrusionDir[mpI] = points[ptc[mpI]] - points[mp[mpI]];
00066         }
00067     }
00068     else
00069     {
00070         if (debug)
00071         {
00072             Pout<< "void layerAdditionRemoval::extrusionDir() const "
00073                 << " for object " << name() << " : "
00074                 << "A valid layer could not be found in front of "
00075                 << "the addition face layer.  Using face-based "
00076                 << "point normals for point addition"
00077                 << endl;
00078         }
00079 
00080         extrusionDir = minLayerThickness_*masterFaceLayer.pointNormals();
00081     }
00082     return textrusionDir;
00083 }
00084 
00085 
00086 void Foam::layerAdditionRemoval::addCellLayer
00087 (
00088     polyTopoChange& ref
00089 ) const
00090 {
00091     // Insert the layer addition instructions into the topological change
00092 
00093     // Algorithm:
00094     // 1.  For every point in the master zone add a new point
00095     // 2.  For every face in the master zone add a cell
00096     // 3.  Go through all the edges of the master zone.  For all internal edges,
00097     //     add a face with the correct orientation and make it internal.
00098     //     For all boundary edges, find the patch it belongs to and add the face
00099     //     to this patch
00100     // 4.  Create a set of new faces on the patch image and assign them to be
00101     //     between the old master cells and the newly created cells
00102     // 5.  Modify all the faces in the patch such that they are located
00103     //     between the old slave cells and newly created cells
00104 
00105     if (debug)
00106     {
00107         Pout<< "void layerAdditionRemoval::addCellLayer("
00108             << "polyTopoChange& ref) const for object " << name() << " : "
00109             << "Adding cell layer" << endl;
00110     }
00111 
00112     // Create the points
00113 
00114     const polyMesh& mesh = topoChanger().mesh();
00115     const primitiveFacePatch& masterFaceLayer =
00116         mesh.faceZones()[faceZoneID_.index()]();
00117 
00118     const pointField& points = mesh.points();
00119     const labelList& mp = masterFaceLayer.meshPoints();
00120 
00121     // Get the extrusion direction for the added points
00122 
00123     tmp<vectorField> tpointOffsets = extrusionDir();
00124 
00125     // Add the new points
00126     labelList addedPoints(mp.size());
00127 
00128     forAll (mp, pointI)
00129     {
00130         // Add the point nominal thickness away from the master zone point
00131         // and grab the label
00132         addedPoints[pointI] =
00133             ref.setAction
00134             (
00135                 polyAddPoint
00136                 (
00137                     points[mp[pointI]]                  // point
00138                   + addDelta_*tpointOffsets()[pointI],
00139                     mp[pointI],                         // master point
00140                     -1,                                 // zone for point
00141                     true                                // supports a cell
00142                 )
00143             );
00144     }
00145 
00146 // Pout << "mp: " << mp << " addedPoints: " << addedPoints << endl;
00147     // Create the cells
00148 
00149     const labelList& mc =
00150         mesh.faceZones()[faceZoneID_.index()].masterCells();
00151     const labelList& sc =
00152         mesh.faceZones()[faceZoneID_.index()].slaveCells();
00153 // Pout << "mc: " << mc << " sc: " << sc << endl;
00154     const labelList& mf = mesh.faceZones()[faceZoneID_.index()];
00155     const boolList& mfFlip = mesh.faceZones()[faceZoneID_.index()].flipMap();
00156 
00157     const labelList& own = mesh.faceOwner();
00158     const labelList& nei = mesh.faceNeighbour();
00159 
00160     labelList addedCells(mf.size());
00161 
00162     forAll (mf, faceI)
00163     {
00164         addedCells[faceI] =
00165             ref.setAction
00166             (
00167                 polyAddCell
00168                 (
00169                     -1,           // master point
00170                     -1,           // master edge
00171                     mf[faceI],    // master face
00172                     -1,           // master cell
00173                     -1            // zone for cell
00174                 )
00175             );
00176     }
00177 
00178     // Create the new faces
00179 
00180     // Grab the local faces from the master zone
00181     const faceList& zoneFaces = masterFaceLayer.localFaces();
00182 
00183     // Create the new faces by copying the master zone.  All the added
00184     // faces need to point into the newly created cells, which means
00185     // all the faces from the master layer are flipped.  The flux flip
00186     // is determined from the original master layer face and the face
00187     // owner: if the master cell is equal to the face owner the flux
00188     // remains the same; otherwise it is flipped
00189 
00190     forAll (zoneFaces, faceI)
00191     {
00192         const face oldFace = zoneFaces[faceI].reverseFace();
00193 
00194         face newFace(oldFace.size());
00195 
00196         forAll (oldFace, pointI)
00197         {
00198             newFace[pointI] = addedPoints[oldFace[pointI]];
00199         }
00200 
00201         bool flipFaceFlux = false;
00202 
00203         // Flip the face as necessary
00204         if
00205         (
00206             mc[faceI] == nei[mf[faceI]]
00207          || !mesh.isInternalFace(mf[faceI])
00208         )
00209         {
00210             flipFaceFlux = true;
00211         }
00212 
00213         // Add the face
00214         ref.setAction
00215         (
00216             polyAddFace
00217             (
00218                 newFace,               // face
00219                 mc[faceI],             // owner
00220                 addedCells[faceI],     // neighbour
00221                 -1,                    // master point
00222                 -1,                    // master edge
00223                 mf[faceI],             // master face for addition
00224                 flipFaceFlux,          // flux flip
00225                 -1,                    // patch for face
00226                 -1,                    // zone for face
00227                 false                  // face zone flip
00228             )
00229         );
00230 
00231 // Pout << "adding face: " << newFace << " own: " << mc[faceI] << " nei: " << addedCells[faceI] << endl;
00232     }
00233 
00234     // Modify the faces from the master zone for the new neighbour
00235 
00236     const faceList& faces = mesh.faces();
00237 // Pout << "mfFlip: " << mfFlip << endl;
00238     forAll (mf, faceI)
00239     {
00240         const label curfaceID = mf[faceI];
00241 
00242         // If the face is internal, modify its owner to be the newly
00243         // created cell.  No flip is necessary
00244         if (!mesh.isInternalFace(curfaceID))
00245         {
00246             ref.setAction
00247             (
00248                 polyModifyFace
00249                 (
00250                     faces[curfaceID],            // modified face
00251                     curfaceID,                   // label of face being modified
00252                     addedCells[faceI],           // owner
00253                     -1,                          // neighbour
00254                     false,                       // face flip
00255                     mesh.boundaryMesh().whichPatch(curfaceID),// patch for face
00256                     false,                       // remove from zone
00257                     faceZoneID_.index(),         // zone for face
00258                     mfFlip[faceI]                // face flip in zone
00259                 )
00260             );
00261 // Pout << "Modifying a boundary face. Face: " << curfaceID << " flip: " << mfFlip[faceI] << endl;
00262         }
00263         // If slave cell is owner, the face remains the same (but with
00264         // a new neighbour - the newly created cell).  Otherwise, the
00265         // face is flipped.
00266         else if (sc[faceI] == own[curfaceID])
00267         {
00268             // Orientation is good, just change neighbour
00269             ref.setAction
00270             (
00271                 polyModifyFace
00272                 (
00273                     faces[curfaceID],            // modified face
00274                     curfaceID,                   // label of face being modified
00275                     own[curfaceID],              // owner
00276                     addedCells[faceI],           // neighbour
00277                     false,                       // face flip
00278                     mesh.boundaryMesh().whichPatch(curfaceID),// patch for face
00279                     false,                       // remove from zone
00280                     faceZoneID_.index(),         // zone for face
00281                     mfFlip[faceI]                // face flip in zone
00282                 )
00283             );
00284 
00285 // Pout << "modify face, no flip " << curfaceID << " own: " << own[curfaceID] << " nei: " << addedCells[faceI] << endl;
00286         }
00287         else
00288         {
00289             // Change in orientation; flip face
00290             ref.setAction
00291             (
00292                 polyModifyFace
00293                 (
00294                     faces[curfaceID].reverseFace(), // modified face
00295                     curfaceID,                   // label of face being modified
00296                     nei[curfaceID],                 // owner
00297                     addedCells[faceI],              // neighbour
00298                     true,                           // face flip
00299                     mesh.boundaryMesh().whichPatch(curfaceID), // patch for face
00300                     false,                          // remove from zone
00301                     faceZoneID_.index(),            // zone for face
00302                     !mfFlip[faceI]                  // face flip in zone
00303                 )
00304             );
00305 // Pout << "modify face, with flip " << curfaceID << " own: " << own[curfaceID] << " nei: " << addedCells[faceI] << endl;
00306         }
00307     }
00308 
00309     // Create new faces from edges
00310 
00311     const edgeList& zoneLocalEdges = masterFaceLayer.edges();
00312 
00313     const labelListList& edgeFaces = masterFaceLayer.edgeFaces();
00314 
00315     label nInternalEdges = masterFaceLayer.nInternalEdges();
00316 
00317     const labelList& meshEdges =
00318         mesh.faceZones()[faceZoneID_.index()].meshEdges();
00319 
00320     // Do all internal edges
00321     for (label curEdgeID = 0; curEdgeID < nInternalEdges; curEdgeID++)
00322     {
00323         face newFace(4);
00324 
00325         newFace[0] = mp[zoneLocalEdges[curEdgeID].start()];
00326         newFace[1] = mp[zoneLocalEdges[curEdgeID].end()];
00327         newFace[2] = addedPoints[zoneLocalEdges[curEdgeID].end()];
00328         newFace[3] = addedPoints[zoneLocalEdges[curEdgeID].start()];
00329 
00330         ref.setAction
00331         (
00332             polyAddFace
00333             (
00334                 newFace,                               // face
00335                 addedCells[edgeFaces[curEdgeID][0]],   // owner
00336                 addedCells[edgeFaces[curEdgeID][1]],   // neighbour
00337                 -1,                                    // master point
00338                 meshEdges[curEdgeID],                  // master edge
00339                 -1,                                    // master face
00340                 false,                                 // flip flux
00341                 -1,                                    // patch for face
00342                 -1,                                    // zone for face
00343                 false                                  // face zone flip
00344             )
00345         );
00346 
00347 // Pout << "Add internal face off edge: " << newFace << " own: " << addedCells[edgeFaces[curEdgeID][0]] << " nei: " << addedCells[edgeFaces[curEdgeID][1]] << endl;
00348     }
00349 
00350     // Prepare creation of faces from boundary edges.
00351     // Note:
00352     // A tricky part of the algorithm is finding the patch into which the
00353     // newly created face will be added.  For this purpose, take the edge
00354     // and grab all the faces coming from it.  From the set of faces
00355     // eliminate the internal faces and find the boundary face from the rest.
00356     //  If there is more than one boundary face (excluding the ones in
00357     // the master zone), the patch with the lower label is selected.
00358 
00359     const labelListList& meshEdgeFaces = mesh.edgeFaces();
00360 
00361     const faceZoneMesh& zoneMesh = mesh.faceZones();
00362 
00363     // Do all boundary edges
00364 
00365     for
00366     (
00367         label curEdgeID = nInternalEdges;
00368         curEdgeID < zoneLocalEdges.size();
00369         curEdgeID++
00370     )
00371     {
00372         face newFace(4);
00373         newFace[0] = mp[zoneLocalEdges[curEdgeID].start()];
00374         newFace[1] = mp[zoneLocalEdges[curEdgeID].end()];
00375         newFace[2] = addedPoints[zoneLocalEdges[curEdgeID].end()];
00376         newFace[3] = addedPoints[zoneLocalEdges[curEdgeID].start()];
00377 
00378         // Determine the patch for insertion
00379         const labelList& curFaces = meshEdgeFaces[meshEdges[curEdgeID]];
00380 
00381         label patchID = -1;
00382         label zoneID = -1;
00383 
00384         forAll (curFaces, faceI)
00385         {
00386             const label cf = curFaces[faceI];
00387 
00388             if (!mesh.isInternalFace(cf))
00389             {
00390                 // Face not internal. Check if it is in the zone
00391                 if (zoneMesh.whichZone(cf) != faceZoneID_.index())
00392                 {
00393                     // Found the face in a boundary patch which is not in zone
00394                     patchID = mesh.boundaryMesh().whichPatch(cf);
00395                     zoneID = mesh.faceZones().whichZone(cf);
00396 
00397                     break;
00398                 }
00399             }
00400         }
00401 
00402         if (patchID < 0)
00403         {
00404             FatalErrorIn
00405             (
00406                 "void Foam::layerAdditionRemoval::setRefinement("
00407                 "polyTopoChange& ref)"
00408             )   << "Cannot find patch for edge " << meshEdges[curEdgeID]
00409                 << ". Edge: " << mesh.edges()[meshEdges[curEdgeID]]
00410                 << abort(FatalError);
00411         }
00412 
00413         ref.setAction
00414         (
00415             polyAddFace
00416             (
00417                 newFace,                               // face
00418                 addedCells[edgeFaces[curEdgeID][0]],   // owner
00419                 -1,                                    // neighbour
00420                 -1,                                    // master point
00421                 meshEdges[curEdgeID],                  // master edge
00422                 -1,                                    // master face
00423                 false,                                 // flip flux
00424                 patchID,                               // patch for face
00425                 zoneID,                                // zone
00426                 false                                  // zone face flip
00427             )
00428         );
00429 // Pout << "add boundary face: " << newFace << " into patch " << patchID << " own: " << addedCells[edgeFaces[curEdgeID][0]] << endl;
00430     }
00431 
00432     // Modify the remaining faces of the master cells to reconnect to the new
00433     // layer of faces.
00434     // Algorithm: Go through all the cells of the master zone and make
00435     // a map of faces to avoid duplicates.  Do not insert the faces in
00436     // the master patch (as they have already been dealt with).  Make
00437     // a master layer point renumbering map, which for every point in
00438     // the master layer gives its new label. Loop through all faces in
00439     // the map and attempt to renumber them using the master layer
00440     // point renumbering map.  Once the face is renumbered, compare it
00441     // with the original face; if they are the same, the face has not
00442     // changed; if not, modify the face but keep all of its old
00443     // attributes (apart from the vertex numbers).
00444 
00445     // Create the map of faces in the master cell layer
00446     labelHashSet masterCellFaceMap(primitiveMesh::facesPerCell_*mc.size());
00447 
00448     const cellList& cells = mesh.cells();
00449 
00450     forAll (mc, cellI)
00451     {
00452         const labelList& curFaces = cells[mc[cellI]];
00453 
00454         forAll (curFaces, faceI)
00455         {
00456             // Check if the face belongs to the master zone; if not add it
00457             if (zoneMesh.whichZone(curFaces[faceI]) != faceZoneID_.index())
00458             {
00459                 masterCellFaceMap.insert(curFaces[faceI]);
00460             }
00461         }
00462     }
00463 
00464     // Create the master layer point map
00465     Map<label> masterLayerPointMap(2*mp.size());
00466 
00467     forAll (mp, pointI)
00468     {
00469         masterLayerPointMap.insert
00470         (
00471             mp[pointI],
00472             addedPoints[pointI]
00473         );
00474     }
00475 
00476     // Grab the list of faces of the master layer
00477     const labelList masterCellFaces = masterCellFaceMap.toc();
00478 
00479     forAll (masterCellFaces, faceI)
00480     {
00481         // Attempt to renumber the face using the masterLayerPointMap.
00482         // Missing point remain the same
00483 
00484         const label curFaceID = masterCellFaces[faceI];
00485 
00486         const face& oldFace = faces[curFaceID];
00487 
00488         face newFace(oldFace.size());
00489 
00490         bool changed = false;
00491 
00492         forAll (oldFace, pointI)
00493         {
00494             if (masterLayerPointMap.found(oldFace[pointI]))
00495             {
00496                 changed = true;
00497 
00498                 newFace[pointI] = masterLayerPointMap.find(oldFace[pointI])();
00499             }
00500             else
00501             {
00502                 newFace[pointI] = oldFace[pointI];
00503             }
00504         }
00505 
00506         // If the face has changed, create a modification entry
00507         if (changed)
00508         {
00509             // Get face zone and its flip
00510             label modifiedFaceZone = mesh.faceZones().whichZone(curFaceID);
00511             bool modifiedFaceZoneFlip = false;
00512 
00513             if (modifiedFaceZone >= 0)
00514             {
00515                 modifiedFaceZoneFlip =
00516                     mesh.faceZones()[modifiedFaceZone].flipMap()
00517                     [
00518                         mesh.faceZones()[modifiedFaceZone].whichFace(curFaceID)
00519                     ];
00520             }
00521 
00522             if (mesh.isInternalFace(curFaceID))
00523             {
00524                 ref.setAction
00525                 (
00526                     polyModifyFace
00527                     (
00528                         newFace,                // modified face
00529                         curFaceID,              // label of face being modified
00530                         own[curFaceID],         // owner
00531                         nei[curFaceID],         // neighbour
00532                         false,                  // face flip
00533                         -1,                     // patch for face
00534                         false,                  // remove from zone
00535                         modifiedFaceZone,       // zone for face
00536                         modifiedFaceZoneFlip    // face flip in zone
00537                     )
00538                 );
00539 // Pout << "modifying stick-out face. Internal Old face: " << oldFace << " new face: " << newFace << " own: " << own[curFaceID] << " nei: " << nei[curFaceID] << endl;
00540             }
00541             else
00542             {
00543                 ref.setAction
00544                 (
00545                     polyModifyFace
00546                     (
00547                         newFace,                // modified face
00548                         curFaceID,              // label of face being modified
00549                         own[curFaceID],         // owner
00550                         -1,                     // neighbour
00551                         false,                  // face flip
00552                         mesh.boundaryMesh().whichPatch(curFaceID), // patch for face
00553                         false,                  // remove from zone
00554                         modifiedFaceZone,       // zone for face
00555                         modifiedFaceZoneFlip    // face flip in zone
00556                     )
00557                 );
00558 // Pout << "modifying stick-out face. Boundary Old face: " << oldFace << " new face: " << newFace << " own: " << own[curFaceID] << " patch: " << mesh.boundaryMesh().whichPatch(curFaceID) << endl;
00559             }
00560         }
00561     }
00562 
00563     if (debug)
00564     {
00565         Pout<< "void layerAdditionRemoval::addCellLayer("
00566             << "polyTopoChange& ref) const "
00567             << " for object " << name() << " : "
00568             << "Finished adding cell layer" << endl;
00569     }
00570 }
00571 
00572 
00573 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines