1 /* Copyright 2007,2010 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       : dorder_io_tree.c                        **/
35 /**                                                        **/
36 /**   AUTHOR     : Francois PELLEGRINI                     **/
37 /**                                                        **/
38 /**   FUNCTION   : This module handles distributed         **/
39 /**                orderings.                              **/
40 /**                                                        **/
41 /**   DATES      : # Version 5.0  : from : 26 jul 2007     **/
42 /**                                 to     26 jul 2007     **/
43 /**                # Version 5.1  : from : 30 jul 2010     **/
44 /**                                 to     30 jul 2010     **/
45 /**                                                        **/
46 /************************************************************/
47 
48 /*
49 **  The defines and includes.
50 */
51 
52 #define DORDER
53 
54 #include "module.h"
55 #include "common.h"
56 #include "comm.h"
57 #include "dgraph.h"
58 #include "order.h"
59 #include "dorder.h"
60 
61 /************************************/
62 /*                                  */
63 /* These routines handle orderings. */
64 /*                                  */
65 /************************************/
66 
67 /* This routine saves a distributed ordering.
68 ** It returns:
69 ** - 0   : on success.
70 ** - !0  : on error.
71 */
72 
73 int
dorderSaveTree2(const Dorder * restrict const ordeptr,const Dgraph * restrict const grafptr,FILE * restrict const stream,int (* funcptr)(const Order * const,const Gnum * const,FILE * const))74 dorderSaveTree2 (
75 const Dorder * restrict const ordeptr,
76 const Dgraph * restrict const grafptr,
77 FILE * restrict const         stream,
78 int                        (* funcptr) (const Order * const, const Gnum * const, FILE * const))
79 {
80   Order                 corddat;                  /* Centralized ordering for tree structure */
81   Gnum * restrict       vlbltab;
82   int                   procglbnbr;
83   int                   protnum;
84   int                   reduloctab[3];
85   int                   reduglbtab[3];
86   int                   cheklocval;
87   int                   chekglbval;
88 
89   if (stream != NULL) {                           /* If file provided         */
90     reduloctab[0] = 1;                            /* This process is the root */
91     reduloctab[1] = ordeptr->proclocnum;          /* Get its rank             */
92   }
93   else {
94     reduloctab[0] =                               /* This process is not the root */
95     reduloctab[1] = 0;
96   }
97   reduloctab[2] = (grafptr->vlblloctax != NULL) ? 1 : 0; /* See if vertex labels provided */
98   if (MPI_Allreduce (reduloctab, reduglbtab, 3, MPI_INT, MPI_SUM, ordeptr->proccomm) != MPI_SUCCESS) {
99     errorPrint ("dorderSaveTree2: communication error (1)");
100     return     (1);
101   }
102   if (reduglbtab[0] != 1) {
103     errorPrint ("dorderSaveTree2: should have only one root");
104     return     (1);
105   }
106   MPI_Comm_size (ordeptr->proccomm, &procglbnbr);
107   if ((reduglbtab[2] != 0) && (reduglbtab[2] != procglbnbr)) {
108     errorPrint ("dorderSaveTree2: inconsistent parameters");
109     return     (1);
110   }
111   protnum = (int) reduglbtab[1];                  /* Get rank of root process */
112 
113   cheklocval = 0;
114   vlbltab = NULL;
115   if (reduglbtab[2] != 0) {
116     if (protnum == ordeptr->proclocnum)
117       if ((vlbltab = memAlloc (ordeptr->vnodglbnbr * sizeof (Gnum))) == NULL) {
118         errorPrint ("dorderSaveTree2: out of memory");
119         cheklocval = 1;
120       }
121 #ifdef SCOTCH_DEBUG_DORDER1                       /* Communication cannot be merged with a useful one */
122     if (MPI_Bcast (&cheklocval, 1, MPI_INT, protnum, ordeptr->proccomm) != MPI_SUCCESS) {
123       errorPrint ("dorderSaveTree2: communication error (2)");
124       return     (1);
125     }
126 #endif /* SCOTCH_DEBUG_DORDER1 */
127     if (cheklocval != 0)
128       return (1);
129     if (commGatherv (grafptr->vlblloctax + grafptr->baseval, grafptr->vertlocnbr, GNUM_MPI,
130                      vlbltab, grafptr->proccnttab, grafptr->procdsptab, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) {
131       errorPrint ("dorderSaveTree2: communication error (3)");
132       return     (1);
133     }
134   }
135 
136   if (protnum == ordeptr->proclocnum)
137     cheklocval = orderInit (&corddat, ordeptr->baseval, ordeptr->vnodglbnbr, NULL);
138 #ifdef SCOTCH_DEBUG_DORDER1                       /* Communication cannot be merged with a useful one */
139   if (MPI_Bcast (&cheklocval, 1, MPI_INT, protnum, ordeptr->proccomm) != MPI_SUCCESS) {
140     errorPrint ("dorderSaveTree2: communication error (4)");
141     return     (1);
142   }
143 #endif /* SCOTCH_DEBUG_DORDER1 */
144   if (cheklocval != 0)
145     return (1);
146 
147   if (protnum == ordeptr->proclocnum) {
148     cheklocval = dorderGather (ordeptr, &corddat); /* Need inverse permutation too */
149     if (cheklocval == 0)
150       cheklocval = funcptr (&corddat, vlbltab, stream);
151     orderExit (&corddat);
152   }
153   else
154     cheklocval = dorderGather (ordeptr, NULL);
155 
156   if (vlbltab != NULL)
157     memFree (vlbltab);
158 
159 #ifdef SCOTCH_DEBUG_DORDER1                       /* Communication cannot be merged with a useful one */
160   if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, ordeptr->proccomm) != MPI_SUCCESS) {
161     errorPrint ("dorderSaveTree2: communication error (3)");
162     return     (1);
163   }
164 #else /* SCOTCH_DEBUG_DORDER1 */
165   chekglbval = cheklocval;
166 #endif /* SCOTCH_DEBUG_DORDER1 */
167 
168   return  (chekglbval);
169 }
170 
171 /* This routine saves the separator tree
172 ** data of the given distributed ordering.
173 ** It returns:
174 ** - 0   : on success.
175 ** - !0  : on error.
176 */
177 
178 int
dorderSaveTree(const Dorder * restrict const ordeptr,const Dgraph * restrict const grafptr,FILE * restrict const stream)179 dorderSaveTree (
180 const Dorder * restrict const ordeptr,
181 const Dgraph * restrict const grafptr,
182 FILE * restrict const         stream)
183 {
184   return (dorderSaveTree2 (ordeptr, grafptr, stream, orderSaveTree));
185 }
186 
187 /* This routine saves the column block
188 ** mapping data of the given distributed
189 ** ordering.
190 ** It returns:
191 ** - 0   : on success.
192 ** - !0  : on error.
193 */
194 
195 int
dorderSaveMap(const Dorder * restrict const ordeptr,const Dgraph * restrict const grafptr,FILE * restrict const stream)196 dorderSaveMap (
197 const Dorder * restrict const ordeptr,
198 const Dgraph * restrict const grafptr,
199 FILE * restrict const         stream)
200 {
201   return (dorderSaveTree2 (ordeptr, grafptr, stream, orderSaveMap));
202 }
203