Commit eb378867 authored by Steffen Müthing's avatar Steffen Müthing Committed by Steffen Müthing

Merge branch 'feature/fix-parmetisgridpartitioner-compilation' into 'master'

Feature/fix parmetisgridpartitioner compilation

While running the dune-grid tests for the 2.4.1 release, I stumbled over
`test-loadbalancing`, which stubbornly refused to work on Ubuntu 14.04.
This merge request fixes two things:

- It makes the partitioner work with ParMETIS 3.x by adding the
  necessary typedefs for `idx_t` and `real_t`.
- It completely disables the partitioner when running with scotch,
  because scotch doesn't emulate all of the functions required by it.

See merge request !34
(cherry picked from commit 616551eb)
Signed-off-by: Steffen Müthing's avatarSteffen Müthing <muething@dune-project.org>
parent 03f5c8cd
......@@ -13,7 +13,7 @@
#include <dune/common/parametertree.hh>
#include <dune/common/parametertreeparser.hh>
#if HAVE_PARMETIS
#if HAVE_PARMETIS && defined(PARMETIS_MAJOR_VERSION)
#include <dune/grid/utility/parmetisgridpartitioner.hh>
#endif
......@@ -78,7 +78,7 @@ typedef GridType::LeafGridView GV;
int main(int argc, char** argv) try
{
#if ! HAVE_PARMETIS
#if ! (HAVE_PARMETIS && defined(PARMETIS_MAJOR_VERSION))
// Skip test -- without ParMetis it doesn't do anything useful
return 77;
#else
......@@ -183,7 +183,7 @@ int main(int argc, char** argv) try
}
return 0;
#endif // HAVE_PARMETIS
#endif // (HAVE_PARMETIS && defined(PARMETIS_MAJOR_VERSION))
}
catch (Exception &e){
std::cerr << "Exception: " << e << std::endl;
......
......@@ -17,8 +17,14 @@
#include <dune/grid/common/mcmgmapper.hh>
#if HAVE_PARMETIS
// only enable for ParMETIS because the implementation uses functions that
// are not emulated by scotch
#ifdef PARMETIS_MAJOR_VERSION
#include <parmetis.h>
namespace Dune
{
......@@ -28,10 +34,15 @@ namespace Dune
*/
template<class GridView>
struct ParMetisGridPartitioner {
#if PARMETIS_MAJOR_VERSION < 4
typedef idxtype idx_t;
typedef float real_t;
#endif
// define index type as provided by ParMETIS
#if PARMETIS_MAJOR_VERSION > 3
typedef idx_t idx_type;
typedef real_t real_type;
#else
typedef int idx_type;
typedef float real_type;
#endif // PARMETIS_MAJOR_VERSION > 3
typedef typename GridView::template Codim<0>::Iterator ElementIterator;
typedef typename GridView::template Codim<0>::template Partition<Interior_Partition>::Iterator InteriorElementIterator;
......@@ -58,24 +69,24 @@ namespace Dune
std::vector<unsigned> part(numElements);
// Setup parameters for ParMETIS
idx_t wgtflag = 0; // we don't use weights
idx_t numflag = 0; // we are using C-style arrays
idx_t ncon = 1; // number of balance constraints
idx_t ncommonnodes = 2; // number of nodes elements must have in common to be considered adjacent to each other
idx_t options[4] = {0, 0, 0, 0}; // use default values for random seed, output and coupling
idx_t edgecut; // will store number of edges cut by partition
idx_t nparts = mpihelper.size(); // number of parts equals number of processes
std::vector<real_t> tpwgts(ncon*nparts, 1./nparts); // load per subdomain and weight (same load on every process)
std::vector<real_t> ubvec(ncon, 1.05); // weight tolerance (same weight tolerance for every weight there is)
idx_type wgtflag = 0; // we don't use weights
idx_type numflag = 0; // we are using C-style arrays
idx_type ncon = 1; // number of balance constraints
idx_type ncommonnodes = 2; // number of nodes elements must have in common to be considered adjacent to each other
idx_type options[4] = {0, 0, 0, 0}; // use default values for random seed, output and coupling
idx_type edgecut; // will store number of edges cut by partition
idx_type nparts = mpihelper.size(); // number of parts equals number of processes
std::vector<real_type> tpwgts(ncon*nparts, 1./nparts); // load per subdomain and weight (same load on every process)
std::vector<real_type> ubvec(ncon, 1.05); // weight tolerance (same weight tolerance for every weight there is)
// The difference elmdist[i+1] - elmdist[i] is the number of nodes that are on process i
std::vector<idx_t> elmdist(nparts+1);
std::vector<idx_type> elmdist(nparts+1);
elmdist[0] = 0;
std::fill(elmdist.begin()+1, elmdist.end(), gv.size(0)); // all elements are on process zero
// Create and fill arrays "eptr", where eptr[i] is the number of vertices that belong to the i-th element, and
// "eind" contains the vertex-numbers of the i-the element in eind[eptr[i]] to eind[eptr[i+1]-1]
std::vector<idx_t> eptr, eind;
std::vector<idx_type> eptr, eind;
int numVertices = 0;
eptr.push_back(numVertices);
......@@ -98,7 +109,7 @@ namespace Dune
#endif
ParMETIS_V3_PartMeshKway(elmdist.data(), eptr.data(), eind.data(), NULL, &wgtflag, &numflag,
&ncon, &ncommonnodes, &nparts, tpwgts.data(), ubvec.data(),
options, &edgecut, reinterpret_cast<idx_t*>(part.data()), &comm);
options, &edgecut, reinterpret_cast<idx_type*>(part.data()), &comm);
#if PARMETIS_MAJOR_VERSION >= 4
if (OK != METIS_OK)
......@@ -120,7 +131,7 @@ namespace Dune
* \return std::vector with one uint per All_Partition element. For each Interior_Partition element, the entry is the
* number of the partition the element is assigned to.
*/
static std::vector<unsigned> repartition(const GridView& gv, const Dune::MPIHelper& mpihelper, real_t& itr = 1000) {
static std::vector<unsigned> repartition(const GridView& gv, const Dune::MPIHelper& mpihelper, real_type& itr = 1000) {
// Create global index map
GlobalIndexSet<GridView> globalIndex(gv,0);
......@@ -131,14 +142,14 @@ namespace Dune
std::vector<unsigned> interiorPart(numElements);
// Setup parameters for ParMETIS
idx_t wgtflag = 0; // we don't use weights
idx_t numflag = 0; // we are using C-style arrays
idx_t ncon = 1; // number of balance constraints
idx_t options[4] = {0, 0, 0, 0}; // use default values for random seed, output and coupling
idx_t edgecut; // will store number of edges cut by partition
idx_t nparts = mpihelper.size(); // number of parts equals number of processes
std::vector<real_t> tpwgts(ncon*nparts, 1./nparts); // load per subdomain and weight (same load on every process)
std::vector<real_t> ubvec(ncon, 1.05); // weight tolerance (same weight tolerance for every weight there is)
idx_type wgtflag = 0; // we don't use weights
idx_type numflag = 0; // we are using C-style arrays
idx_type ncon = 1; // number of balance constraints
idx_type options[4] = {0, 0, 0, 0}; // use default values for random seed, output and coupling
idx_type edgecut; // will store number of edges cut by partition
idx_type nparts = mpihelper.size(); // number of parts equals number of processes
std::vector<real_type> tpwgts(ncon*nparts, 1./nparts); // load per subdomain and weight (same load on every process)
std::vector<real_type> ubvec(ncon, 1.05); // weight tolerance (same weight tolerance for every weight there is)
MPI_Comm comm = Dune::MPIHelper::getCommunicator();
......@@ -149,14 +160,14 @@ namespace Dune
gv.comm().template allgather<int>(&numElements, 1, offset.data());
// The difference vtxdist[i+1] - vtxdist[i] is the number of elements that are on process i
std::vector<idx_t> vtxdist(gv.comm().size()+1);
std::vector<idx_type> vtxdist(gv.comm().size()+1);
vtxdist[0] = 0;
for (unsigned int i=1; i<vtxdist.size(); ++i)
vtxdist[i] = vtxdist[i-1] + offset[i-1];
// Set up element adjacency lists
std::vector<idx_t> xadj, adjncy;
std::vector<idx_type> xadj, adjncy;
xadj.push_back(0);
for (InteriorElementIterator eIt = gv.template begin<0, Interior_Partition>(); eIt != gv.template end<0, Interior_Partition>(); ++eIt)
......@@ -179,7 +190,7 @@ namespace Dune
#endif
ParMETIS_V3_AdaptiveRepart(vtxdist.data(), xadj.data(), adjncy.data(), NULL, NULL, NULL,
&wgtflag, &numflag, &ncon, &nparts, tpwgts.data(), ubvec.data(),
&itr, options, &edgecut, reinterpret_cast<idx_t*>(interiorPart.data()), &comm);
&itr, options, &edgecut, reinterpret_cast<idx_type*>(interiorPart.data()), &comm);
#if PARMETIS_MAJOR_VERSION >= 4
if (OK != METIS_OK)
......@@ -210,6 +221,10 @@ namespace Dune
} // namespace Dune
#else // PARMETIS_MAJOR_VERSION
#warning "You seem to be using the ParMETIS emulation layer of scotch, which does not work with this file."
#endif
#else // HAVE_PARMETIS
#warning "PARMETIS was not found, please check your configuration"
#endif
......
Markdown is supported
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