xref: /petsc/src/mat/impls/sbaij/seq/aijsbaij.c (revision e2df7a95c5ea77c899beea10ff9effd6061e7c8f)
1 #define PETSCMAT_DLL
2 
3 #include "src/mat/impls/aij/seq/aij.h"
4 #include "src/mat/impls/baij/seq/baij.h"
5 #include "src/mat/impls/sbaij/seq/sbaij.h"
6 
7 EXTERN_C_BEGIN
8 #undef __FUNCT__
9 #define __FUNCT__ "MatConvert_SeqSBAI_SeqAIJ"
10 PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqSBAIJ_SeqAIJ(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
11 {
12   Mat            B;
13   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
14   Mat_SeqAIJ     *b;
15   PetscErrorCode ierr;
16   PetscInt       *ai=a->i,*aj=a->j,m=A->m,n=A->n,i,j,k,*bi,*bj,*rowlengths,nz,*rowstart,itmp;
17   PetscInt       bs=A->bs,bs2=bs*bs,mbs=A->m/bs;
18   PetscScalar    *av,*bv;
19 
20   PetscFunctionBegin;
21 
22   /* compute rowlengths of newmat */
23   ierr = PetscMalloc((2*m+1)*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
24   rowstart = rowlengths + m;
25 
26   for (i=0; i<mbs; i++) rowlengths[i*bs] = 0;
27   aj = a->j;
28   k = 0;
29   for (i=0; i<mbs; i++) {
30     nz = ai[i+1] - ai[i];
31     aj++; /* skip diagonal */
32     for (j=1; j<nz; j++) { /* no. of lower triangular blocks */
33       rowlengths[(*aj)*bs]++; aj++;
34     }
35     rowlengths[k] += nz;   /* no. of upper triangular blocks */
36     rowlengths[k] *= bs;
37     for (j=1; j<bs; j++) {
38       rowlengths[k+j] = rowlengths[k];
39     }
40     k += bs;
41     /* printf(" rowlengths[%d]: %d\n",i, rowlengths[i]); */
42   }
43 
44   ierr = MatCreate(A->comm,&B);CHKERRQ(ierr);
45   ierr = MatSetSizes(B,m,n,m,n);CHKERRQ(ierr);
46   ierr = MatSetType(B,newtype);CHKERRQ(ierr);
47   ierr = MatSeqAIJSetPreallocation(B,0,rowlengths);CHKERRQ(ierr);
48   ierr = MatSetOption(B,MAT_COLUMN_ORIENTED);CHKERRQ(ierr);
49   ierr = MatSetOption(B,MAT_ROWS_SORTED);CHKERRQ(ierr);
50   ierr = MatSetOption(B,MAT_COLUMNS_SORTED);CHKERRQ(ierr);
51   B->bs = A->bs;
52 
53   b  = (Mat_SeqAIJ*)(B->data);
54   bi = b->i;
55   bj = b->j;
56   bv = b->a;
57 
58   /* set b->i */
59   bi[0] = 0; rowstart[0] = 0;
60   for (i=0; i<mbs; i++){
61     for (j=0; j<bs; j++){
62       b->ilen[i*bs+j]  = rowlengths[i*bs];
63       rowstart[i*bs+j+1] = rowstart[i*bs+j] + rowlengths[i*bs];
64     }
65     bi[i+1]     = bi[i] + rowlengths[i*bs]/bs;
66   }
67   if (bi[mbs] != 2*a->nz - mbs) SETERRQ2(PETSC_ERR_PLIB,"bi[mbs]: %D != 2*a->nz-mbs: %D\n",bi[mbs],2*a->nz - mbs);
68 
69   /* set b->j and b->a */
70   aj = a->j; av = a->a;
71   for (i=0; i<mbs; i++) {
72     /* diagonal block */
73     for (j=0; j<bs; j++){   /* row i*bs+j */
74       itmp = i*bs+j;
75       for (k=0; k<bs; k++){ /* col i*bs+k */
76         *(bj + rowstart[itmp]) = (*aj)*bs+k;
77         *(bv + rowstart[itmp]) = *(av+k*bs+j);
78         rowstart[itmp]++;
79       }
80     }
81     aj++; av += bs2;
82 
83     nz = ai[i+1] - ai[i] -1;
84     while (nz--){
85       /* lower triangular blocks */
86       for (j=0; j<bs; j++){   /* row (*aj)*bs+j */
87         itmp = (*aj)*bs+j;
88         for (k=0; k<bs; k++){ /* col i*bs+k */
89           *(bj + rowstart[itmp]) = i*bs+k;
90           *(bv + rowstart[itmp]) = *(av+k*bs+j);
91           rowstart[itmp]++;
92         }
93       }
94       /* upper triangular blocks */
95       for (j=0; j<bs; j++){   /* row i*bs+j */
96         itmp = i*bs+j;
97         for (k=0; k<bs; k++){ /* col (*aj)*bs+k */
98           *(bj + rowstart[itmp]) = (*aj)*bs+k;
99           *(bv + rowstart[itmp]) = *(av+k*bs+j);
100           rowstart[itmp]++;
101         }
102       }
103       aj++; av += bs2;
104     }
105   }
106   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
107   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
108   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
109 
110   if (reuse == MAT_REUSE_MATRIX) {
111     ierr = MatHeaderReplace(A,B);CHKERRQ(ierr);
112   } else {
113     *newmat = B;
114   }
115   PetscFunctionReturn(0);
116 }
117 EXTERN_C_END
118 
119 EXTERN_C_BEGIN
120 #undef __FUNCT__
121 #define __FUNCT__ "MatConvert_SeqAIJ_SeqSBAIJ"
122 PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqAIJ_SeqSBAIJ(Mat A, MatType newtype,MatReuse reuse,Mat *newmat) {
123   Mat            B;
124   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
125   Mat_SeqSBAIJ   *b;
126   PetscErrorCode ierr;
127   PetscInt       *ai=a->i,*aj,m=A->M,n=A->N,i,j,*bi,*bj,*rowlengths;
128   PetscScalar    *av,*bv;
129 
130   PetscFunctionBegin;
131   if (n != m) SETERRQ(PETSC_ERR_ARG_WRONG,"Matrix must be square");
132   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); /* check for missing diagonals, then mark diag */
133 
134   ierr = PetscMalloc(m*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
135   for (i=0; i<m; i++) {
136     rowlengths[i] = ai[i+1] - a->diag[i];
137   }
138   ierr = MatCreate(A->comm,&B);CHKERRQ(ierr);
139   ierr = MatSetSizes(B,m,n,m,n);CHKERRQ(ierr);
140   ierr = MatSetType(B,newtype);CHKERRQ(ierr);
141   ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(B,1,0,rowlengths);CHKERRQ(ierr);
142 
143   ierr = MatSetOption(B,MAT_ROW_ORIENTED);CHKERRQ(ierr);
144   ierr = MatSetOption(B,MAT_ROWS_SORTED);CHKERRQ(ierr);
145   ierr = MatSetOption(B,MAT_COLUMNS_SORTED);CHKERRQ(ierr);
146 
147   b  = (Mat_SeqSBAIJ*)(B->data);
148   bi = b->i;
149   bj = b->j;
150   bv = b->a;
151 
152   bi[0] = 0;
153   for (i=0; i<m; i++) {
154     aj = a->j + a->diag[i];
155     av = a->a + a->diag[i];
156     for (j=0; j<rowlengths[i]; j++){
157       *bj = *aj; bj++; aj++;
158       *bv = *av; bv++; av++;
159     }
160     bi[i+1]    = bi[i] + rowlengths[i];
161     b->ilen[i] = rowlengths[i];
162   }
163 
164   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
165   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
166   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
167 
168   if (reuse == MAT_REUSE_MATRIX) {
169     ierr = MatHeaderReplace(A,B);CHKERRQ(ierr);
170   } else {
171     *newmat = B;
172   }
173   PetscFunctionReturn(0);
174 }
175 EXTERN_C_END
176 
177 EXTERN_C_BEGIN
178 #undef __FUNCT__
179 #define __FUNCT__ "MatConvert_SeqSBAI_SeqBAIJ"
180 PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqSBAIJ_SeqBAIJ(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
181 {
182   Mat            B;
183   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
184   Mat_SeqBAIJ    *b;
185   PetscErrorCode ierr;
186   PetscInt       *ai=a->i,*aj=a->j,m=A->m,n=A->n,i,k,*bi,*bj,*browlengths,nz,*browstart,itmp;
187   PetscInt       bs=A->bs,bs2=bs*bs,mbs=m/bs;
188   PetscScalar    *av,*bv;
189 
190   PetscFunctionBegin;
191   /* compute browlengths of newmat */
192   ierr = PetscMalloc(2*mbs*sizeof(PetscInt),&browlengths);CHKERRQ(ierr);
193   browstart = browlengths + mbs;
194   for (i=0; i<mbs; i++) browlengths[i] = 0;
195   aj = a->j;
196   for (i=0; i<mbs; i++) {
197     nz = ai[i+1] - ai[i];
198     aj++; /* skip diagonal */
199     for (k=1; k<nz; k++) { /* no. of lower triangular blocks */
200       browlengths[*aj]++; aj++;
201     }
202     browlengths[i] += nz;   /* no. of upper triangular blocks */
203   }
204 
205   ierr = MatCreate(A->comm,&B);CHKERRQ(ierr);
206   ierr = MatSetSizes(B,m,n,m,n);CHKERRQ(ierr);
207   ierr = MatSetType(B,newtype);CHKERRQ(ierr);
208   ierr = MatSeqBAIJSetPreallocation(B,bs,0,browlengths);CHKERRQ(ierr);
209   ierr = MatSetOption(B,MAT_ROW_ORIENTED);CHKERRQ(ierr);
210   ierr = MatSetOption(B,MAT_ROWS_SORTED);CHKERRQ(ierr);
211   ierr = MatSetOption(B,MAT_COLUMNS_SORTED);CHKERRQ(ierr);
212 
213   b  = (Mat_SeqBAIJ*)(B->data);
214   bi = b->i;
215   bj = b->j;
216   bv = b->a;
217 
218   /* set b->i */
219   bi[0] = 0;
220   for (i=0; i<mbs; i++){
221     b->ilen[i]    = browlengths[i];
222     bi[i+1]       = bi[i] + browlengths[i];
223     browstart[i]  = bi[i];
224   }
225   if (bi[mbs] != 2*a->nz - mbs) SETERRQ2(PETSC_ERR_PLIB,"bi[mbs]: %D != 2*a->nz - mbs: %D\n",bi[mbs],2*a->nz - mbs);
226 
227   /* set b->j and b->a */
228   aj = a->j; av = a->a;
229   for (i=0; i<mbs; i++) {
230     /* diagonal block */
231     *(bj + browstart[i]) = *aj; aj++;
232     itmp = bs2*browstart[i];
233     for (k=0; k<bs2; k++){
234       *(bv + itmp + k) = *av; av++;
235     }
236     browstart[i]++;
237 
238     nz = ai[i+1] - ai[i] -1;
239     while (nz--){
240       /* lower triangular blocks */
241       *(bj + browstart[*aj]) = i;
242       itmp = bs2*browstart[*aj];
243       for (k=0; k<bs2; k++){
244         *(bv + itmp + k) = *(av + k);
245       }
246       browstart[*aj]++;
247 
248       /* upper triangular blocks */
249       *(bj + browstart[i]) = *aj; aj++;
250       itmp = bs2*browstart[i];
251       for (k=0; k<bs2; k++){
252         *(bv + itmp + k) = *av; av++;
253       }
254       browstart[i]++;
255     }
256   }
257   ierr = PetscFree(browlengths);CHKERRQ(ierr);
258   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
259   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
260 
261   if (reuse == MAT_REUSE_MATRIX) {
262     ierr = MatHeaderReplace(A,B);CHKERRQ(ierr);
263   } else {
264     *newmat = B;
265   }
266   PetscFunctionReturn(0);
267 }
268 EXTERN_C_END
269 
270 EXTERN_C_BEGIN
271 #undef __FUNCT__
272 #define __FUNCT__ "MatConvert_SeqBAIJ_SeqSBAIJ"
273 PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqBAIJ_SeqSBAIJ(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
274 {
275   Mat            B;
276   Mat_SeqBAIJ    *a = (Mat_SeqBAIJ*)A->data;
277   Mat_SeqSBAIJ   *b;
278   PetscErrorCode ierr;
279   PetscInt       *ai=a->i,*aj,m=A->m,n=A->n,i,j,k,*bi,*bj,*browlengths;
280   PetscInt       bs=A->bs,bs2=bs*bs,mbs=m/bs;
281   PetscScalar    *av,*bv;
282 
283   PetscFunctionBegin;
284   if (n != m) SETERRQ(PETSC_ERR_ARG_WRONG,"Matrix must be square");
285   ierr = MatMissingDiagonal_SeqBAIJ(A);CHKERRQ(ierr); /* check for missing diagonals, then mark diag */
286 
287   ierr = PetscMalloc(mbs*sizeof(PetscInt),&browlengths);CHKERRQ(ierr);
288   for (i=0; i<mbs; i++) {
289     browlengths[i] = ai[i+1] - a->diag[i];
290   }
291 
292   ierr = MatCreate(A->comm,&B);CHKERRQ(ierr);
293   ierr = MatSetSizes(B,m,n,m,n);CHKERRQ(ierr);
294   ierr = MatSetType(B,newtype);CHKERRQ(ierr);
295   ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(B,bs,0,browlengths);CHKERRQ(ierr);
296   ierr = MatSetOption(B,MAT_ROW_ORIENTED);CHKERRQ(ierr);
297   ierr = MatSetOption(B,MAT_ROWS_SORTED);CHKERRQ(ierr);
298   ierr = MatSetOption(B,MAT_COLUMNS_SORTED);CHKERRQ(ierr);
299 
300   b  = (Mat_SeqSBAIJ*)(B->data);
301   bi = b->i;
302   bj = b->j;
303   bv = b->a;
304 
305   bi[0] = 0;
306   for (i=0; i<mbs; i++) {
307     aj = a->j + a->diag[i];
308     av = a->a + (a->diag[i])*bs2;
309     for (j=0; j<browlengths[i]; j++){
310       *bj = *aj; bj++; aj++;
311       for (k=0; k<bs2; k++){
312         *bv = *av; bv++; av++;
313       }
314     }
315     bi[i+1]    = bi[i] + browlengths[i];
316     b->ilen[i] = browlengths[i];
317   }
318   ierr = PetscFree(browlengths);CHKERRQ(ierr);
319   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
320   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
321 
322   if (reuse == MAT_REUSE_MATRIX) {
323     ierr = MatHeaderReplace(A,B);CHKERRQ(ierr);
324   } else {
325     *newmat = B;
326   }
327 
328   PetscFunctionReturn(0);
329 }
330 EXTERN_C_END
331