xref: /petsc/src/mat/impls/sbaij/seq/sbaij.c (revision 7d6bfa3b9d7db0ccd4cc481237114ca8dbb0dbff)
1 #define PETSCMAT_DLL
2 
3 /*
4     Defines the basic matrix operations for the SBAIJ (compressed row)
5   matrix storage format.
6 */
7 #include "../src/mat/impls/baij/seq/baij.h"         /*I "petscmat.h" I*/
8 #include "../src/inline/spops.h"
9 #include "../src/mat/impls/sbaij/seq/sbaij.h"
10 
11 extern PetscErrorCode MatSeqSBAIJSetNumericFactorization(Mat,PetscTruth);
12 #define CHUNKSIZE  10
13 
14 /*
15      Checks for missing diagonals
16 */
17 #undef __FUNCT__
18 #define __FUNCT__ "MatMissingDiagonal_SeqSBAIJ"
19 PetscErrorCode MatMissingDiagonal_SeqSBAIJ(Mat A,PetscTruth *missing,PetscInt *dd)
20 {
21   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
22   PetscErrorCode ierr;
23   PetscInt       *diag,*jj = a->j,i;
24 
25   PetscFunctionBegin;
26   ierr = MatMarkDiagonal_SeqSBAIJ(A);CHKERRQ(ierr);
27   diag = a->diag;
28   *missing = PETSC_FALSE;
29   for (i=0; i<a->mbs; i++) {
30     if (jj[diag[i]] != i) {
31       *missing    = PETSC_TRUE;
32       if (dd) *dd = i;
33       break;
34     }
35   }
36   PetscFunctionReturn(0);
37 }
38 
39 #undef __FUNCT__
40 #define __FUNCT__ "MatMarkDiagonal_SeqSBAIJ"
41 PetscErrorCode MatMarkDiagonal_SeqSBAIJ(Mat A)
42 {
43   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
44   PetscErrorCode ierr;
45   PetscInt       i;
46 
47   PetscFunctionBegin;
48   if (!a->diag) {
49     ierr = PetscMalloc(a->mbs*sizeof(PetscInt),&a->diag);CHKERRQ(ierr);
50   }
51   for (i=0; i<a->mbs; i++) a->diag[i] = a->i[i];
52   PetscFunctionReturn(0);
53 }
54 
55 #undef __FUNCT__
56 #define __FUNCT__ "MatGetRowIJ_SeqSBAIJ"
57 static PetscErrorCode MatGetRowIJ_SeqSBAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth blockcompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
58 {
59   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
60   PetscInt     i,j,n = a->mbs,nz = a->i[n],bs = A->rmap->bs;
61   PetscErrorCode ierr;
62 
63   PetscFunctionBegin;
64   *nn = n;
65   if (!ia) PetscFunctionReturn(0);
66   if (!blockcompressed) {
67     /* malloc & create the natural set of indices */
68     ierr = PetscMalloc2((n+1)*bs,PetscInt,ia,nz*bs,PetscInt,ja);CHKERRQ(ierr);
69     for (i=0; i<n+1; i++) {
70       for (j=0; j<bs; j++) {
71         *ia[i*bs+j] = a->i[i]*bs+j+oshift;
72       }
73     }
74     for (i=0; i<nz; i++) {
75       for (j=0; j<bs; j++) {
76         *ja[i*bs+j] = a->j[i]*bs+j+oshift;
77       }
78     }
79   } else { /* blockcompressed */
80     if (oshift == 1) {
81       /* temporarily add 1 to i and j indices */
82       for (i=0; i<nz; i++) a->j[i]++;
83       for (i=0; i<n+1; i++) a->i[i]++;
84     }
85     *ia = a->i; *ja = a->j;
86   }
87 
88   PetscFunctionReturn(0);
89 }
90 
91 #undef __FUNCT__
92 #define __FUNCT__ "MatRestoreRowIJ_SeqSBAIJ"
93 static PetscErrorCode MatRestoreRowIJ_SeqSBAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth blockcompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
94 {
95   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
96   PetscInt     i,n = a->mbs,nz = a->i[n];
97   PetscErrorCode ierr;
98 
99   PetscFunctionBegin;
100   if (!ia) PetscFunctionReturn(0);
101 
102   if (!blockcompressed) {
103     ierr = PetscFree2(*ia,*ja);CHKERRQ(ierr);
104   } else if (oshift == 1) { /* blockcompressed */
105     for (i=0; i<nz; i++) a->j[i]--;
106     for (i=0; i<n+1; i++) a->i[i]--;
107   }
108 
109   PetscFunctionReturn(0);
110 }
111 
112 #undef __FUNCT__
113 #define __FUNCT__ "MatDestroy_SeqSBAIJ"
114 PetscErrorCode MatDestroy_SeqSBAIJ(Mat A)
115 {
116   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
117   PetscErrorCode ierr;
118 
119   PetscFunctionBegin;
120 #if defined(PETSC_USE_LOG)
121   PetscLogObjectState((PetscObject)A,"Rows=%D, NZ=%D",A->rmap->N,a->nz);
122 #endif
123   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
124   if (a->row) {ierr = ISDestroy(a->row);CHKERRQ(ierr);}
125   if (a->col){ierr = ISDestroy(a->col);CHKERRQ(ierr);}
126   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);}
127   ierr = PetscFree(a->diag);CHKERRQ(ierr);
128   ierr = PetscFree2(a->imax,a->ilen);CHKERRQ(ierr);
129   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
130   ierr = PetscFree(a->relax_work);CHKERRQ(ierr);
131   ierr = PetscFree(a->solves_work);CHKERRQ(ierr);
132   ierr = PetscFree(a->mult_work);CHKERRQ(ierr);
133   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
134   ierr = PetscFree(a->xtoy);CHKERRQ(ierr);
135 
136   ierr = PetscFree(a->inew);CHKERRQ(ierr);
137   ierr = PetscFree(a);CHKERRQ(ierr);
138 
139   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
140   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C","",PETSC_NULL);CHKERRQ(ierr);
141   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C","",PETSC_NULL);CHKERRQ(ierr);
142   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqSBAIJSetColumnIndices_C","",PETSC_NULL);CHKERRQ(ierr);
143   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqsbaij_seqaij_C","",PETSC_NULL);CHKERRQ(ierr);
144   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqsbaij_seqbaij_C","",PETSC_NULL);CHKERRQ(ierr);
145   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqSBAIJSetPreallocation_C","",PETSC_NULL);CHKERRQ(ierr);
146   PetscFunctionReturn(0);
147 }
148 
149 #undef __FUNCT__
150 #define __FUNCT__ "MatSetOption_SeqSBAIJ"
151 PetscErrorCode MatSetOption_SeqSBAIJ(Mat A,MatOption op,PetscTruth flg)
152 {
153   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
154   PetscErrorCode ierr;
155 
156   PetscFunctionBegin;
157   switch (op) {
158   case MAT_ROW_ORIENTED:
159     a->roworiented = flg;
160     break;
161   case MAT_KEEP_ZEROED_ROWS:
162     a->keepzeroedrows = flg;
163     break;
164   case MAT_NEW_NONZERO_LOCATIONS:
165     a->nonew = (flg ? 0 : 1);
166     break;
167   case MAT_NEW_NONZERO_LOCATION_ERR:
168     a->nonew = (flg ? -1 : 0);
169     break;
170   case MAT_NEW_NONZERO_ALLOCATION_ERR:
171     a->nonew = (flg ? -2 : 0);
172     break;
173   case MAT_UNUSED_NONZERO_LOCATION_ERR:
174     a->nounused = (flg ? -1 : 0);
175     break;
176   case MAT_NEW_DIAGONALS:
177   case MAT_IGNORE_OFF_PROC_ENTRIES:
178   case MAT_USE_HASH_TABLE:
179     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
180     break;
181   case MAT_HERMITIAN:
182     if (flg) SETERRQ(PETSC_ERR_SUP,"Matrix must be symmetric");
183   case MAT_SYMMETRIC:
184   case MAT_STRUCTURALLY_SYMMETRIC:
185   case MAT_SYMMETRY_ETERNAL:
186     if (!flg) SETERRQ(PETSC_ERR_SUP,"Matrix must be symmetric");
187     ierr = PetscInfo1(A,"Option %s not relevent\n",MatOptions[op]);CHKERRQ(ierr);
188     break;
189   case MAT_IGNORE_LOWER_TRIANGULAR:
190     a->ignore_ltriangular = flg;
191     break;
192   case MAT_ERROR_LOWER_TRIANGULAR:
193     a->ignore_ltriangular = flg;
194     break;
195   case MAT_GETROW_UPPERTRIANGULAR:
196     a->getrow_utriangular = flg;
197     break;
198   default:
199     SETERRQ1(PETSC_ERR_SUP,"unknown option %d",op);
200   }
201   PetscFunctionReturn(0);
202 }
203 
204 #undef __FUNCT__
205 #define __FUNCT__ "MatGetRow_SeqSBAIJ"
206 PetscErrorCode MatGetRow_SeqSBAIJ(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **v)
207 {
208   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
209   PetscErrorCode ierr;
210   PetscInt       itmp,i,j,k,M,*ai,*aj,bs,bn,bp,*cols_i,bs2;
211   MatScalar      *aa,*aa_i;
212   PetscScalar    *v_i;
213 
214   PetscFunctionBegin;
215   if (A && !a->getrow_utriangular) SETERRQ(PETSC_ERR_SUP,"MatGetRow is not supported for SBAIJ matrix format. Getting the upper triangular part of row, run with -mat_getrow_uppertriangular, call MatSetOption(mat,MAT_GETROW_UPPERTRIANGULAR,PETSC_TRUE) or MatGetRowUpperTriangular()");
216   /* Get the upper triangular part of the row */
217   bs  = A->rmap->bs;
218   ai  = a->i;
219   aj  = a->j;
220   aa  = a->a;
221   bs2 = a->bs2;
222 
223   if (row < 0 || row >= A->rmap->N) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Row %D out of range", row);
224 
225   bn  = row/bs;   /* Block number */
226   bp  = row % bs; /* Block position */
227   M   = ai[bn+1] - ai[bn];
228   *ncols = bs*M;
229 
230   if (v) {
231     *v = 0;
232     if (*ncols) {
233       ierr = PetscMalloc((*ncols+row)*sizeof(PetscScalar),v);CHKERRQ(ierr);
234       for (i=0; i<M; i++) { /* for each block in the block row */
235         v_i  = *v + i*bs;
236         aa_i = aa + bs2*(ai[bn] + i);
237         for (j=bp,k=0; j<bs2; j+=bs,k++) {v_i[k] = aa_i[j];}
238       }
239     }
240   }
241 
242   if (cols) {
243     *cols = 0;
244     if (*ncols) {
245       ierr = PetscMalloc((*ncols+row)*sizeof(PetscInt),cols);CHKERRQ(ierr);
246       for (i=0; i<M; i++) { /* for each block in the block row */
247         cols_i = *cols + i*bs;
248         itmp  = bs*aj[ai[bn] + i];
249         for (j=0; j<bs; j++) {cols_i[j] = itmp++;}
250       }
251     }
252   }
253 
254   /*search column A(0:row-1,row) (=A(row,0:row-1)). Could be expensive! */
255   /* this segment is currently removed, so only entries in the upper triangle are obtained */
256 #ifdef column_search
257   v_i    = *v    + M*bs;
258   cols_i = *cols + M*bs;
259   for (i=0; i<bn; i++){ /* for each block row */
260     M = ai[i+1] - ai[i];
261     for (j=0; j<M; j++){
262       itmp = aj[ai[i] + j];    /* block column value */
263       if (itmp == bn){
264         aa_i   = aa    + bs2*(ai[i] + j) + bs*bp;
265         for (k=0; k<bs; k++) {
266           *cols_i++ = i*bs+k;
267           *v_i++    = aa_i[k];
268         }
269         *ncols += bs;
270         break;
271       }
272     }
273   }
274 #endif
275   PetscFunctionReturn(0);
276 }
277 
278 #undef __FUNCT__
279 #define __FUNCT__ "MatRestoreRow_SeqSBAIJ"
280 PetscErrorCode MatRestoreRow_SeqSBAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
281 {
282   PetscErrorCode ierr;
283 
284   PetscFunctionBegin;
285   if (idx) {ierr = PetscFree(*idx);CHKERRQ(ierr);}
286   if (v)   {ierr = PetscFree(*v);CHKERRQ(ierr);}
287   PetscFunctionReturn(0);
288 }
289 
290 #undef __FUNCT__
291 #define __FUNCT__ "MatGetRowUpperTriangular_SeqSBAIJ"
292 PetscErrorCode MatGetRowUpperTriangular_SeqSBAIJ(Mat A)
293 {
294   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
295 
296   PetscFunctionBegin;
297   a->getrow_utriangular = PETSC_TRUE;
298   PetscFunctionReturn(0);
299 }
300 #undef __FUNCT__
301 #define __FUNCT__ "MatRestoreRowUpperTriangular_SeqSBAIJ"
302 PetscErrorCode MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A)
303 {
304   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
305 
306   PetscFunctionBegin;
307   a->getrow_utriangular = PETSC_FALSE;
308   PetscFunctionReturn(0);
309 }
310 
311 #undef __FUNCT__
312 #define __FUNCT__ "MatTranspose_SeqSBAIJ"
313 PetscErrorCode MatTranspose_SeqSBAIJ(Mat A,MatReuse reuse,Mat *B)
314 {
315   PetscErrorCode ierr;
316   PetscFunctionBegin;
317   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
318     ierr = MatDuplicate(A,MAT_COPY_VALUES,B);CHKERRQ(ierr);
319   }
320   PetscFunctionReturn(0);
321 }
322 
323 #undef __FUNCT__
324 #define __FUNCT__ "MatView_SeqSBAIJ_ASCII"
325 static PetscErrorCode MatView_SeqSBAIJ_ASCII(Mat A,PetscViewer viewer)
326 {
327   Mat_SeqSBAIJ      *a = (Mat_SeqSBAIJ*)A->data;
328   PetscErrorCode    ierr;
329   PetscInt          i,j,bs = A->rmap->bs,k,l,bs2=a->bs2;
330   const char        *name;
331   PetscViewerFormat format;
332 
333   PetscFunctionBegin;
334   ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
335   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
336   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
337     ierr = PetscViewerASCIIPrintf(viewer,"  block size is %D\n",bs);CHKERRQ(ierr);
338   } else if (format == PETSC_VIEWER_ASCII_MATLAB) {
339     Mat aij;
340 
341     if (A->factor && bs>1){
342       ierr = PetscPrintf(PETSC_COMM_SELF,"Warning: matrix is factored with bs>1. MatView() with PETSC_VIEWER_ASCII_MATLAB is not supported and ignored!\n");CHKERRQ(ierr);
343       PetscFunctionReturn(0);
344     }
345     ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&aij);CHKERRQ(ierr);
346     ierr = MatView(aij,viewer);CHKERRQ(ierr);
347     ierr = MatDestroy(aij);CHKERRQ(ierr);
348   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
349     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
350     for (i=0; i<a->mbs; i++) {
351       for (j=0; j<bs; j++) {
352         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i*bs+j);CHKERRQ(ierr);
353         for (k=a->i[i]; k<a->i[i+1]; k++) {
354           for (l=0; l<bs; l++) {
355 #if defined(PETSC_USE_COMPLEX)
356             if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
357               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i) ",bs*a->j[k]+l,
358                                             PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
359             } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
360               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i) ",bs*a->j[k]+l,
361                                             PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
362             } else if (PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
363               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
364             }
365 #else
366             if (a->a[bs2*k + l*bs + j] != 0.0) {
367               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);CHKERRQ(ierr);
368             }
369 #endif
370           }
371         }
372         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
373       }
374     }
375     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
376   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
377      PetscFunctionReturn(0);
378   } else {
379     if (A->factor && bs>1){
380       ierr = PetscPrintf(PETSC_COMM_SELF,"Warning: matrix is factored. MatView_SeqSBAIJ_ASCII() may not display complete or logically correct entries!\n");CHKERRQ(ierr);
381     }
382     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
383     for (i=0; i<a->mbs; i++) {
384       for (j=0; j<bs; j++) {
385         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i*bs+j);CHKERRQ(ierr);
386         for (k=a->i[i]; k<a->i[i+1]; k++) {
387           for (l=0; l<bs; l++) {
388 #if defined(PETSC_USE_COMPLEX)
389             if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0) {
390               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i) ",bs*a->j[k]+l,
391                                             PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
392             } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0) {
393               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i) ",bs*a->j[k]+l,
394                                             PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
395             } else {
396               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
397             }
398 #else
399             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);CHKERRQ(ierr);
400 #endif
401           }
402         }
403         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
404       }
405     }
406     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
407   }
408   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
409   PetscFunctionReturn(0);
410 }
411 
412 #undef __FUNCT__
413 #define __FUNCT__ "MatView_SeqSBAIJ_Draw_Zoom"
414 static PetscErrorCode MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
415 {
416   Mat            A = (Mat) Aa;
417   Mat_SeqSBAIJ   *a=(Mat_SeqSBAIJ*)A->data;
418   PetscErrorCode ierr;
419   PetscInt       row,i,j,k,l,mbs=a->mbs,color,bs=A->rmap->bs,bs2=a->bs2;
420   PetscMPIInt    rank;
421   PetscReal      xl,yl,xr,yr,x_l,x_r,y_l,y_r;
422   MatScalar      *aa;
423   MPI_Comm       comm;
424   PetscViewer    viewer;
425 
426   PetscFunctionBegin;
427   /*
428     This is nasty. If this is called from an originally parallel matrix
429     then all processes call this,but only the first has the matrix so the
430     rest should return immediately.
431   */
432   ierr = PetscObjectGetComm((PetscObject)draw,&comm);CHKERRQ(ierr);
433   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
434   if (rank) PetscFunctionReturn(0);
435 
436   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
437 
438   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
439   PetscDrawString(draw, .3*(xl+xr), .3*(yl+yr), PETSC_DRAW_BLACK, "symmetric");
440 
441   /* loop over matrix elements drawing boxes */
442   color = PETSC_DRAW_BLUE;
443   for (i=0,row=0; i<mbs; i++,row+=bs) {
444     for (j=a->i[i]; j<a->i[i+1]; j++) {
445       y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0;
446       x_l = a->j[j]*bs; x_r = x_l + 1.0;
447       aa = a->a + j*bs2;
448       for (k=0; k<bs; k++) {
449         for (l=0; l<bs; l++) {
450           if (PetscRealPart(*aa++) >=  0.) continue;
451           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
452         }
453       }
454     }
455   }
456   color = PETSC_DRAW_CYAN;
457   for (i=0,row=0; i<mbs; i++,row+=bs) {
458     for (j=a->i[i]; j<a->i[i+1]; j++) {
459       y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0;
460       x_l = a->j[j]*bs; x_r = x_l + 1.0;
461       aa = a->a + j*bs2;
462       for (k=0; k<bs; k++) {
463         for (l=0; l<bs; l++) {
464           if (PetscRealPart(*aa++) != 0.) continue;
465           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
466         }
467       }
468     }
469   }
470 
471   color = PETSC_DRAW_RED;
472   for (i=0,row=0; i<mbs; i++,row+=bs) {
473     for (j=a->i[i]; j<a->i[i+1]; j++) {
474       y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0;
475       x_l = a->j[j]*bs; x_r = x_l + 1.0;
476       aa = a->a + j*bs2;
477       for (k=0; k<bs; k++) {
478         for (l=0; l<bs; l++) {
479           if (PetscRealPart(*aa++) <= 0.) continue;
480           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
481         }
482       }
483     }
484   }
485   PetscFunctionReturn(0);
486 }
487 
488 #undef __FUNCT__
489 #define __FUNCT__ "MatView_SeqSBAIJ_Draw"
490 static PetscErrorCode MatView_SeqSBAIJ_Draw(Mat A,PetscViewer viewer)
491 {
492   PetscErrorCode ierr;
493   PetscReal      xl,yl,xr,yr,w,h;
494   PetscDraw      draw;
495   PetscTruth     isnull;
496 
497   PetscFunctionBegin;
498   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
499   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
500 
501   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
502   xr  = A->rmap->N; yr = A->rmap->N; h = yr/10.0; w = xr/10.0;
503   xr += w;    yr += h;  xl = -w;     yl = -h;
504   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
505   ierr = PetscDrawZoom(draw,MatView_SeqSBAIJ_Draw_Zoom,A);CHKERRQ(ierr);
506   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
507   PetscFunctionReturn(0);
508 }
509 
510 #undef __FUNCT__
511 #define __FUNCT__ "MatView_SeqSBAIJ"
512 PetscErrorCode MatView_SeqSBAIJ(Mat A,PetscViewer viewer)
513 {
514   PetscErrorCode ierr;
515   PetscTruth     iascii,isdraw;
516 
517   PetscFunctionBegin;
518   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
519   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
520   if (iascii){
521     ierr = MatView_SeqSBAIJ_ASCII(A,viewer);CHKERRQ(ierr);
522   } else if (isdraw) {
523     ierr = MatView_SeqSBAIJ_Draw(A,viewer);CHKERRQ(ierr);
524   } else {
525     Mat B;
526     ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
527     ierr = MatView(B,viewer);CHKERRQ(ierr);
528     ierr = MatDestroy(B);CHKERRQ(ierr);
529   }
530   PetscFunctionReturn(0);
531 }
532 
533 
534 #undef __FUNCT__
535 #define __FUNCT__ "MatGetValues_SeqSBAIJ"
536 PetscErrorCode MatGetValues_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
537 {
538   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
539   PetscInt     *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
540   PetscInt     *ai = a->i,*ailen = a->ilen;
541   PetscInt     brow,bcol,ridx,cidx,bs=A->rmap->bs,bs2=a->bs2;
542   MatScalar    *ap,*aa = a->a;
543 
544   PetscFunctionBegin;
545   for (k=0; k<m; k++) { /* loop over rows */
546     row  = im[k]; brow = row/bs;
547     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
548     if (row >= A->rmap->N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->N-1);
549     rp   = aj + ai[brow] ; ap = aa + bs2*ai[brow] ;
550     nrow = ailen[brow];
551     for (l=0; l<n; l++) { /* loop over columns */
552       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
553       if (in[l] >= A->cmap->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
554       col  = in[l] ;
555       bcol = col/bs;
556       cidx = col%bs;
557       ridx = row%bs;
558       high = nrow;
559       low  = 0; /* assume unsorted */
560       while (high-low > 5) {
561         t = (low+high)/2;
562         if (rp[t] > bcol) high = t;
563         else             low  = t;
564       }
565       for (i=low; i<high; i++) {
566         if (rp[i] > bcol) break;
567         if (rp[i] == bcol) {
568           *v++ = ap[bs2*i+bs*cidx+ridx];
569           goto finished;
570         }
571       }
572       *v++ = 0.0;
573       finished:;
574     }
575   }
576   PetscFunctionReturn(0);
577 }
578 
579 
580 #undef __FUNCT__
581 #define __FUNCT__ "MatSetValuesBlocked_SeqSBAIJ"
582 PetscErrorCode MatSetValuesBlocked_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
583 {
584   Mat_SeqSBAIJ      *a = (Mat_SeqSBAIJ*)A->data;
585   PetscErrorCode    ierr;
586   PetscInt          *rp,k,low,high,t,ii,jj,row,nrow,i,col,l,rmax,N,lastcol = -1;
587   PetscInt          *imax=a->imax,*ai=a->i,*ailen=a->ilen;
588   PetscInt          *aj=a->j,nonew=a->nonew,bs2=a->bs2,bs=A->rmap->bs,stepval;
589   PetscTruth        roworiented=a->roworiented;
590   const PetscScalar *value = v;
591   MatScalar         *ap,*aa = a->a,*bap;
592 
593   PetscFunctionBegin;
594   if (roworiented) {
595     stepval = (n-1)*bs;
596   } else {
597     stepval = (m-1)*bs;
598   }
599   for (k=0; k<m; k++) { /* loop over added rows */
600     row  = im[k];
601     if (row < 0) continue;
602 #if defined(PETSC_USE_DEBUG)
603     if (row >= a->mbs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,a->mbs-1);
604 #endif
605     rp   = aj + ai[row];
606     ap   = aa + bs2*ai[row];
607     rmax = imax[row];
608     nrow = ailen[row];
609     low  = 0;
610     high = nrow;
611     for (l=0; l<n; l++) { /* loop over added columns */
612       if (in[l] < 0) continue;
613       col = in[l];
614 #if defined(PETSC_USE_DEBUG)
615       if (col >= a->nbs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",col,a->nbs-1);
616 #endif
617       if (col < row) continue; /* ignore lower triangular block */
618       if (roworiented) {
619         value = v + k*(stepval+bs)*bs + l*bs;
620       } else {
621         value = v + l*(stepval+bs)*bs + k*bs;
622       }
623       if (col <= lastcol) low = 0; else high = nrow;
624       lastcol = col;
625       while (high-low > 7) {
626         t = (low+high)/2;
627         if (rp[t] > col) high = t;
628         else             low  = t;
629       }
630       for (i=low; i<high; i++) {
631         if (rp[i] > col) break;
632         if (rp[i] == col) {
633           bap  = ap +  bs2*i;
634           if (roworiented) {
635             if (is == ADD_VALUES) {
636               for (ii=0; ii<bs; ii++,value+=stepval) {
637                 for (jj=ii; jj<bs2; jj+=bs) {
638                   bap[jj] += *value++;
639                 }
640               }
641             } else {
642               for (ii=0; ii<bs; ii++,value+=stepval) {
643                 for (jj=ii; jj<bs2; jj+=bs) {
644                   bap[jj] = *value++;
645                 }
646                }
647             }
648           } else {
649             if (is == ADD_VALUES) {
650               for (ii=0; ii<bs; ii++,value+=stepval) {
651                 for (jj=0; jj<bs; jj++) {
652                   *bap++ += *value++;
653                 }
654               }
655             } else {
656               for (ii=0; ii<bs; ii++,value+=stepval) {
657                 for (jj=0; jj<bs; jj++) {
658                   *bap++  = *value++;
659                 }
660               }
661             }
662           }
663           goto noinsert2;
664         }
665       }
666       if (nonew == 1) goto noinsert2;
667       if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col);
668       MatSeqXAIJReallocateAIJ(A,a->mbs,bs2,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
669       N = nrow++ - 1; high++;
670       /* shift up all the later entries in this row */
671       for (ii=N; ii>=i; ii--) {
672         rp[ii+1] = rp[ii];
673         ierr = PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));CHKERRQ(ierr);
674       }
675       if (N >= i) {
676         ierr = PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));CHKERRQ(ierr);
677       }
678       rp[i] = col;
679       bap   = ap +  bs2*i;
680       if (roworiented) {
681         for (ii=0; ii<bs; ii++,value+=stepval) {
682           for (jj=ii; jj<bs2; jj+=bs) {
683             bap[jj] = *value++;
684           }
685         }
686       } else {
687         for (ii=0; ii<bs; ii++,value+=stepval) {
688           for (jj=0; jj<bs; jj++) {
689             *bap++  = *value++;
690           }
691         }
692        }
693     noinsert2:;
694       low = i;
695     }
696     ailen[row] = nrow;
697   }
698    PetscFunctionReturn(0);
699 }
700 
701 #undef __FUNCT__
702 #define __FUNCT__ "MatAssemblyEnd_SeqSBAIJ"
703 PetscErrorCode MatAssemblyEnd_SeqSBAIJ(Mat A,MatAssemblyType mode)
704 {
705   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
706   PetscErrorCode ierr;
707   PetscInt       fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
708   PetscInt       m = A->rmap->N,*ip,N,*ailen = a->ilen;
709   PetscInt       mbs = a->mbs,bs2 = a->bs2,rmax = 0;
710   MatScalar      *aa = a->a,*ap;
711 
712   PetscFunctionBegin;
713   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
714 
715   if (m) rmax = ailen[0];
716   for (i=1; i<mbs; i++) {
717     /* move each row back by the amount of empty slots (fshift) before it*/
718     fshift += imax[i-1] - ailen[i-1];
719      rmax   = PetscMax(rmax,ailen[i]);
720      if (fshift) {
721        ip = aj + ai[i]; ap = aa + bs2*ai[i];
722        N = ailen[i];
723        for (j=0; j<N; j++) {
724          ip[j-fshift] = ip[j];
725          ierr = PetscMemcpy(ap+(j-fshift)*bs2,ap+j*bs2,bs2*sizeof(MatScalar));CHKERRQ(ierr);
726        }
727      }
728      ai[i] = ai[i-1] + ailen[i-1];
729   }
730   if (mbs) {
731     fshift += imax[mbs-1] - ailen[mbs-1];
732      ai[mbs] = ai[mbs-1] + ailen[mbs-1];
733   }
734   /* reset ilen and imax for each row */
735   for (i=0; i<mbs; i++) {
736     ailen[i] = imax[i] = ai[i+1] - ai[i];
737   }
738   a->nz = ai[mbs];
739 
740   /* diagonals may have moved, reset it */
741   if (a->diag) {
742     ierr = PetscMemcpy(a->diag,ai,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr);
743   }
744   if (fshift && a->nounused == -1) {
745     SETERRQ4(PETSC_ERR_PLIB, "Unused space detected in matrix: %D X %D block size %D, %D unneeded", m, A->cmap->n, A->rmap->bs, fshift*bs2);
746   }
747   ierr = PetscInfo5(A,"Matrix size: %D X %D, block size %D; storage space: %D unneeded, %D used\n",m,A->rmap->N,A->rmap->bs,fshift*bs2,a->nz*bs2);CHKERRQ(ierr);
748   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues is %D\n",a->reallocs);CHKERRQ(ierr);
749   ierr = PetscInfo1(A,"Most nonzeros blocks in any row is %D\n",rmax);CHKERRQ(ierr);
750   a->reallocs          = 0;
751   A->info.nz_unneeded  = (PetscReal)fshift*bs2;
752   PetscFunctionReturn(0);
753 }
754 
755 /*
756    This function returns an array of flags which indicate the locations of contiguous
757    blocks that should be zeroed. for eg: if bs = 3  and is = [0,1,2,3,5,6,7,8,9]
758    then the resulting sizes = [3,1,1,3,1] correspondig to sets [(0,1,2),(3),(5),(6,7,8),(9)]
759    Assume: sizes should be long enough to hold all the values.
760 */
761 #undef __FUNCT__
762 #define __FUNCT__ "MatZeroRows_SeqSBAIJ_Check_Blocks"
763 PetscErrorCode MatZeroRows_SeqSBAIJ_Check_Blocks(PetscInt idx[],PetscInt n,PetscInt bs,PetscInt sizes[], PetscInt *bs_max)
764 {
765   PetscInt   i,j,k,row;
766   PetscTruth flg;
767 
768   PetscFunctionBegin;
769    for (i=0,j=0; i<n; j++) {
770      row = idx[i];
771      if (row%bs!=0) { /* Not the begining of a block */
772        sizes[j] = 1;
773        i++;
774      } else if (i+bs > n) { /* Beginning of a block, but complete block doesn't exist (at idx end) */
775        sizes[j] = 1;         /* Also makes sure atleast 'bs' values exist for next else */
776        i++;
777      } else { /* Begining of the block, so check if the complete block exists */
778        flg = PETSC_TRUE;
779        for (k=1; k<bs; k++) {
780          if (row+k != idx[i+k]) { /* break in the block */
781            flg = PETSC_FALSE;
782            break;
783          }
784        }
785        if (flg) { /* No break in the bs */
786          sizes[j] = bs;
787          i+= bs;
788        } else {
789          sizes[j] = 1;
790          i++;
791        }
792      }
793    }
794    *bs_max = j;
795    PetscFunctionReturn(0);
796 }
797 
798 
799 /* Only add/insert a(i,j) with i<=j (blocks).
800    Any a(i,j) with i>j input by user is ingored.
801 */
802 
803 #undef __FUNCT__
804 #define __FUNCT__ "MatSetValues_SeqSBAIJ"
805 PetscErrorCode MatSetValues_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
806 {
807   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
808   PetscErrorCode ierr;
809   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,lastcol = -1;
810   PetscInt       *imax=a->imax,*ai=a->i,*ailen=a->ilen,roworiented=a->roworiented;
811   PetscInt       *aj=a->j,nonew=a->nonew,bs=A->rmap->bs,brow,bcol;
812   PetscInt       ridx,cidx,bs2=a->bs2;
813   MatScalar      *ap,value,*aa=a->a,*bap;
814 
815   PetscFunctionBegin;
816   for (k=0; k<m; k++) { /* loop over added rows */
817     row  = im[k];       /* row number */
818     brow = row/bs;      /* block row number */
819     if (row < 0) continue;
820 #if defined(PETSC_USE_DEBUG)
821     if (row >= A->rmap->N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->N-1);
822 #endif
823     rp   = aj + ai[brow]; /*ptr to beginning of column value of the row block*/
824     ap   = aa + bs2*ai[brow]; /*ptr to beginning of element value of the row block*/
825     rmax = imax[brow];  /* maximum space allocated for this row */
826     nrow = ailen[brow]; /* actual length of this row */
827     low  = 0;
828 
829     for (l=0; l<n; l++) { /* loop over added columns */
830       if (in[l] < 0) continue;
831 #if defined(PETSC_USE_DEBUG)
832       if (in[l] >= A->rmap->N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->rmap->N-1);
833 #endif
834       col = in[l];
835       bcol = col/bs;              /* block col number */
836 
837       if (brow > bcol) {
838         if (a->ignore_ltriangular){
839           continue; /* ignore lower triangular values */
840         } else {
841           SETERRQ(PETSC_ERR_USER,"Lower triangular value cannot be set for sbaij format. Ignoring these values, run with -mat_ignore_lower_triangular or call MatSetOption(mat,MAT_IGNORE_LOWER_TRIANGULAR,PETSC_TRUE)");
842         }
843       }
844 
845       ridx = row % bs; cidx = col % bs; /*row and col index inside the block */
846       if ((brow==bcol && ridx<=cidx) || (brow<bcol)){
847         /* element value a(k,l) */
848         if (roworiented) {
849           value = v[l + k*n];
850         } else {
851           value = v[k + l*m];
852         }
853 
854         /* move pointer bap to a(k,l) quickly and add/insert value */
855         if (col <= lastcol) low = 0; high = nrow;
856         lastcol = col;
857         while (high-low > 7) {
858           t = (low+high)/2;
859           if (rp[t] > bcol) high = t;
860           else              low  = t;
861         }
862         for (i=low; i<high; i++) {
863           if (rp[i] > bcol) break;
864           if (rp[i] == bcol) {
865             bap  = ap +  bs2*i + bs*cidx + ridx;
866             if (is == ADD_VALUES) *bap += value;
867             else                  *bap  = value;
868             /* for diag block, add/insert its symmetric element a(cidx,ridx) */
869             if (brow == bcol && ridx < cidx){
870               bap  = ap +  bs2*i + bs*ridx + cidx;
871               if (is == ADD_VALUES) *bap += value;
872               else                  *bap  = value;
873             }
874             goto noinsert1;
875           }
876         }
877 
878         if (nonew == 1) goto noinsert1;
879         if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col);
880         MatSeqXAIJReallocateAIJ(A,a->mbs,bs2,nrow,brow,bcol,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
881 
882         N = nrow++ - 1; high++;
883         /* shift up all the later entries in this row */
884         for (ii=N; ii>=i; ii--) {
885           rp[ii+1] = rp[ii];
886           ierr     = PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));CHKERRQ(ierr);
887         }
888         if (N>=i) {
889           ierr = PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));CHKERRQ(ierr);
890         }
891         rp[i]                      = bcol;
892         ap[bs2*i + bs*cidx + ridx] = value;
893       noinsert1:;
894         low = i;
895       }
896     }   /* end of loop over added columns */
897     ailen[brow] = nrow;
898   }   /* end of loop over added rows */
899   PetscFunctionReturn(0);
900 }
901 
902 #undef __FUNCT__
903 #define __FUNCT__ "MatICCFactor_SeqSBAIJ"
904 PetscErrorCode MatICCFactor_SeqSBAIJ(Mat inA,IS row,const MatFactorInfo *info)
905 {
906   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)inA->data;
907   Mat            outA;
908   PetscErrorCode ierr;
909   PetscTruth     row_identity;
910 
911   PetscFunctionBegin;
912   if (info->levels != 0) SETERRQ(PETSC_ERR_SUP,"Only levels=0 is supported for in-place icc");
913   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
914   if (!row_identity) SETERRQ(PETSC_ERR_SUP,"Matrix reordering is not supported");
915   if (inA->rmap->bs != 1) SETERRQ1(PETSC_ERR_SUP,"Matrix block size %D is not supported",inA->rmap->bs); /* Need to replace MatCholeskyFactorSymbolic_SeqSBAIJ_MSR()! */
916 
917   outA        = inA;
918   inA->factor = MAT_FACTOR_ICC;
919 
920   ierr = MatMarkDiagonal_SeqSBAIJ(inA);CHKERRQ(ierr);
921   ierr = MatSeqSBAIJSetNumericFactorization(inA,row_identity);CHKERRQ(ierr);
922 
923   ierr   = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
924   if (a->row) { ierr = ISDestroy(a->row);CHKERRQ(ierr); }
925   a->row = row;
926   ierr   = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
927   if (a->col) { ierr = ISDestroy(a->col);CHKERRQ(ierr); }
928   a->col = row;
929 
930   /* Create the invert permutation so that it can be used in MatCholeskyFactorNumeric() */
931   if (a->icol) {ierr = ISInvertPermutation(row,PETSC_DECIDE, &a->icol);CHKERRQ(ierr);}
932   ierr = PetscLogObjectParent(inA,a->icol);CHKERRQ(ierr);
933 
934   if (!a->solve_work) {
935     ierr = PetscMalloc((inA->rmap->N+inA->rmap->bs)*sizeof(PetscScalar),&a->solve_work);CHKERRQ(ierr);
936     ierr = PetscLogObjectMemory(inA,(inA->rmap->N+inA->rmap->bs)*sizeof(PetscScalar));CHKERRQ(ierr);
937   }
938 
939   ierr = MatCholeskyFactorNumeric(outA,inA,info);CHKERRQ(ierr);
940   PetscFunctionReturn(0);
941 }
942 
943 EXTERN_C_BEGIN
944 #undef __FUNCT__
945 #define __FUNCT__ "MatSeqSBAIJSetColumnIndices_SeqSBAIJ"
946 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat,PetscInt *indices)
947 {
948   Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)mat->data;
949   PetscInt     i,nz,n;
950 
951   PetscFunctionBegin;
952   nz = baij->maxnz;
953   n  = mat->cmap->n;
954   for (i=0; i<nz; i++) {
955     baij->j[i] = indices[i];
956   }
957    baij->nz = nz;
958    for (i=0; i<n; i++) {
959      baij->ilen[i] = baij->imax[i];
960    }
961    PetscFunctionReturn(0);
962 }
963 EXTERN_C_END
964 
965 #undef __FUNCT__
966 #define __FUNCT__ "MatSeqSBAIJSetColumnIndices"
967 /*@
968   MatSeqSBAIJSetColumnIndices - Set the column indices for all the rows
969   in the matrix.
970 
971   Input Parameters:
972   +  mat     - the SeqSBAIJ matrix
973   -  indices - the column indices
974 
975   Level: advanced
976 
977   Notes:
978   This can be called if you have precomputed the nonzero structure of the
979   matrix and want to provide it to the matrix object to improve the performance
980   of the MatSetValues() operation.
981 
982   You MUST have set the correct numbers of nonzeros per row in the call to
983   MatCreateSeqSBAIJ(), and the columns indices MUST be sorted.
984 
985   MUST be called before any calls to MatSetValues()
986 
987   .seealso: MatCreateSeqSBAIJ
988 @*/
989 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetColumnIndices(Mat mat,PetscInt *indices)
990 {
991   PetscErrorCode ierr,(*f)(Mat,PetscInt *);
992 
993   PetscFunctionBegin;
994   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
995   PetscValidPointer(indices,2);
996   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqSBAIJSetColumnIndices_C",(void (**)(void))&f);CHKERRQ(ierr);
997   if (f) {
998     ierr = (*f)(mat,indices);CHKERRQ(ierr);
999   } else {
1000     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to set column indices");
1001   }
1002   PetscFunctionReturn(0);
1003 }
1004 
1005 #undef __FUNCT__
1006 #define __FUNCT__ "MatCopy_SeqSBAIJ"
1007 PetscErrorCode MatCopy_SeqSBAIJ(Mat A,Mat B,MatStructure str)
1008 {
1009   PetscErrorCode ierr;
1010 
1011   PetscFunctionBegin;
1012   /* If the two matrices have the same copy implementation, use fast copy. */
1013   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
1014     Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
1015     Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ*)B->data;
1016 
1017     if (a->i[A->rmap->N] != b->i[B->rmap->N]) {
1018       SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different");
1019     }
1020     ierr = PetscMemcpy(b->a,a->a,(a->i[A->rmap->N])*sizeof(PetscScalar));CHKERRQ(ierr);
1021   } else {
1022     ierr = MatGetRowUpperTriangular(A);CHKERRQ(ierr);
1023     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
1024     ierr = MatRestoreRowUpperTriangular(A);CHKERRQ(ierr);
1025   }
1026   PetscFunctionReturn(0);
1027 }
1028 
1029 #undef __FUNCT__
1030 #define __FUNCT__ "MatSetUpPreallocation_SeqSBAIJ"
1031 PetscErrorCode MatSetUpPreallocation_SeqSBAIJ(Mat A)
1032 {
1033   PetscErrorCode ierr;
1034 
1035   PetscFunctionBegin;
1036   ierr =  MatSeqSBAIJSetPreallocation_SeqSBAIJ(A,-PetscMax(A->rmap->bs,1),PETSC_DEFAULT,0);CHKERRQ(ierr);
1037   PetscFunctionReturn(0);
1038 }
1039 
1040 #undef __FUNCT__
1041 #define __FUNCT__ "MatGetArray_SeqSBAIJ"
1042 PetscErrorCode MatGetArray_SeqSBAIJ(Mat A,PetscScalar *array[])
1043 {
1044   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
1045   PetscFunctionBegin;
1046   *array = a->a;
1047   PetscFunctionReturn(0);
1048 }
1049 
1050 #undef __FUNCT__
1051 #define __FUNCT__ "MatRestoreArray_SeqSBAIJ"
1052 PetscErrorCode MatRestoreArray_SeqSBAIJ(Mat A,PetscScalar *array[])
1053 {
1054   PetscFunctionBegin;
1055   PetscFunctionReturn(0);
1056  }
1057 
1058 #include "petscblaslapack.h"
1059 #undef __FUNCT__
1060 #define __FUNCT__ "MatAXPY_SeqSBAIJ"
1061 PetscErrorCode MatAXPY_SeqSBAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
1062 {
1063   Mat_SeqSBAIJ   *x=(Mat_SeqSBAIJ *)X->data, *y=(Mat_SeqSBAIJ *)Y->data;
1064   PetscErrorCode ierr;
1065   PetscInt       i,bs=Y->rmap->bs,bs2,j;
1066   PetscBLASInt   one = 1,bnz = PetscBLASIntCast(x->nz);
1067 
1068   PetscFunctionBegin;
1069   if (str == SAME_NONZERO_PATTERN) {
1070     PetscScalar alpha = a;
1071     BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one);
1072   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
1073     if (y->xtoy && y->XtoY != X) {
1074       ierr = PetscFree(y->xtoy);CHKERRQ(ierr);
1075       ierr = MatDestroy(y->XtoY);CHKERRQ(ierr);
1076     }
1077     if (!y->xtoy) { /* get xtoy */
1078       ierr = MatAXPYGetxtoy_Private(x->mbs,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);CHKERRQ(ierr);
1079       y->XtoY = X;
1080     }
1081     bs2 = bs*bs;
1082     for (i=0; i<x->nz; i++) {
1083       j = 0;
1084       while (j < bs2){
1085         y->a[bs2*y->xtoy[i]+j] += a*(x->a[bs2*i+j]);
1086         j++;
1087       }
1088     }
1089     ierr = PetscInfo3(Y,"ratio of nnz_s(X)/nnz_s(Y): %D/%D = %G\n",bs2*x->nz,bs2*y->nz,(PetscReal)(bs2*x->nz)/(bs2*y->nz));CHKERRQ(ierr);
1090   } else {
1091     ierr = MatGetRowUpperTriangular(X);CHKERRQ(ierr);
1092     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
1093     ierr = MatRestoreRowUpperTriangular(X);CHKERRQ(ierr);
1094   }
1095   PetscFunctionReturn(0);
1096 }
1097 
1098 #undef __FUNCT__
1099 #define __FUNCT__ "MatIsSymmetric_SeqSBAIJ"
1100 PetscErrorCode MatIsSymmetric_SeqSBAIJ(Mat A,PetscReal tol,PetscTruth *flg)
1101 {
1102   PetscFunctionBegin;
1103   *flg = PETSC_TRUE;
1104   PetscFunctionReturn(0);
1105 }
1106 
1107 #undef __FUNCT__
1108 #define __FUNCT__ "MatIsStructurallySymmetric_SeqSBAIJ"
1109 PetscErrorCode MatIsStructurallySymmetric_SeqSBAIJ(Mat A,PetscTruth *flg)
1110 {
1111    PetscFunctionBegin;
1112    *flg = PETSC_TRUE;
1113    PetscFunctionReturn(0);
1114 }
1115 
1116 #undef __FUNCT__
1117 #define __FUNCT__ "MatIsHermitian_SeqSBAIJ"
1118 PetscErrorCode MatIsHermitian_SeqSBAIJ(Mat A,PetscReal tol,PetscTruth *flg)
1119  {
1120    PetscFunctionBegin;
1121    *flg = PETSC_FALSE;
1122    PetscFunctionReturn(0);
1123  }
1124 
1125 #undef __FUNCT__
1126 #define __FUNCT__ "MatRealPart_SeqSBAIJ"
1127 PetscErrorCode MatRealPart_SeqSBAIJ(Mat A)
1128 {
1129   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
1130   PetscInt       i,nz = a->bs2*a->i[a->mbs];
1131   MatScalar      *aa = a->a;
1132 
1133   PetscFunctionBegin;
1134   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
1135   PetscFunctionReturn(0);
1136 }
1137 
1138 #undef __FUNCT__
1139 #define __FUNCT__ "MatImaginaryPart_SeqSBAIJ"
1140 PetscErrorCode MatImaginaryPart_SeqSBAIJ(Mat A)
1141 {
1142   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
1143   PetscInt       i,nz = a->bs2*a->i[a->mbs];
1144   MatScalar      *aa = a->a;
1145 
1146   PetscFunctionBegin;
1147   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
1148   PetscFunctionReturn(0);
1149 }
1150 
1151 /* -------------------------------------------------------------------*/
1152 static struct _MatOps MatOps_Values = {MatSetValues_SeqSBAIJ,
1153        MatGetRow_SeqSBAIJ,
1154        MatRestoreRow_SeqSBAIJ,
1155        MatMult_SeqSBAIJ_N,
1156 /* 4*/ MatMultAdd_SeqSBAIJ_N,
1157        MatMult_SeqSBAIJ_N,       /* transpose versions are same as non-transpose versions */
1158        MatMultAdd_SeqSBAIJ_N,
1159        0,
1160        0,
1161        0,
1162 /*10*/ 0,
1163        0,
1164        MatCholeskyFactor_SeqSBAIJ,
1165        MatRelax_SeqSBAIJ,
1166        MatTranspose_SeqSBAIJ,
1167 /*15*/ MatGetInfo_SeqSBAIJ,
1168        MatEqual_SeqSBAIJ,
1169        MatGetDiagonal_SeqSBAIJ,
1170        MatDiagonalScale_SeqSBAIJ,
1171        MatNorm_SeqSBAIJ,
1172 /*20*/ 0,
1173        MatAssemblyEnd_SeqSBAIJ,
1174        0,
1175        MatSetOption_SeqSBAIJ,
1176        MatZeroEntries_SeqSBAIJ,
1177 /*25*/ 0,
1178        0,
1179        0,
1180        0,
1181        0,
1182 /*30*/ MatSetUpPreallocation_SeqSBAIJ,
1183        0,
1184        0,
1185        MatGetArray_SeqSBAIJ,
1186        MatRestoreArray_SeqSBAIJ,
1187 /*35*/ MatDuplicate_SeqSBAIJ,
1188        0,
1189        0,
1190        0,
1191        MatICCFactor_SeqSBAIJ,
1192 /*40*/ MatAXPY_SeqSBAIJ,
1193        MatGetSubMatrices_SeqSBAIJ,
1194        MatIncreaseOverlap_SeqSBAIJ,
1195        MatGetValues_SeqSBAIJ,
1196        MatCopy_SeqSBAIJ,
1197 /*45*/ 0,
1198        MatScale_SeqSBAIJ,
1199        0,
1200        0,
1201        0,
1202 /*50*/ 0,
1203        MatGetRowIJ_SeqSBAIJ,
1204        MatRestoreRowIJ_SeqSBAIJ,
1205        0,
1206        0,
1207 /*55*/ 0,
1208        0,
1209        0,
1210        0,
1211        MatSetValuesBlocked_SeqSBAIJ,
1212 /*60*/ MatGetSubMatrix_SeqSBAIJ,
1213        0,
1214        0,
1215        0,
1216        0,
1217 /*65*/ 0,
1218        0,
1219        0,
1220        0,
1221        0,
1222 /*70*/ MatGetRowMaxAbs_SeqSBAIJ,
1223        0,
1224        0,
1225        0,
1226        0,
1227 /*75*/ 0,
1228        0,
1229        0,
1230        0,
1231        0,
1232 /*80*/ 0,
1233        0,
1234        0,
1235 #if !defined(PETSC_USE_COMPLEX)
1236        MatGetInertia_SeqSBAIJ,
1237 #else
1238        0,
1239 #endif
1240        MatLoad_SeqSBAIJ,
1241 /*85*/ MatIsSymmetric_SeqSBAIJ,
1242        MatIsHermitian_SeqSBAIJ,
1243        MatIsStructurallySymmetric_SeqSBAIJ,
1244        0,
1245        0,
1246 /*90*/ 0,
1247        0,
1248        0,
1249        0,
1250        0,
1251 /*95*/ 0,
1252        0,
1253        0,
1254        0,
1255        0,
1256 /*100*/0,
1257        0,
1258        0,
1259        0,
1260        0,
1261 /*105*/0,
1262        MatRealPart_SeqSBAIJ,
1263        MatImaginaryPart_SeqSBAIJ,
1264        MatGetRowUpperTriangular_SeqSBAIJ,
1265        MatRestoreRowUpperTriangular_SeqSBAIJ,
1266 /*110*/0,
1267        0,
1268        0,
1269        0,
1270        MatMissingDiagonal_SeqSBAIJ
1271 };
1272 
1273 EXTERN_C_BEGIN
1274 #undef __FUNCT__
1275 #define __FUNCT__ "MatStoreValues_SeqSBAIJ"
1276 PetscErrorCode PETSCMAT_DLLEXPORT MatStoreValues_SeqSBAIJ(Mat mat)
1277 {
1278   Mat_SeqSBAIJ   *aij = (Mat_SeqSBAIJ *)mat->data;
1279   PetscInt       nz = aij->i[mat->rmap->N]*mat->rmap->bs*aij->bs2;
1280   PetscErrorCode ierr;
1281 
1282   PetscFunctionBegin;
1283   if (aij->nonew != 1) {
1284     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
1285   }
1286 
1287   /* allocate space for values if not already there */
1288   if (!aij->saved_values) {
1289     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr);
1290   }
1291 
1292   /* copy values over */
1293   ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr);
1294   PetscFunctionReturn(0);
1295 }
1296 EXTERN_C_END
1297 
1298 EXTERN_C_BEGIN
1299 #undef __FUNCT__
1300 #define __FUNCT__ "MatRetrieveValues_SeqSBAIJ"
1301 PetscErrorCode PETSCMAT_DLLEXPORT MatRetrieveValues_SeqSBAIJ(Mat mat)
1302 {
1303   Mat_SeqSBAIJ   *aij = (Mat_SeqSBAIJ *)mat->data;
1304   PetscErrorCode ierr;
1305   PetscInt       nz = aij->i[mat->rmap->N]*mat->rmap->bs*aij->bs2;
1306 
1307   PetscFunctionBegin;
1308   if (aij->nonew != 1) {
1309     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
1310   }
1311   if (!aij->saved_values) {
1312     SETERRQ(PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
1313   }
1314 
1315   /* copy values over */
1316   ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr);
1317   PetscFunctionReturn(0);
1318 }
1319 EXTERN_C_END
1320 
1321 EXTERN_C_BEGIN
1322 #undef __FUNCT__
1323 #define __FUNCT__ "MatSeqSBAIJSetPreallocation_SeqSBAIJ"
1324 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B,PetscInt bs,PetscInt nz,PetscInt *nnz)
1325 {
1326   Mat_SeqSBAIJ   *b = (Mat_SeqSBAIJ*)B->data;
1327   PetscErrorCode ierr;
1328   PetscInt       i,mbs,bs2, newbs = PetscAbs(bs);
1329   PetscTruth     skipallocation = PETSC_FALSE,flg;
1330 
1331   PetscFunctionBegin;
1332   B->preallocated = PETSC_TRUE;
1333   if (bs < 0) {
1334     ierr = PetscOptionsBegin(((PetscObject)B)->comm,((PetscObject)B)->prefix,"Options for MPISBAIJ matrix","Mat");CHKERRQ(ierr);
1335       ierr = PetscOptionsInt("-mat_block_size","Set the blocksize used to store the matrix","MatSeqSBAIJSetPreallocation",newbs,&newbs,PETSC_NULL);CHKERRQ(ierr);
1336     ierr = PetscOptionsEnd();CHKERRQ(ierr);
1337     bs   = PetscAbs(bs);
1338   }
1339   if (nnz && newbs != bs) {
1340     SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot change blocksize from command line if setting nnz");
1341   }
1342   bs = newbs;
1343 
1344   B->rmap->bs = B->cmap->bs = bs;
1345   ierr = PetscMapSetUp(B->rmap);CHKERRQ(ierr);
1346   ierr = PetscMapSetUp(B->cmap);CHKERRQ(ierr);
1347 
1348   mbs  = B->rmap->N/bs;
1349   bs2  = bs*bs;
1350 
1351   if (mbs*bs != B->rmap->N) {
1352     SETERRQ(PETSC_ERR_ARG_SIZ,"Number rows, cols must be divisible by blocksize");
1353   }
1354 
1355   if (nz == MAT_SKIP_ALLOCATION) {
1356     skipallocation = PETSC_TRUE;
1357     nz             = 0;
1358   }
1359 
1360   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3;
1361   if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
1362   if (nnz) {
1363     for (i=0; i<mbs; i++) {
1364       if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %D value %D",i,nnz[i]);
1365       if (nnz[i] > mbs) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than block row length: local row %D value %D rowlength %D",i,nnz[i],mbs);
1366     }
1367   }
1368 
1369   B->ops->mult             = MatMult_SeqSBAIJ_N;
1370   B->ops->multadd          = MatMultAdd_SeqSBAIJ_N;
1371   B->ops->multtranspose    = MatMult_SeqSBAIJ_N;
1372   B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N;
1373   ierr    = PetscOptionsHasName(((PetscObject)B)->prefix,"-mat_no_unroll",&flg);CHKERRQ(ierr);
1374   if (!flg) {
1375     switch (bs) {
1376     case 1:
1377       B->ops->mult             = MatMult_SeqSBAIJ_1;
1378       B->ops->multadd          = MatMultAdd_SeqSBAIJ_1;
1379       B->ops->multtranspose    = MatMult_SeqSBAIJ_1;
1380       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1;
1381       break;
1382     case 2:
1383       B->ops->mult             = MatMult_SeqSBAIJ_2;
1384       B->ops->multadd          = MatMultAdd_SeqSBAIJ_2;
1385       B->ops->multtranspose    = MatMult_SeqSBAIJ_2;
1386       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2;
1387       break;
1388     case 3:
1389       B->ops->mult             = MatMult_SeqSBAIJ_3;
1390       B->ops->multadd          = MatMultAdd_SeqSBAIJ_3;
1391       B->ops->multtranspose    = MatMult_SeqSBAIJ_3;
1392       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3;
1393       break;
1394     case 4:
1395       B->ops->mult             = MatMult_SeqSBAIJ_4;
1396       B->ops->multadd          = MatMultAdd_SeqSBAIJ_4;
1397       B->ops->multtranspose    = MatMult_SeqSBAIJ_4;
1398       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4;
1399       break;
1400     case 5:
1401       B->ops->mult             = MatMult_SeqSBAIJ_5;
1402       B->ops->multadd          = MatMultAdd_SeqSBAIJ_5;
1403       B->ops->multtranspose    = MatMult_SeqSBAIJ_5;
1404       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5;
1405       break;
1406     case 6:
1407       B->ops->mult             = MatMult_SeqSBAIJ_6;
1408       B->ops->multadd          = MatMultAdd_SeqSBAIJ_6;
1409       B->ops->multtranspose    = MatMult_SeqSBAIJ_6;
1410       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6;
1411       break;
1412     case 7:
1413       B->ops->mult             = MatMult_SeqSBAIJ_7;
1414       B->ops->multadd          = MatMultAdd_SeqSBAIJ_7;
1415       B->ops->multtranspose    = MatMult_SeqSBAIJ_7;
1416       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7;
1417       break;
1418     }
1419   }
1420 
1421   b->mbs = mbs;
1422   b->nbs = mbs;
1423   if (!skipallocation) {
1424     if (!b->imax) {
1425       ierr = PetscMalloc2(mbs,PetscInt,&b->imax,mbs,PetscInt,&b->ilen);CHKERRQ(ierr);
1426       ierr = PetscLogObjectMemory(B,2*mbs*sizeof(PetscInt));CHKERRQ(ierr);
1427     }
1428     if (!nnz) {
1429       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
1430       else if (nz <= 0)        nz = 1;
1431       for (i=0; i<mbs; i++) {
1432         b->imax[i] = nz;
1433       }
1434       nz = nz*mbs; /* total nz */
1435     } else {
1436       nz = 0;
1437       for (i=0; i<mbs; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
1438     }
1439     /* b->ilen will count nonzeros in each block row so far. */
1440     for (i=0; i<mbs; i++) { b->ilen[i] = 0;}
1441     /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */
1442 
1443     /* allocate the matrix space */
1444     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
1445     ierr = PetscMalloc3(bs2*nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap->N+1,PetscInt,&b->i);CHKERRQ(ierr);
1446     ierr = PetscLogObjectMemory(B,(B->rmap->N+1)*sizeof(PetscInt)+nz*(bs2*sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
1447     ierr = PetscMemzero(b->a,nz*bs2*sizeof(MatScalar));CHKERRQ(ierr);
1448     ierr = PetscMemzero(b->j,nz*sizeof(PetscInt));CHKERRQ(ierr);
1449     b->singlemalloc = PETSC_TRUE;
1450 
1451     /* pointer to beginning of each row */
1452     b->i[0] = 0;
1453     for (i=1; i<mbs+1; i++) {
1454       b->i[i] = b->i[i-1] + b->imax[i-1];
1455     }
1456     b->free_a     = PETSC_TRUE;
1457     b->free_ij    = PETSC_TRUE;
1458   } else {
1459     b->free_a     = PETSC_FALSE;
1460     b->free_ij    = PETSC_FALSE;
1461   }
1462 
1463   B->rmap->bs               = bs;
1464   b->bs2              = bs2;
1465   b->nz             = 0;
1466   b->maxnz          = nz*bs2;
1467 
1468   b->inew             = 0;
1469   b->jnew             = 0;
1470   b->anew             = 0;
1471   b->a2anew           = 0;
1472   b->permute          = PETSC_FALSE;
1473   PetscFunctionReturn(0);
1474 }
1475 EXTERN_C_END
1476 
1477 #undef __FUNCT__
1478 #define __FUNCT__ "MatSeqBAIJSetNumericFactorization"
1479 /*
1480    This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization
1481 */
1482 PetscErrorCode MatSeqSBAIJSetNumericFactorization(Mat B,PetscTruth natural)
1483 {
1484   PetscErrorCode ierr;
1485   PetscTruth     flg;
1486   PetscInt       bs = B->rmap->bs;
1487 
1488   PetscFunctionBegin;
1489   ierr    = PetscOptionsHasName(((PetscObject)B)->prefix,"-mat_no_unroll",&flg);CHKERRQ(ierr);
1490   if (flg) bs = 8;
1491 
1492   if (!natural) {
1493     switch (bs) {
1494     case 1:
1495       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1;
1496       break;
1497     case 2:
1498       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2;
1499       break;
1500     case 3:
1501       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3;
1502       break;
1503     case 4:
1504       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4;
1505       break;
1506     case 5:
1507       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5;
1508       break;
1509     case 6:
1510       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6;
1511       break;
1512     case 7:
1513       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7;
1514       break;
1515     default:
1516       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N;
1517       break;
1518     }
1519   } else {
1520     switch (bs) {
1521     case 1:
1522       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering;
1523       break;
1524     case 2:
1525       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering;
1526       break;
1527     case 3:
1528       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering;
1529       break;
1530     case 4:
1531       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering;
1532       break;
1533     case 5:
1534       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering;
1535       break;
1536     case 6:
1537       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering;
1538       break;
1539     case 7:
1540       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering;
1541       break;
1542     default:
1543       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering;
1544       break;
1545     }
1546   }
1547   PetscFunctionReturn(0);
1548 }
1549 
1550 EXTERN_C_BEGIN
1551 EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType,MatReuse,Mat*);
1552 EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType,MatReuse,Mat*);
1553 EXTERN_C_END
1554 
1555 
1556 EXTERN_C_BEGIN
1557 #undef __FUNCT__
1558 #define __FUNCT__ "MatGetFactor_seqsbaij_petsc"
1559 PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A,MatFactorType ftype,Mat *B)
1560 {
1561   PetscInt           n = A->rmap->n;
1562   PetscErrorCode     ierr;
1563 
1564   PetscFunctionBegin;
1565   ierr = MatCreate(((PetscObject)A)->comm,B);CHKERRQ(ierr);
1566   ierr = MatSetSizes(*B,n,n,n,n);CHKERRQ(ierr);
1567   if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1568     ierr = MatSetType(*B,MATSEQSBAIJ);CHKERRQ(ierr);
1569     ierr = MatSeqSBAIJSetPreallocation(*B,1,MAT_SKIP_ALLOCATION,PETSC_NULL);CHKERRQ(ierr);
1570     (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ;
1571     (*B)->ops->iccfactorsymbolic      = MatICCFactorSymbolic_SeqSBAIJ;
1572   } else SETERRQ(PETSC_ERR_SUP,"Factor type not supported");
1573   (*B)->factor = ftype;
1574   PetscFunctionReturn(0);
1575 }
1576 EXTERN_C_END
1577 
1578 EXTERN_C_BEGIN
1579 #undef __FUNCT__
1580 #define __FUNCT__ "MatGetFactorAvailable_seqsbaij_petsc"
1581 PetscErrorCode MatGetFactorAvailable_seqsbaij_petsc(Mat A,MatFactorType ftype,PetscTruth *flg)
1582 {
1583   PetscFunctionBegin;
1584   if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1585     *flg = PETSC_TRUE;
1586   } else {
1587     *flg = PETSC_FALSE;
1588   }
1589   PetscFunctionReturn(0);
1590 }
1591 EXTERN_C_END
1592 
1593 EXTERN_C_BEGIN
1594 #if defined(PETSC_HAVE_MUMPS)
1595 extern PetscErrorCode MatGetFactor_seqsbaij_mumps(Mat,MatFactorType,Mat*);
1596 #endif
1597 #if defined(PETSC_HAVE_SPOOLES)
1598 extern PetscErrorCode MatGetFactor_seqsbaij_spooles(Mat,MatFactorType,Mat*);
1599 #endif
1600 EXTERN_C_END
1601 
1602 /*MC
1603   MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices,
1604   based on block compressed sparse row format.  Only the upper triangular portion of the matrix is stored.
1605 
1606   Options Database Keys:
1607   . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to MatSetFromOptions()
1608 
1609   Level: beginner
1610 
1611   .seealso: MatCreateSeqSBAIJ
1612 M*/
1613 
1614 EXTERN_C_BEGIN
1615 #undef __FUNCT__
1616 #define __FUNCT__ "MatCreate_SeqSBAIJ"
1617 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_SeqSBAIJ(Mat B)
1618 {
1619   Mat_SeqSBAIJ   *b;
1620   PetscErrorCode ierr;
1621   PetscMPIInt    size;
1622   PetscTruth     flg;
1623 
1624   PetscFunctionBegin;
1625   ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr);
1626   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"Comm must be of size 1");
1627 
1628   ierr    = PetscNewLog(B,Mat_SeqSBAIJ,&b);CHKERRQ(ierr);
1629   B->data = (void*)b;
1630   ierr    = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
1631   B->ops->destroy     = MatDestroy_SeqSBAIJ;
1632   B->ops->view        = MatView_SeqSBAIJ;
1633   B->mapping          = 0;
1634   b->row              = 0;
1635   b->icol             = 0;
1636   b->reallocs         = 0;
1637   b->saved_values     = 0;
1638 
1639 
1640   b->roworiented      = PETSC_TRUE;
1641   b->nonew            = 0;
1642   b->diag             = 0;
1643   b->solve_work       = 0;
1644   b->mult_work        = 0;
1645   B->spptr            = 0;
1646   b->keepzeroedrows   = PETSC_FALSE;
1647   b->xtoy             = 0;
1648   b->XtoY             = 0;
1649 
1650   b->inew             = 0;
1651   b->jnew             = 0;
1652   b->anew             = 0;
1653   b->a2anew           = 0;
1654   b->permute          = PETSC_FALSE;
1655 
1656   b->ignore_ltriangular = PETSC_FALSE;
1657   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_ignore_lower_triangular",&flg);CHKERRQ(ierr);
1658   if (flg) b->ignore_ltriangular = PETSC_TRUE;
1659 
1660   b->getrow_utriangular = PETSC_FALSE;
1661   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_getrow_uppertriangular",&flg);CHKERRQ(ierr);
1662   if (flg) b->getrow_utriangular = PETSC_TRUE;
1663 
1664 #if defined(PETSC_HAVE_SPOOLES)
1665   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_spooles_C",
1666                                      "MatGetFactor_seqsbaij_spooles",
1667                                      MatGetFactor_seqsbaij_spooles);CHKERRQ(ierr);
1668 #endif
1669 #if defined(PETSC_HAVE_MUMPS)
1670   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_mumps_C",
1671                                      "MatGetFactor_seqsbaij_mumps",
1672                                      MatGetFactor_seqsbaij_mumps);CHKERRQ(ierr);
1673 #endif
1674   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_seqsbaij_petsc_C",
1675                                      "MatGetFactorAvailable_seqsbaij_petsc",
1676                                      MatGetFactorAvailable_seqsbaij_petsc);CHKERRQ(ierr);
1677   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_petsc_C",
1678                                      "MatGetFactor_seqsbaij_petsc",
1679                                      MatGetFactor_seqsbaij_petsc);CHKERRQ(ierr);
1680   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
1681                                      "MatStoreValues_SeqSBAIJ",
1682                                      MatStoreValues_SeqSBAIJ);CHKERRQ(ierr);
1683   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
1684                                      "MatRetrieveValues_SeqSBAIJ",
1685                                      (void*)MatRetrieveValues_SeqSBAIJ);CHKERRQ(ierr);
1686   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetColumnIndices_C",
1687                                      "MatSeqSBAIJSetColumnIndices_SeqSBAIJ",
1688                                      MatSeqSBAIJSetColumnIndices_SeqSBAIJ);CHKERRQ(ierr);
1689   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqaij_C",
1690                                      "MatConvert_SeqSBAIJ_SeqAIJ",
1691                                       MatConvert_SeqSBAIJ_SeqAIJ);CHKERRQ(ierr);
1692   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqbaij_C",
1693                                      "MatConvert_SeqSBAIJ_SeqBAIJ",
1694                                       MatConvert_SeqSBAIJ_SeqBAIJ);CHKERRQ(ierr);
1695   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetPreallocation_C",
1696                                      "MatSeqSBAIJSetPreallocation_SeqSBAIJ",
1697                                      MatSeqSBAIJSetPreallocation_SeqSBAIJ);CHKERRQ(ierr);
1698 
1699   B->symmetric                  = PETSC_TRUE;
1700   B->structurally_symmetric     = PETSC_TRUE;
1701   B->symmetric_set              = PETSC_TRUE;
1702   B->structurally_symmetric_set = PETSC_TRUE;
1703   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQSBAIJ);CHKERRQ(ierr);
1704   PetscFunctionReturn(0);
1705 }
1706 EXTERN_C_END
1707 
1708 #undef __FUNCT__
1709 #define __FUNCT__ "MatSeqSBAIJSetPreallocation"
1710 /*@C
1711    MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block
1712    compressed row) format.  For good matrix assembly performance the
1713    user should preallocate the matrix storage by setting the parameter nz
1714    (or the array nnz).  By setting these parameters accurately, performance
1715    during matrix assembly can be increased by more than a factor of 50.
1716 
1717    Collective on Mat
1718 
1719    Input Parameters:
1720 +  A - the symmetric matrix
1721 .  bs - size of block
1722 .  nz - number of block nonzeros per block row (same for all rows)
1723 -  nnz - array containing the number of block nonzeros in the upper triangular plus
1724          diagonal portion of each block (possibly different for each block row) or PETSC_NULL
1725 
1726    Options Database Keys:
1727 .   -mat_no_unroll - uses code that does not unroll the loops in the
1728                      block calculations (much slower)
1729 .    -mat_block_size - size of the blocks to use (only works if a negative bs is passed in
1730 
1731    Level: intermediate
1732 
1733    Notes:
1734    Specify the preallocated storage with either nz or nnz (not both).
1735    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
1736    allocation.  For additional details, see the users manual chapter on
1737    matrices.
1738 
1739    You can call MatGetInfo() to get information on how effective the preallocation was;
1740    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
1741    You can also run with the option -info and look for messages with the string
1742    malloc in them to see if additional memory allocation was needed.
1743 
1744    If the nnz parameter is given then the nz parameter is ignored
1745 
1746 
1747 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ()
1748 @*/
1749 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetPreallocation(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[])
1750 {
1751   PetscErrorCode ierr,(*f)(Mat,PetscInt,PetscInt,const PetscInt[]);
1752 
1753   PetscFunctionBegin;
1754   ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqSBAIJSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr);
1755   if (f) {
1756     ierr = (*f)(B,bs,nz,nnz);CHKERRQ(ierr);
1757   }
1758   PetscFunctionReturn(0);
1759 }
1760 
1761 #undef __FUNCT__
1762 #define __FUNCT__ "MatCreateSeqSBAIJ"
1763 /*@C
1764    MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in block AIJ (block
1765    compressed row) format.  For good matrix assembly performance the
1766    user should preallocate the matrix storage by setting the parameter nz
1767    (or the array nnz).  By setting these parameters accurately, performance
1768    during matrix assembly can be increased by more than a factor of 50.
1769 
1770    Collective on MPI_Comm
1771 
1772    Input Parameters:
1773 +  comm - MPI communicator, set to PETSC_COMM_SELF
1774 .  bs - size of block
1775 .  m - number of rows, or number of columns
1776 .  nz - number of block nonzeros per block row (same for all rows)
1777 -  nnz - array containing the number of block nonzeros in the upper triangular plus
1778          diagonal portion of each block (possibly different for each block row) or PETSC_NULL
1779 
1780    Output Parameter:
1781 .  A - the symmetric matrix
1782 
1783    Options Database Keys:
1784 .   -mat_no_unroll - uses code that does not unroll the loops in the
1785                      block calculations (much slower)
1786 .    -mat_block_size - size of the blocks to use
1787 
1788    Level: intermediate
1789 
1790    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
1791    MatXXXXSetPreallocation() paradgm instead of this routine directly. This is definitely
1792    true if you plan to use the external direct solvers such as SuperLU, MUMPS or Spooles.
1793    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
1794 
1795    Notes:
1796    The number of rows and columns must be divisible by blocksize.
1797    This matrix type does not support complex Hermitian operation.
1798 
1799    Specify the preallocated storage with either nz or nnz (not both).
1800    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
1801    allocation.  For additional details, see the users manual chapter on
1802    matrices.
1803 
1804    If the nnz parameter is given then the nz parameter is ignored
1805 
1806 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ()
1807 @*/
1808 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqSBAIJ(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
1809 {
1810   PetscErrorCode ierr;
1811 
1812   PetscFunctionBegin;
1813   ierr = MatCreate(comm,A);CHKERRQ(ierr);
1814   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
1815   ierr = MatSetType(*A,MATSEQSBAIJ);CHKERRQ(ierr);
1816   ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(*A,bs,nz,(PetscInt*)nnz);CHKERRQ(ierr);
1817   PetscFunctionReturn(0);
1818 }
1819 
1820 #undef __FUNCT__
1821 #define __FUNCT__ "MatDuplicate_SeqSBAIJ"
1822 PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
1823 {
1824   Mat            C;
1825   Mat_SeqSBAIJ   *c,*a = (Mat_SeqSBAIJ*)A->data;
1826   PetscErrorCode ierr;
1827   PetscInt       i,mbs = a->mbs,nz = a->nz,bs2 =a->bs2;
1828 
1829   PetscFunctionBegin;
1830   if (a->i[mbs] != nz) SETERRQ(PETSC_ERR_PLIB,"Corrupt matrix");
1831 
1832   *B = 0;
1833   ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr);
1834   ierr = MatSetSizes(C,A->rmap->N,A->cmap->n,A->rmap->N,A->cmap->n);CHKERRQ(ierr);
1835   ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
1836   ierr = PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1837   c    = (Mat_SeqSBAIJ*)C->data;
1838 
1839   C->preallocated   = PETSC_TRUE;
1840   C->factor         = A->factor;
1841   c->row            = 0;
1842   c->icol           = 0;
1843   c->saved_values   = 0;
1844   c->keepzeroedrows = a->keepzeroedrows;
1845   C->assembled      = PETSC_TRUE;
1846 
1847   ierr = PetscMapCopy(((PetscObject)A)->comm,A->rmap,C->rmap);CHKERRQ(ierr);
1848   ierr = PetscMapCopy(((PetscObject)A)->comm,A->cmap,C->cmap);CHKERRQ(ierr);
1849   c->bs2  = a->bs2;
1850   c->mbs  = a->mbs;
1851   c->nbs  = a->nbs;
1852 
1853   ierr = PetscMalloc2((mbs+1),PetscInt,&c->imax,(mbs+1),PetscInt,&c->ilen);CHKERRQ(ierr);
1854   for (i=0; i<mbs; i++) {
1855     c->imax[i] = a->imax[i];
1856     c->ilen[i] = a->ilen[i];
1857   }
1858 
1859   /* allocate the matrix space */
1860   ierr = PetscMalloc3(bs2*nz,MatScalar,&c->a,nz,PetscInt,&c->j,mbs+1,PetscInt,&c->i);CHKERRQ(ierr);
1861   c->singlemalloc = PETSC_TRUE;
1862   ierr = PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr);
1863   ierr = PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt) + nz*(bs2*sizeof(MatScalar) + sizeof(PetscInt)));CHKERRQ(ierr);
1864   if (mbs > 0) {
1865     ierr = PetscMemcpy(c->j,a->j,nz*sizeof(PetscInt));CHKERRQ(ierr);
1866     if (cpvalues == MAT_COPY_VALUES) {
1867       ierr = PetscMemcpy(c->a,a->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr);
1868     } else {
1869       ierr = PetscMemzero(c->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr);
1870     }
1871   }
1872 
1873   c->roworiented = a->roworiented;
1874   c->nonew       = a->nonew;
1875 
1876   if (a->diag) {
1877     ierr = PetscMalloc((mbs+1)*sizeof(PetscInt),&c->diag);CHKERRQ(ierr);
1878     ierr = PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr);
1879     for (i=0; i<mbs; i++) {
1880       c->diag[i] = a->diag[i];
1881     }
1882   } else c->diag  = 0;
1883   c->nz           = a->nz;
1884   c->maxnz        = a->maxnz;
1885   c->solve_work   = 0;
1886   c->mult_work    = 0;
1887   c->free_a       = PETSC_TRUE;
1888   c->free_ij      = PETSC_TRUE;
1889   *B = C;
1890   ierr = PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
1891   PetscFunctionReturn(0);
1892 }
1893 
1894 #undef __FUNCT__
1895 #define __FUNCT__ "MatLoad_SeqSBAIJ"
1896 PetscErrorCode MatLoad_SeqSBAIJ(PetscViewer viewer, const MatType type,Mat *A)
1897 {
1898   Mat_SeqSBAIJ   *a;
1899   Mat            B;
1900   PetscErrorCode ierr;
1901   int            fd;
1902   PetscMPIInt    size;
1903   PetscInt       i,nz,header[4],*rowlengths=0,M,N,bs=1;
1904   PetscInt       *mask,mbs,*jj,j,rowcount,nzcount,k,*s_browlengths,maskcount;
1905   PetscInt       kmax,jcount,block,idx,point,nzcountb,extra_rows;
1906   PetscInt       *masked,nmask,tmp,bs2,ishift;
1907   PetscScalar    *aa;
1908   MPI_Comm       comm = ((PetscObject)viewer)->comm;
1909 
1910   PetscFunctionBegin;
1911   ierr = PetscOptionsGetInt(PETSC_NULL,"-matload_block_size",&bs,PETSC_NULL);CHKERRQ(ierr);
1912   bs2  = bs*bs;
1913 
1914   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1915   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"view must have one processor");
1916   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
1917   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
1918   if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not Mat object");
1919   M = header[1]; N = header[2]; nz = header[3];
1920 
1921   if (header[3] < 0) {
1922     SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format, cannot load as SeqSBAIJ");
1923   }
1924 
1925   if (M != N) SETERRQ(PETSC_ERR_SUP,"Can only do square matrices");
1926 
1927   /*
1928      This code adds extra rows to make sure the number of rows is
1929     divisible by the blocksize
1930   */
1931   mbs        = M/bs;
1932   extra_rows = bs - M + bs*(mbs);
1933   if (extra_rows == bs) extra_rows = 0;
1934   else                  mbs++;
1935   if (extra_rows) {
1936     ierr = PetscInfo(viewer,"Padding loaded matrix to match blocksize\n");CHKERRQ(ierr);
1937   }
1938 
1939   /* read in row lengths */
1940   ierr = PetscMalloc((M+extra_rows)*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
1941   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
1942   for (i=0; i<extra_rows; i++) rowlengths[M+i] = 1;
1943 
1944   /* read in column indices */
1945   ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscInt),&jj);CHKERRQ(ierr);
1946   ierr = PetscBinaryRead(fd,jj,nz,PETSC_INT);CHKERRQ(ierr);
1947   for (i=0; i<extra_rows; i++) jj[nz+i] = M+i;
1948 
1949   /* loop over row lengths determining block row lengths */
1950   ierr     = PetscMalloc(mbs*sizeof(PetscInt),&s_browlengths);CHKERRQ(ierr);
1951   ierr     = PetscMemzero(s_browlengths,mbs*sizeof(PetscInt));CHKERRQ(ierr);
1952   ierr     = PetscMalloc(2*mbs*sizeof(PetscInt),&mask);CHKERRQ(ierr);
1953   ierr     = PetscMemzero(mask,mbs*sizeof(PetscInt));CHKERRQ(ierr);
1954   masked   = mask + mbs;
1955   rowcount = 0; nzcount = 0;
1956   for (i=0; i<mbs; i++) {
1957     nmask = 0;
1958     for (j=0; j<bs; j++) {
1959       kmax = rowlengths[rowcount];
1960       for (k=0; k<kmax; k++) {
1961         tmp = jj[nzcount++]/bs;   /* block col. index */
1962         if (!mask[tmp] && tmp >= i) {masked[nmask++] = tmp; mask[tmp] = 1;}
1963       }
1964       rowcount++;
1965     }
1966     s_browlengths[i] += nmask;
1967 
1968     /* zero out the mask elements we set */
1969     for (j=0; j<nmask; j++) mask[masked[j]] = 0;
1970   }
1971 
1972   /* create our matrix */
1973   ierr = MatCreate(comm,&B);CHKERRQ(ierr);
1974   ierr = MatSetSizes(B,M+extra_rows,N+extra_rows,M+extra_rows,N+extra_rows);CHKERRQ(ierr);
1975   ierr = MatSetType(B,type);CHKERRQ(ierr);
1976   ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(B,bs,0,s_browlengths);CHKERRQ(ierr);
1977   a = (Mat_SeqSBAIJ*)B->data;
1978 
1979   /* set matrix "i" values */
1980   a->i[0] = 0;
1981   for (i=1; i<= mbs; i++) {
1982     a->i[i]      = a->i[i-1] + s_browlengths[i-1];
1983     a->ilen[i-1] = s_browlengths[i-1];
1984   }
1985   a->nz = a->i[mbs];
1986 
1987   /* read in nonzero values */
1988   ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscScalar),&aa);CHKERRQ(ierr);
1989   ierr = PetscBinaryRead(fd,aa,nz,PETSC_SCALAR);CHKERRQ(ierr);
1990   for (i=0; i<extra_rows; i++) aa[nz+i] = 1.0;
1991 
1992   /* set "a" and "j" values into matrix */
1993   nzcount = 0; jcount = 0;
1994   for (i=0; i<mbs; i++) {
1995     nzcountb = nzcount;
1996     nmask    = 0;
1997     for (j=0; j<bs; j++) {
1998       kmax = rowlengths[i*bs+j];
1999       for (k=0; k<kmax; k++) {
2000         tmp = jj[nzcount++]/bs; /* block col. index */
2001         if (!mask[tmp] && tmp >= i) { masked[nmask++] = tmp; mask[tmp] = 1;}
2002       }
2003     }
2004     /* sort the masked values */
2005     ierr = PetscSortInt(nmask,masked);CHKERRQ(ierr);
2006 
2007     /* set "j" values into matrix */
2008     maskcount = 1;
2009     for (j=0; j<nmask; j++) {
2010       a->j[jcount++]  = masked[j];
2011       mask[masked[j]] = maskcount++;
2012     }
2013 
2014     /* set "a" values into matrix */
2015     ishift = bs2*a->i[i];
2016     for (j=0; j<bs; j++) {
2017       kmax = rowlengths[i*bs+j];
2018       for (k=0; k<kmax; k++) {
2019         tmp       = jj[nzcountb]/bs ; /* block col. index */
2020         if (tmp >= i){
2021           block     = mask[tmp] - 1;
2022           point     = jj[nzcountb] - bs*tmp;
2023           idx       = ishift + bs2*block + j + bs*point;
2024           a->a[idx] = aa[nzcountb];
2025         }
2026         nzcountb++;
2027       }
2028     }
2029     /* zero out the mask elements we set */
2030     for (j=0; j<nmask; j++) mask[masked[j]] = 0;
2031   }
2032   if (jcount != a->nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Bad binary matrix");
2033 
2034   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
2035   ierr = PetscFree(s_browlengths);CHKERRQ(ierr);
2036   ierr = PetscFree(aa);CHKERRQ(ierr);
2037   ierr = PetscFree(jj);CHKERRQ(ierr);
2038   ierr = PetscFree(mask);CHKERRQ(ierr);
2039 
2040   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2041   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2042   ierr = MatView_Private(B);CHKERRQ(ierr);
2043   *A = B;
2044   PetscFunctionReturn(0);
2045 }
2046 
2047 #undef __FUNCT__
2048 #define __FUNCT__ "MatRelax_SeqSBAIJ"
2049 PetscErrorCode MatRelax_SeqSBAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
2050 {
2051   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
2052   MatScalar      *aa=a->a,*v,*v1;
2053   PetscScalar    *x,*b,*t,sum,d;
2054   PetscErrorCode ierr;
2055   PetscInt       m=a->mbs,bs=A->rmap->bs,*ai=a->i,*aj=a->j;
2056   PetscInt       nz,nz1,*vj,*vj1,i;
2057 
2058   PetscFunctionBegin;
2059   if (flag & SOR_EISENSTAT) SETERRQ(PETSC_ERR_SUP,"No support yet for Eisenstat");
2060 
2061   its = its*lits;
2062   if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits);
2063 
2064   if (bs > 1)
2065     SETERRQ(PETSC_ERR_SUP,"SSOR for block size > 1 is not yet implemented");
2066 
2067   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
2068   if (xx != bb) {
2069     ierr = VecGetArray(bb,&b);CHKERRQ(ierr);
2070   } else {
2071     b = x;
2072   }
2073 
2074   if (!a->relax_work) {
2075     ierr = PetscMalloc(m*sizeof(PetscScalar),&a->relax_work);CHKERRQ(ierr);
2076   }
2077   t = a->relax_work;
2078 
2079   if (flag & SOR_ZERO_INITIAL_GUESS) {
2080     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
2081       ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr);
2082 
2083       for (i=0; i<m; i++){
2084         d  = *(aa + ai[i]);  /* diag[i] */
2085         v  = aa + ai[i] + 1;
2086         vj = aj + ai[i] + 1;
2087         nz = ai[i+1] - ai[i] - 1;
2088         ierr = PetscLogFlops(2*nz-1);CHKERRQ(ierr);
2089         x[i] = omega*t[i]/d;
2090         while (nz--) t[*vj++] -= x[i]*(*v++); /* update rhs */
2091       }
2092     }
2093 
2094     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
2095       if (!(flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP)){
2096         t = b;
2097       }
2098 
2099       for (i=m-1; i>=0; i--){
2100         d  = *(aa + ai[i]);
2101         v  = aa + ai[i] + 1;
2102         vj = aj + ai[i] + 1;
2103         nz = ai[i+1] - ai[i] - 1;
2104         ierr = PetscLogFlops(2*nz-1);CHKERRQ(ierr);
2105         sum = t[i];
2106         while (nz--) sum -= x[*vj++]*(*v++);
2107         x[i] =   (1-omega)*x[i] + omega*sum/d;
2108       }
2109       t = a->relax_work;
2110     }
2111     its--;
2112   }
2113 
2114   while (its--) {
2115     /*
2116        forward sweep:
2117        for i=0,...,m-1:
2118          sum[i] = (b[i] - U(i,:)x )/d[i];
2119          x[i]   = (1-omega)x[i] + omega*sum[i];
2120          b      = b - x[i]*U^T(i,:);
2121 
2122     */
2123     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
2124       ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr);
2125 
2126       for (i=0; i<m; i++){
2127         d  = *(aa + ai[i]);  /* diag[i] */
2128         v  = aa + ai[i] + 1; v1=v;
2129         vj = aj + ai[i] + 1; vj1=vj;
2130         nz = ai[i+1] - ai[i] - 1; nz1=nz;
2131         sum = t[i];
2132         ierr = PetscLogFlops(4*nz-2);CHKERRQ(ierr);
2133         while (nz1--) sum -= (*v1++)*x[*vj1++];
2134         x[i] = (1-omega)*x[i] + omega*sum/d;
2135         while (nz--) t[*vj++] -= x[i]*(*v++);
2136       }
2137     }
2138 
2139     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
2140       /*
2141        backward sweep:
2142        b = b - x[i]*U^T(i,:), i=0,...,n-2
2143        for i=m-1,...,0:
2144          sum[i] = (b[i] - U(i,:)x )/d[i];
2145          x[i]   = (1-omega)x[i] + omega*sum[i];
2146       */
2147       /* if there was a forward sweep done above then I thing the next two for loops are not needed */
2148       ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr);
2149 
2150       for (i=0; i<m-1; i++){  /* update rhs */
2151         v  = aa + ai[i] + 1;
2152         vj = aj + ai[i] + 1;
2153         nz = ai[i+1] - ai[i] - 1;
2154         ierr = PetscLogFlops(2*nz-1);CHKERRQ(ierr);
2155         while (nz--) t[*vj++] -= x[i]*(*v++);
2156       }
2157       for (i=m-1; i>=0; i--){
2158         d  = *(aa + ai[i]);
2159         v  = aa + ai[i] + 1;
2160         vj = aj + ai[i] + 1;
2161         nz = ai[i+1] - ai[i] - 1;
2162         ierr = PetscLogFlops(2*nz-1);CHKERRQ(ierr);
2163         sum = t[i];
2164         while (nz--) sum -= x[*vj++]*(*v++);
2165         x[i] =   (1-omega)*x[i] + omega*sum/d;
2166       }
2167     }
2168   }
2169 
2170   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
2171   if (bb != xx) {
2172     ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr);
2173   }
2174   PetscFunctionReturn(0);
2175 }
2176 
2177 #undef __FUNCT__
2178 #define __FUNCT__ "MatCreateSeqSBAIJWithArrays"
2179 /*@
2180      MatCreateSeqSBAIJWithArrays - Creates an sequential SBAIJ matrix using matrix elements
2181               (upper triangular entries in CSR format) provided by the user.
2182 
2183      Collective on MPI_Comm
2184 
2185    Input Parameters:
2186 +  comm - must be an MPI communicator of size 1
2187 .  bs - size of block
2188 .  m - number of rows
2189 .  n - number of columns
2190 .  i - row indices
2191 .  j - column indices
2192 -  a - matrix values
2193 
2194    Output Parameter:
2195 .  mat - the matrix
2196 
2197    Level: intermediate
2198 
2199    Notes:
2200        The i, j, and a arrays are not copied by this routine, the user must free these arrays
2201     once the matrix is destroyed
2202 
2203        You cannot set new nonzero locations into this matrix, that will generate an error.
2204 
2205        The i and j indices are 0 based
2206 
2207 .seealso: MatCreate(), MatCreateMPISBAIJ(), MatCreateSeqSBAIJ()
2208 
2209 @*/
2210 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqSBAIJWithArrays(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat)
2211 {
2212   PetscErrorCode ierr;
2213   PetscInt       ii;
2214   Mat_SeqSBAIJ   *sbaij;
2215 
2216   PetscFunctionBegin;
2217   if (bs != 1) SETERRQ1(PETSC_ERR_SUP,"block size %D > 1 is not supported yet",bs);
2218   if (i[0]) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
2219 
2220   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
2221   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
2222   ierr = MatSetType(*mat,MATSEQSBAIJ);CHKERRQ(ierr);
2223   ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(*mat,bs,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr);
2224   sbaij = (Mat_SeqSBAIJ*)(*mat)->data;
2225   ierr = PetscMalloc2(m,PetscInt,&sbaij->imax,m,PetscInt,&sbaij->ilen);CHKERRQ(ierr);
2226 
2227   sbaij->i = i;
2228   sbaij->j = j;
2229   sbaij->a = a;
2230   sbaij->singlemalloc = PETSC_FALSE;
2231   sbaij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2232   sbaij->free_a       = PETSC_FALSE;
2233   sbaij->free_ij      = PETSC_FALSE;
2234 
2235   for (ii=0; ii<m; ii++) {
2236     sbaij->ilen[ii] = sbaij->imax[ii] = i[ii+1] - i[ii];
2237 #if defined(PETSC_USE_DEBUG)
2238     if (i[ii+1] - i[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %d length = %d",ii,i[ii+1] - i[ii]);
2239 #endif
2240   }
2241 #if defined(PETSC_USE_DEBUG)
2242   for (ii=0; ii<sbaij->i[m]; ii++) {
2243     if (j[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]);
2244     if (j[ii] > n - 1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]);
2245   }
2246 #endif
2247 
2248   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2249   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2250   PetscFunctionReturn(0);
2251 }
2252 
2253 
2254 
2255 
2256 
2257