PaStiX Handbook  6.4.0
order_supernodes.c
Go to the documentation of this file.
1 /**
2  *
3  * @file order_supernodes.c
4  *
5  * PaStiX order routines dedicated to split supernodes thanks to graph connectivity
6  *
7  * @copyright 2004-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
8  * Univ. Bordeaux. All rights reserved.
9  *
10  * @version 6.4.0
11  * @author Gregoire Pichon
12  * @author Mathieu Faverge
13  * @date 2024-07-05
14  *
15  */
16 #include "common.h"
17 #include <string.h>
18 #include "graph/graph.h"
19 #include "order/order_internal.h"
20 #include "blend/elimintree.h"
21 #include "blend/extendVector.h"
22 
23 /**
24  *******************************************************************************
25  *
26  * @ingroup pastix_order
27  *
28  * @brief Order the supernodes with one of the clustering strategies.
29  *
30  *******************************************************************************
31  *
32  * @param[in] graph
33  * The graph that represents the sparse matrix.
34  *
35  * @param[inout] order
36  * The graph that represents the sparse matrix. On exit, this ordering
37  * is updated with the refined partition obtained thanks to one of the
38  * clustering strategies.
39  *
40  * @param[inout] etree
41  * The elimination tree. On exit it can be modified by
42  * eTreeComputeLevels().
43  *
44  * @param[in] iparm
45  * The integer array of parameters.
46  *
47  * @param[in] do_schur
48  * If do_schur is not zero, the last cblk represents the schur. Thus,
49  * neither k-way nor projection applied on it. If do_schur is zero,
50  * both k-way and projection can be performed everywhere.
51  *
52  *******************************************************************************
53  *
54  * @retval PASTIX_SUCCESS on successful exit,
55  * @retval PASTIX_ERR_BADPARAMETER if one parameter is incorrect,
56  *
57  *******************************************************************************/
59 orderSupernodes( const pastix_graph_t *graph,
60  pastix_order_t *order,
61  EliminTree *etree,
62  pastix_int_t *iparm,
63  int do_schur )
64 {
65  ExtendVectorINT sn_parts;
66  pastix_split_t strategy = iparm[IPARM_SPLITTING_STRATEGY];
71  pastix_int_t lvl_kway = iparm[IPARM_SPLITTING_LEVELS_KWAY];
72  pastix_int_t *depth_size = NULL;
73  int *n_levels = NULL;
74  pastix_int_t i, sn_first, sn_id;
75  pastix_int_t new_cblknbr;
76  pastix_int_t *perm_treetab;
77  pastix_int_t *new_rangtab;
78  pastix_int_t *new_treetab;
79  int8_t *new_selevtx;
80 
81  if ( strategy == PastixSplitNot ) {
82  return PASTIX_SUCCESS;
83  }
84 
85  if ( order == NULL ) {
86  pastix_print_error( "orderSupernodes: invalid order pointer" );
88  }
89 
90  lvl_kway = pastix_imax( lvl_proj, lvl_kway );
91 
92  pastixOrderBase( order, 0 );
93 
94  /* Make sure the node levels are computed in the etree */
95  eTreeComputeLevels( etree, eTreeRoot(etree), 0 );
96 
97  /* Get the minimal index of a node at the max depth considered */
98  sn_first = eTreeGetLevelMinIdx( etree, eTreeRoot(etree), lvl_kway, order->cblknbr );
99 
100  extendint_Init( &sn_parts, 16 );
101 
102  /*
103  * Create an array with the depth of each vertex in the elimination tree
104  * used to compute the projection
105  */
106  if ( strategy == PastixSplitKwayProjections )
107  {
108  /* Allocate the size of each projection */
109  MALLOC_INTERN( depth_size, max_depth, pastix_int_t );
110 
111  /* Store the level of each node */
112  MALLOC_INTERN( n_levels, graph->n, int );
113  for( sn_id=0; sn_id<order->cblknbr; sn_id++ ) {
114  int level = etree->nodetab[sn_id].ndlevel;
115  assert( level > 0 );
116 
117  for(i=order->rangtab[sn_id]; i<order->rangtab[sn_id+1]; i++) {
118  n_levels[ order->peritab[i] ] = level;
119  }
120  }
121  }
122 
123  /* Backup initial rangtab and allocated the permutation array for top elements of the treetab */
124  MALLOC_INTERN( perm_treetab, order->cblknbr - sn_first, pastix_int_t );
125  MALLOC_INTERN( new_rangtab, order->vertnbr+1, pastix_int_t );
126  MALLOC_INTERN( new_treetab, order->vertnbr, pastix_int_t );
127  MALLOC_INTERN( new_selevtx, order->vertnbr, int8_t );
128 
129  memcpy( new_rangtab, order->rangtab, sizeof(pastix_int_t) * (sn_first+1) );
130  memcpy( new_treetab, order->treetab, sizeof(pastix_int_t) * sn_first );
131  memset( new_selevtx, 0, order->vertnbr * sizeof(int8_t) );
132 
133  new_cblknbr = sn_first;
134 
135  for (sn_id = sn_first; sn_id < order->cblknbr; sn_id++) {
136  pastix_graph_t sn_graph;
137  pastix_order_t sn_order;
138  pastix_int_t sn_level, sn_vertnbr;
139  pastix_int_t fnode, lnode, ret; /* , sorted; */
140  pastix_int_t sn_nbpart_proj, sn_nbparts, sn_nbparts_max;
141 
142  perm_treetab[sn_id-sn_first] = new_cblknbr;
143 
144  /* sorted = 0; */
145  fnode = order->rangtab[sn_id];
146  lnode = order->rangtab[sn_id+1];
147  sn_vertnbr = lnode - fnode;
148  sn_level = etree->nodetab[sn_id].ndlevel;
149  sn_nbparts_max = pastix_iceil( sn_vertnbr, iparm[IPARM_MAX_BLOCKSIZE] );
150 
151  if ( (sn_level > (lvl_kway)) ||
152  (sn_nbparts_max == 1) ||
153  ((sn_id == order->cblknbr-1) && (do_schur)) )
154  {
155  new_treetab[ new_cblknbr ] = order->treetab[sn_id];
156  new_cblknbr++;
157  new_rangtab[ new_cblknbr ] = lnode;
158  continue;
159  }
160 
161  if ( iparm[IPARM_VERBOSE] > 2 ) {
162  fprintf( stdout, " - Working on cblk %ld (level= %d, n= %ld):\n",
163  (long)sn_id, (int)sn_level, (long)(lnode-fnode) );
164  }
165 
166  /* Reinitialize data structures */
167  extendint_Clear( &sn_parts );
168 
169  pastixOrderAllocId( &sn_order, sn_vertnbr );
170  memset( &sn_graph, 0, sizeof(pastix_graph_t) );
171 
172  /**
173  * Extract the subgraph with unknowns of the supernode sn_id
174  *
175  * 1 is sufficient for the max_distance in most cases, but set to 2 for
176  * corner cases that need extra connexions.
177  */
178  ret = graphIsolateRange( graph, order, &sn_graph,
179  fnode, lnode, 2 );
180  if ( ret != EXIT_SUCCESS ) {
181  fprintf(stderr, "Fatal error in graphIsolateSupernode()!\n");
182  exit(1);
183  }
184  assert( sn_vertnbr == sn_graph.n );
185 
186  /**
187  * Compute sets of preselected unknowns based on projections
188  */
189  if ( ( sn_vertnbr > (16 * iparm[IPARM_MAX_BLOCKSIZE]) ) &&
190  ( sn_level <= lvl_proj ) &&
191  ( strategy == PastixSplitKwayProjections ) &&
192  ( etree->nodetab[ sn_id ].sonsnbr == 2 ) )
193  {
194  memset( depth_size, 0, max_depth * sizeof(pastix_int_t) );
195 
196  pastix_int_t *permtab = malloc(graph->n * sizeof(pastix_int_t));
197  pastix_int_t *peritab = malloc(graph->n * sizeof(pastix_int_t));
198  memcpy(permtab, order->permtab, graph->n * sizeof(pastix_int_t));
199  memcpy(peritab, order->peritab, graph->n * sizeof(pastix_int_t));
200 
201  /* Compute the projection of the sublevel separators onto the subgraph */
202  graphComputeProjection( graph, n_levels, order,
203  &sn_graph, &sn_order,
204  fnode, lnode, sn_level,
205  max_distance, max_depth, max_width,
206  depth_size );
207 
208  /* Print statistics */
209  if ( iparm[IPARM_VERBOSE] > 2 )
210  {
211  fprintf(stdout, " - Results of the projection:\n" );
212  for( i=0; i<max_depth; i++ ) {
213  fprintf( stdout, " - At level %d: %8ld\n",
214  (int)(i+1), (long)depth_size[i] );
215  }
216  }
217 
218  /* Partition the supernode if sets of preselected unknowns have correct sizes */
219  {
220  pastix_int_t selected, total, totalsel;
221  pastix_int_t selecmax = 20 * sqrt( sn_vertnbr );
222  selected = 0;
223  totalsel = 0;
224  total = sn_vertnbr;
225 
226  for( i=0; i<max_depth; i++ ) {
227  totalsel += depth_size[i];
228 
229  /* If we reach the maximum size of pre-selected unknowns, we exit */
230  if ( totalsel > selecmax ) {
231  break;
232  }
233 
234  total -= depth_size[i];
235  selected += depth_size[i];
236 
237  if ( selected > iparm[IPARM_MIN_BLOCKSIZE] ) {
238  extendint_Add( &sn_parts, selected );
239  selected = 0;
240  }
241  }
242 
243  /* Add last partition of selected unknowns */
244  if ( selected > iparm[IPARM_MIN_BLOCKSIZE] ) {
245  extendint_Add( &sn_parts, selected );
246  selected = 0;
247  }
248  else {
249  /* Unselect the unknowns */
250  total += selected;
251  selected = 0;
252  }
253 
254  if ( iparm[IPARM_VERBOSE] > 2 ) {
255  fprintf( stdout, " - %ld nodes selected, %ld remains for K-Way\n",
256  (long)(sn_vertnbr - total), (long)(total) );
257  }
258 
259  /*
260  * The number of remaining unknowns is the non-selected unknowns
261  * + the selected unknows not extracted
262  */
263  if ( (sn_vertnbr - total) == 0 ) {
264  memcpy( order->permtab, permtab, graph->n * sizeof(pastix_int_t) );
265  memcpy( order->peritab, peritab, graph->n * sizeof(pastix_int_t) );
266  }
267 
268  sn_vertnbr = total;
269  }
270  free(permtab);
271  free(peritab);
272  }
273 
274  sn_nbparts = extendint_Size( &sn_parts );
275  sn_nbpart_proj = sn_nbparts;
276 
277  /* Ordering based on K-way */
278  if ( ( strategy == PastixSplitKway ) ||
279  ( strategy == PastixSplitKwayProjections ) )
280  {
281  pastix_queue_t queue;
282  pastix_int_t *comp_vtx, *comp_sze;
283  pastix_int_t comp_nbr = 1;
284  pastix_int_t nbpart_kway;
285  pastix_int_t smallcp_id, smallcp_sz, cp_id, cp_sz;
286  nbpart_kway = pastix_iceil( sn_vertnbr, iparm[IPARM_MAX_BLOCKSIZE] );
287 
288  /* Quick return */
289  if ( nbpart_kway < 2 ) {
290  goto cblk_end;
291  }
292 
293  /* Update the subgraph by removing the selected vertices if any */
294  if ( sn_nbparts > 0 ) {
295  pastix_graph_t tmpgraph;
296  memset( &tmpgraph, 0, sizeof(pastix_graph_t) );
297 
298  /*
299  * We isolate with a distance 0 here, as we already reconnected
300  * the graph at a given distance previously. In that case, we
301  * really want to disconnect components that are connected
302  * though selected vertices
303  */
304  graphIsolateRange( &sn_graph, &sn_order, &tmpgraph,
305  0, sn_vertnbr, 0 );
306  graphExit( &sn_graph );
307  memcpy( &sn_graph, &tmpgraph, sizeof(pastix_graph_t) );
308 
309  /*
310  * Reduce the suborder structure.
311  * We use thefact that the main peritab as always been updated
312  * along with the subarrays.
313  */
314  pastixOrderExit( &sn_order );
315  pastixOrderAllocId( &sn_order, sn_vertnbr );
316  }
317 
318  /* Isolate the connected components */
319  comp_vtx = malloc( sn_vertnbr * sizeof(pastix_int_t) );
320  comp_sze = malloc( sn_vertnbr * sizeof(pastix_int_t) );
321 
322  comp_nbr = graphIsolateConnectedComponents( &sn_graph, comp_vtx, comp_sze );
323 
324  if ( iparm[IPARM_VERBOSE] > 2 ) {
325  fprintf(stdout, " - Connected components: %ld\n", (long)comp_nbr );
326  }
327 
328  pqueueInit( &queue, comp_nbr );
329  for( i=0; i<comp_nbr; i++) {
330  pqueuePush1( &queue, i, comp_sze[i] );
331  }
332 
333  smallcp_id = -1;
334  smallcp_sz = 0;
335  while( pqueueSize( &queue ) > 0 ) {
336  cp_id = pqueuePop( &queue );
337  cp_sz = comp_sze[cp_id];
338 
339  if ( cp_sz < iparm[IPARM_COMPRESS_MIN_WIDTH] ) {
340  /* Merge with other small components */
341  smallcp_sz += cp_sz;
342  if ( smallcp_id == -1 ) {
343  smallcp_id = cp_id;
344  }
345  else {
346  comp_sze[cp_id] = 0;
347  for( i=0; (i<sn_graph.n) && (cp_sz>0); i++) {
348  if ( comp_vtx[i] == cp_id ) {
349  comp_vtx[i] = smallcp_id;
350  cp_sz--;
351  }
352  }
353  }
354  comp_sze[ smallcp_id ] = smallcp_sz;
355  }
356  else {
357  /* Update the local number of K-Way */
358  nbpart_kway = pastix_iceil( cp_sz, iparm[IPARM_MAX_BLOCKSIZE] );
359  if ( nbpart_kway < 2 ) {
360  continue;
361  }
362 
363  /* if (!sorted) { */
364  /* void *sortptr[3]; */
365  /* pastix_int_t *perm = sn_order.permtab; */
366  /* pastix_int_t *invp = sn_order.peritab; */
367 
368  /* sortptr[0] = comp_vtx; */
369  /* sortptr[1] = order->peritab + fnode; */
370  /* sortptr[2] = invp; */
371 
372  /* qsort3IntAsc( sortptr, sn_graph.n ); */
373 
374  /* /\* Update the perm array *\/ */
375  /* for(i=0; i<sn_graph.n; i++) { */
376  /* perm[invp[i]] = i; */
377  /* } */
378 
379  /* sorted = 1; */
380  /* } */
381 
382  graphComputeKway( &sn_graph, &sn_order, order->peritab + fnode,
383  &comp_nbr, comp_sze, comp_vtx,
384  cp_id, nbpart_kway );
385  }
386  }
387  pqueueExit( &queue );
388 
389  /* If multiple partitions, let's sort the unknowns */
390  if ( comp_nbr > 1 ) {
391  void *sortptr[2];
392  sortptr[0] = comp_vtx;
393  sortptr[1] = order->peritab + fnode;
394 
395  qsort2IntAsc( sortptr, sn_graph.n );
396  }
397 
398  for(i=comp_nbr-1; i>=0; i--) {
399  if (comp_sze[i] > 0) {
400  extendint_Add( &sn_parts, comp_sze[i] );
401  }
402  }
403  sn_vertnbr = 0;
404 
405  free( comp_vtx );
406  free( comp_sze );
407 
408  }
409 
410  /* Let's add a first cblk with remaining nodes */
411  cblk_end:
412  if ( sn_vertnbr > 0 ) {
413  extendint_Add( &sn_parts, sn_vertnbr );
414  }
415 
416  sn_nbparts = extendint_Size( &sn_parts );
417  assert( sn_nbparts >= 1 );
418  assert( new_rangtab[ new_cblknbr ] == fnode );
419 
420  /* First cblk */
421  fnode += extendint_Read( &sn_parts, sn_nbparts-1 );
422  new_selevtx[ new_cblknbr ] = ( sn_nbparts-1 < sn_nbpart_proj ) ? SYMBCBLK_PROJ : SYMBCBLK_KWAY;
423  new_cblknbr++;
424  new_rangtab[ new_cblknbr ] = fnode;
425 
426  assert( extendint_Read( &sn_parts, sn_nbparts-1 ) > 0 );
427  assert( fnode <= lnode );
428 
429  /*
430  * Update rangtab and treetab
431  */
432  for(i=sn_nbparts-2; i>=0; i--)
433  {
434  /* Chain cblk together */
435  new_treetab[new_cblknbr-1] = -1 - new_cblknbr;
436  new_selevtx[ new_cblknbr ] = ( i < sn_nbpart_proj ) ? SYMBCBLK_PROJ : SYMBCBLK_KWAY;
437  fnode += extendint_Read( &sn_parts, i );
438  new_cblknbr++;
439  new_rangtab[new_cblknbr] = fnode;
440 
441  assert( extendint_Read( &sn_parts, i ) > 0 );
442  assert( fnode <= lnode );
443  }
444 
445  new_treetab[ new_cblknbr-1 ] = order->treetab[sn_id];
446 
447  /* Update permtab for future extractions */
448  for (i=order->rangtab[sn_id]; i<order->rangtab[sn_id+1]; i++){
449  order->permtab[order->peritab[i]] = i;
450  }
451 
452  graphExit( &sn_graph );
453  pastixOrderExit( &sn_order );
454  }
455  assert( new_rangtab[new_cblknbr] == order->vertnbr );
456 
457  if ( n_levels != NULL ) {
458  free( n_levels );
459  }
460  if ( depth_size != NULL ) {
461  free( depth_size );
462  }
463  extendint_Exit( &sn_parts );
464 
465  /* Update the treetab */
466  {
467  pastix_int_t *oldtree, *newtree;
468 
469  memFree_null( order->treetab );
470  MALLOC_INTERN( order->treetab, new_cblknbr, pastix_int_t );
471 
472  newtree = order->treetab;
473  oldtree = new_treetab;
474  for(i=0; i<new_cblknbr; i++, newtree++, oldtree++) {
475  if ( *oldtree >= sn_first ) {
476  *newtree = perm_treetab[ *oldtree - sn_first ];
477  }
478  else if ( *oldtree >= 0 ) {
479  *newtree = *oldtree;
480  }
481  else if ( *oldtree == -1 ) {
482  *newtree = -1;
483  }
484  else { /* < -1 */
485  /* Use the fact that 0 will never be a father to shift only by one to escape the root */
486  *newtree = - *oldtree - 1;
487  }
488  }
489  memFree_null( new_treetab );
490  memFree_null( perm_treetab );
491  }
492 
493  /* Update the rangtab */
494  free(order->rangtab);
495  order->rangtab = realloc( new_rangtab, (new_cblknbr+1) * sizeof( pastix_int_t ) );
496 
497  order->cblknbr = new_cblknbr;
498  order->selevtx = realloc( new_selevtx, new_cblknbr * sizeof(int8_t) );
499 
500  if ( pastixOrderCheck( order ) != 0 ) {
501  printf("pastixOrderCheck() at the end of OrderSupernodes() failed !!!");
502  assert(0);
503  }
504 
505  return PASTIX_SUCCESS;
506 }
BEGIN_C_DECLS typedef int pastix_int_t
Definition: datatypes.h:51
eTreeNode_t * nodetab
Definition: elimintree.h:42
static pastix_int_t eTreeRoot(const EliminTree *etree)
Return the root of the elimination tree.
Definition: elimintree.h:126
pastix_int_t eTreeGetLevelMinIdx(const EliminTree *, pastix_int_t, pastix_int_t, pastix_int_t)
Return the smallest index of the nodes belonging to the level lvl in the elimination tree.
Definition: elimintree.c:429
pastix_int_t eTreeComputeLevels(EliminTree *, pastix_int_t, pastix_int_t)
Compute the number of level existing below a given node.
Definition: elimintree.c:250
Elimination tree.
Definition: elimintree.h:39
pastix_int_t extendint_Size(const ExtendVectorINT *)
Return the number of element stored in the vector.
Definition: extendVector.c:112
void extendint_Clear(ExtendVectorINT *)
Cleanup the vector.
Definition: extendVector.c:220
pastix_int_t extendint_Read(const ExtendVectorINT *, pastix_int_t)
Return the element of index eltnum.
Definition: extendVector.c:136
pastix_int_t * extendint_Init(ExtendVectorINT *, pastix_int_t)
Initialize the extendVector structure with the initial size given.
Definition: extendVector.c:45
void extendint_Add(ExtendVectorINT *, pastix_int_t)
Add an element elt to the end of the vector.
Definition: extendVector.c:90
void extendint_Exit(ExtendVectorINT *)
Free the extendVector structure.
Definition: extendVector.c:66
The extend integer array structure.
Definition: extendVector.h:29
static void pqueuePush1(pastix_queue_t *q, pastix_int_t elt, double key1)
Push an element with a single key.
Definition: queue.h:64
void pqueueExit(pastix_queue_t *)
Free the structure associated to the queue.
Definition: queue.c:110
pastix_int_t pqueueSize(const pastix_queue_t *)
Return the size of the queue.
Definition: queue.c:135
static pastix_int_t pqueuePop(pastix_queue_t *q)
Pop the head of the queue whithout returning the keys.
Definition: queue.h:75
int pqueueInit(pastix_queue_t *, pastix_int_t)
Initialize the queue structure with an initial space to store the elements.
Definition: queue.c:81
Queue structure.
Definition: queue.h:38
enum pastix_split_e pastix_split_t
Splitting strategy available for IPARM_SPLITTING_STRATEGY parameter.
@ IPARM_COMPRESS_MIN_WIDTH
Definition: api.h:129
@ IPARM_MIN_BLOCKSIZE
Definition: api.h:88
@ IPARM_SPLITTING_PROJECTIONS_DISTANCE
Definition: api.h:84
@ IPARM_VERBOSE
Definition: api.h:36
@ IPARM_MAX_BLOCKSIZE
Definition: api.h:89
@ IPARM_SPLITTING_LEVELS_PROJECTIONS
Definition: api.h:81
@ IPARM_SPLITTING_STRATEGY
Definition: api.h:80
@ IPARM_SPLITTING_LEVELS_KWAY
Definition: api.h:82
@ IPARM_SPLITTING_PROJECTIONS_WIDTH
Definition: api.h:85
@ IPARM_SPLITTING_PROJECTIONS_DEPTH
Definition: api.h:83
@ PASTIX_SUCCESS
Definition: api.h:367
@ PASTIX_ERR_BADPARAMETER
Definition: api.h:374
@ PastixSplitNot
Definition: api.h:416
@ PastixSplitKway
Definition: api.h:417
@ PastixSplitKwayProjections
Definition: api.h:418
void graphExit(pastix_graph_t *graph)
Free the content of the graph structure.
Definition: graph.c:73
pastix_int_t graphIsolateConnectedComponents(const pastix_graph_t *graph, pastix_int_t *comp_vtx, pastix_int_t *comp_sze)
Isolate the connected components from the original graph.
void graphComputeProjection(const pastix_graph_t *graph, const int *vertlvl, pastix_order_t *order, const pastix_graph_t *subgraph, pastix_order_t *suborder, pastix_int_t fnode, pastix_int_t lnode, pastix_int_t sn_level, pastix_int_t distance, pastix_int_t maxdepth, pastix_int_t maxwidth, pastix_int_t *depthsze)
TODO.
int graphIsolateRange(const pastix_graph_t *graphIn, const pastix_order_t *order, pastix_graph_t *graphOut, pastix_int_t fnode, pastix_int_t lnode, pastix_int_t distance)
Isolate the subgraph associated to a range of unknowns in the permuted graph.
int graphComputeKway(const pastix_graph_t *graph, pastix_order_t *order, pastix_int_t *peritab, pastix_int_t *comp_nbr, pastix_int_t *comp_sze, pastix_int_t *comp_vtx, pastix_int_t comp_id, pastix_int_t nbpart)
Compute the K-way partition of a given set of unknowns.
pastix_int_t * treetab
Definition: order.h:54
int8_t * selevtx
Definition: order.h:55
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
pastix_int_t vertnbr
Definition: order.h:49
void pastixOrderBase(pastix_order_t *ordeptr, pastix_int_t baseval)
This routine sets the base of the given ordering structure to the given base value.
Definition: order.c:322
pastix_int_t orderSupernodes(const pastix_graph_t *graph, pastix_order_t *order, EliminTree *etree, pastix_int_t *iparm, int do_schur)
Order the supernodes with one of the clustering strategies.
int pastixOrderCheck(const pastix_order_t *ordeptr)
This routine checks the correctness of the ordering structure.
Definition: order_check.c:39
int pastixOrderAllocId(pastix_order_t *ordeptr, pastix_int_t vertnbr)
Allocate the order structure for a given number of vertices with no cblk, and id permutation.
Definition: order.c:123
void pastixOrderExit(pastix_order_t *ordeptr)
Free the arrays initialized in the order structure.
Definition: order.c:273
Order structure.
Definition: order.h:47