diff --git a/src/gpu/VirtualFluids_GPU/CMakeLists.txt b/src/gpu/VirtualFluids_GPU/CMakeLists.txt index ed647cb406bca23ef90667b7d17171c7b3f46283..ffab484b28870fcc278e6aabbb4db618d30d0e99 100644 --- a/src/gpu/VirtualFluids_GPU/CMakeLists.txt +++ b/src/gpu/VirtualFluids_GPU/CMakeLists.txt @@ -24,5 +24,7 @@ if(BUILD_VF_UNIT_TESTS) set_source_files_properties(DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp PROPERTIES LANGUAGE CUDA) set_source_files_properties(Communication/ExchangeData27Test.cpp PROPERTIES LANGUAGE CUDA) set_source_files_properties(BoundaryConditions/BoundaryConditionFactoryTest.cpp PROPERTIES LANGUAGE CUDA) + set_source_files_properties(Parameter/ParameterTest.cpp PROPERTIES LANGUAGE CUDA) target_include_directories(VirtualFluids_GPUTests PRIVATE "${VF_THIRD_DIR}/cuda_samples/") + target_include_directories(VirtualFluids_GPUTests PRIVATE "${VF_ROOT_DIR}/src/gpu/GridGenerator/") endif() 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)); +} diff --git a/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactory.h b/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactory.h index c6877cbfeffe5b32c0c2d336e46b02d68cd946a3..09f1a44166829f73c79cd839a7ecf75deae0e67e 100644 --- a/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactory.h +++ b/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactory.h @@ -161,15 +161,14 @@ public: // void setOutflowBoundaryCondition(...); // TODO: // https://git.rz.tu-bs.de/m.schoenherr/VirtualFluids_dev/-/issues/16 - [[nodiscard]] boundaryCondition getVelocityBoundaryConditionPost(bool isGeometryBC = false) const; + [[nodiscard]] virtual boundaryCondition getVelocityBoundaryConditionPost(bool isGeometryBC = false) const; [[nodiscard]] boundaryCondition getNoSlipBoundaryConditionPost(bool isGeometryBC = false) const; [[nodiscard]] boundaryCondition getSlipBoundaryConditionPost(bool isGeometryBC = false) const; [[nodiscard]] boundaryCondition getPressureBoundaryConditionPre() const; [[nodiscard]] boundaryCondition getGeometryBoundaryConditionPost() const; - [[nodiscard]] precursorBoundaryConditionFunc getPrecursorBoundaryConditionPost() const; - [[nodiscard]] boundaryConditionWithParameter getStressBoundaryConditionPost() const; + [[nodiscard]] precursorBoundaryConditionFunc getPrecursorBoundaryConditionPost() const; private: VelocityBC velocityBoundaryCondition = VelocityBC::NotSpecified; diff --git a/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactoryTest.cpp b/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactoryTest.cpp index 14d01d6df3334d767d97e8db87b7e2a9964022e3..a01b6af7abfebcdf488a66fc0c0ba1c9d3c81987 100644 --- a/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactoryTest.cpp +++ b/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactoryTest.cpp @@ -55,6 +55,8 @@ TEST(BoundaryConditionFactoryTest, defaultStressBC) EXPECT_THROW(bc(nullptr, nullptr, 0), std::bad_function_call); } +// tests for boundary conditions which are set by the user (tests both set and get functions) + bcFunction getVelocityBcTarget(BoundaryConditionFactory &bcFactory) { auto bc = bcFactory.getVelocityBoundaryConditionPost(); @@ -63,8 +65,6 @@ bcFunction getVelocityBcTarget(BoundaryConditionFactory &bcFactory) return bcTarget; } -// tests for boundary conditions whcih are set by the user (tests both set and get functions) - TEST(BoundaryConditionFactoryTest, velocityBC) { auto bcFactory = BoundaryConditionFactory(); diff --git a/src/gpu/VirtualFluids_GPU/KernelManager/BCKernelManagerTest.cpp b/src/gpu/VirtualFluids_GPU/KernelManager/BCKernelManagerTest.cpp index a0e02112e821eedcfeb013d3465529f668309529..6b429d2d9c03e546286d3d2b0ced3612c0a4649a 100644 --- a/src/gpu/VirtualFluids_GPU/KernelManager/BCKernelManagerTest.cpp +++ b/src/gpu/VirtualFluids_GPU/KernelManager/BCKernelManagerTest.cpp @@ -1,3 +1,4 @@ + #include <gmock/gmock.h> #include <stdexcept> @@ -18,44 +19,123 @@ protected: } }; -TEST_F(BCKernelManagerTest_BCsNotSpecified, velocityBoundaryConditionPost_NotSpecified) +TEST_F(BCKernelManagerTest_BCsNotSpecified, velocityBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow) +{ + para->getParD(0)->velocityBC.numberOfBCnodes = 0; + EXPECT_NO_THROW(BCKernelManager(para, &bcFactory)); +} + +TEST_F(BCKernelManagerTest_BCsNotSpecified, velocityBoundaryConditionPostNotSpecified_withBoundaryNodes_throws) { para->getParD(0)->velocityBC.numberOfBCnodes = 1; EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error); } -TEST_F(BCKernelManagerTest_BCsNotSpecified, noSlipBoundaryConditionPost_NotSpecified) +TEST_F(BCKernelManagerTest_BCsNotSpecified, noSlipBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow) +{ + para->getParD(0)->noSlipBC.numberOfBCnodes = 0; + EXPECT_NO_THROW(BCKernelManager(para, &bcFactory)); +} + +TEST_F(BCKernelManagerTest_BCsNotSpecified, noSlipBoundaryConditionPostNotSpecified_withBoundaryNodes_doesNotThrow) { para->getParD(0)->noSlipBC.numberOfBCnodes = 1; EXPECT_NO_THROW(BCKernelManager(para, &bcFactory)); // no throw, as a default is specified } -TEST_F(BCKernelManagerTest_BCsNotSpecified, slipBoundaryConditionPost_NotSpecified) +TEST_F(BCKernelManagerTest_BCsNotSpecified, slipBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow) +{ + para->getParD(0)->slipBC.numberOfBCnodes = 0; + EXPECT_NO_THROW(BCKernelManager(para, &bcFactory)); +} + +TEST_F(BCKernelManagerTest_BCsNotSpecified, slipBoundaryConditionPostNotSpecified_withBoundaryNodes_throws) { para->getParD(0)->slipBC.numberOfBCnodes = 1; EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error); } -TEST_F(BCKernelManagerTest_BCsNotSpecified, pressureBoundaryConditionPre_NotSpecified) +TEST_F(BCKernelManagerTest_BCsNotSpecified, pressureBoundaryConditionPreNotSpecified_noBoundaryNodes_doesNotThrow) +{ + para->getParD(0)->pressureBC.numberOfBCnodes = 0; + EXPECT_NO_THROW(BCKernelManager(para, &bcFactory)); +} + +TEST_F(BCKernelManagerTest_BCsNotSpecified, pressureBoundaryConditionPreNotSpecified_withBoundaryNodes_throws) { para->getParD(0)->pressureBC.numberOfBCnodes = 1; EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error); } -TEST_F(BCKernelManagerTest_BCsNotSpecified, geometryBoundaryConditionPost_NotSpecified) +TEST_F(BCKernelManagerTest_BCsNotSpecified, geometryBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow) +{ + para->getParD(0)->geometryBC.numberOfBCnodes = 0; + EXPECT_NO_THROW(BCKernelManager(para, &bcFactory)); +} + +TEST_F(BCKernelManagerTest_BCsNotSpecified, geometryBoundaryConditionPostNotSpecified_withBoundaryNodes_doesNotThrow) { para->getParD(0)->geometryBC.numberOfBCnodes = 1; EXPECT_NO_THROW(BCKernelManager(para, &bcFactory)); // no throw, as a default is specified } -TEST_F(BCKernelManagerTest_BCsNotSpecified, stressBoundaryConditionPost_NotSpecified) +TEST_F(BCKernelManagerTest_BCsNotSpecified, stressBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow) +{ + para->getParD(0)->stressBC.numberOfBCnodes = 0; + EXPECT_NO_THROW(BCKernelManager(para, &bcFactory)); +} + +TEST_F(BCKernelManagerTest_BCsNotSpecified, stressBoundaryConditionPostNotSpecified_withBoundaryNodes_throws) { para->getParD(0)->stressBC.numberOfBCnodes = 1; EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error); } -TEST_F(BCKernelManagerTest_BCsNotSpecified, precursorBoundaryConditionPost_NotSpecified) +TEST_F(BCKernelManagerTest_BCsNotSpecified, precursorBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow) +{ + para->getParD(0)->precursorBC.numberOfBCnodes = 0; + EXPECT_NO_THROW(BCKernelManager(para, &bcFactory)); +} + +TEST_F(BCKernelManagerTest_BCsNotSpecified, precursorBoundaryConditionPostNotSpecified_withBoundaryNodes_throws) { para->getParD(0)->precursorBC.numberOfBCnodes = 1; EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error); } + +class BoundaryConditionFactoryMock : public BoundaryConditionFactory +{ +public: + mutable uint numberOfCalls = 0; + + [[nodiscard]] boundaryCondition getVelocityBoundaryConditionPost(bool) const override + { + return [this](LBMSimulationParameter *, QforBoundaryConditions *) { numberOfCalls++; }; + } +}; + +class BCKernelManagerTest_runBCs : public testing::Test +{ +protected: + BoundaryConditionFactoryMock bcFactory; + SPtr<Parameter> para = std::make_shared<Parameter>(); + UPtr<BCKernelManager> sut; + + void SetUp() override + { + para->initLBMSimulationParameter(); + sut = std::make_unique<BCKernelManager>(para, &bcFactory); + } +}; + +TEST_F(BCKernelManagerTest_runBCs, runVelocityBCKernelPost) +{ + para->getParD(0)->velocityBC.numberOfBCnodes = 1; + sut->runVelocityBCKernelPost(0); + EXPECT_THAT(bcFactory.numberOfCalls, testing::Eq(1)); + + bcFactory.numberOfCalls = 0; + para->getParD(0)->velocityBC.numberOfBCnodes = 0; + sut->runVelocityBCKernelPost(0); + EXPECT_THAT(bcFactory.numberOfCalls, testing::Eq(0)); +} diff --git a/src/gpu/VirtualFluids_GPU/KernelManager/GridScalingKernelManagerTest.cpp b/src/gpu/VirtualFluids_GPU/KernelManager/GridScalingKernelManagerTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b86e167ca8d2f95897b1a87d4b850acbfbe8a1b3 --- /dev/null +++ b/src/gpu/VirtualFluids_GPU/KernelManager/GridScalingKernelManagerTest.cpp @@ -0,0 +1,81 @@ +#include <gmock/gmock.h> +#include <stdexcept> + +#include "GridScalingKernelManager.h" +#include "Factories/GridScalingFactory.h" +#include "Parameter/Parameter.h" +#include "PointerDefinitions.h" + +class GridScalingKernelManagerTest_Initialization : public testing::Test +{ +protected: + GridScalingFactory scalingFactory; + SPtr<Parameter> para = std::make_shared<Parameter>(); + + void SetUp() override + { + para->setGridX({2, 8}); + para->setGridY({2, 8}); + para->setGridZ({2, 8}); + para->setDistX({0, 0}); + para->setDistY({0, 0}); + para->setDistZ({0, 0}); + } +}; + +TEST_F(GridScalingKernelManagerTest_Initialization, singleLevel_noScalingFactoryProvided_doesNotThrow) +{ + // only one level --> no scaling factory needed --> no error + para->initLBMSimulationParameter(); + EXPECT_NO_THROW(GridScalingKernelManager(para, nullptr)); +} + +TEST_F(GridScalingKernelManagerTest_Initialization, singleLevel_scalingFactoryProvided_doesNotThrow) +{ + // only one level --> no scaling function needed --> no error + para->initLBMSimulationParameter(); + EXPECT_NO_THROW(GridScalingKernelManager(para, &scalingFactory)); +} + +TEST_F(GridScalingKernelManagerTest_Initialization, singleLevel_scalingFactoryAndFunctionProvided_doesNotThrow) +{ + // only one level, but the user provided a scaling function anyway --> no error + para->initLBMSimulationParameter(); + scalingFactory.setScalingFactory(GridScalingFactory::GridScaling::ScaleCompressible); + EXPECT_NO_THROW(GridScalingKernelManager(para, &scalingFactory)); +} + +TEST_F(GridScalingKernelManagerTest_Initialization, multipleLevels_notScalingFactoryProvided_throws) +{ + // multiple levels, but the user forgot the scaling factory --> error + para->setMaxLevel(2); + para->initLBMSimulationParameter(); + EXPECT_THROW(GridScalingKernelManager(para, nullptr), std::runtime_error); +} + +TEST_F(GridScalingKernelManagerTest_Initialization, multipleLevelWithoutInterpolationNodes_noScalingFunctionProvided_doesNotThrow) +{ + // multiple levels, but no interpolation nodes specified --> no scaling function needed --> no error + para->setMaxLevel(2); + para->initLBMSimulationParameter(); + EXPECT_NO_THROW(GridScalingKernelManager(para, &scalingFactory)); +} + +TEST_F(GridScalingKernelManagerTest_Initialization, multipleLevelWithoutInterpolationNodes_scalingFunctionProvided_doesNotThrow) +{ + // multiple levels and NO interpolation nodes specified, but the user provided a scaling function anyway --> no error + para->setMaxLevel(2); + para->initLBMSimulationParameter(); + scalingFactory.setScalingFactory(GridScalingFactory::GridScaling::ScaleRhoSq); + EXPECT_NO_THROW(GridScalingKernelManager(para, &scalingFactory)); +} + +TEST_F(GridScalingKernelManagerTest_Initialization, multipleLevelWithInterpolationNodes_noScalingFunctionProvided_throws) +{ + // multiple levels and interpolation nodes specified, but the user forgot to set the scalingFunction --> error + para->setMaxLevel(2); + para->initLBMSimulationParameter(); + para->getParD(0)->fineToCoarse.numberOfCells = 100; + EXPECT_THROW(GridScalingKernelManager(para, &scalingFactory), std::runtime_error); +} + diff --git a/src/gpu/VirtualFluids_GPU/Parameter/ParameterTest.cpp b/src/gpu/VirtualFluids_GPU/Parameter/ParameterTest.cpp index b86d5657922deb9dca6e89574efc72766bcd16ce..bdd22ab27669363ef7b52ac1b16854e5fa25a3c8 100644 --- a/src/gpu/VirtualFluids_GPU/Parameter/ParameterTest.cpp +++ b/src/gpu/VirtualFluids_GPU/Parameter/ParameterTest.cpp @@ -4,9 +4,18 @@ #include <iostream> #include <string> +#include "LBM/Simulation.h" #include "Parameter.h" +#include "PointerDefinitions.h" #include "basics/config/ConfigurationFile.h" +#include "Factories/BoundaryConditionFactory.h" +#include "Factories/GridScalingFactory.h" +#include "Communication/Communicator.h" +#include "DataStructureInitializer/GridReaderGenerator/GridGenerator.h" +#include "GPU/CudaMemoryManager.h" +#include "gpu/GridGenerator/grid/GridBuilder/MultipleGridBuilder.h" + TEST(ParameterTest, passingEmptyFileWithoutPath_ShouldNotThrow) { // assuming that the config files is stored parallel to this file. @@ -198,6 +207,72 @@ TEST(ParameterTest, userMissedSlashMultiGPU) EXPECT_THAT(para.getConcentration(), testing::Eq("gridPathTest/0/conc.dat")); } +class MockGridGenerator : public GridGenerator +{ + +public: + MockGridGenerator(std::shared_ptr<GridBuilder> builder, std::shared_ptr<Parameter> para, + std::shared_ptr<CudaMemoryManager> cudaMemoryManager, vf::gpu::Communicator &communicator) + : GridGenerator(builder, para, cudaMemoryManager, communicator) + { + } + + void initalGridInformations() override + { + para->setGridX({ 2, 8 }); + para->setGridY({ 2, 8 }); + para->setGridZ({ 2, 8 }); + para->setDistX({ 0, 0 }); + para->setDistY({ 0, 0 }); + para->setDistZ({ 0, 0 }); + } + void allocArrays_CoordNeighborGeo() override{}; + void setBoundingBox() override{}; + void allocArrays_OffsetScale() override{}; + void allocArrays_BoundaryValues() override{}; + void allocArrays_BoundaryQs() override{}; +}; + +TEST(ParameterTest, whenCreatingParameterClassWithGridRefinement_afterCallingInitLBMSimulationParameter_shouldNotThrow) +{ + auto para = std::make_shared<Parameter>(); + para->setMaxLevel(2); + + para->setGridX({ 2, 8 }); + para->setGridY({ 2, 8 }); + para->setGridZ({ 2, 8 }); + para->setDistX({ 0, 0 }); + para->setDistY({ 0, 0 }); + para->setDistZ({ 0, 0 }); + + EXPECT_THAT(para->getParH(1), testing::Eq(nullptr)); // Parameter initialization incomplete + para->initLBMSimulationParameter(); + EXPECT_THAT(para->getParH(1), testing::Ne(nullptr)); +} + +TEST(ParameterTest, whenCreatingParameterClassWithGridRefinement_afterCallingSimulationConstructor_shouldNotThrow) +{ + spdlog::set_level(spdlog::level::warn); // avoids logger spam in output + + auto para = std::make_shared<Parameter>(); + para->setMaxLevel(2); + + SPtr<CudaMemoryManager> cudaMemoryManager = std::make_shared<CudaMemoryManager>(para); + vf::gpu::Communicator &communicator = vf::gpu::Communicator::getInstance(); + auto gridFactory = GridFactory::make(); + auto gridBuilder = MultipleGridBuilder::makeShared(gridFactory); + SPtr<GridProvider> gridGenerator = + std::make_shared<MockGridGenerator>(gridBuilder, para, cudaMemoryManager, communicator); + BoundaryConditionFactory bcFactory = BoundaryConditionFactory(); + GridScalingFactory scalingFactory = GridScalingFactory(); + + EXPECT_THAT(para->getParH(1), testing::Eq(nullptr)); // Parameter initialization incomplete + // Simulation() calls para->initLBMSimulationParameter() --> that function completes the initialization of Parameter + Simulation sim(para, cudaMemoryManager, communicator, *gridGenerator, &bcFactory, &scalingFactory); + EXPECT_THAT(para->getParH(1), testing::Ne(nullptr)); + EXPECT_NO_THROW(cudaMemoryManager->cudaAllocLevelForcing(1)); // throws if para->getParH(1) is a null pointer +} + class ParameterTestCumulantK17 : public testing::Test { protected: