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

ProcessorTopology_.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 "ProcessorTopology_.H"
00027 #include <OpenFOAM/ListOps.H>
00028 #include <OpenFOAM/Pstream.H>
00029 #include "commSchedule.H"
00030 
00031 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00032 
00033 template<class Patch, class ProcPatch>
00034 Foam::labelList Foam::ProcessorTopology<Patch, ProcPatch>::procNeighbours
00035 (
00036     const PtrList<Patch>& patches
00037 )
00038 {
00039     // Determine number of processor neighbours and max neighbour id.
00040 
00041     label nNeighbours = 0;
00042 
00043     label maxNb = 0;
00044 
00045     forAll(patches, patchi)
00046     {
00047         const Patch& patch = patches[patchi];
00048 
00049         if (isA<ProcPatch>(patch))
00050         {
00051             const ProcPatch& procPatch = 
00052                 refCast<const ProcPatch>(patch);
00053 
00054             nNeighbours++;
00055 
00056             maxNb = max(maxNb, procPatch.neighbProcNo());
00057         }
00058     }
00059 
00060     labelList neighbours(nNeighbours);
00061 
00062     procPatchMap_.setSize(maxNb + 1);
00063     procPatchMap_ = -1;
00064 
00065     nNeighbours = 0;
00066 
00067     forAll(patches, patchi)
00068     {
00069         const Patch& patch = patches[patchi];
00070 
00071         if (isA<ProcPatch>(patch))
00072         {
00073             const ProcPatch& procPatch = 
00074                 refCast<const ProcPatch>(patch);
00075 
00076             neighbours[nNeighbours++] = procPatch.neighbProcNo();
00077 
00078             // Construct reverse map
00079             procPatchMap_[procPatch.neighbProcNo()] = patchi;
00080         }
00081     }
00082 
00083     return neighbours;
00084 }
00085 
00086 
00087 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00088 
00089 // Construct from components
00090 template<class Patch, class ProcPatch>
00091 Foam::ProcessorTopology<Patch, ProcPatch>::ProcessorTopology
00092 (
00093     const PtrList<Patch>& patches
00094 )
00095 :
00096     labelListList(Pstream::nProcs()),
00097     patchSchedule_(2*patches.size())
00098 {
00099     if (Pstream::parRun())
00100     {
00101         // Fill my 'slot' with my neighbours
00102         operator[](Pstream::myProcNo()) = procNeighbours(patches);
00103 
00104         // Distribute to all processors
00105         Pstream::gatherList(*this);
00106         Pstream::scatterList(*this);
00107     }
00108 
00109     if (Pstream::parRun() && Pstream::defaultCommsType == Pstream::scheduled)
00110     {
00111         label patchEvali = 0;
00112 
00113         // 1. All non-processor patches
00114         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00115 
00116         forAll(patches, patchi)
00117         {
00118             if (!isA<ProcPatch>(patches[patchi]))
00119             {
00120                 patchSchedule_[patchEvali].patch = patchi;
00121                 patchSchedule_[patchEvali++].init = true;
00122                 patchSchedule_[patchEvali].patch = patchi;
00123                 patchSchedule_[patchEvali++].init = false;
00124             }
00125         }
00126 
00127         // 2. All processor patches
00128         // ~~~~~~~~~~~~~~~~~~~~~~~~
00129 
00130         // Determine the schedule for all. Insert processor pair once
00131         // to determine the schedule. Each processor pair stands for both
00132         // send and receive.
00133         label nComms = 0;
00134         forAll(*this, procI)
00135         {
00136             nComms += operator[](procI).size();
00137         }
00138         DynamicList<labelPair> comms(nComms);
00139 
00140         forAll(*this, procI)
00141         {
00142             const labelList& nbrs = operator[](procI);
00143 
00144             forAll(nbrs, i)
00145             {
00146                 if (procI < nbrs[i])
00147                 {
00148                     comms.append(labelPair(procI, nbrs[i]));
00149                 }
00150             }
00151         }
00152         comms.shrink();
00153 
00154         // Determine a schedule.
00155         labelList mySchedule
00156         (
00157             commSchedule
00158             (
00159                 Pstream::nProcs(),
00160                 comms
00161             ).procSchedule()[Pstream::myProcNo()]
00162         );
00163 
00164         forAll(mySchedule, iter)
00165         {
00166             label commI = mySchedule[iter];
00167 
00168             // Get the other processor
00169             label nb = comms[commI][0];
00170             if (nb == Pstream::myProcNo())
00171             {
00172                 nb = comms[commI][1];
00173             }
00174             label patchi = procPatchMap_[nb];
00175 
00176             if (Pstream::myProcNo() > nb)
00177             {
00178                 patchSchedule_[patchEvali].patch = patchi;
00179                 patchSchedule_[patchEvali++].init = true;
00180                 patchSchedule_[patchEvali].patch = patchi;
00181                 patchSchedule_[patchEvali++].init = false;
00182             }
00183             else
00184             {
00185                 patchSchedule_[patchEvali].patch = patchi;
00186                 patchSchedule_[patchEvali++].init = false;
00187                 patchSchedule_[patchEvali].patch = patchi;
00188                 patchSchedule_[patchEvali++].init = true;
00189             }
00190         }
00191     }
00192     else
00193     {
00194         label patchEvali = 0;
00195 
00196         // 1. All non-processor patches
00197         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00198 
00199         // Have evaluate directly after initEvaluate. Could have them separated
00200         // as long as they're not intermingled with processor patches since
00201         // then e.g. any reduce parallel traffic would interfere with the
00202         // processor swaps.
00203 
00204         forAll(patches, patchi)
00205         {
00206             if (!isA<ProcPatch>(patches[patchi]))
00207             {
00208                 patchSchedule_[patchEvali].patch = patchi;
00209                 patchSchedule_[patchEvali++].init = true;
00210                 patchSchedule_[patchEvali].patch = patchi;
00211                 patchSchedule_[patchEvali++].init = false;
00212             }
00213         }
00214 
00215         // 2. All processor patches
00216         // ~~~~~~~~~~~~~~~~~~~~~~~~
00217 
00218         // 2a. initEvaluate
00219         forAll(patches, patchi)
00220         {
00221             if (isA<ProcPatch>(patches[patchi]))
00222             {
00223                 patchSchedule_[patchEvali].patch = patchi;
00224                 patchSchedule_[patchEvali++].init = true;
00225             }
00226         }
00227 
00228         // 2b. evaluate
00229         forAll(patches, patchi)
00230         {
00231             if (isA<ProcPatch>(patches[patchi]))
00232             {
00233                 patchSchedule_[patchEvali].patch = patchi;
00234                 patchSchedule_[patchEvali++].init = false;
00235             }
00236         }
00237     }
00238 }
00239 
00240 
00241 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines