globalIndexI.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-2016 OpenFOAM Foundation
9  Copyright (C) 2018-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "ListOps.H"
30 
31 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
32 
34 (
35  const labelUList& listOffsets
36 )
37 {
38  if (listOffsets.size() > 1) // Enforce sizing sanity
39  {
40  offsets_ = listOffsets;
41  }
42 }
43 
44 
46 (
47  labelList&& listOffsets
48 )
49 :
50  offsets_(std::move(listOffsets))
51 {
52  if (offsets_.size() == 1) // Enforce sizing sanity
53  {
54  offsets_.clear();
55  }
56 }
57 
58 
60 (
61  const globalIndex::gatherNone,
62  const labelUList& localSizes
63 )
64 {
65  reset(localSizes);
66 }
67 
68 
70 (
71  const label localSize,
72  const label comm,
73  const bool parallel
74 )
75 {
76  reset(localSize, comm, parallel);
77 }
78 
79 
81 (
83  const label localSize,
84  const label /* comm (ignored) */
85 )
86 :
87  offsets_(2)
88 {
89  offsets_[0] = 0;
90  offsets_[1] = localSize;
91 }
92 
93 
95 (
97  const label localSize,
98  const label comm
99 )
100 {
101  // one-sided
102  reset(UPstream::listGatherValues(localSize, comm));
103 }
104 
105 
107 (
109  const label localSize,
110  const label comm
111 )
112 {
113  // one-sided: non-master sizes only
114  reset
115  (
117  (
118  (UPstream::master(comm) ? label(0) : localSize),
119  comm
120  )
121  );
122 }
123 
124 
125 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
126 
128 {
129  const label len = (offsets_.size() - 1);
130  return (len < 1) || (*(offsets_.cdata() + len) == 0);
131 }
132 
134 inline bool Foam::globalIndex::single() const noexcept
135 {
136  return (offsets_.size() == 2);
137 }
138 
139 
140 inline Foam::label Foam::globalIndex::length() const noexcept
141 {
142  const label len = (offsets_.size() - 1);
143  return (len < 1) ? 0 : len;
144 }
145 
147 inline Foam::label Foam::globalIndex::span() const noexcept
148 {
149  return (end_value() - begin_value());
150 }
151 
153 inline Foam::label Foam::globalIndex::begin_value() const noexcept
154 {
155  return (offsets_.empty() ? 0 : *(offsets_.cdata()));
156 }
157 
158 
159 inline Foam::label Foam::globalIndex::end_value() const noexcept
160 {
161  const label len = (offsets_.size() - 1);
162  return (len < 1) ? 0 : *(offsets_.cdata() + len);
163 }
164 
166 inline bool Foam::globalIndex::contains(const label i) const noexcept
167 {
168  return (begin_value() <= i) && (i < end_value());
169 }
170 
172 inline Foam::label Foam::globalIndex::totalSize() const noexcept
173 {
174  return end_value();
175 }
176 
178 inline Foam::label Foam::globalIndex::size() const
179 {
180  return totalSize();
181 }
182 
185 {
186  return localSizes();
187 }
188 
190 inline Foam::label Foam::globalIndex::nProcs() const noexcept
191 {
192  return length();
193 }
194 
195 
197 {
198  // Proc 0 -> nProcs
199  const label len = (offsets_.size() - 1);
200  return (len < 1) ? labelRange() : labelRange(0, len);
201 }
202 
203 
205 {
206  // Proc 1 -> nProcs
207  const label len = (offsets_.size() - 2);
208  return (len < 1) ? labelRange() : labelRange(1, len);
209 }
210 
213 {
214  return offsets_;
215 }
216 
219 {
220  return offsets_;
221 }
222 
224 inline void Foam::globalIndex::clear()
225 {
226  offsets_.clear();
227 }
228 
229 
231 {
232  const label len = (offsets_.size() - 1);
234  if (len < 1) return labelUList::null();
235 
236  return labelList::subList(offsets_, len);
237 }
238 
240 inline Foam::label Foam::globalIndex::localStart(const label proci) const
241 {
242  return offsets_[proci];
243 }
244 
246 inline Foam::label Foam::globalIndex::localStart() const
247 {
248  return localStart(UPstream::myProcNo(UPstream::worldComm));
249 }
250 
252 inline Foam::label Foam::globalIndex::localEnd(const label proci) const
253 {
254  return offsets_[proci+1];
255 }
256 
258 inline Foam::label Foam::globalIndex::localEnd() const
259 {
260  return localEnd(UPstream::myProcNo(UPstream::worldComm));
261 }
262 
264 inline Foam::label Foam::globalIndex::localSize(const label proci) const
265 {
266  return offsets_[proci+1] - offsets_[proci];
267 }
268 
270 inline Foam::label Foam::globalIndex::localSize() const
271 {
272  return localSize(UPstream::myProcNo(UPstream::worldComm));
273 }
274 
275 
276 inline Foam::label Foam::globalIndex::maxSize() const
277 {
278  // Use out-of-range proci to avoid excluding any processor
279  return maxNonLocalSize(-1);
280 }
281 
283 inline Foam::label Foam::globalIndex::maxNonLocalSize() const
284 {
285  return maxNonLocalSize(UPstream::myProcNo(UPstream::worldComm));
286 }
287 
289 inline Foam::labelRange Foam::globalIndex::range(const label proci) const
290 {
291  return labelRange(offsets_[proci], offsets_[proci+1] - offsets_[proci]);
292 }
293 
296 {
298 }
299 
300 
301 inline bool Foam::globalIndex::isLocal(const label proci, const label i) const
302 {
303  // range contains()
304  return (offsets_[proci] <= i) && (i < offsets_[proci+1]);
305 }
306 
307 
308 inline bool Foam::globalIndex::isLocal(const label i) const
309 {
310  return isLocal(UPstream::myProcNo(UPstream::worldComm), i);
311 }
312 
313 
314 inline Foam::label Foam::globalIndex::toGlobal
315 (
316  const label proci,
317  const label i
318 ) const
319 {
320  return i + offsets_[proci];
321 }
322 
323 
324 inline Foam::label Foam::globalIndex::toGlobal(const label i) const
325 {
326  return toGlobal(UPstream::myProcNo(UPstream::worldComm), i);
327 }
328 
329 
331 (
332  const label proci,
333  const labelUList& labels
334 ) const
335 {
336  // Or using std::transform
337 
338  //std::transform(labels.begin(), labels.end(), result.begin(),
339  // [=](label id) { return id += off });
340 
341  labelList result(labels);
342  inplaceToGlobal(proci, result);
343 
344  return result;
345 }
346 
347 
349 (
350  const labelUList& labels
351 ) const
352 {
353  return toGlobal(UPstream::myProcNo(UPstream::worldComm), labels);
354 }
355 
356 
358 (
359  const label proci,
360  labelUList& labels
361 ) const
362 {
363  const label off = offsets_[proci];
364 
365  for (label& val : labels)
366  {
367  val += off;
368  }
369 
370  // or
371  //std::for_each(labels.begin(), labels.end(),
372  // [=](label& val) { val += off; }
373  // );
374 }
375 
376 
378 {
379  inplaceToGlobal(UPstream::myProcNo(UPstream::worldComm), labels);
380 }
381 
382 
383 inline Foam::label
384 Foam::globalIndex::toLocal(const label proci, const label i) const
385 {
386  // range !contains()
387  if (i < offsets_[proci] || i >= offsets_[proci+1])
388  {
390  << "Global id:" << i << " does not belong on processor "
391  << proci << nl
392  << " Offsets:" << offsets_
393  << abort(FatalError);
394  }
395  return (i - offsets_[proci]);
396 }
397 
398 
399 inline Foam::label Foam::globalIndex::toLocal(const label i) const
400 {
401  return toLocal(UPstream::myProcNo(UPstream::worldComm), i);
402 }
403 
404 
405 inline Foam::label Foam::globalIndex::findProc
406 (
407  const label proci,
408  const label i
409 ) const
410 {
411  // Simple checks first
412  if
413  (
414  (proci < 0) // Invalid proc
415  || (proci+1 > offsets_.size()) // Invalid proc
416  || (i < offsets_.front()) // Below the start
417  || (i >= offsets_.back()) // Beyond the end
418  )
419  {
420  return -1;
421  }
422 
423  // Assume that in many cases we have many queries for the local proci,
424  // so query that first but also make it the split point for
425  // restricting the binary searches
426 
427  if (isLocal(proci, i))
428  {
429  return proci;
430  }
431 
432  if (i < offsets_[proci])
433  {
434  // Can restrict search to procs below proci
435  const labelList::subList slice(offsets_, proci);
436  return findLower(slice, i+1);
437  }
439  // Search starts at proci+1 (and above)
440  return findLower(offsets_, i+1, proci+1);
441 }
442 
443 
444 inline Foam::label Foam::globalIndex::findProcAbove
445 (
446  const label proci,
447  const label i
448 ) const
449 {
450  // Simple checks first
451  if
452  (
453  (proci < 0) // Invalid proci
454  || (proci+1 >= offsets_.size()) // Nothing above last proc
455  || (i < offsets_[proci+1]) // Exclude proc-local and below
456  || (i >= offsets_.back()) // Beyond the end
457  )
458  {
459  return -1;
460  }
462  // Search starts at proci+1 (and above)
463  return findLower(offsets_, i+1, (proci+1));
464 }
465 
466 
467 inline Foam::label Foam::globalIndex::findProcBelow
468 (
469  const label proci,
470  const label i
471 ) const
472 {
473  if
474  (
475  (proci <= 0) // Nothing below first proc
476  || (proci >= offsets_.size()) // Invalid proci
477  || (i >= offsets_[proci]) // Exclude proc-local and above
478  || (i < offsets_[0]) // Beyond the begin
479  )
480  {
481  return -1;
482  }
483 
484  // Restrict search to procs below proci
485  const labelList::subList slice(offsets_, proci);
486  return findLower(slice, i+1);
487 }
488 
489 
490 // Note: could split this into failsafe/non-failsafe versions
491 inline Foam::label Foam::globalIndex::whichProcID
492 (
493  const label proci,
494  const label i
495 ) const
496 {
497  label foundProc = findProc(proci, i);
498 
499  if (foundProc < 0)
500  {
502  << "Global id:" << i << " does not belong on any processor." << nl
503  << "Offsets:" << offsets_
504  << abort(FatalError);
505  }
506 
507  return foundProc;
508 }
509 
510 
511 inline Foam::label Foam::globalIndex::whichProcID
512 (
513  const label i
514 ) const
515 {
516  return whichProcID(UPstream::myProcNo(UPstream::worldComm), i);
517 }
518 
519 
520 inline void Foam::globalIndex::reset
521 (
523  const label localSize,
524  const label /* comm (ignored) */
525 )
526 {
527  offsets_.resize_nocopy(2);
528  offsets_[0] = 0;
529  offsets_[1] = localSize;
530 }
531 
532 
533 inline void Foam::globalIndex::reset
534 (
536  const label localSize,
537  const label comm
538 )
539 {
540  // one-sided
541  reset(UPstream::listGatherValues(localSize, comm));
542 }
543 
544 
545 inline void Foam::globalIndex::reset
546 (
548  const label localSize,
549  const label comm
550 )
551 {
552  // one-sided: non-master sizes only
553  reset
554  (
556  (
557  (UPstream::master(comm) ? label(0) : localSize),
558  comm
559  )
560  );
561 }
562 
563 
564 inline void Foam::globalIndex::reset(const globalIndex& rhs)
565 {
566  if (this == &rhs)
567  {
568  return; // Self-assignment is a no-op
569  }
570  this->offsets_ = rhs.offsets_;
571 }
572 
573 
574 // * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * //
575 
578 (
579  const globalIndex* globalIdx,
580  const label i
581 ) noexcept
582 :
583  parent_(globalIdx),
584  index_(i)
585 {}
586 
587 
588 inline Foam::label Foam::globalIndex::const_iterator::
590 {
591  return index_;
592 }
593 
594 
595 inline Foam::label Foam::globalIndex::const_iterator::
596 start() const
597 {
598  return (*parent_).localStart(index_);
599 }
600 
601 
602 inline Foam::label Foam::globalIndex::const_iterator::
603 size() const
604 {
605  return (*parent_).localSize(index_);
606 }
607 
608 
610 range() const
611 {
612  return (*parent_).range(index_);
613 }
614 
615 
617 operator*() const
618 {
619  return this->range();
620 }
621 
622 
625 operator++()
626 {
627  ++index_;
628  return *this;
629 }
630 
631 
634 operator++(int)
635 {
636  const_iterator old(*this);
637  ++index_;
638  return old;
639 }
640 
641 
644 operator--()
645 {
646  --index_;
647  return *this;
648 }
649 
650 
653 operator--(int)
654 {
655  const_iterator old(*this);
656  --index_;
657  return old;
658 }
659 
660 
661 inline bool
662 Foam::globalIndex::const_iterator::
663 operator==
664 (
665  const const_iterator& iter
666 ) const noexcept
667 {
668  return (index_ == iter.index_);
669 }
670 
671 
672 inline bool
673 Foam::globalIndex::const_iterator::
674 operator!=
675 (
676  const const_iterator& iter
677 ) const noexcept
678 {
679  return (index_ != iter.index_);
680 }
681 
682 
683 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
684 
687 {
688  return const_iterator(this);
689 }
690 
691 
694 {
695  return const_iterator(this, this->length());
696 }
697 
698 
701 {
702  return const_iterator(this);
703 }
704 
705 
708 {
709  return const_iterator(this, this->length());
710 }
711 
712 
714 Foam::globalIndex::cbegin(const label i) const noexcept
715 {
716  const label len = this->length();
717  return const_iterator(this, (i < 0 ? 0 : len < i ? len : i));
718 }
719 
720 
722 Foam::globalIndex::begin(const label i) const noexcept
723 {
724  return this->cbegin(i);
725 }
726 
727 
728 // ************************************************************************* //
label toLocal(const label proci, const label i) const
From global to local on proci.
Definition: globalIndexI.H:377
const_iterator(const globalIndex *globalIdx, const label i=0) noexcept
Construct from globalIndex list at given index.
Definition: globalIndexI.H:571
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:346
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
label findLower(const ListType &input, const T &val, const label start, const ComparePredicate &comp)
Binary search to find the index of the last element in a sorted list that is less than value...
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:52
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
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
static List< T > listGatherValues(const T &localValue, const label communicator=worldComm)
Gather individual values into list locations.
Dispatch tag: Construct &#39;one-sided&#39; from local sizes, using gather but no broadcast.
Definition: globalIndex.H:110
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
label span() const noexcept
The span size covered by the offsets, zero if empty.
Definition: globalIndexI.H:140
SubList< label > subList
Declare type of subList.
Definition: List.H:144
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1074
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:409
scalar range
void inplaceToGlobal(const label proci, labelUList &labels) const
From local to global index on proci (inplace)
Definition: globalIndexI.H:351
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
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
Various functions to operate on Lists.
globalIndex() noexcept=default
Default construct (empty)
const labelList & offsets() const noexcept
Const-access to the offsets.
Definition: globalIndexI.H:205
bool single() const noexcept
True if local-only content (ie, nProcs == 1). Such content is often created with gatherNone.
Definition: globalIndexI.H:127
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:61
A List obtained as a section of another List.
Definition: SubList.H:50
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
Dispatch tag: Construct with a single (local size) entry, no communication.
Definition: globalIndex.H:103
Forward input iterator with const access that is used to iterate across the globalIndex offsets() tab...
Definition: globalIndex.H:580
const_iterator cbegin() const noexcept
A const_iterator set to the beginning.
Definition: globalIndexI.H:679
const_iterator begin() const noexcept
A const_iterator set to the beginning.
Definition: globalIndexI.H:693
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:137
label length() const noexcept
The number of items covered by the offsets.
Definition: globalIndexI.H:133
label size() const
Global sum of localSizes. Same as totalSize()
Definition: globalIndexI.H:171
labelRange range() const
The local range.
Definition: globalIndexI.H:603
labelRange operator*() const
The local range.
Definition: globalIndexI.H:610
bool isLocal(const label proci, const label i) const
Is on processor proci.
Definition: globalIndexI.H:294
errorManip< error > abort(error &err)
Definition: errorManip.H:139
label size() const
The local size.
Definition: globalIndexI.H:596
const direction noexcept
Definition: Scalar.H:258
labelList sizes() const
The local sizes. Same as localSizes()
Definition: globalIndexI.H:177
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
static const UList< label > & null()
Return a UList reference to a nullObject.
Definition: UListI.H:90
constexpr auto cbegin(const C &c) -> decltype(c.begin())
Return const_iterator to the beginning of the container c.
Definition: stdFoam.H:190
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
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
label index() const noexcept
The index into the arrays.
Definition: globalIndexI.H:582
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
bool empty() const noexcept
Check for default constructed or total-size == 0.
Definition: globalIndexI.H:120
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
List< label > labelList
A List of labels.
Definition: List.H:62
label start() const
The local start.
Definition: globalIndexI.H:589
label maxSize() const
Global max of localSizes.
Definition: globalIndexI.H:269
void clear()
Reset to be empty (no offsets)
Definition: globalIndexI.H:217
label localEnd() const
Local end on myProcNo()
Definition: globalIndexI.H:251
Dispatch tag: Construct &#39;one-sided&#39; from the non-master local sizes using gather but no broadcast...
Definition: globalIndex.H:117
label maxNonLocalSize() const
The max of localSizes, excluding current (myProcNo) rank.
Definition: globalIndexI.H:276
label localSize() const
Local size on myProcNo()
Definition: globalIndexI.H:263
const labelUList localStarts() const
The local starts.
Definition: globalIndexI.H:223