ENH: autoLayerDriver: better layering information message
[OpenFOAM-2.0.x.git] / src / OpenFOAM / db / IOstreams / Pstreams / combineGatherScatter.C
bloba3e75fc95f61b89b3f743e50a39154a9788c2cbb
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     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<UPstream::commsStruct>& comms,
52     T& Value,
53     const CombineOp& cop
56     if (UPstream::parRun())
57     {
58         // Get my communication order
59         const commsStruct& myComm = comms[UPstream::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                 UIPstream::read
70                 (
71                     UPstream::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(UPstream::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                 UOPstream::write
112                 (
113                     UPstream::scheduled,
114                     myComm.above(),
115                     reinterpret_cast<const char*>(&Value),
116                     sizeof(T)
117                 );
118             }
119             else
120             {
121                 OPstream toAbove(UPstream::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 (UPstream::nProcs() < UPstream::nProcsSimpleSum)
133     {
134         combineGather(UPstream::linearCommunication(), Value, cop);
135     }
136     else
137     {
138         combineGather(UPstream::treeCommunication(), Value, cop);
139     }
143 template <class T>
144 void Pstream::combineScatter
146     const List<UPstream::commsStruct>& comms,
147     T& Value
150     if (UPstream::parRun())
151     {
152         // Get my communication order
153         const UPstream::commsStruct& myComm = comms[UPstream::myProcNo()];
155         // Reveive from up
156         if (myComm.above() != -1)
157         {
158             if (contiguous<T>())
159             {
160                 UIPstream::read
161                 (
162                     UPstream::scheduled,
163                     myComm.above(),
164                     reinterpret_cast<char*>(&Value),
165                     sizeof(T)
166                 );
167             }
168             else
169             {
170                 IPstream fromAbove(UPstream::scheduled, myComm.above());
171                 Value = T(fromAbove);
172             }
174             if (debug & 2)
175             {
176                 Pout<< " received from "
177                     << myComm.above() << " data:" << Value << endl;
178             }
179         }
181         // Send to my downstairs neighbours
182         forAll(myComm.below(), belowI)
183         {
184             label belowID = myComm.below()[belowI];
186             if (debug & 2)
187             {
188                 Pout<< " sending to " << belowID << " data:" << Value << endl;
189             }
191             if (contiguous<T>())
192             {
193                 UOPstream::write
194                 (
195                     UPstream::scheduled,
196                     belowID,
197                     reinterpret_cast<const char*>(&Value),
198                     sizeof(T)
199                 );
200             }
201             else
202             {
203                 OPstream toBelow(UPstream::scheduled, belowID);
204                 toBelow << Value;
205             }
206         }
207     }
211 template <class T>
212 void Pstream::combineScatter(T& Value)
214     if (UPstream::nProcs() < UPstream::nProcsSimpleSum)
215     {
216         combineScatter(UPstream::linearCommunication(), Value);
217     }
218     else
219     {
220         combineScatter(UPstream::treeCommunication(), Value);
221     }
225 // Same thing but for whole list at a time
226 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
229 template <class T, class CombineOp>
230 void Pstream::listCombineGather
232     const List<UPstream::commsStruct>& comms,
233     List<T>& Values,
234     const CombineOp& cop
237     if (UPstream::parRun())
238     {
239         // Get my communication order
240         const commsStruct& myComm = comms[UPstream::myProcNo()];
242         // Receive from my downstairs neighbours
243         forAll(myComm.below(), belowI)
244         {
245             label belowID = myComm.below()[belowI];
247             if (contiguous<T>())
248             {
249                 List<T> receivedValues(Values.size());
251                 UIPstream::read
252                 (
253                     UPstream::scheduled,
254                     belowID,
255                     reinterpret_cast<char*>(receivedValues.begin()),
256                     receivedValues.byteSize()
257                 );
259                 if (debug & 2)
260                 {
261                     Pout<< " received from "
262                         << belowID << " data:" << receivedValues << endl;
263                 }
265                 forAll(Values, i)
266                 {
267                     cop(Values[i], receivedValues[i]);
268                 }
269             }
270             else
271             {
272                 IPstream fromBelow(UPstream::scheduled, belowID);
273                 List<T> receivedValues(fromBelow);
275                 if (debug & 2)
276                 {
277                     Pout<< " received from "
278                         << belowID << " data:" << receivedValues << endl;
279                 }
281                 forAll(Values, i)
282                 {
283                     cop(Values[i], receivedValues[i]);
284                 }
285             }
286         }
288         // Send up Value
289         if (myComm.above() != -1)
290         {
291             if (debug & 2)
292             {
293                 Pout<< " sending to " << myComm.above()
294                     << " data:" << Values << endl;
295             }
297             if (contiguous<T>())
298             {
299                 UOPstream::write
300                 (
301                     UPstream::scheduled,
302                     myComm.above(),
303                     reinterpret_cast<const char*>(Values.begin()),
304                     Values.byteSize()
305                 );
306             }
307             else
308             {
309                 OPstream toAbove(UPstream::scheduled, myComm.above());
310                 toAbove << Values;
311             }
312         }
313     }
317 template <class T, class CombineOp>
318 void Pstream::listCombineGather(List<T>& Values, const CombineOp& cop)
320     if (UPstream::nProcs() < UPstream::nProcsSimpleSum)
321     {
322         listCombineGather(UPstream::linearCommunication(), Values, cop);
323     }
324     else
325     {
326         listCombineGather(UPstream::treeCommunication(), Values, cop);
327     }
331 template <class T>
332 void Pstream::listCombineScatter
334     const List<UPstream::commsStruct>& comms,
335     List<T>& Values
338     if (UPstream::parRun())
339     {
340         // Get my communication order
341         const UPstream::commsStruct& myComm = comms[UPstream::myProcNo()];
343         // Reveive from up
344         if (myComm.above() != -1)
345         {
346             if (contiguous<T>())
347             {
348                 UIPstream::read
349                 (
350                     UPstream::scheduled,
351                     myComm.above(),
352                     reinterpret_cast<char*>(Values.begin()),
353                     Values.byteSize()
354                 );
355             }
356             else
357             {
358                 IPstream fromAbove(UPstream::scheduled, myComm.above());
359                 fromAbove >> Values;
360             }
362             if (debug & 2)
363             {
364                 Pout<< " received from "
365                     << myComm.above() << " data:" << Values << endl;
366             }
367         }
369         // Send to my downstairs neighbours
370         forAll(myComm.below(), belowI)
371         {
372             label belowID = myComm.below()[belowI];
374             if (debug & 2)
375             {
376                 Pout<< " sending to " << belowID << " data:" << Values << endl;
377             }
379             if (contiguous<T>())
380             {
381                 UOPstream::write
382                 (
383                     UPstream::scheduled,
384                     belowID,
385                     reinterpret_cast<const char*>(Values.begin()),
386                     Values.byteSize()
387                 );
388             }
389             else
390             {
391                 OPstream toBelow(UPstream::scheduled, belowID);
392                 toBelow << Values;
393             }
394         }
395     }
399 template <class T>
400 void Pstream::listCombineScatter(List<T>& Values)
402     if (UPstream::nProcs() < UPstream::nProcsSimpleSum)
403     {
404         listCombineScatter(UPstream::linearCommunication(), Values);
405     }
406     else
407     {
408         listCombineScatter(UPstream::treeCommunication(), Values);
409     }
415 // Same thing but for sparse list (map)
416 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
419 template <class Container, class CombineOp>
420 void Pstream::mapCombineGather
422     const List<UPstream::commsStruct>& comms,
423     Container& Values,
424     const CombineOp& cop
427     if (UPstream::parRun())
428     {
429         // Get my communication order
430         const commsStruct& myComm = comms[UPstream::myProcNo()];
432         // Receive from my downstairs neighbours
433         forAll(myComm.below(), belowI)
434         {
435             label belowID = myComm.below()[belowI];
437             IPstream fromBelow(UPstream::scheduled, belowID);
438             Container receivedValues(fromBelow);
440             if (debug & 2)
441             {
442                 Pout<< " received from "
443                     << belowID << " data:" << receivedValues << endl;
444             }
446             for
447             (
448                 typename Container::const_iterator slaveIter =
449                     receivedValues.begin();
450                 slaveIter != receivedValues.end();
451                 ++slaveIter
452             )
453             {
454                 typename Container::iterator
455                     masterIter = Values.find(slaveIter.key());
457                 if (masterIter != Values.end())
458                 {
459                     cop(masterIter(), slaveIter());
460                 }
461                 else
462                 {
463                     Values.insert(slaveIter.key(), slaveIter());
464                 }
465             }
466         }
468         // Send up Value
469         if (myComm.above() != -1)
470         {
471             if (debug & 2)
472             {
473                 Pout<< " sending to " << myComm.above()
474                     << " data:" << Values << endl;
475             }
477             OPstream toAbove(UPstream::scheduled, myComm.above());
478             toAbove << Values;
479         }
480     }
484 template <class Container, class CombineOp>
485 void Pstream::mapCombineGather(Container& Values, const CombineOp& cop)
487     if (UPstream::nProcs() < UPstream::nProcsSimpleSum)
488     {
489         mapCombineGather(UPstream::linearCommunication(), Values, cop);
490     }
491     else
492     {
493         mapCombineGather(UPstream::treeCommunication(), Values, cop);
494     }
498 template <class Container>
499 void Pstream::mapCombineScatter
501     const List<UPstream::commsStruct>& comms,
502     Container& Values
505     if (UPstream::parRun())
506     {
507         // Get my communication order
508         const UPstream::commsStruct& myComm = comms[UPstream::myProcNo()];
510         // Reveive from up
511         if (myComm.above() != -1)
512         {
513             IPstream fromAbove(UPstream::scheduled, myComm.above());
514             fromAbove >> Values;
516             if (debug & 2)
517             {
518                 Pout<< " received from "
519                     << myComm.above() << " data:" << Values << endl;
520             }
521         }
523         // Send to my downstairs neighbours
524         forAll(myComm.below(), belowI)
525         {
526             label belowID = myComm.below()[belowI];
528             if (debug & 2)
529             {
530                 Pout<< " sending to " << belowID << " data:" << Values << endl;
531             }
533             OPstream toBelow(UPstream::scheduled, belowID);
534             toBelow << Values;
535         }
536     }
540 template <class Container>
541 void Pstream::mapCombineScatter(Container& Values)
543     if (UPstream::nProcs() < UPstream::nProcsSimpleSum)
544     {
545         mapCombineScatter(UPstream::linearCommunication(), Values);
546     }
547     else
548     {
549         mapCombineScatter(UPstream::treeCommunication(), Values);
550     }
554 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
556 } // End namespace Foam
558 // ************************************************************************* //