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

Pstream.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 "Pstream.H"
00027 #include <OpenFOAM/debug.H>
00028 #include <OpenFOAM/dictionary.H>
00029 
00030 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00031 
00032 defineTypeNameAndDebug(Foam::Pstream, 0);
00033 
00034 template<>
00035 const char* Foam::NamedEnum<Foam::Pstream::commsTypes, 3>::names[] =
00036 {
00037     "blocking",
00038     "scheduled",
00039     "nonBlocking"
00040 };
00041 
00042 const Foam::NamedEnum<Foam::Pstream::commsTypes, 3>
00043     Foam::Pstream::commsTypeNames;
00044 
00045 Foam::autoPtr<Foam::PstreamImpl> Foam::Pstream::impl_;
00046 
00047 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00048 
00049 
00050 void Foam::Pstream::calcLinearComm(const label nProcs)
00051 {
00052     linearCommunication_.setSize(nProcs);
00053 
00054     // Master
00055     labelList belowIDs(nProcs - 1);
00056     forAll(belowIDs, i)
00057     {
00058         belowIDs[i] = i + 1;
00059     }
00060 
00061     linearCommunication_[0] = commsStruct
00062     (
00063         nProcs,
00064         0,
00065         -1,
00066         belowIDs,
00067         labelList(0)
00068     );
00069 
00070     // Slaves. Have no below processors, only communicate up to master
00071     for (label procID = 1; procID < nProcs; procID++)
00072     {
00073         linearCommunication_[procID] = commsStruct
00074         (
00075             nProcs,
00076             procID,
00077             0,
00078             labelList(0),
00079             labelList(0)
00080         );
00081     }
00082 }
00083 
00084 
00085 // Append my children (and my children children etc.) to allReceives.
00086 void Foam::Pstream::collectReceives
00087 (
00088     const label procID,
00089     const List<DynamicList<label> >& receives,
00090     DynamicList<label>& allReceives
00091 )
00092 {
00093     const DynamicList<label>& myChildren = receives[procID];
00094 
00095     forAll(myChildren, childI)
00096     {
00097         allReceives.append(myChildren[childI]);
00098         collectReceives(myChildren[childI], receives, allReceives);
00099     }
00100 }
00101 
00102 
00103 // Tree like schedule. For 8 procs:
00104 // (level 0)
00105 //      0 receives from 1
00106 //      2 receives from 3
00107 //      4 receives from 5
00108 //      6 receives from 7
00109 // (level 1)
00110 //      0 receives from 2
00111 //      4 receives from 6
00112 // (level 2)
00113 //      0 receives from 4
00114 //
00115 // The sends/receives for all levels are collected per processor (one send per
00116 // processor; multiple receives possible) creating a table:
00117 //
00118 // So per processor:
00119 // proc     receives from   sends to
00120 // ----     -------------   --------
00121 //  0       1,2,4           -
00122 //  1       -               0
00123 //  2       3               0
00124 //  3       -               2
00125 //  4       5               0
00126 //  5       -               4
00127 //  6       7               4
00128 //  7       -               6
00129 void Foam::Pstream::calcTreeComm(label nProcs)
00130 {
00131     label nLevels = 1;
00132     while ((1 << nLevels) < nProcs)
00133     {
00134         nLevels++;
00135     }
00136 
00137     List<DynamicList<label> > receives(nProcs);
00138     labelList sends(nProcs, -1);
00139 
00140     // Info<< "Using " << nLevels << " communication levels" << endl;
00141 
00142     label offset = 2;
00143     label childOffset = offset/2;
00144 
00145     for (label level = 0; level < nLevels; level++)
00146     {
00147         label receiveID = 0;
00148         while (receiveID < nProcs)
00149         {
00150             // Determine processor that sends and we receive from
00151             label sendID = receiveID + childOffset;
00152 
00153             if (sendID < nProcs)
00154             {
00155                 receives[receiveID].append(sendID);
00156                 sends[sendID] = receiveID;
00157             }
00158 
00159             receiveID += offset;
00160         }
00161 
00162         offset <<= 1;
00163         childOffset <<= 1;
00164     }
00165 
00166     // For all processors find the processors it receives data from
00167     // (and the processors they receive data from etc.)
00168     List<DynamicList<label> > allReceives(nProcs);
00169     for (label procID = 0; procID < nProcs; procID++)
00170     {
00171         collectReceives(procID, receives, allReceives[procID]);
00172     }
00173 
00174 
00175     treeCommunication_.setSize(nProcs);
00176 
00177     for (label procID = 0; procID < nProcs; procID++)
00178     {
00179         treeCommunication_[procID] = commsStruct
00180         (
00181             nProcs,
00182             procID,
00183             sends[procID],
00184             receives[procID].shrink(),
00185             allReceives[procID].shrink()
00186         );
00187     }
00188 }
00189 
00190 
00191 // Callback from Pstream::init() : initialize linear and tree communication
00192 // schedules now that nProcs is known.
00193 void Foam::Pstream::initCommunicationSchedule()
00194 {
00195     calcLinearComm(nProcs());
00196     calcTreeComm(nProcs());
00197 }
00198 
00199 
00200 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00201 
00202 // Initialise my process number to 0 (the master)
00203 int Foam::Pstream::myProcNo_(0);
00204 
00205 // By default this is not a parallel run
00206 bool Foam::Pstream::parRun_(false);
00207 
00208 // List of process IDs
00209 Foam::List<int> Foam::Pstream::procIDs_(1, 0);
00210 
00211 // Standard transfer message type
00212 const int Foam::Pstream::msgType_(1);
00213 
00214 // Linear communication schedule
00215 Foam::List<Foam::Pstream::commsStruct> Foam::Pstream::linearCommunication_(0);
00216 
00217 // Multi level communication schedule
00218 Foam::List<Foam::Pstream::commsStruct> Foam::Pstream::treeCommunication_(0);
00219 
00220 // Should compact transfer be used in which floats replace doubles
00221 // reducing the bandwidth requirement at the expense of some loss
00222 // in accuracy
00223 bool Foam::Pstream::floatTransfer
00224 (
00225     debug::optimisationSwitch("floatTransfer", 0)
00226 );
00227 
00228 // Number of processors at which the reduce algorithm changes from linear to
00229 // tree
00230 int Foam::Pstream::nProcsSimpleSum
00231 (
00232     debug::optimisationSwitch("nProcsSimpleSum", 16)
00233 );
00234 
00235 // Default commsType
00236 Foam::Pstream::commsTypes Foam::Pstream::defaultCommsType
00237 (
00238     commsTypeNames.read(debug::optimisationSwitches().lookup("commsType"))
00239 );
00240 
00241 
00242 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines