initial commit for version 1.6.x patch release
[OpenFOAM-1.6.x.git] / src / OpenFOAM / db / IOstreams / Pstreams / gatherScatterList.C
blob52f13d1688f721bc3087c685e2ae6b10483a3295
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
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 the
13     Free Software Foundation; either version 2 of the License, or (at your
14     option) any later version.
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.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM; if not, write to the Free Software Foundation,
23     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 Description
26     Gather data from all processors onto single processor according to some
27     communication schedule (usually linear-to-master or tree-to-master).
28     The gathered data will be a list with element procID the data from processor
29     procID. Before calling every processor should insert its value into
30     Values[Pstream::myProcNo()].
31     Note: after gather every processor only knows its own data and that of the
32     processors below it. Only the 'master' of the communication schedule holds
33     a fully filled List. Use scatter to distribute the data.
35 \*---------------------------------------------------------------------------*/
37 #include "IPstream.H"
38 #include "OPstream.H"
39 #include "contiguous.H"
41 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43 namespace Foam
46 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
48 template <class T>
49 void Pstream::gatherList
51     const List<Pstream::commsStruct>& comms,
52     List<T>& Values
55     if (Pstream::parRun())
56     {
57         if (Values.size() != Pstream::nProcs())
58         {
59             FatalErrorIn
60             (
61                 "Pstream::gatherList(const List<Pstream::commsStruct>&"
62                 ", List<T>)"
63             )   << "Size of list:" << Values.size()
64                 << " does not equal the number of processors:"
65                 << Pstream::nProcs()
66                 << Foam::abort(FatalError);
67         }
69         // Get my communication order
70         const commsStruct& myComm = comms[Pstream::myProcNo()];
72         // Receive from my downstairs neighbours
73         forAll(myComm.below(), belowI)
74         {
75             label belowID = myComm.below()[belowI];
76             const labelList& belowLeaves = comms[belowID].allBelow();
78             if (contiguous<T>())
79             {
80                 List<T> receivedValues(belowLeaves.size() + 1);
82                 IPstream::read
83                 (
84                     Pstream::scheduled,
85                     belowID,
86                     reinterpret_cast<char*>(receivedValues.begin()),
87                     receivedValues.byteSize()
88                 );
90                 Values[belowID] = receivedValues[0];
92                 forAll(belowLeaves, leafI)
93                 {
94                     Values[belowLeaves[leafI]] = receivedValues[leafI + 1];
95                 }
96             }
97             else
98             {
99                 IPstream fromBelow(Pstream::scheduled, belowID);
100                 fromBelow >> Values[belowID];
102                 if (debug & 2)
103                 {
104                     Pout<< " received through "
105                         << belowID << " data from:" << belowID
106                         << " data:" << Values[belowID] << endl;
107                 }
109                 // Receive from all other processors below belowID
110                 forAll(belowLeaves, leafI)
111                 {
112                     label leafID = belowLeaves[leafI];
113                     fromBelow >> Values[leafID];
115                     if (debug & 2)
116                     {
117                         Pout<< " received through "
118                             << belowID << " data from:" << leafID
119                             << " data:" << Values[leafID] << endl;
120                     }
121                 }
122             }
123         }
125         // Send up from Values:
126         // - my own value first
127         // - all belowLeaves next
128         if (myComm.above() != -1)
129         {
130             const labelList& belowLeaves = myComm.allBelow();
132             if (debug & 2)
133             {
134                 Pout<< " sending to " << myComm.above()
135                     << " data from me:" << Pstream::myProcNo()
136                     << " data:" << Values[Pstream::myProcNo()] << endl;
137             }
139             if (contiguous<T>())
140             {
141                 List<T> sendingValues(belowLeaves.size() + 1);
142                 sendingValues[0] = Values[Pstream::myProcNo()];
144                 forAll(belowLeaves, leafI)
145                 {
146                     sendingValues[leafI + 1] = Values[belowLeaves[leafI]];
147                 }
149                 OPstream::write
150                 (
151                     Pstream::scheduled,
152                     myComm.above(),
153                     reinterpret_cast<const char*>(sendingValues.begin()),
154                     sendingValues.byteSize()
155                 );
156             }
157             else
158             {
159                 OPstream toAbove(Pstream::scheduled, myComm.above());
160                 toAbove << Values[Pstream::myProcNo()];
162                 forAll(belowLeaves, leafI)
163                 {
164                     label leafID = belowLeaves[leafI];
166                     if (debug & 2)
167                     {
168                         Pout<< " sending to "
169                             << myComm.above() << " data from:" << leafID
170                             << " data:" << Values[leafID] << endl;
171                     }
172                     toAbove << Values[leafID];
173                 }
174             }
175         }
176     }
180 template <class T>
181 void Pstream::gatherList(List<T>& Values)
183     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
184     {
185         gatherList(Pstream::linearCommunication(), Values);
186     }
187     else
188     {
189         gatherList(Pstream::treeCommunication(), Values);
190     }
194 template <class T>
195 void Pstream::scatterList
197     const List<Pstream::commsStruct>& comms,
198     List<T>& Values
201     if (Pstream::parRun())
202     {
203         if (Values.size() != Pstream::nProcs())
204         {
205             FatalErrorIn
206             (
207                 "Pstream::scatterList(const List<Pstream::commsStruct>&"
208                 ", List<T>)"
209             )   << "Size of list:" << Values.size()
210                 << " does not equal the number of processors:"
211                 << Pstream::nProcs()
212                 << Foam::abort(FatalError);
213         }
215         // Get my communication order
216         const commsStruct& myComm = comms[Pstream::myProcNo()];
218         // Reveive from up
219         if (myComm.above() != -1)
220         {
221             const labelList& notBelowLeaves = myComm.allNotBelow();
223             if (contiguous<T>())
224             {
225                 List<T> receivedValues(notBelowLeaves.size());
227                 IPstream::read
228                 (
229                     Pstream::scheduled,
230                     myComm.above(),
231                     reinterpret_cast<char*>(receivedValues.begin()),
232                     receivedValues.byteSize()
233                 );
235                 forAll(notBelowLeaves, leafI)
236                 {
237                     Values[notBelowLeaves[leafI]] = receivedValues[leafI];
238                 }
239             }
240             else
241             {
242                 IPstream fromAbove(Pstream::scheduled, myComm.above());
244                 forAll(notBelowLeaves, leafI)
245                 {
246                     label leafID = notBelowLeaves[leafI];
247                     fromAbove >> Values[leafID];
249                     if (debug)
250                     {
251                         Pout<< " received through "
252                             << myComm.above() << " data for:" << leafID
253                             << " data:" << Values[leafID] << endl;
254                     }
255                 }
256             }
257         }
259         // Send to my downstairs neighbours
260         forAll(myComm.below(), belowI)
261         {
262             label belowID = myComm.below()[belowI];
263             const labelList& notBelowLeaves = comms[belowID].allNotBelow();
265             if (contiguous<T>())
266             {
267                 List<T> sendingValues(notBelowLeaves.size());
269                 forAll(notBelowLeaves, leafI)
270                 {
271                     sendingValues[leafI] = Values[notBelowLeaves[leafI]];
272                 }
274                 OPstream::write
275                 (
276                     Pstream::scheduled,
277                     belowID,
278                     reinterpret_cast<const char*>(sendingValues.begin()),
279                     sendingValues.byteSize()
280                 );
281             }
282             else
283             {
284                 OPstream toBelow(Pstream::scheduled, belowID);
286                 // Send data destined for all other processors below belowID
287                 forAll(notBelowLeaves, leafI)
288                 {
289                     label leafID = notBelowLeaves[leafI];
290                     toBelow << Values[leafID];
292                     if (debug)
293                     {
294                         Pout<< " sent through "
295                             << belowID << " data for:" << leafID
296                             << " data:" << Values[leafID] << endl;
297                     }
298                 }
299             }
300         }
301     }
305 template <class T>
306 void Pstream::scatterList(List<T>& Values)
308     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
309     {
310         scatterList(Pstream::linearCommunication(), Values);
311     }
312     else
313     {
314         scatterList(Pstream::treeCommunication(), Values);
315     }
319 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
321 } // End namespace Foam
323 // ************************************************************************* //