From 0a499aa2b00a04a28576e4b87947eea504525e88 Mon Sep 17 00:00:00 2001 From: Mathieu Faverge <mathieu.faverge@inria.fr> Date: Thu, 31 Aug 2017 15:17:13 +0200 Subject: [PATCH] Add subroutines to introduce diagonal elements in graph structure for fake factorizations --- spm_gen_fake_values.c | 138 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 134 insertions(+), 4 deletions(-) diff --git a/spm_gen_fake_values.c b/spm_gen_fake_values.c index 7869c741..3c641618 100644 --- a/spm_gen_fake_values.c +++ b/spm_gen_fake_values.c @@ -34,8 +34,12 @@ * Array of size spm->n allocated on entry. On exit, contains the * degree of each vertex in the spm matrix. * + ******************************************************************************* + * + * @return the number of diagonal elements found during the computation. + * *******************************************************************************/ -static inline void +static inline pastix_int_t spm_compute_degrees( const pastix_spm_t *spm, pastix_int_t *degrees ) { @@ -43,6 +47,7 @@ spm_compute_degrees( const pastix_spm_t *spm, pastix_int_t *colptr = spm->colptr; pastix_int_t *rowptr = spm->rowptr; pastix_int_t baseval; + pastix_int_t diagval = 0; baseval = spmFindBase( spm ); memset( degrees, 0, spm->n * sizeof(pastix_int_t) ); @@ -65,6 +70,9 @@ spm_compute_degrees( const pastix_spm_t *spm, degrees[i] += 1; } } + else { + diagval++; + } } } break; @@ -81,8 +89,125 @@ spm_compute_degrees( const pastix_spm_t *spm, degrees[i] += 1; } } + else { + diagval++; + } } } + + return diagval; +} + +/** + ******************************************************************************* + * + * @ingroup spm_dev_driver + * + * @brief Insert diagonal elements to the graph to have a full Laplacian + * generated + * + ******************************************************************************* + * + * @param[in] spm + * At start, the initial spm structure with missing diagonal elements. + * At exit, contains the same sparse matrix with diagonal elements added. + * + * @param[in] diagval + * The number of diagonal elements already present in the matrix. + * + *******************************************************************************/ +static inline void +spm_add_diag( pastix_spm_t *spm, + pastix_int_t diagval ) +{ + pastix_spm_t oldspm; + pastix_int_t i, j, k; + pastix_int_t *oldcol = spm->colptr; + pastix_int_t *oldrow = spm->rowptr; + pastix_int_t *newrow, *newcol; + pastix_int_t baseval; + + baseval = spmFindBase( spm ); + + memcpy( &oldspm, spm, sizeof(pastix_spm_t)); + + spm->nnz = oldspm.nnz + (spm->n - diagval); + newrow = malloc( spm->nnz * sizeof(pastix_int_t) ); + + switch(spm->fmttype) + { + case PastixCSR: + /* Swap pointers to call CSC */ + oldcol = spm->rowptr; + oldrow = spm->colptr; + spm->colptr = newrow; + + case PastixCSC: + newcol = oldcol; + if ( spm->fmttype == PastixCSC ) { + spm->rowptr = newrow; + } + diagval = 0; + for(j=0; j<spm->n; j++, newcol++) { + pastix_int_t nbelt = newcol[1] - newcol[0]; + int diag = 0; + + memcpy( newrow, oldrow, nbelt * sizeof(pastix_int_t) ); + newrow += nbelt; + + for(k=0; k<nbelt; k++, oldrow++) { + i = *oldrow - baseval; + + if ( i == j ) { + diag = 1; + } + } + newcol[0] += diagval; + if ( !diag ) { + *newrow = j + baseval; + newrow++; + diagval++; + } + } + newcol[0] += diagval; + + if ( spm->fmttype == PastixCSC ) { + free( oldspm.rowptr ); + } + else { + free( oldspm.colptr ); + } + assert( diagval == spm->n ); + break; + + case PastixIJV: + newcol = malloc( spm->nnz * sizeof(pastix_int_t) ); + spm->colptr = newcol; + spm->rowptr = newrow; + + for(k=0; k<spm->n; k++, newrow++, newcol++) + { + *newrow = k + baseval; + *newcol = k + baseval; + } + + for(k=0; k<spm->nnz; k++, oldrow++, oldcol++) + { + i = *oldrow - baseval; + j = *oldcol - baseval; + + if ( i == j ) { + continue; + } + + *newrow = i + baseval; + *newcol = j + baseval; + newrow++; + newcol++; + } + free( oldspm.colptr ); + free( oldspm.rowptr ); + } } /** @@ -178,9 +303,9 @@ spm_generate_fake_values( pastix_spm_t *spm, void spmGenFakeValues( pastix_spm_t *spm ) { - pastix_int_t *degrees; + pastix_int_t *degrees, diagval; double alpha = 10.; - double beta = 1.; + double beta = 1.; assert( spm->flttype == PastixPattern ); assert( spm->values == NULL ); @@ -216,7 +341,12 @@ spmGenFakeValues( pastix_spm_t *spm ) } degrees = malloc( spm->n * sizeof(pastix_int_t)); - spm_compute_degrees( spm, degrees ); + diagval = spm_compute_degrees( spm, degrees ); + if ( diagval != spm->n ) { + /* Diagonal elements must be added to the sparse matrix */ + spm_add_diag( spm, diagval ); + spmUpdateComputedFields( spm ); + } spm_generate_fake_values( spm, degrees, alpha, beta ); free( degrees ); -- GitLab