xref: /petsc/src/mat/impls/sbaij/seq/sbaij.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
149b5e25fSSatish Balay 
249b5e25fSSatish Balay /*
3a1373b80SHong Zhang     Defines the basic matrix operations for the SBAIJ (compressed row)
449b5e25fSSatish Balay   matrix storage format.
549b5e25fSSatish Balay */
6c6db04a5SJed Brown #include <../src/mat/impls/baij/seq/baij.h> /*I "petscmat.h" I*/
7c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/sbaij.h>
8c6db04a5SJed Brown #include <petscblaslapack.h>
949b5e25fSSatish Balay 
10c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/relax.h>
1170dcbbb9SBarry Smith #define USESHORT
12c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/relax.h>
1370dcbbb9SBarry Smith 
146214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
15cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_Elemental(Mat, MatType, MatReuse, Mat *);
166214f412SHong Zhang #endif
17d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
18d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_SBAIJ_ScaLAPACK(Mat, MatType, MatReuse, Mat *);
19d24d4204SJose E. Roman #endif
2028d58a37SPierre Jolivet PETSC_INTERN PetscErrorCode MatConvert_MPISBAIJ_Basic(Mat, MatType, MatReuse, Mat *);
21b5b17502SBarry Smith 
2249b5e25fSSatish Balay /*
2349b5e25fSSatish Balay      Checks for missing diagonals
2449b5e25fSSatish Balay */
259371c9d4SSatish Balay PetscErrorCode MatMissingDiagonal_SeqSBAIJ(Mat A, PetscBool *missing, PetscInt *dd) {
26045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
277734d3b5SMatthew G. Knepley   PetscInt     *diag, *ii = a->i, i;
2849b5e25fSSatish Balay 
2949b5e25fSSatish Balay   PetscFunctionBegin;
309566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqSBAIJ(A));
312af78befSBarry Smith   *missing = PETSC_FALSE;
327734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
33358d2f5dSShri Abhyankar     *missing = PETSC_TRUE;
34358d2f5dSShri Abhyankar     if (dd) *dd = 0;
359566063dSJacob Faibussowitsch     PetscCall(PetscInfo(A, "Matrix has no entries therefore is missing diagonal\n"));
36358d2f5dSShri Abhyankar   } else {
37358d2f5dSShri Abhyankar     diag = a->diag;
3849b5e25fSSatish Balay     for (i = 0; i < a->mbs; i++) {
397734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i + 1]) {
402af78befSBarry Smith         *missing = PETSC_TRUE;
412af78befSBarry Smith         if (dd) *dd = i;
422af78befSBarry Smith         break;
432af78befSBarry Smith       }
4449b5e25fSSatish Balay     }
45358d2f5dSShri Abhyankar   }
4649b5e25fSSatish Balay   PetscFunctionReturn(0);
4749b5e25fSSatish Balay }
4849b5e25fSSatish Balay 
499371c9d4SSatish Balay PetscErrorCode MatMarkDiagonal_SeqSBAIJ(Mat A) {
50045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
5148dd3d27SHong Zhang   PetscInt      i, j;
5249b5e25fSSatish Balay 
5349b5e25fSSatish Balay   PetscFunctionBegin;
5409f38230SBarry Smith   if (!a->diag) {
559566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(a->mbs, &a->diag));
56c760cd28SBarry Smith     a->free_diag = PETSC_TRUE;
5709f38230SBarry Smith   }
5848dd3d27SHong Zhang   for (i = 0; i < a->mbs; i++) {
5948dd3d27SHong Zhang     a->diag[i] = a->i[i + 1];
6048dd3d27SHong Zhang     for (j = a->i[i]; j < a->i[i + 1]; j++) {
6148dd3d27SHong Zhang       if (a->j[j] == i) {
6248dd3d27SHong Zhang         a->diag[i] = j;
6348dd3d27SHong Zhang         break;
6448dd3d27SHong Zhang       }
6548dd3d27SHong Zhang     }
6648dd3d27SHong Zhang   }
6749b5e25fSSatish Balay   PetscFunctionReturn(0);
6849b5e25fSSatish Balay }
6949b5e25fSSatish Balay 
709371c9d4SSatish Balay static PetscErrorCode MatGetRowIJ_SeqSBAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool blockcompressed, PetscInt *nn, const PetscInt *inia[], const PetscInt *inja[], PetscBool *done) {
71a6ece127SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
722462f5fdSStefano Zampini   PetscInt      i, j, n = a->mbs, nz = a->i[n], *tia, *tja, bs = A->rmap->bs, k, l, cnt;
732462f5fdSStefano Zampini   PetscInt    **ia = (PetscInt **)inia, **ja = (PetscInt **)inja;
7449b5e25fSSatish Balay 
7549b5e25fSSatish Balay   PetscFunctionBegin;
76d3e5a4abSHong Zhang   *nn = n;
77a1373b80SHong Zhang   if (!ia) PetscFunctionReturn(0);
782462f5fdSStefano Zampini   if (symmetric) {
799566063dSJacob Faibussowitsch     PetscCall(MatToSymmetricIJ_SeqAIJ(n, a->i, a->j, PETSC_FALSE, 0, 0, &tia, &tja));
802462f5fdSStefano Zampini     nz = tia[n];
812462f5fdSStefano Zampini   } else {
829371c9d4SSatish Balay     tia = a->i;
839371c9d4SSatish Balay     tja = a->j;
842462f5fdSStefano Zampini   }
852462f5fdSStefano Zampini 
862462f5fdSStefano Zampini   if (!blockcompressed && bs > 1) {
872462f5fdSStefano Zampini     (*nn) *= bs;
888f7157efSSatish Balay     /* malloc & create the natural set of indices */
899566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((n + 1) * bs, ia));
902462f5fdSStefano Zampini     if (n) {
912462f5fdSStefano Zampini       (*ia)[0] = oshift;
92ad540459SPierre Jolivet       for (j = 1; j < bs; j++) (*ia)[j] = (tia[1] - tia[0]) * bs + (*ia)[j - 1];
932462f5fdSStefano Zampini     }
942462f5fdSStefano Zampini 
952462f5fdSStefano Zampini     for (i = 1; i < n; i++) {
962462f5fdSStefano Zampini       (*ia)[i * bs] = (tia[i] - tia[i - 1]) * bs + (*ia)[i * bs - 1];
97ad540459SPierre Jolivet       for (j = 1; j < bs; j++) (*ia)[i * bs + j] = (tia[i + 1] - tia[i]) * bs + (*ia)[i * bs + j - 1];
982462f5fdSStefano Zampini     }
99ad540459SPierre Jolivet     if (n) (*ia)[n * bs] = (tia[n] - tia[n - 1]) * bs + (*ia)[n * bs - 1];
1002462f5fdSStefano Zampini 
1012462f5fdSStefano Zampini     if (inja) {
1029566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz * bs * bs, ja));
1032462f5fdSStefano Zampini       cnt = 0;
1042462f5fdSStefano Zampini       for (i = 0; i < n; i++) {
1058f7157efSSatish Balay         for (j = 0; j < bs; j++) {
1062462f5fdSStefano Zampini           for (k = tia[i]; k < tia[i + 1]; k++) {
107ad540459SPierre Jolivet             for (l = 0; l < bs; l++) (*ja)[cnt++] = bs * tja[k] + l;
1088f7157efSSatish Balay           }
1098f7157efSSatish Balay         }
1108f7157efSSatish Balay       }
1118f7157efSSatish Balay     }
1122462f5fdSStefano Zampini 
1132462f5fdSStefano Zampini     if (symmetric) { /* deallocate memory allocated in MatToSymmetricIJ_SeqAIJ() */
1149566063dSJacob Faibussowitsch       PetscCall(PetscFree(tia));
1159566063dSJacob Faibussowitsch       PetscCall(PetscFree(tja));
1162462f5fdSStefano Zampini     }
1172462f5fdSStefano Zampini   } else if (oshift == 1) {
1182462f5fdSStefano Zampini     if (symmetric) {
1192462f5fdSStefano Zampini       nz = tia[A->rmap->n / bs];
1202462f5fdSStefano Zampini       /*  add 1 to i and j indices */
1212462f5fdSStefano Zampini       for (i = 0; i < A->rmap->n / bs + 1; i++) tia[i] = tia[i] + 1;
1222462f5fdSStefano Zampini       *ia = tia;
1232462f5fdSStefano Zampini       if (ja) {
1242462f5fdSStefano Zampini         for (i = 0; i < nz; i++) tja[i] = tja[i] + 1;
1252462f5fdSStefano Zampini         *ja = tja;
1262462f5fdSStefano Zampini       }
1272462f5fdSStefano Zampini     } else {
1282462f5fdSStefano Zampini       nz = a->i[A->rmap->n / bs];
1292462f5fdSStefano Zampini       /* malloc space and  add 1 to i and j indices */
1309566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(A->rmap->n / bs + 1, ia));
1312462f5fdSStefano Zampini       for (i = 0; i < A->rmap->n / bs + 1; i++) (*ia)[i] = a->i[i] + 1;
1322462f5fdSStefano Zampini       if (ja) {
1339566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(nz, ja));
1342462f5fdSStefano Zampini         for (i = 0; i < nz; i++) (*ja)[i] = a->j[i] + 1;
1352462f5fdSStefano Zampini       }
1362462f5fdSStefano Zampini     }
1372462f5fdSStefano Zampini   } else {
1382462f5fdSStefano Zampini     *ia = tia;
1392462f5fdSStefano Zampini     if (ja) *ja = tja;
140a6ece127SHong Zhang   }
14149b5e25fSSatish Balay   PetscFunctionReturn(0);
14249b5e25fSSatish Balay }
14349b5e25fSSatish Balay 
1449371c9d4SSatish Balay static PetscErrorCode MatRestoreRowIJ_SeqSBAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool blockcompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
14549b5e25fSSatish Balay   PetscFunctionBegin;
14649b5e25fSSatish Balay   if (!ia) PetscFunctionReturn(0);
1472462f5fdSStefano Zampini   if ((!blockcompressed && A->rmap->bs > 1) || (symmetric || oshift == 1)) {
1489566063dSJacob Faibussowitsch     PetscCall(PetscFree(*ia));
1499566063dSJacob Faibussowitsch     if (ja) PetscCall(PetscFree(*ja));
150a6ece127SHong Zhang   }
151a6ece127SHong Zhang   PetscFunctionReturn(0);
15249b5e25fSSatish Balay }
15349b5e25fSSatish Balay 
1549371c9d4SSatish Balay PetscErrorCode MatDestroy_SeqSBAIJ(Mat A) {
15549b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
15649b5e25fSSatish Balay 
15749b5e25fSSatish Balay   PetscFunctionBegin;
158a9f03627SSatish Balay #if defined(PETSC_USE_LOG)
159c0aa6a63SJacob Faibussowitsch   PetscLogObjectState((PetscObject)A, "Rows=%" PetscInt_FMT ", NZ=%" PetscInt_FMT, A->rmap->N, a->nz);
160a9f03627SSatish Balay #endif
1619566063dSJacob Faibussowitsch   PetscCall(MatSeqXAIJFreeAIJ(A, &a->a, &a->j, &a->i));
1629566063dSJacob Faibussowitsch   if (a->free_diag) PetscCall(PetscFree(a->diag));
1639566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
1649566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
1659566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->icol));
1669566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->idiag));
1679566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->inode.size));
1689566063dSJacob Faibussowitsch   if (a->free_imax_ilen) PetscCall(PetscFree2(a->imax, a->ilen));
1699566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->solve_work));
1709566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->sor_work));
1719566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->solves_work));
1729566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->mult_work));
1739566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->saved_values));
1749566063dSJacob Faibussowitsch   if (a->free_jshort) PetscCall(PetscFree(a->jshort));
1759566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->inew));
1769566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&a->parent));
1779566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
178901853e0SKris Buschelman 
1799566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL));
1802e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJGetArray_C", NULL));
1812e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJRestoreArray_C", NULL));
1829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatStoreValues_C", NULL));
1839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatRetrieveValues_C", NULL));
1849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetColumnIndices_C", NULL));
1859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqaij_C", NULL));
1869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqbaij_C", NULL));
1879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocation_C", NULL));
1889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocationCSR_C", NULL));
1896214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_elemental_C", NULL));
1916214f412SHong Zhang #endif
192d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
1939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_scalapack_C", NULL));
194d24d4204SJose E. Roman #endif
1952e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL));
19649b5e25fSSatish Balay   PetscFunctionReturn(0);
19749b5e25fSSatish Balay }
19849b5e25fSSatish Balay 
1999371c9d4SSatish Balay PetscErrorCode MatSetOption_SeqSBAIJ(Mat A, MatOption op, PetscBool flg) {
200045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
201eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
202eb1ec7c1SStefano Zampini   PetscInt bs;
203eb1ec7c1SStefano Zampini #endif
20449b5e25fSSatish Balay 
20549b5e25fSSatish Balay   PetscFunctionBegin;
206eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2079566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &bs));
208eb1ec7c1SStefano Zampini #endif
2094d9d31abSKris Buschelman   switch (op) {
2109371c9d4SSatish Balay   case MAT_ROW_ORIENTED: a->roworiented = flg; break;
2119371c9d4SSatish Balay   case MAT_KEEP_NONZERO_PATTERN: a->keepnonzeropattern = flg; break;
2129371c9d4SSatish Balay   case MAT_NEW_NONZERO_LOCATIONS: a->nonew = (flg ? 0 : 1); break;
2139371c9d4SSatish Balay   case MAT_NEW_NONZERO_LOCATION_ERR: a->nonew = (flg ? -1 : 0); break;
2149371c9d4SSatish Balay   case MAT_NEW_NONZERO_ALLOCATION_ERR: a->nonew = (flg ? -2 : 0); break;
2159371c9d4SSatish Balay   case MAT_UNUSED_NONZERO_LOCATION_ERR: a->nounused = (flg ? -1 : 0); break;
2168c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
2174d9d31abSKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
2184d9d31abSKris Buschelman   case MAT_USE_HASH_TABLE:
2199371c9d4SSatish Balay   case MAT_SORTED_FULL: PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op])); break;
2209a4540c5SBarry Smith   case MAT_HERMITIAN:
221eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
222eb1ec7c1SStefano Zampini     if (flg) { /* disable transpose ops */
22308401ef6SPierre Jolivet       PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for Hermitian with block size greater than 1");
224eb1ec7c1SStefano Zampini       A->ops->multtranspose    = NULL;
225eb1ec7c1SStefano Zampini       A->ops->multtransposeadd = NULL;
226b94d7dedSBarry Smith       A->symmetric             = PETSC_BOOL3_FALSE;
227eb1ec7c1SStefano Zampini     }
2280f2140c7SStefano Zampini #endif
229eeffb40dSHong Zhang     break;
23077e54ba9SKris Buschelman   case MAT_SYMMETRIC:
231eb1ec7c1SStefano Zampini   case MAT_SPD:
232eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
233eb1ec7c1SStefano Zampini     if (flg) { /* An hermitian and symmetric matrix has zero imaginary part (restore back transpose ops) */
234eb1ec7c1SStefano Zampini       A->ops->multtranspose    = A->ops->mult;
235eb1ec7c1SStefano Zampini       A->ops->multtransposeadd = A->ops->multadd;
236eb1ec7c1SStefano Zampini     }
237eb1ec7c1SStefano Zampini #endif
238eb1ec7c1SStefano Zampini     break;
239eb1ec7c1SStefano Zampini     /* These options are handled directly by MatSetOption() */
24077e54ba9SKris Buschelman   case MAT_STRUCTURALLY_SYMMETRIC:
2419a4540c5SBarry Smith   case MAT_SYMMETRY_ETERNAL:
242b94d7dedSBarry Smith   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
243672ba085SHong Zhang   case MAT_STRUCTURE_ONLY:
244b94d7dedSBarry Smith   case MAT_SPD_ETERNAL:
2454dcd73b1SHong Zhang     /* These options are handled directly by MatSetOption() */
246290bbb0aSBarry Smith     break;
2479371c9d4SSatish Balay   case MAT_IGNORE_LOWER_TRIANGULAR: a->ignore_ltriangular = flg; break;
2489371c9d4SSatish Balay   case MAT_ERROR_LOWER_TRIANGULAR: a->ignore_ltriangular = flg; break;
2499371c9d4SSatish Balay   case MAT_GETROW_UPPERTRIANGULAR: a->getrow_utriangular = flg; break;
2509371c9d4SSatish Balay   case MAT_SUBMAT_SINGLEIS: break;
2519371c9d4SSatish Balay   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %d", op);
25249b5e25fSSatish Balay   }
25349b5e25fSSatish Balay   PetscFunctionReturn(0);
25449b5e25fSSatish Balay }
25549b5e25fSSatish Balay 
2569371c9d4SSatish Balay PetscErrorCode MatGetRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) {
25749b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
25849b5e25fSSatish Balay 
25949b5e25fSSatish Balay   PetscFunctionBegin;
26008401ef6SPierre Jolivet   PetscCheck(!A || a->getrow_utriangular, PETSC_COMM_SELF, 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()");
26152768537SHong Zhang 
262f5edf698SHong Zhang   /* Get the upper triangular part of the row */
2639566063dSJacob Faibussowitsch   PetscCall(MatGetRow_SeqBAIJ_private(A, row, nz, idx, v, a->i, a->j, a->a));
26449b5e25fSSatish Balay   PetscFunctionReturn(0);
26549b5e25fSSatish Balay }
26649b5e25fSSatish Balay 
2679371c9d4SSatish Balay PetscErrorCode MatRestoreRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) {
26849b5e25fSSatish Balay   PetscFunctionBegin;
269cb4a9cd9SHong Zhang   if (nz) *nz = 0;
2709566063dSJacob Faibussowitsch   if (idx) PetscCall(PetscFree(*idx));
2719566063dSJacob Faibussowitsch   if (v) PetscCall(PetscFree(*v));
27249b5e25fSSatish Balay   PetscFunctionReturn(0);
27349b5e25fSSatish Balay }
27449b5e25fSSatish Balay 
2759371c9d4SSatish Balay PetscErrorCode MatGetRowUpperTriangular_SeqSBAIJ(Mat A) {
276f5edf698SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
277f5edf698SHong Zhang 
278f5edf698SHong Zhang   PetscFunctionBegin;
279f5edf698SHong Zhang   a->getrow_utriangular = PETSC_TRUE;
280f5edf698SHong Zhang   PetscFunctionReturn(0);
281f5edf698SHong Zhang }
282a323099bSStefano Zampini 
2839371c9d4SSatish Balay PetscErrorCode MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A) {
284f5edf698SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
285f5edf698SHong Zhang 
286f5edf698SHong Zhang   PetscFunctionBegin;
287f5edf698SHong Zhang   a->getrow_utriangular = PETSC_FALSE;
288f5edf698SHong Zhang   PetscFunctionReturn(0);
289f5edf698SHong Zhang }
290f5edf698SHong Zhang 
2919371c9d4SSatish Balay PetscErrorCode MatTranspose_SeqSBAIJ(Mat A, MatReuse reuse, Mat *B) {
29249b5e25fSSatish Balay   PetscFunctionBegin;
2937fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B));
294cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX) {
2959566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A, MAT_COPY_VALUES, B));
296cf37664fSBarry Smith   } else if (reuse == MAT_REUSE_MATRIX) {
2979566063dSJacob Faibussowitsch     PetscCall(MatCopy(A, *B, SAME_NONZERO_PATTERN));
298fc4dec0aSBarry Smith   }
2998115998fSBarry Smith   PetscFunctionReturn(0);
30049b5e25fSSatish Balay }
30149b5e25fSSatish Balay 
3029371c9d4SSatish Balay PetscErrorCode MatView_SeqSBAIJ_ASCII(Mat A, PetscViewer viewer) {
30349b5e25fSSatish Balay   Mat_SeqSBAIJ     *a = (Mat_SeqSBAIJ *)A->data;
304d0f46423SBarry Smith   PetscInt          i, j, bs = A->rmap->bs, k, l, bs2 = a->bs2;
305f3ef73ceSBarry Smith   PetscViewerFormat format;
306121deb67SSatish Balay   PetscInt         *diag;
30749b5e25fSSatish Balay 
30849b5e25fSSatish Balay   PetscFunctionBegin;
3099566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
310456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
3119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  block size is %" PetscInt_FMT "\n", bs));
312fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_MATLAB) {
313d2507d54SMatthew Knepley     Mat         aij;
314ade3a672SBarry Smith     const char *matname;
315ade3a672SBarry Smith 
316d5f3da31SBarry Smith     if (A->factortype && bs > 1) {
3179566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF, "Warning: matrix is factored with bs>1. MatView() with PETSC_VIEWER_ASCII_MATLAB is not supported and ignored!\n"));
31870d5e725SHong Zhang       PetscFunctionReturn(0);
31970d5e725SHong Zhang     }
3209566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &aij));
3219566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)A, &matname));
3229566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)aij, matname));
3239566063dSJacob Faibussowitsch     PetscCall(MatView(aij, viewer));
3249566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&aij));
325fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
3269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
32749b5e25fSSatish Balay     for (i = 0; i < a->mbs; i++) {
32849b5e25fSSatish Balay       for (j = 0; j < bs; j++) {
3299566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i * bs + j));
33049b5e25fSSatish Balay         for (k = a->i[i]; k < a->i[i + 1]; k++) {
33149b5e25fSSatish Balay           for (l = 0; l < bs; l++) {
33249b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX)
33349b5e25fSSatish Balay             if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) > 0.0 && PetscRealPart(a->a[bs2 * k + l * bs + j]) != 0.0) {
3349371c9d4SSatish Balay               PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j]), (double)PetscImaginaryPart(a->a[bs2 * k + l * bs + j])));
33549b5e25fSSatish Balay             } else if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) < 0.0 && PetscRealPart(a->a[bs2 * k + l * bs + j]) != 0.0) {
3369371c9d4SSatish Balay               PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j]), -(double)PetscImaginaryPart(a->a[bs2 * k + l * bs + j])));
33749b5e25fSSatish Balay             } else if (PetscRealPart(a->a[bs2 * k + l * bs + j]) != 0.0) {
3389566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j])));
33949b5e25fSSatish Balay             }
34049b5e25fSSatish Balay #else
34148a46eb9SPierre Jolivet             if (a->a[bs2 * k + l * bs + j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)a->a[bs2 * k + l * bs + j]));
34249b5e25fSSatish Balay #endif
34349b5e25fSSatish Balay           }
34449b5e25fSSatish Balay         }
3459566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
34649b5e25fSSatish Balay       }
34749b5e25fSSatish Balay     }
3489566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
349c1490034SHong Zhang   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
350c1490034SHong Zhang     PetscFunctionReturn(0);
35149b5e25fSSatish Balay   } else {
3529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
3532c990fa1SHong Zhang     if (A->factortype) { /* for factored matrix */
35408401ef6SPierre Jolivet       PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix is factored with bs>1. Not implemented yet");
3552c990fa1SHong Zhang 
356121deb67SSatish Balay       diag = a->diag;
357121deb67SSatish Balay       for (i = 0; i < a->mbs; i++) { /* for row block i */
3589566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
3592c990fa1SHong Zhang         /* diagonal entry */
3602c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX)
3612c990fa1SHong Zhang         if (PetscImaginaryPart(a->a[diag[i]]) > 0.0) {
3629566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", a->j[diag[i]], (double)PetscRealPart(1.0 / a->a[diag[i]]), (double)PetscImaginaryPart(1.0 / a->a[diag[i]])));
3632c990fa1SHong Zhang         } else if (PetscImaginaryPart(a->a[diag[i]]) < 0.0) {
3649566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i) ", a->j[diag[i]], (double)PetscRealPart(1.0 / a->a[diag[i]]), -(double)PetscImaginaryPart(1.0 / a->a[diag[i]])));
3652c990fa1SHong Zhang         } else {
3669566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)PetscRealPart(1.0 / a->a[diag[i]])));
3672c990fa1SHong Zhang         }
3682c990fa1SHong Zhang #else
3699566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)(1.0 / a->a[diag[i]])));
3702c990fa1SHong Zhang #endif
3712c990fa1SHong Zhang         /* off-diagonal entries */
3722c990fa1SHong Zhang         for (k = a->i[i]; k < a->i[i + 1] - 1; k++) {
3732c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX)
374ca0704adSBarry Smith           if (PetscImaginaryPart(a->a[k]) > 0.0) {
3759566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), (double)PetscImaginaryPart(a->a[k])));
376ca0704adSBarry Smith           } else if (PetscImaginaryPart(a->a[k]) < 0.0) {
3779566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), -(double)PetscImaginaryPart(a->a[k])));
3782c990fa1SHong Zhang           } else {
3799566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k], (double)PetscRealPart(a->a[k])));
3802c990fa1SHong Zhang           }
3812c990fa1SHong Zhang #else
3829566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[k], (double)a->a[k]));
3832c990fa1SHong Zhang #endif
3842c990fa1SHong Zhang         }
3859566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
3862c990fa1SHong Zhang       }
3872c990fa1SHong Zhang 
3882c990fa1SHong Zhang     } else {                         /* for non-factored matrix */
3890c74a584SJed Brown       for (i = 0; i < a->mbs; i++) { /* for row block i */
3900c74a584SJed Brown         for (j = 0; j < bs; j++) {   /* for row bs*i + j */
3919566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i * bs + j));
3920c74a584SJed Brown           for (k = a->i[i]; k < a->i[i + 1]; k++) { /* for column block */
3930c74a584SJed Brown             for (l = 0; l < bs; l++) {              /* for column */
39449b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX)
39549b5e25fSSatish Balay               if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) > 0.0) {
3969371c9d4SSatish Balay                 PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j]), (double)PetscImaginaryPart(a->a[bs2 * k + l * bs + j])));
39749b5e25fSSatish Balay               } else if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) < 0.0) {
3989371c9d4SSatish Balay                 PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j]), -(double)PetscImaginaryPart(a->a[bs2 * k + l * bs + j])));
39949b5e25fSSatish Balay               } else {
4009566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j])));
40149b5e25fSSatish Balay               }
40249b5e25fSSatish Balay #else
4039566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)a->a[bs2 * k + l * bs + j]));
40449b5e25fSSatish Balay #endif
40549b5e25fSSatish Balay             }
40649b5e25fSSatish Balay           }
4079566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
40849b5e25fSSatish Balay         }
40949b5e25fSSatish Balay       }
4102c990fa1SHong Zhang     }
4119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
41249b5e25fSSatish Balay   }
4139566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
41449b5e25fSSatish Balay   PetscFunctionReturn(0);
41549b5e25fSSatish Balay }
41649b5e25fSSatish Balay 
4179804daf3SBarry Smith #include <petscdraw.h>
4189371c9d4SSatish Balay static PetscErrorCode MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw, void *Aa) {
41949b5e25fSSatish Balay   Mat           A = (Mat)Aa;
42049b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
421d0f46423SBarry Smith   PetscInt      row, i, j, k, l, mbs = a->mbs, color, bs = A->rmap->bs, bs2 = a->bs2;
42249b5e25fSSatish Balay   PetscReal     xl, yl, xr, yr, x_l, x_r, y_l, y_r;
42349b5e25fSSatish Balay   MatScalar    *aa;
424b0a32e0cSBarry Smith   PetscViewer   viewer;
42549b5e25fSSatish Balay 
42649b5e25fSSatish Balay   PetscFunctionBegin;
4279566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
4289566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
42949b5e25fSSatish Balay 
43049b5e25fSSatish Balay   /* loop over matrix elements drawing boxes */
431383922c3SLisandro Dalcin 
432d0609cedSBarry Smith   PetscDrawCollectiveBegin(draw);
4339566063dSJacob Faibussowitsch   PetscCall(PetscDrawString(draw, .3 * (xl + xr), .3 * (yl + yr), PETSC_DRAW_BLACK, "symmetric"));
434383922c3SLisandro Dalcin   /* Blue for negative, Cyan for zero and  Red for positive */
435b0a32e0cSBarry Smith   color = PETSC_DRAW_BLUE;
43649b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
43749b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4389371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4399371c9d4SSatish Balay       y_r = y_l + 1.0;
4409371c9d4SSatish Balay       x_l = a->j[j] * bs;
4419371c9d4SSatish Balay       x_r = x_l + 1.0;
44249b5e25fSSatish Balay       aa  = a->a + j * bs2;
44349b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
44449b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
44549b5e25fSSatish Balay           if (PetscRealPart(*aa++) >= 0.) continue;
4469566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
44749b5e25fSSatish Balay         }
44849b5e25fSSatish Balay       }
44949b5e25fSSatish Balay     }
45049b5e25fSSatish Balay   }
451b0a32e0cSBarry Smith   color = PETSC_DRAW_CYAN;
45249b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
45349b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4549371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4559371c9d4SSatish Balay       y_r = y_l + 1.0;
4569371c9d4SSatish Balay       x_l = a->j[j] * bs;
4579371c9d4SSatish Balay       x_r = x_l + 1.0;
45849b5e25fSSatish Balay       aa  = a->a + j * bs2;
45949b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
46049b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
46149b5e25fSSatish Balay           if (PetscRealPart(*aa++) != 0.) continue;
4629566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
46349b5e25fSSatish Balay         }
46449b5e25fSSatish Balay       }
46549b5e25fSSatish Balay     }
46649b5e25fSSatish Balay   }
467b0a32e0cSBarry Smith   color = PETSC_DRAW_RED;
46849b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
46949b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4709371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4719371c9d4SSatish Balay       y_r = y_l + 1.0;
4729371c9d4SSatish Balay       x_l = a->j[j] * bs;
4739371c9d4SSatish Balay       x_r = x_l + 1.0;
47449b5e25fSSatish Balay       aa  = a->a + j * bs2;
47549b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
47649b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
47749b5e25fSSatish Balay           if (PetscRealPart(*aa++) <= 0.) continue;
4789566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
47949b5e25fSSatish Balay         }
48049b5e25fSSatish Balay       }
48149b5e25fSSatish Balay     }
48249b5e25fSSatish Balay   }
483d0609cedSBarry Smith   PetscDrawCollectiveEnd(draw);
48449b5e25fSSatish Balay   PetscFunctionReturn(0);
48549b5e25fSSatish Balay }
48649b5e25fSSatish Balay 
4879371c9d4SSatish Balay static PetscErrorCode MatView_SeqSBAIJ_Draw(Mat A, PetscViewer viewer) {
48849b5e25fSSatish Balay   PetscReal xl, yl, xr, yr, w, h;
489b0a32e0cSBarry Smith   PetscDraw draw;
490ace3abfcSBarry Smith   PetscBool isnull;
49149b5e25fSSatish Balay 
49249b5e25fSSatish Balay   PetscFunctionBegin;
4939566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4949566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
495383922c3SLisandro Dalcin   if (isnull) PetscFunctionReturn(0);
49649b5e25fSSatish Balay 
4979371c9d4SSatish Balay   xr = A->rmap->N;
4989371c9d4SSatish Balay   yr = A->rmap->N;
4999371c9d4SSatish Balay   h  = yr / 10.0;
5009371c9d4SSatish Balay   w  = xr / 10.0;
5019371c9d4SSatish Balay   xr += w;
5029371c9d4SSatish Balay   yr += h;
5039371c9d4SSatish Balay   xl = -w;
5049371c9d4SSatish Balay   yl = -h;
5059566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
5069566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
5079566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqSBAIJ_Draw_Zoom, A));
5089566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
5099566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
51049b5e25fSSatish Balay   PetscFunctionReturn(0);
51149b5e25fSSatish Balay }
51249b5e25fSSatish Balay 
513618cc2edSLisandro Dalcin /* Used for both MPIBAIJ and MPISBAIJ matrices */
514618cc2edSLisandro Dalcin #define MatView_SeqSBAIJ_Binary MatView_SeqBAIJ_Binary
515618cc2edSLisandro Dalcin 
5169371c9d4SSatish Balay PetscErrorCode MatView_SeqSBAIJ(Mat A, PetscViewer viewer) {
517618cc2edSLisandro Dalcin   PetscBool iascii, isbinary, isdraw;
51849b5e25fSSatish Balay 
51949b5e25fSSatish Balay   PetscFunctionBegin;
5209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
5219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
5229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
52332077d6dSBarry Smith   if (iascii) {
5249566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_ASCII(A, viewer));
525618cc2edSLisandro Dalcin   } else if (isbinary) {
5269566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_Binary(A, viewer));
52749b5e25fSSatish Balay   } else if (isdraw) {
5289566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_Draw(A, viewer));
52949b5e25fSSatish Balay   } else {
530a5e6ed63SBarry Smith     Mat         B;
531ade3a672SBarry Smith     const char *matname;
5329566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B));
5339566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)A, &matname));
5349566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)B, matname));
5359566063dSJacob Faibussowitsch     PetscCall(MatView(B, viewer));
5369566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
53749b5e25fSSatish Balay   }
53849b5e25fSSatish Balay   PetscFunctionReturn(0);
53949b5e25fSSatish Balay }
54049b5e25fSSatish Balay 
5419371c9d4SSatish Balay PetscErrorCode MatGetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[]) {
542045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
54313f74950SBarry Smith   PetscInt     *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j;
54413f74950SBarry Smith   PetscInt     *ai = a->i, *ailen = a->ilen;
545d0f46423SBarry Smith   PetscInt      brow, bcol, ridx, cidx, bs = A->rmap->bs, bs2 = a->bs2;
54697e567efSBarry Smith   MatScalar    *ap, *aa = a->a;
54749b5e25fSSatish Balay 
54849b5e25fSSatish Balay   PetscFunctionBegin;
54949b5e25fSSatish Balay   for (k = 0; k < m; k++) { /* loop over rows */
5509371c9d4SSatish Balay     row  = im[k];
5519371c9d4SSatish Balay     brow = row / bs;
5529371c9d4SSatish Balay     if (row < 0) {
5539371c9d4SSatish Balay       v += n;
5549371c9d4SSatish Balay       continue;
5559371c9d4SSatish Balay     } /* negative row */
55654c59aa7SJacob Faibussowitsch     PetscCheck(row < A->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, row, A->rmap->N - 1);
5579371c9d4SSatish Balay     rp   = aj + ai[brow];
5589371c9d4SSatish Balay     ap   = aa + bs2 * ai[brow];
55949b5e25fSSatish Balay     nrow = ailen[brow];
56049b5e25fSSatish Balay     for (l = 0; l < n; l++) { /* loop over columns */
5619371c9d4SSatish Balay       if (in[l] < 0) {
5629371c9d4SSatish Balay         v++;
5639371c9d4SSatish Balay         continue;
5649371c9d4SSatish Balay       } /* negative column */
56554c59aa7SJacob Faibussowitsch       PetscCheck(in[l] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, in[l], A->cmap->n - 1);
56649b5e25fSSatish Balay       col  = in[l];
56749b5e25fSSatish Balay       bcol = col / bs;
56849b5e25fSSatish Balay       cidx = col % bs;
56949b5e25fSSatish Balay       ridx = row % bs;
57049b5e25fSSatish Balay       high = nrow;
57149b5e25fSSatish Balay       low  = 0; /* assume unsorted */
57249b5e25fSSatish Balay       while (high - low > 5) {
57349b5e25fSSatish Balay         t = (low + high) / 2;
57449b5e25fSSatish Balay         if (rp[t] > bcol) high = t;
57549b5e25fSSatish Balay         else low = t;
57649b5e25fSSatish Balay       }
57749b5e25fSSatish Balay       for (i = low; i < high; i++) {
57849b5e25fSSatish Balay         if (rp[i] > bcol) break;
57949b5e25fSSatish Balay         if (rp[i] == bcol) {
58049b5e25fSSatish Balay           *v++ = ap[bs2 * i + bs * cidx + ridx];
58149b5e25fSSatish Balay           goto finished;
58249b5e25fSSatish Balay         }
58349b5e25fSSatish Balay       }
58497e567efSBarry Smith       *v++ = 0.0;
58549b5e25fSSatish Balay     finished:;
58649b5e25fSSatish Balay     }
58749b5e25fSSatish Balay   }
58849b5e25fSSatish Balay   PetscFunctionReturn(0);
58949b5e25fSSatish Balay }
59049b5e25fSSatish Balay 
5919371c9d4SSatish Balay PetscErrorCode MatPermute_SeqSBAIJ(Mat A, IS rowp, IS colp, Mat *B) {
592dc29a518SPierre Jolivet   Mat C;
593dc29a518SPierre Jolivet 
594dc29a518SPierre Jolivet   PetscFunctionBegin;
5959566063dSJacob Faibussowitsch   PetscCall(MatConvert(A, MATSEQBAIJ, MAT_INITIAL_MATRIX, &C));
5969566063dSJacob Faibussowitsch   PetscCall(MatPermute(C, rowp, colp, B));
5979566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
59848a46eb9SPierre Jolivet   if (rowp == colp) PetscCall(MatConvert(*B, MATSEQSBAIJ, MAT_INPLACE_MATRIX, B));
599dc29a518SPierre Jolivet   PetscFunctionReturn(0);
600dc29a518SPierre Jolivet }
60149b5e25fSSatish Balay 
6029371c9d4SSatish Balay PetscErrorCode MatSetValuesBlocked_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) {
6030880e062SHong Zhang   Mat_SeqSBAIJ      *a = (Mat_SeqSBAIJ *)A->data;
604e2ee6c50SBarry Smith   PetscInt          *rp, k, low, high, t, ii, jj, row, nrow, i, col, l, rmax, N, lastcol = -1;
60513f74950SBarry Smith   PetscInt          *imax = a->imax, *ai = a->i, *ailen = a->ilen;
606d0f46423SBarry Smith   PetscInt          *aj = a->j, nonew = a->nonew, bs2 = a->bs2, bs = A->rmap->bs, stepval;
607ace3abfcSBarry Smith   PetscBool          roworiented = a->roworiented;
608dd6ea824SBarry Smith   const PetscScalar *value       = v;
609f15d580aSBarry Smith   MatScalar         *ap, *aa = a->a, *bap;
6100880e062SHong Zhang 
61149b5e25fSSatish Balay   PetscFunctionBegin;
61226fbe8dcSKarl Rupp   if (roworiented) stepval = (n - 1) * bs;
61326fbe8dcSKarl Rupp   else stepval = (m - 1) * bs;
61426fbe8dcSKarl Rupp 
6150880e062SHong Zhang   for (k = 0; k < m; k++) { /* loop over added rows */
6160880e062SHong Zhang     row = im[k];
6170880e062SHong Zhang     if (row < 0) continue;
6186bdcaf15SBarry Smith     PetscCheck(row < a->mbs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Block index row too large %" PetscInt_FMT " max %" PetscInt_FMT, row, a->mbs - 1);
6190880e062SHong Zhang     rp   = aj + ai[row];
6200880e062SHong Zhang     ap   = aa + bs2 * ai[row];
6210880e062SHong Zhang     rmax = imax[row];
6220880e062SHong Zhang     nrow = ailen[row];
6230880e062SHong Zhang     low  = 0;
624818f2c47SBarry Smith     high = nrow;
6250880e062SHong Zhang     for (l = 0; l < n; l++) { /* loop over added columns */
6260880e062SHong Zhang       if (in[l] < 0) continue;
6270880e062SHong Zhang       col = in[l];
6286bdcaf15SBarry Smith       PetscCheck(col < a->nbs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Block index column too large %" PetscInt_FMT " max %" PetscInt_FMT, col, a->nbs - 1);
629b98bf0e1SJed Brown       if (col < row) {
63026fbe8dcSKarl Rupp         if (a->ignore_ltriangular) continue; /* ignore lower triangular block */
63126fbe8dcSKarl Rupp         else SETERRQ(PETSC_COMM_SELF, 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)");
632b98bf0e1SJed Brown       }
63326fbe8dcSKarl Rupp       if (roworiented) value = v + k * (stepval + bs) * bs + l * bs;
63426fbe8dcSKarl Rupp       else value = v + l * (stepval + bs) * bs + k * bs;
63526fbe8dcSKarl Rupp 
63626fbe8dcSKarl Rupp       if (col <= lastcol) low = 0;
63726fbe8dcSKarl Rupp       else high = nrow;
63826fbe8dcSKarl Rupp 
639e2ee6c50SBarry Smith       lastcol = col;
6400880e062SHong Zhang       while (high - low > 7) {
6410880e062SHong Zhang         t = (low + high) / 2;
6420880e062SHong Zhang         if (rp[t] > col) high = t;
6430880e062SHong Zhang         else low = t;
6440880e062SHong Zhang       }
6450880e062SHong Zhang       for (i = low; i < high; i++) {
6460880e062SHong Zhang         if (rp[i] > col) break;
6470880e062SHong Zhang         if (rp[i] == col) {
6480880e062SHong Zhang           bap = ap + bs2 * i;
6490880e062SHong Zhang           if (roworiented) {
6500880e062SHong Zhang             if (is == ADD_VALUES) {
6510880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
652ad540459SPierre Jolivet                 for (jj = ii; jj < bs2; jj += bs) bap[jj] += *value++;
6530880e062SHong Zhang               }
6540880e062SHong Zhang             } else {
6550880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
656ad540459SPierre Jolivet                 for (jj = ii; jj < bs2; jj += bs) bap[jj] = *value++;
6570880e062SHong Zhang               }
6580880e062SHong Zhang             }
6590880e062SHong Zhang           } else {
6600880e062SHong Zhang             if (is == ADD_VALUES) {
6610880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
662ad540459SPierre Jolivet                 for (jj = 0; jj < bs; jj++) *bap++ += *value++;
6630880e062SHong Zhang               }
6640880e062SHong Zhang             } else {
6650880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
666ad540459SPierre Jolivet                 for (jj = 0; jj < bs; jj++) *bap++ = *value++;
6670880e062SHong Zhang               }
6680880e062SHong Zhang             }
6690880e062SHong Zhang           }
6700880e062SHong Zhang           goto noinsert2;
6710880e062SHong Zhang         }
6720880e062SHong Zhang       }
6730880e062SHong Zhang       if (nonew == 1) goto noinsert2;
67408401ef6SPierre Jolivet       PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new block index nonzero block (%" PetscInt_FMT ", %" PetscInt_FMT ") in the matrix", row, col);
675fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
6769371c9d4SSatish Balay       N = nrow++ - 1;
6779371c9d4SSatish Balay       high++;
6780880e062SHong Zhang       /* shift up all the later entries in this row */
6799566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1));
6809566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1)));
6819566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(ap + bs2 * i, bs2));
6820880e062SHong Zhang       rp[i] = col;
6830880e062SHong Zhang       bap   = ap + bs2 * i;
6840880e062SHong Zhang       if (roworiented) {
6850880e062SHong Zhang         for (ii = 0; ii < bs; ii++, value += stepval) {
686ad540459SPierre Jolivet           for (jj = ii; jj < bs2; jj += bs) bap[jj] = *value++;
6870880e062SHong Zhang         }
6880880e062SHong Zhang       } else {
6890880e062SHong Zhang         for (ii = 0; ii < bs; ii++, value += stepval) {
690ad540459SPierre Jolivet           for (jj = 0; jj < bs; jj++) *bap++ = *value++;
6910880e062SHong Zhang         }
6920880e062SHong Zhang       }
6930880e062SHong Zhang     noinsert2:;
6940880e062SHong Zhang       low = i;
6950880e062SHong Zhang     }
6960880e062SHong Zhang     ailen[row] = nrow;
6970880e062SHong Zhang   }
6980880e062SHong Zhang   PetscFunctionReturn(0);
69949b5e25fSSatish Balay }
70049b5e25fSSatish Balay 
70164831d72SBarry Smith /*
70264831d72SBarry Smith     This is not yet used
70364831d72SBarry Smith */
7049371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_SeqSBAIJ_SeqAIJ_Inode(Mat A) {
7050def2e27SBarry Smith   Mat_SeqSBAIJ   *a  = (Mat_SeqSBAIJ *)A->data;
7060def2e27SBarry Smith   const PetscInt *ai = a->i, *aj = a->j, *cols;
7070def2e27SBarry Smith   PetscInt        i = 0, j, blk_size, m = A->rmap->n, node_count = 0, nzx, nzy, *ns, row, nz, cnt, cnt2, *counts;
708ace3abfcSBarry Smith   PetscBool       flag;
7090def2e27SBarry Smith 
7100def2e27SBarry Smith   PetscFunctionBegin;
7119566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m, &ns));
7120def2e27SBarry Smith   while (i < m) {
7130def2e27SBarry Smith     nzx = ai[i + 1] - ai[i]; /* Number of nonzeros */
7140def2e27SBarry Smith     /* Limits the number of elements in a node to 'a->inode.limit' */
7150def2e27SBarry Smith     for (j = i + 1, blk_size = 1; j < m && blk_size < a->inode.limit; ++j, ++blk_size) {
7160def2e27SBarry Smith       nzy = ai[j + 1] - ai[j];
7170def2e27SBarry Smith       if (nzy != (nzx - j + i)) break;
7189566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(aj + ai[i] + j - i, aj + ai[j], nzy, &flag));
7190def2e27SBarry Smith       if (!flag) break;
7200def2e27SBarry Smith     }
7210def2e27SBarry Smith     ns[node_count++] = blk_size;
72226fbe8dcSKarl Rupp 
7230def2e27SBarry Smith     i = j;
7240def2e27SBarry Smith   }
7250def2e27SBarry Smith   if (!a->inode.size && m && node_count > .9 * m) {
7269566063dSJacob Faibussowitsch     PetscCall(PetscFree(ns));
7279566063dSJacob Faibussowitsch     PetscCall(PetscInfo(A, "Found %" PetscInt_FMT " nodes out of %" PetscInt_FMT " rows. Not using Inode routines\n", node_count, m));
7280def2e27SBarry Smith   } else {
7290def2e27SBarry Smith     a->inode.node_count = node_count;
73026fbe8dcSKarl Rupp 
7319566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(node_count, &a->inode.size));
7329566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(a->inode.size, ns, node_count));
7339566063dSJacob Faibussowitsch     PetscCall(PetscFree(ns));
7349566063dSJacob Faibussowitsch     PetscCall(PetscInfo(A, "Found %" PetscInt_FMT " nodes of %" PetscInt_FMT ". Limit used: %" PetscInt_FMT ". Using Inode routines\n", node_count, m, a->inode.limit));
7350def2e27SBarry Smith 
7360def2e27SBarry Smith     /* count collections of adjacent columns in each inode */
7370def2e27SBarry Smith     row = 0;
7380def2e27SBarry Smith     cnt = 0;
7390def2e27SBarry Smith     for (i = 0; i < node_count; i++) {
7400def2e27SBarry Smith       cols = aj + ai[row] + a->inode.size[i];
7410def2e27SBarry Smith       nz   = ai[row + 1] - ai[row] - a->inode.size[i];
7420def2e27SBarry Smith       for (j = 1; j < nz; j++) {
74326fbe8dcSKarl Rupp         if (cols[j] != cols[j - 1] + 1) cnt++;
7440def2e27SBarry Smith       }
7450def2e27SBarry Smith       cnt++;
7460def2e27SBarry Smith       row += a->inode.size[i];
7470def2e27SBarry Smith     }
7489566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(2 * cnt, &counts));
7490def2e27SBarry Smith     cnt = 0;
7500def2e27SBarry Smith     row = 0;
7510def2e27SBarry Smith     for (i = 0; i < node_count; i++) {
7520def2e27SBarry Smith       cols            = aj + ai[row] + a->inode.size[i];
7530def2e27SBarry Smith       counts[2 * cnt] = cols[0];
7540def2e27SBarry Smith       nz              = ai[row + 1] - ai[row] - a->inode.size[i];
7550def2e27SBarry Smith       cnt2            = 1;
7560def2e27SBarry Smith       for (j = 1; j < nz; j++) {
7570def2e27SBarry Smith         if (cols[j] != cols[j - 1] + 1) {
7580def2e27SBarry Smith           counts[2 * (cnt++) + 1] = cnt2;
7590def2e27SBarry Smith           counts[2 * cnt]         = cols[j];
7600def2e27SBarry Smith           cnt2                    = 1;
7610def2e27SBarry Smith         } else cnt2++;
7620def2e27SBarry Smith       }
7630def2e27SBarry Smith       counts[2 * (cnt++) + 1] = cnt2;
7640def2e27SBarry Smith       row += a->inode.size[i];
7650def2e27SBarry Smith     }
7669566063dSJacob Faibussowitsch     PetscCall(PetscIntView(2 * cnt, counts, NULL));
7670def2e27SBarry Smith   }
76838702af4SBarry Smith   PetscFunctionReturn(0);
76938702af4SBarry Smith }
77038702af4SBarry Smith 
7719371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_SeqSBAIJ(Mat A, MatAssemblyType mode) {
77249b5e25fSSatish Balay   Mat_SeqSBAIJ *a      = (Mat_SeqSBAIJ *)A->data;
7738f8f2f0dSBarry Smith   PetscInt      fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax;
774d0f46423SBarry Smith   PetscInt      m = A->rmap->N, *ip, N, *ailen = a->ilen;
77513f74950SBarry Smith   PetscInt      mbs = a->mbs, bs2 = a->bs2, rmax = 0;
77649b5e25fSSatish Balay   MatScalar    *aa = a->a, *ap;
77749b5e25fSSatish Balay 
77849b5e25fSSatish Balay   PetscFunctionBegin;
77949b5e25fSSatish Balay   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
78049b5e25fSSatish Balay 
78149b5e25fSSatish Balay   if (m) rmax = ailen[0];
78249b5e25fSSatish Balay   for (i = 1; i < mbs; i++) {
78349b5e25fSSatish Balay     /* move each row back by the amount of empty slots (fshift) before it*/
78449b5e25fSSatish Balay     fshift += imax[i - 1] - ailen[i - 1];
78549b5e25fSSatish Balay     rmax = PetscMax(rmax, ailen[i]);
78649b5e25fSSatish Balay     if (fshift) {
787580bdb30SBarry Smith       ip = aj + ai[i];
788580bdb30SBarry Smith       ap = aa + bs2 * ai[i];
78949b5e25fSSatish Balay       N  = ailen[i];
7909566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ip - fshift, ip, N));
7919566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ap - bs2 * fshift, ap, bs2 * N));
79249b5e25fSSatish Balay     }
79349b5e25fSSatish Balay     ai[i] = ai[i - 1] + ailen[i - 1];
79449b5e25fSSatish Balay   }
79549b5e25fSSatish Balay   if (mbs) {
79649b5e25fSSatish Balay     fshift += imax[mbs - 1] - ailen[mbs - 1];
79749b5e25fSSatish Balay     ai[mbs] = ai[mbs - 1] + ailen[mbs - 1];
79849b5e25fSSatish Balay   }
79949b5e25fSSatish Balay   /* reset ilen and imax for each row */
800ad540459SPierre Jolivet   for (i = 0; i < mbs; i++) ailen[i] = imax[i] = ai[i + 1] - ai[i];
8016c6c5352SBarry Smith   a->nz = ai[mbs];
80249b5e25fSSatish Balay 
803b424e231SHong Zhang   /* diagonals may have moved, reset it */
8041baa6e33SBarry Smith   if (a->diag) PetscCall(PetscArraycpy(a->diag, ai, mbs));
805aed4548fSBarry Smith   PetscCheck(!fshift || a->nounused != -1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unused space detected in matrix: %" PetscInt_FMT " X %" PetscInt_FMT " block size %" PetscInt_FMT ", %" PetscInt_FMT " unneeded", m, A->cmap->n, A->rmap->bs, fshift * bs2);
80626fbe8dcSKarl Rupp 
8079566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Matrix size: %" PetscInt_FMT " X %" PetscInt_FMT ", block size %" PetscInt_FMT "; storage space: %" PetscInt_FMT " unneeded, %" PetscInt_FMT " used\n", m, A->rmap->N, A->rmap->bs, fshift * bs2, a->nz * bs2));
8089566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues is %" PetscInt_FMT "\n", a->reallocs));
8099566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Most nonzeros blocks in any row is %" PetscInt_FMT "\n", rmax));
81026fbe8dcSKarl Rupp 
8118e58a170SBarry Smith   A->info.mallocs += a->reallocs;
81249b5e25fSSatish Balay   a->reallocs         = 0;
81349b5e25fSSatish Balay   A->info.nz_unneeded = (PetscReal)fshift * bs2;
814061b2667SBarry Smith   a->idiagvalid       = PETSC_FALSE;
8154dcd73b1SHong Zhang   a->rmax             = rmax;
81638702af4SBarry Smith 
81738702af4SBarry Smith   if (A->cmap->n < 65536 && A->cmap->bs == 1) {
81844e1c64aSLisandro Dalcin     if (a->jshort && a->free_jshort) {
81917803ae8SHong Zhang       /* when matrix data structure is changed, previous jshort must be replaced */
8209566063dSJacob Faibussowitsch       PetscCall(PetscFree(a->jshort));
82117803ae8SHong Zhang     }
8229566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(a->i[A->rmap->n], &a->jshort));
82338702af4SBarry Smith     for (i = 0; i < a->i[A->rmap->n]; i++) a->jshort[i] = a->j[i];
82438702af4SBarry Smith     A->ops->mult   = MatMult_SeqSBAIJ_1_ushort;
82541f059aeSBarry Smith     A->ops->sor    = MatSOR_SeqSBAIJ_ushort;
8264da8f245SBarry Smith     a->free_jshort = PETSC_TRUE;
82738702af4SBarry Smith   }
82849b5e25fSSatish Balay   PetscFunctionReturn(0);
82949b5e25fSSatish Balay }
83049b5e25fSSatish Balay 
83149b5e25fSSatish Balay /*
83249b5e25fSSatish Balay    This function returns an array of flags which indicate the locations of contiguous
83349b5e25fSSatish Balay    blocks that should be zeroed. for eg: if bs = 3  and is = [0,1,2,3,5,6,7,8,9]
834a5b23f4aSJose E. Roman    then the resulting sizes = [3,1,1,3,1] corresponding to sets [(0,1,2),(3),(5),(6,7,8),(9)]
83549b5e25fSSatish Balay    Assume: sizes should be long enough to hold all the values.
83649b5e25fSSatish Balay */
8379371c9d4SSatish Balay PetscErrorCode MatZeroRows_SeqSBAIJ_Check_Blocks(PetscInt idx[], PetscInt n, PetscInt bs, PetscInt sizes[], PetscInt *bs_max) {
83813f74950SBarry Smith   PetscInt  i, j, k, row;
839ace3abfcSBarry Smith   PetscBool flg;
84049b5e25fSSatish Balay 
84149b5e25fSSatish Balay   PetscFunctionBegin;
84249b5e25fSSatish Balay   for (i = 0, j = 0; i < n; j++) {
84349b5e25fSSatish Balay     row = idx[i];
844a5b23f4aSJose E. Roman     if (row % bs != 0) { /* Not the beginning of a block */
84549b5e25fSSatish Balay       sizes[j] = 1;
84649b5e25fSSatish Balay       i++;
84749b5e25fSSatish Balay     } else if (i + bs > n) { /* Beginning of a block, but complete block doesn't exist (at idx end) */
84849b5e25fSSatish Balay       sizes[j] = 1;          /* Also makes sure at least 'bs' values exist for next else */
84949b5e25fSSatish Balay       i++;
8506aad120cSJose E. Roman     } else { /* Beginning of the block, so check if the complete block exists */
85149b5e25fSSatish Balay       flg = PETSC_TRUE;
85249b5e25fSSatish Balay       for (k = 1; k < bs; k++) {
85349b5e25fSSatish Balay         if (row + k != idx[i + k]) { /* break in the block */
85449b5e25fSSatish Balay           flg = PETSC_FALSE;
85549b5e25fSSatish Balay           break;
85649b5e25fSSatish Balay         }
85749b5e25fSSatish Balay       }
858abc0a331SBarry Smith       if (flg) { /* No break in the bs */
85949b5e25fSSatish Balay         sizes[j] = bs;
86049b5e25fSSatish Balay         i += bs;
86149b5e25fSSatish Balay       } else {
86249b5e25fSSatish Balay         sizes[j] = 1;
86349b5e25fSSatish Balay         i++;
86449b5e25fSSatish Balay       }
86549b5e25fSSatish Balay     }
86649b5e25fSSatish Balay   }
86749b5e25fSSatish Balay   *bs_max = j;
86849b5e25fSSatish Balay   PetscFunctionReturn(0);
86949b5e25fSSatish Balay }
87049b5e25fSSatish Balay 
87149b5e25fSSatish Balay /* Only add/insert a(i,j) with i<=j (blocks).
87249b5e25fSSatish Balay    Any a(i,j) with i>j input by user is ingored.
87349b5e25fSSatish Balay */
87449b5e25fSSatish Balay 
8759371c9d4SSatish Balay PetscErrorCode MatSetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) {
87649b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
877e2ee6c50SBarry Smith   PetscInt     *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N, lastcol = -1;
87813f74950SBarry Smith   PetscInt     *imax = a->imax, *ai = a->i, *ailen = a->ilen, roworiented = a->roworiented;
879d0f46423SBarry Smith   PetscInt     *aj = a->j, nonew = a->nonew, bs = A->rmap->bs, brow, bcol;
88013f74950SBarry Smith   PetscInt      ridx, cidx, bs2                 = a->bs2;
88149b5e25fSSatish Balay   MatScalar    *ap, value, *aa                  = a->a, *bap;
88249b5e25fSSatish Balay 
88349b5e25fSSatish Balay   PetscFunctionBegin;
88449b5e25fSSatish Balay   for (k = 0; k < m; k++) { /* loop over added rows */
88549b5e25fSSatish Balay     row  = im[k];           /* row number */
88649b5e25fSSatish Balay     brow = row / bs;        /* block row number */
88749b5e25fSSatish Balay     if (row < 0) continue;
8886bdcaf15SBarry Smith     PetscCheck(row < A->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, row, A->rmap->N - 1);
88949b5e25fSSatish Balay     rp   = aj + ai[brow];       /*ptr to beginning of column value of the row block*/
89049b5e25fSSatish Balay     ap   = aa + bs2 * ai[brow]; /*ptr to beginning of element value of the row block*/
89149b5e25fSSatish Balay     rmax = imax[brow];          /* maximum space allocated for this row */
89249b5e25fSSatish Balay     nrow = ailen[brow];         /* actual length of this row */
89349b5e25fSSatish Balay     low  = 0;
8948509e838SStefano Zampini     high = nrow;
89549b5e25fSSatish Balay     for (l = 0; l < n; l++) { /* loop over added columns */
89649b5e25fSSatish Balay       if (in[l] < 0) continue;
8976bdcaf15SBarry Smith       PetscCheck(in[l] < A->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, in[l], A->cmap->N - 1);
89849b5e25fSSatish Balay       col  = in[l];
89949b5e25fSSatish Balay       bcol = col / bs; /* block col number */
90049b5e25fSSatish Balay 
901941593c8SHong Zhang       if (brow > bcol) {
90226fbe8dcSKarl Rupp         if (a->ignore_ltriangular) continue; /* ignore lower triangular values */
90326fbe8dcSKarl Rupp         else SETERRQ(PETSC_COMM_SELF, 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)");
904941593c8SHong Zhang       }
905f4989cb3SHong Zhang 
9069371c9d4SSatish Balay       ridx = row % bs;
9079371c9d4SSatish Balay       cidx = col % bs; /*row and col index inside the block */
9088549e402SHong Zhang       if ((brow == bcol && ridx <= cidx) || (brow < bcol)) {
90949b5e25fSSatish Balay         /* element value a(k,l) */
91026fbe8dcSKarl Rupp         if (roworiented) value = v[l + k * n];
91126fbe8dcSKarl Rupp         else value = v[k + l * m];
91249b5e25fSSatish Balay 
91349b5e25fSSatish Balay         /* move pointer bap to a(k,l) quickly and add/insert value */
91426fbe8dcSKarl Rupp         if (col <= lastcol) low = 0;
9158509e838SStefano Zampini         else high = nrow;
9168509e838SStefano Zampini 
917e2ee6c50SBarry Smith         lastcol = col;
91849b5e25fSSatish Balay         while (high - low > 7) {
91949b5e25fSSatish Balay           t = (low + high) / 2;
92049b5e25fSSatish Balay           if (rp[t] > bcol) high = t;
92149b5e25fSSatish Balay           else low = t;
92249b5e25fSSatish Balay         }
92349b5e25fSSatish Balay         for (i = low; i < high; i++) {
92449b5e25fSSatish Balay           if (rp[i] > bcol) break;
92549b5e25fSSatish Balay           if (rp[i] == bcol) {
92649b5e25fSSatish Balay             bap = ap + bs2 * i + bs * cidx + ridx;
92749b5e25fSSatish Balay             if (is == ADD_VALUES) *bap += value;
92849b5e25fSSatish Balay             else *bap = value;
9298549e402SHong Zhang             /* for diag block, add/insert its symmetric element a(cidx,ridx) */
9308549e402SHong Zhang             if (brow == bcol && ridx < cidx) {
9318549e402SHong Zhang               bap = ap + bs2 * i + bs * ridx + cidx;
9328549e402SHong Zhang               if (is == ADD_VALUES) *bap += value;
9338549e402SHong Zhang               else *bap = value;
9348549e402SHong Zhang             }
93549b5e25fSSatish Balay             goto noinsert1;
93649b5e25fSSatish Balay           }
93749b5e25fSSatish Balay         }
93849b5e25fSSatish Balay 
93949b5e25fSSatish Balay         if (nonew == 1) goto noinsert1;
94008401ef6SPierre Jolivet         PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero (%" PetscInt_FMT ", %" PetscInt_FMT ") in the matrix", row, col);
941fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, brow, bcol, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
94249b5e25fSSatish Balay 
9439371c9d4SSatish Balay         N = nrow++ - 1;
9449371c9d4SSatish Balay         high++;
94549b5e25fSSatish Balay         /* shift up all the later entries in this row */
9469566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1));
9479566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1)));
9489566063dSJacob Faibussowitsch         PetscCall(PetscArrayzero(ap + bs2 * i, bs2));
94949b5e25fSSatish Balay         rp[i]                          = bcol;
95049b5e25fSSatish Balay         ap[bs2 * i + bs * cidx + ridx] = value;
9518509e838SStefano Zampini         /* for diag block, add/insert its symmetric element a(cidx,ridx) */
952ad540459SPierre Jolivet         if (brow == bcol && ridx < cidx) ap[bs2 * i + bs * ridx + cidx] = value;
953e56f5c9eSBarry Smith         A->nonzerostate++;
95449b5e25fSSatish Balay       noinsert1:;
95549b5e25fSSatish Balay         low = i;
9568549e402SHong Zhang       }
95749b5e25fSSatish Balay     } /* end of loop over added columns */
95849b5e25fSSatish Balay     ailen[brow] = nrow;
95949b5e25fSSatish Balay   } /* end of loop over added rows */
96049b5e25fSSatish Balay   PetscFunctionReturn(0);
96149b5e25fSSatish Balay }
96249b5e25fSSatish Balay 
9639371c9d4SSatish Balay PetscErrorCode MatICCFactor_SeqSBAIJ(Mat inA, IS row, const MatFactorInfo *info) {
9644ccecd49SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)inA->data;
96549b5e25fSSatish Balay   Mat           outA;
966ace3abfcSBarry Smith   PetscBool     row_identity;
96749b5e25fSSatish Balay 
96849b5e25fSSatish Balay   PetscFunctionBegin;
96908401ef6SPierre Jolivet   PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 is supported for in-place icc");
9709566063dSJacob Faibussowitsch   PetscCall(ISIdentity(row, &row_identity));
97128b400f6SJacob Faibussowitsch   PetscCheck(row_identity, PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix reordering is not supported");
97208401ef6SPierre Jolivet   PetscCheck(inA->rmap->bs == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix block size %" PetscInt_FMT " is not supported", inA->rmap->bs); /* Need to replace MatCholeskyFactorSymbolic_SeqSBAIJ_MSR()! */
973c84f5b01SHong Zhang 
97449b5e25fSSatish Balay   outA            = inA;
975d5f3da31SBarry Smith   inA->factortype = MAT_FACTOR_ICC;
9769566063dSJacob Faibussowitsch   PetscCall(PetscFree(inA->solvertype));
9779566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype));
97849b5e25fSSatish Balay 
9799566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqSBAIJ(inA));
9809566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetNumericFactorization_inplace(inA, row_identity));
98149b5e25fSSatish Balay 
9829566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
9839566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
984c84f5b01SHong Zhang   a->row = row;
9859566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
9869566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
987c84f5b01SHong Zhang   a->col = row;
988c84f5b01SHong Zhang 
989c84f5b01SHong Zhang   /* Create the invert permutation so that it can be used in MatCholeskyFactorNumeric() */
9909566063dSJacob Faibussowitsch   if (a->icol) PetscCall(ISInvertPermutation(row, PETSC_DECIDE, &a->icol));
99149b5e25fSSatish Balay 
992*4dfa11a4SJacob Faibussowitsch   if (!a->solve_work) { PetscCall(PetscMalloc1(inA->rmap->N + inA->rmap->bs, &a->solve_work)); }
99349b5e25fSSatish Balay 
9949566063dSJacob Faibussowitsch   PetscCall(MatCholeskyFactorNumeric(outA, inA, info));
99549b5e25fSSatish Balay   PetscFunctionReturn(0);
99649b5e25fSSatish Balay }
997950f1e5bSHong Zhang 
9989371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat, PetscInt *indices) {
999045c9aa0SHong Zhang   Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)mat->data;
100013f74950SBarry Smith   PetscInt      i, nz, n;
100149b5e25fSSatish Balay 
100249b5e25fSSatish Balay   PetscFunctionBegin;
10036c6c5352SBarry Smith   nz = baij->maxnz;
1004d0f46423SBarry Smith   n  = mat->cmap->n;
100526fbe8dcSKarl Rupp   for (i = 0; i < nz; i++) baij->j[i] = indices[i];
100626fbe8dcSKarl Rupp 
10076c6c5352SBarry Smith   baij->nz = nz;
100826fbe8dcSKarl Rupp   for (i = 0; i < n; i++) baij->ilen[i] = baij->imax[i];
100926fbe8dcSKarl Rupp 
10109566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
101149b5e25fSSatish Balay   PetscFunctionReturn(0);
101249b5e25fSSatish Balay }
101349b5e25fSSatish Balay 
101449b5e25fSSatish Balay /*@
101519585528SSatish Balay   MatSeqSBAIJSetColumnIndices - Set the column indices for all the rows
101611a5261eSBarry Smith   in a `MATSEQSBAIJ` matrix.
101749b5e25fSSatish Balay 
101849b5e25fSSatish Balay   Input Parameters:
101911a5261eSBarry Smith   +  mat     - the `MATSEQSBAIJ` matrix
102049b5e25fSSatish Balay   -  indices - the column indices
102149b5e25fSSatish Balay 
102249b5e25fSSatish Balay   Level: advanced
102349b5e25fSSatish Balay 
102449b5e25fSSatish Balay   Notes:
102549b5e25fSSatish Balay   This can be called if you have precomputed the nonzero structure of the
102649b5e25fSSatish Balay   matrix and want to provide it to the matrix object to improve the performance
102711a5261eSBarry Smith   of the `MatSetValues()` operation.
102849b5e25fSSatish Balay 
102949b5e25fSSatish Balay   You MUST have set the correct numbers of nonzeros per row in the call to
103011a5261eSBarry Smith   `MatCreateSeqSBAIJ()`, and the columns indices MUST be sorted.
103149b5e25fSSatish Balay 
1032ab9f2c04SSatish Balay   MUST be called before any calls to MatSetValues()
103349b5e25fSSatish Balay 
103411a5261eSBarry Smith  .seealso: `MATSEQSBAIJ`, `MatCreateSeqSBAIJ`
103549b5e25fSSatish Balay @*/
10369371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetColumnIndices(Mat mat, PetscInt *indices) {
103749b5e25fSSatish Balay   PetscFunctionBegin;
10380700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1039dadcf809SJacob Faibussowitsch   PetscValidIntPointer(indices, 2);
1040cac4c232SBarry Smith   PetscUseMethod(mat, "MatSeqSBAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices));
104149b5e25fSSatish Balay   PetscFunctionReturn(0);
104249b5e25fSSatish Balay }
104349b5e25fSSatish Balay 
10449371c9d4SSatish Balay PetscErrorCode MatCopy_SeqSBAIJ(Mat A, Mat B, MatStructure str) {
10454c7a3774SStefano Zampini   PetscBool isbaij;
10463c896bc6SHong Zhang 
10473c896bc6SHong Zhang   PetscFunctionBegin;
10489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &isbaij, MATSEQSBAIJ, MATMPISBAIJ, ""));
104928b400f6SJacob Faibussowitsch   PetscCheck(isbaij, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)B)->type_name);
10504c7a3774SStefano Zampini   /* If the two matrices have the same copy implementation and nonzero pattern, use fast copy. */
10514c7a3774SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
10523c896bc6SHong Zhang     Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
10533c896bc6SHong Zhang     Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data;
10543c896bc6SHong Zhang 
105508401ef6SPierre Jolivet     PetscCheck(a->i[a->mbs] == b->i[b->mbs], PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of nonzeros in two matrices are different");
105608401ef6SPierre Jolivet     PetscCheck(a->mbs == b->mbs, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of rows in two matrices are different");
105708401ef6SPierre Jolivet     PetscCheck(a->bs2 == b->bs2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different block size");
10589566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(b->a, a->a, a->bs2 * a->i[a->mbs]));
10599566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)B));
10603c896bc6SHong Zhang   } else {
10619566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(A));
10629566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
10639566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(A));
10643c896bc6SHong Zhang   }
10653c896bc6SHong Zhang   PetscFunctionReturn(0);
10663c896bc6SHong Zhang }
10673c896bc6SHong Zhang 
10689371c9d4SSatish Balay PetscErrorCode MatSetUp_SeqSBAIJ(Mat A) {
1069273d9f13SBarry Smith   PetscFunctionBegin;
10709566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(A, A->rmap->bs, PETSC_DEFAULT, NULL));
1071273d9f13SBarry Smith   PetscFunctionReturn(0);
1072273d9f13SBarry Smith }
1073273d9f13SBarry Smith 
10749371c9d4SSatish Balay static PetscErrorCode MatSeqSBAIJGetArray_SeqSBAIJ(Mat A, PetscScalar *array[]) {
1075a6ece127SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
10765fd66863SKarl Rupp 
1077a6ece127SHong Zhang   PetscFunctionBegin;
1078a6ece127SHong Zhang   *array = a->a;
1079a6ece127SHong Zhang   PetscFunctionReturn(0);
1080a6ece127SHong Zhang }
1081a6ece127SHong Zhang 
10829371c9d4SSatish Balay static PetscErrorCode MatSeqSBAIJRestoreArray_SeqSBAIJ(Mat A, PetscScalar *array[]) {
1083a6ece127SHong Zhang   PetscFunctionBegin;
1084cda14afcSprj-   *array = NULL;
1085a6ece127SHong Zhang   PetscFunctionReturn(0);
1086a6ece127SHong Zhang }
1087a6ece127SHong Zhang 
10889371c9d4SSatish Balay PetscErrorCode MatAXPYGetPreallocation_SeqSBAIJ(Mat Y, Mat X, PetscInt *nnz) {
1089b264fe52SHong Zhang   PetscInt      bs = Y->rmap->bs, mbs = Y->rmap->N / bs;
109052768537SHong Zhang   Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data;
109152768537SHong Zhang   Mat_SeqSBAIJ *y = (Mat_SeqSBAIJ *)Y->data;
109252768537SHong Zhang 
109352768537SHong Zhang   PetscFunctionBegin;
109452768537SHong Zhang   /* Set the number of nonzeros in the new matrix */
10959566063dSJacob Faibussowitsch   PetscCall(MatAXPYGetPreallocation_SeqX_private(mbs, x->i, x->j, y->i, y->j, nnz));
109652768537SHong Zhang   PetscFunctionReturn(0);
109752768537SHong Zhang }
109852768537SHong Zhang 
10999371c9d4SSatish Balay PetscErrorCode MatAXPY_SeqSBAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str) {
110042ee4b1aSHong Zhang   Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data, *y = (Mat_SeqSBAIJ *)Y->data;
110131ce2d13SHong Zhang   PetscInt      bs = Y->rmap->bs, bs2 = bs * bs;
1102e838b9e7SJed Brown   PetscBLASInt  one = 1;
110342ee4b1aSHong Zhang 
110442ee4b1aSHong Zhang   PetscFunctionBegin;
1105134adf20SPierre Jolivet   if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) {
1106134adf20SPierre Jolivet     PetscBool e = x->nz == y->nz && x->mbs == y->mbs ? PETSC_TRUE : PETSC_FALSE;
1107134adf20SPierre Jolivet     if (e) {
11089566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(x->i, y->i, x->mbs + 1, &e));
1109134adf20SPierre Jolivet       if (e) {
11109566063dSJacob Faibussowitsch         PetscCall(PetscArraycmp(x->j, y->j, x->i[x->mbs], &e));
1111134adf20SPierre Jolivet         if (e) str = SAME_NONZERO_PATTERN;
1112134adf20SPierre Jolivet       }
1113134adf20SPierre Jolivet     }
111454c59aa7SJacob Faibussowitsch     if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN");
1115134adf20SPierre Jolivet   }
111642ee4b1aSHong Zhang   if (str == SAME_NONZERO_PATTERN) {
1117f4df32b1SMatthew Knepley     PetscScalar  alpha = a;
1118c5df96a5SBarry Smith     PetscBLASInt bnz;
11199566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(x->nz * bs2, &bnz));
1120792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, x->a, &one, y->a, &one));
11219566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)Y));
1122ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
11239566063dSJacob Faibussowitsch     PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_TRUE));
11249566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
11259566063dSJacob Faibussowitsch     PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_FALSE));
112642ee4b1aSHong Zhang   } else {
112752768537SHong Zhang     Mat       B;
112852768537SHong Zhang     PetscInt *nnz;
112954c59aa7SJacob Faibussowitsch     PetscCheck(bs == X->rmap->bs, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Matrices must have same block size");
11309566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(X));
11319566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(Y));
11329566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Y->rmap->N, &nnz));
11339566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B));
11349566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name));
11359566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, Y->rmap->n, Y->cmap->n, Y->rmap->N, Y->cmap->N));
11369566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, Y, Y));
11379566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, ((PetscObject)Y)->type_name));
11389566063dSJacob Faibussowitsch     PetscCall(MatAXPYGetPreallocation_SeqSBAIJ(Y, X, nnz));
11399566063dSJacob Faibussowitsch     PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz));
114052768537SHong Zhang 
11419566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
114252768537SHong Zhang 
11439566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
11449566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz));
11459566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(X));
11469566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(Y));
114742ee4b1aSHong Zhang   }
114842ee4b1aSHong Zhang   PetscFunctionReturn(0);
114942ee4b1aSHong Zhang }
115042ee4b1aSHong Zhang 
11519371c9d4SSatish Balay PetscErrorCode MatIsSymmetric_SeqSBAIJ(Mat A, PetscReal tol, PetscBool *flg) {
1152efcf0fc3SBarry Smith   PetscFunctionBegin;
1153efcf0fc3SBarry Smith   *flg = PETSC_TRUE;
1154efcf0fc3SBarry Smith   PetscFunctionReturn(0);
1155efcf0fc3SBarry Smith }
1156efcf0fc3SBarry Smith 
11579371c9d4SSatish Balay PetscErrorCode MatIsStructurallySymmetric_SeqSBAIJ(Mat A, PetscBool *flg) {
1158efcf0fc3SBarry Smith   PetscFunctionBegin;
1159efcf0fc3SBarry Smith   *flg = PETSC_TRUE;
1160efcf0fc3SBarry Smith   PetscFunctionReturn(0);
1161efcf0fc3SBarry Smith }
1162efcf0fc3SBarry Smith 
11639371c9d4SSatish Balay PetscErrorCode MatIsHermitian_SeqSBAIJ(Mat A, PetscReal tol, PetscBool *flg) {
1164efcf0fc3SBarry Smith   PetscFunctionBegin;
1165efcf0fc3SBarry Smith   *flg = PETSC_FALSE;
1166efcf0fc3SBarry Smith   PetscFunctionReturn(0);
1167efcf0fc3SBarry Smith }
1168efcf0fc3SBarry Smith 
11699371c9d4SSatish Balay PetscErrorCode MatConjugate_SeqSBAIJ(Mat A) {
11702726fb6dSPierre Jolivet #if defined(PETSC_USE_COMPLEX)
11712726fb6dSPierre Jolivet   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
11722726fb6dSPierre Jolivet   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
11732726fb6dSPierre Jolivet   MatScalar    *aa = a->a;
11742726fb6dSPierre Jolivet 
11752726fb6dSPierre Jolivet   PetscFunctionBegin;
11762726fb6dSPierre Jolivet   for (i = 0; i < nz; i++) aa[i] = PetscConj(aa[i]);
11772726fb6dSPierre Jolivet #else
11782726fb6dSPierre Jolivet   PetscFunctionBegin;
11792726fb6dSPierre Jolivet #endif
11802726fb6dSPierre Jolivet   PetscFunctionReturn(0);
11812726fb6dSPierre Jolivet }
11822726fb6dSPierre Jolivet 
11839371c9d4SSatish Balay PetscErrorCode MatRealPart_SeqSBAIJ(Mat A) {
118499cafbc1SBarry Smith   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
118599cafbc1SBarry Smith   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
1186dd6ea824SBarry Smith   MatScalar    *aa = a->a;
118799cafbc1SBarry Smith 
118899cafbc1SBarry Smith   PetscFunctionBegin;
118999cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]);
119099cafbc1SBarry Smith   PetscFunctionReturn(0);
119199cafbc1SBarry Smith }
119299cafbc1SBarry Smith 
11939371c9d4SSatish Balay PetscErrorCode MatImaginaryPart_SeqSBAIJ(Mat A) {
119499cafbc1SBarry Smith   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
119599cafbc1SBarry Smith   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
1196dd6ea824SBarry Smith   MatScalar    *aa = a->a;
119799cafbc1SBarry Smith 
119899cafbc1SBarry Smith   PetscFunctionBegin;
119999cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
120099cafbc1SBarry Smith   PetscFunctionReturn(0);
120199cafbc1SBarry Smith }
120299cafbc1SBarry Smith 
12039371c9d4SSatish Balay PetscErrorCode MatZeroRowsColumns_SeqSBAIJ(Mat A, PetscInt is_n, const PetscInt is_idx[], PetscScalar diag, Vec x, Vec b) {
12043bededecSBarry Smith   Mat_SeqSBAIJ      *baij = (Mat_SeqSBAIJ *)A->data;
12053bededecSBarry Smith   PetscInt           i, j, k, count;
12063bededecSBarry Smith   PetscInt           bs = A->rmap->bs, bs2 = baij->bs2, row, col;
12073bededecSBarry Smith   PetscScalar        zero = 0.0;
12083bededecSBarry Smith   MatScalar         *aa;
12093bededecSBarry Smith   const PetscScalar *xx;
12103bededecSBarry Smith   PetscScalar       *bb;
121156777dd2SBarry Smith   PetscBool         *zeroed, vecs = PETSC_FALSE;
12123bededecSBarry Smith 
12133bededecSBarry Smith   PetscFunctionBegin;
12143bededecSBarry Smith   /* fix right hand side if needed */
12153bededecSBarry Smith   if (x && b) {
12169566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
12179566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
121856777dd2SBarry Smith     vecs = PETSC_TRUE;
12193bededecSBarry Smith   }
12203bededecSBarry Smith 
12213bededecSBarry Smith   /* zero the columns */
12229566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(A->rmap->n, &zeroed));
12233bededecSBarry Smith   for (i = 0; i < is_n; i++) {
1224aed4548fSBarry Smith     PetscCheck(is_idx[i] >= 0 && is_idx[i] < A->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", is_idx[i]);
12253bededecSBarry Smith     zeroed[is_idx[i]] = PETSC_TRUE;
12263bededecSBarry Smith   }
122756777dd2SBarry Smith   if (vecs) {
122856777dd2SBarry Smith     for (i = 0; i < A->rmap->N; i++) {
122956777dd2SBarry Smith       row = i / bs;
123056777dd2SBarry Smith       for (j = baij->i[row]; j < baij->i[row + 1]; j++) {
123156777dd2SBarry Smith         for (k = 0; k < bs; k++) {
123256777dd2SBarry Smith           col = bs * baij->j[j] + k;
123356777dd2SBarry Smith           if (col <= i) continue;
123456777dd2SBarry Smith           aa = ((MatScalar *)(baij->a)) + j * bs2 + (i % bs) + bs * k;
123526fbe8dcSKarl Rupp           if (!zeroed[i] && zeroed[col]) bb[i] -= aa[0] * xx[col];
123626fbe8dcSKarl Rupp           if (zeroed[i] && !zeroed[col]) bb[col] -= aa[0] * xx[i];
123756777dd2SBarry Smith         }
123856777dd2SBarry Smith       }
123956777dd2SBarry Smith     }
124026fbe8dcSKarl Rupp     for (i = 0; i < is_n; i++) bb[is_idx[i]] = diag * xx[is_idx[i]];
124156777dd2SBarry Smith   }
124256777dd2SBarry Smith 
12433bededecSBarry Smith   for (i = 0; i < A->rmap->N; i++) {
12443bededecSBarry Smith     if (!zeroed[i]) {
12453bededecSBarry Smith       row = i / bs;
12463bededecSBarry Smith       for (j = baij->i[row]; j < baij->i[row + 1]; j++) {
12473bededecSBarry Smith         for (k = 0; k < bs; k++) {
12483bededecSBarry Smith           col = bs * baij->j[j] + k;
12493bededecSBarry Smith           if (zeroed[col]) {
12503bededecSBarry Smith             aa    = ((MatScalar *)(baij->a)) + j * bs2 + (i % bs) + bs * k;
12513bededecSBarry Smith             aa[0] = 0.0;
12523bededecSBarry Smith           }
12533bededecSBarry Smith         }
12543bededecSBarry Smith       }
12553bededecSBarry Smith     }
12563bededecSBarry Smith   }
12579566063dSJacob Faibussowitsch   PetscCall(PetscFree(zeroed));
125856777dd2SBarry Smith   if (vecs) {
12599566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
12609566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
126156777dd2SBarry Smith   }
12623bededecSBarry Smith 
12633bededecSBarry Smith   /* zero the rows */
12643bededecSBarry Smith   for (i = 0; i < is_n; i++) {
12653bededecSBarry Smith     row   = is_idx[i];
12663bededecSBarry Smith     count = (baij->i[row / bs + 1] - baij->i[row / bs]) * bs;
12673bededecSBarry Smith     aa    = ((MatScalar *)(baij->a)) + baij->i[row / bs] * bs2 + (row % bs);
12683bededecSBarry Smith     for (k = 0; k < count; k++) {
12693bededecSBarry Smith       aa[0] = zero;
12703bededecSBarry Smith       aa += bs;
12713bededecSBarry Smith     }
1272dbbe0bcdSBarry Smith     if (diag != 0.0) PetscUseTypeMethod(A, setvalues, 1, &row, 1, &row, &diag, INSERT_VALUES);
12733bededecSBarry Smith   }
12749566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd_SeqSBAIJ(A, MAT_FINAL_ASSEMBLY));
12753bededecSBarry Smith   PetscFunctionReturn(0);
12763bededecSBarry Smith }
12773bededecSBarry Smith 
12789371c9d4SSatish Balay PetscErrorCode MatShift_SeqSBAIJ(Mat Y, PetscScalar a) {
12797d68702bSBarry Smith   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)Y->data;
12807d68702bSBarry Smith 
12817d68702bSBarry Smith   PetscFunctionBegin;
128248a46eb9SPierre Jolivet   if (!Y->preallocated || !aij->nz) PetscCall(MatSeqSBAIJSetPreallocation(Y, Y->rmap->bs, 1, NULL));
12839566063dSJacob Faibussowitsch   PetscCall(MatShift_Basic(Y, a));
12847d68702bSBarry Smith   PetscFunctionReturn(0);
12857d68702bSBarry Smith }
12867d68702bSBarry Smith 
128749b5e25fSSatish Balay /* -------------------------------------------------------------------*/
12883964eb88SJed Brown static struct _MatOps MatOps_Values = {MatSetValues_SeqSBAIJ,
128949b5e25fSSatish Balay                                        MatGetRow_SeqSBAIJ,
129049b5e25fSSatish Balay                                        MatRestoreRow_SeqSBAIJ,
129149b5e25fSSatish Balay                                        MatMult_SeqSBAIJ_N,
129297304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqSBAIJ_N,
1293431c96f7SBarry Smith                                        MatMult_SeqSBAIJ_N, /* transpose versions are same as non-transpose versions */
1294e005ede5SBarry Smith                                        MatMultAdd_SeqSBAIJ_N,
1295f4259b30SLisandro Dalcin                                        NULL,
1296f4259b30SLisandro Dalcin                                        NULL,
1297f4259b30SLisandro Dalcin                                        NULL,
1298f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
1299f4259b30SLisandro Dalcin                                        NULL,
1300c078aec8SLisandro Dalcin                                        MatCholeskyFactor_SeqSBAIJ,
130141f059aeSBarry Smith                                        MatSOR_SeqSBAIJ,
130249b5e25fSSatish Balay                                        MatTranspose_SeqSBAIJ,
130397304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqSBAIJ,
130449b5e25fSSatish Balay                                        MatEqual_SeqSBAIJ,
130549b5e25fSSatish Balay                                        MatGetDiagonal_SeqSBAIJ,
130649b5e25fSSatish Balay                                        MatDiagonalScale_SeqSBAIJ,
130749b5e25fSSatish Balay                                        MatNorm_SeqSBAIJ,
1308f4259b30SLisandro Dalcin                                        /* 20*/ NULL,
130949b5e25fSSatish Balay                                        MatAssemblyEnd_SeqSBAIJ,
131049b5e25fSSatish Balay                                        MatSetOption_SeqSBAIJ,
131149b5e25fSSatish Balay                                        MatZeroEntries_SeqSBAIJ,
1312f4259b30SLisandro Dalcin                                        /* 24*/ NULL,
1313f4259b30SLisandro Dalcin                                        NULL,
1314f4259b30SLisandro Dalcin                                        NULL,
1315f4259b30SLisandro Dalcin                                        NULL,
1316f4259b30SLisandro Dalcin                                        NULL,
13174994cf47SJed Brown                                        /* 29*/ MatSetUp_SeqSBAIJ,
1318f4259b30SLisandro Dalcin                                        NULL,
1319f4259b30SLisandro Dalcin                                        NULL,
1320f4259b30SLisandro Dalcin                                        NULL,
1321f4259b30SLisandro Dalcin                                        NULL,
1322d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqSBAIJ,
1323f4259b30SLisandro Dalcin                                        NULL,
1324f4259b30SLisandro Dalcin                                        NULL,
1325f4259b30SLisandro Dalcin                                        NULL,
1326c84f5b01SHong Zhang                                        MatICCFactor_SeqSBAIJ,
1327d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqSBAIJ,
13287dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqSBAIJ,
132949b5e25fSSatish Balay                                        MatIncreaseOverlap_SeqSBAIJ,
133049b5e25fSSatish Balay                                        MatGetValues_SeqSBAIJ,
13313c896bc6SHong Zhang                                        MatCopy_SeqSBAIJ,
1332f4259b30SLisandro Dalcin                                        /* 44*/ NULL,
133349b5e25fSSatish Balay                                        MatScale_SeqSBAIJ,
13347d68702bSBarry Smith                                        MatShift_SeqSBAIJ,
1335f4259b30SLisandro Dalcin                                        NULL,
13363bededecSBarry Smith                                        MatZeroRowsColumns_SeqSBAIJ,
1337f4259b30SLisandro Dalcin                                        /* 49*/ NULL,
133849b5e25fSSatish Balay                                        MatGetRowIJ_SeqSBAIJ,
133949b5e25fSSatish Balay                                        MatRestoreRowIJ_SeqSBAIJ,
1340f4259b30SLisandro Dalcin                                        NULL,
1341f4259b30SLisandro Dalcin                                        NULL,
1342f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
1343f4259b30SLisandro Dalcin                                        NULL,
1344f4259b30SLisandro Dalcin                                        NULL,
1345dc29a518SPierre Jolivet                                        MatPermute_SeqSBAIJ,
134649b5e25fSSatish Balay                                        MatSetValuesBlocked_SeqSBAIJ,
13477dae84e0SHong Zhang                                        /* 59*/ MatCreateSubMatrix_SeqSBAIJ,
1348f4259b30SLisandro Dalcin                                        NULL,
1349f4259b30SLisandro Dalcin                                        NULL,
1350f4259b30SLisandro Dalcin                                        NULL,
1351f4259b30SLisandro Dalcin                                        NULL,
1352f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
1353f4259b30SLisandro Dalcin                                        NULL,
1354f4259b30SLisandro Dalcin                                        NULL,
1355f4259b30SLisandro Dalcin                                        NULL,
1356f4259b30SLisandro Dalcin                                        NULL,
1357d519adbfSMatthew Knepley                                        /* 69*/ MatGetRowMaxAbs_SeqSBAIJ,
1358f4259b30SLisandro Dalcin                                        NULL,
135928d58a37SPierre Jolivet                                        MatConvert_MPISBAIJ_Basic,
1360f4259b30SLisandro Dalcin                                        NULL,
1361f4259b30SLisandro Dalcin                                        NULL,
1362f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
1363f4259b30SLisandro Dalcin                                        NULL,
1364f4259b30SLisandro Dalcin                                        NULL,
1365f4259b30SLisandro Dalcin                                        NULL,
1366f4259b30SLisandro Dalcin                                        NULL,
1367f4259b30SLisandro Dalcin                                        /* 79*/ NULL,
1368f4259b30SLisandro Dalcin                                        NULL,
1369f4259b30SLisandro Dalcin                                        NULL,
137097304618SKris Buschelman                                        MatGetInertia_SeqSBAIJ,
13715bba2384SShri Abhyankar                                        MatLoad_SeqSBAIJ,
1372d519adbfSMatthew Knepley                                        /* 84*/ MatIsSymmetric_SeqSBAIJ,
1373865e5f61SKris Buschelman                                        MatIsHermitian_SeqSBAIJ,
1374efcf0fc3SBarry Smith                                        MatIsStructurallySymmetric_SeqSBAIJ,
1375f4259b30SLisandro Dalcin                                        NULL,
1376f4259b30SLisandro Dalcin                                        NULL,
1377f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
1378f4259b30SLisandro Dalcin                                        NULL,
1379f4259b30SLisandro Dalcin                                        NULL,
1380f4259b30SLisandro Dalcin                                        NULL,
1381f4259b30SLisandro Dalcin                                        NULL,
1382f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
1383f4259b30SLisandro Dalcin                                        NULL,
1384f4259b30SLisandro Dalcin                                        NULL,
1385f4259b30SLisandro Dalcin                                        NULL,
1386f4259b30SLisandro Dalcin                                        NULL,
1387f4259b30SLisandro Dalcin                                        /* 99*/ NULL,
1388f4259b30SLisandro Dalcin                                        NULL,
1389f4259b30SLisandro Dalcin                                        NULL,
13902726fb6dSPierre Jolivet                                        MatConjugate_SeqSBAIJ,
1391f4259b30SLisandro Dalcin                                        NULL,
1392f4259b30SLisandro Dalcin                                        /*104*/ NULL,
139399cafbc1SBarry Smith                                        MatRealPart_SeqSBAIJ,
1394f5edf698SHong Zhang                                        MatImaginaryPart_SeqSBAIJ,
1395f5edf698SHong Zhang                                        MatGetRowUpperTriangular_SeqSBAIJ,
13962af78befSBarry Smith                                        MatRestoreRowUpperTriangular_SeqSBAIJ,
1397f4259b30SLisandro Dalcin                                        /*109*/ NULL,
1398f4259b30SLisandro Dalcin                                        NULL,
1399f4259b30SLisandro Dalcin                                        NULL,
1400f4259b30SLisandro Dalcin                                        NULL,
1401547795f9SHong Zhang                                        MatMissingDiagonal_SeqSBAIJ,
1402f4259b30SLisandro Dalcin                                        /*114*/ NULL,
1403f4259b30SLisandro Dalcin                                        NULL,
1404f4259b30SLisandro Dalcin                                        NULL,
1405f4259b30SLisandro Dalcin                                        NULL,
1406f4259b30SLisandro Dalcin                                        NULL,
1407f4259b30SLisandro Dalcin                                        /*119*/ NULL,
1408f4259b30SLisandro Dalcin                                        NULL,
1409f4259b30SLisandro Dalcin                                        NULL,
1410f4259b30SLisandro Dalcin                                        NULL,
1411f4259b30SLisandro Dalcin                                        NULL,
1412f4259b30SLisandro Dalcin                                        /*124*/ NULL,
1413f4259b30SLisandro Dalcin                                        NULL,
1414f4259b30SLisandro Dalcin                                        NULL,
1415f4259b30SLisandro Dalcin                                        NULL,
1416f4259b30SLisandro Dalcin                                        NULL,
1417f4259b30SLisandro Dalcin                                        /*129*/ NULL,
1418f4259b30SLisandro Dalcin                                        NULL,
1419f4259b30SLisandro Dalcin                                        NULL,
1420f4259b30SLisandro Dalcin                                        NULL,
1421f4259b30SLisandro Dalcin                                        NULL,
1422f4259b30SLisandro Dalcin                                        /*134*/ NULL,
1423f4259b30SLisandro Dalcin                                        NULL,
1424f4259b30SLisandro Dalcin                                        NULL,
1425f4259b30SLisandro Dalcin                                        NULL,
1426f4259b30SLisandro Dalcin                                        NULL,
142746533700Sstefano_zampini                                        /*139*/ MatSetBlockSizes_Default,
1428f4259b30SLisandro Dalcin                                        NULL,
1429f4259b30SLisandro Dalcin                                        NULL,
1430f4259b30SLisandro Dalcin                                        NULL,
1431f4259b30SLisandro Dalcin                                        NULL,
1432d70f29a3SPierre Jolivet                                        /*144*/ MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ,
1433d70f29a3SPierre Jolivet                                        NULL,
1434d70f29a3SPierre Jolivet                                        NULL,
143599a7f59eSMark Adams                                        NULL,
143699a7f59eSMark Adams                                        NULL,
14377fb60732SBarry Smith                                        NULL,
14389371c9d4SSatish Balay                                        /*150*/ NULL};
1439be1d678aSKris Buschelman 
14409371c9d4SSatish Balay PetscErrorCode MatStoreValues_SeqSBAIJ(Mat mat) {
14414afc71dfSHong Zhang   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1442d0f46423SBarry Smith   PetscInt      nz  = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2;
144349b5e25fSSatish Balay 
144449b5e25fSSatish Balay   PetscFunctionBegin;
144508401ef6SPierre Jolivet   PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
144649b5e25fSSatish Balay 
144749b5e25fSSatish Balay   /* allocate space for values if not already there */
144848a46eb9SPierre Jolivet   if (!aij->saved_values) PetscCall(PetscMalloc1(nz + 1, &aij->saved_values));
144949b5e25fSSatish Balay 
145049b5e25fSSatish Balay   /* copy values over */
14519566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz));
145249b5e25fSSatish Balay   PetscFunctionReturn(0);
145349b5e25fSSatish Balay }
145449b5e25fSSatish Balay 
14559371c9d4SSatish Balay PetscErrorCode MatRetrieveValues_SeqSBAIJ(Mat mat) {
14564afc71dfSHong Zhang   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1457d0f46423SBarry Smith   PetscInt      nz  = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2;
145849b5e25fSSatish Balay 
145949b5e25fSSatish Balay   PetscFunctionBegin;
146008401ef6SPierre Jolivet   PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
146128b400f6SJacob Faibussowitsch   PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first");
146249b5e25fSSatish Balay 
146349b5e25fSSatish Balay   /* copy values over */
14649566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz));
146549b5e25fSSatish Balay   PetscFunctionReturn(0);
146649b5e25fSSatish Balay }
146749b5e25fSSatish Balay 
14689371c9d4SSatish Balay static PetscErrorCode MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B, PetscInt bs, PetscInt nz, PetscInt *nnz) {
1469c464158bSHong Zhang   Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data;
14704dcd73b1SHong Zhang   PetscInt      i, mbs, nbs, bs2;
14712576faa2SJed Brown   PetscBool     skipallocation = PETSC_FALSE, flg = PETSC_FALSE, realalloc = PETSC_FALSE;
147249b5e25fSSatish Balay 
147349b5e25fSSatish Balay   PetscFunctionBegin;
14742576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
1475db4efbfdSBarry Smith 
14769566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(B, PetscAbs(bs)));
14779566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
14789566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
147908401ef6SPierre Jolivet   PetscCheck(B->rmap->N <= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_SUP, "SEQSBAIJ matrix cannot have more rows %" PetscInt_FMT " than columns %" PetscInt_FMT, B->rmap->N, B->cmap->N);
14809566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs));
1481899cda47SBarry Smith 
148221940c7eSstefano_zampini   B->preallocated = PETSC_TRUE;
148321940c7eSstefano_zampini 
1484d0f46423SBarry Smith   mbs = B->rmap->N / bs;
14854dcd73b1SHong Zhang   nbs = B->cmap->n / bs;
148649b5e25fSSatish Balay   bs2 = bs * bs;
148749b5e25fSSatish Balay 
1488aed4548fSBarry Smith   PetscCheck(mbs * bs == B->rmap->N && nbs * bs == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number rows, cols must be divisible by blocksize");
148949b5e25fSSatish Balay 
1490ab93d7beSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
1491ab93d7beSBarry Smith     skipallocation = PETSC_TRUE;
1492ab93d7beSBarry Smith     nz             = 0;
1493ab93d7beSBarry Smith   }
1494ab93d7beSBarry Smith 
1495435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3;
149608401ef6SPierre Jolivet   PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz);
149749b5e25fSSatish Balay   if (nnz) {
149849b5e25fSSatish Balay     for (i = 0; i < mbs; i++) {
149908401ef6SPierre Jolivet       PetscCheck(nnz[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nnz cannot be less than 0: local row %" PetscInt_FMT " value %" PetscInt_FMT, i, nnz[i]);
150008401ef6SPierre Jolivet       PetscCheck(nnz[i] <= nbs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nnz cannot be greater than block row length: local row %" PetscInt_FMT " value %" PetscInt_FMT " block rowlength %" PetscInt_FMT, i, nnz[i], nbs);
150149b5e25fSSatish Balay     }
150249b5e25fSSatish Balay   }
150349b5e25fSSatish Balay 
1504db4efbfdSBarry Smith   B->ops->mult             = MatMult_SeqSBAIJ_N;
1505db4efbfdSBarry Smith   B->ops->multadd          = MatMultAdd_SeqSBAIJ_N;
1506db4efbfdSBarry Smith   B->ops->multtranspose    = MatMult_SeqSBAIJ_N;
1507db4efbfdSBarry Smith   B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N;
150826fbe8dcSKarl Rupp 
15099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL));
151049b5e25fSSatish Balay   if (!flg) {
151149b5e25fSSatish Balay     switch (bs) {
151249b5e25fSSatish Balay     case 1:
151349b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_1;
151449b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_1;
1515431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_1;
1516431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1;
151749b5e25fSSatish Balay       break;
151849b5e25fSSatish Balay     case 2:
151949b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_2;
152049b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_2;
1521431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_2;
1522431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2;
152349b5e25fSSatish Balay       break;
152449b5e25fSSatish Balay     case 3:
152549b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_3;
152649b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_3;
1527431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_3;
1528431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3;
152949b5e25fSSatish Balay       break;
153049b5e25fSSatish Balay     case 4:
153149b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_4;
153249b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_4;
1533431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_4;
1534431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4;
153549b5e25fSSatish Balay       break;
153649b5e25fSSatish Balay     case 5:
153749b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_5;
153849b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_5;
1539431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_5;
1540431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5;
154149b5e25fSSatish Balay       break;
154249b5e25fSSatish Balay     case 6:
154349b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_6;
154449b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_6;
1545431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_6;
1546431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6;
154749b5e25fSSatish Balay       break;
154849b5e25fSSatish Balay     case 7:
1549de53e5efSHong Zhang       B->ops->mult             = MatMult_SeqSBAIJ_7;
155049b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_7;
1551431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_7;
1552431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7;
155349b5e25fSSatish Balay       break;
155449b5e25fSSatish Balay     }
155549b5e25fSSatish Balay   }
155649b5e25fSSatish Balay 
155749b5e25fSSatish Balay   b->mbs = mbs;
15584dcd73b1SHong Zhang   b->nbs = nbs;
1559ab93d7beSBarry Smith   if (!skipallocation) {
15602ee49352SLisandro Dalcin     if (!b->imax) {
15619566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(mbs, &b->imax, mbs, &b->ilen));
156226fbe8dcSKarl Rupp 
1563c760cd28SBarry Smith       b->free_imax_ilen = PETSC_TRUE;
15642ee49352SLisandro Dalcin     }
156549b5e25fSSatish Balay     if (!nnz) {
1566435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
156749b5e25fSSatish Balay       else if (nz <= 0) nz = 1;
15685d2a9ed1SStefano Zampini       nz = PetscMin(nbs, nz);
156926fbe8dcSKarl Rupp       for (i = 0; i < mbs; i++) b->imax[i] = nz;
15709566063dSJacob Faibussowitsch       PetscCall(PetscIntMultError(nz, mbs, &nz));
157149b5e25fSSatish Balay     } else {
1572c73702f5SBarry Smith       PetscInt64 nz64 = 0;
15739371c9d4SSatish Balay       for (i = 0; i < mbs; i++) {
15749371c9d4SSatish Balay         b->imax[i] = nnz[i];
15759371c9d4SSatish Balay         nz64 += nnz[i];
15769371c9d4SSatish Balay       }
15779566063dSJacob Faibussowitsch       PetscCall(PetscIntCast(nz64, &nz));
157849b5e25fSSatish Balay     }
15792ee49352SLisandro Dalcin     /* b->ilen will count nonzeros in each block row so far. */
158026fbe8dcSKarl Rupp     for (i = 0; i < mbs; i++) b->ilen[i] = 0;
15816c6c5352SBarry Smith     /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */
158249b5e25fSSatish Balay 
158349b5e25fSSatish Balay     /* allocate the matrix space */
15849566063dSJacob Faibussowitsch     PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i));
15859566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(bs2 * nz, &b->a, nz, &b->j, B->rmap->N + 1, &b->i));
15869566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->a, nz * bs2));
15879566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->j, nz));
158826fbe8dcSKarl Rupp 
158949b5e25fSSatish Balay     b->singlemalloc = PETSC_TRUE;
159049b5e25fSSatish Balay 
159149b5e25fSSatish Balay     /* pointer to beginning of each row */
1592e60cf9a0SBarry Smith     b->i[0] = 0;
159326fbe8dcSKarl Rupp     for (i = 1; i < mbs + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1];
159426fbe8dcSKarl Rupp 
1595e6b907acSBarry Smith     b->free_a  = PETSC_TRUE;
1596e6b907acSBarry Smith     b->free_ij = PETSC_TRUE;
1597e811da20SHong Zhang   } else {
1598e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
1599e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
1600ab93d7beSBarry Smith   }
160149b5e25fSSatish Balay 
160249b5e25fSSatish Balay   b->bs2     = bs2;
16036c6c5352SBarry Smith   b->nz      = 0;
1604b32cb4a7SJed Brown   b->maxnz   = nz;
1605f4259b30SLisandro Dalcin   b->inew    = NULL;
1606f4259b30SLisandro Dalcin   b->jnew    = NULL;
1607f4259b30SLisandro Dalcin   b->anew    = NULL;
1608f4259b30SLisandro Dalcin   b->a2anew  = NULL;
16091a3463dfSHong Zhang   b->permute = PETSC_FALSE;
1610cb7b82ddSBarry Smith 
1611cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
1612cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
16139566063dSJacob Faibussowitsch   if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
1614c464158bSHong Zhang   PetscFunctionReturn(0);
1615c464158bSHong Zhang }
1616153ea458SHong Zhang 
16179371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ(Mat B, PetscInt bs, const PetscInt ii[], const PetscInt jj[], const PetscScalar V[]) {
16180cd7f59aSBarry Smith   PetscInt     i, j, m, nz, anz, nz_max = 0, *nnz;
1619f4259b30SLisandro Dalcin   PetscScalar *values      = NULL;
162038f409ebSLisandro Dalcin   PetscBool    roworiented = ((Mat_SeqSBAIJ *)B->data)->roworiented;
16210cd7f59aSBarry Smith 
162238f409ebSLisandro Dalcin   PetscFunctionBegin;
162308401ef6SPierre Jolivet   PetscCheck(bs >= 1, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_OUTOFRANGE, "Invalid block size specified, must be positive but it is %" PetscInt_FMT, bs);
16249566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(B->rmap, bs));
16259566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(B->cmap, bs));
16269566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
16279566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
16289566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs));
162938f409ebSLisandro Dalcin   m = B->rmap->n / bs;
163038f409ebSLisandro Dalcin 
1631aed4548fSBarry Smith   PetscCheck(!ii[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ii[0] must be 0 but it is %" PetscInt_FMT, ii[0]);
16329566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &nnz));
163338f409ebSLisandro Dalcin   for (i = 0; i < m; i++) {
163438f409ebSLisandro Dalcin     nz = ii[i + 1] - ii[i];
163508401ef6SPierre Jolivet     PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz);
16360cd7f59aSBarry Smith     anz = 0;
16370cd7f59aSBarry Smith     for (j = 0; j < nz; j++) {
16380cd7f59aSBarry Smith       /* count only values on the diagonal or above */
16390cd7f59aSBarry Smith       if (jj[ii[i] + j] >= i) {
16400cd7f59aSBarry Smith         anz = nz - j;
16410cd7f59aSBarry Smith         break;
16420cd7f59aSBarry Smith       }
16430cd7f59aSBarry Smith     }
16440cd7f59aSBarry Smith     nz_max = PetscMax(nz_max, anz);
16450cd7f59aSBarry Smith     nnz[i] = anz;
164638f409ebSLisandro Dalcin   }
16479566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz));
16489566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
164938f409ebSLisandro Dalcin 
165038f409ebSLisandro Dalcin   values = (PetscScalar *)V;
165148a46eb9SPierre Jolivet   if (!values) PetscCall(PetscCalloc1(bs * bs * nz_max, &values));
165238f409ebSLisandro Dalcin   for (i = 0; i < m; i++) {
165338f409ebSLisandro Dalcin     PetscInt        ncols = ii[i + 1] - ii[i];
165438f409ebSLisandro Dalcin     const PetscInt *icols = jj + ii[i];
165538f409ebSLisandro Dalcin     if (!roworiented || bs == 1) {
165638f409ebSLisandro Dalcin       const PetscScalar *svals = values + (V ? (bs * bs * ii[i]) : 0);
16579566063dSJacob Faibussowitsch       PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, ncols, icols, svals, INSERT_VALUES));
165838f409ebSLisandro Dalcin     } else {
165938f409ebSLisandro Dalcin       for (j = 0; j < ncols; j++) {
166038f409ebSLisandro Dalcin         const PetscScalar *svals = values + (V ? (bs * bs * (ii[i] + j)) : 0);
16619566063dSJacob Faibussowitsch         PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, 1, &icols[j], svals, INSERT_VALUES));
166238f409ebSLisandro Dalcin       }
166338f409ebSLisandro Dalcin     }
166438f409ebSLisandro Dalcin   }
16659566063dSJacob Faibussowitsch   if (!V) PetscCall(PetscFree(values));
16669566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
16679566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
16689566063dSJacob Faibussowitsch   PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
166938f409ebSLisandro Dalcin   PetscFunctionReturn(0);
167038f409ebSLisandro Dalcin }
167138f409ebSLisandro Dalcin 
1672db4efbfdSBarry Smith /*
1673db4efbfdSBarry Smith    This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization
1674db4efbfdSBarry Smith */
16759371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetNumericFactorization_inplace(Mat B, PetscBool natural) {
1676ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
1677db4efbfdSBarry Smith   PetscInt  bs  = B->rmap->bs;
1678db4efbfdSBarry Smith 
1679db4efbfdSBarry Smith   PetscFunctionBegin;
16809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL));
1681db4efbfdSBarry Smith   if (flg) bs = 8;
1682db4efbfdSBarry Smith 
1683db4efbfdSBarry Smith   if (!natural) {
1684db4efbfdSBarry Smith     switch (bs) {
16859371c9d4SSatish Balay     case 1: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_inplace; break;
16869371c9d4SSatish Balay     case 2: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2; break;
16879371c9d4SSatish Balay     case 3: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3; break;
16889371c9d4SSatish Balay     case 4: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4; break;
16899371c9d4SSatish Balay     case 5: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5; break;
16909371c9d4SSatish Balay     case 6: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6; break;
16919371c9d4SSatish Balay     case 7: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7; break;
16929371c9d4SSatish Balay     default: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N; break;
1693db4efbfdSBarry Smith     }
1694db4efbfdSBarry Smith   } else {
1695db4efbfdSBarry Smith     switch (bs) {
16969371c9d4SSatish Balay     case 1: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering_inplace; break;
16979371c9d4SSatish Balay     case 2: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering; break;
16989371c9d4SSatish Balay     case 3: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering; break;
16999371c9d4SSatish Balay     case 4: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering; break;
17009371c9d4SSatish Balay     case 5: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering; break;
17019371c9d4SSatish Balay     case 6: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering; break;
17029371c9d4SSatish Balay     case 7: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering; break;
17039371c9d4SSatish Balay     default: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering; break;
1704db4efbfdSBarry Smith     }
1705db4efbfdSBarry Smith   }
1706db4efbfdSBarry Smith   PetscFunctionReturn(0);
1707db4efbfdSBarry Smith }
1708db4efbfdSBarry Smith 
1709cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType, MatReuse, Mat *);
1710cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType, MatReuse, Mat *);
17119371c9d4SSatish Balay static PetscErrorCode       MatFactorGetSolverType_petsc(Mat A, MatSolverType *type) {
17124ac6704cSBarry Smith         PetscFunctionBegin;
17134ac6704cSBarry Smith         *type = MATSOLVERPETSC;
17144ac6704cSBarry Smith         PetscFunctionReturn(0);
17154ac6704cSBarry Smith }
1716d769727bSBarry Smith 
17179371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A, MatFactorType ftype, Mat *B) {
1718d0f46423SBarry Smith   PetscInt n = A->rmap->n;
17195c9eb25fSBarry Smith 
17205c9eb25fSBarry Smith   PetscFunctionBegin;
17210e92d65fSHong Zhang #if defined(PETSC_USE_COMPLEX)
1722b94d7dedSBarry Smith   PetscCheck(A->hermitian != PETSC_BOOL3_TRUE || A->symmetric == PETSC_BOOL3_TRUE || (ftype != MAT_FACTOR_CHOLESKY && ftype != MAT_FACTOR_ICC), PETSC_COMM_SELF, PETSC_ERR_SUP, "Hermitian CHOLESKY or ICC Factor is not supported");
17230e92d65fSHong Zhang #endif
1724eb1ec7c1SStefano Zampini 
17259566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B));
17269566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*B, n, n, n, n));
17275c9eb25fSBarry Smith   if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
17289566063dSJacob Faibussowitsch     PetscCall(MatSetType(*B, MATSEQSBAIJ));
17299566063dSJacob Faibussowitsch     PetscCall(MatSeqSBAIJSetPreallocation(*B, A->rmap->bs, MAT_SKIP_ALLOCATION, NULL));
173026fbe8dcSKarl Rupp 
17317b056e98SHong Zhang     (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ;
1732c6d0d4f0SHong Zhang     (*B)->ops->iccfactorsymbolic      = MatICCFactorSymbolic_SeqSBAIJ;
17339566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_CHOLESKY]));
17349566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_ICC]));
1735e32f2f54SBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Factor type not supported");
173600c67f3bSHong Zhang 
1737d5f3da31SBarry Smith   (*B)->factortype     = ftype;
1738f73b0415SBarry Smith   (*B)->canuseordering = PETSC_TRUE;
17399566063dSJacob Faibussowitsch   PetscCall(PetscFree((*B)->solvertype));
17409566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*B)->solvertype));
17419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)*B, "MatFactorGetSolverType_C", MatFactorGetSolverType_petsc));
17425c9eb25fSBarry Smith   PetscFunctionReturn(0);
17435c9eb25fSBarry Smith }
17445c9eb25fSBarry Smith 
17458397e458SBarry Smith /*@C
174611a5261eSBarry Smith    MatSeqSBAIJGetArray - gives access to the array where the data for a `MATSEQSBAIJ` matrix is stored
17478397e458SBarry Smith 
17488397e458SBarry Smith    Not Collective
17498397e458SBarry Smith 
17508397e458SBarry Smith    Input Parameter:
175111a5261eSBarry Smith .  mat - a `MATSEQSBAIJ` matrix
17528397e458SBarry Smith 
17538397e458SBarry Smith    Output Parameter:
17548397e458SBarry Smith .   array - pointer to the data
17558397e458SBarry Smith 
17568397e458SBarry Smith    Level: intermediate
17578397e458SBarry Smith 
175811a5261eSBarry Smith .seealso: `MATSEQSBAIJ`, `MatSeqSBAIJRestoreArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`
17598397e458SBarry Smith @*/
17609371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJGetArray(Mat A, PetscScalar **array) {
17618397e458SBarry Smith   PetscFunctionBegin;
1762cac4c232SBarry Smith   PetscUseMethod(A, "MatSeqSBAIJGetArray_C", (Mat, PetscScalar **), (A, array));
17638397e458SBarry Smith   PetscFunctionReturn(0);
17648397e458SBarry Smith }
17658397e458SBarry Smith 
17668397e458SBarry Smith /*@C
176711a5261eSBarry Smith    MatSeqSBAIJRestoreArray - returns access to the array where the data for a `MATSEQSBAIJ` matrix is stored obtained by `MatSeqSBAIJGetArray()`
17688397e458SBarry Smith 
17698397e458SBarry Smith    Not Collective
17708397e458SBarry Smith 
17718397e458SBarry Smith    Input Parameters:
1772a2b725a8SWilliam Gropp +  mat - a MATSEQSBAIJ matrix
1773a2b725a8SWilliam Gropp -  array - pointer to the data
17748397e458SBarry Smith 
17758397e458SBarry Smith    Level: intermediate
17768397e458SBarry Smith 
177711a5261eSBarry Smith .seealso: `MATSEQSBAIJ`, `MatSeqSBAIJGetArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`
17788397e458SBarry Smith @*/
17799371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJRestoreArray(Mat A, PetscScalar **array) {
17808397e458SBarry Smith   PetscFunctionBegin;
1781cac4c232SBarry Smith   PetscUseMethod(A, "MatSeqSBAIJRestoreArray_C", (Mat, PetscScalar **), (A, array));
17828397e458SBarry Smith   PetscFunctionReturn(0);
17838397e458SBarry Smith }
17848397e458SBarry Smith 
17850bad9183SKris Buschelman /*MC
1786fafad747SKris Buschelman   MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices,
17870bad9183SKris Buschelman   based on block compressed sparse row format.  Only the upper triangular portion of the matrix is stored.
17880bad9183SKris Buschelman 
1789828413b8SBarry Smith   For complex numbers by default this matrix is symmetric, NOT Hermitian symmetric. To make it Hermitian symmetric you
179011a5261eSBarry Smith   can call `MatSetOption`(`Mat`, `MAT_HERMITIAN`).
1791828413b8SBarry Smith 
17920bad9183SKris Buschelman   Options Database Keys:
179311a5261eSBarry Smith   . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to `MatSetFromOptions()`
17940bad9183SKris Buschelman 
179595452b02SPatrick Sanan   Notes:
179695452b02SPatrick Sanan     By default if you insert values into the lower triangular part of the matrix they are simply ignored (since they are not
179711a5261eSBarry Smith      stored and it is assumed they symmetric to the upper triangular). If you call `MatSetOption`(`Mat`,`MAT_IGNORE_LOWER_TRIANGULAR`,`PETSC_FALSE`) or use
179871dad5bbSBarry Smith      the options database -mat_ignore_lower_triangular false it will generate an error if you try to set a value in the lower triangular portion.
179971dad5bbSBarry Smith 
1800476417e5SBarry Smith     The number of rows in the matrix must be less than or equal to the number of columns
180171dad5bbSBarry Smith 
18020bad9183SKris Buschelman   Level: beginner
18030bad9183SKris Buschelman 
180411a5261eSBarry Smith   .seealso: `MATSEQSBAIJ`, `MatCreateSeqSBAIJ()`, `MatType`, `MATMPISBAIJ`
18050bad9183SKris Buschelman M*/
18069371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_SeqSBAIJ(Mat B) {
1807a23d5eceSKris Buschelman   Mat_SeqSBAIJ *b;
180813f74950SBarry Smith   PetscMPIInt   size;
1809ace3abfcSBarry Smith   PetscBool     no_unroll = PETSC_FALSE, no_inode = PETSC_FALSE;
1810a23d5eceSKris Buschelman 
1811a23d5eceSKris Buschelman   PetscFunctionBegin;
18129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
181308401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
1814a23d5eceSKris Buschelman 
1815*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
1816a23d5eceSKris Buschelman   B->data = (void *)b;
18179566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(B->ops, &MatOps_Values, sizeof(struct _MatOps)));
181826fbe8dcSKarl Rupp 
1819a23d5eceSKris Buschelman   B->ops->destroy    = MatDestroy_SeqSBAIJ;
1820a23d5eceSKris Buschelman   B->ops->view       = MatView_SeqSBAIJ;
1821f4259b30SLisandro Dalcin   b->row             = NULL;
1822f4259b30SLisandro Dalcin   b->icol            = NULL;
1823a23d5eceSKris Buschelman   b->reallocs        = 0;
1824f4259b30SLisandro Dalcin   b->saved_values    = NULL;
18250def2e27SBarry Smith   b->inode.limit     = 5;
18260def2e27SBarry Smith   b->inode.max_limit = 5;
1827a23d5eceSKris Buschelman 
1828a23d5eceSKris Buschelman   b->roworiented        = PETSC_TRUE;
1829a23d5eceSKris Buschelman   b->nonew              = 0;
1830f4259b30SLisandro Dalcin   b->diag               = NULL;
1831f4259b30SLisandro Dalcin   b->solve_work         = NULL;
1832f4259b30SLisandro Dalcin   b->mult_work          = NULL;
1833f4259b30SLisandro Dalcin   B->spptr              = NULL;
1834f2cbd3d5SJed Brown   B->info.nz_unneeded   = (PetscReal)b->maxnz * b->bs2;
1835a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
1836a23d5eceSKris Buschelman 
1837f4259b30SLisandro Dalcin   b->inew    = NULL;
1838f4259b30SLisandro Dalcin   b->jnew    = NULL;
1839f4259b30SLisandro Dalcin   b->anew    = NULL;
1840f4259b30SLisandro Dalcin   b->a2anew  = NULL;
1841a23d5eceSKris Buschelman   b->permute = PETSC_FALSE;
1842a23d5eceSKris Buschelman 
184371dad5bbSBarry Smith   b->ignore_ltriangular = PETSC_TRUE;
184426fbe8dcSKarl Rupp 
18459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_ignore_lower_triangular", &b->ignore_ltriangular, NULL));
1846941593c8SHong Zhang 
1847f5edf698SHong Zhang   b->getrow_utriangular = PETSC_FALSE;
184826fbe8dcSKarl Rupp 
18499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_getrow_uppertriangular", &b->getrow_utriangular, NULL));
1850f5edf698SHong Zhang 
18519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJGetArray_C", MatSeqSBAIJGetArray_SeqSBAIJ));
18529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJRestoreArray_C", MatSeqSBAIJRestoreArray_SeqSBAIJ));
18539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqSBAIJ));
18549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqSBAIJ));
18559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetColumnIndices_C", MatSeqSBAIJSetColumnIndices_SeqSBAIJ));
18569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqaij_C", MatConvert_SeqSBAIJ_SeqAIJ));
18579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqbaij_C", MatConvert_SeqSBAIJ_SeqBAIJ));
18589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocation_C", MatSeqSBAIJSetPreallocation_SeqSBAIJ));
18599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocationCSR_C", MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ));
18606214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
18619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_elemental_C", MatConvert_SeqSBAIJ_Elemental));
18626214f412SHong Zhang #endif
1863d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
18649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_scalapack_C", MatConvert_SBAIJ_ScaLAPACK));
1865d24d4204SJose E. Roman #endif
186623ce1328SBarry Smith 
1867b94d7dedSBarry Smith   B->symmetry_eternal            = PETSC_TRUE;
1868b94d7dedSBarry Smith   B->structural_symmetry_eternal = PETSC_TRUE;
1869b94d7dedSBarry Smith   B->symmetric                   = PETSC_BOOL3_TRUE;
1870b94d7dedSBarry Smith   B->structurally_symmetric      = PETSC_BOOL3_TRUE;
1871eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1872b94d7dedSBarry Smith   B->hermitian = PETSC_BOOL3_FALSE;
1873eb1ec7c1SStefano Zampini #else
1874b94d7dedSBarry Smith   B->hermitian = PETSC_BOOL3_TRUE;
1875eb1ec7c1SStefano Zampini #endif
187613647f61SHong Zhang 
18779566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQSBAIJ));
18780def2e27SBarry Smith 
1879d0609cedSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)B), ((PetscObject)B)->prefix, "Options for SEQSBAIJ matrix", "Mat");
18809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_no_unroll", "Do not optimize for inodes (slower)", NULL, no_unroll, &no_unroll, NULL));
188148a46eb9SPierre Jolivet   if (no_unroll) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_unroll\n"));
18829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_no_inode", "Do not optimize for inodes (slower)", NULL, no_inode, &no_inode, NULL));
18839566063dSJacob Faibussowitsch   if (no_inode) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_inode\n"));
18849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-mat_inode_limit", "Do not use inodes larger then this value", NULL, b->inode.limit, &b->inode.limit, NULL));
1885d0609cedSBarry Smith   PetscOptionsEnd();
1886ace3abfcSBarry Smith   b->inode.use = (PetscBool)(!(no_unroll || no_inode));
18870def2e27SBarry Smith   if (b->inode.limit > b->inode.max_limit) b->inode.limit = b->inode.max_limit;
1888a23d5eceSKris Buschelman   PetscFunctionReturn(0);
1889a23d5eceSKris Buschelman }
1890a23d5eceSKris Buschelman 
1891a23d5eceSKris Buschelman /*@C
1892a23d5eceSKris Buschelman    MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block
189311a5261eSBarry Smith    compressed row) `MATSEQSBAIJ` format.  For good matrix assembly performance the
1894a23d5eceSKris Buschelman    user should preallocate the matrix storage by setting the parameter nz
1895a23d5eceSKris Buschelman    (or the array nnz).  By setting these parameters accurately, performance
1896a23d5eceSKris Buschelman    during matrix assembly can be increased by more than a factor of 50.
1897a23d5eceSKris Buschelman 
1898a23d5eceSKris Buschelman    Collective on Mat
1899a23d5eceSKris Buschelman 
1900a23d5eceSKris Buschelman    Input Parameters:
19011c4f3114SJed Brown +  B - the symmetric matrix
190211a5261eSBarry Smith .  bs - size of block, the blocks are ALWAYS square. One can use `MatSetBlockSizes()` to set a different row and column blocksize but the row
190311a5261eSBarry Smith           blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with `MatCreateVecs()`
1904a23d5eceSKris Buschelman .  nz - number of block nonzeros per block row (same for all rows)
1905a23d5eceSKris Buschelman -  nnz - array containing the number of block nonzeros in the upper triangular plus
19060298fd71SBarry Smith          diagonal portion of each block (possibly different for each block row) or NULL
1907a23d5eceSKris Buschelman 
1908a23d5eceSKris Buschelman    Options Database Keys:
1909a2b725a8SWilliam Gropp +   -mat_no_unroll - uses code that does not unroll the loops in the
1910a23d5eceSKris Buschelman                      block calculations (much slower)
1911a2b725a8SWilliam Gropp -   -mat_block_size - size of the blocks to use (only works if a negative bs is passed in
1912a23d5eceSKris Buschelman 
1913a23d5eceSKris Buschelman    Level: intermediate
1914a23d5eceSKris Buschelman 
1915a23d5eceSKris Buschelman    Notes:
1916a23d5eceSKris Buschelman    Specify the preallocated storage with either nz or nnz (not both).
191711a5261eSBarry Smith    Set nz = `PETSC_DEFAULT` and nnz = NULL for PETSc to control dynamic memory
1918651615e1SBarry Smith    allocation.  See [Sparse Matrices](sec_matsparse) for details.
1919a23d5eceSKris Buschelman 
192011a5261eSBarry Smith    You can call `MatGetInfo()` to get information on how effective the preallocation was;
1921aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
1922aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
1923aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
1924aa95bbe8SBarry Smith 
192549a6f317SBarry Smith    If the nnz parameter is given then the nz parameter is ignored
192649a6f317SBarry Smith 
1927651615e1SBarry Smith .seealso: [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()`
1928a23d5eceSKris Buschelman @*/
19299371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetPreallocation(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[]) {
1930a23d5eceSKris Buschelman   PetscFunctionBegin;
19316ba663aaSJed Brown   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
19326ba663aaSJed Brown   PetscValidType(B, 1);
19336ba663aaSJed Brown   PetscValidLogicalCollectiveInt(B, bs, 2);
1934cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqSBAIJSetPreallocation_C", (Mat, PetscInt, PetscInt, const PetscInt[]), (B, bs, nz, nnz));
1935a23d5eceSKris Buschelman   PetscFunctionReturn(0);
1936a23d5eceSKris Buschelman }
193749b5e25fSSatish Balay 
193838f409ebSLisandro Dalcin /*@C
193911a5261eSBarry Smith    MatSeqSBAIJSetPreallocationCSR - Creates a sparse parallel matrix in `MATSEQSBAIJ` format using the given nonzero structure and (optional) numerical values
194038f409ebSLisandro Dalcin 
194138f409ebSLisandro Dalcin    Input Parameters:
19421c4f3114SJed Brown +  B - the matrix
1943eab78319SHong Zhang .  bs - size of block, the blocks are ALWAYS square.
194438f409ebSLisandro Dalcin .  i - the indices into j for the start of each local row (starts with zero)
194538f409ebSLisandro Dalcin .  j - the column indices for each local row (starts with zero) these must be sorted for each row
194638f409ebSLisandro Dalcin -  v - optional values in the matrix
194738f409ebSLisandro Dalcin 
1948664954b6SBarry Smith    Level: advanced
194938f409ebSLisandro Dalcin 
195038f409ebSLisandro Dalcin    Notes:
195111a5261eSBarry Smith    The order of the entries in values is specified by the `MatOption` `MAT_ROW_ORIENTED`.  For example, C programs
195211a5261eSBarry Smith    may want to use the default `MAT_ROW_ORIENTED` = `PETSC_TRUE` and use an array v[nnz][bs][bs] where the second index is
195338f409ebSLisandro Dalcin    over rows within a block and the last index is over columns within a block row.  Fortran programs will likely set
195411a5261eSBarry Smith    `MAT_ROW_ORIENTED` = `PETSC_FALSE` and use a Fortran array v(bs,bs,nnz) in which the first index is over rows within a
195538f409ebSLisandro Dalcin    block column and the second index is over columns within a block.
195638f409ebSLisandro Dalcin 
195750c5228eSBarry Smith    Any entries below the diagonal are ignored
19580cd7f59aSBarry Smith 
19590cd7f59aSBarry Smith    Though this routine has Preallocation() in the name it also sets the exact nonzero locations of the matrix entries
19600cd7f59aSBarry Smith    and usually the numerical values as well
1961664954b6SBarry Smith 
196211a5261eSBarry Smith .seealso: `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqSBAIJ()`, `MatSetValuesBlocked()`, `MatSeqSBAIJSetPreallocation()`, `MATSEQSBAIJ`
196338f409ebSLisandro Dalcin @*/
19649371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetPreallocationCSR(Mat B, PetscInt bs, const PetscInt i[], const PetscInt j[], const PetscScalar v[]) {
196538f409ebSLisandro Dalcin   PetscFunctionBegin;
196638f409ebSLisandro Dalcin   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
196738f409ebSLisandro Dalcin   PetscValidType(B, 1);
196838f409ebSLisandro Dalcin   PetscValidLogicalCollectiveInt(B, bs, 2);
1969cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqSBAIJSetPreallocationCSR_C", (Mat, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, bs, i, j, v));
197038f409ebSLisandro Dalcin   PetscFunctionReturn(0);
197138f409ebSLisandro Dalcin }
197238f409ebSLisandro Dalcin 
1973c464158bSHong Zhang /*@C
1974c464158bSHong Zhang    MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in block AIJ (block
197511a5261eSBarry Smith    compressed row) `MATSEQSBAIJ` format.  For good matrix assembly performance the
1976c464158bSHong Zhang    user should preallocate the matrix storage by setting the parameter nz
1977c464158bSHong Zhang    (or the array nnz).  By setting these parameters accurately, performance
1978c464158bSHong Zhang    during matrix assembly can be increased by more than a factor of 50.
197949b5e25fSSatish Balay 
1980d083f849SBarry Smith    Collective
1981c464158bSHong Zhang 
1982c464158bSHong Zhang    Input Parameters:
198311a5261eSBarry Smith +  comm - MPI communicator, set to `PETSC_COMM_SELF`
198411a5261eSBarry Smith .  bs - size of block, the blocks are ALWAYS square. One can use `MatSetBlockSizes()` to set a different row and column blocksize but the row
1985bb7ae925SBarry Smith           blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with MatCreateVecs()
1986c464158bSHong Zhang .  m - number of rows, or number of columns
1987c464158bSHong Zhang .  nz - number of block nonzeros per block row (same for all rows)
1988744e8345SSatish Balay -  nnz - array containing the number of block nonzeros in the upper triangular plus
19890298fd71SBarry Smith          diagonal portion of each block (possibly different for each block row) or NULL
1990c464158bSHong Zhang 
1991c464158bSHong Zhang    Output Parameter:
1992c464158bSHong Zhang .  A - the symmetric matrix
1993c464158bSHong Zhang 
1994c464158bSHong Zhang    Options Database Keys:
1995a2b725a8SWilliam Gropp +   -mat_no_unroll - uses code that does not unroll the loops in the
1996c464158bSHong Zhang                      block calculations (much slower)
1997a2b725a8SWilliam Gropp -   -mat_block_size - size of the blocks to use
1998c464158bSHong Zhang 
1999c464158bSHong Zhang    Level: intermediate
2000c464158bSHong Zhang 
200111a5261eSBarry Smith    It is recommended that one use the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`,
2002f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
200311a5261eSBarry Smith    [MatXXXXSetPreallocation() is, for example, `MatSeqAIJSetPreallocation()`]
2004175b88e8SBarry Smith 
2005c464158bSHong Zhang    Notes:
20066d6d819aSHong Zhang    The number of rows and columns must be divisible by blocksize.
20076d6d819aSHong Zhang    This matrix type does not support complex Hermitian operation.
2008c464158bSHong Zhang 
2009c464158bSHong Zhang    Specify the preallocated storage with either nz or nnz (not both).
201011a5261eSBarry Smith    Set nz = `PETSC_DEFAULT` and nnz = NULL for PETSc to control dynamic memory
2011651615e1SBarry Smith    allocation.  See [Sparse Matrices](sec_matsparse) for details.
2012c464158bSHong Zhang 
201349a6f317SBarry Smith    If the nnz parameter is given then the nz parameter is ignored
201449a6f317SBarry Smith 
2015651615e1SBarry Smith .seealso: [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()`
2016c464158bSHong Zhang @*/
20179371c9d4SSatish Balay PetscErrorCode MatCreateSeqSBAIJ(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A) {
2018c464158bSHong Zhang   PetscFunctionBegin;
20199566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
20209566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
20219566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQSBAIJ));
20229566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*A, bs, nz, (PetscInt *)nnz));
202349b5e25fSSatish Balay   PetscFunctionReturn(0);
202449b5e25fSSatish Balay }
202549b5e25fSSatish Balay 
20269371c9d4SSatish Balay PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B) {
202749b5e25fSSatish Balay   Mat           C;
202849b5e25fSSatish Balay   Mat_SeqSBAIJ *c, *a  = (Mat_SeqSBAIJ *)A->data;
2029b40805acSSatish Balay   PetscInt      i, mbs = a->mbs, nz = a->nz, bs2 = a->bs2;
203049b5e25fSSatish Balay 
203149b5e25fSSatish Balay   PetscFunctionBegin;
203208401ef6SPierre Jolivet   PetscCheck(a->i[mbs] == nz, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupt matrix");
203349b5e25fSSatish Balay 
2034f4259b30SLisandro Dalcin   *B = NULL;
20359566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
20369566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, A->rmap->N, A->cmap->n, A->rmap->N, A->cmap->n));
20379566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(C, A, A));
20389566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATSEQSBAIJ));
2039692f9cbeSHong Zhang   c = (Mat_SeqSBAIJ *)C->data;
2040692f9cbeSHong Zhang 
2041273d9f13SBarry Smith   C->preallocated       = PETSC_TRUE;
2042d5f3da31SBarry Smith   C->factortype         = A->factortype;
2043f4259b30SLisandro Dalcin   c->row                = NULL;
2044f4259b30SLisandro Dalcin   c->icol               = NULL;
2045f4259b30SLisandro Dalcin   c->saved_values       = NULL;
2046a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
204749b5e25fSSatish Balay   C->assembled          = PETSC_TRUE;
204849b5e25fSSatish Balay 
20499566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->rmap, &C->rmap));
20509566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap, &C->cmap));
205149b5e25fSSatish Balay   c->bs2 = a->bs2;
205249b5e25fSSatish Balay   c->mbs = a->mbs;
205349b5e25fSSatish Balay   c->nbs = a->nbs;
205449b5e25fSSatish Balay 
2055c760cd28SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2056c760cd28SBarry Smith     c->imax           = a->imax;
2057c760cd28SBarry Smith     c->ilen           = a->ilen;
2058c760cd28SBarry Smith     c->free_imax_ilen = PETSC_FALSE;
2059c760cd28SBarry Smith   } else {
20609566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2((mbs + 1), &c->imax, (mbs + 1), &c->ilen));
206149b5e25fSSatish Balay     for (i = 0; i < mbs; i++) {
206249b5e25fSSatish Balay       c->imax[i] = a->imax[i];
206349b5e25fSSatish Balay       c->ilen[i] = a->ilen[i];
206449b5e25fSSatish Balay     }
2065c760cd28SBarry Smith     c->free_imax_ilen = PETSC_TRUE;
2066c760cd28SBarry Smith   }
206749b5e25fSSatish Balay 
206849b5e25fSSatish Balay   /* allocate the matrix space */
20694da8f245SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
20709566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(bs2 * nz, &c->a));
207144e1c64aSLisandro Dalcin     c->i            = a->i;
207244e1c64aSLisandro Dalcin     c->j            = a->j;
20734da8f245SBarry Smith     c->singlemalloc = PETSC_FALSE;
207444e1c64aSLisandro Dalcin     c->free_a       = PETSC_TRUE;
20754da8f245SBarry Smith     c->free_ij      = PETSC_FALSE;
20764da8f245SBarry Smith     c->parent       = A;
20779566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)A));
20789566063dSJacob Faibussowitsch     PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
20799566063dSJacob Faibussowitsch     PetscCall(MatSetOption(C, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
20804da8f245SBarry Smith   } else {
20819566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(bs2 * nz, &c->a, nz, &c->j, mbs + 1, &c->i));
20829566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(c->i, a->i, mbs + 1));
20834da8f245SBarry Smith     c->singlemalloc = PETSC_TRUE;
208444e1c64aSLisandro Dalcin     c->free_a       = PETSC_TRUE;
20854da8f245SBarry Smith     c->free_ij      = PETSC_TRUE;
20864da8f245SBarry Smith   }
208749b5e25fSSatish Balay   if (mbs > 0) {
208848a46eb9SPierre Jolivet     if (cpvalues != MAT_SHARE_NONZERO_PATTERN) PetscCall(PetscArraycpy(c->j, a->j, nz));
208949b5e25fSSatish Balay     if (cpvalues == MAT_COPY_VALUES) {
20909566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->a, a->a, bs2 * nz));
209149b5e25fSSatish Balay     } else {
20929566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(c->a, bs2 * nz));
209349b5e25fSSatish Balay     }
2094a1c3900fSBarry Smith     if (a->jshort) {
209544e1c64aSLisandro Dalcin       /* cannot share jshort, it is reallocated in MatAssemblyEnd_SeqSBAIJ() */
209644e1c64aSLisandro Dalcin       /* if the parent matrix is reassembled, this child matrix will never notice */
20979566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz, &c->jshort));
20989566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->jshort, a->jshort, nz));
209926fbe8dcSKarl Rupp 
21004da8f245SBarry Smith       c->free_jshort = PETSC_TRUE;
21014da8f245SBarry Smith     }
2102a1c3900fSBarry Smith   }
210349b5e25fSSatish Balay 
210449b5e25fSSatish Balay   c->roworiented = a->roworiented;
210549b5e25fSSatish Balay   c->nonew       = a->nonew;
210649b5e25fSSatish Balay 
210749b5e25fSSatish Balay   if (a->diag) {
2108c760cd28SBarry Smith     if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2109c760cd28SBarry Smith       c->diag      = a->diag;
2110c760cd28SBarry Smith       c->free_diag = PETSC_FALSE;
2111c760cd28SBarry Smith     } else {
21129566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mbs, &c->diag));
211326fbe8dcSKarl Rupp       for (i = 0; i < mbs; i++) c->diag[i] = a->diag[i];
2114c760cd28SBarry Smith       c->free_diag = PETSC_TRUE;
2115c760cd28SBarry Smith     }
211644e1c64aSLisandro Dalcin   }
21176c6c5352SBarry Smith   c->nz         = a->nz;
2118f2cbd3d5SJed Brown   c->maxnz      = a->nz; /* Since we allocate exactly the right amount */
2119f4259b30SLisandro Dalcin   c->solve_work = NULL;
2120f4259b30SLisandro Dalcin   c->mult_work  = NULL;
212126fbe8dcSKarl Rupp 
212249b5e25fSSatish Balay   *B = C;
21239566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist));
212449b5e25fSSatish Balay   PetscFunctionReturn(0);
212549b5e25fSSatish Balay }
212649b5e25fSSatish Balay 
2127618cc2edSLisandro Dalcin /* Used for both SeqBAIJ and SeqSBAIJ matrices */
2128618cc2edSLisandro Dalcin #define MatLoad_SeqSBAIJ_Binary MatLoad_SeqBAIJ_Binary
2129618cc2edSLisandro Dalcin 
21309371c9d4SSatish Balay PetscErrorCode MatLoad_SeqSBAIJ(Mat mat, PetscViewer viewer) {
21317f489da9SVaclav Hapla   PetscBool isbinary;
21322f480046SShri Abhyankar 
21332f480046SShri Abhyankar   PetscFunctionBegin;
21349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
213528b400f6SJacob Faibussowitsch   PetscCheck(isbinary, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Viewer type %s not yet supported for reading %s matrices", ((PetscObject)viewer)->type_name, ((PetscObject)mat)->type_name);
21369566063dSJacob Faibussowitsch   PetscCall(MatLoad_SeqSBAIJ_Binary(mat, viewer));
21372f480046SShri Abhyankar   PetscFunctionReturn(0);
21382f480046SShri Abhyankar }
21392f480046SShri Abhyankar 
2140c75a6043SHong Zhang /*@
214111a5261eSBarry Smith      MatCreateSeqSBAIJWithArrays - Creates an sequential `MATSEQSBAIJ` matrix using matrix elements
2142c75a6043SHong Zhang               (upper triangular entries in CSR format) provided by the user.
2143c75a6043SHong Zhang 
2144d083f849SBarry Smith      Collective
2145c75a6043SHong Zhang 
2146c75a6043SHong Zhang    Input Parameters:
2147c75a6043SHong Zhang +  comm - must be an MPI communicator of size 1
2148c75a6043SHong Zhang .  bs - size of block
2149c75a6043SHong Zhang .  m - number of rows
2150c75a6043SHong Zhang .  n - number of columns
2151483a2f95SBarry Smith .  i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of block elements in that row block row of the matrix
2152c75a6043SHong Zhang .  j - column indices
2153c75a6043SHong Zhang -  a - matrix values
2154c75a6043SHong Zhang 
2155c75a6043SHong Zhang    Output Parameter:
2156c75a6043SHong Zhang .  mat - the matrix
2157c75a6043SHong Zhang 
2158dfb205c3SBarry Smith    Level: advanced
2159c75a6043SHong Zhang 
2160c75a6043SHong Zhang    Notes:
2161c75a6043SHong Zhang        The i, j, and a arrays are not copied by this routine, the user must free these arrays
2162c75a6043SHong Zhang     once the matrix is destroyed
2163c75a6043SHong Zhang 
2164c75a6043SHong Zhang        You cannot set new nonzero locations into this matrix, that will generate an error.
2165c75a6043SHong Zhang 
2166c75a6043SHong Zhang        The i and j indices are 0 based
2167c75a6043SHong Zhang 
216811a5261eSBarry Smith        When block size is greater than 1 the matrix values must be stored using the SBAIJ storage format (see the SBAIJ source code to determine this). For block size of 1
2169dfb205c3SBarry Smith        it is the regular CSR format excluding the lower triangular elements.
2170dfb205c3SBarry Smith 
217111a5261eSBarry Smith .seealso: `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSBAIJ()`, `MatCreateSeqSBAIJ()`
2172c75a6043SHong Zhang @*/
21739371c9d4SSatish Balay PetscErrorCode MatCreateSeqSBAIJWithArrays(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat) {
2174c75a6043SHong Zhang   PetscInt      ii;
2175c75a6043SHong Zhang   Mat_SeqSBAIJ *sbaij;
2176c75a6043SHong Zhang 
2177c75a6043SHong Zhang   PetscFunctionBegin;
217808401ef6SPierre Jolivet   PetscCheck(bs == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "block size %" PetscInt_FMT " > 1 is not supported yet", bs);
2179aed4548fSBarry Smith   PetscCheck(m == 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0");
2180c75a6043SHong Zhang 
21819566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, mat));
21829566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mat, m, n, m, n));
21839566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mat, MATSEQSBAIJ));
21849566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*mat, bs, MAT_SKIP_ALLOCATION, NULL));
2185c75a6043SHong Zhang   sbaij = (Mat_SeqSBAIJ *)(*mat)->data;
21869566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(m, &sbaij->imax, m, &sbaij->ilen));
2187c75a6043SHong Zhang 
2188c75a6043SHong Zhang   sbaij->i = i;
2189c75a6043SHong Zhang   sbaij->j = j;
2190c75a6043SHong Zhang   sbaij->a = a;
219126fbe8dcSKarl Rupp 
2192c75a6043SHong Zhang   sbaij->singlemalloc   = PETSC_FALSE;
2193c75a6043SHong Zhang   sbaij->nonew          = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2194e6b907acSBarry Smith   sbaij->free_a         = PETSC_FALSE;
2195e6b907acSBarry Smith   sbaij->free_ij        = PETSC_FALSE;
2196ddf7884eSMatthew Knepley   sbaij->free_imax_ilen = PETSC_TRUE;
2197c75a6043SHong Zhang 
2198c75a6043SHong Zhang   for (ii = 0; ii < m; ii++) {
2199c75a6043SHong Zhang     sbaij->ilen[ii] = sbaij->imax[ii] = i[ii + 1] - i[ii];
22006bdcaf15SBarry Smith     PetscCheck(i[ii + 1] >= i[ii], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row length in i (row indices) row = %" PetscInt_FMT " length = %" PetscInt_FMT, ii, i[ii + 1] - i[ii]);
2201c75a6043SHong Zhang   }
220276bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2203c75a6043SHong Zhang     for (ii = 0; ii < sbaij->i[m]; ii++) {
22046bdcaf15SBarry Smith       PetscCheck(j[ii] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative column index at location = %" PetscInt_FMT " index = %" PetscInt_FMT, ii, j[ii]);
22056bdcaf15SBarry Smith       PetscCheck(j[ii] < n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column index too large at location = %" PetscInt_FMT " index = %" PetscInt_FMT, ii, j[ii]);
2206c75a6043SHong Zhang     }
220776bd3646SJed Brown   }
2208c75a6043SHong Zhang 
22099566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY));
22109566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY));
2211c75a6043SHong Zhang   PetscFunctionReturn(0);
2212c75a6043SHong Zhang }
2213d06b337dSHong Zhang 
22149371c9d4SSatish Balay PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat) {
221559f5e6ceSHong Zhang   PetscFunctionBegin;
22169566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPISBAIJ(comm, inmat, n, scall, outmat));
221759f5e6ceSHong Zhang   PetscFunctionReturn(0);
221859f5e6ceSHong Zhang }
2219