diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..21caac4ee5dcc3c861e917b2b25660fd20cd08aa --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,55 @@ +include(RulesPrecisions) + +### reset variables +set(generated_sources "") +set(generated_headers "") + +set(HEADERS + z_spm.h +) + +### Generate the headers in all precisions +precisions_rules_py(generated_headers + "${HEADERS}" + PRECISIONS "p;s;d;c;z") + +set(SOURCES + z_spm.c + z_spm_convert_to_csc.c + z_spm_convert_to_csr.c + z_spm_convert_to_ijv.c + z_spm_genrhs.c + z_spm_matrixvector.c + z_spm_norm.c + z_spm_2dense.c + z_spm_print.c + ) + +set(spm_headers + ${generated_headers} + spm.h + ) + +### Generate the sources in all precisions +precisions_rules_py(generated_sources + "${SOURCES}" + PRECISIONS "p;s;d;c;z") + +set(spm_sources + ${generated_sources} + spm.c + spm_io.c + ) + +add_custom_target(spm_headers_tgt + DEPENDS ${spm_headers} ) + +set_source_files_properties( + spm.c + PROPERTIES DEPENDS spm_headers_tgt + ) + +set(PASTIX_LIB_SRCS + ${PASTIX_LIB_SRCS} + ${spm_sources} + ) diff --git a/spm.c b/spm.c index c08db2fd553d1468c401f00eb0fceeef2733ba29..7e6b362bc61c2402bdf64e2142f3827b58bca9bc 100644 --- a/spm.c +++ b/spm.c @@ -68,6 +68,46 @@ static int (*conversionTable[3][3][6])(pastix_spm_t*) = { }; +/** + ******************************************************************************* + * + * @ingroup pastix_spm + * + * spmInit - Init the spm structure given as parameter + * + ******************************************************************************* + * + * @param[in,out] spm + * The sparse matrix to init. + * + *******************************************************************************/ +void +spmInit( pastix_spm_t *spm ) +{ + spm->mtxtype = PastixGeneral; + spm->flttype = PastixComplex64; + spm->fmttype = PastixCSC; + + spm->gN = 0; + spm->n = 0; + spm->gnnz = 0; + spm->nnz = 0; + + spm->gNexp = 0; + spm->nexp = 0; + spm->gnnzexp = 0; + spm->nnzexp = 0; + + spm->dof = 1; + spm->dofs = NULL; + spm->colmajor = 1; + + spm->colptr = NULL; + spm->rowptr = NULL; + spm->loc2glob = NULL; + spm->values = NULL; +} + /** ******************************************************************************* * @@ -106,6 +146,10 @@ spmExit( pastix_spm_t *spm ) * ******************************************************************************* * + * @param[in] ofmttype + * The output format of the sparse matrix. It might be PastixCSC, + * PastixCSR, or PastixIJV. + * * @param[in,out] spm * The sparse matrix to rebase. * diff --git a/spm.h b/spm.h index 18fd91d2bccc60f8233e298cf976a90ad6b8c0b1..71fd46984fa014bdee1eb995297d11adb207c9b2 100644 --- a/spm.h +++ b/spm.h @@ -36,14 +36,24 @@ struct pastix_spm_s { int flttype; /**< avals datatype: PastixPattern, PastixFloat, PastixDouble, PastixComplex32 or PastixComplex64 */ int fmttype; /**< Matrix storage format: PastixCSC, PastixCSR, PastixIJV */ + pastix_int_t gN; /**< Global number of vertices in the compressed graph */ pastix_int_t n; /**< Local number of vertices in the compressed graph */ pastix_int_t gnnz; /**< Global number of non zeroes in the compressed graph */ pastix_int_t nnz; /**< Local number of non zeroes in the compressed graph */ + + pastix_int_t gNexp; /**< Global number of vertices in the compressed graph */ + pastix_int_t nexp; /**< Local number of vertices in the compressed graph */ + pastix_int_t gnnzexp; /**< Global number of non zeroes in the compressed graph */ + pastix_int_t nnzexp; /**< Local number of non zeroes in the compressed graph */ + pastix_int_t dof; /**< Number of degrees of freedom per unknown, if > 0, constant degree of freedom otherwise, irregular degree of freedom (refer to dofs) */ pastix_int_t *dofs; /**< Number of degrees of freedom per unknown (NULL, if dof > 0) */ + int colmajor; /**< If > 0, column major with dofs + otherwise, row major */ + pastix_int_t *colptr; /**< List of indirections to rows for each vertex */ pastix_int_t *rowptr; /**< List of edges for each vertex */ pastix_int_t *loc2glob; /**< Corresponding numbering from local to global */ @@ -89,4 +99,6 @@ pastix_int_t spmSymmetrize( pastix_spm_t *spm ); pastix_spm_t *spmCheckAndCorrect( pastix_spm_t *spm ); +void dofVar(pastix_spm_t* spm);//tmp + #endif /* _SPM_H_ */ diff --git a/spm_expand.c b/spm_expand.c new file mode 100644 index 0000000000000000000000000000000000000000..6dead986a5be667ed3d5cbd0327960fd32b7e4e5 --- /dev/null +++ b/spm_expand.c @@ -0,0 +1,207 @@ +/** + * + * @file spm_expand.c + * + * PaStiX spm routines + * PaStiX is a software package provided by Inria Bordeaux - Sud-Ouest, + * LaBRI, University of Bordeaux 1 and IPB. + * + * @version 5.1.0 + * @author Mathieu Faverge + * @author Theophile Terraz + * @author Alban Bellot + * @date 2015-01-01 + * + **/ +#include "common.h" +#include "spm.h" +#include "z_spm.h" + +void +spmExpandCSC(pastix_spm_t* spm) +{ + switch(spm->flttype) + { + case PastixFloat: + s_extandCSC(spm); + break; + case PastixComplex32: + c_extandCSC(spm); + break; + case PastixComplex64: + z_extandCSC(spm); + break; + case PastixDouble: + default: + d_extandCSC(spm); + break; + } +} + +void print_tab_int(pastix_int_t* tab, pastix_int_t size) +{ + int i; + for(i=0;i<size;i++) + printf("%d ",tab[i]); + printf("\n"); +} + +void print_tab_cpx(double* tab, pastix_int_t size) +{ + int i; + for(i=0;i<size;i++) + printf("%f ",tab[i]); + printf("\n"); +} + + +void init_rand() +{ + srand(time(NULL)); +} + +int randminmax(pastix_int_t min, pastix_int_t max) +{ + return min + rand()%(max-min+1); +} + +pastix_int_t* computeCorrespondIndex(const pastix_int_t *dofs, pastix_int_t n) +{ + pastix_int_t* dofs_coef=malloc(sizeof(pastix_int_t)*(n+1)); + dofs_coef[0]=0; + int i; + for(i=1;i<n+1;i++) + { + dofs_coef[i]=dofs_coef[i-1]+dofs[i-1]; + } + return dofs_coef; +} + +void genDof(pastix_int_t step,pastix_int_t* dofs,pastix_int_t size) +{ + int i; + for(i=0;i<size;i++) + dofs[i]=i%step+1; +} + +void genRandDof(pastix_int_t min,pastix_int_t max,pastix_int_t* dofs,pastix_int_t size) +{ + int i; + for(i=0;i<size;i++) + dofs[i]=randminmax(min,max); +} + +pastix_int_t* computeEltPerCol(const pastix_spm_t *spm) +{ + pastix_int_t col,row,baseval; + + pastix_int_t* coef=malloc(sizeof(pastix_int_t)*spm->n); + int i; + for(i=0;i<spm->n;i++) + coef[i]=0; + baseval=spmFindBase( spm ); + row=0; + for( col=0; col < spm->n; col++ ) + { + for( row=spm->colptr[col]-baseval; row<spm->colptr[col+1]-baseval; row++) + { + coef[col] += spm->dofs[col] * spm->dofs[spm->rowptr[row]-baseval]; + } + } + return coef; +} + +/** + ******************************************************************************* + * + * @ingroup spm_internal + * + * dofCst - Expand a CSC matrix without dofs into a CSC matrix with constant dofs + * + * + ******************************************************************************* + * + * @param[in] spm + * The spm to expand + * + *******************************************************************************/ +void +dofCst(pastix_spm_t* spm,pastix_int_t dof) +{ + int i; + pastix_int_t* dofs = malloc((spm->n+1)*sizeof(pastix_int_t)); + + spm->dof = dof; + spm->gNexp = spm->n*dof; + spm->nexp = spm->n*dof; + spm->nnzexp = spm->n*dof*dof; + spm->gnnzexp = spm->n*dof*dof; + spm->dofs = dofs; + + for(i=0;i<spm->n+1;i++) + dofs[i]=dof*i; + + spmExpandCSC(spm); +} + + +/** + ******************************************************************************* + * + * @ingroup spm_internal + * + * dofVar - Expand a CSC matrix without dofs into a CSC matrix with variable dofs + * + * + ******************************************************************************* + * + * @param[in] spm + * The spm to expand + * + *******************************************************************************/ +void +dofVar(pastix_spm_t* spm) +{ + pastix_int_t *dofs=malloc(sizeof(pastix_int_t)*spm->n); + pastix_int_t i,nnzexp,nexp; + + spm->gNexp = spm->gN; + spm->nexp = spm->n; + spm->gnnzexp = spm->gnnz; + spm->nnzexp = spm->nnz; + spm->dof = -1; + + genDof(3,dofs,spm->n); //cyclique, pas de 3 + //genRandDof(/*min*/1,/*max*/5 ,spm->dofs,spm->n); //random dofs, entre 1 et 5 + + spm->dofs = dofs; + pastix_int_t *coef = computeEltPerCol(spm); // free coef + + nnzexp = 0; + nexp = 0; + + for(i=0;i<spm->n;i++) + { + nnzexp += coef[i]; + nexp += spm->dofs[i]; + } + + spm->nnzexp = nnzexp; + spm->gnnzexp = nnzexp; + spm->gNexp = nexp; + spm->nexp = nexp; + + pastix_int_t* tab = computeCorrespondIndex(dofs,spm->n); + + spm->dofs = tab; + spmExpandCSC(spm); + + /* + print_tab_int(spm->colptr,spm->n); + print_tab_int(spm->rowptr,spm->nnz); + print_tab_cpx(spm->values,spm->nnzexp); + print_tab_int(spm->dofs,spm->n+1); + */ +} + + diff --git a/z_spm.h b/z_spm.h index 877da184bbc1a4e9a638d9e3f3d20889513373bb..886f39e90f5bc44a54728afc376c50d684e13d27 100644 --- a/z_spm.h +++ b/z_spm.h @@ -37,4 +37,15 @@ pastix_int_t z_spmSymmetrize( pastix_spm_t *csc ); int z_spmGenRHS(int type, int nrhs, const pastix_spm_t *spm, void *x, int ldx, void *b, int ldb ); int z_spmCheckAxb( int nrhs, const pastix_spm_t *spm, void *x0, int ldx0, void *b, int ldb, const void *x, int ldx ); +pastix_complex64_t *z_spm2dense( const pastix_spm_t *spm ); +void z_spmDensePrint( pastix_int_t m, pastix_int_t n, pastix_complex64_t *A, pastix_int_t lda ); +void z_spmPrint( const pastix_spm_t *spm ); + +void z_spmConvertColMaj2RowMaj(pastix_spm_t *spm); +void z_spmConvertRowMaj2ColMaj(pastix_spm_t *spm); + +void z_extandCSC(pastix_spm_t *spm); + +void z_spmDofs2Flat(pastix_spm_t *spm); + #endif /* _z_spm_H_ */ diff --git a/z_spm_2dense.c b/z_spm_2dense.c new file mode 100644 index 0000000000000000000000000000000000000000..ff3dddfa9e7cc8ffc8ca0ec5cf708a44aa6643fd --- /dev/null +++ b/z_spm_2dense.c @@ -0,0 +1,191 @@ +/** + * + * @file z_spm_2dense.c + * + * Convert a sparse matrix into a dense matrix. + * + * @version 5.1.0 + * @author Mathieu Faverge + * @author Theophile Terraz + * @author Alban Bellot + * @date 2015-01-01 + * + * @precisions normal z -> c d s + * + **/ +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <assert.h> +#include "pastix.h" +#include "common.h" +#include "spm.h" +#include "z_spm.h" + +pastix_complex64_t * +z_spm2dense( const pastix_spm_t *spm ) +{ + pastix_int_t i, j, lda, baseval; + pastix_complex64_t *A, *valptr; + pastix_int_t *colptr, *rowptr; + + assert( spm->fmttype == PastixCSC ); + assert( spm->flttype == PastixComplex64 ); + + lda = spm->gNexp; + A = (pastix_complex64_t*)malloc(lda * lda * sizeof(pastix_complex64_t)); + memset( A, 0, lda * lda * sizeof(pastix_complex64_t)); + + baseval = spmFindBase( spm ); + i = 0; j = 0; + + colptr = spm->colptr; + rowptr = spm->rowptr; + valptr = (pastix_complex64_t*)(spm->values); + + /** + * Constant degree of fredom of 1 + */ + if ( spm->dof == 1 ) { + switch( spm->mtxtype ){ +#if defined(PRECISION_z) || defined(PRECISION_c) + case PastixHermitian: + for(i=0; i<spm->n; i++, colptr++) + { + for(j=colptr[0]; j<colptr[1]; j++, rowptr++, valptr++) + { + A[ i * lda + (*rowptr - baseval) ] = *valptr; + A[ (*rowptr - baseval) * lda + i ] = conj(*valptr); + } + } + break; +#endif + case PastixSymmetric: + for(i=0; i<spm->n; i++, colptr++) + { + for(j=colptr[0]; j<colptr[1]; j++, rowptr++, valptr++) + { + A[ i * lda + (*rowptr - baseval) ] = *valptr; + A[ (*rowptr - baseval) * lda + i ] = *valptr; + } + } + break; + case PastixGeneral: + default: + for(i=0; i<spm->n; i++, colptr++) + { + for(j=colptr[0]; j<colptr[1]; j++, rowptr++, valptr++) + { + A[ i * lda + (*rowptr - baseval) ] = *valptr; + } + } + } + } + /** + * General degree of freedom (constant or variable) + */ + else { + pastix_int_t k, ii, jj, dofi, dofj, col, row; + pastix_int_t *dofs = spm->dofs; + + switch( spm->mtxtype ){ +#if defined(PRECISION_z) || defined(PRECISION_c) + case PastixHermitian: + for(i=0; i<spm->n; i++, colptr++) + { + dofi = ( spm->dof > 1 ) ? spm->dof : dofs[i+1] - dofs[i]; + col = dofs[i]; + + for(k=colptr[0]; k<colptr[1]; k++, rowptr++) + { + j = (*rowptr - baseval); + dofj = ( spm->dof > 1 ) ? spm->dof : dofs[j+1] - dofs[j]; + row = dofs[j]; + + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++, valptr++) + { + A[ (col + ii) * lda + (row + jj) ] = *valptr; + A[ (row + jj) * lda + (col + ii) ] = conj(*valptr); + } + } + } + } + break; +#endif + case PastixSymmetric: + for(i=0; i<spm->n; i++, colptr++) + { + dofi = ( spm->dof > 1 ) ? spm->dof : dofs[i+1] - dofs[i]; + col = dofs[i]; + + for(k=colptr[0]; k<colptr[1]; k++, rowptr++) + { + j = (*rowptr - baseval); + dofj = ( spm->dof > 1 ) ? spm->dof : dofs[j+1] - dofs[j]; + row = dofs[j]; + + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++, valptr++) + { + A[ (col + ii) * lda + (row + jj) ] = *valptr; + A[ (row + jj) * lda + (col + ii) ] = *valptr; + } + } + } + } + break; + case PastixGeneral: + default: + for(i=0; i<spm->n; i++, colptr++) + { + dofi = ( spm->dof > 1 ) ? spm->dof : dofs[i+1] - dofs[i]; + col = dofs[i]; + + for(k=colptr[0]; k<colptr[1]; k++, rowptr++) + { + j = (*rowptr - baseval); + dofj = ( spm->dof > 1 ) ? spm->dof : dofs[j+1] - dofs[j]; + row = dofs[j]; + + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++, valptr++) + { + A[ (col + ii) * lda + (row + jj) ] = *valptr; + } + } + } + } + } + } + return A; +} + +void +z_spmDensePrint( pastix_int_t m, pastix_int_t n, pastix_complex64_t *A, pastix_int_t lda ) +{ + pastix_int_t i, j; + + for(i=0; i<m; i++) + { + for(j=0; j<n; j++) + { + if ( cabs( A[ lda *j + i] ) != 0. ) { +#if defined(PRECISION_z) || defined(PRECISION_c) + fprintf( stderr, "%ld %ld (%e, %e)\n", + i, j, creal(A[lda * j + i]), cimag(A[lda * j + i]) ); +#else + fprintf( stderr, "%ld %ld %e\n", + i, j, A[lda * j + i] ); +#endif + } + } + } + return; +} + diff --git a/z_spm_convert_col_row_major.c b/z_spm_convert_col_row_major.c new file mode 100644 index 0000000000000000000000000000000000000000..e13b28ff81b1ca64faf352a9e0d164a445e44270 --- /dev/null +++ b/z_spm_convert_col_row_major.c @@ -0,0 +1,220 @@ +/** + * + * @file z_spm_convert_col_row_major.c + * + * PaStiX spm routines + * PaStiX is a software package provided by Inria Bordeaux - Sud-Ouest, + * LaBRI, University of Bordeaux 1 and IPB. + * + * @version 5.1.0 + * @author Mathieu Faverge + * @author Theophile Terraz + * @author Alban Bellot + * @date 2015-01-01 + * + * @precisions normal z -> c d s p + **/ +#include "common.h" +#include "spm.h" +#include "z_spm.h" + +/** + ******************************************************************************* + * + * @ingroup pastix_spm + * + * z_spmConvertColMaj2RowMaj - convert a matrix in Column Major format to a + * matrix in Row Major format. + * + ******************************************************************************* + * + * @param[in,out] spm + * The colmaj matrix at enter, + * the rowmaj matrix at exit. + * + *******************************************************************************/ +void +z_spmConvertColMaj2RowMaj(pastix_spm_t *spm) +{ + assert(spm->colmajor > 0); + assert(spm->dof != 1); + assert(spm->dofs); + + spm->colmajor = -1; + + pastix_int_t dofi, dofj, ii, jj, i, j, k, baseval; + pastix_int_t cpt=0; + pastix_int_t *dofs = spm->dofs; + pastix_int_t *tmp; + pastix_complex64_t *oavals, *navals; + + baseval = spmFindBase( spm ); + + oavals = (pastix_complex64_t*)spm->values; + navals = malloc(sizeof(pastix_complex64_t)*spm->nnzexp); + + switch(spm->fmttype) + { + case PastixCSC: + for(i=0; i<spm->n; i++) + { + //dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + dofi = dofs[i+1] - dofs[i]; + for(k=spm->colptr[i]; k<spm->colptr[i+1]; k++) + { + j = spm->rowptr[k-baseval] - baseval; + //dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + dofj = dofs[j+1] - dofs[j]; + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++) + { + navals[cpt + jj * dofi + ii] = *oavals; + oavals++; + } + } + cpt += dofi * dofj; + } + } + spm->values = navals; + break; + + case PastixCSR: + tmp = spm->rowptr; + spm->rowptr = spm->colptr; + spm->colptr = tmp; + spm->fmttype = PastixCSC; + + z_spmConvertRowMaj2ColMaj(spm); + + spm->colmajor = -1; + tmp = spm->rowptr; + spm->rowptr = spm->colptr; + spm->colptr = tmp; + spm->fmttype = PastixCSR; + break; + + case PastixIJV: + for(k=0; k<spm->nnz; k++) + { + j = spm->rowptr[k]-baseval; + i = spm->colptr[k]-baseval; + //dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + //dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + dofi = dofs[i+1] - dofs[i]; + dofj = dofs[j+1] - dofs[j]; + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++) + { + navals[cpt + jj * dofi + ii] = *oavals; + oavals++; + } + } + cpt += dofi * dofj; + } + spm->values = navals; + default: + break; + } +} + +/** + ******************************************************************************* + * + * @ingroup pastix_spm + * + * z_spmConvertColMaj2RowMaj - convert a matrix in Row Major format to a matrix + * in Column Major format. + * + ******************************************************************************* + * + * @param[in,out] spm + * The rowmaj matrix at enter, + * the colmaj matrix at exit. + * + *******************************************************************************/ +void +z_spmConvertRowMaj2ColMaj(pastix_spm_t *spm) +{ + assert(spm->colmajor < 0); + assert(spm->dof != 1); + assert(spm->dofs); + + spm->colmajor = 1; + pastix_int_t dofi, dofj, ii, jj, i, j, k, baseval; + pastix_int_t cpt=0; + pastix_int_t *dofs = spm->dofs; + pastix_int_t *tmp; + pastix_complex64_t *oavals, *navals; + + baseval = spmFindBase( spm ); + + oavals = (pastix_complex64_t*)spm->values; + navals = malloc(sizeof(pastix_complex64_t)*spm->nnzexp); + + switch(spm->fmttype) + { + case PastixCSC : + for(i=0; i<spm->n; i++) + { + //dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + dofi = dofs[i+1] - dofs[i]; + for(k=spm->colptr[i]; k<spm->colptr[i+1]; k++) + { + j = spm->rowptr[k-baseval]-baseval; + //dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + dofj = dofs[j+1] - dofs[j]; + for(jj=0; jj<dofj; jj++) + { + for(ii=0; ii<dofi; ii++) + { + navals[cpt + ii * dofj + jj] = *oavals; + oavals++; + } + } + cpt += dofi * dofj; + } + } + spm->values = navals; + break; + + case PastixCSR : + tmp = spm->rowptr; + spm->rowptr = spm->colptr; + spm->colptr = tmp; + spm->fmttype = PastixCSC; + + z_spmConvertColMaj2RowMaj(spm); + + spm->colmajor = 1; + tmp = spm->rowptr; + spm->rowptr = spm->colptr; + spm->colptr = tmp; + spm->fmttype = PastixCSR; + break; + + case PastixIJV: + for(k=0; k<spm->nnz; k++) + { + j = spm->rowptr[k]-baseval; + i = spm->colptr[k]-baseval; + //dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + //dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + dofi = dofs[i+1] - dofs[i]; + dofj = dofs[j+1] - dofs[j]; + for(jj=0; jj<dofj; jj++) + { + for(ii=0; ii<dofi; ii++) + { + navals[cpt + ii * dofj + jj] = *oavals; + oavals++; + } + } + cpt += dofi * dofj; + } + spm->values = navals; + default: + break; + } +} diff --git a/z_spm_convert_to_csc.c b/z_spm_convert_to_csc.c index bd76019cc490bee69ae093d8693344a48c6ab963..5ec2702ca00c13cb679e5f63ec68d1d6940e60d5 100644 --- a/z_spm_convert_to_csc.c +++ b/z_spm_convert_to_csc.c @@ -9,6 +9,7 @@ * @version 5.1.0 * @author Mathieu Faverge * @author Theophile Terraz + * @author Alban Bellot * @date 2015-01-01 * * @precisions normal z -> c d s p @@ -80,11 +81,45 @@ z_spmConvertIJV2CSC( pastix_spm_t *spm ) /* Sort the rows and avals arrays by column */ spm->rowptr = malloc(spm->nnz * sizeof(pastix_int_t)); + pastix_int_t *node = calloc(spm->nnz+1,sizeof(pastix_int_t)); + pastix_int_t *old_node = calloc(spm->nnz+1,sizeof(pastix_int_t)); + pastix_int_t *dofs = spm->dofs; + pastix_int_t row, col, dofi, dofj; + + for(i=0; i<spm->nnz; i++) + { + row = oldspm.rowptr[i]-baseval; + col = oldspm.colptr[i]-baseval; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[col+1] - dofs[col]; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[row+1] - dofs[row]; + old_node[i+1] = dofi * dofj; + node[spm->colptr[col]+1] += dofi * dofj; + spm->colptr[col]++; + } + + for(i=0;i<spm->nnz;i++) + { + node[i+1]+=node[i]; + old_node[i+1]+=old_node[i]; + } + + /* Restore the colptr indexes */ + { + pastix_int_t tmp, tmp2; + tmp = spm->colptr[0]; + spm->colptr[0] = 0; + for (j=0; j<spm->n; j++) { + tmp2 = spm->colptr[j+1]; + spm->colptr[j+1] = tmp; + tmp = tmp2; + } + } #if defined(PRECISION_p) spm->values = NULL; #else - spm->values = malloc(spm->nnz * sizeof(pastix_complex64_t)); + pastix_int_t ii, jj; + spm->values = malloc(spm->nnzexp * sizeof(pastix_complex64_t)); navals = (pastix_complex64_t*)(spm->values); oavals = (pastix_complex64_t*)(oldspm.values); #endif @@ -92,11 +127,20 @@ z_spmConvertIJV2CSC( pastix_spm_t *spm ) for (j=0; j<spm->nnz; j++) { i = oldspm.colptr[j] - baseval; - spm->rowptr[ spm->colptr[i] ] = oldspm.rowptr[j]; #if !defined(PRECISION_p) - navals[ spm->colptr[i] ] = oavals[j]; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[oldspm.rowptr[j]-baseval+1] - dofs[oldspm.rowptr[j]-baseval]; + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++) + { + navals[node[spm->colptr[i]]] = oavals[ old_node[j]]; + old_node[j]++; + node[spm->colptr[i]]++; + } + } #endif (spm->colptr[i])++; @@ -106,7 +150,6 @@ z_spmConvertIJV2CSC( pastix_spm_t *spm ) /* Rebuild the colptr with the correct baseval */ tmp = spm->colptr[0]; spm->colptr[0] = baseval; - spmptx = spm->colptr + 1; for (i=1; i<(spm->n+1); i++, spmptx++) { @@ -119,7 +162,7 @@ z_spmConvertIJV2CSC( pastix_spm_t *spm ) spmExit( &oldspm ); spm->fmttype = PastixCSC; - + spm->colmajor = 1; return PASTIX_SUCCESS; } @@ -152,6 +195,10 @@ z_spmConvertCSR2CSC( pastix_spm_t *spm ) spm->fmttype = PastixCSC; + pastix_int_t type = spm->mtxtype; + if(spm->dof != 1) + spm->mtxtype = PastixGeneral; + switch( spm->mtxtype ) { #if defined(PRECISION_z) || defined(PRECISION_c) case PastixHermitian: @@ -184,26 +231,36 @@ z_spmConvertCSR2CSC( pastix_spm_t *spm ) { pastix_int_t *row_csc; pastix_int_t *col_csc; + pastix_int_t *node; + pastix_int_t *dofs; + #if !defined(PRECISION_p) pastix_complex64_t *val_csc; pastix_complex64_t *valptr = (pastix_complex64_t*)(spm->values); + pastix_int_t ii, jj; + int cpt = 0; #endif - pastix_int_t j, k, col, row, nnz, baseval; + pastix_int_t i, j, k, col, row, nnz, baseval; + pastix_int_t dofi, dofj; baseval = spmFindBase( spm ); nnz = spm->nnz; row_csc = malloc(nnz * sizeof(pastix_int_t)); col_csc = calloc(spm->n+1,sizeof(pastix_int_t)); + node = calloc(spm->nnz+1,sizeof(pastix_int_t)); + dofs = spm->dofs; assert( row_csc ); assert( col_csc ); + assert( node ); + assert( ( (dofs) && !(spm->dof > 0) ) || + ( !(dofs) && (spm->dof > 0) ) ); // (dofs) xor (spm->dof > 0) #if !defined(PRECISION_p) - val_csc = malloc(nnz*sizeof(pastix_complex64_t)); + val_csc = malloc(spm->nnzexp*sizeof(pastix_complex64_t)); assert( val_csc ); #endif - /* Count the number of elements per column */ for (j=0; j<nnz; j++) { col = spm->colptr[j] - baseval; @@ -217,6 +274,35 @@ z_spmConvertCSR2CSC( pastix_spm_t *spm ) col_csc[j+1] += col_csc[j]; } + for(i=0; i<spm->n; i++) + { + for(k=spm->rowptr[i]; k<spm->rowptr[i+1]; k++) + { + j = spm->colptr[k-baseval] - baseval; + row = ( spm->dof > 0 ) ? j : dofs[j]; + col = ( spm->dof > 0) ? i : dofs[i]; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + node[col_csc[j]+1] += dofi * dofj; + col_csc[j]++; + } + } + + for(i=0;i <spm->nnz; i++) + node[i+1] += node[i]; + + /* Restore the colptr indexes */ + { + pastix_int_t tmp, tmp2; + tmp = col_csc[0]; + col_csc[0] = 0; + for (j=0; j<spm->n; j++) { + tmp2 = col_csc[j+1]; + col_csc[j+1] = tmp; + tmp = tmp2; + } + } + assert( (col_csc[spm->gN]) == nnz ); for (row=0; row<spm->n; row++) { @@ -227,27 +313,34 @@ z_spmConvertCSR2CSC( pastix_spm_t *spm ) col = spm->colptr[k] - baseval; j = col_csc[col]; row_csc[j] = row + baseval; - #if !defined(PRECISION_p) - val_csc[j] = valptr[k]; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[col+1] - dofs[col]; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[row+1] - dofs[row]; + for(jj=0; jj < dofj ; jj++) + { + for(ii=0; ii < dofi ; ii++) + { + val_csc[node[j] + ii * dofj + jj] = valptr[cpt]; + cpt++; + } + } #endif - col_csc[col] ++; + col_csc[col]++; } } /* Restore the colptr indexes */ { pastix_int_t tmp, tmp2; - tmp = col_csc[0]; col_csc[0] = baseval; - for (j=0; j<spm->n; j++) { + for (j=0; j<spm->n; j++) + { tmp2 = col_csc[j+1]; col_csc[j+1] = tmp + baseval; tmp = tmp2; } } - spmExit( spm ); spm->colptr = col_csc; spm->rowptr = row_csc; @@ -259,5 +352,8 @@ z_spmConvertCSR2CSC( pastix_spm_t *spm ) } } + if(spm-> dof != 1) + spm->mtxtype = type; + spm->colmajor = 1; return PASTIX_SUCCESS; } diff --git a/z_spm_convert_to_csr.c b/z_spm_convert_to_csr.c index c1d0d4582f0d2edd50c74a231cb6a1419dbfcd50..73822a86722ff523d42c41e67fcbef29b10ddf28 100644 --- a/z_spm_convert_to_csr.c +++ b/z_spm_convert_to_csr.c @@ -9,6 +9,7 @@ * @version 5.1.0 * @author Mathieu Faverge * @author Theophile Terraz + * @authot Alban Bellot * @date 2015-01-01 * * @precisions normal z -> c d s p @@ -43,6 +44,10 @@ z_spmConvertCSC2CSR( pastix_spm_t *spm ) { pastix_int_t *tmp; pastix_int_t result; + pastix_int_t type = spm->mtxtype; + + if(spm->dof != 1) + spm->mtxtype = PastixGeneral; switch( spm->mtxtype ) { #if defined(PRECISION_z) || defined(PRECISION_c) @@ -66,7 +71,6 @@ z_spmConvertCSC2CSR( pastix_spm_t *spm ) spm->rowptr = spm->colptr; spm->colptr = tmp; spm->fmttype = PastixCSR; - return PASTIX_SUCCESS; } break; @@ -91,6 +95,10 @@ z_spmConvertCSC2CSR( pastix_spm_t *spm ) } } + if(spm-> dof != 1) + spm->mtxtype = type; + spm->colmajor = -1; + return result; } @@ -123,16 +131,53 @@ z_spmConvertIJV2CSR( pastix_spm_t *spm ) #endif pastix_int_t *spmptx, *otmp; pastix_int_t i, j, tmp, baseval, total; - pastix_spm_t oldspm; + pastix_int_t row, col, dofi, dofj; - /* Backup the input */ - memcpy( &oldspm, spm, sizeof(pastix_spm_t) ); + pastix_int_t *node = calloc(spm->nnz+1,sizeof(pastix_int_t)); + pastix_int_t *old_node = calloc(spm->nnz+1,sizeof(pastix_int_t)); + pastix_int_t *dofs = spm->dofs; + + pastix_spm_t oldspm; /* * Check the baseval, we consider that arrays are sorted by columns or rows */ baseval = spmFindBase( spm ); +#if !defined(PRECISION_p) + pastix_int_t ii, jj, k; + /* Transpose values in row major format */ + if( spm->colmajor ) + { + pastix_int_t cpt=0; + pastix_int_t* dofs = spm->dofs; + + oavals = (pastix_complex64_t*)spm->values; + navals = malloc(sizeof(pastix_complex64_t)*spm->nnzexp); + + for(k=0; k<spm->nnz; k++) + { + j = spm->rowptr[k]-baseval; + i = spm->colptr[k]-baseval; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++) + { + navals[cpt + jj * dofi + ii] = *oavals; + oavals++; + } + } + cpt += dofi * dofj; + } + spm->values = navals; + } +#endif + + /* Backup the input */ + memcpy( &oldspm, spm, sizeof(pastix_spm_t) ); + /* Compute the new rowptr */ spm->rowptr = (pastix_int_t *) calloc(spm->n+1,sizeof(pastix_int_t)); @@ -158,10 +203,39 @@ z_spmConvertIJV2CSR( pastix_spm_t *spm ) /* Sort the colptr and avals arrays by rows */ spm->colptr = malloc(spm->nnz * sizeof(pastix_int_t)); + for(i=0; i<spm->nnz; i++) + { + row = oldspm.rowptr[i]-baseval; + col = oldspm.colptr[i]-baseval; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[col+1] - dofs[col]; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[row+1] - dofs[row]; + old_node[i+1] = dofi * dofj; + node[spm->rowptr[row]+1] += dofi * dofj; + spm->rowptr[row]++; + } + + for(i=0;i<spm->nnz;i++) + { + node[i+1]+=node[i]; + old_node[i+1]+=old_node[i]; + } + + /* Restore the rowptr indexes */ + { + pastix_int_t tmp, tmp2; + tmp = spm->rowptr[0]; + spm->rowptr[0] = 0; + for (j=0; j<spm->n; j++) { + tmp2 = spm->rowptr[j+1]; + spm->rowptr[j+1] = tmp; + tmp = tmp2; + } + } + #if defined(PRECISION_p) spm->values = NULL; #else - spm->values = malloc(spm->nnz * sizeof(pastix_complex64_t)); + spm->values = malloc(spm->nnzexp * sizeof(pastix_complex64_t)); navals = (pastix_complex64_t*)(spm->values); oavals = (pastix_complex64_t*)(oldspm.values); #endif @@ -173,7 +247,17 @@ z_spmConvertIJV2CSR( pastix_spm_t *spm ) spm->colptr[ spm->rowptr[i] ] = oldspm.colptr[j]; #if !defined(PRECISION_p) - navals[ spm->rowptr[i] ] = oavals[j]; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[oldspm.colptr[j]-baseval+1] - dofs[oldspm.colptr[j]-baseval]; + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++) + { + navals[node[spm->rowptr[i]]] = oavals[ old_node[j]]; + old_node[j]++; + node[spm->rowptr[i]]++; + } + } #endif (spm->rowptr[i])++; @@ -195,7 +279,9 @@ z_spmConvertIJV2CSR( pastix_spm_t *spm ) spmExit( &oldspm ); + spm->colmajor = -1; spm->fmttype = PastixCSR; return PASTIX_SUCCESS; } + diff --git a/z_spm_convert_to_ijv.c b/z_spm_convert_to_ijv.c index 6ab25d095da59c6dc59bcf576e9afcc1c5544472..457f353169a6c87eb36c90e28883bc378c3185a5 100644 --- a/z_spm_convert_to_ijv.c +++ b/z_spm_convert_to_ijv.c @@ -9,6 +9,7 @@ * @version 5.1.0 * @author Mathieu Faverge * @author Theophile Terraz + * @author Alban Bellot * @date 2015-01-01 * * @precisions normal z -> c d s p @@ -62,6 +63,37 @@ z_spmConvertCSC2IJV( pastix_spm_t *spm ) } } + /* Transpose values in row major format */ + /* + if( spm->colmajor < 1 ) //A test + { + int k, ii, jj, dofi, dofj; + int cpt = 0; + pastix_complex64_t* oavals = (pastix_complex64_t*)spm->values; + pastix_complex64_t* navals = malloc(sizeof(pastix_complex64_t)*spm->nnzexp); + pastix_int_t* dofs=spm->dofs; + + for(k=0; k<spm->nnz; k++) + { + j = spm->rowptr[k]-baseval; + i = col_ijv[k]-baseval; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++) + { + navals[cpt + jj * dofi + ii] = *oavals; + oavals++; + } + } + cpt += dofi * dofj; + } + spm->values = navals; + } + + */ + memFree_null(spm->colptr); spm->colptr = col_ijv; @@ -113,6 +145,35 @@ z_spmConvertCSR2IJV( pastix_spm_t *spm ) } } + /* Transpose values in column major format */ + /* + if( spm->colmajor > 1 ) + { + pastix_int_t k, ii, jj, dofi, dofj; + pastix_int_t cpt=0; + pastix_complex64_t* oavals = (pastix_complex64_t*)spm->values; + pastix_complex64_t* navals = malloc(sizeof(pastix_complex64_t)*spm->nnzexp); + pastix_int_t* dofs=spm->dofs; + for(k=0; k<spm->nnz; k++) + { + i = spm->colptr[k]-baseval; + j = row_ijv[k]-baseval; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + for(jj=0; jj<dofj; jj++) + { + for(ii=0; ii<dofi; ii++) + { + navals[cpt + ii * dofj + jj] = *oavals; + oavals++; + } + } + cpt += dofi * dofj; + } + spm->values = navals; + } + */ + memFree_null(spm->rowptr); spm->rowptr = row_ijv; diff --git a/z_spm_dofs2flat.c b/z_spm_dofs2flat.c new file mode 100644 index 0000000000000000000000000000000000000000..b4db59f69be193c6f9eaadbef6fcfe78e1bf8ce5 --- /dev/null +++ b/z_spm_dofs2flat.c @@ -0,0 +1,233 @@ +/** + * + * @file z_spm_dofs2flat.c + * + * PaStiX spm routines + * PaStiX is a software package provided by Inria Bordeaux - Sud-Ouest, + * LaBRI, University of Bordeaux 1 and IPB. + * + * @version 5.1.0 + * @author Mathieu Faverge + * @author Theophile Terraz + * @author Alban Bellot + * @date 2015-01-01 + * + * @precisions normal z -> c d s + * + **/ +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <assert.h> +#include "pastix.h" +#include "common.h" +#include "spm.h" +#include "z_spm.h" + +/** + ******************************************************************************* + * + * @ingroup spm_internal + * + * z_spmDofs2Flat - Convert a sparse matrix with dofs into a sparse matrix without dofs. + * + * + ******************************************************************************* + * + * @param[in] spm + * The sparse matrix which needs to be converted + * + ******************************************************************************* + **/ +void +z_spmDofs2Flat(pastix_spm_t *spm) +{ + pastix_int_t i, j, k, ii, jj, dofi, dofj, col, row, baseval, cpt; + baseval = spmFindBase( spm ); + + pastix_int_t *new_col = calloc(spm->nexp+1,sizeof(pastix_int_t)); + pastix_int_t *new_row; + pastix_int_t *dofs = spm->dofs; + + pastix_complex64_t *new_vals; + pastix_complex64_t *vals = (pastix_complex64_t*)spm->values; + + switch(spm->mtxtype) + { + case PastixGeneral: + new_row = malloc(sizeof(pastix_int_t)*spm->nnzexp); + new_vals = malloc(sizeof(pastix_complex64_t)*spm->nnzexp); + for(i=0;i<spm->n ; i++) + { + col = ( spm->dof > 0 ) ? i : dofs[i]; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + for(k=spm->colptr[i]-baseval; k<spm->colptr[i+1]-baseval; k++) + { + j = spm->rowptr[k]-baseval; + row = ( spm->dof > 0 ) ? j : dofs[j]; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + for(ii=0; ii<dofi; ii++) + { + new_col[col+ii+1] += dofj; + } + } + } + + for(i=0; i<spm->nexp; i++) + { + new_col[i+1]+=new_col[i]; + } + + cpt = 0; + for(i=0; i < spm->n;i++) + { + col = ( spm->dof > 0 ) ? i : dofs[i]; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + for(k=spm->colptr[i]-baseval ; k<spm->colptr[i+1]-baseval ;k++) + { + j = spm->rowptr[k] - baseval; + row = ( spm->dof > 0 ) ? j : dofs[j]; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + for(ii=0;ii < dofi; ii++) + { + for(jj=0;jj < dofj ; jj++) + { + new_vals[new_col[col+ii]] = vals[cpt]; + new_row[new_col[col+ii]] = row + jj + baseval; + new_col[col+ii]++; + cpt++; + } + } + } + } + + { + int tmp; + int tmp1 = 0; + for(i=0; i<spm->nexp; i++) + { + tmp = new_col[i]; + new_col[i] = tmp1+baseval; + tmp1 = tmp; + } + new_col[i] += baseval; + } + spm->gN = spm->gNexp; + spm->n = spm->nexp; + spm->gnnz = spm->gnnzexp; + spm->nnz = spm->nnzexp; + + spm->dof = 1; + spm->dofs = NULL; + spm->colmajor = 1; + + spm->colptr = new_col; + spm->rowptr = new_row; + //spm->loc2glob = NULL; // ? + spm->values = new_vals; + break; + + case PastixSymmetric: + for(i=0;i<spm->n ; i++) + { + col = ( spm->dof > 0 ) ? i : dofs[i]; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + for(k=spm->colptr[i]-baseval; k<spm->colptr[i+1]-baseval; k++) + { + j = spm->rowptr[k]-baseval; + row = ( spm->dof > 0 ) ? j : dofs[j]; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++) + { + if( i != j ) + new_col[col+ii+1] += 1; + else + if(ii <= jj ) + new_col[col+ii+1] += 1; + } + } + } + } + for(i=0; i<spm->nexp; i++) + { + new_col[i+1] += new_col[i]; + } + pastix_int_t nnz = new_col[spm->nexp]; + new_row = malloc(sizeof(pastix_int_t)*nnz); + new_vals = malloc(sizeof(pastix_complex64_t)*nnz); + + cpt = 0; + for(i=0; i < spm->n;i++) + { + col = ( spm->dof > 0 ) ? i : dofs[i]; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + for(k=spm->colptr[i]-baseval ; k<spm->colptr[i+1]-baseval ;k++) + { + j = spm->rowptr[k] - baseval; + row = ( spm->dof > 0 ) ? j : dofs[j]; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + for(ii=0;ii < dofi; ii++) + { + for(jj=0;jj < dofj ; jj++) + { + if( i == j ) + { + if ( ii <= jj ) + { + /* diagonal dominant for spd matrix + if( ii == jj) + new_vals[new_col[col+ii]] = 2*vals[cpt]; + else + */ + new_vals[new_col[col+ii]] = vals[cpt]; + new_row[new_col[col+ii]] = row + jj + baseval; + new_col[col+ii]++; + } + } + else + { + new_vals[new_col[col+ii]] = vals[cpt]; + new_row[new_col[col+ii]] = row + jj + baseval; + new_col[col+ii]++; + + } + cpt++; + } + } + } + } + { + int tmp; + int tmp1 = 0; + for(i=0; i<spm->nexp; i++) + { + tmp = new_col[i]; + new_col[i] = tmp1+baseval; + tmp1 = tmp; + } + new_col[i] += baseval; + } + spm->gN = spm->gNexp; + spm->n = spm->nexp; + spm->gnnz = nnz; + spm->nnz = nnz; + spm->gnnzexp = nnz; + spm->nnzexp = nnz; + + spm->dof = 1; + spm->dofs = NULL; + spm->colmajor = 1; + + spm->colptr = new_col; + spm->rowptr = new_row; + //spm->loc2glob = NULL; // + spm->values = new_vals; + + break; + } + assert(spm->loc2glob == NULL);//to do +} diff --git a/z_spm_expand.c b/z_spm_expand.c new file mode 100644 index 0000000000000000000000000000000000000000..8167b0c537ae154e49c418a2dcb9c14253769042 --- /dev/null +++ b/z_spm_expand.c @@ -0,0 +1,46 @@ +/** + * + * @file z_spm_expand.c + * + * PaStiX spm routines + * PaStiX is a software package provided by Inria Bordeaux - Sud-Ouest, + * LaBRI, University of Bordeaux 1 and IPB. + * + * @version 5.1.0 + * @author Mathieu Faverge + * @author Theophile Terraz + * @author Alban Bellot + * @date 2015-01-01 + * + * @precisions normal z -> c d s p + **/ +#include "common.h" +#include "spm.h" +#include "z_spm.h" + + +void z_extandCSC(pastix_spm_t* spm) +{ + pastix_int_t col, row, i, cpt, dofj, dofi, baseval; + cpt=0; + + pastix_complex64_t *valptr = (pastix_complex64_t*)spm->values; + pastix_complex64_t *newval = calloc(spm->nnzexp,sizeof(pastix_complex64_t)); + + baseval=spmFindBase( spm ); + + for( col=0; col<spm->n; col++) + { + for( row=spm->colptr[col]-baseval; row<spm->colptr[col+1]-baseval; row++) + { + dofi = ( spm->dof > 0 ) ? spm->dof : spm->dofs[col+1] - spm->dofs[col]; + dofj = ( spm->dof > 0 ) ? spm->dof : spm->dofs[spm->rowptr[row]-baseval+1] - spm->dofs[spm->rowptr[row]-baseval]; + for( i=0; i<dofi*dofj; i++) + { + newval[cpt] = valptr[row] / ((i/dofj) + (i%dofj) + 2); // Col major + cpt++; + } + } + } + spm->values=newval; +} diff --git a/z_spm_matrixvector.c b/z_spm_matrixvector.c index e5346ebf9c67c735626e2a43394b9f99133dcc5d..93734bbdf80399195ff8f1eabfc1c4c2fe893b6f 100644 --- a/z_spm_matrixvector.c +++ b/z_spm_matrixvector.c @@ -73,7 +73,9 @@ z_spmGeCSCv( int trans, const pastix_complex64_t *valptr = (pastix_complex64_t*)csc->values; const pastix_complex64_t *xptr = x; pastix_complex64_t *yptr = y; - pastix_int_t col, row, i, baseval; + pastix_int_t col, row, i, j, baseval; + pastix_int_t ii, jj, k, dofi, dofj; + pastix_int_t *dofs = csc->dofs; if ( (csc == NULL) || (x == NULL) || (y == NULL ) ) { @@ -89,10 +91,10 @@ z_spmGeCSCv( int trans, /* first, y = beta*y */ if( beta == 0. ) { - memset( yptr, 0, csc->gN * sizeof(pastix_complex64_t) ); + memset( yptr, 0, csc->gNexp * sizeof(pastix_complex64_t) ); } else { - for( i=0; i<csc->gN; i++, yptr++ ) { + for( i=0; i<csc->gNexp; i++, yptr++ ) { (*yptr) *= beta; } yptr = y; @@ -104,12 +106,22 @@ z_spmGeCSCv( int trans, */ if( trans == PastixNoTrans ) { - for( col=0; col < csc->gN; col++ ) + for( i=0; i < csc->gN; i++ ) { - for( i=csc->colptr[col]; i<csc->colptr[col+1]; i++ ) + dofi = ( csc->dof > 0 ) ? csc->dof : dofs[i+1] - dofs[i]; + col = ( csc->dof > 0 ) ? i : dofs[i]; + for( k=csc->colptr[i]; k<csc->colptr[i+1]; k++ ) { - row = csc->rowptr[i-baseval]-baseval; - yptr[row] += alpha * valptr[i-baseval] * xptr[col]; + j = csc->rowptr[k-baseval]-baseval; + dofj = ( csc->dof > 0 ) ? csc->dof : dofs[j+1] - dofs[j]; + row = ( csc->dof > 0 ) ? j : dofs[j]; + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++, valptr++) + { + yptr[row+jj] += alpha * (*valptr) * xptr[col+ii]; + } + } } } } @@ -118,15 +130,26 @@ z_spmGeCSCv( int trans, */ else if( trans == PastixTrans ) { - for( col=0; col < csc->gN; col++ ) + for( i=0; i < csc->gN; i++ ) { - for( i=csc->colptr[col]; i<csc->colptr[col+1]; i++ ) + dofi = ( csc->dof > 0 ) ? csc->dof : dofs[i+1] - dofs[i]; + col = ( csc->dof > 0 ) ? i : dofs[i]; + for( k=csc->colptr[i]; k<csc->colptr[i+1]; k++ ) { - row = csc->rowptr[i-baseval]-baseval; - yptr[col] += alpha * valptr[i-baseval] * xptr[row]; + j = csc->rowptr[k-baseval]-baseval; + dofj = ( csc->dof > 0 ) ? csc->dof : dofs[j+1] - dofs[j]; + row = ( csc->dof > 0 ) ? j : dofs[j]; + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++, valptr++) + { + yptr[col+ii] += alpha * (*valptr) * xptr[row+jj]; + } + } } } } + #if defined(PRECISION_c) || defined(PRECISION_z) else if( trans == PastixConjTrans ) { @@ -145,7 +168,6 @@ z_spmGeCSCv( int trans, return PASTIX_ERR_BADPARAMETER; } } - return PASTIX_SUCCESS; } @@ -194,7 +216,9 @@ z_spmSyCSCv( pastix_complex64_t alpha, const pastix_complex64_t *valptr = (pastix_complex64_t*)csc->values; const pastix_complex64_t *xptr = x; pastix_complex64_t *yptr = y; - pastix_int_t col, row, i, baseval; + pastix_int_t col, row, i, j, baseval; + pastix_int_t ii, jj, k, dofi, dofj; + pastix_int_t *dofs = csc->dofs; if ( (csc == NULL) || (x == NULL) || (y == NULL ) ) { @@ -210,30 +234,40 @@ z_spmSyCSCv( pastix_complex64_t alpha, /* First, y = beta*y */ if( beta == 0. ) { - memset( yptr, 0, csc->gN * sizeof(pastix_complex64_t) ); + memset( yptr, 0, csc->gNexp * sizeof(pastix_complex64_t) ); } else { - for( i=0; i<csc->gN; i++, yptr++ ) { + for( i=0; i<csc->gNexp; i++, yptr++ ) { (*yptr) *= beta; } yptr = y; } - if( alpha != 0. ) { - for( col=0; col < csc->gN; col++ ) + if(alpha != 0.) + { + for( i=0; i < csc->gN; i++ ) { - for( i=csc->colptr[col]; i < csc->colptr[col+1]; i++ ) + dofi = ( csc->dof > 0 ) ? csc->dof : dofs[i+1] - dofs[i]; + col = ( csc->dof > 0 ) ? i : dofs[i]; + for( k=csc->colptr[i]; k<csc->colptr[i+1]; k++ ) { - row = csc->rowptr[i-baseval]-baseval; - yptr[row] += alpha * valptr[i-baseval] * xptr[col]; - if( col != row ) + j = csc->rowptr[k-baseval]-baseval; + dofj = ( csc->dof > 0 ) ? csc->dof : dofs[j+1] - dofs[j]; + row = ( csc->dof > 0 ) ? j : dofs[j]; + for(ii=0; ii<dofi; ii++) { - yptr[col] += alpha * valptr[i-baseval] * xptr[row]; + for(jj=0; jj<dofj; jj++, valptr++) + { + yptr[row+jj] += alpha * (*valptr) * xptr[col+ii]; + if( i != j ) + { + yptr[col+ii] += alpha * (*valptr) * xptr[row+jj]; + } + } } } } } - return PASTIX_SUCCESS; } @@ -283,7 +317,9 @@ z_spmHeCSCv( pastix_complex64_t alpha, const pastix_complex64_t *valptr = (pastix_complex64_t*)csc->values; const pastix_complex64_t *xptr = x; pastix_complex64_t *yptr = y; - pastix_int_t col, row, i, baseval; + pastix_int_t col, row, i, j, baseval; + pastix_int_t ii, jj, k, dofi, dofj; + pastix_int_t *dofs = csc->dofs; if ( (csc == NULL) || (x == NULL) || (y == NULL ) ) { @@ -297,30 +333,41 @@ z_spmHeCSCv( pastix_complex64_t alpha, /* First, y = beta*y */ if( beta == 0. ) { - memset( yptr, 0, csc->gN * sizeof(pastix_complex64_t) ); + memset( yptr, 0, csc->gNexp * sizeof(pastix_complex64_t) ); } else { - for( i=0; i<csc->gN; i++, yptr++ ) { + for( i=0; i<csc->gNexp; i++, yptr++ ) { (*yptr) *= beta; } yptr = y; } baseval = spmFindBase( csc ); - - if( alpha != 0. ) { - for( col=0; col < csc->gN; col++ ) + if( alpha != 0.) + { + for( i=0; i < csc->gN; i++ ) { - for( i=csc->colptr[col]; i < csc->colptr[col+1]; i++ ) + dofi = ( csc->dof > 0 ) ? csc->dof : dofs[i+1] - dofs[i]; + col = ( csc->dof > 0 ) ? i : dofs[i]; + for( k=csc->colptr[i]; k<csc->colptr[i+1]; k++ ) { - row=csc->rowptr[i-baseval]-baseval; - yptr[row] += alpha * valptr[i-baseval] * xptr[col]; - if( col != row ) - yptr[col] += alpha * conj( valptr[i-baseval] ) * xptr[row]; + j = csc->rowptr[k-baseval]-baseval; + dofj = ( csc->dof > 0 ) ? csc->dof : dofs[j+1] - dofs[j]; + row = ( csc->dof > 0 ) ? j : dofs[j]; + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++, valptr++) + { + yptr[row+jj] += alpha * (*valptr) * xptr[col+ii]; + if( i != j ) + { + yptr[col+ii] += alpha * conj( *valptr ) * xptr[row+jj]; + } + } + } } } } - return PASTIX_SUCCESS; } #endif diff --git a/z_spm_norm.c b/z_spm_norm.c index 422ace0b4cb31e7eeb46a987f731ebdb3f340622..60880281fb44b686916caeab192301c3da756ae4 100644 --- a/z_spm_norm.c +++ b/z_spm_norm.c @@ -50,7 +50,7 @@ z_spmFrobeniusNorm( const pastix_spm_t *spm ) double sumsq = 0.; if (spm->mtxtype == PastixGeneral) { - for(i=0; i <spm->nnz; i++, valptr++) { + for(i=0; i <spm->nnzexp; i++, valptr++) { frobenius_update( 1, &scale, &sumsq, valptr ); #if defined(PRECISION_z) || defined(PRECISION_c) @@ -62,20 +62,32 @@ z_spmFrobeniusNorm( const pastix_spm_t *spm ) else { pastix_int_t *colptr = spm->colptr; pastix_int_t *rowptr = spm->rowptr; - int nb; + pastix_int_t *dofs = spm->dofs; + + int nb, dofi, dofj, ii, jj; baseval = spmFindBase( spm ); switch( spm->fmttype ){ case PastixCSC: - for(i=0; i<spm->n; i++, colptr++) { - for(j=colptr[0]; j<colptr[1]; j++, rowptr++, valptr++) { - nb = ( i == (*rowptr-baseval) ) ? 1 : 2; - frobenius_update( nb, &scale, &sumsq, valptr ); + for(i=0; i<spm->n; i++, colptr++) + { + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + for(j=colptr[0]; j<colptr[1]; j++, rowptr++) + { + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[(*rowptr-baseval)+1] - dofs[(*rowptr-baseval)]; + for(ii=0 ; ii < dofi; ii++) + { + for(jj=0; jj < dofj ;jj++,valptr++) + { + nb = ( i == (*rowptr-baseval) ) ? 1 : 2; + frobenius_update( nb, &scale, &sumsq, valptr ); #if defined(PRECISION_z) || defined(PRECISION_c) - valptr++; - frobenius_update( nb, &scale, &sumsq, valptr ); + valptr++; + frobenius_update( nb, &scale, &sumsq, valptr ); #endif + } + } } } break; @@ -139,11 +151,10 @@ z_spmMaxNorm( const pastix_spm_t *spm ) pastix_complex64_t *valptr = (pastix_complex64_t*)spm->values; double tmp, norm = 0.; - for(i=0; i <spm->nnz; i++, valptr++) { + for(i=0; i < spm->nnzexp; i++, valptr++) { tmp = cabs( *valptr ); norm = norm > tmp ? norm : tmp; } - return norm; } @@ -171,22 +182,37 @@ z_spmMaxNorm( const pastix_spm_t *spm ) double z_spmInfNorm( const pastix_spm_t *spm ) { - pastix_int_t col, row, i, baseval; + pastix_int_t col, row, i, j, k, ii, jj, baseval; + pastix_int_t dofi, dofj; + pastix_int_t *dofs = spm->dofs; + pastix_complex64_t *valptr = (pastix_complex64_t*)spm->values; double norm = 0.; double *sumcol; - MALLOC_INTERN( sumcol, spm->gN, double ); - memset( sumcol, 0, spm->gN * sizeof(double) ); + MALLOC_INTERN( sumcol, spm->gNexp, double ); + memset( sumcol, 0, spm->gNexp * sizeof(double) ); baseval = spmFindBase( spm ); switch( spm->fmttype ){ case PastixCSC: - for( col=0; col < spm->gN; col++ ) + for( i=0; i < spm->n; i++) { - for( i=spm->colptr[col]-baseval; i<spm->colptr[col+1]-baseval; i++ ) + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + for(k=spm->colptr[i]; k < spm->colptr[i+1]; k++) { - sumcol[spm->rowptr[i]-baseval] += cabs( valptr[i] ); + j = spm->rowptr[k - baseval] - baseval; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + row = ( spm->dof > 0 ) ? j : dofs[j]; + for(ii=0; ii < dofi; ii++) + { + for(jj=0; jj < dofj; jj++, valptr++) + { + { + sumcol[row + jj] += cabs( *valptr ); + } + } + } } } @@ -194,11 +220,29 @@ z_spmInfNorm( const pastix_spm_t *spm ) if ( (spm->mtxtype == PastixHermitian) || (spm->mtxtype == PastixSymmetric) ) { - for( col=0; col < spm->gN; col++ ) + valptr = (pastix_complex64_t*)spm->values; + for(i=0; i < spm->n; i++) { - for( i=spm->colptr[col]-baseval+1; i<spm->colptr[col+1]-baseval; i++ ) + col = ( spm->dof > 0 ) ? i : dofs[i]; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + for(k=spm->colptr[i]; k < spm->colptr[i+1]; k++) { - sumcol[col] += cabs( valptr[i] ); + j = spm->rowptr[k - baseval] - baseval; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + if(i != j) + { + for(ii=0; ii < dofi; ii++) + { + for(jj=0; jj < dofj; jj++, valptr++) + { + sumcol[col + ii] += cabs( *valptr ); + } + } + } + else + { + valptr += dofi * dofj; + } } } } @@ -250,7 +294,7 @@ z_spmInfNorm( const pastix_spm_t *spm ) return PASTIX_ERR_BADPARAMETER; } - for( i=0; i<spm->gN; i++) + for( i=0; i<spm->gNexp; i++) { if(norm < sumcol[i]) { @@ -286,22 +330,37 @@ z_spmInfNorm( const pastix_spm_t *spm ) double z_spmOneNorm( const pastix_spm_t *spm ) { - pastix_int_t col, row, i, baseval; + pastix_int_t col, row, i, j, k, ii, jj, baseval; + pastix_int_t dofi, dofj; + pastix_int_t* dofs = spm->dofs; + pastix_complex64_t *valptr = (pastix_complex64_t*)spm->values; double norm = 0.; double *sumrow; - MALLOC_INTERN( sumrow, spm->gN, double ); - memset( sumrow, 0, spm->gN * sizeof(double) ); + MALLOC_INTERN( sumrow, spm->gNexp, double ); + memset( sumrow, 0, spm->gNexp * sizeof(double) ); baseval = spmFindBase( spm ); switch( spm->fmttype ){ case PastixCSC: - for( col=0; col < spm->gN; col++ ) + for(i=0; i < spm->n; i++) { - for( i=spm->colptr[col]-baseval; i<spm->colptr[col+1]-baseval; i++ ) + col = ( spm->dof > 0 ) ? i : dofs[i]; + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + for(k=spm->colptr[i]; k < spm->colptr[i+1]; k++) { - sumrow[col] += cabs( valptr[i] ); + j = spm->rowptr[k - baseval] - baseval; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + for(ii=0; ii < dofi; ii++) + { + for(jj=0; jj < dofj; jj++, valptr++) + { + { + sumrow[col + ii] += cabs( *valptr ); + } + } + } } } @@ -309,11 +368,29 @@ z_spmOneNorm( const pastix_spm_t *spm ) if ( (spm->mtxtype == PastixHermitian) || (spm->mtxtype == PastixSymmetric) ) { - for( col=0; col < spm->gN; col++ ) + valptr = (pastix_complex64_t*)spm->values; + for(i=0; i < spm->n; i++) { - for( i=spm->colptr[col]-baseval+1; i<spm->colptr[col+1]-baseval; i++ ) + dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i]; + for(k=spm->colptr[i]; k < spm->colptr[i+1]; k++) { - sumrow[spm->rowptr[i]-baseval] += cabs( valptr[i] ); + j = spm->rowptr[k - baseval] - baseval; + row = ( spm->dof > 0 ) ? j : dofs[j]; + dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j]; + if(i != j) + { + for(ii=0; ii < dofi; ii++) + { + for(jj=0; jj < dofj; jj++, valptr++) + { + sumrow[row + jj] += cabs( *valptr ); + } + } + } + else + { + valptr += dofi * dofj; + } } } } @@ -365,7 +442,7 @@ z_spmOneNorm( const pastix_spm_t *spm ) return PASTIX_ERR_BADPARAMETER; } - for( i=0; i<spm->gN; i++) + for( i=0; i<spm->gNexp; i++) { if(norm < sumrow[i]) { diff --git a/z_spm_print.c b/z_spm_print.c new file mode 100644 index 0000000000000000000000000000000000000000..6e4f99298b45d6ba5d4188550fc4c76932e18ce5 --- /dev/null +++ b/z_spm_print.c @@ -0,0 +1,129 @@ +/** + * + * @file z_spm_print.c + * + * Convert a sparse matrix into a dense matrix. + * + * @version 5.1.0 + * @author Mathieu Faverge + * @author Theophile Terraz + * @author Alban Bellot + * @date 2015-01-01 + * + * @precisions normal z -> c d s + * + **/ +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <assert.h> +#include "pastix.h" +#include "common.h" +#include "spm.h" +#include "z_spm.h" + +void +z_spmPrint( const pastix_spm_t *spm ) +{ + pastix_int_t i, j, baseval; + pastix_int_t k, ii, jj, dofi, dofj, col, row; + pastix_complex64_t *valptr; + pastix_int_t *colptr, *rowptr, *dofs; + + assert( spm->fmttype == PastixCSC ); + assert( spm->flttype == PastixComplex64 ); + + baseval = spmFindBase( spm ); + i = 0; j = 0; + + colptr = spm->colptr; + rowptr = spm->rowptr; + valptr = (pastix_complex64_t*)(spm->values); + dofs = spm->dofs; + + switch( spm->mtxtype ){ +#if defined(PRECISION_z) || defined(PRECISION_c) + case PastixHermitian: + for(i=0; i<spm->n; i++, colptr++) + { + dofi = ( spm->dof > 1 ) ? spm->dof : dofs[i+1] - dofs[i]; + col = dofs[i]; + + for(k=colptr[0]; k<colptr[1]; k++, rowptr++) + { + j = (*rowptr - baseval); + dofj = ( spm->dof > 1 ) ? spm->dof : dofs[j+1] - dofs[j]; + row = dofs[j]; + + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++, valptr++) + { + fprintf( stderr, "%ld %ld %e\n", + row + jj, col + ii, *valptr ); + if (i != j) { + fprintf( stderr, "%ld %ld %e\n", + col + ii, row + jj, conj(*valptr) ); + } + } + } + } + } + break; +#endif + case PastixSymmetric: + for(i=0; i<spm->n; i++, colptr++) + { + dofi = ( spm->dof > 1 ) ? spm->dof : dofs[i+1] - dofs[i]; + col = dofs[i]; + + for(k=colptr[0]; k<colptr[1]; k++, rowptr++) + { + j = (*rowptr - baseval); + dofj = ( spm->dof > 1 ) ? spm->dof : dofs[j+1] - dofs[j]; + row = dofs[j]; + + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++, valptr++) + { + fprintf( stderr, "%ld %ld %e\n", + row + jj, col + ii, *valptr ); + if (i != j) { + fprintf( stderr, "%ld %ld %e\n", + col + ii, row + jj, *valptr ); + } + } + } + } + } + break; + case PastixGeneral: + default: + for(i=0; i<spm->n; i++, colptr++) + { + dofi = ( spm->dof > 1 ) ? spm->dof : dofs[i+1] - dofs[i]; + col = dofs[i]; + + for(k=colptr[0]; k<colptr[1]; k++, rowptr++) + { + j = (*rowptr - baseval); + dofj = ( spm->dof > 1 ) ? spm->dof : dofs[j+1] - dofs[j]; + row = dofs[j]; + + for(ii=0; ii<dofi; ii++) + { + for(jj=0; jj<dofj; jj++, valptr++) + { + fprintf( stderr, "%ld %ld %e\n", + row + jj, col + ii, *valptr ); + } + } + } + } + } + return; +} +