ENH: new bitSet class and improved PackedList class (closes #751)

- The bitSet class replaces the old PackedBoolList class.
  The redesign provides better block-wise access and reduced method
  calls. This helps both in cases where the bitSet may be relatively
  sparse, and in cases where advantage of contiguous operations can be
  made. This makes it easier to work with a bitSet as top-level object.

  In addition to the previously available count() method to determine
  if a bitSet is being used, now have simpler queries:

    - all()  - true if all bits in the addressable range are empty
    - any()  - true if any bits are set at all.
    - none() - true if no bits are set.

  These are faster than count() and allow early termination.

  The new test() method tests the value of a single bit position and
  returns a bool without any ambiguity caused by the return type
  (like the get() method), nor the const/non-const access (like
  operator[] has). The name corresponds to what std::bitset uses.

  The new find_first(), find_last(), find_next() methods provide a faster
  means of searching for bits that are set.

  This can be especially useful when using a bitSet to control an
  conditional:

  OLD (with macro):

      forAll(selected, celli)
      {
          if (selected[celli])
          {
              sumVol += mesh_.cellVolumes()[celli];
          }
      }

  NEW (with const_iterator):

      for (const label celli : selected)
      {
          sumVol += mesh_.cellVolumes()[celli];
      }

      or manually

      for
      (
          label celli = selected.find_first();
          celli != -1;
          celli = selected.find_next()
      )
      {
          sumVol += mesh_.cellVolumes()[celli];
      }

- When marking up contiguous parts of a bitset, an interval can be
  represented more efficiently as a labelRange of start/size.
  For example,

  OLD:

      if (isA<processorPolyPatch>(pp))
      {
          forAll(pp, i)
          {
              ignoreFaces.set(i);
          }
      }

  NEW:

      if (isA<processorPolyPatch>(pp))
      {
          ignoreFaces.set(pp.range());
      }
This commit is contained in:
Mark Olesen
2018-03-07 11:21:48 +01:00
parent 2768500d57
commit bac943e6fc
191 changed files with 4995 additions and 3151 deletions

View File

@ -25,7 +25,7 @@ License
#include "AABBTree.H"
#include "meshTools.H"
#include "PackedBoolList.H"
#include "bitSet.H"
//#include "OFstream.H"
template<class Type>
@ -157,7 +157,7 @@ void Foam::AABBTree<Type>::createBoxes
{
// Pick up points used by this set of objects
PackedBoolList isUsedPoint(points.size());
bitSet isUsedPoint(points.size());
DynamicList<scalar> component(points.size());
for (const label objI : objectIDs)

View File

@ -47,7 +47,7 @@ SourceFiles
#ifndef FaceCellWave_H
#define FaceCellWave_H
#include "PackedBoolList.H"
#include "bitSet.H"
#include "DynamicList.H"
#include "primitiveFieldsFwd.H"
#include "labelPair.H"
@ -106,13 +106,13 @@ protected:
TrackingData& td_;
//- Has face changed
PackedBoolList changedFace_;
bitSet changedFace_;
//- List of changed faces
DynamicList<label> changedFaces_;
//- Has cell changed
PackedBoolList changedCell_;
bitSet changedCell_;
// Cells that have changed
DynamicList<label> changedCells_;

View File

@ -170,7 +170,7 @@ syncEdges()
{
const globalMeshData& globalData = mesh_.globalData();
const mapDistribute& map = globalData.globalEdgeSlavesMap();
const PackedBoolList& cppOrientation = globalData.globalEdgeOrientation();
const bitSet& cppOrientation = globalData.globalEdgeOrientation();
// Convert patch-edge data into cpp-edge data
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -37,8 +37,8 @@ SourceFiles
#ifndef PatchEdgeFaceWave_H
#define PatchEdgeFaceWave_H
#include "bitSet.H"
#include "scalarField.H"
#include "PackedBoolList.H"
#include "PrimitivePatch.H"
#include "vectorTensorTransform.H"
@ -101,13 +101,13 @@ class PatchEdgeFaceWave
TrackingData& td_;
//- Has edge changed
PackedBoolList changedEdge_;
bitSet changedEdge_;
//- List of changed edges
DynamicList<label> changedEdges_;
//- Has face changed
PackedBoolList changedFace_;
bitSet changedFace_;
//- List of changed faces
DynamicList<label> changedFaces_;
@ -123,7 +123,7 @@ class PatchEdgeFaceWave
// Addressing between edges of patch_ and globalData.coupledPatch()
labelList patchEdges_;
labelList coupledEdges_;
PackedBoolList sameEdgeOrientation_;
bitSet sameEdgeOrientation_;
// Private Member Functions

View File

@ -58,7 +58,7 @@ SourceFiles
#ifndef PointEdgeWave_H
#define PointEdgeWave_H
#include "boolList.H"
#include "bitSet.H"
#include "scalarField.H"
#include "tensorField.H"
@ -114,7 +114,7 @@ class PointEdgeWave
TrackingData& td_;
//- Has point changed
boolList changedPoint_;
bitSet changedPoint_;
//- List of changed points
labelList changedPoints_;
@ -123,7 +123,8 @@ class PointEdgeWave
label nChangedPoints_;
//- Edges that have changed
boolList changedEdge_;
bitSet changedEdge_;
labelList changedEdges_;
label nChangedEdges_;

View File

@ -29,7 +29,7 @@ License
#include "addToMemberFunctionSelectionTable.H"
#include "ListOps.H"
#include "edgeHashes.H"
#include "PackedBoolList.H"
#include "bitSet.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -237,7 +237,7 @@ void Foam::edgeMesh::mergePoints(const scalar mergeDist)
void Foam::edgeMesh::mergeEdges()
{
edgeHashSet uniqEdges(2*edges_.size());
PackedBoolList pointIsUsed(points_.size());
bitSet pointIsUsed(points_.size());
label nUniqEdges = 0;
label nUniqPoints = 0;

View File

@ -26,7 +26,7 @@ License
#include "NASedgeFormat.H"
#include "IFstream.H"
#include "StringStream.H"
#include "PackedBoolList.H"
#include "bitSet.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -173,7 +173,7 @@ bool Foam::fileFormats::NASedgeFormat::read
}
// note which points were really used and which can be culled
PackedBoolList usedPoints(points().size());
bitSet usedPoints(points().size());
// Pass1: relabel edges
@ -189,29 +189,25 @@ bool Foam::fileFormats::NASedgeFormat::read
pointId.clearStorage();
mapPointId.clear();
// Not all the points were used, cull them accordingly
if (unsigned(points().size()) != usedPoints.count())
// Not all points were used, subset/cull them accordingly
if (!usedPoints.all())
{
label nUsed = 0;
pointField& pts = storedPoints();
forAll(pts, pointi)
for (const label pointi : usedPoints)
{
if (usedPoints.test(pointi))
if (nUsed != pointi)
{
if (nUsed != pointi)
{
pts[nUsed] = pts[pointi];
}
// map prev -> new id
mapPointId[pointi] = nUsed;
++nUsed;
pts[nUsed] = pts[pointi];
}
}
pts.setSize(nUsed);
// map prev -> new id
mapPointId.set(pointi, nUsed);
++nUsed;
}
pts.resize(nUsed);
// Renumber edge vertices
for (edge& e : dynEdges)
@ -221,8 +217,6 @@ bool Foam::fileFormats::NASedgeFormat::read
}
}
// transfer to normal lists
storedEdges().transfer(dynEdges);
return true;

View File

@ -26,7 +26,7 @@ License
#include "STARCDedgeFormat.H"
#include "ListOps.H"
#include "clock.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "StringStream.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -132,7 +132,7 @@ bool Foam::fileFormats::STARCDedgeFormat::read
pointId.clear();
// note which points were really used and which can be culled
PackedBoolList usedPoints(points().size());
bitSet usedPoints(points().size());
//
// read .cel file
@ -187,31 +187,27 @@ bool Foam::fileFormats::STARCDedgeFormat::read
mapPointId.clear();
// not all the points were used, cull them accordingly
if (unsigned(points().size()) != usedPoints.count())
// Not all points were used, subset/cull them accordingly
if (!usedPoints.all())
{
label nUsed = 0;
pointField& pts = storedPoints();
forAll(pts, pointi)
for (const label pointi : usedPoints)
{
if (usedPoints.test(pointi))
if (nUsed != pointi)
{
if (nUsed != pointi)
{
pts[nUsed] = pts[pointi];
}
// map prev -> new id
mapPointId.set(pointi, nUsed);
++nUsed;
pts[nUsed] = pts[pointi];
}
// map prev -> new id
mapPointId.set(pointi, nUsed);
++nUsed;
}
pts.resize(nUsed);
pts.setSize(nUsed);
// renumber edge vertices
// Renumber edge vertices
forAll(dynEdges, edgeI)
{
edge& e = dynEdges[edgeI];
@ -221,7 +217,6 @@ bool Foam::fileFormats::STARCDedgeFormat::read
}
}
storedEdges().transfer(dynEdges);
return true;

View File

@ -1481,7 +1481,7 @@ void Foam::extendedEdgeMesh::autoMap
// Compact region edges
labelList subRegionEdges;
{
PackedBoolList isRegionEdge(edges().size(), regionEdges());
bitSet isRegionEdge(edges().size(), regionEdges());
DynamicList<label> newRegionEdges(regionEdges().size());
forAll(edgeMap, subEdgeI)
@ -1525,7 +1525,7 @@ void Foam::extendedEdgeMesh::autoMap
DynamicList<label> normalMap(normals().size());
{
PackedBoolList isSubNormal(normals().size());
bitSet isSubNormal(normals().size());
for (label subPointI = 0; subPointI < subNonFeatStart; subPointI++)
{
label pointI = pointMap[subPointI];

View File

@ -26,7 +26,7 @@ License
#include "extendedEdgeMesh.H"
#include "ListListOps.H"
#include "unitConversion.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "PatchTools.H"
#include "searchableBox.H"
@ -98,7 +98,7 @@ void Foam::extendedEdgeMesh::sortPointsAndEdges
// All feature points have been added
nonFeatureStart_ = tmpPts.size();
PackedBoolList isRegionFeatureEdge(regionFeatureEdges);
bitSet isRegionFeatureEdge(regionFeatureEdges);
forAll(featureEdges, i)
{

View File

@ -26,7 +26,7 @@ License
#include "extendedFeatureEdgeMesh.H"
#include "ListListOps.H"
#include "unitConversion.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "PatchTools.H"
#include "searchableBox.H"
@ -98,7 +98,7 @@ void Foam::extendedFeatureEdgeMesh::sortPointsAndEdges
// All feature points have been added
nonFeatureStart_ = tmpPts.size();
PackedBoolList isRegionFeatureEdge(regionFeatureEdges);
bitSet isRegionFeatureEdge(regionFeatureEdges);
forAll(featureEdges, i)
{

View File

@ -38,7 +38,7 @@ SourceFiles
#include "face.H"
#include "indexedOctree.H"
#include "treeBoundBoxList.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "primitiveMesh.H"
#include "volumeType.H"
@ -72,7 +72,7 @@ class treeDataFace
const labelList faceLabels_;
//- Inverse of faceLabels. For every mesh whether face is in faceLabels.
PackedBoolList isTreeFace_;
bitSet isTreeFace_;
//- Whether to precalculate and store face bounding box
const bool cacheBb_;

View File

@ -716,7 +716,7 @@ void Foam::mappedPatchBase::calcMapping() const
if (debug)
{
// Check that all elements get a value.
PackedBoolList used(patch_.size());
bitSet used(patch_.size());
forAll(constructMap, proci)
{
const labelList& map = constructMap[proci];

View File

@ -67,10 +67,10 @@ void Foam::regionSplit::calcNonCompactRegionSplit
// Seed all faces on (real) boundaries and cell faces next to blockFace,
// since regions can only occur because of boundaries (or blocked faces)
PackedBoolList isSeed(mesh().nFaces());
bitSet isSeed(mesh().nFaces());
// Get internal or coupled faces
PackedBoolList isConnection(syncTools::getInternalOrCoupledFaces(mesh()));
bitSet isConnection(syncTools::getInternalOrCoupledFaces(mesh()));
// 1. Seed (real) boundaries
for
@ -145,7 +145,7 @@ void Foam::regionSplit::calcNonCompactRegionSplit
}
}
List<label> seedFaces(isSeed.used());
List<label> seedFaces(isSeed.toc());
List<minData> seedData(seedFaces.size());
// Seed face with globally unique number

View File

@ -57,7 +57,7 @@ Foam::topoSetSource::addToUsageTable Foam::targetVolumeToCell::usage_
Foam::scalar Foam::targetVolumeToCell::volumeOfSet
(
const PackedBoolList& selected
const bitSet& selected
) const
{
scalar sumVol = 0.0;
@ -76,8 +76,8 @@ Foam::scalar Foam::targetVolumeToCell::volumeOfSet
Foam::label Foam::targetVolumeToCell::selectCells
(
const scalar normalComp,
const PackedBoolList& maskSet,
PackedBoolList& selected
const bitSet& maskSet,
bitSet& selected
) const
{
selected.resize(mesh_.nCells());
@ -89,7 +89,7 @@ Foam::label Foam::targetVolumeToCell::selectCells
{
const point& cc = mesh_.cellCentres()[celli];
if (maskSet[celli] && ((cc&n_) < normalComp))
if (maskSet.test(celli) && ((cc&n_) < normalComp))
{
selected.set(celli);
nSelected++;
@ -108,7 +108,7 @@ void Foam::targetVolumeToCell::combine(topoSet& set, const bool add) const
}
PackedBoolList maskSet(mesh_.nCells(), true);
bitSet maskSet(mesh_.nCells(), true);
label nTotCells = mesh_.globalData().nTotalCells();
if (maskSetName_.size())
{
@ -157,7 +157,7 @@ void Foam::targetVolumeToCell::combine(topoSet& set, const bool add) const
}
}
PackedBoolList maxSelected(mesh_.nCells());
bitSet maxSelected(mesh_.nCells());
maxCells = selectCells(maxComp, maskSet, maxSelected);
//maxVol = volumeOfSet(maxSelected);
@ -177,7 +177,7 @@ void Foam::targetVolumeToCell::combine(topoSet& set, const bool add) const
// Bisection
// ~~~~~~~~~
PackedBoolList selected(mesh_.nCells());
bitSet selected(mesh_.nCells());
label nSelected = -1;
scalar selectedVol = 0.0;
//scalar selectedComp = 0.0;
@ -204,7 +204,7 @@ void Foam::targetVolumeToCell::combine(topoSet& set, const bool add) const
{
low = mid;
PackedBoolList highSelected(mesh_.nCells());
bitSet highSelected(mesh_.nCells());
label nHigh = selectCells(high, maskSet, selected);
if (nSelected == nHigh)
{
@ -215,7 +215,7 @@ void Foam::targetVolumeToCell::combine(topoSet& set, const bool add) const
{
high = mid;
PackedBoolList lowSelected(mesh_.nCells());
bitSet lowSelected(mesh_.nCells());
label nLow = selectCells(low, maskSet, selected);
if (nSelected == nLow)
{
@ -259,7 +259,7 @@ void Foam::targetVolumeToCell::combine(topoSet& set, const bool add) const
forAll(selected, celli)
{
if (selected[celli])
if (selected.test(celli))
{
addOrDelete(set, celli, add);
}

View File

@ -37,7 +37,7 @@ SourceFiles
#define targetVolumeToCell_H
#include "topoSetSource.H"
#include "PackedBoolList.H"
#include "bitSet.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -70,13 +70,13 @@ class targetVolumeToCell
// Private Member Functions
scalar volumeOfSet(const PackedBoolList&) const;
scalar volumeOfSet(const bitSet&) const;
label selectCells
(
const scalar normalComp,
const PackedBoolList&,
PackedBoolList& selected
const bitSet&,
bitSet& selected
) const;
void combine(topoSet& set, const bool add) const;

View File

@ -37,7 +37,7 @@ SourceFiles
#define regionToFace_H
#include "topoSetSource.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "indirectPrimitivePatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -383,7 +383,7 @@ void Foam::faceZoneSet::sync(const polyMesh& mesh)
syncTools::swapBoundaryFaceList(mesh, neiZoneFace);
const PackedBoolList isMasterFace(syncTools::getMasterFaces(mesh));
const bitSet isMasterFace(syncTools::getMasterFaces(mesh));
// Rebuild faceZone addressing and flipMap

View File

@ -27,7 +27,7 @@ License
#include "triSurfaceSearch.H"
#include "OBJstream.H"
#include "labelPairHashes.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "triSurface.H"
#include "pointIndexHit.H"
#include "mergePoints.H"
@ -820,7 +820,7 @@ void Foam::surfaceIntersection::doCutEdges
// Optionally prevent intersection within a single region.
// Like self-intersect, but only if regions are different
PackedBoolList maskRegions(32);
bitSet maskRegions(32);
treeDataTriSurface::findAllIntersectOp
allIntersectOp(searchTree, maskFaces);