Actual source code: symtranspose.c

petsc-3.11.4 2019-09-28
Report Typos and Errors

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

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

  9:   Also defined is a faster implementation of MatTranspose for SeqAIJ
 10:   matrices which avoids calls to MatSetValues. This routine is the new
 11:   standard since it is much faster than MatTranspose_AIJ.

 13: */

 15:  #include <../src/mat/impls/aij/seq/aij.h>


 18: PetscErrorCode MatGetSymbolicTranspose_SeqAIJ(Mat A,PetscInt *Ati[],PetscInt *Atj[])
 19: {
 21:   PetscInt       i,j,anzj;
 22:   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
 23:   PetscInt       an=A->cmap->N,am=A->rmap->N;
 24:   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;

 27:   PetscInfo(A,"Getting Symbolic Transpose.\n");

 29:   /* Set up timers */
 30:   PetscLogEventBegin(MAT_Getsymtranspose,A,0,0,0);

 32:   /* Allocate space for symbolic transpose info and work array */
 33:   PetscCalloc1(an+1,&ati);
 34:   PetscMalloc1(ai[am],&atj);
 35:   PetscMalloc1(an,&atfill);

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

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

 50:   /* Walk through A row-wise and mark nonzero entries of A^T. */
 51:   for (i=0; i<am; i++) {
 52:     anzj = ai[i+1] - ai[i];
 53:     for (j=0; j<anzj; j++) {
 54:       atj[atfill[*aj]] = i;
 55:       atfill[*aj++]   += 1;
 56:     }
 57:   }

 59:   /* Clean up temporary space and complete requests. */
 60:   PetscFree(atfill);
 61:   *Ati = ati;
 62:   *Atj = atj;

 64:   PetscLogEventEnd(MAT_Getsymtranspose,A,0,0,0);
 65:   return(0);
 66: }
 67: /*
 68:   MatGetSymbolicTransposeReduced_SeqAIJ() - Get symbolic matrix structure of submatrix A[rstart:rend,:],
 69:      modified from MatGetSymbolicTranspose_SeqAIJ()
 70: */
 71: PetscErrorCode MatGetSymbolicTransposeReduced_SeqAIJ(Mat A,PetscInt rstart,PetscInt rend,PetscInt *Ati[],PetscInt *Atj[])
 72: {
 74:   PetscInt       i,j,anzj;
 75:   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
 76:   PetscInt       an=A->cmap->N;
 77:   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;

 80:   PetscInfo(A,"Getting Symbolic Transpose\n");
 81:   PetscLogEventBegin(MAT_Getsymtransreduced,A,0,0,0);

 83:   /* Allocate space for symbolic transpose info and work array */
 84:   PetscCalloc1(an+1,&ati);
 85:   anzj = ai[rend] - ai[rstart];
 86:   PetscMalloc1(anzj+1,&atj);
 87:   PetscMalloc1(an+1,&atfill);

 89:   /* Walk through aj and count ## of non-zeros in each row of A^T. */
 90:   /* Note: offset by 1 for fast conversion into csr format. */
 91:   for (i=ai[rstart]; i<ai[rend]; i++) {
 92:     ati[aj[i]+1] += 1;
 93:   }
 94:   /* Form ati for csr format of A^T. */
 95:   for (i=0;i<an;i++) {
 96:     ati[i+1] += ati[i];
 97:   }

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

102:   /* Walk through A row-wise and mark nonzero entries of A^T. */
103:   aj = aj + ai[rstart];
104:   for (i=rstart; i<rend; i++) {
105:     anzj = ai[i+1] - ai[i];
106:     for (j=0; j<anzj; j++) {
107:       atj[atfill[*aj]] = i-rstart;
108:       atfill[*aj++]   += 1;
109:     }
110:   }

112:   /* Clean up temporary space and complete requests. */
113:   PetscFree(atfill);
114:   *Ati = ati;
115:   *Atj = atj;

117:   PetscLogEventEnd(MAT_Getsymtransreduced,A,0,0,0);
118:   return(0);
119: }

121: PetscErrorCode MatTranspose_SeqAIJ_FAST(Mat A,MatReuse reuse,Mat *B)
122: {
124:   PetscInt       i,j,anzj;
125:   Mat            At;
126:   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*at;
127:   PetscInt       an=A->cmap->N,am=A->rmap->N;
128:   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
129:   MatScalar      *ata,*aa=a->a;

132:   PetscLogEventBegin(MAT_Transpose_SeqAIJ,A,0,0,0);

134:   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
135:     /* Allocate space for symbolic transpose info and work array */
136:     PetscCalloc1(an+1,&ati);
137:     PetscMalloc1(ai[am],&atj);
138:     PetscMalloc1(ai[am],&ata);
139:     /* Walk through aj and count ## of non-zeros in each row of A^T. */
140:     /* Note: offset by 1 for fast conversion into csr format. */
141:     for (i=0;i<ai[am];i++) {
142:       ati[aj[i]+1] += 1;
143:     }
144:     /* Form ati for csr format of A^T. */
145:     for (i=0;i<an;i++) {
146:       ati[i+1] += ati[i];
147:     }
148:   } else {
149:     Mat_SeqAIJ *sub_B = (Mat_SeqAIJ*) (*B)->data;
150:     ati = sub_B->i;
151:     atj = sub_B->j;
152:     ata = sub_B->a;
153:     At  = *B;
154:   }

156:   /* Copy ati into atfill so we have locations of the next free space in atj */
157:   PetscMalloc1(an,&atfill);
158:   PetscMemcpy(atfill,ati,an*sizeof(PetscInt));

160:   /* Walk through A row-wise and mark nonzero entries of A^T. */
161:   for (i=0;i<am;i++) {
162:     anzj = ai[i+1] - ai[i];
163:     for (j=0;j<anzj;j++) {
164:       atj[atfill[*aj]] = i;
165:       ata[atfill[*aj]] = *aa++;
166:       atfill[*aj++]   += 1;
167:     }
168:   }

170:   /* Clean up temporary space and complete requests. */
171:   PetscFree(atfill);
172:   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
173:     MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,ata,&At);

175:     at          = (Mat_SeqAIJ*)(At->data);
176:     at->free_a  = PETSC_TRUE;
177:     at->free_ij = PETSC_TRUE;
178:     at->nonew   = 0;
179:     at->maxnz   = ati[an];

181:     MatSetType(At,((PetscObject)A)->type_name);
182:   }

184:   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
185:     *B = At;
186:   } else {
187:     MatHeaderMerge(A,&At);
188:   }
189:   PetscLogEventEnd(MAT_Transpose_SeqAIJ,A,0,0,0);
190:   return(0);
191: }

193: PetscErrorCode MatRestoreSymbolicTranspose_SeqAIJ(Mat A,PetscInt *ati[],PetscInt *atj[])
194: {

198:   PetscInfo(A,"Restoring Symbolic Transpose.\n");
199:   PetscFree(*ati);
200:   PetscFree(*atj);
201:   return(0);
202: }