~ubuntu-branches/ubuntu/trusty/scotch/trusty

« back to all changes in this revision

Viewing changes to src/libscotch/hdgraph_gather.c

  • Committer: Bazaar Package Importer
  • Author(s): Christophe Prud'homme
  • Date: 2008-01-25 09:13:53 UTC
  • Revision ID: james.westby@ubuntu.com-20080125091353-zghdao60dfsyc2bt
Tags: upstream-5.0.1.dfsg
ImportĀ upstreamĀ versionĀ 5.0.1.dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2007 ENSEIRB, INRIA & CNRS
 
2
**
 
3
** This file is part of the Scotch software package for static mapping,
 
4
** graph partitioning and sparse matrix ordering.
 
5
**
 
6
** This software is governed by the CeCILL-C license under French law
 
7
** and abiding by the rules of distribution of free software. You can
 
8
** use, modify and/or redistribute the software under the terms of the
 
9
** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
 
10
** URL: "http://www.cecill.info".
 
11
** 
 
12
** As a counterpart to the access to the source code and rights to copy,
 
13
** modify and redistribute granted by the license, users are provided
 
14
** only with a limited warranty and the software's author, the holder of
 
15
** the economic rights, and the successive licensors have only limited
 
16
** liability.
 
17
** 
 
18
** In this respect, the user's attention is drawn to the risks associated
 
19
** with loading, using, modifying and/or developing or reproducing the
 
20
** software by the user in light of its specific status of free software,
 
21
** that may mean that it is complicated to manipulate, and that also
 
22
** therefore means that it is reserved for developers and experienced
 
23
** professionals having in-depth computer knowledge. Users are therefore
 
24
** encouraged to load and test the software's suitability as regards
 
25
** their requirements in conditions enabling the security of their
 
26
** systems and/or data to be ensured and, more generally, to use and
 
27
** operate it in the same conditions as regards security.
 
28
** 
 
29
** The fact that you are presently reading this means that you have had
 
30
** knowledge of the CeCILL-C license and that you accept its terms.
 
31
*/
 
32
/************************************************************/
 
33
/**                                                        **/
 
34
/**   NAME       : hdgraph_gather.c                        **/
 
35
/**                                                        **/
 
36
/**   AUTHORS    : Francois PELLEGRINI                     **/
 
37
/**                                                        **/
 
38
/**   FUNCTION   : This module contains the routine which  **/
 
39
/**                builds a centralized halo graph by      **/
 
40
/**                gathering the pieces of a distributed   **/
 
41
/**                halo graph.                             **/
 
42
/**                                                        **/
 
43
/**   DATES      : # Version 5.0  : from : 19 apr 2006     **/
 
44
/**                                 to   : 10 sep 2007     **/
 
45
/**                                                        **/
 
46
/************************************************************/
 
47
 
 
48
/*
 
49
** The defines and includes.
 
50
*/
 
51
 
 
52
#define HDGRAPH_GATHER
 
53
 
 
54
#include "module.h"
 
55
#include "common.h"
 
56
#include "graph.h"
 
57
#include "hgraph.h"
 
58
#include "dgraph.h"
 
59
#include "hdgraph.h"
 
60
 
 
61
/******************************/
 
62
/*                            */
 
63
/* These routines handle halo */
 
64
/* distributed source graphs. */
 
65
/*                            */
 
66
/******************************/
 
67
 
 
68
/* This function gathers the pieces of
 
69
** a distributed halo graph to build a
 
70
** centralized halo graph.
 
71
** There is no gathered vnumtab array if
 
72
** the original graph did not have one, as
 
73
** vertices are gathered in global order, or
 
74
** else the original vnumloctab is gathered.
 
75
** It returns:
 
76
** - 0   : if graph data are consistent.
 
77
** - !0  : on error.
 
78
*/
 
79
 
 
80
int
 
81
hdgraphGather (
 
82
Hdgraph * restrict const    dgrfptr,              /* Distributed halo graph */
 
83
Hgraph * restrict const     cgrfptr)              /* Centralized halo graph */
 
