Skip to content
Snippets Groups Projects
Commit 74c2c5d7 authored by Sebastian Eibl's avatar Sebastian Eibl
Browse files

made DynamicDiffusive balance levelwise optional

parent 5c456a60
No related merge requests found
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#pragma once #pragma once
#include "NoPhantomData.h" #include "NoPhantomData.h"
#include "blockforest/BlockForest.h"
#include "blockforest/PhantomBlockForest.h" #include "blockforest/PhantomBlockForest.h"
#include "core/DataTypes.h" #include "core/DataTypes.h"
...@@ -41,20 +42,26 @@ namespace walberla { ...@@ -41,20 +42,26 @@ namespace walberla {
namespace blockforest { namespace blockforest {
/**
* This class implements a diffusive algorithm for load balancing.
*
* All algorithms are implemented to work levelwise. Load balancing with levels ignored is possible
* by specifying levelwise = false in the constructor.
**/
template< typename PhantomData_T > template< typename PhantomData_T >
class DynamicLevelwiseDiffusionBalance class DynamicDiffusionBalance
{ {
public: public:
enum Mode { DIFFUSION_PUSH, DIFFUSION_PULL, DIFFUSION_PUSHPULL }; enum Mode { DIFFUSION_PUSH, DIFFUSION_PULL, DIFFUSION_PUSHPULL };
DynamicLevelwiseDiffusionBalance( const uint_t maxIterations, const uint_t flowIterations ) : DynamicDiffusionBalance( const uint_t maxIterations, const uint_t flowIterations, const bool levelwise = true ) :
mode_( DIFFUSION_PUSHPULL ), maxIterations_( maxIterations ), mode_( DIFFUSION_PUSHPULL ), maxIterations_( maxIterations ),
defineProcessWeightLimitByMultipleOfMaxBlockWeight_( true ), checkForEarlyAbort_( true ), abortThreshold_( 1.0 ), defineProcessWeightLimitByMultipleOfMaxBlockWeight_( true ), checkForEarlyAbort_( true ), abortThreshold_( 1.0 ),
adaptOutflowWithGlobalInformation_( true ), adaptInflowWithGlobalInformation_( true ), adaptOutflowWithGlobalInformation_( true ), adaptInflowWithGlobalInformation_( true ),
flowIterations_( flowIterations ), flowIterationsIncreaseStart_( maxIterations ), flowIterationsIncrease_( 0.0 ), flowIterations_( flowIterations ), flowIterationsIncreaseStart_( maxIterations ), flowIterationsIncrease_( 0.0 ),
regardConnectivity_( true ), disregardConnectivityStart_( maxIterations ), outflowExceedFactor_( 1.0 ), inflowExceedFactor_( 1.0 ) regardConnectivity_( true ), disregardConnectivityStart_( maxIterations ), outflowExceedFactor_( 1.0 ), inflowExceedFactor_( 1.0 ),
levelwise_(levelwise)
{} {}
void setMode( const Mode mode ) { mode_ = mode; } void setMode( const Mode mode ) { mode_ = mode; }
...@@ -132,12 +139,18 @@ private: ...@@ -132,12 +139,18 @@ private:
double inflowExceedFactor_; double inflowExceedFactor_;
math::IntRandom< uint_t > random_; math::IntRandom< uint_t > random_;
/// All gets for levels are wrapped like
/// \code levelwise_ ? getCorrectLevel() : 0
///
/// This allows to use the same algorithm for levelwise balancing as well as for balancing without levels.
bool levelwise_;
}; };
template< typename PhantomData_T > template< typename PhantomData_T >
bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, bool DynamicDiffusionBalance< PhantomData_T >::operator()( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess,
std::set< uint_t > & processesToRecvFrom, std::set< uint_t > & processesToRecvFrom,
const PhantomBlockForest & phantomForest, const PhantomBlockForest & phantomForest,
const uint_t iteration ) const uint_t iteration )
...@@ -145,7 +158,7 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -145,7 +158,7 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
auto & blockforest = phantomForest.getBlockForest(); auto & blockforest = phantomForest.getBlockForest();
auto & neighborhood = phantomForest.getNeighborhood(); auto & neighborhood = phantomForest.getNeighborhood();
const uint_t levels = phantomForest.getNumberOfLevels(); const uint_t levels = levelwise_ ? phantomForest.getNumberOfLevels() : uint_t(1);
// determine process weight (for every level) // determine process weight (for every level)
...@@ -154,9 +167,11 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -154,9 +167,11 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
std::vector< double > maxBlockWeight( levels, 0.0 ); std::vector< double > maxBlockWeight( levels, 0.0 );
std::vector< double > processWeightLimit( levels, 0.0 ); std::vector< double > processWeightLimit( levels, 0.0 );
//fill processWeight with total weight per level
//find maxBlockWeight per level
for( auto it = targetProcess.begin(); it != targetProcess.end(); ++it ) for( auto it = targetProcess.begin(); it != targetProcess.end(); ++it )
{ {
const uint_t level = it->first->getLevel(); const uint_t level = levelwise_ ? it->first->getLevel() : uint_t(0);
const auto blockWeight = weight( it->first ); const auto blockWeight = weight( it->first );
WALBERLA_ASSERT_LESS( level, levels ); WALBERLA_ASSERT_LESS( level, levels );
WALBERLA_CHECK_GREATER_EQUAL( blockWeight, 0.0 ); WALBERLA_CHECK_GREATER_EQUAL( blockWeight, 0.0 );
...@@ -223,7 +238,7 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -223,7 +238,7 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
mpi::BufferSystem alphaBufferSystem( MPIManager::instance()->comm(), 1708 ); // dynamicdiffusion = 100 121 110 097 109 105 099 100 105 102 102 117 115 105 111 110 mpi::BufferSystem alphaBufferSystem( MPIManager::instance()->comm(), 1708 ); // dynamicdiffusion = 100 121 110 097 109 105 099 100 105 102 102 117 115 105 111 110
alphaBufferSystem.setReceiverInfo( alphaRanksToRecvFrom ); alphaBufferSystem.setReceiverInfo( alphaRanksToRecvFrom );
std::map< uint_t, double > alpha; std::map< uint_t, double > alpha; //process rank -> alpha
for( auto n = neighborhood.begin(); n != neighborhood.end(); ++n ) for( auto n = neighborhood.begin(); n != neighborhood.end(); ++n )
{ {
WALBERLA_ASSERT( alpha.find(*n) == alpha.end() ); WALBERLA_ASSERT( alpha.find(*n) == alpha.end() );
...@@ -246,7 +261,7 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -246,7 +261,7 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
WALBERLA_ASSERT( alpha.find( np ) != alpha.end() ); WALBERLA_ASSERT( alpha.find( np ) != alpha.end() );
double a( 0.0 ); double a( 0.0 );
recvIt.buffer() >> a; recvIt.buffer() >> a;
alpha[np] = std::min( alpha[np], a ); alpha[np] = std::min( alpha[np], a ); //find smallest alpha between neighbors
} }
// calculate flow for every edge (process-process connection) for every level // calculate flow for every edge (process-process connection) for every level
...@@ -258,11 +273,11 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -258,11 +273,11 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
mpi::BufferSystem bufferSystem( MPIManager::instance()->comm(), 1709 ); // dynamicdiffusion = 100 121 110 097 109 105 099 100 105 102 102 117 115 105 111 110 + 1 mpi::BufferSystem bufferSystem( MPIManager::instance()->comm(), 1709 ); // dynamicdiffusion = 100 121 110 097 109 105 099 100 105 102 102 117 115 105 111 110 + 1
bufferSystem.setReceiverInfo( ranksToRecvFrom ); bufferSystem.setReceiverInfo( ranksToRecvFrom );
std::map< uint_t, std::vector< double > > flow; std::map< uint_t, std::vector< double > > flow; //process rank -> flow on every level
for( auto n = neighborhood.begin(); n != neighborhood.end(); ++n ) for( auto n = neighborhood.begin(); n != neighborhood.end(); ++n )
flow[*n].resize( levels, 0.0 ); flow[*n].resize( levels, 0.0 );
std::vector< double > localWeight( processWeight ); std::vector< double > localWeight( processWeight ); //per level
double flowIterations( double_c( flowIterations_ ) ); double flowIterations( double_c( flowIterations_ ) );
if( iteration >= flowIterationsIncreaseStart_ ) if( iteration >= flowIterationsIncreaseStart_ )
...@@ -391,7 +406,8 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -391,7 +406,8 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
for( uint_t i = uint_t(0); i != targetProcess.size(); ++i ) for( uint_t i = uint_t(0); i != targetProcess.size(); ++i )
{ {
const auto * block = targetProcess[i].first; const auto * block = targetProcess[i].first;
if( block->getLevel() == l && targetProcess[i].second == blockforest.getProcess() ) const uint_t level = levelwise_ ? block->getLevel() : uint_t(0);
if( level == l && targetProcess[i].second == blockforest.getProcess() )
{ {
const uint_t * faces = blockforest::getFaceNeighborhoodSectionIndices(); const uint_t * faces = blockforest::getFaceNeighborhoodSectionIndices();
for( uint_t j = uint_t(0); j != uint_t(6); ++j ) for( uint_t j = uint_t(0); j != uint_t(6); ++j )
...@@ -464,7 +480,8 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -464,7 +480,8 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
// no distinction between different connection types (face,edge,corner) // no distinction between different connection types (face,edge,corner)
for( uint_t i = uint_t(0); i != targetProcess.size(); ++i ) for( uint_t i = uint_t(0); i != targetProcess.size(); ++i )
{ {
if( targetProcess[i].first->getLevel() == l && targetProcess[i].second == blockforest.getProcess() ) const uint_t level = levelwise_ ? targetProcess[i].first->getLevel() : uint_t(0);
if( level == l && targetProcess[i].second == blockforest.getProcess() )
{ {
bool connectedToPickedProcess( false ); bool connectedToPickedProcess( false );
for( auto n = targetProcess[i].first->getNeighborhood().begin(); for( auto n = targetProcess[i].first->getNeighborhood().begin();
...@@ -481,7 +498,8 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -481,7 +498,8 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
// blocks of this level, not yet assigned to another process and not only connected to other blocks of this process (= no 'inner' block) // blocks of this level, not yet assigned to another process and not only connected to other blocks of this process (= no 'inner' block)
for( uint_t i = uint_t(0); i != targetProcess.size(); ++i ) for( uint_t i = uint_t(0); i != targetProcess.size(); ++i )
{ {
if( targetProcess[i].first->getLevel() == l && targetProcess[i].second == blockforest.getProcess() && const uint_t level = levelwise_ ? targetProcess[i].first->getLevel() : uint_t(0);
if( level == l && targetProcess[i].second == blockforest.getProcess() &&
assigned.find(i) == assigned.end() ) assigned.find(i) == assigned.end() )
{ {
bool connectedToOtherProcesses( false ); bool connectedToOtherProcesses( false );
...@@ -498,7 +516,8 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -498,7 +516,8 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
// all blocks of this level, not yet assigned to another process and still assigned to this process // all blocks of this level, not yet assigned to another process and still assigned to this process
for( uint_t i = uint_t(0); i != targetProcess.size(); ++i ) for( uint_t i = uint_t(0); i != targetProcess.size(); ++i )
{ {
if( targetProcess[i].first->getLevel() == l && targetProcess[i].second == blockforest.getProcess() && const uint_t level = levelwise_ ? targetProcess[i].first->getLevel() : uint_t(0);
if( level == l && targetProcess[i].second == blockforest.getProcess() &&
assigned.find(i) == assigned.end() ) assigned.find(i) == assigned.end() )
candidates.push_back( i ); candidates.push_back( i );
} }
...@@ -508,7 +527,8 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -508,7 +527,8 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
std::vector< uint_t > blocksToPick; std::vector< uint_t > blocksToPick;
for( uint_t i = uint_t(0); i != targetProcess.size(); ++i ) for( uint_t i = uint_t(0); i != targetProcess.size(); ++i )
{ {
if( targetProcess[i].first->getLevel() == l && targetProcess[i].second == blockforest.getProcess() ) const uint_t level = levelwise_ ? targetProcess[i].first->getLevel() : uint_t(0);
if( level == l && targetProcess[i].second == blockforest.getProcess() )
blocksToPick.push_back( i ); blocksToPick.push_back( i );
} }
while( ! blocksToPick.empty() ) while( ! blocksToPick.empty() )
...@@ -522,7 +542,8 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -522,7 +542,8 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
/* /*
for( uint_t i = uint_t(0); i != targetProcess.size(); ++i ) for( uint_t i = uint_t(0); i != targetProcess.size(); ++i )
{ {
if( targetProcess[i].first->getLevel() == l && targetProcess[i].second == blockforest.getProcess() ) const uint_t level = levelwise_ ? targetProcess[i].first->getLevel() : uint_t(0);
if( level == l && targetProcess[i].second == blockforest.getProcess() )
candidates.push_back( i ); candidates.push_back( i );
} }
*/ */
...@@ -629,7 +650,7 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -629,7 +650,7 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
for( uint_t i = uint_t(0); i != targetProcess.size(); ++i ) for( uint_t i = uint_t(0); i != targetProcess.size(); ++i )
{ {
const auto * block = targetProcess[i].first; const auto * block = targetProcess[i].first;
const uint_t level = block->getLevel(); const uint_t level = levelwise_ ? block->getLevel() : uint_t(0);
if( processLevel[level] ) if( processLevel[level] )
{ {
if( regardConnectivity_ && iteration < disregardConnectivityStart_ ) if( regardConnectivity_ && iteration < disregardConnectivityStart_ )
...@@ -801,7 +822,7 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -801,7 +822,7 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
blocksFromNeighbors[ it->first ].resize( levels ); blocksFromNeighbors[ it->first ].resize( levels );
for( auto pr = it->second.begin(); pr != it->second.end(); ++pr ) for( auto pr = it->second.begin(); pr != it->second.end(); ++pr )
{ {
const uint_t level = blockforest.getLevelFromBlockId( pr->first ); const uint_t level = levelwise_ ? blockforest.getLevelFromBlockId( pr->first ) : uint_t(0);
WALBERLA_ASSERT_LESS( level, blocksFromNeighbors[ it->first ].size() ); WALBERLA_ASSERT_LESS( level, blocksFromNeighbors[ it->first ].size() );
blocksFromNeighbors[ it->first ][ level ].push_back( *pr ); blocksFromNeighbors[ it->first ][ level ].push_back( *pr );
} }
...@@ -920,7 +941,7 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -920,7 +941,7 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
++index; ++index;
} }
WALBERLA_ASSERT( index < targetProcess.size() && targetProcess[ index ].first->getId() == it->first ); WALBERLA_ASSERT( index < targetProcess.size() && targetProcess[ index ].first->getId() == it->first );
const uint_t level = targetProcess[ index ].first->getLevel(); const uint_t level = levelwise_ ? targetProcess[ index ].first->getLevel() : uint_t(0);
auto p = it->second.begin(); auto p = it->second.begin();
uint_t pickedProcess = *p; uint_t pickedProcess = *p;
...@@ -974,7 +995,9 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector< ...@@ -974,7 +995,9 @@ bool DynamicLevelwiseDiffusionBalance< PhantomData_T >::operator()( std::vector<
return ( iteration + uint_t(1) ) < maxIterations_; return ( iteration + uint_t(1) ) < maxIterations_;
} }
///This class is deprecated use DynamicDiffusionBalance instead.
template< typename PhantomData_T >
using DynamicLevelwiseDiffusionBalance = DynamicDiffusionBalance<PhantomData_T> ;
} // namespace blockforest } // namespace blockforest
} // namespace walberla } // namespace walberla
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment