xref: /petsc/src/mat/impls/sbaij/seq/sbaij.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
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));
569566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A, a->mbs * sizeof(PetscInt)));
57c760cd28SBarry Smith     a->free_diag = PETSC_TRUE;
5809f38230SBarry Smith   }
5948dd3d27SHong Zhang   for (i = 0; i < a->mbs; i++) {
6048dd3d27SHong Zhang     a->diag[i] = a->i[i + 1];
6148dd3d27SHong Zhang     for (j = a->i[i]; j < a->i[i + 1]; j++) {
6248dd3d27SHong Zhang       if (a->j[j] == i) {
6348dd3d27SHong Zhang         a->diag[i] = j;
6448dd3d27SHong Zhang         break;
6548dd3d27SHong Zhang       }
6648dd3d27SHong Zhang     }
6748dd3d27SHong Zhang   }
6849b5e25fSSatish Balay   PetscFunctionReturn(0);
6949b5e25fSSatish Balay }
7049b5e25fSSatish Balay 
719371c9d4SSatish Balay static PetscErrorCode MatGetRowIJ_SeqSBAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool blockcompressed, PetscInt *nn, const PetscInt *inia[], const PetscInt *inja[], PetscBool *done) {
72a6ece127SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
732462f5fdSStefano Zampini   PetscInt      i, j, n = a->mbs, nz = a->i[n], *tia, *tja, bs = A->rmap->bs, k, l, cnt;
742462f5fdSStefano Zampini   PetscInt    **ia = (PetscInt **)inia, **ja = (PetscInt **)inja;
7549b5e25fSSatish Balay 
7649b5e25fSSatish Balay   PetscFunctionBegin;
77d3e5a4abSHong Zhang   *nn = n;
78a1373b80SHong Zhang   if (!ia) PetscFunctionReturn(0);
792462f5fdSStefano Zampini   if (symmetric) {
809566063dSJacob Faibussowitsch     PetscCall(MatToSymmetricIJ_SeqAIJ(n, a->i, a->j, PETSC_FALSE, 0, 0, &tia, &tja));
812462f5fdSStefano Zampini     nz = tia[n];
822462f5fdSStefano Zampini   } else {
839371c9d4SSatish Balay     tia = a->i;
849371c9d4SSatish Balay     tja = a->j;
852462f5fdSStefano Zampini   }
862462f5fdSStefano Zampini 
872462f5fdSStefano Zampini   if (!blockcompressed && bs > 1) {
882462f5fdSStefano Zampini     (*nn) *= bs;
898f7157efSSatish Balay     /* malloc & create the natural set of indices */
909566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((n + 1) * bs, ia));
912462f5fdSStefano Zampini     if (n) {
922462f5fdSStefano Zampini       (*ia)[0] = oshift;
939371c9d4SSatish Balay       for (j = 1; j < bs; j++) { (*ia)[j] = (tia[1] - tia[0]) * bs + (*ia)[j - 1]; }
942462f5fdSStefano Zampini     }
952462f5fdSStefano Zampini 
962462f5fdSStefano Zampini     for (i = 1; i < n; i++) {
972462f5fdSStefano Zampini       (*ia)[i * bs] = (tia[i] - tia[i - 1]) * bs + (*ia)[i * bs - 1];
989371c9d4SSatish Balay       for (j = 1; j < bs; j++) { (*ia)[i * bs + j] = (tia[i + 1] - tia[i]) * bs + (*ia)[i * bs + j - 1]; }
992462f5fdSStefano Zampini     }
1009371c9d4SSatish Balay     if (n) { (*ia)[n * bs] = (tia[n] - tia[n - 1]) * bs + (*ia)[n * bs - 1]; }
1012462f5fdSStefano Zampini 
1022462f5fdSStefano Zampini     if (inja) {
1039566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz * bs * bs, ja));
1042462f5fdSStefano Zampini       cnt = 0;
1052462f5fdSStefano Zampini       for (i = 0; i < n; i++) {
1068f7157efSSatish Balay         for (j = 0; j < bs; j++) {
1072462f5fdSStefano Zampini           for (k = tia[i]; k < tia[i + 1]; k++) {
1089371c9d4SSatish Balay             for (l = 0; l < bs; l++) { (*ja)[cnt++] = bs * tja[k] + l; }
1098f7157efSSatish Balay           }
1108f7157efSSatish Balay         }
1118f7157efSSatish Balay       }
1128f7157efSSatish Balay     }
1132462f5fdSStefano Zampini 
1142462f5fdSStefano Zampini     if (symmetric) { /* deallocate memory allocated in MatToSymmetricIJ_SeqAIJ() */
1159566063dSJacob Faibussowitsch       PetscCall(PetscFree(tia));
1169566063dSJacob Faibussowitsch       PetscCall(PetscFree(tja));
1172462f5fdSStefano Zampini     }
1182462f5fdSStefano Zampini   } else if (oshift == 1) {
1192462f5fdSStefano Zampini     if (symmetric) {
1202462f5fdSStefano Zampini       nz = tia[A->rmap->n / bs];
1212462f5fdSStefano Zampini       /*  add 1 to i and j indices */
1222462f5fdSStefano Zampini       for (i = 0; i < A->rmap->n / bs + 1; i++) tia[i] = tia[i] + 1;
1232462f5fdSStefano Zampini       *ia = tia;
1242462f5fdSStefano Zampini       if (ja) {
1252462f5fdSStefano Zampini         for (i = 0; i < nz; i++) tja[i] = tja[i] + 1;
1262462f5fdSStefano Zampini         *ja = tja;
1272462f5fdSStefano Zampini       }
1282462f5fdSStefano Zampini     } else {
1292462f5fdSStefano Zampini       nz = a->i[A->rmap->n / bs];
1302462f5fdSStefano Zampini       /* malloc space and  add 1 to i and j indices */
1319566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(A->rmap->n / bs + 1, ia));
1322462f5fdSStefano Zampini       for (i = 0; i < A->rmap->n / bs + 1; i++) (*ia)[i] = a->i[i] + 1;
1332462f5fdSStefano Zampini       if (ja) {
1349566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(nz, ja));
1352462f5fdSStefano Zampini         for (i = 0; i < nz; i++) (*ja)[i] = a->j[i] + 1;
1362462f5fdSStefano Zampini       }
1372462f5fdSStefano Zampini     }
1382462f5fdSStefano Zampini   } else {
1392462f5fdSStefano Zampini     *ia = tia;
1402462f5fdSStefano Zampini     if (ja) *ja = tja;
141a6ece127SHong Zhang   }
14249b5e25fSSatish Balay   PetscFunctionReturn(0);
14349b5e25fSSatish Balay }
14449b5e25fSSatish Balay 
1459371c9d4SSatish Balay static PetscErrorCode MatRestoreRowIJ_SeqSBAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool blockcompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
14649b5e25fSSatish Balay   PetscFunctionBegin;
14749b5e25fSSatish Balay   if (!ia) PetscFunctionReturn(0);
1482462f5fdSStefano Zampini   if ((!blockcompressed && A->rmap->bs > 1) || (symmetric || oshift == 1)) {
1499566063dSJacob Faibussowitsch     PetscCall(PetscFree(*ia));
1509566063dSJacob Faibussowitsch     if (ja) PetscCall(PetscFree(*ja));
151a6ece127SHong Zhang   }
152a6ece127SHong Zhang   PetscFunctionReturn(0);
15349b5e25fSSatish Balay }
15449b5e25fSSatish Balay 
1559371c9d4SSatish Balay PetscErrorCode MatDestroy_SeqSBAIJ(Mat A) {
15649b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
15749b5e25fSSatish Balay 
15849b5e25fSSatish Balay   PetscFunctionBegin;
159a9f03627SSatish Balay #if defined(PETSC_USE_LOG)
160c0aa6a63SJacob Faibussowitsch   PetscLogObjectState((PetscObject)A, "Rows=%" PetscInt_FMT ", NZ=%" PetscInt_FMT, A->rmap->N, a->nz);
161a9f03627SSatish Balay #endif
1629566063dSJacob Faibussowitsch   PetscCall(MatSeqXAIJFreeAIJ(A, &a->a, &a->j, &a->i));
1639566063dSJacob Faibussowitsch   if (a->free_diag) PetscCall(PetscFree(a->diag));
1649566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
1659566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
1669566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->icol));
1679566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->idiag));
1689566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->inode.size));
1699566063dSJacob Faibussowitsch   if (a->free_imax_ilen) PetscCall(PetscFree2(a->imax, a->ilen));
1709566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->solve_work));
1719566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->sor_work));
1729566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->solves_work));
1739566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->mult_work));
1749566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->saved_values));
1759566063dSJacob Faibussowitsch   if (a->free_jshort) PetscCall(PetscFree(a->jshort));
1769566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->inew));
1779566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&a->parent));
1789566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
179901853e0SKris Buschelman 
1809566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL));
1812e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJGetArray_C", NULL));
1822e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJRestoreArray_C", NULL));
1839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatStoreValues_C", NULL));
1849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatRetrieveValues_C", NULL));
1859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetColumnIndices_C", NULL));
1869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqaij_C", NULL));
1879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqbaij_C", NULL));
1889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocation_C", NULL));
1899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocationCSR_C", NULL));
1906214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_elemental_C", NULL));
1926214f412SHong Zhang #endif
193d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
1949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_scalapack_C", NULL));
195d24d4204SJose E. Roman #endif
1962e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL));
19749b5e25fSSatish Balay   PetscFunctionReturn(0);
19849b5e25fSSatish Balay }
19949b5e25fSSatish Balay 
2009371c9d4SSatish Balay PetscErrorCode MatSetOption_SeqSBAIJ(Mat A, MatOption op, PetscBool flg) {
201045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
202eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
203eb1ec7c1SStefano Zampini   PetscInt bs;
204eb1ec7c1SStefano Zampini #endif
20549b5e25fSSatish Balay 
20649b5e25fSSatish Balay   PetscFunctionBegin;
207eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2089566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &bs));
209eb1ec7c1SStefano Zampini #endif
2104d9d31abSKris Buschelman   switch (op) {
2119371c9d4SSatish Balay   case MAT_ROW_ORIENTED: a->roworiented = flg; break;
2129371c9d4SSatish Balay   case MAT_KEEP_NONZERO_PATTERN: a->keepnonzeropattern = flg; break;
2139371c9d4SSatish Balay   case MAT_NEW_NONZERO_LOCATIONS: a->nonew = (flg ? 0 : 1); break;
2149371c9d4SSatish Balay   case MAT_NEW_NONZERO_LOCATION_ERR: a->nonew = (flg ? -1 : 0); break;
2159371c9d4SSatish Balay   case MAT_NEW_NONZERO_ALLOCATION_ERR: a->nonew = (flg ? -2 : 0); break;
2169371c9d4SSatish Balay   case MAT_UNUSED_NONZERO_LOCATION_ERR: a->nounused = (flg ? -1 : 0); break;
2178c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
2184d9d31abSKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
2194d9d31abSKris Buschelman   case MAT_USE_HASH_TABLE:
2209371c9d4SSatish Balay   case MAT_SORTED_FULL: PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op])); break;
2219a4540c5SBarry Smith   case MAT_HERMITIAN:
222eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
223eb1ec7c1SStefano Zampini     if (flg) { /* disable transpose ops */
22408401ef6SPierre Jolivet       PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for Hermitian with block size greater than 1");
225eb1ec7c1SStefano Zampini       A->ops->multtranspose    = NULL;
226eb1ec7c1SStefano Zampini       A->ops->multtransposeadd = NULL;
227b94d7dedSBarry Smith       A->symmetric             = PETSC_BOOL3_FALSE;
228eb1ec7c1SStefano Zampini     }
2290f2140c7SStefano Zampini #endif
230eeffb40dSHong Zhang     break;
23177e54ba9SKris Buschelman   case MAT_SYMMETRIC:
232eb1ec7c1SStefano Zampini   case MAT_SPD:
233eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
234eb1ec7c1SStefano Zampini     if (flg) { /* An hermitian and symmetric matrix has zero imaginary part (restore back transpose ops) */
235eb1ec7c1SStefano Zampini       A->ops->multtranspose    = A->ops->mult;
236eb1ec7c1SStefano Zampini       A->ops->multtransposeadd = A->ops->multadd;
237eb1ec7c1SStefano Zampini     }
238eb1ec7c1SStefano Zampini #endif
239eb1ec7c1SStefano Zampini     break;
240eb1ec7c1SStefano Zampini     /* These options are handled directly by MatSetOption() */
24177e54ba9SKris Buschelman   case MAT_STRUCTURALLY_SYMMETRIC:
2429a4540c5SBarry Smith   case MAT_SYMMETRY_ETERNAL:
243b94d7dedSBarry Smith   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
244672ba085SHong Zhang   case MAT_STRUCTURE_ONLY:
245b94d7dedSBarry Smith   case MAT_SPD_ETERNAL:
2464dcd73b1SHong Zhang     /* These options are handled directly by MatSetOption() */
247290bbb0aSBarry Smith     break;
2489371c9d4SSatish Balay   case MAT_IGNORE_LOWER_TRIANGULAR: a->ignore_ltriangular = flg; break;
2499371c9d4SSatish Balay   case MAT_ERROR_LOWER_TRIANGULAR: a->ignore_ltriangular = flg; break;
2509371c9d4SSatish Balay   case MAT_GETROW_UPPERTRIANGULAR: a->getrow_utriangular = flg; break;
2519371c9d4SSatish Balay   case MAT_SUBMAT_SINGLEIS: break;
2529371c9d4SSatish Balay   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %d", op);
25349b5e25fSSatish Balay   }
25449b5e25fSSatish Balay   PetscFunctionReturn(0);
25549b5e25fSSatish Balay }
25649b5e25fSSatish Balay 
2579371c9d4SSatish Balay PetscErrorCode MatGetRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) {
25849b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
25949b5e25fSSatish Balay 
26049b5e25fSSatish Balay   PetscFunctionBegin;
26108401ef6SPierre 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()");
26252768537SHong Zhang 
263f5edf698SHong Zhang   /* Get the upper triangular part of the row */
2649566063dSJacob Faibussowitsch   PetscCall(MatGetRow_SeqBAIJ_private(A, row, nz, idx, v, a->i, a->j, a->a));
26549b5e25fSSatish Balay   PetscFunctionReturn(0);
26649b5e25fSSatish Balay }
26749b5e25fSSatish Balay 
2689371c9d4SSatish Balay PetscErrorCode MatRestoreRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) {
26949b5e25fSSatish Balay   PetscFunctionBegin;
270cb4a9cd9SHong Zhang   if (nz) *nz = 0;
2719566063dSJacob Faibussowitsch   if (idx) PetscCall(PetscFree(*idx));
2729566063dSJacob Faibussowitsch   if (v) PetscCall(PetscFree(*v));
27349b5e25fSSatish Balay   PetscFunctionReturn(0);
27449b5e25fSSatish Balay }
27549b5e25fSSatish Balay 
2769371c9d4SSatish Balay PetscErrorCode MatGetRowUpperTriangular_SeqSBAIJ(Mat A) {
277f5edf698SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
278f5edf698SHong Zhang 
279f5edf698SHong Zhang   PetscFunctionBegin;
280f5edf698SHong Zhang   a->getrow_utriangular = PETSC_TRUE;
281f5edf698SHong Zhang   PetscFunctionReturn(0);
282f5edf698SHong Zhang }
283a323099bSStefano Zampini 
2849371c9d4SSatish Balay PetscErrorCode MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A) {
285f5edf698SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
286f5edf698SHong Zhang 
287f5edf698SHong Zhang   PetscFunctionBegin;
288f5edf698SHong Zhang   a->getrow_utriangular = PETSC_FALSE;
289f5edf698SHong Zhang   PetscFunctionReturn(0);
290f5edf698SHong Zhang }
291f5edf698SHong Zhang 
2929371c9d4SSatish Balay PetscErrorCode MatTranspose_SeqSBAIJ(Mat A, MatReuse reuse, Mat *B) {
29349b5e25fSSatish Balay   PetscFunctionBegin;
2947fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B));
295cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX) {
2969566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A, MAT_COPY_VALUES, B));
297cf37664fSBarry Smith   } else if (reuse == MAT_REUSE_MATRIX) {
2989566063dSJacob Faibussowitsch     PetscCall(MatCopy(A, *B, SAME_NONZERO_PATTERN));
299fc4dec0aSBarry Smith   }
3008115998fSBarry Smith   PetscFunctionReturn(0);
30149b5e25fSSatish Balay }
30249b5e25fSSatish Balay 
3039371c9d4SSatish Balay PetscErrorCode MatView_SeqSBAIJ_ASCII(Mat A, PetscViewer viewer) {
30449b5e25fSSatish Balay   Mat_SeqSBAIJ     *a = (Mat_SeqSBAIJ *)A->data;
305d0f46423SBarry Smith   PetscInt          i, j, bs = A->rmap->bs, k, l, bs2 = a->bs2;
306f3ef73ceSBarry Smith   PetscViewerFormat format;
307121deb67SSatish Balay   PetscInt         *diag;
30849b5e25fSSatish Balay 
30949b5e25fSSatish Balay   PetscFunctionBegin;
3109566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
311456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
3129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  block size is %" PetscInt_FMT "\n", bs));
313fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_MATLAB) {
314d2507d54SMatthew Knepley     Mat         aij;
315ade3a672SBarry Smith     const char *matname;
316ade3a672SBarry Smith 
317d5f3da31SBarry Smith     if (A->factortype && bs > 1) {
3189566063dSJacob 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"));
31970d5e725SHong Zhang       PetscFunctionReturn(0);
32070d5e725SHong Zhang     }
3219566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &aij));
3229566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)A, &matname));
3239566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)aij, matname));
3249566063dSJacob Faibussowitsch     PetscCall(MatView(aij, viewer));
3259566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&aij));
326fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
3279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
32849b5e25fSSatish Balay     for (i = 0; i < a->mbs; i++) {
32949b5e25fSSatish Balay       for (j = 0; j < bs; j++) {
3309566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i * bs + j));
33149b5e25fSSatish Balay         for (k = a->i[i]; k < a->i[i + 1]; k++) {
33249b5e25fSSatish Balay           for (l = 0; l < bs; l++) {
33349b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX)
33449b5e25fSSatish Balay             if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) > 0.0 && PetscRealPart(a->a[bs2 * k + l * bs + j]) != 0.0) {
3359371c9d4SSatish 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])));
33649b5e25fSSatish Balay             } else if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) < 0.0 && PetscRealPart(a->a[bs2 * k + l * bs + j]) != 0.0) {
3379371c9d4SSatish 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])));
33849b5e25fSSatish Balay             } else if (PetscRealPart(a->a[bs2 * k + l * bs + j]) != 0.0) {
3399566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j])));
34049b5e25fSSatish Balay             }
34149b5e25fSSatish Balay #else
342*48a46eb9SPierre 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]));
34349b5e25fSSatish Balay #endif
34449b5e25fSSatish Balay           }
34549b5e25fSSatish Balay         }
3469566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
34749b5e25fSSatish Balay       }
34849b5e25fSSatish Balay     }
3499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
350c1490034SHong Zhang   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
351c1490034SHong Zhang     PetscFunctionReturn(0);
35249b5e25fSSatish Balay   } else {
3539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
3542c990fa1SHong Zhang     if (A->factortype) { /* for factored matrix */
35508401ef6SPierre Jolivet       PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix is factored with bs>1. Not implemented yet");
3562c990fa1SHong Zhang 
357121deb67SSatish Balay       diag = a->diag;
358121deb67SSatish Balay       for (i = 0; i < a->mbs; i++) { /* for row block i */
3599566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
3602c990fa1SHong Zhang         /* diagonal entry */
3612c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX)
3622c990fa1SHong Zhang         if (PetscImaginaryPart(a->a[diag[i]]) > 0.0) {
3639566063dSJacob 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]])));
3642c990fa1SHong Zhang         } else if (PetscImaginaryPart(a->a[diag[i]]) < 0.0) {
3659566063dSJacob 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]])));
3662c990fa1SHong Zhang         } else {
3679566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)PetscRealPart(1.0 / a->a[diag[i]])));
3682c990fa1SHong Zhang         }
3692c990fa1SHong Zhang #else
3709566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)(1.0 / a->a[diag[i]])));
3712c990fa1SHong Zhang #endif
3722c990fa1SHong Zhang         /* off-diagonal entries */
3732c990fa1SHong Zhang         for (k = a->i[i]; k < a->i[i + 1] - 1; k++) {
3742c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX)
375ca0704adSBarry Smith           if (PetscImaginaryPart(a->a[k]) > 0.0) {
3769566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), (double)PetscImaginaryPart(a->a[k])));
377ca0704adSBarry Smith           } else if (PetscImaginaryPart(a->a[k]) < 0.0) {
3789566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), -(double)PetscImaginaryPart(a->a[k])));
3792c990fa1SHong Zhang           } else {
3809566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k], (double)PetscRealPart(a->a[k])));
3812c990fa1SHong Zhang           }
3822c990fa1SHong Zhang #else
3839566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[k], (double)a->a[k]));
3842c990fa1SHong Zhang #endif
3852c990fa1SHong Zhang         }
3869566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
3872c990fa1SHong Zhang       }
3882c990fa1SHong Zhang 
3892c990fa1SHong Zhang     } else {                         /* for non-factored matrix */
3900c74a584SJed Brown       for (i = 0; i < a->mbs; i++) { /* for row block i */
3910c74a584SJed Brown         for (j = 0; j < bs; j++) {   /* for row bs*i + j */
3929566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i * bs + j));
3930c74a584SJed Brown           for (k = a->i[i]; k < a->i[i + 1]; k++) { /* for column block */
3940c74a584SJed Brown             for (l = 0; l < bs; l++) {              /* for column */
39549b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX)
39649b5e25fSSatish Balay               if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) > 0.0) {
3979371c9d4SSatish 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])));
39849b5e25fSSatish Balay               } else if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) < 0.0) {
3999371c9d4SSatish 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])));
40049b5e25fSSatish Balay               } else {
4019566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j])));
40249b5e25fSSatish Balay               }
40349b5e25fSSatish Balay #else
4049566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)a->a[bs2 * k + l * bs + j]));
40549b5e25fSSatish Balay #endif
40649b5e25fSSatish Balay             }
40749b5e25fSSatish Balay           }
4089566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
40949b5e25fSSatish Balay         }
41049b5e25fSSatish Balay       }
4112c990fa1SHong Zhang     }
4129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
41349b5e25fSSatish Balay   }
4149566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
41549b5e25fSSatish Balay   PetscFunctionReturn(0);
41649b5e25fSSatish Balay }
41749b5e25fSSatish Balay 
4189804daf3SBarry Smith #include <petscdraw.h>
4199371c9d4SSatish Balay static PetscErrorCode MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw, void *Aa) {
42049b5e25fSSatish Balay   Mat           A = (Mat)Aa;
42149b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
422d0f46423SBarry Smith   PetscInt      row, i, j, k, l, mbs = a->mbs, color, bs = A->rmap->bs, bs2 = a->bs2;
42349b5e25fSSatish Balay   PetscReal     xl, yl, xr, yr, x_l, x_r, y_l, y_r;
42449b5e25fSSatish Balay   MatScalar    *aa;
425b0a32e0cSBarry Smith   PetscViewer   viewer;
42649b5e25fSSatish Balay 
42749b5e25fSSatish Balay   PetscFunctionBegin;
4289566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
4299566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
43049b5e25fSSatish Balay 
43149b5e25fSSatish Balay   /* loop over matrix elements drawing boxes */
432383922c3SLisandro Dalcin 
433d0609cedSBarry Smith   PetscDrawCollectiveBegin(draw);
4349566063dSJacob Faibussowitsch   PetscCall(PetscDrawString(draw, .3 * (xl + xr), .3 * (yl + yr), PETSC_DRAW_BLACK, "symmetric"));
435383922c3SLisandro Dalcin   /* Blue for negative, Cyan for zero and  Red for positive */
436b0a32e0cSBarry Smith   color = PETSC_DRAW_BLUE;
43749b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
43849b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4399371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4409371c9d4SSatish Balay       y_r = y_l + 1.0;
4419371c9d4SSatish Balay       x_l = a->j[j] * bs;
4429371c9d4SSatish Balay       x_r = x_l + 1.0;
44349b5e25fSSatish Balay       aa  = a->a + j * bs2;
44449b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
44549b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
44649b5e25fSSatish Balay           if (PetscRealPart(*aa++) >= 0.) continue;
4479566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
44849b5e25fSSatish Balay         }
44949b5e25fSSatish Balay       }
45049b5e25fSSatish Balay     }
45149b5e25fSSatish Balay   }
452b0a32e0cSBarry Smith   color = PETSC_DRAW_CYAN;
45349b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
45449b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4559371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4569371c9d4SSatish Balay       y_r = y_l + 1.0;
4579371c9d4SSatish Balay       x_l = a->j[j] * bs;
4589371c9d4SSatish Balay       x_r = x_l + 1.0;
45949b5e25fSSatish Balay       aa  = a->a + j * bs2;
46049b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
46149b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
46249b5e25fSSatish Balay           if (PetscRealPart(*aa++) != 0.) continue;
4639566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
46449b5e25fSSatish Balay         }
46549b5e25fSSatish Balay       }
46649b5e25fSSatish Balay     }
46749b5e25fSSatish Balay   }
468b0a32e0cSBarry Smith   color = PETSC_DRAW_RED;
46949b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
47049b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4719371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4729371c9d4SSatish Balay       y_r = y_l + 1.0;
4739371c9d4SSatish Balay       x_l = a->j[j] * bs;
4749371c9d4SSatish Balay       x_r = x_l + 1.0;
47549b5e25fSSatish Balay       aa  = a->a + j * bs2;
47649b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
47749b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
47849b5e25fSSatish Balay           if (PetscRealPart(*aa++) <= 0.) continue;
4799566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
48049b5e25fSSatish Balay         }
48149b5e25fSSatish Balay       }
48249b5e25fSSatish Balay     }
48349b5e25fSSatish Balay   }
484d0609cedSBarry Smith   PetscDrawCollectiveEnd(draw);
48549b5e25fSSatish Balay   PetscFunctionReturn(0);
48649b5e25fSSatish Balay }
48749b5e25fSSatish Balay 
4889371c9d4SSatish Balay static PetscErrorCode MatView_SeqSBAIJ_Draw(Mat A, PetscViewer viewer) {
48949b5e25fSSatish Balay   PetscReal xl, yl, xr, yr, w, h;
490b0a32e0cSBarry Smith   PetscDraw draw;
491ace3abfcSBarry Smith   PetscBool isnull;
49249b5e25fSSatish Balay 
49349b5e25fSSatish Balay   PetscFunctionBegin;
4949566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4959566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
496383922c3SLisandro Dalcin   if (isnull) PetscFunctionReturn(0);
49749b5e25fSSatish Balay 
4989371c9d4SSatish Balay   xr = A->rmap->N;
4999371c9d4SSatish Balay   yr = A->rmap->N;
5009371c9d4SSatish Balay   h  = yr / 10.0;
5019371c9d4SSatish Balay   w  = xr / 10.0;
5029371c9d4SSatish Balay   xr += w;
5039371c9d4SSatish Balay   yr += h;
5049371c9d4SSatish Balay   xl = -w;
5059371c9d4SSatish Balay   yl = -h;
5069566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
5079566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
5089566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqSBAIJ_Draw_Zoom, A));
5099566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
5109566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
51149b5e25fSSatish Balay   PetscFunctionReturn(0);
51249b5e25fSSatish Balay }
51349b5e25fSSatish Balay 
514618cc2edSLisandro Dalcin /* Used for both MPIBAIJ and MPISBAIJ matrices */
515618cc2edSLisandro Dalcin #define MatView_SeqSBAIJ_Binary MatView_SeqBAIJ_Binary
516618cc2edSLisandro Dalcin 
5179371c9d4SSatish Balay PetscErrorCode MatView_SeqSBAIJ(Mat A, PetscViewer viewer) {
518618cc2edSLisandro Dalcin   PetscBool iascii, isbinary, isdraw;
51949b5e25fSSatish Balay 
52049b5e25fSSatish Balay   PetscFunctionBegin;
5219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
5229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
5239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
52432077d6dSBarry Smith   if (iascii) {
5259566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_ASCII(A, viewer));
526618cc2edSLisandro Dalcin   } else if (isbinary) {
5279566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_Binary(A, viewer));
52849b5e25fSSatish Balay   } else if (isdraw) {
5299566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_Draw(A, viewer));
53049b5e25fSSatish Balay   } else {
531a5e6ed63SBarry Smith     Mat         B;
532ade3a672SBarry Smith     const char *matname;
5339566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B));
5349566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)A, &matname));
5359566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)B, matname));
5369566063dSJacob Faibussowitsch     PetscCall(MatView(B, viewer));
5379566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
53849b5e25fSSatish Balay   }
53949b5e25fSSatish Balay   PetscFunctionReturn(0);
54049b5e25fSSatish Balay }
54149b5e25fSSatish Balay 
5429371c9d4SSatish Balay PetscErrorCode MatGetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[]) {
543045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
54413f74950SBarry Smith   PetscInt     *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j;
54513f74950SBarry Smith   PetscInt     *ai = a->i, *ailen = a->ilen;
546d0f46423SBarry Smith   PetscInt      brow, bcol, ridx, cidx, bs = A->rmap->bs, bs2 = a->bs2;
54797e567efSBarry Smith   MatScalar    *ap, *aa = a->a;
54849b5e25fSSatish Balay 
54949b5e25fSSatish Balay   PetscFunctionBegin;
55049b5e25fSSatish Balay   for (k = 0; k < m; k++) { /* loop over rows */
5519371c9d4SSatish Balay     row  = im[k];
5529371c9d4SSatish Balay     brow = row / bs;
5539371c9d4SSatish Balay     if (row < 0) {
5549371c9d4SSatish Balay       v += n;
5559371c9d4SSatish Balay       continue;
5569371c9d4SSatish Balay     } /* negative row */
55754c59aa7SJacob 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);
5589371c9d4SSatish Balay     rp   = aj + ai[brow];
5599371c9d4SSatish Balay     ap   = aa + bs2 * ai[brow];
56049b5e25fSSatish Balay     nrow = ailen[brow];
56149b5e25fSSatish Balay     for (l = 0; l < n; l++) { /* loop over columns */
5629371c9d4SSatish Balay       if (in[l] < 0) {
5639371c9d4SSatish Balay         v++;
5649371c9d4SSatish Balay         continue;
5659371c9d4SSatish Balay       } /* negative column */
56654c59aa7SJacob 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);
56749b5e25fSSatish Balay       col  = in[l];
56849b5e25fSSatish Balay       bcol = col / bs;
56949b5e25fSSatish Balay       cidx = col % bs;
57049b5e25fSSatish Balay       ridx = row % bs;
57149b5e25fSSatish Balay       high = nrow;
57249b5e25fSSatish Balay       low  = 0; /* assume unsorted */
57349b5e25fSSatish Balay       while (high - low > 5) {
57449b5e25fSSatish Balay         t = (low + high) / 2;
57549b5e25fSSatish Balay         if (rp[t] > bcol) high = t;
57649b5e25fSSatish Balay         else low = t;
57749b5e25fSSatish Balay       }
57849b5e25fSSatish Balay       for (i = low; i < high; i++) {
57949b5e25fSSatish Balay         if (rp[i] > bcol) break;
58049b5e25fSSatish Balay         if (rp[i] == bcol) {
58149b5e25fSSatish Balay           *v++ = ap[bs2 * i + bs * cidx + ridx];
58249b5e25fSSatish Balay           goto finished;
58349b5e25fSSatish Balay         }
58449b5e25fSSatish Balay       }
58597e567efSBarry Smith       *v++ = 0.0;
58649b5e25fSSatish Balay     finished:;
58749b5e25fSSatish Balay     }
58849b5e25fSSatish Balay   }
58949b5e25fSSatish Balay   PetscFunctionReturn(0);
59049b5e25fSSatish Balay }
59149b5e25fSSatish Balay 
5929371c9d4SSatish Balay PetscErrorCode MatPermute_SeqSBAIJ(Mat A, IS rowp, IS colp, Mat *B) {
593dc29a518SPierre Jolivet   Mat C;
594dc29a518SPierre Jolivet 
595dc29a518SPierre Jolivet   PetscFunctionBegin;
5969566063dSJacob Faibussowitsch   PetscCall(MatConvert(A, MATSEQBAIJ, MAT_INITIAL_MATRIX, &C));
5979566063dSJacob Faibussowitsch   PetscCall(MatPermute(C, rowp, colp, B));
5989566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
599*48a46eb9SPierre Jolivet   if (rowp == colp) PetscCall(MatConvert(*B, MATSEQSBAIJ, MAT_INPLACE_MATRIX, B));
600dc29a518SPierre Jolivet   PetscFunctionReturn(0);
601dc29a518SPierre Jolivet }
60249b5e25fSSatish Balay 
6039371c9d4SSatish Balay PetscErrorCode MatSetValuesBlocked_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) {
6040880e062SHong Zhang   Mat_SeqSBAIJ      *a = (Mat_SeqSBAIJ *)A->data;
605e2ee6c50SBarry Smith   PetscInt          *rp, k, low, high, t, ii, jj, row, nrow, i, col, l, rmax, N, lastcol = -1;
60613f74950SBarry Smith   PetscInt          *imax = a->imax, *ai = a->i, *ailen = a->ilen;
607d0f46423SBarry Smith   PetscInt          *aj = a->j, nonew = a->nonew, bs2 = a->bs2, bs = A->rmap->bs, stepval;
608ace3abfcSBarry Smith   PetscBool          roworiented = a->roworiented;
609dd6ea824SBarry Smith   const PetscScalar *value       = v;
610f15d580aSBarry Smith   MatScalar         *ap, *aa = a->a, *bap;
6110880e062SHong Zhang 
61249b5e25fSSatish Balay   PetscFunctionBegin;
61326fbe8dcSKarl Rupp   if (roworiented) stepval = (n - 1) * bs;
61426fbe8dcSKarl Rupp   else stepval = (m - 1) * bs;
61526fbe8dcSKarl Rupp 
6160880e062SHong Zhang   for (k = 0; k < m; k++) { /* loop over added rows */
6170880e062SHong Zhang     row = im[k];
6180880e062SHong Zhang     if (row < 0) continue;
6196bdcaf15SBarry 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);
6200880e062SHong Zhang     rp   = aj + ai[row];
6210880e062SHong Zhang     ap   = aa + bs2 * ai[row];
6220880e062SHong Zhang     rmax = imax[row];
6230880e062SHong Zhang     nrow = ailen[row];
6240880e062SHong Zhang     low  = 0;
625818f2c47SBarry Smith     high = nrow;
6260880e062SHong Zhang     for (l = 0; l < n; l++) { /* loop over added columns */
6270880e062SHong Zhang       if (in[l] < 0) continue;
6280880e062SHong Zhang       col = in[l];
6296bdcaf15SBarry 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);
630b98bf0e1SJed Brown       if (col < row) {
63126fbe8dcSKarl Rupp         if (a->ignore_ltriangular) continue; /* ignore lower triangular block */
63226fbe8dcSKarl 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)");
633b98bf0e1SJed Brown       }
63426fbe8dcSKarl Rupp       if (roworiented) value = v + k * (stepval + bs) * bs + l * bs;
63526fbe8dcSKarl Rupp       else value = v + l * (stepval + bs) * bs + k * bs;
63626fbe8dcSKarl Rupp 
63726fbe8dcSKarl Rupp       if (col <= lastcol) low = 0;
63826fbe8dcSKarl Rupp       else high = nrow;
63926fbe8dcSKarl Rupp 
640e2ee6c50SBarry Smith       lastcol = col;
6410880e062SHong Zhang       while (high - low > 7) {
6420880e062SHong Zhang         t = (low + high) / 2;
6430880e062SHong Zhang         if (rp[t] > col) high = t;
6440880e062SHong Zhang         else low = t;
6450880e062SHong Zhang       }
6460880e062SHong Zhang       for (i = low; i < high; i++) {
6470880e062SHong Zhang         if (rp[i] > col) break;
6480880e062SHong Zhang         if (rp[i] == col) {
6490880e062SHong Zhang           bap = ap + bs2 * i;
6500880e062SHong Zhang           if (roworiented) {
6510880e062SHong Zhang             if (is == ADD_VALUES) {
6520880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
6539371c9d4SSatish Balay                 for (jj = ii; jj < bs2; jj += bs) { bap[jj] += *value++; }
6540880e062SHong Zhang               }
6550880e062SHong Zhang             } else {
6560880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
6579371c9d4SSatish Balay                 for (jj = ii; jj < bs2; jj += bs) { bap[jj] = *value++; }
6580880e062SHong Zhang               }
6590880e062SHong Zhang             }
6600880e062SHong Zhang           } else {
6610880e062SHong Zhang             if (is == ADD_VALUES) {
6620880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
6639371c9d4SSatish Balay                 for (jj = 0; jj < bs; jj++) { *bap++ += *value++; }
6640880e062SHong Zhang               }
6650880e062SHong Zhang             } else {
6660880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
6679371c9d4SSatish Balay                 for (jj = 0; jj < bs; jj++) { *bap++ = *value++; }
6680880e062SHong Zhang               }
6690880e062SHong Zhang             }
6700880e062SHong Zhang           }
6710880e062SHong Zhang           goto noinsert2;
6720880e062SHong Zhang         }
6730880e062SHong Zhang       }
6740880e062SHong Zhang       if (nonew == 1) goto noinsert2;
67508401ef6SPierre 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);
676fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
6779371c9d4SSatish Balay       N = nrow++ - 1;
6789371c9d4SSatish Balay       high++;
6790880e062SHong Zhang       /* shift up all the later entries in this row */
6809566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1));
6819566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1)));
6829566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(ap + bs2 * i, bs2));
6830880e062SHong Zhang       rp[i] = col;
6840880e062SHong Zhang       bap   = ap + bs2 * i;
6850880e062SHong Zhang       if (roworiented) {
6860880e062SHong Zhang         for (ii = 0; ii < bs; ii++, value += stepval) {
6879371c9d4SSatish Balay           for (jj = ii; jj < bs2; jj += bs) { bap[jj] = *value++; }
6880880e062SHong Zhang         }
6890880e062SHong Zhang       } else {
6900880e062SHong Zhang         for (ii = 0; ii < bs; ii++, value += stepval) {
6919371c9d4SSatish Balay           for (jj = 0; jj < bs; jj++) { *bap++ = *value++; }
6920880e062SHong Zhang         }
6930880e062SHong Zhang       }
6940880e062SHong Zhang     noinsert2:;
6950880e062SHong Zhang       low = i;
6960880e062SHong Zhang     }
6970880e062SHong Zhang     ailen[row] = nrow;
6980880e062SHong Zhang   }
6990880e062SHong Zhang   PetscFunctionReturn(0);
70049b5e25fSSatish Balay }
70149b5e25fSSatish Balay 
70264831d72SBarry Smith /*
70364831d72SBarry Smith     This is not yet used
70464831d72SBarry Smith */
7059371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_SeqSBAIJ_SeqAIJ_Inode(Mat A) {
7060def2e27SBarry Smith   Mat_SeqSBAIJ   *a  = (Mat_SeqSBAIJ *)A->data;
7070def2e27SBarry Smith   const PetscInt *ai = a->i, *aj = a->j, *cols;
7080def2e27SBarry Smith   PetscInt        i = 0, j, blk_size, m = A->rmap->n, node_count = 0, nzx, nzy, *ns, row, nz, cnt, cnt2, *counts;
709ace3abfcSBarry Smith   PetscBool       flag;
7100def2e27SBarry Smith 
7110def2e27SBarry Smith   PetscFunctionBegin;
7129566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m, &ns));
7130def2e27SBarry Smith   while (i < m) {
7140def2e27SBarry Smith     nzx = ai[i + 1] - ai[i]; /* Number of nonzeros */
7150def2e27SBarry Smith     /* Limits the number of elements in a node to 'a->inode.limit' */
7160def2e27SBarry Smith     for (j = i + 1, blk_size = 1; j < m && blk_size < a->inode.limit; ++j, ++blk_size) {
7170def2e27SBarry Smith       nzy = ai[j + 1] - ai[j];
7180def2e27SBarry Smith       if (nzy != (nzx - j + i)) break;
7199566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(aj + ai[i] + j - i, aj + ai[j], nzy, &flag));
7200def2e27SBarry Smith       if (!flag) break;
7210def2e27SBarry Smith     }
7220def2e27SBarry Smith     ns[node_count++] = blk_size;
72326fbe8dcSKarl Rupp 
7240def2e27SBarry Smith     i = j;
7250def2e27SBarry Smith   }
7260def2e27SBarry Smith   if (!a->inode.size && m && node_count > .9 * m) {
7279566063dSJacob Faibussowitsch     PetscCall(PetscFree(ns));
7289566063dSJacob Faibussowitsch     PetscCall(PetscInfo(A, "Found %" PetscInt_FMT " nodes out of %" PetscInt_FMT " rows. Not using Inode routines\n", node_count, m));
7290def2e27SBarry Smith   } else {
7300def2e27SBarry Smith     a->inode.node_count = node_count;
73126fbe8dcSKarl Rupp 
7329566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(node_count, &a->inode.size));
7339566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A, node_count * sizeof(PetscInt)));
7349566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(a->inode.size, ns, node_count));
7359566063dSJacob Faibussowitsch     PetscCall(PetscFree(ns));
7369566063dSJacob 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));
7370def2e27SBarry Smith 
7380def2e27SBarry Smith     /* count collections of adjacent columns in each inode */
7390def2e27SBarry Smith     row = 0;
7400def2e27SBarry Smith     cnt = 0;
7410def2e27SBarry Smith     for (i = 0; i < node_count; i++) {
7420def2e27SBarry Smith       cols = aj + ai[row] + a->inode.size[i];
7430def2e27SBarry Smith       nz   = ai[row + 1] - ai[row] - a->inode.size[i];
7440def2e27SBarry Smith       for (j = 1; j < nz; j++) {
74526fbe8dcSKarl Rupp         if (cols[j] != cols[j - 1] + 1) cnt++;
7460def2e27SBarry Smith       }
7470def2e27SBarry Smith       cnt++;
7480def2e27SBarry Smith       row += a->inode.size[i];
7490def2e27SBarry Smith     }
7509566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(2 * cnt, &counts));
7510def2e27SBarry Smith     cnt = 0;
7520def2e27SBarry Smith     row = 0;
7530def2e27SBarry Smith     for (i = 0; i < node_count; i++) {
7540def2e27SBarry Smith       cols            = aj + ai[row] + a->inode.size[i];
7550def2e27SBarry Smith       counts[2 * cnt] = cols[0];
7560def2e27SBarry Smith       nz              = ai[row + 1] - ai[row] - a->inode.size[i];
7570def2e27SBarry Smith       cnt2            = 1;
7580def2e27SBarry Smith       for (j = 1; j < nz; j++) {
7590def2e27SBarry Smith         if (cols[j] != cols[j - 1] + 1) {
7600def2e27SBarry Smith           counts[2 * (cnt++) + 1] = cnt2;
7610def2e27SBarry Smith           counts[2 * cnt]         = cols[j];
7620def2e27SBarry Smith           cnt2                    = 1;
7630def2e27SBarry Smith         } else cnt2++;
7640def2e27SBarry Smith       }
7650def2e27SBarry Smith       counts[2 * (cnt++) + 1] = cnt2;
7660def2e27SBarry Smith       row += a->inode.size[i];
7670def2e27SBarry Smith     }
7689566063dSJacob Faibussowitsch     PetscCall(PetscIntView(2 * cnt, counts, NULL));
7690def2e27SBarry Smith   }
77038702af4SBarry Smith   PetscFunctionReturn(0);
77138702af4SBarry Smith }
77238702af4SBarry Smith 
7739371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_SeqSBAIJ(Mat A, MatAssemblyType mode) {
77449b5e25fSSatish Balay   Mat_SeqSBAIJ *a      = (Mat_SeqSBAIJ *)A->data;
7758f8f2f0dSBarry Smith   PetscInt      fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax;
776d0f46423SBarry Smith   PetscInt      m = A->rmap->N, *ip, N, *ailen = a->ilen;
77713f74950SBarry Smith   PetscInt      mbs = a->mbs, bs2 = a->bs2, rmax = 0;
77849b5e25fSSatish Balay   MatScalar    *aa = a->a, *ap;
77949b5e25fSSatish Balay 
78049b5e25fSSatish Balay   PetscFunctionBegin;
78149b5e25fSSatish Balay   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
78249b5e25fSSatish Balay 
78349b5e25fSSatish Balay   if (m) rmax = ailen[0];
78449b5e25fSSatish Balay   for (i = 1; i < mbs; i++) {
78549b5e25fSSatish Balay     /* move each row back by the amount of empty slots (fshift) before it*/
78649b5e25fSSatish Balay     fshift += imax[i - 1] - ailen[i - 1];
78749b5e25fSSatish Balay     rmax = PetscMax(rmax, ailen[i]);
78849b5e25fSSatish Balay     if (fshift) {
789580bdb30SBarry Smith       ip = aj + ai[i];
790580bdb30SBarry Smith       ap = aa + bs2 * ai[i];
79149b5e25fSSatish Balay       N  = ailen[i];
7929566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ip - fshift, ip, N));
7939566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ap - bs2 * fshift, ap, bs2 * N));
79449b5e25fSSatish Balay     }
79549b5e25fSSatish Balay     ai[i] = ai[i - 1] + ailen[i - 1];
79649b5e25fSSatish Balay   }
79749b5e25fSSatish Balay   if (mbs) {
79849b5e25fSSatish Balay     fshift += imax[mbs - 1] - ailen[mbs - 1];
79949b5e25fSSatish Balay     ai[mbs] = ai[mbs - 1] + ailen[mbs - 1];
80049b5e25fSSatish Balay   }
80149b5e25fSSatish Balay   /* reset ilen and imax for each row */
8029371c9d4SSatish Balay   for (i = 0; i < mbs; i++) { ailen[i] = imax[i] = ai[i + 1] - ai[i]; }
8036c6c5352SBarry Smith   a->nz = ai[mbs];
80449b5e25fSSatish Balay 
805b424e231SHong Zhang   /* diagonals may have moved, reset it */
8061baa6e33SBarry Smith   if (a->diag) PetscCall(PetscArraycpy(a->diag, ai, mbs));
807aed4548fSBarry 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);
80826fbe8dcSKarl Rupp 
8099566063dSJacob 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));
8109566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues is %" PetscInt_FMT "\n", a->reallocs));
8119566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Most nonzeros blocks in any row is %" PetscInt_FMT "\n", rmax));
81226fbe8dcSKarl Rupp 
8138e58a170SBarry Smith   A->info.mallocs += a->reallocs;
81449b5e25fSSatish Balay   a->reallocs         = 0;
81549b5e25fSSatish Balay   A->info.nz_unneeded = (PetscReal)fshift * bs2;
816061b2667SBarry Smith   a->idiagvalid       = PETSC_FALSE;
8174dcd73b1SHong Zhang   a->rmax             = rmax;
81838702af4SBarry Smith 
81938702af4SBarry Smith   if (A->cmap->n < 65536 && A->cmap->bs == 1) {
82044e1c64aSLisandro Dalcin     if (a->jshort && a->free_jshort) {
82117803ae8SHong Zhang       /* when matrix data structure is changed, previous jshort must be replaced */
8229566063dSJacob Faibussowitsch       PetscCall(PetscFree(a->jshort));
82317803ae8SHong Zhang     }
8249566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(a->i[A->rmap->n], &a->jshort));
8259566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A, a->i[A->rmap->n] * sizeof(unsigned short)));
82638702af4SBarry Smith     for (i = 0; i < a->i[A->rmap->n]; i++) a->jshort[i] = a->j[i];
82738702af4SBarry Smith     A->ops->mult   = MatMult_SeqSBAIJ_1_ushort;
82841f059aeSBarry Smith     A->ops->sor    = MatSOR_SeqSBAIJ_ushort;
8294da8f245SBarry Smith     a->free_jshort = PETSC_TRUE;
83038702af4SBarry Smith   }
83149b5e25fSSatish Balay   PetscFunctionReturn(0);
83249b5e25fSSatish Balay }
83349b5e25fSSatish Balay 
83449b5e25fSSatish Balay /*
83549b5e25fSSatish Balay    This function returns an array of flags which indicate the locations of contiguous
83649b5e25fSSatish Balay    blocks that should be zeroed. for eg: if bs = 3  and is = [0,1,2,3,5,6,7,8,9]
837a5b23f4aSJose E. Roman    then the resulting sizes = [3,1,1,3,1] corresponding to sets [(0,1,2),(3),(5),(6,7,8),(9)]
83849b5e25fSSatish Balay    Assume: sizes should be long enough to hold all the values.
83949b5e25fSSatish Balay */
8409371c9d4SSatish Balay PetscErrorCode MatZeroRows_SeqSBAIJ_Check_Blocks(PetscInt idx[], PetscInt n, PetscInt bs, PetscInt sizes[], PetscInt *bs_max) {
84113f74950SBarry Smith   PetscInt  i, j, k, row;
842ace3abfcSBarry Smith   PetscBool flg;
84349b5e25fSSatish Balay 
84449b5e25fSSatish Balay   PetscFunctionBegin;
84549b5e25fSSatish Balay   for (i = 0, j = 0; i < n; j++) {
84649b5e25fSSatish Balay     row = idx[i];
847a5b23f4aSJose E. Roman     if (row % bs != 0) { /* Not the beginning of a block */
84849b5e25fSSatish Balay       sizes[j] = 1;
84949b5e25fSSatish Balay       i++;
85049b5e25fSSatish Balay     } else if (i + bs > n) { /* Beginning of a block, but complete block doesn't exist (at idx end) */
85149b5e25fSSatish Balay       sizes[j] = 1;          /* Also makes sure at least 'bs' values exist for next else */
85249b5e25fSSatish Balay       i++;
8536aad120cSJose E. Roman     } else { /* Beginning of the block, so check if the complete block exists */
85449b5e25fSSatish Balay       flg = PETSC_TRUE;
85549b5e25fSSatish Balay       for (k = 1; k < bs; k++) {
85649b5e25fSSatish Balay         if (row + k != idx[i + k]) { /* break in the block */
85749b5e25fSSatish Balay           flg = PETSC_FALSE;
85849b5e25fSSatish Balay           break;
85949b5e25fSSatish Balay         }
86049b5e25fSSatish Balay       }
861abc0a331SBarry Smith       if (flg) { /* No break in the bs */
86249b5e25fSSatish Balay         sizes[j] = bs;
86349b5e25fSSatish Balay         i += bs;
86449b5e25fSSatish Balay       } else {
86549b5e25fSSatish Balay         sizes[j] = 1;
86649b5e25fSSatish Balay         i++;
86749b5e25fSSatish Balay       }
86849b5e25fSSatish Balay     }
86949b5e25fSSatish Balay   }
87049b5e25fSSatish Balay   *bs_max = j;
87149b5e25fSSatish Balay   PetscFunctionReturn(0);
87249b5e25fSSatish Balay }
87349b5e25fSSatish Balay 
87449b5e25fSSatish Balay /* Only add/insert a(i,j) with i<=j (blocks).
87549b5e25fSSatish Balay    Any a(i,j) with i>j input by user is ingored.
87649b5e25fSSatish Balay */
87749b5e25fSSatish Balay 
8789371c9d4SSatish Balay PetscErrorCode MatSetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) {
87949b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
880e2ee6c50SBarry Smith   PetscInt     *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N, lastcol = -1;
88113f74950SBarry Smith   PetscInt     *imax = a->imax, *ai = a->i, *ailen = a->ilen, roworiented = a->roworiented;
882d0f46423SBarry Smith   PetscInt     *aj = a->j, nonew = a->nonew, bs = A->rmap->bs, brow, bcol;
88313f74950SBarry Smith   PetscInt      ridx, cidx, bs2                 = a->bs2;
88449b5e25fSSatish Balay   MatScalar    *ap, value, *aa                  = a->a, *bap;
88549b5e25fSSatish Balay 
88649b5e25fSSatish Balay   PetscFunctionBegin;
88749b5e25fSSatish Balay   for (k = 0; k < m; k++) { /* loop over added rows */
88849b5e25fSSatish Balay     row  = im[k];           /* row number */
88949b5e25fSSatish Balay     brow = row / bs;        /* block row number */
89049b5e25fSSatish Balay     if (row < 0) continue;
8916bdcaf15SBarry 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);
89249b5e25fSSatish Balay     rp   = aj + ai[brow];       /*ptr to beginning of column value of the row block*/
89349b5e25fSSatish Balay     ap   = aa + bs2 * ai[brow]; /*ptr to beginning of element value of the row block*/
89449b5e25fSSatish Balay     rmax = imax[brow];          /* maximum space allocated for this row */
89549b5e25fSSatish Balay     nrow = ailen[brow];         /* actual length of this row */
89649b5e25fSSatish Balay     low  = 0;
8978509e838SStefano Zampini     high = nrow;
89849b5e25fSSatish Balay     for (l = 0; l < n; l++) { /* loop over added columns */
89949b5e25fSSatish Balay       if (in[l] < 0) continue;
9006bdcaf15SBarry 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);
90149b5e25fSSatish Balay       col  = in[l];
90249b5e25fSSatish Balay       bcol = col / bs; /* block col number */
90349b5e25fSSatish Balay 
904941593c8SHong Zhang       if (brow > bcol) {
90526fbe8dcSKarl Rupp         if (a->ignore_ltriangular) continue; /* ignore lower triangular values */
90626fbe8dcSKarl 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)");
907941593c8SHong Zhang       }
908f4989cb3SHong Zhang 
9099371c9d4SSatish Balay       ridx = row % bs;
9109371c9d4SSatish Balay       cidx = col % bs; /*row and col index inside the block */
9118549e402SHong Zhang       if ((brow == bcol && ridx <= cidx) || (brow < bcol)) {
91249b5e25fSSatish Balay         /* element value a(k,l) */
91326fbe8dcSKarl Rupp         if (roworiented) value = v[l + k * n];
91426fbe8dcSKarl Rupp         else value = v[k + l * m];
91549b5e25fSSatish Balay 
91649b5e25fSSatish Balay         /* move pointer bap to a(k,l) quickly and add/insert value */
91726fbe8dcSKarl Rupp         if (col <= lastcol) low = 0;
9188509e838SStefano Zampini         else high = nrow;
9198509e838SStefano Zampini 
920e2ee6c50SBarry Smith         lastcol = col;
92149b5e25fSSatish Balay         while (high - low > 7) {
92249b5e25fSSatish Balay           t = (low + high) / 2;
92349b5e25fSSatish Balay           if (rp[t] > bcol) high = t;
92449b5e25fSSatish Balay           else low = t;
92549b5e25fSSatish Balay         }
92649b5e25fSSatish Balay         for (i = low; i < high; i++) {
92749b5e25fSSatish Balay           if (rp[i] > bcol) break;
92849b5e25fSSatish Balay           if (rp[i] == bcol) {
92949b5e25fSSatish Balay             bap = ap + bs2 * i + bs * cidx + ridx;
93049b5e25fSSatish Balay             if (is == ADD_VALUES) *bap += value;
93149b5e25fSSatish Balay             else *bap = value;
9328549e402SHong Zhang             /* for diag block, add/insert its symmetric element a(cidx,ridx) */
9338549e402SHong Zhang             if (brow == bcol && ridx < cidx) {
9348549e402SHong Zhang               bap = ap + bs2 * i + bs * ridx + cidx;
9358549e402SHong Zhang               if (is == ADD_VALUES) *bap += value;
9368549e402SHong Zhang               else *bap = value;
9378549e402SHong Zhang             }
93849b5e25fSSatish Balay             goto noinsert1;
93949b5e25fSSatish Balay           }
94049b5e25fSSatish Balay         }
94149b5e25fSSatish Balay 
94249b5e25fSSatish Balay         if (nonew == 1) goto noinsert1;
94308401ef6SPierre Jolivet         PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero (%" PetscInt_FMT ", %" PetscInt_FMT ") in the matrix", row, col);
944fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, brow, bcol, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
94549b5e25fSSatish Balay 
9469371c9d4SSatish Balay         N = nrow++ - 1;
9479371c9d4SSatish Balay         high++;
94849b5e25fSSatish Balay         /* shift up all the later entries in this row */
9499566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1));
9509566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1)));
9519566063dSJacob Faibussowitsch         PetscCall(PetscArrayzero(ap + bs2 * i, bs2));
95249b5e25fSSatish Balay         rp[i]                          = bcol;
95349b5e25fSSatish Balay         ap[bs2 * i + bs * cidx + ridx] = value;
9548509e838SStefano Zampini         /* for diag block, add/insert its symmetric element a(cidx,ridx) */
9559371c9d4SSatish Balay         if (brow == bcol && ridx < cidx) { ap[bs2 * i + bs * ridx + cidx] = value; }
956e56f5c9eSBarry Smith         A->nonzerostate++;
95749b5e25fSSatish Balay       noinsert1:;
95849b5e25fSSatish Balay         low = i;
9598549e402SHong Zhang       }
96049b5e25fSSatish Balay     } /* end of loop over added columns */
96149b5e25fSSatish Balay     ailen[brow] = nrow;
96249b5e25fSSatish Balay   } /* end of loop over added rows */
96349b5e25fSSatish Balay   PetscFunctionReturn(0);
96449b5e25fSSatish Balay }
96549b5e25fSSatish Balay 
9669371c9d4SSatish Balay PetscErrorCode MatICCFactor_SeqSBAIJ(Mat inA, IS row, const MatFactorInfo *info) {
9674ccecd49SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)inA->data;
96849b5e25fSSatish Balay   Mat           outA;
969ace3abfcSBarry Smith   PetscBool     row_identity;
97049b5e25fSSatish Balay 
97149b5e25fSSatish Balay   PetscFunctionBegin;
97208401ef6SPierre Jolivet   PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 is supported for in-place icc");
9739566063dSJacob Faibussowitsch   PetscCall(ISIdentity(row, &row_identity));
97428b400f6SJacob Faibussowitsch   PetscCheck(row_identity, PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix reordering is not supported");
97508401ef6SPierre 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()! */
976c84f5b01SHong Zhang 
97749b5e25fSSatish Balay   outA            = inA;
978d5f3da31SBarry Smith   inA->factortype = MAT_FACTOR_ICC;
9799566063dSJacob Faibussowitsch   PetscCall(PetscFree(inA->solvertype));
9809566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype));
98149b5e25fSSatish Balay 
9829566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqSBAIJ(inA));
9839566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetNumericFactorization_inplace(inA, row_identity));
98449b5e25fSSatish Balay 
9859566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
9869566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
987c84f5b01SHong Zhang   a->row = row;
9889566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
9899566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
990c84f5b01SHong Zhang   a->col = row;
991c84f5b01SHong Zhang 
992c84f5b01SHong Zhang   /* Create the invert permutation so that it can be used in MatCholeskyFactorNumeric() */
9939566063dSJacob Faibussowitsch   if (a->icol) PetscCall(ISInvertPermutation(row, PETSC_DECIDE, &a->icol));
9949566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)inA, (PetscObject)a->icol));
99549b5e25fSSatish Balay 
99649b5e25fSSatish Balay   if (!a->solve_work) {
9979566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(inA->rmap->N + inA->rmap->bs, &a->solve_work));
9989566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)inA, (inA->rmap->N + inA->rmap->bs) * sizeof(PetscScalar)));
99949b5e25fSSatish Balay   }
100049b5e25fSSatish Balay 
10019566063dSJacob Faibussowitsch   PetscCall(MatCholeskyFactorNumeric(outA, inA, info));
100249b5e25fSSatish Balay   PetscFunctionReturn(0);
100349b5e25fSSatish Balay }
1004950f1e5bSHong Zhang 
10059371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat, PetscInt *indices) {
1006045c9aa0SHong Zhang   Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)mat->data;
100713f74950SBarry Smith   PetscInt      i, nz, n;
100849b5e25fSSatish Balay 
100949b5e25fSSatish Balay   PetscFunctionBegin;
10106c6c5352SBarry Smith   nz = baij->maxnz;
1011d0f46423SBarry Smith   n  = mat->cmap->n;
101226fbe8dcSKarl Rupp   for (i = 0; i < nz; i++) baij->j[i] = indices[i];
101326fbe8dcSKarl Rupp 
10146c6c5352SBarry Smith   baij->nz = nz;
101526fbe8dcSKarl Rupp   for (i = 0; i < n; i++) baij->ilen[i] = baij->imax[i];
101626fbe8dcSKarl Rupp 
10179566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
101849b5e25fSSatish Balay   PetscFunctionReturn(0);
101949b5e25fSSatish Balay }
102049b5e25fSSatish Balay 
102149b5e25fSSatish Balay /*@
102219585528SSatish Balay   MatSeqSBAIJSetColumnIndices - Set the column indices for all the rows
102349b5e25fSSatish Balay   in the matrix.
102449b5e25fSSatish Balay 
102549b5e25fSSatish Balay   Input Parameters:
102619585528SSatish Balay   +  mat     - the SeqSBAIJ matrix
102749b5e25fSSatish Balay   -  indices - the column indices
102849b5e25fSSatish Balay 
102949b5e25fSSatish Balay   Level: advanced
103049b5e25fSSatish Balay 
103149b5e25fSSatish Balay   Notes:
103249b5e25fSSatish Balay   This can be called if you have precomputed the nonzero structure of the
103349b5e25fSSatish Balay   matrix and want to provide it to the matrix object to improve the performance
103449b5e25fSSatish Balay   of the MatSetValues() operation.
103549b5e25fSSatish Balay 
103649b5e25fSSatish Balay   You MUST have set the correct numbers of nonzeros per row in the call to
1037d1be2dadSMatthew Knepley   MatCreateSeqSBAIJ(), and the columns indices MUST be sorted.
103849b5e25fSSatish Balay 
1039ab9f2c04SSatish Balay   MUST be called before any calls to MatSetValues()
104049b5e25fSSatish Balay 
1041db781477SPatrick Sanan   .seealso: `MatCreateSeqSBAIJ`
104249b5e25fSSatish Balay @*/
10439371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetColumnIndices(Mat mat, PetscInt *indices) {
104449b5e25fSSatish Balay   PetscFunctionBegin;
10450700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1046dadcf809SJacob Faibussowitsch   PetscValidIntPointer(indices, 2);
1047cac4c232SBarry Smith   PetscUseMethod(mat, "MatSeqSBAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices));
104849b5e25fSSatish Balay   PetscFunctionReturn(0);
104949b5e25fSSatish Balay }
105049b5e25fSSatish Balay 
10519371c9d4SSatish Balay PetscErrorCode MatCopy_SeqSBAIJ(Mat A, Mat B, MatStructure str) {
10524c7a3774SStefano Zampini   PetscBool isbaij;
10533c896bc6SHong Zhang 
10543c896bc6SHong Zhang   PetscFunctionBegin;
10559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &isbaij, MATSEQSBAIJ, MATMPISBAIJ, ""));
105628b400f6SJacob Faibussowitsch   PetscCheck(isbaij, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)B)->type_name);
10574c7a3774SStefano Zampini   /* If the two matrices have the same copy implementation and nonzero pattern, use fast copy. */
10584c7a3774SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
10593c896bc6SHong Zhang     Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
10603c896bc6SHong Zhang     Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data;
10613c896bc6SHong Zhang 
106208401ef6SPierre 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");
106308401ef6SPierre Jolivet     PetscCheck(a->mbs == b->mbs, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of rows in two matrices are different");
106408401ef6SPierre Jolivet     PetscCheck(a->bs2 == b->bs2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different block size");
10659566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(b->a, a->a, a->bs2 * a->i[a->mbs]));
10669566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)B));
10673c896bc6SHong Zhang   } else {
10689566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(A));
10699566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
10709566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(A));
10713c896bc6SHong Zhang   }
10723c896bc6SHong Zhang   PetscFunctionReturn(0);
10733c896bc6SHong Zhang }
10743c896bc6SHong Zhang 
10759371c9d4SSatish Balay PetscErrorCode MatSetUp_SeqSBAIJ(Mat A) {
1076273d9f13SBarry Smith   PetscFunctionBegin;
10779566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(A, A->rmap->bs, PETSC_DEFAULT, NULL));
1078273d9f13SBarry Smith   PetscFunctionReturn(0);
1079273d9f13SBarry Smith }
1080273d9f13SBarry Smith 
10819371c9d4SSatish Balay static PetscErrorCode MatSeqSBAIJGetArray_SeqSBAIJ(Mat A, PetscScalar *array[]) {
1082a6ece127SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
10835fd66863SKarl Rupp 
1084a6ece127SHong Zhang   PetscFunctionBegin;
1085a6ece127SHong Zhang   *array = a->a;
1086a6ece127SHong Zhang   PetscFunctionReturn(0);
1087a6ece127SHong Zhang }
1088a6ece127SHong Zhang 
10899371c9d4SSatish Balay static PetscErrorCode MatSeqSBAIJRestoreArray_SeqSBAIJ(Mat A, PetscScalar *array[]) {
1090a6ece127SHong Zhang   PetscFunctionBegin;
1091cda14afcSprj-   *array = NULL;
1092a6ece127SHong Zhang   PetscFunctionReturn(0);
1093a6ece127SHong Zhang }
1094a6ece127SHong Zhang 
10959371c9d4SSatish Balay PetscErrorCode MatAXPYGetPreallocation_SeqSBAIJ(Mat Y, Mat X, PetscInt *nnz) {
1096b264fe52SHong Zhang   PetscInt      bs = Y->rmap->bs, mbs = Y->rmap->N / bs;
109752768537SHong Zhang   Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data;
109852768537SHong Zhang   Mat_SeqSBAIJ *y = (Mat_SeqSBAIJ *)Y->data;
109952768537SHong Zhang 
110052768537SHong Zhang   PetscFunctionBegin;
110152768537SHong Zhang   /* Set the number of nonzeros in the new matrix */
11029566063dSJacob Faibussowitsch   PetscCall(MatAXPYGetPreallocation_SeqX_private(mbs, x->i, x->j, y->i, y->j, nnz));
110352768537SHong Zhang   PetscFunctionReturn(0);
110452768537SHong Zhang }
110552768537SHong Zhang 
11069371c9d4SSatish Balay PetscErrorCode MatAXPY_SeqSBAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str) {
110742ee4b1aSHong Zhang   Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data, *y = (Mat_SeqSBAIJ *)Y->data;
110831ce2d13SHong Zhang   PetscInt      bs = Y->rmap->bs, bs2 = bs * bs;
1109e838b9e7SJed Brown   PetscBLASInt  one = 1;
111042ee4b1aSHong Zhang 
111142ee4b1aSHong Zhang   PetscFunctionBegin;
1112134adf20SPierre Jolivet   if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) {
1113134adf20SPierre Jolivet     PetscBool e = x->nz == y->nz && x->mbs == y->mbs ? PETSC_TRUE : PETSC_FALSE;
1114134adf20SPierre Jolivet     if (e) {
11159566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(x->i, y->i, x->mbs + 1, &e));
1116134adf20SPierre Jolivet       if (e) {
11179566063dSJacob Faibussowitsch         PetscCall(PetscArraycmp(x->j, y->j, x->i[x->mbs], &e));
1118134adf20SPierre Jolivet         if (e) str = SAME_NONZERO_PATTERN;
1119134adf20SPierre Jolivet       }
1120134adf20SPierre Jolivet     }
112154c59aa7SJacob Faibussowitsch     if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN");
1122134adf20SPierre Jolivet   }
112342ee4b1aSHong Zhang   if (str == SAME_NONZERO_PATTERN) {
1124f4df32b1SMatthew Knepley     PetscScalar  alpha = a;
1125c5df96a5SBarry Smith     PetscBLASInt bnz;
11269566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(x->nz * bs2, &bnz));
1127792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, x->a, &one, y->a, &one));
11289566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)Y));
1129ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
11309566063dSJacob Faibussowitsch     PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_TRUE));
11319566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
11329566063dSJacob Faibussowitsch     PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_FALSE));
113342ee4b1aSHong Zhang   } else {
113452768537SHong Zhang     Mat       B;
113552768537SHong Zhang     PetscInt *nnz;
113654c59aa7SJacob Faibussowitsch     PetscCheck(bs == X->rmap->bs, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Matrices must have same block size");
11379566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(X));
11389566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(Y));
11399566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Y->rmap->N, &nnz));
11409566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B));
11419566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name));
11429566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, Y->rmap->n, Y->cmap->n, Y->rmap->N, Y->cmap->N));
11439566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, Y, Y));
11449566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, ((PetscObject)Y)->type_name));
11459566063dSJacob Faibussowitsch     PetscCall(MatAXPYGetPreallocation_SeqSBAIJ(Y, X, nnz));
11469566063dSJacob Faibussowitsch     PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz));
114752768537SHong Zhang 
11489566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
114952768537SHong Zhang 
11509566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
11519566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz));
11529566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(X));
11539566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(Y));
115442ee4b1aSHong Zhang   }
115542ee4b1aSHong Zhang   PetscFunctionReturn(0);
115642ee4b1aSHong Zhang }
115742ee4b1aSHong Zhang 
11589371c9d4SSatish Balay PetscErrorCode MatIsSymmetric_SeqSBAIJ(Mat A, PetscReal tol, PetscBool *flg) {
1159efcf0fc3SBarry Smith   PetscFunctionBegin;
1160efcf0fc3SBarry Smith   *flg = PETSC_TRUE;
1161efcf0fc3SBarry Smith   PetscFunctionReturn(0);
1162efcf0fc3SBarry Smith }
1163efcf0fc3SBarry Smith 
11649371c9d4SSatish Balay PetscErrorCode MatIsStructurallySymmetric_SeqSBAIJ(Mat A, PetscBool *flg) {
1165efcf0fc3SBarry Smith   PetscFunctionBegin;
1166efcf0fc3SBarry Smith   *flg = PETSC_TRUE;
1167efcf0fc3SBarry Smith   PetscFunctionReturn(0);
1168efcf0fc3SBarry Smith }
1169efcf0fc3SBarry Smith 
11709371c9d4SSatish Balay PetscErrorCode MatIsHermitian_SeqSBAIJ(Mat A, PetscReal tol, PetscBool *flg) {
1171efcf0fc3SBarry Smith   PetscFunctionBegin;
1172efcf0fc3SBarry Smith   *flg = PETSC_FALSE;
1173efcf0fc3SBarry Smith   PetscFunctionReturn(0);
1174efcf0fc3SBarry Smith }
1175efcf0fc3SBarry Smith 
11769371c9d4SSatish Balay PetscErrorCode MatConjugate_SeqSBAIJ(Mat A) {
11772726fb6dSPierre Jolivet #if defined(PETSC_USE_COMPLEX)
11782726fb6dSPierre Jolivet   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
11792726fb6dSPierre Jolivet   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
11802726fb6dSPierre Jolivet   MatScalar    *aa = a->a;
11812726fb6dSPierre Jolivet 
11822726fb6dSPierre Jolivet   PetscFunctionBegin;
11832726fb6dSPierre Jolivet   for (i = 0; i < nz; i++) aa[i] = PetscConj(aa[i]);
11842726fb6dSPierre Jolivet #else
11852726fb6dSPierre Jolivet   PetscFunctionBegin;
11862726fb6dSPierre Jolivet #endif
11872726fb6dSPierre Jolivet   PetscFunctionReturn(0);
11882726fb6dSPierre Jolivet }
11892726fb6dSPierre Jolivet 
11909371c9d4SSatish Balay PetscErrorCode MatRealPart_SeqSBAIJ(Mat A) {
119199cafbc1SBarry Smith   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
119299cafbc1SBarry Smith   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
1193dd6ea824SBarry Smith   MatScalar    *aa = a->a;
119499cafbc1SBarry Smith 
119599cafbc1SBarry Smith   PetscFunctionBegin;
119699cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]);
119799cafbc1SBarry Smith   PetscFunctionReturn(0);
119899cafbc1SBarry Smith }
119999cafbc1SBarry Smith 
12009371c9d4SSatish Balay PetscErrorCode MatImaginaryPart_SeqSBAIJ(Mat A) {
120199cafbc1SBarry Smith   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
120299cafbc1SBarry Smith   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
1203dd6ea824SBarry Smith   MatScalar    *aa = a->a;
120499cafbc1SBarry Smith 
120599cafbc1SBarry Smith   PetscFunctionBegin;
120699cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
120799cafbc1SBarry Smith   PetscFunctionReturn(0);
120899cafbc1SBarry Smith }
120999cafbc1SBarry Smith 
12109371c9d4SSatish Balay PetscErrorCode MatZeroRowsColumns_SeqSBAIJ(Mat A, PetscInt is_n, const PetscInt is_idx[], PetscScalar diag, Vec x, Vec b) {
12113bededecSBarry Smith   Mat_SeqSBAIJ      *baij = (Mat_SeqSBAIJ *)A->data;
12123bededecSBarry Smith   PetscInt           i, j, k, count;
12133bededecSBarry Smith   PetscInt           bs = A->rmap->bs, bs2 = baij->bs2, row, col;
12143bededecSBarry Smith   PetscScalar        zero = 0.0;
12153bededecSBarry Smith   MatScalar         *aa;
12163bededecSBarry Smith   const PetscScalar *xx;
12173bededecSBarry Smith   PetscScalar       *bb;
121856777dd2SBarry Smith   PetscBool         *zeroed, vecs = PETSC_FALSE;
12193bededecSBarry Smith 
12203bededecSBarry Smith   PetscFunctionBegin;
12213bededecSBarry Smith   /* fix right hand side if needed */
12223bededecSBarry Smith   if (x && b) {
12239566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
12249566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
122556777dd2SBarry Smith     vecs = PETSC_TRUE;
12263bededecSBarry Smith   }
12273bededecSBarry Smith 
12283bededecSBarry Smith   /* zero the columns */
12299566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(A->rmap->n, &zeroed));
12303bededecSBarry Smith   for (i = 0; i < is_n; i++) {
1231aed4548fSBarry 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]);
12323bededecSBarry Smith     zeroed[is_idx[i]] = PETSC_TRUE;
12333bededecSBarry Smith   }
123456777dd2SBarry Smith   if (vecs) {
123556777dd2SBarry Smith     for (i = 0; i < A->rmap->N; i++) {
123656777dd2SBarry Smith       row = i / bs;
123756777dd2SBarry Smith       for (j = baij->i[row]; j < baij->i[row + 1]; j++) {
123856777dd2SBarry Smith         for (k = 0; k < bs; k++) {
123956777dd2SBarry Smith           col = bs * baij->j[j] + k;
124056777dd2SBarry Smith           if (col <= i) continue;
124156777dd2SBarry Smith           aa = ((MatScalar *)(baij->a)) + j * bs2 + (i % bs) + bs * k;
124226fbe8dcSKarl Rupp           if (!zeroed[i] && zeroed[col]) bb[i] -= aa[0] * xx[col];
124326fbe8dcSKarl Rupp           if (zeroed[i] && !zeroed[col]) bb[col] -= aa[0] * xx[i];
124456777dd2SBarry Smith         }
124556777dd2SBarry Smith       }
124656777dd2SBarry Smith     }
124726fbe8dcSKarl Rupp     for (i = 0; i < is_n; i++) bb[is_idx[i]] = diag * xx[is_idx[i]];
124856777dd2SBarry Smith   }
124956777dd2SBarry Smith 
12503bededecSBarry Smith   for (i = 0; i < A->rmap->N; i++) {
12513bededecSBarry Smith     if (!zeroed[i]) {
12523bededecSBarry Smith       row = i / bs;
12533bededecSBarry Smith       for (j = baij->i[row]; j < baij->i[row + 1]; j++) {
12543bededecSBarry Smith         for (k = 0; k < bs; k++) {
12553bededecSBarry Smith           col = bs * baij->j[j] + k;
12563bededecSBarry Smith           if (zeroed[col]) {
12573bededecSBarry Smith             aa    = ((MatScalar *)(baij->a)) + j * bs2 + (i % bs) + bs * k;
12583bededecSBarry Smith             aa[0] = 0.0;
12593bededecSBarry Smith           }
12603bededecSBarry Smith         }
12613bededecSBarry Smith       }
12623bededecSBarry Smith     }
12633bededecSBarry Smith   }
12649566063dSJacob Faibussowitsch   PetscCall(PetscFree(zeroed));
126556777dd2SBarry Smith   if (vecs) {
12669566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
12679566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
126856777dd2SBarry Smith   }
12693bededecSBarry Smith 
12703bededecSBarry Smith   /* zero the rows */
12713bededecSBarry Smith   for (i = 0; i < is_n; i++) {
12723bededecSBarry Smith     row   = is_idx[i];
12733bededecSBarry Smith     count = (baij->i[row / bs + 1] - baij->i[row / bs]) * bs;
12743bededecSBarry Smith     aa    = ((MatScalar *)(baij->a)) + baij->i[row / bs] * bs2 + (row % bs);
12753bededecSBarry Smith     for (k = 0; k < count; k++) {
12763bededecSBarry Smith       aa[0] = zero;
12773bededecSBarry Smith       aa += bs;
12783bededecSBarry Smith     }
1279dbbe0bcdSBarry Smith     if (diag != 0.0) PetscUseTypeMethod(A, setvalues, 1, &row, 1, &row, &diag, INSERT_VALUES);
12803bededecSBarry Smith   }
12819566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd_SeqSBAIJ(A, MAT_FINAL_ASSEMBLY));
12823bededecSBarry Smith   PetscFunctionReturn(0);
12833bededecSBarry Smith }
12843bededecSBarry Smith 
12859371c9d4SSatish Balay PetscErrorCode MatShift_SeqSBAIJ(Mat Y, PetscScalar a) {
12867d68702bSBarry Smith   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)Y->data;
12877d68702bSBarry Smith 
12887d68702bSBarry Smith   PetscFunctionBegin;
1289*48a46eb9SPierre Jolivet   if (!Y->preallocated || !aij->nz) PetscCall(MatSeqSBAIJSetPreallocation(Y, Y->rmap->bs, 1, NULL));
12909566063dSJacob Faibussowitsch   PetscCall(MatShift_Basic(Y, a));
12917d68702bSBarry Smith   PetscFunctionReturn(0);
12927d68702bSBarry Smith }
12937d68702bSBarry Smith 
129449b5e25fSSatish Balay /* -------------------------------------------------------------------*/
12953964eb88SJed Brown static struct _MatOps MatOps_Values = {MatSetValues_SeqSBAIJ,
129649b5e25fSSatish Balay                                        MatGetRow_SeqSBAIJ,
129749b5e25fSSatish Balay                                        MatRestoreRow_SeqSBAIJ,
129849b5e25fSSatish Balay                                        MatMult_SeqSBAIJ_N,
129997304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqSBAIJ_N,
1300431c96f7SBarry Smith                                        MatMult_SeqSBAIJ_N, /* transpose versions are same as non-transpose versions */
1301e005ede5SBarry Smith                                        MatMultAdd_SeqSBAIJ_N,
1302f4259b30SLisandro Dalcin                                        NULL,
1303f4259b30SLisandro Dalcin                                        NULL,
1304f4259b30SLisandro Dalcin                                        NULL,
1305f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
1306f4259b30SLisandro Dalcin                                        NULL,
1307c078aec8SLisandro Dalcin                                        MatCholeskyFactor_SeqSBAIJ,
130841f059aeSBarry Smith                                        MatSOR_SeqSBAIJ,
130949b5e25fSSatish Balay                                        MatTranspose_SeqSBAIJ,
131097304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqSBAIJ,
131149b5e25fSSatish Balay                                        MatEqual_SeqSBAIJ,
131249b5e25fSSatish Balay                                        MatGetDiagonal_SeqSBAIJ,
131349b5e25fSSatish Balay                                        MatDiagonalScale_SeqSBAIJ,
131449b5e25fSSatish Balay                                        MatNorm_SeqSBAIJ,
1315f4259b30SLisandro Dalcin                                        /* 20*/ NULL,
131649b5e25fSSatish Balay                                        MatAssemblyEnd_SeqSBAIJ,
131749b5e25fSSatish Balay                                        MatSetOption_SeqSBAIJ,
131849b5e25fSSatish Balay                                        MatZeroEntries_SeqSBAIJ,
1319f4259b30SLisandro Dalcin                                        /* 24*/ NULL,
1320f4259b30SLisandro Dalcin                                        NULL,
1321f4259b30SLisandro Dalcin                                        NULL,
1322f4259b30SLisandro Dalcin                                        NULL,
1323f4259b30SLisandro Dalcin                                        NULL,
13244994cf47SJed Brown                                        /* 29*/ MatSetUp_SeqSBAIJ,
1325f4259b30SLisandro Dalcin                                        NULL,
1326f4259b30SLisandro Dalcin                                        NULL,
1327f4259b30SLisandro Dalcin                                        NULL,
1328f4259b30SLisandro Dalcin                                        NULL,
1329d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqSBAIJ,
1330f4259b30SLisandro Dalcin                                        NULL,
1331f4259b30SLisandro Dalcin                                        NULL,
1332f4259b30SLisandro Dalcin                                        NULL,
1333c84f5b01SHong Zhang                                        MatICCFactor_SeqSBAIJ,
1334d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqSBAIJ,
13357dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqSBAIJ,
133649b5e25fSSatish Balay                                        MatIncreaseOverlap_SeqSBAIJ,
133749b5e25fSSatish Balay                                        MatGetValues_SeqSBAIJ,
13383c896bc6SHong Zhang                                        MatCopy_SeqSBAIJ,
1339f4259b30SLisandro Dalcin                                        /* 44*/ NULL,
134049b5e25fSSatish Balay                                        MatScale_SeqSBAIJ,
13417d68702bSBarry Smith                                        MatShift_SeqSBAIJ,
1342f4259b30SLisandro Dalcin                                        NULL,
13433bededecSBarry Smith                                        MatZeroRowsColumns_SeqSBAIJ,
1344f4259b30SLisandro Dalcin                                        /* 49*/ NULL,
134549b5e25fSSatish Balay                                        MatGetRowIJ_SeqSBAIJ,
134649b5e25fSSatish Balay                                        MatRestoreRowIJ_SeqSBAIJ,
1347f4259b30SLisandro Dalcin                                        NULL,
1348f4259b30SLisandro Dalcin                                        NULL,
1349f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
1350f4259b30SLisandro Dalcin                                        NULL,
1351f4259b30SLisandro Dalcin                                        NULL,
1352dc29a518SPierre Jolivet                                        MatPermute_SeqSBAIJ,
135349b5e25fSSatish Balay                                        MatSetValuesBlocked_SeqSBAIJ,
13547dae84e0SHong Zhang                                        /* 59*/ MatCreateSubMatrix_SeqSBAIJ,
1355f4259b30SLisandro Dalcin                                        NULL,
1356f4259b30SLisandro Dalcin                                        NULL,
1357f4259b30SLisandro Dalcin                                        NULL,
1358f4259b30SLisandro Dalcin                                        NULL,
1359f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
1360f4259b30SLisandro Dalcin                                        NULL,
1361f4259b30SLisandro Dalcin                                        NULL,
1362f4259b30SLisandro Dalcin                                        NULL,
1363f4259b30SLisandro Dalcin                                        NULL,
1364d519adbfSMatthew Knepley                                        /* 69*/ MatGetRowMaxAbs_SeqSBAIJ,
1365f4259b30SLisandro Dalcin                                        NULL,
136628d58a37SPierre Jolivet                                        MatConvert_MPISBAIJ_Basic,
1367f4259b30SLisandro Dalcin                                        NULL,
1368f4259b30SLisandro Dalcin                                        NULL,
1369f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
1370f4259b30SLisandro Dalcin                                        NULL,
1371f4259b30SLisandro Dalcin                                        NULL,
1372f4259b30SLisandro Dalcin                                        NULL,
1373f4259b30SLisandro Dalcin                                        NULL,
1374f4259b30SLisandro Dalcin                                        /* 79*/ NULL,
1375f4259b30SLisandro Dalcin                                        NULL,
1376f4259b30SLisandro Dalcin                                        NULL,
137797304618SKris Buschelman                                        MatGetInertia_SeqSBAIJ,
13785bba2384SShri Abhyankar                                        MatLoad_SeqSBAIJ,
1379d519adbfSMatthew Knepley                                        /* 84*/ MatIsSymmetric_SeqSBAIJ,
1380865e5f61SKris Buschelman                                        MatIsHermitian_SeqSBAIJ,
1381efcf0fc3SBarry Smith                                        MatIsStructurallySymmetric_SeqSBAIJ,
1382f4259b30SLisandro Dalcin                                        NULL,
1383f4259b30SLisandro Dalcin                                        NULL,
1384f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
1385f4259b30SLisandro Dalcin                                        NULL,
1386f4259b30SLisandro Dalcin                                        NULL,
1387f4259b30SLisandro Dalcin                                        NULL,
1388f4259b30SLisandro Dalcin                                        NULL,
1389f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
1390f4259b30SLisandro Dalcin                                        NULL,
1391f4259b30SLisandro Dalcin                                        NULL,
1392f4259b30SLisandro Dalcin                                        NULL,
1393f4259b30SLisandro Dalcin                                        NULL,
1394f4259b30SLisandro Dalcin                                        /* 99*/ NULL,
1395f4259b30SLisandro Dalcin                                        NULL,
1396f4259b30SLisandro Dalcin                                        NULL,
13972726fb6dSPierre Jolivet                                        MatConjugate_SeqSBAIJ,
1398f4259b30SLisandro Dalcin                                        NULL,
1399f4259b30SLisandro Dalcin                                        /*104*/ NULL,
140099cafbc1SBarry Smith                                        MatRealPart_SeqSBAIJ,
1401f5edf698SHong Zhang                                        MatImaginaryPart_SeqSBAIJ,
1402f5edf698SHong Zhang                                        MatGetRowUpperTriangular_SeqSBAIJ,
14032af78befSBarry Smith                                        MatRestoreRowUpperTriangular_SeqSBAIJ,
1404f4259b30SLisandro Dalcin                                        /*109*/ NULL,
1405f4259b30SLisandro Dalcin                                        NULL,
1406f4259b30SLisandro Dalcin                                        NULL,
1407f4259b30SLisandro Dalcin                                        NULL,
1408547795f9SHong Zhang                                        MatMissingDiagonal_SeqSBAIJ,
1409f4259b30SLisandro Dalcin                                        /*114*/ NULL,
1410f4259b30SLisandro Dalcin                                        NULL,
1411f4259b30SLisandro Dalcin                                        NULL,
1412f4259b30SLisandro Dalcin                                        NULL,
1413f4259b30SLisandro Dalcin                                        NULL,
1414f4259b30SLisandro Dalcin                                        /*119*/ NULL,
1415f4259b30SLisandro Dalcin                                        NULL,
1416f4259b30SLisandro Dalcin                                        NULL,
1417f4259b30SLisandro Dalcin                                        NULL,
1418f4259b30SLisandro Dalcin                                        NULL,
1419f4259b30SLisandro Dalcin                                        /*124*/ NULL,
1420f4259b30SLisandro Dalcin                                        NULL,
1421f4259b30SLisandro Dalcin                                        NULL,
1422f4259b30SLisandro Dalcin                                        NULL,
1423f4259b30SLisandro Dalcin                                        NULL,
1424f4259b30SLisandro Dalcin                                        /*129*/ NULL,
1425f4259b30SLisandro Dalcin                                        NULL,
1426f4259b30SLisandro Dalcin                                        NULL,
1427f4259b30SLisandro Dalcin                                        NULL,
1428f4259b30SLisandro Dalcin                                        NULL,
1429f4259b30SLisandro Dalcin                                        /*134*/ NULL,
1430f4259b30SLisandro Dalcin                                        NULL,
1431f4259b30SLisandro Dalcin                                        NULL,
1432f4259b30SLisandro Dalcin                                        NULL,
1433f4259b30SLisandro Dalcin                                        NULL,
143446533700Sstefano_zampini                                        /*139*/ MatSetBlockSizes_Default,
1435f4259b30SLisandro Dalcin                                        NULL,
1436f4259b30SLisandro Dalcin                                        NULL,
1437f4259b30SLisandro Dalcin                                        NULL,
1438f4259b30SLisandro Dalcin                                        NULL,
1439d70f29a3SPierre Jolivet                                        /*144*/ MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ,
1440d70f29a3SPierre Jolivet                                        NULL,
1441d70f29a3SPierre Jolivet                                        NULL,
144299a7f59eSMark Adams                                        NULL,
144399a7f59eSMark Adams                                        NULL,
14447fb60732SBarry Smith                                        NULL,
14459371c9d4SSatish Balay                                        /*150*/ NULL};
1446be1d678aSKris Buschelman 
14479371c9d4SSatish Balay PetscErrorCode MatStoreValues_SeqSBAIJ(Mat mat) {
14484afc71dfSHong Zhang   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1449d0f46423SBarry Smith   PetscInt      nz  = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2;
145049b5e25fSSatish Balay 
145149b5e25fSSatish Balay   PetscFunctionBegin;
145208401ef6SPierre Jolivet   PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
145349b5e25fSSatish Balay 
145449b5e25fSSatish Balay   /* allocate space for values if not already there */
1455*48a46eb9SPierre Jolivet   if (!aij->saved_values) PetscCall(PetscMalloc1(nz + 1, &aij->saved_values));
145649b5e25fSSatish Balay 
145749b5e25fSSatish Balay   /* copy values over */
14589566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz));
145949b5e25fSSatish Balay   PetscFunctionReturn(0);
146049b5e25fSSatish Balay }
146149b5e25fSSatish Balay 
14629371c9d4SSatish Balay PetscErrorCode MatRetrieveValues_SeqSBAIJ(Mat mat) {
14634afc71dfSHong Zhang   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1464d0f46423SBarry Smith   PetscInt      nz  = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2;
146549b5e25fSSatish Balay 
146649b5e25fSSatish Balay   PetscFunctionBegin;
146708401ef6SPierre Jolivet   PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
146828b400f6SJacob Faibussowitsch   PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first");
146949b5e25fSSatish Balay 
147049b5e25fSSatish Balay   /* copy values over */
14719566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz));
147249b5e25fSSatish Balay   PetscFunctionReturn(0);
147349b5e25fSSatish Balay }
147449b5e25fSSatish Balay 
14759371c9d4SSatish Balay static PetscErrorCode MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B, PetscInt bs, PetscInt nz, PetscInt *nnz) {
1476c464158bSHong Zhang   Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data;
14774dcd73b1SHong Zhang   PetscInt      i, mbs, nbs, bs2;
14782576faa2SJed Brown   PetscBool     skipallocation = PETSC_FALSE, flg = PETSC_FALSE, realalloc = PETSC_FALSE;
147949b5e25fSSatish Balay 
148049b5e25fSSatish Balay   PetscFunctionBegin;
14812576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
1482db4efbfdSBarry Smith 
14839566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(B, PetscAbs(bs)));
14849566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
14859566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
148608401ef6SPierre 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);
14879566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs));
1488899cda47SBarry Smith 
148921940c7eSstefano_zampini   B->preallocated = PETSC_TRUE;
149021940c7eSstefano_zampini 
1491d0f46423SBarry Smith   mbs = B->rmap->N / bs;
14924dcd73b1SHong Zhang   nbs = B->cmap->n / bs;
149349b5e25fSSatish Balay   bs2 = bs * bs;
149449b5e25fSSatish Balay 
1495aed4548fSBarry 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");
149649b5e25fSSatish Balay 
1497ab93d7beSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
1498ab93d7beSBarry Smith     skipallocation = PETSC_TRUE;
1499ab93d7beSBarry Smith     nz             = 0;
1500ab93d7beSBarry Smith   }
1501ab93d7beSBarry Smith 
1502435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3;
150308401ef6SPierre Jolivet   PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz);
150449b5e25fSSatish Balay   if (nnz) {
150549b5e25fSSatish Balay     for (i = 0; i < mbs; i++) {
150608401ef6SPierre 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]);
150708401ef6SPierre 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);
150849b5e25fSSatish Balay     }
150949b5e25fSSatish Balay   }
151049b5e25fSSatish Balay 
1511db4efbfdSBarry Smith   B->ops->mult             = MatMult_SeqSBAIJ_N;
1512db4efbfdSBarry Smith   B->ops->multadd          = MatMultAdd_SeqSBAIJ_N;
1513db4efbfdSBarry Smith   B->ops->multtranspose    = MatMult_SeqSBAIJ_N;
1514db4efbfdSBarry Smith   B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N;
151526fbe8dcSKarl Rupp 
15169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL));
151749b5e25fSSatish Balay   if (!flg) {
151849b5e25fSSatish Balay     switch (bs) {
151949b5e25fSSatish Balay     case 1:
152049b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_1;
152149b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_1;
1522431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_1;
1523431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1;
152449b5e25fSSatish Balay       break;
152549b5e25fSSatish Balay     case 2:
152649b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_2;
152749b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_2;
1528431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_2;
1529431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2;
153049b5e25fSSatish Balay       break;
153149b5e25fSSatish Balay     case 3:
153249b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_3;
153349b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_3;
1534431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_3;
1535431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3;
153649b5e25fSSatish Balay       break;
153749b5e25fSSatish Balay     case 4:
153849b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_4;
153949b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_4;
1540431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_4;
1541431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4;
154249b5e25fSSatish Balay       break;
154349b5e25fSSatish Balay     case 5:
154449b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_5;
154549b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_5;
1546431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_5;
1547431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5;
154849b5e25fSSatish Balay       break;
154949b5e25fSSatish Balay     case 6:
155049b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_6;
155149b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_6;
1552431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_6;
1553431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6;
155449b5e25fSSatish Balay       break;
155549b5e25fSSatish Balay     case 7:
1556de53e5efSHong Zhang       B->ops->mult             = MatMult_SeqSBAIJ_7;
155749b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_7;
1558431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_7;
1559431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7;
156049b5e25fSSatish Balay       break;
156149b5e25fSSatish Balay     }
156249b5e25fSSatish Balay   }
156349b5e25fSSatish Balay 
156449b5e25fSSatish Balay   b->mbs = mbs;
15654dcd73b1SHong Zhang   b->nbs = nbs;
1566ab93d7beSBarry Smith   if (!skipallocation) {
15672ee49352SLisandro Dalcin     if (!b->imax) {
15689566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(mbs, &b->imax, mbs, &b->ilen));
156926fbe8dcSKarl Rupp 
1570c760cd28SBarry Smith       b->free_imax_ilen = PETSC_TRUE;
157126fbe8dcSKarl Rupp 
15729566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)B, 2 * mbs * sizeof(PetscInt)));
15732ee49352SLisandro Dalcin     }
157449b5e25fSSatish Balay     if (!nnz) {
1575435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
157649b5e25fSSatish Balay       else if (nz <= 0) nz = 1;
15775d2a9ed1SStefano Zampini       nz = PetscMin(nbs, nz);
157826fbe8dcSKarl Rupp       for (i = 0; i < mbs; i++) b->imax[i] = nz;
15799566063dSJacob Faibussowitsch       PetscCall(PetscIntMultError(nz, mbs, &nz));
158049b5e25fSSatish Balay     } else {
1581c73702f5SBarry Smith       PetscInt64 nz64 = 0;
15829371c9d4SSatish Balay       for (i = 0; i < mbs; i++) {
15839371c9d4SSatish Balay         b->imax[i] = nnz[i];
15849371c9d4SSatish Balay         nz64 += nnz[i];
15859371c9d4SSatish Balay       }
15869566063dSJacob Faibussowitsch       PetscCall(PetscIntCast(nz64, &nz));
158749b5e25fSSatish Balay     }
15882ee49352SLisandro Dalcin     /* b->ilen will count nonzeros in each block row so far. */
158926fbe8dcSKarl Rupp     for (i = 0; i < mbs; i++) b->ilen[i] = 0;
15906c6c5352SBarry Smith     /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */
159149b5e25fSSatish Balay 
159249b5e25fSSatish Balay     /* allocate the matrix space */
15939566063dSJacob Faibussowitsch     PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i));
15949566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(bs2 * nz, &b->a, nz, &b->j, B->rmap->N + 1, &b->i));
15959566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)B, (B->rmap->N + 1) * sizeof(PetscInt) + nz * (bs2 * sizeof(PetscScalar) + sizeof(PetscInt))));
15969566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->a, nz * bs2));
15979566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->j, nz));
159826fbe8dcSKarl Rupp 
159949b5e25fSSatish Balay     b->singlemalloc = PETSC_TRUE;
160049b5e25fSSatish Balay 
160149b5e25fSSatish Balay     /* pointer to beginning of each row */
1602e60cf9a0SBarry Smith     b->i[0] = 0;
160326fbe8dcSKarl Rupp     for (i = 1; i < mbs + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1];
160426fbe8dcSKarl Rupp 
1605e6b907acSBarry Smith     b->free_a  = PETSC_TRUE;
1606e6b907acSBarry Smith     b->free_ij = PETSC_TRUE;
1607e811da20SHong Zhang   } else {
1608e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
1609e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
1610ab93d7beSBarry Smith   }
161149b5e25fSSatish Balay 
161249b5e25fSSatish Balay   b->bs2     = bs2;
16136c6c5352SBarry Smith   b->nz      = 0;
1614b32cb4a7SJed Brown   b->maxnz   = nz;
1615f4259b30SLisandro Dalcin   b->inew    = NULL;
1616f4259b30SLisandro Dalcin   b->jnew    = NULL;
1617f4259b30SLisandro Dalcin   b->anew    = NULL;
1618f4259b30SLisandro Dalcin   b->a2anew  = NULL;
16191a3463dfSHong Zhang   b->permute = PETSC_FALSE;
1620cb7b82ddSBarry Smith 
1621cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
1622cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
16239566063dSJacob Faibussowitsch   if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
1624c464158bSHong Zhang   PetscFunctionReturn(0);
1625c464158bSHong Zhang }
1626153ea458SHong Zhang 
16279371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ(Mat B, PetscInt bs, const PetscInt ii[], const PetscInt jj[], const PetscScalar V[]) {
16280cd7f59aSBarry Smith   PetscInt     i, j, m, nz, anz, nz_max = 0, *nnz;
1629f4259b30SLisandro Dalcin   PetscScalar *values      = NULL;
163038f409ebSLisandro Dalcin   PetscBool    roworiented = ((Mat_SeqSBAIJ *)B->data)->roworiented;
16310cd7f59aSBarry Smith 
163238f409ebSLisandro Dalcin   PetscFunctionBegin;
163308401ef6SPierre Jolivet   PetscCheck(bs >= 1, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_OUTOFRANGE, "Invalid block size specified, must be positive but it is %" PetscInt_FMT, bs);
16349566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(B->rmap, bs));
16359566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(B->cmap, bs));
16369566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
16379566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
16389566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs));
163938f409ebSLisandro Dalcin   m = B->rmap->n / bs;
164038f409ebSLisandro Dalcin 
1641aed4548fSBarry Smith   PetscCheck(!ii[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ii[0] must be 0 but it is %" PetscInt_FMT, ii[0]);
16429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &nnz));
164338f409ebSLisandro Dalcin   for (i = 0; i < m; i++) {
164438f409ebSLisandro Dalcin     nz = ii[i + 1] - ii[i];
164508401ef6SPierre Jolivet     PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz);
16460cd7f59aSBarry Smith     anz = 0;
16470cd7f59aSBarry Smith     for (j = 0; j < nz; j++) {
16480cd7f59aSBarry Smith       /* count only values on the diagonal or above */
16490cd7f59aSBarry Smith       if (jj[ii[i] + j] >= i) {
16500cd7f59aSBarry Smith         anz = nz - j;
16510cd7f59aSBarry Smith         break;
16520cd7f59aSBarry Smith       }
16530cd7f59aSBarry Smith     }
16540cd7f59aSBarry Smith     nz_max = PetscMax(nz_max, anz);
16550cd7f59aSBarry Smith     nnz[i] = anz;
165638f409ebSLisandro Dalcin   }
16579566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz));
16589566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
165938f409ebSLisandro Dalcin 
166038f409ebSLisandro Dalcin   values = (PetscScalar *)V;
1661*48a46eb9SPierre Jolivet   if (!values) PetscCall(PetscCalloc1(bs * bs * nz_max, &values));
166238f409ebSLisandro Dalcin   for (i = 0; i < m; i++) {
166338f409ebSLisandro Dalcin     PetscInt        ncols = ii[i + 1] - ii[i];
166438f409ebSLisandro Dalcin     const PetscInt *icols = jj + ii[i];
166538f409ebSLisandro Dalcin     if (!roworiented || bs == 1) {
166638f409ebSLisandro Dalcin       const PetscScalar *svals = values + (V ? (bs * bs * ii[i]) : 0);
16679566063dSJacob Faibussowitsch       PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, ncols, icols, svals, INSERT_VALUES));
166838f409ebSLisandro Dalcin     } else {
166938f409ebSLisandro Dalcin       for (j = 0; j < ncols; j++) {
167038f409ebSLisandro Dalcin         const PetscScalar *svals = values + (V ? (bs * bs * (ii[i] + j)) : 0);
16719566063dSJacob Faibussowitsch         PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, 1, &icols[j], svals, INSERT_VALUES));
167238f409ebSLisandro Dalcin       }
167338f409ebSLisandro Dalcin     }
167438f409ebSLisandro Dalcin   }
16759566063dSJacob Faibussowitsch   if (!V) PetscCall(PetscFree(values));
16769566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
16779566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
16789566063dSJacob Faibussowitsch   PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
167938f409ebSLisandro Dalcin   PetscFunctionReturn(0);
168038f409ebSLisandro Dalcin }
168138f409ebSLisandro Dalcin 
1682db4efbfdSBarry Smith /*
1683db4efbfdSBarry Smith    This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization
1684db4efbfdSBarry Smith */
16859371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetNumericFactorization_inplace(Mat B, PetscBool natural) {
1686ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
1687db4efbfdSBarry Smith   PetscInt  bs  = B->rmap->bs;
1688db4efbfdSBarry Smith 
1689db4efbfdSBarry Smith   PetscFunctionBegin;
16909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL));
1691db4efbfdSBarry Smith   if (flg) bs = 8;
1692db4efbfdSBarry Smith 
1693db4efbfdSBarry Smith   if (!natural) {
1694db4efbfdSBarry Smith     switch (bs) {
16959371c9d4SSatish Balay     case 1: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_inplace; break;
16969371c9d4SSatish Balay     case 2: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2; break;
16979371c9d4SSatish Balay     case 3: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3; break;
16989371c9d4SSatish Balay     case 4: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4; break;
16999371c9d4SSatish Balay     case 5: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5; break;
17009371c9d4SSatish Balay     case 6: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6; break;
17019371c9d4SSatish Balay     case 7: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7; break;
17029371c9d4SSatish Balay     default: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N; break;
1703db4efbfdSBarry Smith     }
1704db4efbfdSBarry Smith   } else {
1705db4efbfdSBarry Smith     switch (bs) {
17069371c9d4SSatish Balay     case 1: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering_inplace; break;
17079371c9d4SSatish Balay     case 2: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering; break;
17089371c9d4SSatish Balay     case 3: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering; break;
17099371c9d4SSatish Balay     case 4: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering; break;
17109371c9d4SSatish Balay     case 5: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering; break;
17119371c9d4SSatish Balay     case 6: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering; break;
17129371c9d4SSatish Balay     case 7: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering; break;
17139371c9d4SSatish Balay     default: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering; break;
1714db4efbfdSBarry Smith     }
1715db4efbfdSBarry Smith   }
1716db4efbfdSBarry Smith   PetscFunctionReturn(0);
1717db4efbfdSBarry Smith }
1718db4efbfdSBarry Smith 
1719cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType, MatReuse, Mat *);
1720cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType, MatReuse, Mat *);
17219371c9d4SSatish Balay static PetscErrorCode       MatFactorGetSolverType_petsc(Mat A, MatSolverType *type) {
17224ac6704cSBarry Smith         PetscFunctionBegin;
17234ac6704cSBarry Smith         *type = MATSOLVERPETSC;
17244ac6704cSBarry Smith         PetscFunctionReturn(0);
17254ac6704cSBarry Smith }
1726d769727bSBarry Smith 
17279371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A, MatFactorType ftype, Mat *B) {
1728d0f46423SBarry Smith   PetscInt n = A->rmap->n;
17295c9eb25fSBarry Smith 
17305c9eb25fSBarry Smith   PetscFunctionBegin;
17310e92d65fSHong Zhang #if defined(PETSC_USE_COMPLEX)
1732b94d7dedSBarry 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");
17330e92d65fSHong Zhang #endif
1734eb1ec7c1SStefano Zampini 
17359566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B));
17369566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*B, n, n, n, n));
17375c9eb25fSBarry Smith   if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
17389566063dSJacob Faibussowitsch     PetscCall(MatSetType(*B, MATSEQSBAIJ));
17399566063dSJacob Faibussowitsch     PetscCall(MatSeqSBAIJSetPreallocation(*B, A->rmap->bs, MAT_SKIP_ALLOCATION, NULL));
174026fbe8dcSKarl Rupp 
17417b056e98SHong Zhang     (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ;
1742c6d0d4f0SHong Zhang     (*B)->ops->iccfactorsymbolic      = MatICCFactorSymbolic_SeqSBAIJ;
17439566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_CHOLESKY]));
17449566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_ICC]));
1745e32f2f54SBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Factor type not supported");
174600c67f3bSHong Zhang 
1747d5f3da31SBarry Smith   (*B)->factortype     = ftype;
1748f73b0415SBarry Smith   (*B)->canuseordering = PETSC_TRUE;
17499566063dSJacob Faibussowitsch   PetscCall(PetscFree((*B)->solvertype));
17509566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*B)->solvertype));
17519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)*B, "MatFactorGetSolverType_C", MatFactorGetSolverType_petsc));
17525c9eb25fSBarry Smith   PetscFunctionReturn(0);
17535c9eb25fSBarry Smith }
17545c9eb25fSBarry Smith 
17558397e458SBarry Smith /*@C
17568397e458SBarry Smith    MatSeqSBAIJGetArray - gives access to the array where the data for a MATSEQSBAIJ matrix is stored
17578397e458SBarry Smith 
17588397e458SBarry Smith    Not Collective
17598397e458SBarry Smith 
17608397e458SBarry Smith    Input Parameter:
17618397e458SBarry Smith .  mat - a MATSEQSBAIJ matrix
17628397e458SBarry Smith 
17638397e458SBarry Smith    Output Parameter:
17648397e458SBarry Smith .   array - pointer to the data
17658397e458SBarry Smith 
17668397e458SBarry Smith    Level: intermediate
17678397e458SBarry Smith 
1768db781477SPatrick Sanan .seealso: `MatSeqSBAIJRestoreArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`
17698397e458SBarry Smith @*/
17709371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJGetArray(Mat A, PetscScalar **array) {
17718397e458SBarry Smith   PetscFunctionBegin;
1772cac4c232SBarry Smith   PetscUseMethod(A, "MatSeqSBAIJGetArray_C", (Mat, PetscScalar **), (A, array));
17738397e458SBarry Smith   PetscFunctionReturn(0);
17748397e458SBarry Smith }
17758397e458SBarry Smith 
17768397e458SBarry Smith /*@C
17778397e458SBarry Smith    MatSeqSBAIJRestoreArray - returns access to the array where the data for a MATSEQSBAIJ matrix is stored obtained by MatSeqSBAIJGetArray()
17788397e458SBarry Smith 
17798397e458SBarry Smith    Not Collective
17808397e458SBarry Smith 
17818397e458SBarry Smith    Input Parameters:
1782a2b725a8SWilliam Gropp +  mat - a MATSEQSBAIJ matrix
1783a2b725a8SWilliam Gropp -  array - pointer to the data
17848397e458SBarry Smith 
17858397e458SBarry Smith    Level: intermediate
17868397e458SBarry Smith 
1787db781477SPatrick Sanan .seealso: `MatSeqSBAIJGetArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`
17888397e458SBarry Smith @*/
17899371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJRestoreArray(Mat A, PetscScalar **array) {
17908397e458SBarry Smith   PetscFunctionBegin;
1791cac4c232SBarry Smith   PetscUseMethod(A, "MatSeqSBAIJRestoreArray_C", (Mat, PetscScalar **), (A, array));
17928397e458SBarry Smith   PetscFunctionReturn(0);
17938397e458SBarry Smith }
17948397e458SBarry Smith 
17950bad9183SKris Buschelman /*MC
1796fafad747SKris Buschelman   MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices,
17970bad9183SKris Buschelman   based on block compressed sparse row format.  Only the upper triangular portion of the matrix is stored.
17980bad9183SKris Buschelman 
1799828413b8SBarry Smith   For complex numbers by default this matrix is symmetric, NOT Hermitian symmetric. To make it Hermitian symmetric you
1800eb1ec7c1SStefano Zampini   can call MatSetOption(Mat, MAT_HERMITIAN).
1801828413b8SBarry Smith 
18020bad9183SKris Buschelman   Options Database Keys:
18030bad9183SKris Buschelman   . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to MatSetFromOptions()
18040bad9183SKris Buschelman 
180595452b02SPatrick Sanan   Notes:
180695452b02SPatrick Sanan     By default if you insert values into the lower triangular part of the matrix they are simply ignored (since they are not
180771dad5bbSBarry 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
180871dad5bbSBarry 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.
180971dad5bbSBarry Smith 
1810476417e5SBarry Smith     The number of rows in the matrix must be less than or equal to the number of columns
181171dad5bbSBarry Smith 
18120bad9183SKris Buschelman   Level: beginner
18130bad9183SKris Buschelman 
1814db781477SPatrick Sanan   .seealso: `MatCreateSeqSBAIJ()`, `MatType`, `MATMPISBAIJ`
18150bad9183SKris Buschelman M*/
18169371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_SeqSBAIJ(Mat B) {
1817a23d5eceSKris Buschelman   Mat_SeqSBAIJ *b;
181813f74950SBarry Smith   PetscMPIInt   size;
1819ace3abfcSBarry Smith   PetscBool     no_unroll = PETSC_FALSE, no_inode = PETSC_FALSE;
1820a23d5eceSKris Buschelman 
1821a23d5eceSKris Buschelman   PetscFunctionBegin;
18229566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
182308401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
1824a23d5eceSKris Buschelman 
18259566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(B, &b));
1826a23d5eceSKris Buschelman   B->data = (void *)b;
18279566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(B->ops, &MatOps_Values, sizeof(struct _MatOps)));
182826fbe8dcSKarl Rupp 
1829a23d5eceSKris Buschelman   B->ops->destroy    = MatDestroy_SeqSBAIJ;
1830a23d5eceSKris Buschelman   B->ops->view       = MatView_SeqSBAIJ;
1831f4259b30SLisandro Dalcin   b->row             = NULL;
1832f4259b30SLisandro Dalcin   b->icol            = NULL;
1833a23d5eceSKris Buschelman   b->reallocs        = 0;
1834f4259b30SLisandro Dalcin   b->saved_values    = NULL;
18350def2e27SBarry Smith   b->inode.limit     = 5;
18360def2e27SBarry Smith   b->inode.max_limit = 5;
1837a23d5eceSKris Buschelman 
1838a23d5eceSKris Buschelman   b->roworiented        = PETSC_TRUE;
1839a23d5eceSKris Buschelman   b->nonew              = 0;
1840f4259b30SLisandro Dalcin   b->diag               = NULL;
1841f4259b30SLisandro Dalcin   b->solve_work         = NULL;
1842f4259b30SLisandro Dalcin   b->mult_work          = NULL;
1843f4259b30SLisandro Dalcin   B->spptr              = NULL;
1844f2cbd3d5SJed Brown   B->info.nz_unneeded   = (PetscReal)b->maxnz * b->bs2;
1845a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
1846a23d5eceSKris Buschelman 
1847f4259b30SLisandro Dalcin   b->inew    = NULL;
1848f4259b30SLisandro Dalcin   b->jnew    = NULL;
1849f4259b30SLisandro Dalcin   b->anew    = NULL;
1850f4259b30SLisandro Dalcin   b->a2anew  = NULL;
1851a23d5eceSKris Buschelman   b->permute = PETSC_FALSE;
1852a23d5eceSKris Buschelman 
185371dad5bbSBarry Smith   b->ignore_ltriangular = PETSC_TRUE;
185426fbe8dcSKarl Rupp 
18559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_ignore_lower_triangular", &b->ignore_ltriangular, NULL));
1856941593c8SHong Zhang 
1857f5edf698SHong Zhang   b->getrow_utriangular = PETSC_FALSE;
185826fbe8dcSKarl Rupp 
18599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_getrow_uppertriangular", &b->getrow_utriangular, NULL));
1860f5edf698SHong Zhang 
18619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJGetArray_C", MatSeqSBAIJGetArray_SeqSBAIJ));
18629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJRestoreArray_C", MatSeqSBAIJRestoreArray_SeqSBAIJ));
18639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqSBAIJ));
18649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqSBAIJ));
18659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetColumnIndices_C", MatSeqSBAIJSetColumnIndices_SeqSBAIJ));
18669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqaij_C", MatConvert_SeqSBAIJ_SeqAIJ));
18679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqbaij_C", MatConvert_SeqSBAIJ_SeqBAIJ));
18689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocation_C", MatSeqSBAIJSetPreallocation_SeqSBAIJ));
18699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocationCSR_C", MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ));
18706214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
18719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_elemental_C", MatConvert_SeqSBAIJ_Elemental));
18726214f412SHong Zhang #endif
1873d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
18749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_scalapack_C", MatConvert_SBAIJ_ScaLAPACK));
1875d24d4204SJose E. Roman #endif
187623ce1328SBarry Smith 
1877b94d7dedSBarry Smith   B->symmetry_eternal            = PETSC_TRUE;
1878b94d7dedSBarry Smith   B->structural_symmetry_eternal = PETSC_TRUE;
1879b94d7dedSBarry Smith   B->symmetric                   = PETSC_BOOL3_TRUE;
1880b94d7dedSBarry Smith   B->structurally_symmetric      = PETSC_BOOL3_TRUE;
1881eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1882b94d7dedSBarry Smith   B->hermitian = PETSC_BOOL3_FALSE;
1883eb1ec7c1SStefano Zampini #else
1884b94d7dedSBarry Smith   B->hermitian = PETSC_BOOL3_TRUE;
1885eb1ec7c1SStefano Zampini #endif
188613647f61SHong Zhang 
18879566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQSBAIJ));
18880def2e27SBarry Smith 
1889d0609cedSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)B), ((PetscObject)B)->prefix, "Options for SEQSBAIJ matrix", "Mat");
18909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_no_unroll", "Do not optimize for inodes (slower)", NULL, no_unroll, &no_unroll, NULL));
1891*48a46eb9SPierre Jolivet   if (no_unroll) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_unroll\n"));
18929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_no_inode", "Do not optimize for inodes (slower)", NULL, no_inode, &no_inode, NULL));
18939566063dSJacob Faibussowitsch   if (no_inode) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_inode\n"));
18949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-mat_inode_limit", "Do not use inodes larger then this value", NULL, b->inode.limit, &b->inode.limit, NULL));
1895d0609cedSBarry Smith   PetscOptionsEnd();
1896ace3abfcSBarry Smith   b->inode.use = (PetscBool)(!(no_unroll || no_inode));
18970def2e27SBarry Smith   if (b->inode.limit > b->inode.max_limit) b->inode.limit = b->inode.max_limit;
1898a23d5eceSKris Buschelman   PetscFunctionReturn(0);
1899a23d5eceSKris Buschelman }
1900a23d5eceSKris Buschelman 
1901a23d5eceSKris Buschelman /*@C
1902a23d5eceSKris Buschelman    MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block
1903a23d5eceSKris Buschelman    compressed row) format.  For good matrix assembly performance the
1904a23d5eceSKris Buschelman    user should preallocate the matrix storage by setting the parameter nz
1905a23d5eceSKris Buschelman    (or the array nnz).  By setting these parameters accurately, performance
1906a23d5eceSKris Buschelman    during matrix assembly can be increased by more than a factor of 50.
1907a23d5eceSKris Buschelman 
1908a23d5eceSKris Buschelman    Collective on Mat
1909a23d5eceSKris Buschelman 
1910a23d5eceSKris Buschelman    Input Parameters:
19111c4f3114SJed Brown +  B - the symmetric matrix
1912bb7ae925SBarry 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
1913bb7ae925SBarry Smith           blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with MatCreateVecs()
1914a23d5eceSKris Buschelman .  nz - number of block nonzeros per block row (same for all rows)
1915a23d5eceSKris Buschelman -  nnz - array containing the number of block nonzeros in the upper triangular plus
19160298fd71SBarry Smith          diagonal portion of each block (possibly different for each block row) or NULL
1917a23d5eceSKris Buschelman 
1918a23d5eceSKris Buschelman    Options Database Keys:
1919a2b725a8SWilliam Gropp +   -mat_no_unroll - uses code that does not unroll the loops in the
1920a23d5eceSKris Buschelman                      block calculations (much slower)
1921a2b725a8SWilliam Gropp -   -mat_block_size - size of the blocks to use (only works if a negative bs is passed in
1922a23d5eceSKris Buschelman 
1923a23d5eceSKris Buschelman    Level: intermediate
1924a23d5eceSKris Buschelman 
1925a23d5eceSKris Buschelman    Notes:
1926a23d5eceSKris Buschelman    Specify the preallocated storage with either nz or nnz (not both).
19270298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
1928a7f22e61SSatish Balay    allocation.  See Users-Manual: ch_mat for details.
1929a23d5eceSKris Buschelman 
1930aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
1931aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
1932aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
1933aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
1934aa95bbe8SBarry Smith 
193549a6f317SBarry Smith    If the nnz parameter is given then the nz parameter is ignored
193649a6f317SBarry Smith 
1937db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()`
1938a23d5eceSKris Buschelman @*/
19399371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetPreallocation(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[]) {
1940a23d5eceSKris Buschelman   PetscFunctionBegin;
19416ba663aaSJed Brown   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
19426ba663aaSJed Brown   PetscValidType(B, 1);
19436ba663aaSJed Brown   PetscValidLogicalCollectiveInt(B, bs, 2);
1944cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqSBAIJSetPreallocation_C", (Mat, PetscInt, PetscInt, const PetscInt[]), (B, bs, nz, nnz));
1945a23d5eceSKris Buschelman   PetscFunctionReturn(0);
1946a23d5eceSKris Buschelman }
194749b5e25fSSatish Balay 
194838f409ebSLisandro Dalcin /*@C
1949664954b6SBarry Smith    MatSeqSBAIJSetPreallocationCSR - Creates a sparse parallel matrix in SBAIJ format using the given nonzero structure and (optional) numerical values
195038f409ebSLisandro Dalcin 
195138f409ebSLisandro Dalcin    Input Parameters:
19521c4f3114SJed Brown +  B - the matrix
1953eab78319SHong Zhang .  bs - size of block, the blocks are ALWAYS square.
195438f409ebSLisandro Dalcin .  i - the indices into j for the start of each local row (starts with zero)
195538f409ebSLisandro Dalcin .  j - the column indices for each local row (starts with zero) these must be sorted for each row
195638f409ebSLisandro Dalcin -  v - optional values in the matrix
195738f409ebSLisandro Dalcin 
1958664954b6SBarry Smith    Level: advanced
195938f409ebSLisandro Dalcin 
196038f409ebSLisandro Dalcin    Notes:
196138f409ebSLisandro Dalcin    The order of the entries in values is specified by the MatOption MAT_ROW_ORIENTED.  For example, C programs
196238f409ebSLisandro Dalcin    may want to use the default MAT_ROW_ORIENTED=PETSC_TRUE and use an array v[nnz][bs][bs] where the second index is
196338f409ebSLisandro Dalcin    over rows within a block and the last index is over columns within a block row.  Fortran programs will likely set
196438f409ebSLisandro Dalcin    MAT_ROW_ORIENTED=PETSC_FALSE and use a Fortran array v(bs,bs,nnz) in which the first index is over rows within a
196538f409ebSLisandro Dalcin    block column and the second index is over columns within a block.
196638f409ebSLisandro Dalcin 
196750c5228eSBarry Smith    Any entries below the diagonal are ignored
19680cd7f59aSBarry Smith 
19690cd7f59aSBarry Smith    Though this routine has Preallocation() in the name it also sets the exact nonzero locations of the matrix entries
19700cd7f59aSBarry Smith    and usually the numerical values as well
1971664954b6SBarry Smith 
1972db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqSBAIJ()`, `MatSetValuesBlocked()`, `MatSeqSBAIJSetPreallocation()`, `MATSEQSBAIJ`
197338f409ebSLisandro Dalcin @*/
19749371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetPreallocationCSR(Mat B, PetscInt bs, const PetscInt i[], const PetscInt j[], const PetscScalar v[]) {
197538f409ebSLisandro Dalcin   PetscFunctionBegin;
197638f409ebSLisandro Dalcin   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
197738f409ebSLisandro Dalcin   PetscValidType(B, 1);
197838f409ebSLisandro Dalcin   PetscValidLogicalCollectiveInt(B, bs, 2);
1979cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqSBAIJSetPreallocationCSR_C", (Mat, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, bs, i, j, v));
198038f409ebSLisandro Dalcin   PetscFunctionReturn(0);
198138f409ebSLisandro Dalcin }
198238f409ebSLisandro Dalcin 
1983c464158bSHong Zhang /*@C
1984c464158bSHong Zhang    MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in block AIJ (block
1985c464158bSHong Zhang    compressed row) format.  For good matrix assembly performance the
1986c464158bSHong Zhang    user should preallocate the matrix storage by setting the parameter nz
1987c464158bSHong Zhang    (or the array nnz).  By setting these parameters accurately, performance
1988c464158bSHong Zhang    during matrix assembly can be increased by more than a factor of 50.
198949b5e25fSSatish Balay 
1990d083f849SBarry Smith    Collective
1991c464158bSHong Zhang 
1992c464158bSHong Zhang    Input Parameters:
1993c464158bSHong Zhang +  comm - MPI communicator, set to PETSC_COMM_SELF
1994bb7ae925SBarry 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
1995bb7ae925SBarry Smith           blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with MatCreateVecs()
1996c464158bSHong Zhang .  m - number of rows, or number of columns
1997c464158bSHong Zhang .  nz - number of block nonzeros per block row (same for all rows)
1998744e8345SSatish Balay -  nnz - array containing the number of block nonzeros in the upper triangular plus
19990298fd71SBarry Smith          diagonal portion of each block (possibly different for each block row) or NULL
2000c464158bSHong Zhang 
2001c464158bSHong Zhang    Output Parameter:
2002c464158bSHong Zhang .  A - the symmetric matrix
2003c464158bSHong Zhang 
2004c464158bSHong Zhang    Options Database Keys:
2005a2b725a8SWilliam Gropp +   -mat_no_unroll - uses code that does not unroll the loops in the
2006c464158bSHong Zhang                      block calculations (much slower)
2007a2b725a8SWilliam Gropp -   -mat_block_size - size of the blocks to use
2008c464158bSHong Zhang 
2009c464158bSHong Zhang    Level: intermediate
2010c464158bSHong Zhang 
2011175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
2012f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
2013175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
2014175b88e8SBarry Smith 
2015c464158bSHong Zhang    Notes:
20166d6d819aSHong Zhang    The number of rows and columns must be divisible by blocksize.
20176d6d819aSHong Zhang    This matrix type does not support complex Hermitian operation.
2018c464158bSHong Zhang 
2019c464158bSHong Zhang    Specify the preallocated storage with either nz or nnz (not both).
20200298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
2021a7f22e61SSatish Balay    allocation.  See Users-Manual: ch_mat for details.
2022c464158bSHong Zhang 
202349a6f317SBarry Smith    If the nnz parameter is given then the nz parameter is ignored
202449a6f317SBarry Smith 
2025db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()`
2026c464158bSHong Zhang @*/
20279371c9d4SSatish Balay PetscErrorCode MatCreateSeqSBAIJ(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A) {
2028c464158bSHong Zhang   PetscFunctionBegin;
20299566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
20309566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
20319566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQSBAIJ));
20329566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*A, bs, nz, (PetscInt *)nnz));
203349b5e25fSSatish Balay   PetscFunctionReturn(0);
203449b5e25fSSatish Balay }
203549b5e25fSSatish Balay 
20369371c9d4SSatish Balay PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B) {
203749b5e25fSSatish Balay   Mat           C;
203849b5e25fSSatish Balay   Mat_SeqSBAIJ *c, *a  = (Mat_SeqSBAIJ *)A->data;
2039b40805acSSatish Balay   PetscInt      i, mbs = a->mbs, nz = a->nz, bs2 = a->bs2;
204049b5e25fSSatish Balay 
204149b5e25fSSatish Balay   PetscFunctionBegin;
204208401ef6SPierre Jolivet   PetscCheck(a->i[mbs] == nz, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupt matrix");
204349b5e25fSSatish Balay 
2044f4259b30SLisandro Dalcin   *B = NULL;
20459566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
20469566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, A->rmap->N, A->cmap->n, A->rmap->N, A->cmap->n));
20479566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(C, A, A));
20489566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATSEQSBAIJ));
2049692f9cbeSHong Zhang   c = (Mat_SeqSBAIJ *)C->data;
2050692f9cbeSHong Zhang 
2051273d9f13SBarry Smith   C->preallocated       = PETSC_TRUE;
2052d5f3da31SBarry Smith   C->factortype         = A->factortype;
2053f4259b30SLisandro Dalcin   c->row                = NULL;
2054f4259b30SLisandro Dalcin   c->icol               = NULL;
2055f4259b30SLisandro Dalcin   c->saved_values       = NULL;
2056a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
205749b5e25fSSatish Balay   C->assembled          = PETSC_TRUE;
205849b5e25fSSatish Balay 
20599566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->rmap, &C->rmap));
20609566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap, &C->cmap));
206149b5e25fSSatish Balay   c->bs2 = a->bs2;
206249b5e25fSSatish Balay   c->mbs = a->mbs;
206349b5e25fSSatish Balay   c->nbs = a->nbs;
206449b5e25fSSatish Balay 
2065c760cd28SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2066c760cd28SBarry Smith     c->imax           = a->imax;
2067c760cd28SBarry Smith     c->ilen           = a->ilen;
2068c760cd28SBarry Smith     c->free_imax_ilen = PETSC_FALSE;
2069c760cd28SBarry Smith   } else {
20709566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2((mbs + 1), &c->imax, (mbs + 1), &c->ilen));
20719566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)C, 2 * (mbs + 1) * sizeof(PetscInt)));
207249b5e25fSSatish Balay     for (i = 0; i < mbs; i++) {
207349b5e25fSSatish Balay       c->imax[i] = a->imax[i];
207449b5e25fSSatish Balay       c->ilen[i] = a->ilen[i];
207549b5e25fSSatish Balay     }
2076c760cd28SBarry Smith     c->free_imax_ilen = PETSC_TRUE;
2077c760cd28SBarry Smith   }
207849b5e25fSSatish Balay 
207949b5e25fSSatish Balay   /* allocate the matrix space */
20804da8f245SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
20819566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(bs2 * nz, &c->a));
20829566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)C, nz * bs2 * sizeof(MatScalar)));
208344e1c64aSLisandro Dalcin     c->i            = a->i;
208444e1c64aSLisandro Dalcin     c->j            = a->j;
20854da8f245SBarry Smith     c->singlemalloc = PETSC_FALSE;
208644e1c64aSLisandro Dalcin     c->free_a       = PETSC_TRUE;
20874da8f245SBarry Smith     c->free_ij      = PETSC_FALSE;
20884da8f245SBarry Smith     c->parent       = A;
20899566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)A));
20909566063dSJacob Faibussowitsch     PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
20919566063dSJacob Faibussowitsch     PetscCall(MatSetOption(C, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
20924da8f245SBarry Smith   } else {
20939566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(bs2 * nz, &c->a, nz, &c->j, mbs + 1, &c->i));
20949566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(c->i, a->i, mbs + 1));
20959566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)C, (mbs + 1) * sizeof(PetscInt) + nz * (bs2 * sizeof(MatScalar) + sizeof(PetscInt))));
20964da8f245SBarry Smith     c->singlemalloc = PETSC_TRUE;
209744e1c64aSLisandro Dalcin     c->free_a       = PETSC_TRUE;
20984da8f245SBarry Smith     c->free_ij      = PETSC_TRUE;
20994da8f245SBarry Smith   }
210049b5e25fSSatish Balay   if (mbs > 0) {
2101*48a46eb9SPierre Jolivet     if (cpvalues != MAT_SHARE_NONZERO_PATTERN) PetscCall(PetscArraycpy(c->j, a->j, nz));
210249b5e25fSSatish Balay     if (cpvalues == MAT_COPY_VALUES) {
21039566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->a, a->a, bs2 * nz));
210449b5e25fSSatish Balay     } else {
21059566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(c->a, bs2 * nz));
210649b5e25fSSatish Balay     }
2107a1c3900fSBarry Smith     if (a->jshort) {
210844e1c64aSLisandro Dalcin       /* cannot share jshort, it is reallocated in MatAssemblyEnd_SeqSBAIJ() */
210944e1c64aSLisandro Dalcin       /* if the parent matrix is reassembled, this child matrix will never notice */
21109566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz, &c->jshort));
21119566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)C, nz * sizeof(unsigned short)));
21129566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->jshort, a->jshort, nz));
211326fbe8dcSKarl Rupp 
21144da8f245SBarry Smith       c->free_jshort = PETSC_TRUE;
21154da8f245SBarry Smith     }
2116a1c3900fSBarry Smith   }
211749b5e25fSSatish Balay 
211849b5e25fSSatish Balay   c->roworiented = a->roworiented;
211949b5e25fSSatish Balay   c->nonew       = a->nonew;
212049b5e25fSSatish Balay 
212149b5e25fSSatish Balay   if (a->diag) {
2122c760cd28SBarry Smith     if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2123c760cd28SBarry Smith       c->diag      = a->diag;
2124c760cd28SBarry Smith       c->free_diag = PETSC_FALSE;
2125c760cd28SBarry Smith     } else {
21269566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mbs, &c->diag));
21279566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)C, mbs * sizeof(PetscInt)));
212826fbe8dcSKarl Rupp       for (i = 0; i < mbs; i++) c->diag[i] = a->diag[i];
2129c760cd28SBarry Smith       c->free_diag = PETSC_TRUE;
2130c760cd28SBarry Smith     }
213144e1c64aSLisandro Dalcin   }
21326c6c5352SBarry Smith   c->nz         = a->nz;
2133f2cbd3d5SJed Brown   c->maxnz      = a->nz; /* Since we allocate exactly the right amount */
2134f4259b30SLisandro Dalcin   c->solve_work = NULL;
2135f4259b30SLisandro Dalcin   c->mult_work  = NULL;
213626fbe8dcSKarl Rupp 
213749b5e25fSSatish Balay   *B = C;
21389566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist));
213949b5e25fSSatish Balay   PetscFunctionReturn(0);
214049b5e25fSSatish Balay }
214149b5e25fSSatish Balay 
2142618cc2edSLisandro Dalcin /* Used for both SeqBAIJ and SeqSBAIJ matrices */
2143618cc2edSLisandro Dalcin #define MatLoad_SeqSBAIJ_Binary MatLoad_SeqBAIJ_Binary
2144618cc2edSLisandro Dalcin 
21459371c9d4SSatish Balay PetscErrorCode MatLoad_SeqSBAIJ(Mat mat, PetscViewer viewer) {
21467f489da9SVaclav Hapla   PetscBool isbinary;
21472f480046SShri Abhyankar 
21482f480046SShri Abhyankar   PetscFunctionBegin;
21499566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
215028b400f6SJacob 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);
21519566063dSJacob Faibussowitsch   PetscCall(MatLoad_SeqSBAIJ_Binary(mat, viewer));
21522f480046SShri Abhyankar   PetscFunctionReturn(0);
21532f480046SShri Abhyankar }
21542f480046SShri Abhyankar 
2155c75a6043SHong Zhang /*@
2156c75a6043SHong Zhang      MatCreateSeqSBAIJWithArrays - Creates an sequential SBAIJ matrix using matrix elements
2157c75a6043SHong Zhang               (upper triangular entries in CSR format) provided by the user.
2158c75a6043SHong Zhang 
2159d083f849SBarry Smith      Collective
2160c75a6043SHong Zhang 
2161c75a6043SHong Zhang    Input Parameters:
2162c75a6043SHong Zhang +  comm - must be an MPI communicator of size 1
2163c75a6043SHong Zhang .  bs - size of block
2164c75a6043SHong Zhang .  m - number of rows
2165c75a6043SHong Zhang .  n - number of columns
2166483a2f95SBarry 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
2167c75a6043SHong Zhang .  j - column indices
2168c75a6043SHong Zhang -  a - matrix values
2169c75a6043SHong Zhang 
2170c75a6043SHong Zhang    Output Parameter:
2171c75a6043SHong Zhang .  mat - the matrix
2172c75a6043SHong Zhang 
2173dfb205c3SBarry Smith    Level: advanced
2174c75a6043SHong Zhang 
2175c75a6043SHong Zhang    Notes:
2176c75a6043SHong Zhang        The i, j, and a arrays are not copied by this routine, the user must free these arrays
2177c75a6043SHong Zhang     once the matrix is destroyed
2178c75a6043SHong Zhang 
2179c75a6043SHong Zhang        You cannot set new nonzero locations into this matrix, that will generate an error.
2180c75a6043SHong Zhang 
2181c75a6043SHong Zhang        The i and j indices are 0 based
2182c75a6043SHong Zhang 
2183dfb205c3SBarry Smith        When block size is greater than 1 the matrix values must be stored using the SBAIJ storage format (see the SBAIJ code to determine this). For block size of 1
2184dfb205c3SBarry Smith        it is the regular CSR format excluding the lower triangular elements.
2185dfb205c3SBarry Smith 
2186db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSBAIJ()`, `MatCreateSeqSBAIJ()`
2187c75a6043SHong Zhang 
2188c75a6043SHong Zhang @*/
21899371c9d4SSatish Balay PetscErrorCode MatCreateSeqSBAIJWithArrays(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat) {
2190c75a6043SHong Zhang   PetscInt      ii;
2191c75a6043SHong Zhang   Mat_SeqSBAIJ *sbaij;
2192c75a6043SHong Zhang 
2193c75a6043SHong Zhang   PetscFunctionBegin;
219408401ef6SPierre Jolivet   PetscCheck(bs == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "block size %" PetscInt_FMT " > 1 is not supported yet", bs);
2195aed4548fSBarry Smith   PetscCheck(m == 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0");
2196c75a6043SHong Zhang 
21979566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, mat));
21989566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mat, m, n, m, n));
21999566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mat, MATSEQSBAIJ));
22009566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*mat, bs, MAT_SKIP_ALLOCATION, NULL));
2201c75a6043SHong Zhang   sbaij = (Mat_SeqSBAIJ *)(*mat)->data;
22029566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(m, &sbaij->imax, m, &sbaij->ilen));
22039566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectMemory((PetscObject)*mat, 2 * m * sizeof(PetscInt)));
2204c75a6043SHong Zhang 
2205c75a6043SHong Zhang   sbaij->i = i;
2206c75a6043SHong Zhang   sbaij->j = j;
2207c75a6043SHong Zhang   sbaij->a = a;
220826fbe8dcSKarl Rupp 
2209c75a6043SHong Zhang   sbaij->singlemalloc   = PETSC_FALSE;
2210c75a6043SHong Zhang   sbaij->nonew          = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2211e6b907acSBarry Smith   sbaij->free_a         = PETSC_FALSE;
2212e6b907acSBarry Smith   sbaij->free_ij        = PETSC_FALSE;
2213ddf7884eSMatthew Knepley   sbaij->free_imax_ilen = PETSC_TRUE;
2214c75a6043SHong Zhang 
2215c75a6043SHong Zhang   for (ii = 0; ii < m; ii++) {
2216c75a6043SHong Zhang     sbaij->ilen[ii] = sbaij->imax[ii] = i[ii + 1] - i[ii];
22176bdcaf15SBarry 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]);
2218c75a6043SHong Zhang   }
221976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2220c75a6043SHong Zhang     for (ii = 0; ii < sbaij->i[m]; ii++) {
22216bdcaf15SBarry 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]);
22226bdcaf15SBarry 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]);
2223c75a6043SHong Zhang     }
222476bd3646SJed Brown   }
2225c75a6043SHong Zhang 
22269566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY));
22279566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY));
2228c75a6043SHong Zhang   PetscFunctionReturn(0);
2229c75a6043SHong Zhang }
2230d06b337dSHong Zhang 
22319371c9d4SSatish Balay PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat) {
223259f5e6ceSHong Zhang   PetscFunctionBegin;
22339566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPISBAIJ(comm, inmat, n, scall, outmat));
223459f5e6ceSHong Zhang   PetscFunctionReturn(0);
223559f5e6ceSHong Zhang }
2236