initial commit for version 1.6.x patch release
[OpenFOAM-1.6.x.git] / src / OpenFOAM / db / IOstreams / Pstreams / combineGatherScatter.C
blob20cf9db4a6c2be0c09c175bb438876a30125788b
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     Variant of gather, scatter.
27     Normal gather uses:
28     - construct null and read (>>) from Istream
29     - binary operator and assignment operator to combine values
31     combineGather uses:
32     - construct from Istream
33     - modify operator which modifies its lhs
35 \*---------------------------------------------------------------------------*/
37 #include "OPstream.H"
38 #include "IPstream.H"
39 #include "IOstreams.H"
40 #include "contiguous.H"
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44 namespace Foam
47 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
49 template <class T, class CombineOp>
50 void Pstream::combineGather
52     const List<Pstream::commsStruct>& comms,
53     T& Value,
54     const CombineOp& cop
57     if (Pstream::parRun())
58     {
59         // Get my communication order
60         const commsStruct& myComm = comms[Pstream::myProcNo()];
62         // Receive from my downstairs neighbours
63         forAll(myComm.below(), belowI)
64         {
65             label belowID = myComm.below()[belowI];
67             if (contiguous<T>())
68             {
69                 T value;
70                 IPstream::read
71                 (
72                     Pstream::scheduled,
73                     belowID,
74                     reinterpret_cast<char*>(&value),
75                     sizeof(T)
76                 );
78                 if (debug & 2)
79                 {
80                     Pout<< " received from "
81                         << belowID << " data:" << value << endl;
82                 }
84                 cop(Value, value);
85             }
86             else
87             {
88                 IPstream fromBelow(Pstream::scheduled, belowID);
89                 T value(fromBelow);
91                 if (debug & 2)
92                 {
93                     Pout<< " received from "
94                         << belowID << " data:" << value << endl;
95                 }
97                 cop(Value, value);
98             }
99         }
101         // Send up Value
102         if (myComm.above() != -1)
103         {
104             if (debug & 2)
105             {
106                 Pout<< " sending to " << myComm.above()
107                     << " data:" << Value << endl;
108             }
110             if (contiguous<T>())
111             {
112                 OPstream::write
113                 (
114                     Pstream::scheduled,
115                     myComm.above(),
116                     reinterpret_cast<const char*>(&Value),
117                     sizeof(T)
118                 );
119             }
120             else
121             {
122                 OPstream toAbove(Pstream::scheduled, myComm.above());
123                 toAbove << Value;
124             }
125         }
126     }
130 template <class T, class CombineOp>
131 void Pstream::combineGather(T& Value, const CombineOp& cop)
133     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
134     {
135         combineGather(Pstream::linearCommunication(), Value, cop);
136     }
137     else
138     {
139         combineGather(Pstream::treeCommunication(), Value, cop);
140     }
144 template <class T>
145 void Pstream::combineScatter(const List<Pstream::commsStruct>& comms, T& Value)
147     if (Pstream::parRun())
148     {
149         // Get my communication order
150         const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
152         // Reveive from up
153         if (myComm.above() != -1)
154         {
155             if (contiguous<T>())
156             {
157                 IPstream::read
158                 (
159                     Pstream::scheduled,
160                     myComm.above(),
161                     reinterpret_cast<char*>(&Value),
162                     sizeof(T)
163                 );
164             }
165             else
166             {
167                 IPstream fromAbove(Pstream::scheduled, myComm.above());
168                 Value = T(fromAbove);
169             }
171             if (debug & 2)
172             {
173                 Pout<< " received from "
174                     << myComm.above() << " data:" << Value << endl;
175             }
176         }
178         // Send to my downstairs neighbours
179         forAll(myComm.below(), belowI)
180         {
181             label belowID = myComm.below()[belowI];
183             if (debug & 2)
184             {
185                 Pout<< " sending to " << belowID << " data:" << Value << endl;
186             }
188             if (contiguous<T>())
189             {
190                 OPstream::write
191                 (
192                     Pstream::scheduled,
193                     belowID,
194                     reinterpret_cast<const char*>(&Value),
195                     sizeof(T)
196                 );
197             }
198             else
199             {
200                 OPstream toBelow(Pstream::scheduled, belowID);
201                 toBelow << Value;
202             }
203         }
204     }
208 template <class T>
209 void Pstream::combineScatter(T& Value)
211     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
212     {
213         combineScatter(Pstream::linearCommunication(), Value);
214     }
215     else
216     {
217         combineScatter(Pstream::treeCommunication(), Value);
218     }
222 // Same thing but for whole list at a time
223 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
226 template <class T, class CombineOp>
227 void Pstream::listCombineGather
229     const List<Pstream::commsStruct>& comms,
230     List<T>& Values,
231     const CombineOp& cop
234     if (Pstream::parRun())
235     {
236         // Get my communication order
237         const commsStruct& myComm = comms[Pstream::myProcNo()];
239         // Receive from my downstairs neighbours
240         forAll(myComm.below(), belowI)
241         {
242             label belowID = myComm.below()[belowI];
244             if (contiguous<T>())
245             {
246                 List<T> receivedValues(Values.size());
248                 IPstream::read
249                 (
250                     Pstream::scheduled,
251                     belowID,
252                     reinterpret_cast<char*>(receivedValues.begin()),
253                     receivedValues.byteSize()
254                 );
256                 if (debug & 2)
257                 {
258                     Pout<< " received from "
259                         << belowID << " data:" << receivedValues << endl;
260                 }
262                 forAll(Values, i)
263                 {
264                     cop(Values[i], receivedValues[i]);
265                 }
266             }
267             else
268             {
269                 IPstream fromBelow(Pstream::scheduled, belowID);
270                 List<T> receivedValues(fromBelow);
272                 if (debug & 2)
273                 {
274                     Pout<< " received from "
275                         << belowID << " data:" << receivedValues << endl;
276                 }
278                 forAll(Values, i)
279                 {
280                     cop(Values[i], receivedValues[i]);
281                 }
282             }
283         }
285         // Send up Value
286         if (myComm.above() != -1)
287         {
288             if (debug & 2)
289             {
290                 Pout<< " sending to " << myComm.above()
291                     << " data:" << Values << endl;
292             }
294             if (contiguous<T>())
295             {
296                 OPstream::write
297                 (
298                     Pstream::scheduled,
299                     myComm.above(),
300                     reinterpret_cast<const char*>(Values.begin()),
301                     Values.byteSize()
302                 );
303             }
304             else
305             {
306                 OPstream toAbove(Pstream::scheduled, myComm.above());
307                 toAbove << Values;
308             }
309         }
310     }
314 template <class T, class CombineOp>
315 void Pstream::listCombineGather(List<T>& Values, const CombineOp& cop)
317     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
318     {
319         listCombineGather(Pstream::linearCommunication(), Values, cop);
320     }
321     else
322     {
323         listCombineGather(Pstream::treeCommunication(), Values, cop);
324     }
328 template <class T>
329 void Pstream::listCombineScatter
331     const List<Pstream::commsStruct>& comms,
332     List<T>& Values
335     if (Pstream::parRun())
336     {
337         // Get my communication order
338         const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
340         // Reveive from up
341         if (myComm.above() != -1)
342         {
343             if (contiguous<T>())
344             {
345                 IPstream::read
346                 (
347                     Pstream::scheduled,
348                     myComm.above(),
349                     reinterpret_cast<char*>(Values.begin()),
350                     Values.byteSize()
351                 );
352             }
353             else
354             {
355                 IPstream fromAbove(Pstream::scheduled, myComm.above());
356                 fromAbove >> Values;
357             }
359             if (debug & 2)
360             {
361                 Pout<< " received from "
362                     << myComm.above() << " data:" << Values << endl;
363             }
364         }
366         // Send to my downstairs neighbours
367         forAll(myComm.below(), belowI)
368         {
369             label belowID = myComm.below()[belowI];
371             if (debug & 2)
372             {
373                 Pout<< " sending to " << belowID << " data:" << Values << endl;
374             }
376             if (contiguous<T>())
377             {
378                 OPstream::write
379                 (
380                     Pstream::scheduled,
381                     belowID,
382                     reinterpret_cast<const char*>(Values.begin()),
383                     Values.byteSize()
384                 );
385             }
386             else
387             {
388                 OPstream toBelow(Pstream::scheduled, belowID);
389                 toBelow << Values;
390             }
391         }
392     }
396 template <class T>
397 void Pstream::listCombineScatter(List<T>& Values)
399     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
400     {
401         listCombineScatter(Pstream::linearCommunication(), Values);
402     }
403     else
404     {
405         listCombineScatter(Pstream::treeCommunication(), Values);
406     }
412 // Same thing but for sparse list (map)
413 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
416 template <class Container, class CombineOp>
417 void Pstream::mapCombineGather
419     const List<Pstream::commsStruct>& comms,
420     Container& Values,
421     const CombineOp& cop
424     if (Pstream::parRun())
425     {
426         // Get my communication order
427         const commsStruct& myComm = comms[Pstream::myProcNo()];
429         // Receive from my downstairs neighbours
430         forAll(myComm.below(), belowI)
431         {
432             label belowID = myComm.below()[belowI];
434             IPstream fromBelow(Pstream::scheduled, belowID);
435             Container receivedValues(fromBelow);
437             if (debug & 2)
438             {
439                 Pout<< " received from "
440                     << belowID << " data:" << receivedValues << endl;
441             }
443             for
444             (
445                 typename Container::const_iterator slaveIter =
446                     receivedValues.begin();
447                 slaveIter != receivedValues.end();
448                 ++slaveIter
449             )
450             {
451                 typename Container::iterator
452                     masterIter = Values.find(slaveIter.key());
454                 if (masterIter != Values.end())
455                 {
456                     cop(masterIter(), slaveIter());
457                 }
458                 else
459                 {
460                     Values.insert(slaveIter.key(), slaveIter());
461                 }
462             }
463         }
465         // Send up Value
466         if (myComm.above() != -1)
467         {
468             if (debug & 2)
469             {
470                 Pout<< " sending to " << myComm.above()
471                     << " data:" << Values << endl;
472             }
474             OPstream toAbove(Pstream::scheduled, myComm.above());
475             toAbove << Values;
476         }
477     }
481 template <class Container, class CombineOp>
482 void Pstream::mapCombineGather(Container& Values, const CombineOp& cop)
484     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
485     {
486         mapCombineGather(Pstream::linearCommunication(), Values, cop);
487     }
488     else
489     {
490         mapCombineGather(Pstream::treeCommunication(), Values, cop);
491     }
495 template <class Container>
496 void Pstream::mapCombineScatter
498     const List<Pstream::commsStruct>& comms,
499     Container& Values
502     if (Pstream::parRun())
503     {
504         // Get my communication order
505         const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
507         // Reveive from up
508         if (myComm.above() != -1)
509         {
510             IPstream fromAbove(Pstream::scheduled, myComm.above());
511             fromAbove >> Values;
513             if (debug & 2)
514             {
515                 Pout<< " received from "
516                     << myComm.above() << " data:" << Values << endl;
517             }
518         }
520         // Send to my downstairs neighbours
521         forAll(myComm.below(), belowI)
522         {
523             label belowID = myComm.below()[belowI];
525             if (debug & 2)
526             {
527                 Pout<< " sending to " << belowID << " data:" << Values << endl;
528             }
530             OPstream toBelow(Pstream::scheduled, belowID);
531             toBelow << Values;
532         }
533     }
537 template <class Container>
538 void Pstream::mapCombineScatter(Container& Values)
540     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
541     {
542         mapCombineScatter(Pstream::linearCommunication(), Values);
543     }
544     else
545     {
546         mapCombineScatter(Pstream::treeCommunication(), Values);
547     }
553 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
555 } // End namespace Foam
557 // ************************************************************************* //