Loading...
Searching...
No Matches
mapDistributeBase.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-2025 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 "mapDistributeBase.H"
30#include "bitSet.H"
31#include "commSchedule.H"
32#include "labelPairHashes.H"
33#include "globalIndex.H"
34#include "ListOps.H"
35
36// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37
38namespace Foam
41}
42
43
44// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
45
47{
48 for (const label val : map)
49 {
50 if (!val)
51 {
52 // Cannot be flipped addressing if it contains zero.
53 return false;
54 }
55 else if (val < 0)
56 {
57 // Must be flipped addressing if it contains negatives.
58 return true;
59 }
60 }
61
62 return false;
63}
64
65
67{
68 for (const labelList& map : maps)
69 {
70 for (const label val : map)
71 {
72 if (!val)
73 {
74 // Cannot be flipped addressing if it contains zero.
75 return false;
76 }
77 else if (val < 0)
78 {
79 // Must be flipped addressing if it contains negatives.
80 return true;
81 }
82 }
83 }
84
85 return false;
86}
87
88
90(
91 const labelListList& maps,
92 const bool hasFlip
93)
94{
95 label maxIndex = -1;
96
97 for (const labelList& map : maps)
98 {
99 for (label index : map)
100 {
101 if (hasFlip)
102 {
103 index = mag(index)-1;
104 }
105
106 maxIndex = max(maxIndex, index);
108 }
109
110 return (maxIndex+1);
111}
112
113
115(
116 const labelUList& elements,
117 const labelListList& maps,
118 const bool hasFlip
119)
120{
121 if (elements.empty())
122 {
123 return 0;
124 }
125
126 // Moderately efficient markup/search
127
128 bitSet unvisited(elements);
129 label nUnmapped = unvisited.count();
130
131 if (hasFlip)
132 {
133 for (const labelList& map : maps)
134 {
135 for (label index : map)
136 {
137 index = mag(index)-1;
138
139 if (unvisited.unset(index))
140 {
141 --nUnmapped;
142 if (!nUnmapped) break;
143 }
144 }
145 }
146 }
147 else
148 {
149 for (const labelList& map : maps)
150 {
151 for (label index : map)
152 {
153 if (unvisited.unset(index))
154 {
155 --nUnmapped;
156 if (!nUnmapped) break;
157 }
158 }
160 }
161
162 return nUnmapped;
163}
164
165
167(
168 const label proci,
169 const label expectedSize,
170 const label receivedSize
171)
172{
173 if (receivedSize != expectedSize)
174 {
176 << "From processor " << proci
177 << " : expected " << expectedSize
178 << " but received " << receivedSize << " elements" << nl
180 }
181}
182
183
184// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
185
187(
188 const labelListList& subMap,
189 const labelListList& constructMap,
190 const int tag,
191 const label comm
192)
193{
194 const label myRank = UPstream::myProcNo(comm);
195 const label nProcs = UPstream::nProcs(comm);
196
197 // Communications: send and receive processor
198 List<labelPair> allComms;
199
200 {
201 labelPairHashSet commsSet(nProcs);
202
203 // Find what communication is required
204 forAll(subMap, proci)
205 {
206 if (proci != myRank)
207 {
208 if (subMap[proci].size())
209 {
210 // I need to send to proci
211 commsSet.insert(labelPair(myRank, proci));
212 }
213 if (constructMap[proci].size())
214 {
215 // I need to receive from proci
216 commsSet.insert(labelPair(proci, myRank));
217 }
218 }
219 }
220 allComms = commsSet.toc();
221 }
222
223
224 // Gather/reduce
225 if (UPstream::master(comm))
226 {
227 // Receive and merge
228 for (const int proci : UPstream::subProcs(comm))
229 {
230 List<labelPair> nbrData;
231 IPstream::recv(nbrData, proci, tag, comm);
232
233 for (const labelPair& connection : nbrData)
234 {
235 allComms.push_uniq(connection);
236 }
237 }
238 }
239 else
240 {
241 if (UPstream::parRun())
242 {
243 OPstream::send(allComms, UPstream::masterNo(), tag, comm);
244 }
245 }
246
247 // Broadcast: send comms information to all
248 Pstream::broadcast(allComms, comm);
249
250 // Determine my schedule.
251 labelList mySchedule
252 (
254 (
255 nProcs,
256 allComms
257 ).procSchedule()[myRank]
258 );
259
260 // Processors involved in my schedule
261 return List<labelPair>(allComms, mySchedule);
262}
263
264
266{
267 if (!schedulePtr_)
268 {
269 schedulePtr_.reset
270 (
272 (
273 schedule(subMap_, constructMap_, UPstream::msgType(), comm_)
274 )
275 );
276 }
277
278 return *schedulePtr_;
279}
280
281
283(
284 const UPstream::commsTypes commsType
285) const
286{
287 if (commsType == UPstream::commsTypes::scheduled)
288 {
289 return schedule();
290 }
291
292 return List<labelPair>::null();
293}
294
295
296void Foam::mapDistributeBase::printLayout(Ostream& os) const
297{
298 const label myRank = UPstream::myProcNo(comm_);
299 const label nProcs = UPstream::nProcs(comm_);
300
301 // Determine offsets of remote data.
302 labelList minIndex(nProcs, labelMax);
303 labelList maxIndex(nProcs, labelMin);
304 forAll(constructMap_, proci)
305 {
306 const labelList& construct = constructMap_[proci];
307 if (constructHasFlip_)
308 {
309 forAll(construct, i)
310 {
311 label index = mag(construct[i])-1;
312 minIndex[proci] = min(minIndex[proci], index);
313 maxIndex[proci] = max(maxIndex[proci], index);
314 }
315 }
316 else
317 {
318 forAll(construct, i)
319 {
320 label index = construct[i];
321 minIndex[proci] = min(minIndex[proci], index);
322 maxIndex[proci] = max(maxIndex[proci], index);
323 }
324 }
325 }
326
327 label localSize(0);
328
329 if (maxIndex[myRank] != labelMin)
330 {
331 localSize = maxIndex[myRank]+1;
332 }
333
334 os << "Layout: (constructSize:" << constructSize_
335 << " subHasFlip:" << subHasFlip_
336 << " constructHasFlip:" << constructHasFlip_
337 << ")" << nl
338 << "local (processor " << myRank << "):" << nl
339 << " start : 0" << nl
340 << " size : " << localSize << endl;
341
342 label offset = localSize;
343 forAll(minIndex, proci)
344 {
345 if (proci != myRank && !constructMap_[proci].empty())
346 {
347 label size(0);
348
349 if (maxIndex[proci] != labelMin)
350 {
351 size = maxIndex[proci]-minIndex[proci]+1;
352 if (minIndex[proci] != offset)
353 {
355 << "offset:" << offset
356 << " proci:" << proci
357 << " minIndex:" << minIndex[proci]
358 << abort(FatalError);
359 }
360 }
361
362 os << "processor " << proci << ':' << nl
363 << " start : " << offset << nl
364 << " size : " << size << endl;
366 offset += size;
367 }
368 }
369}
370
371
373(
374 const globalIndex& globalNumbering,
375 const labelUList& elements,
376 List<Map<label>>& compactMap
377) const
378{
379 const label myRank = UPstream::myProcNo(comm_);
380 const label nProcs = UPstream::nProcs(comm_);
381
382 // Count all (non-local) elements needed. Just for presizing map.
383 labelList nNonLocal(nProcs, Zero);
384
385 for (const label globalIdx : elements)
386 {
387 if (globalIdx != -1 && !globalNumbering.isLocal(myRank, globalIdx))
388 {
389 label proci = globalNumbering.whichProcID(myRank, globalIdx);
390 nNonLocal[proci]++;
391 }
392 }
393
394 compactMap.resize_nocopy(nProcs);
395
396 forAll(compactMap, proci)
397 {
398 compactMap[proci].clear();
399 if (proci != myRank)
400 {
401 compactMap[proci].reserve(nNonLocal[proci]);
402 }
403 }
404
405
406 // Collect all (non-local) elements needed.
407 for (const label globalIdx : elements)
408 {
409 if (globalIdx != -1 && !globalNumbering.isLocal(myRank, globalIdx))
410 {
411 label proci = globalNumbering.whichProcID(myRank, globalIdx);
412 label index = globalNumbering.toLocal(proci, globalIdx);
413 compactMap[proci].insert(index, compactMap[proci].size());
414 }
415 }
416}
417
418
420(
421 const globalIndex& globalNumbering,
422 const labelListList& cellCells,
423 List<Map<label>>& compactMap
424) const
425{
426 const label myRank = UPstream::myProcNo(comm_);
427 const label nProcs = UPstream::nProcs(comm_);
428
429 // Count all (non-local) elements needed. Just for presizing map.
430 labelList nNonLocal(nProcs, Zero);
431
432 for (const labelList& cCells : cellCells)
433 {
434 for (const label globalIdx : cCells)
435 {
436 if (globalIdx != -1 && !globalNumbering.isLocal(myRank, globalIdx))
437 {
438 label proci = globalNumbering.whichProcID(myRank, globalIdx);
439 nNonLocal[proci]++;
440 }
441 }
442 }
443
444 compactMap.resize_nocopy(nProcs);
445
446 forAll(compactMap, proci)
448 compactMap[proci].clear();
449 if (proci != myRank)
450 {
451 compactMap[proci].reserve(nNonLocal[proci]);
453 }
454
455
456 // Collect all (non-local) elements needed.
457 for (const labelList& cCells : cellCells)
458 {
459 for (const label globalIdx : cCells)
460 {
461 if (globalIdx != -1 && !globalNumbering.isLocal(myRank, globalIdx))
463 label proci = globalNumbering.whichProcID(myRank, globalIdx);
464 label index = globalNumbering.toLocal(proci, globalIdx);
465 compactMap[proci].insert(index, compactMap[proci].size());
466 }
467 }
468 }
469}
470
471
473(
474 const int tag,
475 const globalIndex& globalNumbering,
476 labelList& elements,
477 List<Map<label>>& compactMap,
478 labelList& compactStart
479)
480{
481 const label myRank = UPstream::myProcNo(comm_);
482 const label nProcs = UPstream::nProcs(comm_);
483
484 // The overall compact addressing is
485 // - myProcNo data first (uncompacted)
486 // - all other processors consecutively
487
488 compactStart.setSize(nProcs);
489 compactStart[myRank] = 0;
490 constructSize_ = globalNumbering.localSize(myRank);
491 forAll(compactStart, proci)
492 {
493 if (proci != myRank)
494 {
495 compactStart[proci] = constructSize_;
496 constructSize_ += compactMap[proci].size();
497 }
498 }
499
500
501 // Find out what to receive/send in compact addressing.
502
503 // What I want to receive is what others have to send
504 labelListList wantedRemoteElements(nProcs);
505 // Compact addressing for received data
506 constructMap_.setSize(nProcs);
507 forAll(compactMap, proci)
508 {
509 if (proci == myRank)
510 {
511 // All my own elements are used
512 label nLocal = globalNumbering.localSize(myRank);
513 wantedRemoteElements[proci] = identity(nLocal);
514 constructMap_[proci] = identity(nLocal);
515 }
516 else
517 {
518 // Remote elements wanted from processor proci
519 labelList& remoteElem = wantedRemoteElements[proci];
520 labelList& localElem = constructMap_[proci];
521 remoteElem.setSize(compactMap[proci].size());
522 localElem.setSize(compactMap[proci].size());
523 label i = 0;
524 forAllIters(compactMap[proci], iter)
525 {
526 const label compactI = compactStart[proci] + iter.val();
527 remoteElem[i] = iter.key();
528 localElem[i] = compactI;
529 iter.val() = compactI;
530 i++;
531 }
532 }
533 }
534
535 subMap_.setSize(nProcs);
537 (
538 wantedRemoteElements,
539 subMap_,
540 tag,
541 comm_
542 );
543
544 // Renumber elements
545 for (label& elem : elements)
546 {
547 elem = renumber(globalNumbering, comm_, compactMap, elem);
548 }
549}
550
551
553(
554 const int tag,
555 const globalIndex& globalNumbering,
556 labelListList& cellCells,
557 List<Map<label>>& compactMap,
558 labelList& compactStart
559)
560{
561 const label myRank = UPstream::myProcNo(comm_);
562 const label nProcs = UPstream::nProcs(comm_);
563
564 // The overall compact addressing is
565 // - myProcNo data first (uncompacted)
566 // - all other processors consecutively
567
568 compactStart.setSize(nProcs);
569 compactStart[myRank] = 0;
570 constructSize_ = globalNumbering.localSize(myRank);
571 forAll(compactStart, proci)
572 {
573 if (proci != myRank)
574 {
575 compactStart[proci] = constructSize_;
576 constructSize_ += compactMap[proci].size();
577 }
578 }
579
580
581 // Find out what to receive/send in compact addressing.
582
583 // What I want to receive is what others have to send
584 labelListList wantedRemoteElements(nProcs);
585 // Compact addressing for received data
586 constructMap_.setSize(nProcs);
587 forAll(compactMap, proci)
588 {
589 if (proci == myRank)
590 {
591 // All my own elements are used
592 label nLocal = globalNumbering.localSize(myRank);
593 wantedRemoteElements[proci] = identity(nLocal);
594 constructMap_[proci] = identity(nLocal);
595 }
596 else
597 {
598 // Remote elements wanted from processor proci
599 labelList& remoteElem = wantedRemoteElements[proci];
600 labelList& localElem = constructMap_[proci];
601 remoteElem.setSize(compactMap[proci].size());
602 localElem.setSize(compactMap[proci].size());
603 label i = 0;
604 forAllIters(compactMap[proci], iter)
605 {
606 const label compactI = compactStart[proci] + iter.val();
607 remoteElem[i] = iter.key();
608 localElem[i] = compactI;
609 iter.val() = compactI;
610 i++;
611 }
612 }
613 }
614
615 subMap_.setSize(nProcs);
617 (
618 wantedRemoteElements,
619 subMap_,
620 tag,
621 comm_
622 );
623
624 // Renumber elements
625 for (labelList& cCells : cellCells)
626 {
627 for (label& celli : cCells)
628 {
629 celli = renumber(globalNumbering, comm_, compactMap, celli);
631 }
632}
633
634
635// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
638:
639 mapDistributeBase(UPstream::worldComm)
640{}
641
642
644:
645 constructSize_(0),
646 subMap_(),
647 constructMap_(),
648 subHasFlip_(false),
649 constructHasFlip_(false),
650 comm_(comm),
651 schedulePtr_(nullptr)
652{}
653
654
656:
657 constructSize_(map.constructSize_),
658 subMap_(map.subMap_),
659 constructMap_(map.constructMap_),
660 subHasFlip_(map.subHasFlip_),
661 constructHasFlip_(map.constructHasFlip_),
662 comm_(map.comm_),
663 schedulePtr_(nullptr)
664{}
665
666
670{
671 transfer(map);
672}
673
674
676(
677 const label constructSize,
678 labelListList&& subMap,
679 labelListList&& constructMap,
680 const bool subHasFlip,
681 const bool constructHasFlip,
682 const label comm
683)
684:
685 constructSize_(constructSize),
686 subMap_(std::move(subMap)),
687 constructMap_(std::move(constructMap)),
688 subHasFlip_(subHasFlip),
689 constructHasFlip_(constructHasFlip),
690 comm_(comm),
691 schedulePtr_(nullptr)
692{}
693
694
696(
697 const labelUList& sendProcs,
698 const labelUList& recvProcs,
699 const label comm
700)
701:
702 constructSize_(0),
703 subMap_(),
704 constructMap_(),
705 subHasFlip_(false),
706 constructHasFlip_(false),
707 comm_(comm),
708 schedulePtr_(nullptr)
709{
710 const label myRank = UPstream::myProcNo(comm_);
711 const label nProcs = UPstream::nProcs(comm_);
712
713 if (sendProcs.size() != recvProcs.size())
714 {
716 << "The send and receive data is not the same length. sendProcs:"
717 << sendProcs.size() << " recvProcs:" << recvProcs.size()
718 << abort(FatalError);
719 }
720
721 // Per processor the number of samples we have to send/receive.
722 labelList nSend(nProcs, Zero);
723 labelList nRecv(nProcs, Zero);
724
725 forAll(sendProcs, sampleI)
726 {
727 const label sendProc = sendProcs[sampleI];
728 const label recvProc = recvProcs[sampleI];
729
730 // Note that also need to include local communication (both
731 // RecvProc and sendProc on local processor)
732
733 if (myRank == sendProc)
734 {
735 // I am the sender.
736 nSend[recvProc]++;
737 }
738 if (myRank == recvProc)
739 {
740 // I am the receiver.
741 nRecv[sendProc]++;
742 }
743 }
744
745 subMap_.setSize(nProcs);
746 constructMap_.setSize(nProcs);
747 forAll(nSend, proci)
748 {
749 subMap_[proci].setSize(nSend[proci]);
750 constructMap_[proci].setSize(nRecv[proci]);
751 }
752 nSend = 0;
753 nRecv = 0;
754
755 // Largest entry inside constructMap
756 label maxRecvIndex = -1;
757
758 forAll(sendProcs, sampleI)
759 {
760 const label sendProc = sendProcs[sampleI];
761 const label recvProc = recvProcs[sampleI];
762
763 if (myRank == sendProc)
764 {
765 // I am the sender. Store index I need to send.
766 subMap_[recvProc][nSend[recvProc]++] = sampleI;
767 }
768 if (myRank == recvProc)
769 {
770 // I am the receiver.
771 constructMap_[sendProc][nRecv[sendProc]++] = sampleI;
772 maxRecvIndex = sampleI;
774 }
775
776 constructSize_ = maxRecvIndex+1;
777}
778
779
781(
782 const globalIndex& globalNumbering,
783 labelList& elements,
784 List<Map<label>>& compactMap,
785 const int tag,
786 const label comm
787)
788:
789 constructSize_(0),
790 subMap_(),
791 constructMap_(),
792 subHasFlip_(false),
793 constructHasFlip_(false),
794 comm_(comm),
795 schedulePtr_(nullptr)
796{
797 // Construct per processor compact addressing of the global elements
798 // needed. The ones from the local processor are not included since
799 // these are always all needed.
801 (
802 globalNumbering,
803 elements,
804 compactMap
805 );
806
808 //forAll(compactMap, proci)
809 //{
810 // if (proci != myRank)
811 // {
812 // Map<label>& globalMap = compactMap[proci];
813 //
814 // const List<label> sorted(globalMap.sortedToc());
815 //
816 // forAll(sorted, i)
817 // {
818 // globalMap(sorted[i]) = i;
819 // }
820 // }
821 //}
822
823
824 // Exchange what I need with processor that supplies it. Renumber elements
825 // into compact numbering
826 labelList compactStart;
828 (
829 tag,
830 globalNumbering,
831 elements,
832 compactMap,
833 compactStart
834 );
835
836 if (debug)
837 {
839 }
840}
841
842
844(
845 const globalIndex& globalNumbering,
846 labelListList& cellCells,
847 List<Map<label>>& compactMap,
848 const int tag,
849 const label comm
850)
851:
852 constructSize_(0),
853 subMap_(),
854 constructMap_(),
855 subHasFlip_(false),
856 constructHasFlip_(false),
857 comm_(comm),
858 schedulePtr_(nullptr)
859{
860 // Construct per processor compact addressing of the global elements
861 // needed. The ones from the local processor are not included since
862 // these are always all needed.
864 (
865 globalNumbering,
866 cellCells,
867 compactMap
868 );
869
871 //forAll(compactMap, proci)
872 //{
873 // if (proci != myRank)
874 // {
875 // Map<label>& globalMap = compactMap[proci];
876 //
877 // const List<label> sorted(globalMap.sortedToc());
878 //
879 // forAll(sorted, i)
880 // {
881 // globalMap(sorted[i]) = i;
882 // }
883 // }
884 //}
885
886
887 // Exchange what I need with processor that supplies it. Renumber elements
888 // into compact numbering
889 labelList compactStart;
891 (
892 tag,
893 globalNumbering,
894 cellCells,
895 compactMap,
896 compactStart
897 );
898
899 if (debug)
900 {
902 }
903}
904
905
907(
908 const layoutTypes constructLayout,
909 labelListList&& subMap,
910 const bool subHasFlip,
911 const bool constructHasFlip,
912 const label comm
913)
914:
915 constructSize_(0),
916 subMap_(std::move(subMap)),
917 constructMap_(),
918 subHasFlip_(subHasFlip),
919 constructHasFlip_(constructHasFlip),
920 comm_(comm),
921 schedulePtr_(nullptr)
922{
923 const label myRank = UPstream::myProcNo(comm_);
924 const label nProcs = UPstream::nProcs(comm_);
925
926 // Send over how many i need to receive.
927 labelList recvSizes;
928 Pstream::exchangeSizes(subMap_, recvSizes, comm_);
929
930 constructSize_ = 0;
931 constructMap_.resize(nProcs);
932
933 // The order of receiving:
934
935 if (constructLayout == layoutTypes::linear)
936 {
937 forAll(constructMap_, proci)
938 {
939 const label len = recvSizes[proci];
940
941 constructMap_[proci] = identity(len, constructSize_);
942 constructSize_ += len;
943 }
944 }
945 else
946 {
947 // layoutTypes::localFirst
948
949 // My data first
950 {
951 const label len = recvSizes[myRank];
952
953 constructMap_[myRank] = identity(len, constructSize_);
954 constructSize_ += len;
955 }
956
957 // What the other processors are sending to me
958 forAll(constructMap_, proci)
959 {
960 if (proci != myRank)
961 {
962 const label len = recvSizes[proci];
963
964 constructMap_[proci] = identity(len, constructSize_);
965 constructSize_ += len;
966 }
967 }
968 }
969}
970
971
973(
974 labelListList&& subMap,
975 const bool subHasFlip,
976 const bool constructHasFlip,
977 const label comm
978)
979:
981 (
982 layoutTypes::localFirst,
983 std::move(subMap),
986 comm
987 )
988{}
989
990
992(
994 const labelList& localRanks,
995 const label newComm,
996 const labelListList& newToOldRanks,// from newComm to comm_
997 labelList& startOfLocal,
998 List<Map<label>>& compactMaps
999)
1000:
1001 constructSize_(0),
1002 subHasFlip_(false),
1003 constructHasFlip_(false),
1004 comm_(newComm),
1005 schedulePtr_(nullptr)
1006{
1007 // localRanks : gives for every map the index (=rank in original
1008 // communicator) in subMap,constructMap that refers to
1009 // the local data. -1 if the map did not contain any data
1010 // (can happen for e.g. agglomerating of cyclicAMI data)
1011 // newToOldRanks : gives for every rank in the newComm the ranks in the
1012 // maps that agglomerate to it. This is used to decide
1013 // - data was local and stays local
1014 // - data that was remote and now becomes local
1015 // - and same for remote
1016 // Currently can contain -1 entries. Probably should be
1017 // filtered...
1018
1019 // Find set index
1020 label validMapi = -1;
1021 forAll(maps, mapi)
1022 {
1023 if (maps.set(mapi) && localRanks[mapi] != -1)
1024 {
1025 validMapi = mapi;
1026 break;
1027 }
1028 }
1029
1030 if (validMapi == -1)
1031 {
1032 return;
1033 }
1034
1035 subHasFlip_ = maps[validMapi].subHasFlip();
1036 constructHasFlip_ = maps[validMapi].constructHasFlip();
1037
1038 const label nNewRanks = newToOldRanks.size();
1039 const label myNewRank = UPstream::myProcNo(newComm);
1040 if (nNewRanks != UPstream::nProcs(newComm))
1041 {
1042 FatalErrorInFunction<< "nNewRanks:" << nNewRanks
1043 << " nProcs:" << UPstream::nProcs(newComm)
1044 << exit(FatalError);
1045 }
1046
1047 if (localRanks.size() != maps.size())
1048 {
1050 << "Number of maps:" << maps.size()
1051 << " number of localRanks:" << localRanks.size()
1052 << exit(FatalError);
1053 }
1054
1055 // Sanity checks
1056 const auto& map0 = maps[validMapi];
1057 forAll(maps, mapi)
1058 {
1059 if (!maps.set(mapi) || localRanks[mapi] == -1)
1060 {
1061 continue;
1062 }
1063
1064 const auto& map = maps[mapi];
1065
1066 if
1067 (
1068 //(map.comm() != map0.comm())
1069 (map.subHasFlip() != map0.subHasFlip())
1070 || (map.constructHasFlip() != map0.constructHasFlip())
1071 )
1072 {
1074 << "Maps should all be the same form"
1075 << " Map " << mapi
1076 << " has comm:" << map.comm()
1077 << " subHasFlip:" << map.subHasFlip()
1078 << " constructHasFlip:" << map.constructHasFlip()
1079 << " which is different from map 0 "
1080 << " comm:" << map0.comm()
1081 << " subHasFlip:" << map0.subHasFlip()
1082 << " constructHasFlip:" << map0.constructHasFlip()
1083 << exit(FatalError);
1084 }
1085
1086 const label localRank = localRanks[mapi];
1087 const auto& constructOwn = maps[mapi].constructMap()[localRank];
1088 forAll(constructOwn, i)
1089 {
1090 if (constructOwn[i] != i)
1091 {
1093 << "Maps constructMap not identity."
1094 << " Map " << mapi
1095 << " constructMap:" << flatOutput(constructOwn)
1096 << exit(FatalError);
1097 }
1098 }
1099 }
1100
1101
1102 // Determine start of constructed remote data. This is used to get the
1103 // local offset which can then be used to get the relative subMap location.
1104 labelListList startOfRemote(maps.size());
1105 forAll(maps, mapi)
1106 {
1107 if (!maps.set(mapi))
1108 {
1109 continue;
1110 }
1111
1112 const label nOldRanks = maps[mapi].constructMap().size();
1113 labelList& starts = startOfRemote[mapi];
1114
1115 starts.setSize(nOldRanks, labelMax);
1116 forAll(maps[mapi].constructMap(), oldRanki)
1117 {
1118 const labelList& map = maps[mapi].constructMap()[oldRanki];
1119 forAll(map, i)
1120 {
1121 const label index
1122 (
1123 constructHasFlip_
1124 ? mag(map[i])-1
1125 : map[i]
1126 );
1127 starts[oldRanki] = min(starts[oldRanki], index);
1128 }
1129 }
1130 }
1131
1132
1133
1134 constructMap_.resize_nocopy(nNewRanks);
1135 subMap_.resize_nocopy(nNewRanks);
1136
1137
1138 // Store starts
1139 startOfLocal.setSize(maps.size()+1);
1140 compactMaps.resize_nocopy(maps.size());
1141
1142 label constructi = 0;
1143 forAll(maps, mapi)
1144 {
1145 startOfLocal[mapi] = constructi;
1146
1147 const label localRank = localRanks[mapi];
1148
1149 if (!maps.set(mapi) || localRank == -1)
1150 {
1151 continue;
1152 }
1153
1154 const auto& map = maps[mapi].constructMap()[localRank];
1155
1156 // Presize compaction array
1157 const label nRemote = maps[mapi].constructSize()-map.size();
1158 compactMaps[mapi].resize(2*nRemote);
1159
1160 constructi += map.size();
1161 }
1162 startOfLocal.last() = constructi;
1163
1164
1165
1166 // Construct map
1167 // ~~~~~~~~~~~~~
1168 // - all localRanks:
1169 // - data gets appended in map order
1170 // - map is just an offset (startOfLocal)
1171 // - all previously remote ranks:
1172 // - data is already present according to startOfLocal
1173 // - map is old-to-new index
1174 // - all still remote ranks:
1175 // - data gets appended in map order after the startOfLocal
1176 // - map is old-to-new index
1177
1178
1179 // Append local (= myRank) data. TBD: assumes subMap and constructMap
1180 // are identity maps.
1181 {
1182 labelList& myConstruct = constructMap_[myNewRank];
1183 myConstruct.resize_nocopy(constructi);
1184 constructi = 0;
1185 forAll(maps, mapi)
1186 {
1187 const label localRank = localRanks[mapi];
1188
1189 if (!maps.set(mapi) || localRank == -1)
1190 {
1191 continue;
1192 }
1193
1194 const auto& map = maps[mapi].constructMap()[localRank];
1195 const label offset = startOfLocal[mapi];
1196
1197 forAll(map, i)
1198 {
1199 if (constructHasFlip_)
1200 {
1201 forAll(map, i)
1202 {
1203 if (map[i] < 0)
1204 {
1205 myConstruct[constructi++] = map[i]-offset;
1206 }
1207 else
1208 {
1209 myConstruct[constructi++] = map[i]+offset;
1210 }
1211 }
1212 }
1213 else
1214 {
1215 myConstruct[constructi++] = map[i]+offset;
1216 }
1217 }
1218 }
1219
1220 if (constructi != startOfLocal.last())
1221 {
1223 << "constructi:" << constructi
1224 << " startOfLocal:" << startOfLocal.last()
1225 << exit(FatalError);
1226 }
1227 }
1228
1229
1230 // Filter remote construct data
1231 {
1232 // Remote ranks that are now local
1233 // - store new index for mapping stencils
1234 // - no need to construct since already
1235 const auto& oldRanks = newToOldRanks[myNewRank];
1236
1237 // Determine number of old ranks. Note: should have passed in old-to-new
1238 // ranks instead of new-to-old ranks?
1239 label maxOldRank = -1;
1240 for (const auto& elems : newToOldRanks)
1241 {
1242 for (const label el : elems)
1243 {
1244 maxOldRank = max(maxOldRank, el);
1245 }
1246 }
1247
1248 // Construct mapping from oldRanks to map. Note: could probably
1249 // use some ListOps invert routine ...
1250 labelList oldRankToMap(maxOldRank+1, -1);
1251 {
1252 forAll(localRanks, mapi)
1253 {
1254 const label localRank = localRanks[mapi];
1255 if (localRank != -1)
1256 {
1257 oldRankToMap[localRank] = mapi;
1258 }
1259 }
1260 }
1261
1262 forAll(maps, mapi)
1263 {
1264 if (!maps.set(mapi) || localRanks[mapi] == -1)
1265 {
1266 continue;
1267 }
1268
1269 for (const label oldRanki : oldRanks)
1270 {
1271 if (oldRanki == -1)
1272 {
1273 continue;
1274 }
1275
1276 if (oldRanki != localRanks[mapi])
1277 {
1278 // Note:
1279 // - constructMap is sized with the map's communicator
1280 const auto& map = maps[mapi].constructMap()[oldRanki];
1281
1282 if (!map.size())
1283 {
1284 continue;
1285 }
1286
1287
1288 // The slots come from a local map so we can look up the
1289 // new location
1290 const label sourceMapi = oldRankToMap[oldRanki];
1291 const auto& subMap =
1292 maps[sourceMapi].subMap()[localRanks[mapi]];
1293
1294 //Pout<< "From oldRank:" << oldRanki
1295 // << " sending to masterRank:" << localRanks[mapi]
1296 // << " elements:" << flatOutput(subMap)
1297 // << nl
1298 // << " received as elements:" << flatOutput(map)
1299 // << endl;
1300
1301 if (map.size() != subMap.size())
1302 {
1303 FatalErrorInFunction << "Problem:"
1304 << "oldRanki:" << oldRanki
1305 << " mapi:" << mapi
1306 << " constructMap:" << map.size()
1307 << " sourceMapi:" << sourceMapi
1308 << " subMap:" << subMap.size()
1309 << exit(FatalError);
1310 }
1311
1312 const label offset = startOfLocal[sourceMapi];
1313 // Construct map starts after the local data
1314 const label nMapLocal = startOfRemote[mapi][oldRanki];
1315
1316 auto& cptMap = compactMaps[mapi];
1317 forAll(map, i)
1318 {
1319 // old slot position to new slot position
1320 const label index
1321 (
1322 constructHasFlip_
1323 ? mag(map[i])-1
1324 : map[i]
1325 );
1326 const label newIndex = subMap[index-nMapLocal]+offset;
1327
1328 // Note: should always warn for duplicates? Or only if
1329 // different?
1330 if
1331 (
1332 !cptMap.insert(index, newIndex)
1333 && cptMap[index] != newIndex
1334 )
1335 {
1336 FatalErrorInFunction<< "Duplicate insertion"
1337 << "From oldRank:" << oldRanki
1338 << " on map:" << mapi
1339 << " at index:" << i
1340 << " have construct slot:" << index
1341 << " new index:" << newIndex
1342 << " but already have entry:" << cptMap[index]
1343 << " on for that slot"
1344 << exit(FatalError);
1345 }
1346 }
1347 }
1348 }
1349 }
1350
1351
1352 // Remote ranks that are still remote
1353 // - store new index for mapping stencils
1354 // - append to construction
1355
1356 // Either loop over all old ranks and filter out ones already handled
1357 // or loop over all new ranks and avoid myNewRank
1358
1359 forAll(newToOldRanks, newRanki)
1360 {
1361 if (newRanki != myNewRank)
1362 {
1363 const auto& oldRanks = newToOldRanks[newRanki];
1364
1365 label allSize = 0;
1366 forAll(maps, mapi)
1367 {
1368 if (!maps.set(mapi))
1369 {
1370 continue;
1371 }
1372
1373 for (const label oldRanki : oldRanks)
1374 {
1375 if (oldRanki == -1)
1376 {
1377 continue;
1378 }
1379 allSize += maps[mapi].constructMap()[oldRanki].size();
1380 }
1381 }
1382
1383 labelList& myConstruct = constructMap_[newRanki];
1384 myConstruct.resize_nocopy(allSize);
1385
1386 allSize = 0;
1387 forAll(maps, mapi)
1388 {
1389 if (!maps.set(mapi))
1390 {
1391 continue;
1392 }
1393
1394 for (const label oldRanki : oldRanks)
1395 {
1396 if (oldRanki == -1)
1397 {
1398 continue;
1399 }
1400
1401 const auto& map = maps[mapi].constructMap()[oldRanki];
1402 // Construct map starts after the local data
1403 const label nMapLocal = startOfRemote[mapi][oldRanki];
1404 SubList<label> slice(myConstruct, map.size(), allSize);
1405
1406 if (constructHasFlip_)
1407 {
1408 forAll(map, i)
1409 {
1410 if (map[i] < 0)
1411 {
1412 slice[i] = map[i]+nMapLocal-constructi;
1413 }
1414 else
1415 {
1416 slice[i] = map[i]-nMapLocal+constructi;
1417 }
1418 }
1419
1420 auto& cptMap = compactMaps[mapi];
1421 forAll(map, i)
1422 {
1423 cptMap.insert(mag(map[i])-1,mag(slice[i])-1);
1424 }
1425 }
1426 else
1427 {
1428 forAll(map, i)
1429 {
1430 slice[i] = map[i]-nMapLocal+constructi;
1431 compactMaps[mapi].insert(map[i], slice[i]);
1432 }
1433 }
1434 allSize += map.size();
1435 constructi += map.size();
1436 }
1437 }
1438 }
1439 }
1440 }
1441
1442
1443 // Sub (=send) map
1444 // ~~~~~~~~~~~~~~~
1445 // - all localRanks:
1446 // - get appended in map order
1447 // - all previously remote ranks:
1448 // - not needed. Stay empty
1449 // - all still remote ranks:
1450 // - convert to new local index
1451
1452 // Append local (= myRank) data
1453 {
1454 label allSize = 0;
1455 forAll(maps, mapi)
1456 {
1457 const label localRank = localRanks[mapi];
1458
1459 if (!maps.set(mapi) || localRank == -1)
1460 {
1461 continue;
1462 }
1463
1464 allSize += maps[mapi].subMap()[localRank].size();
1465 }
1466
1467 labelList& mySub = subMap_[myNewRank];
1468 mySub.resize_nocopy(allSize);
1469 allSize = 0;
1470 forAll(maps, mapi)
1471 {
1472 const label localRank = localRanks[mapi];
1473
1474 if (!maps.set(mapi) || localRank == -1)
1475 {
1476 continue;
1477 }
1478
1479 const auto& map = maps[mapi].subMap()[localRank];
1480 SubList<label> slice(mySub, map.size(), allSize);
1481
1482 if (subHasFlip_)
1483 {
1484 forAll(slice, i)
1485 {
1486 if (map[i] < 0)
1487 {
1488 slice[i] = map[i]-startOfLocal[mapi];
1489 }
1490 else
1491 {
1492 slice[i] = map[i]+startOfLocal[mapi];
1493 }
1494 }
1495 }
1496 else
1497 {
1498 forAll(slice, i)
1499 {
1500 slice[i] = map[i]+startOfLocal[mapi];
1501 }
1502 }
1503 allSize += map.size();
1504 }
1505 }
1506 // Filter remote sub data
1507 forAll(newToOldRanks, newRanki)
1508 {
1509 if (newRanki != myNewRank)
1510 {
1511 const auto& oldRanks = newToOldRanks[newRanki];
1512
1513 label allSize = 0;
1514 forAll(maps, mapi)
1515 {
1516 if (!maps.set(mapi))
1517 {
1518 continue;
1519 }
1520
1521 for (const label oldRanki : oldRanks)
1522 {
1523 if (oldRanki == -1)
1524 {
1525 continue;
1526 }
1527 allSize += maps[mapi].subMap()[oldRanki].size();
1528 }
1529 }
1530
1531 labelList& mySub = subMap_[newRanki];
1532 mySub.resize_nocopy(allSize);
1533
1534 allSize = 0;
1535 for (const label oldRanki : oldRanks)
1536 {
1537 if (oldRanki == -1)
1538 {
1539 continue;
1540 }
1541
1542 forAll(maps, mapi)
1543 {
1544 if (!maps.set(mapi))
1545 {
1546 continue;
1547 }
1548
1549 const auto& map = maps[mapi].subMap()[oldRanki];
1550 SubList<label> slice(mySub, map.size(), allSize);
1551 if (subHasFlip_)
1552 {
1553 forAll(map, i)
1554 {
1555 if (map[i] < 0)
1556 {
1557 slice[i] = map[i]-startOfLocal[mapi];
1558 }
1559 else
1560 {
1561 slice[i] = map[i]+startOfLocal[mapi];
1562 }
1563 }
1564 }
1565 else
1566 {
1567 forAll(map, i)
1568 {
1569 slice[i] = map[i]+startOfLocal[mapi];
1570 }
1571 }
1572 allSize += map.size();
1573 }
1574 }
1575 }
1576 }
1577
1579 constructSize_ = constructi;
1580}
1581
1582
1583// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
1584
1586{
1587 labelList sizes(subMap_.size());
1588 forAll(subMap_, i)
1590 sizes[i] = subMap_[i].size();
1591 }
1592 return sizes;
1593}
1594
1595
1597{
1598 labelList sizes(constructMap_.size());
1599 forAll(constructMap_, i)
1601 sizes[i] = constructMap_[i].size();
1602 }
1603 return sizes;
1604}
1605
1606
1608{
1609 label total = 0;
1610 for (const auto& list : subMap_)
1612 total += list.size();
1613 }
1614 return total;
1615}
1616
1617
1619{
1620 label total = 0;
1621 for (const auto& list : constructMap_)
1623 total += list.size();
1624 }
1625 return total;
1626}
1627
1628
1630{
1631 constructSize_ = 0;
1632 subMap_.clear();
1633 constructMap_.clear();
1634 subHasFlip_ = false;
1635 constructHasFlip_ = false;
1636 // Leave comm_ intact
1637 schedulePtr_.reset(nullptr);
1638}
1639
1640
1642{
1643 if (this == &rhs)
1644 {
1645 // Self-assignment is a no-op
1646 return;
1647 }
1648
1649 constructSize_ = rhs.constructSize_;
1650 subMap_.transfer(rhs.subMap_);
1651 constructMap_.transfer(rhs.constructMap_);
1652 subHasFlip_ = rhs.subHasFlip_;
1653 constructHasFlip_ = rhs.constructHasFlip_;
1654 comm_ = rhs.comm_;
1655 schedulePtr_.reset(nullptr);
1657 rhs.constructSize_ = 0;
1658 rhs.subHasFlip_ = false;
1659 rhs.constructHasFlip_ = false;
1660}
1661
1662
1664(
1665 const globalIndex& globalNumbering,
1666 const label comm,
1667 const List<Map<label>>& compactMap,
1668 const label globalI
1669)
1670{
1671 const label myRank = Pstream::myProcNo(comm);
1672
1673 if (globalI == -1)
1674 {
1675 return globalI;
1676 }
1677 if (globalNumbering.isLocal(myRank, globalI))
1678 {
1679 return globalNumbering.toLocal(myRank, globalI);
1680 }
1681 else
1682 {
1683 label proci = globalNumbering.whichProcID(myRank, globalI);
1684 label index = globalNumbering.toLocal(proci, globalI);
1685 return compactMap[proci][index];
1686 }
1687}
1688
1689
1690// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1691
1692void Foam::mapDistributeBase::operator=(const mapDistributeBase& rhs)
1693{
1694 if (this == &rhs)
1695 {
1696 return; // Self-assignment is a no-op
1697 }
1698
1699 constructSize_ = rhs.constructSize_;
1700 subMap_ = rhs.subMap_;
1701 constructMap_ = rhs.constructMap_;
1702 subHasFlip_ = rhs.subHasFlip_;
1703 constructHasFlip_ = rhs.constructHasFlip_;
1704 comm_ = rhs.comm_;
1705 schedulePtr_.reset(nullptr);
1706}
1707
1708
1710{
1711 if (this != &rhs)
1712 {
1713 // Avoid self assignment
1714 transfer(rhs);
1715 }
1716}
1717
1718
1719// ************************************************************************* //
Various functions to operate on Lists.
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition HashSet.H:229
List< Key > toc() const
The table of contents (the keys) in unsorted order.
Definition HashTable.C:141
static void recv(Type &value, const int fromProcNo, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm, IOstreamOption::streamFormat fmt=IOstreamOption::BINARY)
Receive and deserialize a value. Uses operator>> for de-serialization.
Definition IPstream.H:80
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition ListI.H:171
label push_uniq(const T &val)
Append an element if not already in the list.
Definition ListI.H:278
void setSize(label n)
Alias for resize().
Definition List.H:536
void resize(const label len)
Adjust allocated size of list.
Definition ListI.H:153
static const List< T > & null() noexcept
Return a null List (reference to a nullObject). Behaves like an empty List.
Definition List.H:138
A HashTable to objects of type <T> with a label key.
Definition Map.H:54
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition Ostream.H:59
static void exchange(const UList< Container > &sendBufs, const labelUList &recvSizes, List< Container > &recvBufs, const int tag=UPstream::msgType(), const int comm=UPstream::worldComm, const bool wait=true)
Helper: exchange contiguous data. Sends sendBufs, receives into recvBufs using predetermined receive ...
static void exchangeSizes(const labelUList &sendProcs, const labelUList &recvProcs, const Container &sendBufs, labelList &sizes, const int tag=UPstream::msgType(), const int comm=UPstream::worldComm)
Helper: exchange sizes of sendBufs for specified send/recv ranks.
A non-owning sub-view of a List (allocated or unallocated storage).
Definition SubList.H:61
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
T & last()
Access last element of the list, position [size()-1].
Definition UList.H:971
bool send()
Send buffer contents now and not in destructor [advanced usage]. Returns true on success.
Definition OPstreams.C:84
Inter-processor communications stream.
Definition UPstream.H:69
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
Definition UPstream.H:1706
commsTypes
Communications types.
Definition UPstream.H:81
@ scheduled
"scheduled" (MPI standard) : (MPI_Send, MPI_Recv)
Definition UPstream.H:83
static bool parRun(const bool on) noexcept
Set as parallel run on/off.
Definition UPstream.H:1669
static int & msgType() noexcept
Message tag of standard messages.
Definition UPstream.H:1926
static constexpr int masterNo() noexcept
Relative rank for the master process - is always 0.
Definition UPstream.H:1691
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run.
Definition UPstream.H:1697
static rangeType subProcs(const label communicator=worldComm)
Range of process indices for sub-processes.
Definition UPstream.H:1866
@ broadcast
broadcast [MPI]
Definition UPstream.H:189
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition UPtrList.H:101
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie,...
Definition UPtrList.H:366
label size() const noexcept
The number of entries in the list.
Definition UPtrListI.H:106
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition bitSet.H:61
unsigned int count(const bool on=true) const
Count number of bits set.
Definition bitSetI.H:420
bitSet & unset(const bitSet &other)
Unset (subtract) the bits specified in the other bitset, which is a set difference corresponds to the...
Definition bitSetI.H:540
Determines the order in which a set of processors should communicate with one another.
Calculates a non-overlapping list of offsets based on an input size (eg, number of cells) from differ...
Definition globalIndex.H:77
label toLocal(const label proci, const label i) const
From global to local on proci.
label whichProcID(const label proci, const label i) const
Which processor does global id come from? Checks proci first (assumed to occur reasonably frequently)...
bool isLocal(const label proci, const label i) const
Is on processor proci.
label localSize(const label proci) const
Size of proci data.
Class containing processor-to-processor mapping information.
mapDistributeBase() noexcept
Default construct (uses worldComm).
void operator=(const mapDistributeBase &rhs)
Copy assignment.
const List< labelPair > & whichSchedule(const UPstream::commsTypes commsType) const
Return real or dummy schedule depending on the communication type.
const List< labelPair > & schedule() const
Return a schedule. Demand driven. See above.
void printLayout(Ostream &os) const
Debug: print layout. Can only be used on maps with sorted.
const labelListList & constructMap() const noexcept
From subsetted data to new reconstructed data.
void transfer(mapDistributeBase &rhs)
Transfer the contents of the argument and annul the argument.
static List< labelPair > schedule(const labelListList &subMap, const labelListList &constructMap, const int tag, const label comm=UPstream::worldComm)
Calculate a communication schedule. See above.
bool constructHasFlip() const noexcept
Does constructMap include a sign.
const labelListList & subMap() const noexcept
From subsetted data back to original data.
void calcCompactAddressing(const globalIndex &globalNumbering, const labelUList &elements, List< Map< label > > &compactMap) const
Construct per processor compact addressing of the global elements.
static void checkReceivedSize(const label proci, const label expectedSize, const label receivedSize)
Fatal if expected != received size.
bool subHasFlip() const noexcept
Does subMap include a sign.
labelList constructMapSizes() const
The sizes of the constructMap lists.
void exchangeAddressing(const int tag, const globalIndex &globalNumbering, labelList &elements, List< Map< label > > &compactMap, labelList &compactStart)
static label renumber(const globalIndex &, const label comm, const List< Map< label > > &compactMap, const label globalElement)
Helper for construct from globalIndex. Renumbers element.
labelList subMapSizes() const
The sizes of the subMap lists.
static label countUnmapped(const labelUList &elements, const labelListList &maps, const bool hasFlip)
Count the number of unmapped elements.
static label getMappedSize(const labelListList &maps, const bool hasFlip)
Scan the maps for the max addressed index.
label comm() const noexcept
The communicator used.
void clear()
Reset to zero size, only retaining communicator.
static bool hasFlipAddressing(const labelUList &map)
Test for flip addressing, where flips are encoded as negative indices and non-flips are encoded as po...
label subMapTotalSize() const noexcept
The sum of the subMap list sizes.
label constructMapTotalSize() const noexcept
The sum of the constructMap list sizes.
layoutTypes
The map layout (eg, of the constructMap).
label constructSize() const noexcept
Constructed data size.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
OBJstream os(runTime.globalPath()/outputName)
A HashTable to objects of type <T> with a labelPair key. The hashing is based on labelPair (FixedList...
Namespace for handling debugging switches.
Definition debug.C:45
Namespace for OpenFOAM.
Pair< label > labelPair
A pair of labels.
Definition Pair.H:54
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
List< label > labelList
A List of labels.
Definition List.H:62
constexpr label labelMin
Definition label.H:54
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values within a list.
constexpr label labelMax
Definition label.H:55
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:26
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition FlatOutput.H:217
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
errorManip< error > abort(error &err)
Definition errorManip.H:139
void rhs(fvMatrix< typename Expr::value_type > &m, const Expr &expression)
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
const direction noexcept
Definition scalarImpl.H:265
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
UList< label > labelUList
A UList of labels.
Definition UList.H:75
HashSet< labelPair, Foam::Hash< labelPair > > labelPairHashSet
A HashSet for a labelPair. The hashing is based on labelPair (FixedList) and is thus non-commutative.
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
#define forAllIters(container, iter)
Iterate across all elements in the container object.
Definition stdFoam.H:214