xref: /petsc/src/mat/impls/baij/seq/baij.c (revision f2a5309cf2bd60e875de7457ab3728dd4e42fdc5)
1*f2a5309cSSatish Balay /*$Id: baij.c,v 1.218 2001/01/20 03:34:53 bsmith 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 */
7e090d566SSatish Balay #include "petscsys.h"
870f55243SBarry Smith #include "src/mat/impls/baij/seq/baij.h"
91a6a6d98SBarry Smith #include "src/vec/vecimpl.h"
101a6a6d98SBarry Smith #include "src/inline/spops.h"
113b547af2SSatish Balay 
1295d5f7c2SBarry Smith /*  UGLY, ugly, ugly
1395d5f7c2SBarry Smith    When MatScalar == Scalar the function MatSetValuesBlocked_SeqBAIJ_MatScalar() does
1495d5f7c2SBarry Smith    not exist. Otherwise ..._MatScalar() takes matrix elements 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
2495d5f7c2SBarry Smith 
252d61bbb3SSatish Balay #define CHUNKSIZE  10
26de6a44a3SBarry Smith 
27be5855fcSBarry Smith /*
28be5855fcSBarry Smith      Checks for missing diagonals
29be5855fcSBarry Smith */
30be5855fcSBarry Smith #undef __FUNC__
31b0a32e0cSBarry Smith #define __FUNC__ "MatMissingDiagonal_SeqBAIJ"
32c4992f7dSBarry Smith int MatMissingDiagonal_SeqBAIJ(Mat A)
33be5855fcSBarry Smith {
34be5855fcSBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
35883fce79SBarry Smith   int         *diag,*jj = a->j,i,ierr;
36be5855fcSBarry Smith 
37be5855fcSBarry Smith   PetscFunctionBegin;
38c4992f7dSBarry Smith   ierr = MatMarkDiagonal_SeqBAIJ(A);CHKERRQ(ierr);
39883fce79SBarry Smith   diag = a->diag;
400e8e8aceSBarry Smith   for (i=0; i<a->mbs; i++) {
41be5855fcSBarry Smith     if (jj[diag[i]] != i) {
4229bbc08cSBarry Smith       SETERRQ1(1,"Matrix is missing diagonal number %d",i);
43be5855fcSBarry Smith     }
44be5855fcSBarry Smith   }
45be5855fcSBarry Smith   PetscFunctionReturn(0);
46be5855fcSBarry Smith }
47be5855fcSBarry Smith 
485615d1e5SSatish Balay #undef __FUNC__
49b0a32e0cSBarry Smith #define __FUNC__ "MatMarkDiagonal_SeqBAIJ"
50c4992f7dSBarry Smith int MatMarkDiagonal_SeqBAIJ(Mat A)
51de6a44a3SBarry Smith {
52de6a44a3SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
5382502324SSatish Balay   int         i,j,*diag,m = a->mbs,ierr;
54de6a44a3SBarry Smith 
553a40ed3dSBarry Smith   PetscFunctionBegin;
56883fce79SBarry Smith   if (a->diag) PetscFunctionReturn(0);
57883fce79SBarry Smith 
58b0a32e0cSBarry Smith   ierr = PetscMalloc((m+1)*sizeof(int),&diag);CHKERRQ(ierr);
59b0a32e0cSBarry Smith   PetscLogObjectMemory(A,(m+1)*sizeof(int));
607fc0212eSBarry Smith   for (i=0; i<m; i++) {
61ecc615b2SBarry Smith     diag[i] = a->i[i+1];
62de6a44a3SBarry Smith     for (j=a->i[i]; j<a->i[i+1]; j++) {
63de6a44a3SBarry Smith       if (a->j[j] == i) {
64de6a44a3SBarry Smith         diag[i] = j;
65de6a44a3SBarry Smith         break;
66de6a44a3SBarry Smith       }
67de6a44a3SBarry Smith     }
68de6a44a3SBarry Smith   }
69de6a44a3SBarry Smith   a->diag = diag;
703a40ed3dSBarry Smith   PetscFunctionReturn(0);
71de6a44a3SBarry Smith }
722593348eSBarry Smith 
732593348eSBarry Smith 
74ca44d042SBarry Smith EXTERN int MatToSymmetricIJ_SeqAIJ(int,int*,int*,int,int,int**,int**);
753b2fbd54SBarry Smith 
765615d1e5SSatish Balay #undef __FUNC__
77b0a32e0cSBarry Smith #define __FUNC__ "MatGetRowIJ_SeqBAIJ"
780e6d2581SBarry Smith static int MatGetRowIJ_SeqBAIJ(Mat A,int oshift,PetscTruth symmetric,int *nn,int **ia,int **ja,PetscTruth *done)
793b2fbd54SBarry Smith {
803b2fbd54SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
813b2fbd54SBarry Smith   int         ierr,n = a->mbs,i;
823b2fbd54SBarry Smith 
833a40ed3dSBarry Smith   PetscFunctionBegin;
843b2fbd54SBarry Smith   *nn = n;
853a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
863b2fbd54SBarry Smith   if (symmetric) {
873b2fbd54SBarry Smith     ierr = MatToSymmetricIJ_SeqAIJ(n,a->i,a->j,0,oshift,ia,ja);CHKERRQ(ierr);
883b2fbd54SBarry Smith   } else if (oshift == 1) {
893b2fbd54SBarry Smith     /* temporarily add 1 to i and j indices */
903b2fbd54SBarry Smith     int nz = a->i[n] + 1;
913b2fbd54SBarry Smith     for (i=0; i<nz; i++) a->j[i]++;
923b2fbd54SBarry Smith     for (i=0; i<n+1; i++) a->i[i]++;
933b2fbd54SBarry Smith     *ia = a->i; *ja = a->j;
943b2fbd54SBarry Smith   } else {
953b2fbd54SBarry Smith     *ia = a->i; *ja = a->j;
963b2fbd54SBarry Smith   }
973b2fbd54SBarry Smith 
983a40ed3dSBarry Smith   PetscFunctionReturn(0);
993b2fbd54SBarry Smith }
1003b2fbd54SBarry Smith 
1015615d1e5SSatish Balay #undef __FUNC__
102b0a32e0cSBarry Smith #define __FUNC__ "MatRestoreRowIJ_SeqBAIJ"
1033b2fbd54SBarry Smith static int MatRestoreRowIJ_SeqBAIJ(Mat A,int oshift,PetscTruth symmetric,int *nn,int **ia,int **ja,
1043b2fbd54SBarry Smith                                 PetscTruth *done)
1053b2fbd54SBarry Smith {
1063b2fbd54SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
107606d414cSSatish Balay   int         i,n = a->mbs,ierr;
1083b2fbd54SBarry Smith 
1093a40ed3dSBarry Smith   PetscFunctionBegin;
1103a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
1113b2fbd54SBarry Smith   if (symmetric) {
112606d414cSSatish Balay     ierr = PetscFree(*ia);CHKERRQ(ierr);
113606d414cSSatish Balay     ierr = PetscFree(*ja);CHKERRQ(ierr);
114af5da2bfSBarry Smith   } else if (oshift == 1) {
1153b2fbd54SBarry Smith     int nz = a->i[n];
1163b2fbd54SBarry Smith     for (i=0; i<nz; i++) a->j[i]--;
1173b2fbd54SBarry Smith     for (i=0; i<n+1; i++) a->i[i]--;
1183b2fbd54SBarry Smith   }
1193a40ed3dSBarry Smith   PetscFunctionReturn(0);
1203b2fbd54SBarry Smith }
1213b2fbd54SBarry Smith 
1222d61bbb3SSatish Balay #undef __FUNC__
123b0a32e0cSBarry Smith #define __FUNC__ "MatGetBlockSize_SeqBAIJ"
1242d61bbb3SSatish Balay int MatGetBlockSize_SeqBAIJ(Mat mat,int *bs)
1252d61bbb3SSatish Balay {
1262d61bbb3SSatish Balay   Mat_SeqBAIJ *baij = (Mat_SeqBAIJ*)mat->data;
1272d61bbb3SSatish Balay 
1282d61bbb3SSatish Balay   PetscFunctionBegin;
1292d61bbb3SSatish Balay   *bs = baij->bs;
1302d61bbb3SSatish Balay   PetscFunctionReturn(0);
1312d61bbb3SSatish Balay }
1322d61bbb3SSatish Balay 
1332d61bbb3SSatish Balay 
1342d61bbb3SSatish Balay #undef __FUNC__
135b0a32e0cSBarry Smith #define __FUNC__ "MatDestroy_SeqBAIJ"
136e1311b90SBarry Smith int MatDestroy_SeqBAIJ(Mat A)
1372d61bbb3SSatish Balay {
1382d61bbb3SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
139e51c0b9cSSatish Balay   int         ierr;
1402d61bbb3SSatish Balay 
141433994e6SBarry Smith   PetscFunctionBegin;
142aa482453SBarry Smith #if defined(PETSC_USE_LOG)
143b0a32e0cSBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%d, Cols=%d, NZ=%d",A->m,A->n,a->nz);
1442d61bbb3SSatish Balay #endif
145606d414cSSatish Balay   ierr = PetscFree(a->a);CHKERRQ(ierr);
146606d414cSSatish Balay   if (!a->singlemalloc) {
147606d414cSSatish Balay     ierr = PetscFree(a->i);CHKERRQ(ierr);
148606d414cSSatish Balay     ierr = PetscFree(a->j);CHKERRQ(ierr);
149606d414cSSatish Balay   }
150c38d4ed2SBarry Smith   if (a->row) {
151c38d4ed2SBarry Smith     ierr = ISDestroy(a->row);CHKERRQ(ierr);
152c38d4ed2SBarry Smith   }
153c38d4ed2SBarry Smith   if (a->col) {
154c38d4ed2SBarry Smith     ierr = ISDestroy(a->col);CHKERRQ(ierr);
155c38d4ed2SBarry Smith   }
156606d414cSSatish Balay   if (a->diag) {ierr = PetscFree(a->diag);CHKERRQ(ierr);}
157606d414cSSatish Balay   if (a->ilen) {ierr = PetscFree(a->ilen);CHKERRQ(ierr);}
158606d414cSSatish Balay   if (a->imax) {ierr = PetscFree(a->imax);CHKERRQ(ierr);}
159606d414cSSatish Balay   if (a->solve_work) {ierr = PetscFree(a->solve_work);CHKERRQ(ierr);}
160606d414cSSatish Balay   if (a->mult_work) {ierr = PetscFree(a->mult_work);CHKERRQ(ierr);}
161e51c0b9cSSatish Balay   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);}
162606d414cSSatish Balay   if (a->saved_values) {ierr = PetscFree(a->saved_values);CHKERRQ(ierr);}
163563b5814SBarry Smith #if defined(PETSC_USE_MAT_SINGLE)
164563b5814SBarry Smith   if (a->setvaluescopy) {ierr = PetscFree(a->setvaluescopy);CHKERRQ(ierr);}
165563b5814SBarry Smith #endif
166606d414cSSatish Balay   ierr = PetscFree(a);CHKERRQ(ierr);
1672d61bbb3SSatish Balay   PetscFunctionReturn(0);
1682d61bbb3SSatish Balay }
1692d61bbb3SSatish Balay 
1702d61bbb3SSatish Balay #undef __FUNC__
171b0a32e0cSBarry Smith #define __FUNC__ "MatSetOption_SeqBAIJ"
1722d61bbb3SSatish Balay int MatSetOption_SeqBAIJ(Mat A,MatOption op)
1732d61bbb3SSatish Balay {
1742d61bbb3SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
1752d61bbb3SSatish Balay 
1762d61bbb3SSatish Balay   PetscFunctionBegin;
177c4992f7dSBarry Smith   if      (op == MAT_ROW_ORIENTED)                 a->roworiented    = PETSC_TRUE;
178c4992f7dSBarry Smith   else if (op == MAT_COLUMN_ORIENTED)              a->roworiented    = PETSC_FALSE;
179c4992f7dSBarry Smith   else if (op == MAT_COLUMNS_SORTED)               a->sorted         = PETSC_TRUE;
180c4992f7dSBarry Smith   else if (op == MAT_COLUMNS_UNSORTED)             a->sorted         = PETSC_FALSE;
181c4992f7dSBarry Smith   else if (op == MAT_KEEP_ZEROED_ROWS)             a->keepzeroedrows = PETSC_TRUE;
1822d61bbb3SSatish Balay   else if (op == MAT_NO_NEW_NONZERO_LOCATIONS)     a->nonew          = 1;
1834787f768SSatish Balay   else if (op == MAT_NEW_NONZERO_LOCATION_ERR)     a->nonew          = -1;
1844787f768SSatish Balay   else if (op == MAT_NEW_NONZERO_ALLOCATION_ERR)   a->nonew          = -2;
1852d61bbb3SSatish Balay   else if (op == MAT_YES_NEW_NONZERO_LOCATIONS)    a->nonew          = 0;
1862d61bbb3SSatish Balay   else if (op == MAT_ROWS_SORTED ||
1872d61bbb3SSatish Balay            op == MAT_ROWS_UNSORTED ||
1882d61bbb3SSatish Balay            op == MAT_SYMMETRIC ||
1892d61bbb3SSatish Balay            op == MAT_STRUCTURALLY_SYMMETRIC ||
1902d61bbb3SSatish Balay            op == MAT_YES_NEW_DIAGONALS ||
191b51ba29fSSatish Balay            op == MAT_IGNORE_OFF_PROC_ENTRIES ||
192b51ba29fSSatish Balay            op == MAT_USE_HASH_TABLE) {
193b0a32e0cSBarry Smith     PetscLogInfo(A,"MatSetOption_SeqBAIJ:Option ignored\n");
1942d61bbb3SSatish Balay   } else if (op == MAT_NO_NEW_DIAGONALS) {
19529bbc08cSBarry Smith     SETERRQ(PETSC_ERR_SUP,"MAT_NO_NEW_DIAGONALS");
1962d61bbb3SSatish Balay   } else {
19729bbc08cSBarry Smith     SETERRQ(PETSC_ERR_SUP,"unknown option");
1982d61bbb3SSatish Balay   }
1992d61bbb3SSatish Balay   PetscFunctionReturn(0);
2002d61bbb3SSatish Balay }
2012d61bbb3SSatish Balay 
2022d61bbb3SSatish Balay #undef __FUNC__
203b0a32e0cSBarry Smith #define __FUNC__ "MatGetOwnershipRange_SeqBAIJ"
2042d61bbb3SSatish Balay int MatGetOwnershipRange_SeqBAIJ(Mat A,int *m,int *n)
2052d61bbb3SSatish Balay {
2062d61bbb3SSatish Balay   PetscFunctionBegin;
2074c49b128SBarry Smith   if (m) *m = 0;
208273d9f13SBarry Smith   if (n) *n = A->m;
2092d61bbb3SSatish Balay   PetscFunctionReturn(0);
2102d61bbb3SSatish Balay }
2112d61bbb3SSatish Balay 
2122d61bbb3SSatish Balay #undef __FUNC__
213b0a32e0cSBarry Smith #define __FUNC__ "MatGetRow_SeqBAIJ"
2142d61bbb3SSatish Balay int MatGetRow_SeqBAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
2152d61bbb3SSatish Balay {
2162d61bbb3SSatish Balay   Mat_SeqBAIJ  *a = (Mat_SeqBAIJ*)A->data;
21782502324SSatish Balay   int          itmp,i,j,k,M,*ai,*aj,bs,bn,bp,*idx_i,bs2,ierr;
2183f1db9ecSBarry Smith   MatScalar    *aa,*aa_i;
2193f1db9ecSBarry Smith   Scalar       *v_i;
2202d61bbb3SSatish Balay 
2212d61bbb3SSatish Balay   PetscFunctionBegin;
2222d61bbb3SSatish Balay   bs  = a->bs;
2232d61bbb3SSatish Balay   ai  = a->i;
2242d61bbb3SSatish Balay   aj  = a->j;
2252d61bbb3SSatish Balay   aa  = a->a;
2262d61bbb3SSatish Balay   bs2 = a->bs2;
2272d61bbb3SSatish Balay 
228273d9f13SBarry Smith   if (row < 0 || row >= A->m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Row out of range");
2292d61bbb3SSatish Balay 
2302d61bbb3SSatish Balay   bn  = row/bs;   /* Block number */
2312d61bbb3SSatish Balay   bp  = row % bs; /* Block Position */
2322d61bbb3SSatish Balay   M   = ai[bn+1] - ai[bn];
2332d61bbb3SSatish Balay   *nz = bs*M;
2342d61bbb3SSatish Balay 
2352d61bbb3SSatish Balay   if (v) {
2362d61bbb3SSatish Balay     *v = 0;
2372d61bbb3SSatish Balay     if (*nz) {
238b0a32e0cSBarry Smith       ierr = PetscMalloc((*nz)*sizeof(Scalar),v);CHKERRQ(ierr);
2392d61bbb3SSatish Balay       for (i=0; i<M; i++) { /* for each block in the block row */
2402d61bbb3SSatish Balay         v_i  = *v + i*bs;
2412d61bbb3SSatish Balay         aa_i = aa + bs2*(ai[bn] + i);
2422d61bbb3SSatish Balay         for (j=bp,k=0; j<bs2; j+=bs,k++) {v_i[k] = aa_i[j];}
2432d61bbb3SSatish Balay       }
2442d61bbb3SSatish Balay     }
2452d61bbb3SSatish Balay   }
2462d61bbb3SSatish Balay 
2472d61bbb3SSatish Balay   if (idx) {
2482d61bbb3SSatish Balay     *idx = 0;
2492d61bbb3SSatish Balay     if (*nz) {
250b0a32e0cSBarry Smith       ierr = PetscMalloc((*nz)*sizeof(int),idx);CHKERRQ(ierr);
2512d61bbb3SSatish Balay       for (i=0; i<M; i++) { /* for each block in the block row */
2522d61bbb3SSatish Balay         idx_i = *idx + i*bs;
2532d61bbb3SSatish Balay         itmp  = bs*aj[ai[bn] + i];
2542d61bbb3SSatish Balay         for (j=0; j<bs; j++) {idx_i[j] = itmp++;}
2552d61bbb3SSatish Balay       }
2562d61bbb3SSatish Balay     }
2572d61bbb3SSatish Balay   }
2582d61bbb3SSatish Balay   PetscFunctionReturn(0);
2592d61bbb3SSatish Balay }
2602d61bbb3SSatish Balay 
2612d61bbb3SSatish Balay #undef __FUNC__
262b0a32e0cSBarry Smith #define __FUNC__ "MatRestoreRow_SeqBAIJ"
2632d61bbb3SSatish Balay int MatRestoreRow_SeqBAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
2642d61bbb3SSatish Balay {
265606d414cSSatish Balay   int ierr;
266606d414cSSatish Balay 
2672d61bbb3SSatish Balay   PetscFunctionBegin;
268606d414cSSatish Balay   if (idx) {if (*idx) {ierr = PetscFree(*idx);CHKERRQ(ierr);}}
269606d414cSSatish Balay   if (v)   {if (*v)   {ierr = PetscFree(*v);CHKERRQ(ierr);}}
2702d61bbb3SSatish Balay   PetscFunctionReturn(0);
2712d61bbb3SSatish Balay }
2722d61bbb3SSatish Balay 
2732d61bbb3SSatish Balay #undef __FUNC__
274b0a32e0cSBarry Smith #define __FUNC__ "MatTranspose_SeqBAIJ"
2752d61bbb3SSatish Balay int MatTranspose_SeqBAIJ(Mat A,Mat *B)
2762d61bbb3SSatish Balay {
2772d61bbb3SSatish Balay   Mat_SeqBAIJ *a=(Mat_SeqBAIJ *)A->data;
2782d61bbb3SSatish Balay   Mat         C;
2792d61bbb3SSatish Balay   int         i,j,k,ierr,*aj=a->j,*ai=a->i,bs=a->bs,mbs=a->mbs,nbs=a->nbs,len,*col;
280273d9f13SBarry Smith   int         *rows,*cols,bs2=a->bs2;
281375fe846SBarry Smith   Scalar      *array;
2822d61bbb3SSatish Balay 
2832d61bbb3SSatish Balay   PetscFunctionBegin;
28429bbc08cSBarry Smith   if (!B && mbs!=nbs) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Square matrix only for in-place");
285b0a32e0cSBarry Smith   ierr = PetscMalloc((1+nbs)*sizeof(int),&col);CHKERRQ(ierr);
286549d3d68SSatish Balay   ierr = PetscMemzero(col,(1+nbs)*sizeof(int));CHKERRQ(ierr);
2872d61bbb3SSatish Balay 
288375fe846SBarry Smith #if defined(PETSC_USE_MAT_SINGLE)
289b0a32e0cSBarry Smith   ierr = PetscMalloc(a->bs2*a->nz*sizeof(Scalar),&array);CHKERRQ(ierr);
290375fe846SBarry Smith   for (i=0; i<a->bs2*a->nz; i++) array[i] = (Scalar)a->a[i];
291375fe846SBarry Smith #else
2923eda8832SBarry Smith   array = a->a;
293375fe846SBarry Smith #endif
294375fe846SBarry Smith 
2952d61bbb3SSatish Balay   for (i=0; i<ai[mbs]; i++) col[aj[i]] += 1;
296273d9f13SBarry Smith   ierr = MatCreateSeqBAIJ(A->comm,bs,A->n,A->m,PETSC_NULL,col,&C);CHKERRQ(ierr);
297606d414cSSatish Balay   ierr = PetscFree(col);CHKERRQ(ierr);
298b0a32e0cSBarry Smith   ierr = PetscMalloc(2*bs*sizeof(int),&rows);CHKERRQ(ierr);
2992d61bbb3SSatish Balay   cols = rows + bs;
3002d61bbb3SSatish Balay   for (i=0; i<mbs; i++) {
3012d61bbb3SSatish Balay     cols[0] = i*bs;
3022d61bbb3SSatish Balay     for (k=1; k<bs; k++) cols[k] = cols[k-1] + 1;
3032d61bbb3SSatish Balay     len = ai[i+1] - ai[i];
3042d61bbb3SSatish Balay     for (j=0; j<len; j++) {
3052d61bbb3SSatish Balay       rows[0] = (*aj++)*bs;
3062d61bbb3SSatish Balay       for (k=1; k<bs; k++) rows[k] = rows[k-1] + 1;
3072d61bbb3SSatish Balay       ierr = MatSetValues(C,bs,rows,bs,cols,array,INSERT_VALUES);CHKERRQ(ierr);
3082d61bbb3SSatish Balay       array += bs2;
3092d61bbb3SSatish Balay     }
3102d61bbb3SSatish Balay   }
311606d414cSSatish Balay   ierr = PetscFree(rows);CHKERRQ(ierr);
312375fe846SBarry Smith #if defined(PETSC_USE_MAT_SINGLE)
313375fe846SBarry Smith   ierr = PetscFree(array);
314375fe846SBarry Smith #endif
3152d61bbb3SSatish Balay 
3162d61bbb3SSatish Balay   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3172d61bbb3SSatish Balay   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3182d61bbb3SSatish Balay 
319c4992f7dSBarry Smith   if (B) {
3202d61bbb3SSatish Balay     *B = C;
3212d61bbb3SSatish Balay   } else {
322273d9f13SBarry Smith     ierr = MatHeaderCopy(A,C);CHKERRQ(ierr);
3232d61bbb3SSatish Balay   }
3242d61bbb3SSatish Balay   PetscFunctionReturn(0);
3252d61bbb3SSatish Balay }
3262d61bbb3SSatish Balay 
3275615d1e5SSatish Balay #undef __FUNC__
328b0a32e0cSBarry Smith #define __FUNC__ "MatView_SeqBAIJ_Binary"
329b0a32e0cSBarry Smith static int MatView_SeqBAIJ_Binary(Mat A,PetscViewer viewer)
3302593348eSBarry Smith {
331b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
3329df24120SSatish Balay   int         i,fd,*col_lens,ierr,bs = a->bs,count,*jj,j,k,l,bs2=a->bs2;
333b6490206SBarry Smith   Scalar      *aa;
334ce6f0cecSBarry Smith   FILE        *file;
3352593348eSBarry Smith 
3363a40ed3dSBarry Smith   PetscFunctionBegin;
337b0a32e0cSBarry Smith   ierr        = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
338b0a32e0cSBarry Smith   ierr        = PetscMalloc((4+A->m)*sizeof(int),&col_lens);CHKERRQ(ierr);
3392593348eSBarry Smith   col_lens[0] = MAT_COOKIE;
3403b2fbd54SBarry Smith 
341273d9f13SBarry Smith   col_lens[1] = A->m;
342273d9f13SBarry Smith   col_lens[2] = A->n;
3437e67e3f9SSatish Balay   col_lens[3] = a->nz*bs2;
3442593348eSBarry Smith 
3452593348eSBarry Smith   /* store lengths of each row and write (including header) to file */
346b6490206SBarry Smith   count = 0;
347b6490206SBarry Smith   for (i=0; i<a->mbs; i++) {
348b6490206SBarry Smith     for (j=0; j<bs; j++) {
349b6490206SBarry Smith       col_lens[4+count++] = bs*(a->i[i+1] - a->i[i]);
350b6490206SBarry Smith     }
3512593348eSBarry Smith   }
352273d9f13SBarry Smith   ierr = PetscBinaryWrite(fd,col_lens,4+A->m,PETSC_INT,1);CHKERRQ(ierr);
353606d414cSSatish Balay   ierr = PetscFree(col_lens);CHKERRQ(ierr);
3542593348eSBarry Smith 
3552593348eSBarry Smith   /* store column indices (zero start index) */
356b0a32e0cSBarry Smith   ierr  = PetscMalloc((a->nz+1)*bs2*sizeof(int),&jj);CHKERRQ(ierr);
357b6490206SBarry Smith   count = 0;
358b6490206SBarry Smith   for (i=0; i<a->mbs; i++) {
359b6490206SBarry Smith     for (j=0; j<bs; j++) {
360b6490206SBarry Smith       for (k=a->i[i]; k<a->i[i+1]; k++) {
361b6490206SBarry Smith         for (l=0; l<bs; l++) {
362b6490206SBarry Smith           jj[count++] = bs*a->j[k] + l;
3632593348eSBarry Smith         }
3642593348eSBarry Smith       }
365b6490206SBarry Smith     }
366b6490206SBarry Smith   }
3670752156aSBarry Smith   ierr = PetscBinaryWrite(fd,jj,bs2*a->nz,PETSC_INT,0);CHKERRQ(ierr);
368606d414cSSatish Balay   ierr = PetscFree(jj);CHKERRQ(ierr);
3692593348eSBarry Smith 
3702593348eSBarry Smith   /* store nonzero values */
371b0a32e0cSBarry Smith   ierr  = PetscMalloc((a->nz+1)*bs2*sizeof(Scalar),&aa);CHKERRQ(ierr);
372b6490206SBarry Smith   count = 0;
373b6490206SBarry Smith   for (i=0; i<a->mbs; i++) {
374b6490206SBarry Smith     for (j=0; j<bs; j++) {
375b6490206SBarry Smith       for (k=a->i[i]; k<a->i[i+1]; k++) {
376b6490206SBarry Smith         for (l=0; l<bs; l++) {
3777e67e3f9SSatish Balay           aa[count++] = a->a[bs2*k + l*bs + j];
378b6490206SBarry Smith         }
379b6490206SBarry Smith       }
380b6490206SBarry Smith     }
381b6490206SBarry Smith   }
3820752156aSBarry Smith   ierr = PetscBinaryWrite(fd,aa,bs2*a->nz,PETSC_SCALAR,0);CHKERRQ(ierr);
383606d414cSSatish Balay   ierr = PetscFree(aa);CHKERRQ(ierr);
384ce6f0cecSBarry Smith 
385b0a32e0cSBarry Smith   ierr = PetscViewerBinaryGetInfoPointer(viewer,&file);CHKERRQ(ierr);
386ce6f0cecSBarry Smith   if (file) {
387ce6f0cecSBarry Smith     fprintf(file,"-matload_block_size %d\n",a->bs);
388ce6f0cecSBarry Smith   }
3893a40ed3dSBarry Smith   PetscFunctionReturn(0);
3902593348eSBarry Smith }
3912593348eSBarry Smith 
3925615d1e5SSatish Balay #undef __FUNC__
393b0a32e0cSBarry Smith #define __FUNC__ "MatView_SeqBAIJ_ASCII"
394b0a32e0cSBarry Smith static int MatView_SeqBAIJ_ASCII(Mat A,PetscViewer viewer)
3952593348eSBarry Smith {
396b6490206SBarry Smith   Mat_SeqBAIJ       *a = (Mat_SeqBAIJ*)A->data;
397fb9695e5SSatish Balay   int               ierr,i,j,bs = a->bs,k,l,bs2=a->bs2;
398f3ef73ceSBarry Smith   PetscViewerFormat format;
3992593348eSBarry Smith 
4003a40ed3dSBarry Smith   PetscFunctionBegin;
401b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
402fb9695e5SSatish Balay   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_LONG) {
403b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  block size is %d\n",bs);CHKERRQ(ierr);
404fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_MATLAB) {
40529bbc08cSBarry Smith     SETERRQ(PETSC_ERR_SUP,"Matlab format not supported");
406fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
407b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
40844cd7ae7SLois Curfman McInnes     for (i=0; i<a->mbs; i++) {
40944cd7ae7SLois Curfman McInnes       for (j=0; j<bs; j++) {
410b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %d:",i*bs+j);CHKERRQ(ierr);
41144cd7ae7SLois Curfman McInnes         for (k=a->i[i]; k<a->i[i+1]; k++) {
41244cd7ae7SLois Curfman McInnes           for (l=0; l<bs; l++) {
413aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
4140e6d2581SBarry Smith             if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
415b0a32e0cSBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," %d %g + %gi",bs*a->j[k]+l,
4160e6d2581SBarry Smith                       PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
4170e6d2581SBarry Smith             } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
418b0a32e0cSBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," %d %g - %gi",bs*a->j[k]+l,
4190e6d2581SBarry Smith                       PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
4200e6d2581SBarry Smith             } else if (PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
421b0a32e0cSBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," %d %g ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
4220ef38995SBarry Smith             }
42344cd7ae7SLois Curfman McInnes #else
4240ef38995SBarry Smith             if (a->a[bs2*k + l*bs + j] != 0.0) {
425b0a32e0cSBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," %d %g ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);CHKERRQ(ierr);
4260ef38995SBarry Smith             }
42744cd7ae7SLois Curfman McInnes #endif
42844cd7ae7SLois Curfman McInnes           }
42944cd7ae7SLois Curfman McInnes         }
430b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
43144cd7ae7SLois Curfman McInnes       }
43244cd7ae7SLois Curfman McInnes     }
433b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
4340ef38995SBarry Smith   } else {
435b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
436b6490206SBarry Smith     for (i=0; i<a->mbs; i++) {
437b6490206SBarry Smith       for (j=0; j<bs; j++) {
438b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %d:",i*bs+j);CHKERRQ(ierr);
439b6490206SBarry Smith         for (k=a->i[i]; k<a->i[i+1]; k++) {
440b6490206SBarry Smith           for (l=0; l<bs; l++) {
441aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
4420e6d2581SBarry Smith             if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0) {
443b0a32e0cSBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," %d %g + %g i",bs*a->j[k]+l,
4440e6d2581SBarry Smith                 PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
4450e6d2581SBarry Smith             } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0) {
446b0a32e0cSBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," %d %g - %g i",bs*a->j[k]+l,
4470e6d2581SBarry Smith                 PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
4480ef38995SBarry Smith             } else {
449b0a32e0cSBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," %d %g ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
45088685aaeSLois Curfman McInnes             }
45188685aaeSLois Curfman McInnes #else
452b0a32e0cSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," %d %g ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);CHKERRQ(ierr);
45388685aaeSLois Curfman McInnes #endif
4542593348eSBarry Smith           }
4552593348eSBarry Smith         }
456b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
4572593348eSBarry Smith       }
4582593348eSBarry Smith     }
459b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
460b6490206SBarry Smith   }
461b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
4623a40ed3dSBarry Smith   PetscFunctionReturn(0);
4632593348eSBarry Smith }
4642593348eSBarry Smith 
4655615d1e5SSatish Balay #undef __FUNC__
466b0a32e0cSBarry Smith #define __FUNC__ "MatView_SeqBAIJ_Draw_Zoom"
467b0a32e0cSBarry Smith static int MatView_SeqBAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
4683270192aSSatish Balay {
46977ed5343SBarry Smith   Mat          A = (Mat) Aa;
4703270192aSSatish Balay   Mat_SeqBAIJ  *a=(Mat_SeqBAIJ*)A->data;
471b65db4caSBarry Smith   int          row,ierr,i,j,k,l,mbs=a->mbs,color,bs=a->bs,bs2=a->bs2;
4720e6d2581SBarry Smith   PetscReal    xl,yl,xr,yr,x_l,x_r,y_l,y_r;
4733f1db9ecSBarry Smith   MatScalar    *aa;
474b0a32e0cSBarry Smith   PetscViewer       viewer;
4753270192aSSatish Balay 
4763a40ed3dSBarry Smith   PetscFunctionBegin;
4773270192aSSatish Balay 
478b65db4caSBarry Smith   /* still need to add support for contour plot of nonzeros; see MatView_SeqAIJ_Draw_Zoom()*/
47977ed5343SBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
48077ed5343SBarry Smith 
481b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
48277ed5343SBarry Smith 
4833270192aSSatish Balay   /* loop over matrix elements drawing boxes */
484b0a32e0cSBarry Smith   color = PETSC_DRAW_BLUE;
4853270192aSSatish Balay   for (i=0,row=0; i<mbs; i++,row+=bs) {
4863270192aSSatish Balay     for (j=a->i[i]; j<a->i[i+1]; j++) {
487273d9f13SBarry Smith       y_l = A->m - row - 1.0; y_r = y_l + 1.0;
4883270192aSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
4893270192aSSatish Balay       aa = a->a + j*bs2;
4903270192aSSatish Balay       for (k=0; k<bs; k++) {
4913270192aSSatish Balay         for (l=0; l<bs; l++) {
4920e6d2581SBarry Smith           if (PetscRealPart(*aa++) >=  0.) continue;
493b0a32e0cSBarry Smith           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
4943270192aSSatish Balay         }
4953270192aSSatish Balay       }
4963270192aSSatish Balay     }
4973270192aSSatish Balay   }
498b0a32e0cSBarry Smith   color = PETSC_DRAW_CYAN;
4993270192aSSatish Balay   for (i=0,row=0; i<mbs; i++,row+=bs) {
5003270192aSSatish Balay     for (j=a->i[i]; j<a->i[i+1]; j++) {
501273d9f13SBarry Smith       y_l = A->m - row - 1.0; y_r = y_l + 1.0;
5023270192aSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
5033270192aSSatish Balay       aa = a->a + j*bs2;
5043270192aSSatish Balay       for (k=0; k<bs; k++) {
5053270192aSSatish Balay         for (l=0; l<bs; l++) {
5060e6d2581SBarry Smith           if (PetscRealPart(*aa++) != 0.) continue;
507b0a32e0cSBarry Smith           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
5083270192aSSatish Balay         }
5093270192aSSatish Balay       }
5103270192aSSatish Balay     }
5113270192aSSatish Balay   }
5123270192aSSatish Balay 
513b0a32e0cSBarry Smith   color = PETSC_DRAW_RED;
5143270192aSSatish Balay   for (i=0,row=0; i<mbs; i++,row+=bs) {
5153270192aSSatish Balay     for (j=a->i[i]; j<a->i[i+1]; j++) {
516273d9f13SBarry Smith       y_l = A->m - row - 1.0; y_r = y_l + 1.0;
5173270192aSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
5183270192aSSatish Balay       aa = a->a + j*bs2;
5193270192aSSatish Balay       for (k=0; k<bs; k++) {
5203270192aSSatish Balay         for (l=0; l<bs; l++) {
5210e6d2581SBarry Smith           if (PetscRealPart(*aa++) <= 0.) continue;
522b0a32e0cSBarry Smith           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
5233270192aSSatish Balay         }
5243270192aSSatish Balay       }
5253270192aSSatish Balay     }
5263270192aSSatish Balay   }
52777ed5343SBarry Smith   PetscFunctionReturn(0);
52877ed5343SBarry Smith }
5293270192aSSatish Balay 
53077ed5343SBarry Smith #undef __FUNC__
531b0a32e0cSBarry Smith #define __FUNC__ "MatView_SeqBAIJ_Draw"
532b0a32e0cSBarry Smith static int MatView_SeqBAIJ_Draw(Mat A,PetscViewer viewer)
53377ed5343SBarry Smith {
5347dce120fSSatish Balay   int          ierr;
5350e6d2581SBarry Smith   PetscReal    xl,yl,xr,yr,w,h;
536b0a32e0cSBarry Smith   PetscDraw         draw;
53777ed5343SBarry Smith   PetscTruth   isnull;
5383270192aSSatish Balay 
53977ed5343SBarry Smith   PetscFunctionBegin;
54077ed5343SBarry Smith 
541b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
542b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
54377ed5343SBarry Smith 
54477ed5343SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
545273d9f13SBarry Smith   xr  = A->n; yr = A->m; h = yr/10.0; w = xr/10.0;
54677ed5343SBarry Smith   xr += w;    yr += h;  xl = -w;     yl = -h;
547b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
548b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqBAIJ_Draw_Zoom,A);CHKERRQ(ierr);
54977ed5343SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
5503a40ed3dSBarry Smith   PetscFunctionReturn(0);
5513270192aSSatish Balay }
5523270192aSSatish Balay 
5535615d1e5SSatish Balay #undef __FUNC__
554b0a32e0cSBarry Smith #define __FUNC__ "MatView_SeqBAIJ"
555b0a32e0cSBarry Smith int MatView_SeqBAIJ(Mat A,PetscViewer viewer)
5562593348eSBarry Smith {
55719bcc07fSBarry Smith   int        ierr;
5586831982aSBarry Smith   PetscTruth issocket,isascii,isbinary,isdraw;
5592593348eSBarry Smith 
5603a40ed3dSBarry Smith   PetscFunctionBegin;
561b0a32e0cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);CHKERRQ(ierr);
562b0a32e0cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
563fb9695e5SSatish Balay   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);CHKERRQ(ierr);
564fb9695e5SSatish Balay   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
5650f5bd95cSBarry Smith   if (issocket) {
56629bbc08cSBarry Smith     SETERRQ(PETSC_ERR_SUP,"Socket viewer not supported");
5670f5bd95cSBarry Smith   } else if (isascii){
5683a40ed3dSBarry Smith     ierr = MatView_SeqBAIJ_ASCII(A,viewer);CHKERRQ(ierr);
5690f5bd95cSBarry Smith   } else if (isbinary) {
5703a40ed3dSBarry Smith     ierr = MatView_SeqBAIJ_Binary(A,viewer);CHKERRQ(ierr);
5710f5bd95cSBarry Smith   } else if (isdraw) {
5723a40ed3dSBarry Smith     ierr = MatView_SeqBAIJ_Draw(A,viewer);CHKERRQ(ierr);
5735cd90555SBarry Smith   } else {
57429bbc08cSBarry Smith     SETERRQ1(1,"Viewer type %s not supported by SeqBAIJ matrices",((PetscObject)viewer)->type_name);
5752593348eSBarry Smith   }
5763a40ed3dSBarry Smith   PetscFunctionReturn(0);
5772593348eSBarry Smith }
578b6490206SBarry Smith 
579cd0e1443SSatish Balay 
5805615d1e5SSatish Balay #undef __FUNC__
581b0a32e0cSBarry Smith #define __FUNC__ "MatGetValues_SeqBAIJ"
5822d61bbb3SSatish Balay int MatGetValues_SeqBAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v)
583cd0e1443SSatish Balay {
584cd0e1443SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
5852d61bbb3SSatish Balay   int        *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
5862d61bbb3SSatish Balay   int        *ai = a->i,*ailen = a->ilen;
5872d61bbb3SSatish Balay   int        brow,bcol,ridx,cidx,bs=a->bs,bs2=a->bs2;
5883f1db9ecSBarry Smith   MatScalar  *ap,*aa = a->a,zero = 0.0;
589cd0e1443SSatish Balay 
5903a40ed3dSBarry Smith   PetscFunctionBegin;
5912d61bbb3SSatish Balay   for (k=0; k<m; k++) { /* loop over rows */
592cd0e1443SSatish Balay     row  = im[k]; brow = row/bs;
59329bbc08cSBarry Smith     if (row < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative row");
594273d9f13SBarry Smith     if (row >= A->m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
5952d61bbb3SSatish Balay     rp   = aj + ai[brow] ; ap = aa + bs2*ai[brow] ;
5962c3acbe9SBarry Smith     nrow = ailen[brow];
5972d61bbb3SSatish Balay     for (l=0; l<n; l++) { /* loop over columns */
59829bbc08cSBarry Smith       if (in[l] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative column");
599273d9f13SBarry Smith       if (in[l] >= A->n) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
6002d61bbb3SSatish Balay       col  = in[l] ;
6012d61bbb3SSatish Balay       bcol = col/bs;
6022d61bbb3SSatish Balay       cidx = col%bs;
6032d61bbb3SSatish Balay       ridx = row%bs;
6042d61bbb3SSatish Balay       high = nrow;
6052d61bbb3SSatish Balay       low  = 0; /* assume unsorted */
6062d61bbb3SSatish Balay       while (high-low > 5) {
607cd0e1443SSatish Balay         t = (low+high)/2;
608cd0e1443SSatish Balay         if (rp[t] > bcol) high = t;
609cd0e1443SSatish Balay         else             low  = t;
610cd0e1443SSatish Balay       }
611cd0e1443SSatish Balay       for (i=low; i<high; i++) {
612cd0e1443SSatish Balay         if (rp[i] > bcol) break;
613cd0e1443SSatish Balay         if (rp[i] == bcol) {
6142d61bbb3SSatish Balay           *v++ = ap[bs2*i+bs*cidx+ridx];
6152d61bbb3SSatish Balay           goto finished;
616cd0e1443SSatish Balay         }
617cd0e1443SSatish Balay       }
6182d61bbb3SSatish Balay       *v++ = zero;
6192d61bbb3SSatish Balay       finished:;
620cd0e1443SSatish Balay     }
621cd0e1443SSatish Balay   }
6223a40ed3dSBarry Smith   PetscFunctionReturn(0);
623cd0e1443SSatish Balay }
624cd0e1443SSatish Balay 
62595d5f7c2SBarry Smith #if defined(PETSC_USE_MAT_SINGLE)
62695d5f7c2SBarry Smith #undef __FUNC__
627b0a32e0cSBarry Smith #define __FUNC__ "MatSetValuesBlocked_SeqBAIJ"
62895d5f7c2SBarry Smith int MatSetValuesBlocked_SeqBAIJ(Mat mat,int m,int *im,int n,int *in,Scalar *v,InsertMode addv)
62995d5f7c2SBarry Smith {
630563b5814SBarry Smith   Mat_SeqBAIJ *b = (Mat_SeqBAIJ*)mat->data;
631563b5814SBarry Smith   int         ierr,i,N = m*n*b->bs2;
632563b5814SBarry Smith   MatScalar   *vsingle;
63395d5f7c2SBarry Smith 
63495d5f7c2SBarry Smith   PetscFunctionBegin;
635563b5814SBarry Smith   if (N > b->setvalueslen) {
636563b5814SBarry Smith     if (b->setvaluescopy) {ierr = PetscFree(b->setvaluescopy);CHKERRQ(ierr);}
637b0a32e0cSBarry Smith     ierr = PetscMalloc(N*sizeof(MatScalar),&b->setvaluescopy);CHKERRQ(ierr);
638563b5814SBarry Smith     b->setvalueslen  = N;
639563b5814SBarry Smith   }
640563b5814SBarry Smith   vsingle = b->setvaluescopy;
64195d5f7c2SBarry Smith   for (i=0; i<N; i++) {
64295d5f7c2SBarry Smith     vsingle[i] = v[i];
64395d5f7c2SBarry Smith   }
64495d5f7c2SBarry Smith   ierr = MatSetValuesBlocked_SeqBAIJ_MatScalar(mat,m,im,n,in,vsingle,addv);CHKERRQ(ierr);
64595d5f7c2SBarry Smith   PetscFunctionReturn(0);
64695d5f7c2SBarry Smith }
64795d5f7c2SBarry Smith #endif
64895d5f7c2SBarry Smith 
6492d61bbb3SSatish Balay 
6505615d1e5SSatish Balay #undef __FUNC__
651b0a32e0cSBarry Smith #define __FUNC__ "MatSetValuesBlocked_SeqBAIJ"
65295d5f7c2SBarry Smith int MatSetValuesBlocked_SeqBAIJ_MatScalar(Mat A,int m,int *im,int n,int *in,MatScalar *v,InsertMode is)
65392c4ed94SBarry Smith {
65492c4ed94SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
6558a84c255SSatish Balay   int         *rp,k,low,high,t,ii,jj,row,nrow,i,col,l,rmax,N,sorted=a->sorted;
656273d9f13SBarry Smith   int         *imax=a->imax,*ai=a->i,*ailen=a->ilen;
657549d3d68SSatish Balay   int         *aj=a->j,nonew=a->nonew,bs2=a->bs2,bs=a->bs,stepval,ierr;
658273d9f13SBarry Smith   PetscTruth  roworiented=a->roworiented;
65995d5f7c2SBarry Smith   MatScalar   *value = v,*ap,*aa = a->a,*bap;
66092c4ed94SBarry Smith 
6613a40ed3dSBarry Smith   PetscFunctionBegin;
6620e324ae4SSatish Balay   if (roworiented) {
6630e324ae4SSatish Balay     stepval = (n-1)*bs;
6640e324ae4SSatish Balay   } else {
6650e324ae4SSatish Balay     stepval = (m-1)*bs;
6660e324ae4SSatish Balay   }
66792c4ed94SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
66892c4ed94SBarry Smith     row  = im[k];
6695ef9f2a5SBarry Smith     if (row < 0) continue;
670aa482453SBarry Smith #if defined(PETSC_USE_BOPT_g)
67129bbc08cSBarry Smith     if (row >= a->mbs) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
67292c4ed94SBarry Smith #endif
67392c4ed94SBarry Smith     rp   = aj + ai[row];
67492c4ed94SBarry Smith     ap   = aa + bs2*ai[row];
67592c4ed94SBarry Smith     rmax = imax[row];
67692c4ed94SBarry Smith     nrow = ailen[row];
67792c4ed94SBarry Smith     low  = 0;
67892c4ed94SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
6795ef9f2a5SBarry Smith       if (in[l] < 0) continue;
680aa482453SBarry Smith #if defined(PETSC_USE_BOPT_g)
68129bbc08cSBarry Smith       if (in[l] >= a->nbs) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
68292c4ed94SBarry Smith #endif
68392c4ed94SBarry Smith       col = in[l];
68492c4ed94SBarry Smith       if (roworiented) {
6850e324ae4SSatish Balay         value = v + k*(stepval+bs)*bs + l*bs;
6860e324ae4SSatish Balay       } else {
6870e324ae4SSatish Balay         value = v + l*(stepval+bs)*bs + k*bs;
68892c4ed94SBarry Smith       }
68992c4ed94SBarry Smith       if (!sorted) low = 0; high = nrow;
69092c4ed94SBarry Smith       while (high-low > 7) {
69192c4ed94SBarry Smith         t = (low+high)/2;
69292c4ed94SBarry Smith         if (rp[t] > col) high = t;
69392c4ed94SBarry Smith         else             low  = t;
69492c4ed94SBarry Smith       }
69592c4ed94SBarry Smith       for (i=low; i<high; i++) {
69692c4ed94SBarry Smith         if (rp[i] > col) break;
69792c4ed94SBarry Smith         if (rp[i] == col) {
6988a84c255SSatish Balay           bap  = ap +  bs2*i;
6990e324ae4SSatish Balay           if (roworiented) {
7008a84c255SSatish Balay             if (is == ADD_VALUES) {
701dd9472c6SBarry Smith               for (ii=0; ii<bs; ii++,value+=stepval) {
702dd9472c6SBarry Smith                 for (jj=ii; jj<bs2; jj+=bs) {
7038a84c255SSatish Balay                   bap[jj] += *value++;
704dd9472c6SBarry Smith                 }
705dd9472c6SBarry Smith               }
7060e324ae4SSatish Balay             } else {
707dd9472c6SBarry Smith               for (ii=0; ii<bs; ii++,value+=stepval) {
708dd9472c6SBarry Smith                 for (jj=ii; jj<bs2; jj+=bs) {
7090e324ae4SSatish Balay                   bap[jj] = *value++;
7108a84c255SSatish Balay                 }
711dd9472c6SBarry Smith               }
712dd9472c6SBarry Smith             }
7130e324ae4SSatish Balay           } else {
7140e324ae4SSatish Balay             if (is == ADD_VALUES) {
715dd9472c6SBarry Smith               for (ii=0; ii<bs; ii++,value+=stepval) {
716dd9472c6SBarry Smith                 for (jj=0; jj<bs; jj++) {
7170e324ae4SSatish Balay                   *bap++ += *value++;
718dd9472c6SBarry Smith                 }
719dd9472c6SBarry Smith               }
7200e324ae4SSatish Balay             } else {
721dd9472c6SBarry Smith               for (ii=0; ii<bs; ii++,value+=stepval) {
722dd9472c6SBarry Smith                 for (jj=0; jj<bs; jj++) {
7230e324ae4SSatish Balay                   *bap++  = *value++;
7240e324ae4SSatish Balay                 }
7258a84c255SSatish Balay               }
726dd9472c6SBarry Smith             }
727dd9472c6SBarry Smith           }
728f1241b54SBarry Smith           goto noinsert2;
72992c4ed94SBarry Smith         }
73092c4ed94SBarry Smith       }
73189280ab3SLois Curfman McInnes       if (nonew == 1) goto noinsert2;
73229bbc08cSBarry Smith       else if (nonew == -1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
73392c4ed94SBarry Smith       if (nrow >= rmax) {
73492c4ed94SBarry Smith         /* there is no extra room in row, therefore enlarge */
73592c4ed94SBarry Smith         int       new_nz = ai[a->mbs] + CHUNKSIZE,len,*new_i,*new_j;
7363f1db9ecSBarry Smith         MatScalar *new_a;
73792c4ed94SBarry Smith 
73829bbc08cSBarry Smith         if (nonew == -2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
73989280ab3SLois Curfman McInnes 
74092c4ed94SBarry Smith         /* malloc new storage space */
7413f1db9ecSBarry Smith         len     = new_nz*(sizeof(int)+bs2*sizeof(MatScalar))+(a->mbs+1)*sizeof(int);
742b0a32e0cSBarry Smith 	ierr    = PetscMalloc(len,&new_a);CHKERRQ(ierr);
74392c4ed94SBarry Smith         new_j   = (int*)(new_a + bs2*new_nz);
74492c4ed94SBarry Smith         new_i   = new_j + new_nz;
74592c4ed94SBarry Smith 
74692c4ed94SBarry Smith         /* copy over old data into new slots */
74792c4ed94SBarry Smith         for (ii=0; ii<row+1; ii++) {new_i[ii] = ai[ii];}
74892c4ed94SBarry Smith         for (ii=row+1; ii<a->mbs+1; ii++) {new_i[ii] = ai[ii]+CHUNKSIZE;}
749549d3d68SSatish Balay         ierr = PetscMemcpy(new_j,aj,(ai[row]+nrow)*sizeof(int));CHKERRQ(ierr);
75092c4ed94SBarry Smith         len  = (new_nz - CHUNKSIZE - ai[row] - nrow);
751549d3d68SSatish Balay         ierr = PetscMemcpy(new_j+ai[row]+nrow+CHUNKSIZE,aj+ai[row]+nrow,len*sizeof(int));CHKERRQ(ierr);
752549d3d68SSatish Balay         ierr = PetscMemcpy(new_a,aa,(ai[row]+nrow)*bs2*sizeof(MatScalar));CHKERRQ(ierr);
753549d3d68SSatish Balay         ierr = PetscMemzero(new_a+bs2*(ai[row]+nrow),bs2*CHUNKSIZE*sizeof(MatScalar));CHKERRQ(ierr);
754549d3d68SSatish Balay         ierr = PetscMemcpy(new_a+bs2*(ai[row]+nrow+CHUNKSIZE),aa+bs2*(ai[row]+nrow),bs2*len*sizeof(MatScalar));CHKERRQ(ierr);
75592c4ed94SBarry Smith         /* free up old matrix storage */
756606d414cSSatish Balay         ierr = PetscFree(a->a);CHKERRQ(ierr);
757606d414cSSatish Balay         if (!a->singlemalloc) {
758606d414cSSatish Balay           ierr = PetscFree(a->i);CHKERRQ(ierr);
759606d414cSSatish Balay           ierr = PetscFree(a->j);CHKERRQ(ierr);
760606d414cSSatish Balay         }
76192c4ed94SBarry Smith         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;
762c4992f7dSBarry Smith         a->singlemalloc = PETSC_TRUE;
76392c4ed94SBarry Smith 
76492c4ed94SBarry Smith         rp   = aj + ai[row]; ap = aa + bs2*ai[row];
76592c4ed94SBarry Smith         rmax = imax[row] = imax[row] + CHUNKSIZE;
766b0a32e0cSBarry Smith         PetscLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + bs2*sizeof(MatScalar)));
76792c4ed94SBarry Smith         a->maxnz += bs2*CHUNKSIZE;
76892c4ed94SBarry Smith         a->reallocs++;
76992c4ed94SBarry Smith         a->nz++;
77092c4ed94SBarry Smith       }
77192c4ed94SBarry Smith       N = nrow++ - 1;
77292c4ed94SBarry Smith       /* shift up all the later entries in this row */
77392c4ed94SBarry Smith       for (ii=N; ii>=i; ii--) {
77492c4ed94SBarry Smith         rp[ii+1] = rp[ii];
775549d3d68SSatish Balay         ierr = PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));CHKERRQ(ierr);
77692c4ed94SBarry Smith       }
777549d3d68SSatish Balay       if (N >= i) {
778549d3d68SSatish Balay         ierr = PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));CHKERRQ(ierr);
779549d3d68SSatish Balay       }
78092c4ed94SBarry Smith       rp[i] = col;
7818a84c255SSatish Balay       bap   = ap +  bs2*i;
7820e324ae4SSatish Balay       if (roworiented) {
783dd9472c6SBarry Smith         for (ii=0; ii<bs; ii++,value+=stepval) {
784dd9472c6SBarry Smith           for (jj=ii; jj<bs2; jj+=bs) {
7850e324ae4SSatish Balay             bap[jj] = *value++;
786dd9472c6SBarry Smith           }
787dd9472c6SBarry Smith         }
7880e324ae4SSatish Balay       } else {
789dd9472c6SBarry Smith         for (ii=0; ii<bs; ii++,value+=stepval) {
790dd9472c6SBarry Smith           for (jj=0; jj<bs; jj++) {
7910e324ae4SSatish Balay             *bap++  = *value++;
7920e324ae4SSatish Balay           }
793dd9472c6SBarry Smith         }
794dd9472c6SBarry Smith       }
795f1241b54SBarry Smith       noinsert2:;
79692c4ed94SBarry Smith       low = i;
79792c4ed94SBarry Smith     }
79892c4ed94SBarry Smith     ailen[row] = nrow;
79992c4ed94SBarry Smith   }
8003a40ed3dSBarry Smith   PetscFunctionReturn(0);
80192c4ed94SBarry Smith }
80292c4ed94SBarry Smith 
803f2501298SSatish Balay 
8045615d1e5SSatish Balay #undef __FUNC__
805b0a32e0cSBarry Smith #define __FUNC__ "MatAssemblyEnd_SeqBAIJ"
8068f6be9afSLois Curfman McInnes int MatAssemblyEnd_SeqBAIJ(Mat A,MatAssemblyType mode)
807584200bdSSatish Balay {
808584200bdSSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
809584200bdSSatish Balay   int        fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
810273d9f13SBarry Smith   int        m = A->m,*ip,N,*ailen = a->ilen;
811549d3d68SSatish Balay   int        mbs = a->mbs,bs2 = a->bs2,rmax = 0,ierr;
8123f1db9ecSBarry Smith   MatScalar  *aa = a->a,*ap;
813584200bdSSatish Balay 
8143a40ed3dSBarry Smith   PetscFunctionBegin;
8153a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
816584200bdSSatish Balay 
81743ee02c3SBarry Smith   if (m) rmax = ailen[0];
818584200bdSSatish Balay   for (i=1; i<mbs; i++) {
819584200bdSSatish Balay     /* move each row back by the amount of empty slots (fshift) before it*/
820584200bdSSatish Balay     fshift += imax[i-1] - ailen[i-1];
821d402145bSBarry Smith     rmax   = PetscMax(rmax,ailen[i]);
822584200bdSSatish Balay     if (fshift) {
823a7c10996SSatish Balay       ip = aj + ai[i]; ap = aa + bs2*ai[i];
824584200bdSSatish Balay       N = ailen[i];
825584200bdSSatish Balay       for (j=0; j<N; j++) {
826584200bdSSatish Balay         ip[j-fshift] = ip[j];
827549d3d68SSatish Balay         ierr = PetscMemcpy(ap+(j-fshift)*bs2,ap+j*bs2,bs2*sizeof(MatScalar));CHKERRQ(ierr);
828584200bdSSatish Balay       }
829584200bdSSatish Balay     }
830584200bdSSatish Balay     ai[i] = ai[i-1] + ailen[i-1];
831584200bdSSatish Balay   }
832584200bdSSatish Balay   if (mbs) {
833584200bdSSatish Balay     fshift += imax[mbs-1] - ailen[mbs-1];
834584200bdSSatish Balay     ai[mbs] = ai[mbs-1] + ailen[mbs-1];
835584200bdSSatish Balay   }
836584200bdSSatish Balay   /* reset ilen and imax for each row */
837584200bdSSatish Balay   for (i=0; i<mbs; i++) {
838584200bdSSatish Balay     ailen[i] = imax[i] = ai[i+1] - ai[i];
839584200bdSSatish Balay   }
840a7c10996SSatish Balay   a->nz = ai[mbs];
841584200bdSSatish Balay 
842584200bdSSatish Balay   /* diagonals may have moved, so kill the diagonal pointers */
843584200bdSSatish Balay   if (fshift && a->diag) {
844606d414cSSatish Balay     ierr = PetscFree(a->diag);CHKERRQ(ierr);
845b0a32e0cSBarry Smith     PetscLogObjectMemory(A,-(m+1)*sizeof(int));
846584200bdSSatish Balay     a->diag = 0;
847584200bdSSatish Balay   }
848b0a32e0cSBarry Smith   PetscLogInfo(A,"MatAssemblyEnd_SeqBAIJ:Matrix size: %d X %d, block size %d; storage space: %d unneeded, %d used\n",
849273d9f13SBarry Smith            m,A->n,a->bs,fshift*bs2,a->nz*bs2);
850b0a32e0cSBarry Smith   PetscLogInfo(A,"MatAssemblyEnd_SeqBAIJ:Number of mallocs during MatSetValues is %d\n",
851584200bdSSatish Balay            a->reallocs);
852b0a32e0cSBarry Smith   PetscLogInfo(A,"MatAssemblyEnd_SeqBAIJ:Most nonzeros blocks in any row is %d\n",rmax);
853e2f3b5e9SSatish Balay   a->reallocs          = 0;
8540e6d2581SBarry Smith   A->info.nz_unneeded  = (PetscReal)fshift*bs2;
8554e220ebcSLois Curfman McInnes 
8563a40ed3dSBarry Smith   PetscFunctionReturn(0);
857584200bdSSatish Balay }
858584200bdSSatish Balay 
8595a838052SSatish Balay 
860bea157c4SSatish Balay 
861bea157c4SSatish Balay /*
862bea157c4SSatish Balay    This function returns an array of flags which indicate the locations of contiguous
863bea157c4SSatish Balay    blocks that should be zeroed. for eg: if bs = 3  and is = [0,1,2,3,5,6,7,8,9]
864bea157c4SSatish Balay    then the resulting sizes = [3,1,1,3,1] correspondig to sets [(0,1,2),(3),(5),(6,7,8),(9)]
865bea157c4SSatish Balay    Assume: sizes should be long enough to hold all the values.
866bea157c4SSatish Balay */
8675615d1e5SSatish Balay #undef __FUNC__
868b0a32e0cSBarry Smith #define __FUNC__ "MatZeroRows_SeqBAIJ_Check_Blocks"
869bea157c4SSatish Balay static int MatZeroRows_SeqBAIJ_Check_Blocks(int idx[],int n,int bs,int sizes[], int *bs_max)
870d9b7c43dSSatish Balay {
871bea157c4SSatish Balay   int        i,j,k,row;
872bea157c4SSatish Balay   PetscTruth flg;
8733a40ed3dSBarry Smith 
874433994e6SBarry Smith   PetscFunctionBegin;
875bea157c4SSatish Balay   for (i=0,j=0; i<n; j++) {
876bea157c4SSatish Balay     row = idx[i];
877bea157c4SSatish Balay     if (row%bs!=0) { /* Not the begining of a block */
878bea157c4SSatish Balay       sizes[j] = 1;
879bea157c4SSatish Balay       i++;
880e4fda26cSSatish Balay     } else if (i+bs > n) { /* complete block doesn't exist (at idx end) */
881bea157c4SSatish Balay       sizes[j] = 1;         /* Also makes sure atleast 'bs' values exist for next else */
882bea157c4SSatish Balay       i++;
883bea157c4SSatish Balay     } else { /* Begining of the block, so check if the complete block exists */
884bea157c4SSatish Balay       flg = PETSC_TRUE;
885bea157c4SSatish Balay       for (k=1; k<bs; k++) {
886bea157c4SSatish Balay         if (row+k != idx[i+k]) { /* break in the block */
887bea157c4SSatish Balay           flg = PETSC_FALSE;
888bea157c4SSatish Balay           break;
889d9b7c43dSSatish Balay         }
890bea157c4SSatish Balay       }
891bea157c4SSatish Balay       if (flg == PETSC_TRUE) { /* No break in the bs */
892bea157c4SSatish Balay         sizes[j] = bs;
893bea157c4SSatish Balay         i+= bs;
894bea157c4SSatish Balay       } else {
895bea157c4SSatish Balay         sizes[j] = 1;
896bea157c4SSatish Balay         i++;
897bea157c4SSatish Balay       }
898bea157c4SSatish Balay     }
899bea157c4SSatish Balay   }
900bea157c4SSatish Balay   *bs_max = j;
9013a40ed3dSBarry Smith   PetscFunctionReturn(0);
902d9b7c43dSSatish Balay }
903d9b7c43dSSatish Balay 
9045615d1e5SSatish Balay #undef __FUNC__
905b0a32e0cSBarry Smith #define __FUNC__ "MatZeroRows_SeqBAIJ"
9068f6be9afSLois Curfman McInnes int MatZeroRows_SeqBAIJ(Mat A,IS is,Scalar *diag)
907d9b7c43dSSatish Balay {
908d9b7c43dSSatish Balay   Mat_SeqBAIJ *baij=(Mat_SeqBAIJ*)A->data;
909b6815fffSBarry Smith   int         ierr,i,j,k,count,is_n,*is_idx,*rows;
910bea157c4SSatish Balay   int         bs=baij->bs,bs2=baij->bs2,*sizes,row,bs_max;
9113f1db9ecSBarry Smith   Scalar      zero = 0.0;
9123f1db9ecSBarry Smith   MatScalar   *aa;
913d9b7c43dSSatish Balay 
9143a40ed3dSBarry Smith   PetscFunctionBegin;
915d9b7c43dSSatish Balay   /* Make a copy of the IS and  sort it */
916b9b97703SBarry Smith   ierr = ISGetLocalSize(is,&is_n);CHKERRQ(ierr);
917d9b7c43dSSatish Balay   ierr = ISGetIndices(is,&is_idx);CHKERRQ(ierr);
918d9b7c43dSSatish Balay 
919bea157c4SSatish Balay   /* allocate memory for rows,sizes */
920b0a32e0cSBarry Smith   ierr  = PetscMalloc((3*is_n+1)*sizeof(int),&rows);CHKERRQ(ierr);
921bea157c4SSatish Balay   sizes = rows + is_n;
922bea157c4SSatish Balay 
923563b5814SBarry Smith   /* copy IS values to rows, and sort them */
924bea157c4SSatish Balay   for (i=0; i<is_n; i++) { rows[i] = is_idx[i]; }
925bea157c4SSatish Balay   ierr = PetscSortInt(is_n,rows);CHKERRQ(ierr);
926dffd3267SBarry Smith   if (baij->keepzeroedrows) {
927dffd3267SBarry Smith     for (i=0; i<is_n; i++) { sizes[i] = 1; }
928dffd3267SBarry Smith     bs_max = is_n;
929dffd3267SBarry Smith   } else {
930bea157c4SSatish Balay     ierr = MatZeroRows_SeqBAIJ_Check_Blocks(rows,is_n,bs,sizes,&bs_max);CHKERRQ(ierr);
931dffd3267SBarry Smith   }
932b97a56abSSatish Balay   ierr = ISRestoreIndices(is,&is_idx);CHKERRQ(ierr);
933bea157c4SSatish Balay 
934bea157c4SSatish Balay   for (i=0,j=0; i<bs_max; j+=sizes[i],i++) {
935bea157c4SSatish Balay     row   = rows[j];
936273d9f13SBarry Smith     if (row < 0 || row > A->m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"row %d out of range",row);
937bea157c4SSatish Balay     count = (baij->i[row/bs +1] - baij->i[row/bs])*bs;
938bea157c4SSatish Balay     aa    = baij->a + baij->i[row/bs]*bs2 + (row%bs);
939dffd3267SBarry Smith     if (sizes[i] == bs && !baij->keepzeroedrows) {
940bea157c4SSatish Balay       if (diag) {
941bea157c4SSatish Balay         if (baij->ilen[row/bs] > 0) {
942bea157c4SSatish Balay           baij->ilen[row/bs]       = 1;
943bea157c4SSatish Balay           baij->j[baij->i[row/bs]] = row/bs;
944bea157c4SSatish Balay           ierr = PetscMemzero(aa,count*bs*sizeof(MatScalar));CHKERRQ(ierr);
945a07cd24cSSatish Balay         }
946563b5814SBarry Smith         /* Now insert all the diagonal values for this bs */
947bea157c4SSatish Balay         for (k=0; k<bs; k++) {
948bea157c4SSatish Balay           ierr = (*A->ops->setvalues)(A,1,rows+j+k,1,rows+j+k,diag,INSERT_VALUES);CHKERRQ(ierr);
949bea157c4SSatish Balay         }
950bea157c4SSatish Balay       } else { /* (!diag) */
951bea157c4SSatish Balay         baij->ilen[row/bs] = 0;
952bea157c4SSatish Balay       } /* end (!diag) */
953bea157c4SSatish Balay     } else { /* (sizes[i] != bs) */
954aa482453SBarry Smith #if defined (PETSC_USE_DEBUG)
95529bbc08cSBarry Smith       if (sizes[i] != 1) SETERRQ(1,"Internal Error. Value should be 1");
956bea157c4SSatish Balay #endif
957bea157c4SSatish Balay       for (k=0; k<count; k++) {
958d9b7c43dSSatish Balay         aa[0] =  zero;
959d9b7c43dSSatish Balay         aa    += bs;
960d9b7c43dSSatish Balay       }
961d9b7c43dSSatish Balay       if (diag) {
962f830108cSBarry Smith         ierr = (*A->ops->setvalues)(A,1,rows+j,1,rows+j,diag,INSERT_VALUES);CHKERRQ(ierr);
963d9b7c43dSSatish Balay       }
964d9b7c43dSSatish Balay     }
965bea157c4SSatish Balay   }
966bea157c4SSatish Balay 
967606d414cSSatish Balay   ierr = PetscFree(rows);CHKERRQ(ierr);
9689a8dea36SBarry Smith   ierr = MatAssemblyEnd_SeqBAIJ(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9693a40ed3dSBarry Smith   PetscFunctionReturn(0);
970d9b7c43dSSatish Balay }
9711c351548SSatish Balay 
9725615d1e5SSatish Balay #undef __FUNC__
973b0a32e0cSBarry Smith #define __FUNC__ "MatSetValues_SeqBAIJ"
9742d61bbb3SSatish Balay int MatSetValues_SeqBAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v,InsertMode is)
9752d61bbb3SSatish Balay {
9762d61bbb3SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
9772d61bbb3SSatish Balay   int         *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,sorted=a->sorted;
978273d9f13SBarry Smith   int         *imax=a->imax,*ai=a->i,*ailen=a->ilen;
9792d61bbb3SSatish Balay   int         *aj=a->j,nonew=a->nonew,bs=a->bs,brow,bcol;
980549d3d68SSatish Balay   int         ridx,cidx,bs2=a->bs2,ierr;
981273d9f13SBarry Smith   PetscTruth  roworiented=a->roworiented;
9823f1db9ecSBarry Smith   MatScalar   *ap,value,*aa=a->a,*bap;
9832d61bbb3SSatish Balay 
9842d61bbb3SSatish Balay   PetscFunctionBegin;
9852d61bbb3SSatish Balay   for (k=0; k<m; k++) { /* loop over added rows */
9862d61bbb3SSatish Balay     row  = im[k]; brow = row/bs;
9875ef9f2a5SBarry Smith     if (row < 0) continue;
988aa482453SBarry Smith #if defined(PETSC_USE_BOPT_g)
989273d9f13SBarry Smith     if (row >= A->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %d max %d",row,A->m);
9902d61bbb3SSatish Balay #endif
9912d61bbb3SSatish Balay     rp   = aj + ai[brow];
9922d61bbb3SSatish Balay     ap   = aa + bs2*ai[brow];
9932d61bbb3SSatish Balay     rmax = imax[brow];
9942d61bbb3SSatish Balay     nrow = ailen[brow];
9952d61bbb3SSatish Balay     low  = 0;
9962d61bbb3SSatish Balay     for (l=0; l<n; l++) { /* loop over added columns */
9975ef9f2a5SBarry Smith       if (in[l] < 0) continue;
998aa482453SBarry Smith #if defined(PETSC_USE_BOPT_g)
999273d9f13SBarry Smith       if (in[l] >= A->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %d max %d",in[l],A->n);
10002d61bbb3SSatish Balay #endif
10012d61bbb3SSatish Balay       col = in[l]; bcol = col/bs;
10022d61bbb3SSatish Balay       ridx = row % bs; cidx = col % bs;
10032d61bbb3SSatish Balay       if (roworiented) {
10045ef9f2a5SBarry Smith         value = v[l + k*n];
10052d61bbb3SSatish Balay       } else {
10062d61bbb3SSatish Balay         value = v[k + l*m];
10072d61bbb3SSatish Balay       }
10082d61bbb3SSatish Balay       if (!sorted) low = 0; high = nrow;
10092d61bbb3SSatish Balay       while (high-low > 7) {
10102d61bbb3SSatish Balay         t = (low+high)/2;
10112d61bbb3SSatish Balay         if (rp[t] > bcol) high = t;
10122d61bbb3SSatish Balay         else              low  = t;
10132d61bbb3SSatish Balay       }
10142d61bbb3SSatish Balay       for (i=low; i<high; i++) {
10152d61bbb3SSatish Balay         if (rp[i] > bcol) break;
10162d61bbb3SSatish Balay         if (rp[i] == bcol) {
10172d61bbb3SSatish Balay           bap  = ap +  bs2*i + bs*cidx + ridx;
10182d61bbb3SSatish Balay           if (is == ADD_VALUES) *bap += value;
10192d61bbb3SSatish Balay           else                  *bap  = value;
10202d61bbb3SSatish Balay           goto noinsert1;
10212d61bbb3SSatish Balay         }
10222d61bbb3SSatish Balay       }
10232d61bbb3SSatish Balay       if (nonew == 1) goto noinsert1;
102429bbc08cSBarry Smith       else if (nonew == -1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
10252d61bbb3SSatish Balay       if (nrow >= rmax) {
10262d61bbb3SSatish Balay         /* there is no extra room in row, therefore enlarge */
10272d61bbb3SSatish Balay         int       new_nz = ai[a->mbs] + CHUNKSIZE,len,*new_i,*new_j;
10283f1db9ecSBarry Smith         MatScalar *new_a;
10292d61bbb3SSatish Balay 
103029bbc08cSBarry Smith         if (nonew == -2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
10312d61bbb3SSatish Balay 
10322d61bbb3SSatish Balay         /* Malloc new storage space */
10333f1db9ecSBarry Smith         len     = new_nz*(sizeof(int)+bs2*sizeof(MatScalar))+(a->mbs+1)*sizeof(int);
1034b0a32e0cSBarry Smith 	ierr    = PetscMalloc(len,&new_a);CHKERRQ(ierr);
10352d61bbb3SSatish Balay         new_j   = (int*)(new_a + bs2*new_nz);
10362d61bbb3SSatish Balay         new_i   = new_j + new_nz;
10372d61bbb3SSatish Balay 
10382d61bbb3SSatish Balay         /* copy over old data into new slots */
10392d61bbb3SSatish Balay         for (ii=0; ii<brow+1; ii++) {new_i[ii] = ai[ii];}
10402d61bbb3SSatish Balay         for (ii=brow+1; ii<a->mbs+1; ii++) {new_i[ii] = ai[ii]+CHUNKSIZE;}
1041549d3d68SSatish Balay         ierr = PetscMemcpy(new_j,aj,(ai[brow]+nrow)*sizeof(int));CHKERRQ(ierr);
10422d61bbb3SSatish Balay         len  = (new_nz - CHUNKSIZE - ai[brow] - nrow);
1043549d3d68SSatish Balay         ierr = PetscMemcpy(new_j+ai[brow]+nrow+CHUNKSIZE,aj+ai[brow]+nrow,len*sizeof(int));CHKERRQ(ierr);
1044549d3d68SSatish Balay         ierr = PetscMemcpy(new_a,aa,(ai[brow]+nrow)*bs2*sizeof(MatScalar));CHKERRQ(ierr);
1045549d3d68SSatish Balay         ierr = PetscMemzero(new_a+bs2*(ai[brow]+nrow),bs2*CHUNKSIZE*sizeof(MatScalar));CHKERRQ(ierr);
1046549d3d68SSatish Balay         ierr = PetscMemcpy(new_a+bs2*(ai[brow]+nrow+CHUNKSIZE),aa+bs2*(ai[brow]+nrow),bs2*len*sizeof(MatScalar));CHKERRQ(ierr);
10472d61bbb3SSatish Balay         /* free up old matrix storage */
1048606d414cSSatish Balay         ierr = PetscFree(a->a);CHKERRQ(ierr);
1049606d414cSSatish Balay         if (!a->singlemalloc) {
1050606d414cSSatish Balay           ierr = PetscFree(a->i);CHKERRQ(ierr);
1051606d414cSSatish Balay           ierr = PetscFree(a->j);CHKERRQ(ierr);
1052606d414cSSatish Balay         }
10532d61bbb3SSatish Balay         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;
1054c4992f7dSBarry Smith         a->singlemalloc = PETSC_TRUE;
10552d61bbb3SSatish Balay 
10562d61bbb3SSatish Balay         rp   = aj + ai[brow]; ap = aa + bs2*ai[brow];
10572d61bbb3SSatish Balay         rmax = imax[brow] = imax[brow] + CHUNKSIZE;
1058b0a32e0cSBarry Smith         PetscLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + bs2*sizeof(MatScalar)));
10592d61bbb3SSatish Balay         a->maxnz += bs2*CHUNKSIZE;
10602d61bbb3SSatish Balay         a->reallocs++;
10612d61bbb3SSatish Balay         a->nz++;
10622d61bbb3SSatish Balay       }
10632d61bbb3SSatish Balay       N = nrow++ - 1;
10642d61bbb3SSatish Balay       /* shift up all the later entries in this row */
10652d61bbb3SSatish Balay       for (ii=N; ii>=i; ii--) {
10662d61bbb3SSatish Balay         rp[ii+1] = rp[ii];
1067549d3d68SSatish Balay         ierr     = PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));CHKERRQ(ierr);
10682d61bbb3SSatish Balay       }
1069549d3d68SSatish Balay       if (N>=i) {
1070549d3d68SSatish Balay         ierr = PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));CHKERRQ(ierr);
1071549d3d68SSatish Balay       }
10722d61bbb3SSatish Balay       rp[i]                      = bcol;
10732d61bbb3SSatish Balay       ap[bs2*i + bs*cidx + ridx] = value;
10742d61bbb3SSatish Balay       noinsert1:;
10752d61bbb3SSatish Balay       low = i;
10762d61bbb3SSatish Balay     }
10772d61bbb3SSatish Balay     ailen[brow] = nrow;
10782d61bbb3SSatish Balay   }
10792d61bbb3SSatish Balay   PetscFunctionReturn(0);
10802d61bbb3SSatish Balay }
10812d61bbb3SSatish Balay 
1082b9b97703SBarry Smith EXTERN int MatLUFactorSymbolic_SeqBAIJ(Mat,IS,IS,MatLUInfo*,Mat*);
1083b9b97703SBarry Smith EXTERN int MatLUFactor_SeqBAIJ(Mat,IS,IS,MatLUInfo*);
1084ca44d042SBarry Smith EXTERN int MatIncreaseOverlap_SeqBAIJ(Mat,int,IS*,int);
1085ca44d042SBarry Smith EXTERN int MatGetSubMatrix_SeqBAIJ(Mat,IS,IS,int,MatReuse,Mat*);
1086ca44d042SBarry Smith EXTERN int MatGetSubMatrices_SeqBAIJ(Mat,int,IS*,IS*,MatReuse,Mat**);
1087ca44d042SBarry Smith EXTERN int MatMultTranspose_SeqBAIJ(Mat,Vec,Vec);
1088ca44d042SBarry Smith EXTERN int MatMultTransposeAdd_SeqBAIJ(Mat,Vec,Vec,Vec);
1089ca44d042SBarry Smith EXTERN int MatScale_SeqBAIJ(Scalar*,Mat);
1090ca44d042SBarry Smith EXTERN int MatNorm_SeqBAIJ(Mat,NormType,PetscReal *);
1091ca44d042SBarry Smith EXTERN int MatEqual_SeqBAIJ(Mat,Mat,PetscTruth*);
1092ca44d042SBarry Smith EXTERN int MatGetDiagonal_SeqBAIJ(Mat,Vec);
1093ca44d042SBarry Smith EXTERN int MatDiagonalScale_SeqBAIJ(Mat,Vec,Vec);
1094ca44d042SBarry Smith EXTERN int MatGetInfo_SeqBAIJ(Mat,MatInfoType,MatInfo *);
1095ca44d042SBarry Smith EXTERN int MatZeroEntries_SeqBAIJ(Mat);
10962d61bbb3SSatish Balay 
1097ca44d042SBarry Smith EXTERN int MatSolve_SeqBAIJ_N(Mat,Vec,Vec);
1098ca44d042SBarry Smith EXTERN int MatSolve_SeqBAIJ_1(Mat,Vec,Vec);
1099ca44d042SBarry Smith EXTERN int MatSolve_SeqBAIJ_2(Mat,Vec,Vec);
1100ca44d042SBarry Smith EXTERN int MatSolve_SeqBAIJ_3(Mat,Vec,Vec);
1101ca44d042SBarry Smith EXTERN int MatSolve_SeqBAIJ_4(Mat,Vec,Vec);
1102ca44d042SBarry Smith EXTERN int MatSolve_SeqBAIJ_5(Mat,Vec,Vec);
1103ca44d042SBarry Smith EXTERN int MatSolve_SeqBAIJ_6(Mat,Vec,Vec);
1104ca44d042SBarry Smith EXTERN int MatSolve_SeqBAIJ_7(Mat,Vec,Vec);
1105ca44d042SBarry Smith EXTERN int MatSolveTranspose_SeqBAIJ_7(Mat,Vec,Vec);
1106ca44d042SBarry Smith EXTERN int MatSolveTranspose_SeqBAIJ_6(Mat,Vec,Vec);
1107ca44d042SBarry Smith EXTERN int MatSolveTranspose_SeqBAIJ_5(Mat,Vec,Vec);
1108ca44d042SBarry Smith EXTERN int MatSolveTranspose_SeqBAIJ_4(Mat,Vec,Vec);
1109ca44d042SBarry Smith EXTERN int MatSolveTranspose_SeqBAIJ_3(Mat,Vec,Vec);
1110ca44d042SBarry Smith EXTERN int MatSolveTranspose_SeqBAIJ_2(Mat,Vec,Vec);
1111ca44d042SBarry Smith EXTERN int MatSolveTranspose_SeqBAIJ_1(Mat,Vec,Vec);
11122d61bbb3SSatish Balay 
1113ca44d042SBarry Smith EXTERN int MatLUFactorNumeric_SeqBAIJ_N(Mat,Mat*);
1114ca44d042SBarry Smith EXTERN int MatLUFactorNumeric_SeqBAIJ_1(Mat,Mat*);
1115ca44d042SBarry Smith EXTERN int MatLUFactorNumeric_SeqBAIJ_2(Mat,Mat*);
1116ca44d042SBarry Smith EXTERN int MatLUFactorNumeric_SeqBAIJ_3(Mat,Mat*);
1117ca44d042SBarry Smith EXTERN int MatLUFactorNumeric_SeqBAIJ_4(Mat,Mat*);
1118ca44d042SBarry Smith EXTERN int MatLUFactorNumeric_SeqBAIJ_5(Mat,Mat*);
1119ca44d042SBarry Smith EXTERN int MatLUFactorNumeric_SeqBAIJ_6(Mat,Mat*);
11202d61bbb3SSatish Balay 
1121ca44d042SBarry Smith EXTERN int MatMult_SeqBAIJ_1(Mat,Vec,Vec);
1122ca44d042SBarry Smith EXTERN int MatMult_SeqBAIJ_2(Mat,Vec,Vec);
1123ca44d042SBarry Smith EXTERN int MatMult_SeqBAIJ_3(Mat,Vec,Vec);
1124ca44d042SBarry Smith EXTERN int MatMult_SeqBAIJ_4(Mat,Vec,Vec);
1125ca44d042SBarry Smith EXTERN int MatMult_SeqBAIJ_5(Mat,Vec,Vec);
1126ca44d042SBarry Smith EXTERN int MatMult_SeqBAIJ_6(Mat,Vec,Vec);
1127ca44d042SBarry Smith EXTERN int MatMult_SeqBAIJ_7(Mat,Vec,Vec);
1128ca44d042SBarry Smith EXTERN int MatMult_SeqBAIJ_N(Mat,Vec,Vec);
11292d61bbb3SSatish Balay 
1130ca44d042SBarry Smith EXTERN int MatMultAdd_SeqBAIJ_1(Mat,Vec,Vec,Vec);
1131ca44d042SBarry Smith EXTERN int MatMultAdd_SeqBAIJ_2(Mat,Vec,Vec,Vec);
1132ca44d042SBarry Smith EXTERN int MatMultAdd_SeqBAIJ_3(Mat,Vec,Vec,Vec);
1133ca44d042SBarry Smith EXTERN int MatMultAdd_SeqBAIJ_4(Mat,Vec,Vec,Vec);
1134ca44d042SBarry Smith EXTERN int MatMultAdd_SeqBAIJ_5(Mat,Vec,Vec,Vec);
1135ca44d042SBarry Smith EXTERN int MatMultAdd_SeqBAIJ_6(Mat,Vec,Vec,Vec);
1136ca44d042SBarry Smith EXTERN int MatMultAdd_SeqBAIJ_7(Mat,Vec,Vec,Vec);
1137ca44d042SBarry Smith EXTERN int MatMultAdd_SeqBAIJ_N(Mat,Vec,Vec,Vec);
11382d61bbb3SSatish Balay 
11392d61bbb3SSatish Balay #undef __FUNC__
1140b0a32e0cSBarry Smith #define __FUNC__ "MatILUFactor_SeqBAIJ"
11415ef9f2a5SBarry Smith int MatILUFactor_SeqBAIJ(Mat inA,IS row,IS col,MatILUInfo *info)
11422d61bbb3SSatish Balay {
11432d61bbb3SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)inA->data;
11442d61bbb3SSatish Balay   Mat         outA;
11452d61bbb3SSatish Balay   int         ierr;
1146667159a5SBarry Smith   PetscTruth  row_identity,col_identity;
11472d61bbb3SSatish Balay 
11482d61bbb3SSatish Balay   PetscFunctionBegin;
114929bbc08cSBarry Smith   if (info && info->levels != 0) SETERRQ(PETSC_ERR_SUP,"Only levels = 0 supported for in-place ILU");
1150667159a5SBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
1151667159a5SBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
1152667159a5SBarry Smith   if (!row_identity || !col_identity) {
115329bbc08cSBarry Smith     SETERRQ(1,"Row and column permutations must be identity for in-place ILU");
1154667159a5SBarry Smith   }
11552d61bbb3SSatish Balay 
11562d61bbb3SSatish Balay   outA          = inA;
11572d61bbb3SSatish Balay   inA->factor   = FACTOR_LU;
11582d61bbb3SSatish Balay 
11592d61bbb3SSatish Balay   if (!a->diag) {
1160c4992f7dSBarry Smith     ierr = MatMarkDiagonal_SeqBAIJ(inA);CHKERRQ(ierr);
11612d61bbb3SSatish Balay   }
11622d61bbb3SSatish Balay   /*
116315091d37SBarry Smith       Blocksize 2, 3, 4, 5, 6 and 7 have a special faster factorization/solver
116415091d37SBarry Smith       for ILU(0) factorization with natural ordering
11652d61bbb3SSatish Balay   */
116615091d37SBarry Smith   switch (a->bs) {
1167f1af5d2fSBarry Smith   case 1:
1168e37c484bSBarry Smith     inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_1;
1169e37c484bSBarry Smith     inA->ops->solve           = MatSolve_SeqBAIJ_1_NaturalOrdering;
1170e37c484bSBarry Smith     inA->ops->solvetranspose  = MatSolveTranspose_SeqBAIJ_1_NaturalOrdering;
1171b0a32e0cSBarry Smith     PetscLogInfo(inA,"MatILUFactor_SeqBAIJ:Using special in-place natural ordering factor and solve BS=1\n");
117215091d37SBarry Smith   case 2:
117315091d37SBarry Smith     inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_2_NaturalOrdering;
117415091d37SBarry Smith     inA->ops->solve           = MatSolve_SeqBAIJ_2_NaturalOrdering;
11757c922b88SBarry Smith     inA->ops->solvetranspose  = MatSolveTranspose_SeqBAIJ_2_NaturalOrdering;
1176b0a32e0cSBarry Smith     PetscLogInfo(inA,"MatILUFactor_SeqBAIJ:Using special in-place natural ordering factor and solve BS=2\n");
117715091d37SBarry Smith     break;
117815091d37SBarry Smith   case 3:
117915091d37SBarry Smith     inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_3_NaturalOrdering;
118015091d37SBarry Smith     inA->ops->solve           = MatSolve_SeqBAIJ_3_NaturalOrdering;
11817c922b88SBarry Smith     inA->ops->solvetranspose  = MatSolveTranspose_SeqBAIJ_3_NaturalOrdering;
1182b0a32e0cSBarry Smith     PetscLogInfo(inA,"MatILUFactor_SeqBAIJ:Using special in-place natural ordering factor and solve BS=3\n");
118315091d37SBarry Smith     break;
118415091d37SBarry Smith   case 4:
1185667159a5SBarry Smith     inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_4_NaturalOrdering;
1186f830108cSBarry Smith     inA->ops->solve           = MatSolve_SeqBAIJ_4_NaturalOrdering;
11877c922b88SBarry Smith     inA->ops->solvetranspose  = MatSolveTranspose_SeqBAIJ_4_NaturalOrdering;
1188b0a32e0cSBarry Smith     PetscLogInfo(inA,"MatILUFactor_SeqBAIJ:Using special in-place natural ordering factor and solve BS=4\n");
118915091d37SBarry Smith     break;
119015091d37SBarry Smith   case 5:
1191667159a5SBarry Smith     inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_5_NaturalOrdering;
1192667159a5SBarry Smith     inA->ops->solve           = MatSolve_SeqBAIJ_5_NaturalOrdering;
11937c922b88SBarry Smith     inA->ops->solvetranspose  = MatSolveTranspose_SeqBAIJ_5_NaturalOrdering;
1194b0a32e0cSBarry Smith     PetscLogInfo(inA,"MatILUFactor_SeqBAIJ:Using special in-place natural ordering factor and solve BS=5\n");
119515091d37SBarry Smith     break;
119615091d37SBarry Smith   case 6:
119715091d37SBarry Smith     inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_6_NaturalOrdering;
119815091d37SBarry Smith     inA->ops->solve           = MatSolve_SeqBAIJ_6_NaturalOrdering;
11997c922b88SBarry Smith     inA->ops->solvetranspose  = MatSolveTranspose_SeqBAIJ_6_NaturalOrdering;
1200b0a32e0cSBarry Smith     PetscLogInfo(inA,"MatILUFactor_SeqBAIJ:Using special in-place natural ordering factor and solve BS=6\n");
120115091d37SBarry Smith     break;
120215091d37SBarry Smith   case 7:
120315091d37SBarry Smith     inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_7_NaturalOrdering;
12047c922b88SBarry Smith     inA->ops->solvetranspose  = MatSolveTranspose_SeqBAIJ_7_NaturalOrdering;
120515091d37SBarry Smith     inA->ops->solve           = MatSolve_SeqBAIJ_7_NaturalOrdering;
1206b0a32e0cSBarry Smith     PetscLogInfo(inA,"MatILUFactor_SeqBAIJ:Using special in-place natural ordering factor and solve BS=7\n");
120715091d37SBarry Smith     break;
1208c38d4ed2SBarry Smith   default:
1209c38d4ed2SBarry Smith     a->row        = row;
1210c38d4ed2SBarry Smith     a->col        = col;
1211c38d4ed2SBarry Smith     ierr          = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
1212c38d4ed2SBarry Smith     ierr          = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
1213c38d4ed2SBarry Smith 
1214c38d4ed2SBarry Smith     /* Create the invert permutation so that it can be used in MatLUFactorNumeric() */
12154c49b128SBarry Smith     ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
1216b0a32e0cSBarry Smith     PetscLogObjectParent(inA,a->icol);
1217c38d4ed2SBarry Smith 
1218c38d4ed2SBarry Smith     if (!a->solve_work) {
1219b0a32e0cSBarry Smith       ierr = PetscMalloc((inA->m+a->bs)*sizeof(Scalar),&a->solve_work);CHKERRQ(ierr);
1220b0a32e0cSBarry Smith       PetscLogObjectMemory(inA,(inA->m+a->bs)*sizeof(Scalar));
1221c38d4ed2SBarry Smith     }
12222d61bbb3SSatish Balay   }
12232d61bbb3SSatish Balay 
1224667159a5SBarry Smith   ierr = MatLUFactorNumeric(inA,&outA);CHKERRQ(ierr);
1225667159a5SBarry Smith 
12262d61bbb3SSatish Balay   PetscFunctionReturn(0);
12272d61bbb3SSatish Balay }
12282d61bbb3SSatish Balay #undef __FUNC__
1229b0a32e0cSBarry Smith #define __FUNC__ "MatPrintHelp_SeqBAIJ"
1230ba4ca20aSSatish Balay int MatPrintHelp_SeqBAIJ(Mat A)
1231ba4ca20aSSatish Balay {
1232c38d4ed2SBarry Smith   static PetscTruth called = PETSC_FALSE;
1233ba4ca20aSSatish Balay   MPI_Comm          comm = A->comm;
1234d132466eSBarry Smith   int               ierr;
1235ba4ca20aSSatish Balay 
12363a40ed3dSBarry Smith   PetscFunctionBegin;
1237c38d4ed2SBarry Smith   if (called) {PetscFunctionReturn(0);} else called = PETSC_TRUE;
1238d132466eSBarry Smith   ierr = (*PetscHelpPrintf)(comm," Options for MATSEQBAIJ and MATMPIBAIJ matrix formats (the defaults):\n");CHKERRQ(ierr);
1239d132466eSBarry Smith   ierr = (*PetscHelpPrintf)(comm,"  -mat_block_size <block_size>\n");CHKERRQ(ierr);
12403a40ed3dSBarry Smith   PetscFunctionReturn(0);
1241ba4ca20aSSatish Balay }
1242d9b7c43dSSatish Balay 
1243fb2e594dSBarry Smith EXTERN_C_BEGIN
124427a8da17SBarry Smith #undef __FUNC__
1245b0a32e0cSBarry Smith #define __FUNC__ "MatSeqBAIJSetColumnIndices_SeqBAIJ"
124627a8da17SBarry Smith int MatSeqBAIJSetColumnIndices_SeqBAIJ(Mat mat,int *indices)
124727a8da17SBarry Smith {
124827a8da17SBarry Smith   Mat_SeqBAIJ *baij = (Mat_SeqBAIJ *)mat->data;
124927a8da17SBarry Smith   int         i,nz,n;
125027a8da17SBarry Smith 
125127a8da17SBarry Smith   PetscFunctionBegin;
125227a8da17SBarry Smith   nz = baij->maxnz;
1253273d9f13SBarry Smith   n  = mat->n;
125427a8da17SBarry Smith   for (i=0; i<nz; i++) {
125527a8da17SBarry Smith     baij->j[i] = indices[i];
125627a8da17SBarry Smith   }
125727a8da17SBarry Smith   baij->nz = nz;
125827a8da17SBarry Smith   for (i=0; i<n; i++) {
125927a8da17SBarry Smith     baij->ilen[i] = baij->imax[i];
126027a8da17SBarry Smith   }
126127a8da17SBarry Smith 
126227a8da17SBarry Smith   PetscFunctionReturn(0);
126327a8da17SBarry Smith }
1264fb2e594dSBarry Smith EXTERN_C_END
126527a8da17SBarry Smith 
126627a8da17SBarry Smith #undef __FUNC__
1267b0a32e0cSBarry Smith #define __FUNC__ "MatSeqBAIJSetColumnIndices"
126827a8da17SBarry Smith /*@
126927a8da17SBarry Smith     MatSeqBAIJSetColumnIndices - Set the column indices for all the rows
127027a8da17SBarry Smith        in the matrix.
127127a8da17SBarry Smith 
127227a8da17SBarry Smith   Input Parameters:
127327a8da17SBarry Smith +  mat - the SeqBAIJ matrix
127427a8da17SBarry Smith -  indices - the column indices
127527a8da17SBarry Smith 
127615091d37SBarry Smith   Level: advanced
127715091d37SBarry Smith 
127827a8da17SBarry Smith   Notes:
127927a8da17SBarry Smith     This can be called if you have precomputed the nonzero structure of the
128027a8da17SBarry Smith   matrix and want to provide it to the matrix object to improve the performance
128127a8da17SBarry Smith   of the MatSetValues() operation.
128227a8da17SBarry Smith 
128327a8da17SBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
128427a8da17SBarry Smith   MatCreateSeqBAIJ().
128527a8da17SBarry Smith 
128627a8da17SBarry Smith     MUST be called before any calls to MatSetValues();
128727a8da17SBarry Smith 
128827a8da17SBarry Smith @*/
128927a8da17SBarry Smith int MatSeqBAIJSetColumnIndices(Mat mat,int *indices)
129027a8da17SBarry Smith {
129127a8da17SBarry Smith   int ierr,(*f)(Mat,int *);
129227a8da17SBarry Smith 
129327a8da17SBarry Smith   PetscFunctionBegin;
129427a8da17SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1295549d3d68SSatish Balay   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqBAIJSetColumnIndices_C",(void **)&f);CHKERRQ(ierr);
129627a8da17SBarry Smith   if (f) {
129727a8da17SBarry Smith     ierr = (*f)(mat,indices);CHKERRQ(ierr);
129827a8da17SBarry Smith   } else {
129929bbc08cSBarry Smith     SETERRQ(1,"Wrong type of matrix to set column indices");
130027a8da17SBarry Smith   }
130127a8da17SBarry Smith   PetscFunctionReturn(0);
130227a8da17SBarry Smith }
130327a8da17SBarry Smith 
1304273d9f13SBarry Smith #undef __FUNC__
1305273d9f13SBarry Smith #define __FUNC__ "MatGetRowMax_SeqBAIJ"
1306273d9f13SBarry Smith int MatGetRowMax_SeqBAIJ(Mat A,Vec v)
1307273d9f13SBarry Smith {
1308273d9f13SBarry Smith   Mat_SeqBAIJ  *a = (Mat_SeqBAIJ*)A->data;
1309273d9f13SBarry Smith   int          ierr,i,j,n,row,bs,*ai,*aj,mbs;
1310273d9f13SBarry Smith   PetscReal    atmp;
1311273d9f13SBarry Smith   Scalar       *x,zero = 0.0;
1312273d9f13SBarry Smith   MatScalar    *aa;
1313273d9f13SBarry Smith   int          ncols,brow,krow,kcol;
1314273d9f13SBarry Smith 
1315273d9f13SBarry Smith   PetscFunctionBegin;
1316273d9f13SBarry Smith   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1317273d9f13SBarry Smith   bs   = a->bs;
1318273d9f13SBarry Smith   aa   = a->a;
1319273d9f13SBarry Smith   ai   = a->i;
1320273d9f13SBarry Smith   aj   = a->j;
1321273d9f13SBarry Smith   mbs = a->mbs;
1322273d9f13SBarry Smith 
1323273d9f13SBarry Smith   ierr = VecSet(&zero,v);CHKERRQ(ierr);
1324273d9f13SBarry Smith   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1325273d9f13SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1326273d9f13SBarry Smith   if (n != A->m) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1327273d9f13SBarry Smith   for (i=0; i<mbs; i++) {
1328273d9f13SBarry Smith     ncols = ai[1] - ai[0]; ai++;
1329273d9f13SBarry Smith     brow  = bs*i;
1330273d9f13SBarry Smith     for (j=0; j<ncols; j++){
1331273d9f13SBarry Smith       /* bcol = bs*(*aj); */
1332273d9f13SBarry Smith       for (kcol=0; kcol<bs; kcol++){
1333273d9f13SBarry Smith         for (krow=0; krow<bs; krow++){
1334273d9f13SBarry Smith           atmp = PetscAbsScalar(*aa); aa++;
1335273d9f13SBarry Smith           row = brow + krow;    /* row index */
1336273d9f13SBarry Smith           /* printf("val[%d,%d]: %g\n",row,bcol+kcol,atmp); */
1337273d9f13SBarry Smith           if (PetscAbsScalar(x[row]) < atmp) x[row] = atmp;
1338273d9f13SBarry Smith         }
1339273d9f13SBarry Smith       }
1340273d9f13SBarry Smith       aj++;
1341273d9f13SBarry Smith     }
1342273d9f13SBarry Smith   }
1343273d9f13SBarry Smith   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1344273d9f13SBarry Smith   PetscFunctionReturn(0);
1345273d9f13SBarry Smith }
1346273d9f13SBarry Smith 
1347273d9f13SBarry Smith #undef __FUNC__
1348b0a32e0cSBarry Smith #define __FUNC__ "MatSetUpPreallocation_SeqBAIJ"
1349273d9f13SBarry Smith int MatSetUpPreallocation_SeqBAIJ(Mat A)
1350273d9f13SBarry Smith {
1351273d9f13SBarry Smith   int        ierr;
1352273d9f13SBarry Smith 
1353273d9f13SBarry Smith   PetscFunctionBegin;
1354273d9f13SBarry Smith   ierr =  MatSeqBAIJSetPreallocation(A,1,PETSC_DEFAULT,0);CHKERRQ(ierr);
1355273d9f13SBarry Smith   PetscFunctionReturn(0);
1356273d9f13SBarry Smith }
1357273d9f13SBarry Smith 
1358*f2a5309cSSatish Balay #undef __FUNC__
1359*f2a5309cSSatish Balay #define __FUNC__ "MatGetArray_SeqBAIJ"
1360*f2a5309cSSatish Balay int MatGetArray_SeqBAIJ(Mat A,Scalar **array)
1361*f2a5309cSSatish Balay {
1362*f2a5309cSSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data;
1363*f2a5309cSSatish Balay   PetscFunctionBegin;
1364*f2a5309cSSatish Balay   *array = a->a;
1365*f2a5309cSSatish Balay   PetscFunctionReturn(0);
1366*f2a5309cSSatish Balay }
1367*f2a5309cSSatish Balay 
1368*f2a5309cSSatish Balay #undef __FUNC__
1369*f2a5309cSSatish Balay #define __FUNC__ "MatRestoreArray_SeqBAIJ"
1370*f2a5309cSSatish Balay int MatRestoreArray_SeqBAIJ(Mat A,Scalar **array)
1371*f2a5309cSSatish Balay {
1372*f2a5309cSSatish Balay   PetscFunctionBegin;
1373*f2a5309cSSatish Balay   PetscFunctionReturn(0);
1374*f2a5309cSSatish Balay }
1375*f2a5309cSSatish Balay 
13762593348eSBarry Smith /* -------------------------------------------------------------------*/
1377cc2dc46cSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqBAIJ,
1378cc2dc46cSBarry Smith        MatGetRow_SeqBAIJ,
1379cc2dc46cSBarry Smith        MatRestoreRow_SeqBAIJ,
1380cc2dc46cSBarry Smith        MatMult_SeqBAIJ_N,
1381cc2dc46cSBarry Smith        MatMultAdd_SeqBAIJ_N,
13827c922b88SBarry Smith        MatMultTranspose_SeqBAIJ,
13837c922b88SBarry Smith        MatMultTransposeAdd_SeqBAIJ,
1384cc2dc46cSBarry Smith        MatSolve_SeqBAIJ_N,
1385cc2dc46cSBarry Smith        0,
1386cc2dc46cSBarry Smith        0,
1387cc2dc46cSBarry Smith        0,
1388cc2dc46cSBarry Smith        MatLUFactor_SeqBAIJ,
1389cc2dc46cSBarry Smith        0,
1390b6490206SBarry Smith        0,
1391f2501298SSatish Balay        MatTranspose_SeqBAIJ,
1392cc2dc46cSBarry Smith        MatGetInfo_SeqBAIJ,
1393cc2dc46cSBarry Smith        MatEqual_SeqBAIJ,
1394cc2dc46cSBarry Smith        MatGetDiagonal_SeqBAIJ,
1395cc2dc46cSBarry Smith        MatDiagonalScale_SeqBAIJ,
1396cc2dc46cSBarry Smith        MatNorm_SeqBAIJ,
1397b6490206SBarry Smith        0,
1398cc2dc46cSBarry Smith        MatAssemblyEnd_SeqBAIJ,
1399cc2dc46cSBarry Smith        0,
1400cc2dc46cSBarry Smith        MatSetOption_SeqBAIJ,
1401cc2dc46cSBarry Smith        MatZeroEntries_SeqBAIJ,
1402cc2dc46cSBarry Smith        MatZeroRows_SeqBAIJ,
1403cc2dc46cSBarry Smith        MatLUFactorSymbolic_SeqBAIJ,
1404cc2dc46cSBarry Smith        MatLUFactorNumeric_SeqBAIJ_N,
1405cc2dc46cSBarry Smith        0,
1406cc2dc46cSBarry Smith        0,
1407273d9f13SBarry Smith        MatSetUpPreallocation_SeqBAIJ,
1408273d9f13SBarry Smith        0,
1409cc2dc46cSBarry Smith        MatGetOwnershipRange_SeqBAIJ,
1410cc2dc46cSBarry Smith        MatILUFactorSymbolic_SeqBAIJ,
1411cc2dc46cSBarry Smith        0,
1412*f2a5309cSSatish Balay        MatGetArray_SeqBAIJ,
1413*f2a5309cSSatish Balay        MatRestoreArray_SeqBAIJ,
14142e8a6d31SBarry Smith        MatDuplicate_SeqBAIJ,
1415cc2dc46cSBarry Smith        0,
1416cc2dc46cSBarry Smith        0,
1417cc2dc46cSBarry Smith        MatILUFactor_SeqBAIJ,
1418cc2dc46cSBarry Smith        0,
1419cc2dc46cSBarry Smith        0,
1420cc2dc46cSBarry Smith        MatGetSubMatrices_SeqBAIJ,
1421cc2dc46cSBarry Smith        MatIncreaseOverlap_SeqBAIJ,
1422cc2dc46cSBarry Smith        MatGetValues_SeqBAIJ,
1423cc2dc46cSBarry Smith        0,
1424cc2dc46cSBarry Smith        MatPrintHelp_SeqBAIJ,
1425cc2dc46cSBarry Smith        MatScale_SeqBAIJ,
1426cc2dc46cSBarry Smith        0,
1427cc2dc46cSBarry Smith        0,
1428cc2dc46cSBarry Smith        0,
1429cc2dc46cSBarry Smith        MatGetBlockSize_SeqBAIJ,
14303b2fbd54SBarry Smith        MatGetRowIJ_SeqBAIJ,
143192c4ed94SBarry Smith        MatRestoreRowIJ_SeqBAIJ,
1432cc2dc46cSBarry Smith        0,
1433cc2dc46cSBarry Smith        0,
1434cc2dc46cSBarry Smith        0,
1435cc2dc46cSBarry Smith        0,
1436cc2dc46cSBarry Smith        0,
1437cc2dc46cSBarry Smith        0,
1438d3825aa8SBarry Smith        MatSetValuesBlocked_SeqBAIJ,
1439cc2dc46cSBarry Smith        MatGetSubMatrix_SeqBAIJ,
1440b9b97703SBarry Smith        MatDestroy_SeqBAIJ,
1441b9b97703SBarry Smith        MatView_SeqBAIJ,
1442273d9f13SBarry Smith        MatGetMaps_Petsc,
1443273d9f13SBarry Smith        0,
1444273d9f13SBarry Smith        0,
1445273d9f13SBarry Smith        0,
1446273d9f13SBarry Smith        0,
1447273d9f13SBarry Smith        0,
1448273d9f13SBarry Smith        0,
1449273d9f13SBarry Smith        MatGetRowMax_SeqBAIJ,
1450273d9f13SBarry Smith        MatConvert_Basic};
14512593348eSBarry Smith 
14523e90b805SBarry Smith EXTERN_C_BEGIN
14533e90b805SBarry Smith #undef __FUNC__
1454b0a32e0cSBarry Smith #define __FUNC__ "MatStoreValues_SeqBAIJ"
14553e90b805SBarry Smith int MatStoreValues_SeqBAIJ(Mat mat)
14563e90b805SBarry Smith {
14573e90b805SBarry Smith   Mat_SeqBAIJ *aij = (Mat_SeqBAIJ *)mat->data;
1458273d9f13SBarry Smith   int         nz = aij->i[mat->m]*aij->bs*aij->bs2;
1459d132466eSBarry Smith   int         ierr;
14603e90b805SBarry Smith 
14613e90b805SBarry Smith   PetscFunctionBegin;
14623e90b805SBarry Smith   if (aij->nonew != 1) {
146329bbc08cSBarry Smith     SETERRQ(1,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first");
14643e90b805SBarry Smith   }
14653e90b805SBarry Smith 
14663e90b805SBarry Smith   /* allocate space for values if not already there */
14673e90b805SBarry Smith   if (!aij->saved_values) {
1468*f2a5309cSSatish Balay     ierr = PetscMalloc((nz+1)*sizeof(Scalar),&aij->saved_values);CHKERRQ(ierr);
14693e90b805SBarry Smith   }
14703e90b805SBarry Smith 
14713e90b805SBarry Smith   /* copy values over */
1472d132466eSBarry Smith   ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(Scalar));CHKERRQ(ierr);
14733e90b805SBarry Smith   PetscFunctionReturn(0);
14743e90b805SBarry Smith }
14753e90b805SBarry Smith EXTERN_C_END
14763e90b805SBarry Smith 
14773e90b805SBarry Smith EXTERN_C_BEGIN
14783e90b805SBarry Smith #undef __FUNC__
1479b0a32e0cSBarry Smith #define __FUNC__ "MatRetrieveValues_SeqBAIJ"
148032e87ba3SBarry Smith int MatRetrieveValues_SeqBAIJ(Mat mat)
14813e90b805SBarry Smith {
14823e90b805SBarry Smith   Mat_SeqBAIJ *aij = (Mat_SeqBAIJ *)mat->data;
1483273d9f13SBarry Smith   int         nz = aij->i[mat->m]*aij->bs*aij->bs2,ierr;
14843e90b805SBarry Smith 
14853e90b805SBarry Smith   PetscFunctionBegin;
14863e90b805SBarry Smith   if (aij->nonew != 1) {
148729bbc08cSBarry Smith     SETERRQ(1,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first");
14883e90b805SBarry Smith   }
14893e90b805SBarry Smith   if (!aij->saved_values) {
149029bbc08cSBarry Smith     SETERRQ(1,"Must call MatStoreValues(A);first");
14913e90b805SBarry Smith   }
14923e90b805SBarry Smith 
14933e90b805SBarry Smith   /* copy values over */
1494549d3d68SSatish Balay   ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(Scalar));CHKERRQ(ierr);
14953e90b805SBarry Smith   PetscFunctionReturn(0);
14963e90b805SBarry Smith }
14973e90b805SBarry Smith EXTERN_C_END
14983e90b805SBarry Smith 
1499273d9f13SBarry Smith EXTERN_C_BEGIN
1500273d9f13SBarry Smith extern int MatConvert_SeqBAIJ_SeqAIJ(Mat,MatType,Mat*);
1501273d9f13SBarry Smith EXTERN_C_END
1502273d9f13SBarry Smith 
1503273d9f13SBarry Smith EXTERN_C_BEGIN
15045615d1e5SSatish Balay #undef __FUNC__
1505b0a32e0cSBarry Smith #define __FUNC__ "MatCreate_SeqBAIJ"
1506273d9f13SBarry Smith int MatCreate_SeqBAIJ(Mat B)
15072593348eSBarry Smith {
1508273d9f13SBarry Smith   int         ierr,size;
1509b6490206SBarry Smith   Mat_SeqBAIJ *b;
15103b2fbd54SBarry Smith 
15113a40ed3dSBarry Smith   PetscFunctionBegin;
1512273d9f13SBarry Smith   ierr = MPI_Comm_size(B->comm,&size);CHKERRQ(ierr);
151329bbc08cSBarry Smith   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"Comm must be of size 1");
1514b6490206SBarry Smith 
1515273d9f13SBarry Smith   B->m = B->M = PetscMax(B->m,B->M);
1516273d9f13SBarry Smith   B->n = B->N = PetscMax(B->n,B->N);
1517b0a32e0cSBarry Smith   ierr    = PetscNew(Mat_SeqBAIJ,&b);CHKERRQ(ierr);
1518b0a32e0cSBarry Smith   B->data = (void*)b;
1519549d3d68SSatish Balay   ierr    = PetscMemzero(b,sizeof(Mat_SeqBAIJ));CHKERRQ(ierr);
1520549d3d68SSatish Balay   ierr    = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
15212593348eSBarry Smith   B->factor           = 0;
15222593348eSBarry Smith   B->lupivotthreshold = 1.0;
152390f02eecSBarry Smith   B->mapping          = 0;
15242593348eSBarry Smith   b->row              = 0;
15252593348eSBarry Smith   b->col              = 0;
1526e51c0b9cSSatish Balay   b->icol             = 0;
15272593348eSBarry Smith   b->reallocs         = 0;
15283e90b805SBarry Smith   b->saved_values     = 0;
1529563b5814SBarry Smith #if defined(PEYSC_USE_MAT_SINGLE)
1530563b5814SBarry Smith   b->setvalueslen     = 0;
1531563b5814SBarry Smith   b->setvaluescopy    = PETSC_NULL;
1532563b5814SBarry Smith #endif
15332593348eSBarry Smith 
1534273d9f13SBarry Smith   ierr = MapCreateMPI(B->comm,B->m,B->m,&B->rmap);CHKERRQ(ierr);
1535273d9f13SBarry Smith   ierr = MapCreateMPI(B->comm,B->n,B->n,&B->cmap);CHKERRQ(ierr);
1536a5ae1ecdSBarry Smith 
1537c4992f7dSBarry Smith   b->sorted           = PETSC_FALSE;
1538c4992f7dSBarry Smith   b->roworiented      = PETSC_TRUE;
15392593348eSBarry Smith   b->nonew            = 0;
15402593348eSBarry Smith   b->diag             = 0;
15412593348eSBarry Smith   b->solve_work       = 0;
1542de6a44a3SBarry Smith   b->mult_work        = 0;
15432593348eSBarry Smith   b->spptr            = 0;
15440e6d2581SBarry Smith   B->info.nz_unneeded = (PetscReal)b->maxnz;
1545883fce79SBarry Smith   b->keepzeroedrows   = PETSC_FALSE;
15464e220ebcSLois Curfman McInnes 
1547f1af5d2fSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
15483e90b805SBarry Smith                                      "MatStoreValues_SeqBAIJ",
1549bc4b532fSSatish Balay                                       MatStoreValues_SeqBAIJ);CHKERRQ(ierr);
1550f1af5d2fSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
15513e90b805SBarry Smith                                      "MatRetrieveValues_SeqBAIJ",
1552bc4b532fSSatish Balay                                       MatRetrieveValues_SeqBAIJ);CHKERRQ(ierr);
1553f1af5d2fSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqBAIJSetColumnIndices_C",
155427a8da17SBarry Smith                                      "MatSeqBAIJSetColumnIndices_SeqBAIJ",
1555bc4b532fSSatish Balay                                       MatSeqBAIJSetColumnIndices_SeqBAIJ);CHKERRQ(ierr);
1556273d9f13SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_SeqBAIJ_SeqAIJ_C",
1557273d9f13SBarry Smith                                      "MatConvert_SeqBAIJ_SeqAIJ",
1558273d9f13SBarry Smith                                       MatConvert_SeqBAIJ_SeqAIJ);CHKERRQ(ierr);
15593a40ed3dSBarry Smith   PetscFunctionReturn(0);
15602593348eSBarry Smith }
1561273d9f13SBarry Smith EXTERN_C_END
15622593348eSBarry Smith 
15635615d1e5SSatish Balay #undef __FUNC__
1564b0a32e0cSBarry Smith #define __FUNC__ "MatDuplicate_SeqBAIJ"
15652e8a6d31SBarry Smith int MatDuplicate_SeqBAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
15662593348eSBarry Smith {
15672593348eSBarry Smith   Mat         C;
1568b6490206SBarry Smith   Mat_SeqBAIJ *c,*a = (Mat_SeqBAIJ*)A->data;
156927a8da17SBarry Smith   int         i,len,mbs = a->mbs,nz = a->nz,bs2 =a->bs2,ierr;
1570de6a44a3SBarry Smith 
15713a40ed3dSBarry Smith   PetscFunctionBegin;
157229bbc08cSBarry Smith   if (a->i[mbs] != nz) SETERRQ(PETSC_ERR_PLIB,"Corrupt matrix");
15732593348eSBarry Smith 
15742593348eSBarry Smith   *B = 0;
1575273d9f13SBarry Smith   ierr = MatCreate(A->comm,A->m,A->n,A->m,A->n,&C);CHKERRQ(ierr);
1576273d9f13SBarry Smith   ierr = MatSetType(C,MATSEQBAIJ);CHKERRQ(ierr);
1577273d9f13SBarry Smith   c    = (Mat_SeqBAIJ*)C->data;
157844cd7ae7SLois Curfman McInnes 
1579b6490206SBarry Smith   c->bs         = a->bs;
15809df24120SSatish Balay   c->bs2        = a->bs2;
1581b6490206SBarry Smith   c->mbs        = a->mbs;
1582b6490206SBarry Smith   c->nbs        = a->nbs;
158335d8aa7fSBarry Smith   ierr = PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
15842593348eSBarry Smith 
1585b0a32e0cSBarry Smith   ierr = PetscMalloc((mbs+1)*sizeof(int),&c->imax);CHKERRQ(ierr);
1586b0a32e0cSBarry Smith   ierr = PetscMalloc((mbs+1)*sizeof(int),&c->ilen);CHKERRQ(ierr);
1587b6490206SBarry Smith   for (i=0; i<mbs; i++) {
15882593348eSBarry Smith     c->imax[i] = a->imax[i];
15892593348eSBarry Smith     c->ilen[i] = a->ilen[i];
15902593348eSBarry Smith   }
15912593348eSBarry Smith 
15922593348eSBarry Smith   /* allocate the matrix space */
1593c4992f7dSBarry Smith   c->singlemalloc = PETSC_TRUE;
15943f1db9ecSBarry Smith   len  = (mbs+1)*sizeof(int) + nz*(bs2*sizeof(MatScalar) + sizeof(int));
1595b0a32e0cSBarry Smith   ierr = PetscMalloc(len,&c->a);CHKERRQ(ierr);
15967e67e3f9SSatish Balay   c->j = (int*)(c->a + nz*bs2);
1597de6a44a3SBarry Smith   c->i = c->j + nz;
1598549d3d68SSatish Balay   ierr = PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(int));CHKERRQ(ierr);
1599b6490206SBarry Smith   if (mbs > 0) {
1600549d3d68SSatish Balay     ierr = PetscMemcpy(c->j,a->j,nz*sizeof(int));CHKERRQ(ierr);
16012e8a6d31SBarry Smith     if (cpvalues == MAT_COPY_VALUES) {
1602549d3d68SSatish Balay       ierr = PetscMemcpy(c->a,a->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr);
16032e8a6d31SBarry Smith     } else {
1604549d3d68SSatish Balay       ierr = PetscMemzero(c->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr);
16052593348eSBarry Smith     }
16062593348eSBarry Smith   }
16072593348eSBarry Smith 
1608b0a32e0cSBarry Smith   PetscLogObjectMemory(C,len+2*(mbs+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqBAIJ));
16092593348eSBarry Smith   c->sorted      = a->sorted;
16102593348eSBarry Smith   c->roworiented = a->roworiented;
16112593348eSBarry Smith   c->nonew       = a->nonew;
16122593348eSBarry Smith 
16132593348eSBarry Smith   if (a->diag) {
1614b0a32e0cSBarry Smith     ierr = PetscMalloc((mbs+1)*sizeof(int),&c->diag);CHKERRQ(ierr);
1615b0a32e0cSBarry Smith     PetscLogObjectMemory(C,(mbs+1)*sizeof(int));
1616b6490206SBarry Smith     for (i=0; i<mbs; i++) {
16172593348eSBarry Smith       c->diag[i] = a->diag[i];
16182593348eSBarry Smith     }
161998305bb5SBarry Smith   } else c->diag        = 0;
16202593348eSBarry Smith   c->nz                 = a->nz;
16212593348eSBarry Smith   c->maxnz              = a->maxnz;
16222593348eSBarry Smith   c->solve_work         = 0;
16232593348eSBarry Smith   c->spptr              = 0;      /* Dangerous -I'm throwing away a->spptr */
16247fc0212eSBarry Smith   c->mult_work          = 0;
1625273d9f13SBarry Smith   C->preallocated       = PETSC_TRUE;
1626273d9f13SBarry Smith   C->assembled          = PETSC_TRUE;
16272593348eSBarry Smith   *B = C;
1628b0a32e0cSBarry Smith   ierr = PetscFListDuplicate(A->qlist,&C->qlist);CHKERRQ(ierr);
16293a40ed3dSBarry Smith   PetscFunctionReturn(0);
16302593348eSBarry Smith }
16312593348eSBarry Smith 
1632273d9f13SBarry Smith EXTERN_C_BEGIN
16335615d1e5SSatish Balay #undef __FUNC__
1634b0a32e0cSBarry Smith #define __FUNC__ "MatLoad_SeqBAIJ"
1635b0a32e0cSBarry Smith int MatLoad_SeqBAIJ(PetscViewer viewer,MatType type,Mat *A)
16362593348eSBarry Smith {
1637b6490206SBarry Smith   Mat_SeqBAIJ  *a;
16382593348eSBarry Smith   Mat          B;
1639f1af5d2fSBarry Smith   int          i,nz,ierr,fd,header[4],size,*rowlengths=0,M,N,bs=1;
1640b6490206SBarry Smith   int          *mask,mbs,*jj,j,rowcount,nzcount,k,*browlengths,maskcount;
164135aab85fSBarry Smith   int          kmax,jcount,block,idx,point,nzcountb,extra_rows;
1642a7c10996SSatish Balay   int          *masked,nmask,tmp,bs2,ishift;
1643b6490206SBarry Smith   Scalar       *aa;
164419bcc07fSBarry Smith   MPI_Comm     comm = ((PetscObject)viewer)->comm;
16452593348eSBarry Smith 
16463a40ed3dSBarry Smith   PetscFunctionBegin;
1647b0a32e0cSBarry Smith   ierr = PetscOptionsGetInt(PETSC_NULL,"-matload_block_size",&bs,PETSC_NULL);CHKERRQ(ierr);
1648de6a44a3SBarry Smith   bs2  = bs*bs;
1649b6490206SBarry Smith 
1650d132466eSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
165129bbc08cSBarry Smith   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"view must have one processor");
1652b0a32e0cSBarry Smith   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
16530752156aSBarry Smith   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
165429bbc08cSBarry Smith   if (header[0] != MAT_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not Mat object");
16552593348eSBarry Smith   M = header[1]; N = header[2]; nz = header[3];
16562593348eSBarry Smith 
1657d64ed03dSBarry Smith   if (header[3] < 0) {
165829bbc08cSBarry Smith     SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format, cannot load as SeqBAIJ");
1659d64ed03dSBarry Smith   }
1660d64ed03dSBarry Smith 
166129bbc08cSBarry Smith   if (M != N) SETERRQ(PETSC_ERR_SUP,"Can only do square matrices");
166235aab85fSBarry Smith 
166335aab85fSBarry Smith   /*
166435aab85fSBarry Smith      This code adds extra rows to make sure the number of rows is
166535aab85fSBarry Smith     divisible by the blocksize
166635aab85fSBarry Smith   */
1667b6490206SBarry Smith   mbs        = M/bs;
166835aab85fSBarry Smith   extra_rows = bs - M + bs*(mbs);
166935aab85fSBarry Smith   if (extra_rows == bs) extra_rows = 0;
167035aab85fSBarry Smith   else                  mbs++;
167135aab85fSBarry Smith   if (extra_rows) {
1672b0a32e0cSBarry Smith     PetscLogInfo(0,"MatLoad_SeqBAIJ:Padding loaded matrix to match blocksize\n");
167335aab85fSBarry Smith   }
1674b6490206SBarry Smith 
16752593348eSBarry Smith   /* read in row lengths */
1676b0a32e0cSBarry Smith   ierr = PetscMalloc((M+extra_rows)*sizeof(int),&rowlengths);CHKERRQ(ierr);
16770752156aSBarry Smith   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
167835aab85fSBarry Smith   for (i=0; i<extra_rows; i++) rowlengths[M+i] = 1;
16792593348eSBarry Smith 
1680b6490206SBarry Smith   /* read in column indices */
1681b0a32e0cSBarry Smith   ierr = PetscMalloc((nz+extra_rows)*sizeof(int),&jj);CHKERRQ(ierr);
16820752156aSBarry Smith   ierr = PetscBinaryRead(fd,jj,nz,PETSC_INT);CHKERRQ(ierr);
168335aab85fSBarry Smith   for (i=0; i<extra_rows; i++) jj[nz+i] = M+i;
1684b6490206SBarry Smith 
1685b6490206SBarry Smith   /* loop over row lengths determining block row lengths */
1686b0a32e0cSBarry Smith   ierr     = PetscMalloc(mbs*sizeof(int),&browlengths);CHKERRQ(ierr);
1687549d3d68SSatish Balay   ierr     = PetscMemzero(browlengths,mbs*sizeof(int));CHKERRQ(ierr);
1688b0a32e0cSBarry Smith   ierr     = PetscMalloc(2*mbs*sizeof(int),&mask);CHKERRQ(ierr);
1689549d3d68SSatish Balay   ierr     = PetscMemzero(mask,mbs*sizeof(int));CHKERRQ(ierr);
169035aab85fSBarry Smith   masked   = mask + mbs;
1691b6490206SBarry Smith   rowcount = 0; nzcount = 0;
1692b6490206SBarry Smith   for (i=0; i<mbs; i++) {
169335aab85fSBarry Smith     nmask = 0;
1694b6490206SBarry Smith     for (j=0; j<bs; j++) {
1695b6490206SBarry Smith       kmax = rowlengths[rowcount];
1696b6490206SBarry Smith       for (k=0; k<kmax; k++) {
169735aab85fSBarry Smith         tmp = jj[nzcount++]/bs;
169835aab85fSBarry Smith         if (!mask[tmp]) {masked[nmask++] = tmp; mask[tmp] = 1;}
1699b6490206SBarry Smith       }
1700b6490206SBarry Smith       rowcount++;
1701b6490206SBarry Smith     }
170235aab85fSBarry Smith     browlengths[i] += nmask;
170335aab85fSBarry Smith     /* zero out the mask elements we set */
170435aab85fSBarry Smith     for (j=0; j<nmask; j++) mask[masked[j]] = 0;
1705b6490206SBarry Smith   }
1706b6490206SBarry Smith 
17072593348eSBarry Smith   /* create our matrix */
17083eee16b0SBarry Smith   ierr = MatCreateSeqBAIJ(comm,bs,M+extra_rows,N+extra_rows,0,browlengths,A);CHKERRQ(ierr);
17092593348eSBarry Smith   B = *A;
1710b6490206SBarry Smith   a = (Mat_SeqBAIJ*)B->data;
17112593348eSBarry Smith 
17122593348eSBarry Smith   /* set matrix "i" values */
1713de6a44a3SBarry Smith   a->i[0] = 0;
1714b6490206SBarry Smith   for (i=1; i<= mbs; i++) {
1715b6490206SBarry Smith     a->i[i]      = a->i[i-1] + browlengths[i-1];
1716b6490206SBarry Smith     a->ilen[i-1] = browlengths[i-1];
17172593348eSBarry Smith   }
1718b6490206SBarry Smith   a->nz         = 0;
1719b6490206SBarry Smith   for (i=0; i<mbs; i++) a->nz += browlengths[i];
17202593348eSBarry Smith 
1721b6490206SBarry Smith   /* read in nonzero values */
1722b0a32e0cSBarry Smith   ierr = PetscMalloc((nz+extra_rows)*sizeof(Scalar),&aa);CHKERRQ(ierr);
17230752156aSBarry Smith   ierr = PetscBinaryRead(fd,aa,nz,PETSC_SCALAR);CHKERRQ(ierr);
172435aab85fSBarry Smith   for (i=0; i<extra_rows; i++) aa[nz+i] = 1.0;
1725b6490206SBarry Smith 
1726b6490206SBarry Smith   /* set "a" and "j" values into matrix */
1727b6490206SBarry Smith   nzcount = 0; jcount = 0;
1728b6490206SBarry Smith   for (i=0; i<mbs; i++) {
1729b6490206SBarry Smith     nzcountb = nzcount;
173035aab85fSBarry Smith     nmask    = 0;
1731b6490206SBarry Smith     for (j=0; j<bs; j++) {
1732b6490206SBarry Smith       kmax = rowlengths[i*bs+j];
1733b6490206SBarry Smith       for (k=0; k<kmax; k++) {
173435aab85fSBarry Smith         tmp = jj[nzcount++]/bs;
173535aab85fSBarry Smith 	if (!mask[tmp]) { masked[nmask++] = tmp; mask[tmp] = 1;}
1736b6490206SBarry Smith       }
1737b6490206SBarry Smith       rowcount++;
1738b6490206SBarry Smith     }
1739de6a44a3SBarry Smith     /* sort the masked values */
1740433994e6SBarry Smith     ierr = PetscSortInt(nmask,masked);CHKERRQ(ierr);
1741de6a44a3SBarry Smith 
1742b6490206SBarry Smith     /* set "j" values into matrix */
1743b6490206SBarry Smith     maskcount = 1;
174435aab85fSBarry Smith     for (j=0; j<nmask; j++) {
174535aab85fSBarry Smith       a->j[jcount++]  = masked[j];
1746de6a44a3SBarry Smith       mask[masked[j]] = maskcount++;
1747b6490206SBarry Smith     }
1748b6490206SBarry Smith     /* set "a" values into matrix */
1749de6a44a3SBarry Smith     ishift = bs2*a->i[i];
1750b6490206SBarry Smith     for (j=0; j<bs; j++) {
1751b6490206SBarry Smith       kmax = rowlengths[i*bs+j];
1752b6490206SBarry Smith       for (k=0; k<kmax; k++) {
1753de6a44a3SBarry Smith         tmp       = jj[nzcountb]/bs ;
1754de6a44a3SBarry Smith         block     = mask[tmp] - 1;
1755de6a44a3SBarry Smith         point     = jj[nzcountb] - bs*tmp;
1756de6a44a3SBarry Smith         idx       = ishift + bs2*block + j + bs*point;
1757375fe846SBarry Smith         a->a[idx] = (MatScalar)aa[nzcountb++];
1758b6490206SBarry Smith       }
1759b6490206SBarry Smith     }
176035aab85fSBarry Smith     /* zero out the mask elements we set */
176135aab85fSBarry Smith     for (j=0; j<nmask; j++) mask[masked[j]] = 0;
1762b6490206SBarry Smith   }
176329bbc08cSBarry Smith   if (jcount != a->nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Bad binary matrix");
1764b6490206SBarry Smith 
1765606d414cSSatish Balay   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
1766606d414cSSatish Balay   ierr = PetscFree(browlengths);CHKERRQ(ierr);
1767606d414cSSatish Balay   ierr = PetscFree(aa);CHKERRQ(ierr);
1768606d414cSSatish Balay   ierr = PetscFree(jj);CHKERRQ(ierr);
1769606d414cSSatish Balay   ierr = PetscFree(mask);CHKERRQ(ierr);
1770b6490206SBarry Smith 
1771b6490206SBarry Smith   B->assembled = PETSC_TRUE;
1772de6a44a3SBarry Smith 
17739c01be13SBarry Smith   ierr = MatView_Private(B);CHKERRQ(ierr);
17743a40ed3dSBarry Smith   PetscFunctionReturn(0);
17752593348eSBarry Smith }
1776273d9f13SBarry Smith EXTERN_C_END
17772593348eSBarry Smith 
1778273d9f13SBarry Smith #undef __FUNC__
1779b0a32e0cSBarry Smith #define __FUNC__ "MatCreateSeqBAIJ"
1780273d9f13SBarry Smith /*@C
1781273d9f13SBarry Smith    MatCreateSeqBAIJ - Creates a sparse matrix in block AIJ (block
1782273d9f13SBarry Smith    compressed row) format.  For good matrix assembly performance the
1783273d9f13SBarry Smith    user should preallocate the matrix storage by setting the parameter nz
1784273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
1785273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
17862593348eSBarry Smith 
1787273d9f13SBarry Smith    Collective on MPI_Comm
1788273d9f13SBarry Smith 
1789273d9f13SBarry Smith    Input Parameters:
1790273d9f13SBarry Smith +  comm - MPI communicator, set to PETSC_COMM_SELF
1791273d9f13SBarry Smith .  bs - size of block
1792273d9f13SBarry Smith .  m - number of rows
1793273d9f13SBarry Smith .  n - number of columns
179435d8aa7fSBarry Smith .  nz - number of nonzero blocks  per block row (same for all rows)
179535d8aa7fSBarry Smith -  nnz - array containing the number of nonzero blocks in the various block rows
1796273d9f13SBarry Smith          (possibly different for each block row) or PETSC_NULL
1797273d9f13SBarry Smith 
1798273d9f13SBarry Smith    Output Parameter:
1799273d9f13SBarry Smith .  A - the matrix
1800273d9f13SBarry Smith 
1801273d9f13SBarry Smith    Options Database Keys:
1802273d9f13SBarry Smith .   -mat_no_unroll - uses code that does not unroll the loops in the
1803273d9f13SBarry Smith                      block calculations (much slower)
1804273d9f13SBarry Smith .    -mat_block_size - size of the blocks to use
1805273d9f13SBarry Smith 
1806273d9f13SBarry Smith    Level: intermediate
1807273d9f13SBarry Smith 
1808273d9f13SBarry Smith    Notes:
180935d8aa7fSBarry Smith    A nonzero block is any block that as 1 or more nonzeros in it
181035d8aa7fSBarry Smith 
1811273d9f13SBarry Smith    The block AIJ format is fully compatible with standard Fortran 77
1812273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
1813273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
1814273d9f13SBarry Smith 
1815273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
1816273d9f13SBarry Smith    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
1817273d9f13SBarry Smith    allocation.  For additional details, see the users manual chapter on
1818273d9f13SBarry Smith    matrices.
1819273d9f13SBarry Smith 
1820273d9f13SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPIBAIJ()
1821273d9f13SBarry Smith @*/
1822273d9f13SBarry Smith int MatCreateSeqBAIJ(MPI_Comm comm,int bs,int m,int n,int nz,int *nnz,Mat *A)
1823273d9f13SBarry Smith {
1824273d9f13SBarry Smith   int ierr;
1825273d9f13SBarry Smith 
1826273d9f13SBarry Smith   PetscFunctionBegin;
1827273d9f13SBarry Smith   ierr = MatCreate(comm,m,n,m,n,A);CHKERRQ(ierr);
1828273d9f13SBarry Smith   ierr = MatSetType(*A,MATSEQBAIJ);CHKERRQ(ierr);
1829273d9f13SBarry Smith   ierr = MatSeqBAIJSetPreallocation(*A,bs,nz,nnz);CHKERRQ(ierr);
1830273d9f13SBarry Smith   PetscFunctionReturn(0);
1831273d9f13SBarry Smith }
1832273d9f13SBarry Smith 
1833273d9f13SBarry Smith #undef __FUNC__
1834b0a32e0cSBarry Smith #define __FUNC__ "MatSeqBAIJSetPreallocation"
1835273d9f13SBarry Smith /*@C
1836273d9f13SBarry Smith    MatSeqBAIJSetPreallocation - Sets the block size and expected nonzeros
1837273d9f13SBarry Smith    per row in the matrix. For good matrix assembly performance the
1838273d9f13SBarry Smith    user should preallocate the matrix storage by setting the parameter nz
1839273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
1840273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
1841273d9f13SBarry Smith 
1842273d9f13SBarry Smith    Collective on MPI_Comm
1843273d9f13SBarry Smith 
1844273d9f13SBarry Smith    Input Parameters:
1845273d9f13SBarry Smith +  A - the matrix
1846273d9f13SBarry Smith .  bs - size of block
1847273d9f13SBarry Smith .  nz - number of block nonzeros per block row (same for all rows)
1848273d9f13SBarry Smith -  nnz - array containing the number of block nonzeros in the various block rows
1849273d9f13SBarry Smith          (possibly different for each block row) or PETSC_NULL
1850273d9f13SBarry Smith 
1851273d9f13SBarry Smith    Options Database Keys:
1852273d9f13SBarry Smith .   -mat_no_unroll - uses code that does not unroll the loops in the
1853273d9f13SBarry Smith                      block calculations (much slower)
1854273d9f13SBarry Smith .    -mat_block_size - size of the blocks to use
1855273d9f13SBarry Smith 
1856273d9f13SBarry Smith    Level: intermediate
1857273d9f13SBarry Smith 
1858273d9f13SBarry Smith    Notes:
1859273d9f13SBarry Smith    The block AIJ format is fully compatible with standard Fortran 77
1860273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
1861273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
1862273d9f13SBarry Smith 
1863273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
1864273d9f13SBarry Smith    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
1865273d9f13SBarry Smith    allocation.  For additional details, see the users manual chapter on
1866273d9f13SBarry Smith    matrices.
1867273d9f13SBarry Smith 
1868273d9f13SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPIBAIJ()
1869273d9f13SBarry Smith @*/
1870273d9f13SBarry Smith int MatSeqBAIJSetPreallocation(Mat B,int bs,int nz,int *nnz)
1871273d9f13SBarry Smith {
1872273d9f13SBarry Smith   Mat_SeqBAIJ *b;
1873273d9f13SBarry Smith   int         i,len,ierr,mbs,nbs,bs2,newbs = bs;
1874273d9f13SBarry Smith   PetscTruth  flg;
1875273d9f13SBarry Smith 
1876273d9f13SBarry Smith   PetscFunctionBegin;
1877273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)B,MATSEQBAIJ,&flg);CHKERRQ(ierr);
1878273d9f13SBarry Smith   if (!flg) PetscFunctionReturn(0);
1879273d9f13SBarry Smith 
1880273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
1881b0a32e0cSBarry Smith   ierr = PetscOptionsGetInt(B->prefix,"-mat_block_size",&newbs,PETSC_NULL);CHKERRQ(ierr);
1882273d9f13SBarry Smith   if (nnz && newbs != bs) {
1883273d9f13SBarry Smith     SETERRQ(1,"Cannot change blocksize from command line if setting nnz");
1884273d9f13SBarry Smith   }
1885273d9f13SBarry Smith   bs   = newbs;
1886273d9f13SBarry Smith 
1887273d9f13SBarry Smith   mbs  = B->m/bs;
1888273d9f13SBarry Smith   nbs  = B->n/bs;
1889273d9f13SBarry Smith   bs2  = bs*bs;
1890273d9f13SBarry Smith 
1891273d9f13SBarry Smith   if (mbs*bs!=B->m || nbs*bs!=B->n) {
189235d8aa7fSBarry Smith     SETERRQ3(PETSC_ERR_ARG_SIZ,"Number rows %d, cols %d must be divisible by blocksize %d",B->m,B->n,bs);
1893273d9f13SBarry Smith   }
1894273d9f13SBarry Smith 
1895273d9f13SBarry Smith   if (nz < -2) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than -2: value %d",nz);
1896273d9f13SBarry Smith   if (nnz) {
1897273d9f13SBarry Smith     for (i=0; i<mbs; i++) {
1898273d9f13SBarry Smith       if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]);
1899273d9f13SBarry Smith     }
1900273d9f13SBarry Smith   }
1901273d9f13SBarry Smith 
1902273d9f13SBarry Smith   b       = (Mat_SeqBAIJ*)B->data;
1903b0a32e0cSBarry Smith   ierr    = PetscOptionsHasName(PETSC_NULL,"-mat_no_unroll",&flg);CHKERRQ(ierr);
1904273d9f13SBarry Smith   if (!flg) {
1905273d9f13SBarry Smith     switch (bs) {
1906273d9f13SBarry Smith     case 1:
1907273d9f13SBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_1;
1908273d9f13SBarry Smith       B->ops->solve           = MatSolve_SeqBAIJ_1;
1909273d9f13SBarry Smith       B->ops->solvetranspose  = MatSolveTranspose_SeqBAIJ_1;
1910273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_1;
1911273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_1;
1912273d9f13SBarry Smith       break;
1913273d9f13SBarry Smith     case 2:
1914273d9f13SBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_2;
1915273d9f13SBarry Smith       B->ops->solve           = MatSolve_SeqBAIJ_2;
1916273d9f13SBarry Smith       B->ops->solvetranspose  = MatSolveTranspose_SeqBAIJ_2;
1917273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_2;
1918273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_2;
1919273d9f13SBarry Smith       break;
1920273d9f13SBarry Smith     case 3:
1921273d9f13SBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_3;
1922273d9f13SBarry Smith       B->ops->solve           = MatSolve_SeqBAIJ_3;
1923273d9f13SBarry Smith       B->ops->solvetranspose  = MatSolveTranspose_SeqBAIJ_3;
1924273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_3;
1925273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_3;
1926273d9f13SBarry Smith       break;
1927273d9f13SBarry Smith     case 4:
1928273d9f13SBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_4;
1929273d9f13SBarry Smith       B->ops->solve           = MatSolve_SeqBAIJ_4;
1930273d9f13SBarry Smith       B->ops->solvetranspose  = MatSolveTranspose_SeqBAIJ_4;
1931273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_4;
1932273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_4;
1933273d9f13SBarry Smith       break;
1934273d9f13SBarry Smith     case 5:
1935273d9f13SBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_5;
1936273d9f13SBarry Smith       B->ops->solve           = MatSolve_SeqBAIJ_5;
1937273d9f13SBarry Smith       B->ops->solvetranspose  = MatSolveTranspose_SeqBAIJ_5;
1938273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_5;
1939273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_5;
1940273d9f13SBarry Smith       break;
1941273d9f13SBarry Smith     case 6:
1942273d9f13SBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_6;
1943273d9f13SBarry Smith       B->ops->solve           = MatSolve_SeqBAIJ_6;
1944273d9f13SBarry Smith       B->ops->solvetranspose  = MatSolveTranspose_SeqBAIJ_6;
1945273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_6;
1946273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_6;
1947273d9f13SBarry Smith       break;
1948273d9f13SBarry Smith     case 7:
1949273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_7;
1950273d9f13SBarry Smith       B->ops->solve           = MatSolve_SeqBAIJ_7;
1951273d9f13SBarry Smith       B->ops->solvetranspose  = MatSolveTranspose_SeqBAIJ_7;
1952273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_7;
1953273d9f13SBarry Smith       break;
1954273d9f13SBarry Smith     default:
1955273d9f13SBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_N;
1956273d9f13SBarry Smith       B->ops->solve           = MatSolve_SeqBAIJ_N;
1957273d9f13SBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_N;
1958273d9f13SBarry Smith       break;
1959273d9f13SBarry Smith     }
1960273d9f13SBarry Smith   }
1961273d9f13SBarry Smith   b->bs      = bs;
1962273d9f13SBarry Smith   b->mbs     = mbs;
1963273d9f13SBarry Smith   b->nbs     = nbs;
1964b0a32e0cSBarry Smith   ierr = PetscMalloc((mbs+1)*sizeof(int),&b->imax);CHKERRQ(ierr);
1965273d9f13SBarry Smith   if (!nnz) {
1966273d9f13SBarry Smith     if (nz == PETSC_DEFAULT) nz = 5;
1967273d9f13SBarry Smith     else if (nz <= 0)        nz = 1;
1968273d9f13SBarry Smith     for (i=0; i<mbs; i++) b->imax[i] = nz;
1969273d9f13SBarry Smith     nz = nz*mbs;
1970273d9f13SBarry Smith   } else {
1971273d9f13SBarry Smith     nz = 0;
1972273d9f13SBarry Smith     for (i=0; i<mbs; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
1973273d9f13SBarry Smith   }
1974273d9f13SBarry Smith 
1975273d9f13SBarry Smith   /* allocate the matrix space */
1976273d9f13SBarry Smith   len   = nz*sizeof(int) + nz*bs2*sizeof(MatScalar) + (B->m+1)*sizeof(int);
1977b0a32e0cSBarry Smith   ierr  = PetscMalloc(len,&b->a);CHKERRQ(ierr);
1978273d9f13SBarry Smith   ierr  = PetscMemzero(b->a,nz*bs2*sizeof(MatScalar));CHKERRQ(ierr);
1979273d9f13SBarry Smith   b->j  = (int*)(b->a + nz*bs2);
1980273d9f13SBarry Smith   ierr = PetscMemzero(b->j,nz*sizeof(int));CHKERRQ(ierr);
1981273d9f13SBarry Smith   b->i  = b->j + nz;
1982273d9f13SBarry Smith   b->singlemalloc = PETSC_TRUE;
1983273d9f13SBarry Smith 
1984273d9f13SBarry Smith   b->i[0] = 0;
1985273d9f13SBarry Smith   for (i=1; i<mbs+1; i++) {
1986273d9f13SBarry Smith     b->i[i] = b->i[i-1] + b->imax[i-1];
1987273d9f13SBarry Smith   }
1988273d9f13SBarry Smith 
1989273d9f13SBarry Smith   /* b->ilen will count nonzeros in each block row so far. */
1990b0a32e0cSBarry Smith   ierr = PetscMalloc((mbs+1)*sizeof(int),&b->ilen);
1991b0a32e0cSBarry Smith   PetscLogObjectMemory(B,len+2*(mbs+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqBAIJ));
1992273d9f13SBarry Smith   for (i=0; i<mbs; i++) { b->ilen[i] = 0;}
1993273d9f13SBarry Smith 
1994273d9f13SBarry Smith   b->bs               = bs;
1995273d9f13SBarry Smith   b->bs2              = bs2;
1996273d9f13SBarry Smith   b->mbs              = mbs;
1997273d9f13SBarry Smith   b->nz               = 0;
1998273d9f13SBarry Smith   b->maxnz            = nz*bs2;
1999273d9f13SBarry Smith   B->info.nz_unneeded = (PetscReal)b->maxnz;
2000273d9f13SBarry Smith   PetscFunctionReturn(0);
2001273d9f13SBarry Smith }
20022593348eSBarry Smith 
2003