BUG: UListIO: byteSize overflowing on really big faceLists
[OpenFOAM-2.0.x.git] / src / OpenFOAM / db / IOstreams / Pstreams / gatherScatterList.C
blob347de9732eb1c0d7563be5481dbeca5729b37bfa
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
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
13     the Free Software Foundation, either version 3 of the License, or
14     (at your 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, see <http://www.gnu.org/licenses/>.
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()].
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.
34 \*---------------------------------------------------------------------------*/
36 #include "IPstream.H"
37 #include "OPstream.H"
38 #include "contiguous.H"
40 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
42 namespace Foam
45 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
47 template <class T>
48 void Pstream::gatherList
50     const List<UPstream::commsStruct>& comms,
51     List<T>& Values
54     if (UPstream::parRun())
55     {
56         if (Values.size() != UPstream::nProcs())
57         {
58             FatalErrorIn
59             (
60                 "UPstream::gatherList(const List<UPstream::commsStruct>&"
61                 ", List<T>)"
62             )   << "Size of list:" << Values.size()
63                 << " does not equal the number of processors:"
64                 << UPstream::nProcs()
65                 << Foam::abort(FatalError);
66         }
68         // Get my communication order
69         const commsStruct& myComm = comms[UPstream::myProcNo()];
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();
77             if (contiguous<T>())
78             {
79                 List<T> receivedValues(belowLeaves.size() + 1);
81                 UIPstream::read
82                 (
83                     UPstream::scheduled,
84                     belowID,
85                     reinterpret_cast<char*>(receivedValues.begin()),
86                     receivedValues.byteSize()
87                 );
89                 Values[belowID] = receivedValues[0];
91                 forAll(belowLeaves, leafI)
92                 {
93                     Values[belowLeaves[leafI]] = receivedValues[leafI + 1];
94                 }
95             }
96             else
97             {
98                 IPstream fromBelow(UPstream::scheduled, belowID);
99                 fromBelow >> Values[belowID];
101                 if (debug & 2)
102                 {
103                     Pout<< " received through "
104                         << belowID << " data from:" << belowID
105                         << " data:" << Values[belowID] << endl;
106                 }
108                 // Receive from all other processors below belowID
109                 forAll(belowLeaves, leafI)
110                 {
111                     label leafID = belowLeaves[leafI];
112                     fromBelow >> Values[leafID];
114                     if (debug & 2)
115                     {
116                         Pout<< " received through "
117                             << belowID << " data from:" << leafID
118                             << " data:" << Values[leafID] << endl;
119                     }
120                 }
121             }
122         }
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();
131             if (debug & 2)
132             {
133                 Pout<< " sending to " << myComm.above()
134                     << " data from me:" << UPstream::myProcNo()
135                     << " data:" << Values[UPstream::myProcNo()] << endl;
136             }
138             if (contiguous<T>())
139             {
140                 List<T> sendingValues(belowLeaves.size() + 1);
141                 sendingValues[0] = Values[UPstream::myProcNo()];
143                 forAll(belowLeaves, leafI)
144                 {
145                     sendingValues[leafI + 1] = Values[belowLeaves[leafI]];
146                 }
148                 OPstream::write
149                 (
150                     UPstream::scheduled,
151                     myComm.above(),
152                     reinterpret_cast<const char*>(sendingValues.begin()),
153                     sendingValues.byteSize()
154                 );
155             }
156             else
157             {
158                 OPstream toAbove(UPstream::scheduled, myComm.above());
159                 toAbove << Values[UPstream::myProcNo()];
161                 forAll(belowLeaves, leafI)
162                 {
163                     label leafID = belowLeaves[leafI];
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     }
179 template <class T>
180 void Pstream::gatherList(List<T>& Values)
182     if (UPstream::nProcs() < UPstream::nProcsSimpleSum)
183     {
184         gatherList(UPstream::linearCommunication(), Values);
185     }
186     else
187     {
188         gatherList(UPstream::treeCommunication(), Values);
189     }
193 template <class T>
194 void Pstream::scatterList
196     const List<UPstream::commsStruct>& comms,
197     List<T>& Values
200     if (UPstream::parRun())
201     {
202         if (Values.size() != UPstream::nProcs())
203         {
204             FatalErrorIn
205             (
206                 "UPstream::scatterList(const List<UPstream::commsStruct>&"
207                 ", List<T>)"
208             )   << "Size of list:" << Values.size()
209                 << " does not equal the number of processors:"
210                 << UPstream::nProcs()
211                 << Foam::abort(FatalError);
212         }
214         // Get my communication order
215         const commsStruct& myComm = comms[UPstream::myProcNo()];
217         // Reveive from up
218         if (myComm.above() != -1)
219         {
220             const labelList& notBelowLeaves = myComm.allNotBelow();
222             if (contiguous<T>())
223             {
224                 List<T> receivedValues(notBelowLeaves.size());
226                 UIPstream::read
227                 (
228                     UPstream::scheduled,
229                     myComm.above(),
230                     reinterpret_cast<char*>(receivedValues.begin()),
231                     receivedValues.byteSize()
232                 );
234                 forAll(notBelowLeaves, leafI)
235                 {
236                     Values[notBelowLeaves[leafI]] = receivedValues[leafI];
237                 }
238             }
239             else
240             {
241                 IPstream fromAbove(UPstream::scheduled, myComm.above());
243                 forAll(notBelowLeaves, leafI)
244                 {
245                     label leafID = notBelowLeaves[leafI];
246                     fromAbove >> Values[leafID];
248                     if (debug)
249                     {
250                         Pout<< " received through "
251                             << myComm.above() << " data for:" << leafID
252                             << " data:" << Values[leafID] << endl;
253                     }
254                 }
255             }
256         }
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();
264             if (contiguous<T>())
265             {
266                 List<T> sendingValues(notBelowLeaves.size());
268                 forAll(notBelowLeaves, leafI)
269                 {
270                     sendingValues[leafI] = Values[notBelowLeaves[leafI]];
271                 }
273                 OPstream::write
274                 (
275                     UPstream::scheduled,
276                     belowID,
277                     reinterpret_cast<const char*>(sendingValues.begin()),
278                     sendingValues.byteSize()
279                 );
280             }
281             else
282             {
283                 OPstream toBelow(UPstream::scheduled, belowID);
285                 // Send data destined for all other processors below belowID
286                 forAll(notBelowLeaves, leafI)
287                 {
288                     label leafID = notBelowLeaves[leafI];
289                     toBelow << Values[leafID];
291                     if (debug)
292                     {
293                         Pout<< " sent through "
294                             << belowID << " data for:" << leafID
295                             << " data:" << Values[leafID] << endl;
296                     }
297                 }
298             }
299         }
300     }
304 template <class T>
305 void Pstream::scatterList(List<T>& Values)
307     if (UPstream::nProcs() < UPstream::nProcsSimpleSum)
308     {
309         scatterList(UPstream::linearCommunication(), Values);
310     }
311     else
312     {
313         scatterList(UPstream::treeCommunication(), Values);
314     }
318 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
320 } // End namespace Foam
322 // ************************************************************************* //