Compare commits

..

5 Commits

Author SHA1 Message Date
a94db7170d ENH: improve efficiency of point-cell/cell-point construction (#2715)
- calculate point-cell from point-face if available
2023-03-01 13:07:50 +01:00
1c458cbf7c ENH: improve efficiency of point-cell/cell-point construction (#2715)
- with sort/unique
2023-03-01 13:06:16 +01:00
5a75946f1a ENH: improve efficiency of point-cell/cell-point construction (#2715)
- drop tracking with bitSet and just use straight list, on the
  assumption that the local number is still fairly small and linear
  search will be fast.
2023-03-01 12:26:06 +01:00
709472a7bb ENH: improve efficiency of point-cell/cell-point construction (#2715)
- reworked simpler looping, reinstate pointCells() calculation
  but with markup as per cellPoints()
2023-03-01 12:25:20 +01:00
af14230255 ENH: improved point-cell and cell-point topology methods (#2715)
- original idea
2023-03-01 10:05:56 +01:00
9 changed files with 167 additions and 651 deletions

View File

@ -130,7 +130,7 @@ OptimisationSwitches
// Number processors to change to tree communication
nProcsSimpleSum 0;
// Min numProc to use non-blocking exchange algorithm (Hoeffler: NBX)
nonBlockingExchange 1;
nonBlockingExchange 0;
// MPI buffer size (bytes)
// Can override with the MPI_BUFFER_SIZE env variable.

View File

@ -27,52 +27,14 @@ License
\*---------------------------------------------------------------------------*/
#include "PstreamBuffers.H"
#ifdef Foam_PstreamBuffers_dense
#include "bitSet.H"
#endif
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
#ifdef Foam_PstreamBuffers_map_storage
//- Retrieve size of specified buffer, first checking for existence
static inline label getBufferSize
(
const Map<DynamicList<char>>& buffers,
const label proci
)
{
const auto iter = buffers.cfind(proci);
return (iter.good() ? iter.val().size() : 0);
}
#else
//- Retrieve size of specified buffer, no access checking
static inline label getBufferSize
(
const UList<DynamicList<char>>& buffers,
const label proci
)
{
return buffers[proci].size();
}
#endif
} // End namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::PstreamBuffers::finalExchange
(
const bool wait,
#ifdef Foam_PstreamBuffers_map_storage
Map<label>& recvSizes
#else
labelList& recvSizes
#endif
)
{
// Could also check that it is not called twice
@ -81,35 +43,8 @@ void Foam::PstreamBuffers::finalExchange
if (commsType_ == UPstream::commsTypes::nonBlocking)
{
// Use PEX algorithm
#ifdef Foam_PstreamBuffers_map_storage
// PEX stage 1: exchange sizes (non-blocking consensus)
Pstream::exchangeSizes
(
sendBuffers_,
recvSizes,
tag_,
comm_
);
#else
// Like Pstream::exchangeSizes
labelList sendSizes(nProcs_);
forAll(sendBuffers_, proci)
{
sendSizes[proci] = sendBuffers_[proci].size();
}
recvSizes.resize_nocopy(nProcs_);
// PEX stage 1: exchange sizes (non-blocking consensus)
UPstream::allToAllConsensus
(
sendSizes,
recvSizes,
(tag_ + 314159), // some unique tag?
comm_
);
#endif
// Dense storage uses all-to-all
Pstream::exchangeSizes(sendBuffers_, recvSizes, comm_);
Pstream::exchange<DynamicList<char>, char>
(
@ -124,7 +59,6 @@ void Foam::PstreamBuffers::finalExchange
}
#ifdef Foam_PstreamBuffers_dense
void Foam::PstreamBuffers::finalExchange
(
const labelUList& sendProcs,
@ -160,19 +94,14 @@ void Foam::PstreamBuffers::finalExchange
);
}
}
#endif
void Foam::PstreamBuffers::finalGatherScatter
void Foam::PstreamBuffers::finalExchangeGatherScatter
(
const bool isGather,
const bool wait,
const bool needSizes,
#ifdef Foam_PstreamBuffers_map_storage
Map<label>& recvSizes
#else
labelList& recvSizes
#endif
)
{
// Could also check that it is not called twice
@ -185,20 +114,10 @@ void Foam::PstreamBuffers::finalGatherScatter
// Only send to master [0]. Master is also allowed to 'send' to itself
#ifdef Foam_PstreamBuffers_map_storage
forAllIters(sendBuffers_, iter)
{
if (iter.key() != 0)
{
iter.val().clear();
}
}
#else
for (label proci=1; proci < sendBuffers_.size(); ++proci)
{
sendBuffers_[proci].clear();
}
#endif
}
else
{
@ -214,100 +133,40 @@ void Foam::PstreamBuffers::finalGatherScatter
if (commsType_ == UPstream::commsTypes::nonBlocking)
{
#ifdef Foam_PstreamBuffers_map_storage
labelList recvCount;
#else
labelList& recvCount = recvSizes;
#endif
if (isGather)
{
// gather mode (all-to-one): master [0] <- everyone
const label nSend = getBufferSize(sendBuffers_, 0);
recvSizes =
UPstream::listGatherValues(sendBuffers_[0].size(), comm_);
recvCount = UPstream::listGatherValues(nSend, comm_);
#ifdef Foam_PstreamBuffers_map_storage
// Transcribe recv count from list to map
recvSizes.clear();
if (UPstream::master(comm_))
{
for (label proci=1; proci < recvCount.size(); ++proci)
{
if (recvCount[proci] > 0)
{
recvSizes.insert(proci, recvCount[proci]);
}
}
}
#else
if (!UPstream::master(comm_))
{
recvSizes.resize_nocopy(nProcs_);
recvSizes = Zero;
}
#endif
}
else
{
// scatter mode (one-to-all): master [0] -> everyone
recvSizes.resize_nocopy(nProcs_);
if (UPstream::master(comm_))
{
recvCount.resize(nProcs_, Zero);
#ifdef Foam_PstreamBuffers_map_storage
forAllConstIters(sendBuffers_, iter)
{
recvCount[iter.key()] = iter.val().size();
}
#else
forAll(sendBuffers_, proci)
{
recvCount[proci] = sendBuffers_[proci].size();
recvSizes[proci] = sendBuffers_[proci].size();
}
#endif
}
else
{
// Scattering, so non-master sends nothing
recvCount = Zero;
#ifdef Foam_PstreamBuffers_map_storage
recvSizes.clear();
recvSizes.resize_nocopy(nProcs_);
#else
recvSizes = Zero;
#endif
}
const label nRecv(UPstream::listScatterValues(recvCount, comm_));
const label myRecv(UPstream::listScatterValues(recvSizes, comm_));
if (UPstream::master(comm_))
{
#ifdef Foam_PstreamBuffers_map_storage
recvSizes.clear();
#else
recvSizes = Zero;
#endif
}
else
{
#ifdef Foam_PstreamBuffers_map_storage
recvSizes.clear();
if (nRecv)
{
recvSizes.insert(0, nRecv);
}
#else
recvSizes = Zero;
recvSizes[0] = nRecv;
#endif
}
recvSizes = Zero;
recvSizes[0] = myRecv;
}
Pstream::exchange<DynamicList<char>, char>
(
sendBuffers_,
@ -338,18 +197,9 @@ Foam::PstreamBuffers::PstreamBuffers
tag_(tag),
comm_(communicator),
nProcs_(UPstream::nProcs(comm_)),
#ifdef Foam_PstreamBuffers_map_storage
// Default sizing (128) is probably OK.
// Meshes often have 16-20 neighbours (avg) and 100 neighbours (max)
sendBuffers_(),
recvBuffers_(),
recvPositions_()
#else
sendBuffers_(nProcs_),
recvBuffers_(nProcs_),
recvPositions_(nProcs_, Zero)
#endif
{}
@ -357,23 +207,7 @@ Foam::PstreamBuffers::PstreamBuffers
Foam::PstreamBuffers::~PstreamBuffers()
{
// Check that all data has been consumed
#ifdef Foam_PstreamBuffers_map_storage
forAllConstIters(recvBuffers_, iter)
{
const label proci = iter.key();
const label len = iter.val().size();
const label pos = recvPositions_.lookup(proci, len);
if (pos < len)
{
FatalErrorInFunction
<< "Message from processor " << proci
<< " Only consumed " << pos << " of " << len << " bytes" << nl
<< Foam::abort(FatalError);
}
}
#else
// Check that all data has been consumed.
forAll(recvBuffers_, proci)
{
const label pos = recvPositions_[proci];
@ -387,7 +221,6 @@ Foam::PstreamBuffers::~PstreamBuffers()
<< Foam::abort(FatalError);
}
}
#endif
}
@ -398,11 +231,7 @@ Foam::DynamicList<char>& Foam::PstreamBuffers::accessSendBuffer
const label proci
)
{
#ifdef Foam_PstreamBuffers_map_storage
return sendBuffers_(proci); // Created on demand if needed
#else
return sendBuffers_[proci];
#endif
}
@ -411,21 +240,13 @@ Foam::DynamicList<char>& Foam::PstreamBuffers::accessRecvBuffer
const label proci
)
{
#ifdef Foam_PstreamBuffers_map_storage
return recvBuffers_(proci); // Created on demand if needed
#else
return recvBuffers_[proci];
#endif
}
Foam::label& Foam::PstreamBuffers::accessRecvPosition(const label proci)
{
#ifdef Foam_PstreamBuffers_map_storage
return recvPositions_(proci, 0); // Created on demand if needed
#else
return recvPositions_[proci];
#endif
}
@ -433,38 +254,20 @@ Foam::label& Foam::PstreamBuffers::accessRecvPosition(const label proci)
void Foam::PstreamBuffers::clearSends()
{
#ifdef Foam_PstreamBuffers_map_storage
forAllIters(sendBuffers_, iter)
{
iter.val().clear();
}
#else
for (DynamicList<char>& buf : sendBuffers_)
{
buf.clear();
}
#endif
}
void Foam::PstreamBuffers::clearRecvs()
{
#ifdef Foam_PstreamBuffers_map_storage
forAllIters(recvBuffers_, iter)
{
iter.val().clear();
}
forAllIters(recvPositions_, iter)
{
iter.val() = 0;
}
#else
for (DynamicList<char>& buf : recvBuffers_)
{
buf.clear();
}
recvPositions_ = Zero;
#endif
}
@ -478,41 +281,14 @@ void Foam::PstreamBuffers::clear()
void Foam::PstreamBuffers::clearSend(const label proci)
{
#ifdef Foam_PstreamBuffers_map_storage
{
auto iter = sendBuffers_.find(proci);
if (iter.good())
{
iter.val().clear();
}
}
#else
sendBuffers_[proci].clear();
#endif
}
void Foam::PstreamBuffers::clearRecv(const label proci)
{
#ifdef Foam_PstreamBuffers_map_storage
{
auto iter = recvBuffers_.find(proci);
if (iter.good())
{
iter.val().clear();
}
}
{
auto iter = recvPositions_.find(proci);
if (iter.good())
{
iter.val() = 0;
}
}
#else
recvBuffers_[proci].clear();
recvPositions_[proci] = 0;
#endif
}
@ -520,21 +296,6 @@ void Foam::PstreamBuffers::clearStorage()
{
// Could also clear out entire sendBuffers_, recvBuffers_ and reallocate.
// Not sure if it makes much difference
#ifdef Foam_PstreamBuffers_map_storage
forAllIters(sendBuffers_, iter)
{
iter.val().clearStorage();
}
forAllIters(recvBuffers_, iter)
{
iter.val().clearStorage();
}
forAllIters(recvPositions_, iter)
{
iter.val() = 0;
}
#else
for (DynamicList<char>& buf : sendBuffers_)
{
buf.clearStorage();
@ -544,7 +305,6 @@ void Foam::PstreamBuffers::clearStorage()
buf.clearStorage();
}
recvPositions_ = Zero;
#endif
finishedSendsCalled_ = false;
}
@ -552,15 +312,6 @@ void Foam::PstreamBuffers::clearStorage()
bool Foam::PstreamBuffers::hasSendData() const
{
#ifdef Foam_PstreamBuffers_map_storage
forAllConstIters(sendBuffers_, iter)
{
if (!iter.val().empty())
{
return true;
}
}
#else
for (const DynamicList<char>& buf : sendBuffers_)
{
if (!buf.empty())
@ -568,7 +319,6 @@ bool Foam::PstreamBuffers::hasSendData() const
return true;
}
}
#endif
return false;
}
@ -577,18 +327,6 @@ bool Foam::PstreamBuffers::hasRecvData() const
{
if (finishedSendsCalled_)
{
#ifdef Foam_PstreamBuffers_map_storage
forAllConstIters(recvBuffers_, iter)
{
const label proci = iter.key();
const label len = iter.val().size();
if (recvPositions_.lookup(proci, 0) < len)
{
return true;
}
}
#else
forAll(recvBuffers_, proci)
{
if (recvPositions_[proci] < recvBuffers_[proci].size())
@ -596,7 +334,6 @@ bool Foam::PstreamBuffers::hasRecvData() const
return true;
}
}
#endif
}
#ifdef FULLDEBUG
else
@ -612,7 +349,7 @@ bool Foam::PstreamBuffers::hasRecvData() const
Foam::label Foam::PstreamBuffers::sendDataCount(const label proci) const
{
return getBufferSize(sendBuffers_, proci);
return sendBuffers_[proci].size();
}
@ -620,16 +357,8 @@ Foam::label Foam::PstreamBuffers::recvDataCount(const label proci) const
{
if (finishedSendsCalled_)
{
#ifdef Foam_PstreamBuffers_map_storage
#else
const label len
(
getBufferSize(recvBuffers_, proci)
- recvPositions_.lookup(proci, 0)
);
#else
const label len(recvBuffers_[proci].size() - recvPositions_[proci]);
#endif
if (len > 0)
{
return len;
@ -649,25 +378,10 @@ Foam::label Foam::PstreamBuffers::recvDataCount(const label proci) const
Foam::labelList Foam::PstreamBuffers::recvDataCounts() const
{
labelList counts(nProcs_, Zero);
labelList counts(recvPositions_.size(), Zero);
if (finishedSendsCalled_)
{
#ifdef Foam_PstreamBuffers_map_storage
forAllConstIters(recvBuffers_, iter)
{
const label proci = iter.key();
const label len
(
iter.val().size() - recvPositions_.lookup(proci, 0)
);
if (len > 0)
{
counts[proci] = len;
}
}
#else
forAll(recvBuffers_, proci)
{
const label len(recvBuffers_[proci].size() - recvPositions_[proci]);
@ -677,7 +391,6 @@ Foam::labelList Foam::PstreamBuffers::recvDataCounts() const
counts[proci] = len;
}
}
#endif
}
#ifdef FULLDEBUG
else
@ -691,35 +404,20 @@ Foam::labelList Foam::PstreamBuffers::recvDataCounts() const
}
Foam::label Foam::PstreamBuffers::maxNonLocalRecvCount
(
const label excludeProci
) const
Foam::label Foam::PstreamBuffers::maxNonLocalRecvCount(const label proci) const
{
label maxLen = 0;
if (finishedSendsCalled_)
{
#ifdef Foam_PstreamBuffers_map_storage
forAllConstIters(recvBuffers_, iter)
forAll(recvBuffers_, idx)
{
const label proci = iter.key();
if (excludeProci != proci)
const label len(recvBuffers_[idx].size() - recvPositions_[idx]);
if (idx != proci)
{
label len(iter.val().size() - recvPositions_.lookup(proci, 0));
maxLen = max(maxLen, len);
}
}
#else
forAll(recvBuffers_, proci)
{
if (excludeProci != proci)
{
label len(recvBuffers_[proci].size() - recvPositions_[proci]);
maxLen = max(maxLen, len);
}
}
#endif
}
#ifdef FULLDEBUG
else
@ -751,24 +449,6 @@ Foam::PstreamBuffers::peekRecvData(const label proci) const
{
if (finishedSendsCalled_)
{
#ifdef Foam_PstreamBuffers_map_storage
const auto iter = recvBuffers_.cfind(proci);
if (iter.good())
{
const label pos = recvPositions_.lookup(proci, 0);
const label len = iter.val().size();
if (pos < len)
{
return UList<char>
(
const_cast<char*>(iter.val().cbegin(pos)),
(len - pos)
);
}
}
#else
const label pos = recvPositions_[proci];
const label len = recvBuffers_[proci].size();
@ -780,7 +460,6 @@ Foam::PstreamBuffers::peekRecvData(const label proci) const
(len - pos)
);
}
#endif
}
#ifdef FULLDEBUG
else
@ -804,22 +483,14 @@ bool Foam::PstreamBuffers::allowClearRecv(bool on) noexcept
void Foam::PstreamBuffers::finishedSends(const bool wait)
{
#ifdef Foam_PstreamBuffers_map_storage
Map<label> recvSizes;
#else
labelList recvSizes;
#endif
finalExchange(wait, recvSizes);
}
void Foam::PstreamBuffers::finishedSends
(
#ifdef Foam_PstreamBuffers_map_storage
Map<label>& recvSizes,
#else
labelList& recvSizes,
#endif
const bool wait
)
{
@ -839,7 +510,6 @@ void Foam::PstreamBuffers::finishedSends
}
#ifdef Foam_PstreamBuffers_dense
void Foam::PstreamBuffers::finishedSends
(
const labelUList& sendProcs,
@ -942,58 +612,16 @@ bool Foam::PstreamBuffers::finishedSends
return changed;
}
#endif
void Foam::PstreamBuffers::finishedNeighbourSends
(
const labelUList& neighProcs,
#ifdef Foam_PstreamBuffers_map_storage
Map<label>& recvSizes,
#else
labelList& recvSizes,
#endif
const bool wait
)
{
#ifdef Foam_PstreamBuffers_map_storage
recvSizes.clear();
for (const label proci : neighProcs)
{
recvSizes.insert(proci, 0);
}
// Prune any send buffers that are not neighbours
forAllIters(sendBuffers_, iter)
{
if (!recvSizes.contains(iter.key()))
{
iter.val().clear();
}
}
finalExchange(wait, recvSizes);
#else
// Resize for copying back
recvSizes.resize_nocopy(sendBuffers_.size());
// Prune send buffers that are not neighbours
{
labelHashSet keepProcs(neighProcs);
// Prune send buffers that are not neighbours
forAll(sendBuffers_, proci)
{
if (!keepProcs.contains(proci))
{
sendBuffers_[proci].clear();
}
}
}
finalExchange(wait, recvSizes);
#endif
finishedSends(neighProcs, neighProcs, recvSizes, wait);
}
@ -1003,65 +631,31 @@ void Foam::PstreamBuffers::finishedNeighbourSends
const bool wait
)
{
#ifdef Foam_PstreamBuffers_map_storage
finishedSends(neighProcs, neighProcs, wait);
#else
labelList recvSizes;
// Prune send buffers that are not neighbours
{
labelHashSet keepProcs(neighProcs);
// Prune send buffers that are not neighbours
forAll(sendBuffers_, proci)
{
if (!keepProcs.contains(proci))
{
sendBuffers_[proci].clear();
}
}
}
finalExchange(wait, recvSizes);
#endif
}
void Foam::PstreamBuffers::finishedGathers(const bool wait)
{
#ifdef Foam_PstreamBuffers_map_storage
Map<label> recvSizes;
finalGatherScatter(true, wait, false, recvSizes);
#else
labelList recvSizes;
finalGatherScatter(true, wait, false, recvSizes);
#endif
finalExchangeGatherScatter(true, wait, false, recvSizes);
}
void Foam::PstreamBuffers::finishedScatters(const bool wait)
{
#ifdef Foam_PstreamBuffers_map_storage
Map<label> recvSizes;
finalGatherScatter(false, wait, false, recvSizes);
#else
labelList recvSizes;
finalGatherScatter(false, wait, false, recvSizes);
#endif
finalExchangeGatherScatter(false, wait, false, recvSizes);
}
void Foam::PstreamBuffers::finishedGathers
(
#ifdef Foam_PstreamBuffers_map_storage
Map<label>& recvSizes,
#else
labelList& recvSizes,
#endif
const bool wait
)
{
finalGatherScatter(true, wait, true, recvSizes);
finalExchangeGatherScatter(true, wait, true, recvSizes);
if (commsType_ != UPstream::commsTypes::nonBlocking)
{
@ -1079,15 +673,11 @@ void Foam::PstreamBuffers::finishedGathers
void Foam::PstreamBuffers::finishedScatters
(
#ifdef Foam_PstreamBuffers_map_storage
Map<label>& recvSizes,
#else
labelList& recvSizes,
#endif
const bool wait
)
{
finalGatherScatter(false, wait, true, recvSizes);
finalExchangeGatherScatter(false, wait, true, recvSizes);
if (commsType_ != UPstream::commsTypes::nonBlocking)
{

View File

@ -100,27 +100,16 @@ SourceFiles
#define Foam_PstreamBuffers_H
#include "DynamicList.H"
#include "Map.H"
#include "UPstream.H"
#include "IOstream.H"
// Transitional
#define Foam_PstreamBuffers_map_storage
// #define Foam_PstreamBuffers_dense
#ifdef Foam_PstreamBuffers_dense
#undef Foam_PstreamBuffers_map_storage
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
#ifdef Foam_PstreamBuffers_dense
class bitSet;
#endif
/*---------------------------------------------------------------------------*\
Class PstreamBuffers Declaration
@ -154,19 +143,6 @@ class PstreamBuffers
// Buffer storage
#ifdef Foam_PstreamBuffers_map_storage
//- Send buffers (sparse)
Map<DynamicList<char>> sendBuffers_;
//- Receive buffers (sparse)
Map<DynamicList<char>> recvBuffers_;
//- Current read positions within recvBuffers_ (sparse)
Map<label> recvPositions_;
#else
//- Send buffers. Size is nProcs()
List<DynamicList<char>> sendBuffers_;
@ -176,8 +152,6 @@ class PstreamBuffers
//- Current read positions within recvBuffers_. Size is nProcs()
labelList recvPositions_;
#endif
// Private Member Functions
@ -186,17 +160,12 @@ class PstreamBuffers
void finalExchange
(
const bool wait,
#ifdef Foam_PstreamBuffers_map_storage
Map<label>& recvSizes
#else
labelList& recvSizes
#endif
);
//- Mark sends as done.
// Only exchange sizes using the sendProcs/recvProcs subset
// (nonBlocking comms).
#ifdef Foam_PstreamBuffers_dense
void finalExchange
(
const labelUList& sendProcs,
@ -204,7 +173,6 @@ class PstreamBuffers
const bool wait,
labelList& recvSizes
);
#endif
//- For all-to-one or one-to-all
void finalExchangeGatherScatter
@ -212,11 +180,7 @@ class PstreamBuffers
const bool isGather,
const bool wait,
const bool needSizes, // If recvSizes needed or scratch
#ifdef Foam_PstreamBuffers_map_storage
Map<label>& recvSizes
#else
labelList& recvSizes
#endif
);
@ -376,7 +340,7 @@ public:
//- Maximum receive size, excluding the specified processor rank
//- Must call finishedSends() or other finished.. method first!
label maxNonLocalRecvCount(const label excludeProci) const;
label maxNonLocalRecvCount(const label proci) const;
//- Number of unconsumed receive bytes for the specified processor.
//- Must call finishedSends() or other finished.. method first!
@ -428,15 +392,7 @@ public:
// \param wait wait for requests to complete (in nonBlocking mode)
//
// \warning currently only valid for nonBlocking comms.
void finishedSends
(
#ifdef Foam_PstreamBuffers_map_storage
Map<label>& recvSizes,
#else
labelList& recvSizes,
#endif
const bool wait = true
);
void finishedSends(labelList& recvSizes, const bool wait = true);
// Functions with restricted neighbours
@ -450,14 +406,12 @@ public:
// \param wait wait for requests to complete (in nonBlocking mode)
//
// \warning currently only valid for nonBlocking comms.
#ifdef Foam_PstreamBuffers_dense
void finishedSends
(
const labelUList& sendProcs,
const labelUList& recvProcs,
const bool wait = true
);
#endif
//- Mark sends as done using subset of send/recv ranks
//- to exchange data on. Recovers the sizes (bytes) received.
@ -470,7 +424,6 @@ public:
// \param wait wait for requests to complete (in nonBlocking mode)
//
// \warning currently only valid for nonBlocking comms.
#ifdef Foam_PstreamBuffers_dense
void finishedSends
(
const labelUList& sendProcs,
@ -478,7 +431,6 @@ public:
labelList& recvSizes,
const bool wait = true
);
#endif
//- A caching version that uses a limited send/recv connectivity.
//
@ -491,7 +443,6 @@ public:
// \return True if the send/recv connectivity changed
//
// \warning currently only valid for nonBlocking comms.
#ifdef Foam_PstreamBuffers_dense
bool finishedSends
(
bitSet& sendConnections,
@ -499,7 +450,6 @@ public:
DynamicList<label>& recvProcs,
const bool wait = true
);
#endif
//- Mark sends as done using subset of send/recv ranks
//- and recover the sizes (bytes) received.
@ -530,11 +480,7 @@ public:
void finishedNeighbourSends
(
const labelUList& neighProcs,
#ifdef Foam_PstreamBuffers_map_storage
Map<label>& recvSizes,
#else
labelList& recvSizes,
#endif
const bool wait = true
);
@ -559,15 +505,7 @@ public:
// \param wait wait for requests to complete (in nonBlocking mode)
//
// \warning currently only valid for nonBlocking comms.
void finishedGathers
(
#ifdef Foam_PstreamBuffers_map_storage
Map<label>& recvSizes,
#else
labelList& recvSizes,
#endif
const bool wait = true
);
void finishedGathers(labelList& recvSizes, const bool wait = true);
//- Mark all sends to sub-procs as done.
//
@ -587,15 +525,7 @@ public:
// \param wait wait for requests to complete (in nonBlocking mode)
//
// \warning currently only valid for nonBlocking comms.
void finishedScatters
(
#ifdef Foam_PstreamBuffers_map_storage
Map<label>& recvSizes,
#else
labelList& recvSizes,
#endif
const bool wait = true
);
void finishedScatters(labelList& recvSizes, const bool wait = true);
};

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,6 +29,7 @@ License
#include "primitiveMesh.H"
#include "cell.H"
#include "bitSet.H"
#include "DynamicList.H"
#include "ListOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -57,12 +58,49 @@ void Foam::primitiveMesh::calcCellPoints() const
<< "cellPoints already calculated"
<< abort(FatalError);
}
else
else if (hasPointCells())
{
// Invert pointCells
cpPtr_ = new labelListList(nCells());
invertManyToMany(nCells(), pointCells(), *cpPtr_);
}
else
{
// Calculate cell-point topology
cpPtr_ = new labelListList(nCells());
auto& cellPointAddr = *cpPtr_;
const cellList& cellLst = cells();
const faceList& faceLst = faces();
// Vertex labels for the current cell
DynamicList<label> vertices(256);
const label loopLen = nCells();
for (label celli = 0; celli < loopLen; ++celli)
{
// Clear any previous contents
vertices.clear();
for (const label facei : cellLst[celli])
{
for (const label pointi : faceLst[facei])
{
vertices.push_back(pointi);
}
}
// Sort + unique to eliminate duplicates
std::sort(vertices.begin(), vertices.end());
auto last = std::unique(vertices.begin(), vertices.end());
vertices.resize(label(last - vertices.begin()));
cellPointAddr[celli] = vertices;
}
}
}

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,14 +29,13 @@ License
#include "primitiveMesh.H"
#include "cell.H"
#include "bitSet.H"
#include "DynamicList.H"
#include "ListOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::primitiveMesh::calcPointCells() const
{
// Loop through cells and mark up points
if (debug)
{
Pout<< "primitiveMesh::calcPointCells() : "
@ -59,48 +59,121 @@ void Foam::primitiveMesh::calcPointCells() const
<< "pointCells already calculated"
<< abort(FatalError);
}
else if (hasCellPoints())
{
// Invert cellPoints
pcPtr_ = new labelListList(nPoints());
invertManyToMany(nPoints(), cellPoints(), *pcPtr_);
}
else if (hasPointFaces())
{
// Calculate point-cell from point-face information
const labelList& own = faceOwner();
const labelList& nei = faceNeighbour();
const labelListList& pFaces = pointFaces();
const label loopLen = nPoints();
pcPtr_ = new labelListList(nPoints());
auto& pointCellAddr = *pcPtr_;
DynamicList<label> storage(256);
for (label pointi = 0; pointi < loopLen; ++pointi)
{
// Clear any previous contents
storage.clear();
for (const label facei : pFaces[pointi])
{
// Owner cell
storage.push_back(own[facei]);
// Neighbour cell
if (facei < nInternalFaces())
{
storage.push_back(nei[facei]);
}
}
// Sort + unique to eliminate duplicates
std::sort(storage.begin(), storage.end());
auto last = std::unique(storage.begin(), storage.end());
storage.resize(label(last - storage.begin()));
pointCellAddr[pointi] = storage;
}
}
else
{
const cellList& cf = cells();
// Calculate point-cell topology
// Count number of cells per point
const cellList& cellLst = cells();
const faceList& faceLst = faces();
labelList npc(nPoints(), Zero);
// Vertex labels for the current cell
// Note: since the number of points per cell is relatively small,
// using a bitSet to track does not help much.
// Using a labelHashSet to track has too many allocations.
DynamicList<label> vertices(256);
forAll(cf, celli)
const label loopLen = nCells();
// Step 1: count number of cells per point
labelList pointCount(nPoints(), Zero);
for (label celli = 0; celli < loopLen; ++celli)
{
const labelList curPoints = cf[celli].labels(faces());
// Clear any previous contents
vertices.clear();
forAll(curPoints, pointi)
for (const label facei : cellLst[celli])
{
label ptI = curPoints[pointi];
npc[ptI]++;
for (const label pointi : faceLst[facei])
{
// Only once for each point id
if (!vertices.contains(pointi))
{
vertices.push_back(pointi);
++pointCount[pointi];
}
}
}
}
// Size and fill cells per point
// Step 2: set sizing, reset counters
pcPtr_ = new labelListList(npc.size());
labelListList& pointCellAddr = *pcPtr_;
pcPtr_ = new labelListList(nPoints());
auto& pointCellAddr = *pcPtr_;
forAll(pointCellAddr, pointi)
{
pointCellAddr[pointi].setSize(npc[pointi]);
pointCellAddr[pointi].resize_nocopy(pointCount[pointi]);
pointCount[pointi] = 0;
}
npc = 0;
forAll(cf, celli)
// Step 3: fill in values. Logic as per step 1
for (label celli = 0; celli < loopLen; ++celli)
{
const labelList curPoints = cf[celli].labels(faces());
// Clear any previous contents
vertices.clear();
forAll(curPoints, pointi)
for (const label facei : cellLst[celli])
{
label ptI = curPoints[pointi];
pointCellAddr[ptI][npc[ptI]++] = celli;
for (const label pointi : faceLst[facei])
{
// Only once for each point id
if (!vertices.contains(pointi))
{
vertices.push_back(pointi);
pointCellAddr[pointi][pointCount[pointi]++] = celli;
}
}
}
}
}

View File

@ -43,12 +43,7 @@ Foam::zoneDistribute::zoneDistribute(const fvMesh& mesh)
MeshObject<fvMesh, Foam::TopologicalMeshObject, zoneDistribute>(mesh),
stencil_(zoneCPCStencil::New(mesh)),
globalNumbering_(stencil_.globalNumbering()),
#ifdef Foam_PstreamBuffers_dense
send_(UPstream::nProcs()),
#else
// Default map sizing (as per PstreamBuffers)
send_(),
#endif
pBufs_(UPstream::commsTypes::nonBlocking)
{
// Don't clear storage on persistent buffer
@ -95,7 +90,6 @@ void Foam::zoneDistribute::setUpCommforZone
if (UPstream::parRun())
{
#ifdef Foam_PstreamBuffers_dense
List<labelHashSet> needed(UPstream::nProcs());
// Bin according to originating (sending) processor
@ -142,61 +136,6 @@ void Foam::zoneDistribute::setUpCommforZone
fromProc >> send_[proci];
}
}
#else
forAllIters(send_, iter)
{
iter.val().clear();
}
// Bin according to originating (sending) processor
for (const label celli : stencil.needsComm())
{
if (zone[celli])
{
for (const label gblIdx : stencil_[celli])
{
const label proci = globalNumbering_.whichProcID(gblIdx);
if (proci != Pstream::myProcNo())
{
send_(proci).insert(gblIdx);
}
}
}
}
// Stream the send data into PstreamBuffers,
pBufs_.clear();
forAllIters(send_, iter)
{
const label proci = iter.key();
auto& indices = iter.val();
if (proci != UPstream::myProcNo() && !indices.empty())
{
// Serialize as List
UOPstream toProc(proci, pBufs_);
toProc << indices;
}
// Clear out old contents
indices.clear();
}
pBufs_.finishedSends();
for (const int proci : pBufs_.allProcs())
{
if (proci != UPstream::myProcNo() && pBufs_.recvDataCount(proci))
{
UIPstream fromProc(proci, pBufs_);
fromProc >> send_(proci);
}
}
#endif
}
}

View File

@ -90,8 +90,6 @@ class zoneDistribute
//- Global number into index of cells/faces
const globalIndex& globalNumbering_;
#ifdef Foam_PstreamBuffers_dense
//- Global cell/face index to send for processor-to-processor comms
List<labelList> send_;
@ -104,14 +102,6 @@ class zoneDistribute
//- Parallel [cache]: recv data from these ranks
DynamicList<label> recvProcs_;
#else
//- Per proc the global cell/face index to send for
//- processor-to-processor comms
Map<labelHashSet> send_;
#endif
//- Persistent set of exchange buffers
PstreamBuffers pBufs_;

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 DLR
Copyright (C) 2020-2023 OpenCFD Ltd.
Copyright (C) 2020-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -161,8 +161,6 @@ Foam::Map<Type> Foam::zoneDistribute::getDatafromOtherProc
if (UPstream::parRun())
{
#ifdef Foam_PstreamBuffers_dense
if (sendConnections_.empty())
{
WarningInFunction
@ -210,48 +208,6 @@ Foam::Map<Type> Foam::zoneDistribute::getDatafromOtherProc
neiValues += tmpValues;
}
}
#else
pBufs_.clear();
forAllConstIters(send_, iter)
{
const label proci = iter.key();
const auto& indices = iter.val();
if (proci != UPstream::myProcNo() && !indices.empty())
{
// Serialize as Map
Map<Type> sendValues(2*indices.size());
for (const label sendIdx : indices)
{
sendValues.insert
(
sendIdx,
getLocalValue(phi, globalNumbering_.toLocal(sendIdx))
);
}
UOPstream toProc(proci, pBufs_);
toProc << sendValues;
}
}
pBufs_.finishedSends();
for (const int proci : pBufs_.allProcs())
{
if (proci != UPstream::myProcNo() && pBufs_.recvDataCount(proci))
{
UIPstream fromProc(proci, pBufs_);
Map<Type> tmpValues(fromProc);
neiValues += tmpValues;
}
}
#endif
}
return neiValues;