ZoltanPartitioner.cc 16.9 KB
Newer Older
1
2
3
4
5
6
7
/******************************************************************************
 *
 * AMDiS - Adaptive multidimensional simulations
 *
 * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
 * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
 *
8
 * Authors:
9
10
11
12
13
14
15
16
17
 * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 *
 * This file is part of AMDiS
 *
 * See also license.opensource.txt in the distribution.
18
 *
19
 ******************************************************************************/
20

21
#ifdef HAVE_ZOLTAN
22

23
24
25
26
#include <boost/lexical_cast.hpp>
#include "parallel/ZoltanPartitioner.h"
#include "Traverse.h"
#include "ElInfo.h"
27
#include "Initfile.h"
28

Backofen, Rainer's avatar
Backofen, Rainer committed
29
30
using namespace std;

31
namespace AMDiS { namespace Parallel {
32

33
34
35
  ZoltanPartitioner::ZoltanPartitioner(string name,
				       MPI::Intracomm *comm)
    : MeshPartitioner(name, comm),
36
      zoltan(*comm),
37
      elWeights(NULL)
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  {
    /* Read configuration for Zoltan
     * format in initfile:
     * <tag><NameOfZoltanParameter>:<ValueOfParameter>
     * e.g.
     *  zoltan parameter->LB_METHOD: GRAPH
     */
    std::string tag="zoltan parameter->";
    std::string tagInitial="zoltan parameter->";

    Parameters::get("zoltan->parameter tag", tag);
    Parameters::get("zoltan->parameter initial tag", tagInitial);

    Parameters::getParameterMap(tag,paramMap,2);
    Parameters::getParameterMap(tagInitial,paramMapInitial,2);

  }
55
56


57
  bool ZoltanPartitioner::partition(map<int, double> &weights,
58
59
60
61
				    PartitionMode mode)
  {
    FUNCNAME("ZoltanPartitioner::partition()");

Thomas Witkowski's avatar
Thomas Witkowski committed
62
63
64
65
66
67
68
69
70
71
72
    if (!boxPartitioning) {
      zoltan.Set_Num_Obj_Fn(ZoltanFunctions::getNumObj, this);
      zoltan.Set_Obj_List_Fn(ZoltanFunctions::getObjectList, this);
      zoltan.Set_Num_Geom_Fn(ZoltanFunctions::getNumGeom, this);
      zoltan.Set_Geom_Multi_Fn(ZoltanFunctions::getGeomMulti, this);
      zoltan.Set_Num_Edges_Multi_Fn(ZoltanFunctions::getNumEdgeMulti, this);
      zoltan.Set_Edge_List_Multi_Fn(ZoltanFunctions::getEdgeListMulti, this);
    } else {
      zoltan.Set_Num_Obj_Fn(ZoltanFunctions::box_getNumObj, this);
      zoltan.Set_Obj_List_Fn(ZoltanFunctions::box_getObjectList, this);
      zoltan.Set_Num_Geom_Fn(ZoltanFunctions::box_getNumGeom, this);
73
      //zoltan.Set_Geom_Multi_Fn(ZoltanFunctions::box_getGeomMulti, this);
Thomas Witkowski's avatar
Thomas Witkowski committed
74
75
76
77
      zoltan.Set_Num_Edges_Multi_Fn(ZoltanFunctions::box_getNumEdgeMulti, this);
      zoltan.Set_Edge_List_Multi_Fn(ZoltanFunctions::box_getEdgeListMulti, this);
    }

78
79
80
    if (mode != INITIAL)
      elWeights = &weights;

81
82
83
84
85
    using boost::lexical_cast;

    int changes;
    int nGid, nLid;

86
    int nImportEls;
87
88
89
90
91
92
93
94
95
    ZOLTAN_ID_PTR import_global_ids, import_local_ids;
    int *import_procs;
    int *import_to_part;

    int nExportEls;
    ZOLTAN_ID_PTR export_global_ids, export_local_ids;
    int *export_procs;
    int *export_to_part;

96
97
98
99
    /*
     *  Set default configuration for Zoltan
     */

100
101
    if (mode == INITIAL) {
      zoltan.Set_Param("LB_APPROACH", "PARTITION");
102
103
104
105
106
107
      zoltan.Set_Param("LB_METHOD", "GRAPH");
      zoltan.Set_Param("REDUCE_DIMENSIONS", "1");
      zoltan.Set_Param("DEGENERATE_RATIO", "1.1");
      zoltan.Set_Param("RCB_RECTILINEAR_BLOCKS", "1");
      zoltan.Set_Param("AVERAGE_CUTS", "1");
      zoltan.Set_Param("RCB_RECOMPUTE_BOX", "1");
Thomas Witkowski's avatar
Thomas Witkowski committed
108
109
      if (boxPartitioning)
	zoltan.Set_Param("LB_METHOD", "GRAPH");
110
    } else {
111
112
113
114
115
116
117
118
      zoltan.Set_Param("LB_APPROACH", "REPARTITION");
      zoltan.Set_Param("LB_METHOD", "GRAPH");
      zoltan.Set_Param("REFTREE_INITPATH", "CONNECTED");
      zoltan.Set_Param("REDUCE_DIMENSIONS", "1");
      zoltan.Set_Param("DEGENERATE_RATIO", "1.1");
      zoltan.Set_Param("RCB_RECTILINEAR_BLOCKS", "1");
      zoltan.Set_Param("AVERAGE_CUTS", "1");
      zoltan.Set_Param("RCB_RECOMPUTE_BOX", "1");
119
120
    }

121
    /*
122
     * Overwrite  default config of zoltan with Values
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
     * defined in init-file.
     */
    if (mode == INITIAL) {
      std::map<string,string>::const_iterator itr;
      for(itr=paramMapInitial.begin(); itr!= paramMapInitial.end(); ++itr)
	if( zoltan.Set_Param((*itr).first, (*itr).second) != ZOLTAN_OK){
	  ERROR_EXIT("Wrong parameter for Zoltan in Initfile (paramInitialMap): %s : %s \n", (*itr).first.c_str(), (*itr).second.c_str());
	}
    } else {
      std::map<string,string>::const_iterator itr;
      for(itr=paramMap.begin(); itr!= paramMap.end(); ++itr)
	if( zoltan.Set_Param((*itr).first, (*itr).second) != ZOLTAN_OK){
	  	  ERROR_EXIT("Wrong parameter for Zoltan in Initfile (paramMap): %s : %s \n", (*itr).first.c_str(), (*itr).second.c_str());
	}
    }



141
142
    zoltan.Set_Param("OBJ_WEIGHT_DIM", "1");

143
#ifndef NDEBUG
144
145
146
147
148
    zoltan.Set_Param("DEBUG_LEVEL", "1");
#else
    zoltan.Set_Param("DEBUG_LEVEL", "0");
#endif

Thomas Witkowski's avatar
Thomas Witkowski committed
149

150
    int err = zoltan.LB_Partition(changes, nGid, nLid,
151
152
153
154
155
156
157
158
159
160
				  nImportEls,
				  import_global_ids,
				  import_local_ids,
				  import_procs,
				  import_to_part,
				  nExportEls,
				  export_global_ids,
				  export_local_ids,
				  export_procs,
				  export_to_part);
161

162
163
164
    recvElements.clear();
    sendElements.clear();

165

166
    // Check if new partitioning would lead to a empty partition
167
    int createEmptyPartition;
168
169
170
171
172
173
174
175
176
177
178
179
180
    if (!boxPartitioning) {
      createEmptyPartition=
	(mesh->getMacroElements().size() == nExportEls && nImportEls == 0);
    }else{
      int realNrOfExpEl=0;
      for (int i = 0; i < nExportEls; i++) {
	int sendElIndex = export_global_ids[i];
	realNrOfExpEl+=boxSplitting[sendElIndex].size();
      }
      createEmptyPartition=
	(mesh->getMacroElements().size() == realNrOfExpEl && nImportEls == 0);
    }

181
182
183
184
185
    mpi::globalMax(createEmptyPartition);

    if (createEmptyPartition > 0)
      err = ZOLTAN_FATAL;

186
    // if a valid partition was produced, collect all elements to be send or received
187
188
    // in a list
    if (err == ZOLTAN_OK && changes != 0) {
189
190
191
      if (nImportEls > 0) {
	for (int i = 0; i < nImportEls; i++) {
	  int recvElIndex = import_global_ids[i];
192

Thomas Witkowski's avatar
Thomas Witkowski committed
193
194
195
196
197
198
199
200
201
202
203
	  if (!boxPartitioning) {
	    elementInRank[recvElIndex] = true;
	    recvElements[import_procs[i]].push_back(recvElIndex);
	  } else {
	    set<int>& box = boxSplitting[recvElIndex];

	    for (set<int>::iterator it = box.begin(); it != box.end(); ++it) {
	      elementInRank[*it] = true;
	      recvElements[import_procs[i]].push_back(*it);
	    }
	  }
204
205
	}
      }
206

207
208
209
      if (nExportEls > 0) {
	for (int i = 0; i < nExportEls; i++) {
	  int sendElIndex = export_global_ids[i];
210

Thomas Witkowski's avatar
Thomas Witkowski committed
211
212
213
214
215
216
217
218
219
220
221
	  if (!boxPartitioning) {
	    elementInRank[sendElIndex] = false;
	    sendElements[export_procs[i]].push_back(sendElIndex);
	  } else {
	    set<int>& box = boxSplitting[sendElIndex];

	    for (set<int>::iterator it = box.begin(); it != box.end(); ++it) {
	      elementInRank[*it] = false;
	      sendElements[export_procs[i]].push_back(*it);
	    }
	  }
222
	}
223
      }
224
225

      createPartitionMap();
226
227
    }

228
    zoltan.LB_Free_Part(&import_global_ids, &import_local_ids,
229
			&import_procs, &import_to_part);
230
231
    zoltan.LB_Free_Part(&export_global_ids, &export_local_ids,
			&export_procs, &export_to_part);
232
    elWeights = NULL;
233
234
235
236
237
238
239
240

    if (err != ZOLTAN_OK)
      return false;

    return true;
  }


241
  void ZoltanPartitioner::createPartitionMap()
242
243
244
245
246
247
  {
    FUNCNAME("ZoltanPartitioner::getPartitionMap()");

    int mpiSize = mpiComm->Get_size();

    vector<int> localElements;
248
    for (map<int, bool>::iterator it = elementInRank.begin();
249
250
251
	 it != elementInRank.end(); ++it)
      if (it->second)
	localElements.push_back(it->first);
252

253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
    int nLocalElements = localElements.size();
    vector<int> nPartitionElements(mpiSize);
    vector<int> elDist(mpiSize + 1);
    mpiComm->Allgather(&nLocalElements, 1, MPI_INT, &(elDist[1]), 1, MPI_INT);

    elDist[0] = 0;
    nPartitionElements[0] = elDist[1];

    for (int i = 2; i <= mpiSize; i++) {
      nPartitionElements[i - 1] = elDist[i];
      elDist[i] += elDist[i - 1];
    }

    int nOverallElements = elDist[mpiSize];

    TEST_EXIT_DBG(nOverallElements == static_cast<int>(elementInRank.size()))
      ("Number of elements differs: %d %d!\n", nOverallElements, elementInRank.size());

    vector<int> partitionElements(nOverallElements);

    // distribute partition elements
    mpiComm->Allgatherv(&(localElements[0]),
275
276
277
278
			nLocalElements,
			MPI_INT,
			&(partitionElements[0]),
			&(nPartitionElements[0]),
279
280
281
282
			&(elDist[0]),
			MPI_INT);

    // fill partitionMap
283
    partitionMap.clear();
284
285
286
287
288
289
    for (int i = 0; i < mpiSize; i++)
      for (int j = 0; j < nPartitionElements[i]; j++)
	partitionMap[partitionElements[elDist[i] + j]] = i;
  }


Thomas Witkowski's avatar
Thomas Witkowski committed
290
291
292

