FreeFOAM The Cross-Platform CFD Toolkit
gatherScatterList.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 Description
25  Gather data from all processors onto single processor according to some
26  communication schedule (usually linear-to-master or tree-to-master).
27  The gathered data will be a list with element procID the data from processor
28  procID. Before calling every processor should insert its value into
29  Values[Pstream::myProcNo()].
30  Note: after gather every processor only knows its own data and that of the
31  processors below it. Only the 'master' of the communication schedule holds
32  a fully filled List. Use scatter to distribute the data.
33 
34 \*---------------------------------------------------------------------------*/
35 
36 #include "IPstream.H"
37 #include "OPstream.H"
38 #include <OpenFOAM/contiguous.H>
39 
40 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41 
42 namespace Foam
43 {
44 
45 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
46 
47 template <class T>
49 (
50  const List<Pstream::commsStruct>& comms,
51  List<T>& Values
52 )
53 {
54  if (Pstream::parRun())
55  {
56  if (Values.size() != Pstream::nProcs())
57  {
59  (
60  "Pstream::gatherList(const List<Pstream::commsStruct>&"
61  ", List<T>)"
62  ) << "Size of list:" << Values.size()
63  << " does not equal the number of processors:"
64  << Pstream::nProcs()
66  }
67 
68  // Get my communication order
69  const commsStruct& myComm = comms[Pstream::myProcNo()];
70 
71  // Receive from my downstairs neighbours
72  forAll(myComm.below(), belowI)
73  {
74  label belowID = myComm.below()[belowI];
75  const labelList& belowLeaves = comms[belowID].allBelow();
76 
77  if (contiguous<T>())
78  {
79  List<T> receivedValues(belowLeaves.size() + 1);
80 
82  (
84  belowID,
85  reinterpret_cast<char*>(receivedValues.begin()),
86  receivedValues.byteSize()
87  );
88 
89  Values[belowID] = receivedValues[0];
90 
91  forAll(belowLeaves, leafI)
92  {
93  Values[belowLeaves[leafI]] = receivedValues[leafI + 1];
94  }
95  }
96  else
97  {
98  IPstream fromBelow(Pstream::scheduled, belowID);
99  fromBelow >> Values[belowID];
100 
101  if (debug & 2)
102  {
103  Pout<< " received through "
104  << belowID << " data from:" << belowID
105  << " data:" << Values[belowID] << endl;
106  }
107 
108  // Receive from all other processors below belowID
109  forAll(belowLeaves, leafI)
110  {
111  label leafID = belowLeaves[leafI];
112  fromBelow >> Values[leafID];
113 
114  if (debug & 2)
115  {
116  Pout<< " received through "
117  << belowID << " data from:" << leafID
118  << " data:" << Values[leafID] << endl;
119  }
120  }
121  }
122  }
123 
124  // Send up from Values:
125  // - my own value first
126  // - all belowLeaves next
127  if (myComm.above() != -1)
128  {
129  const labelList& belowLeaves = myComm.allBelow();
130 
131  if (debug & 2)
132  {
133  Pout<< " sending to " << myComm.above()
134  << " data from me:" << Pstream::myProcNo()
135  << " data:" << Values[Pstream::myProcNo()] << endl;
136  }
137 
138  if (contiguous<T>())
139  {
140  List<T> sendingValues(belowLeaves.size() + 1);
141  sendingValues[0] = Values[Pstream::myProcNo()];
142 
143  forAll(belowLeaves, leafI)
144  {
145  sendingValues[leafI + 1] = Values[belowLeaves[leafI]];
146  }
147 
149  (
151  myComm.above(),
152  reinterpret_cast<const char*>(sendingValues.begin()),
153  sendingValues.byteSize()
154  );
155  }
156  else
157  {
158  OPstream toAbove(Pstream::scheduled, myComm.above());
159  toAbove << Values[Pstream::myProcNo()];
160 
161  forAll(belowLeaves, leafI)
162  {
163  label leafID = belowLeaves[leafI];
164 
165  if (debug & 2)
166  {
167  Pout<< " sending to "
168  << myComm.above() << " data from:" << leafID
169  << " data:" << Values[leafID] << endl;
170  }
171  toAbove << Values[leafID];
172  }
173  }
174  }
175  }
176 }
177 
178 
179 template <class T>
181 {
183  {
185  }
186  else
187  {
189  }
190 }
191 
192 
193 template <class T>
195 (
196  const List<Pstream::commsStruct>& comms,
197  List<T>& Values
198 )
199 {
200  if (Pstream::parRun())
201  {
202  if (Values.size() != Pstream::nProcs())
203  {
205  (
206  "Pstream::scatterList(const List<Pstream::commsStruct>&"
207  ", List<T>)"
208  ) << "Size of list:" << Values.size()
209  << " does not equal the number of processors:"
210  << Pstream::nProcs()
212  }
213 
214  // Get my communication order
215  const commsStruct& myComm = comms[Pstream::myProcNo()];
216 
217  // Reveive from up
218  if (myComm.above() != -1)
219  {
220  const labelList& notBelowLeaves = myComm.allNotBelow();
221 
222  if (contiguous<T>())
223  {
224  List<T> receivedValues(notBelowLeaves.size());
225 
227  (
229  myComm.above(),
230  reinterpret_cast<char*>(receivedValues.begin()),
231  receivedValues.byteSize()
232  );
233 
234  forAll(notBelowLeaves, leafI)
235  {
236  Values[notBelowLeaves[leafI]] = receivedValues[leafI];
237  }
238  }
239  else
240  {
241  IPstream fromAbove(Pstream::scheduled, myComm.above());
242 
243  forAll(notBelowLeaves, leafI)
244  {
245  label leafID = notBelowLeaves[leafI];
246  fromAbove >> Values[leafID];
247 
248  if (debug)
249  {
250  Pout<< " received through "
251  << myComm.above() << " data for:" << leafID
252  << " data:" << Values[leafID] << endl;
253  }
254  }
255  }
256  }
257 
258  // Send to my downstairs neighbours
259  forAll(myComm.below(), belowI)
260  {
261  label belowID = myComm.below()[belowI];
262  const labelList& notBelowLeaves = comms[belowID].allNotBelow();
263 
264  if (contiguous<T>())
265  {
266  List<T> sendingValues(notBelowLeaves.size());
267 
268  forAll(notBelowLeaves, leafI)
269  {
270  sendingValues[leafI] = Values[notBelowLeaves[leafI]];
271  }
272 
274  (
276  belowID,
277  reinterpret_cast<const char*>(sendingValues.begin()),
278  sendingValues.byteSize()
279  );
280  }
281  else
282  {
283  OPstream toBelow(Pstream::scheduled, belowID);
284 
285  // Send data destined for all other processors below belowID
286  forAll(notBelowLeaves, leafI)
287  {
288  label leafID = notBelowLeaves[leafI];
289  toBelow << Values[leafID];
290 
291  if (debug)
292  {
293  Pout<< " sent through "
294  << belowID << " data for:" << leafID
295  << " data:" << Values[leafID] << endl;
296  }
297  }
298  }
299  }
300  }
301 }
302 
303 
304 template <class T>
306 {
308  {
310  }
311  else
312  {
314  }
315 }
316 
317 
318 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
319 
320 } // End namespace Foam
321 
322 // ************************ vim: set sw=4 sts=4 et: ************************ //