globalIndex.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2018-2025 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 Class
28  Foam::globalIndex
29 
30 Description
31  Calculates a unique integer (label so might not have enough room - 2G max)
32  for processor + local index. E.g.
33 
34  globalIndex globalFaces(mesh.nFaces());
35  label globalFacei = globalFaces.toGlobal(facei);
36 
37 SourceFiles
38  globalIndex.C
39  globalIndexI.H
40  globalIndex.txx
41 
42 \*---------------------------------------------------------------------------*/
43 
44 #ifndef Foam_globalIndex_H
45 #define Foam_globalIndex_H
46 
47 #include "Pstream.H"
48 #include "CompactListList.H"
49 #include "DynamicList.H"
50 
51 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
52 
53 namespace Foam
54 {
55 
56 // Forward Declarations
57 class globalIndex;
58 
59 Istream& operator>>(Istream& is, globalIndex& gi);
60 Ostream& operator<<(Ostream& os, const globalIndex& gi);
61 
62 /*---------------------------------------------------------------------------*\
63  Class globalIndex Declaration
64 \*---------------------------------------------------------------------------*/
65 
66 class globalIndex
67 {
68  // Private Data
69 
70  //- Offset (addressing) table - like CompactListList
71  labelList offsets_;
72 
73 
74  // Private Member Functions
75 
76  //- Sort and bin. validBins contains bins with non-zero size.
78  bin
79  (
80  const labelUList& offsets,
81  const labelUList& globalIds,
82  labelList& order,
83  DynamicList<label>& validBins
84  );
85 
86  // Cannot use non-blocking for non-contiguous data.
87  // template<class Type>
88  // inline static UPstream::commsTypes getCommsType
89  // (
90  // UPstream::commsTypes commsType
91  // ) noexcept;
92 
93  //- Report overflow at specified (non-negative) index
94  static void reportOverflowAndExit
95  (
96  const label idx,
97  const label prevOffset = -1, // The last valid offset value
98  const label count = 0 // The count to add to prevOffset
99  );
100 
101 public:
102 
103  // Public Data Types
104 
105  //- Dispatch tag:
106  //- Construct with a single (local size) entry, no communication.
107  struct gatherNone{};
108 
109  //- Dispatch tag:
110  //- Construct 'one-sided' from local sizes,
111  //- using gather but no broadcast.
112  struct gatherOnly{};
113 
114  //- Dispatch tag:
115  //- Construct 'one-sided' from the non-master local sizes
116  //- using gather but no broadcast.
117  struct gatherNonLocal{};
118 
119 
120  // Static Member Functions
121 
122  //- Return a null globalIndex (reference to a nullObject).
123  //- Behaves like an empty globalIndex
124  static const globalIndex& null() noexcept
125  {
126  return NullObjectRef<globalIndex>();
127  }
128 
129 
130  // Constructors
131 
132  //- Default construct (empty)
133  globalIndex() noexcept = default;
134 
135  //- Copy construct from a list of offsets.
136  //- No communication required
137  inline explicit globalIndex(const labelUList& listOffsets);
138 
139  //- Move construct from a list of offsets.
140  //- No communication required
141  inline explicit globalIndex(labelList&& listOffsets);
142 
143  //- Construct from a list of sizes and calculate the offsets.
144  //- No communication required
145  inline globalIndex
146  (
147  const globalIndex::gatherNone,
148  const labelUList& localSizes
149  );
150 
151  //- Construct from local size, using gather/broadcast
152  //- with default/specified communicator if parallel.
153  inline explicit globalIndex
154  (
155  const label localSize,
156  const label comm = UPstream::worldComm,
157  const bool parallel = UPstream::parRun()
158  );
159 
160  //- Construct with a single (local size) entry, no communication
161  inline globalIndex
162  (
163  const globalIndex::gatherNone,
164  const label localSize,
165  const label comm = -1
166  );
167 
168  //- Construct 'one-sided' from local sizes.
169  //- Uses UPstream::listGatherValues, but no broadcast.
170  //- Will be empty on non-master processes.
171  //
172  // \note can be used when Pstream::parRun() is false.
173  inline globalIndex
174  (
175  const globalIndex::gatherOnly,
176  const label localSize,
177  const label comm = UPstream::worldComm
178  );
179 
180  //- Construct 'one-sided' from the non-master local sizes
181  //- (ie, master size is treated as 0).
182  //- Uses UPstream::listGatherValues, but no broadcast.
183  //- Will be empty on non-master processes.
184  //
185  // \note can be used when Pstream::parRun() is false.
186  inline globalIndex
187  (
189  const label localSize,
190  const label comm = UPstream::worldComm
191  );
192 
193  //- Construct from Istream.
194  //- No communication required
195  explicit globalIndex(Istream& is);
196 
197 
198  // Member Functions
199 
200  //- Check for default constructed or total-size == 0
201  inline bool empty() const noexcept;
202 
203  //- The number of items covered by the offsets
204  inline label length() const noexcept;
205 
206  //- Global sum of localSizes. Same as totalSize()
207  FOAM_DEPRECATED_STRICT(2022-10, "totalSize() - unambiguous")
208  inline label size() const;
209 
210  //- The span size covered by the offsets, zero if empty
211  inline label span() const noexcept;
212 
213  //- The total addressed size, which corresponds to the
214  //- end offset and also the sum of all localSizes.
215  inline label totalSize() const noexcept;
216 
217  //- The local sizes. Same as localSizes()
218  inline labelList sizes() const;
219 
220  //- The local starts
221  inline const labelUList localStarts() const;
222 
223  //- The local sizes
224  labelList localSizes() const;
225 
226  //- Return start/size ranges for all data
227  List<labelRange> ranges() const;
228 
229  //- Global max of localSizes
230  inline label maxSize() const;
231 
232 
233  // Access
234 
235  //- Const-access to the offsets
236  inline const labelList& offsets() const noexcept;
237 
238  //- Write-access to the offsets, for changing after construction
239  inline labelList& offsets() noexcept;
240 
241 
242  // Dimensions
243 
244  //- True if local-only content (ie, nProcs == 1).
245  //- Such content is often created with gatherNone.
246  inline bool single() const noexcept;
247 
248  //- The number of processors covered by the offsets,
249  //- same as the primary length()
250  inline label nProcs() const noexcept;
251 
252  //- Range of process indices for all addressed offsets (processes)
253  inline labelRange allProcs() const noexcept;
254 
255  //- Range of process indices for addressed sub-offsets (processes)
256  inline labelRange subProcs() const noexcept;
257 
258  //- The value corresponding to the first offset
259  inline label begin_value() const noexcept;
260 
261  //- The value corresponding to the last offset (end offset),
262  //- which is 1 beyond the end of the range.
263  inline label end_value() const noexcept;
264 
265  //- The first offset range. It is (0,0) if globalIndex is empty
266  labelRange front() const;
267 
268  //- The last offset range. It is (0,0) if globalIndex is empty
269  labelRange back() const;
270 
271 
272  // Edit
273 
274  //- Reset to be empty (no offsets)
275  inline void clear();
276 
277  //- Change the number of entries (nProcs) in the offsets table.
278  //- Extending will fill with empty local sizes.
279  void resize(const label n);
280 
281  //- Reset from local size, using gather/broadcast
282  //- with default/specified communicator if parallel.
283  void reset
284  (
285  const label localSize,
286  const label comm = UPstream::worldComm,
287  const bool parallel = UPstream::parRun()
288  );
289 
290  //- Reset offsets from a list of local sizes,
291  //- with optional check for label overflow.
292  //- No communication required
293  void reset
294  (
295  const labelUList& counts,
296  const bool checkOverflow = false
297  );
298 
299  //- Reset to a single (local size) entry, no communication
300  inline void reset
301  (
302  const globalIndex::gatherNone,
303  const label localSize,
304  const label comm = -1
305  );
306 
307  //- Reset as 'one-sided' from local sizes.
308  //- Uses UPstream::listGatherValues, but no broadcast.
309  //- Will be empty on non-master processes.
310  //
311  // \note can be used when Pstream::parRun() is false.
312  inline void reset
313  (
314  const globalIndex::gatherOnly,
315  const label localSize,
316  const label comm = UPstream::worldComm
317  );
318 
319  //- Reset as 'one-sided' from the non-master local sizes
320  //- (ie, master size is treated as 0).
321  //- Uses UPstream::listGatherValues, but no broadcast.
322  //- Will be empty on non-master processes.
323  //
324  // \note can be used when Pstream::parRun() is false.
325  inline void reset
326  (
328  const label localSize,
329  const label comm = UPstream::worldComm
330  );
331 
332  //- Reset the globalIndex. Same as copy assignment.
333  inline void reset(const globalIndex& gi);
334 
335  //- Alter local size for given processor
336  void setLocalSize(const label proci, const label len);
337 
338 
339  // Queries and renumbering
340 
341  //- True if contained within the offsets range
342  inline bool contains(const label i) const noexcept;
343 
344  //- Start of proci data
345  inline label localStart(const label proci) const;
346 
347  //- End of proci data
348  inline label localEnd(const label proci) const;
349 
350  //- Size of proci data
351  inline label localSize(const label proci) const;
352 
353  //- The max of localSizes, excluding the specified processor
354  label maxNonLocalSize(const label proci) const;
355 
356  //- Return start/size range of proci data
357  inline labelRange range(const label proci) const;
358 
359  //- Is on processor proci
360  inline bool isLocal(const label proci, const label i) const;
361 
362  //- From local to global on proci
363  inline label toGlobal(const label proci, const label i) const;
364 
365  //- From local to global on proci
366  inline labelList toGlobal
367  (
368  const label proci,
369  const labelUList& labels
370  ) const;
371 
372  //- From local to global index on proci (inplace)
373  inline void inplaceToGlobal
374  (
375  const label proci,
376  labelUList& labels
377  ) const;
378 
379 
380  //- From global to local on proci
381  inline label toLocal(const label proci, const label i) const;
382 
383  //- Find processor with specified global id.
384  //- Check proci first, followed by binary search.
385  // \return the processor number or -1 (not found)
386  inline label findProc(const label proci, const label i) const;
387 
388  //- Find processor above proci with specified global id - binary search.
389  // \return the processor above proci or -1 otherwise
390  // (including for out-of-range indices)
391  inline label findProcAbove(const label proci, const label i) const;
392 
393  //- Find processor below proci with specified global id - binary search.
394  // Binary search.
395  // \return the processor below proci or -1 otherwise
396  // (including for out-of-range indices)
397  inline label findProcBelow(const label proci, const label i) const;
398 
399  //- Which processor does global id come from?
400  //- Checks proci first (assumed to occur reasonably frequently)
401  //- followed by a binary search.
402  //- Fatal for out-of-range indices
403  inline label whichProcID(const label proci, const label i) const;
404 
405 
406  // Queries relating to myProcNo (Caution: uses UPstream::worldComm)
407 
408  //- Local start on myProcNo()
409  inline label localStart() const;
410 
411  //- Local end on myProcNo()
412  inline label localEnd() const;
413 
414  //- Local size on myProcNo()
415  inline label localSize() const;
416 
417  //- The max of localSizes, excluding current (myProcNo) rank
418  inline label maxNonLocalSize() const;
419 
420  //- Return start/size range of local (myProcNo) data
421  inline labelRange range() const;
422 
423  //- Is on local processor
424  inline bool isLocal(const label i) const;
425 
426  //- From local to global index
427  inline label toGlobal(const label i) const;
428 
429  //- From local to global index
430  inline labelList toGlobal(const labelUList& labels) const;
431 
432  //- From local to global index (inplace)
433  inline void inplaceToGlobal(labelUList& labels) const;
434 
435  //- From global to local on current processor.
436  // FatalError if not on local processor.
437  inline label toLocal(const label i) const;
438 
439  //- Which processor does global id come from?
440  // Uses myProcNo for the initial local check.
441  inline label whichProcID(const label i) const;
442 
443 
444  // Iteration
445 
446  //- Forward input iterator with const access that is used to
447  //- iterate across the globalIndex offsets() table.
448  // The de-referenced value is the range() with (start, size),
449  // but it also provides separate index, start, size information.
450  class const_iterator
451  {
452  //- The parent class for which this is an iterator
453  const globalIndex* parent_;
454 
455  //- The index into the parent
456  label index_;
457 
458  public:
459 
460  // Constructors
461 
462  //- Construct from globalIndex list at given index
463  explicit const_iterator
464  (
465  const globalIndex* globalIdx,
466  const label i = 0
467  ) noexcept;
468 
469 
470  // Member Operators
471 
472  //- The index into the arrays
473  inline label index() const noexcept;
474 
475  //- The local start
476  inline label start() const;
477 
478  //- The local size
479  inline label size() const;
480 
481  //- The local range
482  inline labelRange range() const;
483 
484  //- The local range
485  inline labelRange operator*() const;
486 
487  inline const_iterator& operator++();
488  inline const_iterator operator++(int);
489 
490  inline const_iterator& operator--();
491  inline const_iterator operator--(int);
492 
493  inline bool operator==(const const_iterator& iter) const noexcept;
494  inline bool operator!=(const const_iterator& iter) const noexcept;
495  };
496 
497 
498  //- A const_iterator set to the beginning
499  inline const_iterator cbegin() const noexcept;
500 
501  //- A const_iterator set to beyond the end
502  inline const const_iterator cend() const noexcept;
503 
504  //- A const_iterator set to the beginning
505  inline const_iterator begin() const noexcept;
506 
507  //- A const_iterator set to beyond the end
508  inline const const_iterator end() const noexcept;
509 
510  //- Return const_iterator at offset proci from begin,
511  //- clamped to [0,nProcs] range
512  inline const_iterator cbegin(const label proci) const noexcept;
513 
514  //- Return const_iterator at offset proci from begin,
515  //- clamped to [0,nProcs] range
516  inline const_iterator begin(const label proci) const noexcept;
517 
518  // FUTURE?
519  // //- Return start/size range of proci data
520  // labelRange operator[](const label proci) const
521  // {
522  // return this->range(proci);
523  // }
524 
525 
526  // Helper Functions
527 
528  //- Calculate globally-consistent local range (offset/size)
529  //- based on the local input size(s).
530  // Effectively the same as globalIndex(localSize).range()
531  // but without constructing an extra intermediate list of offsets
532  static labelRange calcRange
533  (
534  const label localSize,
535  const label comm = UPstream::worldComm,
536  const bool checkOverflow = false
537  );
538 
539  //- Calculate globally-consistent local start offset
540  //- based on the local input size(s).
541  // Effectively the same as globalIndex(localSize).localStart()
542  // but without constructing an extra intermediate list of offsets
543  static label calcOffset
544  (
545  const label localSize,
546  const label comm = UPstream::worldComm,
547  const bool checkOverflow = false
548  );
549 
550  //- Calculate offsets from a list of local sizes,
551  //- with optional check for label overflow
552  static labelList calcOffsets
553  (
554  const labelUList& counts,
555  const bool checkOverflow = false
556  );
557 
558  //- Calculate offsets from an indirect list of local sizes,
559  //- with optional check for label overflow
560  template<class Addr>
561  static labelList calcOffsets
562  (
563  const IndirectListBase<label, Addr>& counts,
564  const bool checkOverflow = false
565  );
566 
567  //- Calculate offsets from list of lists,
568  //- with optional check for label overflow
569  template<class SubListType>
571  (
572  const List<SubListType>& lists,
573  const bool checkOverflow = false
574  );
575 
576  //- Calculate ranges (offset/size) from a list of local sizes,
577  //- with optional check for label overflow
578  static List<labelRange> calcRanges
579  (
580  const labelUList& counts,
581  const bool checkOverflow = false
582  );
583 
584  //- Split the top-level offsets into inter-node and local-node
585  //- components suitable to a two-stage hierarchy.
586  bool splitNodeOffsets
587  (
589  labelList& interNodeOffsets,
591  labelList& localNodeOffsets,
593  const label communicator = UPstream::worldComm,
595  const bool absoluteLocalNodeOffsets = false
596  ) const;
597 
598 
599  // Misc low-level gather routines
600 
601  //- Collect single values in processor order on master (== procIDs[0]).
602  // Handles contiguous/non-contiguous data.
603  // non-zero output field (master only)
604  template<class ProcIDsContainer, class Type>
605  [[nodiscard]]
606  static List<Type> listGatherValues
607  (
608  const label comm,
609  const ProcIDsContainer& procIDs,
610  const Type& localValue,
611  const int tag = UPstream::msgType(),
612  UPstream::commsTypes commsType = UPstream::commsTypes::nonBlocking
613  );
614 
615  //- Collect data in processor order on master (== procIDs[0]).
616  // Handles contiguous/non-contiguous data, skips empty fields.
617  template<class ProcIDsContainer, class Type>
618  static void gather
619  (
620  const labelUList& offsets,
621  const label comm,
622  const ProcIDsContainer& procIDs,
623  const UList<Type>& fld,
624  UList<Type>& allFld,
626  const int tag = UPstream::msgType(),
627  UPstream::commsTypes commsType = UPstream::commsTypes::nonBlocking
628  );
629 
630  //- Collect indirect data in processor order on master
631  // Handles contiguous/non-contiguous data, skips empty fields.
632  template<class ProcIDsContainer, class Type, class Addr>
633  static void gather
634  (
635  const labelUList& offsets,
636  const label comm,
637  const ProcIDsContainer& procIDs,
638  const IndirectListBase<Type, Addr>& fld,
639  UList<Type>& allFld,
641  const int tag = UPstream::msgType(),
642  UPstream::commsTypes commsType = UPstream::commsTypes::nonBlocking
643  );
644 
645  //- Inplace collect in processor order on master (== procIDs[0]).
646  template<class ProcIDsContainer, class Type>
647  static void gatherInplace
648  (
649  const labelUList& offsets,
650  const label comm,
651  const ProcIDsContainer& procIDs,
652  List<Type>& fld,
653  const int tag = UPstream::msgType(),
654  UPstream::commsTypes commsType = UPstream::commsTypes::nonBlocking
655  );
656 
657  //- Collect data in processor order on master (== procIDs[0]).
658  // \note the globalIndex offsets needed on master only.
659  template<class ProcIDsContainer, class Type>
660  void gather
661  (
662  const label comm,
663  const ProcIDsContainer& procIDs,
664  const UList<Type>& fld,
665  List<Type>& allFld,
667  const int tag = UPstream::msgType(),
668  UPstream::commsTypes commsType = UPstream::commsTypes::nonBlocking
669  ) const;
670 
671  //- Inplace collect in processor order on master (== procIDs[0]).
672  // \note the globalIndex offsets needed on master only.
673  template<class ProcIDsContainer, class Type>
674  void gatherInplace
675  (
676  const label comm,
677  const ProcIDsContainer& procIDs,
678  List<Type>& fld,
679  const int tag = UPstream::msgType(),
680  UPstream::commsTypes commsType = UPstream::commsTypes::nonBlocking
681  ) const
682  {
683  gatherInplace(offsets_, comm, procIDs, fld, tag, commsType);
684  }
685 
686 
687  // Gather
688 
689  //- Collect data in processor order on master
690  //- (in serial: performs a simple copy).
691  // Communication with default/specified communicator, message tag.
692  template<class Type>
693  void gather
694  (
696  const UList<Type>& sendData,
698  List<Type>& allData,
699  const int tag = UPstream::msgType(),
701  const label comm = UPstream::worldComm
702  ) const;
703 
704  //- Collect data indirectly in processor order on master
705  //- (in serial: performs a simple copy).
706  // Communication with default/specified communicator, message tag.
707  template<class Type, class Addr>
708  void gather
709  (
711  const IndirectListBase<Type, Addr>& sendData,
713  List<Type>& allData,
714  const int tag = UPstream::msgType(),
716  const label comm = UPstream::worldComm
717  ) const;
718 
719  //- Collect data in processor order on master
720  //- (in serial: performs a simple copy).
721  // Communication with default/specified communicator, message tag.
722  //
723  // \return output (master), zero-sized on non-master
724  template<class Type, class OutputContainer = List<Type>>
725  [[nodiscard]]
726  OutputContainer gather
727  (
728  const UList<Type>& sendData,
729  const int tag = UPstream::msgType(),
731  const label comm = UPstream::worldComm
732  ) const;
733 
734  //- Collect data indirectly in processor order on master.
735  // Communication with default/specified communicator, message tag.
736  //
737  // \return output (master), zero-sized on non-master
738  template<class Type, class Addr, class OutputContainer = List<Type>>
739  [[nodiscard]]
740  OutputContainer gather
741  (
742  const IndirectListBase<Type, Addr>& sendData,
743  const int tag = UPstream::msgType(),
745  const label comm = UPstream::worldComm
746  ) const;
747 
748  //- Inplace collect data in processor order on master
749  //- (in serial: a no-op).
750  // Communication with default/specified communicator, message tag.
751  // After the gather, the field is zero-sized on non-master.
752  template<class Type>
753  void gatherInplace
754  (
755  List<Type>& fld,
756  const int tag = UPstream::msgType(),
758  const label comm = UPstream::worldComm
759  ) const;
760 
761  //- Use MPI_Gatherv call for contiguous data when possible
762  //- (in serial: performs a simple copy).
763  // Communication with default/specified communicator.
764  // \attention The nProcs for globalIndex and communicator
765  // must match!!
766  template<class Type, class OutputContainer = List<Type>>
767  void mpiGather
768  (
769  const UList<Type>& sendData,
771  OutputContainer& allData,
772  const label comm = UPstream::worldComm,
773 
774  // For fallback routines:
776  const int tag = UPstream::msgType()
777  ) const;
778 
779  //- Use MPI_Gatherv call for contiguous data when possible
780  //- (in serial: performs a simple copy).
781  // Communication with default/specified communicator.
782  // \attention The nProcs for globalIndex and communicator
783  // must match!!
784  //
785  // \return output (master), zero-sized on non-master
786  template<class Type, class OutputContainer = List<Type>>
787  [[nodiscard]]
788  OutputContainer mpiGather
789  (
790  const UList<Type>& sendData,
791  const label comm = UPstream::worldComm,
792 
793  // For fallback routines:
795  const int tag = UPstream::msgType()
796  ) const;
797 
798  //- Use MPI_Gatherv call to inplace collect contiguous data
799  //- when possible.
800  //- (in serial: a no-op).
801  // Communication with default/specified communicator.
802  // \attention The nProcs for globalIndex and communicator
803  // must match!!
804  //
805  // After the gather, the field is zero-sized on non-master.
806  template<class Type>
807  void mpiGatherInplace
808  (
810  List<Type>& fld,
811  const label comm = UPstream::worldComm,
812 
813  // For fallback routines:
815  const int tag = UPstream::msgType()
816  ) const;
817 
818 
819  // Gather Operations
820 
821  //- Use MPI_Gatherv call to collect contiguous data when possible
822  //- (in serial: performs a simple copy).
823  // Communication with default/specified communicator.
824  //
825  // The allData is output (master), zero-sized on non-master
826  template<class Type, class OutputContainer = List<Type>>
827  static void mpiGatherOp
828  (
829  const UList<Type>& sendData,
830  OutputContainer& allData,
831  const label comm = UPstream::worldComm,
832 
833  // For fallback routines:
835  const int tag = UPstream::msgType()
836  );
837 
838  //- Use MPI_Gatherv call to collect contiguous data when possible
839  //- (in serial: performs a simple copy).
840  // Communication with default/specified communicator.
841  //
842  // \return output (master), zero-sized on non-master
843  template<class Type, class OutputContainer = List<Type>>
844  [[nodiscard]]
845  static OutputContainer mpiGatherOp
846  (
847  const UList<Type>& sendData,
848  const label comm = UPstream::worldComm,
849 
850  // For fallback routines:
852  const int tag = UPstream::msgType()
853  );
854 
855  //- Use MPI_Gatherv call to inplace collect contiguous data
856  //- when possible.
857  //- (in serial: a no-op).
858  // Communication with default/specified communicator.
859  //
860  // After the gather, the field is zero-sized on non-master.
861  template<class Type>
862  static void mpiGatherInplaceOp
863  (
865  List<Type>& fld,
866  const label comm = UPstream::worldComm,
867 
868  // For fallback routines:
870  const int tag = UPstream::msgType()
871  );
872 
873  //- Collect data in processor order on master
874  //- (in serial: performs a simple copy).
875  // Communication with default/specified communicator, message tag.
876  template<class Type>
877  static void gatherOp
878  (
879  const UList<Type>& sendData,
881  List<Type>& allData,
882  const int tag = UPstream::msgType(),
884  const label comm = UPstream::worldComm
885  );
886 
887  //- Collect data in processor order on master
888  //- (in serial: performs a simple copy).
889  // Communication with default/specified communicator, message tag.
890  template<class Type, class Addr>
891  static void gatherOp
892  (
893  const IndirectListBase<Type, Addr>& sendData,
895  List<Type>& allData,
896  const int tag = UPstream::msgType(),
898  const label comm = UPstream::worldComm
899  );
900 
901  //- Collect and return data in processor order on master
902  //- (in serial: performs a simple copy).
903  // Communication with default/specified communicator, message tag.
904  //
905  // \return output (master), zero-sized on non-master
906  template<class Type, class OutputContainer = List<Type>>
907  [[nodiscard]]
908  static OutputContainer gatherOp
909  (
910  const UList<Type>& sendData,
911  const int tag = UPstream::msgType(),
913  const label comm = UPstream::worldComm
914  );
915 
916  //- Collect and return data in processor order on master
917  //- (in serial: performs a simple copy).
918  // Communication with default/specified communicator, message tag.
919  //
920  // \return output (master), zero-sized on non-master
921  template<class Type, class Addr, class OutputContainer = List<Type>>
922  [[nodiscard]]
923  static OutputContainer gatherOp
924  (
925  const IndirectListBase<Type, Addr>& sendData,
926  const int tag = UPstream::msgType(),
928  const label comm = UPstream::worldComm
929  );
930 
931  //- Inplace collect data in processor order on master
932  //- (in serial: a no-op).
933  // Communication with default/specified communicator, message tag.
934  //
935  // After the gather, the field is zero-sized on non-master.
936  template<class Type>
937  static void gatherInplaceOp
938  (
940  List<Type>& fld,
941  const int tag = UPstream::msgType(),
943  const label comm = UPstream::worldComm
944  );
945 
946 
947  // Scatter
948 
949  //- Distribute data in processor order.
950  // Requires fld to be correctly sized!
951  // Communication with default/specified communicator, message tag.
952  template<class ProcIDsContainer, class Type>
953  static void scatter
954  (
955  const labelUList& offsets,
956  const label comm,
957  const ProcIDsContainer& procIDs,
958  const UList<Type>& allFld,
959  UList<Type>& fld,
960  const int tag = UPstream::msgType(),
962  );
963 
964  //- Distribute data in processor order.
965  // Requires fld to be correctly sized!
966  // Communication with default/specified communicator, message tag.
967  // \note the globalIndex offsets needed on master only.
968  template<class ProcIDsContainer, class Type>
969  void scatter
970  (
971  const label comm,
972  const ProcIDsContainer& procIDs,
973  const UList<Type>& allFld,
974  UList<Type>& fld,
975  const int tag = UPstream::msgType(),
977  ) const
978  {
979  scatter(offsets_, comm, procIDs, allFld, fld, tag, commsType);
980  }
981 
982  //- Distribute data in processor order.
983  // Requires fld to be correctly sized!
984  // Communication with default/specified communicator, message tag.
985  // \note the globalIndex offsets needed on master only.
986  template<class Type>
987  void scatter
988  (
989  const UList<Type>& allData,
990  UList<Type>& localData,
991  const int tag = UPstream::msgType(),
993  const label comm = UPstream::worldComm
994  ) const;
995 
996  //- Distribute data in processor order
997  //- (in serial: performs a simple copy).
998  // Communication with default/specified communicator, message tag.
999  // \note the globalIndex offsets needed on master only.
1000  template<class Type, class OutputContainer = List<Type>>
1001  [[nodiscard]]
1002  OutputContainer scatter
1003  (
1004  const UList<Type>& allData,
1005  const int tag = UPstream::msgType(),
1007  const label comm = UPstream::worldComm
1008  ) const;
1009 
1010 
1011  // Scatter
1012 
1013  //- Get (potentially remote) data.
1014  //- Elements required given as global indices
1015  // Communication with default/specified communicator, message tag.
1016  template<class Type, class CombineOp>
1017  void get
1018  (
1019  List<Type>& allFld,
1020  const labelUList& globalIds,
1021  const CombineOp& cop,
1022  const label comm = UPstream::worldComm,
1023  const int tag = UPstream::msgType()
1024  ) const;
1025 
1026 
1027  // Member Operators
1028 
1029  //- Compare for equality - uses the offsets
1030  bool operator==(const globalIndex& rhs) const
1031  {
1032  return (this->offsets() == rhs.offsets());
1033  }
1034 
1035  //- Compare for inequality - uses the offsets
1036  bool operator!=(const globalIndex& rhs) const
1037  {
1038  return !(*this == rhs);
1039  }
1040 
1041  //- Compare for less-than - uses the offsets
1042  bool operator<(const globalIndex& rhs) const
1043  {
1044  return (this->offsets() < rhs.offsets());
1045  }
1046 
1047 
1048  // IOstream Operators
1049 
1050  friend Istream& operator>>(Istream& is, globalIndex& gi);
1051  friend Ostream& operator<<(Ostream& os, const globalIndex& gi);
1052 
1053 
1054  // Housekeeping
1055 
1056  //- Construct from local size, using gather/broadcast
1057  //- with default/specified communicator if parallel.
1058  FOAM_DEPRECATED_FOR(2022-03, "construct without message tag")
1059  globalIndex
1060  (
1061  const label localSize,
1062  const int tag, // message tag (unused)
1063  const label comm, // communicator
1064  const bool parallel // use parallel comms
1065  )
1066  {
1067  reset(localSize, comm, parallel);
1068  }
1069 
1070  //- Reset from local size, using gather/broadcast
1071  //- with default/specified communicator if parallel.
1072  FOAM_DEPRECATED_FOR(2022-03, "reset without message tag")
1073  void reset
1074  (
1075  const label localSize,
1076  const int tag, // message tag (unused)
1077  const label comm, // communicator
1078  const bool parallel // use parallel comms
1079  )
1080  {
1081  reset(localSize, comm, parallel);
1082  }
1083 
1084  //- Prefer localStart() to avoid confusing with offsets()
1085  FOAM_DEPRECATED_FOR(2022-02, "use localStart()")
1086  label offset(const label proci) const { return localStart(proci); }
1087 };
1088 
1089 
1090 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1091 
1092 } // End namespace Foam
1093 
1094 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1095 
1096 #include "globalIndexI.H"
1097 
1098 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1099 
1100 #ifdef NoRepository
1101  #include "globalIndex.txx"
1102 #endif
1103 
1104 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1105 
1106 #endif
1107 
1108 // ************************************************************************* //
label toLocal(const label proci, const label i) const
From global to local on proci.
Definition: globalIndexI.H:377
static labelList calcOffsets(const labelUList &counts, const bool checkOverflow=false)
Calculate offsets from a list of local sizes, with optional check for label overflow.
Definition: globalIndex.C:189
void reset(const label localSize, const label comm=UPstream::worldComm, const bool parallel=UPstream::parRun())
Reset from local size, using gather/broadcast with default/specified communicator if parallel...
Definition: globalIndex.C:452
static const globalIndex & null() noexcept
Return a null globalIndex (reference to a nullObject). Behaves like an empty globalIndex.
Definition: globalIndex.H:133
static void mpiGatherOp(const UList< Type > &sendData, OutputContainer &allData, const label comm=UPstream::worldComm, UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking, const int tag=UPstream::msgType())
Use MPI_Gatherv call to collect contiguous data when possible (in serial: performs a simple copy)...
commsTypes
Communications types.
Definition: UPstream.H:77
List< labelRange > ranges() const
Return start/size ranges for all data.
Definition: globalIndex.C:562
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:52
bool operator<(const globalIndex &rhs) const
Compare for less-than - uses the offsets.
Definition: globalIndex.H:1321
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
label whichProcID(const label proci, const label i) const
Which processor does global id come from? Checks proci first (assumed to occur reasonably frequently)...
Definition: globalIndexI.H:485
friend Ostream & operator<<(Ostream &os, const globalIndex &gi)
static List< labelRange > calcRanges(const labelUList &counts, const bool checkOverflow=false)
Calculate ranges (offset/size) from a list of local sizes, with optional check for label overflow...
Definition: globalIndex.C:223
Dispatch tag: Construct &#39;one-sided&#39; from local sizes, using gather but no broadcast.
Definition: globalIndex.H:117
bool contains(const label i) const noexcept
True if contained within the offsets range.
Definition: globalIndexI.H:159
label end_value() const noexcept
The value corresponding to the last offset (end offset), which is 1 beyond the end of the range...
Definition: globalIndexI.H:152
label begin_value() const noexcept
The value corresponding to the first offset.
Definition: globalIndexI.H:146
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1787
label span() const noexcept
The span size covered by the offsets, zero if empty.
Definition: globalIndexI.H:140
static void gather(const labelUList &offsets, const label comm, const ProcIDsContainer &procIDs, const UList< Type > &fld, UList< Type > &allFld, const int tag=UPstream::msgType(), UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking)
Collect data in processor order on master (== procIDs[0]).
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:987
friend Istream & operator>>(Istream &is, globalIndex &gi)
labelList localSizes() const
The local sizes.
Definition: globalIndex.C:539
static void gatherInplaceOp(List< Type > &fld, const int tag=UPstream::msgType(), UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking, const label comm=UPstream::worldComm)
Inplace collect data in processor order on master (in serial: a no-op).
Base for lists with indirect addressing, templated on the list contents type and the addressing type...
void inplaceToGlobal(const label proci, labelUList &labels) const
From local to global index on proci (inplace)
Definition: globalIndexI.H:351
labelRange range() const
Return start/size range of local (myProcNo) data.
Definition: globalIndexI.H:288
label findProcAbove(const label proci, const label i) const
Find processor above proci with specified global id - binary search.
Definition: globalIndexI.H:438
label nProcs() const noexcept
The number of processors covered by the offsets, same as the primary length()
Definition: globalIndexI.H:183
globalIndex() noexcept=default
Default construct (empty)
class FOAM_DEPRECATED_FOR(2017-05, "Foam::Enum") NamedEnum
Definition: NamedEnum.H:65
const labelList & offsets() const noexcept
Const-access to the offsets.
Definition: globalIndexI.H:205
static List< Type > listGatherValues(const label comm, const ProcIDsContainer &procIDs, const Type &localValue, const int tag=UPstream::msgType(), UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking)
Collect single values in processor order on master (== procIDs[0]).
bool single() const noexcept
True if local-only content (ie, nProcs == 1). Such content is often created with gatherNone.
Definition: globalIndexI.H:127
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:61
static void mpiGatherInplaceOp(List< Type > &fld, const label comm=UPstream::worldComm, UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking, const int tag=UPstream::msgType())
Use MPI_Gatherv call to inplace collect contiguous data when possible. (in serial: a no-op)...
label totalSize() const noexcept
The total addressed size, which corresponds to the end offset and also the sum of all localSizes...
Definition: globalIndexI.H:165
void mpiGatherInplace(List< Type > &fld, const label comm=UPstream::worldComm, UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking, const int tag=UPstream::msgType()) const
Use MPI_Gatherv call to inplace collect contiguous data when possible. (in serial: a no-op)...
Dispatch tag: Construct with a single (local size) entry, no communication.
Definition: globalIndex.H:110
tmp< faMatrix< Type > > operator*(const areaScalarField::Internal &, const faMatrix< Type > &)
bool operator==(const globalIndex &rhs) const
Compare for equality - uses the offsets.
Definition: globalIndex.H:1305
static labelList calcListOffsets(const List< SubListType > &lists, const bool checkOverflow=false)
Calculate offsets from list of lists, with optional check for label overflow.
Forward input iterator with const access that is used to iterate across the globalIndex offsets() tab...
Definition: globalIndex.H:599
const_iterator cbegin() const noexcept
A const_iterator set to the beginning.
Definition: globalIndexI.H:679
label offset(const label proci) const
Prefer localStart() to avoid confusing with offsets()
Definition: globalIndex.H:1371
const_iterator begin() const noexcept
A const_iterator set to the beginning.
Definition: globalIndexI.H:693
label length() const noexcept
The number of items covered by the offsets.
Definition: globalIndexI.H:133
Istream & operator>>(Istream &, directionInfo &)
label size() const
Global sum of localSizes. Same as totalSize()
Definition: globalIndexI.H:171
void setLocalSize(const label proci, const label len)
Alter local size for given processor.
Definition: globalIndex.C:521
bool isLocal(const label proci, const label i) const
Is on processor proci.
Definition: globalIndexI.H:294
#define FOAM_DEPRECATED_STRICT(since, replacement)
Definition: stdFoam.H:53
A packed storage of objects of type <T> using an offset table for access.
const direction noexcept
Definition: scalarImpl.H:255
labelList sizes() const
The local sizes. Same as localSizes()
Definition: globalIndexI.H:177
static void gatherOp(const UList< Type > &sendData, List< Type > &allData, const int tag=UPstream::msgType(), UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking, const label comm=UPstream::worldComm)
Collect data in processor order on master (in serial: performs a simple copy).
label findProc(const label proci, const label i) const
Find processor with specified global id. Check proci first, followed by binary search.
Definition: globalIndexI.H:399
OBJstream os(runTime.globalPath()/outputName)
bool splitNodeOffsets(labelList &interNodeOffsets, labelList &localNodeOffsets, const label communicator=UPstream::worldComm, const bool absoluteLocalNodeOffsets=false) const
Split the top-level offsets into inter-node and local-node components suitable to a two-stage hierarc...
Definition: globalIndex.C:260
const const_iterator end() const noexcept
A const_iterator set to beyond the end.
Definition: globalIndexI.H:700
labelRange subProcs() const noexcept
Range of process indices for addressed sub-offsets (processes)
Definition: globalIndexI.H:197
labelRange allProcs() const noexcept
Range of process indices for all addressed offsets (processes)
Definition: globalIndexI.H:189
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:77
static void gatherInplace(const labelUList &offsets, const label comm, const ProcIDsContainer &procIDs, List< Type > &fld, const int tag=UPstream::msgType(), UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking)
Inplace collect in processor order on master (== procIDs[0]).
label toGlobal(const label proci, const label i) const
From local to global on proci.
Definition: globalIndexI.H:308
label findProcBelow(const label proci, const label i) const
Find processor below proci with specified global id - binary search.
Definition: globalIndexI.H:461
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
static labelRange calcRange(const label localSize, const label comm=UPstream::worldComm, const bool checkOverflow=false)
Calculate globally-consistent local range (offset/size) based on the local input size(s).
Definition: globalIndex.C:60
bool empty() const noexcept
Check for default constructed or total-size == 0.
Definition: globalIndexI.H:120
label n
label localStart() const
Local start on myProcNo()
Definition: globalIndexI.H:239
const const_iterator cend() const noexcept
A const_iterator set to beyond the end.
Definition: globalIndexI.H:686
static void scatter(const labelUList &offsets, const label comm, const ProcIDsContainer &procIDs, const UList< Type > &allFld, UList< Type > &fld, const int tag=UPstream::msgType(), UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking)
Distribute data in processor order.
labelRange back() const
The last offset range. It is (0,0) if globalIndex is empty.
Definition: globalIndex.C:623
static label calcOffset(const label localSize, const label comm=UPstream::worldComm, const bool checkOverflow=false)
Calculate globally-consistent local start offset based on the local input size(s).
Definition: globalIndex.C:125
label maxSize() const
Global max of localSizes.
Definition: globalIndexI.H:269
Inter-processor communications stream.
Definition: UPstream.H:65
void mpiGather(const UList< Type > &sendData, OutputContainer &allData, const label comm=UPstream::worldComm, UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking, const int tag=UPstream::msgType()) const
Use MPI_Gatherv call for contiguous data when possible (in serial: performs a simple copy)...
void clear()
Reset to be empty (no offsets)
Definition: globalIndexI.H:217
bool operator!=(const globalIndex &rhs) const
Compare for inequality - uses the offsets.
Definition: globalIndex.H:1313
label localEnd() const
Local end on myProcNo()
Definition: globalIndexI.H:251
Namespace for OpenFOAM.
Dispatch tag: Construct &#39;one-sided&#39; from the non-master local sizes using gather but no broadcast...
Definition: globalIndex.H:124
label maxNonLocalSize() const
The max of localSizes, excluding current (myProcNo) rank.
Definition: globalIndexI.H:276
void resize(const label n)
Change the number of entries (nProcs) in the offsets table. Extending will fill with empty local size...
Definition: globalIndex.C:438
label localSize() const
Local size on myProcNo()
Definition: globalIndexI.H:263
const labelUList localStarts() const
The local starts.
Definition: globalIndexI.H:223
labelRange front() const
The first offset range. It is (0,0) if globalIndex is empty.
Definition: globalIndex.C:612