Actual source code: aijsbaij.c
petsc-3.13.0 2020-03-29
2: #include <../src/mat/impls/aij/seq/aij.h>
3: #include <../src/mat/impls/baij/seq/baij.h>
4: #include <../src/mat/impls/sbaij/seq/sbaij.h>
6: PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
7: {
8: Mat B;
9: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
10: Mat_SeqAIJ *b;
12: PetscInt *ai=a->i,*aj=a->j,m=A->rmap->N,n=A->cmap->n,i,j,k,*bi,*bj,*rowlengths,nz,*rowstart,itmp;
13: PetscInt bs =A->rmap->bs,bs2=bs*bs,mbs=A->rmap->N/bs,diagcnt=0;
14: MatScalar *av,*bv;
15: #if defined(PETSC_USE_COMPLEX)
16: const int aconj = A->hermitian ? 1 : 0;
17: #else
18: const int aconj = 0;
19: #endif
22: /* compute rowlengths of newmat */
23: PetscMalloc2(m,&rowlengths,m+1,&rowstart);
25: for (i=0; i<mbs; i++) rowlengths[i*bs] = 0;
26: k = 0;
27: for (i=0; i<mbs; i++) {
28: nz = ai[i+1] - ai[i];
29: if (nz) {
30: rowlengths[k] += nz; /* no. of upper triangular blocks */
31: if (*aj == i) {aj++;diagcnt++;nz--;} /* skip diagonal */
32: for (j=0; j<nz; j++) { /* no. of lower triangular blocks */
33: rowlengths[(*aj)*bs]++; aj++;
34: }
35: }
36: rowlengths[k] *= bs;
37: for (j=1; j<bs; j++) {
38: rowlengths[k+j] = rowlengths[k];
39: }
40: k += bs;
41: }
43: if (reuse != MAT_REUSE_MATRIX) {
44: MatCreate(PetscObjectComm((PetscObject)A),&B);
45: MatSetSizes(B,m,n,m,n);
46: MatSetType(B,MATSEQAIJ);
47: MatSeqAIJSetPreallocation(B,0,rowlengths);
48: MatSetBlockSize(B,A->rmap->bs);
49: } else B = *newmat;
51: b = (Mat_SeqAIJ*)(B->data);
52: bi = b->i;
53: bj = b->j;
54: bv = b->a;
56: /* set b->i */
57: bi[0] = 0; rowstart[0] = 0;
58: for (i=0; i<mbs; i++) {
59: for (j=0; j<bs; j++) {
60: b->ilen[i*bs+j] = rowlengths[i*bs];
61: rowstart[i*bs+j+1] = rowstart[i*bs+j] + rowlengths[i*bs];
62: }
63: bi[i+1] = bi[i] + rowlengths[i*bs]/bs;
64: }
65: if (bi[mbs] != 2*a->nz - diagcnt) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"bi[mbs]: %D != 2*a->nz-diagcnt: %D\n",bi[mbs],2*a->nz - diagcnt);
67: /* set b->j and b->a */
68: aj = a->j; av = a->a;
69: for (i=0; i<mbs; i++) {
70: nz = ai[i+1] - ai[i];
71: /* diagonal block */
72: if (nz && *aj == i) {
73: nz--;
74: for (j=0; j<bs; j++) { /* row i*bs+j */
75: itmp = i*bs+j;
76: for (k=0; k<bs; k++) { /* col i*bs+k */
77: *(bj + rowstart[itmp]) = (*aj)*bs+k;
78: *(bv + rowstart[itmp]) = *(av+k*bs+j);
79: rowstart[itmp]++;
80: }
81: }
82: aj++; av += bs2;
83: }
85: while (nz--) {
86: /* lower triangular blocks */
87: for (j=0; j<bs; j++) { /* row (*aj)*bs+j */
88: itmp = (*aj)*bs+j;
89: for (k=0; k<bs; k++) { /* col i*bs+k */
90: *(bj + rowstart[itmp]) = i*bs+k;
91: *(bv + rowstart[itmp]) = aconj ? PetscConj(*(av+j*bs+k)) : *(av+j*bs+k);
92: rowstart[itmp]++;
93: }
94: }
95: /* upper triangular blocks */
96: for (j=0; j<bs; j++) { /* row i*bs+j */
97: itmp = i*bs+j;
98: for (k=0; k<bs; k++) { /* col (*aj)*bs+k */
99: *(bj + rowstart[itmp]) = (*aj)*bs+k;
100: *(bv + rowstart[itmp]) = *(av+k*bs+j);
101: rowstart[itmp]++;
102: }
103: }
104: aj++; av += bs2;
105: }
106: }
107: PetscFree2(rowlengths,rowstart);
108: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
109: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
111: if (reuse == MAT_INPLACE_MATRIX) {
112: MatHeaderReplace(A,&B);
113: } else {
114: *newmat = B;
115: }
116: return(0);
117: }
119: PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqSBAIJ(Mat A,MatType newtype,MatReuse reuse,Mat *newmat)
120: {
121: Mat B;
122: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
123: Mat_SeqSBAIJ *b;
125: PetscInt *ai=a->i,*aj,m=A->rmap->N,n=A->cmap->N,i,j,*bi,*bj,*rowlengths,bs=PetscAbs(A->rmap->bs);
126: MatScalar *av,*bv;
129: if (!A->symmetric) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"Matrix must be symmetric. Call MatSetOption(mat,MAT_SYMMETRIC,PETSC_TRUE)");
130: if (n != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Matrix must be square");
132: PetscMalloc1(m/bs,&rowlengths);
133: for (i=0; i<m/bs; i++) {
134: rowlengths[i] = (ai[i*bs+1] - a->diag[i*bs])/bs;
135: }
136: if (reuse != MAT_REUSE_MATRIX) {
137: MatCreate(PetscObjectComm((PetscObject)A),&B);
138: MatSetSizes(B,m,n,m,n);
139: MatSetType(B,MATSEQSBAIJ);
140: MatSeqSBAIJSetPreallocation(B,bs,0,rowlengths);
141: } else B = *newmat;
143: if (bs == 1) {
144: b = (Mat_SeqSBAIJ*)(B->data);
145: bi = b->i;
146: bj = b->j;
147: bv = b->a;
149: bi[0] = 0;
150: for (i=0; i<m; i++) {
151: aj = a->j + a->diag[i];
152: av = a->a + a->diag[i];
153: for (j=0; j<rowlengths[i]; j++) {
154: *bj = *aj; bj++; aj++;
155: *bv = *av; bv++; av++;
156: }
157: bi[i+1] = bi[i] + rowlengths[i];
158: b->ilen[i] = rowlengths[i];
159: }
160: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
161: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
162: } else {
163: MatSetOption(B,MAT_IGNORE_LOWER_TRIANGULAR,PETSC_TRUE);
164: /* reuse may not be equal to MAT_REUSE_MATRIX, but the basic converter will reallocate or replace newmat if this value is not used */
165: /* if reuse is equal to MAT_INITIAL_MATRIX, it has been appropriately preallocated before */
166: /* MAT_INPLACE_MATRIX, it will be replaced with MatHeaderReplace below */
167: MatConvert_Basic(A,newtype,MAT_REUSE_MATRIX,&B);
168: }
169: PetscFree(rowlengths);
170: if (reuse == MAT_INPLACE_MATRIX) {
171: MatHeaderReplace(A,&B);
172: } else *newmat = B;
173: return(0);
174: }
176: PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
177: {
178: Mat B;
179: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
180: Mat_SeqBAIJ *b;
182: PetscInt *ai=a->i,*aj=a->j,m=A->rmap->N,n=A->cmap->n,i,k,*bi,*bj,*browlengths,nz,*browstart,itmp;
183: PetscInt bs =A->rmap->bs,bs2=bs*bs,mbs=m/bs,col,row;
184: MatScalar *av,*bv;
185: #if defined(PETSC_USE_COMPLEX)
186: const int aconj = A->hermitian ? 1 : 0;
187: #else
188: const int aconj = 0;
189: #endif
192: /* compute browlengths of newmat */
193: PetscMalloc2(mbs,&browlengths,mbs,&browstart);
194: for (i=0; i<mbs; i++) browlengths[i] = 0;
195: for (i=0; i<mbs; i++) {
196: nz = ai[i+1] - ai[i];
197: aj++; /* skip diagonal */
198: for (k=1; k<nz; k++) { /* no. of lower triangular blocks */
199: browlengths[*aj]++; aj++;
200: }
201: browlengths[i] += nz; /* no. of upper triangular blocks */
202: }
204: if (reuse != MAT_REUSE_MATRIX) {
205: MatCreate(PetscObjectComm((PetscObject)A),&B);
206: MatSetSizes(B,m,n,m,n);
207: MatSetType(B,MATSEQBAIJ);
208: MatSeqBAIJSetPreallocation(B,bs,0,browlengths);
209: } else B = *newmat;
211: b = (Mat_SeqBAIJ*)(B->data);
212: bi = b->i;
213: bj = b->j;
214: bv = b->a;
216: /* set b->i */
217: bi[0] = 0;
218: for (i=0; i<mbs; i++) {
219: b->ilen[i] = browlengths[i];
220: bi[i+1] = bi[i] + browlengths[i];
221: browstart[i] = bi[i];
222: }
223: if (bi[mbs] != 2*a->nz - mbs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"bi[mbs]: %D != 2*a->nz - mbs: %D\n",bi[mbs],2*a->nz - mbs);
225: /* set b->j and b->a */
226: aj = a->j; av = a->a;
227: for (i=0; i<mbs; i++) {
228: /* diagonal block */
229: *(bj + browstart[i]) = *aj; aj++;
231: itmp = bs2*browstart[i];
232: for (k=0; k<bs2; k++) {
233: *(bv + itmp + k) = *av; av++;
234: }
235: browstart[i]++;
237: nz = ai[i+1] - ai[i] -1;
238: while (nz--) {
239: /* lower triangular blocks - transpose blocks of A */
240: *(bj + browstart[*aj]) = i; /* block col index */
242: itmp = bs2*browstart[*aj]; /* row index */
243: for (col=0; col<bs; col++) {
244: k = col;
245: for (row=0; row<bs; row++) {
246: bv[itmp + col*bs+row] = aconj ? PetscConj(av[k]) : av[k];
247: k+=bs;
248: }
249: }
250: browstart[*aj]++;
252: /* upper triangular blocks */
253: *(bj + browstart[i]) = *aj; aj++;
255: itmp = bs2*browstart[i];
256: for (k=0; k<bs2; k++) {
257: bv[itmp + k] = av[k];
258: }
259: av += bs2;
260: browstart[i]++;
261: }
262: }
263: PetscFree2(browlengths,browstart);
264: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
265: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
267: if (reuse == MAT_INPLACE_MATRIX) {
268: MatHeaderReplace(A,&B);
269: } else *newmat = B;
270: return(0);
271: }
273: PETSC_INTERN PetscErrorCode 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;
279: PetscInt *ai=a->i,*aj,m=A->rmap->N,n=A->cmap->n,i,j,k,*bi,*bj,*browlengths;
280: PetscInt bs =A->rmap->bs,bs2=bs*bs,mbs=m/bs,dd;
281: MatScalar *av,*bv;
282: PetscBool flg;
285: if (!A->symmetric) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"Matrix must be symmetric. Call MatSetOption(mat,MAT_SYMMETRIC,PETSC_TRUE)");
286: if (n != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Matrix must be square");
287: MatMissingDiagonal_SeqBAIJ(A,&flg,&dd); /* check for missing diagonals, then mark diag */
288: if (flg) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal %D",dd);
290: PetscMalloc1(mbs,&browlengths);
291: for (i=0; i<mbs; i++) {
292: browlengths[i] = ai[i+1] - a->diag[i];
293: }
295: if (reuse != MAT_REUSE_MATRIX) {
296: MatCreate(PetscObjectComm((PetscObject)A),&B);
297: MatSetSizes(B,m,n,m,n);
298: MatSetType(B,MATSEQSBAIJ);
299: MatSeqSBAIJSetPreallocation(B,bs,0,browlengths);
300: } else B = *newmat;
302: b = (Mat_SeqSBAIJ*)(B->data);
303: bi = b->i;
304: bj = b->j;
305: bv = b->a;
307: bi[0] = 0;
308: for (i=0; i<mbs; i++) {
309: aj = a->j + a->diag[i];
310: av = a->a + (a->diag[i])*bs2;
311: for (j=0; j<browlengths[i]; j++) {
312: *bj = *aj; bj++; aj++;
313: for (k=0; k<bs2; k++) {
314: *bv = *av; bv++; av++;
315: }
316: }
317: bi[i+1] = bi[i] + browlengths[i];
318: b->ilen[i] = browlengths[i];
319: }
320: PetscFree(browlengths);
321: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
322: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
324: if (reuse == MAT_INPLACE_MATRIX) {
325: MatHeaderReplace(A,&B);
326: } else *newmat = B;
327: return(0);
328: }