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