xref: /petsc/src/mat/impls/aij/seq/symtranspose.c (revision 5b6bfdb9644f185dbf5e5a09b808ec241507e1e7)
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 PetscErrorCode MatGetSymbolicTranspose_SeqAIJ(Mat A,PetscInt *Ati[],PetscInt *Atj[])
19 {
20   PetscErrorCode ierr;
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;
25 
26   PetscFunctionBegin;
27   ierr = PetscInfo(A,"Getting Symbolic Transpose.\n");CHKERRQ(ierr);
28 
29   /* Set up timers */
30   ierr = PetscLogEventBegin(MAT_Getsymtranspose,A,0,0,0);CHKERRQ(ierr);
31 
32   /* Allocate space for symbolic transpose info and work array */
33   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
34   ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
35   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
36 
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   }
46 
47   /* Copy ati into atfill so we have locations of the next free space in atj */
48   ierr = PetscMemcpy(atfill,ati,an*sizeof(PetscInt));CHKERRQ(ierr);
49 
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   }
58 
59   /* Clean up temporary space and complete requests. */
60   ierr = PetscFree(atfill);CHKERRQ(ierr);
61   *Ati = ati;
62   *Atj = atj;
63 
64   ierr = PetscLogEventEnd(MAT_Getsymtranspose,A,0,0,0);CHKERRQ(ierr);
65   PetscFunctionReturn(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 {
73   PetscErrorCode ierr;
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;
78 
79   PetscFunctionBegin;
80   ierr = PetscInfo(A,"Getting Symbolic Transpose\n");CHKERRQ(ierr);
81   ierr = PetscLogEventBegin(MAT_Getsymtransreduced,A,0,0,0);CHKERRQ(ierr);
82 
83   /* Allocate space for symbolic transpose info and work array */
84   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
85   anzj = ai[rend] - ai[rstart];
86   ierr = PetscMalloc1(anzj+1,&atj);CHKERRQ(ierr);
87   ierr = PetscMalloc1(an+1,&atfill);CHKERRQ(ierr);
88 
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   }
98 
99   /* Copy ati into atfill so we have locations of the next free space in atj */
100   ierr = PetscMemcpy(atfill,ati,an*sizeof(PetscInt));CHKERRQ(ierr);
101 
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   }
111 
112   /* Clean up temporary space and complete requests. */
113   ierr = PetscFree(atfill);CHKERRQ(ierr);
114   *Ati = ati;
115   *Atj = atj;
116 
117   ierr = PetscLogEventEnd(MAT_Getsymtransreduced,A,0,0,0);CHKERRQ(ierr);
118   PetscFunctionReturn(0);
119 }
120 
121 PetscErrorCode MatTranspose_SeqAIJ_FAST(Mat A,MatReuse reuse,Mat *B)
122 {
123   PetscErrorCode ierr;
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;
130 
131   PetscFunctionBegin;
132   ierr = PetscLogEventBegin(MAT_Transpose_SeqAIJ,A,0,0,0);CHKERRQ(ierr);
133 
134   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
135     /* Allocate space for symbolic transpose info and work array */
136     ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
137     ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
138     ierr = PetscMalloc1(ai[am],&ata);CHKERRQ(ierr);
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   }
155 
156   /* Copy ati into atfill so we have locations of the next free space in atj */
157   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
158   ierr = PetscMemcpy(atfill,ati,an*sizeof(PetscInt));CHKERRQ(ierr);
159 
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   }
169 
170   /* Clean up temporary space and complete requests. */
171   ierr = PetscFree(atfill);CHKERRQ(ierr);
172   if (reuse == MAT_INITIAL_MATRIX) {
173     ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,ata,&At);CHKERRQ(ierr);
174 
175     at          = (Mat_SeqAIJ*)(At->data);
176     at->free_a  = PETSC_TRUE;
177     at->free_ij = PETSC_TRUE;
178     at->nonew   = 0;
179   }
180 
181   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
182     *B = At;
183   } else {
184     ierr = MatHeaderMerge(A,&At);CHKERRQ(ierr);
185   }
186   ierr = PetscLogEventEnd(MAT_Transpose_SeqAIJ,A,0,0,0);CHKERRQ(ierr);
187   PetscFunctionReturn(0);
188 }
189 
190 PetscErrorCode MatRestoreSymbolicTranspose_SeqAIJ(Mat A,PetscInt *ati[],PetscInt *atj[])
191 {
192   PetscErrorCode ierr;
193 
194   PetscFunctionBegin;
195   ierr = PetscInfo(A,"Restoring Symbolic Transpose.\n");CHKERRQ(ierr);
196   ierr = PetscFree(*ati);CHKERRQ(ierr);
197   ierr = PetscFree(*atj);CHKERRQ(ierr);
198   PetscFunctionReturn(0);
199 }
200 
201