xref: /petsc/src/mat/impls/baij/seq/baij.c (revision 2a1b7f2a44167898ff2a15c48e0d9ef0cd15bbf0)
1bba1ac68SSatish Balay /*$Id: baij.c,v 1.245 2001/08/07 03:02:55 balay Exp bsmith $*/
22593348eSBarry Smith 
32593348eSBarry Smith /*
4b6490206SBarry Smith     Defines the basic matrix operations for the BAIJ (compressed row)
52593348eSBarry Smith   matrix storage format.
62593348eSBarry Smith */
770f55243SBarry Smith #include "src/mat/impls/baij/seq/baij.h"
81a6a6d98SBarry Smith #include "src/vec/vecimpl.h"
91a6a6d98SBarry Smith #include "src/inline/spops.h"
10325e03aeSBarry Smith #include "petscsys.h"                     /*I "petscmat.h" I*/
113b547af2SSatish Balay 
1295d5f7c2SBarry Smith /*  UGLY, ugly, ugly
1387828ca2SBarry Smith    When MatScalar == PetscScalar the function MatSetValuesBlocked_SeqBAIJ_MatScalar() does
143477af42SKris Buschelman    not exist. Otherwise ..._MatScalar() takes matrix dlements in single precision and
1595d5f7c2SBarry Smith    inserts them into the single precision data structure. The function MatSetValuesBlocked_SeqBAIJ()
1695d5f7c2SBarry Smith    converts the entries into single precision and then calls ..._MatScalar() to put them
1795d5f7c2SBarry Smith    into the single precision data structures.
1895d5f7c2SBarry Smith */
1995d5f7c2SBarry Smith #if defined(PETSC_USE_MAT_SINGLE)
20ca44d042SBarry Smith EXTERN int MatSetValuesBlocked_SeqBAIJ_MatScalar(Mat,int,int*,int,int*,MatScalar*,InsertMode);
2195d5f7c2SBarry Smith #else
2295d5f7c2SBarry Smith #define MatSetValuesBlocked_SeqBAIJ_MatScalar MatSetValuesBlocked_SeqBAIJ
2395d5f7c2SBarry Smith #endif
2404929863SHong Zhang #if defined(PETSC_HAVE_DSCPACK)
2504929863SHong Zhang EXTERN int MatUseDSCPACK_MPIBAIJ(Mat);
2604929863SHong Zhang #endif
2795d5f7c2SBarry Smith 
282d61bbb3SSatish Balay #define CHUNKSIZE  10
29de6a44a3SBarry Smith 
30be5855fcSBarry Smith /*
31be5855fcSBarry Smith      Checks for missing diagonals
32be5855fcSBarry Smith */
334a2ae208SSatish Balay #undef __FUNCT__
344a2ae208SSatish Balay #define __FUNCT__ "MatMissingDiagonal_SeqBAIJ"
35c4992f7dSBarry Smith int MatMissingDiagonal_SeqBAIJ(Mat A)
36be5855fcSBarry Smith {
37be5855fcSBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
38883fce79SBarry Smith   int         *diag,*jj = a->j,i,ierr;
39be5855fcSBarry Smith 
40be5855fcSBarry Smith   PetscFunctionBegin;
41c4992f7dSBarry Smith   ierr = MatMarkDiagonal_SeqBAIJ(A);CHKERRQ(ierr);
42883fce79SBarry Smith   diag = a->diag;
430e8e8aceSBarry Smith   for (i=0; i<a->mbs; i++) {
44be5855fcSBarry Smith     if (jj[diag[i]] != i) {
4529bbc08cSBarry Smith       SETERRQ1(1,"Matrix is missing diagonal number %d",i);
46be5855fcSBarry Smith     }
47be5855fcSBarry Smith   }
48be5855fcSBarry Smith   PetscFunctionReturn(0);
49be5855fcSBarry Smith }
50be5855fcSBarry Smith 
514a2ae208SSatish Balay #undef __FUNCT__
524a2ae208SSatish Balay #define __FUNCT__ "MatMarkDiagonal_SeqBAIJ"
53c4992f7dSBarry Smith int MatMarkDiagonal_SeqBAIJ(Mat A)
54de6a44a3SBarry Smith {
55de6a44a3SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
5682502324SSatish Balay   int         i,j,*diag,m = a->mbs,ierr;
57de6a44a3SBarry Smith 
583a40ed3dSBarry Smith   PetscFunctionBegin;
59883fce79SBarry Smith   if (a->diag) PetscFunctionReturn(0);
60883fce79SBarry Smith 
61b0a32e0cSBarry Smith   ierr = PetscMalloc((m+1)*sizeof(int),&diag);CHKERRQ(ierr);
62b0a32e0cSBarry Smith   PetscLogObjectMemory(A,(m+1)*sizeof(int));
637fc0212eSBarry Smith   for (i=0; i<m; i++) {
64ecc615b2SBarry Smith     diag[i] = a->i[i+1];
65de6a44a3SBarry Smith     for (j=a->i[i]; j<a->i[i+1]; j++) {
66de6a44a3SBarry Smith       if (a->j[j] == i) {
67de6a44a3SBarry Smith         diag[i] = j;
68de6a44a3SBarry Smith         break;
69de6a44a3SBarry Smith       }
70de6a44a3SBarry Smith     }
71de6a44a3SBarry Smith   }
72de6a44a3SBarry Smith   a->diag = diag;
733a40ed3dSBarry Smith   PetscFunctionReturn(0);
74de6a44a3SBarry Smith }
752593348eSBarry Smith 
762593348eSBarry Smith 
77ca44d042SBarry Smith EXTERN int MatToSymmetricIJ_SeqAIJ(int,int*,int*,int,int,int**,int**);
783b2fbd54SBarry Smith 
794a2ae208SSatish Balay #undef __FUNCT__
804a2ae208SSatish Balay #define __FUNCT__ "MatGetRowIJ_SeqBAIJ"
810e6d2581SBarry Smith static int MatGetRowIJ_SeqBAIJ(Mat A,int oshift,PetscTruth symmetric,int *nn,int **ia,int **ja,PetscTruth *done)
823b2fbd54SBarry Smith {
833b2fbd54SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
843b2fbd54SBarry Smith   int         ierr,n = a->mbs,i;
853b2fbd54SBarry Smith 
863a40ed3dSBarry Smith   PetscFunctionBegin;
873b2fbd54SBarry Smith   *nn = n;
883a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
893b2fbd54SBarry Smith   if (symmetric) {
903b2fbd54SBarry Smith     ierr = MatToSymmetricIJ_SeqAIJ(n,a->i,a->j,0,oshift,ia,ja);CHKERRQ(ierr);
913b2fbd54SBarry Smith   } else if (oshift == 1) {
923b2fbd54SBarry Smith     /* temporarily add 1 to i and j indices */
93435da068SBarry Smith     int nz = a->i[n];
943b2fbd54SBarry Smith     for (i=0; i<nz; i++) a->j[i]++;
953b2fbd54SBarry Smith     for (i=0; i<n+1; i++) a->i[i]++;
963b2fbd54SBarry Smith     *ia = a->i; *ja = a->j;
973b2fbd54SBarry Smith   } else {
983b2fbd54SBarry Smith     *ia = a->i; *ja = a->j;
993b2fbd54SBarry Smith   }
1003b2fbd54SBarry Smith 
1013a40ed3dSBarry Smith   PetscFunctionReturn(0);
1023b2fbd54SBarry Smith }
1033b2fbd54SBarry Smith 
1044a2ae208SSatish Balay #undef __FUNCT__
1054a2ae208SSatish Balay #define __FUNCT__ "MatRestoreRowIJ_SeqBAIJ"
106435da068SBarry Smith static int MatRestoreRowIJ_SeqBAIJ(Mat A,int oshift,PetscTruth symmetric,int *nn,int **ia,int **ja,PetscTruth *done)
1073b2fbd54SBarry Smith {
1083b2fbd54SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
109606d414cSSatish Balay   int         i,n = a->mbs,ierr;
1103b2fbd54SBarry Smith 
1113a40ed3dSBarry Smith   PetscFunctionBegin;
1123a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
1133b2fbd54SBarry Smith   if (symmetric) {
114606d414cSSatish Balay     ierr = PetscFree(*ia);CHKERRQ(ierr);
115606d414cSSatish Balay     ierr = PetscFree(*ja);CHKERRQ(ierr);
116af5da2bfSBarry Smith   } else if (oshift == 1) {
117435da068SBarry Smith     int nz = a->i[n]-1;
1183b2fbd54SBarry Smith     for (i=0; i<nz; i++) a->j[i]--;
1193b2fbd54SBarry Smith     for (i=0; i<n+1; i++) a->i[i]--;
1203b2fbd54SBarry Smith   }
1213a40ed3dSBarry Smith   PetscFunctionReturn(0);
1223b2fbd54SBarry Smith }
1233b2fbd54SBarry Smith 
1244a2ae208SSatish Balay #undef __FUNCT__
1254a2ae208SSatish Balay #define __FUNCT__ "MatGetBlockSize_SeqBAIJ"
1262d61bbb3SSatish Balay int MatGetBlockSize_SeqBAIJ(Mat mat,int *bs)
1272d61bbb3SSatish Balay {
1282d61bbb3SSatish Balay   Mat_SeqBAIJ *baij = (Mat_SeqBAIJ*)mat->data;
1292d61bbb3SSatish Balay 
1302d61bbb3SSatish Balay   PetscFunctionBegin;
1312d61bbb3SSatish Balay   *bs = baij->bs;
1322d61bbb3SSatish Balay   PetscFunctionReturn(0);
1332d61bbb3SSatish Balay }
1342d61bbb3SSatish Balay 
1352d61bbb3SSatish Balay 
1364a2ae208SSatish Balay #undef __FUNCT__
1374a2ae208SSatish Balay #define __FUNCT__ "MatDestroy_SeqBAIJ"
138e1311b90SBarry Smith int MatDestroy_SeqBAIJ(Mat A)
1392d61bbb3SSatish Balay {
1402d61bbb3SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
141e51c0b9cSSatish Balay   int         ierr;
1422d61bbb3SSatish Balay 
143433994e6SBarry Smith   PetscFunctionBegin;
144aa482453SBarry Smith #if defined(PETSC_USE_LOG)
145b0a32e0cSBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%d, Cols=%d, NZ=%d",A->m,A->n,a->nz);
1462d61bbb3SSatish Balay #endif
147606d414cSSatish Balay   ierr = PetscFree(a->a);CHKERRQ(ierr);
148606d414cSSatish Balay   if (!a->singlemalloc) {
149606d414cSSatish Balay     ierr = PetscFree(a->i);CHKERRQ(ierr);
150606d414cSSatish Balay     ierr = PetscFree(a->j);CHKERRQ(ierr);
151606d414cSSatish Balay   }
152c38d4ed2SBarry Smith   if (a->row) {
153c38d4ed2SBarry Smith     ierr = ISDestroy(a->row);CHKERRQ(ierr);
154c38d4ed2SBarry Smith   }
155c38d4ed2SBarry Smith   if (a->col) {
156c38d4ed2SBarry Smith     ierr = ISDestroy(a->col);CHKERRQ(ierr);
157c38d4ed2SBarry Smith   }
158606d414cSSatish Balay   if (a->diag) {ierr = PetscFree(a->diag);CHKERRQ(ierr);}
159606d414cSSatish Balay   if (a->ilen) {ierr = PetscFree(a->ilen);CHKERRQ(ierr);}
160606d414cSSatish Balay   if (a->imax) {ierr = PetscFree(a->imax);CHKERRQ(ierr);}
161606d414cSSatish Balay   if (a->solve_work) {ierr = PetscFree(a->solve_work);CHKERRQ(ierr);}
162606d414cSSatish Balay   if (a->mult_work) {ierr = PetscFree(a->mult_work);CHKERRQ(ierr);}
163e51c0b9cSSatish Balay   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);}
164606d414cSSatish Balay   if (a->saved_values) {ierr = PetscFree(a->saved_values);CHKERRQ(ierr);}
165563b5814SBarry Smith #if defined(PETSC_USE_MAT_SINGLE)
166563b5814SBarry Smith   if (a->setvaluescopy) {ierr = PetscFree(a->setvaluescopy);CHKERRQ(ierr);}
167563b5814SBarry Smith #endif
168606d414cSSatish Balay   ierr = PetscFree(a);CHKERRQ(ierr);
1692d61bbb3SSatish Balay   PetscFunctionReturn(0);
1702d61bbb3SSatish Balay }
1712d61bbb3SSatish Balay 
1724a2ae208SSatish Balay #undef __FUNCT__
1734a2ae208SSatish Balay #define __FUNCT__ "MatSetOption_SeqBAIJ"
1742d61bbb3SSatish Balay int MatSetOption_SeqBAIJ(Mat A,MatOption op)
1752d61bbb3SSatish Balay {
1762d61bbb3SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
1772d61bbb3SSatish Balay 
1782d61bbb3SSatish Balay   PetscFunctionBegin;
179aa275fccSKris Buschelman   switch (op) {
180aa275fccSKris Buschelman   case MAT_ROW_ORIENTED:
181aa275fccSKris Buschelman     a->roworiented    = PETSC_TRUE;
182aa275fccSKris Buschelman     break;
183aa275fccSKris Buschelman   case MAT_COLUMN_ORIENTED:
184aa275fccSKris Buschelman     a->roworiented    = PETSC_FALSE;
185aa275fccSKris Buschelman     break;
186aa275fccSKris Buschelman   case MAT_COLUMNS_SORTED:
187aa275fccSKris Buschelman     a->sorted         = PETSC_TRUE;
188aa275fccSKris Buschelman     break;
189aa275fccSKris Buschelman   case MAT_COLUMNS_UNSORTED:
190aa275fccSKris Buschelman     a->sorted         = PETSC_FALSE;
191aa275fccSKris Buschelman     break;
192aa275fccSKris Buschelman   case MAT_KEEP_ZEROED_ROWS:
193aa275fccSKris Buschelman     a->keepzeroedrows = PETSC_TRUE;
194aa275fccSKris Buschelman     break;
195aa275fccSKris Buschelman   case MAT_NO_NEW_NONZERO_LOCATIONS:
196aa275fccSKris Buschelman     a->nonew          = 1;
197aa275fccSKris Buschelman     break;
198aa275fccSKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
199aa275fccSKris Buschelman     a->nonew          = -1;
200aa275fccSKris Buschelman     break;
201aa275fccSKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
202aa275fccSKris Buschelman     a->nonew          = -2;
203aa275fccSKris Buschelman     break;
204aa275fccSKris Buschelman   case MAT_YES_NEW_NONZERO_LOCATIONS:
205aa275fccSKris Buschelman     a->nonew          = 0;
206aa275fccSKris Buschelman     break;
207aa275fccSKris Buschelman   case MAT_ROWS_SORTED:
208aa275fccSKris Buschelman   case MAT_ROWS_UNSORTED:
209aa275fccSKris Buschelman   case MAT_YES_NEW_DIAGONALS:
210aa275fccSKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
211aa275fccSKris Buschelman   case MAT_USE_HASH_TABLE:
212b0a32e0cSBarry Smith     PetscLogInfo(A,"MatSetOption_SeqBAIJ:Option ignored\n");
213aa275fccSKris Buschelman     break;
214aa275fccSKris Buschelman   case MAT_NO_NEW_DIAGONALS:
21529bbc08cSBarry Smith     SETERRQ(PETSC_ERR_SUP,"MAT_NO_NEW_DIAGONALS");
216bd648c37SKris Buschelman   case MAT_USE_SINGLE_PRECISION_SOLVES:
217bd648c37SKris Buschelman     if (a->bs==4) {
21894ee7fc8SKris Buschelman       PetscTruth sse_enabled_local,sse_enabled_global;
219bd648c37SKris Buschelman       int        ierr;
22094ee7fc8SKris Buschelman 
22194ee7fc8SKris Buschelman       sse_enabled_local  = PETSC_FALSE;
22294ee7fc8SKris Buschelman       sse_enabled_global = PETSC_FALSE;
22394ee7fc8SKris Buschelman 
22494ee7fc8SKris Buschelman       ierr = PetscSSEIsEnabled(A->comm,&sse_enabled_local,&sse_enabled_global);CHKERRQ(ierr);
225e64df4b9SKris Buschelman #if defined(PETSC_HAVE_SSE)
22694ee7fc8SKris Buschelman       if (sse_enabled_local) {
22754138f6bSKris Buschelman           a->single_precision_solves = PETSC_TRUE;
22854138f6bSKris Buschelman           A->ops->solve              = MatSolve_SeqBAIJ_Update;
22954138f6bSKris Buschelman           A->ops->solvetranspose     = MatSolveTranspose_SeqBAIJ_Update;
230cf242676SKris Buschelman           PetscLogInfo(A,"MatSetOption_SeqBAIJ:Option MAT_USE_SINGLE_PRECISION_SOLVES set\n");
23154138f6bSKris Buschelman           break;
23294ee7fc8SKris Buschelman       } else {
23394ee7fc8SKris Buschelman         PetscLogInfo(A,"MatSetOption_SeqBAIJ:Option MAT_USE_SINGLE_PRECISION_SOLVES ignored\n");
2348661488fSKris Buschelman       }
235e64df4b9SKris Buschelman #else
236bd648c37SKris Buschelman       PetscLogInfo(A,"MatSetOption_SeqBAIJ:Option MAT_USE_SINGLE_PRECISION_SOLVES ignored\n");
237e64df4b9SKris Buschelman #endif
238bd648c37SKris Buschelman     }
239bd648c37SKris Buschelman     break;
240aa275fccSKris Buschelman   default:
24129bbc08cSBarry Smith     SETERRQ(PETSC_ERR_SUP,"unknown option");
2422d61bbb3SSatish Balay   }
2432d61bbb3SSatish Balay   PetscFunctionReturn(0);
2442d61bbb3SSatish Balay }
2452d61bbb3SSatish Balay 
2464a2ae208SSatish Balay #undef __FUNCT__
2474a2ae208SSatish Balay #define __FUNCT__ "MatGetRow_SeqBAIJ"
24887828ca2SBarry Smith int MatGetRow_SeqBAIJ(Mat A,int row,int *nz,int **idx,PetscScalar **v)
2492d61bbb3SSatish Balay {
2502d61bbb3SSatish Balay   Mat_SeqBAIJ  *a = (Mat_SeqBAIJ*)A->data;
25182502324SSatish Balay   int          itmp,i,j,k,M,*ai,*aj,bs,bn,bp,*idx_i,bs2,ierr;
2523f1db9ecSBarry Smith   MatScalar    *aa,*aa_i;
25387828ca2SBarry Smith   PetscScalar  *v_i;
2542d61bbb3SSatish Balay 
2552d61bbb3SSatish Balay   PetscFunctionBegin;
2562d61bbb3SSatish Balay   bs  = a->bs;
2572d61bbb3SSatish Balay   ai  = a->i;
2582d61bbb3SSatish Balay   aj  = a->j;
2592d61bbb3SSatish Balay   aa  = a->a;
2602d61bbb3SSatish Balay   bs2 = a->bs2;
2612d61bbb3SSatish Balay 
262273d9f13SBarry Smith   if (row < 0 || row >= A->m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Row out of range");
2632d61bbb3SSatish Balay 
2642d61bbb3SSatish Balay   bn  = row/bs;   /* Block number */
2652d61bbb3SSatish Balay   bp  = row % bs; /* Block Position */
2662d61bbb3SSatish Balay   M   = ai[bn+1] - ai[bn];
2672d61bbb3SSatish Balay   *nz = bs*M;
2682d61bbb3SSatish Balay 
2692d61bbb3SSatish Balay   if (v) {
2702d61bbb3SSatish Balay     *v = 0;
2712d61bbb3SSatish Balay     if (*nz) {
27287828ca2SBarry Smith       ierr = PetscMalloc((*nz)*sizeof(PetscScalar),v);CHKERRQ(ierr);
2732d61bbb3SSatish Balay       for (i=0; i<M; i++) { /* for each block in the block row */
2742d61bbb3SSatish Balay         v_i  = *v + i*bs;
2752d61bbb3SSatish Balay         aa_i = aa + bs2*(ai[bn] + i);
2762d61bbb3SSatish Balay         for (j=bp,k=0; j<bs2; j+=bs,k++) {v_i[k] = aa_i[j];}
2772d61bbb3SSatish Balay       }
2782d61bbb3SSatish Balay     }
2792d61bbb3SSatish Balay   }
2802d61bbb3SSatish Balay 
2812d61bbb3SSatish Balay   if (idx) {
2822d61bbb3SSatish Balay     *idx = 0;
2832d61bbb3SSatish Balay     if (*nz) {
284b0a32e0cSBarry Smith       ierr = PetscMalloc((*nz)*sizeof(int),idx);CHKERRQ(ierr);
2852d61bbb3SSatish Balay       for (i=0; i<M; i++) { /* for each block in the block row */
2862d61bbb3SSatish Balay         idx_i = *idx + i*bs;
2872d61bbb3SSatish Balay         itmp  = bs*aj[ai[bn] + i];
2882d61bbb3SSatish Balay         for (j=0; j<bs; j++) {idx_i[j] = itmp++;}
2892d61bbb3SSatish Balay       }
2902d61bbb3SSatish Balay     }
2912d61bbb3SSatish Balay   }
2922d61bbb3SSatish Balay   PetscFunctionReturn(0);
2932d61bbb3SSatish Balay }
2942d61bbb3SSatish Balay 
2954a2ae208SSatish Balay #undef __FUNCT__
2964a2ae208SSatish Balay #define __FUNCT__ "MatRestoreRow_SeqBAIJ"
29787828ca2SBarry Smith int MatRestoreRow_SeqBAIJ(Mat A,int row,int *nz,int **idx,PetscScalar **v)
2982d61bbb3SSatish Balay {
299606d414cSSatish Balay   int ierr;
300606d414cSSatish Balay 
3012d61bbb3SSatish Balay   PetscFunctionBegin;
302606d414cSSatish Balay   if (idx) {if (*idx) {ierr = PetscFree(*idx);CHKERRQ(ierr);}}
303606d414cSSatish Balay   if (v)   {if (*v)   {ierr = PetscFree(*v);CHKERRQ(ierr);}}
3042d61bbb3SSatish Balay   PetscFunctionReturn(0);
3052d61bbb3SSatish Balay }
3062d61bbb3SSatish Balay 
3074a2ae208SSatish Balay #undef __FUNCT__
3084a2ae208SSatish Balay #define __FUNCT__ "MatTranspose_SeqBAIJ"
3092d61bbb3SSatish Balay int MatTranspose_SeqBAIJ(Mat A,Mat *B)
3102d61bbb3SSatish Balay {
3112d61bbb3SSatish Balay   Mat_SeqBAIJ *a=(Mat_SeqBAIJ *)A->data;
3122d61bbb3SSatish Balay   Mat         C;
3132d61bbb3SSatish Balay   int         i,j,k,ierr,*aj=a->j,*ai=a->i,bs=a->bs,mbs=a->mbs,nbs=a->nbs,len,*col;
314273d9f13SBarry Smith   int         *rows,*cols,bs2=a->bs2;
31587828ca2SBarry Smith   PetscScalar *array;
3162d61bbb3SSatish Balay 
3172d61bbb3SSatish Balay   PetscFunctionBegin;
31829bbc08cSBarry Smith   if (!B && mbs!=nbs) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Square matrix only for in-place");
319b0a32e0cSBarry Smith   ierr = PetscMalloc((1+nbs)*sizeof(int),&col);CHKERRQ(ierr);
320549d3d68SSatish Balay   ierr = PetscMemzero(col,(1+nbs)*sizeof(int));CHKERRQ(ierr);
3212d61bbb3SSatish Balay 
322375fe846SBarry Smith #if defined(PETSC_USE_MAT_SINGLE)
32387828ca2SBarry Smith   ierr = PetscMalloc(a->bs2*a->nz*sizeof(PetscScalar),&array);CHKERRQ(ierr);
32487828ca2SBarry Smith   for (i=0; i<a->bs2*a->nz; i++) array[i] = (PetscScalar)a->a[i];
325375fe846SBarry Smith #else
3263eda8832SBarry Smith   array = a->a;
327375fe846SBarry Smith #endif
328375fe846SBarry Smith 
3292d61bbb3SSatish Balay   for (i=0; i<ai[mbs]; i++) col[aj[i]] += 1;
330273d9f13SBarry Smith   ierr = MatCreateSeqBAIJ(A->comm,bs,A->n,A->m,PETSC_NULL,col,&C);CHKERRQ(ierr);
331606d414cSSatish Balay   ierr = PetscFree(col);CHKERRQ(ierr);
332b0a32e0cSBarry Smith   ierr = PetscMalloc(2*bs*sizeof(int),&rows);CHKERRQ(ierr);
3332d61bbb3SSatish Balay   cols = rows + bs;
3342d61bbb3SSatish Balay   for (i=0; i<mbs; i++) {
3352d61bbb3SSatish Balay     cols[0] = i*bs;
3362d61bbb3SSatish Balay     for (k=1; k<bs; k++) cols[k] = cols[k-1] + 1;
3372d61bbb3SSatish Balay     len = ai[i+1] - ai[i];
3382d61bbb3SSatish Balay     for (j=0; j<len; j++) {
3392d61bbb3SSatish Balay       rows[0] = (*aj++)*bs;
3402d61bbb3SSatish Balay       for (k=1; k<bs; k++) rows[k] = rows[k-1] + 1;
3412d61bbb3SSatish Balay       ierr = MatSetValues(C,bs,rows,bs,cols,array,INSERT_VALUES);CHKERRQ(ierr);
3422d61bbb3SSatish Balay       array += bs2;
3432d61bbb3SSatish Balay     }
3442d61bbb3SSatish Balay   }
345606d414cSSatish Balay   ierr = PetscFree(rows);CHKERRQ(ierr);
346375fe846SBarry Smith #if defined(PETSC_USE_MAT_SINGLE)
347375fe846SBarry Smith   ierr = PetscFree(array);
348375fe846SBarry Smith #endif
3492d61bbb3SSatish Balay 
3502d61bbb3SSatish Balay   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3512d61bbb3SSatish Balay   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3522d61bbb3SSatish Balay 
353c4992f7dSBarry Smith   if (B) {
3542d61bbb3SSatish Balay     *B = C;
3552d61bbb3SSatish Balay   } else {
356273d9f13SBarry Smith     ierr = MatHeaderCopy(A,C);CHKERRQ(ierr);
3572d61bbb3SSatish Balay   }
3582d61bbb3SSatish Balay   PetscFunctionReturn(0);
3592d61bbb3SSatish Balay }
3602d61bbb3SSatish Balay 
3614a2ae208SSatish Balay #undef __FUNCT__
3624a2ae208SSatish Balay #define __FUNCT__ "MatView_SeqBAIJ_Binary"
363b0a32e0cSBarry Smith static int MatView_SeqBAIJ_Binary(Mat A,PetscViewer viewer)
3642593348eSBarry Smith {
365b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
3669df24120SSatish Balay   int         i,fd,*col_lens,ierr,bs = a->bs,count,*jj,j,k,l,bs2=a->bs2;
36787828ca2SBarry Smith   PetscScalar *aa;
368ce6f0cecSBarry Smith   FILE        *file;
3692593348eSBarry Smith 
3703a40ed3dSBarry Smith   PetscFunctionBegin;
371b0a32e0cSBarry Smith   ierr        = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
372b0a32e0cSBarry Smith   ierr        = PetscMalloc((4+A->m)*sizeof(int),&col_lens);CHKERRQ(ierr);
373552e946dSBarry Smith   col_lens[0] = MAT_FILE_COOKIE;
3743b2fbd54SBarry Smith 
375273d9f13SBarry Smith   col_lens[1] = A->m;
376273d9f13SBarry Smith   col_lens[2] = A->n;
3777e67e3f9SSatish Balay   col_lens[3] = a->nz*bs2;
3782593348eSBarry Smith 
3792593348eSBarry Smith   /* store lengths of each row and write (including header) to file */
380b6490206SBarry Smith   count = 0;
381b6490206SBarry Smith   for (i=0; i<a->mbs; i++) {
382b6490206SBarry Smith     for (j=0; j<bs; j++) {
383b6490206SBarry Smith       col_lens[4+count++] = bs*(a->i[i+1] - a->i[i]);
384b6490206SBarry Smith     }
3852593348eSBarry Smith   }
386273d9f13SBarry Smith   ierr = PetscBinaryWrite(fd,col_lens,4+A->m,PETSC_INT,1);CHKERRQ(ierr);
387606d414cSSatish Balay   ierr = PetscFree(col_lens);CHKERRQ(ierr);
3882593348eSBarry Smith 
3892593348eSBarry Smith   /* store column indices (zero start index) */
390b0a32e0cSBarry Smith   ierr  = PetscMalloc((a->nz+1)*bs2*sizeof(int),&jj);CHKERRQ(ierr);
391b6490206SBarry Smith   count = 0;
392b6490206SBarry Smith   for (i=0; i<a->mbs; i++) {
393b6490206SBarry Smith     for (j=0; j<bs; j++) {
394b6490206SBarry Smith       for (k=a->i[i]; k<a->i[i+1]; k++) {
395b6490206SBarry Smith         for (l=0; l<bs; l++) {
396b6490206SBarry Smith           jj[count++] = bs*a->j[k] + l;
3972593348eSBarry Smith         }
3982593348eSBarry Smith       }
399b6490206SBarry Smith     }
400b6490206SBarry Smith   }
4010752156aSBarry Smith   ierr = PetscBinaryWrite(fd,jj,bs2*a->nz,PETSC_INT,0);CHKERRQ(ierr);
402606d414cSSatish Balay   ierr = PetscFree(jj);CHKERRQ(ierr);
4032593348eSBarry Smith 
4042593348eSBarry Smith   /* store nonzero values */
40587828ca2SBarry Smith   ierr  = PetscMalloc((a->nz+1)*bs2*sizeof(PetscScalar),&aa);CHKERRQ(ierr);
406b6490206SBarry Smith   count = 0;
407b6490206SBarry Smith   for (i=0; i<a->mbs; i++) {
408b6490206SBarry Smith     for (j=0; j<bs; j++) {
409b6490206SBarry Smith       for (k=a->i[i]; k<a->i[i+1]; k++) {
410b6490206SBarry Smith         for (l=0; l<bs; l++) {
4117e67e3f9SSatish Balay           aa[count++] = a->a[bs2*k + l*bs + j];
412b6490206SBarry Smith         }
413b6490206SBarry Smith       }
414b6490206SBarry Smith     }
415b6490206SBarry Smith   }
4160752156aSBarry Smith   ierr = PetscBinaryWrite(fd,aa,bs2*a->nz,PETSC_SCALAR,0);CHKERRQ(ierr);
417606d414cSSatish Balay   ierr = PetscFree(aa);CHKERRQ(ierr);
418ce6f0cecSBarry Smith 
419b0a32e0cSBarry Smith   ierr = PetscViewerBinaryGetInfoPointer(viewer,&file);CHKERRQ(ierr);
420ce6f0cecSBarry Smith   if (file) {
421ce6f0cecSBarry Smith     fprintf(file,"-matload_block_size %d\n",a->bs);
422ce6f0cecSBarry Smith   }
4233a40ed3dSBarry Smith   PetscFunctionReturn(0);
4242593348eSBarry Smith }
4252593348eSBarry Smith 
42604929863SHong Zhang extern int MatMPIBAIJFactorInfo_DSCPACK(Mat,PetscViewer);
42704929863SHong Zhang 
4284a2ae208SSatish Balay #undef __FUNCT__
4294a2ae208SSatish Balay #define __FUNCT__ "MatView_SeqBAIJ_ASCII"
430b0a32e0cSBarry Smith static int MatView_SeqBAIJ_ASCII(Mat A,PetscViewer viewer)
4312593348eSBarry Smith {
432b6490206SBarry Smith   Mat_SeqBAIJ       *a = (Mat_SeqBAIJ*)A->data;
433fb9695e5SSatish Balay   int               ierr,i,j,bs = a->bs,k,l,bs2=a->bs2;
434f3ef73ceSBarry Smith   PetscViewerFormat format;
4352593348eSBarry Smith 
4363a40ed3dSBarry Smith   PetscFunctionBegin;
437b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
438fb9695e5SSatish Balay   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_LONG) {
439b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  block size is %d\n",bs);CHKERRQ(ierr);
440fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_MATLAB) {
441bcd9e38bSBarry Smith     Mat aij;
442bcd9e38bSBarry Smith     ierr = MatConvert(A,MATSEQAIJ,&aij);CHKERRQ(ierr);
443bcd9e38bSBarry Smith     ierr = MatView(aij,viewer);CHKERRQ(ierr);
444bcd9e38bSBarry Smith     ierr = MatDestroy(aij);CHKERRQ(ierr);
44504929863SHong Zhang   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
44604929863SHong Zhang #if defined(PETSC_HAVE_DSCPACK) && !defined(PETSC_USE_SINGLE) && !defined(PETSC_USE_COMPLEX)
44704929863SHong Zhang      ierr = MatMPIBAIJFactorInfo_DSCPACK(A,viewer);CHKERRQ(ierr);
44804929863SHong Zhang #endif
44904929863SHong Zhang      PetscFunctionReturn(0);
450fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
451b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
45244cd7ae7SLois Curfman McInnes     for (i=0; i<a->mbs; i++) {
45344cd7ae7SLois Curfman McInnes       for (j=0; j<bs; j++) {
454b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %d:",i*bs+j);CHKERRQ(ierr);
45544cd7ae7SLois Curfman McInnes         for (k=a->i[i]; k<a->i[i+1]; k++) {
45644cd7ae7SLois Curfman McInnes           for (l=0; l<bs; l++) {
457aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
4580e6d2581SBarry Smith             if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
45962b941d6SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%d, %g + %gi) ",bs*a->j[k]+l,
4600e6d2581SBarry Smith                       PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
4610e6d2581SBarry Smith             } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
46262b941d6SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%d, %g - %gi) ",bs*a->j[k]+l,
4630e6d2581SBarry Smith                       PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
4640e6d2581SBarry Smith             } else if (PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
46562b941d6SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
4660ef38995SBarry Smith             }
46744cd7ae7SLois Curfman McInnes #else
4680ef38995SBarry Smith             if (a->a[bs2*k + l*bs + j] != 0.0) {
46962b941d6SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);CHKERRQ(ierr);
4700ef38995SBarry Smith             }
47144cd7ae7SLois Curfman McInnes #endif
47244cd7ae7SLois Curfman McInnes           }
47344cd7ae7SLois Curfman McInnes         }
474b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
47544cd7ae7SLois Curfman McInnes       }
47644cd7ae7SLois Curfman McInnes     }
477b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
4780ef38995SBarry Smith   } else {
479b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
480b6490206SBarry Smith     for (i=0; i<a->mbs; i++) {
481b6490206SBarry Smith       for (j=0; j<bs; j++) {
482b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %d:",i*bs+j);CHKERRQ(ierr);
483b6490206SBarry Smith         for (k=a->i[i]; k<a->i[i+1]; k++) {
484b6490206SBarry Smith           for (l=0; l<bs; l++) {
485aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
4860e6d2581SBarry Smith             if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0) {
48762b941d6SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%d, %g + %g i) ",bs*a->j[k]+l,
4880e6d2581SBarry Smith                 PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
4890e6d2581SBarry Smith             } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0) {
49062b941d6SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%d, %g - %g i) ",bs*a->j[k]+l,
4910e6d2581SBarry Smith                 PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
4920ef38995SBarry Smith             } else {
49362b941d6SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
49488685aaeSLois Curfman McInnes             }
49588685aaeSLois Curfman McInnes #else
49662b941d6SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);CHKERRQ(ierr);
49788685aaeSLois Curfman McInnes #endif
4982593348eSBarry Smith           }
4992593348eSBarry Smith         }
500b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
5012593348eSBarry Smith       }
5022593348eSBarry Smith     }
503b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
504b6490206SBarry Smith   }
505b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
5063a40ed3dSBarry Smith   PetscFunctionReturn(0);
5072593348eSBarry Smith }
5082593348eSBarry Smith 
5094a2ae208SSatish Balay #undef __FUNCT__
5104a2ae208SSatish Balay #define __FUNCT__ "MatView_SeqBAIJ_Draw_Zoom"
511b0a32e0cSBarry Smith static int MatView_SeqBAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
5123270192aSSatish Balay {
51377ed5343SBarry Smith   Mat          A = (Mat) Aa;
5143270192aSSatish Balay   Mat_SeqBAIJ  *a=(Mat_SeqBAIJ*)A->data;
515b65db4caSBarry Smith   int          row,ierr,i,j,k,l,mbs=a->mbs,color,bs=a->bs,bs2=a->bs2;
5160e6d2581SBarry Smith   PetscReal    xl,yl,xr,yr,x_l,x_r,y_l,y_r;
5173f1db9ecSBarry Smith   MatScalar    *aa;
518b0a32e0cSBarry Smith   PetscViewer  viewer;
5193270192aSSatish Balay 
5203a40ed3dSBarry Smith   PetscFunctionBegin;
5213270192aSSatish Balay 
522b65db4caSBarry Smith   /* still need to add support for contour plot of nonzeros; see MatView_SeqAIJ_Draw_Zoom()*/
52377ed5343SBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
52477ed5343SBarry Smith 
525b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
52677ed5343SBarry Smith 
5273270192aSSatish Balay   /* loop over matrix elements drawing boxes */
528b0a32e0cSBarry Smith   color = PETSC_DRAW_BLUE;
5293270192aSSatish Balay   for (i=0,row=0; i<mbs; i++,row+=bs) {
5303270192aSSatish Balay     for (j=a->i[i]; j<a->i[i+1]; j++) {
531273d9f13SBarry Smith       y_l = A->m - row - 1.0; y_r = y_l + 1.0;
5323270192aSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
5333270192aSSatish Balay       aa = a->a + j*bs2;
5343270192aSSatish Balay       for (k=0; k<bs; k++) {
5353270192aSSatish Balay         for (l=0; l<bs; l++) {
5360e6d2581SBarry Smith           if (PetscRealPart(*aa++) >=  0.) continue;
537b0a32e0cSBarry Smith           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
5383270192aSSatish Balay         }
5393270192aSSatish Balay       }
5403270192aSSatish Balay     }
5413270192aSSatish Balay   }
542b0a32e0cSBarry Smith   color = PETSC_DRAW_CYAN;
5433270192aSSatish Balay   for (i=0,row=0; i<mbs; i++,row+=bs) {
5443270192aSSatish Balay     for (j=a->i[i]; j<a->i[i+1]; j++) {
545273d9f13SBarry Smith       y_l = A->m - row - 1.0; y_r = y_l + 1.0;
5463270192aSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
5473270192aSSatish Balay       aa = a->a + j*bs2;
5483270192aSSatish Balay       for (k=0; k<bs; k++) {
5493270192aSSatish Balay         for (l=0; l<bs; l++) {
5500e6d2581SBarry Smith           if (PetscRealPart(*aa++) != 0.) continue;
551b0a32e0cSBarry Smith           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
5523270192aSSatish Balay         }
5533270192aSSatish Balay       }
5543270192aSSatish Balay     }
5553270192aSSatish Balay   }
5563270192aSSatish Balay 
557b0a32e0cSBarry Smith   color = PETSC_DRAW_RED;
5583270192aSSatish Balay   for (i=0,row=0; i<mbs; i++,row+=bs) {
5593270192aSSatish Balay     for (j=a->i[i]; j<a->i[i+1]; j++) {
560273d9f13SBarry Smith       y_l = A->m - row - 1.0; y_r = y_l + 1.0;
5613270192aSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
5623270192aSSatish Balay       aa = a->a + j*bs2;
5633270192aSSatish Balay       for (k=0; k<bs; k++) {
5643270192aSSatish Balay         for (l=0; l<bs; l++) {
5650e6d2581SBarry Smith           if (PetscRealPart(*aa++) <= 0.) continue;
566b0a32e0cSBarry Smith           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
5673270192aSSatish Balay         }
5683270192aSSatish Balay       }
5693270192aSSatish Balay     }
5703270192aSSatish Balay   }
57177ed5343SBarry Smith   PetscFunctionReturn(0);
57277ed5343SBarry Smith }
5733270192aSSatish Balay 
5744a2ae208SSatish Balay #undef __FUNCT__
5754a2ae208SSatish Balay #define __FUNCT__ "MatView_SeqBAIJ_Draw"
576b0a32e0cSBarry Smith static int MatView_SeqBAIJ_Draw(Mat A,PetscViewer viewer)
57777ed5343SBarry Smith {
5787dce120fSSatish Balay   int          ierr;
5790e6d2581SBarry Smith   PetscReal    xl,yl,xr,yr,w,h;
580b0a32e0cSBarry Smith   PetscDraw    draw;
58177ed5343SBarry Smith   PetscTruth   isnull;
5823270192aSSatish Balay 
58377ed5343SBarry Smith   PetscFunctionBegin;
58477ed5343SBarry Smith 
585b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
586b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
58777ed5343SBarry Smith 
58877ed5343SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
589273d9f13SBarry Smith   xr  = A->n; yr = A->m; h = yr/10.0; w = xr/10.0;
59077ed5343SBarry Smith   xr += w;    yr += h;  xl = -w;     yl = -h;
591b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
592b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqBAIJ_Draw_Zoom,A);CHKERRQ(ierr);
59377ed5343SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
5943a40ed3dSBarry Smith   PetscFunctionReturn(0);
5953270192aSSatish Balay }
5963270192aSSatish Balay 
5974a2ae208SSatish Balay #undef __FUNCT__
5984a2ae208SSatish Balay #define __FUNCT__ "MatView_SeqBAIJ"
599b0a32e0cSBarry Smith int MatView_SeqBAIJ(Mat A,PetscViewer viewer)
6002593348eSBarry Smith {
60119bcc07fSBarry Smith   int        ierr;
6026831982aSBarry Smith   PetscTruth issocket,isascii,isbinary,isdraw;
6032593348eSBarry Smith 
6043a40ed3dSBarry Smith   PetscFunctionBegin;
605b0a32e0cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);CHKERRQ(ierr);
606b0a32e0cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
607fb9695e5SSatish Balay   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);CHKERRQ(ierr);
608fb9695e5SSatish Balay   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
6090f5bd95cSBarry Smith   if (issocket) {
61029bbc08cSBarry Smith     SETERRQ(PETSC_ERR_SUP,"Socket viewer not supported");
6110f5bd95cSBarry Smith   } else if (isascii){
6123a40ed3dSBarry Smith     ierr = MatView_SeqBAIJ_ASCII(A,viewer);CHKERRQ(ierr);
6130f5bd95cSBarry Smith   } else if (isbinary) {
6143a40ed3dSBarry Smith     ierr = MatView_SeqBAIJ_Binary(A,viewer);CHKERRQ(ierr);
6150f5bd95cSBarry Smith   } else if (isdraw) {
6163a40ed3dSBarry Smith     ierr = MatView_SeqBAIJ_Draw(A,viewer);CHKERRQ(ierr);
6175cd90555SBarry Smith   } else {
61829bbc08cSBarry Smith     SETERRQ1(1,"Viewer type %s not supported by SeqBAIJ matrices",((PetscObject)viewer)->type_name);
6192593348eSBarry Smith   }
6203a40ed3dSBarry Smith   PetscFunctionReturn(0);
6212593348eSBarry Smith }
622b6490206SBarry Smith 
623cd0e1443SSatish Balay 
6244a2ae208SSatish Balay #undef __FUNCT__
6254a2ae208SSatish Balay #define __FUNCT__ "MatGetValues_SeqBAIJ"
62687828ca2SBarry Smith int MatGetValues_SeqBAIJ(Mat A,int m,int *im,int n,int *in,PetscScalar *v)
627cd0e1443SSatish Balay {
628cd0e1443SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
6292d61bbb3SSatish Balay   int        *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
6302d61bbb3SSatish Balay   int        *ai = a->i,*ailen = a->ilen;
6312d61bbb3SSatish Balay   int        brow,bcol,ridx,cidx,bs=a->bs,bs2=a->bs2;
6323f1db9ecSBarry Smith   MatScalar  *ap,*aa = a->a,zero = 0.0;
633cd0e1443SSatish Balay 
6343a40ed3dSBarry Smith   PetscFunctionBegin;
6352d61bbb3SSatish Balay   for (k=0; k<m; k++) { /* loop over rows */
636cd0e1443SSatish Balay     row  = im[k]; brow = row/bs;
63729bbc08cSBarry Smith     if (row < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative row");
638273d9f13SBarry Smith     if (row >= A->m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
6392d61bbb3SSatish Balay     rp   = aj + ai[brow] ; ap = aa + bs2*ai[brow] ;
6402c3acbe9SBarry Smith     nrow = ailen[brow];
6412d61bbb3SSatish Balay     for (l=0; l<n; l++) { /* loop over columns */
64229bbc08cSBarry Smith       if (in[l] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative column");
643273d9f13SBarry Smith       if (in[l] >= A->n) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
6442d61bbb3SSatish Balay       col  = in[l] ;
6452d61bbb3SSatish Balay       bcol = col/bs;
6462d61bbb3SSatish Balay       cidx = col%bs;
6472d61bbb3SSatish Balay       ridx = row%bs;
6482d61bbb3SSatish Balay       high = nrow;
6492d61bbb3SSatish Balay       low  = 0; /* assume unsorted */
6502d61bbb3SSatish Balay       while (high-low > 5) {
651cd0e1443SSatish Balay         t = (low+high)/2;
652cd0e1443SSatish Balay         if (rp[t] > bcol) high = t;
653cd0e1443SSatish Balay         else             low  = t;
654cd0e1443SSatish Balay       }
655cd0e1443SSatish Balay       for (i=low; i<high; i++) {
656cd0e1443SSatish Balay         if (rp[i] > bcol) break;
657cd0e1443SSatish Balay         if (rp[i] == bcol) {
6582d61bbb3SSatish Balay           *v++ = ap[bs2*i+bs*cidx+ridx];
6592d61bbb3SSatish Balay           goto finished;
660cd0e1443SSatish Balay         }
661cd0e1443SSatish Balay       }
6622d61bbb3SSatish Balay       *v++ = zero;
6632d61bbb3SSatish Balay       finished:;
664cd0e1443SSatish Balay     }
665cd0e1443SSatish Balay   }
6663a40ed3dSBarry Smith   PetscFunctionReturn(0);
667cd0e1443SSatish Balay }
668cd0e1443SSatish Balay 
66995d5f7c2SBarry Smith #if defined(PETSC_USE_MAT_SINGLE)
6704a2ae208SSatish Balay #undef __FUNCT__
6714a2ae208SSatish Balay #define __FUNCT__ "MatSetValuesBlocked_SeqBAIJ"
67287828ca2SBarry Smith int MatSetValuesBlocked_SeqBAIJ(Mat mat,int m,int *im,int n,int *in,PetscScalar *v,InsertMode addv)
67395d5f7c2SBarry Smith {
674563b5814SBarry Smith   Mat_SeqBAIJ *b = (Mat_SeqBAIJ*)mat->data;
675563b5814SBarry Smith   int         ierr,i,N = m*n*b->bs2;
676563b5814SBarry Smith   MatScalar   *vsingle;
67795d5f7c2SBarry Smith 
67895d5f7c2SBarry Smith   PetscFunctionBegin;
679563b5814SBarry Smith   if (N > b->setvalueslen) {
680563b5814SBarry Smith     if (b->setvaluescopy) {ierr = PetscFree(b->setvaluescopy);CHKERRQ(ierr);}
681b0a32e0cSBarry Smith     ierr = PetscMalloc(N*sizeof(MatScalar),&b->setvaluescopy);CHKERRQ(ierr);
682563b5814SBarry Smith     b->setvalueslen  = N;
683563b5814SBarry Smith   }
684563b5814SBarry Smith   vsingle = b->setvaluescopy;
68595d5f7c2SBarry Smith   for (i=0; i<N; i++) {
68695d5f7c2SBarry Smith     vsingle[i] = v[i];
68795d5f7c2SBarry Smith   }
68895d5f7c2SBarry Smith   ierr = MatSetValuesBlocked_SeqBAIJ_MatScalar(mat,m,im,n,in,vsingle,addv);CHKERRQ(ierr);
68995d5f7c2SBarry Smith   PetscFunctionReturn(0);
69095d5f7c2SBarry Smith }
69195d5f7c2SBarry Smith #endif
69295d5f7c2SBarry Smith 
6932d61bbb3SSatish Balay 
6944a2ae208SSatish Balay #undef __FUNCT__
6954a2ae208SSatish Balay #define __FUNCT__ "MatSetValuesBlocked_SeqBAIJ"
69695d5f7c2SBarry Smith int MatSetValuesBlocked_SeqBAIJ_MatScalar(Mat A,int m,int *im,int n,int *in,MatScalar *v,InsertMode is)
69792c4ed94SBarry Smith {
69892c4ed94SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
6998a84c255SSatish Balay   int         *rp,k,low,high,t,ii,jj,row,nrow,i,col,l,rmax,N,sorted=a->sorted;
700273d9f13SBarry Smith   int         *imax=a->imax,*ai=a->i,*ailen=a->ilen;
701549d3d68SSatish Balay   int         *aj=a->j,nonew=a->nonew,bs2=a->bs2,bs=a->bs,stepval,ierr;
702273d9f13SBarry Smith   PetscTruth  roworiented=a->roworiented;
70395d5f7c2SBarry Smith   MatScalar   *value = v,*ap,*aa = a->a,*bap;
70492c4ed94SBarry Smith 
7053a40ed3dSBarry Smith   PetscFunctionBegin;
7060e324ae4SSatish Balay   if (roworiented) {
7070e324ae4SSatish Balay     stepval = (n-1)*bs;
7080e324ae4SSatish Balay   } else {
7090e324ae4SSatish Balay     stepval = (m-1)*bs;
7100e324ae4SSatish Balay   }
71192c4ed94SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
71292c4ed94SBarry Smith     row  = im[k];
7135ef9f2a5SBarry Smith     if (row < 0) continue;
714aa482453SBarry Smith #if defined(PETSC_USE_BOPT_g)
71529bbc08cSBarry Smith     if (row >= a->mbs) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
71692c4ed94SBarry Smith #endif
71792c4ed94SBarry Smith     rp   = aj + ai[row];
71892c4ed94SBarry Smith     ap   = aa + bs2*ai[row];
71992c4ed94SBarry Smith     rmax = imax[row];
72092c4ed94SBarry Smith     nrow = ailen[row];
72192c4ed94SBarry Smith     low  = 0;
72292c4ed94SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
7235ef9f2a5SBarry Smith       if (in[l] < 0) continue;
724aa482453SBarry Smith #if defined(PETSC_USE_BOPT_g)
72529bbc08cSBarry Smith       if (in[l] >= a->nbs) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
72692c4ed94SBarry Smith #endif
72792c4ed94SBarry Smith       col = in[l];
72892c4ed94SBarry Smith       if (roworiented) {
7290e324ae4SSatish Balay         value = v + k*(stepval+bs)*bs + l*bs;
7300e324ae4SSatish Balay       } else {
7310e324ae4SSatish Balay         value = v + l*(stepval+bs)*bs + k*bs;
73292c4ed94SBarry Smith       }
73392c4ed94SBarry Smith       if (!sorted) low = 0; high = nrow;
73492c4ed94SBarry Smith       while (high-low > 7) {
73592c4ed94SBarry Smith         t = (low+high)/2;
73692c4ed94SBarry Smith         if (rp[t] > col) high = t;
73792c4ed94SBarry Smith         else             low  = t;
73892c4ed94SBarry Smith       }
73992c4ed94SBarry Smith       for (i=low; i<high; i++) {
74092c4ed94SBarry Smith         if (rp[i] > col) break;
74192c4ed94SBarry Smith         if (rp[i] == col) {
7428a84c255SSatish Balay           bap  = ap +  bs2*i;
7430e324ae4SSatish Balay           if (roworiented) {
7448a84c255SSatish Balay             if (is == ADD_VALUES) {
745dd9472c6SBarry Smith               for (ii=0; ii<bs; ii++,value+=stepval) {
746dd9472c6SBarry Smith                 for (jj=ii; jj<bs2; jj+=bs) {
7478a84c255SSatish Balay                   bap[jj] += *value++;
748dd9472c6SBarry Smith                 }
749dd9472c6SBarry Smith               }
7500e324ae4SSatish Balay             } else {
751dd9472c6SBarry Smith               for (ii=0; ii<bs; ii++,value+=stepval) {
752dd9472c6SBarry Smith                 for (jj=ii; jj<bs2; jj+=bs) {
7530e324ae4SSatish Balay                   bap[jj] = *value++;
7548a84c255SSatish Balay                 }
755dd9472c6SBarry Smith               }
756dd9472c6SBarry Smith             }
7570e324ae4SSatish Balay           } else {
7580e324ae4SSatish Balay             if (is == ADD_VALUES) {
759dd9472c6SBarry Smith               for (ii=0; ii<bs; ii++,value+=stepval) {
760dd9472c6SBarry Smith                 for (jj=0; jj<bs; jj++) {
7610e324ae4SSatish Balay                   *bap++ += *value++;
762dd9472c6SBarry Smith                 }
763dd9472c6SBarry Smith               }
7640e324ae4SSatish Balay             } else {
765dd9472c6SBarry Smith               for (ii=0; ii<bs; ii++,value+=stepval) {
766dd9472c6SBarry Smith                 for (jj=0; jj<bs; jj++) {
7670e324ae4SSatish Balay                   *bap++  = *value++;
7680e324ae4SSatish Balay                 }
7698a84c255SSatish Balay               }
770dd9472c6SBarry Smith             }
771dd9472c6SBarry Smith           }
772f1241b54SBarry Smith           goto noinsert2;
77392c4ed94SBarry Smith         }
77492c4ed94SBarry Smith       }
77589280ab3SLois Curfman McInnes       if (nonew == 1) goto noinsert2;
77629bbc08cSBarry Smith       else if (nonew == -1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
77792c4ed94SBarry Smith       if (nrow >= rmax) {
77892c4ed94SBarry Smith         /* there is no extra room in row, therefore enlarge */
77992c4ed94SBarry Smith         int       new_nz = ai[a->mbs] + CHUNKSIZE,len,*new_i,*new_j;
7803f1db9ecSBarry Smith         MatScalar *new_a;
78192c4ed94SBarry Smith 
78229bbc08cSBarry Smith         if (nonew == -2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
78389280ab3SLois Curfman McInnes 
78492c4ed94SBarry Smith         /* malloc new storage space */
7853f1db9ecSBarry Smith         len     = new_nz*(sizeof(int)+bs2*sizeof(MatScalar))+(a->mbs+1)*sizeof(int);
786b0a32e0cSBarry Smith 	ierr    = PetscMalloc(len,&new_a);CHKERRQ(ierr);
78792c4ed94SBarry Smith         new_j   = (int*)(new_a + bs2*new_nz);
78892c4ed94SBarry Smith         new_i   = new_j + new_nz;
78992c4ed94SBarry Smith 
79092c4ed94SBarry Smith         /* copy over old data into new slots */
79192c4ed94SBarry Smith         for (ii=0; ii<row+1; ii++) {new_i[ii] = ai[ii];}
79292c4ed94SBarry Smith         for (ii=row+1; ii<a->mbs+1; ii++) {new_i[ii] = ai[ii]+CHUNKSIZE;}
793549d3d68SSatish Balay         ierr = PetscMemcpy(new_j,aj,(ai[row]+nrow)*sizeof(int));CHKERRQ(ierr);
79492c4ed94SBarry Smith         len  = (new_nz - CHUNKSIZE - ai[row] - nrow);
795549d3d68SSatish Balay         ierr = PetscMemcpy(new_j+ai[row]+nrow+CHUNKSIZE,aj+ai[row]+nrow,len*sizeof(int));CHKERRQ(ierr);
796549d3d68SSatish Balay         ierr = PetscMemcpy(new_a,aa,(ai[row]+nrow)*bs2*sizeof(MatScalar));CHKERRQ(ierr);
797549d3d68SSatish Balay         ierr = PetscMemzero(new_a+bs2*(ai[row]+nrow),bs2*CHUNKSIZE*sizeof(MatScalar));CHKERRQ(ierr);
798549d3d68SSatish Balay         ierr = PetscMemcpy(new_a+bs2*(ai[row]+nrow+CHUNKSIZE),aa+bs2*(ai[row]+nrow),bs2*len*sizeof(MatScalar));CHKERRQ(ierr);
79992c4ed94SBarry Smith         /* free up old matrix storage */
800606d414cSSatish Balay         ierr = PetscFree(a->a);CHKERRQ(ierr);
801606d414cSSatish Balay         if (!a->singlemalloc) {
802606d414cSSatish Balay           ierr = PetscFree(a->i);CHKERRQ(ierr);
803606d414cSSatish Balay           ierr = PetscFree(a->j);CHKERRQ(ierr);
804606d414cSSatish Balay         }
80592c4ed94SBarry Smith         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;
806c4992f7dSBarry Smith         a->singlemalloc = PETSC_TRUE;
80792c4ed94SBarry Smith 
80892c4ed94SBarry Smith         rp   = aj + ai[row]; ap = aa + bs2*ai[row];
80992c4ed94SBarry Smith         rmax = imax[row] = imax[row] + CHUNKSIZE;
810b0a32e0cSBarry Smith         PetscLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + bs2*sizeof(MatScalar)));
81192c4ed94SBarry Smith         a->maxnz += bs2*CHUNKSIZE;
81292c4ed94SBarry Smith         a->reallocs++;
81392c4ed94SBarry Smith         a->nz++;
81492c4ed94SBarry Smith       }
81592c4ed94SBarry Smith       N = nrow++ - 1;
81692c4ed94SBarry Smith       /* shift up all the later entries in this row */
81792c4ed94SBarry Smith       for (ii=N; ii>=i; ii--) {
81892c4ed94SBarry Smith         rp[ii+1] = rp[ii];
819549d3d68SSatish Balay         ierr = PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));CHKERRQ(ierr);
82092c4ed94SBarry Smith       }
821549d3d68SSatish Balay       if (N >= i) {
822549d3d68SSatish Balay         ierr = PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));CHKERRQ(ierr);
823549d3d68SSatish Balay       }
82492c4ed94SBarry Smith       rp[i] = col;
8258a84c255SSatish Balay       bap   = ap +  bs2*i;
8260e324ae4SSatish Balay       if (roworiented) {
827dd9472c6SBarry Smith         for (ii=0; ii<bs; ii++,value+=stepval) {
828dd9472c6SBarry Smith           for (jj=ii; jj<bs2; jj+=bs) {
8290e324ae4SSatish Balay             bap[jj] = *value++;
830dd9472c6SBarry Smith           }
831dd9472c6SBarry Smith         }
8320e324ae4SSatish Balay       } else {
833dd9472c6SBarry Smith         for (ii=0; ii<bs; ii++,value+=stepval) {
834dd9472c6SBarry Smith           for (jj=0; jj<bs; jj++) {
8350e324ae4SSatish Balay             *bap++  = *value++;
8360e324ae4SSatish Balay           }
837dd9472c6SBarry Smith         }
838dd9472c6SBarry Smith       }
839f1241b54SBarry Smith       noinsert2:;
84092c4ed94SBarry Smith       low = i;
84192c4ed94SBarry Smith     }
84292c4ed94SBarry Smith     ailen[row] = nrow;
84392c4ed94SBarry Smith   }
8443a40ed3dSBarry Smith   PetscFunctionReturn(0);
84592c4ed94SBarry Smith }
84692c4ed94SBarry Smith 
84704929863SHong Zhang /* EXTERN int MatUseDSCPACK_MPIBAIJ(Mat); */
8484a2ae208SSatish Balay #undef __FUNCT__
8494a2ae208SSatish Balay #define __FUNCT__ "MatAssemblyEnd_SeqBAIJ"
8508f6be9afSLois Curfman McInnes int MatAssemblyEnd_SeqBAIJ(Mat A,MatAssemblyType mode)
851584200bdSSatish Balay {
852584200bdSSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
853584200bdSSatish Balay   int        fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
854273d9f13SBarry Smith   int        m = A->m,*ip,N,*ailen = a->ilen;
855549d3d68SSatish Balay   int        mbs = a->mbs,bs2 = a->bs2,rmax = 0,ierr;
8563f1db9ecSBarry Smith   MatScalar  *aa = a->a,*ap;
857a56a16c8SHong Zhang #if defined(PETSC_HAVE_DSCPACK)
858a56a16c8SHong Zhang   PetscTruth   flag;
859a56a16c8SHong Zhang #endif
860584200bdSSatish Balay 
8613a40ed3dSBarry Smith   PetscFunctionBegin;
8623a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
863584200bdSSatish Balay 
86443ee02c3SBarry Smith   if (m) rmax = ailen[0];
865584200bdSSatish Balay   for (i=1; i<mbs; i++) {
866584200bdSSatish Balay     /* move each row back by the amount of empty slots (fshift) before it*/
867584200bdSSatish Balay     fshift += imax[i-1] - ailen[i-1];
868d402145bSBarry Smith     rmax   = PetscMax(rmax,ailen[i]);
869584200bdSSatish Balay     if (fshift) {
870a7c10996SSatish Balay       ip = aj + ai[i]; ap = aa + bs2*ai[i];
871584200bdSSatish Balay       N = ailen[i];
872584200bdSSatish Balay       for (j=0; j<N; j++) {
873584200bdSSatish Balay         ip[j-fshift] = ip[j];
874549d3d68SSatish Balay         ierr = PetscMemcpy(ap+(j-fshift)*bs2,ap+j*bs2,bs2*sizeof(MatScalar));CHKERRQ(ierr);
875584200bdSSatish Balay       }
876584200bdSSatish Balay     }
877584200bdSSatish Balay     ai[i] = ai[i-1] + ailen[i-1];
878584200bdSSatish Balay   }
879584200bdSSatish Balay   if (mbs) {
880584200bdSSatish Balay     fshift += imax[mbs-1] - ailen[mbs-1];
881584200bdSSatish Balay     ai[mbs] = ai[mbs-1] + ailen[mbs-1];
882584200bdSSatish Balay   }
883584200bdSSatish Balay   /* reset ilen and imax for each row */
884584200bdSSatish Balay   for (i=0; i<mbs; i++) {
885584200bdSSatish Balay     ailen[i] = imax[i] = ai[i+1] - ai[i];
886584200bdSSatish Balay   }
887a7c10996SSatish Balay   a->nz = ai[mbs];
888584200bdSSatish Balay 
889584200bdSSatish Balay   /* diagonals may have moved, so kill the diagonal pointers */
890584200bdSSatish Balay   if (fshift && a->diag) {
891606d414cSSatish Balay     ierr = PetscFree(a->diag);CHKERRQ(ierr);
892b424e231SHong Zhang     PetscLogObjectMemory(A,-(mbs+1)*sizeof(int));
893584200bdSSatish Balay     a->diag = 0;
894584200bdSSatish Balay   }
895bba1ac68SSatish Balay   PetscLogInfo(A,"MatAssemblyEnd_SeqBAIJ:Matrix size: %d X %d, block size %d; storage space: %d unneeded, %d used\n",m,A->n,a->bs,fshift*bs2,a->nz*bs2);
896bba1ac68SSatish Balay   PetscLogInfo(A,"MatAssemblyEnd_SeqBAIJ:Number of mallocs during MatSetValues is %d\n",a->reallocs);
897b0a32e0cSBarry Smith   PetscLogInfo(A,"MatAssemblyEnd_SeqBAIJ:Most nonzeros blocks in any row is %d\n",rmax);
898e2f3b5e9SSatish Balay   a->reallocs          = 0;
8990e6d2581SBarry Smith   A->info.nz_unneeded  = (PetscReal)fshift*bs2;
900a56a16c8SHong Zhang #if defined(PETSC_HAVE_DSCPACK)
901a56a16c8SHong Zhang   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_baij_dscpack",&flag);CHKERRQ(ierr);
902a56a16c8SHong Zhang   if (flag) { ierr = MatUseDSCPACK_MPIBAIJ(A);CHKERRQ(ierr); }
903a56a16c8SHong Zhang #endif
904a56a16c8SHong Zhang 
9054e220ebcSLois Curfman McInnes 
9063a40ed3dSBarry Smith   PetscFunctionReturn(0);
907584200bdSSatish Balay }
908584200bdSSatish Balay 
9095a838052SSatish Balay 
910bea157c4SSatish Balay 
911bea157c4SSatish Balay /*
912bea157c4SSatish Balay    This function returns an array of flags which indicate the locations of contiguous
913bea157c4SSatish Balay    blocks that should be zeroed. for eg: if bs = 3  and is = [0,1,2,3,5,6,7,8,9]
914bea157c4SSatish Balay    then the resulting sizes = [3,1,1,3,1] correspondig to sets [(0,1,2),(3),(5),(6,7,8),(9)]
915bea157c4SSatish Balay    Assume: sizes should be long enough to hold all the values.
916bea157c4SSatish Balay */
9174a2ae208SSatish Balay #undef __FUNCT__
9184a2ae208SSatish Balay #define __FUNCT__ "MatZeroRows_SeqBAIJ_Check_Blocks"
919bea157c4SSatish Balay static int MatZeroRows_SeqBAIJ_Check_Blocks(int idx[],int n,int bs,int sizes[], int *bs_max)
920d9b7c43dSSatish Balay {
921bea157c4SSatish Balay   int        i,j,k,row;
922bea157c4SSatish Balay   PetscTruth flg;
9233a40ed3dSBarry Smith 
924433994e6SBarry Smith   PetscFunctionBegin;
925bea157c4SSatish Balay   for (i=0,j=0; i<n; j++) {
926bea157c4SSatish Balay     row = idx[i];
927bea157c4SSatish Balay     if (row%bs!=0) { /* Not the begining of a block */
928bea157c4SSatish Balay       sizes[j] = 1;
929bea157c4SSatish Balay       i++;
930e4fda26cSSatish Balay     } else if (i+bs > n) { /* complete block doesn't exist (at idx end) */
931bea157c4SSatish Balay       sizes[j] = 1;         /* Also makes sure atleast 'bs' values exist for next else */
932bea157c4SSatish Balay       i++;
933bea157c4SSatish Balay     } else { /* Begining of the block, so check if the complete block exists */
934bea157c4SSatish Balay       flg = PETSC_TRUE;
935bea157c4SSatish Balay       for (k=1; k<bs; k++) {
936bea157c4SSatish Balay         if (row+k != idx[i+k]) { /* break in the block */
937bea157c4SSatish Balay           flg = PETSC_FALSE;
938bea157c4SSatish Balay           break;
939d9b7c43dSSatish Balay         }
940bea157c4SSatish Balay       }
941bea157c4SSatish Balay       if (flg == PETSC_TRUE) { /* No break in the bs */
942bea157c4SSatish Balay         sizes[j] = bs;
943bea157c4SSatish Balay         i+= bs;
944bea157c4SSatish Balay       } else {
945bea157c4SSatish Balay         sizes[j] = 1;
946bea157c4SSatish Balay         i++;
947bea157c4SSatish Balay       }
948bea157c4SSatish Balay     }
949bea157c4SSatish Balay   }
950bea157c4SSatish Balay   *bs_max = j;
9513a40ed3dSBarry Smith   PetscFunctionReturn(0);
952d9b7c43dSSatish Balay }
953d9b7c43dSSatish Balay 
9544a2ae208SSatish Balay #undef __FUNCT__
9554a2ae208SSatish Balay #define __FUNCT__ "MatZeroRows_SeqBAIJ"
95687828ca2SBarry Smith int MatZeroRows_SeqBAIJ(Mat A,IS is,PetscScalar *diag)
957d9b7c43dSSatish Balay {
958d9b7c43dSSatish Balay   Mat_SeqBAIJ *baij=(Mat_SeqBAIJ*)A->data;
959b6815fffSBarry Smith   int         ierr,i,j,k,count,is_n,*is_idx,*rows;
960bea157c4SSatish Balay   int         bs=baij->bs,bs2=baij->bs2,*sizes,row,bs_max;
96187828ca2SBarry Smith   PetscScalar zero = 0.0;
9623f1db9ecSBarry Smith   MatScalar   *aa;
963d9b7c43dSSatish Balay 
9643a40ed3dSBarry Smith   PetscFunctionBegin;
965d9b7c43dSSatish Balay   /* Make a copy of the IS and  sort it */
966b9b97703SBarry Smith   ierr = ISGetLocalSize(is,&is_n);CHKERRQ(ierr);
967d9b7c43dSSatish Balay   ierr = ISGetIndices(is,&is_idx);CHKERRQ(ierr);
968d9b7c43dSSatish Balay 
969bea157c4SSatish Balay   /* allocate memory for rows,sizes */
970b0a32e0cSBarry Smith   ierr  = PetscMalloc((3*is_n+1)*sizeof(int),&rows);CHKERRQ(ierr);
971bea157c4SSatish Balay   sizes = rows + is_n;
972bea157c4SSatish Balay 
973563b5814SBarry Smith   /* copy IS values to rows, and sort them */
974bea157c4SSatish Balay   for (i=0; i<is_n; i++) { rows[i] = is_idx[i]; }
975bea157c4SSatish Balay   ierr = PetscSortInt(is_n,rows);CHKERRQ(ierr);
976dffd3267SBarry Smith   if (baij->keepzeroedrows) {
977dffd3267SBarry Smith     for (i=0; i<is_n; i++) { sizes[i] = 1; }
978dffd3267SBarry Smith     bs_max = is_n;
979dffd3267SBarry Smith   } else {
980bea157c4SSatish Balay     ierr = MatZeroRows_SeqBAIJ_Check_Blocks(rows,is_n,bs,sizes,&bs_max);CHKERRQ(ierr);
981dffd3267SBarry Smith   }
982b97a56abSSatish Balay   ierr = ISRestoreIndices(is,&is_idx);CHKERRQ(ierr);
983bea157c4SSatish Balay 
984bea157c4SSatish Balay   for (i=0,j=0; i<bs_max; j+=sizes[i],i++) {
985bea157c4SSatish Balay     row   = rows[j];
986273d9f13SBarry Smith     if (row < 0 || row > A->m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"row %d out of range",row);
987bea157c4SSatish Balay     count = (baij->i[row/bs +1] - baij->i[row/bs])*bs;
988bea157c4SSatish Balay     aa    = baij->a + baij->i[row/bs]*bs2 + (row%bs);
989dffd3267SBarry Smith     if (sizes[i] == bs && !baij->keepzeroedrows) {
990bea157c4SSatish Balay       if (diag) {
991bea157c4SSatish Balay         if (baij->ilen[row/bs] > 0) {
992bea157c4SSatish Balay           baij->ilen[row/bs]       = 1;
993bea157c4SSatish Balay           baij->j[baij->i[row/bs]] = row/bs;
994bea157c4SSatish Balay           ierr = PetscMemzero(aa,count*bs*sizeof(MatScalar));CHKERRQ(ierr);
995a07cd24cSSatish Balay         }
996563b5814SBarry Smith         /* Now insert all the diagonal values for this bs */
997bea157c4SSatish Balay         for (k=0; k<bs; k++) {
998bea157c4SSatish Balay           ierr = (*A->ops->setvalues)(A,1,rows+j+k,1,rows+j+k,diag,INSERT_VALUES);CHKERRQ(ierr);
999bea157c4SSatish Balay         }
1000bea157c4SSatish Balay       } else { /* (!diag) */
1001bea157c4SSatish Balay         baij->ilen[row/bs] = 0;
1002bea157c4SSatish Balay       } /* end (!diag) */
1003bea157c4SSatish Balay     } else { /* (sizes[i] != bs) */
1004aa482453SBarry Smith #if defined (PETSC_USE_DEBUG)
100529bbc08cSBarry Smith       if (sizes[i] != 1) SETERRQ(1,"Internal Error. Value should be 1");
1006bea157c4SSatish Balay #endif
1007bea157c4SSatish Balay       for (k=0; k<count; k++) {
1008d9b7c43dSSatish Balay         aa[0] =  zero;
1009d9b7c43dSSatish Balay         aa    += bs;
1010d9b7c43dSSatish Balay       }
1011d9b7c43dSSatish Balay       if (diag) {
1012f830108cSBarry Smith         ierr = (*A->ops->setvalues)(A,1,rows+j,1,rows+j,diag,INSERT_VALUES);CHKERRQ(ierr);
1013d9b7c43dSSatish Balay       }
1014d9b7c43dSSatish Balay     }
1015bea157c4SSatish Balay   }
1016bea157c4SSatish Balay 
1017606d414cSSatish Balay   ierr = PetscFree(rows);CHKERRQ(ierr);
10189a8dea36SBarry Smith   ierr = MatAssemblyEnd_SeqBAIJ(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10193a40ed3dSBarry Smith   PetscFunctionReturn(0);
1020d9b7c43dSSatish Balay }
10211c351548SSatish Balay 
10224a2ae208SSatish Balay #undef __FUNCT__
10234a2ae208SSatish Balay #define __FUNCT__ "MatSetValues_SeqBAIJ"
102487828ca2SBarry Smith int MatSetValues_SeqBAIJ(Mat A,int m,int *im,int n,int *in,PetscScalar *v,InsertMode is)
10252d61bbb3SSatish Balay {
10262d61bbb3SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
10272d61bbb3SSatish Balay   int         *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,sorted=a->sorted;
1028273d9f13SBarry Smith   int         *imax=a->imax,*ai=a->i,*ailen=a->ilen;
10292d61bbb3SSatish Balay   int         *aj=a->j,nonew=a->nonew,bs=a->bs,brow,bcol;
1030549d3d68SSatish Balay   int         ridx,cidx,bs2=a->bs2,ierr;
1031273d9f13SBarry Smith   PetscTruth  roworiented=a->roworiented;
10323f1db9ecSBarry Smith   MatScalar   *ap,value,*aa=a->a,*bap;
10332d61bbb3SSatish Balay 
10342d61bbb3SSatish Balay   PetscFunctionBegin;
10352d61bbb3SSatish Balay   for (k=0; k<m; k++) { /* loop over added rows */
10362d61bbb3SSatish Balay     row  = im[k]; brow = row/bs;
10375ef9f2a5SBarry Smith     if (row < 0) continue;
1038aa482453SBarry Smith #if defined(PETSC_USE_BOPT_g)
1039273d9f13SBarry Smith     if (row >= A->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %d max %d",row,A->m);
10402d61bbb3SSatish Balay #endif
10412d61bbb3SSatish Balay     rp   = aj + ai[brow];
10422d61bbb3SSatish Balay     ap   = aa + bs2*ai[brow];
10432d61bbb3SSatish Balay     rmax = imax[brow];
10442d61bbb3SSatish Balay     nrow = ailen[brow];
10452d61bbb3SSatish Balay     low  = 0;
10462d61bbb3SSatish Balay     for (l=0; l<n; l++) { /* loop over added columns */
10475ef9f2a5SBarry Smith       if (in[l] < 0) continue;
1048aa482453SBarry Smith #if defined(PETSC_USE_BOPT_g)
1049273d9f13SBarry Smith       if (in[l] >= A->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %d max %d",in[l],A->n);
10502d61bbb3SSatish Balay #endif
10512d61bbb3SSatish Balay       col = in[l]; bcol = col/bs;
10522d61bbb3SSatish Balay       ridx = row % bs; cidx = col % bs;
10532d61bbb3SSatish Balay       if (roworiented) {
10545ef9f2a5SBarry Smith         value = v[l + k*n];
10552d61bbb3SSatish Balay       } else {
10562d61bbb3SSatish Balay         value = v[k + l*m];
10572d61bbb3SSatish Balay       }
10582d61bbb3SSatish Balay       if (!sorted) low = 0; high = nrow;
10592d61bbb3SSatish Balay       while (high-low > 7) {
10602d61bbb3SSatish Balay         t = (low+high)/2;
10612d61bbb3SSatish Balay         if (rp[t] > bcol) high = t;
10622d61bbb3SSatish Balay         else              low  = t;
10632d61bbb3SSatish Balay       }
10642d61bbb3SSatish Balay       for (i=low; i<high; i++) {
10652d61bbb3SSatish Balay         if (rp[i] > bcol) break;
10662d61bbb3SSatish Balay         if (rp[i] == bcol) {
10672d61bbb3SSatish Balay           bap  = ap +  bs2*i + bs*cidx + ridx;
10682d61bbb3SSatish Balay           if (is == ADD_VALUES) *bap += value;
10692d61bbb3SSatish Balay           else                  *bap  = value;
10702d61bbb3SSatish Balay           goto noinsert1;
10712d61bbb3SSatish Balay         }
10722d61bbb3SSatish Balay       }
10732d61bbb3SSatish Balay       if (nonew == 1) goto noinsert1;
107429bbc08cSBarry Smith       else if (nonew == -1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
10752d61bbb3SSatish Balay       if (nrow >= rmax) {
10762d61bbb3SSatish Balay         /* there is no extra room in row, therefore enlarge */
10772d61bbb3SSatish Balay         int       new_nz = ai[a->mbs] + CHUNKSIZE,len,*new_i,*new_j;
10783f1db9ecSBarry Smith         MatScalar *new_a;
10792d61bbb3SSatish Balay 
108029bbc08cSBarry Smith         if (nonew == -2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
10812d61bbb3SSatish Balay 
10822d61bbb3SSatish Balay         /* Malloc new storage space */
10833f1db9ecSBarry Smith         len     = new_nz*(sizeof(int)+bs2*sizeof(MatScalar))+(a->mbs+1)*sizeof(int);
1084b0a32e0cSBarry Smith 	ierr    = PetscMalloc(len,&new_a);CHKERRQ(ierr);
10852d61bbb3SSatish Balay         new_j   = (int*)(new_a + bs2*new_nz);
10862d61bbb3SSatish Balay         new_i   = new_j + new_nz;
10872d61bbb3SSatish Balay 
10882d61bbb3SSatish Balay         /* copy over old data into new slots */
10892d61bbb3SSatish Balay         for (ii=0; ii<brow+1; ii++) {new_i[ii] = ai[ii];}
10902d61bbb3SSatish Balay         for (ii=brow+1; ii<a->mbs+1; ii++) {new_i[ii] = ai[ii]+CHUNKSIZE;}
1091549d3d68SSatish Balay         ierr = PetscMemcpy(new_j,aj,(ai[brow]+nrow)*sizeof(int));CHKERRQ(ierr);
10922d61bbb3SSatish Balay         len  = (new_nz - CHUNKSIZE - ai[brow] - nrow);
1093549d3d68SSatish Balay         ierr = PetscMemcpy(new_j+ai[brow]+nrow+CHUNKSIZE,aj+ai[brow]+nrow,len*sizeof(int));CHKERRQ(ierr);
1094549d3d68SSatish Balay         ierr = PetscMemcpy(new_a,aa,(ai[brow]+nrow)*bs2*sizeof(MatScalar));CHKERRQ(ierr);
1095549d3d68SSatish Balay         ierr = PetscMemzero(new_a+bs2*(ai[brow]+nrow),bs2*CHUNKSIZE*sizeof(MatScalar));CHKERRQ(ierr);
1096549d3d68SSatish Balay         ierr = PetscMemcpy(new_a+bs2*(ai[brow]+nrow+CHUNKSIZE),aa+bs2*(ai[brow]+nrow),bs2*len*sizeof(MatScalar));CHKERRQ(ierr);
10972d61bbb3SSatish Balay         /* free up old matrix storage */
1098606d414cSSatish Balay         ierr = PetscFree(a->a);CHKERRQ(ierr);
1099606d414cSSatish Balay         if (!a->singlemalloc) {
1100606d414cSSatish Balay           ierr = PetscFree(a->i);CHKERRQ(ierr);
1101606d414cSSatish Balay           ierr = PetscFree(a->j);CHKERRQ(ierr);
1102606d414cSSatish Balay         }
11032d61bbb3SSatish Balay         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;
1104c4992f7dSBarry Smith         a->singlemalloc = PETSC_TRUE;
11052d61bbb3SSatish Balay 
11062d61bbb3SSatish Balay         rp   = aj + ai[brow]; ap = aa + bs2*ai[brow];
11072d61bbb3SSatish Balay         rmax = imax[brow] = imax[brow] + CHUNKSIZE;
1108b0a32e0cSBarry Smith         PetscLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + bs2*sizeof(MatScalar)));
11092d61bbb3SSatish Balay         a->maxnz += bs2*CHUNKSIZE;
11102d61bbb3SSatish Balay         a->reallocs++;
11112d61bbb3SSatish Balay         a->nz++;
11122d61bbb3SSatish Balay       }
11132d61bbb3SSatish Balay       N = nrow++ - 1;
11142d61bbb3SSatish Balay       /* shift up all the later entries in this row */
11152d61bbb3SSatish Balay       for (ii=N; ii>=i; ii--) {
11162d61bbb3SSatish Balay         rp[ii+1] = rp[ii];
1117549d3d68SSatish Balay         ierr     = PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));CHKERRQ(ierr);
11182d61bbb3SSatish Balay       }
1119549d3d68SSatish Balay       if (N>=i) {
1120549d3d68SSatish Balay         ierr = PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));CHKERRQ(ierr);
1121549d3d68SSatish Balay       }
11222d61bbb3SSatish Balay       rp[i]                      = bcol;
11232d61bbb3SSatish Balay       ap[bs2*i + bs*cidx + ridx] = value;
11242d61bbb3SSatish Balay       noinsert1:;
11252d61bbb3SSatish Balay       low = i;
11262d61bbb3SSatish Balay     }
11272d61bbb3SSatish Balay     ailen[brow] = nrow;
11282d61bbb3SSatish Balay   }
11292d61bbb3SSatish Balay   PetscFunctionReturn(0);
11302d61bbb3SSatish Balay }
11312d61bbb3SSatish Balay 
11322d61bbb3SSatish Balay 
11334a2ae208SSatish Balay #undef __FUNCT__
11344a2ae208SSatish Balay #define __FUNCT__ "MatILUFactor_SeqBAIJ"
11355ef9f2a5SBarry Smith int MatILUFactor_SeqBAIJ(Mat inA,IS row,IS col,MatILUInfo *info)
11362d61bbb3SSatish Balay {
11372d61bbb3SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)inA->data;
11382d61bbb3SSatish Balay   Mat         outA;
11392d61bbb3SSatish Balay   int         ierr;
1140667159a5SBarry Smith   PetscTruth  row_identity,col_identity;
11412d61bbb3SSatish Balay 
11422d61bbb3SSatish Balay   PetscFunctionBegin;
114329bbc08cSBarry Smith   if (info && info->levels != 0) SETERRQ(PETSC_ERR_SUP,"Only levels = 0 supported for in-place ILU");
1144667159a5SBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
1145667159a5SBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
1146667159a5SBarry Smith   if (!row_identity || !col_identity) {
114729bbc08cSBarry Smith     SETERRQ(1,"Row and column permutations must be identity for in-place ILU");
1148667159a5SBarry Smith   }
11492d61bbb3SSatish Balay 
11502d61bbb3SSatish Balay   outA          = inA;
11512d61bbb3SSatish Balay   inA->factor   = FACTOR_LU;
11522d61bbb3SSatish Balay 
11532d61bbb3SSatish Balay   if (!a->diag) {
1154c4992f7dSBarry Smith     ierr = MatMarkDiagonal_SeqBAIJ(inA);CHKERRQ(ierr);
11552d61bbb3SSatish Balay   }
1156cf242676SKris Buschelman 
1157c38d4ed2SBarry Smith   a->row        = row;
1158c38d4ed2SBarry Smith   a->col        = col;
1159c38d4ed2SBarry Smith   ierr          = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
1160c38d4ed2SBarry Smith   ierr          = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
1161c38d4ed2SBarry Smith 
1162c38d4ed2SBarry Smith   /* Create the invert permutation so that it can be used in MatLUFactorNumeric() */
11634c49b128SBarry Smith   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
1164b0a32e0cSBarry Smith   PetscLogObjectParent(inA,a->icol);
1165c38d4ed2SBarry Smith 
1166cf242676SKris Buschelman   /*
1167cf242676SKris Buschelman       Blocksize 2, 3, 4, 5, 6 and 7 have a special faster factorization/solver
1168cf242676SKris Buschelman       for ILU(0) factorization with natural ordering
1169cf242676SKris Buschelman   */
1170cf242676SKris Buschelman   if (a->bs < 8) {
1171cf242676SKris Buschelman     ierr = MatSeqBAIJ_UpdateFactorNumeric_NaturalOrdering(inA);CHKERRQ(ierr);
1172cf242676SKris Buschelman   } else {
1173c38d4ed2SBarry Smith     if (!a->solve_work) {
117487828ca2SBarry Smith       ierr = PetscMalloc((inA->m+a->bs)*sizeof(PetscScalar),&a->solve_work);CHKERRQ(ierr);
117587828ca2SBarry Smith       PetscLogObjectMemory(inA,(inA->m+a->bs)*sizeof(PetscScalar));
1176c38d4ed2SBarry Smith     }
11772d61bbb3SSatish Balay   }
11782d61bbb3SSatish Balay 
1179667159a5SBarry Smith   ierr = MatLUFactorNumeric(inA,&outA);CHKERRQ(ierr);
1180667159a5SBarry Smith 
11812d61bbb3SSatish Balay   PetscFunctionReturn(0);
11822d61bbb3SSatish Balay }
11834a2ae208SSatish Balay #undef __FUNCT__
11844a2ae208SSatish Balay #define __FUNCT__ "MatPrintHelp_SeqBAIJ"
1185ba4ca20aSSatish Balay int MatPrintHelp_SeqBAIJ(Mat A)
1186ba4ca20aSSatish Balay {
1187c38d4ed2SBarry Smith   static PetscTruth called = PETSC_FALSE;
1188ba4ca20aSSatish Balay   MPI_Comm          comm = A->comm;
1189d132466eSBarry Smith   int               ierr;
1190ba4ca20aSSatish Balay 
11913a40ed3dSBarry Smith   PetscFunctionBegin;
1192c38d4ed2SBarry Smith   if (called) {PetscFunctionReturn(0);} else called = PETSC_TRUE;
1193d132466eSBarry Smith   ierr = (*PetscHelpPrintf)(comm," Options for MATSEQBAIJ and MATMPIBAIJ matrix formats (the defaults):\n");CHKERRQ(ierr);
1194d132466eSBarry Smith   ierr = (*PetscHelpPrintf)(comm,"  -mat_block_size <block_size>\n");CHKERRQ(ierr);
11953a40ed3dSBarry Smith   PetscFunctionReturn(0);
1196ba4ca20aSSatish Balay }
1197d9b7c43dSSatish Balay 
1198fb2e594dSBarry Smith EXTERN_C_BEGIN
11994a2ae208SSatish Balay #undef __FUNCT__
12004a2ae208SSatish Balay #define __FUNCT__ "MatSeqBAIJSetColumnIndices_SeqBAIJ"
120127a8da17SBarry Smith int MatSeqBAIJSetColumnIndices_SeqBAIJ(Mat mat,int *indices)
120227a8da17SBarry Smith {
120327a8da17SBarry Smith   Mat_SeqBAIJ *baij = (Mat_SeqBAIJ *)mat->data;
120414db4f74SSatish Balay   int         i,nz,nbs;
120527a8da17SBarry Smith 
120627a8da17SBarry Smith   PetscFunctionBegin;
120714db4f74SSatish Balay   nz  = baij->maxnz/baij->bs2;
120814db4f74SSatish Balay   nbs = baij->nbs;
120927a8da17SBarry Smith   for (i=0; i<nz; i++) {
121027a8da17SBarry Smith     baij->j[i] = indices[i];
121127a8da17SBarry Smith   }
121227a8da17SBarry Smith   baij->nz = nz;
121314db4f74SSatish Balay   for (i=0; i<nbs; i++) {
121427a8da17SBarry Smith     baij->ilen[i] = baij->imax[i];
121527a8da17SBarry Smith   }
121627a8da17SBarry Smith 
121727a8da17SBarry Smith   PetscFunctionReturn(0);
121827a8da17SBarry Smith }
1219fb2e594dSBarry Smith EXTERN_C_END
122027a8da17SBarry Smith 
12214a2ae208SSatish Balay #undef __FUNCT__
12224a2ae208SSatish Balay #define __FUNCT__ "MatSeqBAIJSetColumnIndices"
122327a8da17SBarry Smith /*@
122427a8da17SBarry Smith     MatSeqBAIJSetColumnIndices - Set the column indices for all the rows
122527a8da17SBarry Smith        in the matrix.
122627a8da17SBarry Smith 
122727a8da17SBarry Smith   Input Parameters:
122827a8da17SBarry Smith +  mat - the SeqBAIJ matrix
122927a8da17SBarry Smith -  indices - the column indices
123027a8da17SBarry Smith 
123115091d37SBarry Smith   Level: advanced
123215091d37SBarry Smith 
123327a8da17SBarry Smith   Notes:
123427a8da17SBarry Smith     This can be called if you have precomputed the nonzero structure of the
123527a8da17SBarry Smith   matrix and want to provide it to the matrix object to improve the performance
123627a8da17SBarry Smith   of the MatSetValues() operation.
123727a8da17SBarry Smith 
123827a8da17SBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
123927a8da17SBarry Smith   MatCreateSeqBAIJ().
124027a8da17SBarry Smith 
124127a8da17SBarry Smith     MUST be called before any calls to MatSetValues();
124227a8da17SBarry Smith 
124327a8da17SBarry Smith @*/
124427a8da17SBarry Smith int MatSeqBAIJSetColumnIndices(Mat mat,int *indices)
124527a8da17SBarry Smith {
124627a8da17SBarry Smith   int ierr,(*f)(Mat,int *);
124727a8da17SBarry Smith 
124827a8da17SBarry Smith   PetscFunctionBegin;
124927a8da17SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1250c134de8dSSatish Balay   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqBAIJSetColumnIndices_C",(void (**)(void))&f);CHKERRQ(ierr);
125127a8da17SBarry Smith   if (f) {
125227a8da17SBarry Smith     ierr = (*f)(mat,indices);CHKERRQ(ierr);
125327a8da17SBarry Smith   } else {
125429bbc08cSBarry Smith     SETERRQ(1,"Wrong type of matrix to set column indices");
125527a8da17SBarry Smith   }
125627a8da17SBarry Smith   PetscFunctionReturn(0);
125727a8da17SBarry Smith }
125827a8da17SBarry Smith 
12594a2ae208SSatish Balay #undef __FUNCT__
12604a2ae208SSatish Balay #define __FUNCT__ "MatGetRowMax_SeqBAIJ"
1261273d9f13SBarry Smith int MatGetRowMax_SeqBAIJ(Mat A,Vec v)
1262273d9f13SBarry Smith {
1263273d9f13SBarry Smith   Mat_SeqBAIJ  *a = (Mat_SeqBAIJ*)A->data;
1264273d9f13SBarry Smith   int          ierr,i,j,n,row,bs,*ai,*aj,mbs;
1265273d9f13SBarry Smith   PetscReal    atmp;
126687828ca2SBarry Smith   PetscScalar  *x,zero = 0.0;
1267273d9f13SBarry Smith   MatScalar    *aa;
1268273d9f13SBarry Smith   int          ncols,brow,krow,kcol;
1269273d9f13SBarry Smith 
1270273d9f13SBarry Smith   PetscFunctionBegin;
1271273d9f13SBarry Smith   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1272273d9f13SBarry Smith   bs   = a->bs;
1273273d9f13SBarry Smith   aa   = a->a;
1274273d9f13SBarry Smith   ai   = a->i;
1275273d9f13SBarry Smith   aj   = a->j;
1276273d9f13SBarry Smith   mbs = a->mbs;
1277273d9f13SBarry Smith 
1278273d9f13SBarry Smith   ierr = VecSet(&zero,v);CHKERRQ(ierr);
1279273d9f13SBarry Smith   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1280273d9f13SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1281273d9f13SBarry Smith   if (n != A->m) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1282273d9f13SBarry Smith   for (i=0; i<mbs; i++) {
1283273d9f13SBarry Smith     ncols = ai[1] - ai[0]; ai++;
1284273d9f13SBarry Smith     brow  = bs*i;
1285273d9f13SBarry Smith     for (j=0; j<ncols; j++){
1286273d9f13SBarry Smith       /* bcol = bs*(*aj); */
1287273d9f13SBarry Smith       for (kcol=0; kcol<bs; kcol++){
1288273d9f13SBarry Smith         for (krow=0; krow<bs; krow++){
1289273d9f13SBarry Smith           atmp = PetscAbsScalar(*aa); aa++;
1290273d9f13SBarry Smith           row = brow + krow;    /* row index */
1291273d9f13SBarry Smith           /* printf("val[%d,%d]: %g\n",row,bcol+kcol,atmp); */
1292273d9f13SBarry Smith           if (PetscAbsScalar(x[row]) < atmp) x[row] = atmp;
1293273d9f13SBarry Smith         }
1294273d9f13SBarry Smith       }
1295273d9f13SBarry Smith       aj++;
1296273d9f13SBarry Smith     }
1297273d9f13SBarry Smith   }
1298273d9f13SBarry Smith   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1299273d9f13SBarry Smith   PetscFunctionReturn(0);
1300273d9f13SBarry Smith }
1301273d9f13SBarry Smith 
13024a2ae208SSatish Balay #undef __FUNCT__
13034a2ae208SSatish Balay #define __FUNCT__ "MatSetUpPreallocation_SeqBAIJ"
1304273d9f13SBarry Smith int MatSetUpPreallocation_SeqBAIJ(Mat A)
1305273d9f13SBarry Smith {
1306273d9f13SBarry Smith   int        ierr;
1307273d9f13SBarry Smith 
1308273d9f13SBarry Smith   PetscFunctionBegin;
1309273d9f13SBarry Smith   ierr =  MatSeqBAIJSetPreallocation(A,1,PETSC_DEFAULT,0);CHKERRQ(ierr);
1310273d9f13SBarry Smith   PetscFunctionReturn(0);
1311273d9f13SBarry Smith }
1312273d9f13SBarry Smith 
13134a2ae208SSatish Balay #undef __FUNCT__
13144a2ae208SSatish Balay #define __FUNCT__ "MatGetArray_SeqBAIJ"
131587828ca2SBarry Smith int MatGetArray_SeqBAIJ(Mat A,PetscScalar **array)
1316f2a5309cSSatish Balay {
1317f2a5309cSSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
1318f2a5309cSSatish Balay   PetscFunctionBegin;
1319f2a5309cSSatish Balay   *array = a->a;
1320f2a5309cSSatish Balay   PetscFunctionReturn(0);
1321f2a5309cSSatish Balay }
1322f2a5309cSSatish Balay 
13234a2ae208SSatish Balay #undef __FUNCT__
13244a2ae208SSatish Balay #define __FUNCT__ "MatRestoreArray_SeqBAIJ"
132587828ca2SBarry Smith int MatRestoreArray_SeqBAIJ(Mat A,PetscScalar **array)
1326f2a5309cSSatish Balay {
1327f2a5309cSSatish Balay   PetscFunctionBegin;
1328f2a5309cSSatish Balay   PetscFunctionReturn(0);
1329f2a5309cSSatish Balay }
1330f2a5309cSSatish Balay 
13312593348eSBarry Smith /* -------------------------------------------------------------------*/
1332cc2dc46cSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqBAIJ,
1333cc2dc46cSBarry Smith        MatGetRow_SeqBAIJ,
1334cc2dc46cSBarry Smith        MatRestoreRow_SeqBAIJ,
1335cc2dc46cSBarry Smith        MatMult_SeqBAIJ_N,
1336cc2dc46cSBarry Smith        MatMultAdd_SeqBAIJ_N,
13377c922b88SBarry Smith        MatMultTranspose_SeqBAIJ,
13387c922b88SBarry Smith        MatMultTransposeAdd_SeqBAIJ,
1339cc2dc46cSBarry Smith        MatSolve_SeqBAIJ_N,
1340cc2dc46cSBarry Smith        0,
1341cc2dc46cSBarry Smith        0,
1342cc2dc46cSBarry Smith        0,
1343cc2dc46cSBarry Smith        MatLUFactor_SeqBAIJ,
1344cc2dc46cSBarry Smith        0,
1345b6490206SBarry Smith        0,
1346f2501298SSatish Balay        MatTranspose_SeqBAIJ,
1347cc2dc46cSBarry Smith        MatGetInfo_SeqBAIJ,
1348cc2dc46cSBarry Smith        MatEqual_SeqBAIJ,
1349cc2dc46cSBarry Smith        MatGetDiagonal_SeqBAIJ,
1350cc2dc46cSBarry Smith        MatDiagonalScale_SeqBAIJ,
1351cc2dc46cSBarry Smith        MatNorm_SeqBAIJ,
1352b6490206SBarry Smith        0,
1353cc2dc46cSBarry Smith        MatAssemblyEnd_SeqBAIJ,
1354cc2dc46cSBarry Smith        0,
1355cc2dc46cSBarry Smith        MatSetOption_SeqBAIJ,
1356cc2dc46cSBarry Smith        MatZeroEntries_SeqBAIJ,
1357cc2dc46cSBarry Smith        MatZeroRows_SeqBAIJ,
1358cc2dc46cSBarry Smith        MatLUFactorSymbolic_SeqBAIJ,
1359cc2dc46cSBarry Smith        MatLUFactorNumeric_SeqBAIJ_N,
1360cc2dc46cSBarry Smith        0,
1361cc2dc46cSBarry Smith        0,
1362273d9f13SBarry Smith        MatSetUpPreallocation_SeqBAIJ,
1363cc2dc46cSBarry Smith        MatILUFactorSymbolic_SeqBAIJ,
1364cc2dc46cSBarry Smith        0,
1365f2a5309cSSatish Balay        MatGetArray_SeqBAIJ,
1366f2a5309cSSatish Balay        MatRestoreArray_SeqBAIJ,
13672e8a6d31SBarry Smith        MatDuplicate_SeqBAIJ,
1368cc2dc46cSBarry Smith        0,
1369cc2dc46cSBarry Smith        0,
1370cc2dc46cSBarry Smith        MatILUFactor_SeqBAIJ,
1371cc2dc46cSBarry Smith        0,
1372cc2dc46cSBarry Smith        0,
1373cc2dc46cSBarry Smith        MatGetSubMatrices_SeqBAIJ,
1374cc2dc46cSBarry Smith        MatIncreaseOverlap_SeqBAIJ,
1375cc2dc46cSBarry Smith        MatGetValues_SeqBAIJ,
1376cc2dc46cSBarry Smith        0,
1377cc2dc46cSBarry Smith        MatPrintHelp_SeqBAIJ,
1378cc2dc46cSBarry Smith        MatScale_SeqBAIJ,
1379cc2dc46cSBarry Smith        0,
1380cc2dc46cSBarry Smith        0,
1381cc2dc46cSBarry Smith        0,
1382cc2dc46cSBarry Smith        MatGetBlockSize_SeqBAIJ,
13833b2fbd54SBarry Smith        MatGetRowIJ_SeqBAIJ,
138492c4ed94SBarry Smith        MatRestoreRowIJ_SeqBAIJ,
1385cc2dc46cSBarry Smith        0,
1386cc2dc46cSBarry Smith        0,
1387cc2dc46cSBarry Smith        0,
1388cc2dc46cSBarry Smith        0,
1389cc2dc46cSBarry Smith        0,
1390cc2dc46cSBarry Smith        0,
1391d3825aa8SBarry Smith        MatSetValuesBlocked_SeqBAIJ,
1392cc2dc46cSBarry Smith        MatGetSubMatrix_SeqBAIJ,
1393b9b97703SBarry Smith        MatDestroy_SeqBAIJ,
1394b9b97703SBarry Smith        MatView_SeqBAIJ,
13953a64cc32SBarry Smith        MatGetPetscMaps_Petsc,
1396273d9f13SBarry Smith        0,
1397273d9f13SBarry Smith        0,
1398273d9f13SBarry Smith        0,
1399273d9f13SBarry Smith        0,
1400273d9f13SBarry Smith        0,
1401273d9f13SBarry Smith        0,
1402273d9f13SBarry Smith        MatGetRowMax_SeqBAIJ,
1403273d9f13SBarry Smith        MatConvert_Basic};
14042593348eSBarry Smith 
14053e90b805SBarry Smith EXTERN_C_BEGIN
14064a2ae208SSatish Balay #undef __FUNCT__
14074a2ae208SSatish Balay #define __FUNCT__ "MatStoreValues_SeqBAIJ"
14083e90b805SBarry Smith int MatStoreValues_SeqBAIJ(Mat mat)
14093e90b805SBarry Smith {
14103e90b805SBarry Smith   Mat_SeqBAIJ *aij = (Mat_SeqBAIJ *)mat->data;
1411273d9f13SBarry Smith   int         nz = aij->i[mat->m]*aij->bs*aij->bs2;
1412d132466eSBarry Smith   int         ierr;
14133e90b805SBarry Smith 
14143e90b805SBarry Smith   PetscFunctionBegin;
14153e90b805SBarry Smith   if (aij->nonew != 1) {
141629bbc08cSBarry Smith     SETERRQ(1,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first");
14173e90b805SBarry Smith   }
14183e90b805SBarry Smith 
14193e90b805SBarry Smith   /* allocate space for values if not already there */
14203e90b805SBarry Smith   if (!aij->saved_values) {
142187828ca2SBarry Smith     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr);
14223e90b805SBarry Smith   }
14233e90b805SBarry Smith 
14243e90b805SBarry Smith   /* copy values over */
142587828ca2SBarry Smith   ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr);
14263e90b805SBarry Smith   PetscFunctionReturn(0);
14273e90b805SBarry Smith }
14283e90b805SBarry Smith EXTERN_C_END
14293e90b805SBarry Smith 
14303e90b805SBarry Smith EXTERN_C_BEGIN
14314a2ae208SSatish Balay #undef __FUNCT__
14324a2ae208SSatish Balay #define __FUNCT__ "MatRetrieveValues_SeqBAIJ"
143332e87ba3SBarry Smith int MatRetrieveValues_SeqBAIJ(Mat mat)
14343e90b805SBarry Smith {
14353e90b805SBarry Smith   Mat_SeqBAIJ *aij = (Mat_SeqBAIJ *)mat->data;
1436273d9f13SBarry Smith   int         nz = aij->i[mat->m]*aij->bs*aij->bs2,ierr;
14373e90b805SBarry Smith 
14383e90b805SBarry Smith   PetscFunctionBegin;
14393e90b805SBarry Smith   if (aij->nonew != 1) {
144029bbc08cSBarry Smith     SETERRQ(1,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first");
14413e90b805SBarry Smith   }
14423e90b805SBarry Smith   if (!aij->saved_values) {
144329bbc08cSBarry Smith     SETERRQ(1,"Must call MatStoreValues(A);first");
14443e90b805SBarry Smith   }
14453e90b805SBarry Smith 
14463e90b805SBarry Smith   /* copy values over */
144787828ca2SBarry Smith   ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr);
14483e90b805SBarry Smith   PetscFunctionReturn(0);
14493e90b805SBarry Smith }
14503e90b805SBarry Smith EXTERN_C_END
14513e90b805SBarry Smith 
1452273d9f13SBarry Smith EXTERN_C_BEGIN
1453273d9f13SBarry Smith extern int MatConvert_SeqBAIJ_SeqAIJ(Mat,MatType,Mat*);
1454273d9f13SBarry Smith EXTERN_C_END
1455273d9f13SBarry Smith 
1456273d9f13SBarry Smith EXTERN_C_BEGIN
14574a2ae208SSatish Balay #undef __FUNCT__
14584a2ae208SSatish Balay #define __FUNCT__ "MatCreate_SeqBAIJ"
1459273d9f13SBarry Smith int MatCreate_SeqBAIJ(Mat B)
14602593348eSBarry Smith {
1461273d9f13SBarry Smith   int         ierr,size;
1462b6490206SBarry Smith   Mat_SeqBAIJ *b;
14633b2fbd54SBarry Smith 
14643a40ed3dSBarry Smith   PetscFunctionBegin;
1465273d9f13SBarry Smith   ierr = MPI_Comm_size(B->comm,&size);CHKERRQ(ierr);
146629bbc08cSBarry Smith   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"Comm must be of size 1");
1467b6490206SBarry Smith 
1468273d9f13SBarry Smith   B->m = B->M = PetscMax(B->m,B->M);
1469273d9f13SBarry Smith   B->n = B->N = PetscMax(B->n,B->N);
1470b0a32e0cSBarry Smith   ierr    = PetscNew(Mat_SeqBAIJ,&b);CHKERRQ(ierr);
1471b0a32e0cSBarry Smith   B->data = (void*)b;
1472549d3d68SSatish Balay   ierr    = PetscMemzero(b,sizeof(Mat_SeqBAIJ));CHKERRQ(ierr);
1473549d3d68SSatish Balay   ierr    = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
14742593348eSBarry Smith   B->factor           = 0;
14752593348eSBarry Smith   B->lupivotthreshold = 1.0;
147690f02eecSBarry Smith   B->mapping          = 0;
14772593348eSBarry Smith   b->row              = 0;
14782593348eSBarry Smith   b->col              = 0;
1479e51c0b9cSSatish Balay   b->icol             = 0;
14802593348eSBarry Smith   b->reallocs         = 0;
14813e90b805SBarry Smith   b->saved_values     = 0;
1482cfce73b9SSatish Balay #if defined(PETSC_USE_MAT_SINGLE)
1483563b5814SBarry Smith   b->setvalueslen     = 0;
1484563b5814SBarry Smith   b->setvaluescopy    = PETSC_NULL;
1485563b5814SBarry Smith #endif
14868661488fSKris Buschelman   b->single_precision_solves = PETSC_FALSE;
14872593348eSBarry Smith 
14883a64cc32SBarry Smith   ierr = PetscMapCreateMPI(B->comm,B->m,B->m,&B->rmap);CHKERRQ(ierr);
14893a64cc32SBarry Smith   ierr = PetscMapCreateMPI(B->comm,B->n,B->n,&B->cmap);CHKERRQ(ierr);
1490a5ae1ecdSBarry Smith 
1491c4992f7dSBarry Smith   b->sorted           = PETSC_FALSE;
1492c4992f7dSBarry Smith   b->roworiented      = PETSC_TRUE;
14932593348eSBarry Smith   b->nonew            = 0;
14942593348eSBarry Smith   b->diag             = 0;
14952593348eSBarry Smith   b->solve_work       = 0;
1496de6a44a3SBarry Smith   b->mult_work        = 0;
1497*2a1b7f2aSHong Zhang   B->spptr            = 0;
14980e6d2581SBarry Smith   B->info.nz_unneeded = (PetscReal)b->maxnz;
1499883fce79SBarry Smith   b->keepzeroedrows   = PETSC_FALSE;
15004e220ebcSLois Curfman McInnes 
1501f1af5d2fSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
15023e90b805SBarry Smith                                      "MatStoreValues_SeqBAIJ",
1503bc4b532fSSatish Balay                                       MatStoreValues_SeqBAIJ);CHKERRQ(ierr);
1504f1af5d2fSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
15053e90b805SBarry Smith                                      "MatRetrieveValues_SeqBAIJ",
1506bc4b532fSSatish Balay                                       MatRetrieveValues_SeqBAIJ);CHKERRQ(ierr);
1507f1af5d2fSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqBAIJSetColumnIndices_C",
150827a8da17SBarry Smith                                      "MatSeqBAIJSetColumnIndices_SeqBAIJ",
1509bc4b532fSSatish Balay                                       MatSeqBAIJSetColumnIndices_SeqBAIJ);CHKERRQ(ierr);
1510273d9f13SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_SeqBAIJ_SeqAIJ_C",
1511273d9f13SBarry Smith                                      "MatConvert_SeqBAIJ_SeqAIJ",
1512273d9f13SBarry Smith                                       MatConvert_SeqBAIJ_SeqAIJ);CHKERRQ(ierr);
15133a40ed3dSBarry Smith   PetscFunctionReturn(0);
15142593348eSBarry Smith }
1515273d9f13SBarry Smith EXTERN_C_END
15162593348eSBarry Smith 
15174a2ae208SSatish Balay #undef __FUNCT__
15184a2ae208SSatish Balay #define __FUNCT__ "MatDuplicate_SeqBAIJ"
15192e8a6d31SBarry Smith int MatDuplicate_SeqBAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
15202593348eSBarry Smith {
15212593348eSBarry Smith   Mat         C;
1522b6490206SBarry Smith   Mat_SeqBAIJ *c,*a = (Mat_SeqBAIJ*)A->data;
152327a8da17SBarry Smith   int         i,len,mbs = a->mbs,nz = a->nz,bs2 =a->bs2,ierr;
1524de6a44a3SBarry Smith 
15253a40ed3dSBarry Smith   PetscFunctionBegin;
152629bbc08cSBarry Smith   if (a->i[mbs] != nz) SETERRQ(PETSC_ERR_PLIB,"Corrupt matrix");
15272593348eSBarry Smith 
15282593348eSBarry Smith   *B = 0;
1529273d9f13SBarry Smith   ierr = MatCreate(A->comm,A->m,A->n,A->m,A->n,&C);CHKERRQ(ierr);
1530273d9f13SBarry Smith   ierr = MatSetType(C,MATSEQBAIJ);CHKERRQ(ierr);
1531273d9f13SBarry Smith   c    = (Mat_SeqBAIJ*)C->data;
153244cd7ae7SLois Curfman McInnes 
1533b6490206SBarry Smith   c->bs         = a->bs;
15349df24120SSatish Balay   c->bs2        = a->bs2;
1535b6490206SBarry Smith   c->mbs        = a->mbs;
1536b6490206SBarry Smith   c->nbs        = a->nbs;
153735d8aa7fSBarry Smith   ierr = PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
15382593348eSBarry Smith 
1539b0a32e0cSBarry Smith   ierr = PetscMalloc((mbs+1)*sizeof(int),&c->imax);CHKERRQ(ierr);
1540b0a32e0cSBarry Smith   ierr = PetscMalloc((mbs+1)*sizeof(int),&c->ilen);CHKERRQ(ierr);
1541b6490206SBarry Smith   for (i=0; i<mbs; i++) {
15422593348eSBarry Smith     c->imax[i] = a->imax[i];
15432593348eSBarry Smith     c->ilen[i] = a->ilen[i];
15442593348eSBarry Smith   }
15452593348eSBarry Smith 
15462593348eSBarry Smith   /* allocate the matrix space */
1547c4992f7dSBarry Smith   c->singlemalloc = PETSC_TRUE;
15483f1db9ecSBarry Smith   len  = (mbs+1)*sizeof(int) + nz*(bs2*sizeof(MatScalar) + sizeof(int));
1549b0a32e0cSBarry Smith   ierr = PetscMalloc(len,&c->a);CHKERRQ(ierr);
15507e67e3f9SSatish Balay   c->j = (int*)(c->a + nz*bs2);
1551de6a44a3SBarry Smith   c->i = c->j + nz;
1552549d3d68SSatish Balay   ierr = PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(int));CHKERRQ(ierr);
1553b6490206SBarry Smith   if (mbs > 0) {
1554549d3d68SSatish Balay     ierr = PetscMemcpy(c->j,a->j,nz*sizeof(int));CHKERRQ(ierr);
15552e8a6d31SBarry Smith     if (cpvalues == MAT_COPY_VALUES) {
1556549d3d68SSatish Balay       ierr = PetscMemcpy(c->a,a->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr);
15572e8a6d31SBarry Smith     } else {
1558549d3d68SSatish Balay       ierr = PetscMemzero(c->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr);
15592593348eSBarry Smith     }
15602593348eSBarry Smith   }
15612593348eSBarry Smith 
1562b0a32e0cSBarry Smith   PetscLogObjectMemory(C,len+2*(mbs+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqBAIJ));
15632593348eSBarry Smith   c->sorted      = a->sorted;
15642593348eSBarry Smith   c->roworiented = a->roworiented;
15652593348eSBarry Smith   c->nonew       = a->nonew;
15662593348eSBarry Smith 
15672593348eSBarry Smith   if (a->diag) {
1568b0a32e0cSBarry Smith     ierr = PetscMalloc((mbs+1)*sizeof(int),&c->diag);CHKERRQ(ierr);
1569b0a32e0cSBarry Smith     PetscLogObjectMemory(C,(mbs+1)*sizeof(int));
1570b6490206SBarry Smith     for (i=0; i<mbs; i++) {
15712593348eSBarry Smith       c->diag[i] = a->diag[i];
15722593348eSBarry Smith     }
157398305bb5SBarry Smith   } else c->diag        = 0;
15742593348eSBarry Smith   c->nz                 = a->nz;
15752593348eSBarry Smith   c->maxnz              = a->maxnz;
15762593348eSBarry Smith   c->solve_work         = 0;
1577*2a1b7f2aSHong Zhang   C->spptr              = 0;     /* Dangerous -I'm throwing away a->spptr */
15787fc0212eSBarry Smith   c->mult_work          = 0;
1579273d9f13SBarry Smith   C->preallocated       = PETSC_TRUE;
1580273d9f13SBarry Smith   C->assembled          = PETSC_TRUE;
15812593348eSBarry Smith   *B = C;
1582b0a32e0cSBarry Smith   ierr = PetscFListDuplicate(A->qlist,&C->qlist);CHKERRQ(ierr);
15833a40ed3dSBarry Smith   PetscFunctionReturn(0);
15842593348eSBarry Smith }
15852593348eSBarry Smith 
1586273d9f13SBarry Smith EXTERN_C_BEGIN
15874a2ae208SSatish Balay #undef __FUNCT__
15884a2ae208SSatish Balay #define __FUNCT__ "MatLoad_SeqBAIJ"
1589b0a32e0cSBarry Smith int MatLoad_SeqBAIJ(PetscViewer viewer,MatType type,Mat *A)
15902593348eSBarry Smith {
1591b6490206SBarry Smith   Mat_SeqBAIJ  *a;
15922593348eSBarry Smith   Mat          B;
1593f1af5d2fSBarry Smith   int          i,nz,ierr,fd,header[4],size,*rowlengths=0,M,N,bs=1;
1594b6490206SBarry Smith   int          *mask,mbs,*jj,j,rowcount,nzcount,k,*browlengths,maskcount;
159535aab85fSBarry Smith   int          kmax,jcount,block,idx,point,nzcountb,extra_rows;
1596a7c10996SSatish Balay   int          *masked,nmask,tmp,bs2,ishift;
159787828ca2SBarry Smith   PetscScalar  *aa;
159819bcc07fSBarry Smith   MPI_Comm     comm = ((PetscObject)viewer)->comm;
15992593348eSBarry Smith 
16003a40ed3dSBarry Smith   PetscFunctionBegin;
1601b0a32e0cSBarry Smith   ierr = PetscOptionsGetInt(PETSC_NULL,"-matload_block_size",&bs,PETSC_NULL);CHKERRQ(ierr);
1602de6a44a3SBarry Smith   bs2  = bs*bs;
1603b6490206SBarry Smith 
1604d132466eSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
160529bbc08cSBarry Smith   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"view must have one processor");
1606b0a32e0cSBarry Smith   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
16070752156aSBarry Smith   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
1608552e946dSBarry Smith   if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not Mat object");
16092593348eSBarry Smith   M = header[1]; N = header[2]; nz = header[3];
16102593348eSBarry Smith 
1611d64ed03dSBarry Smith   if (header[3] < 0) {
161229bbc08cSBarry Smith     SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format, cannot load as SeqBAIJ");
1613d64ed03dSBarry Smith   }
1614d64ed03dSBarry Smith 
161529bbc08cSBarry Smith   if (M != N) SETERRQ(PETSC_ERR_SUP,"Can only do square matrices");
161635aab85fSBarry Smith 
161735aab85fSBarry Smith   /*
161835aab85fSBarry Smith      This code adds extra rows to make sure the number of rows is
161935aab85fSBarry Smith     divisible by the blocksize
162035aab85fSBarry Smith   */
1621b6490206SBarry Smith   mbs        = M/bs;
162235aab85fSBarry Smith   extra_rows = bs - M + bs*(mbs);
162335aab85fSBarry Smith   if (extra_rows == bs) extra_rows = 0;
162435aab85fSBarry Smith   else                  mbs++;
162535aab85fSBarry Smith   if (extra_rows) {
1626b0a32e0cSBarry Smith     PetscLogInfo(0,"MatLoad_SeqBAIJ:Padding loaded matrix to match blocksize\n");
162735aab85fSBarry Smith   }
1628b6490206SBarry Smith 
16292593348eSBarry Smith   /* read in row lengths */
1630b0a32e0cSBarry Smith   ierr = PetscMalloc((M+extra_rows)*sizeof(int),&rowlengths);CHKERRQ(ierr);
16310752156aSBarry Smith   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
163235aab85fSBarry Smith   for (i=0; i<extra_rows; i++) rowlengths[M+i] = 1;
16332593348eSBarry Smith 
1634b6490206SBarry Smith   /* read in column indices */
1635b0a32e0cSBarry Smith   ierr = PetscMalloc((nz+extra_rows)*sizeof(int),&jj);CHKERRQ(ierr);
16360752156aSBarry Smith   ierr = PetscBinaryRead(fd,jj,nz,PETSC_INT);CHKERRQ(ierr);
163735aab85fSBarry Smith   for (i=0; i<extra_rows; i++) jj[nz+i] = M+i;
1638b6490206SBarry Smith 
1639b6490206SBarry Smith   /* loop over row lengths determining block row lengths */
1640b0a32e0cSBarry Smith   ierr     = PetscMalloc(mbs*sizeof(int),&browlengths);CHKERRQ(ierr);
1641549d3d68SSatish Balay   ierr     = PetscMemzero(browlengths,mbs*sizeof(int));CHKERRQ(ierr);
1642b0a32e0cSBarry Smith   ierr     = PetscMalloc(2*mbs*sizeof(int),&mask);CHKERRQ(ierr);
1643549d3d68SSatish Balay   ierr     = PetscMemzero(mask,mbs*sizeof(int));CHKERRQ(ierr);
164435aab85fSBarry Smith   masked   = mask + mbs;
1645b6490206SBarry Smith   rowcount = 0; nzcount = 0;
1646b6490206SBarry Smith   for (i=0; i<mbs; i++) {
164735aab85fSBarry Smith     nmask = 0;
1648b6490206SBarry Smith     for (j=0; j<bs; j++) {
1649b6490206SBarry Smith       kmax = rowlengths[rowcount];
1650b6490206SBarry Smith       for (k=0; k<kmax; k++) {
165135aab85fSBarry Smith         tmp = jj[nzcount++]/bs;
165235aab85fSBarry Smith         if (!mask[tmp]) {masked[nmask++] = tmp; mask[tmp] = 1;}
1653b6490206SBarry Smith       }
1654b6490206SBarry Smith       rowcount++;
1655b6490206SBarry Smith     }
165635aab85fSBarry Smith     browlengths[i] += nmask;
165735aab85fSBarry Smith     /* zero out the mask elements we set */
165835aab85fSBarry Smith     for (j=0; j<nmask; j++) mask[masked[j]] = 0;
1659b6490206SBarry Smith   }
1660b6490206SBarry Smith 
16612593348eSBarry Smith   /* create our matrix */
16623eee16b0SBarry Smith   ierr = MatCreateSeqBAIJ(comm,bs,M+extra_rows,N+extra_rows,0,browlengths,A);CHKERRQ(ierr);
16632593348eSBarry Smith   B = *A;
1664b6490206SBarry Smith   a = (Mat_SeqBAIJ*)B->data;
16652593348eSBarry Smith 
16662593348eSBarry Smith   /* set matrix "i" values */
1667de6a44a3SBarry Smith   a->i[0] = 0;
1668b6490206SBarry Smith   for (i=1; i<= mbs; i++) {
1669b6490206SBarry Smith     a->i[i]      = a->i[i-1] + browlengths[i-1];
1670b6490206SBarry Smith     a->ilen[i-1] = browlengths[i-1];
16712593348eSBarry Smith   }
1672b6490206SBarry Smith   a->nz         = 0;
1673b6490206SBarry Smith   for (i=0; i<mbs; i++) a->nz += browlengths[i];
16742593348eSBarry Smith 
1675b6490206SBarry Smith   /* read in nonzero values */
167687828ca2SBarry Smith   ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscScalar),&aa);CHKERRQ(ierr);
16770752156aSBarry Smith   ierr = PetscBinaryRead(fd,aa,nz,PETSC_SCALAR);CHKERRQ(ierr);
167835aab85fSBarry Smith   for (i=0; i<extra_rows; i++) aa[nz+i] = 1.0;
1679b6490206SBarry Smith 
1680b6490206SBarry Smith   /* set "a" and "j" values into matrix */
1681b6490206SBarry Smith   nzcount = 0; jcount = 0;
1682b6490206SBarry Smith   for (i=0; i<mbs; i++) {
1683b6490206SBarry Smith     nzcountb = nzcount;
168435aab85fSBarry Smith     nmask    = 0;
1685b6490206SBarry Smith     for (j=0; j<bs; j++) {
1686b6490206SBarry Smith       kmax = rowlengths[i*bs+j];
1687b6490206SBarry Smith       for (k=0; k<kmax; k++) {
168835aab85fSBarry Smith         tmp = jj[nzcount++]/bs;
168935aab85fSBarry Smith 	if (!mask[tmp]) { masked[nmask++] = tmp; mask[tmp] = 1;}
1690b6490206SBarry Smith       }
1691b6490206SBarry Smith     }
1692de6a44a3SBarry Smith     /* sort the masked values */
1693433994e6SBarry Smith     ierr = PetscSortInt(nmask,masked);CHKERRQ(ierr);
1694de6a44a3SBarry Smith 
1695b6490206SBarry Smith     /* set "j" values into matrix */
1696b6490206SBarry Smith     maskcount = 1;
169735aab85fSBarry Smith     for (j=0; j<nmask; j++) {
169835aab85fSBarry Smith       a->j[jcount++]  = masked[j];
1699de6a44a3SBarry Smith       mask[masked[j]] = maskcount++;
1700b6490206SBarry Smith     }
1701b6490206SBarry Smith     /* set "a" values into matrix */
1702de6a44a3SBarry Smith     ishift = bs2*a->i[i];
1703b6490206SBarry Smith     for (j=0; j<bs; j++) {
1704b6490206SBarry Smith       kmax = rowlengths[i*bs+j];
1705b6490206SBarry Smith       for (k=0; k<kmax; k++) {
1706de6a44a3SBarry Smith         tmp       = jj[nzcountb]/bs ;
1707de6a44a3SBarry Smith         block     = mask[tmp] - 1;
1708de6a44a3SBarry Smith         point     = jj[nzcountb] - bs*tmp;
1709de6a44a3SBarry Smith         idx       = ishift + bs2*block + j + bs*point;
1710375fe846SBarry Smith         a->a[idx] = (MatScalar)aa[nzcountb++];
1711b6490206SBarry Smith       }
1712b6490206SBarry Smith     }
171335aab85fSBarry Smith     /* zero out the mask elements we set */
171435aab85fSBarry Smith     for (j=0; j<nmask; j++) mask[masked[j]] = 0;
1715b6490206SBarry Smith   }
171629bbc08cSBarry Smith   if (jcount != a->nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Bad binary matrix");
1717b6490206SBarry Smith 
1718606d414cSSatish Balay   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
1719606d414cSSatish Balay   ierr = PetscFree(browlengths);CHKERRQ(ierr);
1720606d414cSSatish Balay   ierr = PetscFree(aa);CHKERRQ(ierr);
1721606d414cSSatish Balay   ierr = PetscFree(jj);CHKERRQ(ierr);
1722606d414cSSatish Balay   ierr = PetscFree(mask);CHKERRQ(ierr);
1723b6490206SBarry Smith 
1724b6490206SBarry Smith   B->assembled = PETSC_TRUE;
1725de6a44a3SBarry Smith 
17269c01be13SBarry Smith   ierr = MatView_Private(B);CHKERRQ(ierr);
17273a40ed3dSBarry Smith   PetscFunctionReturn(0);
17282593348eSBarry Smith }
1729273d9f13SBarry Smith EXTERN_C_END
17302593348eSBarry Smith 
17314a2ae208SSatish Balay #undef __FUNCT__
17324a2ae208SSatish Balay #define __FUNCT__ "MatCreateSeqBAIJ"
1733273d9f13SBarry Smith /*@C
1734273d9f13SBarry Smith    MatCreateSeqBAIJ - Creates a sparse matrix in block AIJ (block
1735273d9f13SBarry Smith    compressed row) format.  For good matrix assembly performance the
1736273d9f13SBarry Smith    user should preallocate the matrix storage by setting the parameter nz
1737273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
1738273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
17392593348eSBarry Smith 
1740273d9f13SBarry Smith    Collective on MPI_Comm
1741273d9f13SBarry Smith 
1742273d9f13SBarry Smith    Input Parameters:
1743273d9f13SBarry Smith +  comm - MPI communicator, set to PETSC_COMM_SELF
1744273d9f13SBarry Smith .  bs - size of block
1745273d9f13SBarry Smith .  m - number of rows
1746273d9f13SBarry Smith .  n - number of columns
174735d8aa7fSBarry Smith .  nz - number of nonzero blocks  per block row (same for all rows)
174835d8aa7fSBarry Smith -  nnz - array containing the number of nonzero blocks in the various block rows
1749273d9f13SBarry Smith          (possibly different for each block row) or PETSC_NULL
1750273d9f13SBarry Smith 
1751273d9f13SBarry Smith    Output Parameter:
1752273d9f13SBarry Smith .  A - the matrix
1753273d9f13SBarry Smith 
1754273d9f13SBarry Smith    Options Database Keys:
1755273d9f13SBarry Smith .   -mat_no_unroll - uses code that does not unroll the loops in the
1756273d9f13SBarry Smith                      block calculations (much slower)
1757273d9f13SBarry Smith .    -mat_block_size - size of the blocks to use
1758273d9f13SBarry Smith 
1759273d9f13SBarry Smith    Level: intermediate
1760273d9f13SBarry Smith 
1761273d9f13SBarry Smith    Notes:
176235d8aa7fSBarry Smith    A nonzero block is any block that as 1 or more nonzeros in it
176335d8aa7fSBarry Smith 
1764273d9f13SBarry Smith    The block AIJ format is fully compatible with standard Fortran 77
1765273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
1766273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
1767273d9f13SBarry Smith 
1768273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
1769273d9f13SBarry Smith    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
1770273d9f13SBarry Smith    allocation.  For additional details, see the users manual chapter on
1771273d9f13SBarry Smith    matrices.
1772273d9f13SBarry Smith 
1773273d9f13SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPIBAIJ()
1774273d9f13SBarry Smith @*/
1775273d9f13SBarry Smith int MatCreateSeqBAIJ(MPI_Comm comm,int bs,int m,int n,int nz,int *nnz,Mat *A)
1776273d9f13SBarry Smith {
1777273d9f13SBarry Smith   int ierr;
1778273d9f13SBarry Smith 
1779273d9f13SBarry Smith   PetscFunctionBegin;
1780273d9f13SBarry Smith   ierr = MatCreate(comm,m,n,m,n,A);CHKERRQ(ierr);
1781273d9f13SBarry Smith   ierr = MatSetType(*A,MATSEQBAIJ);CHKERRQ(ierr);
1782273d9f13SBarry Smith   ierr = MatSeqBAIJSetPreallocation(*A,bs,nz,nnz);CHKERRQ(ierr);
1783273d9f13SBarry Smith   PetscFunctionReturn(0);
1784273d9f13SBarry Smith }
1785273d9f13SBarry Smith 
17864a2ae208SSatish Balay #undef __FUNCT__
17874a2ae208SSatish Balay #define __FUNCT__ "MatSeqBAIJSetPreallocation"
1788273d9f13SBarry Smith /*@C
1789273d9f13SBarry Smith    MatSeqBAIJSetPreallocation - Sets the block size and expected nonzeros
1790273d9f13SBarry Smith    per row in the matrix. For good matrix assembly performance the
1791273d9f13SBarry Smith    user should preallocate the matrix storage by setting the parameter nz
1792273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
1793273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
1794273d9f13SBarry Smith 
1795273d9f13SBarry Smith    Collective on MPI_Comm
1796273d9f13SBarry Smith 
1797273d9f13SBarry Smith    Input Parameters:
1798273d9f13SBarry Smith +  A - the matrix
1799273d9f13SBarry Smith .  bs - size of block
1800273d9f13SBarry Smith .  nz - number of block nonzeros per block row (same for all rows)
1801273d9f13SBarry Smith -  nnz - array containing the number of block nonzeros in the various block rows
1802273d9f13SBarry Smith          (possibly different for each block row) or PETSC_NULL
1803273d9f13SBarry Smith 
1804273d9f13SBarry Smith    Options Database Keys:
1805273d9f13SBarry Smith .   -mat_no_unroll - uses code that does not unroll the loops in the
1806273d9f13SBarry Smith                      block calculations (much slower)
1807273d9f13SBarry Smith .    -mat_block_size - size of the blocks to use
1808273d9f13SBarry Smith 
1809273d9f13SBarry Smith    Level: intermediate
1810273d9f13SBarry Smith 
1811273d9f13SBarry Smith    Notes:
1812273d9f13SBarry Smith    The block AIJ format is fully compatible with standard Fortran 77
1813273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
1814273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
1815273d9f13SBarry Smith 
1816273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
1817273d9f13SBarry Smith    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
1818273d9f13SBarry Smith    allocation.  For additional details, see the users manual chapter on
1819273d9f13SBarry Smith    matrices.
1820273d9f13SBarry Smith 
1821273d9f13SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPIBAIJ()
1822273d9f13SBarry Smith @*/
1823273d9f13SBarry Smith int MatSeqBAIJSetPreallocation(Mat B,int bs,int nz,int *nnz)
1824273d9f13SBarry Smith {
1825273d9f13SBarry Smith   Mat_SeqBAIJ *b;
1826273d9f13SBarry Smith   int         i,len,ierr,mbs,nbs,bs2,newbs = bs;
1827273d9f13SBarry Smith   PetscTruth  flg;
1828273d9f13SBarry Smith 
1829273d9f13SBarry Smith   PetscFunctionBegin;
1830273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)B,MATSEQBAIJ,&flg);CHKERRQ(ierr);
1831273d9f13SBarry Smith   if (!flg) PetscFunctionReturn(0);
1832273d9f13SBarry Smith 
1833273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
1834b0a32e0cSBarry Smith   ierr = PetscOptionsGetInt(B->prefix,"-mat_block_size",&newbs,PETSC_NULL);CHKERRQ(ierr);
1835273d9f13SBarry Smith   if (nnz && newbs != bs) {
1836273d9f13SBarry Smith     SETERRQ(1,"Cannot change blocksize from command line if setting nnz");
1837273d9f13SBarry Smith   }
1838273d9f13SBarry Smith   bs   = newbs;
1839273d9f13SBarry Smith 
1840273d9f13SBarry Smith   mbs  = B->m/bs;
1841273d9f13SBarry Smith   nbs  = B->n/bs;
1842273d9f13SBarry Smith   bs2  = bs*bs;
1843273d9f13SBarry Smith 
1844273d9f13SBarry Smith   if (mbs*bs!=B->m || nbs*bs!=B->n) {
184535d8aa7fSBarry Smith     SETERRQ3(PETSC_ERR_ARG_SIZ,"Number rows %d, cols %d must be divisible by blocksize %d",B->m,B->n,bs);
1846273d9f13SBarry Smith   }
1847273d9f13SBarry Smith 
1848435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
1849435da068SBarry Smith   if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
1850273d9f13SBarry Smith   if (nnz) {
1851273d9f13SBarry Smith     for (i=0; i<mbs; i++) {
1852273d9f13SBarry Smith       if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]);
18533a7fca6bSBarry Smith       if (nnz[i] > nbs) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than block row length: local row %d value %d rowlength %d",i,nnz[i],nbs);
1854273d9f13SBarry Smith     }
1855273d9f13SBarry Smith   }
1856273d9f13SBarry Smith 
1857273d9f13SBarry Smith   b       = (Mat_SeqBAIJ*)B->data;
1858b0a32e0cSBarry Smith   ierr    = PetscOptionsHasName(PETSC_NULL,"-mat_no_unroll",&flg);CHKERRQ(ierr);
185954138f6bSKris Buschelman   B->ops->solve               = MatSolve_SeqBAIJ_Update;
186054138f6bSKris Buschelman   B->ops->solvetranspose      = MatSolveTranspose_SeqBAIJ_Update;
1861273d9f13SBarry Smith   if (!flg) {
1862273d9f13SBarry Smith     switch (bs) {
1863273d9f13SBarry Smith     case 1:
1864273d9f13SBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_1;
1865273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_1;
1866273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_1;
1867273d9f13SBarry Smith       break;
1868273d9f13SBarry Smith     case 2:
1869273d9f13SBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_2;
1870273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_2;
1871273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_2;
1872273d9f13SBarry Smith       break;
1873273d9f13SBarry Smith     case 3:
1874273d9f13SBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_3;
1875273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_3;
1876273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_3;
1877273d9f13SBarry Smith       break;
1878273d9f13SBarry Smith     case 4:
1879273d9f13SBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_4;
1880273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_4;
1881273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_4;
1882273d9f13SBarry Smith       break;
1883273d9f13SBarry Smith     case 5:
1884273d9f13SBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_5;
1885273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_5;
1886273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_5;
1887273d9f13SBarry Smith       break;
1888273d9f13SBarry Smith     case 6:
1889273d9f13SBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_6;
1890273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_6;
1891273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_6;
1892273d9f13SBarry Smith       break;
1893273d9f13SBarry Smith     case 7:
189454138f6bSKris Buschelman       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_7;
1895273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_7;
1896273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_7;
1897273d9f13SBarry Smith       break;
1898273d9f13SBarry Smith     default:
189954138f6bSKris Buschelman       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_N;
1900273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_N;
1901273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_N;
1902273d9f13SBarry Smith       break;
1903273d9f13SBarry Smith     }
1904273d9f13SBarry Smith   }
1905273d9f13SBarry Smith   b->bs      = bs;
1906273d9f13SBarry Smith   b->mbs     = mbs;
1907273d9f13SBarry Smith   b->nbs     = nbs;
1908b0a32e0cSBarry Smith   ierr = PetscMalloc((mbs+1)*sizeof(int),&b->imax);CHKERRQ(ierr);
1909273d9f13SBarry Smith   if (!nnz) {
1910435da068SBarry Smith     if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
1911273d9f13SBarry Smith     else if (nz <= 0)        nz = 1;
1912273d9f13SBarry Smith     for (i=0; i<mbs; i++) b->imax[i] = nz;
1913273d9f13SBarry Smith     nz = nz*mbs;
1914273d9f13SBarry Smith   } else {
1915273d9f13SBarry Smith     nz = 0;
1916273d9f13SBarry Smith     for (i=0; i<mbs; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
1917273d9f13SBarry Smith   }
1918273d9f13SBarry Smith 
1919273d9f13SBarry Smith   /* allocate the matrix space */
1920273d9f13SBarry Smith   len   = nz*sizeof(int) + nz*bs2*sizeof(MatScalar) + (B->m+1)*sizeof(int);
1921b0a32e0cSBarry Smith   ierr  = PetscMalloc(len,&b->a);CHKERRQ(ierr);
1922273d9f13SBarry Smith   ierr  = PetscMemzero(b->a,nz*bs2*sizeof(MatScalar));CHKERRQ(ierr);
1923273d9f13SBarry Smith   b->j  = (int*)(b->a + nz*bs2);
1924273d9f13SBarry Smith   ierr = PetscMemzero(b->j,nz*sizeof(int));CHKERRQ(ierr);
1925273d9f13SBarry Smith   b->i  = b->j + nz;
1926273d9f13SBarry Smith   b->singlemalloc = PETSC_TRUE;
1927273d9f13SBarry Smith 
1928273d9f13SBarry Smith   b->i[0] = 0;
1929273d9f13SBarry Smith   for (i=1; i<mbs+1; i++) {
1930273d9f13SBarry Smith     b->i[i] = b->i[i-1] + b->imax[i-1];
1931273d9f13SBarry Smith   }
1932273d9f13SBarry Smith 
1933273d9f13SBarry Smith   /* b->ilen will count nonzeros in each block row so far. */
193416d6aa21SSatish Balay   ierr = PetscMalloc((mbs+1)*sizeof(int),&b->ilen);CHKERRQ(ierr);
1935b0a32e0cSBarry Smith   PetscLogObjectMemory(B,len+2*(mbs+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqBAIJ));
1936273d9f13SBarry Smith   for (i=0; i<mbs; i++) { b->ilen[i] = 0;}
1937273d9f13SBarry Smith 
1938273d9f13SBarry Smith   b->bs               = bs;
1939273d9f13SBarry Smith   b->bs2              = bs2;
1940273d9f13SBarry Smith   b->mbs              = mbs;
1941273d9f13SBarry Smith   b->nz               = 0;
1942273d9f13SBarry Smith   b->maxnz            = nz*bs2;
1943273d9f13SBarry Smith   B->info.nz_unneeded = (PetscReal)b->maxnz;
1944273d9f13SBarry Smith   PetscFunctionReturn(0);
1945273d9f13SBarry Smith }
19462593348eSBarry Smith 
1947