diff --git a/tests/pe/CMakeLists.txt b/tests/pe/CMakeLists.txt index bde1a805f1ed64cb52993eba626109dee85ce94a..5d5273829ffd6329e71f4f712a94fc50fd1cb8ba 100644 --- a/tests/pe/CMakeLists.txt +++ b/tests/pe/CMakeLists.txt @@ -16,6 +16,9 @@ waLBerla_execute_test( NAME PE_BODYITERATORS PROCESSES 2 ) waLBerla_compile_test( NAME PE_BODYSTORAGE FILES BodyStorage.cpp DEPENDS core ) waLBerla_execute_test( NAME PE_BODYSTORAGE ) +waLBerla_compile_test( NAME PE_CALLBACK FILES Callback.cpp DEPENDS blockforest core domain_decomposition ) +waLBerla_execute_test( NAME PE_CALLBACK PROCESSES 2 ) + waLBerla_compile_test( NAME PE_CHECKVITALPARAMETERS FILES CheckVitalParameters.cpp DEPENDS core ) waLBerla_execute_test( NAME PE_CHECKVITALPARAMETERS ) diff --git a/tests/pe/Callback.cpp b/tests/pe/Callback.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7aa026672ddf177fb130e061a71d2e80ce5d3015 --- /dev/null +++ b/tests/pe/Callback.cpp @@ -0,0 +1,176 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Callback.cpp +//! \brief checks callbacks of BodyStorage +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include "pe/basic.h" +#include <pe/utility/DestroyBody.h> + +#include "blockforest/all.h" +#include "core/all.h" +#include "domain_decomposition/all.h" + +#include "core/debug/TestSubsystem.h" + +namespace walberla { +using namespace walberla::pe; + +typedef boost::tuple<Sphere> BodyTypeTuple ; + +enum class State{ LOCALIZED0, SHADOW, MIGRATED, LOCALIZED1, REMOVED}; +State state; + +void addCallbackLocal(BodyID bd) +{ + bool shouldBeCalled = ((state == State::LOCALIZED0) && (mpi::MPIManager::instance()->worldRank() == 0)) || + ((state == State::MIGRATED) && (mpi::MPIManager::instance()->worldRank() == 1)); + WALBERLA_CHECK(shouldBeCalled); + WALBERLA_LOG_DEVEL("Add local body: " << bd->getSystemID() ); +} +void removeCallbackLocal(BodyID bd) +{ + bool shouldBeCalled = ((state == State::MIGRATED) && (mpi::MPIManager::instance()->worldRank() == 0)) || + ((state == State::REMOVED) && (mpi::MPIManager::instance()->worldRank() == 1)); + WALBERLA_CHECK(shouldBeCalled); + WALBERLA_LOG_DEVEL("Remove local body: " << bd->getSystemID() ); +} + +void addCallbackShadow(BodyID bd) +{ + bool shouldBeCalled = ((state == State::SHADOW) && (mpi::MPIManager::instance()->worldRank() == 1)) || + ((state == State::MIGRATED) && (mpi::MPIManager::instance()->worldRank() == 0)); + WALBERLA_CHECK(shouldBeCalled); + WALBERLA_LOG_DEVEL("Add shadow body: " << bd->getSystemID() ); +} +void removeCallbackShadow(BodyID bd) +{ + bool shouldBeCalled = ((state == State::MIGRATED) && (mpi::MPIManager::instance()->worldRank() == 1)) || + ((state == State::LOCALIZED1) && (mpi::MPIManager::instance()->worldRank() == 0)); + WALBERLA_CHECK(shouldBeCalled); + WALBERLA_LOG_DEVEL("Remove shadow body: " << bd->getSystemID() ); +} + +int main( int argc, char** argv ) +{ + walberla::debug::enterTestMode(); + walberla::MPIManager::instance()->initializeMPI( &argc, &argv ); + + shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); + + // create blocks + shared_ptr< BlockForest > forest = createBlockForest( AABB(0,0,0,20,20,20), // simulation domain + Vector3<uint_t>(2,1,1), // blocks in each direction + Vector3<bool>(false, false, false) // periodicity + ); + + SetBodyTypeIDs<BodyTypeTuple>::execute(); + + auto storageID = forest->addBlockData(createStorageDataHandling<BodyTypeTuple>(), "Storage"); + + for (auto& currentBlock : *forest) + { + Storage * storage = currentBlock.getData< Storage >( storageID ); + BodyStorage& localStorage = (*storage)[0]; + BodyStorage& shadowStorage = (*storage)[1]; + + localStorage.registerAddCallback( "Test", addCallbackLocal ); + localStorage.registerRemoveCallback( "Test", removeCallbackLocal ); + + shadowStorage.registerAddCallback( "Test", addCallbackShadow ); + shadowStorage.registerRemoveCallback( "Test", removeCallbackShadow ); + } + + state = State::LOCALIZED0; + BodyID sp = pe::createSphere( + *globalBodyStorage, + *forest, + storageID, + 99, + Vec3(8,5,5), + real_c(1.0)); + if (sp != nullptr) + { + WALBERLA_CHECK_EQUAL( sp->getSystemID(), 1 ); + } + syncNextNeighbors<BodyTypeTuple>(*forest, storageID); + WALBERLA_MPI_BARRIER(); + WALBERLA_LOG_DEVEL_ON_ROOT("=== localized on block 1 ==="); + WALBERLA_MPI_BARRIER(); + + state = State::SHADOW; + sp = getBody(*globalBodyStorage, *forest, storageID, 1); + if (sp != nullptr) + { + sp->setPosition( Vec3(real_t(9.5), 5, 5) ); + } + syncNextNeighbors<BodyTypeTuple>(*forest, storageID); + WALBERLA_MPI_BARRIER(); + WALBERLA_LOG_DEVEL_ON_ROOT("=== shadow on block 2 ==="); + WALBERLA_MPI_BARRIER(); + + state = State::MIGRATED; + sp = getBody(*globalBodyStorage, *forest, storageID, 1); + if (sp != nullptr) + { + sp->setPosition( Vec3(real_t(10.5), 5, 5) ); + } + syncNextNeighbors<BodyTypeTuple>(*forest, storageID); + WALBERLA_MPI_BARRIER(); + WALBERLA_LOG_DEVEL_ON_ROOT("=== migrated to block 2 ==="); + WALBERLA_MPI_BARRIER(); + + state = State::LOCALIZED1; + sp = getBody(*globalBodyStorage, *forest, storageID, 1); + if (sp != nullptr) + { + sp->setPosition( Vec3(real_t(11.5), 5, 5) ); + } + syncNextNeighbors<BodyTypeTuple>(*forest, storageID); + WALBERLA_MPI_BARRIER(); + WALBERLA_LOG_DEVEL_ON_ROOT("=== localized on block 2 ==="); + WALBERLA_MPI_BARRIER(); + + state = State::REMOVED; + destroyBodyBySID(*globalBodyStorage, *forest, storageID, 1); + syncNextNeighbors<BodyTypeTuple>(*forest, storageID); + WALBERLA_MPI_BARRIER(); + WALBERLA_LOG_DEVEL_ON_ROOT("=== removed ==="); + WALBERLA_MPI_BARRIER(); + + for (auto& currentBlock : *forest) + { + Storage * storage = currentBlock.getData< Storage >( storageID ); + BodyStorage& localStorage = (*storage)[0]; + BodyStorage& shadowStorage = (*storage)[1]; + + localStorage.clearAddCallbacks(); + localStorage.clearRemoveCallbacks(); + + shadowStorage.clearAddCallbacks(); + shadowStorage.clearRemoveCallbacks(); + } + + return EXIT_SUCCESS; +} +} // namespace walberla + +int main( int argc, char* argv[] ) +{ + return walberla::main( argc, argv ); +}