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

FECCellToFaceStencil.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 "FECCellToFaceStencil.H"
00027 #include <OpenFOAM/syncTools.H>
00028 #include <OpenFOAM/emptyPolyPatch.H>
00029 //#include "meshTools.H"
00030 //#include "OFstream.H"
00031 //#include "Time.H"
00032 
00033 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00034 
00035 // Calculates per edge the neighbour data (= edgeCells)
00036 void Foam::FECCellToFaceStencil::calcEdgeBoundaryData
00037 (
00038     const boolList& isValidBFace,
00039     const labelList& boundaryEdges,
00040     EdgeMap<labelList>& neiGlobal
00041 ) const
00042 {
00043     neiGlobal.resize(2*boundaryEdges.size());
00044 
00045     labelHashSet edgeGlobals;
00046 
00047     forAll(boundaryEdges, i)
00048     {
00049         label edgeI = boundaryEdges[i];
00050 
00051         neiGlobal.insert
00052         (
00053             mesh().edges()[edgeI],
00054             calcFaceCells
00055             (
00056                 isValidBFace,
00057                 mesh().edgeFaces(edgeI),
00058                 edgeGlobals
00059             )
00060         );
00061     }
00062 
00063     syncTools::syncEdgeMap
00064     (
00065         mesh(),
00066         neiGlobal,
00067         unionEqOp(),
00068         false           // apply separation
00069     );
00070 }
00071 
00072 
00073 // Calculates per face the edge connected data (= cell or boundary in global
00074 // numbering).
00075 void Foam::FECCellToFaceStencil::calcFaceStencil
00076 (
00077     labelListList& faceStencil
00078 ) const
00079 {
00080     const polyBoundaryMesh& patches = mesh().boundaryMesh();
00081     const label nBnd = mesh().nFaces()-mesh().nInternalFaces();
00082     const labelList& own = mesh().faceOwner();
00083     const labelList& nei = mesh().faceNeighbour();
00084 
00085 
00086 
00087     // Determine neighbouring global cell
00088     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00089 
00090     labelList neiGlobalCell(nBnd);
00091     forAll(patches, patchI)
00092     {
00093         const polyPatch& pp = patches[patchI];
00094 
00095         if (pp.coupled())
00096         {
00097             label faceI = pp.start();
00098 
00099             forAll(pp, i)
00100             {
00101                 neiGlobalCell[faceI-mesh().nInternalFaces()] =
00102                     globalNumbering().toGlobal(own[faceI]);
00103                 faceI++;
00104             }
00105         }
00106     }
00107     syncTools::swapBoundaryFaceList(mesh(), neiGlobalCell, false);
00108 
00109 
00110 
00111     // Determine on coupled edges the edge cells on the other side
00112     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00113 
00114     // Calculate edges on coupled patches
00115     labelList boundaryEdges
00116     (
00117         allCoupledFacesPatch()().meshEdges
00118         (
00119             mesh().edges(),
00120             mesh().pointEdges()
00121         )
00122     );
00123 
00124     // Mark boundary faces to be included in stencil (i.e. not coupled or empty)
00125     boolList isValidBFace;
00126     validBoundaryFaces(isValidBFace);
00127 
00128     // Swap edgeCells for coupled edges. Note: use EdgeMap for now since we've
00129     // got syncTools::syncEdgeMap for those. Should be replaced with Map and
00130     // syncTools functionality to handle those.
00131     EdgeMap<labelList> neiGlobal;
00132     calcEdgeBoundaryData
00133     (
00134         isValidBFace,
00135         boundaryEdges,
00136         neiGlobal
00137     );
00138 
00139 
00140 
00141     // Construct stencil in global numbering
00142     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00143 
00144     faceStencil.setSize(mesh().nFaces());
00145 
00146     // Do coupled edges first
00147 
00148     forAll(boundaryEdges, i)
00149     {
00150         label edgeI = boundaryEdges[i];
00151 
00152         const labelList& eGlobals = neiGlobal[mesh().edges()[edgeI]];
00153 
00154         // Distribute to all edgeFaces
00155         const labelList& eFaces = mesh().edgeFaces(edgeI);
00156 
00157         forAll(eFaces, j)
00158         {
00159             label faceI = eFaces[j];
00160 
00161             // Insert eGlobals into faceStencil.
00162             merge(-1, -1, eGlobals, faceStencil[faceI]);
00163         }
00164     }
00165     neiGlobal.clear();
00166 
00167 
00168     // Do remaining edges by looping over all faces
00169 
00170     // Work arrays
00171     DynamicList<label> fEdgesSet;
00172     DynamicList<label> eFacesSet;
00173     labelHashSet faceStencilSet;
00174 
00175     for (label faceI = 0; faceI < mesh().nInternalFaces(); faceI++)
00176     {
00177         label globalOwn = globalNumbering().toGlobal(own[faceI]);
00178         label globalNei = globalNumbering().toGlobal(nei[faceI]);
00179 
00180         // Convert any existing faceStencil (from coupled edges) into
00181         // set and operate on this.
00182 
00183         faceStencilSet.clear();
00184 
00185         // Insert all but global owner and neighbour
00186         forAll(faceStencil[faceI], i)
00187         {
00188             label globalI = faceStencil[faceI][i];
00189             if (globalI != globalOwn && globalI != globalNei)
00190             {
00191                 faceStencilSet.insert(globalI);
00192             }
00193         }
00194         faceStencil[faceI].clear();
00195 
00196         // Collect all edge connected (internal) cells
00197         const labelList& fEdges = mesh().faceEdges(faceI, fEdgesSet);
00198 
00199         forAll(fEdges, i)
00200         {
00201             label edgeI = fEdges[i];
00202 
00203             insertFaceCells
00204             (
00205                 globalOwn,
00206                 globalNei,
00207                 isValidBFace,
00208                 mesh().edgeFaces(edgeI, eFacesSet),
00209                 faceStencilSet
00210             );
00211         }
00212 
00213         // Extract, guarantee owner first, neighbour second.
00214         faceStencil[faceI].setSize(faceStencilSet.size()+2);
00215         label n = 0;
00216         faceStencil[faceI][n++] = globalOwn;
00217         faceStencil[faceI][n++] = globalNei;
00218         forAllConstIter(labelHashSet, faceStencilSet, iter)
00219         {
00220             if (iter.key() == globalOwn || iter.key() == globalNei)
00221             {
00222                 FatalErrorIn("FECCellToFaceStencil::calcFaceStencil(..)")
00223                     << "problem:" << faceStencilSet
00224                     << abort(FatalError);
00225             }
00226             faceStencil[faceI][n++] = iter.key();
00227         }
00228     }
00229     forAll(patches, patchI)
00230     {
00231         const polyPatch& pp = patches[patchI];
00232         label faceI = pp.start();
00233 
00234         if (pp.coupled())
00235         {
00236             forAll(pp, i)
00237             {
00238                 label globalOwn = globalNumbering().toGlobal(own[faceI]);
00239                 label globalNei = neiGlobalCell[faceI-mesh().nInternalFaces()];
00240 
00241                 // Convert any existing faceStencil (from coupled edges) into
00242                 // set and operate on this.
00243 
00244                 faceStencilSet.clear();
00245 
00246                 // Insert all but global owner and neighbour
00247                 forAll(faceStencil[faceI], i)
00248                 {
00249                     label globalI = faceStencil[faceI][i];
00250                     if (globalI != globalOwn && globalI != globalNei)
00251                     {
00252                         faceStencilSet.insert(globalI);
00253                     }
00254                 }
00255                 faceStencil[faceI].clear();
00256 
00257                 // Collect all edge connected (internal) cells
00258                 const labelList& fEdges = mesh().faceEdges(faceI, fEdgesSet);
00259 
00260                 forAll(fEdges, i)
00261                 {
00262                     label edgeI = fEdges[i];
00263 
00264                     insertFaceCells
00265                     (
00266                         globalOwn,
00267                         globalNei,
00268                         isValidBFace,
00269                         mesh().edgeFaces(edgeI, eFacesSet),
00270                         faceStencilSet
00271                     );
00272                 }
00273 
00274                 // Extract, guarantee owner first, neighbour second.
00275                 faceStencil[faceI].setSize(faceStencilSet.size()+2);
00276                 label n = 0;
00277                 faceStencil[faceI][n++] = globalOwn;
00278                 faceStencil[faceI][n++] = globalNei;
00279                 forAllConstIter(labelHashSet, faceStencilSet, iter)
00280                 {
00281                     if (iter.key() == globalOwn || iter.key() == globalNei)
00282                     {
00283                         FatalErrorIn
00284                         (
00285                             "FECCellToFaceStencil::calcFaceStencil(..)"
00286                         )   << "problem:" << faceStencilSet
00287                             << abort(FatalError);
00288                     }
00289                     faceStencil[faceI][n++] = iter.key();
00290                 }
00291 
00292                 if (n != faceStencil[faceI].size())
00293                 {
00294                     FatalErrorIn("problem") << "n:" << n
00295                         << " size:" << faceStencil[faceI].size()
00296                         << abort(FatalError);
00297                 }
00298 
00299                 faceI++;
00300             }
00301         }
00302         else if (!isA<emptyPolyPatch>(pp))
00303         {
00304             forAll(pp, i)
00305             {
00306                 label globalOwn = globalNumbering().toGlobal(own[faceI]);
00307 
00308                 // Convert any existing faceStencil (from coupled edges) into
00309                 // set and operate on this.
00310 
00311                 faceStencilSet.clear();
00312 
00313                 // Insert all but global owner and neighbour
00314                 forAll(faceStencil[faceI], i)
00315                 {
00316                     label globalI = faceStencil[faceI][i];
00317                     if (globalI != globalOwn)
00318                     {
00319                         faceStencilSet.insert(globalI);
00320                     }
00321                 }
00322                 faceStencil[faceI].clear();
00323 
00324                 // Collect all edge connected (internal) cells
00325                 const labelList& fEdges = mesh().faceEdges(faceI, fEdgesSet);
00326 
00327                 forAll(fEdges, i)
00328                 {
00329                     label edgeI = fEdges[i];
00330 
00331                     insertFaceCells
00332                     (
00333                         globalOwn,
00334                         -1,
00335                         isValidBFace,
00336                         mesh().edgeFaces(edgeI, eFacesSet),
00337                         faceStencilSet
00338                     );
00339                 }
00340 
00341                 // Extract, guarantee owner first, neighbour second.
00342                 faceStencil[faceI].setSize(faceStencilSet.size()+1);
00343                 label n = 0;
00344                 faceStencil[faceI][n++] = globalOwn;
00345                 forAllConstIter(labelHashSet, faceStencilSet, iter)
00346                 {
00347                     if (iter.key() == globalOwn)
00348                     {
00349                         FatalErrorIn
00350                         (
00351                             "FECCellToFaceStencil::calcFaceStencil(..)"
00352                         )   << "problem:" << faceStencilSet
00353                             << abort(FatalError);
00354                     }
00355                     faceStencil[faceI][n++] = iter.key();
00356                 }
00357 
00358                 faceI++;
00359             }
00360         }
00361     }
00362 
00363 
00364     for (label faceI = 0; faceI < mesh().nInternalFaces(); faceI++)
00365     {
00366         label globalOwn = globalNumbering().toGlobal(own[faceI]);
00367         if (faceStencil[faceI][0] != globalOwn)
00368         {
00369             FatalErrorIn("FECCellToFaceStencil::calcFaceStencil(..)")
00370                 << "problem:" << faceStencil[faceI]
00371                 << " globalOwn:" << globalOwn
00372                 << abort(FatalError);
00373         }
00374         label globalNei = globalNumbering().toGlobal(nei[faceI]);
00375         if (faceStencil[faceI][1] != globalNei)
00376         {
00377             FatalErrorIn("FECCellToFaceStencil::calcFaceStencil(..)")
00378                 << "problem:" << faceStencil[faceI]
00379                 << " globalNei:" << globalNei
00380                 << abort(FatalError);
00381         }
00382     }
00383 
00384 
00385     forAll(patches, patchI)
00386     {
00387         const polyPatch& pp = patches[patchI];
00388 
00389         if (pp.coupled())
00390         {
00391             forAll(pp, i)
00392             {
00393                 label faceI = pp.start()+i;
00394 
00395                 label globalOwn = globalNumbering().toGlobal(own[faceI]);
00396                 if (faceStencil[faceI][0] != globalOwn)
00397                 {
00398                     FatalErrorIn("FECCellToFaceStencil::calcFaceStencil(..)")
00399                         << "problem:" << faceStencil[faceI]
00400                         << " globalOwn:" << globalOwn
00401                         << abort(FatalError);
00402                 }
00403                 label globalNei = neiGlobalCell[faceI-mesh().nInternalFaces()];
00404                 if (faceStencil[faceI][1] != globalNei)
00405                 {
00406                     FatalErrorIn("FECCellToFaceStencil::calcFaceStencil(..)")
00407                         << "problem:" << faceStencil[faceI]
00408                         << " globalNei:" << globalNei
00409                         << abort(FatalError);
00410                 }
00411             }
00412         }
00413         else if (!isA<emptyPolyPatch>(pp))
00414         {
00415             forAll(pp, i)
00416             {
00417                 label faceI = pp.start()+i;
00418 
00419                 label globalOwn = globalNumbering().toGlobal(own[faceI]);
00420                 if (faceStencil[faceI][0] != globalOwn)
00421                 {
00422                     FatalErrorIn("FECCellToFaceStencil::calcFaceStencil(..)")
00423                         << "problem:" << faceStencil[faceI]
00424                         << " globalOwn:" << globalOwn
00425                         << abort(FatalError);
00426                 }
00427             }
00428         }
00429     }
00430 }
00431 
00432 
00433 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00434 
00435 Foam::FECCellToFaceStencil::FECCellToFaceStencil(const polyMesh& mesh)
00436 :
00437     cellToFaceStencil(mesh)
00438 {
00439     // Calculate per face the (edge) connected cells (in global numbering)
00440     labelListList faceStencil;
00441     calcFaceStencil(faceStencil);
00442 
00443     // Transfer to *this
00444     transfer(faceStencil);
00445 }
00446 
00447 
00448 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines