diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.cpp b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.cpp index 696254c44e0fe1150ded8566650483878377928c..d59fa8d017069b665bd6b91f6cf1e685782fab24 100644 --- a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.cpp +++ b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.cpp @@ -445,7 +445,7 @@ void IndexRearrangementForStreams::findIfSparseIndexIsInSendIndicesAndAddToCommV void IndexRearrangementForStreams::findIndicesNotInCommAfterFtoC(const uint &numberOfSendOrRecvIndices, int *sendOrReceiveIndices, std::vector<int> &sendOrReceiveIndicesAfterFtoC, - std::vector<int> &sendOrIndicesOther) const + std::vector<int> &sendOrIndicesOther) { int sparseIndexSend; for (uint posInSendIndices = 0; posInSendIndices < numberOfSendOrRecvIndices; posInSendIndices++) { diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.h b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.h index 6102c2b10f70e54feb10c4b575cd8c07473b608b..0b0401d3424f7a953bf2fa92d0382fd9256a635a 100644 --- a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.h +++ b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.h @@ -62,9 +62,12 @@ protected: std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const; //! \brief Initializes the send indices for the communication after the interpolation from fine to coarse - void initRecvIndicesForCommAfterFToCX(uint level, int indexOfProcessNeighbor, int direction, std::vector<uint>& recvIndicesForCommAfterFtoCPositions) const; - void initRecvIndicesForCommAfterFToCY(uint level, int indexOfProcessNeighbor, int direction, std::vector<uint>& recvIndicesForCommAfterFtoCPositions) const; - void initRecvIndicesForCommAfterFToCZ(uint level, int indexOfProcessNeighbor, int direction, std::vector<uint>& recvIndicesForCommAfterFtoCPositions) const; + void initRecvIndicesForCommAfterFToCX(uint level, int indexOfProcessNeighbor, int direction, + std::vector<uint> &recvIndicesForCommAfterFtoCPositions) const; + void initRecvIndicesForCommAfterFToCY(uint level, int indexOfProcessNeighbor, int direction, + std::vector<uint> &recvIndicesForCommAfterFtoCPositions) const; + void initRecvIndicesForCommAfterFToCZ(uint level, int indexOfProcessNeighbor, int direction, + std::vector<uint> &recvIndicesForCommAfterFtoCPositions) const; //! \brief Initializes pointers for reduced communication after the interpolation from fine to coarse by copying //! them from "normal" communication @@ -82,10 +85,10 @@ protected: //! \brief The send indices are reordered for the communication after the interpolation from fine to coarse //! \details The indices of nodes which are part of the interpolation are moved to the front of vector with the send - //! indices. - //! \pre para->getParH(level)->intCF needs to be inititalized + //! indices. + //! \pre para->getParH(level)->intCF needs to be inititalized //! \param sendIndices is the pointer to the vector with the send indices, which will be reordered in this function - //! \param numberOfSendNodesAfterFtoC will be set in this method + //! \param numberOfSendNodesAfterFtoC will be set in this method //! \param sendIndicesForCommAfterFtoCPositions stores each sendIndex's positions before reordering void reorderSendIndicesForCommAfterFtoC(int *sendIndices, int &numberOfSendNodesAfterFtoC, int direction, int level, std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const; @@ -105,9 +108,9 @@ protected: std::vector<int> &sendIndicesAfterFtoC, std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const; //! \brief Find all indices which are not part of the communication after the interpolation from fine to coarse - void findIndicesNotInCommAfterFtoC(const uint &numberOfSendOrRecvIndices, int *sendOrReceiveIndices, - std::vector<int> &sendOrReceiveIndicesAfterFtoC, - std::vector<int> &sendOrIndicesOther) const; + static void findIndicesNotInCommAfterFtoC(const uint &numberOfSendOrRecvIndices, int *sendOrReceiveIndices, + std::vector<int> &sendOrReceiveIndicesAfterFtoC, + std::vector<int> &sendOrIndicesOther); //! \brief --> see reorderRecvIndicesForCommAfterFtoC void reorderRecvIndicesForCommAfterFtoCX(int direction, int level, int indexOfProcessNeighbor, @@ -116,15 +119,16 @@ protected: std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const; void reorderRecvIndicesForCommAfterFtoCZ(int direction, int level, int indexOfProcessNeighbor, std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const; - + //! \brief Reorder the receive indices in the same way that the send indices were reordered. //! \details When the send indices are reordered, the receive indices need to be reordered accordingly. //! \pre sendIndicesForCommAfterFtoCPositions should not be empty - //! \param recvIndices is the pointer to the vector with the receive indices, which will be reordered in this function - //! \param numberOfRecvNodesAfterFtoC will be set in this function - //! \param sendIndicesForCommAfterFtoCPositions stores each sendIndex's positions before reordering and is used to reorder the receive indices in the same way - void reorderRecvIndicesForCommAfterFtoC(int *recvIndices, int &numberOfRecvNodesAfterFtoC, int direction, - int level, std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const; + //! \param recvIndices is the pointer to the vector with the receive indices, which will be reordered in this + //! function \param numberOfRecvNodesAfterFtoC will be set in this function \param + //! sendIndicesForCommAfterFtoCPositions stores each sendIndex's positions before reordering and is used to reorder + //! the receive indices in the same way + void reorderRecvIndicesForCommAfterFtoC(int *recvIndices, int &numberOfRecvNodesAfterFtoC, int direction, int level, + std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const; private: std::shared_ptr<GridBuilder> builder; @@ -133,6 +137,7 @@ private: // used for tests friend class IndexRearrangementForStreamsTest_reorderSendIndices; + friend class IndexRearrangementForStreamsTest_reorderRecvIndicesX; friend class IndexRearrangementForStreamsTest_exchangeIndicesForCommAfterFtoCX; friend class IndexRearrangementForStreamsTest_exchangeIndicesForCommAfterFtoCY; friend class IndexRearrangementForStreamsTest_exchangeIndicesForCommAfterFtoCZ; diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp index 3fe22394823e3c33d43f8fe8709d499e57ee66f9..0d4419755b391c28f5e985a9f08d67c2ce493d3f 100644 --- a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp +++ b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp @@ -34,6 +34,7 @@ private: LevelGridBuilderDouble() = default; uint numberOfSendIndices; + uint numberOfRecvIndices; public: LevelGridBuilderDouble(SPtr<Grid> grid) : LevelGridBuilder(), grid(grid){}; @@ -49,6 +50,14 @@ public: { return numberOfSendIndices; }; + uint getNumberOfReceiveIndices(int direction, uint level) override + { + return numberOfRecvIndices; + }; + void setNumberOfRecvIndices(uint numberOfRecvIndices) + { + this->numberOfRecvIndices = numberOfRecvIndices; + }; }; class GridImpDouble : public GridImp @@ -542,3 +551,144 @@ TEST_F(IndexRearrangementForStreamsTest_exchangeIndicesForCommAfterFtoCZ, recvIn EXPECT_THAT(recvIndicesForCommAfterFtoCPositions.size(), testing::Eq(4)); EXPECT_THAT(recvIndicesForCommAfterFtoCPositions, testing::Eq(expected)); } + +////////////////////////////////////////////////////////////////////////// +// Test reorderReceiveIndices +////////////////////////////////////////////////////////////////////////// + +struct RecvIndicesForCommAfterFtoC { + // data to work on + std::vector<int> recvIndices = { 10, 11, 12, 13, 14, 15, 16 }; + std::vector<uint> sendIndicesForCommAfterFtoCPositions = {}; + const int level = 0; + const int direction = CommunicationDirections::MX; + const int numberOfProcessNeighbors = 1; + const int indexOfProcessNeighbor = 0; + + // output data + int numberOfRecvNodesAfterFtoC; + // and reordered recvIndices +}; + +class IndexRearrangementForStreamsTest_reorderRecvIndicesX : public testing::Test +{ +protected: + RecvIndicesForCommAfterFtoC ri; + SPtr<Parameter> para; + std::unique_ptr<IndexRearrangementForStreams> testSubject; + + void setUpParaInX() + { + para->setNumberOfProcessNeighborsX(ri.numberOfProcessNeighbors, ri.level, "recv"); + para->initProcessNeighborsAfterFtoCX(ri.level); + para->getParH(ri.level)->recvProcessNeighborX[ri.indexOfProcessNeighbor].index = ri.recvIndices.data(); + } + + void act() + { + testSubject->reorderRecvIndicesForCommAfterFtoC(ri.recvIndices.data(), ri.numberOfRecvNodesAfterFtoC, + ri.direction, ri.level, + ri.sendIndicesForCommAfterFtoCPositions); + }; + + void actWithX() + { + testSubject->reorderRecvIndicesForCommAfterFtoCX(ri.direction, ri.level, ri.indexOfProcessNeighbor, + ri.sendIndicesForCommAfterFtoCPositions); + }; + +private: + void SetUp() override + { + SPtr<GridImpDouble> grid = + GridImpDouble::makeShared(nullptr, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, Distribution(), 1); + std::shared_ptr<LevelGridBuilderDouble> builder = std::make_shared<LevelGridBuilderDouble>(grid); + builder->setNumberOfRecvIndices((uint)ri.recvIndices.size()); + + para = testingVF::createParameterForLevel(ri.level); + + testSubject = std::make_unique<IndexRearrangementForStreams>( + IndexRearrangementForStreams(para, builder, vf::gpu::Communicator::getInstance())); + }; +}; + +TEST_F(IndexRearrangementForStreamsTest_reorderRecvIndicesX, noSendIndicesForCommunicationAfterScalingFineToCoarse_receiveIndicesAreUnchanged) +{ + ri.sendIndicesForCommAfterFtoCPositions = {}; + auto numberOfRecvNodesAfterFtoC_expected = ri.sendIndicesForCommAfterFtoCPositions.size(); + std::vector<int> recvIndices_expected = { 10, 11, 12, 13, 14, 15, 16 }; + + act(); + EXPECT_THAT(ri.numberOfRecvNodesAfterFtoC, testing::Eq(numberOfRecvNodesAfterFtoC_expected)); + EXPECT_THAT(ri.recvIndices, testing::Eq(recvIndices_expected)); +} + +TEST_F(IndexRearrangementForStreamsTest_reorderRecvIndicesX, someSendIndicesForCommunicationAfterScalingFineToCoarse_receiveIndicesAreReorderedCorrectly) +{ + ri.sendIndicesForCommAfterFtoCPositions = { 0, 2, 4, 6 }; + auto numberOfRecvNodesAfterFtoC_expected = ri.sendIndicesForCommAfterFtoCPositions.size(); + std::vector<int> recvIndices_expected = { 10, 12, 14, 16, 11, 13, 15 }; + + act(); + EXPECT_THAT(ri.numberOfRecvNodesAfterFtoC, testing::Eq(numberOfRecvNodesAfterFtoC_expected)); + EXPECT_THAT(ri.recvIndices, testing::Eq(recvIndices_expected)); +} + +TEST_F(IndexRearrangementForStreamsTest_reorderRecvIndicesX, allIndicesAreSendIndicesForCommunicationAfterScalingFineToCoarse_receiveIndicesAreReorderedCorrectly) +{ + ri.sendIndicesForCommAfterFtoCPositions = { 0, 1, 2, 3, 4, 5, 6 }; + auto numberOfRecvNodesAfterFtoC_expected = ri.sendIndicesForCommAfterFtoCPositions.size(); + std::vector<int> recvIndices_expected = { 10, 11, 12, 13, 14, 15, 16 }; + + act(); + EXPECT_THAT(ri.numberOfRecvNodesAfterFtoC, testing::Eq(numberOfRecvNodesAfterFtoC_expected)); + EXPECT_THAT(ri.recvIndices, testing::Eq(recvIndices_expected)); +} + +TEST_F(IndexRearrangementForStreamsTest_reorderRecvIndicesX, noSendIndicesForCommunicationAfterScalingFineToCoarseInX_receiveIndicesAreUnchanged) +{ + setUpParaInX(); + + ri.sendIndicesForCommAfterFtoCPositions = {}; + auto numberOfRecvNodesAfterFtoC_expected = ri.sendIndicesForCommAfterFtoCPositions.size(); + std::vector<int> recvIndices_expected = { 10, 11, 12, 13, 14, 15, 16 }; + + this->actWithX(); + + EXPECT_THAT(para->getParH(ri.level)->recvProcessNeighborsAfterFtoCX[ri.indexOfProcessNeighbor].numberOfNodes, + testing::Eq(numberOfRecvNodesAfterFtoC_expected)); + EXPECT_TRUE(vectorsAreEqual(para->getParH(ri.level)->recvProcessNeighborX[ri.indexOfProcessNeighbor].index, + recvIndices_expected)); +} + +TEST_F(IndexRearrangementForStreamsTest_reorderRecvIndicesX, someSendIndicesForCommunicationAfterScalingFineToCoarseInX_receiveIndicesAreReorderedCorrectly) +{ + setUpParaInX(); + + ri.sendIndicesForCommAfterFtoCPositions = { 0, 2, 4, 6 }; + auto numberOfRecvNodesAfterFtoC_expected = ri.sendIndicesForCommAfterFtoCPositions.size(); + std::vector<int> recvIndices_expected = { 10, 12, 14, 16, 11, 13, 15 }; + + actWithX(); + + EXPECT_THAT(para->getParH(ri.level)->recvProcessNeighborsAfterFtoCX[ri.indexOfProcessNeighbor].numberOfNodes, + testing::Eq(numberOfRecvNodesAfterFtoC_expected)); + EXPECT_TRUE(vectorsAreEqual(para->getParH(ri.level)->recvProcessNeighborX[ri.indexOfProcessNeighbor].index, + recvIndices_expected)); +} + +TEST_F(IndexRearrangementForStreamsTest_reorderRecvIndicesX, allIndicesAreSendIndicesForCommunicationAfterScalingFineToCoarseInX_receiveIndicesAreReorderedCorrectly) +{ + setUpParaInX(); + + ri.sendIndicesForCommAfterFtoCPositions = { 0, 1, 2, 3, 4, 5, 6 }; + auto numberOfRecvNodesAfterFtoC_expected = ri.sendIndicesForCommAfterFtoCPositions.size(); + std::vector<int> recvIndices_expected = { 10, 11, 12, 13, 14, 15, 16 }; + + actWithX(); + + EXPECT_THAT(para->getParH(ri.level)->recvProcessNeighborsAfterFtoCX[ri.indexOfProcessNeighbor].numberOfNodes, + testing::Eq(numberOfRecvNodesAfterFtoC_expected)); + EXPECT_TRUE(vectorsAreEqual(para->getParH(ri.level)->recvProcessNeighborX[ri.indexOfProcessNeighbor].index, + recvIndices_expected)); +}