PstreamGatherList.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 | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2017 OpenFOAM Foundation
9 Copyright (C) 2015-2022 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27Description
28 Gather data from all processors onto single processor according to some
29 communication schedule (usually linear-to-master or tree-to-master).
30 The gathered data will be a list with element procID the data from processor
31 procID. Before calling every processor should insert its value into
32 values[UPstream::myProcNo(comm)].
33 Note: after gather every processor only knows its own data and that of the
34 processors below it. Only the 'master' of the communication schedule holds
35 a fully filled List. Use scatter to distribute the data.
36
37\*---------------------------------------------------------------------------*/
38
39#include "IPstream.H"
40#include "OPstream.H"
41#include "contiguous.H"
42
43// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
44
45template<class T>
47(
48 const List<UPstream::commsStruct>& comms,
49 List<T>& values,
50 const int tag,
51 const label comm
52)
53{
54 if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
55 {
56 if (values.size() != UPstream::nProcs(comm))
57 {
59 << "Size of list:" << values.size()
60 << " does not equal the number of processors:"
61 << UPstream::nProcs(comm)
63 }
64
65 // My communication order
66 const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
67
68 // Receive from my downstairs neighbours
69 for (const label belowID : myComm.below())
70 {
71 const labelList& belowLeaves = comms[belowID].allBelow();
72
74 {
75 List<T> received(belowLeaves.size() + 1);
76
78 (
80 belowID,
81 received.data_bytes(),
82 received.size_bytes(),
83 tag,
84 comm
85 );
86
87 values[belowID] = received[0];
88
89 forAll(belowLeaves, leafI)
90 {
91 values[belowLeaves[leafI]] = received[leafI + 1];
92 }
93 }
94 else
95 {
96 IPstream fromBelow
97 (
99 belowID,
100 0,
101 tag,
102 comm
103 );
104 fromBelow >> values[belowID];
105
106 if (debug & 2)
107 {
108 Pout<< " received through "
109 << belowID << " data from:" << belowID
110 << " data:" << values[belowID] << endl;
111 }
112
113 // Receive from all other processors below belowID
114 for (const label leafID : belowLeaves)
115 {
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
143 {
144 List<T> sending(belowLeaves.size() + 1);
145 sending[0] = values[UPstream::myProcNo(comm)];
146
147 forAll(belowLeaves, leafI)
148 {
149 sending[leafI + 1] = values[belowLeaves[leafI]];
150 }
151
153 (
155 myComm.above(),
156 sending.cdata_bytes(),
157 sending.size_bytes(),
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 for (const label leafID : belowLeaves)
175 {
176 if (debug & 2)
177 {
178 Pout<< " sending to "
179 << myComm.above() << " data from:" << leafID
180 << " data:" << values[leafID] << endl;
181 }
182 toAbove << values[leafID];
183 }
184 }
185 }
186 }
187}
188
189
190template<class T>
192(
193 const List<UPstream::commsStruct>& comms,
194 List<T>& values,
195 const int tag,
196 const label comm
197)
198{
199 // Apart from the additional (size == nProcs) check, the only difference
200 // between scatterList() and using broadcast(List<T>&) or a regular
201 // scatter(List<T>&) is that processor-local data is skipped.
202
203 if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
204 {
205 if (values.size() != UPstream::nProcs(comm))
206 {
208 << "Size of list:" << values.size()
209 << " does not equal the number of processors:"
210 << UPstream::nProcs(comm)
212 }
213
214 // My communication order
215 const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
216
217 // Receive from up
218 if (myComm.above() != -1)
219 {
220 const labelList& notBelowLeaves = myComm.allNotBelow();
221
223 {
224 List<T> received(notBelowLeaves.size());
225
227 (
229 myComm.above(),
230 received.data_bytes(),
231 received.size_bytes(),
232 tag,
233 comm
234 );
235
236 forAll(notBelowLeaves, leafI)
237 {
238 values[notBelowLeaves[leafI]] = received[leafI];
239 }
240 }
241 else
242 {
243 IPstream fromAbove
244 (
246 myComm.above(),
247 0,
248 tag,
249 comm
250 );
251
252 for (const label leafID : notBelowLeaves)
253 {
254 fromAbove >> values[leafID];
255
256 if (debug)
257 {
258 Pout<< " received through "
259 << myComm.above() << " data for:" << leafID
260 << " data:" << values[leafID] << endl;
261 }
262 }
263 }
264 }
265
266 // Send to my downstairs neighbours
267 forAllReverse(myComm.below(), belowI)
268 {
269 const label belowID = myComm.below()[belowI];
270 const labelList& notBelowLeaves = comms[belowID].allNotBelow();
271
273 {
274 List<T> sending(notBelowLeaves.size());
275
276 forAll(notBelowLeaves, leafI)
277 {
278 sending[leafI] = values[notBelowLeaves[leafI]];
279 }
280
282 (
284 belowID,
285 sending.cdata_bytes(),
286 sending.size_bytes(),
287 tag,
288 comm
289 );
290 }
291 else
292 {
293 OPstream toBelow
294 (
296 belowID,
297 0,
298 tag,
299 comm
300 );
301
302 // Send data destined for all other processors below belowID
303 for (const label leafID : notBelowLeaves)
304 {
305 toBelow << values[leafID];
306
307 if (debug)
308 {
309 Pout<< " sent through "
310 << belowID << " data for:" << leafID
311 << " data:" << values[leafID] << endl;
312 }
313 }
314 }
315 }
316 }
317}
318
319
320template<class T>
322(
323 List<T>& values,
324 const int tag,
325 const label comm
326)
327{
328 Pstream::gatherList(UPstream::whichCommunication(comm), values, tag, comm);
329}
330
331
332template<class T>
334(
335 List<T>& values,
336 const int tag,
337 const label comm
338)
339{
340 Pstream::scatterList(UPstream::whichCommunication(comm), values, tag, comm);
341}
342
343
344template<class T>
346(
347 const List<UPstream::commsStruct>& comms,
348 List<T>& values,
349 const int tag,
350 const label comm
351)
352{
353 Pstream::gatherList(comms, values, tag, comm);
354 Pstream::scatterList(comms, values, tag, comm);
355}
356
357
358template<class T>
360(
361 List<T>& values,
362 const int tag,
363 const label comm
364)
365{
366 if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
367 {
368 const auto& comms = UPstream::whichCommunication(comm);
369
370 Pstream::gatherList(comms, values, tag, comm);
371 Pstream::scatterList(comms, values, tag, comm);
372 }
373}
374
375
376// ************************************************************************* //
Input inter-processor communications stream.
Definition: IPstream.H:57
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:77
Output inter-processor communications stream.
Definition: OPstream.H:57
label nProcs() const noexcept
Number of ranks associated with PstreamBuffers.
static void allGatherList(const List< commsStruct > &comms, List< T > &values, const int tag, const label comm)
static void gatherList(const List< commsStruct > &comms, List< T > &values, const int tag, const label comm)
static void scatterList(const List< commsStruct > &comms, List< T > &values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
virtual bool read()
Re-read model coefficients if they have changed.
char * data_bytes() noexcept
Return pointer to the underlying array serving as data storage,.
Definition: UListI.H:251
const char * cdata_bytes() const noexcept
Return pointer to the underlying array serving as data storage,.
Definition: UListI.H:244
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
std::streamsize size_bytes() const noexcept
Number of contiguous bytes for the List data.
Definition: UListI.H:258
Structure for communicating between processors.
Definition: UPstream.H:81
const labelList & allBelow() const noexcept
Definition: UPstream.H:141
const labelList & below() const noexcept
The procIDs of all processors directly below.
Definition: UPstream.H:134
label above() const noexcept
The procID of the processor directly above.
Definition: UPstream.H:128
const labelList & allNotBelow() const noexcept
Definition: UPstream.H:148
static const List< commsStruct > & whichCommunication(const label communicator=worldComm)
Definition: UPstream.H:542
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
virtual bool write()
Write the output fields.
int myProcNo() const noexcept
Return processor number.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
errorManip< error > abort(error &err)
Definition: errorManip.H:144
error FatalError
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:346
A template class to specify that a data type can be considered as being contiguous in memory.
Definition: contiguous.H:78