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) 2011-2013 OpenFOAM Foundation
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[UPstream::myProcNo(comm)].
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 "contiguous.H"
39 
40 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41 
42 namespace Foam
43 {
44 
45 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
46 
47 template<class T>
49 (
50  const List<UPstream::commsStruct>& comms,
51  List<T>& Values,
52  const int tag,
53  const label comm
54 )
55 {
56  if (UPstream::nProcs(comm) > 1)
57  {
58  if (Values.size() != UPstream::nProcs(comm))
59  {
61  (
62  "UPstream::gatherList(const List<UPstream::commsStruct>&"
63  ", List<T>)"
64  ) << "Size of list:" << Values.size()
65  << " does not equal the number of processors:"
66  << UPstream::nProcs(comm)
68  }
69 
70  // Get my communication order
71  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
72 
73  // Receive from my downstairs neighbours
74  forAll(myComm.below(), belowI)
75  {
76  label belowID = myComm.below()[belowI];
77  const labelList& belowLeaves = comms[belowID].allBelow();
78 
79  if (contiguous<T>())
80  {
81  List<T> receivedValues(belowLeaves.size() + 1);
82 
84  (
86  belowID,
87  reinterpret_cast<char*>(receivedValues.begin()),
88  receivedValues.byteSize(),
89  tag,
90  comm
91  );
92 
93  Values[belowID] = receivedValues[0];
94 
95  forAll(belowLeaves, leafI)
96  {
97  Values[belowLeaves[leafI]] = receivedValues[leafI + 1];
98  }
99  }
100  else
101  {
102  IPstream fromBelow(UPstream::scheduled, belowID, 0, tag, comm);
103  fromBelow >> Values[belowID];
104 
105  if (debug & 2)
106  {
107  Pout<< " received through "
108  << belowID << " data from:" << belowID
109  << " data:" << Values[belowID] << endl;
110  }
111 
112  // Receive from all other processors below belowID
113  forAll(belowLeaves, leafI)
114  {
115  label leafID = belowLeaves[leafI];
116  fromBelow >> Values[leafID];
117 
118  if (debug & 2)
119  {
120  Pout<< " received through "
121  << belowID << " data from:" << leafID
122  << " data:" << Values[leafID] << endl;
123  }
124  }
125  }
126  }
127 
128  // Send up from Values:
129  // - my own value first
130  // - all belowLeaves next
131  if (myComm.above() != -1)
132  {
133  const labelList& belowLeaves = myComm.allBelow();
134 
135  if (debug & 2)
136  {
137  Pout<< " sending to " << myComm.above()
138  << " data from me:" << UPstream::myProcNo(comm)
139  << " data:" << Values[UPstream::myProcNo(comm)] << endl;
140  }
141 
142  if (contiguous<T>())
143  {
144  List<T> sendingValues(belowLeaves.size() + 1);
145  sendingValues[0] = Values[UPstream::myProcNo(comm)];
146 
147  forAll(belowLeaves, leafI)
148  {
149  sendingValues[leafI + 1] = Values[belowLeaves[leafI]];
150  }
151 
153  (
155  myComm.above(),
156  reinterpret_cast<const char*>(sendingValues.begin()),
157  sendingValues.byteSize(),
158  tag,
159  comm
160  );
161  }
162  else
163  {
164  OPstream toAbove
165  (
167  myComm.above(),
168  0,
169  tag,
170  comm
171  );
172  toAbove << Values[UPstream::myProcNo(comm)];
173 
174  forAll(belowLeaves, leafI)
175  {
176  label leafID = belowLeaves[leafI];
177 
178  if (debug & 2)
179  {
180  Pout<< " sending to "
181  << myComm.above() << " data from:" << leafID
182  << " data:" << Values[leafID] << endl;
183  }
184  toAbove << Values[leafID];
185  }
186  }
187  }
188  }
189 }
190 
191 
192 template <class T>
193 void Pstream::gatherList(List<T>& Values, const int tag, const label comm)
194 {
196  {
197  gatherList(UPstream::linearCommunication(comm), Values, tag, comm);
198  }
199  else
200  {
201  gatherList(UPstream::treeCommunication(comm), Values, tag, comm);
202  }
203 }
204 
205 
206 template<class T>
208 (
209  const List<UPstream::commsStruct>& comms,
210  List<T>& Values,
211  const int tag,
212  const label comm
213 )
214 {
215  if (UPstream::nProcs(comm) > 1)
216  {
217  if (Values.size() != UPstream::nProcs(comm))
218  {
220  (
221  "UPstream::scatterList(const List<UPstream::commsStruct>&"
222  ", List<T>)"
223  ) << "Size of list:" << Values.size()
224  << " does not equal the number of processors:"
225  << UPstream::nProcs(comm)
227  }
228 
229  // Get my communication order
230  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
231 
232  // Reveive from up
233  if (myComm.above() != -1)
234  {
235  const labelList& notBelowLeaves = myComm.allNotBelow();
236 
237  if (contiguous<T>())
238  {
239  List<T> receivedValues(notBelowLeaves.size());
240 
242  (
244  myComm.above(),
245  reinterpret_cast<char*>(receivedValues.begin()),
246  receivedValues.byteSize(),
247  tag,
248  comm
249  );
250 
251  forAll(notBelowLeaves, leafI)
252  {
253  Values[notBelowLeaves[leafI]] = receivedValues[leafI];
254  }
255  }
256  else
257  {
258  IPstream fromAbove
259  (
261  myComm.above(),
262  0,
263  tag,
264  comm
265  );
266 
267  forAll(notBelowLeaves, leafI)
268  {
269  label leafID = notBelowLeaves[leafI];
270  fromAbove >> Values[leafID];
271 
272  if (debug)
273  {
274  Pout<< " received through "
275  << myComm.above() << " data for:" << leafID
276  << " data:" << Values[leafID] << endl;
277  }
278  }
279  }
280  }
281 
282  // Send to my downstairs neighbours
283  forAll(myComm.below(), belowI)
284  {
285  label belowID = myComm.below()[belowI];
286  const labelList& notBelowLeaves = comms[belowID].allNotBelow();
287 
288  if (contiguous<T>())
289  {
290  List<T> sendingValues(notBelowLeaves.size());
291 
292  forAll(notBelowLeaves, leafI)
293  {
294  sendingValues[leafI] = Values[notBelowLeaves[leafI]];
295  }
296 
298  (
300  belowID,
301  reinterpret_cast<const char*>(sendingValues.begin()),
302  sendingValues.byteSize(),
303  tag,
304  comm
305  );
306  }
307  else
308  {
309  OPstream toBelow(UPstream::scheduled, belowID, 0, tag, comm);
310 
311  // Send data destined for all other processors below belowID
312  forAll(notBelowLeaves, leafI)
313  {
314  label leafID = notBelowLeaves[leafI];
315  toBelow << Values[leafID];
316 
317  if (debug)
318  {
319  Pout<< " sent through "
320  << belowID << " data for:" << leafID
321  << " data:" << Values[leafID] << endl;
322  }
323  }
324  }
325  }
326  }
327 }
328 
329 
330 template <class T>
331 void Pstream::scatterList(List<T>& Values, const int tag, const label comm)
332 {
334  {
335  scatterList(UPstream::linearCommunication(comm), Values, tag, comm);
336  }
337  else
338  {
339  scatterList(UPstream::treeCommunication(comm), Values, tag, comm);
340  }
341 }
342 
343 
344 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
345 
346 } // End namespace Foam
347 
348 // ************************************************************************* //
std::streamsize byteSize() const
Return the binary size in number of characters of the UList.
Definition: UList.C:92
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
static bool write(const commsTypes commsType, const int toProcNo, const char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label communicator=0)
Write given buffer to given processor.
Definition: UOPwrite.C:34
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Structure for communicating between processors.
Definition: UPstream.H:76
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
Output inter-processor communications stream.
Definition: OPstream.H:50
static label read(const commsTypes commsType, const int fromProcNo, char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label communicator=0)
Read into given buffer from given processor and return the.
Definition: UIPread.C:100
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
Namespace for OpenFOAM.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
iterator begin()
Return an iterator to begin traversing the UList.
Definition: UListI.H:216
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:386
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
static const List< commsStruct > & linearCommunication(const label communicator=0)
Communication schedule for linear all-to-master (proc 0)
Definition: UPstream.H:434
label above() const
Definition: UPstream.H:125
#define forAll(list, i)
Definition: UList.H:421
errorManip< error > abort(error &err)
Definition: errorManip.H:131
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:404
Template function to specify if the data of a type are contiguous.
const labelList & below() const
Definition: UPstream.H:130
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
error FatalError
Input inter-processor communications stream.
Definition: IPstream.H:50
const labelList & allBelow() const
Definition: UPstream.H:135
static const List< commsStruct > & treeCommunication(const label communicator=0)
Communication schedule for tree all-to-master (proc 0)
Definition: UPstream.H:443
const labelList & allNotBelow() const
Definition: UPstream.H:140
prefixOSstream Pout(cout,"Pout")
Definition: IOstreams.H:53
static int nProcsSimpleSum
Number of processors at which the sum algorithm changes from linear.
Definition: UPstream.H:252