diff --git a/src/pe/rigidbody/StorageDataHandling.h b/src/pe/rigidbody/StorageDataHandling.h index 9c8419567e9b902a031ccdea1866f95542fe24f3..6e3b0d2dafad64473a5b63f325e00bdccd49eb38 100644 --- a/src/pe/rigidbody/StorageDataHandling.h +++ b/src/pe/rigidbody/StorageDataHandling.h @@ -37,20 +37,47 @@ namespace pe{ template<typename BodyTuple> -class StorageDataHandling : public domain_decomposition::BlockDataHandling<Storage>{ +class StorageDataHandling : public blockforest::BlockDataHandling<Storage>{ public: - Storage * initialize( IBlock * const /*block*/ ) {return new Storage();} + virtual ~StorageDataHandling() {} /// must be thread-safe ! - virtual inline void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ); + virtual Storage * initialize( IBlock * const block ) WALBERLA_OVERRIDE; + + /// must be thread-safe ! + virtual void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) WALBERLA_OVERRIDE; + /// must be thread-safe ! + virtual Storage * deserialize( IBlock * const block ) WALBERLA_OVERRIDE; + /// must be thread-safe ! + virtual void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) WALBERLA_OVERRIDE; + + /// must be thread-safe ! + virtual void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ) WALBERLA_OVERRIDE; + /// must be thread-safe ! + virtual void serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) WALBERLA_OVERRIDE; + + /// must be thread-safe ! + virtual Storage * deserializeCoarseToFine( Block * const block ) WALBERLA_OVERRIDE; + /// must be thread-safe ! + virtual Storage * deserializeFineToCoarse( Block * const block ) WALBERLA_OVERRIDE; + /// must be thread-safe ! - virtual inline Storage * deserialize( IBlock * const block ); + virtual void deserializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) WALBERLA_OVERRIDE; /// must be thread-safe ! - virtual inline void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ); + virtual void deserializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer, const uint_t child ) WALBERLA_OVERRIDE; + +private: + void deserializeImpl( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ); }; template<typename BodyTuple> -inline void StorageDataHandling<BodyTuple>::serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) +Storage * StorageDataHandling<BodyTuple>::initialize( IBlock * const /*block*/ ) +{ + return new Storage(); +} + +template<typename BodyTuple> +void StorageDataHandling<BodyTuple>::serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) { using namespace walberla::pe::communication; BodyStorage& localBodyStorage = (*(block->getData< Storage >( id )))[0]; @@ -67,18 +94,119 @@ inline void StorageDataHandling<BodyTuple>::serialize( IBlock * const block, con } template<typename BodyTuple> -inline Storage * StorageDataHandling<BodyTuple>::deserialize( IBlock * const block ) +Storage * StorageDataHandling<BodyTuple>::deserialize( IBlock * const block ) { return initialize(block); } template<typename BodyTuple> -inline void StorageDataHandling<BodyTuple>::deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) +void StorageDataHandling<BodyTuple>::deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) +{ + WALBERLA_DEBUG_SECTION() + { + BodyStorage& localBodyStorage = (*(block->getData< Storage >( id )))[0]; + WALBERLA_CHECK_EQUAL( localBodyStorage.size(), 0); + } + deserializeImpl( block, id, buffer); +} + +template<typename BodyTuple> +void StorageDataHandling<BodyTuple>::serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ) +{ + // get child aabb + const math::AABB aabb = block->getAABB(); + const real_t xMid = (aabb.xMax() + aabb.xMin()) * real_t(0.5); + const real_t yMid = (aabb.yMax() + aabb.yMin()) * real_t(0.5); + const real_t zMid = (aabb.zMax() + aabb.zMin()) * real_t(0.5); + + const real_t xMin = (child & uint_t(1)) ? xMid : aabb.xMin(); + const real_t xMax = (child & uint_t(1)) ? aabb.xMax() : xMid; + + const real_t yMin = (child & uint_t(2)) ? yMid : aabb.yMin(); + const real_t yMax = (child & uint_t(2)) ? aabb.yMax() : yMid; + + const real_t zMin = (child & uint_t(4)) ? zMid : aabb.zMin(); + const real_t zMax = (child & uint_t(4)) ? aabb.zMax() : zMid; + + const math::AABB childAABB(xMin, yMin, zMin, xMax, yMax, zMax); + //WALBERLA_LOG_DEVEL( (child & uint_t(1)) << (child & uint_t(2)) << (child & uint_t(4)) << "\naabb: " << aabb << "\nchild: " << childAABB ); + + using namespace walberla::pe::communication; + + BodyStorage& localBodyStorage = (*(block->getData< Storage >( id )))[0]; + + decltype(localBodyStorage.size()) numOfParticles = 0; + + auto ptr = buffer.allocate<decltype(localBodyStorage.size())>(); + for (auto bodyIt = localBodyStorage.begin(); bodyIt != localBodyStorage.end(); ++bodyIt) + { + if ( !block->getAABB().contains( bodyIt->getPosition()) ) + { + WALBERLA_ABORT( "Body to be stored not contained within block!" ); + } + if( childAABB.contains( bodyIt->getPosition()) ) + { + marshal( buffer, RigidBodyCopyNotification( **bodyIt ) ); + MarshalDynamically<BodyTuple>::execute( buffer, **bodyIt ); + ++numOfParticles; + } + } + *ptr = numOfParticles; +} + +template<typename BodyTuple> +void StorageDataHandling<BodyTuple>::serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) +{ + using namespace walberla::pe::communication; + BodyStorage& localBodyStorage = (*(block->getData< Storage >( id )))[0]; + buffer << localBodyStorage.size(); + for (auto bodyIt = localBodyStorage.begin(); bodyIt != localBodyStorage.end(); ++bodyIt) + { + if ( !block->getAABB().contains( bodyIt->getPosition()) ) + { + WALBERLA_ABORT( "Body to be stored not contained within block!" ); + } + marshal( buffer, RigidBodyCopyNotification( **bodyIt ) ); + MarshalDynamically<BodyTuple>::execute( buffer, **bodyIt ); + } +} + +template<typename BodyTuple> +Storage * StorageDataHandling<BodyTuple>::deserializeCoarseToFine( Block * const block ) +{ + return initialize(block); +} + +template<typename BodyTuple> +Storage * StorageDataHandling<BodyTuple>::deserializeFineToCoarse( Block * const block ) +{ + return initialize(block); +} + +template<typename BodyTuple> +void StorageDataHandling<BodyTuple>::deserializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) +{ + WALBERLA_DEBUG_SECTION() + { + BodyStorage& localBodyStorage = (*(block->getData< Storage >( id )))[0]; + WALBERLA_CHECK_EQUAL( localBodyStorage.size(), 0); + } + deserializeImpl( block, id, buffer); +} + +template<typename BodyTuple> +void StorageDataHandling<BodyTuple>::deserializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer, const uint_t /*child*/ ) +{ + deserializeImpl( block, id, buffer); +} + +template<typename BodyTuple> +void StorageDataHandling<BodyTuple>::deserializeImpl( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) { using namespace walberla::pe::communication; BodyStorage& localBodyStorage = (*(block->getData< Storage >( id )))[0]; - auto numBodies = localBodyStorage.size(); // just to get type right!!! can be replaced by decltype (C++11) + decltype(localBodyStorage.size()) numBodies = 0; buffer >> numBodies; while( numBodies > 0 ) @@ -88,10 +216,11 @@ inline void StorageDataHandling<BodyTuple>::deserialize( IBlock * const block, c BodyID bd = UnmarshalDynamically<BodyTuple>::execute(buffer, objparam.geomType_, block->getBlockStorage().getDomain(), block->getAABB()); bd->setRemote( false ); + bd->MPITrait.setOwner(Owner(MPIManager::instance()->rank(), block->getId().getID())); if ( !block->getAABB().contains( bd->getPosition()) ) { - WALBERLA_ABORT("Loaded body not contained within block!\n" << block->getAABB() << "\n" << bd ); + WALBERLA_ABORT("Loaded body not contained within block!\n" << "aabb: " << block->getAABB() << "\nparticle:" << bd ); } WALBERLA_ASSERT_EQUAL(localBodyStorage.find( bd->getSystemID() ), localBodyStorage.end()); localBodyStorage.add(bd);