diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBase.C b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBase.C index a3fb7f2355965a566bbaa1918530411091d60dd0..e6b7537cc7832fe3a823f131fb27d5eb09eebce1 100644 --- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBase.C +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBase.C @@ -944,37 +944,29 @@ Foam::mapDistributeBase::mapDistributeBase Pstream::exchangeSizes(subMap_, recvSizes, comm_); // Determine order of receiving - labelListList constructMap(nProcs); + constructSize_ = 0; + constructMap_.resize(nProcs); + - // My local segments first - label nLocal = recvSizes[myRank]; + // My data first { - labelList& myMap = constructMap[myRank]; - myMap.setSize(nLocal); - forAll(myMap, i) - { - myMap[i] = i; - } + const label len = recvSizes[myRank]; + + constructMap_[myRank] = identity(len, constructSize_); + constructSize_ += len; } - label segmenti = nLocal; - forAll(constructMap, proci) + // What the other processors are sending to me + forAll(constructMap_, proci) { if (proci != myRank) { - // What i need to receive is what other processor is sending to me. - label nRecv = recvSizes[proci]; - constructMap[proci].setSize(nRecv); + const label len = recvSizes[proci]; - for (label i = 0; i < nRecv; i++) - { - constructMap[proci][i] = segmenti++; - } + constructMap_[proci] = identity(len, constructSize_); + constructSize_ += len; } } - - constructSize_ = segmenti; - constructMap_.transfer(constructMap); } @@ -1062,402 +1054,6 @@ Foam::label Foam::mapDistributeBase::renumber } -void Foam::mapDistributeBase::compact -( - const boolList& elemIsUsed, - const int tag -) -{ - const label myRank = Pstream::myProcNo(comm_); - const label nProcs = Pstream::nProcs(comm_); - - // 1. send back to sender. Have sender delete the corresponding element - // from the submap and do the same to the constructMap locally - // (and in same order). - - // Send elemIsUsed field to neighbour. Use nonblocking code from - // mapDistributeBase but in reverse order. - if (Pstream::parRun()) - { - label startOfRequests = Pstream::nRequests(); - - // Set up receives from neighbours - - List<boolList> recvFields(nProcs); - - for (const int domain : Pstream::allProcs(comm_)) - { - const labelList& map = subMap_[domain]; - - if (domain != myRank && map.size()) - { - recvFields[domain].setSize(map.size()); - IPstream::read - ( - Pstream::commsTypes::nonBlocking, - domain, - recvFields[domain].data_bytes(), - recvFields[domain].size_bytes(), - tag, - comm_ - ); - } - } - - - List<boolList> sendFields(nProcs); - - for (const int domain : Pstream::allProcs(comm_)) - { - const labelList& map = constructMap_[domain]; - - if (domain != myRank && map.size()) - { - boolList& subField = sendFields[domain]; - subField.setSize(map.size()); - forAll(map, i) - { - subField[i] = accessAndFlip - ( - elemIsUsed, - map[i], - constructHasFlip_, - identityOp() // Do not flip elemIsUsed value - ); - } - - OPstream::write - ( - Pstream::commsTypes::nonBlocking, - domain, - subField.cdata_bytes(), - subField.size_bytes(), - tag, - comm_ - ); - } - } - - - - // Set up 'send' to myself - write directly into recvFields - - { - const labelList& map = constructMap_[myRank]; - - recvFields[myRank].setSize(map.size()); - forAll(map, i) - { - recvFields[myRank][i] = accessAndFlip - ( - elemIsUsed, - map[i], - constructHasFlip_, - identityOp() // Do not flip elemIsUsed value - ); - } - } - - - // Wait for all to finish - - Pstream::waitRequests(startOfRequests); - - - // Compact out all submap entries that are referring to unused elements - for (const int domain : Pstream::allProcs(comm_)) - { - const labelList& map = subMap_[domain]; - - labelList newMap(map.size()); - label newI = 0; - - forAll(map, i) - { - if (recvFields[domain][i]) - { - // So element is used on destination side - newMap[newI++] = map[i]; - } - } - if (newI < map.size()) - { - newMap.setSize(newI); - subMap_[domain].transfer(newMap); - } - } - } - - - // 2. remove from construct map - since end-result (element in elemIsUsed) - // not used. - - label maxConstructIndex = -1; - - for (const int domain : Pstream::allProcs(comm_)) - { - const labelList& map = constructMap_[domain]; - - labelList newMap(map.size()); - label newI = 0; - - forAll(map, i) - { - label destinationI = map[i]; - if (constructHasFlip_) - { - destinationI = mag(destinationI)-1; - } - - // Is element is used on destination side - if (elemIsUsed[destinationI]) - { - maxConstructIndex = max(maxConstructIndex, destinationI); - - newMap[newI++] = map[i]; - } - } - if (newI < map.size()) - { - newMap.setSize(newI); - constructMap_[domain].transfer(newMap); - } - } - - constructSize_ = maxConstructIndex+1; - - // Clear the schedule (note:not necessary if nothing changed) - schedulePtr_.clear(); -} - - -void Foam::mapDistributeBase::compact -( - const boolList& elemIsUsed, - const label localSize, // max index for subMap - labelList& oldToNewSub, - labelList& oldToNewConstruct, - const int tag -) -{ - const label myRank = Pstream::myProcNo(comm_); - const label nProcs = Pstream::nProcs(comm_); - - // 1. send back to sender. Have sender delete the corresponding element - // from the submap and do the same to the constructMap locally - // (and in same order). - - // Send elemIsUsed field to neighbour. Use nonblocking code from - // mapDistributeBase but in reverse order. - if (Pstream::parRun()) - { - label startOfRequests = Pstream::nRequests(); - - // Set up receives from neighbours - - List<boolList> recvFields(nProcs); - - for (const int domain : Pstream::allProcs(comm_)) - { - const labelList& map = subMap_[domain]; - - if (domain != myRank && map.size()) - { - recvFields[domain].setSize(map.size()); - IPstream::read - ( - Pstream::commsTypes::nonBlocking, - domain, - recvFields[domain].data_bytes(), - recvFields[domain].size_bytes(), - tag, - comm_ - ); - } - } - - - List<boolList> sendFields(nProcs); - - for (const int domain : Pstream::allProcs(comm_)) - { - const labelList& map = constructMap_[domain]; - - if (domain != myRank && map.size()) - { - boolList& subField = sendFields[domain]; - subField.setSize(map.size()); - forAll(map, i) - { - label index = map[i]; - if (constructHasFlip_) - { - index = mag(index)-1; - } - subField[i] = elemIsUsed[index]; - } - - OPstream::write - ( - Pstream::commsTypes::nonBlocking, - domain, - subField.cdata_bytes(), - subField.size_bytes(), - tag, - comm_ - ); - } - } - - - - // Set up 'send' to myself - write directly into recvFields - - { - const labelList& map = constructMap_[myRank]; - - recvFields[myRank].setSize(map.size()); - forAll(map, i) - { - label index = map[i]; - if (constructHasFlip_) - { - index = mag(index)-1; - } - recvFields[myRank][i] = elemIsUsed[index]; - } - } - - - // Wait for all to finish - - Pstream::waitRequests(startOfRequests); - - - - - // Work out which elements on the sending side are needed - { - oldToNewSub.setSize(localSize, -1); - - boolList sendElemIsUsed(localSize, false); - - for (const int domain : Pstream::allProcs(comm_)) - { - const labelList& map = subMap_[domain]; - forAll(map, i) - { - if (recvFields[domain][i]) - { - label index = map[i]; - if (subHasFlip_) - { - index = mag(index)-1; - } - sendElemIsUsed[index] = true; - } - } - } - - label newI = 0; - forAll(sendElemIsUsed, i) - { - if (sendElemIsUsed[i]) - { - oldToNewSub[i] = newI++; - } - } - } - - - // Compact out all submap entries that are referring to unused elements - for (const int domain : Pstream::allProcs(comm_)) - { - const labelList& map = subMap_[domain]; - - labelList newMap(map.size()); - label newI = 0; - - forAll(map, i) - { - if (recvFields[domain][i]) - { - // So element is used on destination side - label index = map[i]; - label sign = 1; - if (subHasFlip_) - { - if (index < 0) - { - sign = -1; - } - index = mag(index)-1; - } - label newIndex = oldToNewSub[index]; - if (subHasFlip_) - { - newIndex = sign*(newIndex+1); - } - newMap[newI++] = newIndex; - } - } - newMap.setSize(newI); - subMap_[domain].transfer(newMap); - } - } - - - // 2. remove from construct map - since end-result (element in elemIsUsed) - // not used. - - - oldToNewConstruct.setSize(elemIsUsed.size(), -1); - constructSize_ = 0; - forAll(elemIsUsed, i) - { - if (elemIsUsed[i]) - { - oldToNewConstruct[i] = constructSize_++; - } - } - - for (const int domain : Pstream::allProcs(comm_)) - { - const labelList& map = constructMap_[domain]; - - labelList newMap(map.size()); - label newI = 0; - - forAll(map, i) - { - label destinationI = map[i]; - label sign = 1; - if (constructHasFlip_) - { - if (destinationI < 0) - { - sign = -1; - } - destinationI = mag(destinationI)-1; - } - - // Is element is used on destination side - if (elemIsUsed[destinationI]) - { - label newIndex = oldToNewConstruct[destinationI]; - if (constructHasFlip_) - { - newIndex = sign*(newIndex+1); - } - newMap[newI++] = newIndex; - } - } - newMap.setSize(newI); - constructMap_[domain].transfer(newMap); - } -} - - // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // void Foam::mapDistributeBase::operator=(const mapDistributeBase& rhs) diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBase.H b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBase.H index 63490af5307d73b61dd7a22a8567f4bef7ad927d..30908213a8354255f63fea5905f8c44ba410227d 100644 --- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBase.H +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBase.H @@ -186,6 +186,34 @@ protected: labelList& compactStart ); + //- Synchronize send/recv mask buffers as a 'copy' operation. + // Somewhat similar to Pstream::exchangeContainer + // + // The masks must be properly sized by the caller, which avoids + // a needless all-to-all for the sizes and the sizing is already + // given by the maps. + static void exchangeMasks + ( + const UList<bitSet>& sendMasks, + UList<bitSet>& recvMasks, + const int tag, + const label comm + ); + + //- Bi-direction sync of send/recv buffers using bitwise '&=' + //- combine operation. + // + // The masks must be properly sized by the caller, which avoids + // a needless all-to-all for the sizes and the sizing is already + // given by the maps. + static void unionCombineMasks + ( + UList<bitSet>& sendMasks, + UList<bitSet>& recvMasks, + const int tag, + const label comm + ); + template<class T, class CombineOp, class NegateOp> static void flipAndCombine @@ -225,6 +253,88 @@ private: // Private Member Functions + //- Helper for compactData (private: filescope only!) + // Establishes the exact send/recv elements used after masking. + // + // \param allowedLocalElems Permissible local mapped elements + // (true/false). Can be longer/shorter than actual number + // of mapped elements. + // \param allowedRemoteElems Permissible remote mapped elements + // (true/false). Can be longer/shorter than actual number + // of mapped elements. + // \param[out] sendMasks Mask of local elements sent to procs. + // \param[out] recvMasks Mask of remote elements received + // from procs + // \param tag The message tag + void calcCompactDataRequirements + ( + const bitSet& allowedLocalElems, + const bitSet& allowedRemoteElems, + List<bitSet>& sendMasks, // [out] + List<bitSet>& recvMasks, // [out] + const int tag + ); + + //- Helper for compactLocalData (private: filescope only!) + // Establishes the exact send/recv elements used after masking. + // + // \param allowedLocalElems Permissible local mapped elements + // (true/false). Can be longer/shorter than actual number + // of mapped elements. + // \param[out] sendMasks Mask of local elements sent to procs. + // \param[out] recvMasks Mask of remote elements received by proc. + // from procs + // \param tag The message tag + void calcCompactLocalDataRequirements + ( + const bitSet& allowedLocalElems, + List<bitSet>& sendMasks, // [out] + List<bitSet>& recvMasks, // [out] + const int tag + ); + + //- Helper for compactRemoteData (private: filescope only!) + // Establishes the exact send/recv elements used after masking. + // + // \param allowedRemoteElems Permissible remote mapped elements + // (true/false). Can be longer/shorter than actual number + // of mapped elements. + // \param[out] sendMasks Mask of local elements sent to procs. + // \param[out] recvMasks Mask of remote elements received by proc. + // \param tag The message tag + void calcCompactRemoteDataRequirements + ( + const bitSet& allowedRemoteElems, + List<bitSet>& sendMasks, // [out] + List<bitSet>& recvMasks, // [out] + const int tag + ); + + //- Implementation for compact{Local,Remote}Data (private). + // Also renumbers the subMap/constructMap if oldToNew maps + // are notNull(). + // + // No communication + void compactData + ( + const UList<bitSet>& sendMasks, + const UList<bitSet>& recvMasks, + labelList& oldToNewSub, + labelList& oldToNewConstruct, + const label localSize = -1 + ); + + //- Wrapper for compactData (private) that supplies oldToNew + //- maps for renumbering if doRenumber is true. + // No communication + void compactDataImpl + ( + const UList<bitSet>& sendMasks, + const UList<bitSet>& recvMasks, + const bool doRenumber + ); + + //- Helper for renumbering compacted map elements and updating the //- supplied old-to-new mapping to account for the visit order of //- the original elements @@ -509,22 +619,163 @@ public: // Compaction - //- Compact all maps and layout. - // Returns compaction maps for subMap and constructMap - void compact + //- Compact send/receive maps based on selection of + //- originating local (send) elements. + // Determines and removes the correspondingly unneeded elements + // in the send/receive maps. + // Only compacts the maps, does not change the local layout. + // + // \param allowedLocalElems Permissible local mapped elements + // (true/false). Can be longer/shorter than actual number + // of mapped elements. + // \param tag The message tag + // \param doRenumber Apply oldToNew internally to renumber + // entries (uses renumberMap) and adjust the constructSize + // + // \note generally preferable to compact based on remote data + // (ie, the actual receiver) + void compactLocalData + ( + const bitSet& allowedLocalElems, + const int tag = UPstream::msgType(), + const bool doRenumber = false + ); + + //- Compact send/receive maps based on selection of + //- remote (receive) elements. + // Determines and removes the correspondingly unneeded elements + // in the send/receive maps. + // Only compacts the maps, does not change the local layout. + // + // \param allowedRemoteElems Permissible remote mapped elements + // (true/false). Can be longer/shorter than actual number + // of mapped elements. + // \param tag The message tag + // \param doRenumber Apply oldToNew internally to renumber + // entries (uses renumberMap) and adjust the constructSize + void compactRemoteData + ( + const bitSet& allowedRemoteElems, + const int tag = UPstream::msgType(), + const bool doRenumber = false + ); + + + //- Compact send/receive maps based on selection of + //- originating local (send) elements. + //- Returns compaction mappings for subMap and constructMap. + // + // \param allowedLocalElems Permissible local mapped elements + // (true/false). Can be longer/shorter than actual number + // of mapped elements. + // \param[out] oldToNewSub Old-to-new mapping: subMap + // Disabled if labelList::null(), + // \param[out] oldToNewConstruct Old-to-new mapping: constructMap + // Disabled if labelList::null(), + // \param localSize The max index for subMap (-1: auto-detect) + // \param tag The message tag + // + // \note Applies oldToNew to renumber entries + // (uses renumberMap) and adjust constructSize + // + // \note generally preferable to compact based on remote data + // (ie, the actual receiver) + void compactLocalData ( - const boolList& elemIsUsed, + const bitSet& allowedLocalElems, + labelList& oldToNewSub, + labelList& oldToNewConstruct, + const label localSize = -1, const int tag = UPstream::msgType() ); - //- Compact all maps and layout. - // Returns compaction maps for subMap and constructMap - void compact + //- Compact send/receive maps based on selection of + //- remote (receive) elements. + //- Returns compaction mappings for subMap and constructMap. + // + // \param allowedRemoteElems Permissible remote mapped elements + // (true/false). Can be longer/shorter than actual number + // of mapped elements. + // \param[out] oldToNewSub Old-to-new mapping: subMap + // Disabled if labelList::null(), + // \param[out] oldToNewConstruct Old-to-new mapping: constructMap + // Disabled if labelList::null(), + // \param localSize The max index for subMap (-1: auto-detect) + // \param tag The message tag + // + // \note Applies oldToNew to renumber entries + // (uses renumberMap) and adjust constructSize + void compactRemoteData + ( + const bitSet& allowedRemoteElems, + labelList& oldToNewSub, + labelList& oldToNewConstruct, + const label localSize = -1, + const int tag = UPstream::msgType() + ); + + + //- Compact send/receive maps based on selection of + //- originating local (send) and remote (receive) elements. + // + // The resulting compact numbering: + // - \c subMap (and \c oldToNewSub) : + // will follow the original ordering of \c localElements. + // - \c constructMap (and \c oldToNewConstruct) : + // will follow the original ordering of \c remoteElements. + // . + // \warning ill-defined behaviour if \c localElements + // or \c remoteElements contains duplicates. + void compactData + ( + const labelUList& localElements, + const labelUList& remoteElements, + labelList& oldToNewSub, + labelList& oldToNewConstruct, + const label localSize = -1, + const int tag = UPstream::msgType() + ); + + //- Compact send/receive maps based on selection of + //- originating local (send) elements. + // + // The resulting compact numbering: + // - \c subMap (and \c oldToNewSub) : + // will follow the original ordering of \c localElements. + // - \c constructMap (and \c oldToNewConstruct) : + // numbered in simple ascending order. + // . + // \warning ill-defined behaviour if \c localElements + // contains duplicates. + // + // \note generally preferable to compact based on remote data + // (ie, the actual receiver) + void compactLocalData ( - const boolList& elemIsUsed, - const label localSize, // max index for subMap + const labelUList& localElements, labelList& oldToNewSub, labelList& oldToNewConstruct, + const label localSize = -1, + const int tag = UPstream::msgType() + ); + + //- Compact send/receive maps based on selection of + //- remote (receive) elements. + // + // The resulting compact numbering: + // - \c subMap (and \c oldToNewSub) : + // numbered in simple ascending order. + // - \c constructMap (and \c oldToNewConstruct) : + // will follow the original ordering of \c remoteElements. + // . + // \warning ill-defined behaviour if \c remoteElements + // contains duplicates. + void compactRemoteData + ( + const labelUList& remoteElements, + labelList& oldToNewSub, + labelList& oldToNewConstruct, + const label localSize = -1, const int tag = UPstream::msgType() ); @@ -745,6 +996,25 @@ public: { NotImplemented; } + + //- OpenFOAM-v2112 and earlier naming for compactRemoteData() + //- using boolList. + void compact + ( + const boolList& remoteElemUsed, + const int tag = UPstream::msgType() + ); + + //- OpenFOAM-v2112 and earlier naming for compactRemoteData(). + //- using boolList. + void compact + ( + const boolList& remoteElemUsed, + const label localSize, + labelList& oldToNewSub, + labelList& oldToNewConstruct, + const int tag = UPstream::msgType() + ); }; diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBaseIO.C b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBaseIO.C index eaeda12c764c81788b7ac5f6983e0e40b3af54f5..f86d5f6a4ee48161a9f56a6879ab7b5a492889db 100644 --- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBaseIO.C +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBaseIO.C @@ -36,25 +36,39 @@ namespace Foam // The maps (labelListList) are not human-modifiable but if we need to // inspect them in ASCII, it is much more convenient if each sub-list // is flattened on a single line. -static void writeMaps(Ostream& os, const word& key, const labelListList& maps) +static Ostream& printMaps(Ostream& os, const labelListList& maps) { - if (os.format() == IOstream::BINARY) + if (os.format() == IOstream::BINARY || maps.empty()) { - os.writeEntry(key, maps); + os << maps; } else { - os << indent << key << nl - << maps.size() << nl + os << nl << maps.size() << nl << token::BEGIN_LIST << nl; - // Single-line output + // Compact single-line output for each labelList for (const labelList& map : maps) { map.writeList(os) << nl; } + os << token::END_LIST; + } + + return os; +} - os << token::END_LIST << token::END_STATEMENT << nl; + +static void writeMaps(Ostream& os, const word& key, const labelListList& maps) +{ + if (os.format() == IOstream::BINARY || maps.empty()) + { + os.writeEntry(key, maps); + } + else + { + os << indent << key; + printMaps(os, maps) << token::END_STATEMENT << nl; } } @@ -129,7 +143,8 @@ Foam::Istream& Foam::operator>>(Istream& is, mapDistributeBase& map) { is.fatalCheck(FUNCTION_NAME); - is >> map.constructSize_ >> map.subMap_ >> map.constructMap_ + is >> map.constructSize_ + >> map.subMap_ >> map.constructMap_ >> map.subHasFlip_ >> map.constructHasFlip_ >> map.comm_; @@ -139,11 +154,14 @@ Foam::Istream& Foam::operator>>(Istream& is, mapDistributeBase& map) Foam::Ostream& Foam::operator<<(Ostream& os, const mapDistributeBase& map) { - os << map.constructSize_ << token::NL - << map.subMap_ << token::NL - << map.constructMap_ << token::NL - << map.subHasFlip_ << token::SPACE << map.constructHasFlip_ - << token::SPACE << map.comm_ << token::NL; + os << map.constructSize_ << token::NL; + + printMaps(os, map.subMap_) << token::NL; + printMaps(os, map.constructMap_) << token::NL; + + os << map.subHasFlip_ << token::SPACE + << map.constructHasFlip_ << token::SPACE + << map.comm_ << token::NL; return os; } diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBaseSubset.C b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBaseSubset.C index 679388429001c08d88fb987bd0f1c53963298d5b..9eedb3ee3d431f6eacb6f0418a1a23477f44f9f1 100644 --- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBaseSubset.C +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBaseSubset.C @@ -29,6 +29,252 @@ License #include "bitSet.H" #include "ListOps.H" +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Setup array of element masks to match maps sizes +// +// \param[out] masks Sized for each position in the maps +// \param maps The element maps +static void blankElementMasks(List<bitSet>& masks, const labelListList& maps) +{ + // If base container not already sized + if (masks.empty()) + { + masks.resize(maps.size()); + } + + forAll(masks, proci) + { + masks[proci].reset(); // zero all bits + masks[proci].resize(maps[proci].size()); + } +} + + +// Calculate the element mask correspondig to allowedElems in the maps +// +// \param allowedElems Permissible mapped elements (true/false) +// \param[out] masks True/false for each position within the maps +// \param maps The element maps +// \param hasFlip Map has flip indexing +// +// \return the max index used. +static label calcElementMasks +( + const bitSet& allowedElems, + List<bitSet>& masks, // [out] - often presized before calling + const labelListList& maps, + const bool hasFlip +) +{ + // Index after flipping + const auto unflippedIndex = + ( + hasFlip + ? [](label idx) -> label { return mag(idx)-1; } + : [](label idx) -> label { return idx; } + ); + + + // If not already sized + if (masks.empty()) + { + masks.resize(maps.size()); + } + + label maxIndex = -1; + + forAll(masks, proci) + { + bitSet& mask = masks[proci]; + const labelList& map = maps[proci]; + + mask.reset(); // zero all bits + mask.resize(map.size()); + + forAll(map, i) + { + // Element is used (or not) + const label index = unflippedIndex(map[i]); + + if (allowedElems.test(index)) + { + mask.set(i); + maxIndex = max(maxIndex, index); + } + } + } + + return maxIndex; +} + +} // End namespace Foam + + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +void Foam::mapDistributeBase::exchangeMasks +( + const UList<bitSet>& sendMasks, + UList<bitSet>& recvMasks, + const int tag, + const label comm +) +{ + // Require properly sized mask buffers. + // The information *is* known from the maps, so always use that + // instead having a needless all-to-all for the sizes. + + if (sendMasks.size() != recvMasks.size()) + { + FatalErrorInFunction + << "Mismatched mask sizes: " + << sendMasks.size() << " != " + << recvMasks.size() << nl + << Foam::abort(FatalError); + } + + const label myRank = UPstream::myProcNo(comm); + + if (UPstream::parRun()) + { + #ifdef FULLDEBUG + if (sendMasks.size() > UPstream::nProcs(comm)) + { + FatalErrorInFunction + << "Mask sizes (" << sendMasks.size() + << ") are larger than number of procs:" + << UPstream::nProcs(comm) << nl + << Foam::abort(FatalError); + } + #endif + + const label startOfRequests = UPstream::nRequests(); + + forAll(recvMasks, proci) + { + if (proci != myRank && recvMasks[proci].size()) + { + IPstream::read + ( + UPstream::commsTypes::nonBlocking, + proci, + recvMasks[proci].data_bytes(), + recvMasks[proci].size_bytes(), + tag, + comm + ); + } + } + + forAll(sendMasks, proci) + { + if (proci != myRank && sendMasks[proci].size()) + { + OPstream::write + ( + UPstream::commsTypes::nonBlocking, + proci, + sendMasks[proci].cdata_bytes(), + sendMasks[proci].size_bytes(), + tag, + comm + ); + } + } + + // Wait for all to finish + Pstream::waitRequests(startOfRequests); + } + + // Receiving myself is just a copy + recvMasks[myRank] = sendMasks[myRank]; +} + + +void Foam::mapDistributeBase::unionCombineMasks +( + UList<bitSet>& sendMasks, + UList<bitSet>& recvMasks, + const int tag, + const label comm +) +{ + // Require properly sized mask buffers. + // The information *is* known from the maps, so always use that + // instead having a needless all-to-all for the sizes. + + if (sendMasks.size() != recvMasks.size()) + { + FatalErrorInFunction + << "Mismatched mask sizes: " + << sendMasks.size() << " != " + << recvMasks.size() << nl + << Foam::abort(FatalError); + } + + if (Pstream::parRun()) + { + // Scratch buffers for union operations + List<bitSet> scratch(recvMasks.size()); + + // Size for receives + forAll(scratch, proci) + { + scratch[proci].resize(recvMasks[proci].size()); + } + + // Exchange: from sendMasks -> scratch (intermediate receive) + exchangeMasks(sendMasks, scratch, tag, comm); + + // Update recvMasks (as union) + forAll(recvMasks, proci) + { + recvMasks[proci] &= scratch[proci]; + } + + // Size for sends + forAll(scratch, proci) + { + scratch[proci].resize(sendMasks[proci].size()); + } + + // Exchange: from recvMasks -> scratch (intermediate send) + exchangeMasks(recvMasks, scratch, tag, comm); + + // Final synchronization + forAll(sendMasks, proci) + { + sendMasks[proci] &= scratch[proci]; + } + } + else + { + // Non-parallel: 'synchronize' myself + const label myRank = Pstream::myProcNo(comm); + + recvMasks[myRank] &= sendMasks[myRank]; + sendMasks[myRank] = recvMasks[myRank]; + } + + // Done with parallel exchanges so can shrink the masks to + // the min-size actually needed. + + for (auto& mask : sendMasks) + { + mask.resize_last(); + } + + for (auto& mask : recvMasks) + { + mask.resize_last(); + } +} + + // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // Foam::label Foam::mapDistributeBase::renumberMap @@ -128,4 +374,568 @@ void Foam::mapDistributeBase::renumberVisitOrder } +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +void Foam::mapDistributeBase::calcCompactDataRequirements +( + const bitSet& allowedLocalElems, + const bitSet& allowedRemoteElems, + List<bitSet>& sendMasks, // [out] + List<bitSet>& recvMasks, // [out] + const int tag +) +{ + sendMasks.resize_nocopy(UPstream::nProcs(comm_)); + recvMasks.resize_nocopy(UPstream::nProcs(comm_)); + + // Determine local elements sent to which procs + calcElementMasks + ( + allowedLocalElems, + sendMasks, + subMap_, + subHasFlip_ + ); + + // Determine remote elements received from which procs + calcElementMasks + ( + allowedRemoteElems, + recvMasks, + constructMap_, + constructHasFlip_ + ); + + // Synchronize - combine as '&' union + unionCombineMasks(sendMasks, recvMasks, tag, comm_); +} + + +void Foam::mapDistributeBase::calcCompactLocalDataRequirements +( + const bitSet& allowedLocalElems, + List<bitSet>& sendMasks, // [out] + List<bitSet>& recvMasks, // [out] + const int tag +) +{ + sendMasks.resize_nocopy(UPstream::nProcs(comm_)); + recvMasks.resize_nocopy(UPstream::nProcs(comm_)); + + // Determine local elements sent to which procs + calcElementMasks + ( + allowedLocalElems, + sendMasks, + subMap_, + subHasFlip_ + ); + + blankElementMasks(recvMasks, constructMap_); + + // Exchange: from sendMasks -> recvMasks + exchangeMasks(sendMasks, recvMasks, tag, comm_); +} + + +void Foam::mapDistributeBase::calcCompactRemoteDataRequirements +( + const bitSet& allowedRemoteElems, + List<bitSet>& sendMasks, // [out] + List<bitSet>& recvMasks, // [out] + const int tag +) +{ + sendMasks.resize_nocopy(UPstream::nProcs(comm_)); + recvMasks.resize_nocopy(UPstream::nProcs(comm_)); + + // Determine remote elements received from which procs + calcElementMasks + ( + allowedRemoteElems, + recvMasks, + constructMap_, + constructHasFlip_ + ); + + blankElementMasks(sendMasks, subMap_); + + // Exchange: from recvMasks -> sendMasks + exchangeMasks(recvMasks, sendMasks, tag, comm_); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +void Foam::mapDistributeBase::compactData +( + const UList<bitSet>& sendMasks, + const UList<bitSet>& recvMasks, + labelList& oldToNewSub, + labelList& oldToNewConstruct, + const label localSize // (known) max sizing for subMap +) +{ + // Linear address (subMap) after any flipping + const auto unflippedSendIndex = + ( + subHasFlip_ + ? [](label idx) -> label { return mag(idx)-1; } + : [](label idx) -> label { return idx; } + ); + + // Linear address (constructMap) after any flipping + const auto unflippedRecvIndex = + ( + constructHasFlip_ + ? [](label idx) -> label { return mag(idx)-1; } + : [](label idx) -> label { return idx; } + ); + + + // Compact renumbering enabled if oldToNew maps are notNull + + bitSet indexUsed; + + // The subMap old-to-new mapping + if (notNull(oldToNewSub)) + { + label subMapSize(localSize); + if (subMapSize < 0) + { + subMapSize = getMappedSize(subMap_, subHasFlip_); + } + + oldToNewSub.resize_nocopy(subMapSize); + oldToNewSub = -1; + + indexUsed.reset(); // zero all bits + indexUsed.resize(subMapSize); + + forAll(sendMasks, proci) + { + const bitSet& mask = sendMasks[proci]; + const auto& map = subMap_[proci]; + + for (const label i : mask) + { + const label index = unflippedSendIndex(map[i]); + + indexUsed.set(index); + } + } + + label nCompact = 0; + for (const label i : indexUsed) + { + oldToNewSub[i] = nCompact++; + } + } + + + // The constructMap old-to-new mapping + if (notNull(oldToNewConstruct)) + { + oldToNewConstruct.resize_nocopy(constructSize_); + oldToNewConstruct = -1; + + indexUsed.reset(); // zero all bits + indexUsed.resize(constructSize_); + + forAll(recvMasks, proci) + { + const bitSet& mask = recvMasks[proci]; + const auto& map = constructMap_[proci]; + + for (const label i : mask) + { + const label index = unflippedRecvIndex(map[i]); + + indexUsed.set(index); + } + } + + label nCompact = 0; + for (const label i : indexUsed) + { + oldToNewConstruct[i] = nCompact++; + } + } + + + // Compact out subMap entries referring to unused elements + forAll(sendMasks, proci) + { + const bitSet& mask = sendMasks[proci]; + labelList& map = subMap_[proci]; + + label nCompact = 0; + + for (const label i : mask) + { + // const label index = unflippedSendIndex(map[i]); + // maxLocalIndex = max(maxLocalIndex, index); + + map[nCompact++] = map[i]; + } + + map.resize(nCompact); + } + + + // Compact out constructMap entries referring to unused elements + + label maxRemoteIndex = -1; + + forAll(recvMasks, proci) + { + const bitSet& mask = recvMasks[proci]; + labelList& map = constructMap_[proci]; + + label nCompact = 0; + + for (const label i : mask) + { + const label index = unflippedRecvIndex(map[i]); + maxRemoteIndex = max(maxRemoteIndex, index); + + map[nCompact++] = map[i]; + } + + map.resize(nCompact); + } + + constructSize_ = maxRemoteIndex+1; + + + // Do compact renumbering... + + if (notNull(oldToNewSub)) + { + renumberMap(subMap_, oldToNewSub, subHasFlip_); + } + + if (notNull(oldToNewConstruct)) + { + constructSize_ = + renumberMap(constructMap_, oldToNewConstruct, constructHasFlip_); + } + + // Clear the schedule (note:not necessary if nothing changed) + schedulePtr_.reset(nullptr); +} + + +void Foam::mapDistributeBase::compactData +( + const labelUList& localElements, + const labelUList& remoteElements, + labelList& oldToNewSub, + labelList& oldToNewConstruct, + const label localSize, + const int tag +) +{ + List<bitSet> sendMasks; + List<bitSet> recvMasks; + + calcCompactDataRequirements + ( + bitSet(localElements), + bitSet(remoteElements), + sendMasks, + recvMasks, + tag + ); + + // Perform compaction and renumbering + compactData + ( + sendMasks, + recvMasks, + oldToNewSub, + oldToNewConstruct, + localSize + ); + + // Renumber according to visit order + renumberVisitOrder + ( + localElements, + oldToNewSub, + subMap_, + subHasFlip_ + ); + + // Renumber according to visit order + renumberVisitOrder + ( + remoteElements, + oldToNewConstruct, + constructMap_, + constructHasFlip_ + ); +} + + +void Foam::mapDistributeBase::compactLocalData +( + const labelUList& localElements, + labelList& oldToNewSub, + labelList& oldToNewConstruct, + const label localSize, + const int tag +) +{ + List<bitSet> sendMasks; + List<bitSet> recvMasks; + + calcCompactLocalDataRequirements + ( + // Retain items required on the local side + bitSet(localElements), + sendMasks, + recvMasks, + tag + ); + + // Perform compaction and renumbering + compactData + ( + sendMasks, + recvMasks, + oldToNewSub, + oldToNewConstruct, + localSize + ); + + // Renumber according to visit order + renumberVisitOrder + ( + localElements, + oldToNewSub, + subMap_, + subHasFlip_ + ); +} + + +void Foam::mapDistributeBase::compactRemoteData +( + const labelUList& remoteElements, + labelList& oldToNewSub, + labelList& oldToNewConstruct, + const label localSize, + const int tag +) +{ + List<bitSet> sendMasks; + List<bitSet> recvMasks; + + calcCompactRemoteDataRequirements + ( + // Retain items required on the remote side + bitSet(remoteElements), + sendMasks, + recvMasks, + tag + ); + + // Perform compaction and renumbering + compactData + ( + sendMasks, + recvMasks, + oldToNewSub, + oldToNewConstruct, + localSize + ); + + // Renumber according to visit order + renumberVisitOrder + ( + remoteElements, + oldToNewConstruct, + constructMap_, + constructHasFlip_ + ); +} + + +void Foam::mapDistributeBase::compactDataImpl +( + const UList<bitSet>& sendMasks, + const UList<bitSet>& recvMasks, + const bool doRenumber +) +{ + if (doRenumber) + { + labelList oldToNewSub; + labelList oldToNewConstruct; + + compactData + ( + sendMasks, + recvMasks, + oldToNewSub, + oldToNewConstruct, + -1 // localSize: automatic + ); + } + else + { + // Call with placeholder values + compactData + ( + sendMasks, + recvMasks, + const_cast<labelList&>(labelList::null()), // disabled + const_cast<labelList&>(labelList::null()), // disabled + -1 // localSize: automatic + ); + } +} + + +void Foam::mapDistributeBase::compactLocalData +( + const bitSet& allowedLocalElems, + const int tag, + const bool doRenumber +) +{ + List<bitSet> sendMasks; + List<bitSet> recvMasks; + + calcCompactLocalDataRequirements + ( + allowedLocalElems, + sendMasks, + recvMasks, + tag + ); + + compactDataImpl(sendMasks, recvMasks, doRenumber); +} + + +void Foam::mapDistributeBase::compactRemoteData +( + const bitSet& allowedRemoteElems, + const int tag, + const bool doRenumber +) +{ + List<bitSet> sendMasks; + List<bitSet> recvMasks; + + calcCompactRemoteDataRequirements + ( + allowedRemoteElems, + sendMasks, + recvMasks, + tag + ); + + compactDataImpl(sendMasks, recvMasks, doRenumber); +} + + +void Foam::mapDistributeBase::compactLocalData +( + const bitSet& allowedLocalElems, + labelList& oldToNewSub, + labelList& oldToNewConstruct, + const label localSize, + const int tag +) +{ + List<bitSet> sendMasks; + List<bitSet> recvMasks; + + calcCompactLocalDataRequirements + ( + allowedLocalElems, + sendMasks, + recvMasks, + tag + ); + + compactData + ( + sendMasks, + recvMasks, + oldToNewSub, + oldToNewConstruct, + localSize + ); +} + + +void Foam::mapDistributeBase::compactRemoteData +( + const bitSet& allowedRemoteElems, + labelList& oldToNewSub, + labelList& oldToNewConstruct, + const label localSize, + const int tag +) +{ + List<bitSet> sendMasks; + List<bitSet> recvMasks; + + calcCompactRemoteDataRequirements + ( + allowedRemoteElems, + sendMasks, + recvMasks, + tag + ); + + compactData + ( + sendMasks, + recvMasks, + oldToNewSub, + oldToNewConstruct, + localSize + ); +} + + +// * * * * * * * * * * * * * * * Housekeeping * * * * * * * * * * * * * * * // + +void Foam::mapDistributeBase::compact +( + const boolList& remoteElemUsed, + const int tag +) +{ + // Forward to bitSet version + compactRemoteData(bitSet(remoteElemUsed), tag); +} + + +void Foam::mapDistributeBase::compact +( + const boolList& remoteElemUsed, + const label localSize, + labelList& oldToNewSub, + labelList& oldToNewConstruct, + const int tag +) +{ + // Forward to bitSet version + compactRemoteData + ( + bitSet(remoteElemUsed), + oldToNewSub, + oldToNewConstruct, + localSize, + tag + ); +} + + // ************************************************************************* // diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMeshIO.C b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMeshIO.C index 1fb1b90e874542d23052e9e15f729282955fa652..50e1663f03be0128941f14da64539fc274f1a1d2 100644 --- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMeshIO.C +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMeshIO.C @@ -150,9 +150,11 @@ Foam::Istream& Foam::operator>>(Istream& is, mapDistributePolyMesh& map) is >> map.nOldPoints_ >> map.nOldFaces_ >> map.nOldCells_ + >> map.oldPatchSizes_ >> map.oldPatchStarts_ >> map.oldPatchNMeshPoints_ + >> map.pointMap_ >> map.faceMap_ >> map.cellMap_ @@ -171,6 +173,7 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const mapDistributePolyMesh& map) << map.oldPatchSizes_ << token::NL << map.oldPatchStarts_ << token::NL << map.oldPatchNMeshPoints_ << token::NL + << map.pointMap_ << token::NL << map.faceMap_ << token::NL << map.cellMap_ << token::NL