xref: /petsc/src/mat/impls/sbaij/seq/sbaij.c (revision 88170d3c014dde9f19b263fccd87ca27ccefd46a)
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        MatSetOption_SeqSBAIJ,
1175        MatZeroEntries_SeqSBAIJ,
1176 /*24*/ 0,
1177        0,
1178        0,
1179        0,
1180        0,
1181 /*29*/ MatSetUpPreallocation_SeqSBAIJ,
1182        0,
1183        0,
1184        MatGetArray_SeqSBAIJ,
1185        MatRestoreArray_SeqSBAIJ,
1186 /*34*/ MatDuplicate_SeqSBAIJ,
1187        0,
1188        0,
1189        0,
1190        MatICCFactor_SeqSBAIJ,
1191 /*39*/ MatAXPY_SeqSBAIJ,
1192        MatGetSubMatrices_SeqSBAIJ,
1193        MatIncreaseOverlap_SeqSBAIJ,
1194        MatGetValues_SeqSBAIJ,
1195        MatCopy_SeqSBAIJ,
1196 /*44*/ 0,
1197        MatScale_SeqSBAIJ,
1198        0,
1199        0,
1200        0,
1201 /*49*/ 0,
1202        MatGetRowIJ_SeqSBAIJ,
1203        MatRestoreRowIJ_SeqSBAIJ,
1204        0,
1205        0,
1206 /*54*/ 0,
1207        0,
1208        0,
1209        0,
1210        MatSetValuesBlocked_SeqSBAIJ,
1211 /*59*/ MatGetSubMatrix_SeqSBAIJ,
1212        0,
1213        0,
1214        0,
1215        0,
1216 /*64*/ 0,
1217        0,
1218        0,
1219        0,
1220        0,
1221 /*69*/ MatGetRowMaxAbs_SeqSBAIJ,
1222        0,
1223        0,
1224        0,
1225        0,
1226 /*74*/ 0,
1227        0,
1228        0,
1229        0,
1230        0,
1231 /*79*/ 0,
1232        0,
1233        0,
1234 #if !defined(PETSC_USE_COMPLEX)
1235        MatGetInertia_SeqSBAIJ,
1236 #else
1237        0,
1238 #endif
1239        MatLoad_SeqSBAIJ,
1240 /*84*/ MatIsSymmetric_SeqSBAIJ,
1241        MatIsHermitian_SeqSBAIJ,
1242        MatIsStructurallySymmetric_SeqSBAIJ,
1243        0,
1244        0,
1245 /*89*/ 0,
1246        0,
1247        0,
1248        0,
1249        0,
1250 /*94*/ 0,
1251        0,
1252        0,
1253        0,
1254        0,
1255 /*99*/ 0,
1256        0,
1257        0,
1258        0,
1259        0,
1260 /*104*/0,
1261        MatRealPart_SeqSBAIJ,
1262        MatImaginaryPart_SeqSBAIJ,
1263        MatGetRowUpperTriangular_SeqSBAIJ,
1264        MatRestoreRowUpperTriangular_SeqSBAIJ,
1265 /*109*/0,
1266        0,
1267        0,
1268        0,
1269        MatMissingDiagonal_SeqSBAIJ
1270 };
1271 
1272 EXTERN_C_BEGIN
1273 #undef __FUNCT__
1274 #define __FUNCT__ "MatStoreValues_SeqSBAIJ"
1275 PetscErrorCode PETSCMAT_DLLEXPORT MatStoreValues_SeqSBAIJ(Mat mat)
1276 {
1277   Mat_SeqSBAIJ   *aij = (Mat_SeqSBAIJ *)mat->data;
1278   PetscInt       nz = aij->i[mat->rmap->N]*mat->rmap->bs*aij->bs2;
1279   PetscErrorCode ierr;
1280 
1281   PetscFunctionBegin;
1282   if (aij->nonew != 1) {
1283     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
1284   }
1285 
1286   /* allocate space for values if not already there */
1287   if (!aij->saved_values) {
1288     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr);
1289   }
1290 
1291   /* copy values over */
1292   ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr);
1293   PetscFunctionReturn(0);
1294 }
1295 EXTERN_C_END
1296 
1297 EXTERN_C_BEGIN
1298 #undef __FUNCT__
1299 #define __FUNCT__ "MatRetrieveValues_SeqSBAIJ"
1300 PetscErrorCode PETSCMAT_DLLEXPORT MatRetrieveValues_SeqSBAIJ(Mat mat)
1301 {
1302   Mat_SeqSBAIJ   *aij = (Mat_SeqSBAIJ *)mat->data;
1303   PetscErrorCode ierr;
1304   PetscInt       nz = aij->i[mat->rmap->N]*mat->rmap->bs*aij->bs2;
1305 
1306   PetscFunctionBegin;
1307   if (aij->nonew != 1) {
1308     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
1309   }
1310   if (!aij->saved_values) {
1311     SETERRQ(PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
1312   }
1313 
1314   /* copy values over */
1315   ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr);
1316   PetscFunctionReturn(0);
1317 }
1318 EXTERN_C_END
1319 
1320 EXTERN_C_BEGIN
1321 #undef __FUNCT__
1322 #define __FUNCT__ "MatSeqSBAIJSetPreallocation_SeqSBAIJ"
1323 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B,PetscInt bs,PetscInt nz,PetscInt *nnz)
1324 {
1325   Mat_SeqSBAIJ   *b = (Mat_SeqSBAIJ*)B->data;
1326   PetscErrorCode ierr;
1327   PetscInt       i,mbs,bs2, newbs = PetscAbs(bs);
1328   PetscTruth     skipallocation = PETSC_FALSE,flg = PETSC_FALSE;
1329 
1330   PetscFunctionBegin;
1331   B->preallocated = PETSC_TRUE;
1332   if (bs < 0) {
1333     ierr = PetscOptionsBegin(((PetscObject)B)->comm,((PetscObject)B)->prefix,"Options for MPISBAIJ matrix","Mat");CHKERRQ(ierr);
1334       ierr = PetscOptionsInt("-mat_block_size","Set the blocksize used to store the matrix","MatSeqSBAIJSetPreallocation",newbs,&newbs,PETSC_NULL);CHKERRQ(ierr);
1335     ierr = PetscOptionsEnd();CHKERRQ(ierr);
1336     bs   = PetscAbs(bs);
1337   }
1338   if (nnz && newbs != bs) {
1339     SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot change blocksize from command line if setting nnz");
1340   }
1341   bs = newbs;
1342 
1343   ierr = PetscMapSetBlockSize(B->rmap,bs);CHKERRQ(ierr);
1344   ierr = PetscMapSetBlockSize(B->cmap,bs);CHKERRQ(ierr);
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  = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_no_unroll",&flg,PETSC_NULL);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 = PETSC_FALSE;
1486   PetscInt       bs = B->rmap->bs;
1487 
1488   PetscFunctionBegin;
1489   ierr    = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_no_unroll",&flg,PETSC_NULL);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 #if defined(PETSC_HAVE_PASTIX)
1601 extern PetscErrorCode MatGetFactor_seqsbaij_pastix(Mat,MatFactorType,Mat*);
1602 #endif
1603 EXTERN_C_END
1604 
1605 /*MC
1606   MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices,
1607   based on block compressed sparse row format.  Only the upper triangular portion of the matrix is stored.
1608 
1609   Options Database Keys:
1610   . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to MatSetFromOptions()
1611 
1612   Level: beginner
1613 
1614   .seealso: MatCreateSeqSBAIJ
1615 M*/
1616 
1617 EXTERN_C_BEGIN
1618 #undef __FUNCT__
1619 #define __FUNCT__ "MatCreate_SeqSBAIJ"
1620 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_SeqSBAIJ(Mat B)
1621 {
1622   Mat_SeqSBAIJ   *b;
1623   PetscErrorCode ierr;
1624   PetscMPIInt    size;
1625 
1626   PetscFunctionBegin;
1627   ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr);
1628   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"Comm must be of size 1");
1629 
1630   ierr    = PetscNewLog(B,Mat_SeqSBAIJ,&b);CHKERRQ(ierr);
1631   B->data = (void*)b;
1632   ierr    = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
1633   B->ops->destroy     = MatDestroy_SeqSBAIJ;
1634   B->ops->view        = MatView_SeqSBAIJ;
1635   B->mapping          = 0;
1636   b->row              = 0;
1637   b->icol             = 0;
1638   b->reallocs         = 0;
1639   b->saved_values     = 0;
1640 
1641 
1642   b->roworiented      = PETSC_TRUE;
1643   b->nonew            = 0;
1644   b->diag             = 0;
1645   b->solve_work       = 0;
1646   b->mult_work        = 0;
1647   B->spptr            = 0;
1648   b->keepzeroedrows   = PETSC_FALSE;
1649   b->xtoy             = 0;
1650   b->XtoY             = 0;
1651 
1652   b->inew             = 0;
1653   b->jnew             = 0;
1654   b->anew             = 0;
1655   b->a2anew           = 0;
1656   b->permute          = PETSC_FALSE;
1657 
1658   b->ignore_ltriangular = PETSC_FALSE;
1659   ierr = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_ignore_lower_triangular",&b->ignore_ltriangular,PETSC_NULL);CHKERRQ(ierr);
1660 
1661   b->getrow_utriangular = PETSC_FALSE;
1662   ierr = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_getrow_uppertriangular",&b->getrow_utriangular,PETSC_NULL);CHKERRQ(ierr);
1663 
1664 #if defined(PETSC_HAVE_PASTIX)
1665   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_pastix_C",
1666 					   "MatGetFactor_seqsbaij_pastix",
1667 					   MatGetFactor_seqsbaij_pastix);CHKERRQ(ierr);
1668 #endif
1669 #if defined(PETSC_HAVE_SPOOLES)
1670   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_spooles_C",
1671                                      "MatGetFactor_seqsbaij_spooles",
1672                                      MatGetFactor_seqsbaij_spooles);CHKERRQ(ierr);
1673 #endif
1674 #if defined(PETSC_HAVE_MUMPS)
1675   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_mumps_C",
1676                                      "MatGetFactor_seqsbaij_mumps",
1677                                      MatGetFactor_seqsbaij_mumps);CHKERRQ(ierr);
1678 #endif
1679   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_seqsbaij_petsc_C",
1680                                      "MatGetFactorAvailable_seqsbaij_petsc",
1681                                      MatGetFactorAvailable_seqsbaij_petsc);CHKERRQ(ierr);
1682   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_petsc_C",
1683                                      "MatGetFactor_seqsbaij_petsc",
1684                                      MatGetFactor_seqsbaij_petsc);CHKERRQ(ierr);
1685   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
1686                                      "MatStoreValues_SeqSBAIJ",
1687                                      MatStoreValues_SeqSBAIJ);CHKERRQ(ierr);
1688   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
1689                                      "MatRetrieveValues_SeqSBAIJ",
1690                                      (void*)MatRetrieveValues_SeqSBAIJ);CHKERRQ(ierr);
1691   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetColumnIndices_C",
1692                                      "MatSeqSBAIJSetColumnIndices_SeqSBAIJ",
1693                                      MatSeqSBAIJSetColumnIndices_SeqSBAIJ);CHKERRQ(ierr);
1694   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqaij_C",
1695                                      "MatConvert_SeqSBAIJ_SeqAIJ",
1696                                       MatConvert_SeqSBAIJ_SeqAIJ);CHKERRQ(ierr);
1697   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqbaij_C",
1698                                      "MatConvert_SeqSBAIJ_SeqBAIJ",
1699                                       MatConvert_SeqSBAIJ_SeqBAIJ);CHKERRQ(ierr);
1700   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetPreallocation_C",
1701                                      "MatSeqSBAIJSetPreallocation_SeqSBAIJ",
1702                                      MatSeqSBAIJSetPreallocation_SeqSBAIJ);CHKERRQ(ierr);
1703 
1704   B->symmetric                  = PETSC_TRUE;
1705   B->structurally_symmetric     = PETSC_TRUE;
1706   B->symmetric_set              = PETSC_TRUE;
1707   B->structurally_symmetric_set = PETSC_TRUE;
1708   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQSBAIJ);CHKERRQ(ierr);
1709   PetscFunctionReturn(0);
1710 }
1711 EXTERN_C_END
1712 
1713 #undef __FUNCT__
1714 #define __FUNCT__ "MatSeqSBAIJSetPreallocation"
1715 /*@C
1716    MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block
1717    compressed row) format.  For good matrix assembly performance the
1718    user should preallocate the matrix storage by setting the parameter nz
1719    (or the array nnz).  By setting these parameters accurately, performance
1720    during matrix assembly can be increased by more than a factor of 50.
1721 
1722    Collective on Mat
1723 
1724    Input Parameters:
1725 +  A - the symmetric matrix
1726 .  bs - size of block
1727 .  nz - number of block nonzeros per block row (same for all rows)
1728 -  nnz - array containing the number of block nonzeros in the upper triangular plus
1729          diagonal portion of each block (possibly different for each block row) or PETSC_NULL
1730 
1731    Options Database Keys:
1732 .   -mat_no_unroll - uses code that does not unroll the loops in the
1733                      block calculations (much slower)
1734 .    -mat_block_size - size of the blocks to use (only works if a negative bs is passed in
1735 
1736    Level: intermediate
1737 
1738    Notes:
1739    Specify the preallocated storage with either nz or nnz (not both).
1740    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
1741    allocation.  For additional details, see the users manual chapter on
1742    matrices.
1743 
1744    You can call MatGetInfo() to get information on how effective the preallocation was;
1745    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
1746    You can also run with the option -info and look for messages with the string
1747    malloc in them to see if additional memory allocation was needed.
1748 
1749    If the nnz parameter is given then the nz parameter is ignored
1750 
1751 
1752 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ()
1753 @*/
1754 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetPreallocation(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[])
1755 {
1756   PetscErrorCode ierr,(*f)(Mat,PetscInt,PetscInt,const PetscInt[]);
1757 
1758   PetscFunctionBegin;
1759   ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqSBAIJSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr);
1760   if (f) {
1761     ierr = (*f)(B,bs,nz,nnz);CHKERRQ(ierr);
1762   }
1763   PetscFunctionReturn(0);
1764 }
1765 
1766 #undef __FUNCT__
1767 #define __FUNCT__ "MatCreateSeqSBAIJ"
1768 /*@C
1769    MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in block AIJ (block
1770    compressed row) format.  For good matrix assembly performance the
1771    user should preallocate the matrix storage by setting the parameter nz
1772    (or the array nnz).  By setting these parameters accurately, performance
1773    during matrix assembly can be increased by more than a factor of 50.
1774 
1775    Collective on MPI_Comm
1776 
1777    Input Parameters:
1778 +  comm - MPI communicator, set to PETSC_COMM_SELF
1779 .  bs - size of block
1780 .  m - number of rows, or number of columns
1781 .  nz - number of block nonzeros per block row (same for all rows)
1782 -  nnz - array containing the number of block nonzeros in the upper triangular plus
1783          diagonal portion of each block (possibly different for each block row) or PETSC_NULL
1784 
1785    Output Parameter:
1786 .  A - the symmetric matrix
1787 
1788    Options Database Keys:
1789 .   -mat_no_unroll - uses code that does not unroll the loops in the
1790                      block calculations (much slower)
1791 .    -mat_block_size - size of the blocks to use
1792 
1793    Level: intermediate
1794 
1795    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
1796    MatXXXXSetPreallocation() paradgm instead of this routine directly.
1797    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
1798 
1799    Notes:
1800    The number of rows and columns must be divisible by blocksize.
1801    This matrix type does not support complex Hermitian operation.
1802 
1803    Specify the preallocated storage with either nz or nnz (not both).
1804    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
1805    allocation.  For additional details, see the users manual chapter on
1806    matrices.
1807 
1808    If the nnz parameter is given then the nz parameter is ignored
1809 
1810 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ()
1811 @*/
1812 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqSBAIJ(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
1813 {
1814   PetscErrorCode ierr;
1815 
1816   PetscFunctionBegin;
1817   ierr = MatCreate(comm,A);CHKERRQ(ierr);
1818   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
1819   ierr = MatSetType(*A,MATSEQSBAIJ);CHKERRQ(ierr);
1820   ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(*A,bs,nz,(PetscInt*)nnz);CHKERRQ(ierr);
1821   PetscFunctionReturn(0);
1822 }
1823 
1824 #undef __FUNCT__
1825 #define __FUNCT__ "MatDuplicate_SeqSBAIJ"
1826 PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
1827 {
1828   Mat            C;
1829   Mat_SeqSBAIJ   *c,*a = (Mat_SeqSBAIJ*)A->data;
1830   PetscErrorCode ierr;
1831   PetscInt       i,mbs = a->mbs,nz = a->nz,bs2 =a->bs2;
1832 
1833   PetscFunctionBegin;
1834   if (a->i[mbs] != nz) SETERRQ(PETSC_ERR_PLIB,"Corrupt matrix");
1835 
1836   *B = 0;
1837   ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr);
1838   ierr = MatSetSizes(C,A->rmap->N,A->cmap->n,A->rmap->N,A->cmap->n);CHKERRQ(ierr);
1839   ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
1840   ierr = PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1841   c    = (Mat_SeqSBAIJ*)C->data;
1842 
1843   C->preallocated   = PETSC_TRUE;
1844   C->factor         = A->factor;
1845   c->row            = 0;
1846   c->icol           = 0;
1847   c->saved_values   = 0;
1848   c->keepzeroedrows = a->keepzeroedrows;
1849   C->assembled      = PETSC_TRUE;
1850 
1851   ierr = PetscMapCopy(((PetscObject)A)->comm,A->rmap,C->rmap);CHKERRQ(ierr);
1852   ierr = PetscMapCopy(((PetscObject)A)->comm,A->cmap,C->cmap);CHKERRQ(ierr);
1853   c->bs2  = a->bs2;
1854   c->mbs  = a->mbs;
1855   c->nbs  = a->nbs;
1856 
1857   ierr = PetscMalloc2((mbs+1),PetscInt,&c->imax,(mbs+1),PetscInt,&c->ilen);CHKERRQ(ierr);
1858   for (i=0; i<mbs; i++) {
1859     c->imax[i] = a->imax[i];
1860     c->ilen[i] = a->ilen[i];
1861   }
1862 
1863   /* allocate the matrix space */
1864   ierr = PetscMalloc3(bs2*nz,MatScalar,&c->a,nz,PetscInt,&c->j,mbs+1,PetscInt,&c->i);CHKERRQ(ierr);
1865   c->singlemalloc = PETSC_TRUE;
1866   ierr = PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr);
1867   ierr = PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt) + nz*(bs2*sizeof(MatScalar) + sizeof(PetscInt)));CHKERRQ(ierr);
1868   if (mbs > 0) {
1869     ierr = PetscMemcpy(c->j,a->j,nz*sizeof(PetscInt));CHKERRQ(ierr);
1870     if (cpvalues == MAT_COPY_VALUES) {
1871       ierr = PetscMemcpy(c->a,a->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr);
1872     } else {
1873       ierr = PetscMemzero(c->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr);
1874     }
1875   }
1876 
1877   c->roworiented = a->roworiented;
1878   c->nonew       = a->nonew;
1879 
1880   if (a->diag) {
1881     ierr = PetscMalloc((mbs+1)*sizeof(PetscInt),&c->diag);CHKERRQ(ierr);
1882     ierr = PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr);
1883     for (i=0; i<mbs; i++) {
1884       c->diag[i] = a->diag[i];
1885     }
1886   } else c->diag  = 0;
1887   c->nz           = a->nz;
1888   c->maxnz        = a->maxnz;
1889   c->solve_work   = 0;
1890   c->mult_work    = 0;
1891   c->free_a       = PETSC_TRUE;
1892   c->free_ij      = PETSC_TRUE;
1893   *B = C;
1894   ierr = PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
1895   PetscFunctionReturn(0);
1896 }
1897 
1898 #undef __FUNCT__
1899 #define __FUNCT__ "MatLoad_SeqSBAIJ"
1900 PetscErrorCode MatLoad_SeqSBAIJ(PetscViewer viewer, const MatType type,Mat *A)
1901 {
1902   Mat_SeqSBAIJ   *a;
1903   Mat            B;
1904   PetscErrorCode ierr;
1905   int            fd;
1906   PetscMPIInt    size;
1907   PetscInt       i,nz,header[4],*rowlengths=0,M,N,bs=1;
1908   PetscInt       *mask,mbs,*jj,j,rowcount,nzcount,k,*s_browlengths,maskcount;
1909   PetscInt       kmax,jcount,block,idx,point,nzcountb,extra_rows;
1910   PetscInt       *masked,nmask,tmp,bs2,ishift;
1911   PetscScalar    *aa;
1912   MPI_Comm       comm = ((PetscObject)viewer)->comm;
1913 
1914   PetscFunctionBegin;
1915   ierr = PetscOptionsGetInt(PETSC_NULL,"-matload_block_size",&bs,PETSC_NULL);CHKERRQ(ierr);
1916   bs2  = bs*bs;
1917 
1918   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1919   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"view must have one processor");
1920   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
1921   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
1922   if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not Mat object");
1923   M = header[1]; N = header[2]; nz = header[3];
1924 
1925   if (header[3] < 0) {
1926     SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format, cannot load as SeqSBAIJ");
1927   }
1928 
1929   if (M != N) SETERRQ(PETSC_ERR_SUP,"Can only do square matrices");
1930 
1931   /*
1932      This code adds extra rows to make sure the number of rows is
1933     divisible by the blocksize
1934   */
1935   mbs        = M/bs;
1936   extra_rows = bs - M + bs*(mbs);
1937   if (extra_rows == bs) extra_rows = 0;
1938   else                  mbs++;
1939   if (extra_rows) {
1940     ierr = PetscInfo(viewer,"Padding loaded matrix to match blocksize\n");CHKERRQ(ierr);
1941   }
1942 
1943   /* read in row lengths */
1944   ierr = PetscMalloc((M+extra_rows)*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
1945   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
1946   for (i=0; i<extra_rows; i++) rowlengths[M+i] = 1;
1947 
1948   /* read in column indices */
1949   ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscInt),&jj);CHKERRQ(ierr);
1950   ierr = PetscBinaryRead(fd,jj,nz,PETSC_INT);CHKERRQ(ierr);
1951   for (i=0; i<extra_rows; i++) jj[nz+i] = M+i;
1952 
1953   /* loop over row lengths determining block row lengths */
1954   ierr     = PetscMalloc(mbs*sizeof(PetscInt),&s_browlengths);CHKERRQ(ierr);
1955   ierr     = PetscMemzero(s_browlengths,mbs*sizeof(PetscInt));CHKERRQ(ierr);
1956   ierr     = PetscMalloc(2*mbs*sizeof(PetscInt),&mask);CHKERRQ(ierr);
1957   ierr     = PetscMemzero(mask,mbs*sizeof(PetscInt));CHKERRQ(ierr);
1958   masked   = mask + mbs;
1959   rowcount = 0; nzcount = 0;
1960   for (i=0; i<mbs; i++) {
1961     nmask = 0;
1962     for (j=0; j<bs; j++) {
1963       kmax = rowlengths[rowcount];
1964       for (k=0; k<kmax; k++) {
1965         tmp = jj[nzcount++]/bs;   /* block col. index */
1966         if (!mask[tmp] && tmp >= i) {masked[nmask++] = tmp; mask[tmp] = 1;}
1967       }
1968       rowcount++;
1969     }
1970     s_browlengths[i] += nmask;
1971 
1972     /* zero out the mask elements we set */
1973     for (j=0; j<nmask; j++) mask[masked[j]] = 0;
1974   }
1975 
1976   /* create our matrix */
1977   ierr = MatCreate(comm,&B);CHKERRQ(ierr);
1978   ierr = MatSetSizes(B,M+extra_rows,N+extra_rows,M+extra_rows,N+extra_rows);CHKERRQ(ierr);
1979   ierr = MatSetType(B,type);CHKERRQ(ierr);
1980   ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(B,bs,0,s_browlengths);CHKERRQ(ierr);
1981   a = (Mat_SeqSBAIJ*)B->data;
1982 
1983   /* set matrix "i" values */
1984   a->i[0] = 0;
1985   for (i=1; i<= mbs; i++) {
1986     a->i[i]      = a->i[i-1] + s_browlengths[i-1];
1987     a->ilen[i-1] = s_browlengths[i-1];
1988   }
1989   a->nz = a->i[mbs];
1990 
1991   /* read in nonzero values */
1992   ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscScalar),&aa);CHKERRQ(ierr);
1993   ierr = PetscBinaryRead(fd,aa,nz,PETSC_SCALAR);CHKERRQ(ierr);
1994   for (i=0; i<extra_rows; i++) aa[nz+i] = 1.0;
1995 
1996   /* set "a" and "j" values into matrix */
1997   nzcount = 0; jcount = 0;
1998   for (i=0; i<mbs; i++) {
1999     nzcountb = nzcount;
2000     nmask    = 0;
2001     for (j=0; j<bs; j++) {
2002       kmax = rowlengths[i*bs+j];
2003       for (k=0; k<kmax; k++) {
2004         tmp = jj[nzcount++]/bs; /* block col. index */
2005         if (!mask[tmp] && tmp >= i) { masked[nmask++] = tmp; mask[tmp] = 1;}
2006       }
2007     }
2008     /* sort the masked values */
2009     ierr = PetscSortInt(nmask,masked);CHKERRQ(ierr);
2010 
2011     /* set "j" values into matrix */
2012     maskcount = 1;
2013     for (j=0; j<nmask; j++) {
2014       a->j[jcount++]  = masked[j];
2015       mask[masked[j]] = maskcount++;
2016     }
2017 
2018     /* set "a" values into matrix */
2019     ishift = bs2*a->i[i];
2020     for (j=0; j<bs; j++) {
2021       kmax = rowlengths[i*bs+j];
2022       for (k=0; k<kmax; k++) {
2023         tmp       = jj[nzcountb]/bs ; /* block col. index */
2024         if (tmp >= i){
2025           block     = mask[tmp] - 1;
2026           point     = jj[nzcountb] - bs*tmp;
2027           idx       = ishift + bs2*block + j + bs*point;
2028           a->a[idx] = aa[nzcountb];
2029         }
2030         nzcountb++;
2031       }
2032     }
2033     /* zero out the mask elements we set */
2034     for (j=0; j<nmask; j++) mask[masked[j]] = 0;
2035   }
2036   if (jcount != a->nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Bad binary matrix");
2037 
2038   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
2039   ierr = PetscFree(s_browlengths);CHKERRQ(ierr);
2040   ierr = PetscFree(aa);CHKERRQ(ierr);
2041   ierr = PetscFree(jj);CHKERRQ(ierr);
2042   ierr = PetscFree(mask);CHKERRQ(ierr);
2043 
2044   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2045   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2046   ierr = MatView_Private(B);CHKERRQ(ierr);
2047   *A = B;
2048   PetscFunctionReturn(0);
2049 }
2050 
2051 #undef __FUNCT__
2052 #define __FUNCT__ "MatRelax_SeqSBAIJ"
2053 PetscErrorCode MatRelax_SeqSBAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
2054 {
2055   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
2056   MatScalar      *aa=a->a,*v,*v1;
2057   PetscScalar    *x,*b,*t,sum,d;
2058   PetscErrorCode ierr;
2059   PetscInt       m=a->mbs,bs=A->rmap->bs,*ai=a->i,*aj=a->j;
2060   PetscInt       nz,nz1,*vj,*vj1,i;
2061 
2062   PetscFunctionBegin;
2063   if (flag & SOR_EISENSTAT) SETERRQ(PETSC_ERR_SUP,"No support yet for Eisenstat");
2064 
2065   its = its*lits;
2066   if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits);
2067 
2068   if (bs > 1)
2069     SETERRQ(PETSC_ERR_SUP,"SSOR for block size > 1 is not yet implemented");
2070 
2071   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
2072   if (xx != bb) {
2073     ierr = VecGetArray(bb,&b);CHKERRQ(ierr);
2074   } else {
2075     b = x;
2076   }
2077 
2078   if (!a->relax_work) {
2079     ierr = PetscMalloc(m*sizeof(PetscScalar),&a->relax_work);CHKERRQ(ierr);
2080   }
2081   t = a->relax_work;
2082 
2083   if (flag & SOR_ZERO_INITIAL_GUESS) {
2084     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
2085       ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr);
2086 
2087       for (i=0; i<m; i++){
2088         d  = *(aa + ai[i]);  /* diag[i] */
2089         v  = aa + ai[i] + 1;
2090         vj = aj + ai[i] + 1;
2091         nz = ai[i+1] - ai[i] - 1;
2092         ierr = PetscLogFlops(2.0*nz-1);CHKERRQ(ierr);
2093         x[i] = omega*t[i]/d;
2094         while (nz--) t[*vj++] -= x[i]*(*v++); /* update rhs */
2095       }
2096     }
2097 
2098     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
2099       if (!(flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP)){
2100         t = b;
2101       }
2102 
2103       for (i=m-1; i>=0; i--){
2104         d  = *(aa + ai[i]);
2105         v  = aa + ai[i] + 1;
2106         vj = aj + ai[i] + 1;
2107         nz = ai[i+1] - ai[i] - 1;
2108         ierr = PetscLogFlops(2.0*nz-1);CHKERRQ(ierr);
2109         sum = t[i];
2110         while (nz--) sum -= x[*vj++]*(*v++);
2111         x[i] =   (1-omega)*x[i] + omega*sum/d;
2112       }
2113       t = a->relax_work;
2114     }
2115     its--;
2116   }
2117 
2118   while (its--) {
2119     /*
2120        forward sweep:
2121        for i=0,...,m-1:
2122          sum[i] = (b[i] - U(i,:)x )/d[i];
2123          x[i]   = (1-omega)x[i] + omega*sum[i];
2124          b      = b - x[i]*U^T(i,:);
2125 
2126     */
2127     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
2128       ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr);
2129 
2130       for (i=0; i<m; i++){
2131         d  = *(aa + ai[i]);  /* diag[i] */
2132         v  = aa + ai[i] + 1; v1=v;
2133         vj = aj + ai[i] + 1; vj1=vj;
2134         nz = ai[i+1] - ai[i] - 1; nz1=nz;
2135         sum = t[i];
2136         ierr = PetscLogFlops(4.0*nz-2);CHKERRQ(ierr);
2137         while (nz1--) sum -= (*v1++)*x[*vj1++];
2138         x[i] = (1-omega)*x[i] + omega*sum/d;
2139         while (nz--) t[*vj++] -= x[i]*(*v++);
2140       }
2141     }
2142 
2143     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
2144       /*
2145        backward sweep:
2146        b = b - x[i]*U^T(i,:), i=0,...,n-2
2147        for i=m-1,...,0:
2148          sum[i] = (b[i] - U(i,:)x )/d[i];
2149          x[i]   = (1-omega)x[i] + omega*sum[i];
2150       */
2151       /* if there was a forward sweep done above then I thing the next two for loops are not needed */
2152       ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr);
2153 
2154       for (i=0; i<m-1; i++){  /* update rhs */
2155         v  = aa + ai[i] + 1;
2156         vj = aj + ai[i] + 1;
2157         nz = ai[i+1] - ai[i] - 1;
2158         ierr = PetscLogFlops(2.0*nz-1);CHKERRQ(ierr);
2159         while (nz--) t[*vj++] -= x[i]*(*v++);
2160       }
2161       for (i=m-1; i>=0; i--){
2162         d  = *(aa + ai[i]);
2163         v  = aa + ai[i] + 1;
2164         vj = aj + ai[i] + 1;
2165         nz = ai[i+1] - ai[i] - 1;
2166         ierr = PetscLogFlops(2.0*nz-1);CHKERRQ(ierr);
2167         sum = t[i];
2168         while (nz--) sum -= x[*vj++]*(*v++);
2169         x[i] =   (1-omega)*x[i] + omega*sum/d;
2170       }
2171     }
2172   }
2173 
2174   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
2175   if (bb != xx) {
2176     ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr);
2177   }
2178   PetscFunctionReturn(0);
2179 }
2180 
2181 #undef __FUNCT__
2182 #define __FUNCT__ "MatCreateSeqSBAIJWithArrays"
2183 /*@
2184      MatCreateSeqSBAIJWithArrays - Creates an sequential SBAIJ matrix using matrix elements
2185               (upper triangular entries in CSR format) provided by the user.
2186 
2187      Collective on MPI_Comm
2188 
2189    Input Parameters:
2190 +  comm - must be an MPI communicator of size 1
2191 .  bs - size of block
2192 .  m - number of rows
2193 .  n - number of columns
2194 .  i - row indices
2195 .  j - column indices
2196 -  a - matrix values
2197 
2198    Output Parameter:
2199 .  mat - the matrix
2200 
2201    Level: intermediate
2202 
2203    Notes:
2204        The i, j, and a arrays are not copied by this routine, the user must free these arrays
2205     once the matrix is destroyed
2206 
2207        You cannot set new nonzero locations into this matrix, that will generate an error.
2208 
2209        The i and j indices are 0 based
2210 
2211 .seealso: MatCreate(), MatCreateMPISBAIJ(), MatCreateSeqSBAIJ()
2212 
2213 @*/
2214 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqSBAIJWithArrays(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat)
2215 {
2216   PetscErrorCode ierr;
2217   PetscInt       ii;
2218   Mat_SeqSBAIJ   *sbaij;
2219 
2220   PetscFunctionBegin;
2221   if (bs != 1) SETERRQ1(PETSC_ERR_SUP,"block size %D > 1 is not supported yet",bs);
2222   if (i[0]) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
2223 
2224   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
2225   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
2226   ierr = MatSetType(*mat,MATSEQSBAIJ);CHKERRQ(ierr);
2227   ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(*mat,bs,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr);
2228   sbaij = (Mat_SeqSBAIJ*)(*mat)->data;
2229   ierr = PetscMalloc2(m,PetscInt,&sbaij->imax,m,PetscInt,&sbaij->ilen);CHKERRQ(ierr);
2230 
2231   sbaij->i = i;
2232   sbaij->j = j;
2233   sbaij->a = a;
2234   sbaij->singlemalloc = PETSC_FALSE;
2235   sbaij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2236   sbaij->free_a       = PETSC_FALSE;
2237   sbaij->free_ij      = PETSC_FALSE;
2238 
2239   for (ii=0; ii<m; ii++) {
2240     sbaij->ilen[ii] = sbaij->imax[ii] = i[ii+1] - i[ii];
2241 #if defined(PETSC_USE_DEBUG)
2242     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]);
2243 #endif
2244   }
2245 #if defined(PETSC_USE_DEBUG)
2246   for (ii=0; ii<sbaij->i[m]; ii++) {
2247     if (j[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]);
2248     if (j[ii] > n - 1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]);
2249   }
2250 #endif
2251 
2252   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2253   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2254   PetscFunctionReturn(0);
2255 }
2256 
2257 
2258 
2259 
2260 
2261