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: #undef __FUNCT__
 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        aishift = a->indexshift,an=A->N,am=A->M;
 26:   int        *ati,*atj,*atfill,*ai=a->i,*aj=a->j;


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

139: #undef __FUNCT__
141: int MatRestoreSymbolicTranspose_SeqAIJ(Mat A,int *ati[],int *atj[]) {

145:   PetscLogInfo(A,"Restoring Symbolic Transpose.n");
146:   PetscFree(*ati);
147:   ati  = PETSC_NULL;
148:   PetscFree(*atj);
149:   atj  = PETSC_NULL;
150:   return(0);
151: }