ENH: globalIndex and CompactListList improvements

- provide a globalIndex::calcOffsets() taking an indirect list, which
  enables convenient offsets calculation from a variety of inputs.

- new CompactListList unpack variant: copy_unpack()
  The copy_unpack() works somewhat like std::copy() in that it writes
  the generated sublists to iterator positions, which makes this
  type of code possible:

      CompactListList<label> compact = ...;
      DynamicList<face> extracted;

      compact.copy_unpack<face>
      (
          std::back_inserter(extracted),
          labelRange(4, 10)
      );

  -and-

      const label nOldFaces = allFaces.size();
      allFaces.resize(allFaces + nNewFaces);

      auto iter = allFaces.begin(nOldFaces);

      iter = compact.copy_unpack<face>(iter, /* selection 1 */);
      ...
      iter = compact.copy_unpack<face>(iter, /* selection 2 */);

ENH: globalIndex resize()

- can be used to shrink or grow the offsets table.
  Any extension of the offsets table corresponds to 'slots'
  with 0 local size.
This commit is contained in:
Mark Olesen 2023-11-18 11:38:10 +01:00
parent ef201ecfea
commit cfb752647a
16 changed files with 384 additions and 88 deletions

View File

@ -1,3 +1,3 @@
Test-CompactListList.C
Test-CompactListList.cxx
EXE = $(FOAM_USER_APPBIN)/Test-CompactListList

View File

@ -38,6 +38,8 @@ Description
#include "SpanStream.H"
#include "faceList.H"
#include <iterator> // for back_inserter
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -161,6 +163,25 @@ int main(int argc, char *argv[])
faceList fcs2 = compactFcs.unpack<face>();
Info<< "deserialized:" << fcs2 << endl;
// Unpack some faces
DynamicList<face> extracted(compactFcs.size());
compactFcs.copy_unpack<face>
(
std::back_inserter(extracted),
2, 2
);
Info<< "copy_unpack 1: " << extracted << nl;
compactFcs.copy_unpack<face>
(
std::back_inserter(extracted)
// labelRange(2, 1)
);
Info<< "copy_unpack 2: " << extracted << nl;
// From some faces
IndirectList<face> subfaces(fcs, labelList({2, 4, 1}));

View File

@ -1,3 +0,0 @@
Test-globalIndex.C
EXE = $(FOAM_USER_APPBIN)/Test-globalIndex

View File

@ -1 +0,0 @@
EXE_INC = /* -DFULLDEBUG -g -O0 */

View File

@ -0,0 +1,3 @@
Test-globalIndex1.cxx
EXE = $(FOAM_USER_APPBIN)/Test-globalIndex1

View File

@ -0,0 +1,2 @@
/* EXE_INC = */
/* EXE_LIBS = */

View File

@ -25,7 +25,7 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
globalIndexTest
Test-globalIndex1
Description
Simple tests for the globalIndex class.
@ -53,7 +53,7 @@ int main(int argc, char *argv[])
#include "createPolyMesh.H"
// Global numbering of cells (proc0 elements first, then proc1, etc.)
globalIndex globalNumbering(mesh.nCells());
const globalIndex globalNumbering(mesh.nCells());
Pout<< "local-offset: " << globalIndex::calcOffset(mesh.nCells()) << nl;
Pout<< "local-range: " << globalIndex::calcRange(mesh.nCells()) << nl;
@ -185,7 +185,7 @@ int main(int argc, char *argv[])
// Get a few cell indices
const label nTotalCells = globalNumbering.size();
const label nTotalCells = globalNumbering.totalSize();
Random rndGen(UPstream::myProcNo());
DynamicList<label> globalIDs;

View File

@ -0,0 +1,3 @@
Test-globalIndex2.cxx
EXE = $(FOAM_USER_APPBIN)/Test-globalIndex2

View File

@ -0,0 +1,2 @@
/* EXE_INC = */
/* EXE_LIBS = */

View File

