mapDistributeBaseTemplates.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) 2015-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2022 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 \*---------------------------------------------------------------------------*/
28 
29 #include "Pstream.H"
30 #include "PstreamBuffers.H"
31 #include "flipOp.H"
32 
33 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34 
35 template<class T, class CombineOp, class NegateOp>
37 (
38  const labelUList& map,
39  const bool hasFlip,
40  const UList<T>& rhs,
41  const CombineOp& cop,
42  const NegateOp& negOp,
43  List<T>& lhs
44 )
45 {
46  if (hasFlip)
47  {
48  forAll(map, i)
49  {
50  if (map[i] > 0)
51  {
52  label index = map[i]-1;
53  cop(lhs[index], rhs[i]);
54  }
55  else if (map[i] < 0)
56  {
57  label index = -map[i]-1;
58  cop(lhs[index], negOp(rhs[i]));
59  }
60  else
61  {
63  << "At index " << i << " out of " << map.size()
64  << " have illegal index " << map[i]
65  << " for field " << rhs.size() << " with flipMap"
66  << exit(FatalError);
67  }
68  }
69  }
70  else
71  {
72  forAll(map, i)
73  {
74  cop(lhs[map[i]], rhs[i]);
75  }
76  }
77 }
78 
79 
80 template<class T, class NegateOp>
82 (
83  const UList<T>& values,
84  const label index,
85  const bool hasFlip,
86  const NegateOp& negOp
87 )
88 {
89  if (hasFlip)
90  {
91  if (index > 0)
92  {
93  return values[index-1];
94  }
95  else if (index < 0)
96  {
97  return negOp(values[-index-1]);
98  }
99  else
100  {
102  << "Illegal index " << index
103  << " into field of size " << values.size()
104  << " with face-flipping"
105  << exit(FatalError);
106  }
107  }
109  return values[index];
110 }
111 
112 
113 template<class T, class NegateOp>
115 (
116  const UList<T>& values,
117  const labelUList& indices,
118  const bool hasFlip,
119  const NegateOp& negOp
120 )
121 {
122  const label len = indices.size();
123 
124  List<T> output(len);
125 
126  if (hasFlip)
127  {
128  for (label i = 0; i < len; ++i)
129  {
130  const label index = indices[i];
131 
132  if (index > 0)
133  {
134  output[i] = values[index-1];
135  }
136  else if (index < 0)
137  {
138  output[i] = negOp(values[-index-1]);
139  }
140  else
141  {
143  << "Illegal index " << index
144  << " into field of size " << values.size()
145  << " with flipping"
146  << exit(FatalError);
147  }
148  }
149  }
150  else
151  {
152  // Like indirect list
153  for (label i = 0; i < len; ++i)
154  {
155  output[i] = values[indices[i]];
156  }
157  }
159  return output;
160 }
161 
162 
163 template<class T, class NegateOp>
165 (
166  const Pstream::commsTypes commsType,
167  const List<labelPair>& schedule,
168  const label constructSize,
169  const labelListList& subMap,
170  const bool subHasFlip,
171  const labelListList& constructMap,
172  const bool constructHasFlip,
173  List<T>& field,
174  const NegateOp& negOp,
175  const int tag,
176  const label comm
177 )
178 {
179  const label myRank = Pstream::myProcNo(comm);
180  const label nProcs = Pstream::nProcs(comm);
181 
182  if (!Pstream::parRun())
183  {
184  // Do only me to me.
185 
186  List<T> subField
187  (
188  accessAndFlip(field, subMap[myRank], subHasFlip, negOp)
189  );
190 
191  // Receive sub field from myself (subField)
192  const labelList& map = constructMap[myRank];
193 
194  field.setSize(constructSize);
195 
196  flipAndCombine
197  (
198  map,
199  constructHasFlip,
200  subField,
201  eqOp<T>(),
202  negOp,
203  field
204  );
205 
206  return;
207  }
208 
209  if (commsType == Pstream::commsTypes::blocking)
210  {
211  // Since buffered sending can reuse the field to collect the
212  // received data.
213 
214  // Send sub field to neighbour
215  for (const int domain : Pstream::allProcs(comm))
216  {
217  const labelList& map = subMap[domain];
218 
219  if (domain != myRank && map.size())
220  {
221  OPstream toNbr
222  (
224  domain,
225  0,
226  tag,
227  comm
228  );
229 
230  List<T> subField
231  (
232  accessAndFlip(field, map, subHasFlip, negOp)
233  );
234 
235  toNbr << subField;
236  }
237  }
238 
239  {
240  // Subset myself
241  List<T> subField
242  (
243  accessAndFlip(field, subMap[myRank], subHasFlip, negOp)
244  );
245 
246  // Receive sub field from myself (subField)
247  const labelList& map = constructMap[myRank];
248 
249  field.setSize(constructSize);
250 
251  flipAndCombine
252  (
253  map,
254  constructHasFlip,
255  subField,
256  eqOp<T>(),
257  negOp,
258  field
259  );
260  }
261 
262  // Receive sub field from neighbour
263  for (const int domain : Pstream::allProcs(comm))
264  {
265  const labelList& map = constructMap[domain];
266 
267  if (domain != myRank && map.size())
268  {
269  IPstream fromNbr
270  (
272  domain,
273  0,
274  tag,
275  comm
276  );
277  List<T> subField(fromNbr);
278 
279  checkReceivedSize(domain, map.size(), subField.size());
280 
281  flipAndCombine
282  (
283  map,
284  constructHasFlip,
285  subField,
286  eqOp<T>(),
287  negOp,
288  field
289  );
290  }
291  }
292  }
293  else if (commsType == Pstream::commsTypes::scheduled)
294  {
295  // Need to make sure I don't overwrite field with received data
296  // since the data might need to be sent to another processor. So
297  // allocate a new field for the results.
298  List<T> newField(constructSize);
299 
300  // Receive sub field from myself
301  {
302  List<T> subField
303  (
304  accessAndFlip(field, subMap[myRank], subHasFlip, negOp)
305  );
306 
307  // Receive sub field from myself (subField)
308  const labelList& map = constructMap[myRank];
309 
310  flipAndCombine
311  (
312  map,
313  constructHasFlip,
314  subField,
315  eqOp<T>(),
316  negOp,
317  newField
318  );
319  }
320 
321  // Schedule will already have pruned 0-sized comms
322  for (const labelPair& twoProcs : schedule)
323  {
324  // twoProcs is a swap pair of processors. The first one is the
325  // one that needs to send first and then receive.
326 
327  const label sendProc = twoProcs[0];
328  const label recvProc = twoProcs[1];
329 
330  if (myRank == sendProc)
331  {
332  // I am send first, receive next
333  {
334  OPstream toNbr
335  (
337  recvProc,
338  0,
339  tag,
340  comm
341  );
342 
343  const labelList& map = subMap[recvProc];
344  List<T> subField
345  (
346  accessAndFlip(field, map, subHasFlip, negOp)
347  );
348 
349  toNbr << subField;
350  }
351  {
352  IPstream fromNbr
353  (
355  recvProc,
356  0,
357  tag,
358  comm
359  );
360  List<T> subField(fromNbr);
361 
362  const labelList& map = constructMap[recvProc];
363 
364  checkReceivedSize(recvProc, map.size(), subField.size());
365 
366  flipAndCombine
367  (
368  map,
369  constructHasFlip,
370  subField,
371  eqOp<T>(),
372  negOp,
373  newField
374  );
375  }
376  }
377  else
378  {
379  // I am receive first, send next
380  {
381  IPstream fromNbr
382  (
384  sendProc,
385  0,
386  tag,
387  comm
388  );
389  List<T> subField(fromNbr);
390 
391  const labelList& map = constructMap[sendProc];
392 
393  checkReceivedSize(sendProc, map.size(), subField.size());
394 
395  flipAndCombine
396  (
397  map,
398  constructHasFlip,
399  subField,
400  eqOp<T>(),
401  negOp,
402  newField
403  );
404  }
405  {
406  OPstream toNbr
407  (
409  sendProc,
410  0,
411  tag,
412  comm
413  );
414 
415  const labelList& map = subMap[sendProc];
416  List<T> subField
417  (
418  accessAndFlip(field, map, subHasFlip, negOp)
419  );
420 
421  toNbr << subField;
422  }
423  }
424  }
425  field.transfer(newField);
426  }
427  else if (commsType == Pstream::commsTypes::nonBlocking)
428  {
429  const label nOutstanding = Pstream::nRequests();
430 
431  if (!is_contiguous<T>::value)
432  {
433  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking, tag, comm);
434 
435  // Stream data into buffer
436  for (const int domain : Pstream::allProcs(comm))
437  {
438  const labelList& map = subMap[domain];
439 
440  if (domain != myRank && map.size())
441  {
442  // Put data into send buffer
443  UOPstream toDomain(domain, pBufs);
444 
445  List<T> subField
446  (
447  accessAndFlip(field, map, subHasFlip, negOp)
448  );
449 
450  toDomain << subField;
451  }
452  }
453 
454  // Start receiving. Do not block.
455  pBufs.finishedSends(false);
456 
457  {
458  // Set up 'send' to myself
459  List<T> mySubField
460  (
461  accessAndFlip(field, subMap[myRank], subHasFlip, negOp)
462  );
463 
464  // Combine bits. Note that can reuse field storage
465  field.setSize(constructSize);
466 
467  // Receive sub field from myself
468  const labelList& map = constructMap[myRank];
469 
470  flipAndCombine
471  (
472  map,
473  constructHasFlip,
474  mySubField,
475  eqOp<T>(),
476  negOp,
477  field
478  );
479  }
480 
481  // Block ourselves, waiting only for the current comms
482  Pstream::waitRequests(nOutstanding);
483 
484  // Consume
485  for (const int domain : Pstream::allProcs(comm))
486  {
487  const labelList& map = constructMap[domain];
488 
489  if (domain != myRank && map.size())
490  {
491  UIPstream str(domain, pBufs);
492  List<T> recvField(str);
493 
494  checkReceivedSize(domain, map.size(), recvField.size());
495 
496  flipAndCombine
497  (
498  map,
499  constructHasFlip,
500  recvField,
501  eqOp<T>(),
502  negOp,
503  field
504  );
505  }
506  }
507  }
508  else
509  {
510  // Set up sends to neighbours
511 
512  List<List<T>> sendFields(nProcs);
513 
514  for (const int domain : Pstream::allProcs(comm))
515  {
516  const labelList& map = subMap[domain];
517 
518  if (domain != myRank && map.size())
519  {
520  sendFields[domain] =
521  accessAndFlip(field, map, subHasFlip, negOp);
522 
524  (
526  domain,
527  sendFields[domain].cdata_bytes(),
528  sendFields[domain].size_bytes(),
529  tag,
530  comm
531  );
532  }
533  }
534 
535  // Set up receives from neighbours
536 
537  List<List<T>> recvFields(nProcs);
538 
539  for (const int domain : Pstream::allProcs(comm))
540  {
541  const labelList& map = constructMap[domain];
542 
543  if (domain != myRank && map.size())
544  {
545  recvFields[domain].resize(map.size());
547  (
549  domain,
550  recvFields[domain].data_bytes(),
551  recvFields[domain].size_bytes(),
552  tag,
553  comm
554  );
555  }
556  }
557 
558  // Set up 'send' to myself
559  {
560  sendFields[myRank] =
561  accessAndFlip(field, subMap[myRank], subHasFlip, negOp);
562  }
563 
564 
565  // Combine bits. Note that can reuse field storage
566 
567  field.setSize(constructSize);
568 
569 
570  // Receive sub field from myself (sendFields[myRank])
571  {
572  const labelList& map = constructMap[myRank];
573  const List<T>& subField = sendFields[myRank];
574 
575  flipAndCombine
576  (
577  map,
578  constructHasFlip,
579  subField,
580  eqOp<T>(),
581  negOp,
582  field
583  );
584  }
585 
586 
587  // Wait for outstanding requests
588  Pstream::waitRequests(nOutstanding);
589 
590 
591  // Collect neighbour fields
592 
593  for (const int domain : Pstream::allProcs(comm))
594  {
595  const labelList& map = constructMap[domain];
596 
597  if (domain != myRank && map.size())
598  {
599  const List<T>& subField = recvFields[domain];
600 
601  checkReceivedSize(domain, map.size(), subField.size());
602 
603  flipAndCombine
604  (
605  map,
606  constructHasFlip,
607  subField,
608  eqOp<T>(),
609  negOp,
610  field
611  );
612  }
613  }
614  }
615  }
616  else
617  {
619  << "Unknown communication schedule " << int(commsType)
621  }
622 }
623 
624 
625 template<class T, class CombineOp, class NegateOp>
627 (
628  const Pstream::commsTypes commsType,
629  const List<labelPair>& schedule,
630  const label constructSize,
631  const labelListList& subMap,
632  const bool subHasFlip,
633  const labelListList& constructMap,
634  const bool constructHasFlip,
635  List<T>& field,
636  const T& nullValue,
637  const CombineOp& cop,
638  const NegateOp& negOp,
639  const int tag,
640  const label comm
641 )
642 {
643  const label myRank = Pstream::myProcNo(comm);
644  const label nProcs = Pstream::nProcs(comm);
645 
646  if (!Pstream::parRun())
647  {
648  // Do only me to me.
649 
650  List<T> subField
651  (
652  accessAndFlip(field, subMap[myRank], subHasFlip, negOp)
653  );
654 
655  // Receive sub field from myself (subField)
656  const labelList& map = constructMap[myRank];
657 
658  field.resize_nocopy(constructSize);
659  field = nullValue;
660 
661  flipAndCombine(map, constructHasFlip, subField, cop, negOp, field);
662 
663  return;
664  }
665 
666  if (commsType == Pstream::commsTypes::blocking)
667  {
668  // Since buffered sending can reuse the field to collect the
669  // received data.
670 
671  // Send sub field to neighbour
672  for (const int domain : Pstream::allProcs(comm))
673  {
674  const labelList& map = subMap[domain];
675 
676  if (domain != myRank && map.size())
677  {
678  OPstream toNbr
679  (
681  domain,
682  0,
683  tag,
684  comm
685  );
686  List<T> subField
687  (
688  accessAndFlip(field, map, subHasFlip, negOp)
689  );
690 
691  toNbr << subField;
692  }
693  }
694 
695  {
696  // Subset myself
697  List<T> subField
698  (
699  accessAndFlip(field, subMap[myRank], subHasFlip, negOp)
700  );
701 
702  // Receive sub field from myself (subField)
703  const labelList& map = constructMap[myRank];
704 
705  field.resize_nocopy(constructSize);
706  field = nullValue;
707 
708  flipAndCombine
709  (
710  map,
711  constructHasFlip,
712  subField,
713  cop,
714  negOp,
715  field
716  );
717  }
718 
719  // Receive sub field from neighbour
720  for (const int domain : Pstream::allProcs(comm))
721  {
722  const labelList& map = constructMap[domain];
723 
724  if (domain != myRank && map.size())
725  {
726  IPstream fromNbr
727  (
729  domain,
730  0,
731  tag,
732  comm
733  );
734  List<T> subField(fromNbr);
735 
736  checkReceivedSize(domain, map.size(), subField.size());
737 
738  flipAndCombine
739  (
740  map,
741  constructHasFlip,
742  subField,
743  cop,
744  negOp,
745  field
746  );
747  }
748  }
749  }
750  else if (commsType == Pstream::commsTypes::scheduled)
751  {
752  // Need to make sure I don't overwrite field with received data
753  // since the data might need to be sent to another processor. So
754  // allocate a new field for the results.
755  List<T> newField(constructSize, nullValue);
756 
757  {
758  // Subset myself
759  List<T> subField
760  (
761  accessAndFlip(field, subMap[myRank], subHasFlip, negOp)
762  );
763 
764  // Receive sub field from myself (subField)
765  const labelList& map = constructMap[myRank];
766 
767  flipAndCombine
768  (
769  map,
770  constructHasFlip,
771  subField,
772  cop,
773  negOp,
774  newField
775  );
776  }
777 
778 
779  // Schedule will already have pruned 0-sized comms
780  for (const labelPair& twoProcs : schedule)
781  {
782  // twoProcs is a swap pair of processors. The first one is the
783  // one that needs to send first and then receive.
784 
785  const label sendProc = twoProcs[0];
786  const label recvProc = twoProcs[1];
787 
788  if (myRank == sendProc)
789  {
790  // I am send first, receive next
791  {
792  OPstream toNbr
793  (
795  recvProc,
796  0,
797  tag,
798  comm
799  );
800 
801  const labelList& map = subMap[recvProc];
802 
803  List<T> subField
804  (
805  accessAndFlip(field, map, subHasFlip, negOp)
806  );
807 
808  toNbr << subField;
809  }
810  {
811  IPstream fromNbr
812  (
814  recvProc,
815  0,
816  tag,
817  comm
818  );
819  List<T> subField(fromNbr);
820  const labelList& map = constructMap[recvProc];
821 
822  checkReceivedSize(recvProc, map.size(), subField.size());
823 
824  flipAndCombine
825  (
826  map,
827  constructHasFlip,
828  subField,
829  cop,
830  negOp,
831  newField
832  );
833  }
834  }
835  else
836  {
837  // I am receive first, send next
838  {
839  IPstream fromNbr
840  (
842  sendProc,
843  0,
844  tag,
845  comm
846  );
847  List<T> subField(fromNbr);
848  const labelList& map = constructMap[sendProc];
849 
850  checkReceivedSize(sendProc, map.size(), subField.size());
851 
852  flipAndCombine
853  (
854  map,
855  constructHasFlip,
856  subField,
857  cop,
858  negOp,
859  newField
860  );
861  }
862  {
863  OPstream toNbr
864  (
866  sendProc,
867  0,
868  tag,
869  comm
870  );
871 
872  const labelList& map = subMap[sendProc];
873 
874  List<T> subField
875  (
876  accessAndFlip(field, map, subHasFlip, negOp)
877  );
878 
879  toNbr << subField;
880  }
881  }
882  }
883  field.transfer(newField);
884  }
885  else if (commsType == Pstream::commsTypes::nonBlocking)
886  {
887  const label nOutstanding = Pstream::nRequests();
888 
889  if (!is_contiguous<T>::value)
890  {
891  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking, tag, comm);
892 
893  // Stream data into buffer
894  for (const int domain : Pstream::allProcs(comm))
895  {
896  const labelList& map = subMap[domain];
897 
898  if (domain != myRank && map.size())
899  {
900  // Put data into send buffer
901  UOPstream toDomain(domain, pBufs);
902 
903  List<T> subField
904  (
905  accessAndFlip(field, map, subHasFlip, negOp)
906  );
907 
908  toDomain << subField;
909  }
910  }
911 
912  // Start receiving. Do not block.
913  pBufs.finishedSends(false);
914 
915  {
916  // Set up 'send' to myself
917  List<T> mySubField
918  (
919  accessAndFlip(field, subMap[myRank], subHasFlip, negOp)
920  );
921 
922  // Combine bits. Note that can reuse field storage
923  field.resize_nocopy(constructSize);
924  field = nullValue;
925 
926  // Receive sub field from myself
927  const labelList& map = constructMap[myRank];
928 
929  flipAndCombine
930  (
931  map,
932  constructHasFlip,
933  mySubField,
934  cop,
935  negOp,
936  field
937  );
938  }
939 
940  // Block ourselves, waiting only for the current comms
941  Pstream::waitRequests(nOutstanding);
942 
943  // Consume
944  for (const int domain : Pstream::allProcs(comm))
945  {
946  const labelList& map = constructMap[domain];
947 
948  if (domain != myRank && map.size())
949  {
950  UIPstream str(domain, pBufs);
951  List<T> recvField(str);
952 
953  checkReceivedSize(domain, map.size(), recvField.size());
954 
955  flipAndCombine
956  (
957  map,
958  constructHasFlip,
959  recvField,
960  cop,
961  negOp,
962  field
963  );
964  }
965  }
966  }
967  else
968  {
969  // Set up sends to neighbours
970 
971  List<List<T>> sendFields(nProcs);
972 
973  for (const int domain : Pstream::allProcs(comm))
974  {
975  const labelList& map = subMap[domain];
976 
977  if (domain != myRank && map.size())
978  {
979  sendFields[domain] =
980  accessAndFlip(field, map, subHasFlip, negOp);
981 
983  (
985  domain,
986  sendFields[domain].cdata_bytes(),
987  sendFields[domain].size_bytes(),
988  tag,
989  comm
990  );
991  }
992  }
993 
994  // Set up receives from neighbours
995 
996  List<List<T>> recvFields(nProcs);
997 
998  for (const int domain : Pstream::allProcs(comm))
999  {
1000  const labelList& map = constructMap[domain];
1001 
1002  if (domain != myRank && map.size())
1003  {
1004  recvFields[domain].resize(map.size());
1006  (
1008  domain,
1009  recvFields[domain].data_bytes(),
1010  recvFields[domain].size_bytes(),
1011  tag,
1012  comm
1013  );
1014  }
1015  }
1016 
1017  // Set up 'send' to myself
1018  {
1019  sendFields[myRank] =
1020  accessAndFlip(field, subMap[myRank], subHasFlip, negOp);
1021  }
1022 
1023 
1024  // Combine bits. Note that can reuse field storage
1025 
1026  field.resize_nocopy(constructSize);
1027  field = nullValue;
1028 
1029  // Receive sub field from myself (subField)
1030  {
1031  const labelList& map = constructMap[myRank];
1032  const List<T>& subField = sendFields[myRank];
1033 
1034  flipAndCombine
1035  (
1036  map,
1037  constructHasFlip,
1038  subField,
1039  cop,
1040  negOp,
1041  field
1042  );
1043  }
1044 
1045 
1046  // Wait for outstanding requests
1047  Pstream::waitRequests(nOutstanding);
1048 
1049 
1050  // Collect neighbour fields
1051 
1052  for (const int domain : Pstream::allProcs(comm))
1053  {
1054  const labelList& map = constructMap[domain];
1055 
1056  if (domain != myRank && map.size())
1057  {
1058  const List<T>& subField = recvFields[domain];
1059 
1060  checkReceivedSize(domain, map.size(), subField.size());
1061 
1062  flipAndCombine
1063  (
1064  map,
1065  constructHasFlip,
1066  subField,
1067  cop,
1068  negOp,
1069  field
1070  );
1071  }
1072  }
1073  }
1074  }
1075  else
1076  {
1078  << "Unknown communication schedule " << int(commsType)
1079  << abort(FatalError);
1080  }
1081 }
1082 
1083 
1084 template<class T>
1085 void Foam::mapDistributeBase::send(PstreamBuffers& pBufs, const List<T>& field)
1086 const
1087 {
1088  // Stream data into buffer
1089  for (const int domain : Pstream::allProcs(comm_))
1090  {
1091  const labelList& map = subMap_[domain];
1092 
1093  if (map.size())
1094  {
1095  // Put data into send buffer
1096  UOPstream toDomain(domain, pBufs);
1097 
1098  List<T> subField
1099  (
1100  accessAndFlip(field, map, subHasFlip_, flipOp())
1101  );
1102 
1103  toDomain << subField;
1104  }
1105  }
1107  // Start sending and receiving but do not block.
1108  pBufs.finishedSends(false);
1109 }
1110 
1111 
1112 template<class T>
1114 const
1115 {
1116  // Consume
1117  field.resize_nocopy(constructSize_);
1118 
1119  for (const int domain : Pstream::allProcs(comm_))
1120  {
1121  const labelList& map = constructMap_[domain];
1122 
1123  if (map.size())
1124  {
1125  UIPstream str(domain, pBufs);
1126  List<T> recvField(str);
1127 
1128  if (recvField.size() != map.size())
1129  {
1131  << "Expected from processor " << domain
1132  << " " << map.size() << " but received "
1133  << recvField.size() << " elements."
1134  << abort(FatalError);
1135  }
1136 
1137  flipAndCombine
1138  (
1139  map,
1140  constructHasFlip_,
1141  recvField,
1142  eqOp<T>(),
1143  flipOp(),
1144  field
1145  );
1146  }
1147  }
1148 }
1149 
1150 
1151 template<class T, class NegateOp>
1153 (
1154  const Pstream::commsTypes commsType,
1155  List<T>& values,
1156  const NegateOp& negOp,
1157  const int tag
1158 ) const
1159 {
1160  distribute
1161  (
1162  commsType,
1163  whichSchedule(commsType),
1164  constructSize_,
1165  subMap_,
1166  subHasFlip_,
1167  constructMap_,
1168  constructHasFlip_,
1169  values,
1170  negOp,
1171  tag,
1172  comm_
1173  );
1174 }
1175 
1176 
1177 template<class T, class NegateOp>
1179 (
1180  const Pstream::commsTypes commsType,
1181  const T& nullValue,
1182  List<T>& values,
1183  const NegateOp& negOp,
1184  const int tag
1185 ) const
1186 {
1187  distribute
1188  (
1189  commsType,
1190  whichSchedule(commsType),
1191  constructSize_,
1192  subMap_,
1193  subHasFlip_,
1194  constructMap_,
1195  constructHasFlip_,
1196  values,
1197  nullValue,
1198  eqOp<T>(),
1199  negOp,
1200  tag,
1201  comm_
1202  );
1203 }
1204 
1205 
1206 template<class T, class NegateOp>
1208 (
1209  List<T>& values,
1210  const NegateOp& negOp,
1211  const int tag
1212 ) const
1213 {
1214  distribute
1215  (
1217  );
1218 }
1219 
1220 
1221 template<class T>
1223 (
1224  List<T>& values,
1225  const int tag
1226 ) const
1228  distribute(values, flipOp(), tag);
1229 }
1230 
1231 
1232 template<class T>
1234 (
1236  const int tag
1237 ) const
1238 {
1239  values.shrink();
1240 
1241  List<T>& list = static_cast<List<T>&>(values);
1242 
1243  distribute(list, tag);
1245  values.setCapacity(list.size());
1246 }
1247 
1248 
1249 template<class T>
1251 (
1252  const Pstream::commsTypes commsType,
1253  const label constructSize,
1254  List<T>& values,
1255  const int tag
1256 ) const
1257 {
1258  reverseDistribute<T, flipOp>
1259  (
1260  commsType,
1261  constructSize,
1262  values,
1263  flipOp(),
1264  tag
1265  );
1266 }
1267 
1268 
1269 template<class T, class NegateOp>
1271 (
1272  const Pstream::commsTypes commsType,
1273  const label constructSize,
1274  List<T>& values,
1275  const NegateOp& negOp,
1276  const int tag
1277 ) const
1278 {
1279  distribute
1280  (
1281  commsType,
1282  whichSchedule(commsType),
1283  constructSize,
1284  constructMap_,
1285  constructHasFlip_,
1286  subMap_,
1287  subHasFlip_,
1288  values,
1289  negOp,
1290  tag,
1291  comm_
1292  );
1293 }
1294 
1295 
1296 template<class T>
1298 (
1299  const Pstream::commsTypes commsType,
1300  const label constructSize,
1301  const T& nullValue,
1302  List<T>& values,
1303  const int tag
1304 ) const
1305 {
1306  distribute
1307  (
1308  commsType,
1309  whichSchedule(commsType),
1310  constructSize,
1311  constructMap_,
1312  constructHasFlip_,
1313  subMap_,
1314  subHasFlip_,
1315  values,
1316 
1317  nullValue,
1318  eqOp<T>(),
1319  flipOp(),
1320 
1321  tag,
1322  comm_
1323  );
1324 }
1325 
1326 
1327 template<class T>
1329 (
1330  const label constructSize,
1331  List<T>& values,
1332  const int tag
1333 ) const
1334 {
1335  reverseDistribute
1336  (
1338  constructSize,
1339  values,
1340  tag
1341  );
1342 }
1343 
1344 
1345 template<class T>
1347 (
1348  const label constructSize,
1349  const T& nullValue,
1350  List<T>& values,
1351  const int tag
1352 ) const
1353 {
1354  reverseDistribute
1355  (
1357  constructSize,
1358  nullValue,
1359  values,
1360  tag
1361  );
1362 }
1363 
1364 
1365 // ************************************************************************* //
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:51
static bool write(const UPstream::commsTypes commsType, const int toProcNo, const char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Write buffer contents to given processor.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
"blocking" : (MPI_Bsend, MPI_Recv)
Definition: ops.H:67
rDeltaTY field()
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:132
commsTypes
Types of communications.
Definition: UPstream.H:66
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
void send(PstreamBuffers &pBufs, const List< T > &field) const
Do all sends using PstreamBuffers.
static label nRequests() noexcept
Number of outstanding requests.
Definition: UPstream.C:83
static rangeType allProcs(const label communicator=worldComm)
Range of process indices for all processes.
Definition: UPstream.H:748
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:639
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:688
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
static void flipAndCombine(const labelUList &map, const bool hasFlip, const UList< T > &rhs, const CombineOp &cop, const NegateOp &negOp, List< T > &lhs)
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:164
Input inter-processor communications stream using MPI send/recv etc. - operating on external buffer...
Definition: UIPstream.H:251
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator) is 1 for serial run.
Definition: UPstream.H:656
static T accessAndFlip(const UList< T > &values, const label index, const bool hasFlip, const NegateOp &negOp)
Lookup a field value at specified index and return its value after any flip negation operations...
"scheduled" : (MPI_Send, MPI_Recv)
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
void reverseDistribute(const label constructSize, List< T > &values, const int tag=UPstream::msgType()) const
Reverse distribute data using default commsType and the default flip/negate operator.
errorManip< error > abort(error &err)
Definition: errorManip.H:139
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:50
Buffers for inter-processor communications streams (UOPstream, UIPstream).
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
static void waitRequests(const label start=0)
Wait until all requests (from start onwards) have finished.
Definition: UPstream.C:93
void receive(PstreamBuffers &pBufs, List< T > &field) const
Do all receives using PstreamBuffers.
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:337
static void distribute(const Pstream::commsTypes commsType, const List< labelPair > &schedule, const label constructSize, const labelListList &subMap, const bool subHasFlip, const labelListList &constructMap, const bool constructHasFlip, List< T > &field, const NegateOp &negOp, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Distribute data with specified negate operator (for flips).
"nonBlocking" : (MPI_Isend, MPI_Irecv)
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:59
List< label > labelList
A List of labels.
Definition: List.H:62
static label read(const commsTypes commsType, const int fromProcNo, char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Read buffer contents from given processor.
Definition: UIPstreamRead.C:35
Functor to negate primitives. Dummy for most other types.
Definition: flipOp.H:66