forked from TUM-I5/PUML2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PartitionMetis.h
158 lines (130 loc) · 3.91 KB
/
PartitionMetis.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/**
* @file
* This file is part of PUML
*
* For conditions of distribution and use, please see the copyright
* notice in the file 'COPYING' at the root directory of this package
* and the copyright notice at https://github.com/TUM-I5/PUMGen
*
* @copyright 2017 Technische Universitaet Muenchen
* @author Sebastian Rettenberger <[email protected]>
*/
#ifndef PUML_PARTITIONMETHIS_H
#define PUML_PARTITIONMETHIS_H
#ifdef USE_MPI
#include <mpi.h>
#endif // USE_MPI
#include <parmetis.h>
#include "Topology.h"
namespace PUML
{
template<TopoType Topo>
class PartitionMetis
{
public:
/** The cell type */
typedef unsigned long cell_t[internal::Topology<Topo>::cellvertices()];
private:
#ifdef USE_MPI
MPI_Comm m_comm;
#endif // USE_MPI
const cell_t * const m_cells;
const idx_t m_numCells;
public:
PartitionMetis(const cell_t* cells, unsigned int numCells) :
#ifdef USE_MPI
m_comm(MPI_COMM_WORLD),
#endif // USE_MPI
m_cells(cells), m_numCells(numCells)
{ }
#ifdef USE_MPI
void setComm(MPI_Comm comm)
{
m_comm = comm;
}
#endif // USE_MPI
#ifdef USE_MPI
/**
* @param partition An array of size <code>numCells</code> which
* will contain the partition for each cells
* @param vertexWeights Weight for each vertex
* @param nWeightsPerVertex Number of weights per vertex
* @param nodeWeights Weight for each node
* @param imbalance The allowed imbalance
*/
void partition(int* partition, int const* vertexWeights = nullptr, int nWeightsPerVertex = 1, double* nodeWeights = nullptr, double imbalance = 1.05)
{
int rank, procs;
MPI_Comm_rank(m_comm, &rank);
MPI_Comm_size(m_comm, &procs);
idx_t* elemdist = new idx_t[procs+1];
MPI_Allgather(const_cast<idx_t*>(&m_numCells), 1, IDX_T, elemdist, 1, IDX_T, m_comm);
idx_t sum = 0;
for (int i = 0; i < procs; i++) {
idx_t e = elemdist[i];
elemdist[i] = sum;
sum += e;
}
elemdist[procs] = sum;
idx_t* eptr = new idx_t[m_numCells+1];
idx_t* eind = new idx_t[m_numCells * internal::Topology<Topo>::cellvertices()];
unsigned long m = 0;
for (idx_t i = 0; i < m_numCells; i++) {
eptr[i] = i * internal::Topology<Topo>::cellvertices();
for (unsigned int j = 0; j < internal::Topology<Topo>::cellvertices(); j++) {
m = std::max(m, m_cells[i][j]);
eind[i*internal::Topology<Topo>::cellvertices() + j] = m_cells[i][j];
}
}
eptr[m_numCells] = m_numCells * internal::Topology<Topo>::cellvertices();
idx_t wgtflag = 0;
idx_t* elmwgt = nullptr;
if (vertexWeights != nullptr) {
wgtflag = 2;
elmwgt = new idx_t[m_numCells];
for (idx_t i = 0; i < m_numCells; i++) {
elmwgt[i] = static_cast<idx_t>(vertexWeights[i]);
}
}
idx_t numflag = 0;
idx_t ncon = nWeightsPerVertex;
idx_t ncommonnodes = 3; // TODO adapt for hex
idx_t nparts = procs;
real_t* tpwgts = new real_t[nparts * ncon];
if (nodeWeights != nullptr) {
for (idx_t i = 0; i < nparts; i++) {
for (idx_t j = 0; j < ncon; ++j) {
tpwgts[i*ncon + j] = nodeWeights[i];
}
}
} else {
for (idx_t i = 0; i < nparts * ncon; i++) {
tpwgts[i] = static_cast<real_t>(1.) / nparts;
}
}
real_t* ubvec = new real_t[ncon];
for (idx_t i = 0; i < ncon; ++i) {
ubvec[i] = imbalance;
}
idx_t edgecut;
idx_t options[3] = {1, 0, METIS_RANDOM_SEED};
idx_t* part = new idx_t[m_numCells];
ParMETIS_V3_PartMeshKway(elemdist, eptr, eind, elmwgt, &wgtflag, &numflag,
&ncon, &ncommonnodes, &nparts, tpwgts, ubvec, options, &edgecut, part, &m_comm);
delete [] elemdist;
delete [] eptr;
delete [] eind;
delete [] tpwgts;
delete [] ubvec;
for (idx_t i = 0; i < m_numCells; i++)
partition[i] = part[i];
delete [] part;
}
#endif // USE_MPI
private:
static const int METIS_RANDOM_SEED = 42;
};
/** Convenient typedef for tetrahrdral meshes */
typedef PartitionMetis<TETRAHEDRON> TETPartitionMetis;
}
#endif // PUML_PARTITIONMETHIS_H