@ -0,0 +1,95 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Test-globalIndex2
Description
More functional tests for the globalIndex class.
\*---------------------------------------------------------------------------*/
#include "globalIndex.H"
#include "argList.H"
#include "Time.H"
#include "IOstreams.H"
#include "Random.H"
#include "IndirectList.H"
#include "SliceList.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
Random rnd(123456);
// #include "setRootCase.H"
// #include "createTime.H"
Info<< nl
<< "simple globalIndex tests" << nl << nl;
Info<< "Construct from indirect list(s)" << nl;
{
// Some sizes
labelList rawSizes(25);
forAll(rawSizes, i)
{
rawSizes[i] = rnd.position<label>(0, 100);
}
Info<< nl
<< "plain sizes: "
<< flatOutput(rawSizes) << nl
<< " offsets: "
<< flatOutput(globalIndex::calcOffsets(rawSizes))
<< nl;
sliceRange slice(0, 5, 5);
Info<< nl
<< "range min/max " << slice.min() << '/' << slice.max() << nl;
SliceList<label> sliceSizes(rawSizes, slice);
Info<< nl
<< "indirect addr: " << sliceSizes.addressing() << nl
<< "indirect sizes: "
<< flatOutput(sliceSizes) << nl
<< " offsets: "
<< flatOutput(globalIndex::calcOffsets(sliceSizes))
<< nl;
}
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -393,6 +393,72 @@ void Foam::CompactListList<T>::transfer
}
template<class T>
template<class SubListType, class OutputIter>
OutputIter Foam::CompactListList<T>::copy_unpack
(
OutputIter d_iter,
const label pos,
label len
) const
{
if (pos >= 0 && pos < this->size())
{
// Change sub-length to (one-past) end position
// len == -1 (like std::string::npos) - search until end
if (len > 0) len += pos;
if (len < 0 || len > this->size())
{
len = this->size();
}
for (label i = pos; i < len; ++i)
{
*d_iter = SubListType(this->localList(i));
++d_iter;
}
}
return d_iter;
}
template<class T>
template<class SubListType, class OutputIter>
OutputIter Foam::CompactListList<T>::copy_unpack
(
OutputIter d_iter,
const labelRange& range
) const
{
return this->copy_unpack<SubListType>(d_iter, range.start(), range.size());
}
template<class T>
template<class SubListType, class OutputIter>
OutputIter Foam::CompactListList<T>::copy_unpack
(
OutputIter d_iter,
const labelUList& indices
) const
{
for (label i : indices)
{
*d_iter = SubListType(this->localList(i));
++d_iter;
}
return d_iter;
}
// Could also support copy_unpack() with IndirectListBase, as required...
// or the caller can also just use copy_unpack with len = 1 and the
// desired position
template<class T>
template<class SubListType>
Foam::List<SubListType>
@ -400,10 +466,7 @@ Foam::CompactListList<T>::unpack() const
{
List<SubListType> lists(size());
forAll(lists, i)
{
lists[i] = SubListType(this->localList(i));
}
this->copy_unpack<SubListType>(lists.begin());
return lists;
}
@ -416,16 +479,24 @@ Foam::CompactListList<T>::unpack(const labelRange& range) const
{
List<SubListType> lists(range.size());
auto iter = lists.begin();
for (const label i : range)
{
*iter = SubListType(this->localList(i));
++iter;
}
this->copy_unpack<SubListType>(lists.begin(), range.start(), range.size());
return lists;
}
template<class T>
template<class SubListType>
Foam::List<SubListType>
Foam::CompactListList<T>::unpack(const labelUList& indices) const
{
List<SubListType> lists(indices.size());
this->copy_unpack<SubListType>(lists.begin(), indices);
return lists;
}
// ************************************************************************* //

View File

@ -319,18 +319,6 @@ public:
void setLocalSize(const label rowi, const label len);
//- Redimension - same as resize()
inline void setSize(const label mRows);
//- Redimension - same as resize()
inline void setSize(const label mRows, const label nVals);
//- Redimension - same as resize()
inline void setSize(const label mRows, const label nVals, const T&);
//- Reset sizes - same as resize()
inline void setSize(const labelUList& listSizes);
//- Swap contents
void swap(CompactListList<T>& other);
@ -358,6 +346,49 @@ public:
// Pack / Unpack
//- Unpack sub-list copies in the range defined by \p pos and \p len
//- with bounding behaviour like List::slice() by copy constructing
//- begin at the destination iterator \p d_iter.
//
// \returns Output iterator to the element in the destination range,
// one past the last element copied.
template<class SubListType, class OutputIter>
OutputIter copy_unpack
(
//! [out] The output destination
OutputIter d_iter,
//! The start of sub-region to copy (no-op if -ve or out-of-range)
const label pos = 0,
//! The length of sub-region to copy (-ve = until the end)
label len = -1
) const;
//- Unpack sub-list copies in the specified range.
//
// \returns Output iterator to the element in the destination range,
// one past the last element copied.
template<class SubListType, class OutputIter>
OutputIter copy_unpack
(
//! [out] The output destination
OutputIter d_iter,
//! The sub-region to copy
const labelRange& range
) const;
//- Unpack sub-list copies for the specified indices
//
// \returns Output iterator to the element in the destination range,
// one past the last element copied.
template<class SubListType, class OutputIter>
OutputIter copy_unpack
(
//! [out] The output destination
OutputIter d_iter,
//! The sub-regions to copy
const labelUList& indices
) const;
//- Return non-compact list of lists
template<class SubListType = List<T>>
List<SubListType> unpack() const;
@ -366,6 +397,10 @@ public:
template<class SubListType = List<T>>
List<SubListType> unpack(const labelRange& range) const;
//- Return non-compact list of lists for specified indices
template<class SubListType = List<T>>
List<SubListType> unpack(const labelUList& indices) const;
// Assignment
@ -443,11 +478,11 @@ public:
// Housekeeping
//- Const access to the packed values
//FOAM_DEPRECATED_STRICT(2022-03, "values()")
FOAM_DEPRECATED_STRICT(2022-03, "values()")
const List<T>& m() const noexcept { return values_; }
//- Non-const access to the packed values
//FOAM_DEPRECATED_STRICT(2022-03, "values()")
FOAM_DEPRECATED_STRICT(2022-03, "values()")
List<T>& m() noexcept { return values_; }
//- Return flat index into packed values
@ -461,6 +496,30 @@ public:
{
return this->toLocal(rowi, i);
}
//- Redimension - same as resize()
void setSize(const label mRows)
{
this->resize(mRows);
}
//- Redimension - same as resize()
void setSize(const label mRows, const label nVals)
{
this->resize(mRows, nVals);
}
//- Redimension - same as resize()
void setSize(const label mRows, const label nVals, const T& val)
{
this->resize(mRows, nVals, val);
}
//- Reset sizes - same as resize()
void setSize(const labelUList& listSizes)
{
this->resize(listSizes);
}
};

