xref: /petsc/src/mat/impls/sbaij/seq/sbaij.c (revision 4da8f2458232f57198ffbca67ee6b4144f494936)
1be1d678aSKris Buschelman #define PETSCMAT_DLL
249b5e25fSSatish Balay 
349b5e25fSSatish Balay /*
4a1373b80SHong Zhang     Defines the basic matrix operations for the SBAIJ (compressed row)
549b5e25fSSatish Balay   matrix storage format.
649b5e25fSSatish Balay */
77c4f633dSBarry Smith #include "../src/mat/impls/baij/seq/baij.h"         /*I "petscmat.h" I*/
87c4f633dSBarry Smith #include "../src/mat/impls/sbaij/seq/sbaij.h"
949b5e25fSSatish Balay 
10b5b17502SBarry Smith #include "../src/mat/impls/sbaij/seq/relax.h"
1170dcbbb9SBarry Smith #define USESHORT
12b5b17502SBarry Smith #include "../src/mat/impls/sbaij/seq/relax.h"
1370dcbbb9SBarry Smith 
14db4efbfdSBarry Smith extern PetscErrorCode MatSeqSBAIJSetNumericFactorization(Mat,PetscTruth);
1549b5e25fSSatish Balay #define CHUNKSIZE  10
1649b5e25fSSatish Balay 
17b5b17502SBarry Smith 
1849b5e25fSSatish Balay /*
1949b5e25fSSatish Balay      Checks for missing diagonals
2049b5e25fSSatish Balay */
214a2ae208SSatish Balay #undef __FUNCT__
224a2ae208SSatish Balay #define __FUNCT__ "MatMissingDiagonal_SeqSBAIJ"
232af78befSBarry Smith PetscErrorCode MatMissingDiagonal_SeqSBAIJ(Mat A,PetscTruth *missing,PetscInt *dd)
2449b5e25fSSatish Balay {
25045c9aa0SHong Zhang   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
266849ba73SBarry Smith   PetscErrorCode ierr;
2713f74950SBarry Smith   PetscInt       *diag,*jj = a->j,i;
2849b5e25fSSatish Balay 
2949b5e25fSSatish Balay   PetscFunctionBegin;
30045c9aa0SHong Zhang   ierr = MatMarkDiagonal_SeqSBAIJ(A);CHKERRQ(ierr);
3149b5e25fSSatish Balay   diag = a->diag;
322af78befSBarry Smith   *missing = PETSC_FALSE;
3349b5e25fSSatish Balay   for (i=0; i<a->mbs; i++) {
342af78befSBarry Smith     if (jj[diag[i]] != i) {
352af78befSBarry Smith       *missing    = PETSC_TRUE;
362af78befSBarry Smith       if (dd) *dd = i;
372af78befSBarry Smith       break;
382af78befSBarry Smith     }
3949b5e25fSSatish Balay   }
4049b5e25fSSatish Balay   PetscFunctionReturn(0);
4149b5e25fSSatish Balay }
4249b5e25fSSatish Balay 
434a2ae208SSatish Balay #undef __FUNCT__
444a2ae208SSatish Balay #define __FUNCT__ "MatMarkDiagonal_SeqSBAIJ"
45dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqSBAIJ(Mat A)
4649b5e25fSSatish Balay {
47045c9aa0SHong Zhang   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
486849ba73SBarry Smith   PetscErrorCode ierr;
4909f38230SBarry Smith   PetscInt       i;
5049b5e25fSSatish Balay 
5149b5e25fSSatish Balay   PetscFunctionBegin;
5209f38230SBarry Smith   if (!a->diag) {
5309f38230SBarry Smith     ierr = PetscMalloc(a->mbs*sizeof(PetscInt),&a->diag);CHKERRQ(ierr);
5409f38230SBarry Smith   }
5509f38230SBarry Smith   for (i=0; i<a->mbs; i++) a->diag[i] = a->i[i];
5649b5e25fSSatish Balay   PetscFunctionReturn(0);
5749b5e25fSSatish Balay }
5849b5e25fSSatish Balay 
594a2ae208SSatish Balay #undef __FUNCT__
604a2ae208SSatish Balay #define __FUNCT__ "MatGetRowIJ_SeqSBAIJ"
618f7157efSSatish Balay static PetscErrorCode MatGetRowIJ_SeqSBAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth blockcompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
6249b5e25fSSatish Balay {
63a6ece127SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
64d0f46423SBarry Smith   PetscInt     i,j,n = a->mbs,nz = a->i[n],bs = A->rmap->bs;
658f7157efSSatish Balay   PetscErrorCode ierr;
6649b5e25fSSatish Balay 
6749b5e25fSSatish Balay   PetscFunctionBegin;
68d3e5a4abSHong Zhang   *nn = n;
69a1373b80SHong Zhang   if (!ia) PetscFunctionReturn(0);
708f7157efSSatish Balay   if (!blockcompressed) {
718f7157efSSatish Balay     /* malloc & create the natural set of indices */
72f1d0d59dSSatish Balay     ierr = PetscMalloc2((n+1)*bs,PetscInt,ia,nz*bs,PetscInt,ja);CHKERRQ(ierr);
738f7157efSSatish Balay     for (i=0; i<n+1; i++) {
748f7157efSSatish Balay       for (j=0; j<bs; j++) {
758f7157efSSatish Balay         *ia[i*bs+j] = a->i[i]*bs+j+oshift;
768f7157efSSatish Balay       }
778f7157efSSatish Balay     }
788f7157efSSatish Balay     for (i=0; i<nz; i++) {
798f7157efSSatish Balay       for (j=0; j<bs; j++) {
808f7157efSSatish Balay         *ja[i*bs+j] = a->j[i]*bs+j+oshift;
818f7157efSSatish Balay       }
828f7157efSSatish Balay     }
838f7157efSSatish Balay   } else { /* blockcompressed */
84a6ece127SHong Zhang     if (oshift == 1) {
85a6ece127SHong Zhang       /* temporarily add 1 to i and j indices */
866c6c5352SBarry Smith       for (i=0; i<nz; i++) a->j[i]++;
87a1373b80SHong Zhang       for (i=0; i<n+1; i++) a->i[i]++;
888f7157efSSatish Balay     }
89a1373b80SHong Zhang     *ia = a->i; *ja = a->j;
90a6ece127SHong Zhang   }
918f7157efSSatish Balay 
9249b5e25fSSatish Balay   PetscFunctionReturn(0);
9349b5e25fSSatish Balay }
9449b5e25fSSatish Balay 
954a2ae208SSatish Balay #undef __FUNCT__
964a2ae208SSatish Balay #define __FUNCT__ "MatRestoreRowIJ_SeqSBAIJ"
978f7157efSSatish Balay static PetscErrorCode MatRestoreRowIJ_SeqSBAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth blockcompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
9849b5e25fSSatish Balay {
99b7aaefc3SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
1008f7157efSSatish Balay   PetscInt     i,n = a->mbs,nz = a->i[n];
1018f7157efSSatish Balay   PetscErrorCode ierr;
102a6ece127SHong Zhang 
10349b5e25fSSatish Balay   PetscFunctionBegin;
10449b5e25fSSatish Balay   if (!ia) PetscFunctionReturn(0);
105a6ece127SHong Zhang 
1068f7157efSSatish Balay   if (!blockcompressed) {
1078f7157efSSatish Balay     ierr = PetscFree2(*ia,*ja);CHKERRQ(ierr);
1088f7157efSSatish Balay   } else if (oshift == 1) { /* blockcompressed */
1096c6c5352SBarry Smith     for (i=0; i<nz; i++) a->j[i]--;
110a6ece127SHong Zhang     for (i=0; i<n+1; i++) a->i[i]--;
111a6ece127SHong Zhang   }
1128f7157efSSatish Balay 
113a6ece127SHong Zhang   PetscFunctionReturn(0);
11449b5e25fSSatish Balay }
11549b5e25fSSatish Balay 
1164a2ae208SSatish Balay #undef __FUNCT__
1174a2ae208SSatish Balay #define __FUNCT__ "MatDestroy_SeqSBAIJ"
118dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqSBAIJ(Mat A)
11949b5e25fSSatish Balay {
12049b5e25fSSatish Balay   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
121dfbe8321SBarry Smith   PetscErrorCode ierr;
12249b5e25fSSatish Balay 
12349b5e25fSSatish Balay   PetscFunctionBegin;
124a9f03627SSatish Balay #if defined(PETSC_USE_LOG)
125d0f46423SBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%D, NZ=%D",A->rmap->N,a->nz);
126a9f03627SSatish Balay #endif
127e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
1289bfd6278SHong Zhang   if (a->row) {ierr = ISDestroy(a->row);CHKERRQ(ierr);}
1299bfd6278SHong Zhang   if (a->col){ierr = ISDestroy(a->col);CHKERRQ(ierr);}
1309bfd6278SHong Zhang   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);}
131061b2667SBarry Smith   if (a->idiag) {ierr = PetscFree(a->idiag);CHKERRQ(ierr);}
1320def2e27SBarry Smith   if (a->inode.size) {ierr = PetscFree(a->inode.size);CHKERRQ(ierr);}
13305b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
13405b42c5fSBarry Smith   ierr = PetscFree2(a->imax,a->ilen);CHKERRQ(ierr);
13505b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
136e2ee2a47SBarry Smith   ierr = PetscFree(a->relax_work);CHKERRQ(ierr);
13705b42c5fSBarry Smith   ierr = PetscFree(a->solves_work);CHKERRQ(ierr);
13805b42c5fSBarry Smith   ierr = PetscFree(a->mult_work);CHKERRQ(ierr);
13905b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
14005b42c5fSBarry Smith   ierr = PetscFree(a->xtoy);CHKERRQ(ierr);
141*4da8f245SBarry Smith   if (a->free_jshort) {ierr = PetscFree(a->jshort);CHKERRQ(ierr);}
1421a3463dfSHong Zhang   ierr = PetscFree(a->inew);CHKERRQ(ierr);
143*4da8f245SBarry Smith   if (a->parent) {ierr = MatDestroy(a->parent);CHKERRQ(ierr);}
14449b5e25fSSatish Balay   ierr = PetscFree(a);CHKERRQ(ierr);
145901853e0SKris Buschelman 
146dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
147901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C","",PETSC_NULL);CHKERRQ(ierr);
148901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C","",PETSC_NULL);CHKERRQ(ierr);
149901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqSBAIJSetColumnIndices_C","",PETSC_NULL);CHKERRQ(ierr);
150901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqsbaij_seqaij_C","",PETSC_NULL);CHKERRQ(ierr);
151901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqsbaij_seqbaij_C","",PETSC_NULL);CHKERRQ(ierr);
152901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqSBAIJSetPreallocation_C","",PETSC_NULL);CHKERRQ(ierr);
15349b5e25fSSatish Balay   PetscFunctionReturn(0);
15449b5e25fSSatish Balay }
15549b5e25fSSatish Balay 
1564a2ae208SSatish Balay #undef __FUNCT__
1574a2ae208SSatish Balay #define __FUNCT__ "MatSetOption_SeqSBAIJ"
1584e0d8c25SBarry Smith PetscErrorCode MatSetOption_SeqSBAIJ(Mat A,MatOption op,PetscTruth flg)
15949b5e25fSSatish Balay {
160045c9aa0SHong Zhang   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
16163ba0a88SBarry Smith   PetscErrorCode ierr;
16249b5e25fSSatish Balay 
16349b5e25fSSatish Balay   PetscFunctionBegin;
1644d9d31abSKris Buschelman   switch (op) {
1654d9d31abSKris Buschelman   case MAT_ROW_ORIENTED:
1664e0d8c25SBarry Smith     a->roworiented = flg;
1674d9d31abSKris Buschelman     break;
168a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
169a9817697SBarry Smith     a->keepnonzeropattern = flg;
1704d9d31abSKris Buschelman     break;
171512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
172512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1734d9d31abSKris Buschelman     break;
1744d9d31abSKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
1754e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1764d9d31abSKris Buschelman     break;
1774d9d31abSKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
1784e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1794d9d31abSKris Buschelman     break;
18028b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
18128b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
18228b2fa4aSMatthew Knepley     break;
1834e0d8c25SBarry Smith   case MAT_NEW_DIAGONALS:
1844d9d31abSKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1854d9d31abSKris Buschelman   case MAT_USE_HASH_TABLE:
186290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1874d9d31abSKris Buschelman     break;
1889a4540c5SBarry Smith   case MAT_HERMITIAN:
1894e0d8c25SBarry Smith     if (flg) SETERRQ(PETSC_ERR_SUP,"Matrix must be symmetric");
19077e54ba9SKris Buschelman   case MAT_SYMMETRIC:
19177e54ba9SKris Buschelman   case MAT_STRUCTURALLY_SYMMETRIC:
1929a4540c5SBarry Smith   case MAT_SYMMETRY_ETERNAL:
1934e0d8c25SBarry Smith     if (!flg) SETERRQ(PETSC_ERR_SUP,"Matrix must be symmetric");
194290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s not relevent\n",MatOptions[op]);CHKERRQ(ierr);
195290bbb0aSBarry Smith     break;
196941593c8SHong Zhang   case MAT_IGNORE_LOWER_TRIANGULAR:
1974e0d8c25SBarry Smith     a->ignore_ltriangular = flg;
198941593c8SHong Zhang     break;
199941593c8SHong Zhang   case MAT_ERROR_LOWER_TRIANGULAR:
2004e0d8c25SBarry Smith     a->ignore_ltriangular = flg;
20177e54ba9SKris Buschelman     break;
202f5edf698SHong Zhang   case MAT_GETROW_UPPERTRIANGULAR:
2034e0d8c25SBarry Smith     a->getrow_utriangular = flg;
204f5edf698SHong Zhang     break;
2054d9d31abSKris Buschelman   default:
206ad86a440SBarry Smith     SETERRQ1(PETSC_ERR_SUP,"unknown option %d",op);
20749b5e25fSSatish Balay   }
20849b5e25fSSatish Balay   PetscFunctionReturn(0);
20949b5e25fSSatish Balay }
21049b5e25fSSatish Balay 
2114a2ae208SSatish Balay #undef __FUNCT__
2124a2ae208SSatish Balay #define __FUNCT__ "MatGetRow_SeqSBAIJ"
21313f74950SBarry Smith PetscErrorCode MatGetRow_SeqSBAIJ(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **v)
21449b5e25fSSatish Balay {
21549b5e25fSSatish Balay   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
2166849ba73SBarry Smith   PetscErrorCode ierr;
21713f74950SBarry Smith   PetscInt       itmp,i,j,k,M,*ai,*aj,bs,bn,bp,*cols_i,bs2;
21849b5e25fSSatish Balay   MatScalar      *aa,*aa_i;
21987828ca2SBarry Smith   PetscScalar    *v_i;
22049b5e25fSSatish Balay 
22149b5e25fSSatish Balay   PetscFunctionBegin;
2224e0d8c25SBarry Smith   if (A && !a->getrow_utriangular) SETERRQ(PETSC_ERR_SUP,"MatGetRow is not supported for SBAIJ matrix format. Getting the upper triangular part of row, run with -mat_getrow_uppertriangular, call MatSetOption(mat,MAT_GETROW_UPPERTRIANGULAR,PETSC_TRUE) or MatGetRowUpperTriangular()");
223f5edf698SHong Zhang   /* Get the upper triangular part of the row */
224d0f46423SBarry Smith   bs  = A->rmap->bs;
22549b5e25fSSatish Balay   ai  = a->i;
22649b5e25fSSatish Balay   aj  = a->j;
22749b5e25fSSatish Balay   aa  = a->a;
22849b5e25fSSatish Balay   bs2 = a->bs2;
22949b5e25fSSatish Balay 
230d0f46423SBarry Smith   if (row < 0 || row >= A->rmap->N) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Row %D out of range", row);
23149b5e25fSSatish Balay 
23249b5e25fSSatish Balay   bn  = row/bs;   /* Block number */
23349b5e25fSSatish Balay   bp  = row % bs; /* Block position */
23449b5e25fSSatish Balay   M   = ai[bn+1] - ai[bn];
23549b5e25fSSatish Balay   *ncols = bs*M;
23649b5e25fSSatish Balay 
23749b5e25fSSatish Balay   if (v) {
23849b5e25fSSatish Balay     *v = 0;
23949b5e25fSSatish Balay     if (*ncols) {
24087828ca2SBarry Smith       ierr = PetscMalloc((*ncols+row)*sizeof(PetscScalar),v);CHKERRQ(ierr);
24149b5e25fSSatish Balay       for (i=0; i<M; i++) { /* for each block in the block row */
24249b5e25fSSatish Balay         v_i  = *v + i*bs;
24349b5e25fSSatish Balay         aa_i = aa + bs2*(ai[bn] + i);
24449b5e25fSSatish Balay         for (j=bp,k=0; j<bs2; j+=bs,k++) {v_i[k] = aa_i[j];}
24549b5e25fSSatish Balay       }
24649b5e25fSSatish Balay     }
24749b5e25fSSatish Balay   }
24849b5e25fSSatish Balay 
24949b5e25fSSatish Balay   if (cols) {
25049b5e25fSSatish Balay     *cols = 0;
25149b5e25fSSatish Balay     if (*ncols) {
25213f74950SBarry Smith       ierr = PetscMalloc((*ncols+row)*sizeof(PetscInt),cols);CHKERRQ(ierr);
25349b5e25fSSatish Balay       for (i=0; i<M; i++) { /* for each block in the block row */
25449b5e25fSSatish Balay         cols_i = *cols + i*bs;
25549b5e25fSSatish Balay         itmp  = bs*aj[ai[bn] + i];
25649b5e25fSSatish Balay         for (j=0; j<bs; j++) {cols_i[j] = itmp++;}
25749b5e25fSSatish Balay       }
25849b5e25fSSatish Balay     }
25949b5e25fSSatish Balay   }
26049b5e25fSSatish Balay 
26149b5e25fSSatish Balay   /*search column A(0:row-1,row) (=A(row,0:row-1)). Could be expensive! */
2625ddb2528SHong Zhang   /* this segment is currently removed, so only entries in the upper triangle are obtained */
2635ddb2528SHong Zhang #ifdef column_search
26449b5e25fSSatish Balay   v_i    = *v    + M*bs;
26549b5e25fSSatish Balay   cols_i = *cols + M*bs;
26649b5e25fSSatish Balay   for (i=0; i<bn; i++){ /* for each block row */
26749b5e25fSSatish Balay     M = ai[i+1] - ai[i];
26849b5e25fSSatish Balay     for (j=0; j<M; j++){
26949b5e25fSSatish Balay       itmp = aj[ai[i] + j];    /* block column value */
27049b5e25fSSatish Balay       if (itmp == bn){
27149b5e25fSSatish Balay         aa_i   = aa    + bs2*(ai[i] + j) + bs*bp;
27249b5e25fSSatish Balay         for (k=0; k<bs; k++) {
27349b5e25fSSatish Balay           *cols_i++ = i*bs+k;
27449b5e25fSSatish Balay           *v_i++    = aa_i[k];
27549b5e25fSSatish Balay         }
27649b5e25fSSatish Balay         *ncols += bs;
27749b5e25fSSatish Balay         break;
27849b5e25fSSatish Balay       }
27949b5e25fSSatish Balay     }
28049b5e25fSSatish Balay   }
2815ddb2528SHong Zhang #endif
28249b5e25fSSatish Balay   PetscFunctionReturn(0);
28349b5e25fSSatish Balay }
28449b5e25fSSatish Balay 
2854a2ae208SSatish Balay #undef __FUNCT__
2864a2ae208SSatish Balay #define __FUNCT__ "MatRestoreRow_SeqSBAIJ"
28713f74950SBarry Smith PetscErrorCode MatRestoreRow_SeqSBAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
28849b5e25fSSatish Balay {
289dfbe8321SBarry Smith   PetscErrorCode ierr;
29049b5e25fSSatish Balay 
29149b5e25fSSatish Balay   PetscFunctionBegin;
29205b42c5fSBarry Smith   if (idx) {ierr = PetscFree(*idx);CHKERRQ(ierr);}
29305b42c5fSBarry Smith   if (v)   {ierr = PetscFree(*v);CHKERRQ(ierr);}
29449b5e25fSSatish Balay   PetscFunctionReturn(0);
29549b5e25fSSatish Balay }
29649b5e25fSSatish Balay 
2974a2ae208SSatish Balay #undef __FUNCT__
298f5edf698SHong Zhang #define __FUNCT__ "MatGetRowUpperTriangular_SeqSBAIJ"
299f5edf698SHong Zhang PetscErrorCode MatGetRowUpperTriangular_SeqSBAIJ(Mat A)
300f5edf698SHong Zhang {
301f5edf698SHong Zhang   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
302f5edf698SHong Zhang 
303f5edf698SHong Zhang   PetscFunctionBegin;
304f5edf698SHong Zhang   a->getrow_utriangular = PETSC_TRUE;
305f5edf698SHong Zhang   PetscFunctionReturn(0);
306f5edf698SHong Zhang }
307f5edf698SHong Zhang #undef __FUNCT__
308f5edf698SHong Zhang #define __FUNCT__ "MatRestoreRowUpperTriangular_SeqSBAIJ"
309f5edf698SHong Zhang PetscErrorCode MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A)
310f5edf698SHong Zhang {
311f5edf698SHong Zhang   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
312f5edf698SHong Zhang 
313f5edf698SHong Zhang   PetscFunctionBegin;
314f5edf698SHong Zhang   a->getrow_utriangular = PETSC_FALSE;
315f5edf698SHong Zhang   PetscFunctionReturn(0);
316f5edf698SHong Zhang }
317f5edf698SHong Zhang 
318f5edf698SHong Zhang #undef __FUNCT__
3194a2ae208SSatish Balay #define __FUNCT__ "MatTranspose_SeqSBAIJ"
320fc4dec0aSBarry Smith PetscErrorCode MatTranspose_SeqSBAIJ(Mat A,MatReuse reuse,Mat *B)
32149b5e25fSSatish Balay {
322dfbe8321SBarry Smith   PetscErrorCode ierr;
32349b5e25fSSatish Balay   PetscFunctionBegin;
324815cbec1SBarry Smith   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
325999d9058SBarry Smith     ierr = MatDuplicate(A,MAT_COPY_VALUES,B);CHKERRQ(ierr);
326fc4dec0aSBarry Smith   }
3278115998fSBarry Smith   PetscFunctionReturn(0);
32849b5e25fSSatish Balay }
32949b5e25fSSatish Balay 
3304a2ae208SSatish Balay #undef __FUNCT__
3314a2ae208SSatish Balay #define __FUNCT__ "MatView_SeqSBAIJ_ASCII"
3326849ba73SBarry Smith static PetscErrorCode MatView_SeqSBAIJ_ASCII(Mat A,PetscViewer viewer)
33349b5e25fSSatish Balay {
33449b5e25fSSatish Balay   Mat_SeqSBAIJ      *a = (Mat_SeqSBAIJ*)A->data;
335dfbe8321SBarry Smith   PetscErrorCode    ierr;
336d0f46423SBarry Smith   PetscInt          i,j,bs = A->rmap->bs,k,l,bs2=a->bs2;
3372dcb1b2aSMatthew Knepley   const char        *name;
338f3ef73ceSBarry Smith   PetscViewerFormat format;
33949b5e25fSSatish Balay 
34049b5e25fSSatish Balay   PetscFunctionBegin;
34180fe4e49SBarry Smith   ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
342b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
343456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
34477431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  block size is %D\n",bs);CHKERRQ(ierr);
345fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_MATLAB) {
346d2507d54SMatthew Knepley     Mat aij;
347d2507d54SMatthew Knepley 
34870d5e725SHong Zhang     if (A->factor && bs>1){
34970d5e725SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"Warning: matrix is factored with bs>1. MatView() with PETSC_VIEWER_ASCII_MATLAB is not supported and ignored!\n");CHKERRQ(ierr);
35070d5e725SHong Zhang       PetscFunctionReturn(0);
35170d5e725SHong Zhang     }
352c9f458caSMatthew Knepley     ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&aij);CHKERRQ(ierr);
353c9f458caSMatthew Knepley     ierr = MatView(aij,viewer);CHKERRQ(ierr);
354c9f458caSMatthew Knepley     ierr = MatDestroy(aij);CHKERRQ(ierr);
355fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
356b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
35749b5e25fSSatish Balay     for (i=0; i<a->mbs; i++) {
35849b5e25fSSatish Balay       for (j=0; j<bs; j++) {
35977431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i*bs+j);CHKERRQ(ierr);
36049b5e25fSSatish Balay         for (k=a->i[i]; k<a->i[i+1]; k++) {
36149b5e25fSSatish Balay           for (l=0; l<bs; l++) {
36249b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX)
36349b5e25fSSatish Balay             if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
364a83599f4SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i) ",bs*a->j[k]+l,
36549b5e25fSSatish Balay                                             PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
36649b5e25fSSatish Balay             } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
367a83599f4SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i) ",bs*a->j[k]+l,
36849b5e25fSSatish Balay                                             PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
36949b5e25fSSatish Balay             } else if (PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
370a83599f4SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
37149b5e25fSSatish Balay             }
37249b5e25fSSatish Balay #else
37349b5e25fSSatish Balay             if (a->a[bs2*k + l*bs + j] != 0.0) {
374a83599f4SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);CHKERRQ(ierr);
37549b5e25fSSatish Balay             }
37649b5e25fSSatish Balay #endif
37749b5e25fSSatish Balay           }
37849b5e25fSSatish Balay         }
379b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
38049b5e25fSSatish Balay       }
38149b5e25fSSatish Balay     }
382b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
383c1490034SHong Zhang   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
384c1490034SHong Zhang      PetscFunctionReturn(0);
38549b5e25fSSatish Balay   } else {
3868608aa04SHong Zhang     if (A->factor && bs>1){
3878608aa04SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"Warning: matrix is factored. MatView_SeqSBAIJ_ASCII() may not display complete or logically correct entries!\n");CHKERRQ(ierr);
3888608aa04SHong Zhang     }
389b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
39049b5e25fSSatish Balay     for (i=0; i<a->mbs; i++) {
39149b5e25fSSatish Balay       for (j=0; j<bs; j++) {
39277431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i*bs+j);CHKERRQ(ierr);
39349b5e25fSSatish Balay         for (k=a->i[i]; k<a->i[i+1]; k++) {
39449b5e25fSSatish Balay           for (l=0; l<bs; l++) {
39549b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX)
39649b5e25fSSatish Balay             if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0) {
397a83599f4SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i) ",bs*a->j[k]+l,
39849b5e25fSSatish Balay                                             PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
39949b5e25fSSatish Balay             } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0) {
400a83599f4SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i) ",bs*a->j[k]+l,
40149b5e25fSSatish Balay                                             PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
40249b5e25fSSatish Balay             } else {
403a83599f4SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
40449b5e25fSSatish Balay             }
40549b5e25fSSatish Balay #else
406e9f7bc9eSHong Zhang             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);CHKERRQ(ierr);
40749b5e25fSSatish Balay #endif
40849b5e25fSSatish Balay           }
40949b5e25fSSatish Balay         }
410b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
41149b5e25fSSatish Balay       }
41249b5e25fSSatish Balay     }
413b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
41449b5e25fSSatish Balay   }
415b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
41649b5e25fSSatish Balay   PetscFunctionReturn(0);
41749b5e25fSSatish Balay }
41849b5e25fSSatish Balay 
4194a2ae208SSatish Balay #undef __FUNCT__
4204a2ae208SSatish Balay #define __FUNCT__ "MatView_SeqSBAIJ_Draw_Zoom"
4216849ba73SBarry Smith static PetscErrorCode MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
42249b5e25fSSatish Balay {
42349b5e25fSSatish Balay   Mat            A = (Mat) Aa;
42449b5e25fSSatish Balay   Mat_SeqSBAIJ   *a=(Mat_SeqSBAIJ*)A->data;
4256849ba73SBarry Smith   PetscErrorCode ierr;
426d0f46423SBarry Smith   PetscInt       row,i,j,k,l,mbs=a->mbs,color,bs=A->rmap->bs,bs2=a->bs2;
42713f74950SBarry Smith   PetscMPIInt    rank;
42849b5e25fSSatish Balay   PetscReal      xl,yl,xr,yr,x_l,x_r,y_l,y_r;
42949b5e25fSSatish Balay   MatScalar      *aa;
43049b5e25fSSatish Balay   MPI_Comm       comm;
431b0a32e0cSBarry Smith   PetscViewer    viewer;
43249b5e25fSSatish Balay 
43349b5e25fSSatish Balay   PetscFunctionBegin;
43449b5e25fSSatish Balay   /*
43549b5e25fSSatish Balay     This is nasty. If this is called from an originally parallel matrix
43649b5e25fSSatish Balay     then all processes call this,but only the first has the matrix so the
43749b5e25fSSatish Balay     rest should return immediately.
43849b5e25fSSatish Balay   */
43949b5e25fSSatish Balay   ierr = PetscObjectGetComm((PetscObject)draw,&comm);CHKERRQ(ierr);
44049b5e25fSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
44149b5e25fSSatish Balay   if (rank) PetscFunctionReturn(0);
44249b5e25fSSatish Balay 
44349b5e25fSSatish Balay   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
44449b5e25fSSatish Balay 
445b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
446b0a32e0cSBarry Smith   PetscDrawString(draw, .3*(xl+xr), .3*(yl+yr), PETSC_DRAW_BLACK, "symmetric");
44749b5e25fSSatish Balay 
44849b5e25fSSatish Balay   /* loop over matrix elements drawing boxes */
449b0a32e0cSBarry Smith   color = PETSC_DRAW_BLUE;
45049b5e25fSSatish Balay   for (i=0,row=0; i<mbs; i++,row+=bs) {
45149b5e25fSSatish Balay     for (j=a->i[i]; j<a->i[i+1]; j++) {
452d0f46423SBarry Smith       y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0;
45349b5e25fSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
45449b5e25fSSatish Balay       aa = a->a + j*bs2;
45549b5e25fSSatish Balay       for (k=0; k<bs; k++) {
45649b5e25fSSatish Balay         for (l=0; l<bs; l++) {
45749b5e25fSSatish Balay           if (PetscRealPart(*aa++) >=  0.) continue;
458b0a32e0cSBarry Smith           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
45949b5e25fSSatish Balay         }
46049b5e25fSSatish Balay       }
46149b5e25fSSatish Balay     }
46249b5e25fSSatish Balay   }
463b0a32e0cSBarry Smith   color = PETSC_DRAW_CYAN;
46449b5e25fSSatish Balay   for (i=0,row=0; i<mbs; i++,row+=bs) {
46549b5e25fSSatish Balay     for (j=a->i[i]; j<a->i[i+1]; j++) {
466d0f46423SBarry Smith       y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0;
46749b5e25fSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
46849b5e25fSSatish Balay       aa = a->a + j*bs2;
46949b5e25fSSatish Balay       for (k=0; k<bs; k++) {
47049b5e25fSSatish Balay         for (l=0; l<bs; l++) {
47149b5e25fSSatish Balay           if (PetscRealPart(*aa++) != 0.) continue;
472b0a32e0cSBarry Smith           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
47349b5e25fSSatish Balay         }
47449b5e25fSSatish Balay       }
47549b5e25fSSatish Balay     }
47649b5e25fSSatish Balay   }
47749b5e25fSSatish Balay 
478b0a32e0cSBarry Smith   color = PETSC_DRAW_RED;
47949b5e25fSSatish Balay   for (i=0,row=0; i<mbs; i++,row+=bs) {
48049b5e25fSSatish Balay     for (j=a->i[i]; j<a->i[i+1]; j++) {
481d0f46423SBarry Smith       y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0;
48249b5e25fSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
48349b5e25fSSatish Balay       aa = a->a + j*bs2;
48449b5e25fSSatish Balay       for (k=0; k<bs; k++) {
48549b5e25fSSatish Balay         for (l=0; l<bs; l++) {
48649b5e25fSSatish Balay           if (PetscRealPart(*aa++) <= 0.) continue;
487b0a32e0cSBarry Smith           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
48849b5e25fSSatish Balay         }
48949b5e25fSSatish Balay       }
49049b5e25fSSatish Balay     }
49149b5e25fSSatish Balay   }
49249b5e25fSSatish Balay   PetscFunctionReturn(0);
49349b5e25fSSatish Balay }
49449b5e25fSSatish Balay 
4954a2ae208SSatish Balay #undef __FUNCT__
4964a2ae208SSatish Balay #define __FUNCT__ "MatView_SeqSBAIJ_Draw"
4976849ba73SBarry Smith static PetscErrorCode MatView_SeqSBAIJ_Draw(Mat A,PetscViewer viewer)
49849b5e25fSSatish Balay {
499dfbe8321SBarry Smith   PetscErrorCode ierr;
50049b5e25fSSatish Balay   PetscReal      xl,yl,xr,yr,w,h;
501b0a32e0cSBarry Smith   PetscDraw      draw;
50249b5e25fSSatish Balay   PetscTruth     isnull;
50349b5e25fSSatish Balay 
50449b5e25fSSatish Balay   PetscFunctionBegin;
505b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
506b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
50749b5e25fSSatish Balay 
50849b5e25fSSatish Balay   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
509d0f46423SBarry Smith   xr  = A->rmap->N; yr = A->rmap->N; h = yr/10.0; w = xr/10.0;
51049b5e25fSSatish Balay   xr += w;    yr += h;  xl = -w;     yl = -h;
511b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
512b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqSBAIJ_Draw_Zoom,A);CHKERRQ(ierr);
51349b5e25fSSatish Balay   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
51449b5e25fSSatish Balay   PetscFunctionReturn(0);
51549b5e25fSSatish Balay }
51649b5e25fSSatish Balay 
5174a2ae208SSatish Balay #undef __FUNCT__
5184a2ae208SSatish Balay #define __FUNCT__ "MatView_SeqSBAIJ"
519dfbe8321SBarry Smith PetscErrorCode MatView_SeqSBAIJ(Mat A,PetscViewer viewer)
52049b5e25fSSatish Balay {
521dfbe8321SBarry Smith   PetscErrorCode ierr;
52232077d6dSBarry Smith   PetscTruth     iascii,isdraw;
52349b5e25fSSatish Balay 
52449b5e25fSSatish Balay   PetscFunctionBegin;
52532077d6dSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
526fb9695e5SSatish Balay   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
52732077d6dSBarry Smith   if (iascii){
52849b5e25fSSatish Balay     ierr = MatView_SeqSBAIJ_ASCII(A,viewer);CHKERRQ(ierr);
52949b5e25fSSatish Balay   } else if (isdraw) {
53049b5e25fSSatish Balay     ierr = MatView_SeqSBAIJ_Draw(A,viewer);CHKERRQ(ierr);
53149b5e25fSSatish Balay   } else {
532a5e6ed63SBarry Smith     Mat B;
533ceb03754SKris Buschelman     ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
534a5e6ed63SBarry Smith     ierr = MatView(B,viewer);CHKERRQ(ierr);
535a5e6ed63SBarry Smith     ierr = MatDestroy(B);CHKERRQ(ierr);
53649b5e25fSSatish Balay   }
53749b5e25fSSatish Balay   PetscFunctionReturn(0);
53849b5e25fSSatish Balay }
53949b5e25fSSatish Balay 
54049b5e25fSSatish Balay 
5414a2ae208SSatish Balay #undef __FUNCT__
5424a2ae208SSatish Balay #define __FUNCT__ "MatGetValues_SeqSBAIJ"
54313f74950SBarry Smith PetscErrorCode MatGetValues_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
54449b5e25fSSatish Balay {
545045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
54613f74950SBarry Smith   PetscInt     *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
54713f74950SBarry Smith   PetscInt     *ai = a->i,*ailen = a->ilen;
548d0f46423SBarry Smith   PetscInt     brow,bcol,ridx,cidx,bs=A->rmap->bs,bs2=a->bs2;
54997e567efSBarry Smith   MatScalar    *ap,*aa = a->a;
55049b5e25fSSatish Balay 
55149b5e25fSSatish Balay   PetscFunctionBegin;
55249b5e25fSSatish Balay   for (k=0; k<m; k++) { /* loop over rows */
55349b5e25fSSatish Balay     row  = im[k]; brow = row/bs;
55497e567efSBarry Smith     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
555d0f46423SBarry Smith     if (row >= A->rmap->N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->N-1);
55649b5e25fSSatish Balay     rp   = aj + ai[brow] ; ap = aa + bs2*ai[brow] ;
55749b5e25fSSatish Balay     nrow = ailen[brow];
55849b5e25fSSatish Balay     for (l=0; l<n; l++) { /* loop over columns */
55997e567efSBarry Smith       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
560d0f46423SBarry Smith       if (in[l] >= A->cmap->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
56149b5e25fSSatish Balay       col  = in[l] ;
56249b5e25fSSatish Balay       bcol = col/bs;
56349b5e25fSSatish Balay       cidx = col%bs;
56449b5e25fSSatish Balay       ridx = row%bs;
56549b5e25fSSatish Balay       high = nrow;
56649b5e25fSSatish Balay       low  = 0; /* assume unsorted */
56749b5e25fSSatish Balay       while (high-low > 5) {
56849b5e25fSSatish Balay         t = (low+high)/2;
56949b5e25fSSatish Balay         if (rp[t] > bcol) high = t;
57049b5e25fSSatish Balay         else             low  = t;
57149b5e25fSSatish Balay       }
57249b5e25fSSatish Balay       for (i=low; i<high; i++) {
57349b5e25fSSatish Balay         if (rp[i] > bcol) break;
57449b5e25fSSatish Balay         if (rp[i] == bcol) {
57549b5e25fSSatish Balay           *v++ = ap[bs2*i+bs*cidx+ridx];
57649b5e25fSSatish Balay           goto finished;
57749b5e25fSSatish Balay         }
57849b5e25fSSatish Balay       }
57997e567efSBarry Smith       *v++ = 0.0;
58049b5e25fSSatish Balay       finished:;
58149b5e25fSSatish Balay     }
58249b5e25fSSatish Balay   }
58349b5e25fSSatish Balay   PetscFunctionReturn(0);
58449b5e25fSSatish Balay }
58549b5e25fSSatish Balay 
58649b5e25fSSatish Balay 
5874a2ae208SSatish Balay #undef __FUNCT__
5884a2ae208SSatish Balay #define __FUNCT__ "MatSetValuesBlocked_SeqSBAIJ"
58913f74950SBarry Smith PetscErrorCode MatSetValuesBlocked_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
59049b5e25fSSatish Balay {
5910880e062SHong Zhang   Mat_SeqSBAIJ      *a = (Mat_SeqSBAIJ*)A->data;
5926849ba73SBarry Smith   PetscErrorCode    ierr;
593e2ee6c50SBarry Smith   PetscInt          *rp,k,low,high,t,ii,jj,row,nrow,i,col,l,rmax,N,lastcol = -1;
59413f74950SBarry Smith   PetscInt          *imax=a->imax,*ai=a->i,*ailen=a->ilen;
595d0f46423SBarry Smith   PetscInt          *aj=a->j,nonew=a->nonew,bs2=a->bs2,bs=A->rmap->bs,stepval;
5960880e062SHong Zhang   PetscTruth        roworiented=a->roworiented;
597dd6ea824SBarry Smith   const PetscScalar *value = v;
598f15d580aSBarry Smith   MatScalar         *ap,*aa = a->a,*bap;
5990880e062SHong Zhang 
60049b5e25fSSatish Balay   PetscFunctionBegin;
6010880e062SHong Zhang   if (roworiented) {
6020880e062SHong Zhang     stepval = (n-1)*bs;
6030880e062SHong Zhang   } else {
6040880e062SHong Zhang     stepval = (m-1)*bs;
6050880e062SHong Zhang   }
6060880e062SHong Zhang   for (k=0; k<m; k++) { /* loop over added rows */
6070880e062SHong Zhang     row  = im[k];
6080880e062SHong Zhang     if (row < 0) continue;
6092515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
61077431f27SBarry Smith     if (row >= a->mbs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,a->mbs-1);
6110880e062SHong Zhang #endif
6120880e062SHong Zhang     rp   = aj + ai[row];
6130880e062SHong Zhang     ap   = aa + bs2*ai[row];
6140880e062SHong Zhang     rmax = imax[row];
6150880e062SHong Zhang     nrow = ailen[row];
6160880e062SHong Zhang     low  = 0;
617818f2c47SBarry Smith     high = nrow;
6180880e062SHong Zhang     for (l=0; l<n; l++) { /* loop over added columns */
6190880e062SHong Zhang       if (in[l] < 0) continue;
6200880e062SHong Zhang       col = in[l];
6212515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
62277431f27SBarry Smith       if (col >= a->nbs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",col,a->nbs-1);
623b1823623SSatish Balay #endif
6240880e062SHong Zhang       if (col < row) continue; /* ignore lower triangular block */
6250880e062SHong Zhang       if (roworiented) {
6260880e062SHong Zhang         value = v + k*(stepval+bs)*bs + l*bs;
6270880e062SHong Zhang       } else {
6280880e062SHong Zhang         value = v + l*(stepval+bs)*bs + k*bs;
6290880e062SHong Zhang       }
6307cd84e04SBarry Smith       if (col <= lastcol) low = 0; else high = nrow;
631e2ee6c50SBarry Smith       lastcol = col;
6320880e062SHong Zhang       while (high-low > 7) {
6330880e062SHong Zhang         t = (low+high)/2;
6340880e062SHong Zhang         if (rp[t] > col) high = t;
6350880e062SHong Zhang         else             low  = t;
6360880e062SHong Zhang       }
6370880e062SHong Zhang       for (i=low; i<high; i++) {
6380880e062SHong Zhang         if (rp[i] > col) break;
6390880e062SHong Zhang         if (rp[i] == col) {
6400880e062SHong Zhang           bap  = ap +  bs2*i;
6410880e062SHong Zhang           if (roworiented) {
6420880e062SHong Zhang             if (is == ADD_VALUES) {
6430880e062SHong Zhang               for (ii=0; ii<bs; ii++,value+=stepval) {
6440880e062SHong Zhang                 for (jj=ii; jj<bs2; jj+=bs) {
6450880e062SHong Zhang                   bap[jj] += *value++;
6460880e062SHong Zhang                 }
6470880e062SHong Zhang               }
6480880e062SHong Zhang             } else {
6490880e062SHong Zhang               for (ii=0; ii<bs; ii++,value+=stepval) {
6500880e062SHong Zhang                 for (jj=ii; jj<bs2; jj+=bs) {
6510880e062SHong Zhang                   bap[jj] = *value++;
6520880e062SHong Zhang                 }
6530880e062SHong Zhang                }
6540880e062SHong Zhang             }
6550880e062SHong Zhang           } else {
6560880e062SHong Zhang             if (is == ADD_VALUES) {
6570880e062SHong Zhang               for (ii=0; ii<bs; ii++,value+=stepval) {
6580880e062SHong Zhang                 for (jj=0; jj<bs; jj++) {
6590880e062SHong Zhang                   *bap++ += *value++;
6600880e062SHong Zhang                 }
6610880e062SHong Zhang               }
6620880e062SHong Zhang             } else {
6630880e062SHong Zhang               for (ii=0; ii<bs; ii++,value+=stepval) {
6640880e062SHong Zhang                 for (jj=0; jj<bs; jj++) {
6650880e062SHong Zhang                   *bap++  = *value++;
6660880e062SHong Zhang                 }
6670880e062SHong Zhang               }
6680880e062SHong Zhang             }
6690880e062SHong Zhang           }
6700880e062SHong Zhang           goto noinsert2;
6710880e062SHong Zhang         }
6720880e062SHong Zhang       }
6730880e062SHong Zhang       if (nonew == 1) goto noinsert2;
674085a36d4SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col);
675421e10b8SBarry Smith       MatSeqXAIJReallocateAIJ(A,a->mbs,bs2,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
676c03d1d03SSatish Balay       N = nrow++ - 1; high++;
6770880e062SHong Zhang       /* shift up all the later entries in this row */
6780880e062SHong Zhang       for (ii=N; ii>=i; ii--) {
6790880e062SHong Zhang         rp[ii+1] = rp[ii];
6800880e062SHong Zhang         ierr = PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));CHKERRQ(ierr);
6810880e062SHong Zhang       }
6820880e062SHong Zhang       if (N >= i) {
6830880e062SHong Zhang         ierr = PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));CHKERRQ(ierr);
6840880e062SHong Zhang       }
6850880e062SHong Zhang       rp[i] = col;
6860880e062SHong Zhang       bap   = ap +  bs2*i;
6870880e062SHong Zhang       if (roworiented) {
6880880e062SHong Zhang         for (ii=0; ii<bs; ii++,value+=stepval) {
6890880e062SHong Zhang           for (jj=ii; jj<bs2; jj+=bs) {
6900880e062SHong Zhang             bap[jj] = *value++;
6910880e062SHong Zhang           }
6920880e062SHong Zhang         }
6930880e062SHong Zhang       } else {
6940880e062SHong Zhang         for (ii=0; ii<bs; ii++,value+=stepval) {
6950880e062SHong Zhang           for (jj=0; jj<bs; jj++) {
6960880e062SHong Zhang             *bap++  = *value++;
6970880e062SHong Zhang           }
6980880e062SHong Zhang         }
6990880e062SHong Zhang        }
7000880e062SHong Zhang     noinsert2:;
7010880e062SHong Zhang       low = i;
7020880e062SHong Zhang     }
7030880e062SHong Zhang     ailen[row] = nrow;
7040880e062SHong Zhang   }
7050880e062SHong Zhang    PetscFunctionReturn(0);
70649b5e25fSSatish Balay }
70749b5e25fSSatish Balay 
70864831d72SBarry Smith /*
70964831d72SBarry Smith     This is not yet used
71064831d72SBarry Smith */
7114a2ae208SSatish Balay #undef __FUNCT__
7120def2e27SBarry Smith #define __FUNCT__ "MatAssemblyEnd_SeqSBAIJ_Inode"
7130def2e27SBarry Smith PetscErrorCode MatAssemblyEnd_SeqSBAIJ_Inode(Mat A)
7140def2e27SBarry Smith {
7150def2e27SBarry Smith   Mat_SeqSBAIJ    *a = (Mat_SeqSBAIJ*)A->data;
7160def2e27SBarry Smith   PetscErrorCode  ierr;
7170def2e27SBarry Smith   const PetscInt  *ai = a->i, *aj = a->j,*cols;
7180def2e27SBarry Smith   PetscInt        i = 0,j,blk_size,m = A->rmap->n,node_count = 0,nzx,nzy,*ns,row,nz,cnt,cnt2,*counts;
7190def2e27SBarry Smith   PetscTruth      flag;
7200def2e27SBarry Smith 
7210def2e27SBarry Smith   PetscFunctionBegin;
7220def2e27SBarry Smith   ierr = PetscMalloc(m*sizeof(PetscInt),&ns);CHKERRQ(ierr);
7230def2e27SBarry Smith   while (i < m){
7240def2e27SBarry Smith     nzx = ai[i+1] - ai[i];       /* Number of nonzeros */
7250def2e27SBarry Smith     /* Limits the number of elements in a node to 'a->inode.limit' */
7260def2e27SBarry Smith     for (j=i+1,blk_size=1; j<m && blk_size <a->inode.limit; ++j,++blk_size) {
7270def2e27SBarry Smith       nzy  = ai[j+1] - ai[j];
7280def2e27SBarry Smith       if (nzy != (nzx - j + i)) break;
7290def2e27SBarry Smith       ierr = PetscMemcmp(aj + ai[i] + j - i,aj + ai[j],nzy*sizeof(PetscInt),&flag);CHKERRQ(ierr);
7300def2e27SBarry Smith       if (!flag) break;
7310def2e27SBarry Smith     }
7320def2e27SBarry Smith     ns[node_count++] = blk_size;
7330def2e27SBarry Smith     i = j;
7340def2e27SBarry Smith   }
7350def2e27SBarry Smith   if (!a->inode.size && m && node_count > .9*m) {
7360def2e27SBarry Smith     ierr = PetscFree(ns);CHKERRQ(ierr);
7370def2e27SBarry Smith     ierr = PetscInfo2(A,"Found %D nodes out of %D rows. Not using Inode routines\n",node_count,m);CHKERRQ(ierr);
7380def2e27SBarry Smith   } else {
7390def2e27SBarry Smith     a->inode.node_count = node_count;
7400def2e27SBarry Smith     ierr = PetscMalloc(node_count*sizeof(PetscInt),&a->inode.size);CHKERRQ(ierr);
7410def2e27SBarry Smith     ierr = PetscMemcpy(a->inode.size,ns,node_count*sizeof(PetscInt));
7420def2e27SBarry Smith     ierr = PetscFree(ns);CHKERRQ(ierr);
7430def2e27SBarry Smith     ierr = PetscInfo3(A,"Found %D nodes of %D. Limit used: %D. Using Inode routines\n",node_count,m,a->inode.limit);CHKERRQ(ierr);
7440def2e27SBarry Smith 
7450def2e27SBarry Smith     /* count collections of adjacent columns in each inode */
7460def2e27SBarry Smith     row = 0;
7470def2e27SBarry Smith     cnt = 0;
7480def2e27SBarry Smith     for (i=0; i<node_count; i++) {
7490def2e27SBarry Smith       cols = aj + ai[row] + a->inode.size[i];
7500def2e27SBarry Smith       nz   = ai[row+1] - ai[row] - a->inode.size[i];
7510def2e27SBarry Smith       for (j=1; j<nz; j++) {
7520def2e27SBarry Smith         if (cols[j] != cols[j-1]+1) {
7530def2e27SBarry Smith           cnt++;
7540def2e27SBarry Smith         }
7550def2e27SBarry Smith       }
7560def2e27SBarry Smith       cnt++;
7570def2e27SBarry Smith       row += a->inode.size[i];
7580def2e27SBarry Smith     }
7590def2e27SBarry Smith     ierr = PetscMalloc(2*cnt*sizeof(PetscInt),&counts);CHKERRQ(ierr);
7600def2e27SBarry Smith     cnt = 0;
7610def2e27SBarry Smith     row = 0;
7620def2e27SBarry Smith     for (i=0; i<node_count; i++) {
7630def2e27SBarry Smith       cols          = aj + ai[row] + a->inode.size[i];
7640def2e27SBarry Smith 	  CHKMEMQ;
7650def2e27SBarry Smith       counts[2*cnt] = cols[0];
7660def2e27SBarry Smith 	  CHKMEMQ;
7670def2e27SBarry Smith       nz            = ai[row+1] - ai[row] - a->inode.size[i];
7680def2e27SBarry Smith       cnt2          = 1;
7690def2e27SBarry Smith       for (j=1; j<nz; j++) {
7700def2e27SBarry Smith         if (cols[j] != cols[j-1]+1) {
7710def2e27SBarry Smith 	  CHKMEMQ;
7720def2e27SBarry Smith           counts[2*(cnt++)+1] = cnt2;
7730def2e27SBarry Smith           counts[2*cnt]       = cols[j];
7740def2e27SBarry Smith 	  CHKMEMQ;
7750def2e27SBarry Smith           cnt2                = 1;
7760def2e27SBarry Smith         } else cnt2++;
7770def2e27SBarry Smith       }
7780def2e27SBarry Smith 	  CHKMEMQ;
7790def2e27SBarry Smith       counts[2*(cnt++)+1] = cnt2;
7800def2e27SBarry Smith 	  CHKMEMQ;
7810def2e27SBarry Smith       row += a->inode.size[i];
7820def2e27SBarry Smith     }
7830def2e27SBarry Smith     ierr = PetscIntView(2*cnt,counts,0);
7840def2e27SBarry Smith   }
78538702af4SBarry Smith   PetscFunctionReturn(0);
78638702af4SBarry Smith }
78738702af4SBarry Smith 
78838702af4SBarry Smith #undef __FUNCT__
7894a2ae208SSatish Balay #define __FUNCT__ "MatAssemblyEnd_SeqSBAIJ"
790dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqSBAIJ(Mat A,MatAssemblyType mode)
79149b5e25fSSatish Balay {
79249b5e25fSSatish Balay   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
7936849ba73SBarry Smith   PetscErrorCode ierr;
79413f74950SBarry Smith   PetscInt       fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
795d0f46423SBarry Smith   PetscInt       m = A->rmap->N,*ip,N,*ailen = a->ilen;
79613f74950SBarry Smith   PetscInt       mbs = a->mbs,bs2 = a->bs2,rmax = 0;
79749b5e25fSSatish Balay   MatScalar      *aa = a->a,*ap;
79849b5e25fSSatish Balay 
79949b5e25fSSatish Balay   PetscFunctionBegin;
80049b5e25fSSatish Balay   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
80149b5e25fSSatish Balay 
80249b5e25fSSatish Balay   if (m) rmax = ailen[0];
80349b5e25fSSatish Balay   for (i=1; i<mbs; i++) {
80449b5e25fSSatish Balay     /* move each row back by the amount of empty slots (fshift) before it*/
80549b5e25fSSatish Balay     fshift += imax[i-1] - ailen[i-1];
80649b5e25fSSatish Balay      rmax   = PetscMax(rmax,ailen[i]);
80749b5e25fSSatish Balay      if (fshift) {
80849b5e25fSSatish Balay        ip = aj + ai[i]; ap = aa + bs2*ai[i];
80949b5e25fSSatish Balay        N = ailen[i];
81049b5e25fSSatish Balay        for (j=0; j<N; j++) {
81149b5e25fSSatish Balay          ip[j-fshift] = ip[j];
81249b5e25fSSatish Balay          ierr = PetscMemcpy(ap+(j-fshift)*bs2,ap+j*bs2,bs2*sizeof(MatScalar));CHKERRQ(ierr);
81349b5e25fSSatish Balay        }
81449b5e25fSSatish Balay      }
81549b5e25fSSatish Balay      ai[i] = ai[i-1] + ailen[i-1];
81649b5e25fSSatish Balay   }
81749b5e25fSSatish Balay   if (mbs) {
81849b5e25fSSatish Balay     fshift += imax[mbs-1] - ailen[mbs-1];
81949b5e25fSSatish Balay      ai[mbs] = ai[mbs-1] + ailen[mbs-1];
82049b5e25fSSatish Balay   }
82149b5e25fSSatish Balay   /* reset ilen and imax for each row */
82249b5e25fSSatish Balay   for (i=0; i<mbs; i++) {
82349b5e25fSSatish Balay     ailen[i] = imax[i] = ai[i+1] - ai[i];
82449b5e25fSSatish Balay   }
8256c6c5352SBarry Smith   a->nz = ai[mbs];
82649b5e25fSSatish Balay 
827b424e231SHong Zhang   /* diagonals may have moved, reset it */
828b424e231SHong Zhang   if (a->diag) {
82913f74950SBarry Smith     ierr = PetscMemcpy(a->diag,ai,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr);
83049b5e25fSSatish Balay   }
83128b2fa4aSMatthew Knepley   if (fshift && a->nounused == -1) {
83228b2fa4aSMatthew Knepley     SETERRQ4(PETSC_ERR_PLIB, "Unused space detected in matrix: %D X %D block size %D, %D unneeded", m, A->cmap->n, A->rmap->bs, fshift*bs2);
83328b2fa4aSMatthew Knepley   }
834d0f46423SBarry Smith   ierr = PetscInfo5(A,"Matrix size: %D X %D, block size %D; storage space: %D unneeded, %D used\n",m,A->rmap->N,A->rmap->bs,fshift*bs2,a->nz*bs2);CHKERRQ(ierr);
835ae15b995SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues is %D\n",a->reallocs);CHKERRQ(ierr);
836ae15b995SBarry Smith   ierr = PetscInfo1(A,"Most nonzeros blocks in any row is %D\n",rmax);CHKERRQ(ierr);
83749b5e25fSSatish Balay   a->reallocs          = 0;
83849b5e25fSSatish Balay   A->info.nz_unneeded  = (PetscReal)fshift*bs2;
839061b2667SBarry Smith   a->idiagvalid = PETSC_FALSE;
84038702af4SBarry Smith 
84138702af4SBarry Smith   if (A->cmap->n < 65536 && A->cmap->bs == 1) {
84238702af4SBarry Smith     if (!a->jshort) {
84338702af4SBarry Smith       ierr = PetscMalloc(a->i[A->rmap->n]*sizeof(unsigned short),&a->jshort);CHKERRQ(ierr);
84438702af4SBarry Smith       for (i=0; i<a->i[A->rmap->n]; i++) a->jshort[i] = a->j[i];
84538702af4SBarry Smith       A->ops->mult  = MatMult_SeqSBAIJ_1_ushort;
84670dcbbb9SBarry Smith       A->ops->relax = MatRelax_SeqSBAIJ_ushort;
847*4da8f245SBarry Smith       a->free_jshort = PETSC_TRUE;
84838702af4SBarry Smith     }
84938702af4SBarry Smith   }
85049b5e25fSSatish Balay   PetscFunctionReturn(0);
85149b5e25fSSatish Balay }
85249b5e25fSSatish Balay 
85349b5e25fSSatish Balay /*
85449b5e25fSSatish Balay    This function returns an array of flags which indicate the locations of contiguous
85549b5e25fSSatish Balay    blocks that should be zeroed. for eg: if bs = 3  and is = [0,1,2,3,5,6,7,8,9]
85649b5e25fSSatish Balay    then the resulting sizes = [3,1,1,3,1] correspondig to sets [(0,1,2),(3),(5),(6,7,8),(9)]
85749b5e25fSSatish Balay    Assume: sizes should be long enough to hold all the values.
85849b5e25fSSatish Balay */
8594a2ae208SSatish Balay #undef __FUNCT__
8604a2ae208SSatish Balay #define __FUNCT__ "MatZeroRows_SeqSBAIJ_Check_Blocks"
86113f74950SBarry Smith PetscErrorCode MatZeroRows_SeqSBAIJ_Check_Blocks(PetscInt idx[],PetscInt n,PetscInt bs,PetscInt sizes[], PetscInt *bs_max)
86249b5e25fSSatish Balay {
86313f74950SBarry Smith   PetscInt   i,j,k,row;
86449b5e25fSSatish Balay   PetscTruth flg;
86549b5e25fSSatish Balay 
86649b5e25fSSatish Balay   PetscFunctionBegin;
86749b5e25fSSatish Balay    for (i=0,j=0; i<n; j++) {
86849b5e25fSSatish Balay      row = idx[i];
86949b5e25fSSatish Balay      if (row%bs!=0) { /* Not the begining of a block */
87049b5e25fSSatish Balay        sizes[j] = 1;
87149b5e25fSSatish Balay        i++;
87249b5e25fSSatish Balay      } else if (i+bs > n) { /* Beginning of a block, but complete block doesn't exist (at idx end) */
87349b5e25fSSatish Balay        sizes[j] = 1;         /* Also makes sure atleast 'bs' values exist for next else */
87449b5e25fSSatish Balay        i++;
87549b5e25fSSatish Balay      } else { /* Begining of the block, so check if the complete block exists */
87649b5e25fSSatish Balay        flg = PETSC_TRUE;
87749b5e25fSSatish Balay        for (k=1; k<bs; k++) {
87849b5e25fSSatish Balay          if (row+k != idx[i+k]) { /* break in the block */
87949b5e25fSSatish Balay            flg = PETSC_FALSE;
88049b5e25fSSatish Balay            break;
88149b5e25fSSatish Balay          }
88249b5e25fSSatish Balay        }
883abc0a331SBarry Smith        if (flg) { /* No break in the bs */
88449b5e25fSSatish Balay          sizes[j] = bs;
88549b5e25fSSatish Balay          i+= bs;
88649b5e25fSSatish Balay        } else {
88749b5e25fSSatish Balay          sizes[j] = 1;
88849b5e25fSSatish Balay          i++;
88949b5e25fSSatish Balay        }
89049b5e25fSSatish Balay      }
89149b5e25fSSatish Balay    }
89249b5e25fSSatish Balay    *bs_max = j;
89349b5e25fSSatish Balay    PetscFunctionReturn(0);
89449b5e25fSSatish Balay }
89549b5e25fSSatish Balay 
89649b5e25fSSatish Balay 
89749b5e25fSSatish Balay /* Only add/insert a(i,j) with i<=j (blocks).
89849b5e25fSSatish Balay    Any a(i,j) with i>j input by user is ingored.
89949b5e25fSSatish Balay */
90049b5e25fSSatish Balay 
9014a2ae208SSatish Balay #undef __FUNCT__
9024a2ae208SSatish Balay #define __FUNCT__ "MatSetValues_SeqSBAIJ"
90313f74950SBarry Smith PetscErrorCode MatSetValues_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
90449b5e25fSSatish Balay {
90549b5e25fSSatish Balay   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
9066849ba73SBarry Smith   PetscErrorCode ierr;
907e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,lastcol = -1;
90813f74950SBarry Smith   PetscInt       *imax=a->imax,*ai=a->i,*ailen=a->ilen,roworiented=a->roworiented;
909d0f46423SBarry Smith   PetscInt       *aj=a->j,nonew=a->nonew,bs=A->rmap->bs,brow,bcol;
91013f74950SBarry Smith   PetscInt       ridx,cidx,bs2=a->bs2;
91149b5e25fSSatish Balay   MatScalar      *ap,value,*aa=a->a,*bap;
91249b5e25fSSatish Balay 
91349b5e25fSSatish Balay   PetscFunctionBegin;
91449b5e25fSSatish Balay   for (k=0; k<m; k++) { /* loop over added rows */
91549b5e25fSSatish Balay     row  = im[k];       /* row number */
91649b5e25fSSatish Balay     brow = row/bs;      /* block row number */
91749b5e25fSSatish Balay     if (row < 0) continue;
9182515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
919d0f46423SBarry Smith     if (row >= A->rmap->N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->N-1);
92049b5e25fSSatish Balay #endif
92149b5e25fSSatish Balay     rp   = aj + ai[brow]; /*ptr to beginning of column value of the row block*/
92249b5e25fSSatish Balay     ap   = aa + bs2*ai[brow]; /*ptr to beginning of element value of the row block*/
92349b5e25fSSatish Balay     rmax = imax[brow];  /* maximum space allocated for this row */
92449b5e25fSSatish Balay     nrow = ailen[brow]; /* actual length of this row */
92549b5e25fSSatish Balay     low  = 0;
92649b5e25fSSatish Balay 
92749b5e25fSSatish Balay     for (l=0; l<n; l++) { /* loop over added columns */
92849b5e25fSSatish Balay       if (in[l] < 0) continue;
9292515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
930d0f46423SBarry Smith       if (in[l] >= A->rmap->N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->rmap->N-1);
93149b5e25fSSatish Balay #endif
93249b5e25fSSatish Balay       col = in[l];
93349b5e25fSSatish Balay       bcol = col/bs;              /* block col number */
93449b5e25fSSatish Balay 
935941593c8SHong Zhang       if (brow > bcol) {
936941593c8SHong Zhang         if (a->ignore_ltriangular){
937941593c8SHong Zhang           continue; /* ignore lower triangular values */
938941593c8SHong Zhang         } else {
9394e0d8c25SBarry Smith           SETERRQ(PETSC_ERR_USER,"Lower triangular value cannot be set for sbaij format. Ignoring these values, run with -mat_ignore_lower_triangular or call MatSetOption(mat,MAT_IGNORE_LOWER_TRIANGULAR,PETSC_TRUE)");
940941593c8SHong Zhang         }
941941593c8SHong Zhang       }
942f4989cb3SHong Zhang 
94349b5e25fSSatish Balay       ridx = row % bs; cidx = col % bs; /*row and col index inside the block */
9448549e402SHong Zhang       if ((brow==bcol && ridx<=cidx) || (brow<bcol)){
94549b5e25fSSatish Balay         /* element value a(k,l) */
94649b5e25fSSatish Balay         if (roworiented) {
94749b5e25fSSatish Balay           value = v[l + k*n];
94849b5e25fSSatish Balay         } else {
94949b5e25fSSatish Balay           value = v[k + l*m];
95049b5e25fSSatish Balay         }
95149b5e25fSSatish Balay 
95249b5e25fSSatish Balay         /* move pointer bap to a(k,l) quickly and add/insert value */
9537cd84e04SBarry Smith         if (col <= lastcol) low = 0; high = nrow;
954e2ee6c50SBarry Smith         lastcol = col;
95549b5e25fSSatish Balay         while (high-low > 7) {
95649b5e25fSSatish Balay           t = (low+high)/2;
95749b5e25fSSatish Balay           if (rp[t] > bcol) high = t;
95849b5e25fSSatish Balay           else              low  = t;
95949b5e25fSSatish Balay         }
96049b5e25fSSatish Balay         for (i=low; i<high; i++) {
96149b5e25fSSatish Balay           if (rp[i] > bcol) break;
96249b5e25fSSatish Balay           if (rp[i] == bcol) {
96349b5e25fSSatish Balay             bap  = ap +  bs2*i + bs*cidx + ridx;
96449b5e25fSSatish Balay             if (is == ADD_VALUES) *bap += value;
96549b5e25fSSatish Balay             else                  *bap  = value;
9668549e402SHong Zhang             /* for diag block, add/insert its symmetric element a(cidx,ridx) */
9678549e402SHong Zhang             if (brow == bcol && ridx < cidx){
9688549e402SHong Zhang               bap  = ap +  bs2*i + bs*ridx + cidx;
9698549e402SHong Zhang               if (is == ADD_VALUES) *bap += value;
9708549e402SHong Zhang               else                  *bap  = value;
9718549e402SHong Zhang             }
97249b5e25fSSatish Balay             goto noinsert1;
97349b5e25fSSatish Balay           }
97449b5e25fSSatish Balay         }
97549b5e25fSSatish Balay 
97649b5e25fSSatish Balay         if (nonew == 1) goto noinsert1;
977085a36d4SBarry Smith         if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col);
978421e10b8SBarry Smith         MatSeqXAIJReallocateAIJ(A,a->mbs,bs2,nrow,brow,bcol,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
97949b5e25fSSatish Balay 
980c03d1d03SSatish Balay         N = nrow++ - 1; high++;
98149b5e25fSSatish Balay         /* shift up all the later entries in this row */
98249b5e25fSSatish Balay         for (ii=N; ii>=i; ii--) {
98349b5e25fSSatish Balay           rp[ii+1] = rp[ii];
98449b5e25fSSatish Balay           ierr     = PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));CHKERRQ(ierr);
98549b5e25fSSatish Balay         }
98649b5e25fSSatish Balay         if (N>=i) {
98749b5e25fSSatish Balay           ierr = PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));CHKERRQ(ierr);
98849b5e25fSSatish Balay         }
98949b5e25fSSatish Balay         rp[i]                      = bcol;
99049b5e25fSSatish Balay         ap[bs2*i + bs*cidx + ridx] = value;
99149b5e25fSSatish Balay       noinsert1:;
99249b5e25fSSatish Balay         low = i;
9938549e402SHong Zhang       }
99449b5e25fSSatish Balay     }   /* end of loop over added columns */
99549b5e25fSSatish Balay     ailen[brow] = nrow;
99649b5e25fSSatish Balay   }   /* end of loop over added rows */
99749b5e25fSSatish Balay   PetscFunctionReturn(0);
99849b5e25fSSatish Balay }
99949b5e25fSSatish Balay 
10004a2ae208SSatish Balay #undef __FUNCT__
10014d101231SSatish Balay #define __FUNCT__ "MatICCFactor_SeqSBAIJ"
10020481f469SBarry Smith PetscErrorCode MatICCFactor_SeqSBAIJ(Mat inA,IS row,const MatFactorInfo *info)
100349b5e25fSSatish Balay {
10044ccecd49SHong Zhang   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)inA->data;
100549b5e25fSSatish Balay   Mat            outA;
1006dfbe8321SBarry Smith   PetscErrorCode ierr;
1007c84f5b01SHong Zhang   PetscTruth     row_identity;
100849b5e25fSSatish Balay 
100949b5e25fSSatish Balay   PetscFunctionBegin;
1010c84f5b01SHong Zhang   if (info->levels != 0) SETERRQ(PETSC_ERR_SUP,"Only levels=0 is supported for in-place icc");
1011c84f5b01SHong Zhang   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
1012c84f5b01SHong Zhang   if (!row_identity) SETERRQ(PETSC_ERR_SUP,"Matrix reordering is not supported");
1013d0f46423SBarry Smith   if (inA->rmap->bs != 1) SETERRQ1(PETSC_ERR_SUP,"Matrix block size %D is not supported",inA->rmap->bs); /* Need to replace MatCholeskyFactorSymbolic_SeqSBAIJ_MSR()! */
1014c84f5b01SHong Zhang 
101549b5e25fSSatish Balay   outA        = inA;
1016c078aec8SLisandro Dalcin   inA->factor = MAT_FACTOR_ICC;
101749b5e25fSSatish Balay 
10181a3463dfSHong Zhang   ierr = MatMarkDiagonal_SeqSBAIJ(inA);CHKERRQ(ierr);
1019db4efbfdSBarry Smith   ierr = MatSeqSBAIJSetNumericFactorization(inA,row_identity);CHKERRQ(ierr);
102049b5e25fSSatish Balay 
1021c3122656SLisandro Dalcin   ierr   = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
1022c3122656SLisandro Dalcin   if (a->row) { ierr = ISDestroy(a->row);CHKERRQ(ierr); }
1023c84f5b01SHong Zhang   a->row = row;
1024c3122656SLisandro Dalcin   ierr   = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
1025c3122656SLisandro Dalcin   if (a->col) { ierr = ISDestroy(a->col);CHKERRQ(ierr); }
1026c84f5b01SHong Zhang   a->col = row;
1027c84f5b01SHong Zhang 
1028c84f5b01SHong Zhang   /* Create the invert permutation so that it can be used in MatCholeskyFactorNumeric() */
1029c84f5b01SHong Zhang   if (a->icol) {ierr = ISInvertPermutation(row,PETSC_DECIDE, &a->icol);CHKERRQ(ierr);}
103052e6d16bSBarry Smith   ierr = PetscLogObjectParent(inA,a->icol);CHKERRQ(ierr);
103149b5e25fSSatish Balay 
103249b5e25fSSatish Balay   if (!a->solve_work) {
1033d0f46423SBarry Smith     ierr = PetscMalloc((inA->rmap->N+inA->rmap->bs)*sizeof(PetscScalar),&a->solve_work);CHKERRQ(ierr);
1034d0f46423SBarry Smith     ierr = PetscLogObjectMemory(inA,(inA->rmap->N+inA->rmap->bs)*sizeof(PetscScalar));CHKERRQ(ierr);
103549b5e25fSSatish Balay   }
103649b5e25fSSatish Balay 
1037719d5645SBarry Smith   ierr = MatCholeskyFactorNumeric(outA,inA,info);CHKERRQ(ierr);
103849b5e25fSSatish Balay   PetscFunctionReturn(0);
103949b5e25fSSatish Balay }
1040950f1e5bSHong Zhang 
104149b5e25fSSatish Balay EXTERN_C_BEGIN
10424a2ae208SSatish Balay #undef __FUNCT__
10434a2ae208SSatish Balay #define __FUNCT__ "MatSeqSBAIJSetColumnIndices_SeqSBAIJ"
1044be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat,PetscInt *indices)
104549b5e25fSSatish Balay {
1046045c9aa0SHong Zhang   Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)mat->data;
104713f74950SBarry Smith   PetscInt     i,nz,n;
104849b5e25fSSatish Balay 
104949b5e25fSSatish Balay   PetscFunctionBegin;
10506c6c5352SBarry Smith   nz = baij->maxnz;
1051d0f46423SBarry Smith   n  = mat->cmap->n;
105249b5e25fSSatish Balay   for (i=0; i<nz; i++) {
105349b5e25fSSatish Balay     baij->j[i] = indices[i];
105449b5e25fSSatish Balay   }
10556c6c5352SBarry Smith    baij->nz = nz;
105649b5e25fSSatish Balay    for (i=0; i<n; i++) {
105749b5e25fSSatish Balay      baij->ilen[i] = baij->imax[i];
105849b5e25fSSatish Balay    }
105949b5e25fSSatish Balay    PetscFunctionReturn(0);
106049b5e25fSSatish Balay }
106149b5e25fSSatish Balay EXTERN_C_END
106249b5e25fSSatish Balay 
10634a2ae208SSatish Balay #undef __FUNCT__
10644a2ae208SSatish Balay #define __FUNCT__ "MatSeqSBAIJSetColumnIndices"
106549b5e25fSSatish Balay /*@
106619585528SSatish Balay   MatSeqSBAIJSetColumnIndices - Set the column indices for all the rows
106749b5e25fSSatish Balay   in the matrix.
106849b5e25fSSatish Balay 
106949b5e25fSSatish Balay   Input Parameters:
107019585528SSatish Balay   +  mat     - the SeqSBAIJ matrix
107149b5e25fSSatish Balay   -  indices - the column indices
107249b5e25fSSatish Balay 
107349b5e25fSSatish Balay   Level: advanced
107449b5e25fSSatish Balay 
107549b5e25fSSatish Balay   Notes:
107649b5e25fSSatish Balay   This can be called if you have precomputed the nonzero structure of the
107749b5e25fSSatish Balay   matrix and want to provide it to the matrix object to improve the performance
107849b5e25fSSatish Balay   of the MatSetValues() operation.
107949b5e25fSSatish Balay 
108049b5e25fSSatish Balay   You MUST have set the correct numbers of nonzeros per row in the call to
1081d1be2dadSMatthew Knepley   MatCreateSeqSBAIJ(), and the columns indices MUST be sorted.
108249b5e25fSSatish Balay 
1083ab9f2c04SSatish Balay   MUST be called before any calls to MatSetValues()
108449b5e25fSSatish Balay 
1085ab9f2c04SSatish Balay   .seealso: MatCreateSeqSBAIJ
108649b5e25fSSatish Balay @*/
1087be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetColumnIndices(Mat mat,PetscInt *indices)
108849b5e25fSSatish Balay {
108913f74950SBarry Smith   PetscErrorCode ierr,(*f)(Mat,PetscInt *);
109049b5e25fSSatish Balay 
109149b5e25fSSatish Balay   PetscFunctionBegin;
10924482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
10934482741eSBarry Smith   PetscValidPointer(indices,2);
1094c134de8dSSatish Balay   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqSBAIJSetColumnIndices_C",(void (**)(void))&f);CHKERRQ(ierr);
109549b5e25fSSatish Balay   if (f) {
109649b5e25fSSatish Balay     ierr = (*f)(mat,indices);CHKERRQ(ierr);
109749b5e25fSSatish Balay   } else {
1098e005ede5SBarry Smith     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to set column indices");
109949b5e25fSSatish Balay   }
110049b5e25fSSatish Balay   PetscFunctionReturn(0);
110149b5e25fSSatish Balay }
110249b5e25fSSatish Balay 
11034a2ae208SSatish Balay #undef __FUNCT__
11043c896bc6SHong Zhang #define __FUNCT__ "MatCopy_SeqSBAIJ"
11053c896bc6SHong Zhang PetscErrorCode MatCopy_SeqSBAIJ(Mat A,Mat B,MatStructure str)
11063c896bc6SHong Zhang {
11073c896bc6SHong Zhang   PetscErrorCode ierr;
11083c896bc6SHong Zhang 
11093c896bc6SHong Zhang   PetscFunctionBegin;
11103c896bc6SHong Zhang   /* If the two matrices have the same copy implementation, use fast copy. */
11113c896bc6SHong Zhang   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
11123c896bc6SHong Zhang     Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
11133c896bc6SHong Zhang     Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ*)B->data;
11143c896bc6SHong Zhang 
1115d0f46423SBarry Smith     if (a->i[A->rmap->N] != b->i[B->rmap->N]) {
11163c896bc6SHong Zhang       SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different");
11173c896bc6SHong Zhang     }
1118d0f46423SBarry Smith     ierr = PetscMemcpy(b->a,a->a,(a->i[A->rmap->N])*sizeof(PetscScalar));CHKERRQ(ierr);
11193c896bc6SHong Zhang   } else {
1120f5edf698SHong Zhang     ierr = MatGetRowUpperTriangular(A);CHKERRQ(ierr);
11213c896bc6SHong Zhang     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
1122f5edf698SHong Zhang     ierr = MatRestoreRowUpperTriangular(A);CHKERRQ(ierr);
11233c896bc6SHong Zhang   }
11243c896bc6SHong Zhang   PetscFunctionReturn(0);
11253c896bc6SHong Zhang }
11263c896bc6SHong Zhang 
11273c896bc6SHong Zhang #undef __FUNCT__
11284a2ae208SSatish Balay #define __FUNCT__ "MatSetUpPreallocation_SeqSBAIJ"
1129dfbe8321SBarry Smith PetscErrorCode MatSetUpPreallocation_SeqSBAIJ(Mat A)
1130273d9f13SBarry Smith {
1131dfbe8321SBarry Smith   PetscErrorCode ierr;
1132273d9f13SBarry Smith 
1133273d9f13SBarry Smith   PetscFunctionBegin;
1134db4efbfdSBarry Smith   ierr =  MatSeqSBAIJSetPreallocation_SeqSBAIJ(A,-PetscMax(A->rmap->bs,1),PETSC_DEFAULT,0);CHKERRQ(ierr);
1135273d9f13SBarry Smith   PetscFunctionReturn(0);
1136273d9f13SBarry Smith }
1137273d9f13SBarry Smith 
1138a6ece127SHong Zhang #undef __FUNCT__
1139a6ece127SHong Zhang #define __FUNCT__ "MatGetArray_SeqSBAIJ"
1140dfbe8321SBarry Smith PetscErrorCode MatGetArray_SeqSBAIJ(Mat A,PetscScalar *array[])
1141a6ece127SHong Zhang {
1142a6ece127SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
1143a6ece127SHong Zhang   PetscFunctionBegin;
1144a6ece127SHong Zhang   *array = a->a;
1145a6ece127SHong Zhang   PetscFunctionReturn(0);
1146a6ece127SHong Zhang }
1147a6ece127SHong Zhang 
1148a6ece127SHong Zhang #undef __FUNCT__
1149a6ece127SHong Zhang #define __FUNCT__ "MatRestoreArray_SeqSBAIJ"
1150dfbe8321SBarry Smith PetscErrorCode MatRestoreArray_SeqSBAIJ(Mat A,PetscScalar *array[])
1151a6ece127SHong Zhang {
1152a6ece127SHong Zhang   PetscFunctionBegin;
1153a6ece127SHong Zhang   PetscFunctionReturn(0);
1154a6ece127SHong Zhang  }
1155a6ece127SHong Zhang 
115642ee4b1aSHong Zhang #include "petscblaslapack.h"
115742ee4b1aSHong Zhang #undef __FUNCT__
115842ee4b1aSHong Zhang #define __FUNCT__ "MatAXPY_SeqSBAIJ"
1159f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqSBAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
116042ee4b1aSHong Zhang {
116142ee4b1aSHong Zhang   Mat_SeqSBAIJ   *x=(Mat_SeqSBAIJ *)X->data, *y=(Mat_SeqSBAIJ *)Y->data;
1162dfbe8321SBarry Smith   PetscErrorCode ierr;
1163d0f46423SBarry Smith   PetscInt       i,bs=Y->rmap->bs,bs2,j;
11640805154bSBarry Smith   PetscBLASInt   one = 1,bnz = PetscBLASIntCast(x->nz);
116542ee4b1aSHong Zhang 
116642ee4b1aSHong Zhang   PetscFunctionBegin;
116742ee4b1aSHong Zhang   if (str == SAME_NONZERO_PATTERN) {
1168f4df32b1SMatthew Knepley     PetscScalar alpha = a;
1169f4df32b1SMatthew Knepley     BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one);
1170c537a176SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
1171c4319e64SHong Zhang     if (y->xtoy && y->XtoY != X) {
1172c4319e64SHong Zhang       ierr = PetscFree(y->xtoy);CHKERRQ(ierr);
1173c4319e64SHong Zhang       ierr = MatDestroy(y->XtoY);CHKERRQ(ierr);
1174c537a176SHong Zhang     }
1175c4319e64SHong Zhang     if (!y->xtoy) { /* get xtoy */
1176c4319e64SHong Zhang       ierr = MatAXPYGetxtoy_Private(x->mbs,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);CHKERRQ(ierr);
1177c4319e64SHong Zhang       y->XtoY = X;
1178c537a176SHong Zhang     }
1179c4319e64SHong Zhang     bs2 = bs*bs;
11806c6c5352SBarry Smith     for (i=0; i<x->nz; i++) {
1181c4319e64SHong Zhang       j = 0;
1182c4319e64SHong Zhang       while (j < bs2){
1183f4df32b1SMatthew Knepley         y->a[bs2*y->xtoy[i]+j] += a*(x->a[bs2*i+j]);
1184c4319e64SHong Zhang         j++;
1185c537a176SHong Zhang       }
1186c4319e64SHong Zhang     }
11871e2582c4SBarry Smith     ierr = PetscInfo3(Y,"ratio of nnz_s(X)/nnz_s(Y): %D/%D = %G\n",bs2*x->nz,bs2*y->nz,(PetscReal)(bs2*x->nz)/(bs2*y->nz));CHKERRQ(ierr);
118842ee4b1aSHong Zhang   } else {
1189f5edf698SHong Zhang     ierr = MatGetRowUpperTriangular(X);CHKERRQ(ierr);
1190f4df32b1SMatthew Knepley     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
1191f5edf698SHong Zhang     ierr = MatRestoreRowUpperTriangular(X);CHKERRQ(ierr);
119242ee4b1aSHong Zhang   }
119342ee4b1aSHong Zhang   PetscFunctionReturn(0);
119442ee4b1aSHong Zhang }
119542ee4b1aSHong Zhang 
1196efcf0fc3SBarry Smith #undef __FUNCT__
1197efcf0fc3SBarry Smith #define __FUNCT__ "MatIsSymmetric_SeqSBAIJ"
1198dfbe8321SBarry Smith PetscErrorCode MatIsSymmetric_SeqSBAIJ(Mat A,PetscReal tol,PetscTruth *flg)
1199efcf0fc3SBarry Smith {
1200efcf0fc3SBarry Smith   PetscFunctionBegin;
1201efcf0fc3SBarry Smith   *flg = PETSC_TRUE;
1202efcf0fc3SBarry Smith   PetscFunctionReturn(0);
1203efcf0fc3SBarry Smith }
1204efcf0fc3SBarry Smith 
1205efcf0fc3SBarry Smith #undef __FUNCT__
1206efcf0fc3SBarry Smith #define __FUNCT__ "MatIsStructurallySymmetric_SeqSBAIJ"
1207dfbe8321SBarry Smith PetscErrorCode MatIsStructurallySymmetric_SeqSBAIJ(Mat A,PetscTruth *flg)
1208efcf0fc3SBarry Smith {
1209efcf0fc3SBarry Smith    PetscFunctionBegin;
1210efcf0fc3SBarry Smith    *flg = PETSC_TRUE;
1211efcf0fc3SBarry Smith    PetscFunctionReturn(0);
1212efcf0fc3SBarry Smith }
1213efcf0fc3SBarry Smith 
1214efcf0fc3SBarry Smith #undef __FUNCT__
1215efcf0fc3SBarry Smith #define __FUNCT__ "MatIsHermitian_SeqSBAIJ"
1216ab5e4463SMatthew Knepley PetscErrorCode MatIsHermitian_SeqSBAIJ(Mat A,PetscReal tol,PetscTruth *flg)
1217efcf0fc3SBarry Smith  {
1218efcf0fc3SBarry Smith    PetscFunctionBegin;
1219efcf0fc3SBarry Smith    *flg = PETSC_FALSE;
1220efcf0fc3SBarry Smith    PetscFunctionReturn(0);
1221efcf0fc3SBarry Smith  }
1222efcf0fc3SBarry Smith 
122399cafbc1SBarry Smith #undef __FUNCT__
122499cafbc1SBarry Smith #define __FUNCT__ "MatRealPart_SeqSBAIJ"
122599cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqSBAIJ(Mat A)
122699cafbc1SBarry Smith {
122799cafbc1SBarry Smith   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
122899cafbc1SBarry Smith   PetscInt       i,nz = a->bs2*a->i[a->mbs];
1229dd6ea824SBarry Smith   MatScalar      *aa = a->a;
123099cafbc1SBarry Smith 
123199cafbc1SBarry Smith   PetscFunctionBegin;
123299cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
123399cafbc1SBarry Smith   PetscFunctionReturn(0);
123499cafbc1SBarry Smith }
123599cafbc1SBarry Smith 
123699cafbc1SBarry Smith #undef __FUNCT__
123799cafbc1SBarry Smith #define __FUNCT__ "MatImaginaryPart_SeqSBAIJ"
123899cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqSBAIJ(Mat A)
123999cafbc1SBarry Smith {
124099cafbc1SBarry Smith   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
124199cafbc1SBarry Smith   PetscInt       i,nz = a->bs2*a->i[a->mbs];
1242dd6ea824SBarry Smith   MatScalar      *aa = a->a;
124399cafbc1SBarry Smith 
124499cafbc1SBarry Smith   PetscFunctionBegin;
124599cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
124699cafbc1SBarry Smith   PetscFunctionReturn(0);
124799cafbc1SBarry Smith }
124899cafbc1SBarry Smith 
124949b5e25fSSatish Balay /* -------------------------------------------------------------------*/
125049b5e25fSSatish Balay static struct _MatOps MatOps_Values = {MatSetValues_SeqSBAIJ,
125149b5e25fSSatish Balay        MatGetRow_SeqSBAIJ,
125249b5e25fSSatish Balay        MatRestoreRow_SeqSBAIJ,
125349b5e25fSSatish Balay        MatMult_SeqSBAIJ_N,
125497304618SKris Buschelman /* 4*/ MatMultAdd_SeqSBAIJ_N,
1255431c96f7SBarry Smith        MatMult_SeqSBAIJ_N,       /* transpose versions are same as non-transpose versions */
1256e005ede5SBarry Smith        MatMultAdd_SeqSBAIJ_N,
1257db4efbfdSBarry Smith        0,
125849b5e25fSSatish Balay        0,
125949b5e25fSSatish Balay        0,
126097304618SKris Buschelman /*10*/ 0,
126149b5e25fSSatish Balay        0,
1262c078aec8SLisandro Dalcin        MatCholeskyFactor_SeqSBAIJ,
1263d06b337dSHong Zhang        MatRelax_SeqSBAIJ,
126449b5e25fSSatish Balay        MatTranspose_SeqSBAIJ,
126597304618SKris Buschelman /*15*/ MatGetInfo_SeqSBAIJ,
126649b5e25fSSatish Balay        MatEqual_SeqSBAIJ,
126749b5e25fSSatish Balay        MatGetDiagonal_SeqSBAIJ,
126849b5e25fSSatish Balay        MatDiagonalScale_SeqSBAIJ,
126949b5e25fSSatish Balay        MatNorm_SeqSBAIJ,
127097304618SKris Buschelman /*20*/ 0,
127149b5e25fSSatish Balay        MatAssemblyEnd_SeqSBAIJ,
127249b5e25fSSatish Balay        MatSetOption_SeqSBAIJ,
127349b5e25fSSatish Balay        MatZeroEntries_SeqSBAIJ,
1274d519adbfSMatthew Knepley /*24*/ 0,
127549b5e25fSSatish Balay        0,
127649b5e25fSSatish Balay        0,
1277db4efbfdSBarry Smith        0,
1278db4efbfdSBarry Smith        0,
1279d519adbfSMatthew Knepley /*29*/ MatSetUpPreallocation_SeqSBAIJ,
1280c464158bSHong Zhang        0,
1281db4efbfdSBarry Smith        0,
1282a6ece127SHong Zhang        MatGetArray_SeqSBAIJ,
1283a6ece127SHong Zhang        MatRestoreArray_SeqSBAIJ,
1284d519adbfSMatthew Knepley /*34*/ MatDuplicate_SeqSBAIJ,
1285719d5645SBarry Smith        0,
1286719d5645SBarry Smith        0,
128749b5e25fSSatish Balay        0,
1288c84f5b01SHong Zhang        MatICCFactor_SeqSBAIJ,
1289d519adbfSMatthew Knepley /*39*/ MatAXPY_SeqSBAIJ,
129049b5e25fSSatish Balay        MatGetSubMatrices_SeqSBAIJ,
129149b5e25fSSatish Balay        MatIncreaseOverlap_SeqSBAIJ,
129249b5e25fSSatish Balay        MatGetValues_SeqSBAIJ,
12933c896bc6SHong Zhang        MatCopy_SeqSBAIJ,
1294d519adbfSMatthew Knepley /*44*/ 0,
129549b5e25fSSatish Balay        MatScale_SeqSBAIJ,
129649b5e25fSSatish Balay        0,
129749b5e25fSSatish Balay        0,
129849b5e25fSSatish Balay        0,
1299d519adbfSMatthew Knepley /*49*/ 0,
130049b5e25fSSatish Balay        MatGetRowIJ_SeqSBAIJ,
130149b5e25fSSatish Balay        MatRestoreRowIJ_SeqSBAIJ,
130249b5e25fSSatish Balay        0,
130349b5e25fSSatish Balay        0,
1304d519adbfSMatthew Knepley /*54*/ 0,
130549b5e25fSSatish Balay        0,
130649b5e25fSSatish Balay        0,
130749b5e25fSSatish Balay        0,
130849b5e25fSSatish Balay        MatSetValuesBlocked_SeqSBAIJ,
1309d519adbfSMatthew Knepley /*59*/ MatGetSubMatrix_SeqSBAIJ,
131049b5e25fSSatish Balay        0,
131149b5e25fSSatish Balay        0,
1312357abbc8SBarry Smith        0,
1313d959ec07SHong Zhang        0,
1314d519adbfSMatthew Knepley /*64*/ 0,
1315d959ec07SHong Zhang        0,
1316d959ec07SHong Zhang        0,
1317d959ec07SHong Zhang        0,
1318d959ec07SHong Zhang        0,
1319d519adbfSMatthew Knepley /*69*/ MatGetRowMaxAbs_SeqSBAIJ,
13203e0d88b5SBarry Smith        0,
13213e0d88b5SBarry Smith        0,
13223e0d88b5SBarry Smith        0,
13233e0d88b5SBarry Smith        0,
1324d519adbfSMatthew Knepley /*74*/ 0,
13253e0d88b5SBarry Smith        0,
13263e0d88b5SBarry Smith        0,
13273e0d88b5SBarry Smith        0,
13283e0d88b5SBarry Smith        0,
1329d519adbfSMatthew Knepley /*79*/ 0,
13303e0d88b5SBarry Smith        0,
13313e0d88b5SBarry Smith        0,
13323e0d88b5SBarry Smith #if !defined(PETSC_USE_COMPLEX)
133397304618SKris Buschelman        MatGetInertia_SeqSBAIJ,
13343e0d88b5SBarry Smith #else
133597304618SKris Buschelman        0,
13363e0d88b5SBarry Smith #endif
1337865e5f61SKris Buschelman        MatLoad_SeqSBAIJ,
1338d519adbfSMatthew Knepley /*84*/ MatIsSymmetric_SeqSBAIJ,
1339865e5f61SKris Buschelman        MatIsHermitian_SeqSBAIJ,
1340efcf0fc3SBarry Smith        MatIsStructurallySymmetric_SeqSBAIJ,
1341865e5f61SKris Buschelman        0,
1342865e5f61SKris Buschelman        0,
1343d519adbfSMatthew Knepley /*89*/ 0,
1344865e5f61SKris Buschelman        0,
1345865e5f61SKris Buschelman        0,
1346865e5f61SKris Buschelman        0,
1347865e5f61SKris Buschelman        0,
1348d519adbfSMatthew Knepley /*94*/ 0,
1349865e5f61SKris Buschelman        0,
1350865e5f61SKris Buschelman        0,
135199cafbc1SBarry Smith        0,
135299cafbc1SBarry Smith        0,
1353d519adbfSMatthew Knepley /*99*/ 0,
135499cafbc1SBarry Smith        0,
135599cafbc1SBarry Smith        0,
135699cafbc1SBarry Smith        0,
135799cafbc1SBarry Smith        0,
1358d519adbfSMatthew Knepley /*104*/0,
135999cafbc1SBarry Smith        MatRealPart_SeqSBAIJ,
1360f5edf698SHong Zhang        MatImaginaryPart_SeqSBAIJ,
1361f5edf698SHong Zhang        MatGetRowUpperTriangular_SeqSBAIJ,
13622af78befSBarry Smith        MatRestoreRowUpperTriangular_SeqSBAIJ,
1363d519adbfSMatthew Knepley /*109*/0,
13642af78befSBarry Smith        0,
13652af78befSBarry Smith        0,
13662af78befSBarry Smith        0,
13672af78befSBarry Smith        MatMissingDiagonal_SeqSBAIJ
136899cafbc1SBarry Smith };
1369be1d678aSKris Buschelman 
137049b5e25fSSatish Balay EXTERN_C_BEGIN
13714a2ae208SSatish Balay #undef __FUNCT__
13724a2ae208SSatish Balay #define __FUNCT__ "MatStoreValues_SeqSBAIJ"
1373be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatStoreValues_SeqSBAIJ(Mat mat)
137449b5e25fSSatish Balay {
13754afc71dfSHong Zhang   Mat_SeqSBAIJ   *aij = (Mat_SeqSBAIJ *)mat->data;
1376d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->N]*mat->rmap->bs*aij->bs2;
1377dfbe8321SBarry Smith   PetscErrorCode ierr;
137849b5e25fSSatish Balay 
137949b5e25fSSatish Balay   PetscFunctionBegin;
138049b5e25fSSatish Balay   if (aij->nonew != 1) {
1381512a5fc5SBarry Smith     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
138249b5e25fSSatish Balay   }
138349b5e25fSSatish Balay 
138449b5e25fSSatish Balay   /* allocate space for values if not already there */
138549b5e25fSSatish Balay   if (!aij->saved_values) {
138687828ca2SBarry Smith     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr);
138749b5e25fSSatish Balay   }
138849b5e25fSSatish Balay 
138949b5e25fSSatish Balay   /* copy values over */
139087828ca2SBarry Smith   ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr);
139149b5e25fSSatish Balay   PetscFunctionReturn(0);
139249b5e25fSSatish Balay }
139349b5e25fSSatish Balay EXTERN_C_END
139449b5e25fSSatish Balay 
139549b5e25fSSatish Balay EXTERN_C_BEGIN
13964a2ae208SSatish Balay #undef __FUNCT__
13974a2ae208SSatish Balay #define __FUNCT__ "MatRetrieveValues_SeqSBAIJ"
1398be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatRetrieveValues_SeqSBAIJ(Mat mat)
139949b5e25fSSatish Balay {
14004afc71dfSHong Zhang   Mat_SeqSBAIJ   *aij = (Mat_SeqSBAIJ *)mat->data;
14016849ba73SBarry Smith   PetscErrorCode ierr;
1402d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->N]*mat->rmap->bs*aij->bs2;
140349b5e25fSSatish Balay 
140449b5e25fSSatish Balay   PetscFunctionBegin;
140549b5e25fSSatish Balay   if (aij->nonew != 1) {
1406512a5fc5SBarry Smith     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
140749b5e25fSSatish Balay   }
140849b5e25fSSatish Balay   if (!aij->saved_values) {
1409e005ede5SBarry Smith     SETERRQ(PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
141049b5e25fSSatish Balay   }
141149b5e25fSSatish Balay 
141249b5e25fSSatish Balay   /* copy values over */
141387828ca2SBarry Smith   ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr);
141449b5e25fSSatish Balay   PetscFunctionReturn(0);
141549b5e25fSSatish Balay }
141649b5e25fSSatish Balay EXTERN_C_END
141749b5e25fSSatish Balay 
14188549e402SHong Zhang EXTERN_C_BEGIN
14194a2ae208SSatish Balay #undef __FUNCT__
1420a23d5eceSKris Buschelman #define __FUNCT__ "MatSeqSBAIJSetPreallocation_SeqSBAIJ"
1421be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B,PetscInt bs,PetscInt nz,PetscInt *nnz)
142249b5e25fSSatish Balay {
1423c464158bSHong Zhang   Mat_SeqSBAIJ   *b = (Mat_SeqSBAIJ*)B->data;
14246849ba73SBarry Smith   PetscErrorCode ierr;
1425db4efbfdSBarry Smith   PetscInt       i,mbs,bs2, newbs = PetscAbs(bs);
142690d69ab7SBarry Smith   PetscTruth     skipallocation = PETSC_FALSE,flg = PETSC_FALSE;
142749b5e25fSSatish Balay 
142849b5e25fSSatish Balay   PetscFunctionBegin;
1429273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
1430db4efbfdSBarry Smith   if (bs < 0) {
1431db4efbfdSBarry Smith     ierr = PetscOptionsBegin(((PetscObject)B)->comm,((PetscObject)B)->prefix,"Options for MPISBAIJ matrix","Mat");CHKERRQ(ierr);
1432db4efbfdSBarry Smith       ierr = PetscOptionsInt("-mat_block_size","Set the blocksize used to store the matrix","MatSeqSBAIJSetPreallocation",newbs,&newbs,PETSC_NULL);CHKERRQ(ierr);
1433db4efbfdSBarry Smith     ierr = PetscOptionsEnd();CHKERRQ(ierr);
1434db4efbfdSBarry Smith     bs   = PetscAbs(bs);
1435db4efbfdSBarry Smith   }
1436db4efbfdSBarry Smith   if (nnz && newbs != bs) {
1437db4efbfdSBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot change blocksize from command line if setting nnz");
1438db4efbfdSBarry Smith   }
1439db4efbfdSBarry Smith   bs = newbs;
1440db4efbfdSBarry Smith 
14417408324eSLisandro Dalcin   ierr = PetscMapSetBlockSize(B->rmap,bs);CHKERRQ(ierr);
14427408324eSLisandro Dalcin   ierr = PetscMapSetBlockSize(B->cmap,bs);CHKERRQ(ierr);
1443d0f46423SBarry Smith   ierr = PetscMapSetUp(B->rmap);CHKERRQ(ierr);
1444d0f46423SBarry Smith   ierr = PetscMapSetUp(B->cmap);CHKERRQ(ierr);
1445899cda47SBarry Smith 
1446d0f46423SBarry Smith   mbs  = B->rmap->N/bs;
144749b5e25fSSatish Balay   bs2  = bs*bs;
144849b5e25fSSatish Balay 
1449d0f46423SBarry Smith   if (mbs*bs != B->rmap->N) {
145029bbc08cSBarry Smith     SETERRQ(PETSC_ERR_ARG_SIZ,"Number rows, cols must be divisible by blocksize");
145149b5e25fSSatish Balay   }
145249b5e25fSSatish Balay 
1453ab93d7beSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
1454ab93d7beSBarry Smith     skipallocation = PETSC_TRUE;
1455ab93d7beSBarry Smith     nz             = 0;
1456ab93d7beSBarry Smith   }
1457ab93d7beSBarry Smith 
1458435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3;
145977431f27SBarry Smith   if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
146049b5e25fSSatish Balay   if (nnz) {
146149b5e25fSSatish Balay     for (i=0; i<mbs; i++) {
146277431f27SBarry Smith       if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %D value %D",i,nnz[i]);
146377431f27SBarry Smith       if (nnz[i] > mbs) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than block row length: local row %D value %D rowlength %D",i,nnz[i],mbs);
146449b5e25fSSatish Balay     }
146549b5e25fSSatish Balay   }
146649b5e25fSSatish Balay 
1467db4efbfdSBarry Smith   B->ops->mult             = MatMult_SeqSBAIJ_N;
1468db4efbfdSBarry Smith   B->ops->multadd          = MatMultAdd_SeqSBAIJ_N;
1469db4efbfdSBarry Smith   B->ops->multtranspose    = MatMult_SeqSBAIJ_N;
1470db4efbfdSBarry Smith   B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N;
147190d69ab7SBarry Smith   ierr  = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_no_unroll",&flg,PETSC_NULL);CHKERRQ(ierr);
147249b5e25fSSatish Balay   if (!flg) {
147349b5e25fSSatish Balay     switch (bs) {
147449b5e25fSSatish Balay     case 1:
147549b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_1;
147649b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_1;
1477431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_1;
1478431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1;
147949b5e25fSSatish Balay       break;
148049b5e25fSSatish Balay     case 2:
148149b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_2;
148249b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_2;
1483431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_2;
1484431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2;
148549b5e25fSSatish Balay       break;
148649b5e25fSSatish Balay     case 3:
148749b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_3;
148849b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_3;
1489431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_3;
1490431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3;
149149b5e25fSSatish Balay       break;
149249b5e25fSSatish Balay     case 4:
149349b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_4;
149449b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_4;
1495431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_4;
1496431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4;
149749b5e25fSSatish Balay       break;
149849b5e25fSSatish Balay     case 5:
149949b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_5;
150049b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_5;
1501431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_5;
1502431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5;
150349b5e25fSSatish Balay       break;
150449b5e25fSSatish Balay     case 6:
150549b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_6;
150649b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_6;
1507431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_6;
1508431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6;
150949b5e25fSSatish Balay       break;
151049b5e25fSSatish Balay     case 7:
1511de53e5efSHong Zhang       B->ops->mult             = MatMult_SeqSBAIJ_7;
151249b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_7;
1513431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_7;
1514431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7;
151549b5e25fSSatish Balay       break;
151649b5e25fSSatish Balay     }
151749b5e25fSSatish Balay   }
151849b5e25fSSatish Balay 
151949b5e25fSSatish Balay   b->mbs = mbs;
15204afc71dfSHong Zhang   b->nbs = mbs;
1521ab93d7beSBarry Smith   if (!skipallocation) {
15222ee49352SLisandro Dalcin     if (!b->imax) {
1523ab93d7beSBarry Smith       ierr = PetscMalloc2(mbs,PetscInt,&b->imax,mbs,PetscInt,&b->ilen);CHKERRQ(ierr);
15242ee49352SLisandro Dalcin       ierr = PetscLogObjectMemory(B,2*mbs*sizeof(PetscInt));CHKERRQ(ierr);
15252ee49352SLisandro Dalcin     }
152649b5e25fSSatish Balay     if (!nnz) {
1527435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
152849b5e25fSSatish Balay       else if (nz <= 0)        nz = 1;
152949b5e25fSSatish Balay       for (i=0; i<mbs; i++) {
15308cef66ccSHong Zhang         b->imax[i] = nz;
153149b5e25fSSatish Balay       }
1532153ea458SHong Zhang       nz = nz*mbs; /* total nz */
153349b5e25fSSatish Balay     } else {
153449b5e25fSSatish Balay       nz = 0;
15358cef66ccSHong Zhang       for (i=0; i<mbs; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
153649b5e25fSSatish Balay     }
15372ee49352SLisandro Dalcin     /* b->ilen will count nonzeros in each block row so far. */
15382ee49352SLisandro Dalcin     for (i=0; i<mbs; i++) { b->ilen[i] = 0;}
15396c6c5352SBarry Smith     /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */
154049b5e25fSSatish Balay 
154149b5e25fSSatish Balay     /* allocate the matrix space */
15422ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
1543d0f46423SBarry Smith     ierr = PetscMalloc3(bs2*nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap->N+1,PetscInt,&b->i);CHKERRQ(ierr);
1544d0f46423SBarry Smith     ierr = PetscLogObjectMemory(B,(B->rmap->N+1)*sizeof(PetscInt)+nz*(bs2*sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
15456c6c5352SBarry Smith     ierr = PetscMemzero(b->a,nz*bs2*sizeof(MatScalar));CHKERRQ(ierr);
154613f74950SBarry Smith     ierr = PetscMemzero(b->j,nz*sizeof(PetscInt));CHKERRQ(ierr);
154749b5e25fSSatish Balay     b->singlemalloc = PETSC_TRUE;
154849b5e25fSSatish Balay 
154949b5e25fSSatish Balay     /* pointer to beginning of each row */
155049b5e25fSSatish Balay     b->i[0] = 0;
155149b5e25fSSatish Balay     for (i=1; i<mbs+1; i++) {
155249b5e25fSSatish Balay       b->i[i] = b->i[i-1] + b->imax[i-1];
155349b5e25fSSatish Balay     }
1554e6b907acSBarry Smith     b->free_a     = PETSC_TRUE;
1555e6b907acSBarry Smith     b->free_ij    = PETSC_TRUE;
1556e811da20SHong Zhang   } else {
1557e6b907acSBarry Smith     b->free_a     = PETSC_FALSE;
1558e6b907acSBarry Smith     b->free_ij    = PETSC_FALSE;
1559ab93d7beSBarry Smith   }
156049b5e25fSSatish Balay 
1561d0f46423SBarry Smith   B->rmap->bs               = bs;
156249b5e25fSSatish Balay   b->bs2              = bs2;
15636c6c5352SBarry Smith   b->nz             = 0;
15646c6c5352SBarry Smith   b->maxnz          = nz*bs2;
1565153ea458SHong Zhang 
156616cdd363SHong Zhang   b->inew             = 0;
156716cdd363SHong Zhang   b->jnew             = 0;
156816cdd363SHong Zhang   b->anew             = 0;
156916cdd363SHong Zhang   b->a2anew           = 0;
15701a3463dfSHong Zhang   b->permute          = PETSC_FALSE;
1571c464158bSHong Zhang   PetscFunctionReturn(0);
1572c464158bSHong Zhang }
1573a23d5eceSKris Buschelman EXTERN_C_END
1574153ea458SHong Zhang 
1575db4efbfdSBarry Smith #undef __FUNCT__
1576db4efbfdSBarry Smith #define __FUNCT__ "MatSeqBAIJSetNumericFactorization"
1577db4efbfdSBarry Smith /*
1578db4efbfdSBarry Smith    This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization
1579db4efbfdSBarry Smith */
1580db4efbfdSBarry Smith PetscErrorCode MatSeqSBAIJSetNumericFactorization(Mat B,PetscTruth natural)
1581db4efbfdSBarry Smith {
1582db4efbfdSBarry Smith   PetscErrorCode ierr;
158390d69ab7SBarry Smith   PetscTruth     flg = PETSC_FALSE;
1584db4efbfdSBarry Smith   PetscInt       bs = B->rmap->bs;
1585db4efbfdSBarry Smith 
1586db4efbfdSBarry Smith   PetscFunctionBegin;
158790d69ab7SBarry Smith   ierr    = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_no_unroll",&flg,PETSC_NULL);CHKERRQ(ierr);
1588db4efbfdSBarry Smith   if (flg) bs = 8;
1589db4efbfdSBarry Smith 
1590db4efbfdSBarry Smith   if (!natural) {
1591db4efbfdSBarry Smith     switch (bs) {
1592db4efbfdSBarry Smith     case 1:
1593db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1;
1594db4efbfdSBarry Smith       break;
1595db4efbfdSBarry Smith     case 2:
1596db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2;
1597db4efbfdSBarry Smith       break;
1598db4efbfdSBarry Smith     case 3:
1599db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3;
1600db4efbfdSBarry Smith       break;
1601db4efbfdSBarry Smith     case 4:
1602db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4;
1603db4efbfdSBarry Smith       break;
1604db4efbfdSBarry Smith     case 5:
1605db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5;
1606db4efbfdSBarry Smith       break;
1607db4efbfdSBarry Smith     case 6:
1608db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6;
1609db4efbfdSBarry Smith       break;
1610db4efbfdSBarry Smith     case 7:
1611db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7;
1612db4efbfdSBarry Smith       break;
1613db4efbfdSBarry Smith     default:
1614db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N;
1615db4efbfdSBarry Smith       break;
1616db4efbfdSBarry Smith     }
1617db4efbfdSBarry Smith   } else {
1618db4efbfdSBarry Smith     switch (bs) {
1619db4efbfdSBarry Smith     case 1:
1620db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering;
1621db4efbfdSBarry Smith       break;
1622db4efbfdSBarry Smith     case 2:
1623db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering;
1624db4efbfdSBarry Smith       break;
1625db4efbfdSBarry Smith     case 3:
1626db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering;
1627db4efbfdSBarry Smith       break;
1628db4efbfdSBarry Smith     case 4:
1629db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering;
1630db4efbfdSBarry Smith       break;
1631db4efbfdSBarry Smith     case 5:
1632db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering;
1633db4efbfdSBarry Smith       break;
1634db4efbfdSBarry Smith     case 6:
1635db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering;
1636db4efbfdSBarry Smith       break;
1637db4efbfdSBarry Smith     case 7:
1638db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering;
1639db4efbfdSBarry Smith       break;
1640db4efbfdSBarry Smith     default:
1641db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering;
1642db4efbfdSBarry Smith       break;
1643db4efbfdSBarry Smith     }
1644db4efbfdSBarry Smith   }
1645db4efbfdSBarry Smith   PetscFunctionReturn(0);
1646db4efbfdSBarry Smith }
1647db4efbfdSBarry Smith 
1648d769727bSBarry Smith EXTERN_C_BEGIN
1649f69a0ea3SMatthew Knepley EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType,MatReuse,Mat*);
1650f69a0ea3SMatthew Knepley EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType,MatReuse,Mat*);
1651d769727bSBarry Smith EXTERN_C_END
1652d769727bSBarry Smith 
1653e631078cSBarry Smith 
1654e631078cSBarry Smith EXTERN_C_BEGIN
16555c9eb25fSBarry Smith #undef __FUNCT__
16565c9eb25fSBarry Smith #define __FUNCT__ "MatGetFactor_seqsbaij_petsc"
16575c9eb25fSBarry Smith PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A,MatFactorType ftype,Mat *B)
16585c9eb25fSBarry Smith {
1659d0f46423SBarry Smith   PetscInt           n = A->rmap->n;
16605c9eb25fSBarry Smith   PetscErrorCode     ierr;
16615c9eb25fSBarry Smith 
16625c9eb25fSBarry Smith   PetscFunctionBegin;
16635c9eb25fSBarry Smith   ierr = MatCreate(((PetscObject)A)->comm,B);CHKERRQ(ierr);
16645c9eb25fSBarry Smith   ierr = MatSetSizes(*B,n,n,n,n);CHKERRQ(ierr);
16655c9eb25fSBarry Smith   if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
16665c9eb25fSBarry Smith     ierr = MatSetType(*B,MATSEQSBAIJ);CHKERRQ(ierr);
16675c9eb25fSBarry Smith     ierr = MatSeqSBAIJSetPreallocation(*B,1,MAT_SKIP_ALLOCATION,PETSC_NULL);CHKERRQ(ierr);
1668db4efbfdSBarry Smith     (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ;
1669db4efbfdSBarry Smith     (*B)->ops->iccfactorsymbolic      = MatICCFactorSymbolic_SeqSBAIJ;
16705c9eb25fSBarry Smith   } else SETERRQ(PETSC_ERR_SUP,"Factor type not supported");
1671719d5645SBarry Smith   (*B)->factor = ftype;
16725c9eb25fSBarry Smith   PetscFunctionReturn(0);
16735c9eb25fSBarry Smith }
1674e631078cSBarry Smith EXTERN_C_END
16755c9eb25fSBarry Smith 
16765c9eb25fSBarry Smith EXTERN_C_BEGIN
1677db4efbfdSBarry Smith #undef __FUNCT__
1678db4efbfdSBarry Smith #define __FUNCT__ "MatGetFactorAvailable_seqsbaij_petsc"
1679db4efbfdSBarry Smith PetscErrorCode MatGetFactorAvailable_seqsbaij_petsc(Mat A,MatFactorType ftype,PetscTruth *flg)
1680db4efbfdSBarry Smith {
1681db4efbfdSBarry Smith   PetscFunctionBegin;
1682db4efbfdSBarry Smith   if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1683db4efbfdSBarry Smith     *flg = PETSC_TRUE;
1684db4efbfdSBarry Smith   } else {
1685db4efbfdSBarry Smith     *flg = PETSC_FALSE;
1686db4efbfdSBarry Smith   }
1687db4efbfdSBarry Smith   PetscFunctionReturn(0);
1688db4efbfdSBarry Smith }
1689db4efbfdSBarry Smith EXTERN_C_END
1690db4efbfdSBarry Smith 
1691db4efbfdSBarry Smith EXTERN_C_BEGIN
1692611f576cSBarry Smith #if defined(PETSC_HAVE_MUMPS)
16935c9eb25fSBarry Smith extern PetscErrorCode MatGetFactor_seqsbaij_mumps(Mat,MatFactorType,Mat*);
1694611f576cSBarry Smith #endif
1695611f576cSBarry Smith #if defined(PETSC_HAVE_SPOOLES)
16965c9eb25fSBarry Smith extern PetscErrorCode MatGetFactor_seqsbaij_spooles(Mat,MatFactorType,Mat*);
1697611f576cSBarry Smith #endif
1698b5e56a35SBarry Smith #if defined(PETSC_HAVE_PASTIX)
1699b5e56a35SBarry Smith extern PetscErrorCode MatGetFactor_seqsbaij_pastix(Mat,MatFactorType,Mat*);
1700b5e56a35SBarry Smith #endif
17015c9eb25fSBarry Smith EXTERN_C_END
17025c9eb25fSBarry Smith 
17030bad9183SKris Buschelman /*MC
1704fafad747SKris Buschelman   MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices,
17050bad9183SKris Buschelman   based on block compressed sparse row format.  Only the upper triangular portion of the matrix is stored.
17060bad9183SKris Buschelman 
17070bad9183SKris Buschelman   Options Database Keys:
17080bad9183SKris Buschelman   . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to MatSetFromOptions()
17090bad9183SKris Buschelman 
17100bad9183SKris Buschelman   Level: beginner
17110bad9183SKris Buschelman 
17120bad9183SKris Buschelman   .seealso: MatCreateSeqSBAIJ
17130bad9183SKris Buschelman M*/
17140bad9183SKris Buschelman 
1715a23d5eceSKris Buschelman EXTERN_C_BEGIN
1716a23d5eceSKris Buschelman #undef __FUNCT__
1717a23d5eceSKris Buschelman #define __FUNCT__ "MatCreate_SeqSBAIJ"
1718be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_SeqSBAIJ(Mat B)
1719a23d5eceSKris Buschelman {
1720a23d5eceSKris Buschelman   Mat_SeqSBAIJ   *b;
1721dfbe8321SBarry Smith   PetscErrorCode ierr;
172213f74950SBarry Smith   PetscMPIInt    size;
17230def2e27SBarry Smith   PetscTruth     no_unroll = PETSC_FALSE,no_inode = PETSC_FALSE;
1724a23d5eceSKris Buschelman 
1725a23d5eceSKris Buschelman   PetscFunctionBegin;
17267adad957SLisandro Dalcin   ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr);
1727a23d5eceSKris Buschelman   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"Comm must be of size 1");
1728a23d5eceSKris Buschelman 
172938f2d2fdSLisandro Dalcin   ierr    = PetscNewLog(B,Mat_SeqSBAIJ,&b);CHKERRQ(ierr);
1730a23d5eceSKris Buschelman   B->data = (void*)b;
1731a23d5eceSKris Buschelman   ierr    = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
1732a23d5eceSKris Buschelman   B->ops->destroy     = MatDestroy_SeqSBAIJ;
1733a23d5eceSKris Buschelman   B->ops->view        = MatView_SeqSBAIJ;
1734a23d5eceSKris Buschelman   B->mapping          = 0;
1735a23d5eceSKris Buschelman   b->row              = 0;
1736a23d5eceSKris Buschelman   b->icol             = 0;
1737a23d5eceSKris Buschelman   b->reallocs         = 0;
1738a23d5eceSKris Buschelman   b->saved_values     = 0;
17390def2e27SBarry Smith   b->inode.limit      = 5;
17400def2e27SBarry Smith   b->inode.max_limit  = 5;
1741a23d5eceSKris Buschelman 
1742a23d5eceSKris Buschelman   b->roworiented      = PETSC_TRUE;
1743a23d5eceSKris Buschelman   b->nonew            = 0;
1744a23d5eceSKris Buschelman   b->diag             = 0;
1745a23d5eceSKris Buschelman   b->solve_work       = 0;
1746a23d5eceSKris Buschelman   b->mult_work        = 0;
1747a23d5eceSKris Buschelman   B->spptr            = 0;
1748a9817697SBarry Smith   b->keepnonzeropattern   = PETSC_FALSE;
1749a23d5eceSKris Buschelman   b->xtoy             = 0;
1750a23d5eceSKris Buschelman   b->XtoY             = 0;
1751a23d5eceSKris Buschelman 
1752a23d5eceSKris Buschelman   b->inew             = 0;
1753a23d5eceSKris Buschelman   b->jnew             = 0;
1754a23d5eceSKris Buschelman   b->anew             = 0;
1755a23d5eceSKris Buschelman   b->a2anew           = 0;
1756a23d5eceSKris Buschelman   b->permute          = PETSC_FALSE;
1757a23d5eceSKris Buschelman 
1758941593c8SHong Zhang   b->ignore_ltriangular = PETSC_FALSE;
175990d69ab7SBarry Smith   ierr = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_ignore_lower_triangular",&b->ignore_ltriangular,PETSC_NULL);CHKERRQ(ierr);
1760941593c8SHong Zhang 
1761f5edf698SHong Zhang   b->getrow_utriangular = PETSC_FALSE;
176290d69ab7SBarry Smith   ierr = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_getrow_uppertriangular",&b->getrow_utriangular,PETSC_NULL);CHKERRQ(ierr);
1763f5edf698SHong Zhang 
1764b5e56a35SBarry Smith #if defined(PETSC_HAVE_PASTIX)
1765b5e56a35SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_pastix_C",
1766b5e56a35SBarry Smith 					   "MatGetFactor_seqsbaij_pastix",
1767b5e56a35SBarry Smith 					   MatGetFactor_seqsbaij_pastix);CHKERRQ(ierr);
1768b5e56a35SBarry Smith #endif
1769611f576cSBarry Smith #if defined(PETSC_HAVE_SPOOLES)
17705c9eb25fSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_spooles_C",
17715c9eb25fSBarry Smith                                      "MatGetFactor_seqsbaij_spooles",
17725c9eb25fSBarry Smith                                      MatGetFactor_seqsbaij_spooles);CHKERRQ(ierr);
1773611f576cSBarry Smith #endif
1774611f576cSBarry Smith #if defined(PETSC_HAVE_MUMPS)
17755c9eb25fSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_mumps_C",
17765c9eb25fSBarry Smith                                      "MatGetFactor_seqsbaij_mumps",
17775c9eb25fSBarry Smith                                      MatGetFactor_seqsbaij_mumps);CHKERRQ(ierr);
1778611f576cSBarry Smith #endif
1779db4efbfdSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_seqsbaij_petsc_C",
1780db4efbfdSBarry Smith                                      "MatGetFactorAvailable_seqsbaij_petsc",
1781db4efbfdSBarry Smith                                      MatGetFactorAvailable_seqsbaij_petsc);CHKERRQ(ierr);
17825c9eb25fSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_petsc_C",
17835c9eb25fSBarry Smith                                      "MatGetFactor_seqsbaij_petsc",
17845c9eb25fSBarry Smith                                      MatGetFactor_seqsbaij_petsc);CHKERRQ(ierr);
1785a23d5eceSKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
1786a23d5eceSKris Buschelman                                      "MatStoreValues_SeqSBAIJ",
1787a23d5eceSKris Buschelman                                      MatStoreValues_SeqSBAIJ);CHKERRQ(ierr);
1788a23d5eceSKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
1789a23d5eceSKris Buschelman                                      "MatRetrieveValues_SeqSBAIJ",
1790a23d5eceSKris Buschelman                                      (void*)MatRetrieveValues_SeqSBAIJ);CHKERRQ(ierr);
1791a23d5eceSKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetColumnIndices_C",
1792a23d5eceSKris Buschelman                                      "MatSeqSBAIJSetColumnIndices_SeqSBAIJ",
1793a23d5eceSKris Buschelman                                      MatSeqSBAIJSetColumnIndices_SeqSBAIJ);CHKERRQ(ierr);
17944e5e7fe4SHong Zhang   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqaij_C",
17954e5e7fe4SHong Zhang                                      "MatConvert_SeqSBAIJ_SeqAIJ",
17964e5e7fe4SHong Zhang                                       MatConvert_SeqSBAIJ_SeqAIJ);CHKERRQ(ierr);
1797a0e1a404SHong Zhang   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqbaij_C",
1798a0e1a404SHong Zhang                                      "MatConvert_SeqSBAIJ_SeqBAIJ",
1799a0e1a404SHong Zhang                                       MatConvert_SeqSBAIJ_SeqBAIJ);CHKERRQ(ierr);
1800a23d5eceSKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetPreallocation_C",
1801a23d5eceSKris Buschelman                                      "MatSeqSBAIJSetPreallocation_SeqSBAIJ",
1802a23d5eceSKris Buschelman                                      MatSeqSBAIJSetPreallocation_SeqSBAIJ);CHKERRQ(ierr);
180323ce1328SBarry Smith 
180423ce1328SBarry Smith   B->symmetric                  = PETSC_TRUE;
180523ce1328SBarry Smith   B->structurally_symmetric     = PETSC_TRUE;
180623ce1328SBarry Smith   B->symmetric_set              = PETSC_TRUE;
180723ce1328SBarry Smith   B->structurally_symmetric_set = PETSC_TRUE;
180817667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQSBAIJ);CHKERRQ(ierr);
18090def2e27SBarry Smith 
18100def2e27SBarry Smith   ierr = PetscOptionsBegin(((PetscObject)B)->comm,((PetscObject)B)->prefix,"Options for SEQSBAIJ matrix","Mat");CHKERRQ(ierr);
18110def2e27SBarry Smith     ierr = PetscOptionsTruth("-mat_no_unroll","Do not optimize for inodes (slower)",PETSC_NULL,no_unroll,&no_unroll,PETSC_NULL);CHKERRQ(ierr);
18120def2e27SBarry Smith     if (no_unroll) {ierr = PetscInfo(B,"Not using Inode routines due to -mat_no_unroll\n");CHKERRQ(ierr);}
18130def2e27SBarry Smith     ierr = PetscOptionsTruth("-mat_no_inode","Do not optimize for inodes (slower)",PETSC_NULL,no_inode,&no_inode,PETSC_NULL);CHKERRQ(ierr);
18140def2e27SBarry Smith     if (no_inode) {ierr = PetscInfo(B,"Not using Inode routines due to -mat_no_inode\n");CHKERRQ(ierr);}
18150def2e27SBarry Smith     ierr = PetscOptionsInt("-mat_inode_limit","Do not use inodes larger then this value",PETSC_NULL,b->inode.limit,&b->inode.limit,PETSC_NULL);CHKERRQ(ierr);
18160def2e27SBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
18170def2e27SBarry Smith   b->inode.use = (PetscTruth)(!(no_unroll || no_inode));
18180def2e27SBarry Smith   if (b->inode.limit > b->inode.max_limit) b->inode.limit = b->inode.max_limit;
18190def2e27SBarry Smith 
1820a23d5eceSKris Buschelman   PetscFunctionReturn(0);
1821a23d5eceSKris Buschelman }
1822a23d5eceSKris Buschelman EXTERN_C_END
1823a23d5eceSKris Buschelman 
1824a23d5eceSKris Buschelman #undef __FUNCT__
1825a23d5eceSKris Buschelman #define __FUNCT__ "MatSeqSBAIJSetPreallocation"
1826a23d5eceSKris Buschelman /*@C
1827a23d5eceSKris Buschelman    MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block
1828a23d5eceSKris Buschelman    compressed row) format.  For good matrix assembly performance the
1829a23d5eceSKris Buschelman    user should preallocate the matrix storage by setting the parameter nz
1830a23d5eceSKris Buschelman    (or the array nnz).  By setting these parameters accurately, performance
1831a23d5eceSKris Buschelman    during matrix assembly can be increased by more than a factor of 50.
1832a23d5eceSKris Buschelman 
1833a23d5eceSKris Buschelman    Collective on Mat
1834a23d5eceSKris Buschelman 
1835a23d5eceSKris Buschelman    Input Parameters:
1836a23d5eceSKris Buschelman +  A - the symmetric matrix
1837a23d5eceSKris Buschelman .  bs - size of block
1838a23d5eceSKris Buschelman .  nz - number of block nonzeros per block row (same for all rows)
1839a23d5eceSKris Buschelman -  nnz - array containing the number of block nonzeros in the upper triangular plus
1840a23d5eceSKris Buschelman          diagonal portion of each block (possibly different for each block row) or PETSC_NULL
1841a23d5eceSKris Buschelman 
1842a23d5eceSKris Buschelman    Options Database Keys:
1843a23d5eceSKris Buschelman .   -mat_no_unroll - uses code that does not unroll the loops in the
1844a23d5eceSKris Buschelman                      block calculations (much slower)
1845db4efbfdSBarry Smith .    -mat_block_size - size of the blocks to use (only works if a negative bs is passed in
1846a23d5eceSKris Buschelman 
1847a23d5eceSKris Buschelman    Level: intermediate
1848a23d5eceSKris Buschelman 
1849a23d5eceSKris Buschelman    Notes:
1850a23d5eceSKris Buschelman    Specify the preallocated storage with either nz or nnz (not both).
1851a23d5eceSKris Buschelman    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
1852a23d5eceSKris Buschelman    allocation.  For additional details, see the users manual chapter on
1853a23d5eceSKris Buschelman    matrices.
1854a23d5eceSKris Buschelman 
1855aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
1856aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
1857aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
1858aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
1859aa95bbe8SBarry Smith 
186049a6f317SBarry Smith    If the nnz parameter is given then the nz parameter is ignored
186149a6f317SBarry Smith 
186249a6f317SBarry Smith 
1863a23d5eceSKris Buschelman .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ()
1864a23d5eceSKris Buschelman @*/
1865be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetPreallocation(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[])
186613f74950SBarry Smith {
186713f74950SBarry Smith   PetscErrorCode ierr,(*f)(Mat,PetscInt,PetscInt,const PetscInt[]);
1868a23d5eceSKris Buschelman 
1869a23d5eceSKris Buschelman   PetscFunctionBegin;
1870a23d5eceSKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqSBAIJSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr);
1871a23d5eceSKris Buschelman   if (f) {
1872a23d5eceSKris Buschelman     ierr = (*f)(B,bs,nz,nnz);CHKERRQ(ierr);
1873a23d5eceSKris Buschelman   }
1874a23d5eceSKris Buschelman   PetscFunctionReturn(0);
1875a23d5eceSKris Buschelman }
187649b5e25fSSatish Balay 
18774a2ae208SSatish Balay #undef __FUNCT__
18784a2ae208SSatish Balay #define __FUNCT__ "MatCreateSeqSBAIJ"
1879c464158bSHong Zhang /*@C
1880c464158bSHong Zhang    MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in block AIJ (block
1881c464158bSHong Zhang    compressed row) format.  For good matrix assembly performance the
1882c464158bSHong Zhang    user should preallocate the matrix storage by setting the parameter nz
1883c464158bSHong Zhang    (or the array nnz).  By setting these parameters accurately, performance
1884c464158bSHong Zhang    during matrix assembly can be increased by more than a factor of 50.
188549b5e25fSSatish Balay 
1886c464158bSHong Zhang    Collective on MPI_Comm
1887c464158bSHong Zhang 
1888c464158bSHong Zhang    Input Parameters:
1889c464158bSHong Zhang +  comm - MPI communicator, set to PETSC_COMM_SELF
1890c464158bSHong Zhang .  bs - size of block
1891c464158bSHong Zhang .  m - number of rows, or number of columns
1892c464158bSHong Zhang .  nz - number of block nonzeros per block row (same for all rows)
1893744e8345SSatish Balay -  nnz - array containing the number of block nonzeros in the upper triangular plus
1894744e8345SSatish Balay          diagonal portion of each block (possibly different for each block row) or PETSC_NULL
1895c464158bSHong Zhang 
1896c464158bSHong Zhang    Output Parameter:
1897c464158bSHong Zhang .  A - the symmetric matrix
1898c464158bSHong Zhang 
1899c464158bSHong Zhang    Options Database Keys:
1900c464158bSHong Zhang .   -mat_no_unroll - uses code that does not unroll the loops in the
1901c464158bSHong Zhang                      block calculations (much slower)
1902c464158bSHong Zhang .    -mat_block_size - size of the blocks to use
1903c464158bSHong Zhang 
1904c464158bSHong Zhang    Level: intermediate
1905c464158bSHong Zhang 
1906175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
1907ae1d86c5SBarry Smith    MatXXXXSetPreallocation() paradgm instead of this routine directly.
1908175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
1909175b88e8SBarry Smith 
1910c464158bSHong Zhang    Notes:
19116d6d819aSHong Zhang    The number of rows and columns must be divisible by blocksize.
19126d6d819aSHong Zhang    This matrix type does not support complex Hermitian operation.
1913c464158bSHong Zhang 
1914c464158bSHong Zhang    Specify the preallocated storage with either nz or nnz (not both).
1915c464158bSHong Zhang    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
1916c464158bSHong Zhang    allocation.  For additional details, see the users manual chapter on
1917c464158bSHong Zhang    matrices.
1918c464158bSHong Zhang 
191949a6f317SBarry Smith    If the nnz parameter is given then the nz parameter is ignored
192049a6f317SBarry Smith 
1921c464158bSHong Zhang .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ()
1922c464158bSHong Zhang @*/
1923be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqSBAIJ(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
1924c464158bSHong Zhang {
1925dfbe8321SBarry Smith   PetscErrorCode ierr;
1926c464158bSHong Zhang 
1927c464158bSHong Zhang   PetscFunctionBegin;
1928f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
1929f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
1930c464158bSHong Zhang   ierr = MatSetType(*A,MATSEQSBAIJ);CHKERRQ(ierr);
1931ab93d7beSBarry Smith   ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(*A,bs,nz,(PetscInt*)nnz);CHKERRQ(ierr);
193249b5e25fSSatish Balay   PetscFunctionReturn(0);
193349b5e25fSSatish Balay }
193449b5e25fSSatish Balay 
19354a2ae208SSatish Balay #undef __FUNCT__
19364a2ae208SSatish Balay #define __FUNCT__ "MatDuplicate_SeqSBAIJ"
1937dfbe8321SBarry Smith PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
193849b5e25fSSatish Balay {
193949b5e25fSSatish Balay   Mat            C;
194049b5e25fSSatish Balay   Mat_SeqSBAIJ   *c,*a = (Mat_SeqSBAIJ*)A->data;
19416849ba73SBarry Smith   PetscErrorCode ierr;
1942b40805acSSatish Balay   PetscInt       i,mbs = a->mbs,nz = a->nz,bs2 =a->bs2;
194349b5e25fSSatish Balay 
194449b5e25fSSatish Balay   PetscFunctionBegin;
194529bbc08cSBarry Smith   if (a->i[mbs] != nz) SETERRQ(PETSC_ERR_PLIB,"Corrupt matrix");
194649b5e25fSSatish Balay 
194749b5e25fSSatish Balay   *B = 0;
19487adad957SLisandro Dalcin   ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr);
1949d0f46423SBarry Smith   ierr = MatSetSizes(C,A->rmap->N,A->cmap->n,A->rmap->N,A->cmap->n);CHKERRQ(ierr);
19507adad957SLisandro Dalcin   ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
19511d5dac46SHong Zhang   ierr = PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1952692f9cbeSHong Zhang   c    = (Mat_SeqSBAIJ*)C->data;
1953692f9cbeSHong Zhang 
1954273d9f13SBarry Smith   C->preallocated       = PETSC_TRUE;
195549b5e25fSSatish Balay   C->factor             = A->factor;
195649b5e25fSSatish Balay   c->row                = 0;
195749b5e25fSSatish Balay   c->icol               = 0;
195849b5e25fSSatish Balay   c->saved_values       = 0;
1959a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
196049b5e25fSSatish Balay   C->assembled          = PETSC_TRUE;
196149b5e25fSSatish Balay 
1962d0f46423SBarry Smith   ierr = PetscMapCopy(((PetscObject)A)->comm,A->rmap,C->rmap);CHKERRQ(ierr);
1963d0f46423SBarry Smith   ierr = PetscMapCopy(((PetscObject)A)->comm,A->cmap,C->cmap);CHKERRQ(ierr);
196449b5e25fSSatish Balay   c->bs2  = a->bs2;
196549b5e25fSSatish Balay   c->mbs  = a->mbs;
196649b5e25fSSatish Balay   c->nbs  = a->nbs;
196749b5e25fSSatish Balay 
19688777fc3fSSatish Balay   ierr = PetscMalloc2((mbs+1),PetscInt,&c->imax,(mbs+1),PetscInt,&c->ilen);CHKERRQ(ierr);
196949b5e25fSSatish Balay   for (i=0; i<mbs; i++) {
197049b5e25fSSatish Balay     c->imax[i] = a->imax[i];
197149b5e25fSSatish Balay     c->ilen[i] = a->ilen[i];
197249b5e25fSSatish Balay   }
197349b5e25fSSatish Balay 
197449b5e25fSSatish Balay   /* allocate the matrix space */
1975*4da8f245SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
1976*4da8f245SBarry Smith     ierr = PetscMalloc(bs2*nz*sizeof(MatScalar),&c->a);CHKERRQ(ierr);
1977*4da8f245SBarry Smith     ierr = PetscLogObjectMemory(C,nz*bs2*sizeof(MatScalar));CHKERRQ(ierr);
1978*4da8f245SBarry Smith     c->singlemalloc = PETSC_FALSE;
1979*4da8f245SBarry Smith     c->free_ij      = PETSC_FALSE;
1980*4da8f245SBarry Smith     c->parent       = A;
1981*4da8f245SBarry Smith     ierr            = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
1982*4da8f245SBarry Smith     ierr            = MatSetOption(A,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
1983*4da8f245SBarry Smith     ierr            = MatSetOption(C,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
1984*4da8f245SBarry Smith   } else {
1985b40805acSSatish Balay     ierr = PetscMalloc3(bs2*nz,MatScalar,&c->a,nz,PetscInt,&c->j,mbs+1,PetscInt,&c->i);CHKERRQ(ierr);
198613f74950SBarry Smith     ierr = PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr);
1987b40805acSSatish Balay     ierr = PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt) + nz*(bs2*sizeof(MatScalar) + sizeof(PetscInt)));CHKERRQ(ierr);
1988*4da8f245SBarry Smith     c->singlemalloc = PETSC_TRUE;
1989*4da8f245SBarry Smith     c->free_ij      = PETSC_TRUE;
1990*4da8f245SBarry Smith   }
199149b5e25fSSatish Balay   if (mbs > 0) {
1992*4da8f245SBarry Smith     if (cpvalues != MAT_SHARE_NONZERO_PATTERN) {
199313f74950SBarry Smith       ierr = PetscMemcpy(c->j,a->j,nz*sizeof(PetscInt));CHKERRQ(ierr);
1994*4da8f245SBarry Smith     }
199549b5e25fSSatish Balay     if (cpvalues == MAT_COPY_VALUES) {
199649b5e25fSSatish Balay       ierr = PetscMemcpy(c->a,a->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr);
199749b5e25fSSatish Balay     } else {
199849b5e25fSSatish Balay       ierr = PetscMemzero(c->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr);
199949b5e25fSSatish Balay     }
2000a1c3900fSBarry Smith     if (a->jshort) {
2001*4da8f245SBarry Smith       if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2002*4da8f245SBarry Smith         c->jshort      = a->jshort;
2003*4da8f245SBarry Smith         c->free_jshort = PETSC_FALSE;
2004*4da8f245SBarry Smith       } else {
2005a1c3900fSBarry Smith         ierr = PetscMalloc(nz*sizeof(unsigned short),&c->jshort);CHKERRQ(ierr);
2006a1c3900fSBarry Smith         ierr = PetscMemcpy(c->jshort,a->jshort,nz*sizeof(unsigned short));CHKERRQ(ierr);
2007*4da8f245SBarry Smith         c->free_jshort = PETSC_TRUE;
2008*4da8f245SBarry Smith       }
2009a1c3900fSBarry Smith     }
201049b5e25fSSatish Balay   }
201149b5e25fSSatish Balay 
201249b5e25fSSatish Balay   c->roworiented = a->roworiented;
201349b5e25fSSatish Balay   c->nonew       = a->nonew;
201449b5e25fSSatish Balay 
201549b5e25fSSatish Balay   if (a->diag) {
201613f74950SBarry Smith     ierr = PetscMalloc((mbs+1)*sizeof(PetscInt),&c->diag);CHKERRQ(ierr);
201752e6d16bSBarry Smith     ierr = PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr);
201849b5e25fSSatish Balay     for (i=0; i<mbs; i++) {
201949b5e25fSSatish Balay       c->diag[i] = a->diag[i];
202049b5e25fSSatish Balay     }
202149b5e25fSSatish Balay   } else c->diag  = 0;
20226c6c5352SBarry Smith   c->nz           = a->nz;
20236c6c5352SBarry Smith   c->maxnz        = a->maxnz;
202449b5e25fSSatish Balay   c->solve_work   = 0;
202549b5e25fSSatish Balay   c->mult_work    = 0;
2026e6b907acSBarry Smith   c->free_a       = PETSC_TRUE;
202749b5e25fSSatish Balay   *B = C;
20287adad957SLisandro Dalcin   ierr = PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
202949b5e25fSSatish Balay   PetscFunctionReturn(0);
203049b5e25fSSatish Balay }
203149b5e25fSSatish Balay 
20324a2ae208SSatish Balay #undef __FUNCT__
20334a2ae208SSatish Balay #define __FUNCT__ "MatLoad_SeqSBAIJ"
2034a313700dSBarry Smith PetscErrorCode MatLoad_SeqSBAIJ(PetscViewer viewer, const MatType type,Mat *A)
203549b5e25fSSatish Balay {
203649b5e25fSSatish Balay   Mat_SeqSBAIJ   *a;
203749b5e25fSSatish Balay   Mat            B;
20386849ba73SBarry Smith   PetscErrorCode ierr;
203913f74950SBarry Smith   int            fd;
204013f74950SBarry Smith   PetscMPIInt    size;
204113f74950SBarry Smith   PetscInt       i,nz,header[4],*rowlengths=0,M,N,bs=1;
204213f74950SBarry Smith   PetscInt       *mask,mbs,*jj,j,rowcount,nzcount,k,*s_browlengths,maskcount;
204313f74950SBarry Smith   PetscInt       kmax,jcount,block,idx,point,nzcountb,extra_rows;
204413f74950SBarry Smith   PetscInt       *masked,nmask,tmp,bs2,ishift;
204587828ca2SBarry Smith   PetscScalar    *aa;
204649b5e25fSSatish Balay   MPI_Comm       comm = ((PetscObject)viewer)->comm;
204749b5e25fSSatish Balay 
204849b5e25fSSatish Balay   PetscFunctionBegin;
2049b0a32e0cSBarry Smith   ierr = PetscOptionsGetInt(PETSC_NULL,"-matload_block_size",&bs,PETSC_NULL);CHKERRQ(ierr);
205049b5e25fSSatish Balay   bs2  = bs*bs;
205149b5e25fSSatish Balay 
205249b5e25fSSatish Balay   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
205329bbc08cSBarry Smith   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"view must have one processor");
2054b0a32e0cSBarry Smith   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
205549b5e25fSSatish Balay   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
2056552e946dSBarry Smith   if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not Mat object");
205749b5e25fSSatish Balay   M = header[1]; N = header[2]; nz = header[3];
205849b5e25fSSatish Balay 
205949b5e25fSSatish Balay   if (header[3] < 0) {
206029bbc08cSBarry Smith     SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format, cannot load as SeqSBAIJ");
206149b5e25fSSatish Balay   }
206249b5e25fSSatish Balay 
206329bbc08cSBarry Smith   if (M != N) SETERRQ(PETSC_ERR_SUP,"Can only do square matrices");
206449b5e25fSSatish Balay 
206549b5e25fSSatish Balay   /*
206649b5e25fSSatish Balay      This code adds extra rows to make sure the number of rows is
206749b5e25fSSatish Balay     divisible by the blocksize
206849b5e25fSSatish Balay   */
206949b5e25fSSatish Balay   mbs        = M/bs;
207049b5e25fSSatish Balay   extra_rows = bs - M + bs*(mbs);
207149b5e25fSSatish Balay   if (extra_rows == bs) extra_rows = 0;
207249b5e25fSSatish Balay   else                  mbs++;
207349b5e25fSSatish Balay   if (extra_rows) {
20741e2582c4SBarry Smith     ierr = PetscInfo(viewer,"Padding loaded matrix to match blocksize\n");CHKERRQ(ierr);
207549b5e25fSSatish Balay   }
207649b5e25fSSatish Balay 
207749b5e25fSSatish Balay   /* read in row lengths */
207813f74950SBarry Smith   ierr = PetscMalloc((M+extra_rows)*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
207949b5e25fSSatish Balay   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
208049b5e25fSSatish Balay   for (i=0; i<extra_rows; i++) rowlengths[M+i] = 1;
208149b5e25fSSatish Balay 
208249b5e25fSSatish Balay   /* read in column indices */
208313f74950SBarry Smith   ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscInt),&jj);CHKERRQ(ierr);
208449b5e25fSSatish Balay   ierr = PetscBinaryRead(fd,jj,nz,PETSC_INT);CHKERRQ(ierr);
208549b5e25fSSatish Balay   for (i=0; i<extra_rows; i++) jj[nz+i] = M+i;
208649b5e25fSSatish Balay 
208749b5e25fSSatish Balay   /* loop over row lengths determining block row lengths */
208813f74950SBarry Smith   ierr     = PetscMalloc(mbs*sizeof(PetscInt),&s_browlengths);CHKERRQ(ierr);
208913f74950SBarry Smith   ierr     = PetscMemzero(s_browlengths,mbs*sizeof(PetscInt));CHKERRQ(ierr);
209013f74950SBarry Smith   ierr     = PetscMalloc(2*mbs*sizeof(PetscInt),&mask);CHKERRQ(ierr);
209113f74950SBarry Smith   ierr     = PetscMemzero(mask,mbs*sizeof(PetscInt));CHKERRQ(ierr);
209249b5e25fSSatish Balay   masked   = mask + mbs;
209349b5e25fSSatish Balay   rowcount = 0; nzcount = 0;
209449b5e25fSSatish Balay   for (i=0; i<mbs; i++) {
209549b5e25fSSatish Balay     nmask = 0;
209649b5e25fSSatish Balay     for (j=0; j<bs; j++) {
209749b5e25fSSatish Balay       kmax = rowlengths[rowcount];
209849b5e25fSSatish Balay       for (k=0; k<kmax; k++) {
20992d703238SHong Zhang         tmp = jj[nzcount++]/bs;   /* block col. index */
210003630b6eSHong Zhang         if (!mask[tmp] && tmp >= i) {masked[nmask++] = tmp; mask[tmp] = 1;}
210149b5e25fSSatish Balay       }
210249b5e25fSSatish Balay       rowcount++;
210349b5e25fSSatish Balay     }
2104574b2666SHong Zhang     s_browlengths[i] += nmask;
2105574b2666SHong Zhang 
210649b5e25fSSatish Balay     /* zero out the mask elements we set */
210749b5e25fSSatish Balay     for (j=0; j<nmask; j++) mask[masked[j]] = 0;
210849b5e25fSSatish Balay   }
210949b5e25fSSatish Balay 
211049b5e25fSSatish Balay   /* create our matrix */
2111f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,&B);CHKERRQ(ierr);
2112f69a0ea3SMatthew Knepley   ierr = MatSetSizes(B,M+extra_rows,N+extra_rows,M+extra_rows,N+extra_rows);CHKERRQ(ierr);
21139abb65ffSKris Buschelman   ierr = MatSetType(B,type);CHKERRQ(ierr);
2114ab93d7beSBarry Smith   ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(B,bs,0,s_browlengths);CHKERRQ(ierr);
211549b5e25fSSatish Balay   a = (Mat_SeqSBAIJ*)B->data;
211649b5e25fSSatish Balay 
211749b5e25fSSatish Balay   /* set matrix "i" values */
211849b5e25fSSatish Balay   a->i[0] = 0;
211949b5e25fSSatish Balay   for (i=1; i<= mbs; i++) {
2120574b2666SHong Zhang     a->i[i]      = a->i[i-1] + s_browlengths[i-1];
2121574b2666SHong Zhang     a->ilen[i-1] = s_browlengths[i-1];
212249b5e25fSSatish Balay   }
21236c6c5352SBarry Smith   a->nz = a->i[mbs];
212449b5e25fSSatish Balay 
212549b5e25fSSatish Balay   /* read in nonzero values */
212687828ca2SBarry Smith   ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscScalar),&aa);CHKERRQ(ierr);
212749b5e25fSSatish Balay   ierr = PetscBinaryRead(fd,aa,nz,PETSC_SCALAR);CHKERRQ(ierr);
212849b5e25fSSatish Balay   for (i=0; i<extra_rows; i++) aa[nz+i] = 1.0;
212949b5e25fSSatish Balay 
213049b5e25fSSatish Balay   /* set "a" and "j" values into matrix */
213149b5e25fSSatish Balay   nzcount = 0; jcount = 0;
213249b5e25fSSatish Balay   for (i=0; i<mbs; i++) {
213349b5e25fSSatish Balay     nzcountb = nzcount;
213449b5e25fSSatish Balay     nmask    = 0;
213549b5e25fSSatish Balay     for (j=0; j<bs; j++) {
213649b5e25fSSatish Balay       kmax = rowlengths[i*bs+j];
213749b5e25fSSatish Balay       for (k=0; k<kmax; k++) {
21382d703238SHong Zhang         tmp = jj[nzcount++]/bs; /* block col. index */
213903630b6eSHong Zhang         if (!mask[tmp] && tmp >= i) { masked[nmask++] = tmp; mask[tmp] = 1;}
21402d703238SHong Zhang       }
21412d703238SHong Zhang     }
21422d703238SHong Zhang     /* sort the masked values */
21432d703238SHong Zhang     ierr = PetscSortInt(nmask,masked);CHKERRQ(ierr);
21442d703238SHong Zhang 
21452d703238SHong Zhang     /* set "j" values into matrix */
21462d703238SHong Zhang     maskcount = 1;
21472d703238SHong Zhang     for (j=0; j<nmask; j++) {
214849b5e25fSSatish Balay       a->j[jcount++]  = masked[j];
214949b5e25fSSatish Balay       mask[masked[j]] = maskcount++;
215049b5e25fSSatish Balay     }
2151574b2666SHong Zhang 
215249b5e25fSSatish Balay     /* set "a" values into matrix */
215349b5e25fSSatish Balay     ishift = bs2*a->i[i];
215449b5e25fSSatish Balay     for (j=0; j<bs; j++) {
215549b5e25fSSatish Balay       kmax = rowlengths[i*bs+j];
215649b5e25fSSatish Balay       for (k=0; k<kmax; k++) {
2157574b2666SHong Zhang         tmp       = jj[nzcountb]/bs ; /* block col. index */
2158574b2666SHong Zhang         if (tmp >= i){
215949b5e25fSSatish Balay           block     = mask[tmp] - 1;
216049b5e25fSSatish Balay           point     = jj[nzcountb] - bs*tmp;
216149b5e25fSSatish Balay           idx       = ishift + bs2*block + j + bs*point;
2162574b2666SHong Zhang           a->a[idx] = aa[nzcountb];
2163574b2666SHong Zhang         }
2164574b2666SHong Zhang         nzcountb++;
216549b5e25fSSatish Balay       }
216649b5e25fSSatish Balay     }
216749b5e25fSSatish Balay     /* zero out the mask elements we set */
216849b5e25fSSatish Balay     for (j=0; j<nmask; j++) mask[masked[j]] = 0;
216949b5e25fSSatish Balay   }
21706c6c5352SBarry Smith   if (jcount != a->nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Bad binary matrix");
217149b5e25fSSatish Balay 
217249b5e25fSSatish Balay   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
2173574b2666SHong Zhang   ierr = PetscFree(s_browlengths);CHKERRQ(ierr);
217449b5e25fSSatish Balay   ierr = PetscFree(aa);CHKERRQ(ierr);
217549b5e25fSSatish Balay   ierr = PetscFree(jj);CHKERRQ(ierr);
217649b5e25fSSatish Balay   ierr = PetscFree(mask);CHKERRQ(ierr);
217749b5e25fSSatish Balay 
21789abb65ffSKris Buschelman   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
21799abb65ffSKris Buschelman   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
218049b5e25fSSatish Balay   ierr = MatView_Private(B);CHKERRQ(ierr);
21819abb65ffSKris Buschelman   *A = B;
218249b5e25fSSatish Balay   PetscFunctionReturn(0);
218349b5e25fSSatish Balay }
2184574b2666SHong Zhang 
2185d06b337dSHong Zhang #undef __FUNCT__
2186c75a6043SHong Zhang #define __FUNCT__ "MatCreateSeqSBAIJWithArrays"
2187c75a6043SHong Zhang /*@
2188c75a6043SHong Zhang      MatCreateSeqSBAIJWithArrays - Creates an sequential SBAIJ matrix using matrix elements
2189c75a6043SHong Zhang               (upper triangular entries in CSR format) provided by the user.
2190c75a6043SHong Zhang 
2191c75a6043SHong Zhang      Collective on MPI_Comm
2192c75a6043SHong Zhang 
2193c75a6043SHong Zhang    Input Parameters:
2194c75a6043SHong Zhang +  comm - must be an MPI communicator of size 1
2195c75a6043SHong Zhang .  bs - size of block
2196c75a6043SHong Zhang .  m - number of rows
2197c75a6043SHong Zhang .  n - number of columns
2198c75a6043SHong Zhang .  i - row indices
2199c75a6043SHong Zhang .  j - column indices
2200c75a6043SHong Zhang -  a - matrix values
2201c75a6043SHong Zhang 
2202c75a6043SHong Zhang    Output Parameter:
2203c75a6043SHong Zhang .  mat - the matrix
2204c75a6043SHong Zhang 
2205c75a6043SHong Zhang    Level: intermediate
2206c75a6043SHong Zhang 
2207c75a6043SHong Zhang    Notes:
2208c75a6043SHong Zhang        The i, j, and a arrays are not copied by this routine, the user must free these arrays
2209c75a6043SHong Zhang     once the matrix is destroyed
2210c75a6043SHong Zhang 
2211c75a6043SHong Zhang        You cannot set new nonzero locations into this matrix, that will generate an error.
2212c75a6043SHong Zhang 
2213c75a6043SHong Zhang        The i and j indices are 0 based
2214c75a6043SHong Zhang 
2215c75a6043SHong Zhang .seealso: MatCreate(), MatCreateMPISBAIJ(), MatCreateSeqSBAIJ()
2216c75a6043SHong Zhang 
2217c75a6043SHong Zhang @*/
2218c75a6043SHong Zhang PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqSBAIJWithArrays(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat)
2219c75a6043SHong Zhang {
2220c75a6043SHong Zhang   PetscErrorCode ierr;
2221c75a6043SHong Zhang   PetscInt       ii;
2222c75a6043SHong Zhang   Mat_SeqSBAIJ   *sbaij;
2223c75a6043SHong Zhang 
2224c75a6043SHong Zhang   PetscFunctionBegin;
2225c75a6043SHong Zhang   if (bs != 1) SETERRQ1(PETSC_ERR_SUP,"block size %D > 1 is not supported yet",bs);
2226c75a6043SHong Zhang   if (i[0]) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
2227c75a6043SHong Zhang 
2228c75a6043SHong Zhang   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
2229c75a6043SHong Zhang   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
2230c75a6043SHong Zhang   ierr = MatSetType(*mat,MATSEQSBAIJ);CHKERRQ(ierr);
2231c75a6043SHong Zhang   ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(*mat,bs,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr);
2232c75a6043SHong Zhang   sbaij = (Mat_SeqSBAIJ*)(*mat)->data;
2233c75a6043SHong Zhang   ierr = PetscMalloc2(m,PetscInt,&sbaij->imax,m,PetscInt,&sbaij->ilen);CHKERRQ(ierr);
2234c75a6043SHong Zhang 
2235c75a6043SHong Zhang   sbaij->i = i;
2236c75a6043SHong Zhang   sbaij->j = j;
2237c75a6043SHong Zhang   sbaij->a = a;
2238c75a6043SHong Zhang   sbaij->singlemalloc = PETSC_FALSE;
2239c75a6043SHong Zhang   sbaij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2240e6b907acSBarry Smith   sbaij->free_a       = PETSC_FALSE;
2241e6b907acSBarry Smith   sbaij->free_ij      = PETSC_FALSE;
2242c75a6043SHong Zhang 
2243c75a6043SHong Zhang   for (ii=0; ii<m; ii++) {
2244c75a6043SHong Zhang     sbaij->ilen[ii] = sbaij->imax[ii] = i[ii+1] - i[ii];
2245c75a6043SHong Zhang #if defined(PETSC_USE_DEBUG)
2246c75a6043SHong Zhang     if (i[ii+1] - i[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %d length = %d",ii,i[ii+1] - i[ii]);
2247c75a6043SHong Zhang #endif
2248c75a6043SHong Zhang   }
2249c75a6043SHong Zhang #if defined(PETSC_USE_DEBUG)
2250c75a6043SHong Zhang   for (ii=0; ii<sbaij->i[m]; ii++) {
2251c75a6043SHong Zhang     if (j[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]);
2252c75a6043SHong Zhang     if (j[ii] > n - 1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]);
2253c75a6043SHong Zhang   }
2254c75a6043SHong Zhang #endif
2255c75a6043SHong Zhang 
2256c75a6043SHong Zhang   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2257c75a6043SHong Zhang   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2258c75a6043SHong Zhang   PetscFunctionReturn(0);
2259c75a6043SHong Zhang }
2260d06b337dSHong Zhang 
2261d06b337dSHong Zhang 
2262d06b337dSHong Zhang 
226349b5e25fSSatish Balay 
226449b5e25fSSatish Balay 
2265