Actual source code: symtranspose.c

  1: /*
  2:   Defines symbolic transpose routines for SeqAIJ matrices.

  4:   Currently Get/Restore only allocates/frees memory for holding the
  5:   (i,j) info for the transpose.  Someday, this info could be
  6:   maintained so successive calls to Get will not recompute the info.

  8:   Also defined is a "faster" implementation of MatTranspose for SeqAIJ
  9:   matrices which avoids calls to MatSetValues.  This routine has not
 10:   been adopted as the standard yet as it is somewhat untested.

 12: */

 14:  #include src/mat/impls/aij/seq/aij.h

 16: static int logkey_matgetsymtranspose    = 0;
 17: static int logkey_mattranspose          = 0;


 20: int MatGetSymbolicTranspose_SeqAIJ(Mat A,int *Ati[],int *Atj[]) {
 21:   int        ierr,i,j,anzj;
 22:   Mat_SeqAIJ *a=(Mat_SeqAIJ *)A->data;
 23:   int        aishift = a->indexshift,an=A->N,am=A->M;
 24:   int        *ati,*atj,*atfill,*ai=a->i,*aj=a->j;


 28:   PetscLogInfo(A,"Getting Symbolic Transpose.n");
 29:   if (aishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported.");

 31:   /* Set up timers */
 32:   if (!logkey_matgetsymtranspose) {
 33:     PetscLogEventRegister(&logkey_matgetsymtranspose,"MatGetSymbolicTranspose",MAT_COOKIE);
 34:   }
 35:   PetscLogEventBegin(logkey_matgetsymtranspose,A,0,0,0);

 37:   /* Allocate space for symbolic transpose info and work array */
 38:   PetscMalloc((an+1)*sizeof(int),&ati);
 39:   PetscMalloc(ai[am]*sizeof(int),&atj);
 40:   PetscMalloc(an*sizeof(int),&atfill);
 41:   PetscMemzero(ati,(an+1)*sizeof(int));

 43:   /* Walk through aj and count ## of non-zeros in each row of A^T. */
 44:   /* Note: offset by 1 for fast conversion into csr format. */
 45:   for (i=0;i<ai[am];i++) {
 46:     ati[aj[i]+1] += 1;
 47:   }
 48:   /* Form ati for csr format of A^T. */
 49:   for (i=0;i<an;i++) {
 50:     ati[i+1] += ati[i];
 51:   }

 53:   /* Copy ati into atfill so we have locations of the next free space in atj */
 54:   PetscMemcpy(atfill,ati,an*sizeof(int));

 56:   /* Walk through A row-wise and mark nonzero entries of A^T. */
 57:   for (i=0;i<am;i++) {
 58:     anzj = ai[i+1] - ai[i];
 59:     for (j=0;j<anzj;j++) {
 60:       atj[atfill[*aj]] = i;
 61:       atfill[*aj++]   += 1;
 62:     }
 63:   }

 65:   /* Clean up temporary space and complete requests. */
 66:   PetscFree(atfill);
 67:   *Ati = ati;
 68:   *Atj = atj;

 70:   PetscLogEventEnd(logkey_matgetsymtranspose,A,0,0,0);
 71:   return(0);
 72: }

 74: int MatTranspose_SeqAIJ_FAST(Mat A,Mat *B) {
 75:   int        ierr,i,j,anzj;
 76:   Mat        At;
 77:   Mat_SeqAIJ *a=(Mat_SeqAIJ *)A->data,*at;
 78:   int        aishift = a->indexshift,an=A->N,am=A->M;
 79:   int        *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
 80:   MatScalar  *ata,*aa=a->a;

 83:   if (aishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported.");

 85:   /* Set up timers */
 86:   if (!logkey_mattranspose) {
 87:     PetscLogEventRegister(&logkey_mattranspose,"MatTranspose_SeqAIJ_FAST",MAT_COOKIE);
 88:   }
 89:   PetscLogEventBegin(logkey_mattranspose,A,0,0,0);

 91:   /* Allocate space for symbolic transpose info and work array */
 92:   PetscMalloc((an+1)*sizeof(int),&ati);
 93:   PetscMalloc(ai[am]*sizeof(int),&atj);
 94:   PetscMalloc(ai[am]*sizeof(MatScalar),&ata);
 95:   PetscMalloc(an*sizeof(int),&atfill);
 96:   PetscMemzero(ati,(an+1)*sizeof(int));
 97:   /* Walk through aj and count ## of non-zeros in each row of A^T. */
 98:   /* Note: offset by 1 for fast conversion into csr format. */
 99:   for (i=0;i<ai[am];i++) {
100:     ati[aj[i]+1] += 1;
101:   }
102:   /* Form ati for csr format of A^T. */
103:   for (i=0;i<an;i++) {
104:     ati[i+1] += ati[i];
105:   }

107:   /* Copy ati into atfill so we have locations of the next free space in atj */
108:   PetscMemcpy(atfill,ati,an*sizeof(int));

110:   /* Walk through A row-wise and mark nonzero entries of A^T. */
111:   for (i=0;i<am;i++) {
112:     anzj = ai[i+1] - ai[i];
113:     for (j=0;j<anzj;j++) {
114:       atj[atfill[*aj]] = i;
115:       ata[atfill[*aj]] = *aa++;
116:       atfill[*aj++]   += 1;
117:     }
118:   }

120:   /* Clean up temporary space and complete requests. */
121:   PetscFree(atfill);
122:   MatCreateSeqAIJWithArrays(A->comm,an,am,ati,atj,ata,&At);
123:   at   = (Mat_SeqAIJ *)(At->data);
124:   at->freedata = PETSC_TRUE;
125:   at->nonew    = 0;
126:   if (B) {
127:     *B = At;
128:   } else {
129:     MatHeaderCopy(A,At);
130:   }
131:   PetscLogEventEnd(logkey_mattranspose,A,0,0,0);
132:   return(0);
133: }

135: int MatRestoreSymbolicTranspose_SeqAIJ(Mat A,int *ati[],int *atj[]) {

139:   PetscLogInfo(A,"Restoring Symbolic Transpose.n");
140:   PetscFree(*ati);
141:   ati  = PETSC_NULL;
142:   PetscFree(*atj);
143:   atj  = PETSC_NULL;
144:   return(0);
145: }