xref: /petsc/src/mat/impls/sbaij/seq/sbaij.c (revision e87b5d96567786df49b4af65cff3120eb2cdf5c2)
149b5e25fSSatish Balay /*
2a1373b80SHong Zhang     Defines the basic matrix operations for the SBAIJ (compressed row)
349b5e25fSSatish Balay   matrix storage format.
449b5e25fSSatish Balay */
5c6db04a5SJed Brown #include <../src/mat/impls/baij/seq/baij.h> /*I "petscmat.h" I*/
6c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/sbaij.h>
7c6db04a5SJed Brown #include <petscblaslapack.h>
849b5e25fSSatish Balay 
9c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/relax.h>
1070dcbbb9SBarry Smith #define USESHORT
11c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/relax.h>
1270dcbbb9SBarry Smith 
1326cec326SBarry Smith /* defines MatSetValues_Seq_Hash(), MatAssemblyEnd_Seq_Hash(), MatSetUp_Seq_Hash() */
1426cec326SBarry Smith #define TYPE SBAIJ
1526cec326SBarry Smith #define TYPE_SBAIJ
1626cec326SBarry Smith #define TYPE_BS
1726cec326SBarry Smith #include "../src/mat/impls/aij/seq/seqhashmatsetvalues.h"
1826cec326SBarry Smith #undef TYPE_BS
1926cec326SBarry Smith #define TYPE_BS _BS
2026cec326SBarry Smith #define TYPE_BS_ON
2126cec326SBarry Smith #include "../src/mat/impls/aij/seq/seqhashmatsetvalues.h"
2226cec326SBarry Smith #undef TYPE_BS
2326cec326SBarry Smith #undef TYPE_SBAIJ
2426cec326SBarry Smith #include "../src/mat/impls/aij/seq/seqhashmat.h"
2526cec326SBarry Smith #undef TYPE
2626cec326SBarry Smith #undef TYPE_BS_ON
2726cec326SBarry Smith 
286214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
29cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_Elemental(Mat, MatType, MatReuse, Mat *);
306214f412SHong Zhang #endif
31d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
32d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_SBAIJ_ScaLAPACK(Mat, MatType, MatReuse, Mat *);
33d24d4204SJose E. Roman #endif
3428d58a37SPierre Jolivet PETSC_INTERN PetscErrorCode MatConvert_MPISBAIJ_Basic(Mat, MatType, MatReuse, Mat *);
35b5b17502SBarry Smith 
3649b5e25fSSatish Balay /*
3749b5e25fSSatish Balay      Checks for missing diagonals
3849b5e25fSSatish Balay */
39ba38deedSJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_SeqSBAIJ(Mat A, PetscBool *missing, PetscInt *dd)
40d71ae5a4SJacob Faibussowitsch {
41045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
427734d3b5SMatthew G. Knepley   PetscInt     *diag, *ii = a->i, i;
4349b5e25fSSatish Balay 
4449b5e25fSSatish Balay   PetscFunctionBegin;
459566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqSBAIJ(A));
462af78befSBarry Smith   *missing = PETSC_FALSE;
477734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
48358d2f5dSShri Abhyankar     *missing = PETSC_TRUE;
49358d2f5dSShri Abhyankar     if (dd) *dd = 0;
509566063dSJacob Faibussowitsch     PetscCall(PetscInfo(A, "Matrix has no entries therefore is missing diagonal\n"));
51358d2f5dSShri Abhyankar   } else {
52358d2f5dSShri Abhyankar     diag = a->diag;
5349b5e25fSSatish Balay     for (i = 0; i < a->mbs; i++) {
547734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i + 1]) {
552af78befSBarry Smith         *missing = PETSC_TRUE;
562af78befSBarry Smith         if (dd) *dd = i;
572af78befSBarry Smith         break;
582af78befSBarry Smith       }
5949b5e25fSSatish Balay     }
60358d2f5dSShri Abhyankar   }
613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6249b5e25fSSatish Balay }
6349b5e25fSSatish Balay 
64d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMarkDiagonal_SeqSBAIJ(Mat A)
65d71ae5a4SJacob Faibussowitsch {
66045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
6748dd3d27SHong Zhang   PetscInt      i, j;
6849b5e25fSSatish Balay 
6949b5e25fSSatish Balay   PetscFunctionBegin;
7009f38230SBarry Smith   if (!a->diag) {
719566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(a->mbs, &a->diag));
72c760cd28SBarry Smith     a->free_diag = PETSC_TRUE;
7309f38230SBarry Smith   }
7448dd3d27SHong Zhang   for (i = 0; i < a->mbs; i++) {
7548dd3d27SHong Zhang     a->diag[i] = a->i[i + 1];
7648dd3d27SHong Zhang     for (j = a->i[i]; j < a->i[i + 1]; j++) {
7748dd3d27SHong Zhang       if (a->j[j] == i) {
7848dd3d27SHong Zhang         a->diag[i] = j;
7948dd3d27SHong Zhang         break;
8048dd3d27SHong Zhang       }
8148dd3d27SHong Zhang     }
8248dd3d27SHong Zhang   }
833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8449b5e25fSSatish Balay }
8549b5e25fSSatish Balay 
86d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowIJ_SeqSBAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool blockcompressed, PetscInt *nn, const PetscInt *inia[], const PetscInt *inja[], PetscBool *done)
87d71ae5a4SJacob Faibussowitsch {
88a6ece127SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
892462f5fdSStefano Zampini   PetscInt      i, j, n = a->mbs, nz = a->i[n], *tia, *tja, bs = A->rmap->bs, k, l, cnt;
902462f5fdSStefano Zampini   PetscInt    **ia = (PetscInt **)inia, **ja = (PetscInt **)inja;
9149b5e25fSSatish Balay 
9249b5e25fSSatish Balay   PetscFunctionBegin;
93d3e5a4abSHong Zhang   *nn = n;
943ba16761SJacob Faibussowitsch   if (!ia) PetscFunctionReturn(PETSC_SUCCESS);
952462f5fdSStefano Zampini   if (symmetric) {
969566063dSJacob Faibussowitsch     PetscCall(MatToSymmetricIJ_SeqAIJ(n, a->i, a->j, PETSC_FALSE, 0, 0, &tia, &tja));
972462f5fdSStefano Zampini     nz = tia[n];
982462f5fdSStefano Zampini   } else {
999371c9d4SSatish Balay     tia = a->i;
1009371c9d4SSatish Balay     tja = a->j;
1012462f5fdSStefano Zampini   }
1022462f5fdSStefano Zampini 
1032462f5fdSStefano Zampini   if (!blockcompressed && bs > 1) {
1042462f5fdSStefano Zampini     (*nn) *= bs;
1058f7157efSSatish Balay     /* malloc & create the natural set of indices */
1069566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((n + 1) * bs, ia));
1072462f5fdSStefano Zampini     if (n) {
1082462f5fdSStefano Zampini       (*ia)[0] = oshift;
109ad540459SPierre Jolivet       for (j = 1; j < bs; j++) (*ia)[j] = (tia[1] - tia[0]) * bs + (*ia)[j - 1];
1102462f5fdSStefano Zampini     }
1112462f5fdSStefano Zampini 
1122462f5fdSStefano Zampini     for (i = 1; i < n; i++) {
1132462f5fdSStefano Zampini       (*ia)[i * bs] = (tia[i] - tia[i - 1]) * bs + (*ia)[i * bs - 1];
114ad540459SPierre Jolivet       for (j = 1; j < bs; j++) (*ia)[i * bs + j] = (tia[i + 1] - tia[i]) * bs + (*ia)[i * bs + j - 1];
1152462f5fdSStefano Zampini     }
116ad540459SPierre Jolivet     if (n) (*ia)[n * bs] = (tia[n] - tia[n - 1]) * bs + (*ia)[n * bs - 1];
1172462f5fdSStefano Zampini 
1182462f5fdSStefano Zampini     if (inja) {
1199566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz * bs * bs, ja));
1202462f5fdSStefano Zampini       cnt = 0;
1212462f5fdSStefano Zampini       for (i = 0; i < n; i++) {
1228f7157efSSatish Balay         for (j = 0; j < bs; j++) {
1232462f5fdSStefano Zampini           for (k = tia[i]; k < tia[i + 1]; k++) {
124ad540459SPierre Jolivet             for (l = 0; l < bs; l++) (*ja)[cnt++] = bs * tja[k] + l;
1258f7157efSSatish Balay           }
1268f7157efSSatish Balay         }
1278f7157efSSatish Balay       }
1288f7157efSSatish Balay     }
1292462f5fdSStefano Zampini 
1302462f5fdSStefano Zampini     if (symmetric) { /* deallocate memory allocated in MatToSymmetricIJ_SeqAIJ() */
1319566063dSJacob Faibussowitsch       PetscCall(PetscFree(tia));
1329566063dSJacob Faibussowitsch       PetscCall(PetscFree(tja));
1332462f5fdSStefano Zampini     }
1342462f5fdSStefano Zampini   } else if (oshift == 1) {
1352462f5fdSStefano Zampini     if (symmetric) {
1362462f5fdSStefano Zampini       nz = tia[A->rmap->n / bs];
1372462f5fdSStefano Zampini       /*  add 1 to i and j indices */
1382462f5fdSStefano Zampini       for (i = 0; i < A->rmap->n / bs + 1; i++) tia[i] = tia[i] + 1;
1392462f5fdSStefano Zampini       *ia = tia;
1402462f5fdSStefano Zampini       if (ja) {
1412462f5fdSStefano Zampini         for (i = 0; i < nz; i++) tja[i] = tja[i] + 1;
1422462f5fdSStefano Zampini         *ja = tja;
1432462f5fdSStefano Zampini       }
1442462f5fdSStefano Zampini     } else {
1452462f5fdSStefano Zampini       nz = a->i[A->rmap->n / bs];
1462462f5fdSStefano Zampini       /* malloc space and  add 1 to i and j indices */
1479566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(A->rmap->n / bs + 1, ia));
1482462f5fdSStefano Zampini       for (i = 0; i < A->rmap->n / bs + 1; i++) (*ia)[i] = a->i[i] + 1;
1492462f5fdSStefano Zampini       if (ja) {
1509566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(nz, ja));
1512462f5fdSStefano Zampini         for (i = 0; i < nz; i++) (*ja)[i] = a->j[i] + 1;
1522462f5fdSStefano Zampini       }
1532462f5fdSStefano Zampini     }
1542462f5fdSStefano Zampini   } else {
1552462f5fdSStefano Zampini     *ia = tia;
1562462f5fdSStefano Zampini     if (ja) *ja = tja;
157a6ece127SHong Zhang   }
1583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15949b5e25fSSatish Balay }
16049b5e25fSSatish Balay 
161d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRowIJ_SeqSBAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool blockcompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
162d71ae5a4SJacob Faibussowitsch {
16349b5e25fSSatish Balay   PetscFunctionBegin;
1643ba16761SJacob Faibussowitsch   if (!ia) PetscFunctionReturn(PETSC_SUCCESS);
1652462f5fdSStefano Zampini   if ((!blockcompressed && A->rmap->bs > 1) || (symmetric || oshift == 1)) {
1669566063dSJacob Faibussowitsch     PetscCall(PetscFree(*ia));
1679566063dSJacob Faibussowitsch     if (ja) PetscCall(PetscFree(*ja));
168a6ece127SHong Zhang   }
1693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17049b5e25fSSatish Balay }
17149b5e25fSSatish Balay 
172d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_SeqSBAIJ(Mat A)
173d71ae5a4SJacob Faibussowitsch {
17449b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
17549b5e25fSSatish Balay 
17649b5e25fSSatish Balay   PetscFunctionBegin;
177b4e2f619SBarry Smith   if (A->hash_active) {
178b4e2f619SBarry Smith     PetscInt bs;
179e3c72094SPierre Jolivet     A->ops[0] = a->cops;
180b4e2f619SBarry Smith     PetscCall(PetscHMapIJVDestroy(&a->ht));
181b4e2f619SBarry Smith     PetscCall(MatGetBlockSize(A, &bs));
182b4e2f619SBarry Smith     if (bs > 1) PetscCall(PetscHSetIJDestroy(&a->bht));
183b4e2f619SBarry Smith     PetscCall(PetscFree(a->dnz));
184b4e2f619SBarry Smith     PetscCall(PetscFree(a->bdnz));
185b4e2f619SBarry Smith     A->hash_active = PETSC_FALSE;
186b4e2f619SBarry Smith   }
1873ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)A, "Rows=%" PetscInt_FMT ", NZ=%" PetscInt_FMT, A->rmap->N, a->nz));
1889566063dSJacob Faibussowitsch   PetscCall(MatSeqXAIJFreeAIJ(A, &a->a, &a->j, &a->i));
1899566063dSJacob Faibussowitsch   if (a->free_diag) PetscCall(PetscFree(a->diag));
1909566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
1919566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
1929566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->icol));
1939566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->idiag));
1944d12350bSJunchao Zhang   PetscCall(PetscFree(a->inode.size_csr));
1959566063dSJacob Faibussowitsch   if (a->free_imax_ilen) PetscCall(PetscFree2(a->imax, a->ilen));
1969566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->solve_work));
1979566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->sor_work));
1989566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->solves_work));
1999566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->mult_work));
2009566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->saved_values));
2019566063dSJacob Faibussowitsch   if (a->free_jshort) PetscCall(PetscFree(a->jshort));
2029566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->inew));
2039566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&a->parent));
2049566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
205901853e0SKris Buschelman 
2069566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL));
2072e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJGetArray_C", NULL));
2082e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJRestoreArray_C", NULL));
2099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatStoreValues_C", NULL));
2109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatRetrieveValues_C", NULL));
2119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetColumnIndices_C", NULL));
2129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqaij_C", NULL));
2139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqbaij_C", NULL));
2149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocation_C", NULL));
2159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocationCSR_C", NULL));
2166214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
2179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_elemental_C", NULL));
2186214f412SHong Zhang #endif
219d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
2209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_scalapack_C", NULL));
221d24d4204SJose E. Roman #endif
2222e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL));
2233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22449b5e25fSSatish Balay }
22549b5e25fSSatish Balay 
226ba38deedSJacob Faibussowitsch static PetscErrorCode MatSetOption_SeqSBAIJ(Mat A, MatOption op, PetscBool flg)
227d71ae5a4SJacob Faibussowitsch {
228045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
229eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
230eb1ec7c1SStefano Zampini   PetscInt bs;
231eb1ec7c1SStefano Zampini #endif
23249b5e25fSSatish Balay 
23349b5e25fSSatish Balay   PetscFunctionBegin;
234eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2359566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &bs));
236eb1ec7c1SStefano Zampini #endif
2374d9d31abSKris Buschelman   switch (op) {
238d71ae5a4SJacob Faibussowitsch   case MAT_ROW_ORIENTED:
239d71ae5a4SJacob Faibussowitsch     a->roworiented = flg;
240d71ae5a4SJacob Faibussowitsch     break;
241d71ae5a4SJacob Faibussowitsch   case MAT_KEEP_NONZERO_PATTERN:
242d71ae5a4SJacob Faibussowitsch     a->keepnonzeropattern = flg;
243d71ae5a4SJacob Faibussowitsch     break;
244d71ae5a4SJacob Faibussowitsch   case MAT_NEW_NONZERO_LOCATIONS:
245d71ae5a4SJacob Faibussowitsch     a->nonew = (flg ? 0 : 1);
246d71ae5a4SJacob Faibussowitsch     break;
247d71ae5a4SJacob Faibussowitsch   case MAT_NEW_NONZERO_LOCATION_ERR:
248d71ae5a4SJacob Faibussowitsch     a->nonew = (flg ? -1 : 0);
249d71ae5a4SJacob Faibussowitsch     break;
250d71ae5a4SJacob Faibussowitsch   case MAT_NEW_NONZERO_ALLOCATION_ERR:
251d71ae5a4SJacob Faibussowitsch     a->nonew = (flg ? -2 : 0);
252d71ae5a4SJacob Faibussowitsch     break;
253d71ae5a4SJacob Faibussowitsch   case MAT_UNUSED_NONZERO_LOCATION_ERR:
254d71ae5a4SJacob Faibussowitsch     a->nounused = (flg ? -1 : 0);
255d71ae5a4SJacob Faibussowitsch     break;
2569a4540c5SBarry Smith   case MAT_HERMITIAN:
257eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
258eb1ec7c1SStefano Zampini     if (flg) { /* disable transpose ops */
25908401ef6SPierre Jolivet       PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for Hermitian with block size greater than 1");
260eb1ec7c1SStefano Zampini       A->ops->multtranspose    = NULL;
261eb1ec7c1SStefano Zampini       A->ops->multtransposeadd = NULL;
262b94d7dedSBarry Smith       A->symmetric             = PETSC_BOOL3_FALSE;
263eb1ec7c1SStefano Zampini     }
2640f2140c7SStefano Zampini #endif
265eeffb40dSHong Zhang     break;
26677e54ba9SKris Buschelman   case MAT_SYMMETRIC:
267eb1ec7c1SStefano Zampini   case MAT_SPD:
268eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
269eb1ec7c1SStefano Zampini     if (flg) { /* An hermitian and symmetric matrix has zero imaginary part (restore back transpose ops) */
270eb1ec7c1SStefano Zampini       A->ops->multtranspose    = A->ops->mult;
271eb1ec7c1SStefano Zampini       A->ops->multtransposeadd = A->ops->multadd;
272eb1ec7c1SStefano Zampini     }
273eb1ec7c1SStefano Zampini #endif
274eb1ec7c1SStefano Zampini     break;
275d71ae5a4SJacob Faibussowitsch   case MAT_IGNORE_LOWER_TRIANGULAR:
276d71ae5a4SJacob Faibussowitsch     a->ignore_ltriangular = flg;
277d71ae5a4SJacob Faibussowitsch     break;
278d71ae5a4SJacob Faibussowitsch   case MAT_ERROR_LOWER_TRIANGULAR:
279d71ae5a4SJacob Faibussowitsch     a->ignore_ltriangular = flg;
280d71ae5a4SJacob Faibussowitsch     break;
281d71ae5a4SJacob Faibussowitsch   case MAT_GETROW_UPPERTRIANGULAR:
282d71ae5a4SJacob Faibussowitsch     a->getrow_utriangular = flg;
283d71ae5a4SJacob Faibussowitsch     break;
284d71ae5a4SJacob Faibussowitsch   default:
285888c827cSStefano Zampini     break;
28649b5e25fSSatish Balay   }
2873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28849b5e25fSSatish Balay }
28949b5e25fSSatish Balay 
290d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
291d71ae5a4SJacob Faibussowitsch {
29249b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
29349b5e25fSSatish Balay 
29449b5e25fSSatish Balay   PetscFunctionBegin;
29508401ef6SPierre 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()");
29652768537SHong Zhang 
297f5edf698SHong Zhang   /* Get the upper triangular part of the row */
2989566063dSJacob Faibussowitsch   PetscCall(MatGetRow_SeqBAIJ_private(A, row, nz, idx, v, a->i, a->j, a->a));
2993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30049b5e25fSSatish Balay }
30149b5e25fSSatish Balay 
302d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
303d71ae5a4SJacob Faibussowitsch {
30449b5e25fSSatish Balay   PetscFunctionBegin;
3059566063dSJacob Faibussowitsch   if (idx) PetscCall(PetscFree(*idx));
3069566063dSJacob Faibussowitsch   if (v) PetscCall(PetscFree(*v));
3073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30849b5e25fSSatish Balay }
30949b5e25fSSatish Balay 
310ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetRowUpperTriangular_SeqSBAIJ(Mat A)
311d71ae5a4SJacob Faibussowitsch {
312f5edf698SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
313f5edf698SHong Zhang 
314f5edf698SHong Zhang   PetscFunctionBegin;
315f5edf698SHong Zhang   a->getrow_utriangular = PETSC_TRUE;
3163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
317f5edf698SHong Zhang }
318a323099bSStefano Zampini 
319ba38deedSJacob Faibussowitsch static PetscErrorCode MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A)
320d71ae5a4SJacob Faibussowitsch {
321f5edf698SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
322f5edf698SHong Zhang 
323f5edf698SHong Zhang   PetscFunctionBegin;
324f5edf698SHong Zhang   a->getrow_utriangular = PETSC_FALSE;
3253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
326f5edf698SHong Zhang }
327f5edf698SHong Zhang 
328ba38deedSJacob Faibussowitsch static PetscErrorCode MatTranspose_SeqSBAIJ(Mat A, MatReuse reuse, Mat *B)
329d71ae5a4SJacob Faibussowitsch {
33049b5e25fSSatish Balay   PetscFunctionBegin;
3317fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B));
332cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX) {
3339566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A, MAT_COPY_VALUES, B));
334cf37664fSBarry Smith   } else if (reuse == MAT_REUSE_MATRIX) {
3359566063dSJacob Faibussowitsch     PetscCall(MatCopy(A, *B, SAME_NONZERO_PATTERN));
336fc4dec0aSBarry Smith   }
3373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33849b5e25fSSatish Balay }
33949b5e25fSSatish Balay 
340ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_ASCII(Mat A, PetscViewer viewer)
341d71ae5a4SJacob Faibussowitsch {
34249b5e25fSSatish Balay   Mat_SeqSBAIJ     *a = (Mat_SeqSBAIJ *)A->data;
343d0f46423SBarry Smith   PetscInt          i, j, bs = A->rmap->bs, k, l, bs2 = a->bs2;
344f3ef73ceSBarry Smith   PetscViewerFormat format;
345121deb67SSatish Balay   PetscInt         *diag;
346b3a0534dSBarry Smith   const char       *matname;
34749b5e25fSSatish Balay 
34849b5e25fSSatish Balay   PetscFunctionBegin;
3499566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
350456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
3519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  block size is %" PetscInt_FMT "\n", bs));
352fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_MATLAB) {
353d2507d54SMatthew Knepley     Mat aij;
354ade3a672SBarry Smith 
355d5f3da31SBarry Smith     if (A->factortype && bs > 1) {
3569566063dSJacob 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"));
3573ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
35870d5e725SHong Zhang     }
3599566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &aij));
36023a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname));
36123a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)aij, matname));
36223a3927dSBarry Smith     PetscCall(MatView_SeqAIJ(aij, viewer));
3639566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&aij));
364fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
365b3a0534dSBarry Smith     Mat B;
366b3a0534dSBarry Smith 
367b3a0534dSBarry Smith     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B));
368b3a0534dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname));
369b3a0534dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)B, matname));
370b3a0534dSBarry Smith     PetscCall(MatView_SeqAIJ(B, viewer));
371b3a0534dSBarry Smith     PetscCall(MatDestroy(&B));
372c1490034SHong Zhang   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
3733ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
37449b5e25fSSatish Balay   } else {
3759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
3762c990fa1SHong Zhang     if (A->factortype) { /* for factored matrix */
37708401ef6SPierre Jolivet       PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix is factored with bs>1. Not implemented yet");
3782c990fa1SHong Zhang 
379121deb67SSatish Balay       diag = a->diag;
380121deb67SSatish Balay       for (i = 0; i < a->mbs; i++) { /* for row block i */
3819566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
3822c990fa1SHong Zhang         /* diagonal entry */
3832c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX)
3842c990fa1SHong Zhang         if (PetscImaginaryPart(a->a[diag[i]]) > 0.0) {
3859566063dSJacob 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]])));
3862c990fa1SHong Zhang         } else if (PetscImaginaryPart(a->a[diag[i]]) < 0.0) {
3879566063dSJacob 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]])));
3882c990fa1SHong Zhang         } else {
3899566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)PetscRealPart(1.0 / a->a[diag[i]])));
3902c990fa1SHong Zhang         }
3912c990fa1SHong Zhang #else
392835f2295SStefano Zampini         PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)(1 / a->a[diag[i]])));
3932c990fa1SHong Zhang #endif
3942c990fa1SHong Zhang         /* off-diagonal entries */
3952c990fa1SHong Zhang         for (k = a->i[i]; k < a->i[i + 1] - 1; k++) {
3962c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX)
397ca0704adSBarry Smith           if (PetscImaginaryPart(a->a[k]) > 0.0) {
3989566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), (double)PetscImaginaryPart(a->a[k])));
399ca0704adSBarry Smith           } else if (PetscImaginaryPart(a->a[k]) < 0.0) {
4009566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), -(double)PetscImaginaryPart(a->a[k])));
4012c990fa1SHong Zhang           } else {
4029566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k], (double)PetscRealPart(a->a[k])));
4032c990fa1SHong Zhang           }
4042c990fa1SHong Zhang #else
4059566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[k], (double)a->a[k]));
4062c990fa1SHong Zhang #endif
4072c990fa1SHong Zhang         }
4089566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
4092c990fa1SHong Zhang       }
4102c990fa1SHong Zhang 
4112c990fa1SHong Zhang     } else {                         /* for non-factored matrix */
4120c74a584SJed Brown       for (i = 0; i < a->mbs; i++) { /* for row block i */
4130c74a584SJed Brown         for (j = 0; j < bs; j++) {   /* for row bs*i + j */
4149566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i * bs + j));
4150c74a584SJed Brown           for (k = a->i[i]; k < a->i[i + 1]; k++) { /* for column block */
4160c74a584SJed Brown             for (l = 0; l < bs; l++) {              /* for column */
41749b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX)
41849b5e25fSSatish Balay               if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) > 0.0) {
4199371c9d4SSatish 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])));
42049b5e25fSSatish Balay               } else if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) < 0.0) {
4219371c9d4SSatish 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])));
42249b5e25fSSatish Balay               } else {
4239566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j])));
42449b5e25fSSatish Balay               }
42549b5e25fSSatish Balay #else
4269566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)a->a[bs2 * k + l * bs + j]));
42749b5e25fSSatish Balay #endif
42849b5e25fSSatish Balay             }
42949b5e25fSSatish Balay           }
4309566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
43149b5e25fSSatish Balay         }
43249b5e25fSSatish Balay       }
4332c990fa1SHong Zhang     }
4349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
43549b5e25fSSatish Balay   }
4369566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
4373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43849b5e25fSSatish Balay }
43949b5e25fSSatish Balay 
4409804daf3SBarry Smith #include <petscdraw.h>
441d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw, void *Aa)
442d71ae5a4SJacob Faibussowitsch {
44349b5e25fSSatish Balay   Mat           A = (Mat)Aa;
44449b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
4456497c311SBarry Smith   PetscInt      row, i, j, k, l, mbs = a->mbs, bs = A->rmap->bs, bs2 = a->bs2;
44649b5e25fSSatish Balay   PetscReal     xl, yl, xr, yr, x_l, x_r, y_l, y_r;
44749b5e25fSSatish Balay   MatScalar    *aa;
448b0a32e0cSBarry Smith   PetscViewer   viewer;
4496497c311SBarry Smith   int           color;
45049b5e25fSSatish Balay 
45149b5e25fSSatish Balay   PetscFunctionBegin;
4529566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
4539566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
45449b5e25fSSatish Balay 
45549b5e25fSSatish Balay   /* loop over matrix elements drawing boxes */
456383922c3SLisandro Dalcin 
457d0609cedSBarry Smith   PetscDrawCollectiveBegin(draw);
4589566063dSJacob Faibussowitsch   PetscCall(PetscDrawString(draw, .3 * (xl + xr), .3 * (yl + yr), PETSC_DRAW_BLACK, "symmetric"));
459383922c3SLisandro Dalcin   /* Blue for negative, Cyan for zero and  Red for positive */
460b0a32e0cSBarry Smith   color = PETSC_DRAW_BLUE;
46149b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
46249b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4639371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4649371c9d4SSatish Balay       y_r = y_l + 1.0;
4659371c9d4SSatish Balay       x_l = a->j[j] * bs;
4669371c9d4SSatish Balay       x_r = x_l + 1.0;
46749b5e25fSSatish Balay       aa  = a->a + j * bs2;
46849b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
46949b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
47049b5e25fSSatish Balay           if (PetscRealPart(*aa++) >= 0.) continue;
4719566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
47249b5e25fSSatish Balay         }
47349b5e25fSSatish Balay       }
47449b5e25fSSatish Balay     }
47549b5e25fSSatish Balay   }
476b0a32e0cSBarry Smith   color = PETSC_DRAW_CYAN;
47749b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
47849b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4799371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4809371c9d4SSatish Balay       y_r = y_l + 1.0;
4819371c9d4SSatish Balay       x_l = a->j[j] * bs;
4829371c9d4SSatish Balay       x_r = x_l + 1.0;
48349b5e25fSSatish Balay       aa  = a->a + j * bs2;
48449b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
48549b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
48649b5e25fSSatish Balay           if (PetscRealPart(*aa++) != 0.) continue;
4879566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
48849b5e25fSSatish Balay         }
48949b5e25fSSatish Balay       }
49049b5e25fSSatish Balay     }
49149b5e25fSSatish Balay   }
492b0a32e0cSBarry Smith   color = PETSC_DRAW_RED;
49349b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
49449b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4959371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4969371c9d4SSatish Balay       y_r = y_l + 1.0;
4979371c9d4SSatish Balay       x_l = a->j[j] * bs;
4989371c9d4SSatish Balay       x_r = x_l + 1.0;
49949b5e25fSSatish Balay       aa  = a->a + j * bs2;
50049b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
50149b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
50249b5e25fSSatish Balay           if (PetscRealPart(*aa++) <= 0.) continue;
5039566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
50449b5e25fSSatish Balay         }
50549b5e25fSSatish Balay       }
50649b5e25fSSatish Balay     }
50749b5e25fSSatish Balay   }
508d0609cedSBarry Smith   PetscDrawCollectiveEnd(draw);
5093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51049b5e25fSSatish Balay }
51149b5e25fSSatish Balay 
512d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_Draw(Mat A, PetscViewer viewer)
513d71ae5a4SJacob Faibussowitsch {
51449b5e25fSSatish Balay   PetscReal xl, yl, xr, yr, w, h;
515b0a32e0cSBarry Smith   PetscDraw draw;
516ace3abfcSBarry Smith   PetscBool isnull;
51749b5e25fSSatish Balay 
51849b5e25fSSatish Balay   PetscFunctionBegin;
5199566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5209566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
5213ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
52249b5e25fSSatish Balay 
5239371c9d4SSatish Balay   xr = A->rmap->N;
5249371c9d4SSatish Balay   yr = A->rmap->N;
5259371c9d4SSatish Balay   h  = yr / 10.0;
5269371c9d4SSatish Balay   w  = xr / 10.0;
5279371c9d4SSatish Balay   xr += w;
5289371c9d4SSatish Balay   yr += h;
5299371c9d4SSatish Balay   xl = -w;
5309371c9d4SSatish Balay   yl = -h;
5319566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
5329566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
5339566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqSBAIJ_Draw_Zoom, A));
5349566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
5359566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
5363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53749b5e25fSSatish Balay }
53849b5e25fSSatish Balay 
539618cc2edSLisandro Dalcin /* Used for both MPIBAIJ and MPISBAIJ matrices */
540618cc2edSLisandro Dalcin #define MatView_SeqSBAIJ_Binary MatView_SeqBAIJ_Binary
541618cc2edSLisandro Dalcin 
542d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqSBAIJ(Mat A, PetscViewer viewer)
543d71ae5a4SJacob Faibussowitsch {
544618cc2edSLisandro Dalcin   PetscBool iascii, isbinary, isdraw;
54549b5e25fSSatish Balay 
54649b5e25fSSatish Balay   PetscFunctionBegin;
5479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
5489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
5499566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
55032077d6dSBarry Smith   if (iascii) {
5519566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_ASCII(A, viewer));
552618cc2edSLisandro Dalcin   } else if (isbinary) {
5539566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_Binary(A, viewer));
55449b5e25fSSatish Balay   } else if (isdraw) {
5559566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_Draw(A, viewer));
55649b5e25fSSatish Balay   } else {
557a5e6ed63SBarry Smith     Mat         B;
558ade3a672SBarry Smith     const char *matname;
5599566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B));
56023a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname));
56123a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)B, matname));
5629566063dSJacob Faibussowitsch     PetscCall(MatView(B, viewer));
5639566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
56449b5e25fSSatish Balay   }
5653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56649b5e25fSSatish Balay }
56749b5e25fSSatish Balay 
568d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[])
569d71ae5a4SJacob Faibussowitsch {
570045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
57113f74950SBarry Smith   PetscInt     *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j;
57213f74950SBarry Smith   PetscInt     *ai = a->i, *ailen = a->ilen;
573d0f46423SBarry Smith   PetscInt      brow, bcol, ridx, cidx, bs = A->rmap->bs, bs2 = a->bs2;
57497e567efSBarry Smith   MatScalar    *ap, *aa = a->a;
57549b5e25fSSatish Balay 
57649b5e25fSSatish Balay   PetscFunctionBegin;
57749b5e25fSSatish Balay   for (k = 0; k < m; k++) { /* loop over rows */
5789371c9d4SSatish Balay     row  = im[k];
5799371c9d4SSatish Balay     brow = row / bs;
5809371c9d4SSatish Balay     if (row < 0) {
5819371c9d4SSatish Balay       v += n;
5829371c9d4SSatish Balay       continue;
5839371c9d4SSatish Balay     } /* negative row */
58454c59aa7SJacob 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);
5859371c9d4SSatish Balay     rp   = aj + ai[brow];
5869371c9d4SSatish Balay     ap   = aa + bs2 * ai[brow];
58749b5e25fSSatish Balay     nrow = ailen[brow];
58849b5e25fSSatish Balay     for (l = 0; l < n; l++) { /* loop over columns */
5899371c9d4SSatish Balay       if (in[l] < 0) {
5909371c9d4SSatish Balay         v++;
5919371c9d4SSatish Balay         continue;
5929371c9d4SSatish Balay       } /* negative column */
59354c59aa7SJacob 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);
59449b5e25fSSatish Balay       col  = in[l];
59549b5e25fSSatish Balay       bcol = col / bs;
59649b5e25fSSatish Balay       cidx = col % bs;
59749b5e25fSSatish Balay       ridx = row % bs;
59849b5e25fSSatish Balay       high = nrow;
59949b5e25fSSatish Balay       low  = 0; /* assume unsorted */
60049b5e25fSSatish Balay       while (high - low > 5) {
60149b5e25fSSatish Balay         t = (low + high) / 2;
60249b5e25fSSatish Balay         if (rp[t] > bcol) high = t;
60349b5e25fSSatish Balay         else low = t;
60449b5e25fSSatish Balay       }
60549b5e25fSSatish Balay       for (i = low; i < high; i++) {
60649b5e25fSSatish Balay         if (rp[i] > bcol) break;
60749b5e25fSSatish Balay         if (rp[i] == bcol) {
60849b5e25fSSatish Balay           *v++ = ap[bs2 * i + bs * cidx + ridx];
60949b5e25fSSatish Balay           goto finished;
61049b5e25fSSatish Balay         }
61149b5e25fSSatish Balay       }
61297e567efSBarry Smith       *v++ = 0.0;
61349b5e25fSSatish Balay     finished:;
61449b5e25fSSatish Balay     }
61549b5e25fSSatish Balay   }
6163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
61749b5e25fSSatish Balay }
61849b5e25fSSatish Balay 
619ba38deedSJacob Faibussowitsch static PetscErrorCode MatPermute_SeqSBAIJ(Mat A, IS rowp, IS colp, Mat *B)
620d71ae5a4SJacob Faibussowitsch {
621dc29a518SPierre Jolivet   Mat       C;
62257069620SPierre Jolivet   PetscBool flg = (PetscBool)(rowp == colp);
623dc29a518SPierre Jolivet 
624dc29a518SPierre Jolivet   PetscFunctionBegin;
6259566063dSJacob Faibussowitsch   PetscCall(MatConvert(A, MATSEQBAIJ, MAT_INITIAL_MATRIX, &C));
6269566063dSJacob Faibussowitsch   PetscCall(MatPermute(C, rowp, colp, B));
6279566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
62857069620SPierre Jolivet   if (!flg) PetscCall(ISEqual(rowp, colp, &flg));
62957069620SPierre Jolivet   if (flg) PetscCall(MatConvert(*B, MATSEQSBAIJ, MAT_INPLACE_MATRIX, B));
6303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
631dc29a518SPierre Jolivet }
63249b5e25fSSatish Balay 
633d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesBlocked_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is)
634d71ae5a4SJacob Faibussowitsch {
6350880e062SHong Zhang   Mat_SeqSBAIJ      *a = (Mat_SeqSBAIJ *)A->data;
636e2ee6c50SBarry Smith   PetscInt          *rp, k, low, high, t, ii, jj, row, nrow, i, col, l, rmax, N, lastcol = -1;
63713f74950SBarry Smith   PetscInt          *imax = a->imax, *ai = a->i, *ailen = a->ilen;
638d0f46423SBarry Smith   PetscInt          *aj = a->j, nonew = a->nonew, bs2 = a->bs2, bs = A->rmap->bs, stepval;
639ace3abfcSBarry Smith   PetscBool          roworiented = a->roworiented;
640dd6ea824SBarry Smith   const PetscScalar *value       = v;
641f15d580aSBarry Smith   MatScalar         *ap, *aa = a->a, *bap;
6420880e062SHong Zhang 
64349b5e25fSSatish Balay   PetscFunctionBegin;
64426fbe8dcSKarl Rupp   if (roworiented) stepval = (n - 1) * bs;
64526fbe8dcSKarl Rupp   else stepval = (m - 1) * bs;
6460880e062SHong Zhang   for (k = 0; k < m; k++) { /* loop over added rows */
6470880e062SHong Zhang     row = im[k];
6480880e062SHong Zhang     if (row < 0) continue;
6496bdcaf15SBarry 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);
6500880e062SHong Zhang     rp   = aj + ai[row];
6510880e062SHong Zhang     ap   = aa + bs2 * ai[row];
6520880e062SHong Zhang     rmax = imax[row];
6530880e062SHong Zhang     nrow = ailen[row];
6540880e062SHong Zhang     low  = 0;
655818f2c47SBarry Smith     high = nrow;
6560880e062SHong Zhang     for (l = 0; l < n; l++) { /* loop over added columns */
6570880e062SHong Zhang       if (in[l] < 0) continue;
6580880e062SHong Zhang       col = in[l];
6596bdcaf15SBarry 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);
660b98bf0e1SJed Brown       if (col < row) {
66126fbe8dcSKarl Rupp         if (a->ignore_ltriangular) continue; /* ignore lower triangular block */
66226fbe8dcSKarl 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)");
663b98bf0e1SJed Brown       }
66426fbe8dcSKarl Rupp       if (roworiented) value = v + k * (stepval + bs) * bs + l * bs;
66526fbe8dcSKarl Rupp       else value = v + l * (stepval + bs) * bs + k * bs;
66626fbe8dcSKarl Rupp 
66726fbe8dcSKarl Rupp       if (col <= lastcol) low = 0;
66826fbe8dcSKarl Rupp       else high = nrow;
66926fbe8dcSKarl Rupp 
670e2ee6c50SBarry Smith       lastcol = col;
6710880e062SHong Zhang       while (high - low > 7) {
6720880e062SHong Zhang         t = (low + high) / 2;
6730880e062SHong Zhang         if (rp[t] > col) high = t;
6740880e062SHong Zhang         else low = t;
6750880e062SHong Zhang       }
6760880e062SHong Zhang       for (i = low; i < high; i++) {
6770880e062SHong Zhang         if (rp[i] > col) break;
6780880e062SHong Zhang         if (rp[i] == col) {
6790880e062SHong Zhang           bap = ap + bs2 * i;
6800880e062SHong Zhang           if (roworiented) {
6810880e062SHong Zhang             if (is == ADD_VALUES) {
6820880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
683ad540459SPierre Jolivet                 for (jj = ii; jj < bs2; jj += bs) bap[jj] += *value++;
6840880e062SHong Zhang               }
6850880e062SHong Zhang             } else {
6860880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
687ad540459SPierre Jolivet                 for (jj = ii; jj < bs2; jj += bs) bap[jj] = *value++;
6880880e062SHong Zhang               }
6890880e062SHong Zhang             }
6900880e062SHong Zhang           } else {
6910880e062SHong Zhang             if (is == ADD_VALUES) {
6920880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
693ad540459SPierre Jolivet                 for (jj = 0; jj < bs; jj++) *bap++ += *value++;
6940880e062SHong Zhang               }
6950880e062SHong Zhang             } else {
6960880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
697ad540459SPierre Jolivet                 for (jj = 0; jj < bs; jj++) *bap++ = *value++;
6980880e062SHong Zhang               }
6990880e062SHong Zhang             }
7000880e062SHong Zhang           }
7010880e062SHong Zhang           goto noinsert2;
7020880e062SHong Zhang         }
7030880e062SHong Zhang       }
7040880e062SHong Zhang       if (nonew == 1) goto noinsert2;
70508401ef6SPierre 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);
706fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
7079371c9d4SSatish Balay       N = nrow++ - 1;
7089371c9d4SSatish Balay       high++;
7090880e062SHong Zhang       /* shift up all the later entries in this row */
7109566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1));
7119566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1)));
7129566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(ap + bs2 * i, bs2));
7130880e062SHong Zhang       rp[i] = col;
7140880e062SHong Zhang       bap   = ap + bs2 * i;
7150880e062SHong Zhang       if (roworiented) {
7160880e062SHong Zhang         for (ii = 0; ii < bs; ii++, value += stepval) {
717ad540459SPierre Jolivet           for (jj = ii; jj < bs2; jj += bs) bap[jj] = *value++;
7180880e062SHong Zhang         }
7190880e062SHong Zhang       } else {
7200880e062SHong Zhang         for (ii = 0; ii < bs; ii++, value += stepval) {
721ad540459SPierre Jolivet           for (jj = 0; jj < bs; jj++) *bap++ = *value++;
7220880e062SHong Zhang         }
7230880e062SHong Zhang       }
7240880e062SHong Zhang     noinsert2:;
7250880e062SHong Zhang       low = i;
7260880e062SHong Zhang     }
7270880e062SHong Zhang     ailen[row] = nrow;
7280880e062SHong Zhang   }
7293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
73049b5e25fSSatish Balay }
73149b5e25fSSatish Balay 
732ba38deedSJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_SeqSBAIJ(Mat A, MatAssemblyType mode)
733d71ae5a4SJacob Faibussowitsch {
73449b5e25fSSatish Balay   Mat_SeqSBAIJ *a      = (Mat_SeqSBAIJ *)A->data;
7358f8f2f0dSBarry Smith   PetscInt      fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax;
736d0f46423SBarry Smith   PetscInt      m = A->rmap->N, *ip, N, *ailen = a->ilen;
73713f74950SBarry Smith   PetscInt      mbs = a->mbs, bs2 = a->bs2, rmax = 0;
73849b5e25fSSatish Balay   MatScalar    *aa = a->a, *ap;
73949b5e25fSSatish Balay 
74049b5e25fSSatish Balay   PetscFunctionBegin;
741d32568d8SPierre Jolivet   if (mode == MAT_FLUSH_ASSEMBLY || (A->was_assembled && A->ass_nonzerostate == A->nonzerostate)) PetscFunctionReturn(PETSC_SUCCESS);
74249b5e25fSSatish Balay 
74349b5e25fSSatish Balay   if (m) rmax = ailen[0];
74449b5e25fSSatish Balay   for (i = 1; i < mbs; i++) {
74549b5e25fSSatish Balay     /* move each row back by the amount of empty slots (fshift) before it*/
74649b5e25fSSatish Balay     fshift += imax[i - 1] - ailen[i - 1];
74749b5e25fSSatish Balay     rmax = PetscMax(rmax, ailen[i]);
74849b5e25fSSatish Balay     if (fshift) {
749580bdb30SBarry Smith       ip = aj + ai[i];
750580bdb30SBarry Smith       ap = aa + bs2 * ai[i];
75149b5e25fSSatish Balay       N  = ailen[i];
7529566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ip - fshift, ip, N));
7539566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ap - bs2 * fshift, ap, bs2 * N));
75449b5e25fSSatish Balay     }
75549b5e25fSSatish Balay     ai[i] = ai[i - 1] + ailen[i - 1];
75649b5e25fSSatish Balay   }
75749b5e25fSSatish Balay   if (mbs) {
75849b5e25fSSatish Balay     fshift += imax[mbs - 1] - ailen[mbs - 1];
75949b5e25fSSatish Balay     ai[mbs] = ai[mbs - 1] + ailen[mbs - 1];
76049b5e25fSSatish Balay   }
76149b5e25fSSatish Balay   /* reset ilen and imax for each row */
762ad540459SPierre Jolivet   for (i = 0; i < mbs; i++) ailen[i] = imax[i] = ai[i + 1] - ai[i];
7636c6c5352SBarry Smith   a->nz = ai[mbs];
76449b5e25fSSatish Balay 
765b424e231SHong Zhang   /* diagonals may have moved, reset it */
7661baa6e33SBarry Smith   if (a->diag) PetscCall(PetscArraycpy(a->diag, ai, mbs));
767aed4548fSBarry 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);
76826fbe8dcSKarl Rupp 
7699566063dSJacob 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));
7709566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues is %" PetscInt_FMT "\n", a->reallocs));
7719566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Most nonzeros blocks in any row is %" PetscInt_FMT "\n", rmax));
77226fbe8dcSKarl Rupp 
7738e58a170SBarry Smith   A->info.mallocs += a->reallocs;
77449b5e25fSSatish Balay   a->reallocs         = 0;
77549b5e25fSSatish Balay   A->info.nz_unneeded = (PetscReal)fshift * bs2;
776061b2667SBarry Smith   a->idiagvalid       = PETSC_FALSE;
7774dcd73b1SHong Zhang   a->rmax             = rmax;
77838702af4SBarry Smith 
77938702af4SBarry Smith   if (A->cmap->n < 65536 && A->cmap->bs == 1) {
78044e1c64aSLisandro Dalcin     if (a->jshort && a->free_jshort) {
78117803ae8SHong Zhang       /* when matrix data structure is changed, previous jshort must be replaced */
7829566063dSJacob Faibussowitsch       PetscCall(PetscFree(a->jshort));
78317803ae8SHong Zhang     }
7849566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(a->i[A->rmap->n], &a->jshort));
7856497c311SBarry Smith     for (i = 0; i < a->i[A->rmap->n]; i++) a->jshort[i] = (short)a->j[i];
78638702af4SBarry Smith     A->ops->mult   = MatMult_SeqSBAIJ_1_ushort;
78741f059aeSBarry Smith     A->ops->sor    = MatSOR_SeqSBAIJ_ushort;
7884da8f245SBarry Smith     a->free_jshort = PETSC_TRUE;
78938702af4SBarry Smith   }
7903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79149b5e25fSSatish Balay }
79249b5e25fSSatish Balay 
79349b5e25fSSatish Balay /* Only add/insert a(i,j) with i<=j (blocks).
794da81f932SPierre Jolivet    Any a(i,j) with i>j input by user is ignored.
79549b5e25fSSatish Balay */
79649b5e25fSSatish Balay 
797d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is)
798d71ae5a4SJacob Faibussowitsch {
79949b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
800e2ee6c50SBarry Smith   PetscInt     *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N, lastcol = -1;
80113f74950SBarry Smith   PetscInt     *imax = a->imax, *ai = a->i, *ailen = a->ilen, roworiented = a->roworiented;
802d0f46423SBarry Smith   PetscInt     *aj = a->j, nonew = a->nonew, bs = A->rmap->bs, brow, bcol;
80313f74950SBarry Smith   PetscInt      ridx, cidx, bs2                 = a->bs2;
80449b5e25fSSatish Balay   MatScalar    *ap, value, *aa                  = a->a, *bap;
80549b5e25fSSatish Balay 
80649b5e25fSSatish Balay   PetscFunctionBegin;
80749b5e25fSSatish Balay   for (k = 0; k < m; k++) { /* loop over added rows */
80849b5e25fSSatish Balay     row  = im[k];           /* row number */
80949b5e25fSSatish Balay     brow = row / bs;        /* block row number */
81049b5e25fSSatish Balay     if (row < 0) continue;
8116bdcaf15SBarry 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);
81249b5e25fSSatish Balay     rp   = aj + ai[brow];       /*ptr to beginning of column value of the row block*/
81349b5e25fSSatish Balay     ap   = aa + bs2 * ai[brow]; /*ptr to beginning of element value of the row block*/
81449b5e25fSSatish Balay     rmax = imax[brow];          /* maximum space allocated for this row */
81549b5e25fSSatish Balay     nrow = ailen[brow];         /* actual length of this row */
81649b5e25fSSatish Balay     low  = 0;
8178509e838SStefano Zampini     high = nrow;
81849b5e25fSSatish Balay     for (l = 0; l < n; l++) { /* loop over added columns */
81949b5e25fSSatish Balay       if (in[l] < 0) continue;
8206bdcaf15SBarry 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);
82149b5e25fSSatish Balay       col  = in[l];
82249b5e25fSSatish Balay       bcol = col / bs; /* block col number */
82349b5e25fSSatish Balay 
824941593c8SHong Zhang       if (brow > bcol) {
82526fbe8dcSKarl Rupp         if (a->ignore_ltriangular) continue; /* ignore lower triangular values */
82626fbe8dcSKarl 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)");
827941593c8SHong Zhang       }
828f4989cb3SHong Zhang 
8299371c9d4SSatish Balay       ridx = row % bs;
8309371c9d4SSatish Balay       cidx = col % bs; /*row and col index inside the block */
8318549e402SHong Zhang       if ((brow == bcol && ridx <= cidx) || (brow < bcol)) {
83249b5e25fSSatish Balay         /* element value a(k,l) */
83326fbe8dcSKarl Rupp         if (roworiented) value = v[l + k * n];
83426fbe8dcSKarl Rupp         else value = v[k + l * m];
83549b5e25fSSatish Balay 
83649b5e25fSSatish Balay         /* move pointer bap to a(k,l) quickly and add/insert value */
83726fbe8dcSKarl Rupp         if (col <= lastcol) low = 0;
8388509e838SStefano Zampini         else high = nrow;
8398509e838SStefano Zampini 
840e2ee6c50SBarry Smith         lastcol = col;
84149b5e25fSSatish Balay         while (high - low > 7) {
84249b5e25fSSatish Balay           t = (low + high) / 2;
84349b5e25fSSatish Balay           if (rp[t] > bcol) high = t;
84449b5e25fSSatish Balay           else low = t;
84549b5e25fSSatish Balay         }
84649b5e25fSSatish Balay         for (i = low; i < high; i++) {
84749b5e25fSSatish Balay           if (rp[i] > bcol) break;
84849b5e25fSSatish Balay           if (rp[i] == bcol) {
84949b5e25fSSatish Balay             bap = ap + bs2 * i + bs * cidx + ridx;
85049b5e25fSSatish Balay             if (is == ADD_VALUES) *bap += value;
85149b5e25fSSatish Balay             else *bap = value;
8528549e402SHong Zhang             /* for diag block, add/insert its symmetric element a(cidx,ridx) */
8538549e402SHong Zhang             if (brow == bcol && ridx < cidx) {
8548549e402SHong Zhang               bap = ap + bs2 * i + bs * ridx + cidx;
8558549e402SHong Zhang               if (is == ADD_VALUES) *bap += value;
8568549e402SHong Zhang               else *bap = value;
8578549e402SHong Zhang             }
85849b5e25fSSatish Balay             goto noinsert1;
85949b5e25fSSatish Balay           }
86049b5e25fSSatish Balay         }
86149b5e25fSSatish Balay 
86249b5e25fSSatish Balay         if (nonew == 1) goto noinsert1;
86308401ef6SPierre Jolivet         PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero (%" PetscInt_FMT ", %" PetscInt_FMT ") in the matrix", row, col);
864fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, brow, bcol, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
86549b5e25fSSatish Balay 
8669371c9d4SSatish Balay         N = nrow++ - 1;
8679371c9d4SSatish Balay         high++;
86849b5e25fSSatish Balay         /* shift up all the later entries in this row */
8699566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1));
8709566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1)));
8719566063dSJacob Faibussowitsch         PetscCall(PetscArrayzero(ap + bs2 * i, bs2));
87249b5e25fSSatish Balay         rp[i]                          = bcol;
87349b5e25fSSatish Balay         ap[bs2 * i + bs * cidx + ridx] = value;
8748509e838SStefano Zampini         /* for diag block, add/insert its symmetric element a(cidx,ridx) */
875ad540459SPierre Jolivet         if (brow == bcol && ridx < cidx) ap[bs2 * i + bs * ridx + cidx] = value;
87649b5e25fSSatish Balay       noinsert1:;
87749b5e25fSSatish Balay         low = i;
8788549e402SHong Zhang       }
87949b5e25fSSatish Balay     } /* end of loop over added columns */
88049b5e25fSSatish Balay     ailen[brow] = nrow;
88149b5e25fSSatish Balay   } /* end of loop over added rows */
8823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
88349b5e25fSSatish Balay }
88449b5e25fSSatish Balay 
885ba38deedSJacob Faibussowitsch static PetscErrorCode MatICCFactor_SeqSBAIJ(Mat inA, IS row, const MatFactorInfo *info)
886d71ae5a4SJacob Faibussowitsch {
8874ccecd49SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)inA->data;
88849b5e25fSSatish Balay   Mat           outA;
889ace3abfcSBarry Smith   PetscBool     row_identity;
89049b5e25fSSatish Balay 
89149b5e25fSSatish Balay   PetscFunctionBegin;
89208401ef6SPierre Jolivet   PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 is supported for in-place icc");
8939566063dSJacob Faibussowitsch   PetscCall(ISIdentity(row, &row_identity));
89428b400f6SJacob Faibussowitsch   PetscCheck(row_identity, PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix reordering is not supported");
89508401ef6SPierre 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()! */
896c84f5b01SHong Zhang 
89749b5e25fSSatish Balay   outA            = inA;
898d5f3da31SBarry Smith   inA->factortype = MAT_FACTOR_ICC;
8999566063dSJacob Faibussowitsch   PetscCall(PetscFree(inA->solvertype));
9009566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype));
90149b5e25fSSatish Balay 
9029566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqSBAIJ(inA));
9039566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetNumericFactorization_inplace(inA, row_identity));
90449b5e25fSSatish Balay 
9059566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
9069566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
907c84f5b01SHong Zhang   a->row = row;
9089566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
9099566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
910c84f5b01SHong Zhang   a->col = row;
911c84f5b01SHong Zhang 
912c84f5b01SHong Zhang   /* Create the invert permutation so that it can be used in MatCholeskyFactorNumeric() */
9139566063dSJacob Faibussowitsch   if (a->icol) PetscCall(ISInvertPermutation(row, PETSC_DECIDE, &a->icol));
91449b5e25fSSatish Balay 
915aa624791SPierre Jolivet   if (!a->solve_work) PetscCall(PetscMalloc1(inA->rmap->N + inA->rmap->bs, &a->solve_work));
91649b5e25fSSatish Balay 
9179566063dSJacob Faibussowitsch   PetscCall(MatCholeskyFactorNumeric(outA, inA, info));
9183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91949b5e25fSSatish Balay }
920950f1e5bSHong Zhang 
921ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat, PetscInt *indices)
922d71ae5a4SJacob Faibussowitsch {
923045c9aa0SHong Zhang   Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)mat->data;
92413f74950SBarry Smith   PetscInt      i, nz, n;
92549b5e25fSSatish Balay 
92649b5e25fSSatish Balay   PetscFunctionBegin;
9276c6c5352SBarry Smith   nz = baij->maxnz;
928d0f46423SBarry Smith   n  = mat->cmap->n;
92926fbe8dcSKarl Rupp   for (i = 0; i < nz; i++) baij->j[i] = indices[i];
93026fbe8dcSKarl Rupp 
9316c6c5352SBarry Smith   baij->nz = nz;
93226fbe8dcSKarl Rupp   for (i = 0; i < n; i++) baij->ilen[i] = baij->imax[i];
93326fbe8dcSKarl Rupp 
9349566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
9353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
93649b5e25fSSatish Balay }
93749b5e25fSSatish Balay 
93849b5e25fSSatish Balay /*@
93919585528SSatish Balay   MatSeqSBAIJSetColumnIndices - Set the column indices for all the rows
94011a5261eSBarry Smith   in a `MATSEQSBAIJ` matrix.
94149b5e25fSSatish Balay 
94249b5e25fSSatish Balay   Input Parameters:
94311a5261eSBarry Smith + mat     - the `MATSEQSBAIJ` matrix
94449b5e25fSSatish Balay - indices - the column indices
94549b5e25fSSatish Balay 
94649b5e25fSSatish Balay   Level: advanced
94749b5e25fSSatish Balay 
94849b5e25fSSatish Balay   Notes:
94949b5e25fSSatish Balay   This can be called if you have precomputed the nonzero structure of the
95049b5e25fSSatish Balay   matrix and want to provide it to the matrix object to improve the performance
95111a5261eSBarry Smith   of the `MatSetValues()` operation.
95249b5e25fSSatish Balay 
95349b5e25fSSatish Balay   You MUST have set the correct numbers of nonzeros per row in the call to
95411a5261eSBarry Smith   `MatCreateSeqSBAIJ()`, and the columns indices MUST be sorted.
95549b5e25fSSatish Balay 
9562ef1f0ffSBarry Smith   MUST be called before any calls to `MatSetValues()`
95749b5e25fSSatish Balay 
9581cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreateSeqSBAIJ`
95949b5e25fSSatish Balay @*/
960d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetColumnIndices(Mat mat, PetscInt *indices)
961d71ae5a4SJacob Faibussowitsch {
96249b5e25fSSatish Balay   PetscFunctionBegin;
9630700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9644f572ea9SToby Isaac   PetscAssertPointer(indices, 2);
965cac4c232SBarry Smith   PetscUseMethod(mat, "MatSeqSBAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices));
9663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
96749b5e25fSSatish Balay }
96849b5e25fSSatish Balay 
969ba38deedSJacob Faibussowitsch static PetscErrorCode MatCopy_SeqSBAIJ(Mat A, Mat B, MatStructure str)
970d71ae5a4SJacob Faibussowitsch {
9714c7a3774SStefano Zampini   PetscBool isbaij;
9723c896bc6SHong Zhang 
9733c896bc6SHong Zhang   PetscFunctionBegin;
9749566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &isbaij, MATSEQSBAIJ, MATMPISBAIJ, ""));
97528b400f6SJacob Faibussowitsch   PetscCheck(isbaij, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)B)->type_name);
9764c7a3774SStefano Zampini   /* If the two matrices have the same copy implementation and nonzero pattern, use fast copy. */
9774c7a3774SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
9783c896bc6SHong Zhang     Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
9793c896bc6SHong Zhang     Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data;
9803c896bc6SHong Zhang 
98108401ef6SPierre 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");
98208401ef6SPierre Jolivet     PetscCheck(a->mbs == b->mbs, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of rows in two matrices are different");
98308401ef6SPierre Jolivet     PetscCheck(a->bs2 == b->bs2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different block size");
9849566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(b->a, a->a, a->bs2 * a->i[a->mbs]));
9859566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)B));
9863c896bc6SHong Zhang   } else {
9879566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(A));
9889566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
9899566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(A));
9903c896bc6SHong Zhang   }
9913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9923c896bc6SHong Zhang }
9933c896bc6SHong Zhang 
994d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJGetArray_SeqSBAIJ(Mat A, PetscScalar *array[])
995d71ae5a4SJacob Faibussowitsch {
996a6ece127SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
9975fd66863SKarl Rupp 
998a6ece127SHong Zhang   PetscFunctionBegin;
999a6ece127SHong Zhang   *array = a->a;
10003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1001a6ece127SHong Zhang }
1002a6ece127SHong Zhang 
1003d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJRestoreArray_SeqSBAIJ(Mat A, PetscScalar *array[])
1004d71ae5a4SJacob Faibussowitsch {
1005a6ece127SHong Zhang   PetscFunctionBegin;
1006cda14afcSprj-   *array = NULL;
10073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1008a6ece127SHong Zhang }
1009a6ece127SHong Zhang 
1010d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPYGetPreallocation_SeqSBAIJ(Mat Y, Mat X, PetscInt *nnz)
1011d71ae5a4SJacob Faibussowitsch {
1012b264fe52SHong Zhang   PetscInt      bs = Y->rmap->bs, mbs = Y->rmap->N / bs;
101352768537SHong Zhang   Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data;
101452768537SHong Zhang   Mat_SeqSBAIJ *y = (Mat_SeqSBAIJ *)Y->data;
101552768537SHong Zhang 
101652768537SHong Zhang   PetscFunctionBegin;
101752768537SHong Zhang   /* Set the number of nonzeros in the new matrix */
10189566063dSJacob Faibussowitsch   PetscCall(MatAXPYGetPreallocation_SeqX_private(mbs, x->i, x->j, y->i, y->j, nnz));
10193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
102052768537SHong Zhang }
102152768537SHong Zhang 
1022ba38deedSJacob Faibussowitsch static PetscErrorCode MatAXPY_SeqSBAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str)
1023d71ae5a4SJacob Faibussowitsch {
102442ee4b1aSHong Zhang   Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data, *y = (Mat_SeqSBAIJ *)Y->data;
102531ce2d13SHong Zhang   PetscInt      bs = Y->rmap->bs, bs2 = bs * bs;
1026e838b9e7SJed Brown   PetscBLASInt  one = 1;
102742ee4b1aSHong Zhang 
102842ee4b1aSHong Zhang   PetscFunctionBegin;
1029134adf20SPierre Jolivet   if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) {
1030134adf20SPierre Jolivet     PetscBool e = x->nz == y->nz && x->mbs == y->mbs ? PETSC_TRUE : PETSC_FALSE;
1031134adf20SPierre Jolivet     if (e) {
10329566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(x->i, y->i, x->mbs + 1, &e));
1033134adf20SPierre Jolivet       if (e) {
10349566063dSJacob Faibussowitsch         PetscCall(PetscArraycmp(x->j, y->j, x->i[x->mbs], &e));
1035134adf20SPierre Jolivet         if (e) str = SAME_NONZERO_PATTERN;
1036134adf20SPierre Jolivet       }
1037134adf20SPierre Jolivet     }
103854c59aa7SJacob Faibussowitsch     if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN");
1039134adf20SPierre Jolivet   }
104042ee4b1aSHong Zhang   if (str == SAME_NONZERO_PATTERN) {
1041f4df32b1SMatthew Knepley     PetscScalar  alpha = a;
1042c5df96a5SBarry Smith     PetscBLASInt bnz;
10439566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(x->nz * bs2, &bnz));
1044792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, x->a, &one, y->a, &one));
10459566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)Y));
1046ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
10479566063dSJacob Faibussowitsch     PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_TRUE));
10489566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
10499566063dSJacob Faibussowitsch     PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_FALSE));
105042ee4b1aSHong Zhang   } else {
105152768537SHong Zhang     Mat       B;
105252768537SHong Zhang     PetscInt *nnz;
105354c59aa7SJacob Faibussowitsch     PetscCheck(bs == X->rmap->bs, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Matrices must have same block size");
10549566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(X));
10559566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(Y));
10569566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Y->rmap->N, &nnz));
10579566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B));
10589566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name));
10599566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, Y->rmap->n, Y->cmap->n, Y->rmap->N, Y->cmap->N));
10609566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, Y, Y));
10619566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, ((PetscObject)Y)->type_name));
10629566063dSJacob Faibussowitsch     PetscCall(MatAXPYGetPreallocation_SeqSBAIJ(Y, X, nnz));
10639566063dSJacob Faibussowitsch     PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz));
106452768537SHong Zhang 
10659566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
106652768537SHong Zhang 
10679566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
10689566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz));
10699566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(X));
10709566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(Y));
107142ee4b1aSHong Zhang   }
10723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
107342ee4b1aSHong Zhang }
107442ee4b1aSHong Zhang 
1075ba38deedSJacob Faibussowitsch static PetscErrorCode MatIsStructurallySymmetric_SeqSBAIJ(Mat A, PetscBool *flg)
1076d71ae5a4SJacob Faibussowitsch {
1077efcf0fc3SBarry Smith   PetscFunctionBegin;
1078efcf0fc3SBarry Smith   *flg = PETSC_TRUE;
10793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1080efcf0fc3SBarry Smith }
1081efcf0fc3SBarry Smith 
1082ba38deedSJacob Faibussowitsch static PetscErrorCode MatConjugate_SeqSBAIJ(Mat A)
1083d71ae5a4SJacob Faibussowitsch {
10842726fb6dSPierre Jolivet #if defined(PETSC_USE_COMPLEX)
10852726fb6dSPierre Jolivet   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
10862726fb6dSPierre Jolivet   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
10872726fb6dSPierre Jolivet   MatScalar    *aa = a->a;
10882726fb6dSPierre Jolivet 
10892726fb6dSPierre Jolivet   PetscFunctionBegin;
10902726fb6dSPierre Jolivet   for (i = 0; i < nz; i++) aa[i] = PetscConj(aa[i]);
10912726fb6dSPierre Jolivet #else
10922726fb6dSPierre Jolivet   PetscFunctionBegin;
10932726fb6dSPierre Jolivet #endif
10943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10952726fb6dSPierre Jolivet }
10962726fb6dSPierre Jolivet 
1097ba38deedSJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqSBAIJ(Mat A)
1098d71ae5a4SJacob Faibussowitsch {
109999cafbc1SBarry Smith   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
110099cafbc1SBarry Smith   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
1101dd6ea824SBarry Smith   MatScalar    *aa = a->a;
110299cafbc1SBarry Smith 
110399cafbc1SBarry Smith   PetscFunctionBegin;
110499cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]);
11053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
110699cafbc1SBarry Smith }
110799cafbc1SBarry Smith 
1108ba38deedSJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqSBAIJ(Mat A)
1109d71ae5a4SJacob Faibussowitsch {
111099cafbc1SBarry Smith   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
111199cafbc1SBarry Smith   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
1112dd6ea824SBarry Smith   MatScalar    *aa = a->a;
111399cafbc1SBarry Smith 
111499cafbc1SBarry Smith   PetscFunctionBegin;
111599cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
11163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
111799cafbc1SBarry Smith }
111899cafbc1SBarry Smith 
1119ba38deedSJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_SeqSBAIJ(Mat A, PetscInt is_n, const PetscInt is_idx[], PetscScalar diag, Vec x, Vec b)
1120d71ae5a4SJacob Faibussowitsch {
11213bededecSBarry Smith   Mat_SeqSBAIJ      *baij = (Mat_SeqSBAIJ *)A->data;
11223bededecSBarry Smith   PetscInt           i, j, k, count;
11233bededecSBarry Smith   PetscInt           bs = A->rmap->bs, bs2 = baij->bs2, row, col;
11243bededecSBarry Smith   PetscScalar        zero = 0.0;
11253bededecSBarry Smith   MatScalar         *aa;
11263bededecSBarry Smith   const PetscScalar *xx;
11273bededecSBarry Smith   PetscScalar       *bb;
112856777dd2SBarry Smith   PetscBool         *zeroed, vecs = PETSC_FALSE;
11293bededecSBarry Smith 
11303bededecSBarry Smith   PetscFunctionBegin;
1131dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
11323bededecSBarry Smith   if (x && b) {
11339566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
11349566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
113556777dd2SBarry Smith     vecs = PETSC_TRUE;
11363bededecSBarry Smith   }
11373bededecSBarry Smith 
11383bededecSBarry Smith   /* zero the columns */
11399566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(A->rmap->n, &zeroed));
11403bededecSBarry Smith   for (i = 0; i < is_n; i++) {
1141aed4548fSBarry 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]);
11423bededecSBarry Smith     zeroed[is_idx[i]] = PETSC_TRUE;
11433bededecSBarry Smith   }
114456777dd2SBarry Smith   if (vecs) {
114556777dd2SBarry Smith     for (i = 0; i < A->rmap->N; i++) {
114656777dd2SBarry Smith       row = i / bs;
114756777dd2SBarry Smith       for (j = baij->i[row]; j < baij->i[row + 1]; j++) {
114856777dd2SBarry Smith         for (k = 0; k < bs; k++) {
114956777dd2SBarry Smith           col = bs * baij->j[j] + k;
115056777dd2SBarry Smith           if (col <= i) continue;
1151835f2295SStefano Zampini           aa = baij->a + j * bs2 + (i % bs) + bs * k;
115226fbe8dcSKarl Rupp           if (!zeroed[i] && zeroed[col]) bb[i] -= aa[0] * xx[col];
115326fbe8dcSKarl Rupp           if (zeroed[i] && !zeroed[col]) bb[col] -= aa[0] * xx[i];
115456777dd2SBarry Smith         }
115556777dd2SBarry Smith       }
115656777dd2SBarry Smith     }
115726fbe8dcSKarl Rupp     for (i = 0; i < is_n; i++) bb[is_idx[i]] = diag * xx[is_idx[i]];
115856777dd2SBarry Smith   }
115956777dd2SBarry Smith 
11603bededecSBarry Smith   for (i = 0; i < A->rmap->N; i++) {
11613bededecSBarry Smith     if (!zeroed[i]) {
11623bededecSBarry Smith       row = i / bs;
11633bededecSBarry Smith       for (j = baij->i[row]; j < baij->i[row + 1]; j++) {
11643bededecSBarry Smith         for (k = 0; k < bs; k++) {
11653bededecSBarry Smith           col = bs * baij->j[j] + k;
11663bededecSBarry Smith           if (zeroed[col]) {
1167835f2295SStefano Zampini             aa    = baij->a + j * bs2 + (i % bs) + bs * k;
11683bededecSBarry Smith             aa[0] = 0.0;
11693bededecSBarry Smith           }
11703bededecSBarry Smith         }
11713bededecSBarry Smith       }
11723bededecSBarry Smith     }
11733bededecSBarry Smith   }
11749566063dSJacob Faibussowitsch   PetscCall(PetscFree(zeroed));
117556777dd2SBarry Smith   if (vecs) {
11769566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
11779566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
117856777dd2SBarry Smith   }
11793bededecSBarry Smith 
11803bededecSBarry Smith   /* zero the rows */
11813bededecSBarry Smith   for (i = 0; i < is_n; i++) {
11823bededecSBarry Smith     row   = is_idx[i];
11833bededecSBarry Smith     count = (baij->i[row / bs + 1] - baij->i[row / bs]) * bs;
1184835f2295SStefano Zampini     aa    = baij->a + baij->i[row / bs] * bs2 + (row % bs);
11853bededecSBarry Smith     for (k = 0; k < count; k++) {
11863bededecSBarry Smith       aa[0] = zero;
11873bededecSBarry Smith       aa += bs;
11883bededecSBarry Smith     }
1189dbbe0bcdSBarry Smith     if (diag != 0.0) PetscUseTypeMethod(A, setvalues, 1, &row, 1, &row, &diag, INSERT_VALUES);
11903bededecSBarry Smith   }
11919566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd_SeqSBAIJ(A, MAT_FINAL_ASSEMBLY));
11923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11933bededecSBarry Smith }
11943bededecSBarry Smith 
1195ba38deedSJacob Faibussowitsch static PetscErrorCode MatShift_SeqSBAIJ(Mat Y, PetscScalar a)
1196d71ae5a4SJacob Faibussowitsch {
11977d68702bSBarry Smith   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)Y->data;
11987d68702bSBarry Smith 
11997d68702bSBarry Smith   PetscFunctionBegin;
120048a46eb9SPierre Jolivet   if (!Y->preallocated || !aij->nz) PetscCall(MatSeqSBAIJSetPreallocation(Y, Y->rmap->bs, 1, NULL));
12019566063dSJacob Faibussowitsch   PetscCall(MatShift_Basic(Y, a));
12023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12037d68702bSBarry Smith }
12047d68702bSBarry Smith 
120517ea310bSPierre Jolivet PetscErrorCode MatEliminateZeros_SeqSBAIJ(Mat A, PetscBool keep)
120617ea310bSPierre Jolivet {
120717ea310bSPierre Jolivet   Mat_SeqSBAIJ *a      = (Mat_SeqSBAIJ *)A->data;
120817ea310bSPierre Jolivet   PetscInt      fshift = 0, fshift_prev = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax, j, k;
120917ea310bSPierre Jolivet   PetscInt      m = A->rmap->N, *ailen = a->ilen;
121017ea310bSPierre Jolivet   PetscInt      mbs = a->mbs, bs2 = a->bs2, rmax = 0;
121117ea310bSPierre Jolivet   MatScalar    *aa = a->a, *ap;
121217ea310bSPierre Jolivet   PetscBool     zero;
121317ea310bSPierre Jolivet 
121417ea310bSPierre Jolivet   PetscFunctionBegin;
121517ea310bSPierre Jolivet   PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot eliminate zeros for unassembled matrix");
121617ea310bSPierre Jolivet   if (m) rmax = ailen[0];
121717ea310bSPierre Jolivet   for (i = 1; i <= mbs; i++) {
121817ea310bSPierre Jolivet     for (k = ai[i - 1]; k < ai[i]; k++) {
121917ea310bSPierre Jolivet       zero = PETSC_TRUE;
122017ea310bSPierre Jolivet       ap   = aa + bs2 * k;
122117ea310bSPierre Jolivet       for (j = 0; j < bs2 && zero; j++) {
122217ea310bSPierre Jolivet         if (ap[j] != 0.0) zero = PETSC_FALSE;
122317ea310bSPierre Jolivet       }
122417ea310bSPierre Jolivet       if (zero && (aj[k] != i - 1 || !keep)) fshift++;
122517ea310bSPierre Jolivet       else {
122617ea310bSPierre Jolivet         if (zero && aj[k] == i - 1) PetscCall(PetscInfo(A, "Keep the diagonal block at row %" PetscInt_FMT "\n", i - 1));
122717ea310bSPierre Jolivet         aj[k - fshift] = aj[k];
122817ea310bSPierre Jolivet         PetscCall(PetscArraymove(ap - bs2 * fshift, ap, bs2));
122917ea310bSPierre Jolivet       }
123017ea310bSPierre Jolivet     }
123117ea310bSPierre Jolivet     ai[i - 1] -= fshift_prev;
123217ea310bSPierre Jolivet     fshift_prev  = fshift;
123317ea310bSPierre Jolivet     ailen[i - 1] = imax[i - 1] = ai[i] - fshift - ai[i - 1];
123417ea310bSPierre Jolivet     a->nonzerorowcnt += ((ai[i] - fshift - ai[i - 1]) > 0);
123517ea310bSPierre Jolivet     rmax = PetscMax(rmax, ailen[i - 1]);
123617ea310bSPierre Jolivet   }
123717ea310bSPierre Jolivet   if (fshift) {
123817ea310bSPierre Jolivet     if (mbs) {
123917ea310bSPierre Jolivet       ai[mbs] -= fshift;
124017ea310bSPierre Jolivet       a->nz = ai[mbs];
124117ea310bSPierre Jolivet     }
124217ea310bSPierre Jolivet     PetscCall(PetscInfo(A, "Matrix size: %" PetscInt_FMT " X %" PetscInt_FMT "; zeros eliminated: %" PetscInt_FMT "; nonzeros left: %" PetscInt_FMT "\n", m, A->cmap->n, fshift, a->nz));
124317ea310bSPierre Jolivet     A->nonzerostate++;
124417ea310bSPierre Jolivet     A->info.nz_unneeded += (PetscReal)fshift;
124517ea310bSPierre Jolivet     a->rmax = rmax;
124617ea310bSPierre Jolivet     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
124717ea310bSPierre Jolivet     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
124817ea310bSPierre Jolivet   }
124917ea310bSPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
125017ea310bSPierre Jolivet }
125117ea310bSPierre Jolivet 
12523964eb88SJed Brown static struct _MatOps MatOps_Values = {MatSetValues_SeqSBAIJ,
125349b5e25fSSatish Balay                                        MatGetRow_SeqSBAIJ,
125449b5e25fSSatish Balay                                        MatRestoreRow_SeqSBAIJ,
125549b5e25fSSatish Balay                                        MatMult_SeqSBAIJ_N,
125697304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqSBAIJ_N,
1257431c96f7SBarry Smith                                        MatMult_SeqSBAIJ_N, /* transpose versions are same as non-transpose versions */
1258e005ede5SBarry Smith                                        MatMultAdd_SeqSBAIJ_N,
1259f4259b30SLisandro Dalcin                                        NULL,
1260f4259b30SLisandro Dalcin                                        NULL,
1261f4259b30SLisandro Dalcin                                        NULL,
1262f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
1263f4259b30SLisandro Dalcin                                        NULL,
1264c078aec8SLisandro Dalcin                                        MatCholeskyFactor_SeqSBAIJ,
126541f059aeSBarry Smith                                        MatSOR_SeqSBAIJ,
126649b5e25fSSatish Balay                                        MatTranspose_SeqSBAIJ,
126797304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqSBAIJ,
126849b5e25fSSatish Balay                                        MatEqual_SeqSBAIJ,
126949b5e25fSSatish Balay                                        MatGetDiagonal_SeqSBAIJ,
127049b5e25fSSatish Balay                                        MatDiagonalScale_SeqSBAIJ,
127149b5e25fSSatish Balay                                        MatNorm_SeqSBAIJ,
1272f4259b30SLisandro Dalcin                                        /* 20*/ NULL,
127349b5e25fSSatish Balay                                        MatAssemblyEnd_SeqSBAIJ,
127449b5e25fSSatish Balay                                        MatSetOption_SeqSBAIJ,
127549b5e25fSSatish Balay                                        MatZeroEntries_SeqSBAIJ,
1276f4259b30SLisandro Dalcin                                        /* 24*/ NULL,
1277f4259b30SLisandro Dalcin                                        NULL,
1278f4259b30SLisandro Dalcin                                        NULL,
1279f4259b30SLisandro Dalcin                                        NULL,
1280f4259b30SLisandro Dalcin                                        NULL,
128126cec326SBarry Smith                                        /* 29*/ MatSetUp_Seq_Hash,
1282f4259b30SLisandro Dalcin                                        NULL,
1283f4259b30SLisandro Dalcin                                        NULL,
1284f4259b30SLisandro Dalcin                                        NULL,
1285f4259b30SLisandro Dalcin                                        NULL,
1286d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqSBAIJ,
1287f4259b30SLisandro Dalcin                                        NULL,
1288f4259b30SLisandro Dalcin                                        NULL,
1289f4259b30SLisandro Dalcin                                        NULL,
1290c84f5b01SHong Zhang                                        MatICCFactor_SeqSBAIJ,
1291d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqSBAIJ,
12927dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqSBAIJ,
129349b5e25fSSatish Balay                                        MatIncreaseOverlap_SeqSBAIJ,
129449b5e25fSSatish Balay                                        MatGetValues_SeqSBAIJ,
12953c896bc6SHong Zhang                                        MatCopy_SeqSBAIJ,
1296f4259b30SLisandro Dalcin                                        /* 44*/ NULL,
129749b5e25fSSatish Balay                                        MatScale_SeqSBAIJ,
12987d68702bSBarry Smith                                        MatShift_SeqSBAIJ,
1299f4259b30SLisandro Dalcin                                        NULL,
13003bededecSBarry Smith                                        MatZeroRowsColumns_SeqSBAIJ,
1301f4259b30SLisandro Dalcin                                        /* 49*/ NULL,
130249b5e25fSSatish Balay                                        MatGetRowIJ_SeqSBAIJ,
130349b5e25fSSatish Balay                                        MatRestoreRowIJ_SeqSBAIJ,
1304f4259b30SLisandro Dalcin                                        NULL,
1305f4259b30SLisandro Dalcin                                        NULL,
1306f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
1307f4259b30SLisandro Dalcin                                        NULL,
1308f4259b30SLisandro Dalcin                                        NULL,
1309dc29a518SPierre Jolivet                                        MatPermute_SeqSBAIJ,
131049b5e25fSSatish Balay                                        MatSetValuesBlocked_SeqSBAIJ,
13117dae84e0SHong Zhang                                        /* 59*/ MatCreateSubMatrix_SeqSBAIJ,
1312f4259b30SLisandro Dalcin                                        NULL,
1313f4259b30SLisandro Dalcin                                        NULL,
1314f4259b30SLisandro Dalcin                                        NULL,
1315f4259b30SLisandro Dalcin                                        NULL,
1316f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
1317f4259b30SLisandro Dalcin                                        NULL,
1318f4259b30SLisandro Dalcin                                        NULL,
1319f4259b30SLisandro Dalcin                                        NULL,
1320f4259b30SLisandro Dalcin                                        NULL,
1321d519adbfSMatthew Knepley                                        /* 69*/ MatGetRowMaxAbs_SeqSBAIJ,
1322f4259b30SLisandro Dalcin                                        NULL,
132328d58a37SPierre Jolivet                                        MatConvert_MPISBAIJ_Basic,
1324f4259b30SLisandro Dalcin                                        NULL,
1325f4259b30SLisandro Dalcin                                        NULL,
1326f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
1327f4259b30SLisandro Dalcin                                        NULL,
1328f4259b30SLisandro Dalcin                                        NULL,
1329f4259b30SLisandro Dalcin                                        NULL,
1330f4259b30SLisandro Dalcin                                        NULL,
1331f4259b30SLisandro Dalcin                                        /* 79*/ NULL,
1332f4259b30SLisandro Dalcin                                        NULL,
1333f4259b30SLisandro Dalcin                                        NULL,
133497304618SKris Buschelman                                        MatGetInertia_SeqSBAIJ,
13355bba2384SShri Abhyankar                                        MatLoad_SeqSBAIJ,
13366cff0a6bSPierre Jolivet                                        /* 84*/ NULL,
13376cff0a6bSPierre Jolivet                                        NULL,
1338efcf0fc3SBarry Smith                                        MatIsStructurallySymmetric_SeqSBAIJ,
1339f4259b30SLisandro Dalcin                                        NULL,
1340f4259b30SLisandro Dalcin                                        NULL,
1341f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
1342f4259b30SLisandro Dalcin                                        NULL,
1343f4259b30SLisandro Dalcin                                        NULL,
1344f4259b30SLisandro Dalcin                                        NULL,
1345f4259b30SLisandro Dalcin                                        NULL,
1346f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
1347f4259b30SLisandro Dalcin                                        NULL,
1348f4259b30SLisandro Dalcin                                        NULL,
1349f4259b30SLisandro Dalcin                                        NULL,
1350f4259b30SLisandro Dalcin                                        NULL,
1351f4259b30SLisandro Dalcin                                        /* 99*/ NULL,
1352f4259b30SLisandro Dalcin                                        NULL,
1353f4259b30SLisandro Dalcin                                        NULL,
13542726fb6dSPierre Jolivet                                        MatConjugate_SeqSBAIJ,
1355f4259b30SLisandro Dalcin                                        NULL,
1356f4259b30SLisandro Dalcin                                        /*104*/ NULL,
135799cafbc1SBarry Smith                                        MatRealPart_SeqSBAIJ,
1358f5edf698SHong Zhang                                        MatImaginaryPart_SeqSBAIJ,
1359f5edf698SHong Zhang                                        MatGetRowUpperTriangular_SeqSBAIJ,
13602af78befSBarry Smith                                        MatRestoreRowUpperTriangular_SeqSBAIJ,
1361f4259b30SLisandro Dalcin                                        /*109*/ NULL,
1362f4259b30SLisandro Dalcin                                        NULL,
1363f4259b30SLisandro Dalcin                                        NULL,
1364f4259b30SLisandro Dalcin                                        NULL,
1365547795f9SHong Zhang                                        MatMissingDiagonal_SeqSBAIJ,
1366f4259b30SLisandro Dalcin                                        /*114*/ NULL,
1367f4259b30SLisandro Dalcin                                        NULL,
1368f4259b30SLisandro Dalcin                                        NULL,
1369f4259b30SLisandro Dalcin                                        NULL,
1370f4259b30SLisandro Dalcin                                        NULL,
1371f4259b30SLisandro Dalcin                                        /*119*/ NULL,
1372f4259b30SLisandro Dalcin                                        NULL,
1373f4259b30SLisandro Dalcin                                        NULL,
1374f4259b30SLisandro Dalcin                                        NULL,
1375f4259b30SLisandro Dalcin                                        NULL,
1376f4259b30SLisandro Dalcin                                        /*124*/ NULL,
1377f4259b30SLisandro Dalcin                                        NULL,
1378f4259b30SLisandro Dalcin                                        NULL,
1379f4259b30SLisandro Dalcin                                        NULL,
1380f4259b30SLisandro Dalcin                                        NULL,
1381f4259b30SLisandro Dalcin                                        /*129*/ NULL,
1382f4259b30SLisandro Dalcin                                        NULL,
1383f4259b30SLisandro Dalcin                                        NULL,
1384f4259b30SLisandro Dalcin                                        NULL,
1385f4259b30SLisandro Dalcin                                        NULL,
1386f4259b30SLisandro Dalcin                                        /*134*/ NULL,
1387f4259b30SLisandro Dalcin                                        NULL,
1388f4259b30SLisandro Dalcin                                        NULL,
1389f4259b30SLisandro Dalcin                                        NULL,
1390f4259b30SLisandro Dalcin                                        NULL,
139146533700Sstefano_zampini                                        /*139*/ MatSetBlockSizes_Default,
1392f4259b30SLisandro Dalcin                                        NULL,
1393f4259b30SLisandro Dalcin                                        NULL,
1394f4259b30SLisandro Dalcin                                        NULL,
1395f4259b30SLisandro Dalcin                                        NULL,
1396d70f29a3SPierre Jolivet                                        /*144*/ MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ,
1397d70f29a3SPierre Jolivet                                        NULL,
1398d70f29a3SPierre Jolivet                                        NULL,
139999a7f59eSMark Adams                                        NULL,
140099a7f59eSMark Adams                                        NULL,
14017fb60732SBarry Smith                                        NULL,
1402dec0b466SHong Zhang                                        /*150*/ NULL,
1403eede4a3fSMark Adams                                        MatEliminateZeros_SeqSBAIJ,
14044cc2b5b5SPierre Jolivet                                        NULL,
140542ce410bSJunchao Zhang                                        NULL,
140642ce410bSJunchao Zhang                                        NULL,
1407fe1fc275SAlexander                                        /*155*/ NULL,
1408fe1fc275SAlexander                                        MatCopyHashToXAIJ_Seq_Hash};
1409be1d678aSKris Buschelman 
1410ba38deedSJacob Faibussowitsch static PetscErrorCode MatStoreValues_SeqSBAIJ(Mat mat)
1411d71ae5a4SJacob Faibussowitsch {
14124afc71dfSHong Zhang   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1413d0f46423SBarry Smith   PetscInt      nz  = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2;
141449b5e25fSSatish Balay 
141549b5e25fSSatish Balay   PetscFunctionBegin;
141608401ef6SPierre Jolivet   PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
141749b5e25fSSatish Balay 
141849b5e25fSSatish Balay   /* allocate space for values if not already there */
141948a46eb9SPierre Jolivet   if (!aij->saved_values) PetscCall(PetscMalloc1(nz + 1, &aij->saved_values));
142049b5e25fSSatish Balay 
142149b5e25fSSatish Balay   /* copy values over */
14229566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz));
14233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
142449b5e25fSSatish Balay }
142549b5e25fSSatish Balay 
1426ba38deedSJacob Faibussowitsch static PetscErrorCode MatRetrieveValues_SeqSBAIJ(Mat mat)
1427d71ae5a4SJacob Faibussowitsch {
14284afc71dfSHong Zhang   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1429d0f46423SBarry Smith   PetscInt      nz  = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2;
143049b5e25fSSatish Balay 
143149b5e25fSSatish Balay   PetscFunctionBegin;
143208401ef6SPierre Jolivet   PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
143328b400f6SJacob Faibussowitsch   PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first");
143449b5e25fSSatish Balay 
143549b5e25fSSatish Balay   /* copy values over */
14369566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz));
14373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
143849b5e25fSSatish Balay }
143949b5e25fSSatish Balay 
1440f9663b93SPierre Jolivet static PetscErrorCode MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[])
1441d71ae5a4SJacob Faibussowitsch {
1442c464158bSHong Zhang   Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data;
14434dcd73b1SHong Zhang   PetscInt      i, mbs, nbs, bs2;
14442576faa2SJed Brown   PetscBool     skipallocation = PETSC_FALSE, flg = PETSC_FALSE, realalloc = PETSC_FALSE;
144549b5e25fSSatish Balay 
1446b4e2f619SBarry Smith   PetscFunctionBegin;
1447ad79cf63SBarry Smith   if (B->hash_active) {
1448ad79cf63SBarry Smith     PetscInt bs;
1449aea10558SJacob Faibussowitsch     B->ops[0] = b->cops;
1450ad79cf63SBarry Smith     PetscCall(PetscHMapIJVDestroy(&b->ht));
1451ad79cf63SBarry Smith     PetscCall(MatGetBlockSize(B, &bs));
1452ad79cf63SBarry Smith     if (bs > 1) PetscCall(PetscHSetIJDestroy(&b->bht));
1453ad79cf63SBarry Smith     PetscCall(PetscFree(b->dnz));
1454ad79cf63SBarry Smith     PetscCall(PetscFree(b->bdnz));
1455ad79cf63SBarry Smith     B->hash_active = PETSC_FALSE;
1456ad79cf63SBarry Smith   }
14572576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
1458db4efbfdSBarry Smith 
145958b7e2c1SStefano Zampini   PetscCall(MatSetBlockSize(B, bs));
14609566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
14619566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
146208401ef6SPierre 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);
14639566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs));
1464899cda47SBarry Smith 
146521940c7eSstefano_zampini   B->preallocated = PETSC_TRUE;
146621940c7eSstefano_zampini 
1467d0f46423SBarry Smith   mbs = B->rmap->N / bs;
14684dcd73b1SHong Zhang   nbs = B->cmap->n / bs;
146949b5e25fSSatish Balay   bs2 = bs * bs;
147049b5e25fSSatish Balay 
1471aed4548fSBarry 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");
147249b5e25fSSatish Balay 
1473ab93d7beSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
1474ab93d7beSBarry Smith     skipallocation = PETSC_TRUE;
1475ab93d7beSBarry Smith     nz             = 0;
1476ab93d7beSBarry Smith   }
1477ab93d7beSBarry Smith 
1478435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3;
147908401ef6SPierre Jolivet   PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz);
148049b5e25fSSatish Balay   if (nnz) {
148149b5e25fSSatish Balay     for (i = 0; i < mbs; i++) {
148208401ef6SPierre 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]);
148308401ef6SPierre 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);
148449b5e25fSSatish Balay     }
148549b5e25fSSatish Balay   }
148649b5e25fSSatish Balay 
1487db4efbfdSBarry Smith   B->ops->mult             = MatMult_SeqSBAIJ_N;
1488db4efbfdSBarry Smith   B->ops->multadd          = MatMultAdd_SeqSBAIJ_N;
1489db4efbfdSBarry Smith   B->ops->multtranspose    = MatMult_SeqSBAIJ_N;
1490db4efbfdSBarry Smith   B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N;
149126fbe8dcSKarl Rupp 
14929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL));
149349b5e25fSSatish Balay   if (!flg) {
149449b5e25fSSatish Balay     switch (bs) {
149549b5e25fSSatish Balay     case 1:
149649b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_1;
149749b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_1;
1498431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_1;
1499431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1;
150049b5e25fSSatish Balay       break;
150149b5e25fSSatish Balay     case 2:
150249b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_2;
150349b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_2;
1504431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_2;
1505431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2;
150649b5e25fSSatish Balay       break;
150749b5e25fSSatish Balay     case 3:
150849b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_3;
150949b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_3;
1510431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_3;
1511431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3;
151249b5e25fSSatish Balay       break;
151349b5e25fSSatish Balay     case 4:
151449b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_4;
151549b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_4;
1516431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_4;
1517431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4;
151849b5e25fSSatish Balay       break;
151949b5e25fSSatish Balay     case 5:
152049b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_5;
152149b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_5;
1522431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_5;
1523431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5;
152449b5e25fSSatish Balay       break;
152549b5e25fSSatish Balay     case 6:
152649b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_6;
152749b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_6;
1528431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_6;
1529431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6;
153049b5e25fSSatish Balay       break;
153149b5e25fSSatish Balay     case 7:
1532de53e5efSHong Zhang       B->ops->mult             = MatMult_SeqSBAIJ_7;
153349b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_7;
1534431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_7;
1535431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7;
153649b5e25fSSatish Balay       break;
153749b5e25fSSatish Balay     }
153849b5e25fSSatish Balay   }
153949b5e25fSSatish Balay 
154049b5e25fSSatish Balay   b->mbs = mbs;
15414dcd73b1SHong Zhang   b->nbs = nbs;
1542ab93d7beSBarry Smith   if (!skipallocation) {
15432ee49352SLisandro Dalcin     if (!b->imax) {
15449566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(mbs, &b->imax, mbs, &b->ilen));
154526fbe8dcSKarl Rupp 
1546c760cd28SBarry Smith       b->free_imax_ilen = PETSC_TRUE;
15472ee49352SLisandro Dalcin     }
154849b5e25fSSatish Balay     if (!nnz) {
1549435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
155049b5e25fSSatish Balay       else if (nz <= 0) nz = 1;
15515d2a9ed1SStefano Zampini       nz = PetscMin(nbs, nz);
155226fbe8dcSKarl Rupp       for (i = 0; i < mbs; i++) b->imax[i] = nz;
15539566063dSJacob Faibussowitsch       PetscCall(PetscIntMultError(nz, mbs, &nz));
155449b5e25fSSatish Balay     } else {
1555c73702f5SBarry Smith       PetscInt64 nz64 = 0;
15569371c9d4SSatish Balay       for (i = 0; i < mbs; i++) {
15579371c9d4SSatish Balay         b->imax[i] = nnz[i];
15589371c9d4SSatish Balay         nz64 += nnz[i];
15599371c9d4SSatish Balay       }
15609566063dSJacob Faibussowitsch       PetscCall(PetscIntCast(nz64, &nz));
156149b5e25fSSatish Balay     }
15622ee49352SLisandro Dalcin     /* b->ilen will count nonzeros in each block row so far. */
156326fbe8dcSKarl Rupp     for (i = 0; i < mbs; i++) b->ilen[i] = 0;
15646c6c5352SBarry Smith     /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */
156549b5e25fSSatish Balay 
156649b5e25fSSatish Balay     /* allocate the matrix space */
15679566063dSJacob Faibussowitsch     PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i));
15689f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(bs2 * nz, sizeof(PetscScalar), (void **)&b->a));
15699f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&b->j));
15709f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(B->rmap->n + 1, sizeof(PetscInt), (void **)&b->i));
15719f0612e4SBarry Smith     b->free_a  = PETSC_TRUE;
15729f0612e4SBarry Smith     b->free_ij = PETSC_TRUE;
15739566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->a, nz * bs2));
15749566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->j, nz));
15759f0612e4SBarry Smith     b->free_a  = PETSC_TRUE;
15769f0612e4SBarry Smith     b->free_ij = PETSC_TRUE;
157749b5e25fSSatish Balay 
157849b5e25fSSatish Balay     /* pointer to beginning of each row */
1579e60cf9a0SBarry Smith     b->i[0] = 0;
158026fbe8dcSKarl Rupp     for (i = 1; i < mbs + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1];
158126fbe8dcSKarl Rupp 
1582e811da20SHong Zhang   } else {
1583e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
1584e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
1585ab93d7beSBarry Smith   }
158649b5e25fSSatish Balay 
158749b5e25fSSatish Balay   b->bs2     = bs2;
15886c6c5352SBarry Smith   b->nz      = 0;
1589b32cb4a7SJed Brown   b->maxnz   = nz;
1590f4259b30SLisandro Dalcin   b->inew    = NULL;
1591f4259b30SLisandro Dalcin   b->jnew    = NULL;
1592f4259b30SLisandro Dalcin   b->anew    = NULL;
1593f4259b30SLisandro Dalcin   b->a2anew  = NULL;
15941a3463dfSHong Zhang   b->permute = PETSC_FALSE;
1595cb7b82ddSBarry Smith 
1596cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
1597cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
15989566063dSJacob Faibussowitsch   if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
15993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1600c464158bSHong Zhang }
1601153ea458SHong Zhang 
1602ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ(Mat B, PetscInt bs, const PetscInt ii[], const PetscInt jj[], const PetscScalar V[])
1603d71ae5a4SJacob Faibussowitsch {
16040cd7f59aSBarry Smith   PetscInt      i, j, m, nz, anz, nz_max = 0, *nnz;
1605f4259b30SLisandro Dalcin   PetscScalar  *values      = NULL;
16061c466ed6SStefano Zampini   Mat_SeqSBAIJ *b           = (Mat_SeqSBAIJ *)B->data;
16071c466ed6SStefano Zampini   PetscBool     roworiented = b->roworiented;
16081c466ed6SStefano Zampini   PetscBool     ilw         = b->ignore_ltriangular;
16090cd7f59aSBarry Smith 
161038f409ebSLisandro Dalcin   PetscFunctionBegin;
161108401ef6SPierre Jolivet   PetscCheck(bs >= 1, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_OUTOFRANGE, "Invalid block size specified, must be positive but it is %" PetscInt_FMT, bs);
16129566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(B->rmap, bs));
16139566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(B->cmap, bs));
16149566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
16159566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
16169566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs));
161738f409ebSLisandro Dalcin   m = B->rmap->n / bs;
161838f409ebSLisandro Dalcin 
1619aed4548fSBarry Smith   PetscCheck(!ii[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ii[0] must be 0 but it is %" PetscInt_FMT, ii[0]);
16209566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &nnz));
162138f409ebSLisandro Dalcin   for (i = 0; i < m; i++) {
162238f409ebSLisandro Dalcin     nz = ii[i + 1] - ii[i];
162308401ef6SPierre Jolivet     PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz);
16241c466ed6SStefano Zampini     PetscCheckSorted(nz, jj + ii[i]);
16250cd7f59aSBarry Smith     anz = 0;
16260cd7f59aSBarry Smith     for (j = 0; j < nz; j++) {
16270cd7f59aSBarry Smith       /* count only values on the diagonal or above */
16280cd7f59aSBarry Smith       if (jj[ii[i] + j] >= i) {
16290cd7f59aSBarry Smith         anz = nz - j;
16300cd7f59aSBarry Smith         break;
16310cd7f59aSBarry Smith       }
16320cd7f59aSBarry Smith     }
16331c466ed6SStefano Zampini     nz_max = PetscMax(nz_max, nz);
16340cd7f59aSBarry Smith     nnz[i] = anz;
163538f409ebSLisandro Dalcin   }
16369566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz));
16379566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
163838f409ebSLisandro Dalcin 
163938f409ebSLisandro Dalcin   values = (PetscScalar *)V;
164048a46eb9SPierre Jolivet   if (!values) PetscCall(PetscCalloc1(bs * bs * nz_max, &values));
16411c466ed6SStefano Zampini   b->ignore_ltriangular = PETSC_TRUE;
164238f409ebSLisandro Dalcin   for (i = 0; i < m; i++) {
164338f409ebSLisandro Dalcin     PetscInt        ncols = ii[i + 1] - ii[i];
164438f409ebSLisandro Dalcin     const PetscInt *icols = jj + ii[i];
16451c466ed6SStefano Zampini 
164638f409ebSLisandro Dalcin     if (!roworiented || bs == 1) {
164738f409ebSLisandro Dalcin       const PetscScalar *svals = values + (V ? (bs * bs * ii[i]) : 0);
16489566063dSJacob Faibussowitsch       PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, ncols, icols, svals, INSERT_VALUES));
164938f409ebSLisandro Dalcin     } else {
165038f409ebSLisandro Dalcin       for (j = 0; j < ncols; j++) {
165138f409ebSLisandro Dalcin         const PetscScalar *svals = values + (V ? (bs * bs * (ii[i] + j)) : 0);
16529566063dSJacob Faibussowitsch         PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, 1, &icols[j], svals, INSERT_VALUES));
165338f409ebSLisandro Dalcin       }
165438f409ebSLisandro Dalcin     }
165538f409ebSLisandro Dalcin   }
16569566063dSJacob Faibussowitsch   if (!V) PetscCall(PetscFree(values));
16579566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
16589566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
16599566063dSJacob Faibussowitsch   PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
16601c466ed6SStefano Zampini   b->ignore_ltriangular = ilw;
16613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
166238f409ebSLisandro Dalcin }
166338f409ebSLisandro Dalcin 
1664db4efbfdSBarry Smith /*
1665db4efbfdSBarry Smith    This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization
1666db4efbfdSBarry Smith */
1667d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetNumericFactorization_inplace(Mat B, PetscBool natural)
1668d71ae5a4SJacob Faibussowitsch {
1669ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
1670db4efbfdSBarry Smith   PetscInt  bs  = B->rmap->bs;
1671db4efbfdSBarry Smith 
1672db4efbfdSBarry Smith   PetscFunctionBegin;
16739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL));
1674db4efbfdSBarry Smith   if (flg) bs = 8;
1675db4efbfdSBarry Smith 
1676db4efbfdSBarry Smith   if (!natural) {
1677db4efbfdSBarry Smith     switch (bs) {
1678d71ae5a4SJacob Faibussowitsch     case 1:
1679d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_inplace;
1680d71ae5a4SJacob Faibussowitsch       break;
1681d71ae5a4SJacob Faibussowitsch     case 2:
1682d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2;
1683d71ae5a4SJacob Faibussowitsch       break;
1684d71ae5a4SJacob Faibussowitsch     case 3:
1685d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3;
1686d71ae5a4SJacob Faibussowitsch       break;
1687d71ae5a4SJacob Faibussowitsch     case 4:
1688d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4;
1689d71ae5a4SJacob Faibussowitsch       break;
1690d71ae5a4SJacob Faibussowitsch     case 5:
1691d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5;
1692d71ae5a4SJacob Faibussowitsch       break;
1693d71ae5a4SJacob Faibussowitsch     case 6:
1694d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6;
1695d71ae5a4SJacob Faibussowitsch       break;
1696d71ae5a4SJacob Faibussowitsch     case 7:
1697d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7;
1698d71ae5a4SJacob Faibussowitsch       break;
1699d71ae5a4SJacob Faibussowitsch     default:
1700d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N;
1701d71ae5a4SJacob Faibussowitsch       break;
1702db4efbfdSBarry Smith     }
1703db4efbfdSBarry Smith   } else {
1704db4efbfdSBarry Smith     switch (bs) {
1705d71ae5a4SJacob Faibussowitsch     case 1:
1706d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering_inplace;
1707d71ae5a4SJacob Faibussowitsch       break;
1708d71ae5a4SJacob Faibussowitsch     case 2:
1709d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering;
1710d71ae5a4SJacob Faibussowitsch       break;
1711d71ae5a4SJacob Faibussowitsch     case 3:
1712d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering;
1713d71ae5a4SJacob Faibussowitsch       break;
1714d71ae5a4SJacob Faibussowitsch     case 4:
1715d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering;
1716d71ae5a4SJacob Faibussowitsch       break;
1717d71ae5a4SJacob Faibussowitsch     case 5:
1718d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering;
1719d71ae5a4SJacob Faibussowitsch       break;
1720d71ae5a4SJacob Faibussowitsch     case 6:
1721d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering;
1722d71ae5a4SJacob Faibussowitsch       break;
1723d71ae5a4SJacob Faibussowitsch     case 7:
1724d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering;
1725d71ae5a4SJacob Faibussowitsch       break;
1726d71ae5a4SJacob Faibussowitsch     default:
1727d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering;
1728d71ae5a4SJacob Faibussowitsch       break;
1729db4efbfdSBarry Smith     }
1730db4efbfdSBarry Smith   }
17313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1732db4efbfdSBarry Smith }
1733db4efbfdSBarry Smith 
1734cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType, MatReuse, Mat *);
1735cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType, MatReuse, Mat *);
1736d71ae5a4SJacob Faibussowitsch static PetscErrorCode       MatFactorGetSolverType_petsc(Mat A, MatSolverType *type)
1737d71ae5a4SJacob Faibussowitsch {
17384ac6704cSBarry Smith   PetscFunctionBegin;
17394ac6704cSBarry Smith   *type = MATSOLVERPETSC;
17403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17414ac6704cSBarry Smith }
1742d769727bSBarry Smith 
1743d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A, MatFactorType ftype, Mat *B)
1744d71ae5a4SJacob Faibussowitsch {
1745d0f46423SBarry Smith   PetscInt n = A->rmap->n;
17465c9eb25fSBarry Smith 
17475c9eb25fSBarry Smith   PetscFunctionBegin;
17480e92d65fSHong Zhang #if defined(PETSC_USE_COMPLEX)
174903e5aca4SStefano Zampini   if ((ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) && A->hermitian == PETSC_BOOL3_TRUE && A->symmetric != PETSC_BOOL3_TRUE) {
175003e5aca4SStefano Zampini     PetscCall(PetscInfo(A, "Hermitian MAT_FACTOR_CHOLESKY or MAT_FACTOR_ICC are not supported. Use MAT_FACTOR_LU instead.\n"));
175103e5aca4SStefano Zampini     *B = NULL;
175203e5aca4SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
175303e5aca4SStefano Zampini   }
17540e92d65fSHong Zhang #endif
1755eb1ec7c1SStefano Zampini 
17569566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B));
17579566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*B, n, n, n, n));
17585c9eb25fSBarry Smith   if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
17599566063dSJacob Faibussowitsch     PetscCall(MatSetType(*B, MATSEQSBAIJ));
17609566063dSJacob Faibussowitsch     PetscCall(MatSeqSBAIJSetPreallocation(*B, A->rmap->bs, MAT_SKIP_ALLOCATION, NULL));
176126fbe8dcSKarl Rupp 
17627b056e98SHong Zhang     (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ;
1763c6d0d4f0SHong Zhang     (*B)->ops->iccfactorsymbolic      = MatICCFactorSymbolic_SeqSBAIJ;
17649566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_CHOLESKY]));
17659566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_ICC]));
1766e32f2f54SBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Factor type not supported");
176700c67f3bSHong Zhang 
1768d5f3da31SBarry Smith   (*B)->factortype     = ftype;
1769f73b0415SBarry Smith   (*B)->canuseordering = PETSC_TRUE;
17709566063dSJacob Faibussowitsch   PetscCall(PetscFree((*B)->solvertype));
17719566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*B)->solvertype));
17729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)*B, "MatFactorGetSolverType_C", MatFactorGetSolverType_petsc));
17733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17745c9eb25fSBarry Smith }
17755c9eb25fSBarry Smith 
17768397e458SBarry Smith /*@C
17772ef1f0ffSBarry Smith   MatSeqSBAIJGetArray - gives access to the array where the numerical data for a `MATSEQSBAIJ` matrix is stored
17788397e458SBarry Smith 
17798397e458SBarry Smith   Not Collective
17808397e458SBarry Smith 
17818397e458SBarry Smith   Input Parameter:
1782fe59aa6dSJacob Faibussowitsch . A - a `MATSEQSBAIJ` matrix
17838397e458SBarry Smith 
17848397e458SBarry Smith   Output Parameter:
17858397e458SBarry Smith . array - pointer to the data
17868397e458SBarry Smith 
17878397e458SBarry Smith   Level: intermediate
17888397e458SBarry Smith 
17891cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatSeqSBAIJRestoreArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`
17908397e458SBarry Smith @*/
17915d83a8b1SBarry Smith PetscErrorCode MatSeqSBAIJGetArray(Mat A, PetscScalar *array[])
1792d71ae5a4SJacob Faibussowitsch {
17938397e458SBarry Smith   PetscFunctionBegin;
1794cac4c232SBarry Smith   PetscUseMethod(A, "MatSeqSBAIJGetArray_C", (Mat, PetscScalar **), (A, array));
17953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17968397e458SBarry Smith }
17978397e458SBarry Smith 
17988397e458SBarry Smith /*@C
17992ef1f0ffSBarry Smith   MatSeqSBAIJRestoreArray - returns access to the array where the numerical data for a `MATSEQSBAIJ` matrix is stored obtained by `MatSeqSBAIJGetArray()`
18008397e458SBarry Smith 
18018397e458SBarry Smith   Not Collective
18028397e458SBarry Smith 
18038397e458SBarry Smith   Input Parameters:
1804fe59aa6dSJacob Faibussowitsch + A     - a `MATSEQSBAIJ` matrix
1805a2b725a8SWilliam Gropp - array - pointer to the data
18068397e458SBarry Smith 
18078397e458SBarry Smith   Level: intermediate
18088397e458SBarry Smith 
18091cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatSeqSBAIJGetArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`
18108397e458SBarry Smith @*/
18115d83a8b1SBarry Smith PetscErrorCode MatSeqSBAIJRestoreArray(Mat A, PetscScalar *array[])
1812d71ae5a4SJacob Faibussowitsch {
18138397e458SBarry Smith   PetscFunctionBegin;
1814cac4c232SBarry Smith   PetscUseMethod(A, "MatSeqSBAIJRestoreArray_C", (Mat, PetscScalar **), (A, array));
18153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18168397e458SBarry Smith }
18178397e458SBarry Smith 
18180bad9183SKris Buschelman /*MC
1819fafad747SKris Buschelman   MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices,
18200bad9183SKris Buschelman   based on block compressed sparse row format.  Only the upper triangular portion of the matrix is stored.
18210bad9183SKris Buschelman 
1822828413b8SBarry Smith   For complex numbers by default this matrix is symmetric, NOT Hermitian symmetric. To make it Hermitian symmetric you
182311a5261eSBarry Smith   can call `MatSetOption`(`Mat`, `MAT_HERMITIAN`).
1824828413b8SBarry Smith 
18252ef1f0ffSBarry Smith   Options Database Key:
182611a5261eSBarry Smith   . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to `MatSetFromOptions()`
18270bad9183SKris Buschelman 
18282ef1f0ffSBarry Smith   Level: beginner
18292ef1f0ffSBarry Smith 
183095452b02SPatrick Sanan   Notes:
183195452b02SPatrick Sanan   By default if you insert values into the lower triangular part of the matrix they are simply ignored (since they are not
183211a5261eSBarry 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
18332ef1f0ffSBarry 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.
183471dad5bbSBarry Smith 
1835476417e5SBarry Smith   The number of rows in the matrix must be less than or equal to the number of columns
183671dad5bbSBarry Smith 
18371cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreateSeqSBAIJ()`, `MatType`, `MATMPISBAIJ`
18380bad9183SKris Buschelman M*/
1839d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_SeqSBAIJ(Mat B)
1840d71ae5a4SJacob Faibussowitsch {
1841a23d5eceSKris Buschelman   Mat_SeqSBAIJ *b;
184213f74950SBarry Smith   PetscMPIInt   size;
1843ace3abfcSBarry Smith   PetscBool     no_unroll = PETSC_FALSE, no_inode = PETSC_FALSE;
1844a23d5eceSKris Buschelman 
1845a23d5eceSKris Buschelman   PetscFunctionBegin;
18469566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
184708401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
1848a23d5eceSKris Buschelman 
18494dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
1850a23d5eceSKris Buschelman   B->data   = (void *)b;
1851aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
185226fbe8dcSKarl Rupp 
1853a23d5eceSKris Buschelman   B->ops->destroy    = MatDestroy_SeqSBAIJ;
1854a23d5eceSKris Buschelman   B->ops->view       = MatView_SeqSBAIJ;
1855f4259b30SLisandro Dalcin   b->row             = NULL;
1856f4259b30SLisandro Dalcin   b->icol            = NULL;
1857a23d5eceSKris Buschelman   b->reallocs        = 0;
1858f4259b30SLisandro Dalcin   b->saved_values    = NULL;
18590def2e27SBarry Smith   b->inode.limit     = 5;
18600def2e27SBarry Smith   b->inode.max_limit = 5;
1861a23d5eceSKris Buschelman 
1862a23d5eceSKris Buschelman   b->roworiented        = PETSC_TRUE;
1863a23d5eceSKris Buschelman   b->nonew              = 0;
1864f4259b30SLisandro Dalcin   b->diag               = NULL;
1865f4259b30SLisandro Dalcin   b->solve_work         = NULL;
1866f4259b30SLisandro Dalcin   b->mult_work          = NULL;
1867f4259b30SLisandro Dalcin   B->spptr              = NULL;
1868f2cbd3d5SJed Brown   B->info.nz_unneeded   = (PetscReal)b->maxnz * b->bs2;
1869a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
1870a23d5eceSKris Buschelman 
1871f4259b30SLisandro Dalcin   b->inew    = NULL;
1872f4259b30SLisandro Dalcin   b->jnew    = NULL;
1873f4259b30SLisandro Dalcin   b->anew    = NULL;
1874f4259b30SLisandro Dalcin   b->a2anew  = NULL;
1875a23d5eceSKris Buschelman   b->permute = PETSC_FALSE;
1876a23d5eceSKris Buschelman 
187771dad5bbSBarry Smith   b->ignore_ltriangular = PETSC_TRUE;
187826fbe8dcSKarl Rupp 
18799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_ignore_lower_triangular", &b->ignore_ltriangular, NULL));
1880941593c8SHong Zhang 
1881f5edf698SHong Zhang   b->getrow_utriangular = PETSC_FALSE;
188226fbe8dcSKarl Rupp 
18839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_getrow_uppertriangular", &b->getrow_utriangular, NULL));
1884f5edf698SHong Zhang 
18859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJGetArray_C", MatSeqSBAIJGetArray_SeqSBAIJ));
18869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJRestoreArray_C", MatSeqSBAIJRestoreArray_SeqSBAIJ));
18879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqSBAIJ));
18889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqSBAIJ));
18899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetColumnIndices_C", MatSeqSBAIJSetColumnIndices_SeqSBAIJ));
18909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqaij_C", MatConvert_SeqSBAIJ_SeqAIJ));
18919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqbaij_C", MatConvert_SeqSBAIJ_SeqBAIJ));
18929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocation_C", MatSeqSBAIJSetPreallocation_SeqSBAIJ));
18939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocationCSR_C", MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ));
18946214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
18959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_elemental_C", MatConvert_SeqSBAIJ_Elemental));
18966214f412SHong Zhang #endif
1897d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
18989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_scalapack_C", MatConvert_SBAIJ_ScaLAPACK));
1899d24d4204SJose E. Roman #endif
190023ce1328SBarry Smith 
1901b94d7dedSBarry Smith   B->symmetry_eternal            = PETSC_TRUE;
1902b94d7dedSBarry Smith   B->structural_symmetry_eternal = PETSC_TRUE;
1903b94d7dedSBarry Smith   B->symmetric                   = PETSC_BOOL3_TRUE;
1904b94d7dedSBarry Smith   B->structurally_symmetric      = PETSC_BOOL3_TRUE;
1905eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1906b94d7dedSBarry Smith   B->hermitian = PETSC_BOOL3_FALSE;
1907eb1ec7c1SStefano Zampini #else
1908b94d7dedSBarry Smith   B->hermitian = PETSC_BOOL3_TRUE;
1909eb1ec7c1SStefano Zampini #endif
191013647f61SHong Zhang 
19119566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQSBAIJ));
19120def2e27SBarry Smith 
1913d0609cedSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)B), ((PetscObject)B)->prefix, "Options for SEQSBAIJ matrix", "Mat");
19149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_no_unroll", "Do not optimize for inodes (slower)", NULL, no_unroll, &no_unroll, NULL));
191548a46eb9SPierre Jolivet   if (no_unroll) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_unroll\n"));
19169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_no_inode", "Do not optimize for inodes (slower)", NULL, no_inode, &no_inode, NULL));
19179566063dSJacob Faibussowitsch   if (no_inode) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_inode\n"));
1918*e87b5d96SPierre Jolivet   PetscCall(PetscOptionsInt("-mat_inode_limit", "Do not use inodes larger than this value", NULL, b->inode.limit, &b->inode.limit, NULL));
1919d0609cedSBarry Smith   PetscOptionsEnd();
1920ace3abfcSBarry Smith   b->inode.use = (PetscBool)(!(no_unroll || no_inode));
19210def2e27SBarry Smith   if (b->inode.limit > b->inode.max_limit) b->inode.limit = b->inode.max_limit;
19223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1923a23d5eceSKris Buschelman }
1924a23d5eceSKris Buschelman 
19255d83a8b1SBarry Smith /*@
1926a23d5eceSKris Buschelman   MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block
192711a5261eSBarry Smith   compressed row) `MATSEQSBAIJ` format.  For good matrix assembly performance the
192820f4b53cSBarry Smith   user should preallocate the matrix storage by setting the parameter `nz`
192920f4b53cSBarry Smith   (or the array `nnz`).
1930a23d5eceSKris Buschelman 
1931c3339decSBarry Smith   Collective
1932a23d5eceSKris Buschelman 
1933a23d5eceSKris Buschelman   Input Parameters:
19341c4f3114SJed Brown + B   - the symmetric matrix
193511a5261eSBarry 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
193611a5261eSBarry Smith         blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with `MatCreateVecs()`
1937a23d5eceSKris Buschelman . nz  - number of block nonzeros per block row (same for all rows)
1938a23d5eceSKris Buschelman - nnz - array containing the number of block nonzeros in the upper triangular plus
19392ef1f0ffSBarry Smith         diagonal portion of each block (possibly different for each block row) or `NULL`
1940a23d5eceSKris Buschelman 
1941a23d5eceSKris Buschelman   Options Database Keys:
1942d8a51d2aSBarry Smith + -mat_no_unroll  - uses code that does not unroll the loops in the block calculations (much slower)
1943a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use (only works if a negative bs is passed in
1944a23d5eceSKris Buschelman 
1945a23d5eceSKris Buschelman   Level: intermediate
1946a23d5eceSKris Buschelman 
1947a23d5eceSKris Buschelman   Notes:
194820f4b53cSBarry Smith   Specify the preallocated storage with either `nz` or `nnz` (not both).
19492ef1f0ffSBarry Smith   Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory
1950651615e1SBarry Smith   allocation.  See [Sparse Matrices](sec_matsparse) for details.
1951a23d5eceSKris Buschelman 
195211a5261eSBarry Smith   You can call `MatGetInfo()` to get information on how effective the preallocation was;
1953aa95bbe8SBarry Smith   for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
19542ef1f0ffSBarry Smith   You can also run with the option `-info` and look for messages with the string
1955aa95bbe8SBarry Smith   malloc in them to see if additional memory allocation was needed.
1956aa95bbe8SBarry Smith 
19572ef1f0ffSBarry Smith   If the `nnz` parameter is given then the `nz` parameter is ignored
195849a6f317SBarry Smith 
19591cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()`
1960a23d5eceSKris Buschelman @*/
1961d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetPreallocation(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[])
1962d71ae5a4SJacob Faibussowitsch {
1963a23d5eceSKris Buschelman   PetscFunctionBegin;
19646ba663aaSJed Brown   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
19656ba663aaSJed Brown   PetscValidType(B, 1);
19666ba663aaSJed Brown   PetscValidLogicalCollectiveInt(B, bs, 2);
1967cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqSBAIJSetPreallocation_C", (Mat, PetscInt, PetscInt, const PetscInt[]), (B, bs, nz, nnz));
19683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1969a23d5eceSKris Buschelman }
197049b5e25fSSatish Balay 
197138f409ebSLisandro Dalcin /*@C
197211a5261eSBarry Smith   MatSeqSBAIJSetPreallocationCSR - Creates a sparse parallel matrix in `MATSEQSBAIJ` format using the given nonzero structure and (optional) numerical values
197338f409ebSLisandro Dalcin 
197438f409ebSLisandro Dalcin   Input Parameters:
19751c4f3114SJed Brown + B  - the matrix
1976eab78319SHong Zhang . bs - size of block, the blocks are ALWAYS square.
1977d8a51d2aSBarry Smith . i  - the indices into `j` for the start of each local row (indices start with zero)
1978d8a51d2aSBarry Smith . j  - the column indices for each local row (indices start with zero) these must be sorted for each row
1979d8a51d2aSBarry Smith - v  - optional values in the matrix, use `NULL` if not provided
198038f409ebSLisandro Dalcin 
1981664954b6SBarry Smith   Level: advanced
198238f409ebSLisandro Dalcin 
198338f409ebSLisandro Dalcin   Notes:
1984d8a51d2aSBarry Smith   The `i`,`j`,`v` values are COPIED with this routine; to avoid the copy use `MatCreateSeqSBAIJWithArrays()`
1985d8a51d2aSBarry Smith 
198611a5261eSBarry Smith   The order of the entries in values is specified by the `MatOption` `MAT_ROW_ORIENTED`.  For example, C programs
198711a5261eSBarry Smith   may want to use the default `MAT_ROW_ORIENTED` = `PETSC_TRUE` and use an array v[nnz][bs][bs] where the second index is
198838f409ebSLisandro Dalcin   over rows within a block and the last index is over columns within a block row.  Fortran programs will likely set
198911a5261eSBarry Smith   `MAT_ROW_ORIENTED` = `PETSC_FALSE` and use a Fortran array v(bs,bs,nnz) in which the first index is over rows within a
199038f409ebSLisandro Dalcin   block column and the second index is over columns within a block.
199138f409ebSLisandro Dalcin 
1992d8a51d2aSBarry Smith   Any entries provided that lie below the diagonal are ignored
19930cd7f59aSBarry Smith 
19940cd7f59aSBarry Smith   Though this routine has Preallocation() in the name it also sets the exact nonzero locations of the matrix entries
19950cd7f59aSBarry Smith   and usually the numerical values as well
1996664954b6SBarry Smith 
1997fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqSBAIJ()`, `MatSetValuesBlocked()`, `MatSeqSBAIJSetPreallocation()`
199838f409ebSLisandro Dalcin @*/
1999d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetPreallocationCSR(Mat B, PetscInt bs, const PetscInt i[], const PetscInt j[], const PetscScalar v[])
2000d71ae5a4SJacob Faibussowitsch {
200138f409ebSLisandro Dalcin   PetscFunctionBegin;
200238f409ebSLisandro Dalcin   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
200338f409ebSLisandro Dalcin   PetscValidType(B, 1);
200438f409ebSLisandro Dalcin   PetscValidLogicalCollectiveInt(B, bs, 2);
2005cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqSBAIJSetPreallocationCSR_C", (Mat, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, bs, i, j, v));
20063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
200738f409ebSLisandro Dalcin }
200838f409ebSLisandro Dalcin 
20095d83a8b1SBarry Smith /*@
20102ef1f0ffSBarry Smith   MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in (block
201111a5261eSBarry Smith   compressed row) `MATSEQSBAIJ` format.  For good matrix assembly performance the
20122ef1f0ffSBarry Smith   user should preallocate the matrix storage by setting the parameter `nz`
20132ef1f0ffSBarry Smith   (or the array `nnz`).
201449b5e25fSSatish Balay 
2015d083f849SBarry Smith   Collective
2016c464158bSHong Zhang 
2017c464158bSHong Zhang   Input Parameters:
201811a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
201911a5261eSBarry 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
2020bb7ae925SBarry Smith           blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with MatCreateVecs()
202120f4b53cSBarry Smith . m    - number of rows
202220f4b53cSBarry Smith . n    - number of columns
2023c464158bSHong Zhang . nz   - number of block nonzeros per block row (same for all rows)
2024744e8345SSatish Balay - nnz  - array containing the number of block nonzeros in the upper triangular plus
20252ef1f0ffSBarry Smith          diagonal portion of each block (possibly different for each block row) or `NULL`
2026c464158bSHong Zhang 
2027c464158bSHong Zhang   Output Parameter:
2028c464158bSHong Zhang . A - the symmetric matrix
2029c464158bSHong Zhang 
2030c464158bSHong Zhang   Options Database Keys:
2031d8a51d2aSBarry Smith + -mat_no_unroll  - uses code that does not unroll the loops in the block calculations (much slower)
2032a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use
2033c464158bSHong Zhang 
2034c464158bSHong Zhang   Level: intermediate
2035c464158bSHong Zhang 
20362ef1f0ffSBarry Smith   Notes:
203777433607SBarry Smith   It is recommended that one use `MatCreateFromOptions()` or the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`,
2038f6f02116SRichard Tran Mills   MatXXXXSetPreallocation() paradigm instead of this routine directly.
203911a5261eSBarry Smith   [MatXXXXSetPreallocation() is, for example, `MatSeqAIJSetPreallocation()`]
2040175b88e8SBarry Smith 
20416d6d819aSHong Zhang   The number of rows and columns must be divisible by blocksize.
20426d6d819aSHong Zhang   This matrix type does not support complex Hermitian operation.
2043c464158bSHong Zhang 
20442ef1f0ffSBarry Smith   Specify the preallocated storage with either `nz` or `nnz` (not both).
20452ef1f0ffSBarry Smith   Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory
2046651615e1SBarry Smith   allocation.  See [Sparse Matrices](sec_matsparse) for details.
2047c464158bSHong Zhang 
20482ef1f0ffSBarry Smith   If the `nnz` parameter is given then the `nz` parameter is ignored
204949a6f317SBarry Smith 
20501cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()`
2051c464158bSHong Zhang @*/
2052d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqSBAIJ(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A)
2053d71ae5a4SJacob Faibussowitsch {
2054c464158bSHong Zhang   PetscFunctionBegin;
20559566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
20569566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
20579566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQSBAIJ));
20589566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*A, bs, nz, (PetscInt *)nnz));
20593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
206049b5e25fSSatish Balay }
206149b5e25fSSatish Balay 
2062d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B)
2063d71ae5a4SJacob Faibussowitsch {
206449b5e25fSSatish Balay   Mat           C;
206549b5e25fSSatish Balay   Mat_SeqSBAIJ *c, *a  = (Mat_SeqSBAIJ *)A->data;
2066b40805acSSatish Balay   PetscInt      i, mbs = a->mbs, nz = a->nz, bs2 = a->bs2;
206749b5e25fSSatish Balay 
206849b5e25fSSatish Balay   PetscFunctionBegin;
206931fe6a7dSBarry Smith   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix");
207008401ef6SPierre Jolivet   PetscCheck(a->i[mbs] == nz, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupt matrix");
207149b5e25fSSatish Balay 
2072f4259b30SLisandro Dalcin   *B = NULL;
20739566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
20749566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, A->rmap->N, A->cmap->n, A->rmap->N, A->cmap->n));
20759566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(C, A, A));
20769566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATSEQSBAIJ));
2077692f9cbeSHong Zhang   c = (Mat_SeqSBAIJ *)C->data;
2078692f9cbeSHong Zhang 
2079273d9f13SBarry Smith   C->preallocated       = PETSC_TRUE;
2080d5f3da31SBarry Smith   C->factortype         = A->factortype;
2081f4259b30SLisandro Dalcin   c->row                = NULL;
2082f4259b30SLisandro Dalcin   c->icol               = NULL;
2083f4259b30SLisandro Dalcin   c->saved_values       = NULL;
2084a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
208549b5e25fSSatish Balay   C->assembled          = PETSC_TRUE;
208649b5e25fSSatish Balay 
20879566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->rmap, &C->rmap));
20889566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap, &C->cmap));
208949b5e25fSSatish Balay   c->bs2 = a->bs2;
209049b5e25fSSatish Balay   c->mbs = a->mbs;
209149b5e25fSSatish Balay   c->nbs = a->nbs;
209249b5e25fSSatish Balay 
2093c760cd28SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2094c760cd28SBarry Smith     c->imax           = a->imax;
2095c760cd28SBarry Smith     c->ilen           = a->ilen;
2096c760cd28SBarry Smith     c->free_imax_ilen = PETSC_FALSE;
2097c760cd28SBarry Smith   } else {
209857508eceSPierre Jolivet     PetscCall(PetscMalloc2(mbs + 1, &c->imax, mbs + 1, &c->ilen));
209949b5e25fSSatish Balay     for (i = 0; i < mbs; i++) {
210049b5e25fSSatish Balay       c->imax[i] = a->imax[i];
210149b5e25fSSatish Balay       c->ilen[i] = a->ilen[i];
210249b5e25fSSatish Balay     }
2103c760cd28SBarry Smith     c->free_imax_ilen = PETSC_TRUE;
2104c760cd28SBarry Smith   }
210549b5e25fSSatish Balay 
210649b5e25fSSatish Balay   /* allocate the matrix space */
21079f0612e4SBarry Smith   PetscCall(PetscShmgetAllocateArray(bs2 * nz, sizeof(PetscScalar), (void **)&c->a));
21089f0612e4SBarry Smith   c->free_a = PETSC_TRUE;
21094da8f245SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
21109f0612e4SBarry Smith     PetscCall(PetscArrayzero(c->a, bs2 * nz));
211144e1c64aSLisandro Dalcin     c->i       = a->i;
211244e1c64aSLisandro Dalcin     c->j       = a->j;
21134da8f245SBarry Smith     c->free_ij = PETSC_FALSE;
21144da8f245SBarry Smith     c->parent  = A;
21159566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)A));
21169566063dSJacob Faibussowitsch     PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
21179566063dSJacob Faibussowitsch     PetscCall(MatSetOption(C, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
21184da8f245SBarry Smith   } else {
21199f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&c->j));
21209f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(mbs + 1, sizeof(PetscInt), (void **)&c->i));
21219566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(c->i, a->i, mbs + 1));
21224da8f245SBarry Smith     c->free_ij = PETSC_TRUE;
21234da8f245SBarry Smith   }
212449b5e25fSSatish Balay   if (mbs > 0) {
212548a46eb9SPierre Jolivet     if (cpvalues != MAT_SHARE_NONZERO_PATTERN) PetscCall(PetscArraycpy(c->j, a->j, nz));
212649b5e25fSSatish Balay     if (cpvalues == MAT_COPY_VALUES) {
21279566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->a, a->a, bs2 * nz));
212849b5e25fSSatish Balay     } else {
21299566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(c->a, bs2 * nz));
213049b5e25fSSatish Balay     }
2131a1c3900fSBarry Smith     if (a->jshort) {
213244e1c64aSLisandro Dalcin       /* cannot share jshort, it is reallocated in MatAssemblyEnd_SeqSBAIJ() */
213344e1c64aSLisandro Dalcin       /* if the parent matrix is reassembled, this child matrix will never notice */
21349566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz, &c->jshort));
21359566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->jshort, a->jshort, nz));
213626fbe8dcSKarl Rupp 
21374da8f245SBarry Smith       c->free_jshort = PETSC_TRUE;
21384da8f245SBarry Smith     }
2139a1c3900fSBarry Smith   }
214049b5e25fSSatish Balay 
214149b5e25fSSatish Balay   c->roworiented = a->roworiented;
214249b5e25fSSatish Balay   c->nonew       = a->nonew;
214349b5e25fSSatish Balay 
214449b5e25fSSatish Balay   if (a->diag) {
2145c760cd28SBarry Smith     if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2146c760cd28SBarry Smith       c->diag      = a->diag;
2147c760cd28SBarry Smith       c->free_diag = PETSC_FALSE;
2148c760cd28SBarry Smith     } else {
21499566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mbs, &c->diag));
215026fbe8dcSKarl Rupp       for (i = 0; i < mbs; i++) c->diag[i] = a->diag[i];
2151c760cd28SBarry Smith       c->free_diag = PETSC_TRUE;
2152c760cd28SBarry Smith     }
215344e1c64aSLisandro Dalcin   }
21546c6c5352SBarry Smith   c->nz         = a->nz;
2155f2cbd3d5SJed Brown   c->maxnz      = a->nz; /* Since we allocate exactly the right amount */
2156f4259b30SLisandro Dalcin   c->solve_work = NULL;
2157f4259b30SLisandro Dalcin   c->mult_work  = NULL;
215826fbe8dcSKarl Rupp 
215949b5e25fSSatish Balay   *B = C;
21609566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist));
21613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
216249b5e25fSSatish Balay }
216349b5e25fSSatish Balay 
2164618cc2edSLisandro Dalcin /* Used for both SeqBAIJ and SeqSBAIJ matrices */
2165618cc2edSLisandro Dalcin #define MatLoad_SeqSBAIJ_Binary MatLoad_SeqBAIJ_Binary
2166618cc2edSLisandro Dalcin 
2167d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_SeqSBAIJ(Mat mat, PetscViewer viewer)
2168d71ae5a4SJacob Faibussowitsch {
21697f489da9SVaclav Hapla   PetscBool isbinary;
21702f480046SShri Abhyankar 
21712f480046SShri Abhyankar   PetscFunctionBegin;
21729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
217328b400f6SJacob 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);
21749566063dSJacob Faibussowitsch   PetscCall(MatLoad_SeqSBAIJ_Binary(mat, viewer));
21753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21762f480046SShri Abhyankar }
21772f480046SShri Abhyankar 
2178c75a6043SHong Zhang /*@
217911a5261eSBarry Smith   MatCreateSeqSBAIJWithArrays - Creates an sequential `MATSEQSBAIJ` matrix using matrix elements
2180c75a6043SHong Zhang   (upper triangular entries in CSR format) provided by the user.
2181c75a6043SHong Zhang 
2182d083f849SBarry Smith   Collective
2183c75a6043SHong Zhang 
2184c75a6043SHong Zhang   Input Parameters:
2185c75a6043SHong Zhang + comm - must be an MPI communicator of size 1
2186c75a6043SHong Zhang . bs   - size of block
2187c75a6043SHong Zhang . m    - number of rows
2188c75a6043SHong Zhang . n    - number of columns
2189483a2f95SBarry 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
2190c75a6043SHong Zhang . j    - column indices
2191c75a6043SHong Zhang - a    - matrix values
2192c75a6043SHong Zhang 
2193c75a6043SHong Zhang   Output Parameter:
2194c75a6043SHong Zhang . mat - the matrix
2195c75a6043SHong Zhang 
2196dfb205c3SBarry Smith   Level: advanced
2197c75a6043SHong Zhang 
2198c75a6043SHong Zhang   Notes:
21992ef1f0ffSBarry Smith   The `i`, `j`, and `a` arrays are not copied by this routine, the user must free these arrays
2200c75a6043SHong Zhang   once the matrix is destroyed
2201c75a6043SHong Zhang 
2202c75a6043SHong Zhang   You cannot set new nonzero locations into this matrix, that will generate an error.
2203c75a6043SHong Zhang 
22042ef1f0ffSBarry Smith   The `i` and `j` indices are 0 based
2205c75a6043SHong Zhang 
22062ef1f0ffSBarry Smith   When block size is greater than 1 the matrix values must be stored using the `MATSBAIJ` storage format. For block size of 1
2207dfb205c3SBarry Smith   it is the regular CSR format excluding the lower triangular elements.
2208dfb205c3SBarry Smith 
22091cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSBAIJ()`, `MatCreateSeqSBAIJ()`
2210c75a6043SHong Zhang @*/
2211d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqSBAIJWithArrays(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat)
2212d71ae5a4SJacob Faibussowitsch {
2213c75a6043SHong Zhang   PetscInt      ii;
2214c75a6043SHong Zhang   Mat_SeqSBAIJ *sbaij;
2215c75a6043SHong Zhang 
2216c75a6043SHong Zhang   PetscFunctionBegin;
221708401ef6SPierre Jolivet   PetscCheck(bs == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "block size %" PetscInt_FMT " > 1 is not supported yet", bs);
2218aed4548fSBarry Smith   PetscCheck(m == 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0");
2219c75a6043SHong Zhang 
22209566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, mat));
22219566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mat, m, n, m, n));
22229566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mat, MATSEQSBAIJ));
22239566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*mat, bs, MAT_SKIP_ALLOCATION, NULL));
2224c75a6043SHong Zhang   sbaij = (Mat_SeqSBAIJ *)(*mat)->data;
22259566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(m, &sbaij->imax, m, &sbaij->ilen));
2226c75a6043SHong Zhang 
2227c75a6043SHong Zhang   sbaij->i = i;
2228c75a6043SHong Zhang   sbaij->j = j;
2229c75a6043SHong Zhang   sbaij->a = a;
223026fbe8dcSKarl Rupp 
2231c75a6043SHong Zhang   sbaij->nonew          = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2232e6b907acSBarry Smith   sbaij->free_a         = PETSC_FALSE;
2233e6b907acSBarry Smith   sbaij->free_ij        = PETSC_FALSE;
2234ddf7884eSMatthew Knepley   sbaij->free_imax_ilen = PETSC_TRUE;
2235c75a6043SHong Zhang 
2236c75a6043SHong Zhang   for (ii = 0; ii < m; ii++) {
2237c75a6043SHong Zhang     sbaij->ilen[ii] = sbaij->imax[ii] = i[ii + 1] - i[ii];
22386bdcaf15SBarry 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]);
2239c75a6043SHong Zhang   }
224076bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2241c75a6043SHong Zhang     for (ii = 0; ii < sbaij->i[m]; ii++) {
22426bdcaf15SBarry 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]);
22436bdcaf15SBarry 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]);
2244c75a6043SHong Zhang     }
224576bd3646SJed Brown   }
2246c75a6043SHong Zhang 
22479566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY));
22489566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY));
22493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2250c75a6043SHong Zhang }
2251d06b337dSHong Zhang 
2252d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
2253d71ae5a4SJacob Faibussowitsch {
225459f5e6ceSHong Zhang   PetscFunctionBegin;
22559566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPISBAIJ(comm, inmat, n, scall, outmat));
22563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
225759f5e6ceSHong Zhang }
2258