1*70f19b1fSKris Buschelman /* 2*70f19b1fSKris Buschelman Defines symbolic transpose routines for SeqAIJ matrices. 3*70f19b1fSKris Buschelman 4*70f19b1fSKris Buschelman Currently Get/Restore only allocates/frees memory for holding the 5*70f19b1fSKris Buschelman (i,j) info for the transpose. Someday, this info could be 6*70f19b1fSKris Buschelman maintained so successive calls to Get will not recompute the info. 7*70f19b1fSKris Buschelman 8*70f19b1fSKris Buschelman Also defined is a "faster" implementation of MatTranspose for SeqAIJ 9*70f19b1fSKris Buschelman matrices which avoids calls to MatSetValues. This routine has not 10*70f19b1fSKris Buschelman been adopted as the standard yet as it is somewhat untested. 11*70f19b1fSKris Buschelman 12*70f19b1fSKris Buschelman */ 13*70f19b1fSKris Buschelman 14*70f19b1fSKris Buschelman #include "src/mat/impls/aij/seq/aij.h" 15*70f19b1fSKris Buschelman 16*70f19b1fSKris Buschelman static int logkey_matgetsymtranspose = 0; 17*70f19b1fSKris Buschelman static int logkey_mattranspose = 0; 18*70f19b1fSKris Buschelman 19*70f19b1fSKris Buschelman 20*70f19b1fSKris Buschelman #undef __FUNCT__ 21*70f19b1fSKris Buschelman #define __FUNCT__ "MatGetSymbolicTranspose_SeqIJ" 22*70f19b1fSKris Buschelman int MatGetSymbolicTranspose_SeqAIJ(Mat A,int *Ati[],int *Atj[]) { 23*70f19b1fSKris Buschelman int ierr,i,j,anzj; 24*70f19b1fSKris Buschelman Mat_SeqAIJ *a=(Mat_SeqAIJ *)A->data; 25*70f19b1fSKris Buschelman int aishift = a->indexshift,an=A->N,am=A->M; 26*70f19b1fSKris Buschelman int *ati,*atj,*atfill,*ai=a->i,*aj=a->j; 27*70f19b1fSKris Buschelman 28*70f19b1fSKris Buschelman PetscFunctionBegin; 29*70f19b1fSKris Buschelman 30*70f19b1fSKris Buschelman ierr = PetscLogInfo(A,"Getting Symbolic Transpose.\n");CHKERRQ(ierr); 31*70f19b1fSKris Buschelman if (aishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported."); 32*70f19b1fSKris Buschelman 33*70f19b1fSKris Buschelman /* Set up timers */ 34*70f19b1fSKris Buschelman if (!logkey_matgetsymtranspose) { 35*70f19b1fSKris Buschelman ierr = PetscLogEventRegister(&logkey_matgetsymtranspose,"MatGetSymbolicTranspose",MAT_COOKIE);CHKERRQ(ierr); 36*70f19b1fSKris Buschelman } 37*70f19b1fSKris Buschelman ierr = PetscLogEventBegin(logkey_matgetsymtranspose,A,0,0,0);CHKERRQ(ierr); 38*70f19b1fSKris Buschelman 39*70f19b1fSKris Buschelman /* Allocate space for symbolic transpose info and work array */ 40*70f19b1fSKris Buschelman ierr = PetscMalloc((an+1)*sizeof(int),&ati);CHKERRQ(ierr); 41*70f19b1fSKris Buschelman ierr = PetscMalloc(ai[am]*sizeof(int),&atj);CHKERRQ(ierr); 42*70f19b1fSKris Buschelman ierr = PetscMalloc(an*sizeof(int),&atfill);CHKERRQ(ierr); 43*70f19b1fSKris Buschelman ierr = PetscMemzero(ati,(an+1)*sizeof(int));CHKERRQ(ierr); 44*70f19b1fSKris Buschelman 45*70f19b1fSKris Buschelman /* Walk through aj and count ## of non-zeros in each row of A^T. */ 46*70f19b1fSKris Buschelman /* Note: offset by 1 for fast conversion into csr format. */ 47*70f19b1fSKris Buschelman for (i=0;i<ai[am];i++) { 48*70f19b1fSKris Buschelman ati[aj[i]+1] += 1; 49*70f19b1fSKris Buschelman } 50*70f19b1fSKris Buschelman /* Form ati for csr format of A^T. */ 51*70f19b1fSKris Buschelman for (i=0;i<an;i++) { 52*70f19b1fSKris Buschelman ati[i+1] += ati[i]; 53*70f19b1fSKris Buschelman } 54*70f19b1fSKris Buschelman 55*70f19b1fSKris Buschelman /* Copy ati into atfill so we have locations of the next free space in atj */ 56*70f19b1fSKris Buschelman ierr = PetscMemcpy(atfill,ati,an*sizeof(int));CHKERRQ(ierr); 57*70f19b1fSKris Buschelman 58*70f19b1fSKris Buschelman /* Walk through A row-wise and mark nonzero entries of A^T. */ 59*70f19b1fSKris Buschelman for (i=0;i<am;i++) { 60*70f19b1fSKris Buschelman anzj = ai[i+1] - ai[i]; 61*70f19b1fSKris Buschelman for (j=0;j<anzj;j++) { 62*70f19b1fSKris Buschelman atj[atfill[*aj]] = i; 63*70f19b1fSKris Buschelman atfill[*aj++] += 1; 64*70f19b1fSKris Buschelman } 65*70f19b1fSKris Buschelman } 66*70f19b1fSKris Buschelman 67*70f19b1fSKris Buschelman /* Clean up temporary space and complete requests. */ 68*70f19b1fSKris Buschelman ierr = PetscFree(atfill);CHKERRQ(ierr); 69*70f19b1fSKris Buschelman *Ati = ati; 70*70f19b1fSKris Buschelman *Atj = atj; 71*70f19b1fSKris Buschelman 72*70f19b1fSKris Buschelman ierr = PetscLogEventEnd(logkey_matgetsymtranspose,A,0,0,0);CHKERRQ(ierr); 73*70f19b1fSKris Buschelman PetscFunctionReturn(0); 74*70f19b1fSKris Buschelman } 75*70f19b1fSKris Buschelman 76*70f19b1fSKris Buschelman #undef __FUNCT__ 77*70f19b1fSKris Buschelman #define __FUNCT__ "MatTranspose_SeqIJ_FAST" 78*70f19b1fSKris Buschelman int MatTranspose_SeqAIJ_FAST(Mat A,Mat *B) { 79*70f19b1fSKris Buschelman int ierr,i,j,anzj; 80*70f19b1fSKris Buschelman Mat At; 81*70f19b1fSKris Buschelman Mat_SeqAIJ *a=(Mat_SeqAIJ *)A->data,*at; 82*70f19b1fSKris Buschelman int aishift = a->indexshift,an=A->N,am=A->M; 83*70f19b1fSKris Buschelman int *ati,*atj,*atfill,*ai=a->i,*aj=a->j; 84*70f19b1fSKris Buschelman MatScalar *ata,*aa=a->a; 85*70f19b1fSKris Buschelman PetscFunctionBegin; 86*70f19b1fSKris Buschelman 87*70f19b1fSKris Buschelman if (aishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported."); 88*70f19b1fSKris Buschelman 89*70f19b1fSKris Buschelman /* Set up timers */ 90*70f19b1fSKris Buschelman if (!logkey_mattranspose) { 91*70f19b1fSKris Buschelman ierr = PetscLogEventRegister(&logkey_mattranspose,"MatTranspose_SeqAIJ_FAST",MAT_COOKIE);CHKERRQ(ierr); 92*70f19b1fSKris Buschelman } 93*70f19b1fSKris Buschelman ierr = PetscLogEventBegin(logkey_mattranspose,A,0,0,0);CHKERRQ(ierr); 94*70f19b1fSKris Buschelman 95*70f19b1fSKris Buschelman /* Allocate space for symbolic transpose info and work array */ 96*70f19b1fSKris Buschelman ierr = PetscMalloc((an+1)*sizeof(int),&ati);CHKERRQ(ierr); 97*70f19b1fSKris Buschelman ierr = PetscMalloc(ai[am]*sizeof(int),&atj);CHKERRQ(ierr); 98*70f19b1fSKris Buschelman ierr = PetscMalloc(ai[am]*sizeof(MatScalar),&ata);CHKERRQ(ierr); 99*70f19b1fSKris Buschelman ierr = PetscMalloc(an*sizeof(int),&atfill);CHKERRQ(ierr); 100*70f19b1fSKris Buschelman ierr = PetscMemzero(ati,(an+1)*sizeof(int));CHKERRQ(ierr); 101*70f19b1fSKris Buschelman /* Walk through aj and count ## of non-zeros in each row of A^T. */ 102*70f19b1fSKris Buschelman /* Note: offset by 1 for fast conversion into csr format. */ 103*70f19b1fSKris Buschelman for (i=0;i<ai[am];i++) { 104*70f19b1fSKris Buschelman ati[aj[i]+1] += 1; 105*70f19b1fSKris Buschelman } 106*70f19b1fSKris Buschelman /* Form ati for csr format of A^T. */ 107*70f19b1fSKris Buschelman for (i=0;i<an;i++) { 108*70f19b1fSKris Buschelman ati[i+1] += ati[i]; 109*70f19b1fSKris Buschelman } 110*70f19b1fSKris Buschelman 111*70f19b1fSKris Buschelman /* Copy ati into atfill so we have locations of the next free space in atj */ 112*70f19b1fSKris Buschelman ierr = PetscMemcpy(atfill,ati,an*sizeof(int));CHKERRQ(ierr); 113*70f19b1fSKris Buschelman 114*70f19b1fSKris Buschelman /* Walk through A row-wise and mark nonzero entries of A^T. */ 115*70f19b1fSKris Buschelman for (i=0;i<am;i++) { 116*70f19b1fSKris Buschelman anzj = ai[i+1] - ai[i]; 117*70f19b1fSKris Buschelman for (j=0;j<anzj;j++) { 118*70f19b1fSKris Buschelman atj[atfill[*aj]] = i; 119*70f19b1fSKris Buschelman ata[atfill[*aj]] = *aa++; 120*70f19b1fSKris Buschelman atfill[*aj++] += 1; 121*70f19b1fSKris Buschelman } 122*70f19b1fSKris Buschelman } 123*70f19b1fSKris Buschelman 124*70f19b1fSKris Buschelman /* Clean up temporary space and complete requests. */ 125*70f19b1fSKris Buschelman ierr = PetscFree(atfill);CHKERRQ(ierr); 126*70f19b1fSKris Buschelman ierr = MatCreateSeqAIJWithArrays(A->comm,an,am,ati,atj,ata,&At);CHKERRQ(ierr); 127*70f19b1fSKris Buschelman at = (Mat_SeqAIJ *)(At->data); 128*70f19b1fSKris Buschelman at->freedata = PETSC_TRUE; 129*70f19b1fSKris Buschelman at->nonew = 0; 130*70f19b1fSKris Buschelman if (B) { 131*70f19b1fSKris Buschelman *B = At; 132*70f19b1fSKris Buschelman } else { 133*70f19b1fSKris Buschelman ierr = MatHeaderCopy(A,At); 134*70f19b1fSKris Buschelman } 135*70f19b1fSKris Buschelman ierr = PetscLogEventEnd(logkey_mattranspose,A,0,0,0);CHKERRQ(ierr); 136*70f19b1fSKris Buschelman PetscFunctionReturn(0); 137*70f19b1fSKris Buschelman } 138*70f19b1fSKris Buschelman 139*70f19b1fSKris Buschelman #undef __FUNCT__ 140*70f19b1fSKris Buschelman #define __FUNCT__ "MatRestoreSymbolicTranspose_SeqAIJ" 141*70f19b1fSKris Buschelman int MatRestoreSymbolicTranspose_SeqAIJ(Mat A,int *ati[],int *atj[]) { 142*70f19b1fSKris Buschelman int ierr; 143*70f19b1fSKris Buschelman 144*70f19b1fSKris Buschelman PetscFunctionBegin; 145*70f19b1fSKris Buschelman ierr = PetscLogInfo(A,"Restoring Symbolic Transpose.\n");CHKERRQ(ierr); 146*70f19b1fSKris Buschelman ierr = PetscFree(*ati);CHKERRQ(ierr); 147*70f19b1fSKris Buschelman ati = PETSC_NULL; 148*70f19b1fSKris Buschelman ierr = PetscFree(*atj);CHKERRQ(ierr); 149*70f19b1fSKris Buschelman atj = PETSC_NULL; 150*70f19b1fSKris Buschelman PetscFunctionReturn(0); 151*70f19b1fSKris Buschelman } 152*70f19b1fSKris Buschelman 153