diff --git a/src/blockforest/AABBRefinementSelection.h b/src/blockforest/AABBRefinementSelection.h index 4637f36f7c7c51adccd412b66cd98ed4aefc0f7d..fc454bedc4de777788d6b4a25ceb202bf950a373 100644 --- a/src/blockforest/AABBRefinementSelection.h +++ b/src/blockforest/AABBRefinementSelection.h @@ -22,6 +22,7 @@ #pragma once #include "SetupBlockForest.h" +#include "BlockForest.h" #include "core/config/Config.h" #include "core/math/AABB.h" @@ -39,6 +40,8 @@ class AABBRefinementSelection { public: + AABBRefinementSelection(){} + AABBRefinementSelection( const Config::BlockHandle & configBlock ) { if( configBlock ) @@ -79,25 +82,10 @@ public: regions_.push_back( std::make_pair( region, level ) ); } - std::vector< std::pair< math::AABB, uint_t > > transformRegionsToAABBs( SetupBlockForest & forest ) const - { - std::vector< std::pair< math::AABB, uint_t > > aabbs; - math::AABB aabb = forest.getDomain(); - for( auto region = regions_.begin(); region != regions_.end(); ++region ) - { - aabbs.push_back( std::make_pair( math::AABB( aabb.xMin() + region->first.xMin() * aabb.xSize(), - aabb.yMin() + region->first.yMin() * aabb.ySize(), - aabb.zMin() + region->first.zMin() * aabb.zSize(), - aabb.xMin() + region->first.xMax() * aabb.xSize(), - aabb.yMin() + region->first.yMax() * aabb.ySize(), - aabb.zMin() + region->first.zMax() * aabb.zSize() ), region->second ) ); - } - return aabbs; - } - + // for static refinement void operator()( SetupBlockForest & forest ) { - std::vector< std::pair< math::AABB, uint_t > > aabbs = transformRegionsToAABBs( forest ); + std::vector< std::pair< math::AABB, uint_t > > aabbs = transformRegionsToAABBs( forest.getDomain() ); aabbs.insert( aabbs.end(), aabbs_.begin(), aabbs_.end() ); if( aabbs.empty() ) @@ -113,8 +101,60 @@ public: } } + // for dynamic refinement + void operator()(std::vector< std::pair< const Block *, uint_t > > & minTargetLevels, + std::vector< const Block * > &, const BlockForest & forest ) + { + std::vector< std::pair< math::AABB, uint_t > > aabbs = transformRegionsToAABBs( forest.getDomain() ); + aabbs.insert( aabbs.end(), aabbs_.begin(), aabbs_.end() ); + + for( auto it = minTargetLevels.begin(); it != minTargetLevels.end(); ++it ) + { + uint_t currentLevelOfBlock = it->first->getLevel(); + uint_t targetLevelOfBlock = currentLevelOfBlock; + + for( auto aabb = aabbs.begin(); aabb != aabbs.end(); ++aabb ) + { + if( it->first->getAABB().intersects( aabb->first ) ) + { + uint_t targetLevelOfAABB = aabb->second; + if( currentLevelOfBlock > targetLevelOfAABB ) + { + targetLevelOfBlock = currentLevelOfBlock - uint_t(1); + } + else if ( currentLevelOfBlock < targetLevelOfBlock ) + { + targetLevelOfBlock = currentLevelOfBlock + uint_t(1); + } + // only the first found intersecting AABB is taken into account + break; + } + } + + WALBERLA_CHECK_LESS_EQUAL(std::abs(int_c(targetLevelOfBlock) - int_c(currentLevelOfBlock)), uint_t(1), "Only level difference of maximum 1 allowed!"); + it->second = targetLevelOfBlock; + } + } + + private: + std::vector< std::pair< math::AABB, uint_t > > transformRegionsToAABBs( const math::AABB & simulationDomain ) const + { + std::vector< std::pair< math::AABB, uint_t > > aabbs; + for( auto region = regions_.begin(); region != regions_.end(); ++region ) + { + aabbs.push_back( std::make_pair( math::AABB( simulationDomain.xMin() + region->first.xMin() * simulationDomain.xSize(), + simulationDomain.yMin() + region->first.yMin() * simulationDomain.ySize(), + simulationDomain.zMin() + region->first.zMin() * simulationDomain.zSize(), + simulationDomain.xMin() + region->first.xMax() * simulationDomain.xSize(), + simulationDomain.yMin() + region->first.yMax() * simulationDomain.ySize(), + simulationDomain.zMin() + region->first.zMax() * simulationDomain.zSize() ), region->second ) ); + } + return aabbs; + } + + std::vector< std::pair< math::AABB, uint_t > > aabbs_; std::vector< std::pair< math::AABB, uint_t > > regions_; diff --git a/src/blockforest/BlockForest.h b/src/blockforest/BlockForest.h index 42d1081e1feb7d6af47aba14e398966cdf055066..5d9a28628a7e23aa9029c1707d435bb0ef82fad0 100644 --- a/src/blockforest/BlockForest.h +++ b/src/blockforest/BlockForest.h @@ -989,6 +989,62 @@ private: +class CombinedMinTargetLevelDeterminationFunctions +{ +public: + + typedef blockforest::BlockForest::RefreshMinTargetLevelDeterminationFunction MinTargetLevelDeterminationFunction; + + CombinedMinTargetLevelDeterminationFunctions(const std::function<uint_t(const std::vector<uint_t> &)> & targetLevelReductionFct = [](const std::vector<uint_t> & t){ return *std::max_element(t.begin(), t.end());}) + : targetLevelReductionFct_( targetLevelReductionFct ) + { + + } + + void add( const MinTargetLevelDeterminationFunction & function ) + { + functions_.push_back( function ); + } + + void operator()( std::vector< std::pair< const Block *, uint_t > > & minTargetLevels, + std::vector< const Block * > & blocksAlreadyMarkedForRefinement, + const blockforest::BlockForest & forest ) + { + const uint_t numberOfBlocks = minTargetLevels.size(); + + std::vector< std::vector< std::pair< const Block *, uint_t > > > minTargetLevelsPerFunction(functions_.size(), minTargetLevels); + + // evaluate the different determination functions + auto iter = minTargetLevelsPerFunction.begin(); + for( auto function = functions_.begin(); function != functions_.end(); ++function, ++iter ) + { + (*function)( *iter, blocksAlreadyMarkedForRefinement, forest ); + WALBERLA_ASSERT_EQUAL(iter->size(), numberOfBlocks, "Number of blocks has changed during min target level determination!"); + } + + // combine the outcome of the different functions into a single target level + std::vector<uint_t> targetLevels(functions_.size()); + for( uint_t block = 0; block < numberOfBlocks; ++block ) + { + for( uint_t fct = 0; fct < functions_.size(); ++fct) + { + WALBERLA_ASSERT_EQUAL(minTargetLevelsPerFunction[fct][block].first->getId(), minTargetLevels[block].first->getId()); + targetLevels[fct] = minTargetLevelsPerFunction[fct][block].second; + } + minTargetLevels[block].second = targetLevelReductionFct_(targetLevels); + } + + } + +private: + + std::vector< MinTargetLevelDeterminationFunction > functions_; + std::function<uint_t(const std::vector<uint_t> &)> targetLevelReductionFct_; + +}; // class CombinedMinTargetLevelDeterminationFunctions + + + } // namespace blockforest using blockforest::BlockForest; diff --git a/src/blockforest/loadbalancing/DynamicParMetis.cpp b/src/blockforest/loadbalancing/DynamicParMetis.cpp index 0e215b6f92bc7b8bd835d165b2b76b7892e9c06b..369339eee4c0fc726e8da72a6e0335157ae76fc8 100644 --- a/src/blockforest/loadbalancing/DynamicParMetis.cpp +++ b/src/blockforest/loadbalancing/DynamicParMetis.cpp @@ -101,19 +101,6 @@ std::map< blockforest::BlockID, uint_t > getBlockIdToSequenceMapping( const Phan return mapping; } -template< typename T > -T * ptr( std::vector<T> & v ) -{ - if( v.empty() ) - return NULL; - else - return &( v.front() ); -} - -typedef uint_t idx_t; - - - bool DynamicParMetis::operator()( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, std::set< uint_t > & processesToRecvFrom, const PhantomBlockForest & phantomForest, @@ -163,6 +150,7 @@ bool DynamicParMetis::operator()( std::vector< std::pair< const PhantomBlock *, std::vector<double> xyz; uint_t blockIndex = 0; + int64_t ncon = int64_c(ncon_); for( auto it = targetProcess.begin(); it != targetProcess.end(); ++it, ++blockIndex ) { WALBERLA_CHECK_EQUAL(blockIndex, mapping.find(it->first->getId())->second - blockSequenceRange.first); @@ -181,7 +169,7 @@ bool DynamicParMetis::operator()( std::vector< std::pair< const PhantomBlock *, WALBERLA_CHECK_LESS( mapIt->second, vtxdist.back() ); adjncy.push_back( int64_c( mapIt->second ) ); auto edgeWeightIt = bi.getEdgeWeights().find( nit->getId() ); - //WALBERLA_CHECK_UNEQUAL( edgeWeightIt->second, 0 ); // perhaps WARNING + WALBERLA_CHECK_GREATER_EQUAL( edgeWeightIt->second, 0 ); adjwgt.push_back( edgeWeightIt == bi.getEdgeWeights().end() ? int64_t( 1 ) : edgeWeightIt->second ); } break; @@ -193,14 +181,22 @@ bool DynamicParMetis::operator()( std::vector< std::pair< const PhantomBlock *, WALBERLA_CHECK_GREATER_EQUAL( mapIt->second, 0 ); WALBERLA_CHECK_LESS( mapIt->second, vtxdist.back() ); adjncy.push_back( int64_c( mapIt->second ) ); - //WALBERLA_CHECK_UNEQUAL( edgeIt->second, 0 ); // perhaps WARNING + WALBERLA_CHECK_GREATER_EQUAL( edgeIt->second, 0 ); adjwgt.push_back( edgeIt->second ); } break; } - WALBERLA_CHECK_UNEQUAL( bi.getVertexWeight(), 0 ); - vwgt.push_back( bi.getVertexWeight() ); + + WALBERLA_CHECK_EQUAL(ncon, int64_c(bi.getNcon()), "Number of constraints on block does not fit to specified number of constraints in ParMetis setup!"); + + for( uint_t con = uint_t(0); con < bi.getNcon(); ++con ) + { + WALBERLA_CHECK_GREATER_EQUAL( bi.getVertexWeight(con), 0 ); + vwgt.push_back( bi.getVertexWeight(con) ); + } + vsize.push_back( bi.getVertexSize() ); + xyz.push_back( bi.getVertexCoords()[0] ); xyz.push_back( bi.getVertexCoords()[1] ); xyz.push_back( bi.getVertexCoords()[2] ); @@ -215,20 +211,19 @@ bool DynamicParMetis::operator()( std::vector< std::pair< const PhantomBlock *, { WALBERLA_ASSERT_LESS( xadj[i-1], xadj[i] ); } - WALBERLA_CHECK_EQUAL( vwgt.size(), targetProcess.size() ); + WALBERLA_CHECK_EQUAL( int64_c(vwgt.size()), int64_c(targetProcess.size()) * ncon); WALBERLA_CHECK_EQUAL( vsize.size(), targetProcess.size() ); WALBERLA_CHECK_EQUAL( xyz.size(), targetProcess.size() * 3 ); WALBERLA_CHECK_EQUAL( adjncy.size(), adjwgt.size() ); WALBERLA_CHECK_EQUAL( adjwgt.size(), xadj.back() ); - int64_t wgtflag = weightsToUse_; - int64_t numflag = 0; // C-style ordering - int64_t ncon = 1; // Number of constraints - int64_t ndims = 3; // Number of dimensions - std::vector<double> ubvec( uint_c(ncon), double_c( 1.05 ) ); // imbalance tolerance - int64_t nparts = int64_c( MPIManager::instance()->numProcesses() ); // number of subdomains - double ipc2redist = double_c(ipc2redist_); - MPI_Comm comm = subComm; //MPIManager::instance()->comm(); + int64_t wgtflag = weightsToUse_; + int64_t numflag = 0; // C-style ordering + int64_t ndims = 3; // Number of dimensions + std::vector<double> ubvec = ubvec_; // imbalance tolerance + int64_t nparts = int64_c( MPIManager::instance()->numProcesses() ); // number of subdomains + double ipc2redist = double_c(ipc2redist_); + MPI_Comm comm = subComm; //MPIManager::instance()->comm(); std::vector<double> tpwgts( uint_c(nparts * ncon), 1.0 / double_c( nparts ) ); // vertex weight fraction that is stored in a subdomain std::vector<int64_t> options = { int64_t( 1 ), int64_t( 0 ), int64_t( 23 ), int64_t( 1 ) }; @@ -237,34 +232,36 @@ bool DynamicParMetis::operator()( std::vector< std::pair< const PhantomBlock *, switch( algorithm_ ) { case PARMETIS_PART_GEOM: + WALBERLA_ASSERT_EQUAL(ncon, int64_t(1), "Chosen algorithm can only work with single constraints!"); parmetisTimer.start(); - metisResult = core::ParMETIS_V3_PartGeom( ptr( vtxdist ), &ndims, ptr( xyz ), ptr( part ), &comm ); + metisResult = core::ParMETIS_V3_PartGeom( vtxdist.data(), &ndims, xyz.data(), part.data(), &comm ); parmetisTimer.end(); break; case PARMETIS_PART_GEOM_KWAY: parmetisTimer.start(); - metisResult = core::ParMETIS_V3_PartGeomKway( ptr( vtxdist ), ptr( xadj ), ptr( adjncy ), ptr( vwgt ), ptr( adjwgt ), &wgtflag, &numflag, &ndims, ptr( xyz ), &ncon, &nparts, ptr( tpwgts ), ptr( ubvec ), ptr( options ), &edgecut, ptr( part ), &comm ); + metisResult = core::ParMETIS_V3_PartGeomKway( vtxdist.data(), xadj.data(), adjncy.data(), vwgt.data(), adjwgt.data(), &wgtflag, &numflag, &ndims, xyz.data(), &ncon, &nparts, tpwgts.data(), ubvec.data(), options.data(), &edgecut, part.data(), &comm ); parmetisTimer.end(); break; case PARMETIS_PART_KWAY: parmetisTimer.start(); - metisResult = core::ParMETIS_V3_PartKway( ptr( vtxdist ), ptr( xadj ), ptr( adjncy ), ptr( vwgt ), ptr( adjwgt ), &wgtflag, &numflag, &ncon, &nparts, ptr( tpwgts ), ptr(ubvec), ptr(options), &edgecut, ptr( part ), &comm ); + metisResult = core::ParMETIS_V3_PartKway( vtxdist.data(), xadj.data(), adjncy.data(), vwgt.data(), adjwgt.data(), &wgtflag, &numflag, &ncon, &nparts, tpwgts.data(), ubvec.data(), options.data(), &edgecut, part.data(), &comm ); parmetisTimer.end(); break; case PARMETIS_ADAPTIVE_REPART: parmetisTimer.start(); - metisResult = core::ParMETIS_V3_AdaptiveRepart( ptr( vtxdist ), ptr( xadj ), ptr( adjncy ), ptr( vwgt ), ptr( vsize ), ptr( adjwgt ), &wgtflag, &numflag, &ncon, &nparts, ptr( tpwgts ), ptr(ubvec), &ipc2redist, ptr(options), &edgecut, ptr( part ), &comm ); + metisResult = core::ParMETIS_V3_AdaptiveRepart( vtxdist.data(), xadj.data(), adjncy.data(), vwgt.data(), vsize.data(), adjwgt.data(), &wgtflag, &numflag, &ncon, &nparts, tpwgts.data(), ubvec.data(), &ipc2redist, options.data(), &edgecut, part.data(), &comm ); parmetisTimer.end(); break; case PARMETIS_REFINE_KWAY: parmetisTimer.start(); - metisResult = core::ParMETIS_V3_RefineKway( ptr( vtxdist ), ptr( xadj ), ptr( adjncy ), ptr( vwgt ), ptr( adjwgt ), &wgtflag, &numflag, &ncon, &nparts, ptr( tpwgts ), ptr(ubvec), ptr(options), &edgecut, ptr( part ), &comm ); + metisResult = core::ParMETIS_V3_RefineKway( vtxdist.data(), xadj.data(), adjncy.data(), vwgt.data(), adjwgt.data(), &wgtflag, &numflag, &ncon, &nparts, tpwgts.data(), ubvec.data(), options.data(), &edgecut, part.data(), &comm ); parmetisTimer.end(); break; } if( metisResult != core::METIS_OK ) WALBERLA_ABORT("ParMetis failed!"); + } // Determine which processes will receive a block from this process @@ -278,7 +275,7 @@ bool DynamicParMetis::operator()( std::vector< std::pair< const PhantomBlock *, isSendingBlockToProcess[uint_c(MPIManager::instance()->rank())] = uint8_t( 0 ); std::vector<uint8_t> isReceivingBlockFromProcess( uint_c(MPIManager::instance()->numProcesses()), uint8_t( 0 ) ); - MPI_Alltoall( ptr( isSendingBlockToProcess ), 1, MPITrait<uint8_t>::type(), ptr( isReceivingBlockFromProcess ), 1, MPITrait<uint8_t>::type(), MPIManager::instance()->comm() ); + MPI_Alltoall( isSendingBlockToProcess.data(), 1, MPITrait<uint8_t>::type(), isReceivingBlockFromProcess.data(), 1, MPITrait<uint8_t>::type(), MPIManager::instance()->comm() ); for( uint_t i = 0; i < isReceivingBlockFromProcess.size(); ++i ) if( isReceivingBlockFromProcess[i] == uint8_t( 1 ) ) processesToRecvFrom.insert( i ); @@ -317,12 +314,12 @@ DynamicParMetis::Algorithm DynamicParMetis::stringToAlgorithm( std::string s ) return PARMETIS_PART_GEOM; else if( s == "PART_KWAY" ) return PARMETIS_PART_KWAY; - else if( s == "PART_ADAPTIVE_REPART" ) + else if( s == "ADAPTIVE_REPART" ) return PARMETIS_ADAPTIVE_REPART; else if( s == "REFINE_KWAY" ) return PARMETIS_REFINE_KWAY; else - WALBERLA_ABORT( "Illegal ParMetis algorithm specified (" << s << ")! Valid choices are: \"PART_GEOM_KWAY\", \"PART_KWAY\", \"PART_ADAPTIVE_REPART\", or \"REFINE_KWAY\"." ); + WALBERLA_ABORT( "Illegal ParMetis algorithm specified (" << s << ")! Valid choices are: \"PART_GEOM_KWAY\", \"PART_GEOM\", \"PART_KWAY\", \"ADAPTIVE_REPART\", or \"REFINE_KWAY\"." ); } @@ -369,7 +366,7 @@ std::string DynamicParMetis::algorithmToString( ) const case walberla::blockforest::DynamicParMetis::PARMETIS_PART_KWAY: return "PART_KWAY"; case walberla::blockforest::DynamicParMetis::PARMETIS_ADAPTIVE_REPART: - return "PART_ADAPTIVE_REPART"; + return "ADAPTIVE_REPART"; case walberla::blockforest::DynamicParMetis::PARMETIS_REFINE_KWAY: return "PARMETIS_REFINE_KWAY"; } diff --git a/src/blockforest/loadbalancing/DynamicParMetis.h b/src/blockforest/loadbalancing/DynamicParMetis.h index d1b3acd1f877c755279f8a4b3f0d2a2586549cd7..fa5663db5961e89cb57f4150cca10902706379d3 100644 --- a/src/blockforest/loadbalancing/DynamicParMetis.h +++ b/src/blockforest/loadbalancing/DynamicParMetis.h @@ -30,6 +30,7 @@ #include <cmath> #include <map> +#include <vector> namespace walberla { namespace blockforest { @@ -48,8 +49,9 @@ public: DynamicParMetis( const Algorithm algorithm = PARMETIS_PART_GEOM_KWAY, const WeightsToUse weightsToUse = PARMETIS_BOTH_WEIGHTS, - const EdgeSource edgeSource = PARMETIS_EDGES_FROM_EDGE_WEIGHTS ) - : algorithm_( algorithm ), weightsToUse_( weightsToUse ), edgeSource_( edgeSource ) {} + const EdgeSource edgeSource = PARMETIS_EDGES_FROM_EDGE_WEIGHTS, + const uint_t ncon = uint_t(1)) + : algorithm_( algorithm ), weightsToUse_( weightsToUse ), edgeSource_( edgeSource ), ncon_( ncon ), ubvec_( ncon, real_t(1.05) ) {} bool operator()( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, std::set< uint_t > & processesToRecvFrom, @@ -60,6 +62,10 @@ public: void setipc2redist(double val) {ipc2redist_ = val;} double getipc2redist() const {return ipc2redist_;} + void setImbalanceTolerances(const std::vector<double> & tolerances){ WALBERLA_ASSERT_EQUAL(tolerances.size(), ncon_-uint_t(1)); ubvec_ = tolerances; } + void setImbalanceTolerance(double tolerance, const uint_t con = 0){ WALBERLA_ASSERT_LESS(con, ncon_); ubvec_[con] = tolerance; } + double getImbalanceTolerance(const uint_t con = 0) const { WALBERLA_ASSERT_LESS(con, ncon_); return ubvec_[con]; } + bool edgeWeightsUsed() const { return ( weightsToUse_ == PARMETIS_EDGE_WEIGHTS ) || ( weightsToUse_ == PARMETIS_BOTH_WEIGHTS ); } bool vertexWeightsUsed() const { return ( weightsToUse_ == PARMETIS_VERTEX_WEIGHTS ) || ( weightsToUse_ == PARMETIS_BOTH_WEIGHTS ); } bool vertexSizeUsed() const { return algorithm_ == PARMETIS_ADAPTIVE_REPART; } @@ -77,6 +83,8 @@ protected: WeightsToUse weightsToUse_; EdgeSource edgeSource_; + uint_t ncon_ = uint_t(1); ///< number of constraints + std::vector<double> ubvec_; ///< imbalance tolerance for each constraint, value between 1 (perfect balance) and number of subdomains (= number of processes, perfect imbalance) double ipc2redist_ = real_t( 1000.0 ); ///< compute repartitioning with low edge cut (set lower (down to 0.000001) to get minimal repartitioning ) }; @@ -87,8 +95,8 @@ public: typedef int64_t weight_t; typedef int64_t vsize_t; - DynamicParMetisBlockInfo( const weight_t vertexWeight ) - : vertexWeight_(vertexWeight), vertexSize_(1) + DynamicParMetisBlockInfo( const weight_t vertexWeight, const uint_t ncon = 1 ) + : vertexWeight_(ncon, vertexWeight), vertexSize_(1) { } DynamicParMetisBlockInfo( mpi::RecvBuffer & buffer ) @@ -96,13 +104,35 @@ public: buffer >> vertexWeight_ >> vertexSize_ >> vertexCoords_ >> edgeWeights_; } - weight_t getVertexWeight() const { return vertexWeight_; } - void setVertexWeight( const weight_t vertexWeight ) { vertexWeight_ = vertexWeight; } + DynamicParMetisBlockInfo( const std::vector<weight_t> & vertexWeight ) + : vertexWeight_(vertexWeight), vertexSize_(1) + { } + + // get number of constraints ( = number of vertex weights), default: 1, > 1 for multi physics problems + uint_t getNcon() const + { + return vertexWeight_.size(); + } + + weight_t getVertexWeight( const uint_t con = 0 ) const + { + WALBERLA_ASSERT_LESS(con, getNcon()); + return vertexWeight_[con]; + } + void setVertexWeight( const weight_t vertexWeight, const uint_t con = 0 ) + { + WALBERLA_ASSERT_LESS(con, getNcon()); + vertexWeight_[con] = vertexWeight; + } - vsize_t getVertexSize() const { return vertexSize_; } - void setVertexSize( const vsize_t size ) { vertexSize_ = size; } + vsize_t getVertexSize( ) const { return vertexSize_; } + void setVertexSize( const vsize_t size) { vertexSize_ = size; } - const Vector3<double> & getVertexCoords() const { WALBERLA_ASSERT( !std::isnan(vertexCoords_[0]) && !std::isnan(vertexCoords_[1]) && !std::isnan(vertexCoords_[2]) ); return vertexCoords_; } + const Vector3<double> & getVertexCoords() const + { + WALBERLA_ASSERT( !std::isnan(vertexCoords_[0]) && !std::isnan(vertexCoords_[1]) && !std::isnan(vertexCoords_[2]) ); + return vertexCoords_; + } void setVertexCoords( const Vector3<double> & p ) { vertexCoords_ = p; } void setEdgeWeight( const blockforest::BlockID & blockId, const weight_t edgeWeight ) { edgeWeights_[blockId] = edgeWeight; } @@ -117,8 +147,8 @@ public: private: - weight_t vertexWeight_; /// Defines the weight of a block - vsize_t vertexSize_; /// Defines the cost of rebalancing a block + std::vector<weight_t> vertexWeight_; /// Defines the ncon weights of a block + vsize_t vertexSize_; /// Defines the cost of rebalancing a block. Needed by some ParMetis algorithms Vector3<double> vertexCoords_ = Vector3<double>(std::numeric_limits<double>::signaling_NaN()); /// Defines where the block is located in space. Needed by some ParMetis algorithms std::map< blockforest::BlockID, weight_t > edgeWeights_; /// Defines the cost of communication with other blocks }; diff --git a/src/blockforest/loadbalancing/all.h b/src/blockforest/loadbalancing/all.h index a4a2cb31b899f0da423196d5203db0327d275894..b3c956f8b13ac1efc0c3a3de4369c04239a1cfb8 100644 --- a/src/blockforest/loadbalancing/all.h +++ b/src/blockforest/loadbalancing/all.h @@ -25,5 +25,8 @@ #include "Cartesian.h" #include "DynamicCurve.h" #include "DynamicDiffusive.h" +#include "DynamicParMetis.h" #include "NoPhantomData.h" +#include "PODPhantomData.h" #include "StaticCurve.h" +#include "StaticParMetis.h" diff --git a/tests/pe/ParMetis.cpp b/tests/pe/ParMetis.cpp index e35a8cb2336015a2f6aa3f925a1c4a74c9ed263b..f43a92f57e36d2ea6acbb7fcf643d074a7aaff4f 100644 --- a/tests/pe/ParMetis.cpp +++ b/tests/pe/ParMetis.cpp @@ -129,7 +129,7 @@ int main( int argc, char ** argv ) walberla::MPIManager::instance()->initializeMPI( &argc, &argv ); walberla::MPIManager::instance()->useWorldComm(); - std::vector<std::string> algs = {"PART_GEOM", "PART_GEOM_KWAY", "PART_KWAY", "PART_ADAPTIVE_REPART", "REFINE_KWAY"}; + std::vector<std::string> algs = {"PART_GEOM", "PART_GEOM_KWAY", "PART_KWAY", "ADAPTIVE_REPART", "REFINE_KWAY"}; std::vector<std::string> wtu = {"NO_WEIGHTS", "EDGE_WEIGHTS", "VERTEX_WEIGHTS", "BOTH_WEIGHTS"}; std::vector<std::string> es = {"EDGES_FROM_FOREST", "EDGES_FROM_EDGE_WEIGHTS"};