ENH: globalIndex contains(), findProcAbove(), findProcBelow() methods

- these help when building upper or lower connected topologies.
  The new findProc() method is a non-failing whichProcID alternative
This commit is contained in:
Mark Olesen 2023-11-12 11:00:44 +01:00
parent cfb752647a
commit 3fd1b74b26
3 changed files with 195 additions and 18 deletions

View File

@ -42,6 +42,21 @@ Description
using namespace Foam;
void printTest1
(
const globalIndex& gi,
const label proci,
const label value
)
{
// With range check
Info<< " value:" << value << " on:" << gi.findProc(proci, value)
<< " below/above: ("
<< gi.findProcBelow(proci, value) << ' '
<< gi.findProcAbove(proci, value) << ')' << nl;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
@ -87,6 +102,52 @@ int main(int argc, char *argv[])
<< nl;
}
{
// From some offsets
globalIndex gi;
globalIndex gi0
(
labelList({ 0, 10, 20, 30, 40, 50, 60 })
);
Info<< "offsets: " << gi0.offsets() << nl;
// Alternative to copy assigment
gi.reset(gi0);
Info<< "globalIndex :"; gi.offsets().writeList(Info) << nl;
// Resizing is fine, but also check the binary search results!
gi.resize(10);
Info<< "globalIndex :"; gi.offsets().writeList(Info) << nl;
// NB: these routines are mostly failsafe on bad addresses
// for (const label proci : { 4, 8, -1 })
for (const label proci : { 4 })
{
Info<< "proc:" << proci
<< " : [" << gi.localStart(proci)
<< "," << gi.localEnd(proci) << ")" << nl;
for (label i = 0; i < 25; ++i)
{
const label value = rnd.position<label>(-8, 100);
printTest1(gi, proci, value);
}
Info<< "other on proc:" << proci << nl;
printTest1(gi, proci, gi.localStart(proci));
printTest1(gi, proci, gi.localEnd(proci));
Info<< "other on proc:0" << nl;
printTest1(gi, 0, gi.localStart(proci));
printTest1(gi, 0, gi.localEnd(proci));
}
}
Info<< "\nEnd\n" << endl;
return 0;
}

View File

@ -321,6 +321,9 @@ public:
// Queries and renumbering
//- True if contained within the offsets range
inline bool contains(const label i) const noexcept;
//- Start of proci data
inline label localStart(const label proci) const;
@ -360,14 +363,26 @@ public:
//- From global to local on proci
inline label toLocal(const label proci, const label i) const;
//- Which processor does global id come from?
// Does an initial check for isLocal first (assumed to occur
// reasonably frequently) followed by a binary search.
//- Fatal for out of range ids (eg, negative or >= totalSize()
inline label whichProcID(const label i) const;
//- Find processor with specified global id.
//- Check proci first, followed by binary search.
// \return the processor number or -1 (not found)
inline label findProc(const label proci, const label i) const;
//- Find processor above proci with specified global id - binary search.
// \return the processor above proci or -1 otherwise
// (including for out-of-range indices)
inline label findProcAbove(const label proci, const label i) const;
//- Find processor below proci with specified global id - binary search.
// Binary search.
// \return the processor below proci or -1 otherwise
// (including for out-of-range indices)
inline label findProcBelow(const label proci, const label i) const;
//- Which processor does global id come from?
//- Checks proci first.
//- Checks proci first (assumed to occur reasonably frequently)
//- followed by a binary search.
//- Fatal for out-of-range indices
inline label whichProcID(const label proci, const label i) const;
@ -404,10 +419,17 @@ public:
// FatalError if not on local processor.
inline label toLocal(const label i) const;
//- Which processor does global id come from?
// Uses myProcNo for the initial local check.
inline label whichProcID(const label i) const;
// Iteration
//- Forward input iterator with const access
//- Forward input iterator with const access that is used to
//- iterate across the globalIndex offsets() table.
// The de-referenced value is the range() with (start, size),
// but it also provides separate index, start, size information.
class const_iterator
{
//- The parent class for which this is an iterator

View File

@ -163,6 +163,12 @@ inline Foam::label Foam::globalIndex::end_value() const noexcept
}
inline bool Foam::globalIndex::contains(const label i) const noexcept
{
return (begin_value() <= i) && (i < end_value());
}
inline Foam::label Foam::globalIndex::totalSize() const noexcept
{
return end_value();
@ -295,7 +301,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];
return (offsets_[proci] <= i) && (i < offsets_[proci+1]);
}
@ -377,16 +383,16 @@ inline void Foam::globalIndex::inplaceToGlobal(labelUList& labels) const
inline Foam::label
Foam::globalIndex::toLocal(const label proci, const label i) const
{
const label locali = i - offsets_[proci];
if (locali < 0 || i >= offsets_[proci+1])
// range !contains()
if (i < offsets_[proci] || i >= offsets_[proci+1])
{
FatalErrorInFunction
<< "Global " << i << " does not belong on processor "
<< proci << nl << "Offsets:" << offsets_
<< "Global id:" << i << " does not belong on processor "
<< proci << nl
<< " Offsets:" << offsets_
<< abort(FatalError);
}
return locali;
return (i - offsets_[proci]);
}
@ -396,21 +402,109 @@ inline Foam::label Foam::globalIndex::toLocal(const label i) const
}
inline Foam::label Foam::globalIndex::findProc
(
const label proci,
const label i
) const
{
// Simple checks first
if
(
(proci < 0) // Invalid proc
|| (proci+1 > offsets_.size()) // Invalid proc
|| (i < offsets_.front()) // Below the start
|| (i >= offsets_.back()) // Beyond the end
)
{
return -1;
}
// Assume that in many cases we have many queries for the local proci,
// so query that first but also make it the split point for
// restricting the binary searches
if (isLocal(proci, i))
{
return proci;
}
if (i < offsets_[proci])
{
// Can restrict search to procs below proci
const labelList::subList slice(offsets_, proci);
return findLower(slice, i+1);
}
// Search starts at proci+1 (and above)
return findLower(offsets_, i+1, proci+1);
}
inline Foam::label Foam::globalIndex::findProcAbove
(
const label proci,
const label i
) const
{
// Simple checks first
if
(
(proci < 0) // Invalid proci
|| (proci+1 >= offsets_.size()) // Nothing above last proc
|| (i < offsets_[proci+1]) // Exclude proc-local and below
|| (i >= offsets_.back()) // Beyond the end
)
{
return -1;
}
// Search starts at proci+1 (and above)
return findLower(offsets_, i+1, (proci+1));
}
inline Foam::label Foam::globalIndex::findProcBelow
(
const label proci,
const label i
) const
{
if
(
(proci <= 0) // Nothing below first proc
|| (proci >= offsets_.size()) // Invalid proci
|| (i >= offsets_[proci]) // Exclude proc-local and above
|| (i < offsets_[0]) // Beyond the begin
)
{
return -1;
}
// Restrict search to procs below proci
const labelList::subList slice(offsets_, proci);
return findLower(slice, i+1);
}
// Note: could split this into failsafe/non-failsafe versions
inline Foam::label Foam::globalIndex::whichProcID
(
const label proci,
const label i
) const
{
if (i < 0 || i >= totalSize())
label foundProc = findProc(proci, i);
if (foundProc < 0)
{
FatalErrorInFunction
<< "Global " << i << " does not belong on any processor."
<< " Offsets:" << offsets_
<< "Global id:" << i << " does not belong on any processor." << nl
<< "Offsets:" << offsets_
<< abort(FatalError);
}
return isLocal(proci, i) ? proci : findLower(offsets_, i+1);
return foundProc;
}