Actual source code: aijsbaij.c

petsc-3.13.1 2020-05-02
Report Typos and Errors

  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: }