xref: /petsc/src/mat/impls/sbaij/seq/sbaij.c (revision a2d7c930c15e95ddda5912518f03f801095d7a75)
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 
10db4efbfdSBarry Smith extern PetscErrorCode MatSeqSBAIJSetNumericFactorization(Mat,PetscTruth);
1149b5e25fSSatish Balay #define CHUNKSIZE  10
1249b5e25fSSatish Balay 
1349b5e25fSSatish Balay /*
1449b5e25fSSatish Balay      Checks for missing diagonals
1549b5e25fSSatish Balay */
164a2ae208SSatish Balay #undef __FUNCT__
174a2ae208SSatish Balay #define __FUNCT__ "MatMissingDiagonal_SeqSBAIJ"
182af78befSBarry Smith PetscErrorCode MatMissingDiagonal_SeqSBAIJ(Mat A,PetscTruth *missing,PetscInt *dd)
1949b5e25fSSatish Balay {
20045c9aa0SHong Zhang   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
216849ba73SBarry Smith   PetscErrorCode ierr;
2213f74950SBarry Smith   PetscInt       *diag,*jj = a->j,i;
2349b5e25fSSatish Balay 
2449b5e25fSSatish Balay   PetscFunctionBegin;
25045c9aa0SHong Zhang   ierr = MatMarkDiagonal_SeqSBAIJ(A);CHKERRQ(ierr);
2649b5e25fSSatish Balay   diag = a->diag;
272af78befSBarry Smith   *missing = PETSC_FALSE;
2849b5e25fSSatish Balay   for (i=0; i<a->mbs; i++) {
292af78befSBarry Smith     if (jj[diag[i]] != i) {
302af78befSBarry Smith       *missing    = PETSC_TRUE;
312af78befSBarry Smith       if (dd) *dd = i;
322af78befSBarry Smith       break;
332af78befSBarry Smith     }
3449b5e25fSSatish Balay   }
3549b5e25fSSatish Balay   PetscFunctionReturn(0);
3649b5e25fSSatish Balay }
3749b5e25fSSatish Balay 
384a2ae208SSatish Balay #undef __FUNCT__
394a2ae208SSatish Balay #define __FUNCT__ "MatMarkDiagonal_SeqSBAIJ"
40dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqSBAIJ(Mat A)
4149b5e25fSSatish Balay {
42045c9aa0SHong Zhang   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
436849ba73SBarry Smith   PetscErrorCode ierr;
4409f38230SBarry Smith   PetscInt       i;
4549b5e25fSSatish Balay 
4649b5e25fSSatish Balay   PetscFunctionBegin;
4709f38230SBarry Smith   if (!a->diag) {
4809f38230SBarry Smith     ierr = PetscMalloc(a->mbs*sizeof(PetscInt),&a->diag);CHKERRQ(ierr);
4909f38230SBarry Smith   }
5009f38230SBarry Smith   for (i=0; i<a->mbs; i++) a->diag[i] = a->i[i];
5149b5e25fSSatish Balay   PetscFunctionReturn(0);
5249b5e25fSSatish Balay }
5349b5e25fSSatish Balay 
544a2ae208SSatish Balay #undef __FUNCT__
554a2ae208SSatish Balay #define __FUNCT__ "MatGetRowIJ_SeqSBAIJ"
568f7157efSSatish Balay static PetscErrorCode MatGetRowIJ_SeqSBAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth blockcompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
5749b5e25fSSatish Balay {
58a6ece127SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
59d0f46423SBarry Smith   PetscInt     i,j,n = a->mbs,nz = a->i[n],bs = A->rmap->bs;
608f7157efSSatish Balay   PetscErrorCode ierr;
6149b5e25fSSatish Balay 
6249b5e25fSSatish Balay   PetscFunctionBegin;
63d3e5a4abSHong Zhang   *nn = n;
64a1373b80SHong Zhang   if (!ia) PetscFunctionReturn(0);
658f7157efSSatish Balay   if (!blockcompressed) {
668f7157efSSatish Balay     /* malloc & create the natural set of indices */
67f1d0d59dSSatish Balay     ierr = PetscMalloc2((n+1)*bs,PetscInt,ia,nz*bs,PetscInt,ja);CHKERRQ(ierr);
688f7157efSSatish Balay     for (i=0; i<n+1; i++) {
698f7157efSSatish Balay       for (j=0; j<bs; j++) {
708f7157efSSatish Balay         *ia[i*bs+j] = a->i[i]*bs+j+oshift;
718f7157efSSatish Balay       }
728f7157efSSatish Balay     }
738f7157efSSatish Balay     for (i=0; i<nz; i++) {
748f7157efSSatish Balay       for (j=0; j<bs; j++) {
758f7157efSSatish Balay         *ja[i*bs+j] = a->j[i]*bs+j+oshift;
768f7157efSSatish Balay       }
778f7157efSSatish Balay     }
788f7157efSSatish Balay   } else { /* blockcompressed */
79a6ece127SHong Zhang     if (oshift == 1) {
80a6ece127SHong Zhang       /* temporarily add 1 to i and j indices */
816c6c5352SBarry Smith       for (i=0; i<nz; i++) a->j[i]++;
82a1373b80SHong Zhang       for (i=0; i<n+1; i++) a->i[i]++;
838f7157efSSatish Balay     }
84a1373b80SHong Zhang     *ia = a->i; *ja = a->j;
85a6ece127SHong Zhang   }
868f7157efSSatish Balay 
8749b5e25fSSatish Balay   PetscFunctionReturn(0);
8849b5e25fSSatish Balay }
8949b5e25fSSatish Balay 
904a2ae208SSatish Balay #undef __FUNCT__
914a2ae208SSatish Balay #define __FUNCT__ "MatRestoreRowIJ_SeqSBAIJ"
928f7157efSSatish Balay static PetscErrorCode MatRestoreRowIJ_SeqSBAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth blockcompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
9349b5e25fSSatish Balay {
94b7aaefc3SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
958f7157efSSatish Balay   PetscInt     i,n = a->mbs,nz = a->i[n];
968f7157efSSatish Balay   PetscErrorCode ierr;
97a6ece127SHong Zhang 
9849b5e25fSSatish Balay   PetscFunctionBegin;
9949b5e25fSSatish Balay   if (!ia) PetscFunctionReturn(0);
100a6ece127SHong Zhang 
1018f7157efSSatish Balay   if (!blockcompressed) {
1028f7157efSSatish Balay     ierr = PetscFree2(*ia,*ja);CHKERRQ(ierr);
1038f7157efSSatish Balay   } else if (oshift == 1) { /* blockcompressed */
1046c6c5352SBarry Smith     for (i=0; i<nz; i++) a->j[i]--;
105a6ece127SHong Zhang     for (i=0; i<n+1; i++) a->i[i]--;
106a6ece127SHong Zhang   }
1078f7157efSSatish Balay 
108a6ece127SHong Zhang   PetscFunctionReturn(0);
10949b5e25fSSatish Balay }
11049b5e25fSSatish Balay 
1114a2ae208SSatish Balay #undef __FUNCT__
1124a2ae208SSatish Balay #define __FUNCT__ "MatDestroy_SeqSBAIJ"
113dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqSBAIJ(Mat A)
11449b5e25fSSatish Balay {
11549b5e25fSSatish Balay   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
116dfbe8321SBarry Smith   PetscErrorCode ierr;
11749b5e25fSSatish Balay 
11849b5e25fSSatish Balay   PetscFunctionBegin;
119a9f03627SSatish Balay #if defined(PETSC_USE_LOG)
120d0f46423SBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%D, NZ=%D",A->rmap->N,a->nz);
121a9f03627SSatish Balay #endif
122e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
1239bfd6278SHong Zhang   if (a->row) {ierr = ISDestroy(a->row);CHKERRQ(ierr);}
1249bfd6278SHong Zhang   if (a->col){ierr = ISDestroy(a->col);CHKERRQ(ierr);}
1259bfd6278SHong Zhang   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);}
126061b2667SBarry Smith   if (a->idiag) {ierr = PetscFree(a->idiag);CHKERRQ(ierr);}
1270def2e27SBarry Smith   if (a->inode.size) {ierr = PetscFree(a->inode.size);CHKERRQ(ierr);}
12805b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
12905b42c5fSBarry Smith   ierr = PetscFree2(a->imax,a->ilen);CHKERRQ(ierr);
13005b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
131e2ee2a47SBarry Smith   ierr = PetscFree(a->relax_work);CHKERRQ(ierr);
13205b42c5fSBarry Smith   ierr = PetscFree(a->solves_work);CHKERRQ(ierr);
13305b42c5fSBarry Smith   ierr = PetscFree(a->mult_work);CHKERRQ(ierr);
13405b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
13505b42c5fSBarry Smith   ierr = PetscFree(a->xtoy);CHKERRQ(ierr);
1361a3463dfSHong Zhang 
1371a3463dfSHong Zhang   ierr = PetscFree(a->inew);CHKERRQ(ierr);
13849b5e25fSSatish Balay   ierr = PetscFree(a);CHKERRQ(ierr);
139901853e0SKris Buschelman 
140dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
141901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C","",PETSC_NULL);CHKERRQ(ierr);
142901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C","",PETSC_NULL);CHKERRQ(ierr);
143901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqSBAIJSetColumnIndices_C","",PETSC_NULL);CHKERRQ(ierr);
144901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqsbaij_seqaij_C","",PETSC_NULL);CHKERRQ(ierr);
145901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqsbaij_seqbaij_C","",PETSC_NULL);CHKERRQ(ierr);
146901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqSBAIJSetPreallocation_C","",PETSC_NULL);CHKERRQ(ierr);
14749b5e25fSSatish Balay   PetscFunctionReturn(0);
14849b5e25fSSatish Balay }
14949b5e25fSSatish Balay 
1504a2ae208SSatish Balay #undef __FUNCT__
1514a2ae208SSatish Balay #define __FUNCT__ "MatSetOption_SeqSBAIJ"
1524e0d8c25SBarry Smith PetscErrorCode MatSetOption_SeqSBAIJ(Mat A,MatOption op,PetscTruth flg)
15349b5e25fSSatish Balay {
154045c9aa0SHong Zhang   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
15563ba0a88SBarry Smith   PetscErrorCode ierr;
15649b5e25fSSatish Balay 
15749b5e25fSSatish Balay   PetscFunctionBegin;
1584d9d31abSKris Buschelman   switch (op) {
1594d9d31abSKris Buschelman   case MAT_ROW_ORIENTED:
1604e0d8c25SBarry Smith     a->roworiented = flg;
1614d9d31abSKris Buschelman     break;
162a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
163a9817697SBarry Smith     a->keepnonzeropattern = flg;
1644d9d31abSKris Buschelman     break;
165512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
166512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1674d9d31abSKris Buschelman     break;
1684d9d31abSKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
1694e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1704d9d31abSKris Buschelman     break;
1714d9d31abSKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
1724e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1734d9d31abSKris Buschelman     break;
17428b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
17528b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
17628b2fa4aSMatthew Knepley     break;
1774e0d8c25SBarry Smith   case MAT_NEW_DIAGONALS:
1784d9d31abSKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1794d9d31abSKris Buschelman   case MAT_USE_HASH_TABLE:
180290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1814d9d31abSKris Buschelman     break;
1829a4540c5SBarry Smith   case MAT_HERMITIAN:
1834e0d8c25SBarry Smith     if (flg) SETERRQ(PETSC_ERR_SUP,"Matrix must be symmetric");
18477e54ba9SKris Buschelman   case MAT_SYMMETRIC:
18577e54ba9SKris Buschelman   case MAT_STRUCTURALLY_SYMMETRIC:
1869a4540c5SBarry Smith   case MAT_SYMMETRY_ETERNAL:
1874e0d8c25SBarry Smith     if (!flg) SETERRQ(PETSC_ERR_SUP,"Matrix must be symmetric");
188290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s not relevent\n",MatOptions[op]);CHKERRQ(ierr);
189290bbb0aSBarry Smith     break;
190941593c8SHong Zhang   case MAT_IGNORE_LOWER_TRIANGULAR:
1914e0d8c25SBarry Smith     a->ignore_ltriangular = flg;
192941593c8SHong Zhang     break;
193941593c8SHong Zhang   case MAT_ERROR_LOWER_TRIANGULAR:
1944e0d8c25SBarry Smith     a->ignore_ltriangular = flg;
19577e54ba9SKris Buschelman     break;
196f5edf698SHong Zhang   case MAT_GETROW_UPPERTRIANGULAR:
1974e0d8c25SBarry Smith     a->getrow_utriangular = flg;
198f5edf698SHong Zhang     break;
1994d9d31abSKris Buschelman   default:
200ad86a440SBarry Smith     SETERRQ1(PETSC_ERR_SUP,"unknown option %d",op);
20149b5e25fSSatish Balay   }
20249b5e25fSSatish Balay   PetscFunctionReturn(0);
20349b5e25fSSatish Balay }
20449b5e25fSSatish Balay 
2054a2ae208SSatish Balay #undef __FUNCT__
2064a2ae208SSatish Balay #define __FUNCT__ "MatGetRow_SeqSBAIJ"
20713f74950SBarry Smith PetscErrorCode MatGetRow_SeqSBAIJ(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **v)
20849b5e25fSSatish Balay {
20949b5e25fSSatish Balay   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
2106849ba73SBarry Smith   PetscErrorCode ierr;
21113f74950SBarry Smith   PetscInt       itmp,i,j,k,M,*ai,*aj,bs,bn,bp,*cols_i,bs2;
21249b5e25fSSatish Balay   MatScalar      *aa,*aa_i;
21387828ca2SBarry Smith   PetscScalar    *v_i;
21449b5e25fSSatish Balay 
21549b5e25fSSatish Balay   PetscFunctionBegin;
2164e0d8c25SBarry 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()");
217f5edf698SHong Zhang   /* Get the upper triangular part of the row */
218d0f46423SBarry Smith   bs  = A->rmap->bs;
21949b5e25fSSatish Balay   ai  = a->i;
22049b5e25fSSatish Balay   aj  = a->j;
22149b5e25fSSatish Balay   aa  = a->a;
22249b5e25fSSatish Balay   bs2 = a->bs2;
22349b5e25fSSatish Balay 
224d0f46423SBarry Smith   if (row < 0 || row >= A->rmap->N) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Row %D out of range", row);
22549b5e25fSSatish Balay 
22649b5e25fSSatish Balay   bn  = row/bs;   /* Block number */
22749b5e25fSSatish Balay   bp  = row % bs; /* Block position */
22849b5e25fSSatish Balay   M   = ai[bn+1] - ai[bn];
22949b5e25fSSatish Balay   *ncols = bs*M;
23049b5e25fSSatish Balay 
23149b5e25fSSatish Balay   if (v) {
23249b5e25fSSatish Balay     *v = 0;
23349b5e25fSSatish Balay     if (*ncols) {
23487828ca2SBarry Smith       ierr = PetscMalloc((*ncols+row)*sizeof(PetscScalar),v);CHKERRQ(ierr);
23549b5e25fSSatish Balay       for (i=0; i<M; i++) { /* for each block in the block row */
23649b5e25fSSatish Balay         v_i  = *v + i*bs;
23749b5e25fSSatish Balay         aa_i = aa + bs2*(ai[bn] + i);
23849b5e25fSSatish Balay         for (j=bp,k=0; j<bs2; j+=bs,k++) {v_i[k] = aa_i[j];}
23949b5e25fSSatish Balay       }
24049b5e25fSSatish Balay     }
24149b5e25fSSatish Balay   }
24249b5e25fSSatish Balay 
24349b5e25fSSatish Balay   if (cols) {
24449b5e25fSSatish Balay     *cols = 0;
24549b5e25fSSatish Balay     if (*ncols) {
24613f74950SBarry Smith       ierr = PetscMalloc((*ncols+row)*sizeof(PetscInt),cols);CHKERRQ(ierr);
24749b5e25fSSatish Balay       for (i=0; i<M; i++) { /* for each block in the block row */
24849b5e25fSSatish Balay         cols_i = *cols + i*bs;
24949b5e25fSSatish Balay         itmp  = bs*aj[ai[bn] + i];
25049b5e25fSSatish Balay         for (j=0; j<bs; j++) {cols_i[j] = itmp++;}
25149b5e25fSSatish Balay       }
25249b5e25fSSatish Balay     }
25349b5e25fSSatish Balay   }
25449b5e25fSSatish Balay 
25549b5e25fSSatish Balay   /*search column A(0:row-1,row) (=A(row,0:row-1)). Could be expensive! */
2565ddb2528SHong Zhang   /* this segment is currently removed, so only entries in the upper triangle are obtained */
2575ddb2528SHong Zhang #ifdef column_search
25849b5e25fSSatish Balay   v_i    = *v    + M*bs;
25949b5e25fSSatish Balay   cols_i = *cols + M*bs;
26049b5e25fSSatish Balay   for (i=0; i<bn; i++){ /* for each block row */
26149b5e25fSSatish Balay     M = ai[i+1] - ai[i];
26249b5e25fSSatish Balay     for (j=0; j<M; j++){
26349b5e25fSSatish Balay       itmp = aj[ai[i] + j];    /* block column value */
26449b5e25fSSatish Balay       if (itmp == bn){
26549b5e25fSSatish Balay         aa_i   = aa    + bs2*(ai[i] + j) + bs*bp;
26649b5e25fSSatish Balay         for (k=0; k<bs; k++) {
26749b5e25fSSatish Balay           *cols_i++ = i*bs+k;
26849b5e25fSSatish Balay           *v_i++    = aa_i[k];
26949b5e25fSSatish Balay         }
27049b5e25fSSatish Balay         *ncols += bs;
27149b5e25fSSatish Balay         break;
27249b5e25fSSatish Balay       }
27349b5e25fSSatish Balay     }
27449b5e25fSSatish Balay   }
2755ddb2528SHong Zhang #endif
27649b5e25fSSatish Balay   PetscFunctionReturn(0);
27749b5e25fSSatish Balay }
27849b5e25fSSatish Balay 
2794a2ae208SSatish Balay #undef __FUNCT__
2804a2ae208SSatish Balay #define __FUNCT__ "MatRestoreRow_SeqSBAIJ"
28113f74950SBarry Smith PetscErrorCode MatRestoreRow_SeqSBAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
28249b5e25fSSatish Balay {
283dfbe8321SBarry Smith   PetscErrorCode ierr;
28449b5e25fSSatish Balay 
28549b5e25fSSatish Balay   PetscFunctionBegin;
28605b42c5fSBarry Smith   if (idx) {ierr = PetscFree(*idx);CHKERRQ(ierr);}
28705b42c5fSBarry Smith   if (v)   {ierr = PetscFree(*v);CHKERRQ(ierr);}
28849b5e25fSSatish Balay   PetscFunctionReturn(0);
28949b5e25fSSatish Balay }
29049b5e25fSSatish Balay 
2914a2ae208SSatish Balay #undef __FUNCT__
292f5edf698SHong Zhang #define __FUNCT__ "MatGetRowUpperTriangular_SeqSBAIJ"
293f5edf698SHong Zhang PetscErrorCode MatGetRowUpperTriangular_SeqSBAIJ(Mat A)
294f5edf698SHong Zhang {
295f5edf698SHong Zhang   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
296f5edf698SHong Zhang 
297f5edf698SHong Zhang   PetscFunctionBegin;
298f5edf698SHong Zhang   a->getrow_utriangular = PETSC_TRUE;
299f5edf698SHong Zhang   PetscFunctionReturn(0);
300f5edf698SHong Zhang }
301f5edf698SHong Zhang #undef __FUNCT__
302f5edf698SHong Zhang #define __FUNCT__ "MatRestoreRowUpperTriangular_SeqSBAIJ"
303f5edf698SHong Zhang PetscErrorCode MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A)
304f5edf698SHong Zhang {
305f5edf698SHong Zhang   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
306f5edf698SHong Zhang 
307f5edf698SHong Zhang   PetscFunctionBegin;
308f5edf698SHong Zhang   a->getrow_utriangular = PETSC_FALSE;
309f5edf698SHong Zhang   PetscFunctionReturn(0);
310f5edf698SHong Zhang }
311f5edf698SHong Zhang 
312f5edf698SHong Zhang #undef __FUNCT__
3134a2ae208SSatish Balay #define __FUNCT__ "MatTranspose_SeqSBAIJ"
314fc4dec0aSBarry Smith PetscErrorCode MatTranspose_SeqSBAIJ(Mat A,MatReuse reuse,Mat *B)
31549b5e25fSSatish Balay {
316dfbe8321SBarry Smith   PetscErrorCode ierr;
31749b5e25fSSatish Balay   PetscFunctionBegin;
318815cbec1SBarry Smith   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
319999d9058SBarry Smith     ierr = MatDuplicate(A,MAT_COPY_VALUES,B);CHKERRQ(ierr);
320fc4dec0aSBarry Smith   }
3218115998fSBarry Smith   PetscFunctionReturn(0);
32249b5e25fSSatish Balay }
32349b5e25fSSatish Balay 
3244a2ae208SSatish Balay #undef __FUNCT__
3254a2ae208SSatish Balay #define __FUNCT__ "MatView_SeqSBAIJ_ASCII"
3266849ba73SBarry Smith static PetscErrorCode MatView_SeqSBAIJ_ASCII(Mat A,PetscViewer viewer)
32749b5e25fSSatish Balay {
32849b5e25fSSatish Balay   Mat_SeqSBAIJ      *a = (Mat_SeqSBAIJ*)A->data;
329dfbe8321SBarry Smith   PetscErrorCode    ierr;
330d0f46423SBarry Smith   PetscInt          i,j,bs = A->rmap->bs,k,l,bs2=a->bs2;
3312dcb1b2aSMatthew Knepley   const char        *name;
332f3ef73ceSBarry Smith   PetscViewerFormat format;
33349b5e25fSSatish Balay 
33449b5e25fSSatish Balay   PetscFunctionBegin;
33580fe4e49SBarry Smith   ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
336b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
337456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
33877431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  block size is %D\n",bs);CHKERRQ(ierr);
339fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_MATLAB) {
340d2507d54SMatthew Knepley     Mat aij;
341d2507d54SMatthew Knepley 
34270d5e725SHong Zhang     if (A->factor && bs>1){
34370d5e725SHong 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);
34470d5e725SHong Zhang       PetscFunctionReturn(0);
34570d5e725SHong Zhang     }
346c9f458caSMatthew Knepley     ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&aij);CHKERRQ(ierr);
347c9f458caSMatthew Knepley     ierr = MatView(aij,viewer);CHKERRQ(ierr);
348c9f458caSMatthew Knepley     ierr = MatDestroy(aij);CHKERRQ(ierr);
349fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
350b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
35149b5e25fSSatish Balay     for (i=0; i<a->mbs; i++) {
35249b5e25fSSatish Balay       for (j=0; j<bs; j++) {
35377431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i*bs+j);CHKERRQ(ierr);
35449b5e25fSSatish Balay         for (k=a->i[i]; k<a->i[i+1]; k++) {
35549b5e25fSSatish Balay           for (l=0; l<bs; l++) {
35649b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX)
35749b5e25fSSatish Balay             if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
358a83599f4SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i) ",bs*a->j[k]+l,
35949b5e25fSSatish Balay                                             PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
36049b5e25fSSatish Balay             } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
361a83599f4SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i) ",bs*a->j[k]+l,
36249b5e25fSSatish Balay                                             PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
36349b5e25fSSatish Balay             } else if (PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
364a83599f4SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
36549b5e25fSSatish Balay             }
36649b5e25fSSatish Balay #else
36749b5e25fSSatish Balay             if (a->a[bs2*k + l*bs + j] != 0.0) {
368a83599f4SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);CHKERRQ(ierr);
36949b5e25fSSatish Balay             }
37049b5e25fSSatish Balay #endif
37149b5e25fSSatish Balay           }
37249b5e25fSSatish Balay         }
373b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
37449b5e25fSSatish Balay       }
37549b5e25fSSatish Balay     }
376b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
377c1490034SHong Zhang   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
378c1490034SHong Zhang      PetscFunctionReturn(0);
37949b5e25fSSatish Balay   } else {
3808608aa04SHong Zhang     if (A->factor && bs>1){
3818608aa04SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"Warning: matrix is factored. MatView_SeqSBAIJ_ASCII() may not display complete or logically correct entries!\n");CHKERRQ(ierr);
3828608aa04SHong Zhang     }
383b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
38449b5e25fSSatish Balay     for (i=0; i<a->mbs; i++) {
38549b5e25fSSatish Balay       for (j=0; j<bs; j++) {
38677431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i*bs+j);CHKERRQ(ierr);
38749b5e25fSSatish Balay         for (k=a->i[i]; k<a->i[i+1]; k++) {
38849b5e25fSSatish Balay           for (l=0; l<bs; l++) {
38949b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX)
39049b5e25fSSatish Balay             if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0) {
391a83599f4SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i) ",bs*a->j[k]+l,
39249b5e25fSSatish Balay                                             PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
39349b5e25fSSatish Balay             } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0) {
394a83599f4SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i) ",bs*a->j[k]+l,
39549b5e25fSSatish Balay                                             PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
39649b5e25fSSatish Balay             } else {
397a83599f4SBarry Smith               ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr);
39849b5e25fSSatish Balay             }
39949b5e25fSSatish Balay #else
400e9f7bc9eSHong Zhang             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);CHKERRQ(ierr);
40149b5e25fSSatish Balay #endif
40249b5e25fSSatish Balay           }
40349b5e25fSSatish Balay         }
404b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
40549b5e25fSSatish Balay       }
40649b5e25fSSatish Balay     }
407b0a32e0cSBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
40849b5e25fSSatish Balay   }
409b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
41049b5e25fSSatish Balay   PetscFunctionReturn(0);
41149b5e25fSSatish Balay }
41249b5e25fSSatish Balay 
4134a2ae208SSatish Balay #undef __FUNCT__
4144a2ae208SSatish Balay #define __FUNCT__ "MatView_SeqSBAIJ_Draw_Zoom"
4156849ba73SBarry Smith static PetscErrorCode MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
41649b5e25fSSatish Balay {
41749b5e25fSSatish Balay   Mat            A = (Mat) Aa;
41849b5e25fSSatish Balay   Mat_SeqSBAIJ   *a=(Mat_SeqSBAIJ*)A->data;
4196849ba73SBarry Smith   PetscErrorCode ierr;
420d0f46423SBarry Smith   PetscInt       row,i,j,k,l,mbs=a->mbs,color,bs=A->rmap->bs,bs2=a->bs2;
42113f74950SBarry Smith   PetscMPIInt    rank;
42249b5e25fSSatish Balay   PetscReal      xl,yl,xr,yr,x_l,x_r,y_l,y_r;
42349b5e25fSSatish Balay   MatScalar      *aa;
42449b5e25fSSatish Balay   MPI_Comm       comm;
425b0a32e0cSBarry Smith   PetscViewer    viewer;
42649b5e25fSSatish Balay 
42749b5e25fSSatish Balay   PetscFunctionBegin;
42849b5e25fSSatish Balay   /*
42949b5e25fSSatish Balay     This is nasty. If this is called from an originally parallel matrix
43049b5e25fSSatish Balay     then all processes call this,but only the first has the matrix so the
43149b5e25fSSatish Balay     rest should return immediately.
43249b5e25fSSatish Balay   */
43349b5e25fSSatish Balay   ierr = PetscObjectGetComm((PetscObject)draw,&comm);CHKERRQ(ierr);
43449b5e25fSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
43549b5e25fSSatish Balay   if (rank) PetscFunctionReturn(0);
43649b5e25fSSatish Balay 
43749b5e25fSSatish Balay   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
43849b5e25fSSatish Balay 
439b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
440b0a32e0cSBarry Smith   PetscDrawString(draw, .3*(xl+xr), .3*(yl+yr), PETSC_DRAW_BLACK, "symmetric");
44149b5e25fSSatish Balay 
44249b5e25fSSatish Balay   /* loop over matrix elements drawing boxes */
443b0a32e0cSBarry Smith   color = PETSC_DRAW_BLUE;
44449b5e25fSSatish Balay   for (i=0,row=0; i<mbs; i++,row+=bs) {
44549b5e25fSSatish Balay     for (j=a->i[i]; j<a->i[i+1]; j++) {
446d0f46423SBarry Smith       y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0;
44749b5e25fSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
44849b5e25fSSatish Balay       aa = a->a + j*bs2;
44949b5e25fSSatish Balay       for (k=0; k<bs; k++) {
45049b5e25fSSatish Balay         for (l=0; l<bs; l++) {
45149b5e25fSSatish Balay           if (PetscRealPart(*aa++) >=  0.) continue;
452b0a32e0cSBarry Smith           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
45349b5e25fSSatish Balay         }
45449b5e25fSSatish Balay       }
45549b5e25fSSatish Balay     }
45649b5e25fSSatish Balay   }
457b0a32e0cSBarry Smith   color = PETSC_DRAW_CYAN;
45849b5e25fSSatish Balay   for (i=0,row=0; i<mbs; i++,row+=bs) {
45949b5e25fSSatish Balay     for (j=a->i[i]; j<a->i[i+1]; j++) {
460d0f46423SBarry Smith       y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0;
46149b5e25fSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
46249b5e25fSSatish Balay       aa = a->a + j*bs2;
46349b5e25fSSatish Balay       for (k=0; k<bs; k++) {
46449b5e25fSSatish Balay         for (l=0; l<bs; l++) {
46549b5e25fSSatish Balay           if (PetscRealPart(*aa++) != 0.) continue;
466b0a32e0cSBarry Smith           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
46749b5e25fSSatish Balay         }
46849b5e25fSSatish Balay       }
46949b5e25fSSatish Balay     }
47049b5e25fSSatish Balay   }
47149b5e25fSSatish Balay 
472b0a32e0cSBarry Smith   color = PETSC_DRAW_RED;
47349b5e25fSSatish Balay   for (i=0,row=0; i<mbs; i++,row+=bs) {
47449b5e25fSSatish Balay     for (j=a->i[i]; j<a->i[i+1]; j++) {
475d0f46423SBarry Smith       y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0;
47649b5e25fSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
47749b5e25fSSatish Balay       aa = a->a + j*bs2;
47849b5e25fSSatish Balay       for (k=0; k<bs; k++) {
47949b5e25fSSatish Balay         for (l=0; l<bs; l++) {
48049b5e25fSSatish Balay           if (PetscRealPart(*aa++) <= 0.) continue;
481b0a32e0cSBarry Smith           ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr);
48249b5e25fSSatish Balay         }
48349b5e25fSSatish Balay       }
48449b5e25fSSatish Balay     }
48549b5e25fSSatish Balay   }
48649b5e25fSSatish Balay   PetscFunctionReturn(0);
48749b5e25fSSatish Balay }
48849b5e25fSSatish Balay 
4894a2ae208SSatish Balay #undef __FUNCT__
4904a2ae208SSatish Balay #define __FUNCT__ "MatView_SeqSBAIJ_Draw"
4916849ba73SBarry Smith static PetscErrorCode MatView_SeqSBAIJ_Draw(Mat A,PetscViewer viewer)
49249b5e25fSSatish Balay {
493dfbe8321SBarry Smith   PetscErrorCode ierr;
49449b5e25fSSatish Balay   PetscReal      xl,yl,xr,yr,w,h;
495b0a32e0cSBarry Smith   PetscDraw      draw;
49649b5e25fSSatish Balay   PetscTruth     isnull;
49749b5e25fSSatish Balay 
49849b5e25fSSatish Balay   PetscFunctionBegin;
499b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
500b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
50149b5e25fSSatish Balay 
50249b5e25fSSatish Balay   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
503d0f46423SBarry Smith   xr  = A->rmap->N; yr = A->rmap->N; h = yr/10.0; w = xr/10.0;
50449b5e25fSSatish Balay   xr += w;    yr += h;  xl = -w;     yl = -h;
505b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
506b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqSBAIJ_Draw_Zoom,A);CHKERRQ(ierr);
50749b5e25fSSatish Balay   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
50849b5e25fSSatish Balay   PetscFunctionReturn(0);
50949b5e25fSSatish Balay }
51049b5e25fSSatish Balay 
5114a2ae208SSatish Balay #undef __FUNCT__
5124a2ae208SSatish Balay #define __FUNCT__ "MatView_SeqSBAIJ"
513dfbe8321SBarry Smith PetscErrorCode MatView_SeqSBAIJ(Mat A,PetscViewer viewer)
51449b5e25fSSatish Balay {
515dfbe8321SBarry Smith   PetscErrorCode ierr;
51632077d6dSBarry Smith   PetscTruth     iascii,isdraw;
51749b5e25fSSatish Balay 
51849b5e25fSSatish Balay   PetscFunctionBegin;
51932077d6dSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
520fb9695e5SSatish Balay   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
52132077d6dSBarry Smith   if (iascii){
52249b5e25fSSatish Balay     ierr = MatView_SeqSBAIJ_ASCII(A,viewer);CHKERRQ(ierr);
52349b5e25fSSatish Balay   } else if (isdraw) {
52449b5e25fSSatish Balay     ierr = MatView_SeqSBAIJ_Draw(A,viewer);CHKERRQ(ierr);
52549b5e25fSSatish Balay   } else {
526a5e6ed63SBarry Smith     Mat B;
527ceb03754SKris Buschelman     ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
528a5e6ed63SBarry Smith     ierr = MatView(B,viewer);CHKERRQ(ierr);
529a5e6ed63SBarry Smith     ierr = MatDestroy(B);CHKERRQ(ierr);
53049b5e25fSSatish Balay   }
53149b5e25fSSatish Balay   PetscFunctionReturn(0);
53249b5e25fSSatish Balay }
53349b5e25fSSatish Balay 
53449b5e25fSSatish Balay 
5354a2ae208SSatish Balay #undef __FUNCT__
5364a2ae208SSatish Balay #define __FUNCT__ "MatGetValues_SeqSBAIJ"
53713f74950SBarry Smith PetscErrorCode MatGetValues_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
53849b5e25fSSatish Balay {
539045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
54013f74950SBarry Smith   PetscInt     *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
54113f74950SBarry Smith   PetscInt     *ai = a->i,*ailen = a->ilen;
542d0f46423SBarry Smith   PetscInt     brow,bcol,ridx,cidx,bs=A->rmap->bs,bs2=a->bs2;
54397e567efSBarry Smith   MatScalar    *ap,*aa = a->a;
54449b5e25fSSatish Balay 
54549b5e25fSSatish Balay   PetscFunctionBegin;
54649b5e25fSSatish Balay   for (k=0; k<m; k++) { /* loop over rows */
54749b5e25fSSatish Balay     row  = im[k]; brow = row/bs;
54897e567efSBarry Smith     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
549d0f46423SBarry Smith     if (row >= A->rmap->N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->N-1);
55049b5e25fSSatish Balay     rp   = aj + ai[brow] ; ap = aa + bs2*ai[brow] ;
55149b5e25fSSatish Balay     nrow = ailen[brow];
55249b5e25fSSatish Balay     for (l=0; l<n; l++) { /* loop over columns */
55397e567efSBarry Smith       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
554d0f46423SBarry 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);
55549b5e25fSSatish Balay       col  = in[l] ;
55649b5e25fSSatish Balay       bcol = col/bs;
55749b5e25fSSatish Balay       cidx = col%bs;
55849b5e25fSSatish Balay       ridx = row%bs;
55949b5e25fSSatish Balay       high = nrow;
56049b5e25fSSatish Balay       low  = 0; /* assume unsorted */
56149b5e25fSSatish Balay       while (high-low > 5) {
56249b5e25fSSatish Balay         t = (low+high)/2;
56349b5e25fSSatish Balay         if (rp[t] > bcol) high = t;
56449b5e25fSSatish Balay         else             low  = t;
56549b5e25fSSatish Balay       }
56649b5e25fSSatish Balay       for (i=low; i<high; i++) {
56749b5e25fSSatish Balay         if (rp[i] > bcol) break;
56849b5e25fSSatish Balay         if (rp[i] == bcol) {
56949b5e25fSSatish Balay           *v++ = ap[bs2*i+bs*cidx+ridx];
57049b5e25fSSatish Balay           goto finished;
57149b5e25fSSatish Balay         }
57249b5e25fSSatish Balay       }
57397e567efSBarry Smith       *v++ = 0.0;
57449b5e25fSSatish Balay       finished:;
57549b5e25fSSatish Balay     }
57649b5e25fSSatish Balay   }
57749b5e25fSSatish Balay   PetscFunctionReturn(0);
57849b5e25fSSatish Balay }
57949b5e25fSSatish Balay 
58049b5e25fSSatish Balay 
5814a2ae208SSatish Balay #undef __FUNCT__
5824a2ae208SSatish Balay #define __FUNCT__ "MatSetValuesBlocked_SeqSBAIJ"
58313f74950SBarry Smith PetscErrorCode MatSetValuesBlocked_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
58449b5e25fSSatish Balay {
5850880e062SHong Zhang   Mat_SeqSBAIJ      *a = (Mat_SeqSBAIJ*)A->data;
5866849ba73SBarry Smith   PetscErrorCode    ierr;
587e2ee6c50SBarry Smith   PetscInt          *rp,k,low,high,t,ii,jj,row,nrow,i,col,l,rmax,N,lastcol = -1;
58813f74950SBarry Smith   PetscInt          *imax=a->imax,*ai=a->i,*ailen=a->ilen;
589d0f46423SBarry Smith   PetscInt          *aj=a->j,nonew=a->nonew,bs2=a->bs2,bs=A->rmap->bs,stepval;
5900880e062SHong Zhang   PetscTruth        roworiented=a->roworiented;
591dd6ea824SBarry Smith   const PetscScalar *value = v;
592f15d580aSBarry Smith   MatScalar         *ap,*aa = a->a,*bap;
5930880e062SHong Zhang 
59449b5e25fSSatish Balay   PetscFunctionBegin;
5950880e062SHong Zhang   if (roworiented) {
5960880e062SHong Zhang     stepval = (n-1)*bs;
5970880e062SHong Zhang   } else {
5980880e062SHong Zhang     stepval = (m-1)*bs;
5990880e062SHong Zhang   }
6000880e062SHong Zhang   for (k=0; k<m; k++) { /* loop over added rows */
6010880e062SHong Zhang     row  = im[k];
6020880e062SHong Zhang     if (row < 0) continue;
6032515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
60477431f27SBarry Smith     if (row >= a->mbs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,a->mbs-1);
6050880e062SHong Zhang #endif
6060880e062SHong Zhang     rp   = aj + ai[row];
6070880e062SHong Zhang     ap   = aa + bs2*ai[row];
6080880e062SHong Zhang     rmax = imax[row];
6090880e062SHong Zhang     nrow = ailen[row];
6100880e062SHong Zhang     low  = 0;
611818f2c47SBarry Smith     high = nrow;
6120880e062SHong Zhang     for (l=0; l<n; l++) { /* loop over added columns */
6130880e062SHong Zhang       if (in[l] < 0) continue;
6140880e062SHong Zhang       col = in[l];
6152515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
61677431f27SBarry Smith       if (col >= a->nbs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",col,a->nbs-1);
617b1823623SSatish Balay #endif
6180880e062SHong Zhang       if (col < row) continue; /* ignore lower triangular block */
6190880e062SHong Zhang       if (roworiented) {
6200880e062SHong Zhang         value = v + k*(stepval+bs)*bs + l*bs;
6210880e062SHong Zhang       } else {
6220880e062SHong Zhang         value = v + l*(stepval+bs)*bs + k*bs;
6230880e062SHong Zhang       }
6247cd84e04SBarry Smith       if (col <= lastcol) low = 0; else high = nrow;
625e2ee6c50SBarry Smith       lastcol = col;
6260880e062SHong Zhang       while (high-low > 7) {
6270880e062SHong Zhang         t = (low+high)/2;
6280880e062SHong Zhang         if (rp[t] > col) high = t;
6290880e062SHong Zhang         else             low  = t;
6300880e062SHong Zhang       }
6310880e062SHong Zhang       for (i=low; i<high; i++) {
6320880e062SHong Zhang         if (rp[i] > col) break;
6330880e062SHong Zhang         if (rp[i] == col) {
6340880e062SHong Zhang           bap  = ap +  bs2*i;
6350880e062SHong Zhang           if (roworiented) {
6360880e062SHong Zhang             if (is == ADD_VALUES) {
6370880e062SHong Zhang               for (ii=0; ii<bs; ii++,value+=stepval) {
6380880e062SHong Zhang                 for (jj=ii; jj<bs2; jj+=bs) {
6390880e062SHong Zhang                   bap[jj] += *value++;
6400880e062SHong Zhang                 }
6410880e062SHong Zhang               }
6420880e062SHong Zhang             } else {
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             }
6490880e062SHong Zhang           } else {
6500880e062SHong Zhang             if (is == ADD_VALUES) {
6510880e062SHong Zhang               for (ii=0; ii<bs; ii++,value+=stepval) {
6520880e062SHong Zhang                 for (jj=0; jj<bs; jj++) {
6530880e062SHong Zhang                   *bap++ += *value++;
6540880e062SHong Zhang                 }
6550880e062SHong Zhang               }
6560880e062SHong Zhang             } else {
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             }
6630880e062SHong Zhang           }
6640880e062SHong Zhang           goto noinsert2;
6650880e062SHong Zhang         }
6660880e062SHong Zhang       }
6670880e062SHong Zhang       if (nonew == 1) goto noinsert2;
668085a36d4SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col);
669421e10b8SBarry Smith       MatSeqXAIJReallocateAIJ(A,a->mbs,bs2,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
670c03d1d03SSatish Balay       N = nrow++ - 1; high++;
6710880e062SHong Zhang       /* shift up all the later entries in this row */
6720880e062SHong Zhang       for (ii=N; ii>=i; ii--) {
6730880e062SHong Zhang         rp[ii+1] = rp[ii];
6740880e062SHong Zhang         ierr = PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));CHKERRQ(ierr);
6750880e062SHong Zhang       }
6760880e062SHong Zhang       if (N >= i) {
6770880e062SHong Zhang         ierr = PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));CHKERRQ(ierr);
6780880e062SHong Zhang       }
6790880e062SHong Zhang       rp[i] = col;
6800880e062SHong Zhang       bap   = ap +  bs2*i;
6810880e062SHong Zhang       if (roworiented) {
6820880e062SHong Zhang         for (ii=0; ii<bs; ii++,value+=stepval) {
6830880e062SHong Zhang           for (jj=ii; jj<bs2; jj+=bs) {
6840880e062SHong Zhang             bap[jj] = *value++;
6850880e062SHong Zhang           }
6860880e062SHong Zhang         }
6870880e062SHong Zhang       } else {
6880880e062SHong Zhang         for (ii=0; ii<bs; ii++,value+=stepval) {
6890880e062SHong Zhang           for (jj=0; jj<bs; jj++) {
6900880e062SHong Zhang             *bap++  = *value++;
6910880e062SHong Zhang           }
6920880e062SHong Zhang         }
6930880e062SHong Zhang        }
6940880e062SHong Zhang     noinsert2:;
6950880e062SHong Zhang       low = i;
6960880e062SHong Zhang     }
6970880e062SHong Zhang     ailen[row] = nrow;
6980880e062SHong Zhang   }
6990880e062SHong Zhang    PetscFunctionReturn(0);
70049b5e25fSSatish Balay }
70149b5e25fSSatish Balay 
70264831d72SBarry Smith /*
70364831d72SBarry Smith     This is not yet used
70464831d72SBarry Smith */
7054a2ae208SSatish Balay #undef __FUNCT__
7060def2e27SBarry Smith #define __FUNCT__ "MatAssemblyEnd_SeqSBAIJ_Inode"
7070def2e27SBarry Smith PetscErrorCode MatAssemblyEnd_SeqSBAIJ_Inode(Mat A)
7080def2e27SBarry Smith {
7090def2e27SBarry Smith   Mat_SeqSBAIJ    *a = (Mat_SeqSBAIJ*)A->data;
7100def2e27SBarry Smith   PetscErrorCode  ierr;
7110def2e27SBarry Smith   const PetscInt  *ai = a->i, *aj = a->j,*cols;
7120def2e27SBarry Smith   PetscInt        i = 0,j,blk_size,m = A->rmap->n,node_count = 0,nzx,nzy,*ns,row,nz,cnt,cnt2,*counts;
7130def2e27SBarry Smith   PetscTruth      flag;
7140def2e27SBarry Smith 
7150def2e27SBarry Smith   PetscFunctionBegin;
7160def2e27SBarry Smith   ierr = PetscMalloc(m*sizeof(PetscInt),&ns);CHKERRQ(ierr);
7170def2e27SBarry Smith   while (i < m){
7180def2e27SBarry Smith     nzx = ai[i+1] - ai[i];       /* Number of nonzeros */
7190def2e27SBarry Smith     /* Limits the number of elements in a node to 'a->inode.limit' */
7200def2e27SBarry Smith     for (j=i+1,blk_size=1; j<m && blk_size <a->inode.limit; ++j,++blk_size) {
7210def2e27SBarry Smith       nzy  = ai[j+1] - ai[j];
7220def2e27SBarry Smith       if (nzy != (nzx - j + i)) break;
7230def2e27SBarry Smith       ierr = PetscMemcmp(aj + ai[i] + j - i,aj + ai[j],nzy*sizeof(PetscInt),&flag);CHKERRQ(ierr);
7240def2e27SBarry Smith       if (!flag) break;
7250def2e27SBarry Smith     }
7260def2e27SBarry Smith     ns[node_count++] = blk_size;
7270def2e27SBarry Smith     i = j;
7280def2e27SBarry Smith   }
7290def2e27SBarry Smith   if (!a->inode.size && m && node_count > .9*m) {
7300def2e27SBarry Smith     ierr = PetscFree(ns);CHKERRQ(ierr);
7310def2e27SBarry Smith     ierr = PetscInfo2(A,"Found %D nodes out of %D rows. Not using Inode routines\n",node_count,m);CHKERRQ(ierr);
7320def2e27SBarry Smith   } else {
7330def2e27SBarry Smith     a->inode.node_count = node_count;
7340def2e27SBarry Smith     ierr = PetscMalloc(node_count*sizeof(PetscInt),&a->inode.size);CHKERRQ(ierr);
7350def2e27SBarry Smith     ierr = PetscMemcpy(a->inode.size,ns,node_count*sizeof(PetscInt));
7360def2e27SBarry Smith     ierr = PetscFree(ns);CHKERRQ(ierr);
7370def2e27SBarry Smith     ierr = PetscInfo3(A,"Found %D nodes of %D. Limit used: %D. Using Inode routines\n",node_count,m,a->inode.limit);CHKERRQ(ierr);
7380def2e27SBarry Smith 
7390def2e27SBarry Smith     /* count collections of adjacent columns in each inode */
7400def2e27SBarry Smith     row = 0;
7410def2e27SBarry Smith     cnt = 0;
7420def2e27SBarry Smith     for (i=0; i<node_count; i++) {
7430def2e27SBarry Smith       cols = aj + ai[row] + a->inode.size[i];
7440def2e27SBarry Smith       nz   = ai[row+1] - ai[row] - a->inode.size[i];
7450def2e27SBarry Smith       for (j=1; j<nz; j++) {
7460def2e27SBarry Smith         if (cols[j] != cols[j-1]+1) {
7470def2e27SBarry Smith           cnt++;
7480def2e27SBarry Smith         }
7490def2e27SBarry Smith       }
7500def2e27SBarry Smith       cnt++;
7510def2e27SBarry Smith       row += a->inode.size[i];
7520def2e27SBarry Smith     }
7530def2e27SBarry Smith     ierr = PetscMalloc(2*cnt*sizeof(PetscInt),&counts);CHKERRQ(ierr);
7540def2e27SBarry Smith     cnt = 0;
7550def2e27SBarry Smith     row = 0;
7560def2e27SBarry Smith     for (i=0; i<node_count; i++) {
7570def2e27SBarry Smith       cols          = aj + ai[row] + a->inode.size[i];
7580def2e27SBarry Smith 	  CHKMEMQ;
7590def2e27SBarry Smith       counts[2*cnt] = cols[0];
7600def2e27SBarry Smith 	  CHKMEMQ;
7610def2e27SBarry Smith       nz            = ai[row+1] - ai[row] - a->inode.size[i];
7620def2e27SBarry Smith       cnt2          = 1;
7630def2e27SBarry Smith       for (j=1; j<nz; j++) {
7640def2e27SBarry Smith         if (cols[j] != cols[j-1]+1) {
7650def2e27SBarry Smith 	  CHKMEMQ;
7660def2e27SBarry Smith           counts[2*(cnt++)+1] = cnt2;
7670def2e27SBarry Smith           counts[2*cnt]       = cols[j];
7680def2e27SBarry Smith 	  CHKMEMQ;
7690def2e27SBarry Smith           cnt2                = 1;
7700def2e27SBarry Smith         } else cnt2++;
7710def2e27SBarry Smith       }
7720def2e27SBarry Smith 	  CHKMEMQ;
7730def2e27SBarry Smith       counts[2*(cnt++)+1] = cnt2;
7740def2e27SBarry Smith 	  CHKMEMQ;
7750def2e27SBarry Smith       row += a->inode.size[i];
7760def2e27SBarry Smith     }
7770def2e27SBarry Smith     ierr = PetscIntView(2*cnt,counts,0);
7780def2e27SBarry Smith   }
7790def2e27SBarry Smith 
7800def2e27SBarry Smith 
7810def2e27SBarry Smith   PetscFunctionReturn(0);
7820def2e27SBarry Smith }
7830def2e27SBarry Smith 
7840def2e27SBarry Smith #undef __FUNCT__
7854a2ae208SSatish Balay #define __FUNCT__ "MatAssemblyEnd_SeqSBAIJ"
786dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqSBAIJ(Mat A,MatAssemblyType mode)
78749b5e25fSSatish Balay {
78849b5e25fSSatish Balay   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
7896849ba73SBarry Smith   PetscErrorCode ierr;
79013f74950SBarry Smith   PetscInt       fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
791d0f46423SBarry Smith   PetscInt       m = A->rmap->N,*ip,N,*ailen = a->ilen;
79213f74950SBarry Smith   PetscInt       mbs = a->mbs,bs2 = a->bs2,rmax = 0;
79349b5e25fSSatish Balay   MatScalar      *aa = a->a,*ap;
79449b5e25fSSatish Balay 
79549b5e25fSSatish Balay   PetscFunctionBegin;
79649b5e25fSSatish Balay   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
79749b5e25fSSatish Balay 
79849b5e25fSSatish Balay   if (m) rmax = ailen[0];
79949b5e25fSSatish Balay   for (i=1; i<mbs; i++) {
80049b5e25fSSatish Balay     /* move each row back by the amount of empty slots (fshift) before it*/
80149b5e25fSSatish Balay     fshift += imax[i-1] - ailen[i-1];
80249b5e25fSSatish Balay      rmax   = PetscMax(rmax,ailen[i]);
80349b5e25fSSatish Balay      if (fshift) {
80449b5e25fSSatish Balay        ip = aj + ai[i]; ap = aa + bs2*ai[i];
80549b5e25fSSatish Balay        N = ailen[i];
80649b5e25fSSatish Balay        for (j=0; j<N; j++) {
80749b5e25fSSatish Balay          ip[j-fshift] = ip[j];
80849b5e25fSSatish Balay          ierr = PetscMemcpy(ap+(j-fshift)*bs2,ap+j*bs2,bs2*sizeof(MatScalar));CHKERRQ(ierr);
80949b5e25fSSatish Balay        }
81049b5e25fSSatish Balay      }
81149b5e25fSSatish Balay      ai[i] = ai[i-1] + ailen[i-1];
81249b5e25fSSatish Balay   }
81349b5e25fSSatish Balay   if (mbs) {
81449b5e25fSSatish Balay     fshift += imax[mbs-1] - ailen[mbs-1];
81549b5e25fSSatish Balay      ai[mbs] = ai[mbs-1] + ailen[mbs-1];
81649b5e25fSSatish Balay   }
81749b5e25fSSatish Balay   /* reset ilen and imax for each row */
81849b5e25fSSatish Balay   for (i=0; i<mbs; i++) {
81949b5e25fSSatish Balay     ailen[i] = imax[i] = ai[i+1] - ai[i];
82049b5e25fSSatish Balay   }
8216c6c5352SBarry Smith   a->nz = ai[mbs];
82249b5e25fSSatish Balay 
823b424e231SHong Zhang   /* diagonals may have moved, reset it */
824b424e231SHong Zhang   if (a->diag) {
82513f74950SBarry Smith     ierr = PetscMemcpy(a->diag,ai,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr);
82649b5e25fSSatish Balay   }
82728b2fa4aSMatthew Knepley   if (fshift && a->nounused == -1) {
82828b2fa4aSMatthew 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);
82928b2fa4aSMatthew Knepley   }
830d0f46423SBarry 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);
831ae15b995SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues is %D\n",a->reallocs);CHKERRQ(ierr);
832ae15b995SBarry Smith   ierr = PetscInfo1(A,"Most nonzeros blocks in any row is %D\n",rmax);CHKERRQ(ierr);
83349b5e25fSSatish Balay   a->reallocs          = 0;
83449b5e25fSSatish Balay   A->info.nz_unneeded  = (PetscReal)fshift*bs2;
835061b2667SBarry Smith   a->idiagvalid = PETSC_FALSE;
83664831d72SBarry Smith   /* if (bs2 == 1) {
8370def2e27SBarry Smith     ierr = MatAssemblyEnd_SeqSBAIJ_Inode(A);CHKERRQ(ierr);
83864831d72SBarry Smith   } */
83949b5e25fSSatish Balay   PetscFunctionReturn(0);
84049b5e25fSSatish Balay }
84149b5e25fSSatish Balay 
84249b5e25fSSatish Balay /*
84349b5e25fSSatish Balay    This function returns an array of flags which indicate the locations of contiguous
84449b5e25fSSatish Balay    blocks that should be zeroed. for eg: if bs = 3  and is = [0,1,2,3,5,6,7,8,9]
84549b5e25fSSatish Balay    then the resulting sizes = [3,1,1,3,1] correspondig to sets [(0,1,2),(3),(5),(6,7,8),(9)]
84649b5e25fSSatish Balay    Assume: sizes should be long enough to hold all the values.
84749b5e25fSSatish Balay */
8484a2ae208SSatish Balay #undef __FUNCT__
8494a2ae208SSatish Balay #define __FUNCT__ "MatZeroRows_SeqSBAIJ_Check_Blocks"
85013f74950SBarry Smith PetscErrorCode MatZeroRows_SeqSBAIJ_Check_Blocks(PetscInt idx[],PetscInt n,PetscInt bs,PetscInt sizes[], PetscInt *bs_max)
85149b5e25fSSatish Balay {
85213f74950SBarry Smith   PetscInt   i,j,k,row;
85349b5e25fSSatish Balay   PetscTruth flg;
85449b5e25fSSatish Balay 
85549b5e25fSSatish Balay   PetscFunctionBegin;
85649b5e25fSSatish Balay    for (i=0,j=0; i<n; j++) {
85749b5e25fSSatish Balay      row = idx[i];
85849b5e25fSSatish Balay      if (row%bs!=0) { /* Not the begining of a block */
85949b5e25fSSatish Balay        sizes[j] = 1;
86049b5e25fSSatish Balay        i++;
86149b5e25fSSatish Balay      } else if (i+bs > n) { /* Beginning of a block, but complete block doesn't exist (at idx end) */
86249b5e25fSSatish Balay        sizes[j] = 1;         /* Also makes sure atleast 'bs' values exist for next else */
86349b5e25fSSatish Balay        i++;
86449b5e25fSSatish Balay      } else { /* Begining of the block, so check if the complete block exists */
86549b5e25fSSatish Balay        flg = PETSC_TRUE;
86649b5e25fSSatish Balay        for (k=1; k<bs; k++) {
86749b5e25fSSatish Balay          if (row+k != idx[i+k]) { /* break in the block */
86849b5e25fSSatish Balay            flg = PETSC_FALSE;
86949b5e25fSSatish Balay            break;
87049b5e25fSSatish Balay          }
87149b5e25fSSatish Balay        }
872abc0a331SBarry Smith        if (flg) { /* No break in the bs */
87349b5e25fSSatish Balay          sizes[j] = bs;
87449b5e25fSSatish Balay          i+= bs;
87549b5e25fSSatish Balay        } else {
87649b5e25fSSatish Balay          sizes[j] = 1;
87749b5e25fSSatish Balay          i++;
87849b5e25fSSatish Balay        }
87949b5e25fSSatish Balay      }
88049b5e25fSSatish Balay    }
88149b5e25fSSatish Balay    *bs_max = j;
88249b5e25fSSatish Balay    PetscFunctionReturn(0);
88349b5e25fSSatish Balay }
88449b5e25fSSatish Balay 
88549b5e25fSSatish Balay 
88649b5e25fSSatish Balay /* Only add/insert a(i,j) with i<=j (blocks).
88749b5e25fSSatish Balay    Any a(i,j) with i>j input by user is ingored.
88849b5e25fSSatish Balay */
88949b5e25fSSatish Balay 
8904a2ae208SSatish Balay #undef __FUNCT__
8914a2ae208SSatish Balay #define __FUNCT__ "MatSetValues_SeqSBAIJ"
89213f74950SBarry Smith PetscErrorCode MatSetValues_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
89349b5e25fSSatish Balay {
89449b5e25fSSatish Balay   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
8956849ba73SBarry Smith   PetscErrorCode ierr;
896e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,lastcol = -1;
89713f74950SBarry Smith   PetscInt       *imax=a->imax,*ai=a->i,*ailen=a->ilen,roworiented=a->roworiented;
898d0f46423SBarry Smith   PetscInt       *aj=a->j,nonew=a->nonew,bs=A->rmap->bs,brow,bcol;
89913f74950SBarry Smith   PetscInt       ridx,cidx,bs2=a->bs2;
90049b5e25fSSatish Balay   MatScalar      *ap,value,*aa=a->a,*bap;
90149b5e25fSSatish Balay 
90249b5e25fSSatish Balay   PetscFunctionBegin;
90349b5e25fSSatish Balay   for (k=0; k<m; k++) { /* loop over added rows */
90449b5e25fSSatish Balay     row  = im[k];       /* row number */
90549b5e25fSSatish Balay     brow = row/bs;      /* block row number */
90649b5e25fSSatish Balay     if (row < 0) continue;
9072515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
908d0f46423SBarry Smith     if (row >= A->rmap->N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->N-1);
90949b5e25fSSatish Balay #endif
91049b5e25fSSatish Balay     rp   = aj + ai[brow]; /*ptr to beginning of column value of the row block*/
91149b5e25fSSatish Balay     ap   = aa + bs2*ai[brow]; /*ptr to beginning of element value of the row block*/
91249b5e25fSSatish Balay     rmax = imax[brow];  /* maximum space allocated for this row */
91349b5e25fSSatish Balay     nrow = ailen[brow]; /* actual length of this row */
91449b5e25fSSatish Balay     low  = 0;
91549b5e25fSSatish Balay 
91649b5e25fSSatish Balay     for (l=0; l<n; l++) { /* loop over added columns */
91749b5e25fSSatish Balay       if (in[l] < 0) continue;
9182515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
919d0f46423SBarry 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);
92049b5e25fSSatish Balay #endif
92149b5e25fSSatish Balay       col = in[l];
92249b5e25fSSatish Balay       bcol = col/bs;              /* block col number */
92349b5e25fSSatish Balay 
924941593c8SHong Zhang       if (brow > bcol) {
925941593c8SHong Zhang         if (a->ignore_ltriangular){
926941593c8SHong Zhang           continue; /* ignore lower triangular values */
927941593c8SHong Zhang         } else {
9284e0d8c25SBarry 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)");
929941593c8SHong Zhang         }
930941593c8SHong Zhang       }
931f4989cb3SHong Zhang 
93249b5e25fSSatish Balay       ridx = row % bs; cidx = col % bs; /*row and col index inside the block */
9338549e402SHong Zhang       if ((brow==bcol && ridx<=cidx) || (brow<bcol)){
93449b5e25fSSatish Balay         /* element value a(k,l) */
93549b5e25fSSatish Balay         if (roworiented) {
93649b5e25fSSatish Balay           value = v[l + k*n];
93749b5e25fSSatish Balay         } else {
93849b5e25fSSatish Balay           value = v[k + l*m];
93949b5e25fSSatish Balay         }
94049b5e25fSSatish Balay 
94149b5e25fSSatish Balay         /* move pointer bap to a(k,l) quickly and add/insert value */
9427cd84e04SBarry Smith         if (col <= lastcol) low = 0; high = nrow;
943e2ee6c50SBarry Smith         lastcol = col;
94449b5e25fSSatish Balay         while (high-low > 7) {
94549b5e25fSSatish Balay           t = (low+high)/2;
94649b5e25fSSatish Balay           if (rp[t] > bcol) high = t;
94749b5e25fSSatish Balay           else              low  = t;
94849b5e25fSSatish Balay         }
94949b5e25fSSatish Balay         for (i=low; i<high; i++) {
95049b5e25fSSatish Balay           if (rp[i] > bcol) break;
95149b5e25fSSatish Balay           if (rp[i] == bcol) {
95249b5e25fSSatish Balay             bap  = ap +  bs2*i + bs*cidx + ridx;
95349b5e25fSSatish Balay             if (is == ADD_VALUES) *bap += value;
95449b5e25fSSatish Balay             else                  *bap  = value;
9558549e402SHong Zhang             /* for diag block, add/insert its symmetric element a(cidx,ridx) */
9568549e402SHong Zhang             if (brow == bcol && ridx < cidx){
9578549e402SHong Zhang               bap  = ap +  bs2*i + bs*ridx + cidx;
9588549e402SHong Zhang               if (is == ADD_VALUES) *bap += value;
9598549e402SHong Zhang               else                  *bap  = value;
9608549e402SHong Zhang             }
96149b5e25fSSatish Balay             goto noinsert1;
96249b5e25fSSatish Balay           }
96349b5e25fSSatish Balay         }
96449b5e25fSSatish Balay 
96549b5e25fSSatish Balay         if (nonew == 1) goto noinsert1;
966085a36d4SBarry Smith         if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col);
967421e10b8SBarry Smith         MatSeqXAIJReallocateAIJ(A,a->mbs,bs2,nrow,brow,bcol,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
96849b5e25fSSatish Balay 
969c03d1d03SSatish Balay         N = nrow++ - 1; high++;
97049b5e25fSSatish Balay         /* shift up all the later entries in this row */
97149b5e25fSSatish Balay         for (ii=N; ii>=i; ii--) {
97249b5e25fSSatish Balay           rp[ii+1] = rp[ii];
97349b5e25fSSatish Balay           ierr     = PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));CHKERRQ(ierr);
97449b5e25fSSatish Balay         }
97549b5e25fSSatish Balay         if (N>=i) {
97649b5e25fSSatish Balay           ierr = PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));CHKERRQ(ierr);
97749b5e25fSSatish Balay         }
97849b5e25fSSatish Balay         rp[i]                      = bcol;
97949b5e25fSSatish Balay         ap[bs2*i + bs*cidx + ridx] = value;
98049b5e25fSSatish Balay       noinsert1:;
98149b5e25fSSatish Balay         low = i;
9828549e402SHong Zhang       }
98349b5e25fSSatish Balay     }   /* end of loop over added columns */
98449b5e25fSSatish Balay     ailen[brow] = nrow;
98549b5e25fSSatish Balay   }   /* end of loop over added rows */
98649b5e25fSSatish Balay   PetscFunctionReturn(0);
98749b5e25fSSatish Balay }
98849b5e25fSSatish Balay 
9894a2ae208SSatish Balay #undef __FUNCT__
9904d101231SSatish Balay #define __FUNCT__ "MatICCFactor_SeqSBAIJ"
9910481f469SBarry Smith PetscErrorCode MatICCFactor_SeqSBAIJ(Mat inA,IS row,const MatFactorInfo *info)
99249b5e25fSSatish Balay {
9934ccecd49SHong Zhang   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)inA->data;
99449b5e25fSSatish Balay   Mat            outA;
995dfbe8321SBarry Smith   PetscErrorCode ierr;
996c84f5b01SHong Zhang   PetscTruth     row_identity;
99749b5e25fSSatish Balay 
99849b5e25fSSatish Balay   PetscFunctionBegin;
999c84f5b01SHong Zhang   if (info->levels != 0) SETERRQ(PETSC_ERR_SUP,"Only levels=0 is supported for in-place icc");
1000c84f5b01SHong Zhang   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
1001c84f5b01SHong Zhang   if (!row_identity) SETERRQ(PETSC_ERR_SUP,"Matrix reordering is not supported");
1002d0f46423SBarry 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()! */
1003c84f5b01SHong Zhang 
100449b5e25fSSatish Balay   outA        = inA;
1005c078aec8SLisandro Dalcin   inA->factor = MAT_FACTOR_ICC;
100649b5e25fSSatish Balay 
10071a3463dfSHong Zhang   ierr = MatMarkDiagonal_SeqSBAIJ(inA);CHKERRQ(ierr);
1008db4efbfdSBarry Smith   ierr = MatSeqSBAIJSetNumericFactorization(inA,row_identity);CHKERRQ(ierr);
100949b5e25fSSatish Balay 
1010c3122656SLisandro Dalcin   ierr   = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
1011c3122656SLisandro Dalcin   if (a->row) { ierr = ISDestroy(a->row);CHKERRQ(ierr); }
1012c84f5b01SHong Zhang   a->row = row;
1013c3122656SLisandro Dalcin   ierr   = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
1014c3122656SLisandro Dalcin   if (a->col) { ierr = ISDestroy(a->col);CHKERRQ(ierr); }
1015c84f5b01SHong Zhang   a->col = row;
1016c84f5b01SHong Zhang 
1017c84f5b01SHong Zhang   /* Create the invert permutation so that it can be used in MatCholeskyFactorNumeric() */
1018c84f5b01SHong Zhang   if (a->icol) {ierr = ISInvertPermutation(row,PETSC_DECIDE, &a->icol);CHKERRQ(ierr);}
101952e6d16bSBarry Smith   ierr = PetscLogObjectParent(inA,a->icol);CHKERRQ(ierr);
102049b5e25fSSatish Balay 
102149b5e25fSSatish Balay   if (!a->solve_work) {
1022d0f46423SBarry Smith     ierr = PetscMalloc((inA->rmap->N+inA->rmap->bs)*sizeof(PetscScalar),&a->solve_work);CHKERRQ(ierr);
1023d0f46423SBarry Smith     ierr = PetscLogObjectMemory(inA,(inA->rmap->N+inA->rmap->bs)*sizeof(PetscScalar));CHKERRQ(ierr);
102449b5e25fSSatish Balay   }
102549b5e25fSSatish Balay 
1026719d5645SBarry Smith   ierr = MatCholeskyFactorNumeric(outA,inA,info);CHKERRQ(ierr);
102749b5e25fSSatish Balay   PetscFunctionReturn(0);
102849b5e25fSSatish Balay }
1029950f1e5bSHong Zhang 
103049b5e25fSSatish Balay EXTERN_C_BEGIN
10314a2ae208SSatish Balay #undef __FUNCT__
10324a2ae208SSatish Balay #define __FUNCT__ "MatSeqSBAIJSetColumnIndices_SeqSBAIJ"
1033be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat,PetscInt *indices)
103449b5e25fSSatish Balay {
1035045c9aa0SHong Zhang   Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)mat->data;
103613f74950SBarry Smith   PetscInt     i,nz,n;
103749b5e25fSSatish Balay 
103849b5e25fSSatish Balay   PetscFunctionBegin;
10396c6c5352SBarry Smith   nz = baij->maxnz;
1040d0f46423SBarry Smith   n  = mat->cmap->n;
104149b5e25fSSatish Balay   for (i=0; i<nz; i++) {
104249b5e25fSSatish Balay     baij->j[i] = indices[i];
104349b5e25fSSatish Balay   }
10446c6c5352SBarry Smith    baij->nz = nz;
104549b5e25fSSatish Balay    for (i=0; i<n; i++) {
104649b5e25fSSatish Balay      baij->ilen[i] = baij->imax[i];
104749b5e25fSSatish Balay    }
104849b5e25fSSatish Balay    PetscFunctionReturn(0);
104949b5e25fSSatish Balay }
105049b5e25fSSatish Balay EXTERN_C_END
105149b5e25fSSatish Balay 
10524a2ae208SSatish Balay #undef __FUNCT__
10534a2ae208SSatish Balay #define __FUNCT__ "MatSeqSBAIJSetColumnIndices"
105449b5e25fSSatish Balay /*@
105519585528SSatish Balay   MatSeqSBAIJSetColumnIndices - Set the column indices for all the rows
105649b5e25fSSatish Balay   in the matrix.
105749b5e25fSSatish Balay 
105849b5e25fSSatish Balay   Input Parameters:
105919585528SSatish Balay   +  mat     - the SeqSBAIJ matrix
106049b5e25fSSatish Balay   -  indices - the column indices
106149b5e25fSSatish Balay 
106249b5e25fSSatish Balay   Level: advanced
106349b5e25fSSatish Balay 
106449b5e25fSSatish Balay   Notes:
106549b5e25fSSatish Balay   This can be called if you have precomputed the nonzero structure of the
106649b5e25fSSatish Balay   matrix and want to provide it to the matrix object to improve the performance
106749b5e25fSSatish Balay   of the MatSetValues() operation.
106849b5e25fSSatish Balay 
106949b5e25fSSatish Balay   You MUST have set the correct numbers of nonzeros per row in the call to
1070d1be2dadSMatthew Knepley   MatCreateSeqSBAIJ(), and the columns indices MUST be sorted.
107149b5e25fSSatish Balay 
1072ab9f2c04SSatish Balay   MUST be called before any calls to MatSetValues()
107349b5e25fSSatish Balay 
1074ab9f2c04SSatish Balay   .seealso: MatCreateSeqSBAIJ
107549b5e25fSSatish Balay @*/
1076be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetColumnIndices(Mat mat,PetscInt *indices)
107749b5e25fSSatish Balay {
107813f74950SBarry Smith   PetscErrorCode ierr,(*f)(Mat,PetscInt *);
107949b5e25fSSatish Balay 
108049b5e25fSSatish Balay   PetscFunctionBegin;
10814482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
10824482741eSBarry Smith   PetscValidPointer(indices,2);
1083c134de8dSSatish Balay   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqSBAIJSetColumnIndices_C",(void (**)(void))&f);CHKERRQ(ierr);
108449b5e25fSSatish Balay   if (f) {
108549b5e25fSSatish Balay     ierr = (*f)(mat,indices);CHKERRQ(ierr);
108649b5e25fSSatish Balay   } else {
1087e005ede5SBarry Smith     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to set column indices");
108849b5e25fSSatish Balay   }
108949b5e25fSSatish Balay   PetscFunctionReturn(0);
109049b5e25fSSatish Balay }
109149b5e25fSSatish Balay 
10924a2ae208SSatish Balay #undef __FUNCT__
10933c896bc6SHong Zhang #define __FUNCT__ "MatCopy_SeqSBAIJ"
10943c896bc6SHong Zhang PetscErrorCode MatCopy_SeqSBAIJ(Mat A,Mat B,MatStructure str)
10953c896bc6SHong Zhang {
10963c896bc6SHong Zhang   PetscErrorCode ierr;
10973c896bc6SHong Zhang 
10983c896bc6SHong Zhang   PetscFunctionBegin;
10993c896bc6SHong Zhang   /* If the two matrices have the same copy implementation, use fast copy. */
11003c896bc6SHong Zhang   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
11013c896bc6SHong Zhang     Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
11023c896bc6SHong Zhang     Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ*)B->data;
11033c896bc6SHong Zhang 
1104d0f46423SBarry Smith     if (a->i[A->rmap->N] != b->i[B->rmap->N]) {
11053c896bc6SHong Zhang       SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different");
11063c896bc6SHong Zhang     }
1107d0f46423SBarry Smith     ierr = PetscMemcpy(b->a,a->a,(a->i[A->rmap->N])*sizeof(PetscScalar));CHKERRQ(ierr);
11083c896bc6SHong Zhang   } else {
1109f5edf698SHong Zhang     ierr = MatGetRowUpperTriangular(A);CHKERRQ(ierr);
11103c896bc6SHong Zhang     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
1111f5edf698SHong Zhang     ierr = MatRestoreRowUpperTriangular(A);CHKERRQ(ierr);
11123c896bc6SHong Zhang   }
11133c896bc6SHong Zhang   PetscFunctionReturn(0);
11143c896bc6SHong Zhang }
11153c896bc6SHong Zhang 
11163c896bc6SHong Zhang #undef __FUNCT__
11174a2ae208SSatish Balay #define __FUNCT__ "MatSetUpPreallocation_SeqSBAIJ"
1118dfbe8321SBarry Smith PetscErrorCode MatSetUpPreallocation_SeqSBAIJ(Mat A)
1119273d9f13SBarry Smith {
1120dfbe8321SBarry Smith   PetscErrorCode ierr;
1121273d9f13SBarry Smith 
1122273d9f13SBarry Smith   PetscFunctionBegin;
1123db4efbfdSBarry Smith   ierr =  MatSeqSBAIJSetPreallocation_SeqSBAIJ(A,-PetscMax(A->rmap->bs,1),PETSC_DEFAULT,0);CHKERRQ(ierr);
1124273d9f13SBarry Smith   PetscFunctionReturn(0);
1125273d9f13SBarry Smith }
1126273d9f13SBarry Smith 
1127a6ece127SHong Zhang #undef __FUNCT__
1128a6ece127SHong Zhang #define __FUNCT__ "MatGetArray_SeqSBAIJ"
1129dfbe8321SBarry Smith PetscErrorCode MatGetArray_SeqSBAIJ(Mat A,PetscScalar *array[])
1130a6ece127SHong Zhang {
1131a6ece127SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
1132a6ece127SHong Zhang   PetscFunctionBegin;
1133a6ece127SHong Zhang   *array = a->a;
1134a6ece127SHong Zhang   PetscFunctionReturn(0);
1135a6ece127SHong Zhang }
1136a6ece127SHong Zhang 
1137a6ece127SHong Zhang #undef __FUNCT__
1138a6ece127SHong Zhang #define __FUNCT__ "MatRestoreArray_SeqSBAIJ"
1139dfbe8321SBarry Smith PetscErrorCode MatRestoreArray_SeqSBAIJ(Mat A,PetscScalar *array[])
1140a6ece127SHong Zhang {
1141a6ece127SHong Zhang   PetscFunctionBegin;
1142a6ece127SHong Zhang   PetscFunctionReturn(0);
1143a6ece127SHong Zhang  }
1144a6ece127SHong Zhang 
114542ee4b1aSHong Zhang #include "petscblaslapack.h"
114642ee4b1aSHong Zhang #undef __FUNCT__
114742ee4b1aSHong Zhang #define __FUNCT__ "MatAXPY_SeqSBAIJ"
1148f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqSBAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
114942ee4b1aSHong Zhang {
115042ee4b1aSHong Zhang   Mat_SeqSBAIJ   *x=(Mat_SeqSBAIJ *)X->data, *y=(Mat_SeqSBAIJ *)Y->data;
1151dfbe8321SBarry Smith   PetscErrorCode ierr;
1152d0f46423SBarry Smith   PetscInt       i,bs=Y->rmap->bs,bs2,j;
11530805154bSBarry Smith   PetscBLASInt   one = 1,bnz = PetscBLASIntCast(x->nz);
115442ee4b1aSHong Zhang 
115542ee4b1aSHong Zhang   PetscFunctionBegin;
115642ee4b1aSHong Zhang   if (str == SAME_NONZERO_PATTERN) {
1157f4df32b1SMatthew Knepley     PetscScalar alpha = a;
1158f4df32b1SMatthew Knepley     BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one);
1159c537a176SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
1160c4319e64SHong Zhang     if (y->xtoy && y->XtoY != X) {
1161c4319e64SHong Zhang       ierr = PetscFree(y->xtoy);CHKERRQ(ierr);
1162c4319e64SHong Zhang       ierr = MatDestroy(y->XtoY);CHKERRQ(ierr);
1163c537a176SHong Zhang     }
1164c4319e64SHong Zhang     if (!y->xtoy) { /* get xtoy */
1165c4319e64SHong Zhang       ierr = MatAXPYGetxtoy_Private(x->mbs,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);CHKERRQ(ierr);
1166c4319e64SHong Zhang       y->XtoY = X;
1167c537a176SHong Zhang     }
1168c4319e64SHong Zhang     bs2 = bs*bs;
11696c6c5352SBarry Smith     for (i=0; i<x->nz; i++) {
1170c4319e64SHong Zhang       j = 0;
1171c4319e64SHong Zhang       while (j < bs2){
1172f4df32b1SMatthew Knepley         y->a[bs2*y->xtoy[i]+j] += a*(x->a[bs2*i+j]);
1173c4319e64SHong Zhang         j++;
1174c537a176SHong Zhang       }
1175c4319e64SHong Zhang     }
11761e2582c4SBarry 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);
117742ee4b1aSHong Zhang   } else {
1178f5edf698SHong Zhang     ierr = MatGetRowUpperTriangular(X);CHKERRQ(ierr);
1179f4df32b1SMatthew Knepley     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
1180f5edf698SHong Zhang     ierr = MatRestoreRowUpperTriangular(X);CHKERRQ(ierr);
118142ee4b1aSHong Zhang   }
118242ee4b1aSHong Zhang   PetscFunctionReturn(0);
118342ee4b1aSHong Zhang }
118442ee4b1aSHong Zhang 
1185efcf0fc3SBarry Smith #undef __FUNCT__
1186efcf0fc3SBarry Smith #define __FUNCT__ "MatIsSymmetric_SeqSBAIJ"
1187dfbe8321SBarry Smith PetscErrorCode MatIsSymmetric_SeqSBAIJ(Mat A,PetscReal tol,PetscTruth *flg)
1188efcf0fc3SBarry Smith {
1189efcf0fc3SBarry Smith   PetscFunctionBegin;
1190efcf0fc3SBarry Smith   *flg = PETSC_TRUE;
1191efcf0fc3SBarry Smith   PetscFunctionReturn(0);
1192efcf0fc3SBarry Smith }
1193efcf0fc3SBarry Smith 
1194efcf0fc3SBarry Smith #undef __FUNCT__
1195efcf0fc3SBarry Smith #define __FUNCT__ "MatIsStructurallySymmetric_SeqSBAIJ"
1196dfbe8321SBarry Smith PetscErrorCode MatIsStructurallySymmetric_SeqSBAIJ(Mat A,PetscTruth *flg)
1197efcf0fc3SBarry Smith {
1198efcf0fc3SBarry Smith    PetscFunctionBegin;
1199efcf0fc3SBarry Smith    *flg = PETSC_TRUE;
1200efcf0fc3SBarry Smith    PetscFunctionReturn(0);
1201efcf0fc3SBarry Smith }
1202efcf0fc3SBarry Smith 
1203efcf0fc3SBarry Smith #undef __FUNCT__
1204efcf0fc3SBarry Smith #define __FUNCT__ "MatIsHermitian_SeqSBAIJ"
1205ab5e4463SMatthew Knepley PetscErrorCode MatIsHermitian_SeqSBAIJ(Mat A,PetscReal tol,PetscTruth *flg)
1206efcf0fc3SBarry Smith  {
1207efcf0fc3SBarry Smith    PetscFunctionBegin;
1208efcf0fc3SBarry Smith    *flg = PETSC_FALSE;
1209efcf0fc3SBarry Smith    PetscFunctionReturn(0);
1210efcf0fc3SBarry Smith  }
1211efcf0fc3SBarry Smith 
121299cafbc1SBarry Smith #undef __FUNCT__
121399cafbc1SBarry Smith #define __FUNCT__ "MatRealPart_SeqSBAIJ"
121499cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqSBAIJ(Mat A)
121599cafbc1SBarry Smith {
121699cafbc1SBarry Smith   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
121799cafbc1SBarry Smith   PetscInt       i,nz = a->bs2*a->i[a->mbs];
1218dd6ea824SBarry Smith   MatScalar      *aa = a->a;
121999cafbc1SBarry Smith 
122099cafbc1SBarry Smith   PetscFunctionBegin;
122199cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
122299cafbc1SBarry Smith   PetscFunctionReturn(0);
122399cafbc1SBarry Smith }
122499cafbc1SBarry Smith 
122599cafbc1SBarry Smith #undef __FUNCT__
122699cafbc1SBarry Smith #define __FUNCT__ "MatImaginaryPart_SeqSBAIJ"
122799cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqSBAIJ(Mat A)
122899cafbc1SBarry Smith {
122999cafbc1SBarry Smith   Mat_SeqSBAIJ   *a = (Mat_SeqSBAIJ*)A->data;
123099cafbc1SBarry Smith   PetscInt       i,nz = a->bs2*a->i[a->mbs];
1231dd6ea824SBarry Smith   MatScalar      *aa = a->a;
123299cafbc1SBarry Smith 
123399cafbc1SBarry Smith   PetscFunctionBegin;
123499cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
123599cafbc1SBarry Smith   PetscFunctionReturn(0);
123699cafbc1SBarry Smith }
123799cafbc1SBarry Smith 
123849b5e25fSSatish Balay /* -------------------------------------------------------------------*/
123949b5e25fSSatish Balay static struct _MatOps MatOps_Values = {MatSetValues_SeqSBAIJ,
124049b5e25fSSatish Balay        MatGetRow_SeqSBAIJ,
124149b5e25fSSatish Balay        MatRestoreRow_SeqSBAIJ,
124249b5e25fSSatish Balay        MatMult_SeqSBAIJ_N,
124397304618SKris Buschelman /* 4*/ MatMultAdd_SeqSBAIJ_N,
1244431c96f7SBarry Smith        MatMult_SeqSBAIJ_N,       /* transpose versions are same as non-transpose versions */
1245e005ede5SBarry Smith        MatMultAdd_SeqSBAIJ_N,
1246db4efbfdSBarry Smith        0,
124749b5e25fSSatish Balay        0,
124849b5e25fSSatish Balay        0,
124997304618SKris Buschelman /*10*/ 0,
125049b5e25fSSatish Balay        0,
1251c078aec8SLisandro Dalcin        MatCholeskyFactor_SeqSBAIJ,
1252d06b337dSHong Zhang        MatRelax_SeqSBAIJ,
125349b5e25fSSatish Balay        MatTranspose_SeqSBAIJ,
125497304618SKris Buschelman /*15*/ MatGetInfo_SeqSBAIJ,
125549b5e25fSSatish Balay        MatEqual_SeqSBAIJ,
125649b5e25fSSatish Balay        MatGetDiagonal_SeqSBAIJ,
125749b5e25fSSatish Balay        MatDiagonalScale_SeqSBAIJ,
125849b5e25fSSatish Balay        MatNorm_SeqSBAIJ,
125997304618SKris Buschelman /*20*/ 0,
126049b5e25fSSatish Balay        MatAssemblyEnd_SeqSBAIJ,
126149b5e25fSSatish Balay        MatSetOption_SeqSBAIJ,
126249b5e25fSSatish Balay        MatZeroEntries_SeqSBAIJ,
1263d519adbfSMatthew Knepley /*24*/ 0,
126449b5e25fSSatish Balay        0,
126549b5e25fSSatish Balay        0,
1266db4efbfdSBarry Smith        0,
1267db4efbfdSBarry Smith        0,
1268d519adbfSMatthew Knepley /*29*/ MatSetUpPreallocation_SeqSBAIJ,
1269c464158bSHong Zhang        0,
1270db4efbfdSBarry Smith        0,
1271a6ece127SHong Zhang        MatGetArray_SeqSBAIJ,
1272a6ece127SHong Zhang        MatRestoreArray_SeqSBAIJ,
1273d519adbfSMatthew Knepley /*34*/ MatDuplicate_SeqSBAIJ,
1274719d5645SBarry Smith        0,
1275719d5645SBarry Smith        0,
127649b5e25fSSatish Balay        0,
1277c84f5b01SHong Zhang        MatICCFactor_SeqSBAIJ,
1278d519adbfSMatthew Knepley /*39*/ MatAXPY_SeqSBAIJ,
127949b5e25fSSatish Balay        MatGetSubMatrices_SeqSBAIJ,
128049b5e25fSSatish Balay        MatIncreaseOverlap_SeqSBAIJ,
128149b5e25fSSatish Balay        MatGetValues_SeqSBAIJ,
12823c896bc6SHong Zhang        MatCopy_SeqSBAIJ,
1283d519adbfSMatthew Knepley /*44*/ 0,
128449b5e25fSSatish Balay        MatScale_SeqSBAIJ,
128549b5e25fSSatish Balay        0,
128649b5e25fSSatish Balay        0,
128749b5e25fSSatish Balay        0,
1288d519adbfSMatthew Knepley /*49*/ 0,
128949b5e25fSSatish Balay        MatGetRowIJ_SeqSBAIJ,
129049b5e25fSSatish Balay        MatRestoreRowIJ_SeqSBAIJ,
129149b5e25fSSatish Balay        0,
129249b5e25fSSatish Balay        0,
1293d519adbfSMatthew Knepley /*54*/ 0,
129449b5e25fSSatish Balay        0,
129549b5e25fSSatish Balay        0,
129649b5e25fSSatish Balay        0,
129749b5e25fSSatish Balay        MatSetValuesBlocked_SeqSBAIJ,
1298d519adbfSMatthew Knepley /*59*/ MatGetSubMatrix_SeqSBAIJ,
129949b5e25fSSatish Balay        0,
130049b5e25fSSatish Balay        0,
1301357abbc8SBarry Smith        0,
1302d959ec07SHong Zhang        0,
1303d519adbfSMatthew Knepley /*64*/ 0,
1304d959ec07SHong Zhang        0,
1305d959ec07SHong Zhang        0,
1306d959ec07SHong Zhang        0,
1307d959ec07SHong Zhang        0,
1308d519adbfSMatthew Knepley /*69*/ MatGetRowMaxAbs_SeqSBAIJ,
13093e0d88b5SBarry Smith        0,
13103e0d88b5SBarry Smith        0,
13113e0d88b5SBarry Smith        0,
13123e0d88b5SBarry Smith        0,
1313d519adbfSMatthew Knepley /*74*/ 0,
13143e0d88b5SBarry Smith        0,
13153e0d88b5SBarry Smith        0,
13163e0d88b5SBarry Smith        0,
13173e0d88b5SBarry Smith        0,
1318d519adbfSMatthew Knepley /*79*/ 0,
13193e0d88b5SBarry Smith        0,
13203e0d88b5SBarry Smith        0,
13213e0d88b5SBarry Smith #if !defined(PETSC_USE_COMPLEX)
132297304618SKris Buschelman        MatGetInertia_SeqSBAIJ,
13233e0d88b5SBarry Smith #else
132497304618SKris Buschelman        0,
13253e0d88b5SBarry Smith #endif
1326865e5f61SKris Buschelman        MatLoad_SeqSBAIJ,
1327d519adbfSMatthew Knepley /*84*/ MatIsSymmetric_SeqSBAIJ,
1328865e5f61SKris Buschelman        MatIsHermitian_SeqSBAIJ,
1329efcf0fc3SBarry Smith        MatIsStructurallySymmetric_SeqSBAIJ,
1330865e5f61SKris Buschelman        0,
1331865e5f61SKris Buschelman        0,
1332d519adbfSMatthew Knepley /*89*/ 0,
1333865e5f61SKris Buschelman        0,
1334865e5f61SKris Buschelman        0,
1335865e5f61SKris Buschelman        0,
1336865e5f61SKris Buschelman        0,
1337d519adbfSMatthew Knepley /*94*/ 0,
1338865e5f61SKris Buschelman        0,
1339865e5f61SKris Buschelman        0,
134099cafbc1SBarry Smith        0,
134199cafbc1SBarry Smith        0,
1342d519adbfSMatthew Knepley /*99*/ 0,
134399cafbc1SBarry Smith        0,
134499cafbc1SBarry Smith        0,
134599cafbc1SBarry Smith        0,
134699cafbc1SBarry Smith        0,
1347d519adbfSMatthew Knepley /*104*/0,
134899cafbc1SBarry Smith        MatRealPart_SeqSBAIJ,
1349f5edf698SHong Zhang        MatImaginaryPart_SeqSBAIJ,
1350f5edf698SHong Zhang        MatGetRowUpperTriangular_SeqSBAIJ,
13512af78befSBarry Smith        MatRestoreRowUpperTriangular_SeqSBAIJ,
1352d519adbfSMatthew Knepley /*109*/0,
13532af78befSBarry Smith        0,
13542af78befSBarry Smith        0,
13552af78befSBarry Smith        0,
13562af78befSBarry Smith        MatMissingDiagonal_SeqSBAIJ
135799cafbc1SBarry Smith };
1358be1d678aSKris Buschelman 
135949b5e25fSSatish Balay EXTERN_C_BEGIN
13604a2ae208SSatish Balay #undef __FUNCT__
13614a2ae208SSatish Balay #define __FUNCT__ "MatStoreValues_SeqSBAIJ"
1362be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatStoreValues_SeqSBAIJ(Mat mat)
136349b5e25fSSatish Balay {
13644afc71dfSHong Zhang   Mat_SeqSBAIJ   *aij = (Mat_SeqSBAIJ *)mat->data;
1365d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->N]*mat->rmap->bs*aij->bs2;
1366dfbe8321SBarry Smith   PetscErrorCode ierr;
136749b5e25fSSatish Balay 
136849b5e25fSSatish Balay   PetscFunctionBegin;
136949b5e25fSSatish Balay   if (aij->nonew != 1) {
1370512a5fc5SBarry Smith     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
137149b5e25fSSatish Balay   }
137249b5e25fSSatish Balay 
137349b5e25fSSatish Balay   /* allocate space for values if not already there */
137449b5e25fSSatish Balay   if (!aij->saved_values) {
137587828ca2SBarry Smith     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr);
137649b5e25fSSatish Balay   }
137749b5e25fSSatish Balay 
137849b5e25fSSatish Balay   /* copy values over */
137987828ca2SBarry Smith   ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr);
138049b5e25fSSatish Balay   PetscFunctionReturn(0);
138149b5e25fSSatish Balay }
138249b5e25fSSatish Balay EXTERN_C_END
138349b5e25fSSatish Balay 
138449b5e25fSSatish Balay EXTERN_C_BEGIN
13854a2ae208SSatish Balay #undef __FUNCT__
13864a2ae208SSatish Balay #define __FUNCT__ "MatRetrieveValues_SeqSBAIJ"
1387be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatRetrieveValues_SeqSBAIJ(Mat mat)
138849b5e25fSSatish Balay {
13894afc71dfSHong Zhang   Mat_SeqSBAIJ   *aij = (Mat_SeqSBAIJ *)mat->data;
13906849ba73SBarry Smith   PetscErrorCode ierr;
1391d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->N]*mat->rmap->bs*aij->bs2;
139249b5e25fSSatish Balay 
139349b5e25fSSatish Balay   PetscFunctionBegin;
139449b5e25fSSatish Balay   if (aij->nonew != 1) {
1395512a5fc5SBarry Smith     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
139649b5e25fSSatish Balay   }
139749b5e25fSSatish Balay   if (!aij->saved_values) {
1398e005ede5SBarry Smith     SETERRQ(PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
139949b5e25fSSatish Balay   }
140049b5e25fSSatish Balay 
140149b5e25fSSatish Balay   /* copy values over */
140287828ca2SBarry Smith   ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr);
140349b5e25fSSatish Balay   PetscFunctionReturn(0);
140449b5e25fSSatish Balay }
140549b5e25fSSatish Balay EXTERN_C_END
140649b5e25fSSatish Balay 
14078549e402SHong Zhang EXTERN_C_BEGIN
14084a2ae208SSatish Balay #undef __FUNCT__
1409a23d5eceSKris Buschelman #define __FUNCT__ "MatSeqSBAIJSetPreallocation_SeqSBAIJ"
1410be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B,PetscInt bs,PetscInt nz,PetscInt *nnz)
141149b5e25fSSatish Balay {
1412c464158bSHong Zhang   Mat_SeqSBAIJ   *b = (Mat_SeqSBAIJ*)B->data;
14136849ba73SBarry Smith   PetscErrorCode ierr;
1414db4efbfdSBarry Smith   PetscInt       i,mbs,bs2, newbs = PetscAbs(bs);
141590d69ab7SBarry Smith   PetscTruth     skipallocation = PETSC_FALSE,flg = PETSC_FALSE;
141649b5e25fSSatish Balay 
141749b5e25fSSatish Balay   PetscFunctionBegin;
1418273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
1419db4efbfdSBarry Smith   if (bs < 0) {
1420db4efbfdSBarry Smith     ierr = PetscOptionsBegin(((PetscObject)B)->comm,((PetscObject)B)->prefix,"Options for MPISBAIJ matrix","Mat");CHKERRQ(ierr);
1421db4efbfdSBarry Smith       ierr = PetscOptionsInt("-mat_block_size","Set the blocksize used to store the matrix","MatSeqSBAIJSetPreallocation",newbs,&newbs,PETSC_NULL);CHKERRQ(ierr);
1422db4efbfdSBarry Smith     ierr = PetscOptionsEnd();CHKERRQ(ierr);
1423db4efbfdSBarry Smith     bs   = PetscAbs(bs);
1424db4efbfdSBarry Smith   }
1425db4efbfdSBarry Smith   if (nnz && newbs != bs) {
1426db4efbfdSBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot change blocksize from command line if setting nnz");
1427db4efbfdSBarry Smith   }
1428db4efbfdSBarry Smith   bs = newbs;
1429db4efbfdSBarry Smith 
14307408324eSLisandro Dalcin   ierr = PetscMapSetBlockSize(B->rmap,bs);CHKERRQ(ierr);
14317408324eSLisandro Dalcin   ierr = PetscMapSetBlockSize(B->cmap,bs);CHKERRQ(ierr);
1432d0f46423SBarry Smith   ierr = PetscMapSetUp(B->rmap);CHKERRQ(ierr);
1433d0f46423SBarry Smith   ierr = PetscMapSetUp(B->cmap);CHKERRQ(ierr);
1434899cda47SBarry Smith 
1435d0f46423SBarry Smith   mbs  = B->rmap->N/bs;
143649b5e25fSSatish Balay   bs2  = bs*bs;
143749b5e25fSSatish Balay 
1438d0f46423SBarry Smith   if (mbs*bs != B->rmap->N) {
143929bbc08cSBarry Smith     SETERRQ(PETSC_ERR_ARG_SIZ,"Number rows, cols must be divisible by blocksize");
144049b5e25fSSatish Balay   }
144149b5e25fSSatish Balay 
1442ab93d7beSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
1443ab93d7beSBarry Smith     skipallocation = PETSC_TRUE;
1444ab93d7beSBarry Smith     nz             = 0;
1445ab93d7beSBarry Smith   }
1446ab93d7beSBarry Smith 
1447435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3;
144877431f27SBarry Smith   if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
144949b5e25fSSatish Balay   if (nnz) {
145049b5e25fSSatish Balay     for (i=0; i<mbs; i++) {
145177431f27SBarry Smith       if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %D value %D",i,nnz[i]);
145277431f27SBarry 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);
145349b5e25fSSatish Balay     }
145449b5e25fSSatish Balay   }
145549b5e25fSSatish Balay 
1456db4efbfdSBarry Smith   B->ops->mult             = MatMult_SeqSBAIJ_N;
1457db4efbfdSBarry Smith   B->ops->multadd          = MatMultAdd_SeqSBAIJ_N;
1458db4efbfdSBarry Smith   B->ops->multtranspose    = MatMult_SeqSBAIJ_N;
1459db4efbfdSBarry Smith   B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N;
146090d69ab7SBarry Smith   ierr  = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_no_unroll",&flg,PETSC_NULL);CHKERRQ(ierr);
146149b5e25fSSatish Balay   if (!flg) {
146249b5e25fSSatish Balay     switch (bs) {
146349b5e25fSSatish Balay     case 1:
146449b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_1;
146549b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_1;
1466431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_1;
1467431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1;
146849b5e25fSSatish Balay       break;
146949b5e25fSSatish Balay     case 2:
147049b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_2;
147149b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_2;
1472431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_2;
1473431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2;
147449b5e25fSSatish Balay       break;
147549b5e25fSSatish Balay     case 3:
147649b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_3;
147749b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_3;
1478431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_3;
1479431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3;
148049b5e25fSSatish Balay       break;
148149b5e25fSSatish Balay     case 4:
148249b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_4;
148349b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_4;
1484431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_4;
1485431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4;
148649b5e25fSSatish Balay       break;
148749b5e25fSSatish Balay     case 5:
148849b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_5;
148949b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_5;
1490431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_5;
1491431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5;
149249b5e25fSSatish Balay       break;
149349b5e25fSSatish Balay     case 6:
149449b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_6;
149549b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_6;
1496431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_6;
1497431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6;
149849b5e25fSSatish Balay       break;
149949b5e25fSSatish Balay     case 7:
1500de53e5efSHong Zhang       B->ops->mult             = MatMult_SeqSBAIJ_7;
150149b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_7;
1502431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_7;
1503431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7;
150449b5e25fSSatish Balay       break;
150549b5e25fSSatish Balay     }
150649b5e25fSSatish Balay   }
150749b5e25fSSatish Balay 
150849b5e25fSSatish Balay   b->mbs = mbs;
15094afc71dfSHong Zhang   b->nbs = mbs;
1510ab93d7beSBarry Smith   if (!skipallocation) {
15112ee49352SLisandro Dalcin     if (!b->imax) {
1512ab93d7beSBarry Smith       ierr = PetscMalloc2(mbs,PetscInt,&b->imax,mbs,PetscInt,&b->ilen);CHKERRQ(ierr);
15132ee49352SLisandro Dalcin       ierr = PetscLogObjectMemory(B,2*mbs*sizeof(PetscInt));CHKERRQ(ierr);
15142ee49352SLisandro Dalcin     }
151549b5e25fSSatish Balay     if (!nnz) {
1516435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
151749b5e25fSSatish Balay       else if (nz <= 0)        nz = 1;
151849b5e25fSSatish Balay       for (i=0; i<mbs; i++) {
15198cef66ccSHong Zhang         b->imax[i] = nz;
152049b5e25fSSatish Balay       }
1521153ea458SHong Zhang       nz = nz*mbs; /* total nz */
152249b5e25fSSatish Balay     } else {
152349b5e25fSSatish Balay       nz = 0;
15248cef66ccSHong Zhang       for (i=0; i<mbs; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
152549b5e25fSSatish Balay     }
15262ee49352SLisandro Dalcin     /* b->ilen will count nonzeros in each block row so far. */
15272ee49352SLisandro Dalcin     for (i=0; i<mbs; i++) { b->ilen[i] = 0;}
15286c6c5352SBarry Smith     /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */
152949b5e25fSSatish Balay 
153049b5e25fSSatish Balay     /* allocate the matrix space */
15312ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
1532d0f46423SBarry Smith     ierr = PetscMalloc3(bs2*nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap->N+1,PetscInt,&b->i);CHKERRQ(ierr);
1533d0f46423SBarry Smith     ierr = PetscLogObjectMemory(B,(B->rmap->N+1)*sizeof(PetscInt)+nz*(bs2*sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
15346c6c5352SBarry Smith     ierr = PetscMemzero(b->a,nz*bs2*sizeof(MatScalar));CHKERRQ(ierr);
153513f74950SBarry Smith     ierr = PetscMemzero(b->j,nz*sizeof(PetscInt));CHKERRQ(ierr);
153649b5e25fSSatish Balay     b->singlemalloc = PETSC_TRUE;
153749b5e25fSSatish Balay 
153849b5e25fSSatish Balay     /* pointer to beginning of each row */
153949b5e25fSSatish Balay     b->i[0] = 0;
154049b5e25fSSatish Balay     for (i=1; i<mbs+1; i++) {
154149b5e25fSSatish Balay       b->i[i] = b->i[i-1] + b->imax[i-1];
154249b5e25fSSatish Balay     }
1543e6b907acSBarry Smith     b->free_a     = PETSC_TRUE;
1544e6b907acSBarry Smith     b->free_ij    = PETSC_TRUE;
1545e811da20SHong Zhang   } else {
1546e6b907acSBarry Smith     b->free_a     = PETSC_FALSE;
1547e6b907acSBarry Smith     b->free_ij    = PETSC_FALSE;
1548ab93d7beSBarry Smith   }
154949b5e25fSSatish Balay 
1550d0f46423SBarry Smith   B->rmap->bs               = bs;
155149b5e25fSSatish Balay   b->bs2              = bs2;
15526c6c5352SBarry Smith   b->nz             = 0;
15536c6c5352SBarry Smith   b->maxnz          = nz*bs2;
1554153ea458SHong Zhang 
155516cdd363SHong Zhang   b->inew             = 0;
155616cdd363SHong Zhang   b->jnew             = 0;
155716cdd363SHong Zhang   b->anew             = 0;
155816cdd363SHong Zhang   b->a2anew           = 0;
15591a3463dfSHong Zhang   b->permute          = PETSC_FALSE;
1560c464158bSHong Zhang   PetscFunctionReturn(0);
1561c464158bSHong Zhang }
1562a23d5eceSKris Buschelman EXTERN_C_END
1563153ea458SHong Zhang 
1564db4efbfdSBarry Smith #undef __FUNCT__
1565db4efbfdSBarry Smith #define __FUNCT__ "MatSeqBAIJSetNumericFactorization"
1566db4efbfdSBarry Smith /*
1567db4efbfdSBarry Smith    This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization
1568db4efbfdSBarry Smith */
1569db4efbfdSBarry Smith PetscErrorCode MatSeqSBAIJSetNumericFactorization(Mat B,PetscTruth natural)
1570db4efbfdSBarry Smith {
1571db4efbfdSBarry Smith   PetscErrorCode ierr;
157290d69ab7SBarry Smith   PetscTruth     flg = PETSC_FALSE;
1573db4efbfdSBarry Smith   PetscInt       bs = B->rmap->bs;
1574db4efbfdSBarry Smith 
1575db4efbfdSBarry Smith   PetscFunctionBegin;
157690d69ab7SBarry Smith   ierr    = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_no_unroll",&flg,PETSC_NULL);CHKERRQ(ierr);
1577db4efbfdSBarry Smith   if (flg) bs = 8;
1578db4efbfdSBarry Smith 
1579db4efbfdSBarry Smith   if (!natural) {
1580db4efbfdSBarry Smith     switch (bs) {
1581db4efbfdSBarry Smith     case 1:
1582db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1;
1583db4efbfdSBarry Smith       break;
1584db4efbfdSBarry Smith     case 2:
1585db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2;
1586db4efbfdSBarry Smith       break;
1587db4efbfdSBarry Smith     case 3:
1588db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3;
1589db4efbfdSBarry Smith       break;
1590db4efbfdSBarry Smith     case 4:
1591db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4;
1592db4efbfdSBarry Smith       break;
1593db4efbfdSBarry Smith     case 5:
1594db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5;
1595db4efbfdSBarry Smith       break;
1596db4efbfdSBarry Smith     case 6:
1597db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6;
1598db4efbfdSBarry Smith       break;
1599db4efbfdSBarry Smith     case 7:
1600db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7;
1601db4efbfdSBarry Smith       break;
1602db4efbfdSBarry Smith     default:
1603db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N;
1604db4efbfdSBarry Smith       break;
1605db4efbfdSBarry Smith     }
1606db4efbfdSBarry Smith   } else {
1607db4efbfdSBarry Smith     switch (bs) {
1608db4efbfdSBarry Smith     case 1:
1609db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering;
1610db4efbfdSBarry Smith       break;
1611db4efbfdSBarry Smith     case 2:
1612db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering;
1613db4efbfdSBarry Smith       break;
1614db4efbfdSBarry Smith     case 3:
1615db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering;
1616db4efbfdSBarry Smith       break;
1617db4efbfdSBarry Smith     case 4:
1618db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering;
1619db4efbfdSBarry Smith       break;
1620db4efbfdSBarry Smith     case 5:
1621db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering;
1622db4efbfdSBarry Smith       break;
1623db4efbfdSBarry Smith     case 6:
1624db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering;
1625db4efbfdSBarry Smith       break;
1626db4efbfdSBarry Smith     case 7:
1627db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering;
1628db4efbfdSBarry Smith       break;
1629db4efbfdSBarry Smith     default:
1630db4efbfdSBarry Smith       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering;
1631db4efbfdSBarry Smith       break;
1632db4efbfdSBarry Smith     }
1633db4efbfdSBarry Smith   }
1634db4efbfdSBarry Smith   PetscFunctionReturn(0);
1635db4efbfdSBarry Smith }
1636db4efbfdSBarry Smith 
1637d769727bSBarry Smith EXTERN_C_BEGIN
1638f69a0ea3SMatthew Knepley EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType,MatReuse,Mat*);
1639f69a0ea3SMatthew Knepley EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType,MatReuse,Mat*);
1640d769727bSBarry Smith EXTERN_C_END
1641d769727bSBarry Smith 
1642e631078cSBarry Smith 
1643e631078cSBarry Smith EXTERN_C_BEGIN
16445c9eb25fSBarry Smith #undef __FUNCT__
16455c9eb25fSBarry Smith #define __FUNCT__ "MatGetFactor_seqsbaij_petsc"
16465c9eb25fSBarry Smith PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A,MatFactorType ftype,Mat *B)
16475c9eb25fSBarry Smith {
1648d0f46423SBarry Smith   PetscInt           n = A->rmap->n;
16495c9eb25fSBarry Smith   PetscErrorCode     ierr;
16505c9eb25fSBarry Smith 
16515c9eb25fSBarry Smith   PetscFunctionBegin;
16525c9eb25fSBarry Smith   ierr = MatCreate(((PetscObject)A)->comm,B);CHKERRQ(ierr);
16535c9eb25fSBarry Smith   ierr = MatSetSizes(*B,n,n,n,n);CHKERRQ(ierr);
16545c9eb25fSBarry Smith   if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
16555c9eb25fSBarry Smith     ierr = MatSetType(*B,MATSEQSBAIJ);CHKERRQ(ierr);
16565c9eb25fSBarry Smith     ierr = MatSeqSBAIJSetPreallocation(*B,1,MAT_SKIP_ALLOCATION,PETSC_NULL);CHKERRQ(ierr);
1657db4efbfdSBarry Smith     (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ;
1658db4efbfdSBarry Smith     (*B)->ops->iccfactorsymbolic      = MatICCFactorSymbolic_SeqSBAIJ;
16595c9eb25fSBarry Smith   } else SETERRQ(PETSC_ERR_SUP,"Factor type not supported");
1660719d5645SBarry Smith   (*B)->factor = ftype;
16615c9eb25fSBarry Smith   PetscFunctionReturn(0);
16625c9eb25fSBarry Smith }
1663e631078cSBarry Smith EXTERN_C_END
16645c9eb25fSBarry Smith 
16655c9eb25fSBarry Smith EXTERN_C_BEGIN
1666db4efbfdSBarry Smith #undef __FUNCT__
1667db4efbfdSBarry Smith #define __FUNCT__ "MatGetFactorAvailable_seqsbaij_petsc"
1668db4efbfdSBarry Smith PetscErrorCode MatGetFactorAvailable_seqsbaij_petsc(Mat A,MatFactorType ftype,PetscTruth *flg)
1669db4efbfdSBarry Smith {
1670db4efbfdSBarry Smith   PetscFunctionBegin;
1671db4efbfdSBarry Smith   if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1672db4efbfdSBarry Smith     *flg = PETSC_TRUE;
1673db4efbfdSBarry Smith   } else {
1674db4efbfdSBarry Smith     *flg = PETSC_FALSE;
1675db4efbfdSBarry Smith   }
1676db4efbfdSBarry Smith   PetscFunctionReturn(0);
1677db4efbfdSBarry Smith }
1678db4efbfdSBarry Smith EXTERN_C_END
1679db4efbfdSBarry Smith 
1680db4efbfdSBarry Smith EXTERN_C_BEGIN
1681611f576cSBarry Smith #if defined(PETSC_HAVE_MUMPS)
16825c9eb25fSBarry Smith extern PetscErrorCode MatGetFactor_seqsbaij_mumps(Mat,MatFactorType,Mat*);
1683611f576cSBarry Smith #endif
1684611f576cSBarry Smith #if defined(PETSC_HAVE_SPOOLES)
16855c9eb25fSBarry Smith extern PetscErrorCode MatGetFactor_seqsbaij_spooles(Mat,MatFactorType,Mat*);
1686611f576cSBarry Smith #endif
1687b5e56a35SBarry Smith #if defined(PETSC_HAVE_PASTIX)
1688b5e56a35SBarry Smith extern PetscErrorCode MatGetFactor_seqsbaij_pastix(Mat,MatFactorType,Mat*);
1689b5e56a35SBarry Smith #endif
16905c9eb25fSBarry Smith EXTERN_C_END
16915c9eb25fSBarry Smith 
16920bad9183SKris Buschelman /*MC
1693fafad747SKris Buschelman   MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices,
16940bad9183SKris Buschelman   based on block compressed sparse row format.  Only the upper triangular portion of the matrix is stored.
16950bad9183SKris Buschelman 
16960bad9183SKris Buschelman   Options Database Keys:
16970bad9183SKris Buschelman   . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to MatSetFromOptions()
16980bad9183SKris Buschelman 
16990bad9183SKris Buschelman   Level: beginner
17000bad9183SKris Buschelman 
17010bad9183SKris Buschelman   .seealso: MatCreateSeqSBAIJ
17020bad9183SKris Buschelman M*/
17030bad9183SKris Buschelman 
1704a23d5eceSKris Buschelman EXTERN_C_BEGIN
1705a23d5eceSKris Buschelman #undef __FUNCT__
1706a23d5eceSKris Buschelman #define __FUNCT__ "MatCreate_SeqSBAIJ"
1707be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_SeqSBAIJ(Mat B)
1708a23d5eceSKris Buschelman {
1709a23d5eceSKris Buschelman   Mat_SeqSBAIJ   *b;
1710dfbe8321SBarry Smith   PetscErrorCode ierr;
171113f74950SBarry Smith   PetscMPIInt    size;
17120def2e27SBarry Smith   PetscTruth     no_unroll = PETSC_FALSE,no_inode = PETSC_FALSE;
1713a23d5eceSKris Buschelman 
1714a23d5eceSKris Buschelman   PetscFunctionBegin;
17157adad957SLisandro Dalcin   ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr);
1716a23d5eceSKris Buschelman   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"Comm must be of size 1");
1717a23d5eceSKris Buschelman 
171838f2d2fdSLisandro Dalcin   ierr    = PetscNewLog(B,Mat_SeqSBAIJ,&b);CHKERRQ(ierr);
1719a23d5eceSKris Buschelman   B->data = (void*)b;
1720a23d5eceSKris Buschelman   ierr    = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
1721a23d5eceSKris Buschelman   B->ops->destroy     = MatDestroy_SeqSBAIJ;
1722a23d5eceSKris Buschelman   B->ops->view        = MatView_SeqSBAIJ;
1723a23d5eceSKris Buschelman   B->mapping          = 0;
1724a23d5eceSKris Buschelman   b->row              = 0;
1725a23d5eceSKris Buschelman   b->icol             = 0;
1726a23d5eceSKris Buschelman   b->reallocs         = 0;
1727a23d5eceSKris Buschelman   b->saved_values     = 0;
17280def2e27SBarry Smith   b->inode.limit      = 5;
17290def2e27SBarry Smith   b->inode.max_limit  = 5;
1730a23d5eceSKris Buschelman 
1731a23d5eceSKris Buschelman   b->roworiented      = PETSC_TRUE;
1732a23d5eceSKris Buschelman   b->nonew            = 0;
1733a23d5eceSKris Buschelman   b->diag             = 0;
1734a23d5eceSKris Buschelman   b->solve_work       = 0;
1735a23d5eceSKris Buschelman   b->mult_work        = 0;
1736a23d5eceSKris Buschelman   B->spptr            = 0;
1737a9817697SBarry Smith   b->keepnonzeropattern   = PETSC_FALSE;
1738a23d5eceSKris Buschelman   b->xtoy             = 0;
1739a23d5eceSKris Buschelman   b->XtoY             = 0;
1740a23d5eceSKris Buschelman 
1741a23d5eceSKris Buschelman   b->inew             = 0;
1742a23d5eceSKris Buschelman   b->jnew             = 0;
1743a23d5eceSKris Buschelman   b->anew             = 0;
1744a23d5eceSKris Buschelman   b->a2anew           = 0;
1745a23d5eceSKris Buschelman   b->permute          = PETSC_FALSE;
1746a23d5eceSKris Buschelman 
1747941593c8SHong Zhang   b->ignore_ltriangular = PETSC_FALSE;
174890d69ab7SBarry Smith   ierr = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_ignore_lower_triangular",&b->ignore_ltriangular,PETSC_NULL);CHKERRQ(ierr);
1749941593c8SHong Zhang 
1750f5edf698SHong Zhang   b->getrow_utriangular = PETSC_FALSE;
175190d69ab7SBarry Smith   ierr = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_getrow_uppertriangular",&b->getrow_utriangular,PETSC_NULL);CHKERRQ(ierr);
1752f5edf698SHong Zhang 
1753b5e56a35SBarry Smith #if defined(PETSC_HAVE_PASTIX)
1754b5e56a35SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_pastix_C",
1755b5e56a35SBarry Smith 					   "MatGetFactor_seqsbaij_pastix",
1756b5e56a35SBarry Smith 					   MatGetFactor_seqsbaij_pastix);CHKERRQ(ierr);
1757b5e56a35SBarry Smith #endif
1758611f576cSBarry Smith #if defined(PETSC_HAVE_SPOOLES)
17595c9eb25fSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_spooles_C",
17605c9eb25fSBarry Smith                                      "MatGetFactor_seqsbaij_spooles",
17615c9eb25fSBarry Smith                                      MatGetFactor_seqsbaij_spooles);CHKERRQ(ierr);
1762611f576cSBarry Smith #endif
1763611f576cSBarry Smith #if defined(PETSC_HAVE_MUMPS)
17645c9eb25fSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_mumps_C",
17655c9eb25fSBarry Smith                                      "MatGetFactor_seqsbaij_mumps",
17665c9eb25fSBarry Smith                                      MatGetFactor_seqsbaij_mumps);CHKERRQ(ierr);
1767611f576cSBarry Smith #endif
1768db4efbfdSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_seqsbaij_petsc_C",
1769db4efbfdSBarry Smith                                      "MatGetFactorAvailable_seqsbaij_petsc",
1770db4efbfdSBarry Smith                                      MatGetFactorAvailable_seqsbaij_petsc);CHKERRQ(ierr);
17715c9eb25fSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_petsc_C",
17725c9eb25fSBarry Smith                                      "MatGetFactor_seqsbaij_petsc",
17735c9eb25fSBarry Smith                                      MatGetFactor_seqsbaij_petsc);CHKERRQ(ierr);
1774a23d5eceSKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
1775a23d5eceSKris Buschelman                                      "MatStoreValues_SeqSBAIJ",
1776a23d5eceSKris Buschelman                                      MatStoreValues_SeqSBAIJ);CHKERRQ(ierr);
1777a23d5eceSKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
1778a23d5eceSKris Buschelman                                      "MatRetrieveValues_SeqSBAIJ",
1779a23d5eceSKris Buschelman                                      (void*)MatRetrieveValues_SeqSBAIJ);CHKERRQ(ierr);
1780a23d5eceSKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetColumnIndices_C",
1781a23d5eceSKris Buschelman                                      "MatSeqSBAIJSetColumnIndices_SeqSBAIJ",
1782a23d5eceSKris Buschelman                                      MatSeqSBAIJSetColumnIndices_SeqSBAIJ);CHKERRQ(ierr);
17834e5e7fe4SHong Zhang   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqaij_C",
17844e5e7fe4SHong Zhang                                      "MatConvert_SeqSBAIJ_SeqAIJ",
17854e5e7fe4SHong Zhang                                       MatConvert_SeqSBAIJ_SeqAIJ);CHKERRQ(ierr);
1786a0e1a404SHong Zhang   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqbaij_C",
1787a0e1a404SHong Zhang                                      "MatConvert_SeqSBAIJ_SeqBAIJ",
1788a0e1a404SHong Zhang                                       MatConvert_SeqSBAIJ_SeqBAIJ);CHKERRQ(ierr);
1789a23d5eceSKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetPreallocation_C",
1790a23d5eceSKris Buschelman                                      "MatSeqSBAIJSetPreallocation_SeqSBAIJ",
1791a23d5eceSKris Buschelman                                      MatSeqSBAIJSetPreallocation_SeqSBAIJ);CHKERRQ(ierr);
179223ce1328SBarry Smith 
179323ce1328SBarry Smith   B->symmetric                  = PETSC_TRUE;
179423ce1328SBarry Smith   B->structurally_symmetric     = PETSC_TRUE;
179523ce1328SBarry Smith   B->symmetric_set              = PETSC_TRUE;
179623ce1328SBarry Smith   B->structurally_symmetric_set = PETSC_TRUE;
179717667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQSBAIJ);CHKERRQ(ierr);
17980def2e27SBarry Smith 
17990def2e27SBarry Smith   ierr = PetscOptionsBegin(((PetscObject)B)->comm,((PetscObject)B)->prefix,"Options for SEQSBAIJ matrix","Mat");CHKERRQ(ierr);
18000def2e27SBarry Smith     ierr = PetscOptionsTruth("-mat_no_unroll","Do not optimize for inodes (slower)",PETSC_NULL,no_unroll,&no_unroll,PETSC_NULL);CHKERRQ(ierr);
18010def2e27SBarry Smith     if (no_unroll) {ierr = PetscInfo(B,"Not using Inode routines due to -mat_no_unroll\n");CHKERRQ(ierr);}
18020def2e27SBarry Smith     ierr = PetscOptionsTruth("-mat_no_inode","Do not optimize for inodes (slower)",PETSC_NULL,no_inode,&no_inode,PETSC_NULL);CHKERRQ(ierr);
18030def2e27SBarry Smith     if (no_inode) {ierr = PetscInfo(B,"Not using Inode routines due to -mat_no_inode\n");CHKERRQ(ierr);}
18040def2e27SBarry 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);
18050def2e27SBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
18060def2e27SBarry Smith   b->inode.use = (PetscTruth)(!(no_unroll || no_inode));
18070def2e27SBarry Smith   if (b->inode.limit > b->inode.max_limit) b->inode.limit = b->inode.max_limit;
18080def2e27SBarry Smith 
1809a23d5eceSKris Buschelman   PetscFunctionReturn(0);
1810a23d5eceSKris Buschelman }
1811a23d5eceSKris Buschelman EXTERN_C_END
1812a23d5eceSKris Buschelman 
1813a23d5eceSKris Buschelman #undef __FUNCT__
1814a23d5eceSKris Buschelman #define __FUNCT__ "MatSeqSBAIJSetPreallocation"
1815a23d5eceSKris Buschelman /*@C
1816a23d5eceSKris Buschelman    MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block
1817a23d5eceSKris Buschelman    compressed row) format.  For good matrix assembly performance the
1818a23d5eceSKris Buschelman    user should preallocate the matrix storage by setting the parameter nz
1819a23d5eceSKris Buschelman    (or the array nnz).  By setting these parameters accurately, performance
1820a23d5eceSKris Buschelman    during matrix assembly can be increased by more than a factor of 50.
1821a23d5eceSKris Buschelman 
1822a23d5eceSKris Buschelman    Collective on Mat
1823a23d5eceSKris Buschelman 
1824a23d5eceSKris Buschelman    Input Parameters:
1825a23d5eceSKris Buschelman +  A - the symmetric matrix
1826a23d5eceSKris Buschelman .  bs - size of block
1827a23d5eceSKris Buschelman .  nz - number of block nonzeros per block row (same for all rows)
1828a23d5eceSKris Buschelman -  nnz - array containing the number of block nonzeros in the upper triangular plus
1829a23d5eceSKris Buschelman          diagonal portion of each block (possibly different for each block row) or PETSC_NULL
1830a23d5eceSKris Buschelman 
1831a23d5eceSKris Buschelman    Options Database Keys:
1832a23d5eceSKris Buschelman .   -mat_no_unroll - uses code that does not unroll the loops in the
1833a23d5eceSKris Buschelman                      block calculations (much slower)
1834db4efbfdSBarry Smith .    -mat_block_size - size of the blocks to use (only works if a negative bs is passed in
1835a23d5eceSKris Buschelman 
1836a23d5eceSKris Buschelman    Level: intermediate
1837a23d5eceSKris Buschelman 
1838a23d5eceSKris Buschelman    Notes:
1839a23d5eceSKris Buschelman    Specify the preallocated storage with either nz or nnz (not both).
1840a23d5eceSKris Buschelman    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
1841a23d5eceSKris Buschelman    allocation.  For additional details, see the users manual chapter on
1842a23d5eceSKris Buschelman    matrices.
1843a23d5eceSKris Buschelman 
1844aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
1845aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
1846aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
1847aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
1848aa95bbe8SBarry Smith 
184949a6f317SBarry Smith    If the nnz parameter is given then the nz parameter is ignored
185049a6f317SBarry Smith 
185149a6f317SBarry Smith 
1852a23d5eceSKris Buschelman .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ()
1853a23d5eceSKris Buschelman @*/
1854be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetPreallocation(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[])
185513f74950SBarry Smith {
185613f74950SBarry Smith   PetscErrorCode ierr,(*f)(Mat,PetscInt,PetscInt,const PetscInt[]);
1857a23d5eceSKris Buschelman 
1858a23d5eceSKris Buschelman   PetscFunctionBegin;
1859a23d5eceSKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqSBAIJSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr);
1860a23d5eceSKris Buschelman   if (f) {
1861a23d5eceSKris Buschelman     ierr = (*f)(B,bs,nz,nnz);CHKERRQ(ierr);
1862a23d5eceSKris Buschelman   }
1863a23d5eceSKris Buschelman   PetscFunctionReturn(0);
1864a23d5eceSKris Buschelman }
186549b5e25fSSatish Balay 
18664a2ae208SSatish Balay #undef __FUNCT__
18674a2ae208SSatish Balay #define __FUNCT__ "MatCreateSeqSBAIJ"
1868c464158bSHong Zhang /*@C
1869c464158bSHong Zhang    MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in block AIJ (block
1870c464158bSHong Zhang    compressed row) format.  For good matrix assembly performance the
1871c464158bSHong Zhang    user should preallocate the matrix storage by setting the parameter nz
1872c464158bSHong Zhang    (or the array nnz).  By setting these parameters accurately, performance
1873c464158bSHong Zhang    during matrix assembly can be increased by more than a factor of 50.
187449b5e25fSSatish Balay 
1875c464158bSHong Zhang    Collective on MPI_Comm
1876c464158bSHong Zhang 
1877c464158bSHong Zhang    Input Parameters:
1878c464158bSHong Zhang +  comm - MPI communicator, set to PETSC_COMM_SELF
1879c464158bSHong Zhang .  bs - size of block
1880c464158bSHong Zhang .  m - number of rows, or number of columns
1881c464158bSHong Zhang .  nz - number of block nonzeros per block row (same for all rows)
1882744e8345SSatish Balay -  nnz - array containing the number of block nonzeros in the upper triangular plus
1883744e8345SSatish Balay          diagonal portion of each block (possibly different for each block row) or PETSC_NULL
1884c464158bSHong Zhang 
1885c464158bSHong Zhang    Output Parameter:
1886c464158bSHong Zhang .  A - the symmetric matrix
1887c464158bSHong Zhang 
1888c464158bSHong Zhang    Options Database Keys:
1889c464158bSHong Zhang .   -mat_no_unroll - uses code that does not unroll the loops in the
1890c464158bSHong Zhang                      block calculations (much slower)
1891c464158bSHong Zhang .    -mat_block_size - size of the blocks to use
1892c464158bSHong Zhang 
1893c464158bSHong Zhang    Level: intermediate
1894c464158bSHong Zhang 
1895175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
1896ae1d86c5SBarry Smith    MatXXXXSetPreallocation() paradgm instead of this routine directly.
1897175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
1898175b88e8SBarry Smith 
1899c464158bSHong Zhang    Notes:
19006d6d819aSHong Zhang    The number of rows and columns must be divisible by blocksize.
19016d6d819aSHong Zhang    This matrix type does not support complex Hermitian operation.
1902c464158bSHong Zhang 
1903c464158bSHong Zhang    Specify the preallocated storage with either nz or nnz (not both).
1904c464158bSHong Zhang    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
1905c464158bSHong Zhang    allocation.  For additional details, see the users manual chapter on
1906c464158bSHong Zhang    matrices.
1907c464158bSHong Zhang 
190849a6f317SBarry Smith    If the nnz parameter is given then the nz parameter is ignored
190949a6f317SBarry Smith 
1910c464158bSHong Zhang .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ()
1911c464158bSHong Zhang @*/
1912be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqSBAIJ(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
1913c464158bSHong Zhang {
1914dfbe8321SBarry Smith   PetscErrorCode ierr;
1915c464158bSHong Zhang 
1916c464158bSHong Zhang   PetscFunctionBegin;
1917f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
1918f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
1919c464158bSHong Zhang   ierr = MatSetType(*A,MATSEQSBAIJ);CHKERRQ(ierr);
1920ab93d7beSBarry Smith   ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(*A,bs,nz,(PetscInt*)nnz);CHKERRQ(ierr);
192149b5e25fSSatish Balay   PetscFunctionReturn(0);
192249b5e25fSSatish Balay }
192349b5e25fSSatish Balay 
19244a2ae208SSatish Balay #undef __FUNCT__
19254a2ae208SSatish Balay #define __FUNCT__ "MatDuplicate_SeqSBAIJ"
1926dfbe8321SBarry Smith PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
192749b5e25fSSatish Balay {
192849b5e25fSSatish Balay   Mat            C;
192949b5e25fSSatish Balay   Mat_SeqSBAIJ   *c,*a = (Mat_SeqSBAIJ*)A->data;
19306849ba73SBarry Smith   PetscErrorCode ierr;
1931b40805acSSatish Balay   PetscInt       i,mbs = a->mbs,nz = a->nz,bs2 =a->bs2;
193249b5e25fSSatish Balay 
193349b5e25fSSatish Balay   PetscFunctionBegin;
193429bbc08cSBarry Smith   if (a->i[mbs] != nz) SETERRQ(PETSC_ERR_PLIB,"Corrupt matrix");
193549b5e25fSSatish Balay 
193649b5e25fSSatish Balay   *B = 0;
19377adad957SLisandro Dalcin   ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr);
1938d0f46423SBarry Smith   ierr = MatSetSizes(C,A->rmap->N,A->cmap->n,A->rmap->N,A->cmap->n);CHKERRQ(ierr);
19397adad957SLisandro Dalcin   ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
19401d5dac46SHong Zhang   ierr = PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1941692f9cbeSHong Zhang   c    = (Mat_SeqSBAIJ*)C->data;
1942692f9cbeSHong Zhang 
1943273d9f13SBarry Smith   C->preallocated       = PETSC_TRUE;
194449b5e25fSSatish Balay   C->factor             = A->factor;
194549b5e25fSSatish Balay   c->row                = 0;
194649b5e25fSSatish Balay   c->icol               = 0;
194749b5e25fSSatish Balay   c->saved_values       = 0;
1948a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
194949b5e25fSSatish Balay   C->assembled          = PETSC_TRUE;
195049b5e25fSSatish Balay 
1951d0f46423SBarry Smith   ierr = PetscMapCopy(((PetscObject)A)->comm,A->rmap,C->rmap);CHKERRQ(ierr);
1952d0f46423SBarry Smith   ierr = PetscMapCopy(((PetscObject)A)->comm,A->cmap,C->cmap);CHKERRQ(ierr);
195349b5e25fSSatish Balay   c->bs2  = a->bs2;
195449b5e25fSSatish Balay   c->mbs  = a->mbs;
195549b5e25fSSatish Balay   c->nbs  = a->nbs;
195649b5e25fSSatish Balay 
19578777fc3fSSatish Balay   ierr = PetscMalloc2((mbs+1),PetscInt,&c->imax,(mbs+1),PetscInt,&c->ilen);CHKERRQ(ierr);
195849b5e25fSSatish Balay   for (i=0; i<mbs; i++) {
195949b5e25fSSatish Balay     c->imax[i] = a->imax[i];
196049b5e25fSSatish Balay     c->ilen[i] = a->ilen[i];
196149b5e25fSSatish Balay   }
196249b5e25fSSatish Balay 
196349b5e25fSSatish Balay   /* allocate the matrix space */
1964b40805acSSatish Balay   ierr = PetscMalloc3(bs2*nz,MatScalar,&c->a,nz,PetscInt,&c->j,mbs+1,PetscInt,&c->i);CHKERRQ(ierr);
196549b5e25fSSatish Balay   c->singlemalloc = PETSC_TRUE;
196613f74950SBarry Smith   ierr = PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr);
1967b40805acSSatish Balay   ierr = PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt) + nz*(bs2*sizeof(MatScalar) + sizeof(PetscInt)));CHKERRQ(ierr);
196849b5e25fSSatish Balay   if (mbs > 0) {
196913f74950SBarry Smith     ierr = PetscMemcpy(c->j,a->j,nz*sizeof(PetscInt));CHKERRQ(ierr);
197049b5e25fSSatish Balay     if (cpvalues == MAT_COPY_VALUES) {
197149b5e25fSSatish Balay       ierr = PetscMemcpy(c->a,a->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr);
197249b5e25fSSatish Balay     } else {
197349b5e25fSSatish Balay       ierr = PetscMemzero(c->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr);
197449b5e25fSSatish Balay     }
197549b5e25fSSatish Balay   }
197649b5e25fSSatish Balay 
197749b5e25fSSatish Balay   c->roworiented = a->roworiented;
197849b5e25fSSatish Balay   c->nonew       = a->nonew;
197949b5e25fSSatish Balay 
198049b5e25fSSatish Balay   if (a->diag) {
198113f74950SBarry Smith     ierr = PetscMalloc((mbs+1)*sizeof(PetscInt),&c->diag);CHKERRQ(ierr);
198252e6d16bSBarry Smith     ierr = PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr);
198349b5e25fSSatish Balay     for (i=0; i<mbs; i++) {
198449b5e25fSSatish Balay       c->diag[i] = a->diag[i];
198549b5e25fSSatish Balay     }
198649b5e25fSSatish Balay   } else c->diag  = 0;
19876c6c5352SBarry Smith   c->nz           = a->nz;
19886c6c5352SBarry Smith   c->maxnz        = a->maxnz;
198949b5e25fSSatish Balay   c->solve_work   = 0;
199049b5e25fSSatish Balay   c->mult_work    = 0;
1991e6b907acSBarry Smith   c->free_a       = PETSC_TRUE;
1992e6b907acSBarry Smith   c->free_ij      = PETSC_TRUE;
199349b5e25fSSatish Balay   *B = C;
19947adad957SLisandro Dalcin   ierr = PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
199549b5e25fSSatish Balay   PetscFunctionReturn(0);
199649b5e25fSSatish Balay }
199749b5e25fSSatish Balay 
19984a2ae208SSatish Balay #undef __FUNCT__
19994a2ae208SSatish Balay #define __FUNCT__ "MatLoad_SeqSBAIJ"
2000a313700dSBarry Smith PetscErrorCode MatLoad_SeqSBAIJ(PetscViewer viewer, const MatType type,Mat *A)
200149b5e25fSSatish Balay {
200249b5e25fSSatish Balay   Mat_SeqSBAIJ   *a;
200349b5e25fSSatish Balay   Mat            B;
20046849ba73SBarry Smith   PetscErrorCode ierr;
200513f74950SBarry Smith   int            fd;
200613f74950SBarry Smith   PetscMPIInt    size;
200713f74950SBarry Smith   PetscInt       i,nz,header[4],*rowlengths=0,M,N,bs=1;
200813f74950SBarry Smith   PetscInt       *mask,mbs,*jj,j,rowcount,nzcount,k,*s_browlengths,maskcount;
200913f74950SBarry Smith   PetscInt       kmax,jcount,block,idx,point,nzcountb,extra_rows;
201013f74950SBarry Smith   PetscInt       *masked,nmask,tmp,bs2,ishift;
201187828ca2SBarry Smith   PetscScalar    *aa;
201249b5e25fSSatish Balay   MPI_Comm       comm = ((PetscObject)viewer)->comm;
201349b5e25fSSatish Balay 
201449b5e25fSSatish Balay   PetscFunctionBegin;
2015b0a32e0cSBarry Smith   ierr = PetscOptionsGetInt(PETSC_NULL,"-matload_block_size",&bs,PETSC_NULL);CHKERRQ(ierr);
201649b5e25fSSatish Balay   bs2  = bs*bs;
201749b5e25fSSatish Balay 
201849b5e25fSSatish Balay   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
201929bbc08cSBarry Smith   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"view must have one processor");
2020b0a32e0cSBarry Smith   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
202149b5e25fSSatish Balay   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
2022552e946dSBarry Smith   if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not Mat object");
202349b5e25fSSatish Balay   M = header[1]; N = header[2]; nz = header[3];
202449b5e25fSSatish Balay 
202549b5e25fSSatish Balay   if (header[3] < 0) {
202629bbc08cSBarry Smith     SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format, cannot load as SeqSBAIJ");
202749b5e25fSSatish Balay   }
202849b5e25fSSatish Balay 
202929bbc08cSBarry Smith   if (M != N) SETERRQ(PETSC_ERR_SUP,"Can only do square matrices");
203049b5e25fSSatish Balay 
203149b5e25fSSatish Balay   /*
203249b5e25fSSatish Balay      This code adds extra rows to make sure the number of rows is
203349b5e25fSSatish Balay     divisible by the blocksize
203449b5e25fSSatish Balay   */
203549b5e25fSSatish Balay   mbs        = M/bs;
203649b5e25fSSatish Balay   extra_rows = bs - M + bs*(mbs);
203749b5e25fSSatish Balay   if (extra_rows == bs) extra_rows = 0;
203849b5e25fSSatish Balay   else                  mbs++;
203949b5e25fSSatish Balay   if (extra_rows) {
20401e2582c4SBarry Smith     ierr = PetscInfo(viewer,"Padding loaded matrix to match blocksize\n");CHKERRQ(ierr);
204149b5e25fSSatish Balay   }
204249b5e25fSSatish Balay 
204349b5e25fSSatish Balay   /* read in row lengths */
204413f74950SBarry Smith   ierr = PetscMalloc((M+extra_rows)*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
204549b5e25fSSatish Balay   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
204649b5e25fSSatish Balay   for (i=0; i<extra_rows; i++) rowlengths[M+i] = 1;
204749b5e25fSSatish Balay 
204849b5e25fSSatish Balay   /* read in column indices */
204913f74950SBarry Smith   ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscInt),&jj);CHKERRQ(ierr);
205049b5e25fSSatish Balay   ierr = PetscBinaryRead(fd,jj,nz,PETSC_INT);CHKERRQ(ierr);
205149b5e25fSSatish Balay   for (i=0; i<extra_rows; i++) jj[nz+i] = M+i;
205249b5e25fSSatish Balay 
205349b5e25fSSatish Balay   /* loop over row lengths determining block row lengths */
205413f74950SBarry Smith   ierr     = PetscMalloc(mbs*sizeof(PetscInt),&s_browlengths);CHKERRQ(ierr);
205513f74950SBarry Smith   ierr     = PetscMemzero(s_browlengths,mbs*sizeof(PetscInt));CHKERRQ(ierr);
205613f74950SBarry Smith   ierr     = PetscMalloc(2*mbs*sizeof(PetscInt),&mask);CHKERRQ(ierr);
205713f74950SBarry Smith   ierr     = PetscMemzero(mask,mbs*sizeof(PetscInt));CHKERRQ(ierr);
205849b5e25fSSatish Balay   masked   = mask + mbs;
205949b5e25fSSatish Balay   rowcount = 0; nzcount = 0;
206049b5e25fSSatish Balay   for (i=0; i<mbs; i++) {
206149b5e25fSSatish Balay     nmask = 0;
206249b5e25fSSatish Balay     for (j=0; j<bs; j++) {
206349b5e25fSSatish Balay       kmax = rowlengths[rowcount];
206449b5e25fSSatish Balay       for (k=0; k<kmax; k++) {
20652d703238SHong Zhang         tmp = jj[nzcount++]/bs;   /* block col. index */
206603630b6eSHong Zhang         if (!mask[tmp] && tmp >= i) {masked[nmask++] = tmp; mask[tmp] = 1;}
206749b5e25fSSatish Balay       }
206849b5e25fSSatish Balay       rowcount++;
206949b5e25fSSatish Balay     }
2070574b2666SHong Zhang     s_browlengths[i] += nmask;
2071574b2666SHong Zhang 
207249b5e25fSSatish Balay     /* zero out the mask elements we set */
207349b5e25fSSatish Balay     for (j=0; j<nmask; j++) mask[masked[j]] = 0;
207449b5e25fSSatish Balay   }
207549b5e25fSSatish Balay 
207649b5e25fSSatish Balay   /* create our matrix */
2077f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,&B);CHKERRQ(ierr);
2078f69a0ea3SMatthew Knepley   ierr = MatSetSizes(B,M+extra_rows,N+extra_rows,M+extra_rows,N+extra_rows);CHKERRQ(ierr);
20799abb65ffSKris Buschelman   ierr = MatSetType(B,type);CHKERRQ(ierr);
2080ab93d7beSBarry Smith   ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(B,bs,0,s_browlengths);CHKERRQ(ierr);
208149b5e25fSSatish Balay   a = (Mat_SeqSBAIJ*)B->data;
208249b5e25fSSatish Balay 
208349b5e25fSSatish Balay   /* set matrix "i" values */
208449b5e25fSSatish Balay   a->i[0] = 0;
208549b5e25fSSatish Balay   for (i=1; i<= mbs; i++) {
2086574b2666SHong Zhang     a->i[i]      = a->i[i-1] + s_browlengths[i-1];
2087574b2666SHong Zhang     a->ilen[i-1] = s_browlengths[i-1];
208849b5e25fSSatish Balay   }
20896c6c5352SBarry Smith   a->nz = a->i[mbs];
209049b5e25fSSatish Balay 
209149b5e25fSSatish Balay   /* read in nonzero values */
209287828ca2SBarry Smith   ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscScalar),&aa);CHKERRQ(ierr);
209349b5e25fSSatish Balay   ierr = PetscBinaryRead(fd,aa,nz,PETSC_SCALAR);CHKERRQ(ierr);
209449b5e25fSSatish Balay   for (i=0; i<extra_rows; i++) aa[nz+i] = 1.0;
209549b5e25fSSatish Balay 
209649b5e25fSSatish Balay   /* set "a" and "j" values into matrix */
209749b5e25fSSatish Balay   nzcount = 0; jcount = 0;
209849b5e25fSSatish Balay   for (i=0; i<mbs; i++) {
209949b5e25fSSatish Balay     nzcountb = nzcount;
210049b5e25fSSatish Balay     nmask    = 0;
210149b5e25fSSatish Balay     for (j=0; j<bs; j++) {
210249b5e25fSSatish Balay       kmax = rowlengths[i*bs+j];
210349b5e25fSSatish Balay       for (k=0; k<kmax; k++) {
21042d703238SHong Zhang         tmp = jj[nzcount++]/bs; /* block col. index */
210503630b6eSHong Zhang         if (!mask[tmp] && tmp >= i) { masked[nmask++] = tmp; mask[tmp] = 1;}
21062d703238SHong Zhang       }
21072d703238SHong Zhang     }
21082d703238SHong Zhang     /* sort the masked values */
21092d703238SHong Zhang     ierr = PetscSortInt(nmask,masked);CHKERRQ(ierr);
21102d703238SHong Zhang 
21112d703238SHong Zhang     /* set "j" values into matrix */
21122d703238SHong Zhang     maskcount = 1;
21132d703238SHong Zhang     for (j=0; j<nmask; j++) {
211449b5e25fSSatish Balay       a->j[jcount++]  = masked[j];
211549b5e25fSSatish Balay       mask[masked[j]] = maskcount++;
211649b5e25fSSatish Balay     }
2117574b2666SHong Zhang 
211849b5e25fSSatish Balay     /* set "a" values into matrix */
211949b5e25fSSatish Balay     ishift = bs2*a->i[i];
212049b5e25fSSatish Balay     for (j=0; j<bs; j++) {
212149b5e25fSSatish Balay       kmax = rowlengths[i*bs+j];
212249b5e25fSSatish Balay       for (k=0; k<kmax; k++) {
2123574b2666SHong Zhang         tmp       = jj[nzcountb]/bs ; /* block col. index */
2124574b2666SHong Zhang         if (tmp >= i){
212549b5e25fSSatish Balay           block     = mask[tmp] - 1;
212649b5e25fSSatish Balay           point     = jj[nzcountb] - bs*tmp;
212749b5e25fSSatish Balay           idx       = ishift + bs2*block + j + bs*point;
2128574b2666SHong Zhang           a->a[idx] = aa[nzcountb];
2129574b2666SHong Zhang         }
2130574b2666SHong Zhang         nzcountb++;
213149b5e25fSSatish Balay       }
213249b5e25fSSatish Balay     }
213349b5e25fSSatish Balay     /* zero out the mask elements we set */
213449b5e25fSSatish Balay     for (j=0; j<nmask; j++) mask[masked[j]] = 0;
213549b5e25fSSatish Balay   }
21366c6c5352SBarry Smith   if (jcount != a->nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Bad binary matrix");
213749b5e25fSSatish Balay 
213849b5e25fSSatish Balay   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
2139574b2666SHong Zhang   ierr = PetscFree(s_browlengths);CHKERRQ(ierr);
214049b5e25fSSatish Balay   ierr = PetscFree(aa);CHKERRQ(ierr);
214149b5e25fSSatish Balay   ierr = PetscFree(jj);CHKERRQ(ierr);
214249b5e25fSSatish Balay   ierr = PetscFree(mask);CHKERRQ(ierr);
214349b5e25fSSatish Balay 
21449abb65ffSKris Buschelman   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
21459abb65ffSKris Buschelman   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
214649b5e25fSSatish Balay   ierr = MatView_Private(B);CHKERRQ(ierr);
21479abb65ffSKris Buschelman   *A = B;
214849b5e25fSSatish Balay   PetscFunctionReturn(0);
214949b5e25fSSatish Balay }
2150574b2666SHong Zhang 
21510def2e27SBarry Smith 
21520def2e27SBarry Smith 
2153d06b337dSHong Zhang #undef __FUNCT__
2154d06b337dSHong Zhang #define __FUNCT__ "MatRelax_SeqSBAIJ"
215513f74950SBarry Smith PetscErrorCode MatRelax_SeqSBAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
2156d06b337dSHong Zhang {
2157d06b337dSHong Zhang   Mat_SeqSBAIJ    *a = (Mat_SeqSBAIJ*)A->data;
21589e2a9236SBarry Smith   const MatScalar *aa=a->a,*v,*v1,*aidiag;
21599e2a9236SBarry Smith   PetscScalar     *x,*b,*t,sum;
2160061b2667SBarry Smith   MatScalar       tmp;
21616849ba73SBarry Smith   PetscErrorCode  ierr;
2162061b2667SBarry Smith   PetscInt        m=a->mbs,bs=A->rmap->bs,j;
2163061b2667SBarry Smith   const PetscInt  *ai=a->i,*aj=a->j,*vj,*vj1;
2164061b2667SBarry Smith   PetscInt        nz,nz1,i;
2165d06b337dSHong Zhang 
2166d06b337dSHong Zhang   PetscFunctionBegin;
216751f519a2SBarry Smith   if (flag & SOR_EISENSTAT) SETERRQ(PETSC_ERR_SUP,"No support yet for Eisenstat");
216851f519a2SBarry Smith 
2169b965ef7fSBarry Smith   its = its*lits;
217077431f27SBarry Smith   if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits);
2171d06b337dSHong Zhang 
2172061b2667SBarry Smith   if (bs > 1) SETERRQ(PETSC_ERR_SUP,"SSOR for block size > 1 is not yet implemented");
2173d06b337dSHong Zhang 
21741ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
2175d06b337dSHong Zhang   if (xx != bb) {
21761ebc52fbSHong Zhang     ierr = VecGetArray(bb,&b);CHKERRQ(ierr);
2177d06b337dSHong Zhang   } else {
2178d06b337dSHong Zhang     b = x;
2179d06b337dSHong Zhang   }
2180d06b337dSHong Zhang 
2181061b2667SBarry Smith   if (!a->idiagvalid) {
2182061b2667SBarry Smith     if (!a->idiag) {
2183061b2667SBarry Smith       ierr     = PetscMalloc(m*sizeof(PetscScalar),&a->idiag);CHKERRQ(ierr);
2184061b2667SBarry Smith     }
2185061b2667SBarry Smith     for (i=0; i<a->mbs; i++) a->idiag[i] = 1.0/a->a[a->i[i]];
2186061b2667SBarry Smith     a->idiagvalid = PETSC_TRUE;
2187061b2667SBarry Smith   }
2188061b2667SBarry Smith 
2189e2ee2a47SBarry Smith   if (!a->relax_work) {
2190e2ee2a47SBarry Smith     ierr = PetscMalloc(m*sizeof(PetscScalar),&a->relax_work);CHKERRQ(ierr);
2191e2ee2a47SBarry Smith   }
2192e2ee2a47SBarry Smith   t = a->relax_work;
2193d06b337dSHong Zhang 
21949e2a9236SBarry Smith   aidiag = a->idiag;
2195d06b337dSHong Zhang   if (flag & SOR_ZERO_INITIAL_GUESS) {
21962798e883SHong Zhang     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
2197290bbb0aSBarry Smith       ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr);
2198d06b337dSHong Zhang 
21999e2a9236SBarry Smith       v  = aa + 1;
22009e2a9236SBarry Smith       vj = aj + 1;
2201d06b337dSHong Zhang       for (i=0; i<m; i++){
2202d06b337dSHong Zhang         nz = ai[i+1] - ai[i] - 1;
22039e2a9236SBarry Smith         tmp = - (x[i] = omega*t[i]*aidiag[i]);
2204061b2667SBarry Smith         for (j=0; j<nz; j++) {
22059e2a9236SBarry Smith           t[vj[j]] += tmp*v[j];
2206d06b337dSHong Zhang         }
22079e2a9236SBarry Smith         v  += nz + 1;
22089e2a9236SBarry Smith         vj += nz + 1;
2209d06b337dSHong Zhang       }
2210061b2667SBarry Smith       ierr = PetscLogFlops(2*a->nz);CHKERRQ(ierr);
2211061b2667SBarry Smith     }
2212d06b337dSHong Zhang 
22132798e883SHong Zhang     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
221495d750ceSBarry Smith       if (!(flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP)){
221595d750ceSBarry Smith         t = b;
2216d06b337dSHong Zhang       }
221795d750ceSBarry Smith 
2218*a2d7c930SBarry Smith       v  = aa + ai[m-1] + 1;
2219*a2d7c930SBarry Smith       vj = aj + ai[m-1] + 1;
2220*a2d7c930SBarry Smith       nz = 0;
2221d06b337dSHong Zhang       for (i=m-1; i>=0; i--){
22229e2a9236SBarry Smith 	/*        sum = t[i]; */
22239e2a9236SBarry Smith         sum = 0.0;
22249e2a9236SBarry Smith         PetscSparseDensePlusDot(sum,x,v,vj,nz);
22259e2a9236SBarry Smith         sum = t[i] - sum;
22269e2a9236SBarry Smith         x[i] =   (1-omega)*x[i] + omega*sum*aidiag[i];
2227*a2d7c930SBarry Smith         nz  = ai[i] - ai[i-1] - 1;
22289e2a9236SBarry Smith         v  -= nz + 1;
22299e2a9236SBarry Smith         vj -= nz + 1;
2230d06b337dSHong Zhang       }
223195d750ceSBarry Smith       t = a->relax_work;
2232061b2667SBarry Smith       ierr = PetscLogFlops(2*a->nz);CHKERRQ(ierr);
2233d06b337dSHong Zhang     }
2234d06b337dSHong Zhang     its--;
2235d06b337dSHong Zhang   }
2236d06b337dSHong Zhang 
2237d06b337dSHong Zhang   while (its--) {
223844706875SHong Zhang     /*
223944706875SHong Zhang        forward sweep:
224044706875SHong Zhang        for i=0,...,m-1:
224144706875SHong Zhang          sum[i] = (b[i] - U(i,:)x )/d[i];
224244706875SHong Zhang          x[i]   = (1-omega)x[i] + omega*sum[i];
224344706875SHong Zhang          b      = b - x[i]*U^T(i,:);
2244d06b337dSHong Zhang 
224544706875SHong Zhang     */
22462798e883SHong Zhang     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
2247290bbb0aSBarry Smith       ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr);
2248d06b337dSHong Zhang 
2249d06b337dSHong Zhang       for (i=0; i<m; i++){
2250d06b337dSHong Zhang         v  = aa + ai[i] + 1; v1=v;
2251d06b337dSHong Zhang         vj = aj + ai[i] + 1; vj1=vj;
2252d06b337dSHong Zhang         nz = ai[i+1] - ai[i] - 1; nz1=nz;
2253d06b337dSHong Zhang         sum = t[i];
2254dc0b31edSSatish Balay         ierr = PetscLogFlops(4.0*nz-2);CHKERRQ(ierr);
2255d06b337dSHong Zhang         while (nz1--) sum -= (*v1++)*x[*vj1++];
22569e2a9236SBarry Smith         x[i] = (1-omega)*x[i] + omega*sum*aidiag[i];
2257d06b337dSHong Zhang         while (nz--) t[*vj++] -= x[i]*(*v++);
2258d06b337dSHong Zhang       }
2259d06b337dSHong Zhang     }
2260d06b337dSHong Zhang 
22612798e883SHong Zhang     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
226244706875SHong Zhang       /*
226344706875SHong Zhang        backward sweep:
226444706875SHong Zhang        b = b - x[i]*U^T(i,:), i=0,...,n-2
226544706875SHong Zhang        for i=m-1,...,0:
226644706875SHong Zhang          sum[i] = (b[i] - U(i,:)x )/d[i];
226744706875SHong Zhang          x[i]   = (1-omega)x[i] + omega*sum[i];
226844706875SHong Zhang       */
226995d750ceSBarry Smith       /* if there was a forward sweep done above then I thing the next two for loops are not needed */
2270290bbb0aSBarry Smith       ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr);
2271d06b337dSHong Zhang 
2272d06b337dSHong Zhang       for (i=0; i<m-1; i++){  /* update rhs */
2273d06b337dSHong Zhang         v  = aa + ai[i] + 1;
2274d06b337dSHong Zhang         vj = aj + ai[i] + 1;
2275d06b337dSHong Zhang         nz = ai[i+1] - ai[i] - 1;
2276dc0b31edSSatish Balay         ierr = PetscLogFlops(2.0*nz-1);CHKERRQ(ierr);
2277e6b907acSBarry Smith         while (nz--) t[*vj++] -= x[i]*(*v++);
2278d06b337dSHong Zhang       }
2279d06b337dSHong Zhang       for (i=m-1; i>=0; i--){
2280d06b337dSHong Zhang         v  = aa + ai[i] + 1;
2281d06b337dSHong Zhang         vj = aj + ai[i] + 1;
2282d06b337dSHong Zhang         nz = ai[i+1] - ai[i] - 1;
2283dc0b31edSSatish Balay         ierr = PetscLogFlops(2.0*nz-1);CHKERRQ(ierr);
2284d06b337dSHong Zhang         sum = t[i];
2285d06b337dSHong Zhang         while (nz--) sum -= x[*vj++]*(*v++);
22869e2a9236SBarry Smith         x[i] =   (1-omega)*x[i] + omega*sum*aidiag[i];
2287d06b337dSHong Zhang       }
2288d06b337dSHong Zhang     }
2289d06b337dSHong Zhang   }
2290d06b337dSHong Zhang 
22911ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
2292d06b337dSHong Zhang   if (bb != xx) {
22931ebc52fbSHong Zhang     ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr);
2294d06b337dSHong Zhang   }
2295d06b337dSHong Zhang   PetscFunctionReturn(0);
2296d06b337dSHong Zhang }
2297d06b337dSHong Zhang 
2298c75a6043SHong Zhang #undef __FUNCT__
2299c75a6043SHong Zhang #define __FUNCT__ "MatCreateSeqSBAIJWithArrays"
2300c75a6043SHong Zhang /*@
2301c75a6043SHong Zhang      MatCreateSeqSBAIJWithArrays - Creates an sequential SBAIJ matrix using matrix elements
2302c75a6043SHong Zhang               (upper triangular entries in CSR format) provided by the user.
2303c75a6043SHong Zhang 
2304c75a6043SHong Zhang      Collective on MPI_Comm
2305c75a6043SHong Zhang 
2306c75a6043SHong Zhang    Input Parameters:
2307c75a6043SHong Zhang +  comm - must be an MPI communicator of size 1
2308c75a6043SHong Zhang .  bs - size of block
2309c75a6043SHong Zhang .  m - number of rows
2310c75a6043SHong Zhang .  n - number of columns
2311c75a6043SHong Zhang .  i - row indices
2312c75a6043SHong Zhang .  j - column indices
2313c75a6043SHong Zhang -  a - matrix values
2314c75a6043SHong Zhang 
2315c75a6043SHong Zhang    Output Parameter:
2316c75a6043SHong Zhang .  mat - the matrix
2317c75a6043SHong Zhang 
2318c75a6043SHong Zhang    Level: intermediate
2319c75a6043SHong Zhang 
2320c75a6043SHong Zhang    Notes:
2321c75a6043SHong Zhang        The i, j, and a arrays are not copied by this routine, the user must free these arrays
2322c75a6043SHong Zhang     once the matrix is destroyed
2323c75a6043SHong Zhang 
2324c75a6043SHong Zhang        You cannot set new nonzero locations into this matrix, that will generate an error.
2325c75a6043SHong Zhang 
2326c75a6043SHong Zhang        The i and j indices are 0 based
2327c75a6043SHong Zhang 
2328c75a6043SHong Zhang .seealso: MatCreate(), MatCreateMPISBAIJ(), MatCreateSeqSBAIJ()
2329c75a6043SHong Zhang 
2330c75a6043SHong Zhang @*/
2331c75a6043SHong Zhang PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqSBAIJWithArrays(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat)
2332c75a6043SHong Zhang {
2333c75a6043SHong Zhang   PetscErrorCode ierr;
2334c75a6043SHong Zhang   PetscInt       ii;
2335c75a6043SHong Zhang   Mat_SeqSBAIJ   *sbaij;
2336c75a6043SHong Zhang 
2337c75a6043SHong Zhang   PetscFunctionBegin;
2338c75a6043SHong Zhang   if (bs != 1) SETERRQ1(PETSC_ERR_SUP,"block size %D > 1 is not supported yet",bs);
2339c75a6043SHong Zhang   if (i[0]) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
2340c75a6043SHong Zhang 
2341c75a6043SHong Zhang   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
2342c75a6043SHong Zhang   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
2343c75a6043SHong Zhang   ierr = MatSetType(*mat,MATSEQSBAIJ);CHKERRQ(ierr);
2344c75a6043SHong Zhang   ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(*mat,bs,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr);
2345c75a6043SHong Zhang   sbaij = (Mat_SeqSBAIJ*)(*mat)->data;
2346c75a6043SHong Zhang   ierr = PetscMalloc2(m,PetscInt,&sbaij->imax,m,PetscInt,&sbaij->ilen);CHKERRQ(ierr);
2347c75a6043SHong Zhang 
2348c75a6043SHong Zhang   sbaij->i = i;
2349c75a6043SHong Zhang   sbaij->j = j;
2350c75a6043SHong Zhang   sbaij->a = a;
2351c75a6043SHong Zhang   sbaij->singlemalloc = PETSC_FALSE;
2352c75a6043SHong Zhang   sbaij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2353e6b907acSBarry Smith   sbaij->free_a       = PETSC_FALSE;
2354e6b907acSBarry Smith   sbaij->free_ij      = PETSC_FALSE;
2355c75a6043SHong Zhang 
2356c75a6043SHong Zhang   for (ii=0; ii<m; ii++) {
2357c75a6043SHong Zhang     sbaij->ilen[ii] = sbaij->imax[ii] = i[ii+1] - i[ii];
2358c75a6043SHong Zhang #if defined(PETSC_USE_DEBUG)
2359c75a6043SHong 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]);
2360c75a6043SHong Zhang #endif
2361c75a6043SHong Zhang   }
2362c75a6043SHong Zhang #if defined(PETSC_USE_DEBUG)
2363c75a6043SHong Zhang   for (ii=0; ii<sbaij->i[m]; ii++) {
2364c75a6043SHong Zhang     if (j[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]);
2365c75a6043SHong Zhang     if (j[ii] > n - 1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]);
2366c75a6043SHong Zhang   }
2367c75a6043SHong Zhang #endif
2368c75a6043SHong Zhang 
2369c75a6043SHong Zhang   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2370c75a6043SHong Zhang   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2371c75a6043SHong Zhang   PetscFunctionReturn(0);
2372c75a6043SHong Zhang }
2373d06b337dSHong Zhang 
2374d06b337dSHong Zhang 
2375d06b337dSHong Zhang 
237649b5e25fSSatish Balay 
237749b5e25fSSatish Balay 
2378