ENH: improve efficiency of point-cell/cell-point construction (#2715)

- reworked simpler looping, reinstate pointCells() calculation
  but with markup as per cellPoints()
This commit is contained in:
alonzameret
2023-02-27 15:32:32 +02:00
committed by Mark Olesen
parent af14230255
commit 709472a7bb
2 changed files with 100 additions and 38 deletions

View File

@ -29,6 +29,7 @@ License
#include "primitiveMesh.H"
#include "cell.H"
#include "bitSet.H"
#include "DynamicList.H"
#include "ListOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -67,52 +68,40 @@ void Foam::primitiveMesh::calcCellPoints() const
{
// Calculate cell-point topology
const cellList& cL = cells();
const faceList& fL = faces();
cpPtr_ = new labelListList(nCells());
labelListList& cellPoints = *cpPtr_;
auto& cellPointAddr = *cpPtr_;
// Mark points we have found as to not count them twice for the same cell
Foam::bitSet foundPoint(nPoints(), false);
const cellList& cellLst = cells();
const faceList& faceLst = faces();
forAll (cL, cellIdx)
// For tracking (only use each point id once)
bitSet usedPoints(nPoints());
// Vertex labels for the current cell
DynamicList<label> vertices(256);
const label loopLen = nCells();
for (label celli = 0; celli < loopLen; ++celli)
{
// List of faces on the cell
const Foam::labelList& cellFaces = cL[cellIdx];
// List that will contain the cell's points
Foam::labelList& neiPoints = cellPoints[cellIdx];
// Clear any previous contents
usedPoints.unset(vertices);
vertices.clear();
// Over-Estimate number of neighbour points
int pointCnt = 0;
for (label faceIdx : cellFaces)
for (const label facei : cellLst[celli])
{
pointCnt += fL[faceIdx].size();
}
neiPoints.resize(pointCnt);
// Find the neighbour points
pointCnt = 0;
for (label faceIdx : cellFaces)
{
for (label pointIdx : fL[faceIdx])
for (const label pointi : faceLst[facei])
{
// This check guarantees every point is added exactly once
if (foundPoint[pointIdx]) continue;
foundPoint[pointIdx] = true;
neiPoints[pointCnt++] = pointIdx;
// Only once for each point id
if (usedPoints.set(pointi))
{
vertices.push_back(pointi);
}
}
}
// Resize to actual value
neiPoints.resize(pointCnt);
// Clear bitSet before next iteration
for (label pointIdx : neiPoints)
{
foundPoint[pointIdx] = false;
}
cellPointAddr[celli] = vertices; // unsorted
}
}
}

View File

@ -29,6 +29,7 @@ License
#include "primitiveMesh.H"
#include "cell.H"
#include "bitSet.H"
#include "DynamicList.H"
#include "ListOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -58,13 +59,85 @@ void Foam::primitiveMesh::calcPointCells() const
<< "pointCells already calculated"
<< abort(FatalError);
}
else
else if (hasCellPoints())
{
// Invert cellPoints
(void)cellPoints();
pcPtr_ = new labelListList(nPoints());
invertManyToMany(nPoints(), cellPoints(), *pcPtr_);
}
else
{
// Calculate point-cell topology
const cellList& cellLst = cells();
const faceList& faceLst = faces();
// For tracking (only use each point id once)
bitSet usedPoints(nPoints());
// Vertex labels for the current cell
DynamicList<label> vertices(256);
const label loopLen = nCells();
// Step 1: count number of cells per point
labelList pointCount(nPoints(), Zero);
for (label celli = 0; celli < loopLen; ++celli)
{
// Clear any previous contents
usedPoints.unset(vertices);
vertices.clear();
for (const label facei : cellLst[celli])
{
for (const label pointi : faceLst[facei])
{
// Only once for each point id
if (usedPoints.set(pointi))
{
vertices.push_back(pointi);
++pointCount[pointi];
}
}
}
}
// Step 2: set sizing, reset counters
pcPtr_ = new labelListList(nPoints());
auto& pointCellAddr = *pcPtr_;
forAll(pointCellAddr, pointi)
{
pointCellAddr[pointi].resize_nocopy(pointCount[pointi]);
pointCount[pointi] = 0;
}
// Step 3: fill in values. Logic as per step 1
for (label celli = 0; celli < loopLen; ++celli)
{
// Clear any previous contents
usedPoints.unset(vertices);
vertices.clear();
for (const label facei : cellLst[celli])
{
for (const label pointi : faceLst[facei])
{
// Only once for each point id
if (usedPoints.set(pointi))
{
vertices.push_back(pointi);
pointCellAddr[pointi][pointCount[pointi]++] = celli;
}
}
}
}
}
}