gatherScatterList.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2018 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::parRun() && UPstream::nProcs(comm) > 1)
57  {
58  if (Values.size() != UPstream::nProcs(comm))
59  {
61  << "Size of list:" << Values.size()
62  << " does not equal the number of processors:"
63  << UPstream::nProcs(comm)
65  }
66 
67  // Get my communication order
68  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
69 
70  // Receive from my downstairs neighbours
71  forAll(myComm.below(), belowI)
72  {
73  label belowID = myComm.below()[belowI];
74  const labelList& belowLeaves = comms[belowID].allBelow();
75 
76  if (contiguous<T>())
77  {
78  List<T> receivedValues(belowLeaves.size() + 1);
79 
81  (
83  belowID,
84  reinterpret_cast<char*>(receivedValues.begin()),
85  receivedValues.byteSize(),
86  tag,
87  comm
88  );
89 
90  Values[belowID] = receivedValues[0];
91 
92  forAll(belowLeaves, leafI)
93  {
94  Values[belowLeaves[leafI]] = receivedValues[leafI + 1];
95  }
96  }
97  else
98  {
99  IPstream fromBelow
100  (
102  belowID,
103  0,
104  tag,
105  comm
106  );
107  fromBelow >> Values[belowID];
108 
109  if (debug & 2)
110  {
111  Pout<< " received through "
112  << belowID << " data from:" << belowID
113  << " data:" << Values[belowID] << endl;
114  }
115 
116  // Receive from all other processors below belowID
117  forAll(belowLeaves, leafI)
118  {
119  label leafID = belowLeaves[leafI];
120  fromBelow >> Values[leafID];
121 
122  if (debug & 2)
123  {
124  Pout<< " received through "
125  << belowID << " data from:" << leafID
126  << " data:" << Values[leafID] << endl;
127  }
128  }
129  }
130  }
131 
132  // Send up from Values:
133  // - my own value first
134  // - all belowLeaves next
135  if (myComm.above() != -1)
136  {
137  const labelList& belowLeaves = myComm.allBelow();
138 
139  if (debug & 2)
140  {
141  Pout<< " sending to " << myComm.above()
142  << " data from me:" << UPstream::myProcNo(comm)
143  << " data:" << Values[UPstream::myProcNo(comm)] << endl;
144  }
145 
146  if (contiguous<T>())
147  {
148  List<T> sendingValues(belowLeaves.size() + 1);
149  sendingValues[0] = Values[UPstream::myProcNo(comm)];
150 
151  forAll(belowLeaves, leafI)
152  {
153  sendingValues[leafI + 1] = Values[belowLeaves[leafI]];
154  }
155 
157  (
159  myComm.above(),
160  reinterpret_cast<const char*>(sendingValues.begin()),
161  sendingValues.byteSize(),
162  tag,
163  comm
164  );
165  }
166  else
167  {
168  OPstream toAbove
169  (
171  myComm.above(),
172  0,
173  tag,
174  comm
175  );
176  toAbove << Values[UPstream::myProcNo(comm)];
177 
178  forAll(belowLeaves, leafI)
179  {
180  label leafID = belowLeaves[leafI];
181 
182  if (debug & 2)
183  {
184  Pout<< " sending to "
185  << myComm.above() << " data from:" << leafID
186  << " data:" << Values[leafID] << endl;
187  }
188  toAbove << Values[leafID];
189  }
190  }
191  }
192  }
193 }
194 
195 
196 template<class T>
197 void Pstream::gatherList(List<T>& Values, const int tag, const label comm)
198 {
200  {
201  gatherList(UPstream::linearCommunication(comm), Values, tag, comm);
202  }
203  else
204  {
205  gatherList(UPstream::treeCommunication(comm), Values, tag, comm);
206  }
207 }
208 
209 
210 template<class T>
212 (
213  const List<UPstream::commsStruct>& comms,
214  List<T>& Values,
215  const int tag,
216  const label comm
217 )
218 {
219  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
220  {
221  if (Values.size() != UPstream::nProcs(comm))
222  {
224  << "Size of list:" << Values.size()
225  << " does not equal the number of processors:"
226  << UPstream::nProcs(comm)
228  }
229 
230  // Get my communication order
231  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
232 
233  // Receive from up
234  if (myComm.above() != -1)
235  {
236  const labelList& notBelowLeaves = myComm.allNotBelow();
237 
238  if (contiguous<T>())
239  {
240  List<T> receivedValues(notBelowLeaves.size());
241 
243  (
245  myComm.above(),
246  reinterpret_cast<char*>(receivedValues.begin()),
247  receivedValues.byteSize(),
248  tag,
249  comm
250  );
251 
252  forAll(notBelowLeaves, leafI)
253  {
254  Values[notBelowLeaves[leafI]] = receivedValues[leafI];
255  }
256  }
257  else
258  {
259  IPstream fromAbove
260  (
262  myComm.above(),
263  0,
264  tag,
265  comm
266  );
267 
268  forAll(notBelowLeaves, leafI)
269  {
270  label leafID = notBelowLeaves[leafI];
271  fromAbove >> Values[leafID];
272 
273  if (debug)
274  {
275  Pout<< " received through "
276  << myComm.above() << " data for:" << leafID
277  << " data:" << Values[leafID] << endl;
278  }
279  }
280  }
281  }
282 
283  // Send to my downstairs neighbours
284  forAllReverse(myComm.below(), belowI)
285  {
286  label belowID = myComm.below()[belowI];
287  const labelList& notBelowLeaves = comms[belowID].allNotBelow();
288 
289  if (contiguous<T>())
290  {
291  List<T> sendingValues(notBelowLeaves.size());
292 
293  forAll(notBelowLeaves, leafI)
294  {
295  sendingValues[leafI] = Values[notBelowLeaves[leafI]];
296  }
297 
299  (
301  belowID,
302  reinterpret_cast<const char*>(sendingValues.begin()),
303  sendingValues.byteSize(),
304  tag,
305  comm
306  );
307  }
308  else
309  {
310  OPstream toBelow
311  (
313  belowID,
314  0,
315  tag,
316  comm
317  );
318 
319  // Send data destined for all other processors below belowID
320  forAll(notBelowLeaves, leafI)
321  {
322  label leafID = notBelowLeaves[leafI];
323  toBelow << Values[leafID];
324 
325  if (debug)
326  {
327  Pout<< " sent through "
328  << belowID << " data for:" << leafID
329  << " data:" << Values[leafID] << endl;
330  }
331  }
332  }
333  }
334  }
335 }
336 
337 
338 template<class T>
339 void Pstream::scatterList(List<T>& Values, const int tag, const label comm)
340 {
342  {
343  scatterList(UPstream::linearCommunication(comm), Values, tag, comm);
344  }
345  else
346  {
347  scatterList(UPstream::treeCommunication(comm), Values, tag, comm);
348  }
349 }
350 
351 
352 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
353 
354 } // End namespace Foam
355 
356 // ************************************************************************* //
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
const labelList & below() const
Definition: UPstream.H:130
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
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
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:323
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
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
static int nProcsSimpleSum
Number of processors at which the sum algorithm changes from linear.
Definition: UPstream.H:269
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Template function to specify if the data of a type are contiguous.
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: UList.H:446
static const List< commsStruct > & linearCommunication(const label communicator=0)
Communication schedule for linear all-to-master (proc 0)
Definition: UPstream.H:459
Input inter-processor communications stream.
Definition: IPstream.H:50
iterator begin()
Return an iterator to begin traversing the UList.
Definition: UListI.H:216
static const List< commsStruct > & treeCommunication(const label communicator=0)
Communication schedule for tree all-to-master (proc 0)
Definition: UPstream.H:468
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Structure for communicating between processors.
Definition: UPstream.H:76
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:79
const labelList & allBelow() const
Definition: UPstream.H:135
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
Output inter-processor communications stream.
Definition: OPstream.H:50
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:411
std::streamsize byteSize() const
Return the binary size in number of characters of the UList.
Definition: UList.C:100
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
const labelList & allNotBelow() const
Definition: UPstream.H:140
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
Namespace for OpenFOAM.