PaStiX Handbook  6.3.2
order_compute_ptscotch.c
Go to the documentation of this file.
1 /**
2  *
3  * @file order_compute_ptscotch.c
4  *
5  * PaStiX order driver to perform ordering with PT-Scotch library.
6  *
7  * @copyright 2004-2023 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
8  * Univ. Bordeaux. All rights reserved.
9  *
10  * @version 6.3.2
11  * @author Xavier Lacoste
12  * @author Pierre Ramet
13  * @author Mathieu Faverge
14  * @author Tony Delarue
15  * @date 2023-07-21
16  *
17  **/
18 #include "common.h"
19 #include "graph/graph.h"
20 #include "order/order_internal.h"
21 #if defined(PASTIX_ORDERING_PTSCOTCH)
22 #include <ptscotch.h>
23 #endif
24 
25 /**
26  *******************************************************************************
27  *
28  * @ingroup pastix_order
29  *
30  * @brief Check the PT-Scotch distributed graph.
31  *
32  *******************************************************************************
33  *
34  * @param[in] graph
35  * Pointer to the SCOTCH_Dgraph structure.
36  *
37  * @param[in] procnum
38  * Procnum of the process. Output purpose.
39  *
40  *******************************************************************************/
41 static inline void
42 ocpts_graph_check( const SCOTCH_Dgraph *graph,
43  int procnum )
44 {
45 #if defined(PASTIX_DEBUG_ORDERING)
46  Clock timer;
47  clockStart(timer);
48  if ( SCOTCH_dgraphCheck( graph ) ) {
49  pastix_print_error( "pastix: dgraphCheck" );
50  }
51  clockStop(timer);
52  pastix_print( procnum, 0, "SCOTCH_dgraphCheck done in %lf second\n", clockVal(timer) );
53 #else
54  (void)graph;
55  (void)procnum;
56 #endif /* defined(PASTIX_DEBUG_ORDERING) */
57 }
58 
59 /**
60  *******************************************************************************
61  *
62  * @ingroup pastix_order
63  *
64  * @brief Build the PT-Scotch distributed graph.
65  *
66  *******************************************************************************
67  *
68  * @param[inout] scotchgraph
69  * The SCOTCH_Dgraph structure that will be build.
70  *
71  * @param[inout] graph
72  * The graph prepared by graphPrepare function on which we want to
73  * perform the ordering.
74  *
75  * @param[in] comm
76  * PaStiX communicator.
77  *
78  *******************************************************************************/
79 static inline void
80 ocpts_graph_init( SCOTCH_Dgraph *scotchgraph,
81  pastix_graph_t *graph,
82  PASTIX_Comm comm )
83 {
84  pastix_int_t *colptr, *rowptr;
85  pastix_int_t *weights;
86  pastix_int_t n, nnz, baseval;
87 
88  /* Make sure graph is 0-based */
89  graphBase( graph, 0 );
90 
91  n = graph->n;
92  nnz = graph->nnz;
93  colptr = graph->colptr;
94  rowptr = graph->rowptr;
95  baseval = graph->baseval;
96  weights = NULL;
97 
98  assert( baseval == colptr[0] );
99  assert( nnz == colptr[n] - colptr[0] );
100 
101  SCOTCH_dgraphInit( scotchgraph, comm );
102 
103  /*
104  * Generate the vertex load array if dof != 1
105  */
106  weights = graphGetWeights( graph );
107 
108  if ( SCOTCH_dgraphBuild( scotchgraph,
109  baseval, /* baseval */
110  n, /* Number of local vertices */
111  n, /* Maximum number of local vertices */
112  colptr,
113  NULL,
114  weights, /* Local vertex load array (if any) */
115  NULL, /* Local vertex label array (if any) */
116  nnz,
117  nnz,
118  rowptr, /* Local edge array */
119  NULL, /* Ghost edge array (if any); not const */
120  NULL ) )
121  {
122  pastix_print_error( "pastix : SCOTCH_dgraphBuild\n" );
123  }
124 
125  /* Check the generated Scotch graph structure */
126  ocpts_graph_check( scotchgraph, graph->clustnum );
127 
128  return;
129 }
130 
131 /**
132  *******************************************************************************
133  *
134  * @ingroup pastix_order
135  *
136  * @brief Cleanup the PT-Scotch graph structure and free the associated data.
137  *
138  *******************************************************************************
139  *
140  * @param[inout] scotchgraph
141  * The SCOTCH_Dgraph structure that will be clean.
142  *
143  * @param[inout] comm
144  * The PaStiX communicator.
145  *
146  *******************************************************************************/
147 static inline void
148 ocpts_graph_exit( SCOTCH_Dgraph *scotchgraph,
149  PASTIX_Comm comm )
150 {
151  pastix_int_t *colptr = NULL;
152  pastix_int_t *rowptr = NULL;
153  pastix_int_t *weights = NULL;
154 
155  SCOTCH_dgraphData (
156  scotchgraph,
157  NULL, /* Base value */
158  NULL, /* Global number of vertices */
159  NULL, /* Local number of vertices */
160  NULL, /* Max number of local vertices */
161  NULL, /* Number of local and ghost vertices */
162  &colptr, /* Vertex array [vertnbr+1] */
163  NULL, /* Vertex array [vertnbr] */
164  &weights, /* Vertex load array */
165  NULL, /* Vertex label array */
166  NULL, /* Global number of edges (arcs) */
167  NULL, /* Declared size of the local edge array */
168  NULL, /* Max number of local edges */
169  &rowptr, /* Edge array [edgenbr] */
170  NULL, /* Ghost adjency array */
171  NULL, /* Edge load array */
172  &comm );
173 
174  /* Free the vertex load array */
175  if ( weights != NULL ) {
176  memFree_null( weights );
177  }
178 
179  /* SCOTCH_dgraphExit( scotchgraph ); */
180  return;
181 }
182 
183 /**
184  *******************************************************************************
185  *
186  * @ingroup pastix_order
187  *
188  * @brief Compute the graph ordering
189  *
190  *******************************************************************************
191  *
192  * @param[inout] pastix_data
193  * Pointer to the pastix_data instance.
194  *
195  * @param[inout] scotchgraph
196  * The SCOTCH_Dgraph structure that will be ordered.
197  *
198  ********************************************************************************
199  *
200  * @retval The return value of SCOTCH_graphDOrderList.
201  *
202  *******************************************************************************/
203 static inline int
205  SCOTCH_Dgraph *scotchgraph )
206 {
207  pastix_order_t *ordemesh = pastix_data->ordemesh;
208  SCOTCH_Strat stratdat;
209  SCOTCH_Dordering ordedat;
210  SCOTCH_Ordering ordering;
211 
212  /* Create Strategy string for Scotch */
213  SCOTCH_stratInit( &stratdat );
214 
215  /* Init distributed ordering */
216  if ( SCOTCH_dgraphOrderInit(scotchgraph, &ordedat) )
217  {
218  pastix_print_error("pastix : SCOTCH_dgraphOrderInit\n");
219  }
220 
221  /* Compute distributed ordering */
222  if ( SCOTCH_dgraphOrderCompute( scotchgraph, &ordedat, &stratdat ) )
223  {
224  pastix_print_error( "pastix : SCOTCH_dgraphOrderCompute" );
225  }
226 
227  SCOTCH_stratExit( &stratdat );
228 
229  /* Init centralized ordering */
230  if ( SCOTCH_dgraphCorderInit( scotchgraph,
231  &ordering,
232  (SCOTCH_Num *) ordemesh->permtab,
233  (SCOTCH_Num *) ordemesh->peritab,
234  (SCOTCH_Num *)&ordemesh->cblknbr,
235  (SCOTCH_Num *) ordemesh->rangtab,
236  (SCOTCH_Num *) ordemesh->treetab) )
237  {
238  pastix_print_error( "pastix : SCOTCH_dgraphCorderInit" );
239  }
240 
241  /* Gather distributed ordering on node 0 */
242  if ( pastix_data->procnum == 0 ) {
243  SCOTCH_dgraphOrderGather( scotchgraph, &ordedat, &ordering );
244  }
245  else {
246  SCOTCH_dgraphOrderGather( scotchgraph, &ordedat, NULL );
247  }
248 
249  /* Broadcast node 0 datas on all nodes */
250  {
251  int rangnbr, permnbr;
252  MPI_Bcast( &ordemesh->cblknbr, 1, PASTIX_MPI_INT, 0, pastix_data->pastix_comm );
253 
254  rangnbr = ordemesh->cblknbr;
255  MPI_Bcast( ordemesh->rangtab, rangnbr+1, PASTIX_MPI_INT, 0, pastix_data->pastix_comm );
256  MPI_Bcast( ordemesh->treetab, rangnbr, PASTIX_MPI_INT, 0, pastix_data->pastix_comm );
257 
258  permnbr = pastix_data->graph->gN;
259  MPI_Bcast( ordemesh->permtab, permnbr, PASTIX_MPI_INT, 0, pastix_data->pastix_comm );
260  MPI_Bcast( ordemesh->peritab, permnbr, PASTIX_MPI_INT, 0, pastix_data->pastix_comm );
261  }
262 
263  /* Exit PT-Scotch ordering structures */
264  SCOTCH_dgraphCorderExit( scotchgraph, &ordering );
265  SCOTCH_dgraphOrderExit( scotchgraph, &ordedat );
266 
267  return PASTIX_SUCCESS;
268 }
269 
270 /**
271  *******************************************************************************
272  *
273  * @ingroup pastix_order
274  *
275  * @brief Compute the ordering of the graph given as parameter
276  * with PT-Scotch library.
277  *
278  * This routine is affected by the following parameters:
279  * IPARM_VERBOSE, IPARM_ORDERING_DEFAULT, IPARM_SCOTCH_SWITCH_LEVEL,
280  * IPARM_SCOTCH_CMIN, IPARM_SCOTCH_CMAX, IPARM_SCOTCH_FRAT
281  *
282  *******************************************************************************
283  *
284  * @param[inout] pastix_data
285  * The pastix_data structure that describes the solver instance.
286  * On exit, the field ordemesh is initialized with the result of the
287  * ordering realized by PT-Scotch.
288  *
289  * @param[inout] graph
290  * The graph prepared by graphPrepare function on which we want to
291  * perform the ordering. On exit, the graph might be rebased.
292  *
293  *******************************************************************************
294  *
295  * @retval PASTIX_SUCCESS on successful exit,
296  * @retval PASTIX_ERR_BADPARAMETER if one parameter is incorrect,
297  * @retval PASTIX_ERR_OUTOFMEMORY if one allocation failed,
298  * @retval PASTIX_ERR_INTEGER_TYPE if Scotch integer type is not the
299  * same size as PaStiX ones,
300  * @retval PASTIX_ERR_INTERNAL if an error occurs internally to Scotch.
301  *
302  *******************************************************************************/
303 int
305  pastix_graph_t *graph )
306 {
307  SCOTCH_Dgraph scotchdgraph;
308  int ret = PASTIX_SUCCESS;
309  pastix_order_t *ordemesh = pastix_data->ordemesh;
310  pastix_int_t baseval = graph->baseval;
311 
312  /* Check integer compatibility */
313  if ( sizeof(pastix_int_t) != sizeof(SCOTCH_Num) ) {
314  pastix_print_error( "orderComputePTScotch: Inconsistent integer type between Pastix and PT-Scotch\n" );
316  }
317 
318  /* Enable this define to fix the SCOTCH random generator */
319 #if defined(PASTIX_ORDERING_FIX_SEED)
320  SCOTCH_randomSeed( (SCOTCH_Num)(pastix_data->id) );
321  SCOTCH_randomReset();
322 #endif
323 
324  /* Build The Scotch Dgraph */
325  ocpts_graph_init( &scotchdgraph, graph, pastix_data->pastix_comm );
326 
327  /* Allocate the ordering structure */
328  pastixOrderAlloc( ordemesh, graph->gN, graph->gN );
329 
330  /* Compute the ordering */
331  ret = ocpts_compute_graph_ordering( pastix_data, &scotchdgraph );
332 
333  /*
334  * SCOTCH_graphBase may have had side effects on our graph.
335  * Call this routine again with our saved baseval.
336  */
337  graphBase( graph, baseval );
338 
339  /* Free the Scotch graph structure */
340  ocpts_graph_exit( &scotchdgraph, pastix_data->pastix_comm );
341 
342  /* If something has failed in PT-Scotch */
343  if ( ret != PASTIX_SUCCESS ) {
344  pastixOrderExit( ordemesh );
345  return PASTIX_ERR_INTERNAL;
346  }
348 
349  return ret;
350 }
BEGIN_C_DECLS typedef int pastix_int_t
Definition: datatypes.h:51
@ PASTIX_ERR_INTERNAL
Definition: api.h:373
@ PASTIX_ERR_INTEGER_TYPE
Definition: api.h:376
@ PASTIX_SUCCESS
Definition: api.h:367
void graphBase(pastix_graph_t *graph, pastix_int_t baseval)
Rebase the graph to the given value.
Definition: graph.c:102
pastix_int_t * graphGetWeights(const pastix_graph_t *graph)
Build the vertex weight array out of the dof array.
Definition: graph.c:433
pastix_int_t * treetab
Definition: order.h:54
pastix_int_t * permtab
Definition: order.h:51
pastix_int_t * peritab
Definition: order.h:52
pastix_int_t cblknbr
Definition: order.h:50
pastix_int_t * rangtab
Definition: order.h:53
int pastixOrderAlloc(pastix_order_t *ordeptr, pastix_int_t vertnbr, pastix_int_t cblknbr)
Allocate the order structure.
Definition: order.c:55
static void ocpts_graph_init(SCOTCH_Dgraph *scotchgraph, pastix_graph_t *graph, PASTIX_Comm comm)
Build the PT-Scotch distributed graph.
static void ocpts_graph_exit(SCOTCH_Dgraph *scotchgraph, PASTIX_Comm comm)
Cleanup the PT-Scotch graph structure and free the associated data.
void order_scotch_reallocate_ordemesh(pastix_order_t *ordemesh)
Reallocate the ordering structure.
int orderComputePTScotch(pastix_data_t *pastix_data, pastix_graph_t *graph)
Compute the ordering of the graph given as parameter with PT-Scotch library.
static int ocpts_compute_graph_ordering(pastix_data_t *pastix_data, SCOTCH_Dgraph *scotchgraph)
Compute the graph ordering.
static void ocpts_graph_check(const SCOTCH_Dgraph *graph, int procnum)
Check the PT-Scotch distributed graph.
void pastixOrderExit(pastix_order_t *ordeptr)
Free the arrays initialized in the order structure.
Definition: order.c:273
Order structure.
Definition: order.h:47
PASTIX_Comm pastix_comm
Definition: pastixdata.h:75
pastix_order_t * ordemesh
Definition: pastixdata.h:97
pastix_int_t id
Definition: pastixdata.h:68
pastix_graph_t * graph
Definition: pastixdata.h:91
Main PaStiX data structure.
Definition: pastixdata.h:67