  // === Zoltan query function for "normal" element partitioning. ===

293

294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
  int ZoltanFunctions::getNumObj(void *data, int *ierr)
  {
    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;
    map<int, bool>& elInRank = zoltan->getElementInRank();

    int nObjects = 0;
    for (map<int, bool>::iterator it = elInRank.begin(); it != elInRank.end(); ++it)
      if (it->second)
	nObjects++;

    *ierr = ZOLTAN_OK;

    return nObjects;
  }


310
311
  void ZoltanFunctions::getObjectList(void *data,
				      int sizeGid,
312
				      int sizeLid,
313
				      ZOLTAN_ID_PTR globalId,
314
				      ZOLTAN_ID_PTR localId,
315
316
				      int wgt_dim,
				      float *obj_wgts,
317
318
319
320
321
322
323
324
325
326
				      int *ierr)
  {
    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;
    map<int, bool>& elInRank = zoltan->getElementInRank();
    int localCounter = 0;

    for (map<int, bool>::iterator it = elInRank.begin(); it != elInRank.end(); ++it) {
      if (it->second) {
	globalId[localCounter] = it->first;
	localId[localCounter] = localCounter;
327

328
329
330
331
332
333
	if (wgt_dim > 0) {
	  TEST_EXIT_DBG(wgt_dim == 1)("Should not happen!\n");

	  if (zoltan->elWeights) {
	    TEST_EXIT_DBG(zoltan->elWeights->count(it->first))
	      ("No element weight for element index %d\n", it->first);
334

335
336
337
338
339
340
	    obj_wgts[localCounter] = static_cast<float>((*zoltan->elWeights)[it->first]);
	  } else {
	    obj_wgts[localCounter] = 1.0;
	  }
	}

341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
	localCounter++;
      }
    }

    *ierr = ZOLTAN_OK;
  }


