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

extendedUpwindCellToFaceStencil.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 "extendedUpwindCellToFaceStencil.H"
00027 #include <finiteVolume/cellToFaceStencil.H>
00028 #include <OpenFOAM/syncTools.H>
00029 #include <OpenFOAM/SortableList.H>
00030 
00031 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00032 
00033 void Foam::extendedUpwindCellToFaceStencil::selectOppositeFaces
00034 (
00035     const boolList& nonEmptyFace,
00036     const scalar minOpposedness,
00037     const label faceI,
00038     const label cellI,
00039     DynamicList<label>& oppositeFaces
00040 ) const
00041 {
00042     const vectorField& areas = mesh_.faceAreas();
00043     const labelList& own = mesh_.faceOwner();
00044     const cell& cFaces = mesh_.cells()[cellI];
00045 
00046     SortableList<scalar> opposedness(cFaces.size(), -GREAT);
00047 
00048     // Pick up all the faces that oppose this one.
00049     forAll(cFaces, i)
00050     {
00051         label otherFaceI = cFaces[i];
00052 
00053         if (otherFaceI != faceI && nonEmptyFace[otherFaceI])
00054         {
00055             if ((own[otherFaceI] == cellI) == (own[faceI] == cellI))
00056             {
00057                 opposedness[i] = -(areas[otherFaceI] & areas[faceI]);
00058             }
00059             else
00060             {
00061                 opposedness[i] = (areas[otherFaceI] & areas[faceI]);
00062             }
00063         }
00064     }
00065 
00066     label sz = opposedness.size();
00067 
00068     oppositeFaces.clear();
00069 
00070     scalar myAreaSqr = magSqr(areas[faceI]);
00071 
00072     if (myAreaSqr > VSMALL)
00073     {
00074         forAll(opposedness, i)
00075         {
00076             opposedness[i] /= myAreaSqr;
00077         }
00078         // Sort in incrementing order
00079         opposedness.sort();
00080 
00081         // Pick largest no matter what
00082         oppositeFaces.append(cFaces[opposedness.indices()[sz-1]]);
00083 
00084         for (label i = sz-2; i >= 0; --i)
00085         {
00086             if (opposedness[i] < minOpposedness)
00087             {
00088                 break;
00089             }
00090             oppositeFaces.append(cFaces[opposedness.indices()[i]]);
00091         }
00092     }
00093     else
00094     {
00095         // Sort in incrementing order
00096         opposedness.sort();
00097 
00098         // Tiny face. Do what?
00099         // Pick largest no matter what
00100         oppositeFaces.append(cFaces[opposedness.indices()[sz-1]]);
00101     }
00102 }
00103 
00104 
00105 void Foam::extendedUpwindCellToFaceStencil::transportStencil
00106 (
00107     const boolList& nonEmptyFace,
00108     const labelListList& faceStencil,
00109     const scalar minOpposedness,
00110     const label faceI,
00111     const label cellI,
00112     const bool stencilHasNeighbour,
00113 
00114     DynamicList<label>& oppositeFaces,
00115     labelHashSet& faceStencilSet,
00116     labelList& transportedStencil
00117 ) const
00118 {
00119     label globalOwn = faceStencil[faceI][0];
00120     label globalNei = -1;
00121     if (stencilHasNeighbour && faceStencil[faceI].size() >= 2)
00122     {
00123         globalNei = faceStencil[faceI][1];
00124     }
00125 
00126 
00127     selectOppositeFaces
00128     (
00129         nonEmptyFace,
00130         minOpposedness,
00131         faceI,
00132         cellI,
00133         oppositeFaces
00134     );
00135 
00136     // Collect all stencils of oppositefaces
00137     faceStencilSet.clear();
00138     forAll(oppositeFaces, i)
00139     {
00140         const labelList& fStencil = faceStencil[oppositeFaces[i]];
00141 
00142         forAll(fStencil, j)
00143         {
00144             label globalI = fStencil[j];
00145 
00146             if (globalI != globalOwn && globalI != globalNei)
00147             {
00148                 faceStencilSet.insert(globalI);
00149             }
00150         }
00151     }
00152 
00153     // Add my owner and neighbour first.
00154     if (stencilHasNeighbour)
00155     {
00156         transportedStencil.setSize(faceStencilSet.size()+2);
00157         label n = 0;
00158         transportedStencil[n++] = globalOwn;
00159         transportedStencil[n++] = globalNei;
00160 
00161         forAllConstIter(labelHashSet, faceStencilSet, iter)
00162         {
00163             if (iter.key() != globalOwn && iter.key() != globalNei)
00164             {
00165                 transportedStencil[n++] = iter.key();
00166             }
00167         }
00168         if (n != transportedStencil.size())
00169         {
00170             FatalErrorIn
00171             (
00172                 "extendedUpwindCellToFaceStencil::transportStencil(..)"
00173             )   << "problem:" << faceStencilSet
00174                 << abort(FatalError);
00175         }
00176     }
00177     else
00178     {
00179         transportedStencil.setSize(faceStencilSet.size()+1);
00180         label n = 0;
00181         transportedStencil[n++] = globalOwn;
00182 
00183         forAllConstIter(labelHashSet, faceStencilSet, iter)
00184         {
00185             if (iter.key() != globalOwn)
00186             {
00187                 transportedStencil[n++] = iter.key();
00188             }
00189         }
00190         if (n != transportedStencil.size())
00191         {
00192             FatalErrorIn
00193             (
00194                 "extendedUpwindCellToFaceStencil::transportStencil(..)"
00195             )   << "problem:" << faceStencilSet
00196                 << abort(FatalError);
00197         }
00198     }
00199 }
00200 
00201 
00202 void Foam::extendedUpwindCellToFaceStencil::transportStencils
00203 (
00204     const labelListList& faceStencil,
00205     const scalar minOpposedness,
00206     labelListList& ownStencil,
00207     labelListList& neiStencil
00208 )
00209 {
00210     const polyBoundaryMesh& patches = mesh_.boundaryMesh();
00211     const label nBnd = mesh_.nFaces()-mesh_.nInternalFaces();
00212     const labelList& own = mesh_.faceOwner();
00213     const labelList& nei = mesh_.faceNeighbour();
00214 
00215     // Work arrays
00216     DynamicList<label> oppositeFaces;
00217     labelHashSet faceStencilSet;
00218 
00219 
00220     // For quick detection of empty faces
00221     boolList nonEmptyFace(mesh_.nFaces(), true);
00222     forAll(patches, patchI)
00223     {
00224         const polyPatch& pp = patches[patchI];
00225 
00226         if (isA<emptyPolyPatch>(pp))
00227         {
00228             label faceI = pp.start();
00229             forAll(pp, i)
00230             {
00231                 nonEmptyFace[faceI++] = false;
00232             }
00233         }
00234     }
00235 
00236 
00237     // Do the owner side
00238     // ~~~~~~~~~~~~~~~~~
00239     // stencil is synchronised at entry so no need to swap.
00240 
00241     ownStencil.setSize(mesh_.nFaces());
00242 
00243     // Internal faces
00244     for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
00245     {
00246         // Get stencil as owner + neighbour + stencil from 'opposite' faces
00247         transportStencil
00248         (
00249             nonEmptyFace,
00250             faceStencil,
00251             minOpposedness,
00252             faceI,
00253             own[faceI],
00254             true,                   //stencilHasNeighbour
00255             oppositeFaces,
00256             faceStencilSet,
00257             ownStencil[faceI]
00258         );
00259     }
00260     // Boundary faces
00261     forAll(patches, patchI)
00262     {
00263         const polyPatch& pp = patches[patchI];
00264         label faceI = pp.start();
00265 
00266         if (pp.coupled())
00267         {
00268             forAll(pp, i)
00269             {
00270                 transportStencil
00271                 (
00272                     nonEmptyFace,
00273                     faceStencil,
00274                     minOpposedness,
00275                     faceI,
00276                     own[faceI],
00277                     true,                   //stencilHasNeighbour
00278 
00279                     oppositeFaces,
00280                     faceStencilSet,
00281                     ownStencil[faceI]
00282                 );
00283                 faceI++;
00284             }
00285         }
00286         else if (!isA<emptyPolyPatch>(pp))
00287         {
00288             forAll(pp, i)
00289             {
00290                 // faceStencil does not contain neighbour
00291                 transportStencil
00292                 (
00293                     nonEmptyFace,
00294                     faceStencil,
00295                     minOpposedness,
00296                     faceI,
00297                     own[faceI],
00298                     false,                  //stencilHasNeighbour
00299 
00300                     oppositeFaces,
00301                     faceStencilSet,
00302                     ownStencil[faceI]
00303                 );
00304                 faceI++;
00305             }
00306         }
00307     }
00308 
00309 
00310     // Swap coupled boundary stencil
00311     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00312     
00313     labelListList neiBndStencil(nBnd);
00314     for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
00315     {
00316         neiBndStencil[faceI-mesh_.nInternalFaces()] = ownStencil[faceI];
00317     }
00318     syncTools::swapBoundaryFaceList(mesh_, neiBndStencil, false);
00319 
00320 
00321     // Do the neighbour side
00322     // ~~~~~~~~~~~~~~~~~~~~~
00323     // - internal faces : get opposite faces on neighbour side
00324     // - boundary faces : empty
00325     // - coupled faces  : in neiBndStencil
00326 
00327     neiStencil.setSize(mesh_.nFaces());
00328 
00329     // Internal faces
00330     for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
00331     {
00332         transportStencil
00333         (
00334             nonEmptyFace,
00335             faceStencil,
00336             minOpposedness,
00337             faceI,
00338             nei[faceI],
00339             true,                   //stencilHasNeighbour
00340 
00341             oppositeFaces,
00342             faceStencilSet,
00343             neiStencil[faceI]
00344         );
00345     }
00346 
00347     // Boundary faces
00348     forAll(patches, patchI)
00349     {
00350         const polyPatch& pp = patches[patchI];
00351         label faceI = pp.start();
00352 
00353         if (pp.coupled())
00354         {
00355             forAll(pp, i)
00356             {
00357                 neiStencil[faceI].transfer
00358                 (
00359                     neiBndStencil[faceI-mesh_.nInternalFaces()]
00360                 );
00361                 faceI++;
00362             }
00363         }
00364         else
00365         {
00366             // Boundary has empty neighbour stencil
00367         }
00368     }
00369 }
00370 
00371 
00372 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00373 
00374 Foam::extendedUpwindCellToFaceStencil::extendedUpwindCellToFaceStencil
00375 (
00376     const cellToFaceStencil& stencil,
00377     const bool pureUpwind,
00378     const scalar minOpposedness
00379 )
00380 :
00381     extendedCellToFaceStencil(stencil.mesh()),
00382     pureUpwind_(pureUpwind)
00383 {
00384     //forAll(stencil, faceI)
00385     //{
00386     //    const labelList& fCells = stencil[faceI];
00387     //
00388     //    Pout<< "Face:" << faceI << " at:" << mesh_.faceCentres()[faceI]
00389     //        << endl;
00390     //
00391     //    forAll(fCells, i)
00392     //    {
00393     //        label globalI = fCells[i];
00394     //
00395     //        if (globalI < mesh_.nCells())
00396     //        {
00397     //            Pout<< "    cell:" << globalI
00398     //                << " at:" << mesh_.cellCentres()[globalI] << endl;
00399     //        }
00400     //        else
00401     //        {
00402     //            label faceI = globalI-mesh_.nCells() + mesh_.nInternalFaces();
00403     //
00404     //            Pout<< "    boundary:" << faceI
00405     //                << " at:" << mesh_.faceCentres()[faceI] << endl;
00406     //        }
00407     //    }
00408     //}
00409     //Pout<< endl << endl;
00410 
00411 
00412     // Transport centred stencil to upwind/downwind face
00413     transportStencils
00414     (
00415         stencil,
00416         minOpposedness,
00417         ownStencil_,
00418         neiStencil_
00419     );
00420 
00421     ownMapPtr_ = calcDistributeMap
00422     (
00423         stencil.mesh(),
00424         stencil.globalNumbering(),
00425         ownStencil_
00426     );
00427 
00428     neiMapPtr_ = calcDistributeMap
00429     (
00430         stencil.mesh(),
00431         stencil.globalNumbering(),
00432         neiStencil_
00433     );
00434 
00435     // stencil now in compact form
00436     if (pureUpwind_)
00437     {
00438         const fvMesh& mesh = dynamic_cast<const fvMesh&>(stencil.mesh());
00439 
00440         List<List<point> > stencilPoints(ownStencil_.size());
00441 
00442         // Owner stencil
00443         // ~~~~~~~~~~~~~
00444 
00445         collectData(ownMapPtr_(), ownStencil_, mesh.C(), stencilPoints);
00446 
00447         // Mask off all stencil points on wrong side of face
00448         forAll(stencilPoints, faceI)
00449         {
00450             const point& fc = mesh.faceCentres()[faceI];
00451             const vector& fArea = mesh.faceAreas()[faceI];
00452 
00453             const List<point>& points = stencilPoints[faceI];
00454             const labelList& stencil = ownStencil_[faceI];
00455 
00456             DynamicList<label> newStencil(stencil.size());
00457             forAll(points, i)
00458             {
00459                 if (((points[i]-fc) & fArea) < 0)
00460                 {
00461                     newStencil.append(stencil[i]);
00462                 }
00463             }
00464             if (newStencil.size() != stencil.size())
00465             {
00466                 ownStencil_[faceI].transfer(newStencil);
00467             }
00468         }
00469 
00470 
00471         // Neighbour stencil
00472         // ~~~~~~~~~~~~~~~~~
00473 
00474         collectData(neiMapPtr_(), neiStencil_, mesh.C(), stencilPoints);
00475 
00476         // Mask off all stencil points on wrong side of face
00477         forAll(stencilPoints, faceI)
00478         {
00479             const point& fc = mesh.faceCentres()[faceI];
00480             const vector& fArea = mesh.faceAreas()[faceI];
00481 
00482             const List<point>& points = stencilPoints[faceI];
00483             const labelList& stencil = neiStencil_[faceI];
00484 
00485             DynamicList<label> newStencil(stencil.size());
00486             forAll(points, i)
00487             {
00488                 if (((points[i]-fc) & fArea) > 0)
00489                 {
00490                     newStencil.append(stencil[i]);
00491                 }
00492             }
00493             if (newStencil.size() != stencil.size())
00494             {
00495                 neiStencil_[faceI].transfer(newStencil);
00496             }
00497         }
00498 
00499         // Note: could compact schedule as well. for if cells are not needed
00500         // across any boundary anymore. However relatively rare.
00501     }
00502 }
00503 
00504 
00505 Foam::extendedUpwindCellToFaceStencil::extendedUpwindCellToFaceStencil
00506 (
00507     const cellToFaceStencil& stencil
00508 )
00509 :
00510     extendedCellToFaceStencil(stencil.mesh()),
00511     pureUpwind_(true)
00512 {
00513     // Calculate stencil points with full stencil
00514 
00515     ownStencil_ = stencil;
00516 
00517     ownMapPtr_ = calcDistributeMap
00518     (
00519         stencil.mesh(),
00520         stencil.globalNumbering(),
00521         ownStencil_
00522     );
00523 
00524     const fvMesh& mesh = dynamic_cast<const fvMesh&>(stencil.mesh());
00525 
00526     List<List<point> > stencilPoints(ownStencil_.size());
00527     collectData(ownMapPtr_(), ownStencil_, mesh.C(), stencilPoints);
00528 
00529     // Split stencil into owner and neighbour
00530     neiStencil_.setSize(ownStencil_.size());
00531 
00532     forAll(stencilPoints, faceI)
00533     {
00534         const point& fc = mesh.faceCentres()[faceI];
00535         const vector& fArea = mesh.faceAreas()[faceI];
00536 
00537         const List<point>& points = stencilPoints[faceI];
00538         const labelList& stencil = ownStencil_[faceI];
00539 
00540         DynamicList<label> newOwnStencil(stencil.size());
00541         DynamicList<label> newNeiStencil(stencil.size());
00542         forAll(points, i)
00543         {
00544             if (((points[i]-fc) & fArea) > 0)
00545             {
00546                 newNeiStencil.append(stencil[i]);
00547             }
00548             else
00549             {
00550                 newOwnStencil.append(stencil[i]);
00551             }
00552         }
00553         if (newNeiStencil.size() > 0)
00554         {
00555             ownStencil_[faceI].transfer(newOwnStencil);
00556             neiStencil_[faceI].transfer(newNeiStencil);
00557         }
00558     }
00559 
00560     // Should compact schedule. Or have both return the same schedule.
00561     neiMapPtr_.reset(new mapDistribute(ownMapPtr_()));
00562 }
00563 
00564 
00565 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines