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

edgeFaceCirculatorI.H

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 <OpenFOAM/primitiveMesh.H>
00027 
00028 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00029 
00030 void Foam::edgeFaceCirculator::setEnd()
00031 {
00032     faceLabel_ = -1;
00033     index_ = -1;
00034 }
00035 
00036 
00037 void Foam::edgeFaceCirculator::setFace
00038 (
00039     const label faceI,
00040     const label cellI
00041 )
00042 {
00043     faceLabel_ = faceI;
00044 
00045     if (!isBoundaryEdge_ && !mesh_.isInternalFace(faceI))
00046     {
00047         FatalErrorIn
00048         (
00049             "edgeFaceCirculator::setFace(const label, const label)"
00050         )   << "Edge is not defined as boundary edge but still walked to"
00051             << " boundary face:" << faceI << " on cell:" << cellI
00052             << abort(FatalError);
00053     }
00054 }
00055 
00056 
00057 void Foam::edgeFaceCirculator::otherFace(const label cellI)
00058 {
00059     const face& f = mesh_.faces()[faceLabel_];
00060     label v0 = f[index_];
00061     label v1 = f.nextLabel(index_);
00062 
00063     const cell& cFaces = mesh_.cells()[cellI];
00064 
00065     forAll(cFaces, i)
00066     {
00067         label faceB = cFaces[i];
00068 
00069         if (faceB != faceLabel_)
00070         {
00071             label fp = getMinIndex(mesh_.faces()[faceB], v0, v1);
00072 
00073             if (fp >= 0)
00074             {
00075                 index_ = fp;
00076                 setFace(faceB, cellI);
00077                 return;
00078             }
00079         }
00080     }
00081 
00082     FatalErrorIn("edgeFaceCirculator::otherFace(const label)")
00083         << "Could not find next face stepping"
00084         << " through cell along edge." << endl
00085         << "face:" << faceLabel_ << " index in face:" << index_
00086         << " edge:" << mesh_.points()[v0] << mesh_.points()[v1]
00087         << abort(FatalError);
00088 }
00089 
00090 
00091 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00092 
00093 //- Construct from components
00094 Foam::edgeFaceCirculator::edgeFaceCirculator
00095 (
00096     const primitiveMesh& mesh,
00097     const label faceLabel,
00098     const bool ownerSide,
00099     const label index,
00100     const bool isBoundaryEdge
00101 )
00102 :
00103     mesh_(mesh),
00104     faceLabel_(faceLabel),
00105     ownerSide_(ownerSide),
00106     index_(index),
00107     isBoundaryEdge_(isBoundaryEdge),
00108     startFaceLabel_(faceLabel_)
00109 {}
00110 
00111 
00112 //- Construct copy
00113 Foam::edgeFaceCirculator::edgeFaceCirculator(const edgeFaceCirculator& circ)
00114 :
00115     mesh_(circ.mesh_),
00116     faceLabel_(circ.faceLabel_),
00117     ownerSide_(circ.ownerSide_),
00118     index_(circ.index_),
00119     isBoundaryEdge_(circ.isBoundaryEdge_),
00120     startFaceLabel_(circ.startFaceLabel_)
00121 {}
00122 
00123 
00124 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00125 
00126 Foam::label Foam::edgeFaceCirculator::getMinIndex
00127 (
00128     const face& f,
00129     const label v0,
00130     const label v1
00131 )
00132 {
00133     label fp = findIndex(f, v0);
00134 
00135     if (fp != -1)
00136     {
00137         label fpMin1 = f.rcIndex(fp);
00138 
00139         if (f[fpMin1] == v1)
00140         {
00141             fp = fpMin1;
00142         }
00143         else
00144         {
00145             label fpPlus1 = f.fcIndex(fp);
00146 
00147             if (f[fpPlus1] != v1)
00148             {
00149                 fp = -1;
00150             }
00151         }
00152     }
00153     return fp;
00154 }
00155 
00156 
00157 Foam::label Foam::edgeFaceCirculator::faceLabel() const
00158 {
00159     return faceLabel_;
00160 }
00161 
00162 
00163 bool Foam::edgeFaceCirculator::ownerSide() const
00164 {
00165     return ownerSide_;
00166 }
00167 
00168 
00169 Foam::label Foam::edgeFaceCirculator::index() const
00170 {
00171     return index_;
00172 }
00173 
00174 
00175 Foam::label Foam::edgeFaceCirculator::cellLabel() const
00176 {
00177     if (ownerSide_)
00178     {
00179         return mesh_.faceOwner()[faceLabel_];
00180     }
00181     else if (mesh_.isInternalFace(faceLabel_))
00182     {
00183         return mesh_.faceNeighbour()[faceLabel_];
00184     }
00185     else
00186     {
00187         return -1;
00188     }
00189 }
00190 
00191 
00192 bool Foam::edgeFaceCirculator::sameOrder(const label v0, const label v1) const
00193 {
00194     const face& f = mesh_.faces()[faceLabel_];
00195 
00196     label fp = getMinIndex(f, v0, v1);
00197 
00198     if (fp != index_)
00199     {
00200         FatalErrorIn
00201         (
00202             "edgeFaceCirculator::sameOrder(const label, const label) const"
00203         )   << "v0:" << v1 << " and v1:" << v1
00204             << " not on position:" << index_ << " on face:" << faceLabel_
00205             << " verts:" << f << " or not consecutive." << abort(FatalError);
00206     }
00207 
00208     // If we are neighbour the face would point into us so the min index would
00209     // be v0.
00210     return ownerSide_ != (f[index_] == v0);
00211 }
00212 
00213 
00214 void Foam::edgeFaceCirculator::setCanonical()
00215 {
00216     if (isBoundaryEdge_)
00217     {
00218         // Boundary edge. Step until we're on boundary face and ownerSide
00219         label i = 0;
00220 
00221         while (true)
00222         {
00223             if (mesh_.isInternalFace(faceLabel_))
00224             {
00225                 if (ownerSide_)
00226                 {
00227                     label cellI = mesh_.faceNeighbour()[faceLabel_];
00228                     otherFace(cellI);
00229                     // Maintain reverse direction of walking
00230                     ownerSide_ = (mesh_.faceOwner()[faceLabel_] == cellI);
00231                 }
00232                 else
00233                 {
00234                     label cellI = mesh_.faceOwner()[faceLabel_];
00235                     otherFace(cellI);
00236                     // Maintain reverse direction of walking
00237                     ownerSide_ = (mesh_.faceOwner()[faceLabel_] == cellI);
00238                 }
00239             }
00240             else if (ownerSide_)
00241             {
00242                 break;
00243             }
00244             else
00245             {
00246                 label cellI = mesh_.faceOwner()[faceLabel_];
00247                 otherFace(cellI);
00248                 // Maintain reverse direction of walking
00249                 ownerSide_ = (mesh_.faceOwner()[faceLabel_] == cellI);
00250             }
00251 
00252             i++;
00253 
00254             if (i >= 1000)
00255             {
00256                 const face& f = mesh_.faces()[faceLabel_];
00257 
00258                 FatalErrorIn("Foam::edgeFaceCirculator::setCanonical()")
00259                     << "Walked " << i << " cells around edge "
00260                     << mesh_.points()[f[index_]]
00261                     << mesh_.points()[f.nextLabel(index_)]
00262                     << " without reaching a boundary face."
00263                     << " Are you sure this is a boundary edge?"
00264                     << abort(FatalError);
00265             }
00266         }
00267 
00268         // Set up for correct walking
00269         ownerSide_ = true;
00270         startFaceLabel_ = faceLabel_;
00271     }
00272     else
00273     {
00274         // Internal edge. Walk until we hit minimum face label.
00275         label minFaceI = faceLabel_;
00276         bool minOwnerSide = ownerSide_;
00277         label minIndex = index_;
00278 
00279         while (true)
00280         {
00281             operator++();
00282 
00283             if (operator==(end()))
00284             {
00285                 break;
00286             }
00287 
00288             if (!mesh_.isInternalFace(faceLabel_))
00289             {
00290                 const face& f = mesh_.faces()[faceLabel_];
00291 
00292                 FatalErrorIn("Foam::edgeFaceCirculator::setCanonical()")
00293                     << "Reached boundary face " << faceLabel_
00294                     << " when walking around internal edge "
00295                     << mesh_.points()[f[index_]]
00296                     << mesh_.points()[f.nextLabel(index_)]
00297                     << "." << endl
00298                     << "Are you sure this is an internal edge?"
00299                     << abort(FatalError);
00300             }
00301 
00302             if (faceLabel_ < minFaceI)
00303             {
00304                 minFaceI = faceLabel_;
00305                 minOwnerSide = ownerSide_;
00306                 minIndex = index_;
00307             }
00308         }
00309 
00310         faceLabel_ = minFaceI;
00311         ownerSide_ = minOwnerSide;
00312         index_ = minIndex;
00313         startFaceLabel_ = faceLabel_;
00314     }
00315 }
00316 
00317 
00318 void Foam::edgeFaceCirculator::operator=(const edgeFaceCirculator& circ)
00319 {
00320     faceLabel_ = circ.faceLabel_;
00321     ownerSide_ = circ.ownerSide_;
00322     index_ = circ.index_;
00323     isBoundaryEdge_ = circ.isBoundaryEdge_;
00324     startFaceLabel_ = circ.startFaceLabel_;
00325 }
00326 
00327 
00328 bool Foam::edgeFaceCirculator::operator==(const edgeFaceCirculator& circ) const
00329 {
00330     return faceLabel_ == circ.faceLabel_ && index_ == circ.index_;
00331 
00334     //if (faceLabel_ == -1 && circ.faceLabel_ == -1)
00335     //{
00336     //    // both endConstIter
00337     //    return true;
00338     //}
00339     //
00340     //return
00341     //    faceLabel_ == circ.faceLabel_
00342     // && ownerSide_ == circ.ownerSide_
00343     // && index_ == circ.index_;
00344     // && startFaceLabel_ == circ.startFaceLabel_;
00345 }
00346 
00347 
00348 bool Foam::edgeFaceCirculator::operator!=(const edgeFaceCirculator& circ) const
00349 {
00350     return !(*this == circ);
00351 }
00352 
00353 
00354 //- Step to next face.
00355 Foam::edgeFaceCirculator& Foam::edgeFaceCirculator::operator++()
00356 {
00357     if (faceLabel_ == -1)
00358     {
00359         FatalErrorIn("edgeFaceCirculator::operator++()")
00360             << "Already reached end(). Cannot walk any further."
00361             << abort(FatalError);
00362     }
00363     else if (ownerSide_)
00364     {
00365         // Step to owner
00366         label cellI = mesh_.faceOwner()[faceLabel_];
00367         otherFace(cellI);
00368         // Maintain direction of walking
00369         ownerSide_ = (mesh_.faceOwner()[faceLabel_] != cellI);
00370 
00371         // Check for internal edge : ends on starting face.
00372         if (!isBoundaryEdge_ && faceLabel_ == startFaceLabel_)
00373         {
00374             setEnd();
00375         }
00376     }
00377     else if (mesh_.isInternalFace(faceLabel_))
00378     {
00379         // Step to neighbour
00380         label cellI = mesh_.faceNeighbour()[faceLabel_];
00381         otherFace(cellI);
00382         // Maintain direction of walking
00383         ownerSide_ = (mesh_.faceOwner()[faceLabel_] != cellI);
00384 
00385         // Check for internal edge : ends on starting face.
00386         if (!isBoundaryEdge_ && faceLabel_ == startFaceLabel_)
00387         {
00388             setEnd();
00389         }
00390     }
00391     else
00392     {
00393         // neighbour side of boundary face reached. Mark as endConstIter.
00394         setEnd();
00395     }
00396 
00397     return *this;
00398 }
00399 
00400 
00401 Foam::edgeFaceCirculator Foam::edgeFaceCirculator::begin() const
00402 {
00403     edgeFaceCirculator iter
00404     (
00405         mesh_,
00406         faceLabel_,
00407         ownerSide_,
00408         index_,
00409         isBoundaryEdge_
00410     );
00411 
00412     if (isBoundaryEdge_)
00413     {
00414         iter.setCanonical();
00415     }
00416     return iter;
00417 }
00418 
00419 
00420 Foam::edgeFaceCirculator Foam::edgeFaceCirculator::cbegin() const
00421 {
00422     edgeFaceCirculator iter
00423     (
00424         mesh_,
00425         faceLabel_,
00426         ownerSide_,
00427         index_,
00428         isBoundaryEdge_
00429     );
00430 
00431     if (isBoundaryEdge_)
00432     {
00433         iter.setCanonical();
00434     }
00435     return iter;
00436 }
00437 
00438 
00439 const Foam::edgeFaceCirculator& Foam::edgeFaceCirculator::end() const
00440 {
00441     return endConstIter;
00442 }
00443 
00444 const Foam::edgeFaceCirculator& Foam::edgeFaceCirculator::cend() const
00445 {
00446     return endConstIter;
00447 }
00448 
00449 
00450 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines