combineGatherScatter.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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.
20 
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/>.
23 
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
29 
30  combineGather uses:
31  - construct from Istream
32  - modify operator which modifies its lhs
33 
34 \*---------------------------------------------------------------------------*/
35 
36 #include "OPstream.H"
37 #include "IPstream.H"
38 #include "IOstreams.H"
39 #include "contiguous.H"
40 
41 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
42 
43 template<class T, class CombineOp>
45 (
46  const List<UPstream::commsStruct>& comms,
47  T& Value,
48  const CombineOp& cop,
49  const int tag,
50  const label comm
51 )
52 {
53  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
54  {
55  // Get my communication order
56  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
57 
58  // Receive from my downstairs neighbours
59  forAll(myComm.below(), belowI)
60  {
61  label belowID = myComm.below()[belowI];
62 
63  if (contiguous<T>())
64  {
65  T value;
67  (
68  UPstream::scheduled,
69  belowID,
70  reinterpret_cast<char*>(&value),
71  sizeof(T),
72  tag,
73  comm
74  );
75 
76  if (debug & 2)
77  {
78  Pout<< " received from "
79  << belowID << " data:" << value << endl;
80  }
81 
82  cop(Value, value);
83  }
84  else
85  {
86  IPstream fromBelow(UPstream::scheduled, belowID, 0, tag, comm);
87  T value(fromBelow);
88 
89  if (debug & 2)
90  {
91  Pout<< " received from "
92  << belowID << " data:" << value << endl;
93  }
94 
95  cop(Value, value);
96  }
97  }
98 
99  // Send up Value
100  if (myComm.above() != -1)
101  {
102  if (debug & 2)
103  {
104  Pout<< " sending to " << myComm.above()
105  << " data:" << Value << endl;
106  }
107 
108  if (contiguous<T>())
109  {
111  (
112  UPstream::scheduled,
113  myComm.above(),
114  reinterpret_cast<const char*>(&Value),
115  sizeof(T),
116  tag,
117  comm
118  );
119  }
120  else
121  {
122  OPstream toAbove
123  (
124  UPstream::scheduled,
125  myComm.above(),
126  0,
127  tag,
128  comm
129  );
130  toAbove << Value;
131  }
132  }
133  }
134 }
135 
136 
137 template<class T, class CombineOp>
139 (
140  T& Value,
141  const CombineOp& cop,
142  const int tag,
143  const label comm
144 )
145 {
146  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
147  {
149  (
150  UPstream::linearCommunication(comm),
151  Value,
152  cop,
153  tag,
154  comm
155  );
156  }
157  else
158  {
159  combineGather
160  (
161  UPstream::treeCommunication(comm),
162  Value,
163  cop,
164  tag,
165  comm
166  );
167  }
168 }
169 
170 
171 template<class T>
173 (
174  const List<UPstream::commsStruct>& comms,
175  T& Value,
176  const int tag,
177  const label comm
178 )
179 {
180  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
181  {
182  // Get my communication order
183  const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
184 
185  // Reveive from up
186  if (myComm.above() != -1)
187  {
188  if (contiguous<T>())
189  {
191  (
192  UPstream::scheduled,
193  myComm.above(),
194  reinterpret_cast<char*>(&Value),
195  sizeof(T),
196  tag,
197  comm
198  );
199  }
200  else
201  {
202  IPstream fromAbove
203  (
204  UPstream::scheduled,
205  myComm.above(),
206  0,
207  tag,
208  comm
209  );
210  Value = T(fromAbove);
211  }
212 
213  if (debug & 2)
214  {
215  Pout<< " received from "
216  << myComm.above() << " data:" << Value << endl;
217  }
218  }
219 
220  // Send to my downstairs neighbours
221  forAllReverse(myComm.below(), belowI)
222  {
223  label belowID = myComm.below()[belowI];
224 
225  if (debug & 2)
226  {
227  Pout<< " sending to " << belowID << " data:" << Value << endl;
228  }
229 
230  if (contiguous<T>())
231  {
233  (
234  UPstream::scheduled,
235  belowID,
236  reinterpret_cast<const char*>(&Value),
237  sizeof(T),
238  tag,
239  comm
240  );
241  }
242  else
243  {
244  OPstream toBelow(UPstream::scheduled, belowID, 0, tag, comm);
245  toBelow << Value;
246  }
247  }
248  }
249 }
250 
251 
252 template<class T>
254 (
255  T& Value,
256  const int tag,
257  const label comm
258 )
259 {
260  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
261  {
262  combineScatter(UPstream::linearCommunication(comm), Value, tag, comm);
263  }
264  else
265  {
266  combineScatter(UPstream::treeCommunication(comm), Value, tag, comm);
267  }
268 }
269 
270 
271 template<class T, class CombineOp>
273 (
274  const List<UPstream::commsStruct>& comms,
275  List<T>& Values,
276  const CombineOp& cop,
277  const int tag,
278  const label comm
279 )
280 {
281  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
282  {
283  // Get my communication order
284  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
285 
286  // Receive from my downstairs neighbours
287  forAll(myComm.below(), belowI)
288  {
289  label belowID = myComm.below()[belowI];
290 
291  if (contiguous<T>())
292  {
293  List<T> receivedValues(Values.size());
294 
296  (
297  UPstream::scheduled,
298  belowID,
299  reinterpret_cast<char*>(receivedValues.begin()),
300  receivedValues.byteSize(),
301  tag,
302  comm
303  );
304 
305  if (debug & 2)
306  {
307  Pout<< " received from "
308  << belowID << " data:" << receivedValues << endl;
309  }
310 
311  forAll(Values, i)
312  {
313  cop(Values[i], receivedValues[i]);
314  }
315  }
316  else
317  {
318  IPstream fromBelow(UPstream::scheduled, belowID, 0, tag, comm);
319  List<T> receivedValues(fromBelow);
320 
321  if (debug & 2)
322  {
323  Pout<< " received from "
324  << belowID << " data:" << receivedValues << endl;
325  }
326 
327  forAll(Values, i)
328  {
329  cop(Values[i], receivedValues[i]);
330  }
331  }
332  }
333 
334  // Send up Value
335  if (myComm.above() != -1)
336  {
337  if (debug & 2)
338  {
339  Pout<< " sending to " << myComm.above()
340  << " data:" << Values << endl;
341  }
342 
343  if (contiguous<T>())
344  {
346  (
347  UPstream::scheduled,
348  myComm.above(),
349  reinterpret_cast<const char*>(Values.begin()),
350  Values.byteSize(),
351  tag,
352  comm
353  );
354  }
355  else
356  {
357  OPstream toAbove
358  (
359  UPstream::scheduled,
360  myComm.above(),
361  0,
362  tag,
363  comm
364  );
365  toAbove << Values;
366  }
367  }
368  }
369 }
370 
371 
372 template<class T, class CombineOp>
374 (
375  List<T>& Values,
376  const CombineOp& cop,
377  const int tag,
378  const label comm
379 )
380 {
381  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
382  {
383  listCombineGather
384  (
385  UPstream::linearCommunication(comm),
386  Values,
387  cop,
388  tag,
389  comm
390  );
391  }
392  else
393  {
394  listCombineGather
395  (
396  UPstream::treeCommunication(comm),
397  Values,
398  cop,
399  tag,
400  comm
401  );
402  }
403 }
404 
405 
406 template<class T>
408 (
409  const List<UPstream::commsStruct>& comms,
410  List<T>& Values,
411  const int tag,
412  const label comm
413 )
414 {
415  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
416  {
417  // Get my communication order
418  const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
419 
420  // Reveive from up
421  if (myComm.above() != -1)
422  {
423  if (contiguous<T>())
424  {
426  (
427  UPstream::scheduled,
428  myComm.above(),
429  reinterpret_cast<char*>(Values.begin()),
430  Values.byteSize(),
431  tag,
432  comm
433  );
434  }
435  else
436  {
437  IPstream fromAbove
438  (
439  UPstream::scheduled,
440  myComm.above(),
441  0,
442  tag,
443  comm
444  );
445  fromAbove >> Values;
446  }
447 
448  if (debug & 2)
449  {
450  Pout<< " received from "
451  << myComm.above() << " data:" << Values << endl;
452  }
453  }
454 
455  // Send to my downstairs neighbours
456  forAllReverse(myComm.below(), belowI)
457  {
458  label belowID = myComm.below()[belowI];
459 
460  if (debug & 2)
461  {
462  Pout<< " sending to " << belowID << " data:" << Values << endl;
463  }
464 
465  if (contiguous<T>())
466  {
468  (
469  UPstream::scheduled,
470  belowID,
471  reinterpret_cast<const char*>(Values.begin()),
472  Values.byteSize(),
473  tag,
474  comm
475  );
476  }
477  else
478  {
479  OPstream toBelow(UPstream::scheduled, belowID, 0, tag, comm);
480  toBelow << Values;
481  }
482  }
483  }
484 }
485 
486 
487 template<class T>
489 (
490  List<T>& Values,
491  const int tag,
492  const label comm
493 )
494 {
495  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
496  {
497  listCombineScatter
498  (
499  UPstream::linearCommunication(comm),
500  Values,
501  tag,
502  comm
503  );
504  }
505  else
506  {
507  listCombineScatter
508  (
509  UPstream::treeCommunication(comm),
510  Values,
511  tag,
512  comm
513  );
514  }
515 }
516 
517 
518 template<class Container, class CombineOp>
520 (
521  const List<UPstream::commsStruct>& comms,
522  Container& Values,
523  const CombineOp& cop,
524  const int tag,
525  const label comm
526 )
527 {
528  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
529  {
530  // Get my communication order
531  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
532 
533  // Receive from my downstairs neighbours
534  forAll(myComm.below(), belowI)
535  {
536  label belowID = myComm.below()[belowI];
537 
538  IPstream fromBelow(UPstream::scheduled, belowID, 0, tag, comm);
539  Container receivedValues(fromBelow);
540 
541  if (debug & 2)
542  {
543  Pout<< " received from "
544  << belowID << " data:" << receivedValues << endl;
545  }
546 
547  for
548  (
549  typename Container::const_iterator slaveIter =
550  receivedValues.begin();
551  slaveIter != receivedValues.end();
552  ++slaveIter
553  )
554  {
555  typename Container::iterator
556  masterIter = Values.find(slaveIter.key());
557 
558  if (masterIter != Values.end())
559  {
560  cop(masterIter(), slaveIter());
561  }
562  else
563  {
564  Values.insert(slaveIter.key(), slaveIter());
565  }
566  }
567  }
568 
569  // Send up Value
570  if (myComm.above() != -1)
571  {
572  if (debug & 2)
573  {
574  Pout<< " sending to " << myComm.above()
575  << " data:" << Values << endl;
576  }
577 
578  OPstream toAbove(UPstream::scheduled, myComm.above(), 0, tag, comm);
579  toAbove << Values;
580  }
581  }
582 }
583 
584 
585 template<class Container, class CombineOp>
587 (
588  Container& Values,
589  const CombineOp& cop,
590  const int tag,
591  const label comm
592 )
593 {
594  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
595  {
596  mapCombineGather
597  (
598  UPstream::linearCommunication(comm),
599  Values,
600  cop,
601  tag,
602  comm
603  );
604  }
605  else
606  {
607  mapCombineGather
608  (
609  UPstream::treeCommunication(comm),
610  Values,
611  cop,
612  tag,
613  comm
614  );
615  }
616 }
617 
618 
619 template<class Container>
621 (
622  const List<UPstream::commsStruct>& comms,
623  Container& Values,
624  const int tag,
625  const label comm
626 )
627 {
628  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
629  {
630  // Get my communication order
631  const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
632 
633  // Reveive from up
634  if (myComm.above() != -1)
635  {
636  IPstream fromAbove
637  (
638  UPstream::scheduled,
639  myComm.above(),
640  0,
641  tag,
642  comm
643  );
644  fromAbove >> Values;
645 
646  if (debug & 2)
647  {
648  Pout<< " received from "
649  << myComm.above() << " data:" << Values << endl;
650  }
651  }
652 
653  // Send to my downstairs neighbours
654  forAllReverse(myComm.below(), belowI)
655  {
656  label belowID = myComm.below()[belowI];
657 
658  if (debug & 2)
659  {
660  Pout<< " sending to " << belowID << " data:" << Values << endl;
661  }
662 
663  OPstream toBelow(UPstream::scheduled, belowID, 0, tag, comm);
664  toBelow << Values;
665  }
666  }
667 }
668 
669 
670 template<class Container>
672 (
673  Container& Values,
674  const int tag,
675  const label comm
676 )
677 {
678  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
679  {
680  mapCombineScatter
681  (
682  UPstream::linearCommunication(comm),
683  Values,
684  tag,
685  comm
686  );
687  }
688  else
689  {
690  mapCombineScatter
691  (
692  UPstream::treeCommunication(comm),
693  Values,
694  tag,
695  comm
696  );
697  }
698 }
699 
700 
701 // ************************************************************************* //
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
Template function to specify if the data of a type are contiguous.
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: UList.H:440
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
static void mapCombineScatter(const List< commsStruct > &comms, Container &Values, const int tag, const label comm)
Scatter data. Reverse of combineGather.
Input inter-processor communications stream.
Definition: IPstream.H:50
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
std::streamsize byteSize() const
Return the binary size in number of characters of the UList.
Definition: UList.C:100
bool read(const char *, int32_t &)
Definition: int32IO.C:85
static void combineGather(T &Value, const CombineOp &cop, const int tag=Pstream::msgType(), const label comm=Pstream::worldComm)
Like above but switches between linear/tree communication.
iterator begin()
Return an iterator to begin traversing the UList.
Definition: UListI.H:216
static void combineGather(const List< commsStruct > &comms, T &Value, const CombineOp &cop, const int tag, const label comm)
static void mapCombineGather(const List< commsStruct > &comms, Container &Values, const CombineOp &cop, const int tag, const label comm)
Structure for communicating between processors.
Definition: UPstream.H:76
prefixOSstream Pout(cout,"Pout")
Definition: IOstreams.H:53
Output inter-processor communications stream.
Definition: OPstream.H:50
const volScalarField & T
const labelList & below() const
Definition: UPstream.H:130
label above() const
Definition: UPstream.H:125
static void combineScatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
runTime write()