diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.cpp b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.cpp index 4cd8769407220ec97030489585009d435a6cce8e..3dc3893f5df441b143aa86d19f3446e7e4adca43 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 e6753e21be43a4f004d812cca8b9adafa501ffe8..af8583ce195299925eb0684e30c3382aba1f7e8e 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,20 +85,21 @@ 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; + void reorderSendIndicesForCommAfterFtoC(int *sendIndices, int &numberOfSendNodesAfterFtoC, int direction, int level, + std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const; //! \brief Check if a sparse index occurs in the ICellFCC bool isSparseIndexInICellFCC(uint sizeOfICellFCC, int sparseIndexSend, int level) const; //! \brief Aggregate all nodes in the coarse cells for the interpolation in coarse to fine //! \details For the coarse cells in the interpolation from coarse to fine only one node is stored. This methods //! looks for the other nodes of each cell and puts them into vector. Duplicate nodes are only stored once. void aggregateNodesInICellCFC(int level, std::vector<uint> &nodesCFC) const; - //! \brief Add index to sendIndicesAfterFtoC and sendIndicesForCommAfterFtoCPositions, but omit indices which are already in sendIndicesAfterFtoC + //! \brief Add index to sendIndicesAfterFtoC and sendIndicesForCommAfterFtoCPositions, but omit indices which are + //! already in sendIndicesAfterFtoC void addUniqueIndexToCommunicationVectors(std::vector<int> &sendIndicesAfterFtoC, int &sparseIndexSend, std::vector<unsigned int> &sendIndicesForCommAfterFtoCPositions, uint &posInSendIndices) const; @@ -105,9 +109,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 +120,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; diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp index 7bf534013ab68ba6a58fb3f33ca4ae03610cc12d..04221280d8a9f723db241ba2686cc88711ca9a16 100644 --- a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp +++ b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp @@ -2,8 +2,10 @@ #include <algorithm> #include <iostream> +#include <sys/types.h> #include <vector> +#include "Logger/Logger.h" #include "Utilities/testUtilitiesGPU.h" #include "Communication/Communicator.h" @@ -34,6 +36,7 @@ private: LevelGridBuilderDouble() = default; uint numberOfSendIndices; + uint numberOfRecvIndices; public: LevelGridBuilderDouble(SPtr<Grid> grid) : LevelGridBuilder(), grid(grid){}; @@ -49,6 +52,14 @@ public: { return numberOfSendIndices; }; + uint getNumberOfReceiveIndices(int direction, uint level) override + { + return numberOfRecvIndices; + }; + void setNumberOfRecvIndices(uint numberOfRecvIndices) + { + this->numberOfRecvIndices = numberOfRecvIndices; + }; }; class GridImpDouble : public GridImp @@ -550,3 +561,147 @@ 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 + { + logging::Logger::addStream(&std::cout); + logging::Logger::setDebugLevel(logging::Logger::WARNING); + + 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, noRecvIndices) +{ + 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, someRecvIndices) +{ + 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, allRecvIndices) +{ + 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, noRecvIndices_callWithX) +{ + 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, someRecvIndices_callWithX) +{ + 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, allRecvIndices_callWithX) +{ + 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)); +}