  int ZoltanFunctions::getNumGeom(void *data, int *ierr)
  {
    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;
    *ierr = ZOLTAN_OK;

    return zoltan->getMesh()->getGeo(WORLD);
  }


358
359
360
361
362
363
364
365
  void ZoltanFunctions::getGeomMulti(void *data,
				     int num_gid_entries,
				     int num_lid_entries,
				     int num_obj,
				     ZOLTAN_ID_PTR global_ids,
				     ZOLTAN_ID_PTR local_ids,
				     int num_dim,
				     double *geom_vec,
366
367
368
369
370
371
372
373
374
				     int *ierr)
  {
    FUNCNAME("ZoltanFunctions::getGeomMulti()");

    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;
    Mesh *mesh = zoltan->getMesh();

    TEST_EXIT_DBG(num_dim == mesh->getGeo(WORLD))("Should not happen!\n");

375
    map<int, WorldVector<double> > elIndexToCoords;
376
377
378
    DimVec<double> bary(mesh->getDim(), DEFAULT_VALUE, 1.0 / mesh->getGeo(VERTEX));
    WorldVector<double> coords;
    TraverseStack stack;
379
    ElInfo *elInfo =
380
381
382
383
384
385
386
387
388
389
390
391
392
      stack.traverseFirst(mesh, 0, Mesh::CALL_EL_LEVEL | Mesh::FILL_COORDS);
    while (elInfo) {
      elInfo->coordToWorld(bary, coords);
      elIndexToCoords[elInfo->getElement()->getIndex()] = coords;

      elInfo = stack.traverseNext(elInfo);
    }

    int c = 0;
    for (int i = 0; i < num_obj; i++) {
      int elIndex = global_ids[i];

      TEST_EXIT_DBG(elIndexToCoords.count(elIndex))("Should not happen!\n");
393

394
395
396
397
398
399
      for (int j = 0; j < num_dim; j++)
	geom_vec[c++] = elIndexToCoords[elIndex][j];
    }

    *ierr = ZOLTAN_OK;
  }
400
401


402
403
404
405
406
407
408
  void ZoltanFunctions::getNumEdgeMulti(void *data,
					int num_gid_entries,
					int num_lid_entries,
					int num_obj,
					ZOLTAN_ID_PTR global_ids,
					ZOLTAN_ID_PTR local_ids,
					int *num_edges,
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
					int *ierr)
  {
    FUNCNAME("ZoltanFunctions::getNumEdgeMulti()");

    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;

    for (int i = 0; i < num_obj; i++) {
      TEST_EXIT_DBG(zoltan->elNeighbours.count(global_ids[i]))("Should not happen!\n");

      num_edges[i] = zoltan->elNeighbours[global_ids[i]].size();
    }

    *ierr = ZOLTAN_OK;
  }

424
425
426
427
428
429
430
431
432
433
434
435

