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;


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


 30:   PetscLogInfo(A,"Getting Symbolic Transpose.\n");

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

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

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

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

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

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

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

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

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

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

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

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

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

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

142:   PetscLogInfo(A,"Restoring Symbolic Transpose.\n");
143:   PetscFree(*ati);
144:   ati  = PETSC_NULL;
145:   PetscFree(*atj);
146:   atj  = PETSC_NULL;
147:   return(0);
148: }