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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2019-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Description
28  Variant of gather, scatter.
29  Normal gather uses:
30  - construct null and read (>>) from Istream
31  - binary operator and assignment operator to combine values
32 
33  combineGather uses:
34  - construct from Istream
35  - modify operator which modifies its lhs
36 
37 \*---------------------------------------------------------------------------*/
38 
39 #include "OPstream.H"
40 #include "IPstream.H"
41 #include "IOstreams.H"
42 #include "contiguous.H"
43 
44 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
45 
46 template<class T, class CombineOp>
48 (
49  const List<UPstream::commsStruct>& comms,
50  T& Value,
51  const CombineOp& cop,
52  const int tag,
53  const label comm
54 )
55 {
56  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
57  {
58  // Get my communication order
59  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
60 
61  // Receive from my downstairs neighbours
62  forAll(myComm.below(), belowI)
63  {
64  label belowID = myComm.below()[belowI];
65 
67  {
68  T value;
70  (
71  UPstream::commsTypes::scheduled,
72  belowID,
73  reinterpret_cast<char*>(&value),
74  sizeof(T),
75  tag,
76  comm
77  );
78 
79  if (debug & 2)
80  {
81  Pout<< " received from "
82  << belowID << " data:" << value << endl;
83  }
84 
85  cop(Value, value);
86  }
87  else
88  {
89  IPstream fromBelow
90  (
91  UPstream::commsTypes::scheduled,
92  belowID,
93  0,
94  tag,
95  comm
96  );
97  T value(fromBelow);
98 
99  if (debug & 2)
100  {
101  Pout<< " received from "
102  << belowID << " data:" << value << endl;
103  }
104 
105  cop(Value, value);
106  }
107  }
108 
109  // Send up Value
110  if (myComm.above() != -1)
111  {
112  if (debug & 2)
113  {
114  Pout<< " sending to " << myComm.above()
115  << " data:" << Value << endl;
116  }
117 
119  {
121  (
122  UPstream::commsTypes::scheduled,
123  myComm.above(),
124  reinterpret_cast<const char*>(&Value),
125  sizeof(T),
126  tag,
127  comm
128  );
129  }
130  else
131  {
132  OPstream toAbove
133  (
134  UPstream::commsTypes::scheduled,
135  myComm.above(),
136  0,
137  tag,
138  comm
139  );
140  toAbove << Value;
141  }
142  }
143  }
144 }
145 
146 
147 template<class T, class CombineOp>
149 (
150  T& Value,
151  const CombineOp& cop,
152  const int tag,
153  const label comm
154 )
155 {
156  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
157  {
158  combineGather
159  (
160  UPstream::linearCommunication(comm),
161  Value,
162  cop,
163  tag,
164  comm
165  );
166  }
167  else
168  {
169  combineGather
170  (
171  UPstream::treeCommunication(comm),
172  Value,
173  cop,
174  tag,
175  comm
176  );
177  }
178 }
179 
180 
181 template<class T>
183 (
184  const List<UPstream::commsStruct>& comms,
185  T& Value,
186  const int tag,
187  const label comm
188 )
189 {
190  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
191  {
192  // Get my communication order
193  const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
194 
195  // Receive from up
196  if (myComm.above() != -1)
197  {
199  {
201  (
202  UPstream::commsTypes::scheduled,
203  myComm.above(),
204  reinterpret_cast<char*>(&Value),
205  sizeof(T),
206  tag,
207  comm
208  );
209  }
210  else
211  {
212  IPstream fromAbove
213  (
214  UPstream::commsTypes::scheduled,
215  myComm.above(),
216  0,
217  tag,
218  comm
219  );
220  Value = T(fromAbove);
221  }
222 
223  if (debug & 2)
224  {
225  Pout<< " received from "
226  << myComm.above() << " data:" << Value << endl;
227  }
228  }
229 
230  // Send to my downstairs neighbours
231  forAllReverse(myComm.below(), belowI)
232  {
233  label belowID = myComm.below()[belowI];
234 
235  if (debug & 2)
236  {
237  Pout<< " sending to " << belowID << " data:" << Value << endl;
238  }
239 
241  {
243  (
244  UPstream::commsTypes::scheduled,
245  belowID,
246  reinterpret_cast<const char*>(&Value),
247  sizeof(T),
248  tag,
249  comm
250  );
251  }
252  else
253  {
254  OPstream toBelow
255  (
256  UPstream::commsTypes::scheduled,
257  belowID,
258  0,
259  tag,
260  comm
261  );
262  toBelow << Value;
263  }
264  }
265  }
266 }
267 
268 
269 template<class T>
271 (
272  T& Value,
273  const int tag,
274  const label comm
275 )
276 {
277  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
278  {
279  combineScatter(UPstream::linearCommunication(comm), Value, tag, comm);
280  }
281  else
282  {
283  combineScatter(UPstream::treeCommunication(comm), Value, tag, comm);
284  }
285 }
286 
287 
288 template<class T, class CombineOp>
290 (
291  const List<UPstream::commsStruct>& comms,
292  List<T>& Values,
293  const CombineOp& cop,
294  const int tag,
295  const label comm
296 )
297 {
298  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
299  {
300  // Get my communication order
301  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
302 
303  // Receive from my downstairs neighbours
304  forAll(myComm.below(), belowI)
305  {
306  label belowID = myComm.below()[belowI];
307 
309  {
310  List<T> receivedValues(Values.size());
311 
313  (
314  UPstream::commsTypes::scheduled,
315  belowID,
316  receivedValues.data_bytes(),
317  receivedValues.size_bytes(),
318  tag,
319  comm
320  );
321 
322  if (debug & 2)
323  {
324  Pout<< " received from "
325  << belowID << " data:" << receivedValues << endl;
326  }
327 
328  forAll(Values, i)
329  {
330  cop(Values[i], receivedValues[i]);
331  }
332  }
333  else
334  {
335  IPstream fromBelow
336  (
337  UPstream::commsTypes::scheduled,
338  belowID,
339  0,
340  tag,
341  comm
342  );
343  List<T> receivedValues(fromBelow);
344 
345  if (debug & 2)
346  {
347  Pout<< " received from "
348  << belowID << " data:" << receivedValues << endl;
349  }
350 
351  forAll(Values, i)
352  {
353  cop(Values[i], receivedValues[i]);
354  }
355  }
356  }
357 
358  // Send up Value
359  if (myComm.above() != -1)
360  {
361  if (debug & 2)
362  {
363  Pout<< " sending to " << myComm.above()
364  << " data:" << Values << endl;
365  }
366 
368  {
370  (
371  UPstream::commsTypes::scheduled,
372  myComm.above(),
373  Values.cdata_bytes(),
374  Values.size_bytes(),
375  tag,
376  comm
377  );
378  }
379  else
380  {
381  OPstream toAbove
382  (
383  UPstream::commsTypes::scheduled,
384  myComm.above(),
385  0,
386  tag,
387  comm
388  );
389  toAbove << Values;
390  }
391  }
392  }
393 }
394 
395 
396 template<class T, class CombineOp>
398 (
399  List<T>& Values,
400  const CombineOp& cop,
401  const int tag,
402  const label comm
403 )
404 {
405  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
406  {
407  listCombineGather
408  (
409  UPstream::linearCommunication(comm),
410  Values,
411  cop,
412  tag,
413  comm
414  );
415  }
416  else
417  {
418  listCombineGather
419  (
420  UPstream::treeCommunication(comm),
421  Values,
422  cop,
423  tag,
424  comm
425  );
426  }
427 }
428 
429 
430 template<class T>
432 (
433  const List<UPstream::commsStruct>& comms,
434  List<T>& Values,
435  const int tag,
436  const label comm
437 )
438 {
439  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
440  {
441  // Get my communication order
442  const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
443 
444  // Receive from up
445  if (myComm.above() != -1)
446  {
448  {
450  (
451  UPstream::commsTypes::scheduled,
452  myComm.above(),
453  Values.data_bytes(),
454  Values.size_bytes(),
455  tag,
456  comm
457  );
458  }
459  else
460  {
461  IPstream fromAbove
462  (
463  UPstream::commsTypes::scheduled,
464  myComm.above(),
465  0,
466  tag,
467  comm
468  );
469  fromAbove >> Values;
470  }
471 
472  if (debug & 2)
473  {
474  Pout<< " received from "
475  << myComm.above() << " data:" << Values << endl;
476  }
477  }
478 
479  // Send to my downstairs neighbours
480  forAllReverse(myComm.below(), belowI)
481  {
482  label belowID = myComm.below()[belowI];
483 
484  if (debug & 2)
485  {
486  Pout<< " sending to " << belowID << " data:" << Values << endl;
487  }
488 
490  {
492  (
493  UPstream::commsTypes::scheduled,
494  belowID,
495  Values.cdata_bytes(),
496  Values.size_bytes(),
497  tag,
498  comm
499  );
500  }
501  else
502  {
503  OPstream toBelow
504  (
505  UPstream::commsTypes::scheduled,
506  belowID,
507  0,
508  tag,
509  comm
510  );
511  toBelow << Values;
512  }
513  }
514  }
515 }
516 
517 
518 template<class T>
520 (
521  List<T>& Values,
522  const int tag,
523  const label comm
524 )
525 {
526  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
527  {
528  listCombineScatter
529  (
530  UPstream::linearCommunication(comm),
531  Values,
532  tag,
533  comm
534  );
535  }
536  else
537  {
538  listCombineScatter
539  (
540  UPstream::treeCommunication(comm),
541  Values,
542  tag,
543  comm
544  );
545  }
546 }
547 
548 
549 template<class Container, class CombineOp>
551 (
552  const List<UPstream::commsStruct>& comms,
553  Container& Values,
554  const CombineOp& cop,
555  const int tag,
556  const label comm
557 )
558 {
559  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
560  {
561  // Get my communication order
562  const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
563 
564  // Receive from my downstairs neighbours
565  forAll(myComm.below(), belowI)
566  {
567  label belowID = myComm.below()[belowI];
568 
569  IPstream fromBelow
570  (
571  UPstream::commsTypes::scheduled,
572  belowID,
573  0,
574  tag,
575  comm
576  );
577  Container receivedValues(fromBelow);
578 
579  if (debug & 2)
580  {
581  Pout<< " received from "
582  << belowID << " data:" << receivedValues << endl;
583  }
584 
585  for
586  (
587  typename Container::const_iterator slaveIter =
588  receivedValues.begin();
589  slaveIter != receivedValues.end();
590  ++slaveIter
591  )
592  {
593  typename Container::iterator
594  masterIter = Values.find(slaveIter.key());
595 
596  if (masterIter != Values.end())
597  {
598  cop(masterIter(), slaveIter());
599  }
600  else
601  {
602  Values.insert(slaveIter.key(), slaveIter());
603  }
604  }
605  }
606 
607  // Send up Value
608  if (myComm.above() != -1)
609  {
610  if (debug & 2)
611  {
612  Pout<< " sending to " << myComm.above()
613  << " data:" << Values << endl;
614  }
615 
616  OPstream toAbove
617  (
618  UPstream::commsTypes::scheduled,
619  myComm.above(),
620  0,
621  tag,
622  comm
623  );
624  toAbove << Values;
625  }
626  }
627 }
628 
629 
630 template<class Container, class CombineOp>
632 (
633  Container& Values,
634  const CombineOp& cop,
635  const int tag,
636  const label comm
637 )
638 {
639  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
640  {
641  mapCombineGather
642  (
643  UPstream::linearCommunication(comm),
644  Values,
645  cop,
646  tag,
647  comm
648  );
649  }
650  else
651  {
652  mapCombineGather
653  (
654  UPstream::treeCommunication(comm),
655  Values,
656  cop,
657  tag,
658  comm
659  );
660  }
661 }
662 
663 
664 template<class Container>
666 (
667  const List<UPstream::commsStruct>& comms,
668  Container& Values,
669  const int tag,
670  const label comm
671 )
672 {
673  if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
674  {
675  // Get my communication order
676  const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
677 
678  // Receive from up
679  if (myComm.above() != -1)
680  {
681  IPstream fromAbove
682  (
683  UPstream::commsTypes::scheduled,
684  myComm.above(),
685  0,
686  tag,
687  comm
688  );
689  fromAbove >> Values;
690 
691  if (debug & 2)
692  {
693  Pout<< " received from "
694  << myComm.above() << " data:" << Values << endl;
695  }
696  }
697 
698  // Send to my downstairs neighbours
699  forAllReverse(myComm.below(), belowI)
700  {
701  label belowID = myComm.below()[belowI];
702 
703  if (debug & 2)
704  {
705  Pout<< " sending to " << belowID << " data:" << Values << endl;
706  }
707 
708  OPstream toBelow
709  (
710  UPstream::commsTypes::scheduled,
711  belowID,
712  0,
713  tag,
714  comm
715  );
716  toBelow << Values;
717  }
718  }
719 }
720 
721 
722 template<class Container>
724 (
725  Container& Values,
726  const int tag,
727  const label comm
728 )
729 {
730  if (UPstream::nProcs(comm) < UPstream::nProcsSimpleSum)
731  {
732  mapCombineScatter
733  (
734  UPstream::linearCommunication(comm),
735  Values,
736  tag,
737  comm
738  );
739  }
740  else
741  {
742  mapCombineScatter
743  (
744  UPstream::treeCommunication(comm),
745  Values,
746  tag,
747  comm
748  );
749  }
750 }
751 
752 
753 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::Pstream::mapCombineGather
static void mapCombineGather(const List< commsStruct > &comms, Container &Values, const CombineOp &cop, const int tag, const label comm)
Definition: combineGatherScatter.C:551
IOstreams.H
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
Foam::OPstream
Output inter-processor communications stream.
Definition: OPstream.H:53
OPstream.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Foam::UPstream::commsStruct::below
const labelList & below() const noexcept
Definition: UPstream.H:135
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::blockMeshTools::read
void read(Istream &, label &val, const dictionary &)
In-place read with dictionary lookup.
Definition: blockMeshTools.C:57
IPstream.H
T
const volScalarField & T
Definition: createFieldRefs.H:2
Foam::Pstream::combineGather
static void combineGather(const List< commsStruct > &comms, T &Value, const CombineOp &cop, const int tag, const label comm)
Definition: combineGatherScatter.C:48
Foam::UPstream::commsStruct
Structure for communicating between processors.
Definition: UPstream.H:83
Foam::Pstream::listCombineGather
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
Definition: combineGatherScatter.C:290
Foam::Pstream::mapCombineScatter
static void mapCombineScatter(const List< commsStruct > &comms, Container &Values, const int tag, const label comm)
Scatter data. Reverse of combineGather.
Definition: combineGatherScatter.C:666
contiguous.H
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:63
Foam::vtk::write
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
Definition: foamVtkOutputTemplates.C:36
Foam::UPstream::commsStruct::above
label above() const noexcept
Definition: UPstream.H:130
forAllReverse
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:309
Foam::IPstream
Input inter-processor communications stream.
Definition: IPstream.H:53
Foam::Pstream::listCombineScatter
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
Definition: combineGatherScatter.C:432
Foam::Pstream::combineScatter
static void combineScatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
Definition: combineGatherScatter.C:183
Foam::is_contiguous
A template class to specify that a data type can be considered as being contiguous in memory.
Definition: contiguous.H:75