PaStiX Handbook 6.4.0
Loading...
Searching...
No Matches
symbol.c
Go to the documentation of this file.
1/**
2 *
3 * @file symbol.c
4 *
5 * PaStiX symbol structure routines
6 *
7 * @copyright 2004-2025 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
8 * Univ. Bordeaux. All rights reserved.
9 *
10 * @version 6.4.0
11 * @author David Goudin
12 * @author Francois Pellegrini
13 * @author Mathieu Faverge
14 * @author Pascal Henon
15 * @author Pierre Ramet
16 * @author Tony Delarue
17 * @date 2024-07-05
18 *
19 **/
20#include "common.h"
21#include "graph/graph.h"
22#include "pastix/order.h"
23#include "symbol/symbol.h"
24
25/**
26 *******************************************************************************
27 *
28 * @ingroup symbol_dev
29 *
30 * @brief Add a dof array to the symbol matrix if any.
31 *
32 * If the dof parameter is variadic, then a permuted version of the initial dof
33 * array is constructed to match the symbol matrix that is working the permuted
34 * matrix A.
35 *
36 *******************************************************************************
37 *
38 * @param[in] graph
39 * The original graph of the matrix
40 *
41 * @param[in] order
42 * The ordering structure describing the permutation of the unknowns in
43 * the compressed form.
44 *
45 * @param[inout] symbptr
46 * The symbol structure to which dof array must be added.
47 *
48 *******************************************************************************/
49static inline void
50symbol_init_adddofs( const pastix_graph_t *graph,
51 const pastix_order_t *order,
52 symbol_matrix_t *symbptr )
53{
54 symbptr->dof = graph->dof;
55 symbptr->dofs = NULL;
56
57 if ( symbptr->dof < 1 ) {
58 pastix_int_t symbbase = symbptr->baseval;
59 pastix_int_t ordebase = order->baseval;
60 pastix_int_t i, ip, n, d, *dofs;
61
62 n = graph->gN;
63
64 MALLOC_INTERN( symbptr->dofs, n+1, pastix_int_t );
65
66 dofs = symbptr->dofs;
67 dofs[0] = symbbase;
68
69 for(ip=0; ip<n; ip++, dofs++) {
70 i = order->peritab[ip] - ordebase;
71
72 assert( i < n );
73 d = graph->dofs[i+1] - graph->dofs[i];
74
75 dofs[1] = dofs[0] + d;
76 }
77 assert( (symbptr->dofs[n] - symbbase) == (graph->dofs[n] - graph->dofs[0]) );
78 }
79
80 return;
81}
82
83/**
84 *******************************************************************************
85 *
86 * @brief Initialize the symbol structure.
87 *
88 * Initialized the permuted dof array if graph and order are provided. The
89 * symbol is considered as dof = 1 otherwise.
90 *
91 *******************************************************************************
92 *
93 * @param[in] graph
94 * The original graph of the matrix
95 *
96 * @param[in] order
97 * The ordering structure describing the permutation of the unknowns in
98 * the compressed form.
99 *
100 * @param[inout] symbptr
101 * The symbol structure to initialize.
102 *
103 *******************************************************************************/
104void
105pastixSymbolInit ( const pastix_graph_t *graph,
106 const pastix_order_t *order,
107 symbol_matrix_t *symbptr )
108{
109 memset (symbptr, 0, sizeof (symbol_matrix_t));
110 symbptr->dof = 1;
111 symbptr->schurfcol = -1;
112
113 if ( (graph != NULL) && (order != NULL) ) {
114 symbol_init_adddofs( graph, order, symbptr );
115 }
116
117 return;
118}
119
120/**
121 *******************************************************************************
122 *
123 * @brief Free the content of symbolic matrix.
124 *
125 * All the arrays from the structure are freed and the structure is memset to 0
126 * at exit, but the symbol itself is not freed. It will require a new call to
127 * pastixSymbolInit() if the memory space area needs to be reused for a new
128 * symbol matrix.
129 *
130 *******************************************************************************
131 *
132 * @param[inout] symbptr
133 * The pointer to the structure to free.
134 *
135 *******************************************************************************/
136void
138{
139 if (symbptr->dofs != NULL) {
140 memFree_null( symbptr->dofs );
141 }
142 if (symbptr->cblktab != NULL) {
143 memFree_null( symbptr->cblktab );
144 }
145 if (symbptr->bloktab != NULL) {
146 memFree_null( symbptr->bloktab );
147 }
148 if (symbptr->browtab != NULL) {
149 memFree_null( symbptr->browtab );
150 }
151 pastixSymbolInit( NULL, NULL, symbptr );
152}
153
154/**
155 *******************************************************************************
156 *
157 * @brief Reallocate the data structure to optimize the memory alignment.
158 *
159 * This function is used when the symbol need to be shrinked to a smaller or
160 * larger set of blocks and column blocks. The original data is copied in the
161 * new arrays.
162 *
163 *******************************************************************************
164 *
165 * @param[inout] symbptr
166 * The pointer to the structure that needs to be reallocated.
167 *
168 *******************************************************************************/
169void
171{
172 symbol_cblk_t *cblktab = NULL;
173 symbol_blok_t *bloktab = NULL;
174
175 /* Move column block array */
176 MALLOC_INTERN( cblktab, symbptr->cblknbr+1, symbol_cblk_t );
177 memcpy(cblktab, symbptr->cblktab, (symbptr->cblknbr + 1) * sizeof (symbol_cblk_t));
178 memFree(symbptr->cblktab);
179 symbptr->cblktab = cblktab;
180
181 /* Move block array */
182 MALLOC_INTERN( bloktab, symbptr->bloknbr, symbol_blok_t );
183 memcpy(bloktab, symbptr->bloktab, (symbptr->bloknbr) * sizeof (symbol_blok_t));
184 memFree(symbptr->bloktab);
185 symbptr->bloktab = bloktab;
186}
187
188/**
189 *******************************************************************************
190 *
191 * @brief Search the targeted block C for a couple of blocks A and B.
192 *
193 * When executing the simulation run to map the data on the cores, it requires
194 * to compute dependencies of each block. In that case for each couple of blocks
195 * A (defined by bloknum), and B (defined by bloksrc), we need to find the block
196 * that will receive the contribution for the matrix-matrix product. To speedup
197 * the search, the startsearch parameter can be given to specify that the index
198 * of the block searched is larger than this parameter. It returns the index of
199 * the C block when found, or -1 if no block is facing the update. This happens,
200 * only if ILU(k) factorization is applied and ricar is set to true. Otherwise,
201 * returning -1 is an error.
202 *
203 *******************************************************************************
204 *
205 * @param[in] symbptr
206 * The pointer to the structure that needs to be reallocated.
207 *
208 * @param[in] bloksrc
209 * Index of the block used as A in teh matrix-matrix product.
210 *
211 * @param[in] bloknum
212 * Index of the block used as B in teh matrix-matrix product.
213 *
214 * @param[in] startsearch
215 * Index of a block belonging to the facing cblk of B used as a
216 * starting point to find the index of C.
217 *
218 * @param[in] ricar
219 * Booleen to enable ILU(k) factorization or not
220 *
221 *******************************************************************************
222 *
223 * @retval -1 No block where found. This is an error if ricar is disabled,
224 * otherwise it means that the path is longer than the k parameter in
225 * the ILU(k) factorization.
226 *
227 * @retval i The index of the block C that will receive the contribution from
228 * A * B^t
229 *
230 *******************************************************************************/
233 pastix_int_t bloksrc,
234 pastix_int_t bloknum,
235 pastix_int_t startsearch,
236 int ricar )
237{
238 symbol_blok_t *bsrc;
239 symbol_blok_t *bdst;
240 pastix_int_t i, fcblknum, fbloknum, lbloknum;
241
242 fcblknum = symbptr->bloktab[bloksrc].fcblknm;
243 fbloknum = symbptr->cblktab[fcblknum].bloknum;
244 lbloknum = symbptr->cblktab[fcblknum+1].bloknum;
245
246 if(startsearch < fbloknum )
247 startsearch = fbloknum;
248
249 assert( startsearch < lbloknum );
250
251 /* Block in original column block */
252 bsrc = (symbptr->bloktab) + bloknum;
253
254 /* Search for the facing block in the facing column block */
255 bdst = (symbptr->bloktab) + startsearch;
256
257 if(ricar == 0)
258 {
259 for(i=startsearch; i<lbloknum; i++, bdst++ )
260 if( bdst->lrownum >= bsrc->frownum)
261 break;
262
263 /* We should always exit the loop in non ilu(k) mode */
264 assert( (bdst->frownum <= bsrc->frownum) &&
265 (bdst->lrownum >= bsrc->lrownum) );
266
267 return i;
268 }
269 else
270 {
271 for(i=startsearch; i<lbloknum; i++, bdst++)
272 {
273 if( ((bsrc->frownum >= bdst->frownum) && (bsrc->frownum <= bdst->lrownum)) ||
274 ((bsrc->lrownum >= bdst->frownum) && (bsrc->lrownum <= bdst->lrownum)) ||
275 ((bsrc->frownum <= bdst->frownum) && (bsrc->lrownum >= bdst->lrownum)) )
276 return i; /** We found the first block that matches **/
277
278 if(bsrc->lrownum < bdst->frownum)
279 {
280 return -1;
281 }
282 }
283 }
284 return -1;
285}
286
287/**
288 *******************************************************************************
289 *
290 * @brief Construct the browtab array that stores the blocks in a CSR way.
291 *
292 * The browtab is an equivalent of the columns array in a CSR for the symbolic
293 * structure in terms of block indexes.
294 *
295 *******************************************************************************
296 *
297 * @param[inout] symbptr
298 * The pointer to the symbolic structure to update.
299 *
300 *******************************************************************************/
301void
303{
304 symbol_cblk_t *cblk;
305 symbol_blok_t *blok;
306 pastix_int_t *innbr, *intmp, *browtab;
307 pastix_int_t itercblk;
308 pastix_int_t cblknbr;
309 pastix_int_t edgenbr = symbptr->bloknbr - symbptr->cblknbr;
310
311 symbptr->browmax = 0;
312 cblknbr = symbptr->cblknbr;
313
314 MALLOC_INTERN(innbr, cblknbr, pastix_int_t );
315 memset( innbr, 0, cblknbr * sizeof(pastix_int_t) );
316
317 /* Count the number of input edge per cblk */
318 cblk = symbptr->cblktab;
319 blok = symbptr->bloktab;
320 for(itercblk=0; itercblk<cblknbr; itercblk++, cblk++)
321 {
322 pastix_int_t iterblok = cblk[0].bloknum + 1;
323 pastix_int_t lbloknum = cblk[1].bloknum;
324
325 /* Skip diagonal block */
326 blok++;
327
328 /* Off-diagonal blocks */
329 for( ; iterblok < lbloknum; iterblok++, blok++)
330 {
331 innbr[ blok->fcblknm ]++;
332 }
333 }
334
335 /* Initialize the brownum fields */
336 cblk = symbptr->cblktab;
337 cblk->brownum = 0;
338 for(itercblk=0; itercblk<cblknbr; itercblk++, cblk++)
339 {
340 symbptr->browmax = pastix_imax( symbptr->browmax, innbr[ itercblk ] );
341 cblk[1].brownum = cblk[0].brownum + innbr[ itercblk ];
342 innbr[itercblk] = cblk[0].brownum;
343 }
344 assert( cblk[0].brownum == edgenbr );
345
346 /* Initialize the browtab */
347 MALLOC_INTERN( browtab, edgenbr, pastix_int_t );
348
349 cblk = symbptr->cblktab;
350 blok = symbptr->bloktab;
351 for(itercblk=0; itercblk<cblknbr; itercblk++, cblk++)
352 {
353 pastix_int_t iterblok = cblk[0].bloknum + 1;
354 pastix_int_t lbloknum = cblk[1].bloknum;
355
356 /* Skip diagonal block */
357 blok++;
358
359 /* Off-diagonal blocks */
360 for( ; iterblok < lbloknum; iterblok++, blok++)
361 {
362 intmp = innbr + blok->fcblknm;
363 browtab[ *intmp ] = iterblok;
364 (*intmp)++;
365 }
366 }
367
368 if (symbptr->browtab == NULL) {
369 memFree(symbptr->browtab);
370 }
371 symbptr->browtab = browtab;
372
373 memFree( innbr );
374 return;
375}
376
377/**
378 *******************************************************************************
379 *
380 * @brief Print statistical information about the symbolic matrix structure
381 *
382 *******************************************************************************
383 *
384 * @param[in] symbptr
385 * The pointer to the symbolic structure.
386 *
387 *******************************************************************************/
388void
390{
391 symbol_cblk_t *cblk;
392 symbol_blok_t *blok;
393 pastix_int_t itercblk, dof;
394 pastix_int_t cblknbr, bloknbr, cblksel;
395 pastix_int_t cblkmin, cblkmax;
396 pastix_int_t blokmin, blokmax;
397 double cblkavg1, blokavg1;
398 double cblkavg2, blokavg2;
399 size_t mem = 0;
400
401 cblknbr = symbptr->cblknbr;
402 cblksel = 0;
403 bloknbr = symbptr->bloknbr - cblknbr;
404 cblkmin = PASTIX_INT_MAX;
405 cblkmax = 0;
406 cblkavg1 = 0;
407 cblkavg2 = 0;
408 blokmin = PASTIX_INT_MAX;
409 blokmax = 0;
410 blokavg1 = 0;
411 blokavg2 = 0;
412
413 cblk = symbptr->cblktab;
414 blok = symbptr->bloktab;
415
416 for(itercblk=0; itercblk<cblknbr; itercblk++, cblk++)
417 {
418 pastix_int_t iterblok = cblk[0].bloknum + 1;
419 pastix_int_t lbloknum = cblk[1].bloknum;
420
421 pastix_int_t colnbr = cblk->lcolnum - cblk->fcolnum + 1;
422
423 cblksel += cblk->selevtx;
424 cblkmin = pastix_imin( cblkmin, colnbr );
425 cblkmax = pastix_imax( cblkmax, colnbr );
426 cblkavg1 += colnbr;
427 cblkavg2 += colnbr * colnbr;
428 blok++;
429
430 /* Only extra diagonal */
431 for( ; iterblok < lbloknum; iterblok++, blok++)
432 {
433 pastix_int_t rownbr = blok->lrownum - blok->frownum + 1;
434
435 blokmin = pastix_imin( blokmin, rownbr );
436 blokmax = pastix_imax( blokmax, rownbr );
437 blokavg1 += rownbr;
438 blokavg2 += rownbr * rownbr;
439 }
440 }
441
442 dof = symbptr->dof;
443 cblkmin *= dof;
444 cblkmax *= dof;
445 cblkavg1 = (cblkavg1 * (double)dof ) / (double)cblknbr;
446 cblkavg2 = sqrt( ((cblkavg2 * (double)dof * (double)dof) / (double)cblknbr) - cblkavg1 * cblkavg1 );
447
448 /* Check if we have at least one off-diagonal block */
449 if ( bloknbr > 0 ) {
450 blokmin *= dof;
451 blokmax *= dof;
452 blokavg1 = (blokavg1 * (double)dof ) / (double)bloknbr;
453 blokavg2 = sqrt( ((blokavg2 * (double)dof * (double)dof) / (double)bloknbr) - blokavg1 * blokavg1 );
454 }
455 else {
456 blokmin = 0;
457 blokmax = 0;
458 blokavg1 = 0.;
459 blokavg2 = 0.;
460 }
461
462 /* Compute symbol matrix space */
463 mem = sizeof( symbol_matrix_t );
464 mem += sizeof( symbol_cblk_t ) * (cblknbr + 1);
465 mem += sizeof( symbol_blok_t ) * symbptr->bloknbr;
466 mem += sizeof( pastix_int_t ) * bloknbr;
467
468 fprintf(stdout,
469 " Symbol Matrix statistics:\n"
470 " Number of cblk %10ld\n"
471 " Number of blok %10ld\n"
472 " Cblk width min %10ld\n"
473 " Cblk width max %10ld\n"
474 " Cblk width avg %11.2lf\n"
475 " Cblk width stdev %11.2lf\n"
476 " Blok height min %10ld\n"
477 " Blok height max %10ld\n"
478 " Blok height avg %11.2lf\n"
479 " Blok height stdev %11.2lf\n"
480 " Memory space %11.2lf %co\n",
481 (long)cblknbr, (long)bloknbr,
482 (long)cblkmin, (long)cblkmax, cblkavg1, cblkavg2,
483 (long)blokmin, (long)blokmax, blokavg1, blokavg2,
484 pastix_print_value( mem ),
485 pastix_print_unit( mem ) );
486
487 if ( cblksel > 0 ) {
488 fprintf( stdout,
489 " Number of selected cblk %10ld\n",
490 (long)cblksel );
491 }
492}
BEGIN_C_DECLS typedef int pastix_int_t
Definition datatypes.h:51
pastix_int_t baseval
Definition order.h:48
pastix_int_t * peritab
Definition order.h:52
Order structure.
Definition order.h:47
pastix_int_t fcblknm
Definition symbol.h:63
pastix_int_t frownum
Definition symbol.h:60
pastix_int_t lrownum
Definition symbol.h:61
pastix_int_t bloknbr
Definition symbol.h:80
pastix_int_t * browtab
Definition symbol.h:85
pastix_int_t baseval
Definition symbol.h:78
symbol_cblk_t * cblktab
Definition symbol.h:83
pastix_int_t schurfcol
Definition symbol.h:82
pastix_int_t browmax
Definition symbol.h:86
pastix_int_t bloknum
Definition symbol.h:48
pastix_int_t brownum
Definition symbol.h:49
pastix_int_t fcolnum
Definition symbol.h:46
pastix_int_t lcolnum
Definition symbol.h:47
pastix_int_t dof
Definition symbol.h:87
symbol_blok_t * bloktab
Definition symbol.h:84
pastix_int_t * dofs
Definition symbol.h:89
pastix_int_t cblknbr
Definition symbol.h:79
void pastixSymbolRealloc(symbol_matrix_t *symbptr)
Reallocate the data structure to optimize the memory alignment.
Definition symbol.c:170
void pastixSymbolInit(const pastix_graph_t *graph, const pastix_order_t *order, symbol_matrix_t *symbptr)
Initialize the symbol structure.
Definition symbol.c:105
void pastixSymbolPrintStats(const symbol_matrix_t *symbptr)
Print statistical information about the symbolic matrix structure.
Definition symbol.c:389
struct symbol_matrix_s symbol_matrix_t
Symbol matrix structure.
void pastixSymbolBuildRowtab(symbol_matrix_t *symbptr)
Construct the browtab array that stores the blocks in a CSR way.
Definition symbol.c:302
pastix_int_t pastixSymbolGetFacingBloknum(const symbol_matrix_t *symbptr, pastix_int_t bloksrc, pastix_int_t bloknum, pastix_int_t startsearch, int ricar)
Search the targeted block C for a couple of blocks A and B.
Definition symbol.c:232
struct symbol_blok_s symbol_blok_t
Symbol block structure.
struct symbol_cblk_s symbol_cblk_t
Symbol column block structure.
void pastixSymbolExit(symbol_matrix_t *symbptr)
Free the content of symbolic matrix.
Definition symbol.c:137
Symbol block structure.
Definition symbol.h:59
Symbol column block structure.
Definition symbol.h:45
Symbol matrix structure.
Definition symbol.h:77
static void symbol_init_adddofs(const pastix_graph_t *graph, const pastix_order_t *order, symbol_matrix_t *symbptr)
Add a dof array to the symbol matrix if any.
Definition symbol.c:50