Date: 2013-07-02T14:41:34+00:00

Actual source code: symtranspose.c
petsc-3.4.2 2013-07-02

      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 has not
     11:   been adopted as the standard yet as it is somewhat untested.

     13: */

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

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

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

     31:   /* Set up timers */
     32:   PetscLogEventBegin(MAT_Getsymtranspose,A,0,0,0);

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

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

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

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

     62:   /* Clean up temporary space and complete requests. */
     63:   PetscFree(atfill);
     64:   *Ati = ati;
     65:   *Atj = atj;

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

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

     88:   /* Allocate space for symbolic transpose info and work array */
     89:   PetscMalloc((an+1)*sizeof(PetscInt),&ati);
     90:   anzj = ai[rend] - ai[rstart];
     91:   PetscMalloc((anzj+1)*sizeof(PetscInt),&atj);
     92:   PetscMalloc((an+1)*sizeof(PetscInt),&atfill);
     93:   PetscMemzero(ati,(an+1)*sizeof(PetscInt));

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

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

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

    118:   /* Clean up temporary space and complete requests. */
    119:   PetscFree(atfill);
    120:   *Ati = ati;
    121:   *Atj = atj;

    123:   PetscLogEventEnd(MAT_Getsymtransreduced,A,0,0,0);
    124:   return(0);
    125: }

    129: PetscErrorCode MatTranspose_SeqAIJ_FAST(Mat A,MatReuse reuse,Mat *B)
    130: {
    132:   PetscInt       i,j,anzj;
    133:   Mat            At;
    134:   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*at;
    135:   PetscInt       an=A->cmap->N,am=A->rmap->N;
    136:   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
    137:   MatScalar      *ata,*aa=a->a;

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

    142:   if (reuse == MAT_INITIAL_MATRIX || *B == A) {
    143:     /* Allocate space for symbolic transpose info and work array */
    144:     PetscMalloc((an+1)*sizeof(PetscInt),&ati);
    145:     PetscMalloc(ai[am]*sizeof(PetscInt),&atj);
    146:     PetscMalloc(ai[am]*sizeof(MatScalar),&ata);
    147:     PetscMemzero(ati,(an+1)*sizeof(PetscInt));
    148:     /* Walk through aj and count ## of non-zeros in each row of A^T. */
    149:     /* Note: offset by 1 for fast conversion into csr format. */
    150:     for (i=0;i<ai[am];i++) {
    151:       ati[aj[i]+1] += 1;
    152:     }
    153:     /* Form ati for csr format of A^T. */
    154:     for (i=0;i<an;i++) {
    155:       ati[i+1] += ati[i];
    156:     }
    157:   } else {
    158:     Mat_SeqAIJ *sub_B = (Mat_SeqAIJ*) (*B)->data;
    159:     ati = sub_B->i;
    160:     atj = sub_B->j;
    161:     ata = sub_B->a;
    162:     At  = *B;
    163:   }

    165:   /* Copy ati into atfill so we have locations of the next free space in atj */
    166:   PetscMalloc(an*sizeof(PetscInt),&atfill);
    167:   PetscMemcpy(atfill,ati,an*sizeof(PetscInt));

    169:   /* Walk through A row-wise and mark nonzero entries of A^T. */
    170:   for (i=0;i<am;i++) {
    171:     anzj = ai[i+1] - ai[i];
    172:     for (j=0;j<anzj;j++) {
    173:       atj[atfill[*aj]] = i;
    174:       ata[atfill[*aj]] = *aa++;
    175:       atfill[*aj++]   += 1;
    176:     }
    177:   }

    179:   /* Clean up temporary space and complete requests. */
    180:   PetscFree(atfill);
    181:   if (reuse == MAT_INITIAL_MATRIX) {
    182:     MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,ata,&At);

    184:     at          = (Mat_SeqAIJ*)(At->data);
    185:     at->free_a  = PETSC_TRUE;
    186:     at->free_ij = PETSC_TRUE;
    187:     at->nonew   = 0;
    188:   }

    190:   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
    191:     *B = At;
    192:   } else {
    193:     MatHeaderMerge(A,At);
    194:   }
    195:   PetscLogEventEnd(MAT_Transpose_SeqAIJ,A,0,0,0);
    196:   return(0);
    197: }

    201: PetscErrorCode MatRestoreSymbolicTranspose_SeqAIJ(Mat A,PetscInt *ati[],PetscInt *atj[])
    202: {

    206:   PetscInfo(A,"Restoring Symbolic Transpose.\n");
    207:   PetscFree(*ati);
    208:   PetscFree(*atj);
    209:   return(0);
    210: }