  void ZoltanFunctions::getEdgeListMulti(void *data,
					 int num_gid_entries,
					 int num_lid_entries,
					 int num_obj,
					 ZOLTAN_ID_PTR global_ids,
					 ZOLTAN_ID_PTR local_ids,
					 int *num_edges,
					 ZOLTAN_ID_PTR nbor_global_id,
					 int *nbor_procs,
					 int wgt_dim,
					 float *ewgts,
436
437
438
439
440
441
442
443
					 int *ierr)
  {
    FUNCNAME("ZoltanFunctions::getEdgeListMulti()");

    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;

    int c = 0;
    for (int i = 0; i < num_obj; i++) {
444
      TEST_EXIT_DBG(static_cast<int>(zoltan->elNeighbours[global_ids[i]].size()) ==
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
		    num_edges[i])
	("Wrong sizes for global el index %d: %d %d\n",
	 global_ids[i],
	 zoltan->elNeighbours[global_ids[i]].size(),
	 num_edges[i]);

      for (int j = 0; j < num_edges[i]; j++) {
	int neighIndex = zoltan->elNeighbours[global_ids[i]][j];
	nbor_global_id[c] = neighIndex;
	nbor_procs[c] = zoltan->partitionMap[neighIndex];
	c++;
      }
    }


    TEST_EXIT_DBG(wgt_dim == 0)("Edge weights are not handled yet!\n");

    *ierr = ZOLTAN_OK;
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490


  // === Zoltan query functions for box partitioning. ===

  int ZoltanFunctions::box_getNumObj(void *data, int *ierr)
  {
    FUNCNAME("ZoltanFunctions::box_getNumObj()");

    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;
    map<int, bool>& elInRank = zoltan->getElementInRank();

    int nObjects = 0;
    for (map<int, bool>::iterator it = elInRank.begin(); it != elInRank.end(); ++it)
      if (it->second)
	nObjects++;

    TEST_EXIT_DBG(nObjects % 6 == 0)("Should not happen!\n");

    nObjects = nObjects / 6;

    *ierr = ZOLTAN_OK;

    return nObjects;
  }


491
492
  void ZoltanFunctions::box_getObjectList(void *data,
					  int sizeGid,
Thomas Witkowski's avatar
Thomas Witkowski committed
493
					  int sizeLid,
494
					  ZOLTAN_ID_PTR globalId,
Thomas Witkowski's avatar
Thomas Witkowski committed
495
					  ZOLTAN_ID_PTR localId,
496
497
					  int wgt_dim,
					  float *obj_wgts,
Thomas Witkowski's avatar
Thomas Witkowski committed
498
499
500
501
502
503
504
505
506
507
508
					  int *ierr)
  {
    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;
    map<int, bool>& elInRank = zoltan->getElementInRank();
    set<int> boxes;
    map<int, double> boxWeight;

    for (map<int, bool>::iterator it = elInRank.begin(); it != elInRank.end(); ++it)
      if (it->second) {
	int boxId = zoltan->elInBox[it->first];
	boxes.insert(boxId);
509

Thomas Witkowski's avatar
Thomas Witkowski committed
510
511
512
	if (zoltan->elWeights) {
	  TEST_EXIT_DBG(zoltan->elWeights->count(it->first))
	    ("No element weight for element index %d\n", it->first);
513

Thomas Witkowski's avatar
Thomas Witkowski committed
514
515
516
517
518
519
520
521
	  boxWeight[boxId] += (*zoltan->elWeights)[it->first];
	}
      }

    int localCounter = 0;
    for (set<int>::iterator it = boxes.begin(); it != boxes.end(); ++it) {
      globalId[localCounter] = *it;
      localId[localCounter] = localCounter;
522

Thomas Witkowski's avatar
Thomas Witkowski committed
523
524
      if (wgt_dim > 0) {
	TEST_EXIT_DBG(wgt_dim == 1)("Should not happen!\n");
525

Thomas Witkowski's avatar
Thomas Witkowski committed
526
527
528
	if (zoltan->elWeights)
	  obj_wgts[localCounter] = static_cast<float>(boxWeight[*it]);
	else
529
	  obj_wgts[localCounter] = 1.0;
Thomas Witkowski's avatar
Thomas Witkowski committed
530
      }
531

Thomas Witkowski's avatar
Thomas Witkowski committed
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
      localCounter++;
    }

    *ierr = ZOLTAN_OK;
  }


  int ZoltanFunctions::box_getNumGeom(void *data, int *ierr)
  {
    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;
    *ierr = ZOLTAN_OK;

    return zoltan->getMesh()->getGeo(WORLD);
  }


548
549
550
551
552
553
554
555
  void ZoltanFunctions::box_getGeomMulti(void *data,
					 int num_gid_entries,
					 int num_lid_entries,
					 int num_obj,
					 ZOLTAN_ID_PTR global_ids,
					 ZOLTAN_ID_PTR local_ids,
					 int num_dim,
					 double *geom_vec,
Thomas Witkowski's avatar
Thomas Witkowski committed
556
557
558
559
560
561
562
563
					 int *ierr)
  {
    FUNCNAME("ZoltanFunctions::box_getGeomMulti()");

    ERROR_EXIT("Not yet supported!\n");
  }


564
565
566
567
568
569
570
  void ZoltanFunctions::box_getNumEdgeMulti(void *data,
					    int num_gid_entries,
					    int num_lid_entries,
					    int num_obj,
					    ZOLTAN_ID_PTR global_ids,
					    ZOLTAN_ID_PTR local_ids,
					    int *num_edges,
Thomas Witkowski's avatar
Thomas Witkowski committed
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
					    int *ierr)
  {
    FUNCNAME("ZoltanFunctions::box_getNumEdgeMulti()");

    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;

    for (int i = 0; i < num_obj; i++) {
      TEST_EXIT_DBG(zoltan->boxNeighbours.count(global_ids[i]))("Should not happen!\n");

      num_edges[i] = zoltan->boxNeighbours[global_ids[i]].size();
    }

    *ierr = ZOLTAN_OK;
  }


587
588
589
590
591
592
593
594
595
596
597
  void ZoltanFunctions::box_getEdgeListMulti(void *data,
					     int num_gid_entries,
					     int num_lid_entries,
					     int num_obj,
					     ZOLTAN_ID_PTR global_ids,
					     ZOLTAN_ID_PTR local_ids,
					     int *num_edges,
					     ZOLTAN_ID_PTR nbor_global_id,
					     int *nbor_procs,
					     int wgt_dim,
					     float *ewgts,
Thomas Witkowski's avatar
Thomas Witkowski committed
598
599
600
601
602
603
604
605
					     int *ierr)
  {
    FUNCNAME("ZoltanFunctions::box_getEdgeListMulti()");

    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;

    int c = 0;
    for (int i = 0; i < num_obj; i++) {
606
      TEST_EXIT_DBG(static_cast<int>(zoltan->boxNeighbours[global_ids[i]].size()) ==
Thomas Witkowski's avatar
Thomas Witkowski committed
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
		    num_edges[i])
	("Wrong sizes for global el index %d: %d %d\n",
	 global_ids[i],
	 zoltan->boxNeighbours[global_ids[i]].size(),
	 num_edges[i]);

      set<int> &neigh = zoltan->boxNeighbours[global_ids[i]];
      for (set<int>::iterator it = neigh.begin(); it != neigh.end(); ++it) {
	nbor_global_id[c] = *it;
	nbor_procs[c] = zoltan->partitionMap[*(zoltan->boxSplitting[*it].begin())];
	c++;
      }
    }

    TEST_EXIT_DBG(wgt_dim == 0)("Edge weights are not handled yet!\n");

    *ierr = ZOLTAN_OK;
  }


627
} }
628
629

#endif