ENH: additional globalIndex methods and helpers

- single() method : simply tests if the globalIndex has nProcs == 1,
  which is typically from a gatherNone invocation.
  For example,

     globalIndex gi;
     if (...) gi.reset(localSize);
     else     gi.reset(globalIndex::gatherNone{}, localSize);

     // later...
     const label begin = (gi.single() ? 0 : gi.localStart());
     const label count = (gi.single() ? gi.totalSize() : gi.localSize());

- add front() and back() methods to return the begin/end ranges,
  and begin_value(), end_value() - as per labelRange.

- make more methods noexcept

- calcOffset(), calcRange() helper functions to determine
  the processor-local of a numbering range without the overhead of
  creating a list of offsets.

  For example,

     label myOffset = globalIndex::calcOffset(mesh.nCells());
     labelRange mySlice = globalIndex::calcRange(mesh.nCells());

- add globalIndex localEnd() as per CompactListList method

STYLE: align looping constructs in CompactListList with List

- make more methods noexcept
This commit is contained in:
Mark Olesen 2023-10-25 09:06:32 +02:00
parent d9f0587416
commit b34793c392
7 changed files with 315 additions and 70 deletions

View File

@ -55,6 +55,16 @@ int main(int argc, char *argv[])
// Global numbering of cells (proc0 elements first, then proc1, etc.)
globalIndex globalNumbering(mesh.nCells());
Pout<< "local-offset: " << globalIndex::calcOffset(mesh.nCells()) << nl;
Pout<< "local-range: " << globalIndex::calcRange(mesh.nCells()) << nl;
Info<< "cells from:" << globalNumbering.begin_value()
<< " to:" << globalNumbering.end_value()
<< " span:" << globalNumbering.span() << nl;
Info<< "front: " << globalNumbering.front()
<< " back: " << globalNumbering.back() << nl;
if (globalNumbering.localSize() != mesh.nCells())
{
FatalErrorInFunction

View File

@ -56,7 +56,7 @@ void Foam::CompactListList<T>::reportOverflowAndExit
template<class T>
template<class ListListType>
Foam::CompactListList<T> Foam::CompactListList<T>::packImpl
Foam::CompactListList<T> Foam::CompactListList<T>::pack_impl
(
const ListListType& lists,
const bool checkOverflow
@ -89,17 +89,21 @@ Foam::CompactListList<T> Foam::CompactListList<T>::packImpl
if (total)
{
// Copy in the data
// Make a deepCopy of data
newValues.resize(total);
auto outIter = newValues.begin();
auto iter = newValues.begin();
// NB: operator[] for sub-list read access (eg, an indirect list)
// cannot replace with std::copy
for (const auto& list : lists)
{
forAll(list, i)
const label sublen = list.size();
for (label i = 0; i < sublen; (void)++i, (void)++iter)
{
*outIter = list[i];
++outIter;
*iter = list[i];
}
}
}
@ -116,7 +120,7 @@ Foam::CompactListList<T> Foam::CompactListList<T>::pack
const bool checkOverflow
)
{
return CompactListList<T>::packImpl<UList<SubListType>>
return CompactListList<T>::pack_impl<UList<SubListType>>
(
lists,
checkOverflow
@ -132,7 +136,7 @@ Foam::CompactListList<T> Foam::CompactListList<T>::pack
const bool checkOverflow
)
{
return CompactListList<T>::packImpl<IndirectListBase<SubListType, Addr>>
return CompactListList<T>::pack_impl<IndirectListBase<SubListType, Addr>>
(
lists,
checkOverflow
@ -404,12 +408,12 @@ Foam::CompactListList<T>::unpack(const labelRange& range) const
{
List<SubListType> lists(range.size());
auto outIter = lists.begin();
auto iter = lists.begin();
for (const label i : range)
{
*outIter = SubListType(this->localList(i));
++outIter;
*iter = SubListType(this->localList(i));
++iter;
}
return lists;

View File

@ -28,7 +28,7 @@ Class
Foam::CompactListList
Description
A packed storage unstructured matrix of objects of type \<T\>
A packed storage of objects of type \<T\>
using an offset table for access.
The offset table is the size of the number of rows+1
@ -91,7 +91,7 @@ class CompactListList
//- Construct by packing together the list of lists
template<class ListListType>
static CompactListList<T> packImpl
static CompactListList<T> pack_impl
(
const ListListType& lists,
const bool checkOverflow = false
@ -197,23 +197,29 @@ public:
//- True if the number of rows/sublists is zero
inline bool empty() const noexcept;
//- True if content is a single row/sublist only.
//- Such content could be flattened out into a straight list
//- (for example).
inline bool single() const noexcept;
//- The primary size (the number of rows/sublists)
inline label size() const noexcept;
//- The total addressed size
inline label totalSize() const;
//- The total addressed size, which corresponds to the
//- end (back) offset and also the sum of all localSizes.
inline label totalSize() const noexcept;
//- Return the offset table (= size()+1)
inline const labelList& offsets() const noexcept;
const labelList& offsets() const noexcept { return offsets_; }
//- Return non-const access to the offset table
inline labelList& offsets() noexcept;
labelList& offsets() noexcept { return offsets_; }
//- Return the packed matrix of values
inline const List<T>& values() const noexcept;
//- Return the packed values
const List<T>& values() const noexcept { return values_; }
//- Return non-const access to the packed matrix of values
inline List<T>& values() noexcept;
//- Return non-const access to the packed values
List<T>& values() noexcept { return values_; }
//- Return const pointer to the first data in values()
@ -414,10 +420,12 @@ public:
// Housekeeping
//- Const access to the packed matrix of values
//- Const access to the packed values
//FOAM_DEPRECATED_STRICT(2022-03, "values()")
const List<T>& m() const noexcept { return values_; }
//- Non-const access to the packed matrix of values
//- Non-const access to the packed values
//FOAM_DEPRECATED_STRICT(2022-03, "values()")
List<T>& m() noexcept { return values_; }
//- Return flat index into packed values

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2022 OpenCFD Ltd.
Copyright (C) 2019-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -145,34 +145,6 @@ Foam::CompactListList<T>::clone() const
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T>
inline const Foam::labelList& Foam::CompactListList<T>::offsets() const noexcept
{
return offsets_;
}
template<class T>
inline Foam::labelList& Foam::CompactListList<T>::offsets() noexcept
{
return offsets_;
}
template<class T>
inline const Foam::List<T>& Foam::CompactListList<T>::values() const noexcept
{
return values_;
}
template<class T>
inline Foam::List<T>& Foam::CompactListList<T>::values() noexcept
{
return values_;
}
template<class T>
inline const T* Foam::CompactListList<T>::cdata() const noexcept
{
@ -211,10 +183,20 @@ inline std::streamsize Foam::CompactListList<T>::size_bytes() const noexcept
template<class T>
inline bool Foam::CompactListList<T>::empty() const noexcept
{
// Note: could (should?) also check (offsets_.back() == 0)
// return offsets_.empty()
// || (*(offsets_.cdata() + offsets_.size()-1) == 0);
return (offsets_.size() <= 1);
}
template<class T>
inline bool Foam::CompactListList<T>::single() const noexcept
{
return (offsets_.size() == 2);
}
template<class T>
inline Foam::label Foam::CompactListList<T>::size() const noexcept
{
@ -231,10 +213,9 @@ inline Foam::labelList Foam::CompactListList<T>::sizes() const
template<class T>
inline Foam::label Foam::CompactListList<T>::totalSize() const
inline Foam::label Foam::CompactListList<T>::totalSize() const noexcept
{
const label len = (offsets_.size() - 1);
return (len < 1) ? static_cast<label>(0) : offsets_[len];
return offsets_.empty() ? 0 : *(offsets_.cdata() + offsets_.size()-1);
}

View File

@ -27,6 +27,7 @@ License
\*---------------------------------------------------------------------------*/
#include "globalIndex.H"
#include "Pair.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
@ -52,6 +53,132 @@ void Foam::globalIndex::reportOverflowAndExit
}
Foam::labelRange
Foam::globalIndex::calcRange
(
const label localSize,
const label comm,
const bool checkOverflow
)
{
// Range with 0-offset initially
labelRange myRange(0, localSize);
if (!UPstream::is_parallel(comm))
{
return myRange;
}
const label myProci = UPstream::myProcNo(comm);
const labelList localLens = UPstream::allGatherValues(localSize, comm);
if (checkOverflow)
{
const label len = localLens.size();
label start = 0;
for (label i = 0; i < len; ++i)
{
if (i == myProci)
{
myRange.start() = start;
}
const label prev = start;
start += localLens[i];
if (start < prev)
{
reportOverflowAndExit(i, localLens);
}
}
}
else
{
// std::accumulate
// (
// localLens.cbegin(),
// localLens.cbegin(myProci),
// label(0)
// );
label start = 0;
for (label i = 0; i < myProci; ++i)
{
start += localLens[i];
}
myRange.start() = start;
}
return myRange;
}
Foam::label
Foam::globalIndex::calcOffset
(
const label localSize,
const label comm,
const bool checkOverflow
)
{
// Placeholder value
label myOffset = 0;
if (!UPstream::is_parallel(comm))
{
return myOffset;
}
const label myProci = UPstream::myProcNo(comm);
const labelList localLens = UPstream::allGatherValues(localSize, comm);
if (checkOverflow)
{
const label len = localLens.size();
label start = 0;
for (label i = 0; i < len; ++i)
{
if (i == myProci)
{
myOffset = start;
}
const label prev = start;
start += localLens[i];
if (start < prev)
{
reportOverflowAndExit(i, localLens);
}
}
}
else
{
// std::accumulate
// (
// localLens.cbegin(),
// localLens.cbegin(myProci),
// label(0)
// );
label start = 0;
for (label i = 0; i < myProci; ++i)
{
start += localLens[i];
}
myOffset = start;
}
return myOffset;
}
Foam::labelList
Foam::globalIndex::calcOffsets
(
@ -197,13 +324,13 @@ void Foam::globalIndex::reset
const bool parallel
)
{
labelList localLens;
const label len = UPstream::nProcs(comm);
if (len)
{
if (parallel && UPstream::parRun()) // or UPstream::is_parallel()
labelList localLens;
if (parallel && UPstream::parRun()) // or UPstream::is_parallel(comm)
{
localLens = UPstream::allGatherValues(localSize, comm);
}
@ -350,6 +477,35 @@ Foam::label Foam::globalIndex::maxNonLocalSize(const label proci) const
}
Foam::labelRange Foam::globalIndex::front() const
{
return
(
(offsets_.size() < 2)
? labelRange()
: labelRange(Pair<label>(offsets_[0], offsets_[1]))
);
}
Foam::labelRange Foam::globalIndex::back() const
{
return
(
(offsets_.size() < 2)
? labelRange()
: labelRange
(
Pair<label>
(
offsets_[offsets_.size()-2],
offsets_[offsets_.size()-1]
)
)
);
}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
Foam::Istream& Foam::operator>>(Istream& is, globalIndex& gi)

View File

@ -59,9 +59,8 @@ class globalIndex;
Istream& operator>>(Istream& is, globalIndex& gi);
Ostream& operator<<(Ostream& os, const globalIndex& gi);
/*---------------------------------------------------------------------------*\
Class globalIndex Declaration
Class globalIndex Declaration
\*---------------------------------------------------------------------------*/
class globalIndex
@ -180,14 +179,18 @@ public:
// Member Functions
//- Check for default constructed or global sum == 0
inline bool empty() const;
//- Check for default constructed or total-size == 0
inline bool empty() const noexcept;
//- Global sum of localSizes. Same as totalSize()
inline label size() const;
//- Global sum of localSizes.
inline label totalSize() const;
//- The span size covered by the offsets, zero if empty
inline label span() const noexcept;
//- The total addressed size, which corresponds to the
//- end offset and also the sum of all localSizes.
inline label totalSize() const noexcept;
//- The local sizes. Same as localSizes()
inline labelList sizes() const;
@ -216,6 +219,10 @@ public:
// Dimensions
//- True if local-only content (ie, nProcs == 1).
//- Such content is often created with gatherNone.
inline bool single() const noexcept;
//- The number of processors covered by the offsets
inline label nProcs() const noexcept;
@ -225,6 +232,19 @@ public:
//- Range of process indices for addressed sub-offsets (processes)
inline labelRange subProcs() const noexcept;
//- The value corresponding to the first offset
inline label begin_value() const noexcept;
//- The value corresponding to the last offset (end offset),
//- which is 1 beyond the end of the range.
inline label end_value() const noexcept;
//- The first offset range. It is (0,0) if globalIndex is empty
labelRange front() const;
//- The last offset range. It is (0,0) if globalIndex is empty
labelRange back() const;
// Edit
@ -291,6 +311,9 @@ public:
//- Start of proci data
inline label localStart(const label proci) const;
//- End of proci data
inline label localEnd(const label proci) const;
//- Size of proci data
inline label localSize(const label proci) const;
@ -336,6 +359,9 @@ public:
//- Local start on myProcNo()
inline label localStart() const;
//- Local end on myProcNo()
inline label localEnd() const;
//- Local size on myProcNo()
inline label localSize() const;
@ -443,6 +469,28 @@ public:
// Helper Functions
//- Calculate globally-consistent local range (offset/size)
//- based on the local input size(s).
// Effectively the same as globalIndex(localSize).range()
// but without constructing an extra intermediate list of offsets
static labelRange calcRange
(
const label localSize,
const label comm = UPstream::worldComm, //!< communicator
const bool checkOverflow = false
);
//- Calculate globally-consistent local start offset
//- based on the local input size(s).
// Effectively the same as globalIndex(localSize).localStart()
// but without constructing an extra intermediate list of offsets
static label calcOffset
(
const label localSize,
const label comm = UPstream::worldComm, //!< communicator
const bool checkOverflow = false
);
//- Calculate offsets from a list of local sizes,
//- with optional check for label overflow
static labelList calcOffsets

View File

@ -35,7 +35,7 @@ inline Foam::globalIndex::globalIndex
const labelUList& listOffsets
)
{
if (listOffsets.size() > 1)
if (listOffsets.size() > 1) // Enforce sizing sanity
{
offsets_ = listOffsets;
}
@ -49,7 +49,7 @@ inline Foam::globalIndex::globalIndex
:
offsets_(std::move(listOffsets))
{
if (offsets_.size() == 1)
if (offsets_.size() == 1) // Enforce sizing sanity
{
offsets_.clear();
}
@ -124,16 +124,35 @@ inline Foam::globalIndex::globalIndex
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline bool Foam::globalIndex::empty() const
inline bool Foam::globalIndex::empty() const noexcept
{
return offsets_.empty() || offsets_.back() == 0;
const label len = (offsets_.size() - 1);
return (len < 1) || (*(offsets_.cdata() + len) == 0);
}
inline Foam::label Foam::globalIndex::totalSize() const
inline Foam::label Foam::globalIndex::span() const noexcept
{
return (end_value() - begin_value());
}
inline Foam::label Foam::globalIndex::begin_value() const noexcept
{
return (offsets_.empty() ? 0 : *(offsets_.cdata()));
}
inline Foam::label Foam::globalIndex::end_value() const noexcept
{
const label len = (offsets_.size() - 1);
return (len < 1) ? 0 : offsets_[len];
return (len < 1) ? 0 : *(offsets_.cdata() + len);
}
inline Foam::label Foam::globalIndex::totalSize() const noexcept
{
return end_value();
}
@ -149,6 +168,12 @@ inline Foam::labelList Foam::globalIndex::sizes() const
}
inline bool Foam::globalIndex::single() const noexcept
{
return (offsets_.size() == 2);
}
inline Foam::label Foam::globalIndex::nProcs() const noexcept
{
const label len = (offsets_.size() - 1);
@ -212,6 +237,18 @@ inline Foam::label Foam::globalIndex::localStart() const
}
inline Foam::label Foam::globalIndex::localEnd(const label proci) const
{
return offsets_[proci+1];
}
inline Foam::label Foam::globalIndex::localEnd() const
{
return localEnd(UPstream::myProcNo(UPstream::worldComm));
}
inline Foam::label Foam::globalIndex::localSize(const label proci) const
{
return offsets_[proci+1] - offsets_[proci];
@ -251,6 +288,7 @@ inline Foam::labelRange Foam::globalIndex::range() const
inline bool Foam::globalIndex::isLocal(const label proci, const label i) const
{
// range contains()
return i >= offsets_[proci] && i < offsets_[proci+1];
}