xref: /petsc/src/mat/impls/aij/seq/symtranspose.c (revision 7d0a6c19129e7069c8a40e210b34ed62989173db)
1 
2 /*
3   Defines symbolic transpose routines for SeqAIJ matrices.
4 
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.
8 
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.
12 
13 */
14 
15 #include "../src/mat/impls/aij/seq/aij.h"
16 
17 
18 #undef __FUNCT__
19 #define __FUNCT__ "MatGetSymbolicTranspose_SeqAIJ"
20 PetscErrorCode MatGetSymbolicTranspose_SeqAIJ(Mat A,PetscInt *Ati[],PetscInt *Atj[])
21 {
22   PetscErrorCode ierr;
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;
27 
28   PetscFunctionBegin;
29 
30   ierr = PetscInfo(A,"Getting Symbolic Transpose.\n");CHKERRQ(ierr);
31 
32   /* Set up timers */
33   ierr = PetscLogEventBegin(MAT_Getsymtranspose,A,0,0,0);CHKERRQ(ierr);
34 
35   /* Allocate space for symbolic transpose info and work array */
36   ierr = PetscMalloc((an+1)*sizeof(PetscInt),&ati);CHKERRQ(ierr);
37   ierr = PetscMalloc(ai[am]*sizeof(PetscInt),&atj);CHKERRQ(ierr);
38   ierr = PetscMalloc(an*sizeof(PetscInt),&atfill);CHKERRQ(ierr);
39   ierr = PetscMemzero(ati,(an+1)*sizeof(PetscInt));CHKERRQ(ierr);
40 
41   /* Walk through aj and count ## of non-zeros in each row of A^T. */
42   /* Note: offset by 1 for fast conversion into csr format. */
43   for (i=0;i<ai[am];i++) {
44     ati[aj[i]+1] += 1;
45   }
46   /* Form ati for csr format of A^T. */
47   for (i=0;i<an;i++) {
48     ati[i+1] += ati[i];
49   }
50 
51   /* Copy ati into atfill so we have locations of the next free space in atj */
52   ierr = PetscMemcpy(atfill,ati,an*sizeof(PetscInt));CHKERRQ(ierr);
53 
54   /* Walk through A row-wise and mark nonzero entries of A^T. */
55   for (i=0;i<am;i++) {
56     anzj = ai[i+1] - ai[i];
57     for (j=0;j<anzj;j++) {
58       atj[atfill[*aj]] = i;
59       atfill[*aj++]   += 1;
60     }
61   }
62 
63   /* Clean up temporary space and complete requests. */
64   ierr = PetscFree(atfill);CHKERRQ(ierr);
65   *Ati = ati;
66   *Atj = atj;
67 
68   ierr = PetscLogEventEnd(MAT_Getsymtranspose,A,0,0,0);CHKERRQ(ierr);
69   PetscFunctionReturn(0);
70 }
71 /*
72   MatGetSymbolicTransposeReduced_SeqAIJ() - Get symbolic matrix structure of submatrix A[rstart:rend,:],
73      modified from MatGetSymbolicTranspose_SeqAIJ()
74 */
75 #undef __FUNCT__
76 #define __FUNCT__ "MatGetSymbolicTransposeReduced_SeqAIJ"
77 PetscErrorCode MatGetSymbolicTransposeReduced_SeqAIJ(Mat A,PetscInt rstart,PetscInt rend,PetscInt *Ati[],PetscInt *Atj[])
78 {
79   PetscErrorCode ierr;
80   PetscInt       i,j,anzj;
81   Mat_SeqAIJ     *a=(Mat_SeqAIJ *)A->data;
82   PetscInt       an=A->cmap->N;
83   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
84 
85   PetscFunctionBegin;
86   ierr = PetscInfo(A,"Getting Symbolic Transpose\n");CHKERRQ(ierr);
87   ierr = PetscLogEventBegin(MAT_Getsymtransreduced,A,0,0,0);CHKERRQ(ierr);
88 
89   /* Allocate space for symbolic transpose info and work array */
90   ierr = PetscMalloc((an+1)*sizeof(PetscInt),&ati);CHKERRQ(ierr);
91   anzj = ai[rend] - ai[rstart];
92   ierr = PetscMalloc((anzj+1)*sizeof(PetscInt),&atj);CHKERRQ(ierr);
93   ierr = PetscMalloc((an+1)*sizeof(PetscInt),&atfill);CHKERRQ(ierr);
94   ierr = PetscMemzero(ati,(an+1)*sizeof(PetscInt));CHKERRQ(ierr);
95 
96   /* Walk through aj and count ## of non-zeros in each row of A^T. */
97   /* Note: offset by 1 for fast conversion into csr format. */
98   for (i=ai[rstart]; i<ai[rend]; i++) {
99     ati[aj[i]+1] += 1;
100   }
101   /* Form ati for csr format of A^T. */
102   for (i=0;i<an;i++) {
103     ati[i+1] += ati[i];
104   }
105 
106   /* Copy ati into atfill so we have locations of the next free space in atj */
107   ierr = PetscMemcpy(atfill,ati,an*sizeof(PetscInt));CHKERRQ(ierr);
108 
109   /* Walk through A row-wise and mark nonzero entries of A^T. */
110   aj = aj + ai[rstart];
111   for (i=rstart; i<rend; i++) {
112     anzj = ai[i+1] - ai[i];
113     for (j=0;j<anzj;j++) {
114       atj[atfill[*aj]] = i-rstart;
115       atfill[*aj++]   += 1;
116     }
117   }
118 
119   /* Clean up temporary space and complete requests. */
120   ierr = PetscFree(atfill);CHKERRQ(ierr);
121   *Ati = ati;
122   *Atj = atj;
123 
124   ierr = PetscLogEventEnd(MAT_Getsymtransreduced,A,0,0,0);CHKERRQ(ierr);
125   PetscFunctionReturn(0);
126 }
127 
128 #undef __FUNCT__
129 #define __FUNCT__ "MatTranspose_SeqAIJ_FAST"
130 PetscErrorCode MatTranspose_SeqAIJ_FAST(Mat A,MatReuse reuse,Mat *B)
131 {
132   PetscErrorCode ierr;
133   PetscInt       i,j,anzj;
134   Mat            At;
135   Mat_SeqAIJ     *a=(Mat_SeqAIJ *)A->data,*at;
136   PetscInt       an=A->cmap->N,am=A->rmap->N;
137   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
138   MatScalar      *ata,*aa=a->a;
139 
140   PetscFunctionBegin;
141 
142   ierr = PetscLogEventBegin(MAT_Transpose_SeqAIJ,A,0,0,0);CHKERRQ(ierr);
143 
144   if (reuse == MAT_INITIAL_MATRIX || *B == A) {
145     /* Allocate space for symbolic transpose info and work array */
146     ierr = PetscMalloc((an+1)*sizeof(PetscInt),&ati);CHKERRQ(ierr);
147     ierr = PetscMalloc(ai[am]*sizeof(PetscInt),&atj);CHKERRQ(ierr);
148     ierr = PetscMalloc(ai[am]*sizeof(MatScalar),&ata);CHKERRQ(ierr);
149     ierr = PetscMemzero(ati,(an+1)*sizeof(PetscInt));CHKERRQ(ierr);
150     /* Walk through aj and count ## of non-zeros in each row of A^T. */
151     /* Note: offset by 1 for fast conversion into csr format. */
152     for (i=0;i<ai[am];i++) {
153       ati[aj[i]+1] += 1;
154     }
155     /* Form ati for csr format of A^T. */
156     for (i=0;i<an;i++) {
157       ati[i+1] += ati[i];
158     }
159   } else {
160     Mat_SeqAIJ *sub_B = (Mat_SeqAIJ*) (*B)->data;
161     ati = sub_B->i;
162     atj = sub_B->j;
163     ata = sub_B->a;
164     At = *B;
165   }
166 
167   /* Copy ati into atfill so we have locations of the next free space in atj */
168   ierr = PetscMalloc(an*sizeof(PetscInt),&atfill);CHKERRQ(ierr);
169   ierr = PetscMemcpy(atfill,ati,an*sizeof(PetscInt));CHKERRQ(ierr);
170 
171   /* Walk through A row-wise and mark nonzero entries of A^T. */
172   for (i=0;i<am;i++) {
173     anzj = ai[i+1] - ai[i];
174     for (j=0;j<anzj;j++) {
175       atj[atfill[*aj]] = i;
176       ata[atfill[*aj]] = *aa++;
177       atfill[*aj++]   += 1;
178     }
179   }
180 
181   /* Clean up temporary space and complete requests. */
182   ierr = PetscFree(atfill);CHKERRQ(ierr);
183   if (reuse == MAT_INITIAL_MATRIX) {
184     ierr = MatCreateSeqAIJWithArrays(((PetscObject)A)->comm,an,am,ati,atj,ata,&At);CHKERRQ(ierr);
185     at   = (Mat_SeqAIJ *)(At->data);
186     at->free_a  = PETSC_TRUE;
187     at->free_ij  = PETSC_TRUE;
188     at->nonew   = 0;
189   }
190 
191   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
192     *B = At;
193   } else {
194     ierr = MatHeaderMerge(A,At);
195   }
196   ierr = PetscLogEventEnd(MAT_Transpose_SeqAIJ,A,0,0,0);CHKERRQ(ierr);
197   PetscFunctionReturn(0);
198 }
199 
200 #undef __FUNCT__
201 #define __FUNCT__ "MatRestoreSymbolicTranspose_SeqAIJ"
202 PetscErrorCode MatRestoreSymbolicTranspose_SeqAIJ(Mat A,PetscInt *ati[],PetscInt *atj[])
203 {
204   PetscErrorCode ierr;
205 
206   PetscFunctionBegin;
207   ierr = PetscInfo(A,"Restoring Symbolic Transpose.\n");CHKERRQ(ierr);
208   ierr = PetscFree(*ati);CHKERRQ(ierr);
209   ierr = PetscFree(*atj);CHKERRQ(ierr);
210   PetscFunctionReturn(0);
211 }
212 
213