Merge branch 'master' of ssh://git.code.sf.net/p/foam-extend/foam-extend-3.2
[foam-extend-3.2.git] / src / foam / db / IOstreams / Pstreams / combineGatherScatter.C
blob71972301ab48e3102748d95d30344d80d898eb4d
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | foam-extend: Open Source CFD
4    \\    /   O peration     | Version:     3.2
5     \\  /    A nd           | Web:         http://www.foam-extend.org
6      \\/     M anipulation  | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9     This file is part of foam-extend.
11     foam-extend 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 3 of the License, or (at your
14     option) any later version.
16     foam-extend is distributed in the hope that it will be useful, but
17     WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19     General Public License for more details.
21     You should have received a copy of the GNU General Public License
22     along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.
24 Description
25     Variant of gather, scatter.
26     Normal gather uses:
27     - construct null and read (>>) from Istream
28     - binary operator and assignment operator to combine values
30     combineGather uses:
31     - construct from Istream
32     - modify operator which modifies its lhs
34 \*---------------------------------------------------------------------------*/
36 #include "OPstream.H"
37 #include "IPstream.H"
38 #include "IOstreams.H"
39 #include "contiguous.H"
41 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43 namespace Foam
46 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
48 template <class T, class CombineOp>
49 void Pstream::combineGather
51     const List<Pstream::commsStruct>& comms,
52     T& Value,
53     const CombineOp& cop
56     if (Pstream::parRun())
57     {
58         // Get my communication order
59         const commsStruct& myComm = comms[Pstream::myProcNo()];
61         // Receive from my downstairs neighbours
62         forAll(myComm.below(), belowI)
63         {
64             label belowID = myComm.below()[belowI];
66             if (contiguous<T>())
67             {
68                 T value;
69                 IPstream::read
70                 (
71                     Pstream::scheduled,
72                     belowID,
73                     reinterpret_cast<char*>(&value),
74                     sizeof(T)
75                 );
77                 if (debug & 2)
78                 {
79                     Pout<< " received from "
80                         << belowID << " data:" << value << endl;
81                 }
83                 cop(Value, value);
84             }
85             else
86             {
87                 IPstream fromBelow(Pstream::scheduled, belowID);
88                 T value(fromBelow);
90                 if (debug & 2)
91                 {
92                     Pout<< " received from "
93                         << belowID << " data:" << value << endl;
94                 }
96                 cop(Value, value);
97             }
98         }
100         // Send up Value
101         if (myComm.above() != -1)
102         {
103             if (debug & 2)
104             {
105                 Pout<< " sending to " << myComm.above()
106                     << " data:" << Value << endl;
107             }
109             if (contiguous<T>())
110             {
111                 OPstream::write
112                 (
113                     Pstream::scheduled,
114                     myComm.above(),
115                     reinterpret_cast<const char*>(&Value),
116                     sizeof(T)
117                 );
118             }
119             else
120             {
121                 OPstream toAbove(Pstream::scheduled, myComm.above());
122                 toAbove << Value;
123             }
124         }
125     }
129 template <class T, class CombineOp>
130 void Pstream::combineGather(T& Value, const CombineOp& cop)
132     if (Pstream::nProcs() < Pstream::nProcsSimpleSum())
133     {
134         combineGather(Pstream::linearCommunication(), Value, cop);
135     }
136     else
137     {
138         combineGather(Pstream::treeCommunication(), Value, cop);
139     }
143 template <class T>
144 void Pstream::combineScatter(const List<Pstream::commsStruct>& comms, T& Value)
146     if (Pstream::parRun())
147     {
148         // Get my communication order
149         const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
151         // Receive from up
152         if (myComm.above() != -1)
153         {
154             if (contiguous<T>())
155             {
156                 IPstream::read
157                 (
158                     Pstream::scheduled,
159                     myComm.above(),
160                     reinterpret_cast<char*>(&Value),
161                     sizeof(T)
162                 );
163             }
164             else
165             {
166                 IPstream fromAbove(Pstream::scheduled, myComm.above());
167                 Value = T(fromAbove);
168             }
170             if (debug & 2)
171             {
172                 Pout<< " received from "
173                     << myComm.above() << " data:" << Value << endl;
174             }
175         }
177         // Send to my downstairs neighbours
178         forAll(myComm.below(), belowI)
179         {
180             label belowID = myComm.below()[belowI];
182             if (debug & 2)
183             {
184                 Pout<< " sending to " << belowID << " data:" << Value << endl;
185             }
187             if (contiguous<T>())
188             {
189                 OPstream::write
190                 (
191                     Pstream::scheduled,
192                     belowID,
193                     reinterpret_cast<const char*>(&Value),
194                     sizeof(T)
195                 );
196             }
197             else
198             {
199                 OPstream toBelow(Pstream::scheduled, belowID);
200                 toBelow << Value;
201             }
202         }
203     }
207 template <class T>
208 void Pstream::combineScatter(T& Value)
210     if (Pstream::nProcs() < Pstream::nProcsSimpleSum())
211     {
212         combineScatter(Pstream::linearCommunication(), Value);
213     }
214     else
215     {
216         combineScatter(Pstream::treeCommunication(), Value);
217     }
221 // Same thing but for whole list at a time
222 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
225 template <class T, class CombineOp>
226 void Pstream::listCombineGather
228     const List<Pstream::commsStruct>& comms,
229     List<T>& Values,
230     const CombineOp& cop
233     if (Pstream::parRun())
234     {
235         // Get my communication order
236         const commsStruct& myComm = comms[Pstream::myProcNo()];
238         // Receive from my downstairs neighbours
239         forAll(myComm.below(), belowI)
240         {
241             label belowID = myComm.below()[belowI];
243             if (contiguous<T>())
244             {
245                 List<T> receivedValues(Values.size());
247                 IPstream::read
248                 (
249                     Pstream::scheduled,
250                     belowID,
251                     reinterpret_cast<char*>(receivedValues.begin()),
252                     receivedValues.byteSize()
253                 );
255                 if (debug & 2)
256                 {
257                     Pout<< " received from "
258                         << belowID << " data:" << receivedValues << endl;
259                 }
261                 forAll(Values, i)
262                 {
263                     cop(Values[i], receivedValues[i]);
264                 }
265             }
266             else
267             {
268                 IPstream fromBelow(Pstream::scheduled, belowID);
269                 List<T> receivedValues(fromBelow);
271                 if (debug & 2)
272                 {
273                     Pout<< " received from "
274                         << belowID << " data:" << receivedValues << endl;
275                 }
277                 forAll(Values, i)
278                 {
279                     cop(Values[i], receivedValues[i]);
280                 }
281             }
282         }
284         // Send up Value
285         if (myComm.above() != -1)
286         {
287             if (debug & 2)
288             {
289                 Pout<< " sending to " << myComm.above()
290                     << " data:" << Values << endl;
291             }
293             if (contiguous<T>())
294             {
295                 OPstream::write
296                 (
297                     Pstream::scheduled,
298                     myComm.above(),
299                     reinterpret_cast<const char*>(Values.begin()),
300                     Values.byteSize()
301                 );
302             }
303             else
304             {
305                 OPstream toAbove(Pstream::scheduled, myComm.above());
306                 toAbove << Values;
307             }
308         }
309     }
313 template <class T, class CombineOp>
314 void Pstream::listCombineGather(List<T>& Values, const CombineOp& cop)
316     if (Pstream::nProcs() < Pstream::nProcsSimpleSum())
317     {
318         listCombineGather(Pstream::linearCommunication(), Values, cop);
319     }
320     else
321     {
322         listCombineGather(Pstream::treeCommunication(), Values, cop);
323     }
327 template <class T>
328 void Pstream::listCombineScatter
330     const List<Pstream::commsStruct>& comms,
331     List<T>& Values
334     if (Pstream::parRun())
335     {
336         // Get my communication order
337         const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
339         // Receive from up
340         if (myComm.above() != -1)
341         {
342             if (contiguous<T>())
343             {
344                 IPstream::read
345                 (
346                     Pstream::scheduled,
347                     myComm.above(),
348                     reinterpret_cast<char*>(Values.begin()),
349                     Values.byteSize()
350                 );
351             }
352             else
353             {
354                 IPstream fromAbove(Pstream::scheduled, myComm.above());
355                 fromAbove >> Values;
356             }
358             if (debug & 2)
359             {
360                 Pout<< " received from "
361                     << myComm.above() << " data:" << Values << endl;
362             }
363         }
365         // Send to my downstairs neighbours
366         forAll(myComm.below(), belowI)
367         {
368             label belowID = myComm.below()[belowI];
370             if (debug & 2)
371             {
372                 Pout<< " sending to " << belowID << " data:" << Values << endl;
373             }
375             if (contiguous<T>())
376             {
377                 OPstream::write
378                 (
379                     Pstream::scheduled,
380                     belowID,
381                     reinterpret_cast<const char*>(Values.begin()),
382                     Values.byteSize()
383                 );
384             }
385             else
386             {
387                 OPstream toBelow(Pstream::scheduled, belowID);
388                 toBelow << Values;
389             }
390         }
391     }
395 template <class T>
396 void Pstream::listCombineScatter(List<T>& Values)
398     if (Pstream::nProcs() < Pstream::nProcsSimpleSum())
399     {
400         listCombineScatter(Pstream::linearCommunication(), Values);
401     }
402     else
403     {
404         listCombineScatter(Pstream::treeCommunication(), Values);
405     }
411 // Same thing but for sparse list (map)
412 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
415 template <class Container, class CombineOp>
416 void Pstream::mapCombineGather
418     const List<Pstream::commsStruct>& comms,
419     Container& Values,
420     const CombineOp& cop
423     if (Pstream::parRun())
424     {
425         // Get my communication order
426         const commsStruct& myComm = comms[Pstream::myProcNo()];
428         // Receive from my downstairs neighbours
429         forAll(myComm.below(), belowI)
430         {
431             label belowID = myComm.below()[belowI];
433             IPstream fromBelow(Pstream::scheduled, belowID);
434             Container receivedValues(fromBelow);
436             if (debug & 2)
437             {
438                 Pout<< " received from "
439                     << belowID << " data:" << receivedValues << endl;
440             }
442             for
443             (
444                 typename Container::const_iterator slaveIter =
445                     receivedValues.begin();
446                 slaveIter != receivedValues.end();
447                 ++slaveIter
448             )
449             {
450                 typename Container::iterator
451                     masterIter = Values.find(slaveIter.key());
453                 if (masterIter != Values.end())
454                 {
455                     cop(masterIter(), slaveIter());
456                 }
457                 else
458                 {
459                     Values.insert(slaveIter.key(), slaveIter());
460                 }
461             }
462         }
464         // Send up Value
465         if (myComm.above() != -1)
466         {
467             if (debug & 2)
468             {
469                 Pout<< " sending to " << myComm.above()
470                     << " data:" << Values << endl;
471             }
473             OPstream toAbove(Pstream::scheduled, myComm.above());
474             toAbove << Values;
475         }
476     }
480 template <class Container, class CombineOp>
481 void Pstream::mapCombineGather(Container& Values, const CombineOp& cop)
483     if (Pstream::nProcs() < Pstream::nProcsSimpleSum())
484     {
485         mapCombineGather(Pstream::linearCommunication(), Values, cop);
486     }
487     else
488     {
489         mapCombineGather(Pstream::treeCommunication(), Values, cop);
490     }
494 template <class Container>
495 void Pstream::mapCombineScatter
497     const List<Pstream::commsStruct>& comms,
498     Container& Values
501     if (Pstream::parRun())
502     {
503         // Get my communication order
504         const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
506         // Receive from up
507         if (myComm.above() != -1)
508         {
509             IPstream fromAbove(Pstream::scheduled, myComm.above());
510             fromAbove >> Values;
512             if (debug & 2)
513             {
514                 Pout<< " received from "
515                     << myComm.above() << " data:" << Values << endl;
516             }
517         }
519         // Send to my downstairs neighbours
520         forAll(myComm.below(), belowI)
521         {
522             label belowID = myComm.below()[belowI];
524             if (debug & 2)
525             {
526                 Pout<< " sending to " << belowID << " data:" << Values << endl;
527             }
529             OPstream toBelow(Pstream::scheduled, belowID);
530             toBelow << Values;
531         }
532     }
536 template <class Container>
537 void Pstream::mapCombineScatter(Container& Values)
539     if (Pstream::nProcs() < Pstream::nProcsSimpleSum())
540     {
541         mapCombineScatter(Pstream::linearCommunication(), Values);
542     }
543     else
544     {
545         mapCombineScatter(Pstream::treeCommunication(), Values);
546     }
550 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
552 } // End namespace Foam
554 // ************************************************************************* //