84
{
 
85
  Gnum               vertlocnum;
 
86
  Gnum               vertlocadj;                  /* Local vertex array adjust                  */
 
87
  Gnum               vhallocnnd;
 
88
  int                vhallocnbr;                  /* Local copy for sending as a MPI_INT        */
 
89
  Gnum * restrict    verthaltax;
 
90
  Gnum * restrict    edgehaltax;
 
91
  Gnum               edgehalnum;
 
92
  int                ehallocnbr;                  /* Local copy for sending as a MPI_INT        */
 
93
  int                rootnum;                     /* Index of root process                      */
 
94
  Gnum               reduloctab[4];               /* Arrays for reductions                      */
 
95
  Gnum               reduglbtab[4];
 
96
  int * restrict     recvcnttab;                  /* Arrays for parametrizing gather operations */
 
97
  int * restrict     recvdsptab;
 
98
  int                cheklocval;
 
99
  int                chekglbval;
 
100
  Gnum               degrmax;
 
101
 
 
102
  if (cgrfptr != NULL) {                          /* If centralized graph provided */
 
103
    reduloctab[0] = 1;                            /* This process is the root      */
 
104
    reduloctab[1] = (Gnum) dgrfptr->s.proclocnum; /* Get its rank                  */
 
105
  }
 
106
  else {
 
107
    reduloctab[0] =                               /* This process is not the root */
 
108
    reduloctab[1] = 0;
 
109
  }
 
110
  reduloctab[2] = dgrfptr->vhallocnbr;
 
111
  reduloctab[3] = dgrfptr->ehallocnbr;
 
112
  if (MPI_Allreduce (reduloctab, reduglbtab, 4, GNUM_MPI, MPI_SUM, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
113
    errorPrint ("hdgraphGather: communication error (1)");
 
114
    return     (1);
 
115
  }
 
116
  if (reduglbtab[0] != 1) {
 
117
    errorPrint ("hdgraphGather: should have only one root");
 
118
    return     (1);
 
119
  }
 
120
  rootnum = (int) reduglbtab[1];                  /* Get rank of root process                           */
 
121
  degrmax = dgrfptr->s.degrglbmax;                /* Distributed degree does not account for halo edges */
 
122
 
 
123
  cheklocval = 0;
 
124
  if (cgrfptr != NULL) {                          /* If process is root */
 
125
    Gnum               vnohnbr;
 
126
    Gnum               vertnbr;
 
127
    Gnum               velonbr;
 
128
    Gnum               vnumnbr;
 
129
    Gnum * restrict    velotax;
 
130
    Gnum * restrict    vnumtax;
 
131
    Gnum               edgenbr;
 
132
 
 
133
    vnohnbr = dgrfptr->s.vertglbnbr;
 
134
    vertnbr = vnohnbr + reduglbtab[2];
 
135
    velonbr = (dgrfptr->s.veloloctax != NULL) ? vertnbr : 0;
 
136
    vnumnbr = (dgrfptr->s.vnumloctax != NULL) ? vnohnbr : 0; /* Vertex numbers only serve for non-halo vertices */
 
137
    edgenbr = dgrfptr->s.edgeglbnbr + 2 * reduglbtab[3]; /* Twice since halo vertices will be created for real  */
 
138
 
 
139
    cgrfptr->s.flagval = GRAPHFREEEDGE | GRAPHEDGEGROUP | GRAPHFREEVERT | GRAPHVERTGROUP; /* In case of premature freeing on error */
 
140
    recvcnttab = NULL;
 
141
    if (memAllocGroup ((void **) (void *)
 
142
                       &cgrfptr->s.verttax, (size_t) ((vertnbr + 1) * sizeof (Gnum)), /* Compact vertex array */
 
143
                       &velotax,            (size_t) (velonbr       * sizeof (Gnum)),
 
144
                       &vnumtax,            (size_t) (vnumnbr       * sizeof (Gnum)),
 
145
                       &cgrfptr->vnhdtax,   (size_t) (vnohnbr       * sizeof (Gnum)), NULL) == NULL) {
 
146
      errorPrint ("hdgraphGather: out of memory (1)");
 
147
      cheklocval = 1;
 
148
    }
 
149
    else if (cgrfptr->s.verttax -= dgrfptr->s.baseval,
 
150
             cgrfptr->s.velotax  = (dgrfptr->s.veloloctax != NULL) ? velotax - dgrfptr->s.baseval : NULL,
 
151
             cgrfptr->s.vnumtax  = (dgrfptr->s.vnumloctax != NULL) ? vnumtax - dgrfptr->s.baseval : NULL,
 
152
             cgrfptr->vnhdtax   -= dgrfptr->s.baseval,
 
153
             ((cgrfptr->s.edgetax = (Gnum *) memAlloc (edgenbr * sizeof (Gnum))) == NULL)) {
 
154
      errorPrint ("hdgraphGather: out of memory (2)");
 
155
      cheklocval = 1;
 
156
    }
 
157
    else if (cgrfptr->s.edgetax -= dgrfptr->s.baseval,
 
158
             memAllocGroup ((void **) (void *)
 
159
                            &recvcnttab, (size_t) (dgrfptr->s.procglbnbr * sizeof (int)),
 
160
                            &recvdsptab, (size_t) (dgrfptr->s.procglbnbr * sizeof (int)), NULL) == NULL) {
 
161
      errorPrint ("hdgraphGather: out of memory (3)");
 
162
      cheklocval = 1;
 
163
    }
 
164
    else {
 
165
      cgrfptr->s.baseval    = dgrfptr->s.baseval;
 
166
      cgrfptr->s.vertnbr    = vertnbr;
 
167
      cgrfptr->s.vertnnd    = vertnbr + dgrfptr->s.baseval;
 
168
      cgrfptr->s.vendtax    = cgrfptr->s.verttax + 1; /* Compact edge array                                   */
 
169
      cgrfptr->s.velosum    = dgrfptr->s.veloglbsum + reduglbtab[2]; /* Halo vertices have unity vertex loads */
 
170
      cgrfptr->s.vlbltax    = NULL;
 
171
      cgrfptr->s.edgenbr    = edgenbr;
 
172
      cgrfptr->s.edlotax    = NULL;
 
173
      cgrfptr->s.edlosum    = edgenbr;
 
174
      cgrfptr->s.proccomm   = MPI_COMM_NULL;      /* Not a multi-sequential gather: no communication possible */
 
175
      cgrfptr->s.procglbnbr =
 
176
      cgrfptr->s.proclocnum = 0;
 
177
      cgrfptr->vnohnbr      = vnohnbr;
 
178
      cgrfptr->vnohnnd      = vnohnbr + dgrfptr->s.baseval;
 
179
      cgrfptr->vnlosum      = dgrfptr->s.veloglbsum;
 
180
      cgrfptr->enohnbr      =
 
181
      cgrfptr->enohsum      = dgrfptr->s.edgeglbnbr;
 
182
      cgrfptr->levlnum      = dgrfptr->levlnum;
 
183
    }
 
184
  }
 
185
  if ((cheklocval == 0) &&
 
186
      (memAllocGroup ((void **) (void *)
 
187
                      &verthaltax, (size_t) (dgrfptr->vhallocnbr * sizeof (Gnum)),
 
188
                      &edgehaltax, (size_t) (dgrfptr->ehallocnbr * sizeof (Gnum)), NULL) == NULL)) {
 
189
    errorPrint ("hdgraphGather: out of memory (4)");
 
190
    cheklocval = 1;
 
191
  }
 
192
  else {
 
193
    verthaltax -= dgrfptr->s.baseval;
 
194
    edgehaltax -= dgrfptr->s.baseval;
 
195
  }
 
196
  if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_SUM, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
197
    errorPrint ("hdgraphGather: communication error (2)");
 
198
    return     (1);
 
199
  }
 
200
  if (chekglbval != 0) {
 
201
    if (verthaltax != NULL)
 
202
      memFree (verthaltax + dgrfptr->s.baseval);
 
203
    if (cgrfptr != NULL) {                        /* If data were previously allocated */
 
204
      if (recvcnttab != NULL)
 
205
        memFree (recvcnttab);
 
206
      hgraphExit (cgrfptr);
 
207
    }
 
208
    return (1);
 
209
  }
 
210
 
 
211
  if (dgrfptr->vhndloctax == dgrfptr->s.vertloctax + 1) { /* If distributed halo graph is compact */
 
212
    Gnum               procglbnum;
 
213
    Gnum               edgenum;
 
214
 
 
215
    if (cgrfptr != NULL) {
 
216
      Gnum               vertnum;
 
217
 
 
218
      cgrfptr->s.verttax[dgrfptr->s.baseval] = dgrfptr->s.baseval;
 
219
      if (MPI_Gatherv (dgrfptr->s.vertloctax + 1 + dgrfptr->s.baseval, /* Do not send first index, it is always equal to baseval */
 
220
                       (int) dgrfptr->s.vertlocnbr, GNUM_MPI,
 
221
                       cgrfptr->s.verttax + 1,      /* First index will always be equal to baseval too, and procdsptab holds based values */
 
222
                       dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
223
        errorPrint ("hdgraphGather: communication error (3)");
 
224
        return     (1);
 
225
      }
 
226
      if (MPI_Gatherv (dgrfptr->s.vendloctax + dgrfptr->s.baseval,
 
227
                       (int) dgrfptr->s.vertlocnbr, GNUM_MPI, cgrfptr->vnhdtax, /* procdsptab holds based values */
 
228
                       dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
229
        errorPrint ("hdgraphGather: communication error (4)");
 
230
        return     (1);
 
231
      }
 
232
 
 
233
      for (procglbnum = 1, vertnum = dgrfptr->s.procdsptab[1] + 1; /* Adjust index sub-arrays for all processors except the first one */
 
234
           procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) {
 
235
        Gnum               vertnnd;
 
236
        Gnum               edgeadj;
 
237
 
 
238
        for (vertnnd = dgrfptr->s.procdsptab[procglbnum + 1] + 1,
 
239
             edgeadj = cgrfptr->s.verttax[vertnum - 1] - dgrfptr->s.baseval;
 
240
             vertnum < vertnnd; vertnum ++) {
 
241
          cgrfptr->s.verttax[vertnum]   += edgeadj;
 
242
          cgrfptr->vnhdtax[vertnum - 1] += edgeadj;
 
243
        }
 
244
      }
 
245
 
 
246
      for (procglbnum = 0, edgenum = dgrfptr->s.baseval; /* Build arrays for MPI_Gatherv on edge arrays */
 
247
           procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) {
 
248
        recvcnttab[procglbnum] = cgrfptr->s.verttax[dgrfptr->s.procdsptab[procglbnum + 1]] -
 
249
                                 cgrfptr->s.verttax[dgrfptr->s.procdsptab[procglbnum]]; /* verttax used twice since centralized graph is compact */
 
250
        recvdsptab[procglbnum] = edgenum;
 
251
        edgenum += recvcnttab[procglbnum];
 
252
      }
 
253
      if (MPI_Gatherv (dgrfptr->s.edgeloctax + dgrfptr->s.baseval, /* Gather edge arrays with global vertex indices */
 
254
                       (int) (dgrfptr->s.edgelocnbr + dgrfptr->ehallocnbr), GNUM_MPI, cgrfptr->s.edgetax,
 
255
                       recvcnttab, recvdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
256
        errorPrint ("hdgraphGather: communication error (5)");
 
257
        return     (1);
 
258
      }
 
259
    }
 
260
    else {
 
261
      if (MPI_Gatherv (dgrfptr->s.vertloctax + 1 + dgrfptr->s.baseval, /* Do not send first index, it is always equal to baseval */
 
262
                       (int) dgrfptr->s.vertlocnbr, GNUM_MPI, NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
263
        errorPrint ("hdgraphGather: communication error (6)");
 
264
        return     (1);
 
265
      }
 
266
      if (MPI_Gatherv (dgrfptr->s.vendloctax + dgrfptr->s.baseval,
 
267
                       (int) dgrfptr->s.vertlocnbr, GNUM_MPI, NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
268
        errorPrint ("hdgraphGather: communication error (7)");
 
269
        return     (1);
 
270
      }
 
271
      if (MPI_Gatherv (dgrfptr->s.edgeloctax + dgrfptr->s.baseval, /* Gather edge arrays with global vertex indices */
 
272
                       (int) (dgrfptr->s.edgelocnbr + dgrfptr->ehallocnbr), GNUM_MPI,
 
273
                       NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
274
        errorPrint ("hdgraphGather: communication error (8)");
 
275
        return     (1);
 
276
      }
 
277
    }
 
278
  }
 
279
  else {
 
280
    errorPrint ("hdgraphGather: Not implemented"); /* TODO, but not really necessary as all Hdgraph structures created by Scotch itself are compact */
 
281
    return     (1);
 
282
  }
 
283
 
 
284
  memSet (verthaltax + dgrfptr->s.baseval, 0, dgrfptr->vhallocnbr * sizeof (Gnum)); /* Initialize halo end vertex count array */
 
285
  for (vertlocnum = dgrfptr->s.baseval; vertlocnum < dgrfptr->s.vertlocnnd; vertlocnum ++) {
 
286
    Gnum               edgelocnum;
 
287
 
 
288
    for (edgelocnum = dgrfptr->s.vendloctax[vertlocnum]; edgelocnum < dgrfptr->vhndloctax[vertlocnum]; edgelocnum ++)
 
289
      verthaltax[dgrfptr->s.edgeloctax[edgelocnum]] ++; /* One more edge to this halo vertex */
 
290
  }
 
291
  vhallocnbr = (int) dgrfptr->vhallocnbr;
 
292
  if (MPI_Gather (&vhallocnbr, 1, MPI_INT, recvcnttab, 1, MPI_INT, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
293
    errorPrint ("hdgraphGather: communication error (9)");
 
294
    return     (1);
 
295
  }
 
296
  if (cgrfptr != NULL) {                          /* Build gather parameter array to receive halo edge counts */
 
297
    Gnum               procglbnum;
 
298
    Gnum               vertnum;
 
299
 
 
300
    for (procglbnum = 0, vertnum = 0; procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) { /* Displacements start from zero because adjusted later */
 
301
      recvdsptab[procglbnum] = vertnum;
 
302
      vertnum += recvcnttab[procglbnum];
 
303
    }
 
304
    if (MPI_Gatherv (verthaltax + dgrfptr->s.baseval, (int) dgrfptr->vhallocnbr, GNUM_MPI, /* Gather count arrays of halo vertices */
 
305
                     cgrfptr->s.verttax + cgrfptr->vnohnnd + 1, recvcnttab, recvdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
306
      errorPrint ("hdgraphGather: communication error (10)");
 
307
      return     (1);
 
308
    }
 
309
 
 
310
    for (procglbnum = 0, vertnum = dgrfptr->s.baseval; /* Adjust end vertex indices for halo edges */
 
311
         procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) {
 
312
      Gnum               vertnnd;
 
313
      Gnum               vertadj;
 
314
 
 
315
      for (vertnnd = dgrfptr->s.procdsptab[procglbnum + 1], vertadj = cgrfptr->vnohnbr + recvdsptab[procglbnum];
 
316
           vertnum < vertnnd; vertnum ++) {
 
317
        Gnum               edgenum;
 
318
 
 
319
        if (degrmax < (cgrfptr->s.vendtax[vertnum] - cgrfptr->s.verttax[vertnum])) /* Account for halo edges in maximum degree */
 
320
          degrmax = (cgrfptr->s.vendtax[vertnum] - cgrfptr->s.verttax[vertnum]);
 
321
        for (edgenum = cgrfptr->vnhdtax[vertnum]; edgenum < cgrfptr->s.vendtax[vertnum]; edgenum ++)
 
322
          cgrfptr->s.edgetax[edgenum] += vertadj;
 
323
      }
 
324
    }
 
325
  }
 
326
  else {
 
327
    if (MPI_Gatherv (verthaltax + dgrfptr->s.baseval, (int) dgrfptr->vhallocnbr, GNUM_MPI, /* Gather count arrays of halo vertices */
 
328
                     NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
329
      errorPrint ("hdgraphGather: communication error (11)");
 
330
      return     (1);
 
331
    }
 
332
  }
 
333
  for (vertlocnum = edgehalnum = dgrfptr->s.baseval, vhallocnnd = dgrfptr->vhallocnbr + dgrfptr->s.baseval;
 
334
       vertlocnum < vhallocnnd; vertlocnum ++) { /* Prepare index array for edge collection */
 
335
    Gnum               degrlocval;
 
336
 
 
337
    degrlocval = verthaltax[vertlocnum];
 
338
    verthaltax[vertlocnum] = edgehalnum;
 
339
    edgehalnum += degrlocval;
 
340
  }
 
341
  vertlocadj = dgrfptr->s.procdsptab[dgrfptr->s.proclocnum] - dgrfptr->s.baseval;
 
342
  for (vertlocnum = dgrfptr->s.baseval; vertlocnum < dgrfptr->s.vertlocnnd; vertlocnum ++) { /* Collect halo edge ends */
 
343
    Gnum               edgelocnum;
 
344
 
 
345
    for (edgelocnum = dgrfptr->s.vendloctax[vertlocnum]; edgelocnum < dgrfptr->vhndloctax[vertlocnum]; edgelocnum ++)
 
346
      edgehaltax[verthaltax[dgrfptr->s.edgeloctax[edgelocnum]] ++] = vertlocnum + vertlocadj;
 
347
  }
 
348
  ehallocnbr = (int) dgrfptr->ehallocnbr;
 
349
  if (MPI_Gather (&ehallocnbr, 1, MPI_INT, recvcnttab, 1, MPI_INT, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { /* Gather halo edge counts */
 
350
    errorPrint ("hdgraphGather: communication error (12)");
 
351
    return     (1);
 
352
  }
 
353
  if (cgrfptr != NULL) {                          /* Compute receive arrays for edge sub-arrays of halo vertices */
 
354
    Gnum               procglbnum;
 
355
    Gnum               edgeadj;
 
356
 
 
357
    for (procglbnum = 0, edgeadj = 0; procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) {
 
358
      recvdsptab[procglbnum] = edgeadj;
 
359
      edgeadj += recvcnttab[procglbnum];
 
360
    }
 
361
    if (MPI_Gatherv (edgehaltax + dgrfptr->s.baseval, (int) dgrfptr->ehallocnbr, GNUM_MPI, /* Gather edge arrays of halo vertices */
 
362
                     cgrfptr->s.edgetax + cgrfptr->enohnbr + reduglbtab[3] + dgrfptr->s.baseval, recvcnttab, recvdsptab, GNUM_MPI,
 
363
                     rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
364
      errorPrint ("hdgraphGather: communication error (13)");
 
365
      return     (1);
 
366
    }
 
367
  }
 
368
  else {
 
369
    if (MPI_Gatherv (edgehaltax + dgrfptr->s.baseval, (int) dgrfptr->ehallocnbr, GNUM_MPI, /* Gather edge arrays of halo vertices */
 
370
                     NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
371
      errorPrint ("hdgraphGather: communication error (14)");
 
372
      return     (1);
 
373
    }
 
374
  }
 
375
 
 
376
  memFree (verthaltax + dgrfptr->s.baseval);      /* Free group leader */
 
377
 
 
378
  if (cgrfptr != NULL) {                          /* Finalize vertex and edge arrays of centralized graph */
 
379
    Gnum               vertnum;
 
380
    Gnum               edgeadj;
 
381
 
 
382
    if (dgrfptr->s.veloloctax != NULL) {            /* Get vertex loads if any */
 
383
      if (MPI_Gatherv (dgrfptr->s.veloloctax + dgrfptr->s.baseval, (int) dgrfptr->s.vertlocnbr, GNUM_MPI,
 
384
                       cgrfptr->s.velotax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GNUM_MPI,
 
385
                       rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
386
        errorPrint ("hdgraphGather: communication error (15)");
 
387
        return     (1);
 
388
      }
 
389
 
 
390
      for (vertnum = cgrfptr->vnohnnd; vertnum < cgrfptr->s.vertnnd; vertnum ++) /* complete filling of vertex load array */
 
391
        cgrfptr->s.velotax[vertnum] = 1;
 
392
    }
 
393
    if (dgrfptr->s.vnumloctax != NULL) {            /* Get vertex numbers if any */
 
394
      if (MPI_Gatherv (dgrfptr->s.vnumloctax + dgrfptr->s.baseval, (int) dgrfptr->s.vertlocnbr, GNUM_MPI,
 
395
                       cgrfptr->s.vnumtax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GNUM_MPI,
 
396
                       rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
397
        errorPrint ("hdgraphGather: communication error (16)");
 
398
        return     (1);
 
399
      }
 
400
    }
 
401
 
 
402
    memFree (recvcnttab);                         /* Free group leader */
 
403
 
 
404
    for (vertnum = cgrfptr->vnohnnd + 1, edgeadj = cgrfptr->s.verttax[cgrfptr->vnohnnd]; /* Adjust vertex array for halo vertices */
 
405
         vertnum <= cgrfptr->s.vertnnd; vertnum ++) {
 
406
      Gnum               degrval;
 
407
 
 
408
      degrval = cgrfptr->s.verttax[vertnum];
 
409
      if (degrmax < degrval)                      /* Account for halo edges in maximum degree */
 
410
        degrmax = degrval;
 
411
      edgeadj += degrval;
 
412
      cgrfptr->s.verttax[vertnum] = edgeadj;
 
413
    }
 
414
    cgrfptr->s.degrmax = degrmax;
 
415
  }
 
416
  else {
 
417
    if (dgrfptr->s.veloloctax != NULL) {          /* Get vertex loads if any */
 
418
      if (MPI_Gatherv (dgrfptr->s.veloloctax + dgrfptr->s.baseval, (int) dgrfptr->s.vertlocnbr, GNUM_MPI,
 
419
                       NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
420
        errorPrint ("hdgraphGather: communication error (17)");
 
421
        return     (1);
 
422
      }
 
423
    }
 
424
    if (dgrfptr->s.vnumloctax != NULL) {          /* Get vertex numbers if any */
 
425
      if (MPI_Gatherv (dgrfptr->s.vnumloctax + dgrfptr->s.baseval, (int) dgrfptr->s.vertlocnbr, GNUM_MPI,
 
426
                       NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
427
        errorPrint ("hdgraphGather: communication error (18)");
 
428
        return     (1);
 
429
      }
 
430
    }
 
431
  }
 
432
 
 
433
#ifdef SCOTCH_DEBUG_HDGRAPH2
 
434
  cheklocval = (cgrfptr != NULL) ? hgraphCheck (cgrfptr) : 0;
 
435
  if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->s.proccomm) != MPI_SUCCESS) {
 
436
    errorPrint ("hdgraphGather: communication error (19)");
 
437
    return     (1);
 
438
  }
 
439
  if (chekglbval != 0) {
 
440
    errorPrint ("hdgraphGather: internal error");
 
441
    if (cgrfptr != NULL)
 
442
      hgraphExit (cgrfptr);
 
443
    return (1);
 
444
  }
 
445
#endif /* SCOTCH_DEBUG_HDGRAPH2 */
 
446
 
 
447
  return (0);
 
448
}