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

cellFeatures.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 Description
00025 
00026 \*---------------------------------------------------------------------------*/
00027 
00028 #include "cellFeatures.H"
00029 #include <OpenFOAM/primitiveMesh.H>
00030 #include <OpenFOAM/HashSet.H>
00031 #include <OpenFOAM/Map.H>
00032 #include <OpenFOAM/demandDrivenData.H>
00033 #include <OpenFOAM/ListOps.H>
00034 #include <meshTools/meshTools.H>
00035 
00036 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00037 
00038 
00039 // Return true if edge start and end are on increasing face vertices. (edge is
00040 // guaranteed to be on face)
00041 bool Foam::cellFeatures::faceAlignedEdge(const label faceI, const label edgeI)
00042  const
00043 {
00044     const edge& e = mesh_.edges()[edgeI];
00045 
00046     const face& f = mesh_.faces()[faceI];
00047 
00048     forAll(f, fp)
00049     {
00050         if (f[fp] == e.start())
00051         {
00052             label fp1 = f.fcIndex(fp);
00053 
00054             return f[fp1] == e.end();
00055         }
00056     }
00057 
00058     FatalErrorIn
00059     (
00060         "cellFeatures::faceAlignedEdge(const label, const label)"
00061     )   << "Can not find edge " << mesh_.edges()[edgeI]
00062         << " on face " << faceI << abort(FatalError);
00063 
00064     return false;
00065 }
00066 
00067 
00068 // Return edge in featureEdge that uses vertI and is on same superface
00069 // but is not edgeI
00070 Foam::label Foam::cellFeatures::nextEdge
00071 (
00072     const Map<label>& toSuperFace,
00073     const label superFaceI,
00074     const label thisEdgeI,
00075     const label thisVertI
00076 ) const
00077 {
00078     const labelList& pEdges = mesh_.pointEdges()[thisVertI];
00079 
00080     forAll(pEdges, pEdgeI)
00081     {
00082         label edgeI = pEdges[pEdgeI];
00083 
00084         if ((edgeI != thisEdgeI) && featureEdge_.found(edgeI))
00085         {
00086             // Check that edge is used by a face on same superFace
00087 
00088             const labelList& eFaces = mesh_.edgeFaces()[edgeI];
00089 
00090             forAll(eFaces, eFaceI)
00091             {
00092                 label faceI = eFaces[eFaceI];
00093 
00094                 if
00095                 (
00096                     meshTools::faceOnCell(mesh_, cellI_, faceI)
00097                  && (toSuperFace[faceI] == superFaceI)
00098                 )
00099                 {
00100                     return edgeI;
00101                 }
00102             }
00103         }
00104     }
00105 
00106     FatalErrorIn
00107     (
00108         "cellFeatures::nextEdge(const label, const Map<label>"
00109         ", const labelHashSet&, const label, const label, const label)"
00110     )   << "Can not find edge in " << featureEdge_ << " connected to edge "
00111         << thisEdgeI << " at vertex " << thisVertI << endl
00112         << "This might mean that the externalEdges do not form a closed loop"
00113         << abort(FatalError);
00114 
00115     return -1;
00116 }
00117 
00118 
00119 // Return true if angle between faces using it is larger than certain value.
00120 bool Foam::cellFeatures::isCellFeatureEdge
00121 (
00122     const scalar minCos,
00123     const label edgeI
00124 ) const
00125 {
00126     // Get the two faces using this edge
00127 
00128     label face0;
00129     label face1;
00130     meshTools::getEdgeFaces(mesh_, cellI_, edgeI, face0, face1);
00131 
00132     // Check the angle between them by comparing the face normals.
00133 
00134     vector n0 = mesh_.faceAreas()[face0];
00135     n0 /= mag(n0);
00136 
00137     vector n1 = mesh_.faceAreas()[face1];
00138     n1 /= mag(n1);
00139 
00140     scalar cosAngle = n0 & n1;
00141 
00142 
00143     const edge& e = mesh_.edges()[edgeI];
00144 
00145     const face& f0 = mesh_.faces()[face0];
00146 
00147     label face0Start = findIndex(f0, e.start());
00148     label face0End   = f0.fcIndex(face0Start);
00149 
00150     const face& f1 = mesh_.faces()[face1];
00151 
00152     label face1Start = findIndex(f1, e.start());
00153     label face1End   = f1.fcIndex(face1Start);
00154 
00155     if
00156     (
00157         (
00158             (f0[face0End] == e.end())
00159          && (f1[face1End] != e.end())
00160         )
00161      || (
00162             (f0[face0End] != e.end())
00163          && (f1[face1End] == e.end())
00164         )
00165     )
00166     {
00167     }
00168     else
00169     {
00170         cosAngle = -cosAngle;
00171     }
00172 
00173     if (cosAngle < minCos)
00174     {
00175         return true;
00176     }
00177     else
00178     {
00179         return false;
00180     }
00181 }
00182 
00183 
00184 // Recursively mark (on toSuperFace) all face reachable across non-feature
00185 // edges.
00186 void Foam::cellFeatures::walkSuperFace
00187 (
00188     const label faceI,
00189     const label superFaceI,
00190     Map<label>& toSuperFace
00191 ) const
00192 {
00193     if (!toSuperFace.found(faceI))
00194     {
00195         toSuperFace.insert(faceI, superFaceI);
00196 
00197         const labelList& fEdges = mesh_.faceEdges()[faceI];
00198 
00199         forAll(fEdges, fEdgeI)
00200         {
00201             label edgeI = fEdges[fEdgeI];
00202 
00203             if (!featureEdge_.found(edgeI))
00204             {
00205                 label face0;
00206                 label face1;
00207                 meshTools::getEdgeFaces(mesh_, cellI_, edgeI, face0, face1);
00208 
00209                 if (face0 == faceI)
00210                 {
00211                     face0 = face1;
00212                 }
00213 
00214                 walkSuperFace
00215                 (
00216                     face0,
00217                     superFaceI,
00218                     toSuperFace
00219                 );
00220             }
00221         }
00222     }
00223 }
00224 
00225 
00226 void Foam::cellFeatures::calcSuperFaces() const
00227 {
00228     // Determine superfaces by edge walking across non-feature edges
00229 
00230     const labelList& cFaces = mesh_.cells()[cellI_];
00231 
00232     // Mapping from old to super face:
00233     //    <not found> : not visited
00234     //    >=0 : superFace
00235     Map<label> toSuperFace(10*cFaces.size());
00236 
00237     label superFaceI = 0;
00238 
00239     forAll(cFaces, cFaceI)
00240     {
00241         label faceI = cFaces[cFaceI];
00242 
00243         if (!toSuperFace.found(faceI))
00244         {
00245             walkSuperFace
00246             (
00247                 faceI,
00248                 superFaceI,
00249                 toSuperFace
00250             );
00251             superFaceI++;
00252         }
00253     }
00254 
00255     // Construct superFace-to-oldface mapping.
00256 
00257     faceMap_.setSize(superFaceI);
00258 
00259     forAll(cFaces, cFaceI)
00260     {
00261         label faceI = cFaces[cFaceI];
00262 
00263         faceMap_[toSuperFace[faceI]].append(faceI);
00264     }
00265 
00266     forAll(faceMap_, superI)
00267     {
00268         faceMap_[superI].shrink();
00269     }
00270 
00271 
00272     // Construct superFaces
00273 
00274     facesPtr_ = new faceList(superFaceI);
00275 
00276     faceList& faces = *facesPtr_;
00277 
00278     forAll(cFaces, cFaceI)
00279     {
00280         label faceI = cFaces[cFaceI];
00281 
00282         label superFaceI = toSuperFace[faceI];
00283 
00284         if (faces[superFaceI].empty())
00285         {
00286             // Superface not yet constructed.
00287 
00288             // Find starting feature edge on face.
00289             label startEdgeI = -1;
00290 
00291             const labelList& fEdges = mesh_.faceEdges()[faceI];
00292 
00293             forAll(fEdges, fEdgeI)
00294             {
00295                 label edgeI = fEdges[fEdgeI];
00296 
00297                 if (featureEdge_.found(edgeI))
00298                 {
00299                     startEdgeI = edgeI;
00300 
00301                     break;
00302                 }
00303             }
00304 
00305 
00306             if (startEdgeI != -1)
00307             {
00308                 // Walk point-edge-point along feature edges
00309 
00310                 DynamicList<label> superFace(10*mesh_.faces()[faceI].size());
00311 
00312                 const edge& e = mesh_.edges()[startEdgeI];
00313 
00314                 // Walk either start-end or end-start depending on orientation
00315                 // of face. SuperFace will have cellI as owner.
00316                 bool flipOrientation =
00317                     (mesh_.faceOwner()[faceI] == cellI_)
00318                   ^ (faceAlignedEdge(faceI, startEdgeI));
00319 
00320                 label startVertI = -1;
00321 
00322                 if (flipOrientation)
00323                 {
00324                     startVertI = e.end();
00325                 }
00326                 else
00327                 {
00328                     startVertI = e.start();
00329                 }
00330 
00331                 label edgeI = startEdgeI;
00332 
00333                 label vertI = e.otherVertex(startVertI);
00334 
00335                 do
00336                 {
00337                     label newEdgeI = nextEdge
00338                     (
00339                         toSuperFace,
00340                         superFaceI,
00341                         edgeI,
00342                         vertI
00343                     );
00344 
00345                     // Determine angle between edges.
00346                     if (isFeaturePoint(edgeI, newEdgeI))
00347                     {
00348                         superFace.append(vertI);
00349                     }
00350 
00351                     edgeI = newEdgeI;
00352 
00353                     if (vertI == startVertI)
00354                     {
00355                         break;
00356                     }
00357 
00358                     vertI = mesh_.edges()[edgeI].otherVertex(vertI);
00359                 }
00360                 while (true);
00361 
00362                 if (superFace.size() <= 2)
00363                 {
00364                     WarningIn("cellFeatures::calcSuperFaces")
00365                         << " Can not collapse faces " << faceMap_[superFaceI]
00366                         << " into one big face on cell " << cellI_ << endl
00367                         << "Try decreasing minCos:" << minCos_ << endl;
00368                 }
00369                 else
00370                 {
00371                     faces[superFaceI].transfer(superFace);
00372                 }
00373             }
00374         }
00375     }
00376 }
00377 
00378 
00379 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00380 
00381 // Construct from components
00382 Foam::cellFeatures::cellFeatures
00383 (
00384     const primitiveMesh& mesh,
00385     const scalar minCos,
00386     const label cellI
00387 )
00388 :
00389     mesh_(mesh),
00390     minCos_(minCos),
00391     cellI_(cellI),
00392     featureEdge_(10*mesh.cellEdges()[cellI].size()),
00393     facesPtr_(NULL),
00394     faceMap_(0)
00395 {
00396     const labelList& cEdges = mesh_.cellEdges()[cellI_];
00397 
00398     forAll(cEdges, cEdgeI)
00399     {
00400         label edgeI = cEdges[cEdgeI];
00401 
00402         if (isCellFeatureEdge(minCos_, edgeI))
00403         {
00404             featureEdge_.insert(edgeI);
00405         }
00406     }
00407 
00408 }
00409 
00410 
00411 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00412 
00413 Foam::cellFeatures::~cellFeatures()
00414 {
00415     deleteDemandDrivenData(facesPtr_);
00416 }
00417 
00418 
00419 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00420 
00421 bool Foam::cellFeatures::isFeaturePoint(const label edge0, const label edge1)
00422  const
00423 {
00424     if
00425     (
00426         (edge0 < 0)
00427      || (edge0 >= mesh_.nEdges())
00428      || (edge1 < 0)
00429      || (edge1 >= mesh_.nEdges())
00430     )
00431     {
00432         FatalErrorIn
00433         (
00434             "cellFeatures::isFeatureVertex(const label, const label)"
00435         )   << "Illegal edge labels : edge0:" << edge0 << " edge1:" << edge1
00436             << abort(FatalError);
00437     }
00438 
00439     const edge& e0 = mesh_.edges()[edge0];
00440 
00441     vector e0Vec = e0.vec(mesh_.points());
00442     e0Vec /= mag(e0Vec);
00443 
00444     const edge& e1 = mesh_.edges()[edge1];
00445 
00446     vector e1Vec = e1.vec(mesh_.points());
00447     e1Vec /= mag(e1Vec);
00448 
00449     scalar cosAngle;
00450 
00451     if
00452     (
00453         (e0.start() == e1.end())
00454      || (e0.end() == e1.start())
00455     )
00456     {
00457         // Same direction
00458         cosAngle = e0Vec & e1Vec;
00459     }
00460     else if
00461     (
00462         (e0.start() == e1.start())
00463      || (e0.end() == e1.end())
00464     )
00465     {
00466         // back on back
00467         cosAngle = - e0Vec & e1Vec;
00468     }
00469     else
00470     {
00471         cosAngle = GREAT;   // satisfy compiler
00472 
00473         FatalErrorIn
00474         (
00475             "cellFeatures::isFeaturePoint(const label, const label"
00476             ", const label)"
00477         )   << "Edges do not share common vertex. e0:" << e0
00478             << " e1:" << e1 << abort(FatalError);
00479     }
00480 
00481     if (cosAngle < minCos_)
00482     {
00483         // Angle larger than criterium
00484         return true;
00485     }
00486     else
00487     {
00488         return false;
00489     }
00490 }
00491 
00492 
00493 bool Foam::cellFeatures::isFeatureVertex(const label faceI, const label vertI)
00494  const
00495 {
00496     if
00497     (
00498         (faceI < 0)
00499      || (faceI >= mesh_.nFaces())
00500      || (vertI < 0)
00501      || (vertI >= mesh_.nPoints())
00502     )
00503     {
00504         FatalErrorIn
00505         (
00506             "cellFeatures::isFeatureVertex(const label, const label)"
00507         )   << "Illegal face " << faceI << " or vertex " << vertI
00508             << abort(FatalError);
00509     }
00510 
00511     const labelList& pEdges = mesh_.pointEdges()[vertI];
00512 
00513     label edge0 = -1;
00514     label edge1 = -1;
00515 
00516     forAll(pEdges, pEdgeI)
00517     {
00518         label edgeI = pEdges[pEdgeI];
00519 
00520         if (meshTools::edgeOnFace(mesh_, faceI, edgeI))
00521         {
00522             if (edge0 == -1)
00523             {
00524                 edge0 = edgeI;
00525             }
00526             else
00527             {
00528                 edge1 = edgeI;
00529 
00530                 // Found the two edges.
00531                 break;
00532             }
00533         }
00534     }
00535 
00536     if (edge1 == -1)
00537     {
00538         FatalErrorIn
00539         (
00540             "cellFeatures::isFeatureVertex(const label, const label)"
00541         )   << "Did not find two edges sharing vertex " << vertI
00542             << " on face " << faceI << " vertices:" << mesh_.faces()[faceI]
00543             << abort(FatalError);
00544     }
00545 
00546     return isFeaturePoint(edge0, edge1);
00547 }
00548 
00549 
00550 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines