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-------------------------------------------------------------------------------
11License
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
35template<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
80template<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 }
108
109 return values[index];
110}
111
112
113template<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 }
158
159 return output;
160}
161
162
163template<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
432 {
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());
546
548 (
550 domain,
551 recvFields[domain].data_bytes(),
552 recvFields[domain].size_bytes(),
553 tag,
554 comm
555 );
556 }
557 }
558
559
560 // Set up 'send' to myself
561 {
562 sendFields[myRank] =
563 accessAndFlip(field, subMap[myRank], subHasFlip, negOp);
564 }
565
566
567 // Combine bits. Note that can reuse field storage
568
569 field.setSize(constructSize);
570
571
572 // Receive sub field from myself (sendFields[myRank])
573 {
574 const labelList& map = constructMap[myRank];
575 const List<T>& subField = sendFields[myRank];
576
577 flipAndCombine
578 (
579 map,
580 constructHasFlip,
581 subField,
582 eqOp<T>(),
583 negOp,
584 field
585 );
586 }
587
588
589 // Wait for all to finish
590
591 Pstream::waitRequests(nOutstanding);
592
593
594 // Collect neighbour fields
595
596 for (const int domain : Pstream::allProcs(comm))
597 {
598 const labelList& map = constructMap[domain];
599
600 if (domain != myRank && map.size())
601 {
602 const List<T>& subField = recvFields[domain];
603
604 checkReceivedSize(domain, map.size(), subField.size());
605
606 flipAndCombine
607 (
608 map,
609 constructHasFlip,
610 subField,
611 eqOp<T>(),
612 negOp,
613 field
614 );
615 }
616 }
617 }
618 }
619 else
620 {
622 << "Unknown communication schedule " << int(commsType)
623 << abort(FatalError);
624 }
625}
626
627
628template<class T, class CombineOp, class NegateOp>
630(
631 const Pstream::commsTypes commsType,
632 const List<labelPair>& schedule,
633 const label constructSize,
634 const labelListList& subMap,
635 const bool subHasFlip,
636 const labelListList& constructMap,
637 const bool constructHasFlip,
638 List<T>& field,
639 const T& nullValue,
640 const CombineOp& cop,
641 const NegateOp& negOp,
642 const int tag,
643 const label comm
644)
645{
646 const label myRank = Pstream::myProcNo(comm);
647 const label nProcs = Pstream::nProcs(comm);
648
649 if (!Pstream::parRun())
650 {
651 // Do only me to me.
652
653 List<T> subField
654 (
655 accessAndFlip(field, subMap[myRank], subHasFlip, negOp)
656 );
657
658 // Receive sub field from myself (subField)
659 const labelList& map = constructMap[myRank];
660
661 field.resize_nocopy(constructSize);
662 field = nullValue;
663
664 flipAndCombine(map, constructHasFlip, subField, cop, negOp, field);
665
666 return;
667 }
668
669 if (commsType == Pstream::commsTypes::blocking)
670 {
671 // Since buffered sending can reuse the field to collect the
672 // received data.
673
674 // Send sub field to neighbour
675 for (const int domain : Pstream::allProcs(comm))
676 {
677 const labelList& map = subMap[domain];
678
679 if (domain != myRank && map.size())
680 {
681 OPstream toNbr
682 (
684 domain,
685 0,
686 tag,
687 comm
688 );
689 List<T> subField
690 (
691 accessAndFlip(field, map, subHasFlip, negOp)
692 );
693
694 toNbr << subField;
695 }
696 }
697
698 {
699 // Subset myself
700 List<T> subField
701 (
702 accessAndFlip(field, subMap[myRank], subHasFlip, negOp)
703 );
704
705 // Receive sub field from myself (subField)
706 const labelList& map = constructMap[myRank];
707
708 field.resize_nocopy(constructSize);
709 field = nullValue;
710
711 flipAndCombine
712 (
713 map,
714 constructHasFlip,
715 subField,
716 cop,
717 negOp,
718 field
719 );
720 }
721
722 // Receive sub field from neighbour
723 for (const int domain : Pstream::allProcs(comm))
724 {
725 const labelList& map = constructMap[domain];
726
727 if (domain != myRank && map.size())
728 {
729 IPstream fromNbr
730 (
732 domain,
733 0,
734 tag,
735 comm
736 );
737 List<T> subField(fromNbr);
738
739 checkReceivedSize(domain, map.size(), subField.size());
740
741 flipAndCombine
742 (
743 map,
744 constructHasFlip,
745 subField,
746 cop,
747 negOp,
748 field
749 );
750 }
751 }
752 }
753 else if (commsType == Pstream::commsTypes::scheduled)
754 {
755 // Need to make sure I don't overwrite field with received data
756 // since the data might need to be sent to another processor. So
757 // allocate a new field for the results.
758 List<T> newField(constructSize, nullValue);
759
760 {
761 // Subset myself
762 List<T> subField
763 (
764 accessAndFlip(field, subMap[myRank], subHasFlip, negOp)
765 );
766
767 // Receive sub field from myself (subField)
768 const labelList& map = constructMap[myRank];
769
770 flipAndCombine
771 (
772 map,
773 constructHasFlip,
774 subField,
775 cop,
776 negOp,
777 newField
778 );
779 }
780
781
782 // Schedule will already have pruned 0-sized comms
783 for (const labelPair& twoProcs : schedule)
784 {
785 // twoProcs is a swap pair of processors. The first one is the
786 // one that needs to send first and then receive.
787
788 const label sendProc = twoProcs[0];
789 const label recvProc = twoProcs[1];
790
791 if (myRank == sendProc)
792 {
793 // I am send first, receive next
794 {
795 OPstream toNbr
796 (
798 recvProc,
799 0,
800 tag,
801 comm
802 );
803
804 const labelList& map = subMap[recvProc];
805
806 List<T> subField
807 (
808 accessAndFlip(field, map, subHasFlip, negOp)
809 );
810
811 toNbr << subField;
812 }
813 {
814 IPstream fromNbr
815 (
817 recvProc,
818 0,
819 tag,
820 comm
821 );
822 List<T> subField(fromNbr);
823 const labelList& map = constructMap[recvProc];
824
825 checkReceivedSize(recvProc, map.size(), subField.size());
826
827 flipAndCombine
828 (
829 map,
830 constructHasFlip,
831 subField,
832 cop,
833 negOp,
834 newField
835 );
836 }
837 }
838 else
839 {
840 // I am receive first, send next
841 {
842 IPstream fromNbr
843 (
845 sendProc,
846 0,
847 tag,
848 comm
849 );
850 List<T> subField(fromNbr);
851 const labelList& map = constructMap[sendProc];
852
853 checkReceivedSize(sendProc, map.size(), subField.size());
854
855 flipAndCombine
856 (
857 map,
858 constructHasFlip,
859 subField,
860 cop,
861 negOp,
862 newField
863 );
864 }
865 {
866 OPstream toNbr
867 (
869 sendProc,
870 0,
871 tag,
872 comm
873 );
874
875 const labelList& map = subMap[sendProc];
876
877 List<T> subField
878 (
879 accessAndFlip(field, map, subHasFlip, negOp)
880 );
881
882 toNbr << subField;
883 }
884 }
885 }
886 field.transfer(newField);
887 }
888 else if (commsType == Pstream::commsTypes::nonBlocking)
889 {
890 const label nOutstanding = Pstream::nRequests();
891
893 {
895
896 // Stream data into buffer
897 for (const int domain : Pstream::allProcs(comm))
898 {
899 const labelList& map = subMap[domain];
900
901 if (domain != myRank && map.size())
902 {
903 // Put data into send buffer
904 UOPstream toDomain(domain, pBufs);
905
906 List<T> subField
907 (
908 accessAndFlip(field, map, subHasFlip, negOp)
909 );
910
911 toDomain << subField;
912 }
913 }
914
915 // Start receiving. Do not block.
916 pBufs.finishedSends(false);
917
918 {
919 // Set up 'send' to myself
920 List<T> mySubField
921 (
922 accessAndFlip(field, subMap[myRank], subHasFlip, negOp)
923 );
924
925 // Combine bits. Note that can reuse field storage
926 field.resize_nocopy(constructSize);
927 field = nullValue;
928
929 // Receive sub field from myself
930 const labelList& map = constructMap[myRank];
931
932 flipAndCombine
933 (
934 map,
935 constructHasFlip,
936 mySubField,
937 cop,
938 negOp,
939 field
940 );
941 }
942
943 // Block ourselves, waiting only for the current comms
944 Pstream::waitRequests(nOutstanding);
945
946 // Consume
947 for (const int domain : Pstream::allProcs(comm))
948 {
949 const labelList& map = constructMap[domain];
950
951 if (domain != myRank && map.size())
952 {
953 UIPstream str(domain, pBufs);
954 List<T> recvField(str);
955
956 checkReceivedSize(domain, map.size(), recvField.size());
957
958 flipAndCombine
959 (
960 map,
961 constructHasFlip,
962 recvField,
963 cop,
964 negOp,
965 field
966 );
967 }
968 }
969 }
970 else
971 {
972 // Set up sends to neighbours
973
974 List<List<T>> sendFields(nProcs);
975
976 for (const int domain : Pstream::allProcs(comm))
977 {
978 const labelList& map = subMap[domain];
979
980 if (domain != myRank && map.size())
981 {
982 sendFields[domain] =
983 accessAndFlip(field, map, subHasFlip, negOp);
984
986 (
988 domain,
989 sendFields[domain].cdata_bytes(),
990 sendFields[domain].size_bytes(),
991 tag,
992 comm
993 );
994 }
995 }
996
997 // Set up receives from neighbours
998
999 List<List<T>> recvFields(nProcs);
1000
1001 for (const int domain : Pstream::allProcs(comm))
1002 {
1003 const labelList& map = constructMap[domain];
1004
1005 if (domain != myRank && map.size())
1006 {
1007 recvFields[domain].setSize(map.size());
1009 (
1011 domain,
1012 recvFields[domain].data_bytes(),
1013 recvFields[domain].size_bytes(),
1014 tag,
1015 comm
1016 );
1017 }
1018 }
1019
1020 // Set up 'send' to myself
1021
1022 {
1023 sendFields[myRank] =
1024 accessAndFlip(field, subMap[myRank], subHasFlip, negOp);
1025 }
1026
1027
1028 // Combine bits. Note that can reuse field storage
1029
1030 field.resize_nocopy(constructSize);
1031 field = nullValue;
1032
1033 // Receive sub field from myself (subField)
1034 {
1035 const labelList& map = constructMap[myRank];
1036 const List<T>& subField = sendFields[myRank];
1037
1038 flipAndCombine
1039 (
1040 map,
1041 constructHasFlip,
1042 subField,
1043 cop,
1044 negOp,
1045 field
1046 );
1047 }
1048
1049
1050 // Wait for all to finish
1051
1052 Pstream::waitRequests(nOutstanding);
1053
1054
1055 // Collect neighbour fields
1056
1057 for (const int domain : Pstream::allProcs(comm))
1058 {
1059 const labelList& map = constructMap[domain];
1060
1061 if (domain != myRank && map.size())
1062 {
1063 const List<T>& subField = recvFields[domain];
1064
1065 checkReceivedSize(domain, map.size(), subField.size());
1066
1067 flipAndCombine
1068 (
1069 map,
1070 constructHasFlip,
1071 subField,
1072 cop,
1073 negOp,
1074 field
1075 );
1076 }
1077 }
1078 }
1079 }
1080 else
1081 {
1083 << "Unknown communication schedule " << int(commsType)
1084 << abort(FatalError);
1085 }
1086}
1087
1088
1089template<class T>
1091const
1092{
1093 // Stream data into buffer
1094 for (const int domain : Pstream::allProcs(comm_))
1095 {
1096 const labelList& map = subMap_[domain];
1097
1098 if (map.size())
1099 {
1100 // Put data into send buffer
1101 UOPstream toDomain(domain, pBufs);
1102
1103 List<T> subField
1104 (
1105 accessAndFlip(field, map, subHasFlip_, flipOp())
1106 );
1107
1108 toDomain << subField;
1109 }
1110 }
1111
1112 // Start sending and receiving but do not block.
1113 pBufs.finishedSends(false);
1114}
1115
1116
1117template<class T>
1119const
1120{
1121 // Consume
1122 field.resize_nocopy(constructSize_);
1123
1124 for (const int domain : Pstream::allProcs(comm_))
1125 {
1126 const labelList& map = constructMap_[domain];
1127
1128 if (map.size())
1129 {
1130 UIPstream str(domain, pBufs);
1131 List<T> recvField(str);
1132
1133 if (recvField.size() != map.size())
1134 {
1136 << "Expected from processor " << domain
1137 << " " << map.size() << " but received "
1138 << recvField.size() << " elements."
1139 << abort(FatalError);
1140 }
1141
1142 flipAndCombine
1143 (
1144 map,
1145 constructHasFlip_,
1146 recvField,
1147 eqOp<T>(),
1148 flipOp(),
1149 field
1150 );
1151 }
1152 }
1153}
1154
1155
1156template<class T, class NegateOp>
1158(
1159 const Pstream::commsTypes commsType,
1160 List<T>& values,
1161 const NegateOp& negOp,
1162 const int tag
1163) const
1164{
1165 distribute
1166 (
1167 commsType,
1168 whichSchedule(commsType),
1169 constructSize_,
1170 subMap_,
1171 subHasFlip_,
1172 constructMap_,
1173 constructHasFlip_,
1174 values,
1175 negOp,
1176 tag,
1177 comm_
1178 );
1179}
1180
1181
1182template<class T, class NegateOp>
1184(
1185 const Pstream::commsTypes commsType,
1186 const T& nullValue,
1187 List<T>& values,
1188 const NegateOp& negOp,
1189 const int tag
1190) const
1191{
1192 distribute
1193 (
1194 commsType,
1195 whichSchedule(commsType),
1196 constructSize_,
1197 subMap_,
1198 subHasFlip_,
1199 constructMap_,
1200 constructHasFlip_,
1201 values,
1202 nullValue,
1203 eqOp<T>(),
1204 negOp,
1205 tag,
1206 comm_
1207 );
1208}
1209
1210
1211template<class T, class NegateOp>
1213(
1214 List<T>& values,
1215 const NegateOp& negOp,
1216 const int tag
1217) const
1218{
1219 distribute
1220 (
1221 UPstream::defaultCommsType, values, negOp, tag
1222 );
1223}
1224
1225
1226template<class T>
1228(
1229 List<T>& values,
1230 const int tag
1231) const
1232{
1233 distribute(values, flipOp(), tag);
1234}
1235
1236
1237template<class T>
1239(
1240 DynamicList<T>& values,
1241 const int tag
1242) const
1243{
1244 values.shrink();
1245
1246 List<T>& list = static_cast<List<T>&>(values);
1247
1248 distribute(list, tag);
1249
1250 values.setCapacity(list.size());
1251}
1252
1253
1254template<class T>
1256(
1257 const Pstream::commsTypes commsType,
1258 const label constructSize,
1259 List<T>& values,
1260 const int tag
1261) const
1262{
1263 reverseDistribute<T, flipOp>
1264 (
1265 commsType,
1266 constructSize,
1267 values,
1268 flipOp(),
1269 tag
1270 );
1271}
1272
1273
1274template<class T, class NegateOp>
1276(
1277 const Pstream::commsTypes commsType,
1278 const label constructSize,
1279 List<T>& values,
1280 const NegateOp& negOp,
1281 const int tag
1282) const
1283{
1284 distribute
1285 (
1286 commsType,
1287 whichSchedule(commsType),
1288 constructSize,
1289 constructMap_,
1290 constructHasFlip_,
1291 subMap_,
1292 subHasFlip_,
1293 values,
1294 negOp,
1295 tag,
1296 comm_
1297 );
1298}
1299
1300
1301template<class T>
1303(
1304 const Pstream::commsTypes commsType,
1305 const label constructSize,
1306 const T& nullValue,
1307 List<T>& values,
1308 const int tag
1309) const
1310{
1311 distribute
1312 (
1313 commsType,
1314 whichSchedule(commsType),
1315 constructSize,
1316 constructMap_,
1317 constructHasFlip_,
1318 subMap_,
1319 subHasFlip_,
1320 values,
1321
1322 nullValue,
1323 eqOp<T>(),
1324 flipOp(),
1325
1326 tag,
1327 comm_
1328 );
1329}
1330
1331
1332template<class T>
1334(
1335 const label constructSize,
1336 List<T>& values,
1337 const int tag
1338) const
1339{
1340 reverseDistribute
1341 (
1343 constructSize,
1344 values,
1345 tag
1346 );
1347}
1348
1349
1350template<class T>
1352(
1353 const label constructSize,
1354 const T& nullValue,
1355 List<T>& values,
1356 const int tag
1357) const
1358{
1359 reverseDistribute
1360 (
1362 constructSize,
1363 nullValue,
1364 values,
1365 tag
1366 );
1367}
1368
1369
1370// ************************************************************************* //
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:72
Input inter-processor communications stream.
Definition: IPstream.H:57
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:77
void setSize(const label n)
Alias for resize()
Definition: List.H:218
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
Output inter-processor communications stream.
Definition: OPstream.H:57
Buffers for inter-processor communications streams (UOPstream, UIPstream).
UPstream::rangeType allProcs() const noexcept
Range of ranks indices associated with PstreamBuffers.
label nProcs() const noexcept
Number of ranks associated with PstreamBuffers.
void finishedSends(const bool wait=true)
Mark sends as done.
virtual bool read()
Re-read model coefficients if they have changed.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
commsTypes
Types of communications.
Definition: UPstream.H:67
@ nonBlocking
"nonBlocking"
static label nRequests()
Get number of outstanding requests.
Definition: UPstream.C:90
static void waitRequests(const label start=0)
Wait until all requests (from start onwards) have finished.
Definition: UPstream.C:100
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:281
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
virtual bool write()
Write the output fields.
void send(PstreamBuffers &pBufs, const List< T > &field) const
Do all sends using PstreamBuffers.
void reverseDistribute(const label constructSize, List< T > &values, const int tag=UPstream::msgType()) const
static void flipAndCombine(const labelUList &map, const bool hasFlip, const UList< T > &rhs, const CombineOp &cop, const NegateOp &negOp, List< T > &lhs)
void receive(PstreamBuffers &pBufs, List< T > &field) const
Do all receives using PstreamBuffers.
static T accessAndFlip(const UList< T > &values, const label index, const bool hasFlip, const NegateOp &negOp)
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).
int myProcNo() const noexcept
Return processor number.
const volScalarField & T
rDeltaTY field()
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
errorManip< error > abort(error &err)
Definition: errorManip.H:144
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:66
error FatalError
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
Definition: ops.H:71
Functor to negate primitives. Dummy for most other types.
Definition: flipOp.H:69
A template class to specify that a data type can be considered as being contiguous in memory.
Definition: contiguous.H:78