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

cellToFaceStencil.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 "cellToFaceStencil.H"
00027 #include <OpenFOAM/syncTools.H>
00028 #include <OpenFOAM/SortableList.H>
00029 #include <OpenFOAM/emptyPolyPatch.H>
00030 
00031 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00032 
00033 // Merge two list and guarantee global0,global1 are first.
00034 void Foam::cellToFaceStencil::merge
00035 (
00036     const label global0,
00037     const label global1,
00038     const labelList& listA,
00039     labelList& listB
00040 )
00041 {
00042     sort(listB);
00043 
00044     // See if global0, global1 already present in listB
00045     label nGlobalInsert = 0;
00046 
00047     if (global0 != -1)
00048     {
00049         label index0 = findSortedIndex(listB, global0);
00050         if (index0 == -1)
00051         {
00052             nGlobalInsert++;
00053         }
00054     }
00055 
00056     if (global1 != -1)
00057     {
00058         label index1 = findSortedIndex(listB, global1);
00059         if (index1 == -1)
00060         {
00061             nGlobalInsert++;
00062         }
00063     }
00064 
00065 
00066     // For all in listA see if they are present
00067     label nInsert = 0;
00068 
00069     forAll(listA, i)
00070     {
00071         label elem = listA[i];
00072 
00073         if (elem != global0 && elem != global1)
00074         {
00075             if (findSortedIndex(listB, elem) == -1)
00076             {
00077                 nInsert++;
00078             }
00079         }
00080     }
00081 
00082     // Extend B with nInsert and whether global0,global1 need to be inserted.
00083     labelList result(listB.size() + nGlobalInsert + nInsert);
00084 
00085     label resultI = 0;
00086 
00087     // Insert global0,1 first
00088     if (global0 != -1)
00089     {
00090         result[resultI++] = global0;
00091     }
00092     if (global1 != -1)
00093     {
00094         result[resultI++] = global1;
00095     }
00096 
00097 
00098     // Insert listB
00099     forAll(listB, i)
00100     {
00101         label elem = listB[i];
00102 
00103         if (elem != global0 && elem != global1)
00104         {
00105             result[resultI++] = elem;
00106         }
00107     }
00108 
00109 
00110     // Insert listA
00111     forAll(listA, i)
00112     {
00113         label elem = listA[i];
00114 
00115         if (elem != global0 && elem != global1)
00116         {
00117             if (findSortedIndex(listB, elem) == -1)
00118             {
00119                 result[resultI++] = elem;
00120             }
00121         }
00122     }
00123 
00124     if (resultI != result.size())
00125     {
00126         FatalErrorIn("cellToFaceStencil::merge(..)")
00127             << "problem" << abort(FatalError);
00128     }
00129 
00130     listB.transfer(result);
00131 }
00132 
00133 
00134 // Merge two list and guarantee globalI is first.
00135 void Foam::cellToFaceStencil::merge
00136 (
00137     const label globalI,
00138     const labelList& pGlobals,
00139     labelList& cCells
00140 )
00141 {
00142     labelHashSet set;
00143     forAll(cCells, i)
00144     {
00145         if (cCells[i] != globalI)
00146         {
00147             set.insert(cCells[i]);
00148         }
00149     }
00150 
00151     forAll(pGlobals, i)
00152     {
00153         if (pGlobals[i] != globalI)
00154         {
00155             set.insert(pGlobals[i]);
00156         }
00157     }
00158 
00159     cCells.setSize(set.size()+1);
00160     label n = 0;
00161     cCells[n++] = globalI;
00162 
00163     forAllConstIter(labelHashSet, set, iter)
00164     {
00165         cCells[n++] = iter.key();
00166     }
00167 }
00168 
00169 
00170 void Foam::cellToFaceStencil::validBoundaryFaces(boolList& isValidBFace) const
00171 {
00172     const polyBoundaryMesh& patches = mesh().boundaryMesh();
00173 
00174     isValidBFace.setSize(mesh().nFaces()-mesh().nInternalFaces(), true);
00175 
00176     forAll(patches, patchI)
00177     {
00178         const polyPatch& pp = patches[patchI];
00179 
00180         if (pp.coupled() || isA<emptyPolyPatch>(pp))
00181         {
00182             label bFaceI = pp.start()-mesh().nInternalFaces();
00183             forAll(pp, i)
00184             {
00185                 isValidBFace[bFaceI++] = false;
00186             }
00187         }
00188     }
00189 }
00190 
00191 
00192 Foam::autoPtr<Foam::indirectPrimitivePatch>
00193 Foam::cellToFaceStencil::allCoupledFacesPatch() const
00194 {
00195     const polyBoundaryMesh& patches = mesh().boundaryMesh();
00196 
00197     label nCoupled = 0;
00198 
00199     forAll(patches, patchI)
00200     {
00201         const polyPatch& pp = patches[patchI];
00202 
00203         if (pp.coupled())
00204         {
00205             nCoupled += pp.size();
00206         }
00207     }
00208     labelList coupledFaces(nCoupled);
00209     nCoupled = 0;
00210 
00211     forAll(patches, patchI)
00212     {
00213         const polyPatch& pp = patches[patchI];
00214 
00215         if (pp.coupled())
00216         {
00217             label faceI = pp.start();
00218 
00219             forAll(pp, i)
00220             {
00221                 coupledFaces[nCoupled++] = faceI++;
00222             }
00223         }
00224     }
00225 
00226     return autoPtr<indirectPrimitivePatch>
00227     (
00228         new indirectPrimitivePatch
00229         (
00230             IndirectList<face>
00231             (
00232                 mesh().faces(),
00233                 coupledFaces
00234             ),
00235             mesh().points()
00236         )
00237     );
00238 }
00239 
00240 
00241 void Foam::cellToFaceStencil::unionEqOp::operator()
00242 (
00243     labelList& x,
00244     const labelList& y
00245 ) const
00246 {
00247     if (y.size())
00248     {
00249         if (x.empty())
00250         {
00251             x = y;
00252         }
00253         else
00254         {
00255             labelHashSet set(x);
00256             forAll(y, i)
00257             {
00258                 set.insert(y[i]);
00259             }
00260             x = set.toc();
00261         }
00262     }
00263 }
00264 
00265 
00266 void Foam::cellToFaceStencil::insertFaceCells
00267 (
00268     const label exclude0,
00269     const label exclude1,
00270     const boolList& isValidBFace,
00271     const labelList& faceLabels,
00272     labelHashSet& globals
00273 ) const
00274 {
00275     const labelList& own = mesh().faceOwner();
00276     const labelList& nei = mesh().faceNeighbour();
00277 
00278     forAll(faceLabels, i)
00279     {
00280         label faceI = faceLabels[i];
00281 
00282         label globalOwn = globalNumbering().toGlobal(own[faceI]);
00283         if (globalOwn != exclude0 && globalOwn != exclude1)
00284         {
00285             globals.insert(globalOwn);
00286         }
00287 
00288         if (mesh().isInternalFace(faceI))
00289         {
00290             label globalNei = globalNumbering().toGlobal(nei[faceI]);
00291             if (globalNei != exclude0 && globalNei != exclude1)
00292             {
00293                 globals.insert(globalNei);
00294             }
00295         }
00296         else
00297         {
00298             label bFaceI = faceI-mesh().nInternalFaces();
00299 
00300             if (isValidBFace[bFaceI])
00301             {
00302                 label globalI = globalNumbering().toGlobal
00303                 (
00304                     mesh().nCells()
00305                   + bFaceI
00306                 );
00307 
00308                 if (globalI != exclude0 && globalI != exclude1)
00309                 {
00310                     globals.insert(globalI);
00311                 }
00312             }
00313         }
00314     }
00315 }
00316 
00317 
00318 Foam::labelList Foam::cellToFaceStencil::calcFaceCells
00319 (
00320     const boolList& isValidBFace,
00321     const labelList& faceLabels,
00322     labelHashSet& globals
00323 ) const
00324 {
00325     globals.clear();
00326 
00327     insertFaceCells
00328     (
00329         -1,
00330         -1,
00331         isValidBFace,
00332         faceLabels,
00333         globals
00334     );
00335 
00336     return globals.toc();
00337 }
00338 
00339 
00340 // Calculates per face a list of global cell/face indices.
00341 void Foam::cellToFaceStencil::calcFaceStencil
00342 (
00343     const labelListList& globalCellCells,
00344     labelListList& faceStencil
00345 ) const
00346 {
00347     const polyBoundaryMesh& patches = mesh_.boundaryMesh();
00348     const label nBnd = mesh_.nFaces()-mesh_.nInternalFaces();
00349     const labelList& own = mesh_.faceOwner();
00350     const labelList& nei = mesh_.faceNeighbour();
00351 
00352 
00353     // Determine neighbouring global cell Cells
00354     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00355 
00356     labelListList neiGlobalCellCells(nBnd);
00357     forAll(patches, patchI)
00358     {
00359         const polyPatch& pp = patches[patchI];
00360 
00361         if (pp.coupled())
00362         {
00363             label faceI = pp.start();
00364 
00365             forAll(pp, i)
00366             {
00367                 neiGlobalCellCells[faceI-mesh_.nInternalFaces()] =
00368                     globalCellCells[own[faceI]];
00369                 faceI++;
00370             }
00371         }
00372     }
00373     syncTools::swapBoundaryFaceList(mesh_, neiGlobalCellCells, false);
00374 
00375 
00376 
00377     // Construct stencil in global numbering
00378     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00379 
00380     faceStencil.setSize(mesh_.nFaces());
00381 
00382     labelHashSet faceStencilSet;
00383 
00384     for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
00385     {
00386         faceStencilSet.clear();
00387 
00388         const labelList& ownCCells = globalCellCells[own[faceI]];
00389         label globalOwn = ownCCells[0];
00390         // Insert cellCells
00391         forAll(ownCCells, i)
00392         {
00393             faceStencilSet.insert(ownCCells[i]);
00394         }
00395 
00396         const labelList& neiCCells = globalCellCells[nei[faceI]];
00397         label globalNei = neiCCells[0];
00398         // Insert cellCells
00399         forAll(neiCCells, i)
00400         {
00401             faceStencilSet.insert(neiCCells[i]);
00402         }
00403 
00404         // Guarantee owner first, neighbour second.
00405         faceStencil[faceI].setSize(faceStencilSet.size());
00406         label n = 0;
00407         faceStencil[faceI][n++] = globalOwn;
00408         faceStencil[faceI][n++] = globalNei;
00409         forAllConstIter(labelHashSet, faceStencilSet, iter)
00410         {
00411             if (iter.key() != globalOwn && iter.key() != globalNei)
00412             {
00413                 faceStencil[faceI][n++] = iter.key();
00414             }
00415         }
00416         //Pout<< "internalface:" << faceI << " toc:" << faceStencilSet.toc()
00417         //    << " faceStencil:" << faceStencil[faceI] << endl;
00418     }
00419     forAll(patches, patchI)
00420     {
00421         const polyPatch& pp = patches[patchI];
00422         label faceI = pp.start();
00423 
00424         if (pp.coupled())
00425         {
00426             forAll(pp, i)
00427             {
00428                 faceStencilSet.clear();
00429 
00430                 const labelList& ownCCells = globalCellCells[own[faceI]];
00431                 label globalOwn = ownCCells[0];
00432                 forAll(ownCCells, i)
00433                 {
00434                     faceStencilSet.insert(ownCCells[i]);
00435                 }
00436 
00437                 // And the neighbours of the coupled cell
00438                 const labelList& neiCCells =
00439                     neiGlobalCellCells[faceI-mesh_.nInternalFaces()];
00440                 label globalNei = neiCCells[0];
00441                 forAll(neiCCells, i)
00442                 {
00443                     faceStencilSet.insert(neiCCells[i]);
00444                 }
00445 
00446                 // Guarantee owner first, neighbour second.
00447                 faceStencil[faceI].setSize(faceStencilSet.size());
00448                 label n = 0;
00449                 faceStencil[faceI][n++] = globalOwn;
00450                 faceStencil[faceI][n++] = globalNei;
00451                 forAllConstIter(labelHashSet, faceStencilSet, iter)
00452                 {
00453                     if (iter.key() != globalOwn && iter.key() != globalNei)
00454                     {
00455                         faceStencil[faceI][n++] = iter.key();
00456                     }
00457                 }
00458 
00459                 //Pout<< "coupledface:" << faceI
00460                 //    << " toc:" << faceStencilSet.toc()
00461                 //    << " faceStencil:" << faceStencil[faceI] << endl;
00462 
00463                 faceI++;
00464             }
00465         }
00466         else if (!isA<emptyPolyPatch>(pp))
00467         {
00468             forAll(pp, i)
00469             {
00470                 faceStencilSet.clear();
00471 
00472                 const labelList& ownCCells = globalCellCells[own[faceI]];
00473                 label globalOwn = ownCCells[0];
00474                 forAll(ownCCells, i)
00475                 {
00476                     faceStencilSet.insert(ownCCells[i]);
00477                 }
00478 
00479                 // Guarantee owner first
00480                 faceStencil[faceI].setSize(faceStencilSet.size());
00481                 label n = 0;
00482                 faceStencil[faceI][n++] = globalOwn;
00483                 forAllConstIter(labelHashSet, faceStencilSet, iter)
00484                 {
00485                     if (iter.key() != globalOwn)
00486                     {
00487                         faceStencil[faceI][n++] = iter.key();
00488                     }
00489                 }
00490 
00491                 //Pout<< "boundaryface:" << faceI
00492                 //    << " toc:" << faceStencilSet.toc()
00493                 //    << " faceStencil:" << faceStencil[faceI] << endl;
00494 
00495                 faceI++;
00496             }
00497         }
00498     }
00499 }
00500 
00501 
00502 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00503 
00504 Foam::cellToFaceStencil::cellToFaceStencil(const polyMesh& mesh)
00505 :
00506     mesh_(mesh),
00507     globalNumbering_(mesh_.nCells()+mesh_.nFaces()-mesh_.nInternalFaces())
00508 {}
00509 
00510 
00511 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines