combineGatherScatter.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2018 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::commsTypes::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
87  (
88  UPstream::commsTypes::scheduled,
89  belowID,
90  0,
91  tag,
92  comm
93  );
94  T value(fromBelow);
95 
96  if (debug & 2)
97  {
98  Pout<< " received from "
99  << belowID << " data:" << value << endl;
100  }
101 
102  cop(Value, value);
103  }
104  }
105 
106  // Send up Value
107  if (myComm.above() != -1)
108  {
109  if (debug & 2)
110  {
111  Pout<< " sending to " << myComm.above()
112  << " data:" << Value << endl;
113  }
114 
115  if (contiguous<T>())
116  {
118  (
119  UPstream::commsTypes::scheduled,
120  myComm.above(),
121  reinterpret_cast<const char*>(&Value),
122  sizeof(T),
123  tag,
124  comm
125  );
126  }
127  else
128  {
129  OPstream toAbove
130  (
131  UPstream::commsTypes::scheduled,
132  myComm.above(),
133  0,
134  tag,
135  comm
136  );
137  toAbove << Value;
138  }
139  }
140  }
141 }
142 
143 
144 template<class T, class CombineOp>
146 (
147  T& Value,
148  const CombineOp& cop,
149  const int tag,
150  const label comm
151 )
152 {
153  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
154  {
155  combineGather
156  (
157  UPstream::linearCommunication(comm),
158  Value,
159  cop,
160  tag,
161  comm
162  );
163  }
164  else
165  {
166  combineGather
167  (
168  UPstream::treeCommunication(comm),
169  Value,
170  cop,
171  tag,
172  comm
173  );
174  }
175 }
176 
177 
178 template<class T>
180 (
181  const List<UPstream::commsStruct>& comms,
182  T& Value,
183  const int tag,
184  const label comm
185 )
186 {
187  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
188  {
189  // Get my communication order
190  const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
191 
192  // Receive from up
193  if (myComm.above() != -1)
194  {
195  if (contiguous<T>())
196  {
198  (
199  UPstream::commsTypes::scheduled,
200  myComm.above(),
201  reinterpret_cast<char*>(&Value),
202  sizeof(T),
203  tag,
204  comm
205  );
206  }
207  else
208  {
209  IPstream fromAbove
210  (
211  UPstream::commsTypes::scheduled,
212  myComm.above(),
213  0,
214  tag,
215  comm
216  );
217  Value = T(fromAbove);
218  }
219 
220  if (debug & 2)
221  {
222  Pout<< " received from "
223  << myComm.above() << " data:" << Value << endl;
224  }
225  }
226 
227  // Send to my downstairs neighbours
228  forAllReverse(myComm.below(), belowI)
229  {
230  label belowID = myComm.below()[belowI];
231 
232  if (debug & 2)
233  {
234  Pout<< " sending to " << belowID << " data:" << Value << endl;
235  }
236 
237  if (contiguous<T>())
238  {
240  (
241  UPstream::commsTypes::scheduled,
242  belowID,
243  reinterpret_cast<const char*>(&Value),
244  sizeof(T),
245  tag,
246  comm
247  );
248  }
249  else
250  {
251  OPstream toBelow
252  (
253  UPstream::commsTypes::scheduled,
254  belowID,
255  0,
256  tag,
257  comm
258  );
259  toBelow << Value;
260  }
261  }
262  }
263 }
264 
265 
266 template<class T>
268 (
269  T& Value,
270  const int tag,
271  const label comm
272 )
273 {
274  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
275  {
276  combineScatter(UPstream::linearCommunication(comm), Value, tag, comm);
277  }
278  else
279  {
280  combineScatter(UPstream::treeCommunication(comm), Value, tag, comm);
281  }
282 }
283 
284 
285 template<class T, class CombineOp>
287 (
288  const List<UPstream::commsStruct>& comms,
289  List<T>& Values,
290  const CombineOp& cop,
291  const int tag,
292  const label comm
293 )
294 {
295  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
296  {
297  // Get my communication order
298  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
299 
300  // Receive from my downstairs neighbours
301  forAll(myComm.below(), belowI)
302  {
303  label belowID = myComm.below()[belowI];
304 
305  if (contiguous<T>())
306  {
307  List<T> receivedValues(Values.size());
308 
310  (
311  UPstream::commsTypes::scheduled,
312  belowID,
313  reinterpret_cast<char*>(receivedValues.begin()),
314  receivedValues.byteSize(),
315  tag,
316  comm
317  );
318 
319  if (debug & 2)
320  {
321  Pout<< " received from "
322  << belowID << " data:" << receivedValues << endl;
323  }
324 
325  forAll(Values, i)
326  {
327  cop(Values[i], receivedValues[i]);
328  }
329  }
330  else
331  {
332  IPstream fromBelow
333  (
334  UPstream::commsTypes::scheduled,
335  belowID,
336  0,
337  tag,
338  comm
339  );
340  List<T> receivedValues(fromBelow);
341 
342  if (debug & 2)
343  {
344  Pout<< " received from "
345  << belowID << " data:" << receivedValues << endl;
346  }
347 
348  forAll(Values, i)
349  {
350  cop(Values[i], receivedValues[i]);
351  }
352  }
353  }
354 
355  // Send up Value
356  if (myComm.above() != -1)
357  {
358  if (debug & 2)
359  {
360  Pout<< " sending to " << myComm.above()
361  << " data:" << Values << endl;
362  }
363 
364  if (contiguous<T>())
365  {
367  (
368  UPstream::commsTypes::scheduled,
369  myComm.above(),
370  reinterpret_cast<const char*>(Values.begin()),
371  Values.byteSize(),
372  tag,
373  comm
374  );
375  }
376  else
377  {
378  OPstream toAbove
379  (
380  UPstream::commsTypes::scheduled,
381  myComm.above(),
382  0,
383  tag,
384  comm
385  );
386  toAbove << Values;
387  }
388  }
389  }
390 }
391 
392 
393 template<class T, class CombineOp>
395 (
396  List<T>& Values,
397  const CombineOp& cop,
398  const int tag,
399  const label comm
400 )
401 {
402  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
403  {
404  listCombineGather
405  (
406  UPstream::linearCommunication(comm),
407  Values,
408  cop,
409  tag,
410  comm
411  );
412  }
413  else
414  {
415  listCombineGather
416  (
417  UPstream::treeCommunication(comm),
418  Values,
419  cop,
420  tag,
421  comm
422  );
423  }
424 }
425 
426 
427 template<class T>
429 (
430  const List<UPstream::commsStruct>& comms,
431  List<T>& Values,
432  const int tag,
433  const label comm
434 )
435 {
436  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
437  {
438  // Get my communication order
439  const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
440 
441  // Receive from up
442  if (myComm.above() != -1)
443  {
444  if (contiguous<T>())
445  {
447  (
448  UPstream::commsTypes::scheduled,
449  myComm.above(),
450  reinterpret_cast<char*>(Values.begin()),
451  Values.byteSize(),
452  tag,
453  comm
454  );
455  }
456  else
457  {
458  IPstream fromAbove
459  (
460  UPstream::commsTypes::scheduled,
461  myComm.above(),
462  0,
463  tag,
464  comm
465  );
466  fromAbove >> Values;
467  }
468 
469  if (debug & 2)
470  {
471  Pout<< " received from "
472  << myComm.above() << " data:" << Values << endl;
473  }
474  }
475 
476  // Send to my downstairs neighbours
477  forAllReverse(myComm.below(), belowI)
478  {
479  label belowID = myComm.below()[belowI];
480 
481  if (debug & 2)
482  {
483  Pout<< " sending to " << belowID << " data:" << Values << endl;
484  }
485 
486  if (contiguous<T>())
487  {
489  (
490  UPstream::commsTypes::scheduled,
491  belowID,
492  reinterpret_cast<const char*>(Values.begin()),
493  Values.byteSize(),
494  tag,
495  comm
496  );
497  }
498  else
499  {
500  OPstream toBelow
501  (
502  UPstream::commsTypes::scheduled,
503  belowID,
504  0,
505  tag,
506  comm
507  );
508  toBelow << Values;
509  }
510  }
511  }
512 }
513 
514 
515 template<class T>
517 (
518  List<T>& Values,
519  const int tag,
520  const label comm
521 )
522 {
523  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
524  {
525  listCombineScatter
526  (
527  UPstream::linearCommunication(comm),
528  Values,
529  tag,
530  comm
531  );
532  }
533  else
534  {
535  listCombineScatter
536  (
537  UPstream::treeCommunication(comm),
538  Values,
539  tag,
540  comm
541  );
542  }
543 }
544 
545 
546 template<class Container, class CombineOp>
548 (
549  const List<UPstream::commsStruct>& comms,
550  Container& Values,
551  const CombineOp& cop,
552  const int tag,
553  const label comm
554 )
555 {
556  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
557  {
558  // Get my communication order
559  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
560 
561  // Receive from my downstairs neighbours
562  forAll(myComm.below(), belowI)
563  {
564  label belowID = myComm.below()[belowI];
565 
566  IPstream fromBelow
567  (
568  UPstream::commsTypes::scheduled,
569  belowID,
570  0,
571  tag,
572  comm
573  );
574  Container receivedValues(fromBelow);
575 
576  if (debug & 2)
577  {
578  Pout<< " received from "
579  << belowID << " data:" << receivedValues << endl;
580  }
581 
582  for
583  (
584  typename Container::const_iterator slaveIter =
585  receivedValues.begin();
586  slaveIter != receivedValues.end();
587  ++slaveIter
588  )
589  {
590  typename Container::iterator
591  masterIter = Values.find(slaveIter.key());
592 
593  if (masterIter != Values.end())
594  {
595  cop(masterIter(), slaveIter());
596  }
597  else
598  {
599  Values.insert(slaveIter.key(), slaveIter());
600  }
601  }
602  }
603 
604  // Send up Value
605  if (myComm.above() != -1)
606  {
607  if (debug & 2)
608  {
609  Pout<< " sending to " << myComm.above()
610  << " data:" << Values << endl;
611  }
612 
613  OPstream toAbove
614  (
615  UPstream::commsTypes::scheduled,
616  myComm.above(),
617  0,
618  tag,
619  comm
620  );
621  toAbove << Values;
622  }
623  }
624 }
625 
626 
627 template<class Container, class CombineOp>
629 (
630  Container& Values,
631  const CombineOp& cop,
632  const int tag,
633  const label comm
634 )
635 {
636  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
637  {
638  mapCombineGather
639  (
640  UPstream::linearCommunication(comm),
641  Values,
642  cop,
643  tag,
644  comm
645  );
646  }
647  else
648  {
649  mapCombineGather
650  (
651  UPstream::treeCommunication(comm),
652  Values,
653  cop,
654  tag,
655  comm
656  );
657  }
658 }
659 
660 
661 template<class Container>
663 (
664  const List<UPstream::commsStruct>& comms,
665  Container& Values,
666  const int tag,
667  const label comm
668 )
669 {
670  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
671  {
672  // Get my communication order
673  const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
674 
675  // Receive from up
676  if (myComm.above() != -1)
677  {
678  IPstream fromAbove
679  (
680  UPstream::commsTypes::scheduled,
681  myComm.above(),
682  0,
683  tag,
684  comm
685  );
686  fromAbove >> Values;
687 
688  if (debug & 2)
689  {
690  Pout<< " received from "
691  << myComm.above() << " data:" << Values << endl;
692  }
693  }
694 
695  // Send to my downstairs neighbours
696  forAllReverse(myComm.below(), belowI)
697  {
698  label belowID = myComm.below()[belowI];
699 
700  if (debug & 2)
701  {
702  Pout<< " sending to " << belowID << " data:" << Values << endl;
703  }
704 
705  OPstream toBelow
706  (
707  UPstream::commsTypes::scheduled,
708  belowID,
709  0,
710  tag,
711  comm
712  );
713  toBelow << Values;
714  }
715  }
716 }
717 
718 
719 template<class Container>
721 (
722  Container& Values,
723  const int tag,
724  const label comm
725 )
726 {
727  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
728  {
729  mapCombineScatter
730  (
731  UPstream::linearCommunication(comm),
732  Values,
733  tag,
734  comm
735  );
736  }
737  else
738  {
739  mapCombineScatter
740  (
741  UPstream::treeCommunication(comm),
742  Values,
743  tag,
744  comm
745  );
746  }
747 }
748 
749 
750 // ************************************************************************* //
const labelList & below() const
Definition: UPstream.H:130
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:434
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:164
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
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:446
void read(Istream &, label &, const dictionary &)
In-place read with dictionary lookup.
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...
iterator begin()
Return an iterator to begin traversing the UList.
Definition: UListI.H:216
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
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
Output inter-processor communications stream.
Definition: OPstream.H:50
const volScalarField & T
std::streamsize byteSize() const
Return the binary size in number of characters of the UList.
Definition: UList.C:100
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
static void combineScatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.