View File

@ -364,12 +364,10 @@ inline void Foam::CompactListList<T>::resize(const label mRows)
}
else if (mRows > size())
{
// Grow
FatalErrorInFunction
<< "Cannot be used to extend the list from " << size()
<< " to " << mRows << nl
<< " Please use a different resize() function"
<< abort(FatalError);
// Extend number of rows, each with local size of 0
const label endOffset = offsets_.empty() ? 0 : offsets_.back();
offsets_.resize(mRows+1, endOffset);
}
}
@ -381,9 +379,17 @@ inline void Foam::CompactListList<T>::resize
const label nVals
)
{
offsets_.resize(mRows+1, Zero);
values_.resize(nVals);
// Optionally: enforceSizeSanity();
if (mRows < 1)
{
// Enforce sizing sanity
offsets_.clear();
values_.clear();
}
else
{
offsets_.resize(mRows+1, Zero);
values_.resize(nVals);
}
}
@ -394,9 +400,17 @@ inline void Foam::CompactListList<T>::resize_nocopy
const label nVals
)
{
offsets_.resize(mRows+1, Zero);
values_.resize_nocopy(nVals);
// Optionally: enforceSizeSanity();
if (mRows < 1)
{
// Enforce sizing sanity
offsets_.clear();
values_.clear();
}
else
{
offsets_.resize(mRows+1, Zero);
values_.resize_nocopy(nVals);
}
}
@ -408,49 +422,17 @@ inline void Foam::CompactListList<T>::resize
const T& val
)
{
offsets_.resize(mRows+1, Zero);
values_.resize(nVals, val);
// Optionally: enforceSizeSanity();
}
template<class T>
inline void Foam::CompactListList<T>::setSize(const label mRows)
{
this->resize(mRows);
}
template<class T>
inline void Foam::CompactListList<T>::setSize
(
const label mRows,
const label nVals
)
{
this->resize(mRows+1, nVals);
}
template<class T>
inline void Foam::CompactListList<T>::setSize
(
const label mRows,
const label nVals,
const T& val
)
{
this->resize(mRows+1, nVals, val);
}
template<class T>
inline void Foam::CompactListList<T>::setSize
(
const labelUList& listSizes
)
{
this->resize(listSizes);
if (mRows < 1)
{
// Enforce sizing sanity
offsets_.clear();
values_.clear();
}
else
{
offsets_.resize(mRows+1, Zero);
values_.resize(nVals, val);
}
}

View File

@ -336,6 +336,19 @@ Foam::globalIndex::bin
}
void Foam::globalIndex::resize(const label n)
{
if (n < 1)
{
offsets_.clear();
}
else
{
offsets_.resize(n+1, end_value());
}
}
void Foam::globalIndex::reset
(
const label localSize,

View File

@ -257,6 +257,10 @@ public:
//- Reset to be empty (no offsets)
inline void clear();
//- Change the number of entries (nProcs) in the offsets table.
//- Extending will fill with empty local sizes.
void resize(const label n);
//- Reset from local size, using gather/broadcast
//- with default/specified communicator if parallel.
void reset
@ -512,6 +516,15 @@ public:
const bool checkOverflow = false
);
//- Calculate offsets from an indirect list of local sizes,
//- with optional check for label overflow
template<class Addr>
static labelList calcOffsets
(
const IndirectListBase<label, Addr>& counts,
const bool checkOverflow = false
);
//- Calculate offsets from list of lists,
//- with optional check for label overflow
template<class SubListType>

View File

@ -30,6 +30,42 @@ License
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class Addr>
Foam::labelList
Foam::globalIndex::calcOffsets
(
const IndirectListBase<label, Addr>& counts,
const bool checkOverflow
)
{
labelList values;
const label len = counts.size();
if (len)
{
values.resize(len+1);
label start = 0;
for (label i = 0; i < len; ++i)
{
const label count = counts[i];
values[i] = start;
start += count;
if (checkOverflow && start < values[i])
{
reportOverflowAndExit(i, values[i], count);
}
}
values[len] = start;
}
return values;
}
template<class SubListType>
Foam::labelList
Foam::globalIndex::calcListOffsets