xref: /petsc/src/mat/impls/sbaij/seq/sbaij.c (revision d1a032db6cd7c39db5bfaa476c8e42d0c0ea531b)
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
31*d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE))
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
219*d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE))
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 {
5449f196a02SMartin Diehl   PetscBool isascii, isbinary, isdraw;
54549b5e25fSSatish Balay 
54649b5e25fSSatish Balay   PetscFunctionBegin;
5479f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
5489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
5499566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
5509f196a02SMartin Diehl   if (isascii) {
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) {
661966bd95aSPierre Jolivet         PetscCheck(a->ignore_ltriangular, 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)");
662966bd95aSPierre Jolivet         continue; /* ignore lower triangular block */
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) {
825966bd95aSPierre Jolivet         PetscCheck(a->ignore_ltriangular, 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)");
826966bd95aSPierre Jolivet         continue; /* ignore lower triangular values */
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,
13208bb0f5c6SPierre Jolivet                                        MatGetRowMaxAbs_SeqSBAIJ,
13218bb0f5c6SPierre Jolivet                                        /* 69*/ NULL,
132228d58a37SPierre Jolivet                                        MatConvert_MPISBAIJ_Basic,
1323f4259b30SLisandro Dalcin                                        NULL,
1324f4259b30SLisandro Dalcin                                        NULL,
13258bb0f5c6SPierre Jolivet                                        NULL,
1326f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
1327f4259b30SLisandro Dalcin                                        NULL,
1328f4259b30SLisandro Dalcin                                        NULL,
132997304618SKris Buschelman                                        MatGetInertia_SeqSBAIJ,
13305bba2384SShri Abhyankar                                        MatLoad_SeqSBAIJ,
13318bb0f5c6SPierre Jolivet                                        /* 79*/ NULL,
13326cff0a6bSPierre Jolivet                                        NULL,
1333efcf0fc3SBarry Smith                                        MatIsStructurallySymmetric_SeqSBAIJ,
1334f4259b30SLisandro Dalcin                                        NULL,
1335f4259b30SLisandro Dalcin                                        NULL,
13368bb0f5c6SPierre Jolivet                                        /* 84*/ NULL,
13378bb0f5c6SPierre Jolivet                                        NULL,
13388bb0f5c6SPierre Jolivet                                        NULL,
13398bb0f5c6SPierre Jolivet                                        NULL,
13408bb0f5c6SPierre Jolivet                                        NULL,
1341f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
1342f4259b30SLisandro Dalcin                                        NULL,
1343f4259b30SLisandro Dalcin                                        NULL,
1344f4259b30SLisandro Dalcin                                        NULL,
13458bb0f5c6SPierre Jolivet                                        MatConjugate_SeqSBAIJ,
1346f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
1347f4259b30SLisandro Dalcin                                        NULL,
134899cafbc1SBarry Smith                                        MatRealPart_SeqSBAIJ,
1349f5edf698SHong Zhang                                        MatImaginaryPart_SeqSBAIJ,
1350f5edf698SHong Zhang                                        MatGetRowUpperTriangular_SeqSBAIJ,
13518bb0f5c6SPierre Jolivet                                        /* 99*/ MatRestoreRowUpperTriangular_SeqSBAIJ,
13528bb0f5c6SPierre Jolivet                                        NULL,
13538bb0f5c6SPierre Jolivet                                        NULL,
13548bb0f5c6SPierre Jolivet                                        NULL,
13558bb0f5c6SPierre Jolivet                                        NULL,
13568bb0f5c6SPierre Jolivet                                        /*104*/ MatMissingDiagonal_SeqSBAIJ,
13578bb0f5c6SPierre Jolivet                                        NULL,
13588bb0f5c6SPierre Jolivet                                        NULL,
13598bb0f5c6SPierre Jolivet                                        NULL,
13608bb0f5c6SPierre Jolivet                                        NULL,
1361f4259b30SLisandro Dalcin                                        /*109*/ NULL,
1362f4259b30SLisandro Dalcin                                        NULL,
1363f4259b30SLisandro Dalcin                                        NULL,
1364f4259b30SLisandro Dalcin                                        NULL,
13658bb0f5c6SPierre Jolivet                                        NULL,
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,
13798bb0f5c6SPierre Jolivet                                        MatSetBlockSizes_Default,
1380f4259b30SLisandro Dalcin                                        NULL,
1381f4259b30SLisandro Dalcin                                        /*129*/ NULL,
1382f4259b30SLisandro Dalcin                                        NULL,
13838bb0f5c6SPierre Jolivet                                        MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ,
1384f4259b30SLisandro Dalcin                                        NULL,
1385f4259b30SLisandro Dalcin                                        NULL,
1386f4259b30SLisandro Dalcin                                        /*134*/ NULL,
1387f4259b30SLisandro Dalcin                                        NULL,
1388f4259b30SLisandro Dalcin                                        NULL,
1389eede4a3fSMark Adams                                        MatEliminateZeros_SeqSBAIJ,
13904cc2b5b5SPierre Jolivet                                        NULL,
13918bb0f5c6SPierre Jolivet                                        /*139*/ NULL,
139242ce410bSJunchao Zhang                                        NULL,
139342ce410bSJunchao Zhang                                        NULL,
139403db1824SAlex Lindsay                                        MatCopyHashToXAIJ_Seq_Hash,
1395c2be7ffeSStefano Zampini                                        NULL,
139603db1824SAlex Lindsay                                        NULL};
1397be1d678aSKris Buschelman 
1398ba38deedSJacob Faibussowitsch static PetscErrorCode MatStoreValues_SeqSBAIJ(Mat mat)
1399d71ae5a4SJacob Faibussowitsch {
14004afc71dfSHong Zhang   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1401d0f46423SBarry Smith   PetscInt      nz  = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2;
140249b5e25fSSatish Balay 
140349b5e25fSSatish Balay   PetscFunctionBegin;
140408401ef6SPierre Jolivet   PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
140549b5e25fSSatish Balay 
140649b5e25fSSatish Balay   /* allocate space for values if not already there */
140748a46eb9SPierre Jolivet   if (!aij->saved_values) PetscCall(PetscMalloc1(nz + 1, &aij->saved_values));
140849b5e25fSSatish Balay 
140949b5e25fSSatish Balay   /* copy values over */
14109566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz));
14113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
141249b5e25fSSatish Balay }
141349b5e25fSSatish Balay 
1414ba38deedSJacob Faibussowitsch static PetscErrorCode MatRetrieveValues_SeqSBAIJ(Mat mat)
1415d71ae5a4SJacob Faibussowitsch {
14164afc71dfSHong Zhang   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1417d0f46423SBarry Smith   PetscInt      nz  = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2;
141849b5e25fSSatish Balay 
141949b5e25fSSatish Balay   PetscFunctionBegin;
142008401ef6SPierre Jolivet   PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
142128b400f6SJacob Faibussowitsch   PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first");
142249b5e25fSSatish Balay 
142349b5e25fSSatish Balay   /* copy values over */
14249566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz));
14253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
142649b5e25fSSatish Balay }
142749b5e25fSSatish Balay 
1428f9663b93SPierre Jolivet static PetscErrorCode MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[])
1429d71ae5a4SJacob Faibussowitsch {
1430c464158bSHong Zhang   Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data;
14314dcd73b1SHong Zhang   PetscInt      i, mbs, nbs, bs2;
14322576faa2SJed Brown   PetscBool     skipallocation = PETSC_FALSE, flg = PETSC_FALSE, realalloc = PETSC_FALSE;
143349b5e25fSSatish Balay 
1434b4e2f619SBarry Smith   PetscFunctionBegin;
1435ad79cf63SBarry Smith   if (B->hash_active) {
1436ad79cf63SBarry Smith     PetscInt bs;
1437aea10558SJacob Faibussowitsch     B->ops[0] = b->cops;
1438ad79cf63SBarry Smith     PetscCall(PetscHMapIJVDestroy(&b->ht));
1439ad79cf63SBarry Smith     PetscCall(MatGetBlockSize(B, &bs));
1440ad79cf63SBarry Smith     if (bs > 1) PetscCall(PetscHSetIJDestroy(&b->bht));
1441ad79cf63SBarry Smith     PetscCall(PetscFree(b->dnz));
1442ad79cf63SBarry Smith     PetscCall(PetscFree(b->bdnz));
1443ad79cf63SBarry Smith     B->hash_active = PETSC_FALSE;
1444ad79cf63SBarry Smith   }
14452576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
1446db4efbfdSBarry Smith 
144758b7e2c1SStefano Zampini   PetscCall(MatSetBlockSize(B, bs));
14489566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
14499566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
145008401ef6SPierre 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);
14519566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs));
1452899cda47SBarry Smith 
145321940c7eSstefano_zampini   B->preallocated = PETSC_TRUE;
145421940c7eSstefano_zampini 
1455d0f46423SBarry Smith   mbs = B->rmap->N / bs;
14564dcd73b1SHong Zhang   nbs = B->cmap->n / bs;
145749b5e25fSSatish Balay   bs2 = bs * bs;
145849b5e25fSSatish Balay 
1459aed4548fSBarry 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");
146049b5e25fSSatish Balay 
1461ab93d7beSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
1462ab93d7beSBarry Smith     skipallocation = PETSC_TRUE;
1463ab93d7beSBarry Smith     nz             = 0;
1464ab93d7beSBarry Smith   }
1465ab93d7beSBarry Smith 
1466435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3;
146708401ef6SPierre Jolivet   PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz);
146849b5e25fSSatish Balay   if (nnz) {
146949b5e25fSSatish Balay     for (i = 0; i < mbs; i++) {
147008401ef6SPierre 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]);
147108401ef6SPierre 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);
147249b5e25fSSatish Balay     }
147349b5e25fSSatish Balay   }
147449b5e25fSSatish Balay 
1475db4efbfdSBarry Smith   B->ops->mult             = MatMult_SeqSBAIJ_N;
1476db4efbfdSBarry Smith   B->ops->multadd          = MatMultAdd_SeqSBAIJ_N;
1477db4efbfdSBarry Smith   B->ops->multtranspose    = MatMult_SeqSBAIJ_N;
1478db4efbfdSBarry Smith   B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N;
147926fbe8dcSKarl Rupp 
14809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL));
148149b5e25fSSatish Balay   if (!flg) {
148249b5e25fSSatish Balay     switch (bs) {
148349b5e25fSSatish Balay     case 1:
148449b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_1;
148549b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_1;
1486431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_1;
1487431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1;
148849b5e25fSSatish Balay       break;
148949b5e25fSSatish Balay     case 2:
149049b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_2;
149149b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_2;
1492431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_2;
1493431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2;
149449b5e25fSSatish Balay       break;
149549b5e25fSSatish Balay     case 3:
149649b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_3;
149749b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_3;
1498431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_3;
1499431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3;
150049b5e25fSSatish Balay       break;
150149b5e25fSSatish Balay     case 4:
150249b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_4;
150349b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_4;
1504431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_4;
1505431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4;
150649b5e25fSSatish Balay       break;
150749b5e25fSSatish Balay     case 5:
150849b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_5;
150949b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_5;
1510431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_5;
1511431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5;
151249b5e25fSSatish Balay       break;
151349b5e25fSSatish Balay     case 6:
151449b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_6;
151549b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_6;
1516431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_6;
1517431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6;
151849b5e25fSSatish Balay       break;
151949b5e25fSSatish Balay     case 7:
1520de53e5efSHong Zhang       B->ops->mult             = MatMult_SeqSBAIJ_7;
152149b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_7;
1522431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_7;
1523431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7;
152449b5e25fSSatish Balay       break;
152549b5e25fSSatish Balay     }
152649b5e25fSSatish Balay   }
152749b5e25fSSatish Balay 
152849b5e25fSSatish Balay   b->mbs = mbs;
15294dcd73b1SHong Zhang   b->nbs = nbs;
1530ab93d7beSBarry Smith   if (!skipallocation) {
15312ee49352SLisandro Dalcin     if (!b->imax) {
15329566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(mbs, &b->imax, mbs, &b->ilen));
153326fbe8dcSKarl Rupp 
1534c760cd28SBarry Smith       b->free_imax_ilen = PETSC_TRUE;
15352ee49352SLisandro Dalcin     }
153649b5e25fSSatish Balay     if (!nnz) {
1537435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
153849b5e25fSSatish Balay       else if (nz <= 0) nz = 1;
15395d2a9ed1SStefano Zampini       nz = PetscMin(nbs, nz);
154026fbe8dcSKarl Rupp       for (i = 0; i < mbs; i++) b->imax[i] = nz;
15419566063dSJacob Faibussowitsch       PetscCall(PetscIntMultError(nz, mbs, &nz));
154249b5e25fSSatish Balay     } else {
1543c73702f5SBarry Smith       PetscInt64 nz64 = 0;
15449371c9d4SSatish Balay       for (i = 0; i < mbs; i++) {
15459371c9d4SSatish Balay         b->imax[i] = nnz[i];
15469371c9d4SSatish Balay         nz64 += nnz[i];
15479371c9d4SSatish Balay       }
15489566063dSJacob Faibussowitsch       PetscCall(PetscIntCast(nz64, &nz));
154949b5e25fSSatish Balay     }
15502ee49352SLisandro Dalcin     /* b->ilen will count nonzeros in each block row so far. */
155126fbe8dcSKarl Rupp     for (i = 0; i < mbs; i++) b->ilen[i] = 0;
15526c6c5352SBarry Smith     /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */
155349b5e25fSSatish Balay 
155449b5e25fSSatish Balay     /* allocate the matrix space */
15559566063dSJacob Faibussowitsch     PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i));
15569f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(bs2 * nz, sizeof(PetscScalar), (void **)&b->a));
15579f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&b->j));
15589f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(B->rmap->n + 1, sizeof(PetscInt), (void **)&b->i));
15599f0612e4SBarry Smith     b->free_a  = PETSC_TRUE;
15609f0612e4SBarry Smith     b->free_ij = PETSC_TRUE;
15619566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->a, nz * bs2));
15629566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->j, nz));
15639f0612e4SBarry Smith     b->free_a  = PETSC_TRUE;
15649f0612e4SBarry Smith     b->free_ij = PETSC_TRUE;
156549b5e25fSSatish Balay 
156649b5e25fSSatish Balay     /* pointer to beginning of each row */
1567e60cf9a0SBarry Smith     b->i[0] = 0;
156826fbe8dcSKarl Rupp     for (i = 1; i < mbs + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1];
156926fbe8dcSKarl Rupp 
1570e811da20SHong Zhang   } else {
1571e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
1572e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
1573ab93d7beSBarry Smith   }
157449b5e25fSSatish Balay 
157549b5e25fSSatish Balay   b->bs2     = bs2;
15766c6c5352SBarry Smith   b->nz      = 0;
1577b32cb4a7SJed Brown   b->maxnz   = nz;
1578f4259b30SLisandro Dalcin   b->inew    = NULL;
1579f4259b30SLisandro Dalcin   b->jnew    = NULL;
1580f4259b30SLisandro Dalcin   b->anew    = NULL;
1581f4259b30SLisandro Dalcin   b->a2anew  = NULL;
15821a3463dfSHong Zhang   b->permute = PETSC_FALSE;
1583cb7b82ddSBarry Smith 
1584cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
1585cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
15869566063dSJacob Faibussowitsch   if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
15873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1588c464158bSHong Zhang }
1589153ea458SHong Zhang 
1590ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ(Mat B, PetscInt bs, const PetscInt ii[], const PetscInt jj[], const PetscScalar V[])
1591d71ae5a4SJacob Faibussowitsch {
15920cd7f59aSBarry Smith   PetscInt      i, j, m, nz, anz, nz_max = 0, *nnz;
1593f4259b30SLisandro Dalcin   PetscScalar  *values      = NULL;
15941c466ed6SStefano Zampini   Mat_SeqSBAIJ *b           = (Mat_SeqSBAIJ *)B->data;
15951c466ed6SStefano Zampini   PetscBool     roworiented = b->roworiented;
15961c466ed6SStefano Zampini   PetscBool     ilw         = b->ignore_ltriangular;
15970cd7f59aSBarry Smith 
159838f409ebSLisandro Dalcin   PetscFunctionBegin;
159908401ef6SPierre Jolivet   PetscCheck(bs >= 1, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_OUTOFRANGE, "Invalid block size specified, must be positive but it is %" PetscInt_FMT, bs);
16009566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(B->rmap, bs));
16019566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(B->cmap, bs));
16029566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
16039566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
16049566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs));
160538f409ebSLisandro Dalcin   m = B->rmap->n / bs;
160638f409ebSLisandro Dalcin 
1607aed4548fSBarry Smith   PetscCheck(!ii[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ii[0] must be 0 but it is %" PetscInt_FMT, ii[0]);
16089566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &nnz));
160938f409ebSLisandro Dalcin   for (i = 0; i < m; i++) {
161038f409ebSLisandro Dalcin     nz = ii[i + 1] - ii[i];
161108401ef6SPierre Jolivet     PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz);
16121c466ed6SStefano Zampini     PetscCheckSorted(nz, jj + ii[i]);
16130cd7f59aSBarry Smith     anz = 0;
16140cd7f59aSBarry Smith     for (j = 0; j < nz; j++) {
16150cd7f59aSBarry Smith       /* count only values on the diagonal or above */
16160cd7f59aSBarry Smith       if (jj[ii[i] + j] >= i) {
16170cd7f59aSBarry Smith         anz = nz - j;
16180cd7f59aSBarry Smith         break;
16190cd7f59aSBarry Smith       }
16200cd7f59aSBarry Smith     }
16211c466ed6SStefano Zampini     nz_max = PetscMax(nz_max, nz);
16220cd7f59aSBarry Smith     nnz[i] = anz;
162338f409ebSLisandro Dalcin   }
16249566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz));
16259566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
162638f409ebSLisandro Dalcin 
162738f409ebSLisandro Dalcin   values = (PetscScalar *)V;
162848a46eb9SPierre Jolivet   if (!values) PetscCall(PetscCalloc1(bs * bs * nz_max, &values));
16291c466ed6SStefano Zampini   b->ignore_ltriangular = PETSC_TRUE;
163038f409ebSLisandro Dalcin   for (i = 0; i < m; i++) {
163138f409ebSLisandro Dalcin     PetscInt        ncols = ii[i + 1] - ii[i];
163238f409ebSLisandro Dalcin     const PetscInt *icols = jj + ii[i];
16331c466ed6SStefano Zampini 
163438f409ebSLisandro Dalcin     if (!roworiented || bs == 1) {
163538f409ebSLisandro Dalcin       const PetscScalar *svals = values + (V ? (bs * bs * ii[i]) : 0);
16369566063dSJacob Faibussowitsch       PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, ncols, icols, svals, INSERT_VALUES));
163738f409ebSLisandro Dalcin     } else {
163838f409ebSLisandro Dalcin       for (j = 0; j < ncols; j++) {
163938f409ebSLisandro Dalcin         const PetscScalar *svals = values + (V ? (bs * bs * (ii[i] + j)) : 0);
16409566063dSJacob Faibussowitsch         PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, 1, &icols[j], svals, INSERT_VALUES));
164138f409ebSLisandro Dalcin       }
164238f409ebSLisandro Dalcin     }
164338f409ebSLisandro Dalcin   }
16449566063dSJacob Faibussowitsch   if (!V) PetscCall(PetscFree(values));
16459566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
16469566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
16479566063dSJacob Faibussowitsch   PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
16481c466ed6SStefano Zampini   b->ignore_ltriangular = ilw;
16493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
165038f409ebSLisandro Dalcin }
165138f409ebSLisandro Dalcin 
1652db4efbfdSBarry Smith /*
1653db4efbfdSBarry Smith    This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization
1654db4efbfdSBarry Smith */
1655d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetNumericFactorization_inplace(Mat B, PetscBool natural)
1656d71ae5a4SJacob Faibussowitsch {
1657ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
1658db4efbfdSBarry Smith   PetscInt  bs  = B->rmap->bs;
1659db4efbfdSBarry Smith 
1660db4efbfdSBarry Smith   PetscFunctionBegin;
16619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL));
1662db4efbfdSBarry Smith   if (flg) bs = 8;
1663db4efbfdSBarry Smith 
1664db4efbfdSBarry Smith   if (!natural) {
1665db4efbfdSBarry Smith     switch (bs) {
1666d71ae5a4SJacob Faibussowitsch     case 1:
1667d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_inplace;
1668d71ae5a4SJacob Faibussowitsch       break;
1669d71ae5a4SJacob Faibussowitsch     case 2:
1670d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2;
1671d71ae5a4SJacob Faibussowitsch       break;
1672d71ae5a4SJacob Faibussowitsch     case 3:
1673d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3;
1674d71ae5a4SJacob Faibussowitsch       break;
1675d71ae5a4SJacob Faibussowitsch     case 4:
1676d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4;
1677d71ae5a4SJacob Faibussowitsch       break;
1678d71ae5a4SJacob Faibussowitsch     case 5:
1679d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5;
1680d71ae5a4SJacob Faibussowitsch       break;
1681d71ae5a4SJacob Faibussowitsch     case 6:
1682d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6;
1683d71ae5a4SJacob Faibussowitsch       break;
1684d71ae5a4SJacob Faibussowitsch     case 7:
1685d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7;
1686d71ae5a4SJacob Faibussowitsch       break;
1687d71ae5a4SJacob Faibussowitsch     default:
1688d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N;
1689d71ae5a4SJacob Faibussowitsch       break;
1690db4efbfdSBarry Smith     }
1691db4efbfdSBarry Smith   } else {
1692db4efbfdSBarry Smith     switch (bs) {
1693d71ae5a4SJacob Faibussowitsch     case 1:
1694d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering_inplace;
1695d71ae5a4SJacob Faibussowitsch       break;
1696d71ae5a4SJacob Faibussowitsch     case 2:
1697d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering;
1698d71ae5a4SJacob Faibussowitsch       break;
1699d71ae5a4SJacob Faibussowitsch     case 3:
1700d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering;
1701d71ae5a4SJacob Faibussowitsch       break;
1702d71ae5a4SJacob Faibussowitsch     case 4:
1703d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering;
1704d71ae5a4SJacob Faibussowitsch       break;
1705d71ae5a4SJacob Faibussowitsch     case 5:
1706d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering;
1707d71ae5a4SJacob Faibussowitsch       break;
1708d71ae5a4SJacob Faibussowitsch     case 6:
1709d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering;
1710d71ae5a4SJacob Faibussowitsch       break;
1711d71ae5a4SJacob Faibussowitsch     case 7:
1712d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering;
1713d71ae5a4SJacob Faibussowitsch       break;
1714d71ae5a4SJacob Faibussowitsch     default:
1715d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering;
1716d71ae5a4SJacob Faibussowitsch       break;
1717db4efbfdSBarry Smith     }
1718db4efbfdSBarry Smith   }
17193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1720db4efbfdSBarry Smith }
1721db4efbfdSBarry Smith 
1722cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType, MatReuse, Mat *);
1723cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType, MatReuse, Mat *);
1724d71ae5a4SJacob Faibussowitsch static PetscErrorCode       MatFactorGetSolverType_petsc(Mat A, MatSolverType *type)
1725d71ae5a4SJacob Faibussowitsch {
17264ac6704cSBarry Smith   PetscFunctionBegin;
17274ac6704cSBarry Smith   *type = MATSOLVERPETSC;
17283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17294ac6704cSBarry Smith }
1730d769727bSBarry Smith 
1731d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A, MatFactorType ftype, Mat *B)
1732d71ae5a4SJacob Faibussowitsch {
1733d0f46423SBarry Smith   PetscInt n = A->rmap->n;
17345c9eb25fSBarry Smith 
17355c9eb25fSBarry Smith   PetscFunctionBegin;
17360e92d65fSHong Zhang #if defined(PETSC_USE_COMPLEX)
173703e5aca4SStefano Zampini   if ((ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) && A->hermitian == PETSC_BOOL3_TRUE && A->symmetric != PETSC_BOOL3_TRUE) {
173803e5aca4SStefano Zampini     PetscCall(PetscInfo(A, "Hermitian MAT_FACTOR_CHOLESKY or MAT_FACTOR_ICC are not supported. Use MAT_FACTOR_LU instead.\n"));
173903e5aca4SStefano Zampini     *B = NULL;
174003e5aca4SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
174103e5aca4SStefano Zampini   }
17420e92d65fSHong Zhang #endif
1743eb1ec7c1SStefano Zampini 
17449566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B));
17459566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*B, n, n, n, n));
1746966bd95aSPierre Jolivet   PetscCheck(ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC, PETSC_COMM_SELF, PETSC_ERR_SUP, "Factor type not supported");
17479566063dSJacob Faibussowitsch   PetscCall(MatSetType(*B, MATSEQSBAIJ));
17489566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*B, A->rmap->bs, MAT_SKIP_ALLOCATION, NULL));
174926fbe8dcSKarl Rupp 
17507b056e98SHong Zhang   (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ;
1751c6d0d4f0SHong Zhang   (*B)->ops->iccfactorsymbolic      = MatICCFactorSymbolic_SeqSBAIJ;
17529566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_CHOLESKY]));
17539566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_ICC]));
175400c67f3bSHong Zhang 
1755d5f3da31SBarry Smith   (*B)->factortype     = ftype;
1756f73b0415SBarry Smith   (*B)->canuseordering = PETSC_TRUE;
17579566063dSJacob Faibussowitsch   PetscCall(PetscFree((*B)->solvertype));
17589566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*B)->solvertype));
17599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)*B, "MatFactorGetSolverType_C", MatFactorGetSolverType_petsc));
17603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17615c9eb25fSBarry Smith }
17625c9eb25fSBarry Smith 
17638397e458SBarry Smith /*@C
17642ef1f0ffSBarry Smith   MatSeqSBAIJGetArray - gives access to the array where the numerical data for a `MATSEQSBAIJ` matrix is stored
17658397e458SBarry Smith 
17668397e458SBarry Smith   Not Collective
17678397e458SBarry Smith 
17688397e458SBarry Smith   Input Parameter:
1769fe59aa6dSJacob Faibussowitsch . A - a `MATSEQSBAIJ` matrix
17708397e458SBarry Smith 
17718397e458SBarry Smith   Output Parameter:
17728397e458SBarry Smith . array - pointer to the data
17738397e458SBarry Smith 
17748397e458SBarry Smith   Level: intermediate
17758397e458SBarry Smith 
17761cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatSeqSBAIJRestoreArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`
17778397e458SBarry Smith @*/
17785d83a8b1SBarry Smith PetscErrorCode MatSeqSBAIJGetArray(Mat A, PetscScalar *array[])
1779d71ae5a4SJacob Faibussowitsch {
17808397e458SBarry Smith   PetscFunctionBegin;
1781cac4c232SBarry Smith   PetscUseMethod(A, "MatSeqSBAIJGetArray_C", (Mat, PetscScalar **), (A, array));
17823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17838397e458SBarry Smith }
17848397e458SBarry Smith 
17858397e458SBarry Smith /*@C
17862ef1f0ffSBarry Smith   MatSeqSBAIJRestoreArray - returns access to the array where the numerical data for a `MATSEQSBAIJ` matrix is stored obtained by `MatSeqSBAIJGetArray()`
17878397e458SBarry Smith 
17888397e458SBarry Smith   Not Collective
17898397e458SBarry Smith 
17908397e458SBarry Smith   Input Parameters:
1791fe59aa6dSJacob Faibussowitsch + A     - a `MATSEQSBAIJ` matrix
1792a2b725a8SWilliam Gropp - array - pointer to the data
17938397e458SBarry Smith 
17948397e458SBarry Smith   Level: intermediate
17958397e458SBarry Smith 
17961cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatSeqSBAIJGetArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`
17978397e458SBarry Smith @*/
17985d83a8b1SBarry Smith PetscErrorCode MatSeqSBAIJRestoreArray(Mat A, PetscScalar *array[])
1799d71ae5a4SJacob Faibussowitsch {
18008397e458SBarry Smith   PetscFunctionBegin;
1801cac4c232SBarry Smith   PetscUseMethod(A, "MatSeqSBAIJRestoreArray_C", (Mat, PetscScalar **), (A, array));
18023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18038397e458SBarry Smith }
18048397e458SBarry Smith 
18050bad9183SKris Buschelman /*MC
1806fafad747SKris Buschelman   MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices,
18070bad9183SKris Buschelman   based on block compressed sparse row format.  Only the upper triangular portion of the matrix is stored.
18080bad9183SKris Buschelman 
1809828413b8SBarry Smith   For complex numbers by default this matrix is symmetric, NOT Hermitian symmetric. To make it Hermitian symmetric you
181011a5261eSBarry Smith   can call `MatSetOption`(`Mat`, `MAT_HERMITIAN`).
1811828413b8SBarry Smith 
18122ef1f0ffSBarry Smith   Options Database Key:
181311a5261eSBarry Smith   . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to `MatSetFromOptions()`
18140bad9183SKris Buschelman 
18152ef1f0ffSBarry Smith   Level: beginner
18162ef1f0ffSBarry Smith 
181795452b02SPatrick Sanan   Notes:
181895452b02SPatrick Sanan   By default if you insert values into the lower triangular part of the matrix they are simply ignored (since they are not
181911a5261eSBarry 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
18202ef1f0ffSBarry 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.
182171dad5bbSBarry Smith 
1822476417e5SBarry Smith   The number of rows in the matrix must be less than or equal to the number of columns
182371dad5bbSBarry Smith 
18241cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreateSeqSBAIJ()`, `MatType`, `MATMPISBAIJ`
18250bad9183SKris Buschelman M*/
1826d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_SeqSBAIJ(Mat B)
1827d71ae5a4SJacob Faibussowitsch {
1828a23d5eceSKris Buschelman   Mat_SeqSBAIJ *b;
182913f74950SBarry Smith   PetscMPIInt   size;
1830ace3abfcSBarry Smith   PetscBool     no_unroll = PETSC_FALSE, no_inode = PETSC_FALSE;
1831a23d5eceSKris Buschelman 
1832a23d5eceSKris Buschelman   PetscFunctionBegin;
18339566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
183408401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
1835a23d5eceSKris Buschelman 
18364dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
1837a23d5eceSKris Buschelman   B->data   = (void *)b;
1838aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
183926fbe8dcSKarl Rupp 
1840a23d5eceSKris Buschelman   B->ops->destroy    = MatDestroy_SeqSBAIJ;
1841a23d5eceSKris Buschelman   B->ops->view       = MatView_SeqSBAIJ;
1842f4259b30SLisandro Dalcin   b->row             = NULL;
1843f4259b30SLisandro Dalcin   b->icol            = NULL;
1844a23d5eceSKris Buschelman   b->reallocs        = 0;
1845f4259b30SLisandro Dalcin   b->saved_values    = NULL;
18460def2e27SBarry Smith   b->inode.limit     = 5;
18470def2e27SBarry Smith   b->inode.max_limit = 5;
1848a23d5eceSKris Buschelman 
1849a23d5eceSKris Buschelman   b->roworiented        = PETSC_TRUE;
1850a23d5eceSKris Buschelman   b->nonew              = 0;
1851f4259b30SLisandro Dalcin   b->diag               = NULL;
1852f4259b30SLisandro Dalcin   b->solve_work         = NULL;
1853f4259b30SLisandro Dalcin   b->mult_work          = NULL;
1854f4259b30SLisandro Dalcin   B->spptr              = NULL;
1855f2cbd3d5SJed Brown   B->info.nz_unneeded   = (PetscReal)b->maxnz * b->bs2;
1856a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
1857a23d5eceSKris Buschelman 
1858f4259b30SLisandro Dalcin   b->inew    = NULL;
1859f4259b30SLisandro Dalcin   b->jnew    = NULL;
1860f4259b30SLisandro Dalcin   b->anew    = NULL;
1861f4259b30SLisandro Dalcin   b->a2anew  = NULL;
1862a23d5eceSKris Buschelman   b->permute = PETSC_FALSE;
1863a23d5eceSKris Buschelman 
186471dad5bbSBarry Smith   b->ignore_ltriangular = PETSC_TRUE;
186526fbe8dcSKarl Rupp 
18669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_ignore_lower_triangular", &b->ignore_ltriangular, NULL));
1867941593c8SHong Zhang 
1868f5edf698SHong Zhang   b->getrow_utriangular = PETSC_FALSE;
186926fbe8dcSKarl Rupp 
18709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_getrow_uppertriangular", &b->getrow_utriangular, NULL));
1871f5edf698SHong Zhang 
18729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJGetArray_C", MatSeqSBAIJGetArray_SeqSBAIJ));
18739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJRestoreArray_C", MatSeqSBAIJRestoreArray_SeqSBAIJ));
18749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqSBAIJ));
18759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqSBAIJ));
18769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetColumnIndices_C", MatSeqSBAIJSetColumnIndices_SeqSBAIJ));
18779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqaij_C", MatConvert_SeqSBAIJ_SeqAIJ));
18789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqbaij_C", MatConvert_SeqSBAIJ_SeqBAIJ));
18799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocation_C", MatSeqSBAIJSetPreallocation_SeqSBAIJ));
18809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocationCSR_C", MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ));
18816214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
18829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_elemental_C", MatConvert_SeqSBAIJ_Elemental));
18836214f412SHong Zhang #endif
1884*d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE))
18859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_scalapack_C", MatConvert_SBAIJ_ScaLAPACK));
1886d24d4204SJose E. Roman #endif
188723ce1328SBarry Smith 
1888b94d7dedSBarry Smith   B->symmetry_eternal            = PETSC_TRUE;
1889b94d7dedSBarry Smith   B->structural_symmetry_eternal = PETSC_TRUE;
1890b94d7dedSBarry Smith   B->symmetric                   = PETSC_BOOL3_TRUE;
1891b94d7dedSBarry Smith   B->structurally_symmetric      = PETSC_BOOL3_TRUE;
1892eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1893b94d7dedSBarry Smith   B->hermitian = PETSC_BOOL3_FALSE;
1894eb1ec7c1SStefano Zampini #else
1895b94d7dedSBarry Smith   B->hermitian = PETSC_BOOL3_TRUE;
1896eb1ec7c1SStefano Zampini #endif
189713647f61SHong Zhang 
18989566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQSBAIJ));
18990def2e27SBarry Smith 
1900d0609cedSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)B), ((PetscObject)B)->prefix, "Options for SEQSBAIJ matrix", "Mat");
19019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_no_unroll", "Do not optimize for inodes (slower)", NULL, no_unroll, &no_unroll, NULL));
190248a46eb9SPierre Jolivet   if (no_unroll) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_unroll\n"));
19039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_no_inode", "Do not optimize for inodes (slower)", NULL, no_inode, &no_inode, NULL));
19049566063dSJacob Faibussowitsch   if (no_inode) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_inode\n"));
1905e87b5d96SPierre Jolivet   PetscCall(PetscOptionsInt("-mat_inode_limit", "Do not use inodes larger than this value", NULL, b->inode.limit, &b->inode.limit, NULL));
1906d0609cedSBarry Smith   PetscOptionsEnd();
1907ace3abfcSBarry Smith   b->inode.use = (PetscBool)(!(no_unroll || no_inode));
19080def2e27SBarry Smith   if (b->inode.limit > b->inode.max_limit) b->inode.limit = b->inode.max_limit;
19093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1910a23d5eceSKris Buschelman }
1911a23d5eceSKris Buschelman 
19125d83a8b1SBarry Smith /*@
1913a23d5eceSKris Buschelman   MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block
191411a5261eSBarry Smith   compressed row) `MATSEQSBAIJ` format.  For good matrix assembly performance the
191520f4b53cSBarry Smith   user should preallocate the matrix storage by setting the parameter `nz`
191620f4b53cSBarry Smith   (or the array `nnz`).
1917a23d5eceSKris Buschelman 
1918c3339decSBarry Smith   Collective
1919a23d5eceSKris Buschelman 
1920a23d5eceSKris Buschelman   Input Parameters:
19211c4f3114SJed Brown + B   - the symmetric matrix
192211a5261eSBarry 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
192311a5261eSBarry Smith         blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with `MatCreateVecs()`
1924a23d5eceSKris Buschelman . nz  - number of block nonzeros per block row (same for all rows)
1925a23d5eceSKris Buschelman - nnz - array containing the number of block nonzeros in the upper triangular plus
19262ef1f0ffSBarry Smith         diagonal portion of each block (possibly different for each block row) or `NULL`
1927a23d5eceSKris Buschelman 
1928a23d5eceSKris Buschelman   Options Database Keys:
1929d8a51d2aSBarry Smith + -mat_no_unroll  - uses code that does not unroll the loops in the block calculations (much slower)
1930a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use (only works if a negative bs is passed in
1931a23d5eceSKris Buschelman 
1932a23d5eceSKris Buschelman   Level: intermediate
1933a23d5eceSKris Buschelman 
1934a23d5eceSKris Buschelman   Notes:
193520f4b53cSBarry Smith   Specify the preallocated storage with either `nz` or `nnz` (not both).
19362ef1f0ffSBarry Smith   Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory
1937651615e1SBarry Smith   allocation.  See [Sparse Matrices](sec_matsparse) for details.
1938a23d5eceSKris Buschelman 
193911a5261eSBarry Smith   You can call `MatGetInfo()` to get information on how effective the preallocation was;
1940aa95bbe8SBarry Smith   for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
19412ef1f0ffSBarry Smith   You can also run with the option `-info` and look for messages with the string
1942aa95bbe8SBarry Smith   malloc in them to see if additional memory allocation was needed.
1943aa95bbe8SBarry Smith 
19442ef1f0ffSBarry Smith   If the `nnz` parameter is given then the `nz` parameter is ignored
194549a6f317SBarry Smith 
19461cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()`
1947a23d5eceSKris Buschelman @*/
1948d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetPreallocation(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[])
1949d71ae5a4SJacob Faibussowitsch {
1950a23d5eceSKris Buschelman   PetscFunctionBegin;
19516ba663aaSJed Brown   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
19526ba663aaSJed Brown   PetscValidType(B, 1);
19536ba663aaSJed Brown   PetscValidLogicalCollectiveInt(B, bs, 2);
1954cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqSBAIJSetPreallocation_C", (Mat, PetscInt, PetscInt, const PetscInt[]), (B, bs, nz, nnz));
19553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1956a23d5eceSKris Buschelman }
195749b5e25fSSatish Balay 
195838f409ebSLisandro Dalcin /*@C
195911a5261eSBarry Smith   MatSeqSBAIJSetPreallocationCSR - Creates a sparse parallel matrix in `MATSEQSBAIJ` format using the given nonzero structure and (optional) numerical values
196038f409ebSLisandro Dalcin 
196138f409ebSLisandro Dalcin   Input Parameters:
19621c4f3114SJed Brown + B  - the matrix
1963eab78319SHong Zhang . bs - size of block, the blocks are ALWAYS square.
1964d8a51d2aSBarry Smith . i  - the indices into `j` for the start of each local row (indices start with zero)
1965d8a51d2aSBarry Smith . j  - the column indices for each local row (indices start with zero) these must be sorted for each row
1966d8a51d2aSBarry Smith - v  - optional values in the matrix, use `NULL` if not provided
196738f409ebSLisandro Dalcin 
1968664954b6SBarry Smith   Level: advanced
196938f409ebSLisandro Dalcin 
197038f409ebSLisandro Dalcin   Notes:
1971d8a51d2aSBarry Smith   The `i`,`j`,`v` values are COPIED with this routine; to avoid the copy use `MatCreateSeqSBAIJWithArrays()`
1972d8a51d2aSBarry Smith 
197311a5261eSBarry Smith   The order of the entries in values is specified by the `MatOption` `MAT_ROW_ORIENTED`.  For example, C programs
197411a5261eSBarry 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
197538f409ebSLisandro Dalcin   over rows within a block and the last index is over columns within a block row.  Fortran programs will likely set
197611a5261eSBarry 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
197738f409ebSLisandro Dalcin   block column and the second index is over columns within a block.
197838f409ebSLisandro Dalcin 
1979d8a51d2aSBarry Smith   Any entries provided that lie below the diagonal are ignored
19800cd7f59aSBarry Smith 
19810cd7f59aSBarry Smith   Though this routine has Preallocation() in the name it also sets the exact nonzero locations of the matrix entries
19820cd7f59aSBarry Smith   and usually the numerical values as well
1983664954b6SBarry Smith 
1984fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqSBAIJ()`, `MatSetValuesBlocked()`, `MatSeqSBAIJSetPreallocation()`
198538f409ebSLisandro Dalcin @*/
1986d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetPreallocationCSR(Mat B, PetscInt bs, const PetscInt i[], const PetscInt j[], const PetscScalar v[])
1987d71ae5a4SJacob Faibussowitsch {
198838f409ebSLisandro Dalcin   PetscFunctionBegin;
198938f409ebSLisandro Dalcin   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
199038f409ebSLisandro Dalcin   PetscValidType(B, 1);
199138f409ebSLisandro Dalcin   PetscValidLogicalCollectiveInt(B, bs, 2);
1992cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqSBAIJSetPreallocationCSR_C", (Mat, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, bs, i, j, v));
19933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
199438f409ebSLisandro Dalcin }
199538f409ebSLisandro Dalcin 
19965d83a8b1SBarry Smith /*@
19972ef1f0ffSBarry Smith   MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in (block
199811a5261eSBarry Smith   compressed row) `MATSEQSBAIJ` format.  For good matrix assembly performance the
19992ef1f0ffSBarry Smith   user should preallocate the matrix storage by setting the parameter `nz`
20002ef1f0ffSBarry Smith   (or the array `nnz`).
200149b5e25fSSatish Balay 
2002d083f849SBarry Smith   Collective
2003c464158bSHong Zhang 
2004c464158bSHong Zhang   Input Parameters:
200511a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
200611a5261eSBarry 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
2007bb7ae925SBarry Smith           blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with MatCreateVecs()
200820f4b53cSBarry Smith . m    - number of rows
200920f4b53cSBarry Smith . n    - number of columns
2010c464158bSHong Zhang . nz   - number of block nonzeros per block row (same for all rows)
2011744e8345SSatish Balay - nnz  - array containing the number of block nonzeros in the upper triangular plus
20122ef1f0ffSBarry Smith          diagonal portion of each block (possibly different for each block row) or `NULL`
2013c464158bSHong Zhang 
2014c464158bSHong Zhang   Output Parameter:
2015c464158bSHong Zhang . A - the symmetric matrix
2016c464158bSHong Zhang 
2017c464158bSHong Zhang   Options Database Keys:
2018d8a51d2aSBarry Smith + -mat_no_unroll  - uses code that does not unroll the loops in the block calculations (much slower)
2019a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use
2020c464158bSHong Zhang 
2021c464158bSHong Zhang   Level: intermediate
2022c464158bSHong Zhang 
20232ef1f0ffSBarry Smith   Notes:
202477433607SBarry Smith   It is recommended that one use `MatCreateFromOptions()` or the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`,
2025f6f02116SRichard Tran Mills   MatXXXXSetPreallocation() paradigm instead of this routine directly.
202611a5261eSBarry Smith   [MatXXXXSetPreallocation() is, for example, `MatSeqAIJSetPreallocation()`]
2027175b88e8SBarry Smith 
20286d6d819aSHong Zhang   The number of rows and columns must be divisible by blocksize.
20296d6d819aSHong Zhang   This matrix type does not support complex Hermitian operation.
2030c464158bSHong Zhang 
20312ef1f0ffSBarry Smith   Specify the preallocated storage with either `nz` or `nnz` (not both).
20322ef1f0ffSBarry Smith   Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory
2033651615e1SBarry Smith   allocation.  See [Sparse Matrices](sec_matsparse) for details.
2034c464158bSHong Zhang 
20352ef1f0ffSBarry Smith   If the `nnz` parameter is given then the `nz` parameter is ignored
203649a6f317SBarry Smith 
20371cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()`
2038c464158bSHong Zhang @*/
2039d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqSBAIJ(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A)
2040d71ae5a4SJacob Faibussowitsch {
2041c464158bSHong Zhang   PetscFunctionBegin;
20429566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
20439566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
20449566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQSBAIJ));
20459566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*A, bs, nz, (PetscInt *)nnz));
20463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
204749b5e25fSSatish Balay }
204849b5e25fSSatish Balay 
2049d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B)
2050d71ae5a4SJacob Faibussowitsch {
205149b5e25fSSatish Balay   Mat           C;
205249b5e25fSSatish Balay   Mat_SeqSBAIJ *c, *a  = (Mat_SeqSBAIJ *)A->data;
2053b40805acSSatish Balay   PetscInt      i, mbs = a->mbs, nz = a->nz, bs2 = a->bs2;
205449b5e25fSSatish Balay 
205549b5e25fSSatish Balay   PetscFunctionBegin;
205631fe6a7dSBarry Smith   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix");
205708401ef6SPierre Jolivet   PetscCheck(a->i[mbs] == nz, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupt matrix");
205849b5e25fSSatish Balay 
2059f4259b30SLisandro Dalcin   *B = NULL;
20609566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
20619566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, A->rmap->N, A->cmap->n, A->rmap->N, A->cmap->n));
20629566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(C, A, A));
20639566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATSEQSBAIJ));
2064692f9cbeSHong Zhang   c = (Mat_SeqSBAIJ *)C->data;
2065692f9cbeSHong Zhang 
2066273d9f13SBarry Smith   C->preallocated       = PETSC_TRUE;
2067d5f3da31SBarry Smith   C->factortype         = A->factortype;
2068f4259b30SLisandro Dalcin   c->row                = NULL;
2069f4259b30SLisandro Dalcin   c->icol               = NULL;
2070f4259b30SLisandro Dalcin   c->saved_values       = NULL;
2071a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
207249b5e25fSSatish Balay   C->assembled          = PETSC_TRUE;
207349b5e25fSSatish Balay 
20749566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->rmap, &C->rmap));
20759566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap, &C->cmap));
207649b5e25fSSatish Balay   c->bs2 = a->bs2;
207749b5e25fSSatish Balay   c->mbs = a->mbs;
207849b5e25fSSatish Balay   c->nbs = a->nbs;
207949b5e25fSSatish Balay 
2080c760cd28SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2081c760cd28SBarry Smith     c->imax           = a->imax;
2082c760cd28SBarry Smith     c->ilen           = a->ilen;
2083c760cd28SBarry Smith     c->free_imax_ilen = PETSC_FALSE;
2084c760cd28SBarry Smith   } else {
208557508eceSPierre Jolivet     PetscCall(PetscMalloc2(mbs + 1, &c->imax, mbs + 1, &c->ilen));
208649b5e25fSSatish Balay     for (i = 0; i < mbs; i++) {
208749b5e25fSSatish Balay       c->imax[i] = a->imax[i];
208849b5e25fSSatish Balay       c->ilen[i] = a->ilen[i];
208949b5e25fSSatish Balay     }
2090c760cd28SBarry Smith     c->free_imax_ilen = PETSC_TRUE;
2091c760cd28SBarry Smith   }
209249b5e25fSSatish Balay 
209349b5e25fSSatish Balay   /* allocate the matrix space */
20949f0612e4SBarry Smith   PetscCall(PetscShmgetAllocateArray(bs2 * nz, sizeof(PetscScalar), (void **)&c->a));
20959f0612e4SBarry Smith   c->free_a = PETSC_TRUE;
20964da8f245SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
20979f0612e4SBarry Smith     PetscCall(PetscArrayzero(c->a, bs2 * nz));
209844e1c64aSLisandro Dalcin     c->i       = a->i;
209944e1c64aSLisandro Dalcin     c->j       = a->j;
21004da8f245SBarry Smith     c->free_ij = PETSC_FALSE;
21014da8f245SBarry Smith     c->parent  = A;
21029566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)A));
21039566063dSJacob Faibussowitsch     PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
21049566063dSJacob Faibussowitsch     PetscCall(MatSetOption(C, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
21054da8f245SBarry Smith   } else {
21069f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&c->j));
21079f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(mbs + 1, sizeof(PetscInt), (void **)&c->i));
21089566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(c->i, a->i, mbs + 1));
21094da8f245SBarry Smith     c->free_ij = PETSC_TRUE;
21104da8f245SBarry Smith   }
211149b5e25fSSatish Balay   if (mbs > 0) {
211248a46eb9SPierre Jolivet     if (cpvalues != MAT_SHARE_NONZERO_PATTERN) PetscCall(PetscArraycpy(c->j, a->j, nz));
211349b5e25fSSatish Balay     if (cpvalues == MAT_COPY_VALUES) {
21149566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->a, a->a, bs2 * nz));
211549b5e25fSSatish Balay     } else {
21169566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(c->a, bs2 * nz));
211749b5e25fSSatish Balay     }
2118a1c3900fSBarry Smith     if (a->jshort) {
211944e1c64aSLisandro Dalcin       /* cannot share jshort, it is reallocated in MatAssemblyEnd_SeqSBAIJ() */
212044e1c64aSLisandro Dalcin       /* if the parent matrix is reassembled, this child matrix will never notice */
21219566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz, &c->jshort));
21229566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->jshort, a->jshort, nz));
212326fbe8dcSKarl Rupp 
21244da8f245SBarry Smith       c->free_jshort = PETSC_TRUE;
21254da8f245SBarry Smith     }
2126a1c3900fSBarry Smith   }
212749b5e25fSSatish Balay 
212849b5e25fSSatish Balay   c->roworiented = a->roworiented;
212949b5e25fSSatish Balay   c->nonew       = a->nonew;
213049b5e25fSSatish Balay 
213149b5e25fSSatish Balay   if (a->diag) {
2132c760cd28SBarry Smith     if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2133c760cd28SBarry Smith       c->diag      = a->diag;
2134c760cd28SBarry Smith       c->free_diag = PETSC_FALSE;
2135c760cd28SBarry Smith     } else {
21369566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mbs, &c->diag));
213726fbe8dcSKarl Rupp       for (i = 0; i < mbs; i++) c->diag[i] = a->diag[i];
2138c760cd28SBarry Smith       c->free_diag = PETSC_TRUE;
2139c760cd28SBarry Smith     }
214044e1c64aSLisandro Dalcin   }
21416c6c5352SBarry Smith   c->nz         = a->nz;
2142f2cbd3d5SJed Brown   c->maxnz      = a->nz; /* Since we allocate exactly the right amount */
2143f4259b30SLisandro Dalcin   c->solve_work = NULL;
2144f4259b30SLisandro Dalcin   c->mult_work  = NULL;
214526fbe8dcSKarl Rupp 
214649b5e25fSSatish Balay   *B = C;
21479566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist));
21483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
214949b5e25fSSatish Balay }
215049b5e25fSSatish Balay 
2151618cc2edSLisandro Dalcin /* Used for both SeqBAIJ and SeqSBAIJ matrices */
2152618cc2edSLisandro Dalcin #define MatLoad_SeqSBAIJ_Binary MatLoad_SeqBAIJ_Binary
2153618cc2edSLisandro Dalcin 
2154d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_SeqSBAIJ(Mat mat, PetscViewer viewer)
2155d71ae5a4SJacob Faibussowitsch {
21567f489da9SVaclav Hapla   PetscBool isbinary;
21572f480046SShri Abhyankar 
21582f480046SShri Abhyankar   PetscFunctionBegin;
21599566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
216028b400f6SJacob 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);
21619566063dSJacob Faibussowitsch   PetscCall(MatLoad_SeqSBAIJ_Binary(mat, viewer));
21623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21632f480046SShri Abhyankar }
21642f480046SShri Abhyankar 
2165c75a6043SHong Zhang /*@
216611a5261eSBarry Smith   MatCreateSeqSBAIJWithArrays - Creates an sequential `MATSEQSBAIJ` matrix using matrix elements
2167c75a6043SHong Zhang   (upper triangular entries in CSR format) provided by the user.
2168c75a6043SHong Zhang 
2169d083f849SBarry Smith   Collective
2170c75a6043SHong Zhang 
2171c75a6043SHong Zhang   Input Parameters:
2172c75a6043SHong Zhang + comm - must be an MPI communicator of size 1
2173c75a6043SHong Zhang . bs   - size of block
2174c75a6043SHong Zhang . m    - number of rows
2175c75a6043SHong Zhang . n    - number of columns
2176483a2f95SBarry 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
2177c75a6043SHong Zhang . j    - column indices
2178c75a6043SHong Zhang - a    - matrix values
2179c75a6043SHong Zhang 
2180c75a6043SHong Zhang   Output Parameter:
2181c75a6043SHong Zhang . mat - the matrix
2182c75a6043SHong Zhang 
2183dfb205c3SBarry Smith   Level: advanced
2184c75a6043SHong Zhang 
2185c75a6043SHong Zhang   Notes:
21862ef1f0ffSBarry Smith   The `i`, `j`, and `a` arrays are not copied by this routine, the user must free these arrays
2187c75a6043SHong Zhang   once the matrix is destroyed
2188c75a6043SHong Zhang 
2189c75a6043SHong Zhang   You cannot set new nonzero locations into this matrix, that will generate an error.
2190c75a6043SHong Zhang 
21912ef1f0ffSBarry Smith   The `i` and `j` indices are 0 based
2192c75a6043SHong Zhang 
21932ef1f0ffSBarry Smith   When block size is greater than 1 the matrix values must be stored using the `MATSBAIJ` storage format. For block size of 1
2194dfb205c3SBarry Smith   it is the regular CSR format excluding the lower triangular elements.
2195dfb205c3SBarry Smith 
21961cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSBAIJ()`, `MatCreateSeqSBAIJ()`
2197c75a6043SHong Zhang @*/
2198d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqSBAIJWithArrays(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat)
2199d71ae5a4SJacob Faibussowitsch {
2200c75a6043SHong Zhang   PetscInt      ii;
2201c75a6043SHong Zhang   Mat_SeqSBAIJ *sbaij;
2202c75a6043SHong Zhang 
2203c75a6043SHong Zhang   PetscFunctionBegin;
220408401ef6SPierre Jolivet   PetscCheck(bs == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "block size %" PetscInt_FMT " > 1 is not supported yet", bs);
2205aed4548fSBarry Smith   PetscCheck(m == 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0");
2206c75a6043SHong Zhang 
22079566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, mat));
22089566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mat, m, n, m, n));
22099566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mat, MATSEQSBAIJ));
22109566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*mat, bs, MAT_SKIP_ALLOCATION, NULL));
2211c75a6043SHong Zhang   sbaij = (Mat_SeqSBAIJ *)(*mat)->data;
22129566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(m, &sbaij->imax, m, &sbaij->ilen));
2213c75a6043SHong Zhang 
2214c75a6043SHong Zhang   sbaij->i = i;
2215c75a6043SHong Zhang   sbaij->j = j;
2216c75a6043SHong Zhang   sbaij->a = a;
221726fbe8dcSKarl Rupp 
2218c75a6043SHong Zhang   sbaij->nonew          = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2219e6b907acSBarry Smith   sbaij->free_a         = PETSC_FALSE;
2220e6b907acSBarry Smith   sbaij->free_ij        = PETSC_FALSE;
2221ddf7884eSMatthew Knepley   sbaij->free_imax_ilen = PETSC_TRUE;
2222c75a6043SHong Zhang 
2223c75a6043SHong Zhang   for (ii = 0; ii < m; ii++) {
2224c75a6043SHong Zhang     sbaij->ilen[ii] = sbaij->imax[ii] = i[ii + 1] - i[ii];
22256bdcaf15SBarry 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]);
2226c75a6043SHong Zhang   }
222776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2228c75a6043SHong Zhang     for (ii = 0; ii < sbaij->i[m]; ii++) {
22296bdcaf15SBarry 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]);
22306bdcaf15SBarry 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]);
2231c75a6043SHong Zhang     }
223276bd3646SJed Brown   }
2233c75a6043SHong Zhang 
22349566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY));
22359566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY));
22363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2237c75a6043SHong Zhang }
2238d06b337dSHong Zhang 
2239d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
2240d71ae5a4SJacob Faibussowitsch {
224159f5e6ceSHong Zhang   PetscFunctionBegin;
22429566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPISBAIJ(comm, inmat, n, scall, outmat));
22433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
224459f5e6ceSHong Zhang }
2245