FreeFOAM The Cross-Platform CFD Toolkit
Pstream.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
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.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "Pstream.H"
27 #include <OpenFOAM/debug.H>
28 #include <OpenFOAM/dictionary.H>
29 
30 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
31 
33 
34 template<>
36 {
37  "blocking",
38  "scheduled",
39  "nonBlocking"
40 };
41 
44 
45 Foam::autoPtr<Foam::PstreamImpl> Foam::Pstream::impl_;
46 
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
48 
49 
50 void Foam::Pstream::calcLinearComm(const label nProcs)
51 {
52  linearCommunication_.setSize(nProcs);
53 
54  // Master
55  labelList belowIDs(nProcs - 1);
56  forAll(belowIDs, i)
57  {
58  belowIDs[i] = i + 1;
59  }
60 
61  linearCommunication_[0] = commsStruct
62  (
63  nProcs,
64  0,
65  -1,
66  belowIDs,
67  labelList(0)
68  );
69 
70  // Slaves. Have no below processors, only communicate up to master
71  for (label procID = 1; procID < nProcs; procID++)
72  {
73  linearCommunication_[procID] = commsStruct
74  (
75  nProcs,
76  procID,
77  0,
78  labelList(0),
79  labelList(0)
80  );
81  }
82 }
83 
84 
85 // Append my children (and my children children etc.) to allReceives.
86 void Foam::Pstream::collectReceives
87 (
88  const label procID,
89  const List<DynamicList<label> >& receives,
90  DynamicList<label>& allReceives
91 )
92 {
93  const DynamicList<label>& myChildren = receives[procID];
94 
95  forAll(myChildren, childI)
96  {
97  allReceives.append(myChildren[childI]);
98  collectReceives(myChildren[childI], receives, allReceives);
99  }
100 }
101 
102 
103 // Tree like schedule. For 8 procs:
104 // (level 0)
105 // 0 receives from 1
106 // 2 receives from 3
107 // 4 receives from 5
108 // 6 receives from 7
109 // (level 1)
110 // 0 receives from 2
111 // 4 receives from 6
112 // (level 2)
113 // 0 receives from 4
114 //
115 // The sends/receives for all levels are collected per processor (one send per
116 // processor; multiple receives possible) creating a table:
117 //
118 // So per processor:
119 // proc receives from sends to
120 // ---- ------------- --------
121 // 0 1,2,4 -
122 // 1 - 0
123 // 2 3 0
124 // 3 - 2
125 // 4 5 0
126 // 5 - 4
127 // 6 7 4
128 // 7 - 6
129 void Foam::Pstream::calcTreeComm(label nProcs)
130 {
131  label nLevels = 1;
132  while ((1 << nLevels) < nProcs)
133  {
134  nLevels++;
135  }
136 
137  List<DynamicList<label> > receives(nProcs);
138  labelList sends(nProcs, -1);
139 
140  // Info<< "Using " << nLevels << " communication levels" << endl;
141 
142  label offset = 2;
143  label childOffset = offset/2;
144 
145  for (label level = 0; level < nLevels; level++)
146  {
147  label receiveID = 0;
148  while (receiveID < nProcs)
149  {
150  // Determine processor that sends and we receive from
151  label sendID = receiveID + childOffset;
152 
153  if (sendID < nProcs)
154  {
155  receives[receiveID].append(sendID);
156  sends[sendID] = receiveID;
157  }
158 
159  receiveID += offset;
160  }
161 
162  offset <<= 1;
163  childOffset <<= 1;
164  }
165 
166  // For all processors find the processors it receives data from
167  // (and the processors they receive data from etc.)
168  List<DynamicList<label> > allReceives(nProcs);
169  for (label procID = 0; procID < nProcs; procID++)
170  {
171  collectReceives(procID, receives, allReceives[procID]);
172  }
173 
174 
175  treeCommunication_.setSize(nProcs);
176 
177  for (label procID = 0; procID < nProcs; procID++)
178  {
179  treeCommunication_[procID] = commsStruct
180  (
181  nProcs,
182  procID,
183  sends[procID],
184  receives[procID].shrink(),
185  allReceives[procID].shrink()
186  );
187  }
188 }
189 
190 
191 // Callback from Pstream::init() : initialize linear and tree communication
192 // schedules now that nProcs is known.
193 void Foam::Pstream::initCommunicationSchedule()
194 {
195  calcLinearComm(nProcs());
196  calcTreeComm(nProcs());
197 }
198 
199 
200 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
201 
202 // Initialise my process number to 0 (the master)
203 int Foam::Pstream::myProcNo_(0);
204 
205 // By default this is not a parallel run
206 bool Foam::Pstream::parRun_(false);
207 
208 // List of process IDs
209 Foam::List<int> Foam::Pstream::procIDs_(1, 0);
210 
211 // Standard transfer message type
212 const int Foam::Pstream::msgType_(1);
213 
214 // Linear communication schedule
215 Foam::List<Foam::Pstream::commsStruct> Foam::Pstream::linearCommunication_(0);
216 
217 // Multi level communication schedule
218 Foam::List<Foam::Pstream::commsStruct> Foam::Pstream::treeCommunication_(0);
219 
220 // Should compact transfer be used in which floats replace doubles
221 // reducing the bandwidth requirement at the expense of some loss
222 // in accuracy
224 (
225  debug::optimisationSwitch("floatTransfer", 0)
226 );
227 
228 // Number of processors at which the reduce algorithm changes from linear to
229 // tree
231 (
232  debug::optimisationSwitch("nProcsSimpleSum", 16)
233 );
234 
235 // Default commsType
237 (
238  commsTypeNames.read(debug::optimisationSwitches().lookup("commsType"))
239 );
240 
241 
242 // ************************ vim: set sw=4 sts=4 et: ************************ //