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

extendedCellToFaceStencil.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 "extendedCellToFaceStencil.H"
00027 #include <OpenFOAM/globalIndex.H>
00028 #include <OpenFOAM/syncTools.H>
00029 #include <OpenFOAM/SortableList.H>
00030 
00031 /* * * * * * * * * * * * * * * Static Member Data  * * * * * * * * * * * * * */
00032 
00033 defineTypeNameAndDebug(Foam::extendedCellToFaceStencil, 0);
00034 
00035 
00036 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00037 
00038 void Foam::extendedCellToFaceStencil::writeStencilStats
00039 (
00040     Ostream& os,
00041     const labelListList& stencil,
00042     const mapDistribute& map
00043 )
00044 {
00045     label sumSize = 0;
00046     label nSum = 0;
00047     label minSize = labelMax;
00048     label maxSize = labelMin;
00049 
00050     forAll(stencil, i)
00051     {
00052         const labelList& sCells = stencil[i];
00053 
00054         if (sCells.size() > 0)
00055         {
00056             sumSize += sCells.size();
00057             nSum++;
00058             minSize = min(minSize, sCells.size());
00059             maxSize = max(maxSize, sCells.size());
00060         }
00061     }
00062     reduce(sumSize, sumOp<label>());
00063     reduce(nSum, sumOp<label>());
00064 
00065     reduce(minSize, minOp<label>());
00066     reduce(maxSize, maxOp<label>());
00067 
00068     os  << "Stencil size :" << nl
00069         << "    average : " << scalar(sumSize)/nSum << nl
00070         << "    min     : " << minSize << nl
00071         << "    max     : " << maxSize << nl
00072         << endl;
00073 
00074     // Sum all sent data
00075     label nSent = 0;
00076     label nLocal = 0;
00077     forAll(map.subMap(), procI)
00078     {
00079         if (procI != Pstream::myProcNo())
00080         {
00081             nSent += map.subMap()[procI].size();
00082         }
00083         else
00084         {
00085             nLocal += map.subMap()[procI].size();
00086         }
00087     }
00088 
00089     os  << "Local data size : " << returnReduce(nLocal, sumOp<label>()) << nl
00090         << "Sent data size  : " << returnReduce(nSent, sumOp<label>()) << nl
00091         << endl;
00092 }
00093 
00094 
00095 Foam::autoPtr<Foam::mapDistribute>
00096 Foam::extendedCellToFaceStencil::calcDistributeMap
00097 (
00098     const polyMesh& mesh,
00099     const globalIndex& globalNumbering,
00100     labelListList& faceStencil
00101 )
00102 {
00103     // Convert stencil to schedule
00104     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
00105 
00106     // We now know what information we need from other processors. This needs
00107     // to be converted into what information I need to send as well
00108     // (mapDistribute)
00109 
00110 
00111     // 1. Construct per processor compact addressing of the global cells
00112     //    needed. The ones from the local processor are not included since
00113     //    these are always all needed.
00114     List<Map<label> > globalToProc(Pstream::nProcs());
00115     {
00116         const labelList& procPatchMap = mesh.globalData().procPatchMap();
00117         const polyBoundaryMesh& patches = mesh.boundaryMesh();
00118 
00119         // Presize with (as estimate) size of patch to neighbour.
00120         forAll(procPatchMap, procI)
00121         {
00122             if (procPatchMap[procI] != -1)
00123             {
00124                 globalToProc[procI].resize
00125                 (
00126                     patches[procPatchMap[procI]].size()
00127                 );
00128             }
00129         }
00130 
00131         // Collect all (non-local) globalcells/faces needed.
00132         forAll(faceStencil, faceI)
00133         {
00134             const labelList& stencilCells = faceStencil[faceI];
00135 
00136             forAll(stencilCells, i)
00137             {
00138                 label globalCellI = stencilCells[i];
00139                 label procI = globalNumbering.whichProcID(stencilCells[i]);
00140 
00141                 if (procI != Pstream::myProcNo())
00142                 {
00143                     label nCompact = globalToProc[procI].size();
00144                     globalToProc[procI].insert(globalCellI, nCompact);
00145                 }
00146             }
00147         }
00148         // Sort global cells needed (not really necessary)
00149         forAll(globalToProc, procI)
00150         {
00151             if (procI != Pstream::myProcNo())
00152             {
00153                 Map<label>& globalMap = globalToProc[procI];
00154 
00155                 SortableList<label> sorted(globalMap.toc().xfer());
00156 
00157                 forAll(sorted, i)
00158                 {
00159                     Map<label>::iterator iter = globalMap.find(sorted[i]);
00160                     iter() = i;
00161                 }
00162             }
00163         }
00164 
00165 
00166         //forAll(globalToProc, procI)
00167         //{
00168         //    Pout<< "From processor:" << procI << " want cells/faces:" << endl;
00169         //    forAllConstIter(Map<label>, globalToProc[procI], iter)
00170         //    {
00171         //        Pout<< "    global:" << iter.key()
00172         //            << " local:" << globalNumbering.toLocal(procI, iter.key())
00173         //            << endl;
00174         //    }
00175         //    Pout<< endl;
00176         //}
00177     }
00178 
00179 
00180     // 2. The overall compact addressing is
00181     // - myProcNo data first (uncompacted)
00182     // - all other processors consecutively
00183 
00184     labelList compactStart(Pstream::nProcs());
00185     compactStart[Pstream::myProcNo()] = 0;
00186     label nCompact = globalNumbering.localSize();
00187     forAll(compactStart, procI)
00188     {
00189         if (procI != Pstream::myProcNo())
00190         {
00191             compactStart[procI] = nCompact;
00192             nCompact += globalToProc[procI].size();
00193         }
00194     }
00195 
00196 
00197     // 3. Find out what to receive/send in compact addressing.
00198     labelListList recvCompact(Pstream::nProcs());
00199     for (label procI = 0; procI < Pstream::nProcs(); procI++)
00200     {
00201         if (procI != Pstream::myProcNo())
00202         {
00203             labelList wantedGlobals(globalToProc[procI].size());
00204             recvCompact[procI].setSize(globalToProc[procI].size());
00205 
00206             label i = 0;
00207             forAllConstIter(Map<label>, globalToProc[procI], iter)
00208             {
00209                 wantedGlobals[i] = iter.key();
00210                 recvCompact[procI][i] = compactStart[procI]+iter();
00211                 i++;
00212             }
00213 
00214             // Send the global cell numbers I need from procI
00215             OPstream str(Pstream::blocking, procI);
00216             str << wantedGlobals;
00217         }
00218         else
00219         {
00220             recvCompact[procI] =
00221                 compactStart[procI]
00222               + identity(globalNumbering.localSize());
00223         }
00224     }
00225     labelListList sendCompact(Pstream::nProcs());
00226     for (label procI = 0; procI < Pstream::nProcs(); procI++)
00227     {
00228         if (procI != Pstream::myProcNo())
00229         {
00230             // See what neighbour wants to receive (= what I need to send)
00231 
00232             IPstream str(Pstream::blocking, procI);
00233             labelList globalCells(str);
00234 
00235             labelList& procCompact = sendCompact[procI];
00236             procCompact.setSize(globalCells.size());
00237 
00238             // Convert from globalCells (all on my processor!) into compact
00239             // addressing
00240             forAll(globalCells, i)
00241             {
00242                 label cellI = globalNumbering.toLocal(globalCells[i]);
00243                 procCompact[i] = compactStart[Pstream::myProcNo()]+cellI;
00244             }
00245         }
00246         else
00247         {
00248             sendCompact[procI] = recvCompact[procI];
00249         }
00250     }
00251 
00252     // Convert stencil to compact numbering
00253     forAll(faceStencil, faceI)
00254     {
00255         labelList& stencilCells = faceStencil[faceI];
00256 
00257         forAll(stencilCells, i)
00258         {
00259             label globalCellI = stencilCells[i];
00260             label procI = globalNumbering.whichProcID(globalCellI);
00261             if (procI != Pstream::myProcNo())
00262             {
00263                 label localCompact = globalToProc[procI][globalCellI];
00264                 stencilCells[i] = compactStart[procI]+localCompact;
00265             }
00266             else
00267             {
00268                 label localCompact = globalNumbering.toLocal(globalCellI);
00269                 stencilCells[i] = compactStart[procI]+localCompact;
00270             }
00271 
00272         }
00273     }
00274 
00275 
00276     // Constuct map for distribution of compact data.
00277     autoPtr<mapDistribute> mapPtr
00278     (
00279         new mapDistribute
00280         (
00281             nCompact,
00282             sendCompact,
00283             recvCompact,
00284             true            // reuse send/recv maps.
00285         )
00286     );
00287 
00288     return mapPtr;
00289 }
00290 
00291 
00292 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00293 
00294 Foam::extendedCellToFaceStencil::extendedCellToFaceStencil(const polyMesh& mesh)
00295 :
00296     mesh_(mesh)
00297 {
00298     // Check for transformation - not supported.
00299     const polyBoundaryMesh& patches = mesh.boundaryMesh();
00300 
00301     forAll(patches, patchI)
00302     {
00303         if (isA<coupledPolyPatch>(patches[patchI]))
00304         {
00305             const coupledPolyPatch& cpp =
00306                 refCast<const coupledPolyPatch>(patches[patchI]);
00307 
00308             if (!cpp.parallel() || cpp.separated())
00309             {
00310                 FatalErrorIn
00311                 (
00312                     "extendedCellToFaceStencil::extendedCellToFaceStencil"
00313                     "(const polyMesh&)"
00314                 )   << "Coupled patches with transformations not supported."
00315                     << endl
00316                     << "Problematic patch " << cpp.name() << exit(FatalError);
00317             }
00318         }
00319     }
00320 }
00321 
00322 
00323 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines