xref: /petsc/src/mat/impls/aij/seq/symtranspose.c (revision 70f19b1f7e86062814f7b2efd7f722a70996ac5d)
1*70f19b1fSKris Buschelman /*
2*70f19b1fSKris Buschelman   Defines symbolic transpose routines for SeqAIJ matrices.
3*70f19b1fSKris Buschelman 
4*70f19b1fSKris Buschelman   Currently Get/Restore only allocates/frees memory for holding the
5*70f19b1fSKris Buschelman   (i,j) info for the transpose.  Someday, this info could be
6*70f19b1fSKris Buschelman   maintained so successive calls to Get will not recompute the info.
7*70f19b1fSKris Buschelman 
8*70f19b1fSKris Buschelman   Also defined is a "faster" implementation of MatTranspose for SeqAIJ
9*70f19b1fSKris Buschelman   matrices which avoids calls to MatSetValues.  This routine has not
10*70f19b1fSKris Buschelman   been adopted as the standard yet as it is somewhat untested.
11*70f19b1fSKris Buschelman 
12*70f19b1fSKris Buschelman */
13*70f19b1fSKris Buschelman 
14*70f19b1fSKris Buschelman #include "src/mat/impls/aij/seq/aij.h"
15*70f19b1fSKris Buschelman 
16*70f19b1fSKris Buschelman static int logkey_matgetsymtranspose    = 0;
17*70f19b1fSKris Buschelman static int logkey_mattranspose          = 0;
18*70f19b1fSKris Buschelman 
19*70f19b1fSKris Buschelman 
20*70f19b1fSKris Buschelman #undef __FUNCT__
21*70f19b1fSKris Buschelman #define __FUNCT__ "MatGetSymbolicTranspose_SeqIJ"
22*70f19b1fSKris Buschelman int MatGetSymbolicTranspose_SeqAIJ(Mat A,int *Ati[],int *Atj[]) {
23*70f19b1fSKris Buschelman   int        ierr,i,j,anzj;
24*70f19b1fSKris Buschelman   Mat_SeqAIJ *a=(Mat_SeqAIJ *)A->data;
25*70f19b1fSKris Buschelman   int        aishift = a->indexshift,an=A->N,am=A->M;
26*70f19b1fSKris Buschelman   int        *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
27*70f19b1fSKris Buschelman 
28*70f19b1fSKris Buschelman   PetscFunctionBegin;
29*70f19b1fSKris Buschelman 
30*70f19b1fSKris Buschelman   ierr = PetscLogInfo(A,"Getting Symbolic Transpose.\n");CHKERRQ(ierr);
31*70f19b1fSKris Buschelman   if (aishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported.");
32*70f19b1fSKris Buschelman 
33*70f19b1fSKris Buschelman   /* Set up timers */
34*70f19b1fSKris Buschelman   if (!logkey_matgetsymtranspose) {
35*70f19b1fSKris Buschelman     ierr = PetscLogEventRegister(&logkey_matgetsymtranspose,"MatGetSymbolicTranspose",MAT_COOKIE);CHKERRQ(ierr);
36*70f19b1fSKris Buschelman   }
37*70f19b1fSKris Buschelman   ierr = PetscLogEventBegin(logkey_matgetsymtranspose,A,0,0,0);CHKERRQ(ierr);
38*70f19b1fSKris Buschelman 
39*70f19b1fSKris Buschelman   /* Allocate space for symbolic transpose info and work array */
40*70f19b1fSKris Buschelman   ierr = PetscMalloc((an+1)*sizeof(int),&ati);CHKERRQ(ierr);
41*70f19b1fSKris Buschelman   ierr = PetscMalloc(ai[am]*sizeof(int),&atj);CHKERRQ(ierr);
42*70f19b1fSKris Buschelman   ierr = PetscMalloc(an*sizeof(int),&atfill);CHKERRQ(ierr);
43*70f19b1fSKris Buschelman   ierr = PetscMemzero(ati,(an+1)*sizeof(int));CHKERRQ(ierr);
44*70f19b1fSKris Buschelman 
45*70f19b1fSKris Buschelman   /* Walk through aj and count ## of non-zeros in each row of A^T. */
46*70f19b1fSKris Buschelman   /* Note: offset by 1 for fast conversion into csr format. */
47*70f19b1fSKris Buschelman   for (i=0;i<ai[am];i++) {
48*70f19b1fSKris Buschelman     ati[aj[i]+1] += 1;
49*70f19b1fSKris Buschelman   }
50*70f19b1fSKris Buschelman   /* Form ati for csr format of A^T. */
51*70f19b1fSKris Buschelman   for (i=0;i<an;i++) {
52*70f19b1fSKris Buschelman     ati[i+1] += ati[i];
53*70f19b1fSKris Buschelman   }
54*70f19b1fSKris Buschelman 
55*70f19b1fSKris Buschelman   /* Copy ati into atfill so we have locations of the next free space in atj */
56*70f19b1fSKris Buschelman   ierr = PetscMemcpy(atfill,ati,an*sizeof(int));CHKERRQ(ierr);
57*70f19b1fSKris Buschelman 
58*70f19b1fSKris Buschelman   /* Walk through A row-wise and mark nonzero entries of A^T. */
59*70f19b1fSKris Buschelman   for (i=0;i<am;i++) {
60*70f19b1fSKris Buschelman     anzj = ai[i+1] - ai[i];
61*70f19b1fSKris Buschelman     for (j=0;j<anzj;j++) {
62*70f19b1fSKris Buschelman       atj[atfill[*aj]] = i;
63*70f19b1fSKris Buschelman       atfill[*aj++]   += 1;
64*70f19b1fSKris Buschelman     }
65*70f19b1fSKris Buschelman   }
66*70f19b1fSKris Buschelman 
67*70f19b1fSKris Buschelman   /* Clean up temporary space and complete requests. */
68*70f19b1fSKris Buschelman   ierr = PetscFree(atfill);CHKERRQ(ierr);
69*70f19b1fSKris Buschelman   *Ati = ati;
70*70f19b1fSKris Buschelman   *Atj = atj;
71*70f19b1fSKris Buschelman 
72*70f19b1fSKris Buschelman   ierr = PetscLogEventEnd(logkey_matgetsymtranspose,A,0,0,0);CHKERRQ(ierr);
73*70f19b1fSKris Buschelman   PetscFunctionReturn(0);
74*70f19b1fSKris Buschelman }
75*70f19b1fSKris Buschelman 
76*70f19b1fSKris Buschelman #undef __FUNCT__
77*70f19b1fSKris Buschelman #define __FUNCT__ "MatTranspose_SeqIJ_FAST"
78*70f19b1fSKris Buschelman int MatTranspose_SeqAIJ_FAST(Mat A,Mat *B) {
79*70f19b1fSKris Buschelman   int        ierr,i,j,anzj;
80*70f19b1fSKris Buschelman   Mat        At;
81*70f19b1fSKris Buschelman   Mat_SeqAIJ *a=(Mat_SeqAIJ *)A->data,*at;
82*70f19b1fSKris Buschelman   int        aishift = a->indexshift,an=A->N,am=A->M;
83*70f19b1fSKris Buschelman   int        *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
84*70f19b1fSKris Buschelman   MatScalar  *ata,*aa=a->a;
85*70f19b1fSKris Buschelman   PetscFunctionBegin;
86*70f19b1fSKris Buschelman 
87*70f19b1fSKris Buschelman   if (aishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported.");
88*70f19b1fSKris Buschelman 
89*70f19b1fSKris Buschelman   /* Set up timers */
90*70f19b1fSKris Buschelman   if (!logkey_mattranspose) {
91*70f19b1fSKris Buschelman     ierr = PetscLogEventRegister(&logkey_mattranspose,"MatTranspose_SeqAIJ_FAST",MAT_COOKIE);CHKERRQ(ierr);
92*70f19b1fSKris Buschelman   }
93*70f19b1fSKris Buschelman   ierr = PetscLogEventBegin(logkey_mattranspose,A,0,0,0);CHKERRQ(ierr);
94*70f19b1fSKris Buschelman 
95*70f19b1fSKris Buschelman   /* Allocate space for symbolic transpose info and work array */
96*70f19b1fSKris Buschelman   ierr = PetscMalloc((an+1)*sizeof(int),&ati);CHKERRQ(ierr);
97*70f19b1fSKris Buschelman   ierr = PetscMalloc(ai[am]*sizeof(int),&atj);CHKERRQ(ierr);
98*70f19b1fSKris Buschelman   ierr = PetscMalloc(ai[am]*sizeof(MatScalar),&ata);CHKERRQ(ierr);
99*70f19b1fSKris Buschelman   ierr = PetscMalloc(an*sizeof(int),&atfill);CHKERRQ(ierr);
100*70f19b1fSKris Buschelman   ierr = PetscMemzero(ati,(an+1)*sizeof(int));CHKERRQ(ierr);
101*70f19b1fSKris Buschelman   /* Walk through aj and count ## of non-zeros in each row of A^T. */
102*70f19b1fSKris Buschelman   /* Note: offset by 1 for fast conversion into csr format. */
103*70f19b1fSKris Buschelman   for (i=0;i<ai[am];i++) {
104*70f19b1fSKris Buschelman     ati[aj[i]+1] += 1;
105*70f19b1fSKris Buschelman   }
106*70f19b1fSKris Buschelman   /* Form ati for csr format of A^T. */
107*70f19b1fSKris Buschelman   for (i=0;i<an;i++) {
108*70f19b1fSKris Buschelman     ati[i+1] += ati[i];
109*70f19b1fSKris Buschelman   }
110*70f19b1fSKris Buschelman 
111*70f19b1fSKris Buschelman   /* Copy ati into atfill so we have locations of the next free space in atj */
112*70f19b1fSKris Buschelman   ierr = PetscMemcpy(atfill,ati,an*sizeof(int));CHKERRQ(ierr);
113*70f19b1fSKris Buschelman 
114*70f19b1fSKris Buschelman   /* Walk through A row-wise and mark nonzero entries of A^T. */
115*70f19b1fSKris Buschelman   for (i=0;i<am;i++) {
116*70f19b1fSKris Buschelman     anzj = ai[i+1] - ai[i];
117*70f19b1fSKris Buschelman     for (j=0;j<anzj;j++) {
118*70f19b1fSKris Buschelman       atj[atfill[*aj]] = i;
119*70f19b1fSKris Buschelman       ata[atfill[*aj]] = *aa++;
120*70f19b1fSKris Buschelman       atfill[*aj++]   += 1;
121*70f19b1fSKris Buschelman     }
122*70f19b1fSKris Buschelman   }
123*70f19b1fSKris Buschelman 
124*70f19b1fSKris Buschelman   /* Clean up temporary space and complete requests. */
125*70f19b1fSKris Buschelman   ierr = PetscFree(atfill);CHKERRQ(ierr);
126*70f19b1fSKris Buschelman   ierr = MatCreateSeqAIJWithArrays(A->comm,an,am,ati,atj,ata,&At);CHKERRQ(ierr);
127*70f19b1fSKris Buschelman   at   = (Mat_SeqAIJ *)(At->data);
128*70f19b1fSKris Buschelman   at->freedata = PETSC_TRUE;
129*70f19b1fSKris Buschelman   at->nonew    = 0;
130*70f19b1fSKris Buschelman   if (B) {
131*70f19b1fSKris Buschelman     *B = At;
132*70f19b1fSKris Buschelman   } else {
133*70f19b1fSKris Buschelman     ierr = MatHeaderCopy(A,At);
134*70f19b1fSKris Buschelman   }
135*70f19b1fSKris Buschelman   ierr = PetscLogEventEnd(logkey_mattranspose,A,0,0,0);CHKERRQ(ierr);
136*70f19b1fSKris Buschelman   PetscFunctionReturn(0);
137*70f19b1fSKris Buschelman }
138*70f19b1fSKris Buschelman 
139*70f19b1fSKris Buschelman #undef __FUNCT__
140*70f19b1fSKris Buschelman #define __FUNCT__ "MatRestoreSymbolicTranspose_SeqAIJ"
141*70f19b1fSKris Buschelman int MatRestoreSymbolicTranspose_SeqAIJ(Mat A,int *ati[],int *atj[]) {
142*70f19b1fSKris Buschelman   int ierr;
143*70f19b1fSKris Buschelman 
144*70f19b1fSKris Buschelman   PetscFunctionBegin;
145*70f19b1fSKris Buschelman   ierr = PetscLogInfo(A,"Restoring Symbolic Transpose.\n");CHKERRQ(ierr);
146*70f19b1fSKris Buschelman   ierr = PetscFree(*ati);CHKERRQ(ierr);
147*70f19b1fSKris Buschelman   ati  = PETSC_NULL;
148*70f19b1fSKris Buschelman   ierr = PetscFree(*atj);CHKERRQ(ierr);
149*70f19b1fSKris Buschelman   atj  = PETSC_NULL;
150*70f19b1fSKris Buschelman   PetscFunctionReturn(0);
151*70f19b1fSKris Buschelman }
152*70f19b1fSKris Buschelman 
153