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:
parent
ef201ecfea
commit
cfb752647a
@ -1,3 +1,3 @@
|
||||
Test-CompactListList.C
|
||||
Test-CompactListList.cxx
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-CompactListList
|
||||
|
@ -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}));
|
||||
|
@ -1,3 +0,0 @@
|
||||
Test-globalIndex.C
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-globalIndex
|
@ -1 +0,0 @@
|
||||
EXE_INC = /* -DFULLDEBUG -g -O0 */
|
3
applications/test/globalIndex1/Make/files
Normal file
3
applications/test/globalIndex1/Make/files
Normal file
@ -0,0 +1,3 @@
|
||||
Test-globalIndex1.cxx
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-globalIndex1
|
2
applications/test/globalIndex1/Make/options
Normal file
2
applications/test/globalIndex1/Make/options
Normal file
@ -0,0 +1,2 @@
|
||||
/* EXE_INC = */
|
||||
/* EXE_LIBS = */
|
@ -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;
|
3
applications/test/globalIndex2/Make/files
Normal file
3
applications/test/globalIndex2/Make/files
Normal file
@ -0,0 +1,3 @@
|
||||
Test-globalIndex2.cxx
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-globalIndex2
|
2
applications/test/globalIndex2/Make/options
Normal file
2
applications/test/globalIndex2/Make/options
Normal file
@ -0,0 +1,2 @@
|
||||
/* EXE_INC = */
|
||||
/* EXE_LIBS = */
|
95
applications/test/globalIndex2/Test-globalIndex2.cxx
Normal file
95
applications/test/globalIndex2/Test-globalIndex2.cxx
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user