initial commit for version 1.6.x patch release
[OpenFOAM-1.6.x.git] / src / OpenFOAM / db / IOstreams / Pstreams / Pstream.C
blobbdb31516bac60b06d5e0cf97c183f23b8b018374
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM is free software; you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation; either version 2 of the License, or (at your
14     option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM; if not, write to the Free Software Foundation,
23     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "Pstream.H"
28 #include "debug.H"
29 #include "dictionary.H"
31 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 defineTypeNameAndDebug(Foam::Pstream, 0);
35 template<>
36 const char* Foam::NamedEnum<Foam::Pstream::commsTypes, 3>::names[] =
38     "blocking",
39     "scheduled",
40     "nonBlocking"
43 const Foam::NamedEnum<Foam::Pstream::commsTypes, 3>
44     Foam::Pstream::commsTypeNames;
47 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
49 void Foam::Pstream::setParRun()
51     parRun_ = true;
53     Pout.prefix() = '[' +  name(myProcNo()) + "] ";
54     Perr.prefix() = '[' +  name(myProcNo()) + "] ";
58 void Foam::Pstream::calcLinearComm(const label nProcs)
60     linearCommunication_.setSize(nProcs);
62     // Master
63     labelList belowIDs(nProcs - 1);
64     forAll(belowIDs, i)
65     {
66         belowIDs[i] = i + 1;
67     }
69     linearCommunication_[0] = commsStruct
70     (
71         nProcs,
72         0,
73         -1,
74         belowIDs,
75         labelList(0)
76     );
78     // Slaves. Have no below processors, only communicate up to master
79     for (label procID = 1; procID < nProcs; procID++)
80     {
81         linearCommunication_[procID] = commsStruct
82         (
83             nProcs,
84             procID,
85             0,
86             labelList(0),
87             labelList(0)
88         );
89     }
93 // Append my children (and my children children etc.) to allReceives.
94 void Foam::Pstream::collectReceives
96     const label procID,
97     const List<DynamicList<label> >& receives,
98     DynamicList<label>& allReceives
101     const DynamicList<label>& myChildren = receives[procID];
103     forAll(myChildren, childI)
104     {
105         allReceives.append(myChildren[childI]);
106         collectReceives(myChildren[childI], receives, allReceives);
107     }
111 // Tree like schedule. For 8 procs:
112 // (level 0)
113 //      0 receives from 1
114 //      2 receives from 3
115 //      4 receives from 5
116 //      6 receives from 7
117 // (level 1)
118 //      0 receives from 2
119 //      4 receives from 6
120 // (level 2)
121 //      0 receives from 4
123 // The sends/receives for all levels are collected per processor (one send per
124 // processor; multiple receives possible) creating a table:
126 // So per processor:
127 // proc     receives from   sends to
128 // ----     -------------   --------
129 //  0       1,2,4           -
130 //  1       -               0
131 //  2       3               0
132 //  3       -               2
133 //  4       5               0
134 //  5       -               4
135 //  6       7               4
136 //  7       -               6
137 void Foam::Pstream::calcTreeComm(label nProcs)
139     label nLevels = 1;
140     while ((1 << nLevels) < nProcs)
141     {
142         nLevels++;
143     }
145     List<DynamicList<label> > receives(nProcs);
146     labelList sends(nProcs, -1);
148     // Info<< "Using " << nLevels << " communication levels" << endl;
150     label offset = 2;
151     label childOffset = offset/2;
153     for (label level = 0; level < nLevels; level++)
154     {
155         label receiveID = 0;
156         while (receiveID < nProcs)
157         {
158             // Determine processor that sends and we receive from
159             label sendID = receiveID + childOffset;
161             if (sendID < nProcs)
162             {
163                 receives[receiveID].append(sendID);
164                 sends[sendID] = receiveID;
165             }
167             receiveID += offset;
168         }
170         offset <<= 1;
171         childOffset <<= 1;
172     }
174     // For all processors find the processors it receives data from
175     // (and the processors they receive data from etc.)
176     List<DynamicList<label> > allReceives(nProcs);
177     for (label procID = 0; procID < nProcs; procID++)
178     {
179         collectReceives(procID, receives, allReceives[procID]);
180     }
183     treeCommunication_.setSize(nProcs);
185     for (label procID = 0; procID < nProcs; procID++)
186     {
187         treeCommunication_[procID] = commsStruct
188         (
189             nProcs,
190             procID,
191             sends[procID],
192             receives[procID].shrink(),
193             allReceives[procID].shrink()
194         );
195     }
199 // Callback from Pstream::init() : initialize linear and tree communication
200 // schedules now that nProcs is known.
201 void Foam::Pstream::initCommunicationSchedule()
203     calcLinearComm(nProcs());
204     calcTreeComm(nProcs());
208 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
210 // Initialise my process number to 0 (the master)
211 int Foam::Pstream::myProcNo_(0);
213 // By default this is not a parallel run
214 bool Foam::Pstream::parRun_(false);
216 // List of process IDs
217 Foam::List<int> Foam::Pstream::procIDs_(1, 0);
219 // Standard transfer message type
220 const int Foam::Pstream::msgType_(1);
222 // Linear communication schedule
223 Foam::List<Foam::Pstream::commsStruct> Foam::Pstream::linearCommunication_(0);
225 // Multi level communication schedule
226 Foam::List<Foam::Pstream::commsStruct> Foam::Pstream::treeCommunication_(0);
228 // Should compact transfer be used in which floats replace doubles
229 // reducing the bandwidth requirement at the expense of some loss
230 // in accuracy
231 bool Foam::Pstream::floatTransfer
233     debug::optimisationSwitch("floatTransfer", 0)
236 // Number of processors at which the reduce algorithm changes from linear to
237 // tree
238 int Foam::Pstream::nProcsSimpleSum
240     debug::optimisationSwitch("nProcsSimpleSum", 16)
243 // Default commsType
244 Foam::Pstream::commsTypes Foam::Pstream::defaultCommsType
246     commsTypeNames.read(debug::optimisationSwitches().lookup("commsType"))
250 // ************************************************************************* //