45 #ifndef _ZOLTAN2_ALGPARMETIS_HPP_ 46 #define _ZOLTAN2_ALGPARMETIS_HPP_ 58 #ifndef HAVE_ZOLTAN2_PARMETIS 64 template <
typename Adapter>
69 const RCP<
const Comm<int> > &problemComm,
73 throw std::runtime_error(
74 "BUILD ERROR: ParMETIS requested but not compiled into Zoltan2.\n" 75 "Please set CMake flag Zoltan2_ENABLE_ParMETIS:BOOL=ON.");
85 #ifdef HAVE_ZOLTAN2_PARMETIS 87 #ifndef HAVE_ZOLTAN2_MPI 91 #error "TPL ParMETIS requires compilation with MPI. Configure with -DTPL_ENABLE_MPI:BOOL=ON or -DZoltan2_ENABLE_ParMETIS:BOOL=OFF" 99 #if (PARMETIS_MAJOR_VERSION < 4) 103 #error "Specified version of ParMETIS is not compatible with Zoltan2; upgrade to ParMETIS v4 or later, or build Zoltan2 without ParMETIS." 111 template <
typename Adapter>
117 typedef typename Adapter::lno_t
lno_t;
118 typedef typename Adapter::gno_t
gno_t;
119 typedef typename Adapter::scalar_t
scalar_t;
120 typedef typename Adapter::part_t
part_t;
122 typedef idx_t pm_idx_t;
123 typedef real_t pm_real_t;
136 const RCP<
const Comm<int> > &problemComm__,
137 const RCP<graphModel_t> &model__) :
138 env(env__), problemComm(problemComm__),
139 mpicomm(TeuchosConst2MPI(problemComm__)),
147 const RCP<const Environment> env;
148 const RCP<const Comm<int> > problemComm;
150 const RCP<GraphModel<typename Adapter::base_adapter_t> > model;
158 template <
typename Adapter>
165 size_t numGlobalParts = solution->getTargetGlobalNumberOfParts();
167 int np = problemComm->getSize();
170 ArrayView<const gno_t> vtxgnos;
171 ArrayView<StridedData<lno_t, scalar_t> > vwgts;
172 int nVwgt = model->getNumWeightsPerVertex();
173 size_t nVtx = model->getVertexList(vtxgnos, vwgts);
177 pm_idx_t *pm_vwgts = NULL;
179 pm_vwgts =
new pm_idx_t[nVtx*nVwgt];
180 scale_weights(nVtx, vwgts, pm_vwgts);
184 ArrayView<const gno_t> adjgnos;
185 ArrayView<const lno_t> offsets;
186 ArrayView<StridedData<lno_t, scalar_t> > ewgts;
187 int nEwgt = model->getNumWeightsPerEdge();
188 size_t nEdge = model->getEdgeList(adjgnos, offsets, ewgts);
190 pm_idx_t *pm_ewgts = NULL;
192 pm_ewgts =
new pm_idx_t[nEdge*nEwgt];
193 scale_weights(nEdge, ewgts, pm_ewgts);
197 pm_idx_t *pm_offsets;
203 pm_idx_t *pm_vtxdist =
new pm_idx_t[np+1];
205 Teuchos::gatherAll(*problemComm, 1, &pm_nVtx, np, &(pm_vtxdist[1]));
206 for (
int i = 2; i <= np; i++)
207 pm_vtxdist[i] += pm_vtxdist[i-1];
213 pm_idx_t *pm_partList =
new pm_idx_t[nVtx+1];
217 pm_idx_t pm_nCon = (nVwgt == 0 ? 1 : pm_idx_t(nVwgt));
218 pm_real_t *pm_partsizes =
new pm_real_t[numGlobalParts*pm_nCon];
219 for (pm_idx_t dim = 0; dim < pm_nCon; dim++) {
220 if (!solution->criteriaHasUniformPartSizes(dim))
221 for (
size_t i=0; i<numGlobalParts; i++)
222 pm_partsizes[i*pm_nCon+dim] =
223 pm_real_t(solution->getCriteriaPartSize(dim,i));
225 for (
size_t i=0; i<numGlobalParts; i++)
226 pm_partsizes[i*pm_nCon+dim] = pm_real_t(1.) / pm_real_t(numGlobalParts);
228 pm_real_t *pm_imbTols =
new pm_real_t[pm_nCon];
229 for (pm_idx_t dim = 0; dim < pm_nCon; dim++)
230 pm_imbTols[dim] = 1.05;
232 std::string parmetis_method(
"PARTKWAY");
233 pm_idx_t pm_wgtflag = 2*(nVwgt > 0) + (nEwgt > 0);
234 pm_idx_t pm_numflag = 0;
239 if (parmetis_method ==
"PARTKWAY") {
241 pm_idx_t pm_edgecut = -1;
242 pm_idx_t pm_options[3];
247 ParMETIS_V3_PartKway(pm_vtxdist, pm_offsets, pm_adjs, pm_vwgts, pm_ewgts,
248 &pm_wgtflag, &pm_numflag, &pm_nCon, &pm_nPart,
249 pm_partsizes, pm_imbTols, pm_options,
250 &pm_edgecut, pm_partList, &mpicomm);
252 else if (parmetis_method ==
"ADAPTIVE_REPART") {
254 std::cout <<
"NOT READY FOR ADAPTIVE_REPART YET" << std::endl;
257 else if (parmetis_method ==
"PART_GEOM") {
259 std::cout <<
"NOT READY FOR PART_GEOM YET" << std::endl;
264 delete [] pm_vtxdist;
265 delete [] pm_partsizes;
266 delete [] pm_imbTols;
270 ArrayRCP<part_t> partList;
272 partList = ArrayRCP<part_t>((
part_t *)pm_partList, 0, nVtx,
true);
276 partList = ArrayRCP<part_t>(
new part_t[nVtx], 0, nVtx,
true);
277 for (
size_t i = 0; i < nVtx; i++) {
278 partList[i] =
part_t(pm_partList[i]);
280 delete [] pm_partList;
283 solution->setParts(partList);
285 env->memory(
"Zoltan2-ParMETIS: After creating solution");
291 if (nVwgt)
delete [] pm_vwgts;
292 if (nEwgt)
delete [] pm_ewgts;
305 template <
typename Adapter>
309 typename Adapter::scalar_t> > &fwgts,
313 const double INT_EPSILON = 1e-5;
314 const int nWgt = fwgts.size();
316 int *nonint_local =
new int[nWgt+nWgt];
317 int *nonint = nonint_local + nWgt;
319 double *sum_wgt_local =
new double[nWgt*4];
320 double *max_wgt_local = sum_wgt_local + nWgt;
321 double *sum_wgt = max_wgt_local + nWgt;
322 double *max_wgt = sum_wgt + nWgt;
324 for (
int i = 0; i < nWgt; i++) {
326 sum_wgt_local[i] = 0.;
327 max_wgt_local[i] = 0;
332 for (
int j = 0; j < nWgt; j++) {
333 for (
size_t i = 0; i < n; i++) {
334 double fw = double(fwgts[j][i]);
335 if (!nonint_local[j]) {
336 pm_idx_t tmp = (pm_idx_t) floor(fw + .5);
337 if (fabs((
double)tmp-fw) > INT_EPSILON) {
341 sum_wgt_local[j] += fw;
342 if (fw > max_wgt_local[j]) max_wgt_local[j] = fw;
346 Teuchos::reduceAll<int,int>(*problemComm, Teuchos::REDUCE_MAX, nWgt,
347 nonint_local, nonint);
348 Teuchos::reduceAll<int,double>(*problemComm, Teuchos::REDUCE_SUM, nWgt,
349 sum_wgt_local, sum_wgt);
350 Teuchos::reduceAll<int,double>(*problemComm, Teuchos::REDUCE_MAX, nWgt,
351 max_wgt_local, max_wgt);
353 const double max_wgt_sum = double(std::numeric_limits<pm_idx_t>::max()/8);
354 for (
int j = 0; j < nWgt; j++) {
359 if (nonint[j] || (max_wgt[j]<=INT_EPSILON) || (sum_wgt[j]>max_wgt_sum)) {
361 if (sum_wgt[j] != 0.) scale = max_wgt_sum/sum_wgt[j];
365 for (
size_t i = 0; i < n; i++)
366 iwgts[i*nWgt+j] = (pm_idx_t) ceil(
double(fwgts[j][i])*scale);
368 delete [] nonint_local;
369 delete [] sum_wgt_local;
374 #endif // PARMETIS VERSION 4 OR HIGHER CHECK 376 #endif // HAVE_ZOLTAN2_MPI 378 #endif // HAVE_ZOLTAN2_PARMETIS
static void DELETE_TPL_T_ARRAY(tpl_t **a)
Defines the PartitioningSolution class.
static void ASSIGN_TPL_T(tpl_t &a, zno_t b, const RCP< const Environment > &env)
AlgParMETIS(const RCP< const Environment > &env, const RCP< const Comm< int > > &problemComm, const RCP< GraphModel< typename Adapter::base_adapter_t > > &model)
Adapter::scalar_t scalar_t
A PartitioningSolution is a solution to a partitioning problem.
The StridedData class manages lists of weights or coordinates.
Algorithm defines the base class for all algorithms.
static void ASSIGN_TPL_T_ARRAY(tpl_t **a, ArrayView< const zno_t > &b, const RCP< const Environment > &env)
virtual void partition(const RCP< PartitioningSolution< Adapter > > &solution)
Partitioning method.
GraphModel defines the interface required for graph models.
Defines the GraphModel interface.
A gathering of useful namespace methods.