PaStiX Handbook  6.4.0
graph_compute_kway.c
Go to the documentation of this file.
1 /**
2  *
3  * @file graph_compute_kway.c
4  *
5  * PaStiX routines to compute kway on a given supernode
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  * @author Tony Delarue
14  * @date 2024-07-05
15  *
16  **/
17 #include "common.h"
18 #if !defined(PASTIX_ORDERING_SCOTCH)
19 #error "This file should be compiled inly if SCOTCH is enabled and found"
20 #endif /* defined(PASTIX_ORDERING_PTSCOTCH) */
21 #include <spm.h>
22 #include "graph/graph.h"
23 #include "pastix/order.h"
24 #include <scotch.h>
25 
26 /**
27  *******************************************************************************
28  *
29  * @ingroup pastix_graph
30  *
31  * @brief Compute the K-way partition of a given set of unknowns
32  *
33  * Take a graph with its own associated ordering, and generates a k-way
34  * partition of the graph.
35  *
36  *******************************************************************************
37  *
38  * @param[in] graph
39  * The pointer to the graph structure on wich to apply the K-way
40  * partitioning on the subcomponent comp_id.
41  *
42  * @param[inout] order
43  * The order structure associated to the given graph.
44  * On entry, the structure is initialized through previous operation on
45  * the graph, and on exit vertices are reordered by components in the
46  * K-way partitioning.
47  *
48  * @param[inout] peritab
49  * Array of size n.
50  * Pointer to the peritab array of the global graph in which the
51  * subproblem belongs to. This array is updated according to the
52  * eprmutation performed for the K-way partitioning.
53  *
54  * @param[inout] comp_nbr
55  * On entry the number of components in the graph.
56  * On exit, the new number of components after K-way partitioning.
57  *
58  * @param[inout] comp_sze
59  * The size of each components in the graph.
60  * On entry, only the first comp_nbr sizes are initialized, others are 0.
61  * On exit, the array is extended to store the size of the new
62  * components generated by the k-way partitionning.
63  *
64  * @param[inout] comp_vtx
65  * Array of size n that hold the index of the component for each vertex
66  * of the graph.
67  *
68  * @param[in] comp_id
69  * The index of the component that must be split by K-way paritioning.
70  *
71  * @param[in] nbpart
72  * The number of part wanted in the k-way partitioning.
73  *
74  *******************************************************************************
75  *
76  * @retval PASTIX_SUCCESS on success,
77  * @retval PASTIX_ERR_UNKNOWN if something went wrong with Scotch.
78  *
79  *******************************************************************************/
80 int graphComputeKway( const pastix_graph_t *graph,
81  pastix_order_t *order,
82  pastix_int_t *peritab,
83  pastix_int_t *comp_nbr,
84  pastix_int_t *comp_sze,
85  pastix_int_t *comp_vtx,
86  pastix_int_t comp_id,
87  pastix_int_t nbpart )
88 {
89  SCOTCH_Graph comp_sgraph;
90  SCOTCH_Strat sstrat;
91  pastix_graph_t comp_graph;
92  pastix_int_t i, n, comp_n, fnode, lnode;
93  pastix_int_t *perm = order->permtab;
94  pastix_int_t *invp = order->peritab;
95  pastix_int_t *parttab;
96 
97  n = graph->n;
98 
99  fnode = 0;
100  for (i=0; i<comp_id; i++) {
101  fnode += comp_sze[i];
102  }
103  lnode = fnode + comp_sze[comp_id];
104  assert( comp_sze[comp_id] != 0 );
105  assert( lnode <= n );
106 
107  comp_n = lnode - fnode;
108 
109  /* Isolate unknowns of the component */
110  if ( comp_n == n ) {
111  memcpy( &comp_graph, graph, sizeof(pastix_graph_t) );
112  }
113  else {
114  /* First, let's make sure everything is sorted by component to extract it */
115  {
116  void *sortptr[3];
117  sortptr[0] = comp_vtx;
118  sortptr[1] = invp;
119  sortptr[2] = peritab;
120 
121  qsort3IntAsc( sortptr, n );
122 
123  /* Update the perm array */
124  for(i=0; i<n; i++) {
125  perm[invp[i]] = i;
126  }
127 
128  /* pastixOrderCheck( order ); */
129  }
130  memset( &comp_graph, 0, sizeof(pastix_graph_t) );
131  graphIsolateRange( graph, order, &comp_graph,
132  fnode, lnode, 0 );
133  }
134  assert( comp_graph.n == comp_n );
135 
136  /* Build Scotch graph */
137  if ( ! SCOTCH_graphInit( &comp_sgraph ) ) {
138  SCOTCH_graphBuild( &comp_sgraph,
139  order->baseval,
140  comp_n,
141  comp_graph.colptr,
142  NULL,
143  NULL,
144  NULL,
145  comp_graph.colptr[ comp_n ] - comp_graph.colptr[ 0 ],
146  comp_graph.rowptr,
147  NULL);
148  }
149  else {
150  fprintf(stderr,"Failed to build graph\n");
151  }
152 
153 #if !defined(NDEBUG)
154  if ( SCOTCH_graphCheck( &comp_sgraph ) ) {
155  pastix_print_error( "error in graph graphCheck()...\n" );
157  }
158 #endif
159 
160  if ( SCOTCH_stratInit( &sstrat ) != 0 ) {
161  pastix_print_error( "Failed to initialize partitioning strategy\n" );
162  return PASTIX_ERR_UNKNOWN;
163  }
164 
165  parttab = malloc( comp_n * sizeof(pastix_int_t) );
166  memset( parttab, 0, comp_n * sizeof(pastix_int_t) );
167 
168  SCOTCH_graphPart( &comp_sgraph, nbpart,
169  &sstrat, parttab );
170 
171  SCOTCH_graphExit( &comp_sgraph );
172  SCOTCH_stratExit( &sstrat );
173 
174  /* Update the comp_vtx, and comp_size */
175  {
176  pastix_int_t *vtx;
177  pastix_int_t newid;
178 
179  for(i=0; i<nbpart; i++) {
180  comp_sze[ *comp_nbr + i ] = 0;
181  }
182 
183  for(i=0; i<comp_n; i++) {
184  vtx = comp_vtx + fnode + i;
185  assert( *vtx == comp_id );
186  newid = *comp_nbr + parttab[i];
187  comp_sze[newid]++;
188  *vtx = newid;
189  }
190  comp_sze[comp_id] = 0;
191  *comp_nbr += nbpart;
192  }
193 
194  if ( comp_n != n ) {
195  graphExit( &comp_graph );
196  }
197 
198  /* /\* Sort the unknown of the component *\/ */
199  /* { */
200  /* void *sortptr[3]; */
201  /* sortptr[0] = comp_vtx + fnode; */
202  /* sortptr[1] = invp + fnode; */
203  /* sortptr[2] = peritab + fnode; */
204 
205  /* qsort3IntAsc( sortptr, comp_n ); */
206 
207  /* /\* If necessary, move the partition to the end to keep the right order *\/ */
208  /* if ( (graph->n - lnode) != 0 ) { */
209  /* move_to_end( comp_n, graph->n - lnode, */
210  /* comp_vtx + fnode, parttab ); */
211  /* move_to_end( comp_n, graph->n - lnode, */
212  /* invp + fnode, parttab ); */
213  /* move_to_end( comp_n, graph->n - lnode, */
214  /* peritab + fnode, parttab ); */
215 
216  /* /\* Update the perm array *\/ */
217  /* for(i=0; i<graph->n; i++) { */
218  /* perm[invp[i]] = i; */
219  /* } */
220  /* } */
221  /* else { */
222  /* /\* Update the perm array *\/ */
223  /* for(i=fnode; i<lnode; i++) { */
224  /* perm[invp[i]] = i; */
225  /* } */
226  /* } */
227  /* } */
228 
229  free( parttab );
230  return PASTIX_SUCCESS;
231 }
BEGIN_C_DECLS typedef int pastix_int_t
Definition: datatypes.h:51
@ PASTIX_ERR_UNKNOWN
Definition: api.h:368
@ PASTIX_SUCCESS
Definition: api.h:367
@ PASTIX_ERR_BADPARAMETER
Definition: api.h:374
void graphExit(pastix_graph_t *graph)
Free the content of the graph structure.
Definition: graph.c:73
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 baseval
Definition: order.h:48
pastix_int_t * permtab
Definition: order.h:51
pastix_int_t * peritab
Definition: order.h:52
Order structure.
Definition: order.h:47