diff --git a/src/pe_coupling/partially_saturated_cells_method/BodyAndVolumeFractionMapping.h b/src/pe_coupling/partially_saturated_cells_method/BodyAndVolumeFractionMapping.h index 1e461ebbd57c0ddc48e9027d090e66eee0b1d142..3a6ef85a07db100e4f487548c518a0f0d02d63d9 100644 --- a/src/pe_coupling/partially_saturated_cells_method/BodyAndVolumeFractionMapping.h +++ b/src/pe_coupling/partially_saturated_cells_method/BodyAndVolumeFractionMapping.h @@ -32,6 +32,9 @@ #include "pe_coupling/geometry/PeOverlapFraction.h" #include "pe_coupling/mapping/BodyBBMapping.h" +#include "pe_coupling/utility/BodySelectorFunctions.h" + +#include <boost/function.hpp> namespace walberla { namespace pe_coupling { @@ -79,6 +82,8 @@ void mapPSMBodyAndVolumeFraction( const pe::BodyID body, IBlock & block, Structu * * Upon construction, it uses the free mapping function to initialize the fraction and body mapping field. * + * Whether or not a body is considered by this mapping depends on the return value of 'mappingBodySelectorFct'. + * * Successive calls try to update this field instead of completely recalculating all volume fractions which is expensive. * To do so, the update functionality determines whether bodies have very small velocities, both translational and rotational, * (limited with velocityUpdatingEpsilon) or have not traveled very far (limited by positionUpdatingEpsilon) since the last volume fraction recalculation. @@ -103,13 +108,12 @@ public: const shared_ptr<pe::BodyStorage> & globalBodyStorage, const BlockDataID & bodyStorageID, const BlockDataID & bodyAndVolumeFractionFieldID, - const bool mapFixedBodies = false, - const bool mapGlobalBodies = false, + const boost::function<bool(pe::BodyID)> & mappingBodySelectorFct = selectRegularBodies, const real_t velocityUpdatingEpsilon = real_t(0), const real_t positionUpdatingEpsilon = real_t(0), const uint_t superSamplingDepth = uint_t(4) ) : blockStorage_( blockStorage), globalBodyStorage_( globalBodyStorage ), bodyStorageID_( bodyStorageID ), - bodyAndVolumeFractionFieldID_( bodyAndVolumeFractionFieldID ), mapFixed_( mapFixedBodies ), mapGlobal_( mapGlobalBodies ), + bodyAndVolumeFractionFieldID_( bodyAndVolumeFractionFieldID ), mappingBodySelectorFct_( mappingBodySelectorFct ), velocityUpdatingEpsilonSquared_( velocityUpdatingEpsilon * velocityUpdatingEpsilon ), positionUpdatingEpsilonSquared_( positionUpdatingEpsilon * positionUpdatingEpsilon ), superSamplingDepth_( superSamplingDepth ) @@ -127,11 +131,9 @@ public: private: - void updatePSMBodyAndVolumeFraction( const pe::BodyID body, IBlock & block, + void updatePSMBodyAndVolumeFraction( pe::BodyID body, IBlock & block, BodyAndVolumeFractionField_T * oldBodyAndVolumeFractionField, std::map< walberla::id_t, Vector3< real_t > > & tempLastUpdatedPositionMap ); - void updateGlobalPSMBodyAndVolumeFraction( const pe::BodyID body, IBlock & block, - BodyAndVolumeFractionField_T * oldBodyAndVolumeFractionField); shared_ptr<StructuredBlockStorage> blockStorage_; shared_ptr<pe::BodyStorage> globalBodyStorage_; @@ -139,8 +141,7 @@ private: const BlockDataID bodyStorageID_; const BlockDataID bodyAndVolumeFractionFieldID_; - const bool mapFixed_; - const bool mapGlobal_; + boost::function<bool(pe::BodyID)> mappingBodySelectorFct_; shared_ptr<BodyAndVolumeFractionField_T> updatedBodyAndVolumeFractionField_; std::map< walberla::id_t, Vector3< real_t > > lastUpdatedPositionMap_; @@ -177,20 +178,22 @@ void BodyAndVolumeFractionMapping::initialize() for( auto bodyIt = pe::BodyIterator::begin( *blockIt, bodyStorageID_); bodyIt != pe::BodyIterator::end(); ++bodyIt ) { - // only PSM and finite bodies (no planes, etc.) are mapped - if( /*!isPSMBody( *bodyIt ) ||*/ ( bodyIt->isFixed() && !mapFixed_ ) ) - continue; - mapPSMBodyAndVolumeFraction( *bodyIt, *blockIt, *blockStorage_, bodyAndVolumeFractionFieldID_ ); - lastUpdatedPositionMap_.insert( std::pair< walberla::id_t, Vector3< real_t > >( bodyIt->getSystemID(), bodyIt->getPosition() ) ); + if( mappingBodySelectorFct_(*bodyIt) ) + { + mapPSMBodyAndVolumeFraction( *bodyIt, *blockIt, *blockStorage_, bodyAndVolumeFractionFieldID_ ); + lastUpdatedPositionMap_.insert( std::pair< walberla::id_t, Vector3< real_t > >( bodyIt->getSystemID(), bodyIt->getPosition() ) ); + } } - if( mapGlobal_ ) + for( auto bodyIt = globalBodyStorage_->begin(); bodyIt != globalBodyStorage_->end(); ++bodyIt ) { - for( auto globalBodyIt = globalBodyStorage_->begin(); globalBodyIt != globalBodyStorage_->end(); ++globalBodyIt ) + if( mappingBodySelectorFct_(*bodyIt) ) { - mapPSMBodyAndVolumeFraction( *globalBodyIt, *blockIt, *blockStorage_, bodyAndVolumeFractionFieldID_ ); + mapPSMBodyAndVolumeFraction(*bodyIt, *blockIt, *blockStorage_, bodyAndVolumeFractionFieldID_); + lastUpdatedPositionMap_.insert( std::pair< walberla::id_t, Vector3< real_t > >( bodyIt->getSystemID(), bodyIt->getPosition() ) ); } } + } } @@ -204,17 +207,17 @@ void BodyAndVolumeFractionMapping::update() for( auto bodyIt = pe::BodyIterator::begin( *blockIt, bodyStorageID_); bodyIt != pe::BodyIterator::end(); ++bodyIt ) { - // only PSM and finite bodies (no planes, etc.) are mapped - if( /*!isPSMBody( *bodyIt ) ||*/ ( bodyIt->isFixed() && !mapFixed_ ) ) - continue; - updatePSMBodyAndVolumeFraction( *bodyIt, *blockIt, bodyAndVolumeFractionField, tempLastUpdatedPositionMap ); + if( mappingBodySelectorFct_(*bodyIt) ) + { + updatePSMBodyAndVolumeFraction(*bodyIt, *blockIt, bodyAndVolumeFractionField, tempLastUpdatedPositionMap); + } } - if( mapGlobal_ ) + for( auto bodyIt = globalBodyStorage_->begin(); bodyIt != globalBodyStorage_->end(); ++bodyIt ) { - for( auto globalBodyIt = globalBodyStorage_->begin(); globalBodyIt != globalBodyStorage_->end(); ++globalBodyIt ) + if( mappingBodySelectorFct_(*bodyIt) ) { - updateGlobalPSMBodyAndVolumeFraction( *globalBodyIt, *blockIt, bodyAndVolumeFractionField );; + updatePSMBodyAndVolumeFraction(*bodyIt, *blockIt, bodyAndVolumeFractionField, tempLastUpdatedPositionMap); } } @@ -230,7 +233,7 @@ void BodyAndVolumeFractionMapping::update() lastUpdatedPositionMap_ = tempLastUpdatedPositionMap; } -void BodyAndVolumeFractionMapping::updatePSMBodyAndVolumeFraction( const pe::BodyID body, IBlock & block, +void BodyAndVolumeFractionMapping::updatePSMBodyAndVolumeFraction( pe::BodyID body, IBlock & block, BodyAndVolumeFractionField_T * oldBodyAndVolumeFractionField, std::map< walberla::id_t, Vector3< real_t > > & tempLastUpdatedPositionMap ) { @@ -308,30 +311,6 @@ void BodyAndVolumeFractionMapping::updatePSMBodyAndVolumeFraction( const pe::Bod } } -void BodyAndVolumeFractionMapping::updateGlobalPSMBodyAndVolumeFraction( const pe::BodyID body, IBlock & block, - BodyAndVolumeFractionField_T * oldBodyAndVolumeFractionField ) -{ - - WALBERLA_ASSERT_NOT_NULLPTR( oldBodyAndVolumeFractionField ); - - // get bounding box of body - CellInterval cellBB = getCellBB( body, block, *blockStorage_, oldBodyAndVolumeFractionField->nrOfGhostLayers() ); - - // copy values of global body to new field - for( auto cellIt = cellBB.begin(); cellIt != cellBB.end(); ++cellIt ) - { - Cell cell( *cellIt ); - auto oldVec = oldBodyAndVolumeFractionField->get(cell); - for( auto pairIt = oldVec.begin(); pairIt != oldVec.end(); ++pairIt ) - { - if( pairIt->first == body ) - { - updatedBodyAndVolumeFractionField_->get(cell).push_back(*pairIt); - break; - } - } - } -} } // namespace pe_coupling } // namespace walberla diff --git a/tests/pe_coupling/partially_saturated_cells_method/SegreSilberbergPSM.cpp b/tests/pe_coupling/partially_saturated_cells_method/SegreSilberbergPSM.cpp index f05d9b43db7d971f4364c1daf7fe8faf2d53f1e4..563828ee360da2151c6e5ee36e27d30e9b337a56 100644 --- a/tests/pe_coupling/partially_saturated_cells_method/SegreSilberbergPSM.cpp +++ b/tests/pe_coupling/partially_saturated_cells_method/SegreSilberbergPSM.cpp @@ -550,7 +550,7 @@ int main( int argc, char **argv ) BlockDataID bodyAndVolumeFractionFieldID = field::addToStorage< BodyAndVolumeFractionField_T >( blocks, "body and volume fraction field", std::vector<BodyAndVolumeFraction_T>(), field::zyxf, 0 ); // map bodies and calculate solid volume fraction initially - pe_coupling::BodyAndVolumeFractionMapping bodyMapping( blocks, globalBodyStorage, bodyStorageID, bodyAndVolumeFractionFieldID ); + pe_coupling::BodyAndVolumeFractionMapping bodyMapping( blocks, globalBodyStorage, bodyStorageID, bodyAndVolumeFractionFieldID, pe_coupling::selectRegularBodies ); bodyMapping(); // initialize the PDF field for PSM