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-2013 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 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
42 
43 namespace Foam
44 {
45 
46 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
47 
48 template<class T, class CombineOp>
50 (
51  const List<UPstream::commsStruct>& comms,
52  T& Value,
53  const CombineOp& cop,
54  const int tag,
55  const label comm
56 )
57 {
58  if (UPstream::nProcs(comm) > 1)
59  {
60  // Get my communication order
61  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
62 
63  // Receive from my downstairs neighbours
64  forAll(myComm.below(), belowI)
65  {
66  label belowID = myComm.below()[belowI];
67 
68  if (contiguous<T>())
69  {
70  T value;
72  (
74  belowID,
75  reinterpret_cast<char*>(&value),
76  sizeof(T),
77  tag,
78  comm
79  );
80 
81  if (debug & 2)
82  {
83  Pout<< " received from "
84  << belowID << " data:" << value << endl;
85  }
86 
87  cop(Value, value);
88  }
89  else
90  {
91  IPstream fromBelow(UPstream::scheduled, belowID, 0, tag, comm);
92  T value(fromBelow);
93 
94  if (debug & 2)
95  {
96  Pout<< " received from "
97  << belowID << " data:" << value << endl;
98  }
99 
100  cop(Value, value);
101  }
102  }
103 
104  // Send up Value
105  if (myComm.above() != -1)
106  {
107  if (debug & 2)
108  {
109  Pout<< " sending to " << myComm.above()
110  << " data:" << Value << endl;
111  }
112 
113  if (contiguous<T>())
114  {
116  (
118  myComm.above(),
119  reinterpret_cast<const char*>(&Value),
120  sizeof(T),
121  tag,
122  comm
123  );
124  }
125  else
126  {
127  OPstream toAbove
128  (
130  myComm.above(),
131  0,
132  tag,
133  comm
134  );
135  toAbove << Value;
136  }
137  }
138  }
139 }
140 
141 
142 template <class T, class CombineOp>
144 (
145  T& Value,
146  const CombineOp& cop,
147  const int tag,
148  const label comm
149 )
150 {
152  {
153  combineGather
154  (
156  Value,
157  cop,
158  tag,
159  comm
160  );
161  }
162  else
163  {
164  combineGather
165  (
167  Value,
168  cop,
169  tag,
170  comm
171  );
172  }
173 }
174 
175 
176 template<class T>
178 (
179  const List<UPstream::commsStruct>& comms,
180  T& Value,
181  const int tag,
182  const label comm
183 )
184 {
185  if (UPstream::nProcs(comm) > 1)
186  {
187  // Get my communication order
188  const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
189 
190  // Reveive from up
191  if (myComm.above() != -1)
192  {
193  if (contiguous<T>())
194  {
196  (
198  myComm.above(),
199  reinterpret_cast<char*>(&Value),
200  sizeof(T),
201  tag,
202  comm
203  );
204  }
205  else
206  {
207  IPstream fromAbove
208  (
210  myComm.above(),
211  0,
212  tag,
213  comm
214  );
215  Value = T(fromAbove);
216  }
217 
218  if (debug & 2)
219  {
220  Pout<< " received from "
221  << myComm.above() << " data:" << Value << endl;
222  }
223  }
224 
225  // Send to my downstairs neighbours
226  forAll(myComm.below(), belowI)
227  {
228  label belowID = myComm.below()[belowI];
229 
230  if (debug & 2)
231  {
232  Pout<< " sending to " << belowID << " data:" << Value << endl;
233  }
234 
235  if (contiguous<T>())
236  {
238  (
240  belowID,
241  reinterpret_cast<const char*>(&Value),
242  sizeof(T),
243  tag,
244  comm
245  );
246  }
247  else
248  {
249  OPstream toBelow(UPstream::scheduled, belowID, 0, tag, comm);
250  toBelow << Value;
251  }
252  }
253  }
254 }
255 
256 
257 template <class T>
259 (
260  T& Value,
261  const int tag,
262  const label comm
263 )
264 {
266  {
267  combineScatter(UPstream::linearCommunication(comm), Value, tag, comm);
268  }
269  else
270  {
271  combineScatter(UPstream::treeCommunication(comm), Value, tag, comm);
272  }
273 }
274 
275 
276 // Same thing but for whole list at a time
277 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
278 
279 
280 template<class T, class CombineOp>
282 (
283  const List<UPstream::commsStruct>& comms,
284  List<T>& Values,
285  const CombineOp& cop,
286  const int tag,
287  const label comm
288 )
289 {
290  if (UPstream::nProcs(comm) > 1)
291  {
292  // Get my communication order
293  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
294 
295  // Receive from my downstairs neighbours
296  forAll(myComm.below(), belowI)
297  {
298  label belowID = myComm.below()[belowI];
299 
300  if (contiguous<T>())
301  {
302  List<T> receivedValues(Values.size());
303 
305  (
307  belowID,
308  reinterpret_cast<char*>(receivedValues.begin()),
309  receivedValues.byteSize(),
310  tag,
311  comm
312  );
313 
314  if (debug & 2)
315  {
316  Pout<< " received from "
317  << belowID << " data:" << receivedValues << endl;
318  }
319 
320  forAll(Values, i)
321  {
322  cop(Values[i], receivedValues[i]);
323  }
324  }
325  else
326  {
327  IPstream fromBelow(UPstream::scheduled, belowID, 0, tag, comm);
328  List<T> receivedValues(fromBelow);
329 
330  if (debug & 2)
331  {
332  Pout<< " received from "
333  << belowID << " data:" << receivedValues << endl;
334  }
335 
336  forAll(Values, i)
337  {
338  cop(Values[i], receivedValues[i]);
339  }
340  }
341  }
342 
343  // Send up Value
344  if (myComm.above() != -1)
345  {
346  if (debug & 2)
347  {
348  Pout<< " sending to " << myComm.above()
349  << " data:" << Values << endl;
350  }
351 
352  if (contiguous<T>())
353  {
355  (
357  myComm.above(),
358  reinterpret_cast<const char*>(Values.begin()),
359  Values.byteSize(),
360  tag,
361  comm
362  );
363  }
364  else
365  {
366  OPstream toAbove
367  (
369  myComm.above(),
370  0,
371  tag,
372  comm
373  );
374  toAbove << Values;
375  }
376  }
377  }
378 }
379 
380 
381 template<class T, class CombineOp>
383 (
384  List<T>& Values,
385  const CombineOp& cop,
386  const int tag,
387  const label comm
388 )
389 {
391  {
392  listCombineGather
393  (
395  Values,
396  cop,
397  tag,
398  comm
399  );
400  }
401  else
402  {
403  listCombineGather
404  (
406  Values,
407  cop,
408  tag,
409  comm
410  );
411  }
412 }
413 
414 
415 template<class T>
417 (
418  const List<UPstream::commsStruct>& comms,
419  List<T>& Values,
420  const int tag,
421  const label comm
422 )
423 {
424  if (UPstream::nProcs(comm) > 1)
425  {
426  // Get my communication order
427  const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
428 
429  // Reveive from up
430  if (myComm.above() != -1)
431  {
432  if (contiguous<T>())
433  {
435  (
437  myComm.above(),
438  reinterpret_cast<char*>(Values.begin()),
439  Values.byteSize(),
440  tag,
441  comm
442  );
443  }
444  else
445  {
446  IPstream fromAbove
447  (
449  myComm.above(),
450  0,
451  tag,
452  comm
453  );
454  fromAbove >> Values;
455  }
456 
457  if (debug & 2)
458  {
459  Pout<< " received from "
460  << myComm.above() << " data:" << Values << endl;
461  }
462  }
463 
464  // Send to my downstairs neighbours
465  forAll(myComm.below(), belowI)
466  {
467  label belowID = myComm.below()[belowI];
468 
469  if (debug & 2)
470  {
471  Pout<< " sending to " << belowID << " data:" << Values << endl;
472  }
473 
474  if (contiguous<T>())
475  {
477  (
479  belowID,
480  reinterpret_cast<const char*>(Values.begin()),
481  Values.byteSize(),
482  tag,
483  comm
484  );
485  }
486  else
487  {
488  OPstream toBelow(UPstream::scheduled, belowID, 0, tag, comm);
489  toBelow << Values;
490  }
491  }
492  }
493 }
494 
495 
496 template <class T>
498 (
499  List<T>& Values,
500  const int tag,
501  const label comm
502 )
503 {
505  {
506  listCombineScatter
507  (
509  Values,
510  tag,
511  comm
512  );
513  }
514  else
515  {
516  listCombineScatter
517  (
519  Values,
520  tag,
521  comm
522  );
523  }
524 }
525 
526 
527 
528 
529 // Same thing but for sparse list (map)
530 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
531 
532 
533 template<class Container, class CombineOp>
535 (
536  const List<UPstream::commsStruct>& comms,
537  Container& Values,
538  const CombineOp& cop,
539  const int tag,
540  const label comm
541 )
542 {
543  if (UPstream::nProcs(comm) > 1)
544  {
545  // Get my communication order
546  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
547 
548  // Receive from my downstairs neighbours
549  forAll(myComm.below(), belowI)
550  {
551  label belowID = myComm.below()[belowI];
552 
553  IPstream fromBelow(UPstream::scheduled, belowID, 0, tag, comm);
554  Container receivedValues(fromBelow);
555 
556  if (debug & 2)
557  {
558  Pout<< " received from "
559  << belowID << " data:" << receivedValues << endl;
560  }
561 
562  for
563  (
564  typename Container::const_iterator slaveIter =
565  receivedValues.begin();
566  slaveIter != receivedValues.end();
567  ++slaveIter
568  )
569  {
570  typename Container::iterator
571  masterIter = Values.find(slaveIter.key());
572 
573  if (masterIter != Values.end())
574  {
575  cop(masterIter(), slaveIter());
576  }
577  else
578  {
579  Values.insert(slaveIter.key(), slaveIter());
580  }
581  }
582  }
583 
584  // Send up Value
585  if (myComm.above() != -1)
586  {
587  if (debug & 2)
588  {
589  Pout<< " sending to " << myComm.above()
590  << " data:" << Values << endl;
591  }
592 
593  OPstream toAbove(UPstream::scheduled, myComm.above(), 0, tag, comm);
594  toAbove << Values;
595  }
596  }
597 }
598 
599 
600 template<class Container, class CombineOp>
602 (
603  Container& Values,
604  const CombineOp& cop,
605  const int tag,
606  const label comm
607 )
608 {
610  {
611  mapCombineGather
612  (
614  Values,
615  cop,
616  tag,
617  comm
618  );
619  }
620  else
621  {
622  mapCombineGather
623  (
625  Values,
626  cop,
627  tag,
628  comm
629  );
630  }
631 }
632 
633 
634 template<class Container>
636 (
637  const List<UPstream::commsStruct>& comms,
638  Container& Values,
639  const int tag,
640  const label comm
641 )
642 {
643  if (UPstream::nProcs(comm) > 1)
644  {
645  // Get my communication order
646  const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
647 
648  // Reveive from up
649  if (myComm.above() != -1)
650  {
651  IPstream fromAbove
652  (
654  myComm.above(),
655  0,
656  tag,
657  comm
658  );
659  fromAbove >> Values;
660 
661  if (debug & 2)
662  {
663  Pout<< " received from "
664  << myComm.above() << " data:" << Values << endl;
665  }
666  }
667 
668  // Send to my downstairs neighbours
669  forAll(myComm.below(), belowI)
670  {
671  label belowID = myComm.below()[belowI];
672 
673  if (debug & 2)
674  {
675  Pout<< " sending to " << belowID << " data:" << Values << endl;
676  }
677 
678  OPstream toBelow(UPstream::scheduled, belowID, 0, tag, comm);
679  toBelow << Values;
680  }
681  }
682 }
683 
684 
685 template <class Container>
687 (
688  Container& Values,
689  const int tag,
690  const label comm
691 )
692 {
694  {
695  mapCombineScatter
696  (
698  Values,
699  tag,
700  comm
701  );
702  }
703  else
704  {
705  mapCombineScatter
706  (
708  Values,
709  tag,
710  comm
711  );
712  }
713 }
714 
715 
716 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
717 
718 } // End namespace Foam
719 
720 // ************************************************************************* //
std::streamsize byteSize() const
Return the binary size in number of characters of the UList.
Definition: UList.C:92
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
static bool write(const commsTypes commsType, const int toProcNo, const char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label communicator=0)
Write given buffer to given processor.
Definition: UOPwrite.C:34
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
Structure for communicating between processors.
Definition: UPstream.H:76
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
Output inter-processor communications stream.
Definition: OPstream.H:50
static label read(const commsTypes commsType, const int fromProcNo, char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label communicator=0)
Read into given buffer from given processor and return the.
Definition: UIPread.C:100
Namespace for OpenFOAM.
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
iterator begin()
Return an iterator to begin traversing the UList.
Definition: UListI.H:216
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
static void mapCombineScatter(const List< commsStruct > &comms, Container &Values, const int tag, const label comm)
Scatter data. Reverse of combineGather.
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:386
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
static const List< commsStruct > & linearCommunication(const label communicator=0)
Communication schedule for linear all-to-master (proc 0)
Definition: UPstream.H:434
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
label above() const
Definition: UPstream.H:125
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)
Definition: UList.H:421
static void mapCombineGather(const List< commsStruct > &comms, Container &Values, const CombineOp &cop, const int tag, const label comm)
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:404
Template function to specify if the data of a type are contiguous.
const labelList & below() const
Definition: UPstream.H:130
Input inter-processor communications stream.
Definition: IPstream.H:50
static void combineScatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
static const List< commsStruct > & treeCommunication(const label communicator=0)
Communication schedule for tree all-to-master (proc 0)
Definition: UPstream.H:443
static void combineGather(const List< commsStruct > &comms, T &Value, const CombineOp &cop, const int tag, const label comm)
prefixOSstream Pout(cout,"Pout")
Definition: IOstreams.H:53
static int nProcsSimpleSum
Number of processors at which the sum algorithm changes from linear.
Definition: UPstream.H:252