xref: /petsc/src/mat/impls/sbaij/seq/sbaij.c (revision b0c98d1d8bc8fbb369fd6b04fbfd2a9276aa7d86)
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
31d1a032dbSPierre 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 
36421480d9SBarry Smith MatGetDiagonalMarkers(SeqSBAIJ, A->rmap->bs)
3749b5e25fSSatish Balay 
38d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowIJ_SeqSBAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool blockcompressed, PetscInt *nn, const PetscInt *inia[], const PetscInt *inja[], PetscBool *done)
39d71ae5a4SJacob Faibussowitsch {
40a6ece127SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
412462f5fdSStefano Zampini   PetscInt      i, j, n = a->mbs, nz = a->i[n], *tia, *tja, bs = A->rmap->bs, k, l, cnt;
422462f5fdSStefano Zampini   PetscInt    **ia = (PetscInt **)inia, **ja = (PetscInt **)inja;
4349b5e25fSSatish Balay 
4449b5e25fSSatish Balay   PetscFunctionBegin;
45d3e5a4abSHong Zhang   *nn = n;
463ba16761SJacob Faibussowitsch   if (!ia) PetscFunctionReturn(PETSC_SUCCESS);
472462f5fdSStefano Zampini   if (symmetric) {
489566063dSJacob Faibussowitsch     PetscCall(MatToSymmetricIJ_SeqAIJ(n, a->i, a->j, PETSC_FALSE, 0, 0, &tia, &tja));
492462f5fdSStefano Zampini     nz = tia[n];
502462f5fdSStefano Zampini   } else {
519371c9d4SSatish Balay     tia = a->i;
529371c9d4SSatish Balay     tja = a->j;
532462f5fdSStefano Zampini   }
542462f5fdSStefano Zampini 
552462f5fdSStefano Zampini   if (!blockcompressed && bs > 1) {
562462f5fdSStefano Zampini     (*nn) *= bs;
578f7157efSSatish Balay     /* malloc & create the natural set of indices */
589566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((n + 1) * bs, ia));
592462f5fdSStefano Zampini     if (n) {
602462f5fdSStefano Zampini       (*ia)[0] = oshift;
61ad540459SPierre Jolivet       for (j = 1; j < bs; j++) (*ia)[j] = (tia[1] - tia[0]) * bs + (*ia)[j - 1];
622462f5fdSStefano Zampini     }
632462f5fdSStefano Zampini 
642462f5fdSStefano Zampini     for (i = 1; i < n; i++) {
652462f5fdSStefano Zampini       (*ia)[i * bs] = (tia[i] - tia[i - 1]) * bs + (*ia)[i * bs - 1];
66ad540459SPierre Jolivet       for (j = 1; j < bs; j++) (*ia)[i * bs + j] = (tia[i + 1] - tia[i]) * bs + (*ia)[i * bs + j - 1];
672462f5fdSStefano Zampini     }
68ad540459SPierre Jolivet     if (n) (*ia)[n * bs] = (tia[n] - tia[n - 1]) * bs + (*ia)[n * bs - 1];
692462f5fdSStefano Zampini 
702462f5fdSStefano Zampini     if (inja) {
719566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz * bs * bs, ja));
722462f5fdSStefano Zampini       cnt = 0;
732462f5fdSStefano Zampini       for (i = 0; i < n; i++) {
748f7157efSSatish Balay         for (j = 0; j < bs; j++) {
752462f5fdSStefano Zampini           for (k = tia[i]; k < tia[i + 1]; k++) {
76ad540459SPierre Jolivet             for (l = 0; l < bs; l++) (*ja)[cnt++] = bs * tja[k] + l;
778f7157efSSatish Balay           }
788f7157efSSatish Balay         }
798f7157efSSatish Balay       }
808f7157efSSatish Balay     }
812462f5fdSStefano Zampini 
822462f5fdSStefano Zampini     if (symmetric) { /* deallocate memory allocated in MatToSymmetricIJ_SeqAIJ() */
839566063dSJacob Faibussowitsch       PetscCall(PetscFree(tia));
849566063dSJacob Faibussowitsch       PetscCall(PetscFree(tja));
852462f5fdSStefano Zampini     }
862462f5fdSStefano Zampini   } else if (oshift == 1) {
872462f5fdSStefano Zampini     if (symmetric) {
882462f5fdSStefano Zampini       nz = tia[A->rmap->n / bs];
892462f5fdSStefano Zampini       /*  add 1 to i and j indices */
902462f5fdSStefano Zampini       for (i = 0; i < A->rmap->n / bs + 1; i++) tia[i] = tia[i] + 1;
912462f5fdSStefano Zampini       *ia = tia;
922462f5fdSStefano Zampini       if (ja) {
932462f5fdSStefano Zampini         for (i = 0; i < nz; i++) tja[i] = tja[i] + 1;
942462f5fdSStefano Zampini         *ja = tja;
952462f5fdSStefano Zampini       }
962462f5fdSStefano Zampini     } else {
972462f5fdSStefano Zampini       nz = a->i[A->rmap->n / bs];
982462f5fdSStefano Zampini       /* malloc space and  add 1 to i and j indices */
999566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(A->rmap->n / bs + 1, ia));
1002462f5fdSStefano Zampini       for (i = 0; i < A->rmap->n / bs + 1; i++) (*ia)[i] = a->i[i] + 1;
1012462f5fdSStefano Zampini       if (ja) {
1029566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(nz, ja));
1032462f5fdSStefano Zampini         for (i = 0; i < nz; i++) (*ja)[i] = a->j[i] + 1;
1042462f5fdSStefano Zampini       }
1052462f5fdSStefano Zampini     }
1062462f5fdSStefano Zampini   } else {
1072462f5fdSStefano Zampini     *ia = tia;
1082462f5fdSStefano Zampini     if (ja) *ja = tja;
109a6ece127SHong Zhang   }
1103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11149b5e25fSSatish Balay }
11249b5e25fSSatish Balay 
113d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRowIJ_SeqSBAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool blockcompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
114d71ae5a4SJacob Faibussowitsch {
11549b5e25fSSatish Balay   PetscFunctionBegin;
1163ba16761SJacob Faibussowitsch   if (!ia) PetscFunctionReturn(PETSC_SUCCESS);
1172462f5fdSStefano Zampini   if ((!blockcompressed && A->rmap->bs > 1) || (symmetric || oshift == 1)) {
1189566063dSJacob Faibussowitsch     PetscCall(PetscFree(*ia));
1199566063dSJacob Faibussowitsch     if (ja) PetscCall(PetscFree(*ja));
120a6ece127SHong Zhang   }
1213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12249b5e25fSSatish Balay }
12349b5e25fSSatish Balay 
124d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_SeqSBAIJ(Mat A)
125d71ae5a4SJacob Faibussowitsch {
12649b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
12749b5e25fSSatish Balay 
12849b5e25fSSatish Balay   PetscFunctionBegin;
129b4e2f619SBarry Smith   if (A->hash_active) {
130b4e2f619SBarry Smith     PetscInt bs;
131e3c72094SPierre Jolivet     A->ops[0] = a->cops;
132b4e2f619SBarry Smith     PetscCall(PetscHMapIJVDestroy(&a->ht));
133b4e2f619SBarry Smith     PetscCall(MatGetBlockSize(A, &bs));
134b4e2f619SBarry Smith     if (bs > 1) PetscCall(PetscHSetIJDestroy(&a->bht));
135b4e2f619SBarry Smith     PetscCall(PetscFree(a->dnz));
136b4e2f619SBarry Smith     PetscCall(PetscFree(a->bdnz));
137b4e2f619SBarry Smith     A->hash_active = PETSC_FALSE;
138b4e2f619SBarry Smith   }
1393ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)A, "Rows=%" PetscInt_FMT ", NZ=%" PetscInt_FMT, A->rmap->N, a->nz));
1409566063dSJacob Faibussowitsch   PetscCall(MatSeqXAIJFreeAIJ(A, &a->a, &a->j, &a->i));
141421480d9SBarry Smith   PetscCall(PetscFree(a->diag));
1429566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
1439566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
1449566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->icol));
1459566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->idiag));
1464d12350bSJunchao Zhang   PetscCall(PetscFree(a->inode.size_csr));
1479566063dSJacob Faibussowitsch   if (a->free_imax_ilen) PetscCall(PetscFree2(a->imax, a->ilen));
1489566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->solve_work));
1499566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->sor_work));
1509566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->solves_work));
1519566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->mult_work));
1529566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->saved_values));
1539566063dSJacob Faibussowitsch   if (a->free_jshort) PetscCall(PetscFree(a->jshort));
1549566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->inew));
1559566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&a->parent));
1569566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
157901853e0SKris Buschelman 
1589566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL));
1592e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJGetArray_C", NULL));
1602e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJRestoreArray_C", NULL));
1619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatStoreValues_C", NULL));
1629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatRetrieveValues_C", NULL));
1639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetColumnIndices_C", NULL));
1649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqaij_C", NULL));
1659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqbaij_C", NULL));
1669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocation_C", NULL));
1679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocationCSR_C", NULL));
1686214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_elemental_C", NULL));
1706214f412SHong Zhang #endif
171d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE))
1729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_scalapack_C", NULL));
173d24d4204SJose E. Roman #endif
1742e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL));
1753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17649b5e25fSSatish Balay }
17749b5e25fSSatish Balay 
178ba38deedSJacob Faibussowitsch static PetscErrorCode MatSetOption_SeqSBAIJ(Mat A, MatOption op, PetscBool flg)
179d71ae5a4SJacob Faibussowitsch {
180045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
181eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
182eb1ec7c1SStefano Zampini   PetscInt bs;
183eb1ec7c1SStefano Zampini #endif
18449b5e25fSSatish Balay 
18549b5e25fSSatish Balay   PetscFunctionBegin;
186eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1879566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &bs));
188eb1ec7c1SStefano Zampini #endif
1894d9d31abSKris Buschelman   switch (op) {
190d71ae5a4SJacob Faibussowitsch   case MAT_ROW_ORIENTED:
191d71ae5a4SJacob Faibussowitsch     a->roworiented = flg;
192d71ae5a4SJacob Faibussowitsch     break;
193d71ae5a4SJacob Faibussowitsch   case MAT_KEEP_NONZERO_PATTERN:
194d71ae5a4SJacob Faibussowitsch     a->keepnonzeropattern = flg;
195d71ae5a4SJacob Faibussowitsch     break;
196d71ae5a4SJacob Faibussowitsch   case MAT_NEW_NONZERO_LOCATIONS:
197d71ae5a4SJacob Faibussowitsch     a->nonew = (flg ? 0 : 1);
198d71ae5a4SJacob Faibussowitsch     break;
199d71ae5a4SJacob Faibussowitsch   case MAT_NEW_NONZERO_LOCATION_ERR:
200d71ae5a4SJacob Faibussowitsch     a->nonew = (flg ? -1 : 0);
201d71ae5a4SJacob Faibussowitsch     break;
202d71ae5a4SJacob Faibussowitsch   case MAT_NEW_NONZERO_ALLOCATION_ERR:
203d71ae5a4SJacob Faibussowitsch     a->nonew = (flg ? -2 : 0);
204d71ae5a4SJacob Faibussowitsch     break;
205d71ae5a4SJacob Faibussowitsch   case MAT_UNUSED_NONZERO_LOCATION_ERR:
206d71ae5a4SJacob Faibussowitsch     a->nounused = (flg ? -1 : 0);
207d71ae5a4SJacob Faibussowitsch     break;
2089a4540c5SBarry Smith   case MAT_HERMITIAN:
209eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
210eb1ec7c1SStefano Zampini     if (flg) { /* disable transpose ops */
21108401ef6SPierre Jolivet       PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for Hermitian with block size greater than 1");
212eb1ec7c1SStefano Zampini       A->ops->multtranspose    = NULL;
213eb1ec7c1SStefano Zampini       A->ops->multtransposeadd = NULL;
214eb1ec7c1SStefano Zampini     }
2150f2140c7SStefano Zampini #endif
216eeffb40dSHong Zhang     break;
21777e54ba9SKris Buschelman   case MAT_SYMMETRIC:
218eb1ec7c1SStefano Zampini   case MAT_SPD:
219eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
220*b0c98d1dSPierre Jolivet     if (flg) { /* An Hermitian and symmetric matrix has zero imaginary part (restore back transpose ops) */
221eb1ec7c1SStefano Zampini       A->ops->multtranspose    = A->ops->mult;
222eb1ec7c1SStefano Zampini       A->ops->multtransposeadd = A->ops->multadd;
223eb1ec7c1SStefano Zampini     }
224eb1ec7c1SStefano Zampini #endif
225eb1ec7c1SStefano Zampini     break;
226d71ae5a4SJacob Faibussowitsch   case MAT_IGNORE_LOWER_TRIANGULAR:
227d71ae5a4SJacob Faibussowitsch     a->ignore_ltriangular = flg;
228d71ae5a4SJacob Faibussowitsch     break;
229d71ae5a4SJacob Faibussowitsch   case MAT_ERROR_LOWER_TRIANGULAR:
230d71ae5a4SJacob Faibussowitsch     a->ignore_ltriangular = flg;
231d71ae5a4SJacob Faibussowitsch     break;
232d71ae5a4SJacob Faibussowitsch   case MAT_GETROW_UPPERTRIANGULAR:
233d71ae5a4SJacob Faibussowitsch     a->getrow_utriangular = flg;
234d71ae5a4SJacob Faibussowitsch     break;
235d71ae5a4SJacob Faibussowitsch   default:
236888c827cSStefano Zampini     break;
23749b5e25fSSatish Balay   }
2383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23949b5e25fSSatish Balay }
24049b5e25fSSatish Balay 
241d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
242d71ae5a4SJacob Faibussowitsch {
24349b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
24449b5e25fSSatish Balay 
24549b5e25fSSatish Balay   PetscFunctionBegin;
24608401ef6SPierre 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()");
24752768537SHong Zhang 
248f5edf698SHong Zhang   /* Get the upper triangular part of the row */
2499566063dSJacob Faibussowitsch   PetscCall(MatGetRow_SeqBAIJ_private(A, row, nz, idx, v, a->i, a->j, a->a));
2503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25149b5e25fSSatish Balay }
25249b5e25fSSatish Balay 
253d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
254d71ae5a4SJacob Faibussowitsch {
25549b5e25fSSatish Balay   PetscFunctionBegin;
2569566063dSJacob Faibussowitsch   if (idx) PetscCall(PetscFree(*idx));
2579566063dSJacob Faibussowitsch   if (v) PetscCall(PetscFree(*v));
2583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25949b5e25fSSatish Balay }
26049b5e25fSSatish Balay 
261ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetRowUpperTriangular_SeqSBAIJ(Mat A)
262d71ae5a4SJacob Faibussowitsch {
263f5edf698SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
264f5edf698SHong Zhang 
265f5edf698SHong Zhang   PetscFunctionBegin;
266f5edf698SHong Zhang   a->getrow_utriangular = PETSC_TRUE;
2673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
268f5edf698SHong Zhang }
269a323099bSStefano Zampini 
270ba38deedSJacob Faibussowitsch static PetscErrorCode MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A)
271d71ae5a4SJacob Faibussowitsch {
272f5edf698SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
273f5edf698SHong Zhang 
274f5edf698SHong Zhang   PetscFunctionBegin;
275f5edf698SHong Zhang   a->getrow_utriangular = PETSC_FALSE;
2763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
277f5edf698SHong Zhang }
278f5edf698SHong Zhang 
279ba38deedSJacob Faibussowitsch static PetscErrorCode MatTranspose_SeqSBAIJ(Mat A, MatReuse reuse, Mat *B)
280d71ae5a4SJacob Faibussowitsch {
28149b5e25fSSatish Balay   PetscFunctionBegin;
2827fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B));
283cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX) {
2849566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A, MAT_COPY_VALUES, B));
285cf37664fSBarry Smith   } else if (reuse == MAT_REUSE_MATRIX) {
2869566063dSJacob Faibussowitsch     PetscCall(MatCopy(A, *B, SAME_NONZERO_PATTERN));
287fc4dec0aSBarry Smith   }
2883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28949b5e25fSSatish Balay }
29049b5e25fSSatish Balay 
291ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_ASCII(Mat A, PetscViewer viewer)
292d71ae5a4SJacob Faibussowitsch {
29349b5e25fSSatish Balay   Mat_SeqSBAIJ     *a = (Mat_SeqSBAIJ *)A->data;
294d0f46423SBarry Smith   PetscInt          i, j, bs = A->rmap->bs, k, l, bs2 = a->bs2;
295f3ef73ceSBarry Smith   PetscViewerFormat format;
296421480d9SBarry Smith   const PetscInt   *diag;
297b3a0534dSBarry Smith   const char       *matname;
29849b5e25fSSatish Balay 
29949b5e25fSSatish Balay   PetscFunctionBegin;
3009566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
301456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
3029566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  block size is %" PetscInt_FMT "\n", bs));
303fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_MATLAB) {
304d2507d54SMatthew Knepley     Mat aij;
305ade3a672SBarry Smith 
306d5f3da31SBarry Smith     if (A->factortype && bs > 1) {
3079566063dSJacob 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"));
3083ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
30970d5e725SHong Zhang     }
3109566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &aij));
31123a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname));
31223a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)aij, matname));
31323a3927dSBarry Smith     PetscCall(MatView_SeqAIJ(aij, viewer));
3149566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&aij));
315fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
316b3a0534dSBarry Smith     Mat B;
317b3a0534dSBarry Smith 
318b3a0534dSBarry Smith     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B));
319b3a0534dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname));
320b3a0534dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)B, matname));
321b3a0534dSBarry Smith     PetscCall(MatView_SeqAIJ(B, viewer));
322b3a0534dSBarry Smith     PetscCall(MatDestroy(&B));
323c1490034SHong Zhang   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
3243ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
32549b5e25fSSatish Balay   } else {
3269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
3272c990fa1SHong Zhang     if (A->factortype) { /* for factored matrix */
32808401ef6SPierre Jolivet       PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix is factored with bs>1. Not implemented yet");
329421480d9SBarry Smith       PetscCall(MatGetDiagonalMarkers_SeqSBAIJ(A, &diag, NULL));
330121deb67SSatish Balay       for (i = 0; i < a->mbs; i++) { /* for row block i */
3319566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
3322c990fa1SHong Zhang         /* diagonal entry */
3332c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX)
3342c990fa1SHong Zhang         if (PetscImaginaryPart(a->a[diag[i]]) > 0.0) {
3359566063dSJacob 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]])));
3362c990fa1SHong Zhang         } else if (PetscImaginaryPart(a->a[diag[i]]) < 0.0) {
3379566063dSJacob 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]])));
3382c990fa1SHong Zhang         } else {
3399566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)PetscRealPart(1.0 / a->a[diag[i]])));
3402c990fa1SHong Zhang         }
3412c990fa1SHong Zhang #else
342835f2295SStefano Zampini         PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)(1 / a->a[diag[i]])));
3432c990fa1SHong Zhang #endif
3442c990fa1SHong Zhang         /* off-diagonal entries */
3452c990fa1SHong Zhang         for (k = a->i[i]; k < a->i[i + 1] - 1; k++) {
3462c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX)
347ca0704adSBarry Smith           if (PetscImaginaryPart(a->a[k]) > 0.0) {
3489566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), (double)PetscImaginaryPart(a->a[k])));
349ca0704adSBarry Smith           } else if (PetscImaginaryPart(a->a[k]) < 0.0) {
3509566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), -(double)PetscImaginaryPart(a->a[k])));
3512c990fa1SHong Zhang           } else {
3529566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k], (double)PetscRealPart(a->a[k])));
3532c990fa1SHong Zhang           }
3542c990fa1SHong Zhang #else
3559566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[k], (double)a->a[k]));
3562c990fa1SHong Zhang #endif
3572c990fa1SHong Zhang         }
3589566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
3592c990fa1SHong Zhang       }
3602c990fa1SHong Zhang 
3612c990fa1SHong Zhang     } else {                         /* for non-factored matrix */
3620c74a584SJed Brown       for (i = 0; i < a->mbs; i++) { /* for row block i */
3630c74a584SJed Brown         for (j = 0; j < bs; j++) {   /* for row bs*i + j */
3649566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i * bs + j));
3650c74a584SJed Brown           for (k = a->i[i]; k < a->i[i + 1]; k++) { /* for column block */
3660c74a584SJed Brown             for (l = 0; l < bs; l++) {              /* for column */
36749b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX)
36849b5e25fSSatish Balay               if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) > 0.0) {
3699371c9d4SSatish 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])));
37049b5e25fSSatish Balay               } else if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) < 0.0) {
3719371c9d4SSatish 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])));
37249b5e25fSSatish Balay               } else {
3739566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j])));
37449b5e25fSSatish Balay               }
37549b5e25fSSatish Balay #else
3769566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)a->a[bs2 * k + l * bs + j]));
37749b5e25fSSatish Balay #endif
37849b5e25fSSatish Balay             }
37949b5e25fSSatish Balay           }
3809566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
38149b5e25fSSatish Balay         }
38249b5e25fSSatish Balay       }
3832c990fa1SHong Zhang     }
3849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
38549b5e25fSSatish Balay   }
3869566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
3873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38849b5e25fSSatish Balay }
38949b5e25fSSatish Balay 
3909804daf3SBarry Smith #include <petscdraw.h>
391d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw, void *Aa)
392d71ae5a4SJacob Faibussowitsch {
39349b5e25fSSatish Balay   Mat           A = (Mat)Aa;
39449b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
3956497c311SBarry Smith   PetscInt      row, i, j, k, l, mbs = a->mbs, bs = A->rmap->bs, bs2 = a->bs2;
39649b5e25fSSatish Balay   PetscReal     xl, yl, xr, yr, x_l, x_r, y_l, y_r;
39749b5e25fSSatish Balay   MatScalar    *aa;
398b0a32e0cSBarry Smith   PetscViewer   viewer;
3996497c311SBarry Smith   int           color;
40049b5e25fSSatish Balay 
40149b5e25fSSatish Balay   PetscFunctionBegin;
4029566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
4039566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
40449b5e25fSSatish Balay 
40549b5e25fSSatish Balay   /* loop over matrix elements drawing boxes */
406383922c3SLisandro Dalcin 
407d0609cedSBarry Smith   PetscDrawCollectiveBegin(draw);
4089566063dSJacob Faibussowitsch   PetscCall(PetscDrawString(draw, .3 * (xl + xr), .3 * (yl + yr), PETSC_DRAW_BLACK, "symmetric"));
409383922c3SLisandro Dalcin   /* Blue for negative, Cyan for zero and  Red for positive */
410b0a32e0cSBarry Smith   color = PETSC_DRAW_BLUE;
41149b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
41249b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4139371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4149371c9d4SSatish Balay       y_r = y_l + 1.0;
4159371c9d4SSatish Balay       x_l = a->j[j] * bs;
4169371c9d4SSatish Balay       x_r = x_l + 1.0;
41749b5e25fSSatish Balay       aa  = a->a + j * bs2;
41849b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
41949b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
42049b5e25fSSatish Balay           if (PetscRealPart(*aa++) >= 0.) continue;
4219566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
42249b5e25fSSatish Balay         }
42349b5e25fSSatish Balay       }
42449b5e25fSSatish Balay     }
42549b5e25fSSatish Balay   }
426b0a32e0cSBarry Smith   color = PETSC_DRAW_CYAN;
42749b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
42849b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4299371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4309371c9d4SSatish Balay       y_r = y_l + 1.0;
4319371c9d4SSatish Balay       x_l = a->j[j] * bs;
4329371c9d4SSatish Balay       x_r = x_l + 1.0;
43349b5e25fSSatish Balay       aa  = a->a + j * bs2;
43449b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
43549b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
43649b5e25fSSatish Balay           if (PetscRealPart(*aa++) != 0.) continue;
4379566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
43849b5e25fSSatish Balay         }
43949b5e25fSSatish Balay       }
44049b5e25fSSatish Balay     }
44149b5e25fSSatish Balay   }
442b0a32e0cSBarry Smith   color = PETSC_DRAW_RED;
44349b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
44449b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4459371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4469371c9d4SSatish Balay       y_r = y_l + 1.0;
4479371c9d4SSatish Balay       x_l = a->j[j] * bs;
4489371c9d4SSatish Balay       x_r = x_l + 1.0;
44949b5e25fSSatish Balay       aa  = a->a + j * bs2;
45049b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
45149b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
45249b5e25fSSatish Balay           if (PetscRealPart(*aa++) <= 0.) continue;
4539566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
45449b5e25fSSatish Balay         }
45549b5e25fSSatish Balay       }
45649b5e25fSSatish Balay     }
45749b5e25fSSatish Balay   }
458d0609cedSBarry Smith   PetscDrawCollectiveEnd(draw);
4593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46049b5e25fSSatish Balay }
46149b5e25fSSatish Balay 
462d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_Draw(Mat A, PetscViewer viewer)
463d71ae5a4SJacob Faibussowitsch {
46449b5e25fSSatish Balay   PetscReal xl, yl, xr, yr, w, h;
465b0a32e0cSBarry Smith   PetscDraw draw;
466ace3abfcSBarry Smith   PetscBool isnull;
46749b5e25fSSatish Balay 
46849b5e25fSSatish Balay   PetscFunctionBegin;
4699566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4709566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
4713ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
47249b5e25fSSatish Balay 
4739371c9d4SSatish Balay   xr = A->rmap->N;
4749371c9d4SSatish Balay   yr = A->rmap->N;
4759371c9d4SSatish Balay   h  = yr / 10.0;
4769371c9d4SSatish Balay   w  = xr / 10.0;
4779371c9d4SSatish Balay   xr += w;
4789371c9d4SSatish Balay   yr += h;
4799371c9d4SSatish Balay   xl = -w;
4809371c9d4SSatish Balay   yl = -h;
4819566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
4829566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
4839566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqSBAIJ_Draw_Zoom, A));
4849566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
4859566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
4863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48749b5e25fSSatish Balay }
48849b5e25fSSatish Balay 
489618cc2edSLisandro Dalcin /* Used for both MPIBAIJ and MPISBAIJ matrices */
490618cc2edSLisandro Dalcin #define MatView_SeqSBAIJ_Binary MatView_SeqBAIJ_Binary
491618cc2edSLisandro Dalcin 
492d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqSBAIJ(Mat A, PetscViewer viewer)
493d71ae5a4SJacob Faibussowitsch {
4949f196a02SMartin Diehl   PetscBool isascii, isbinary, isdraw;
49549b5e25fSSatish Balay 
49649b5e25fSSatish Balay   PetscFunctionBegin;
4979f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
4989566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
4999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
5009f196a02SMartin Diehl   if (isascii) {
5019566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_ASCII(A, viewer));
502618cc2edSLisandro Dalcin   } else if (isbinary) {
5039566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_Binary(A, viewer));
50449b5e25fSSatish Balay   } else if (isdraw) {
5059566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_Draw(A, viewer));
50649b5e25fSSatish Balay   } else {
507a5e6ed63SBarry Smith     Mat         B;
508ade3a672SBarry Smith     const char *matname;
5099566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B));
51023a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname));
51123a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)B, matname));
5129566063dSJacob Faibussowitsch     PetscCall(MatView(B, viewer));
5139566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
51449b5e25fSSatish Balay   }
5153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51649b5e25fSSatish Balay }
51749b5e25fSSatish Balay 
518d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[])
519d71ae5a4SJacob Faibussowitsch {
520045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
52113f74950SBarry Smith   PetscInt     *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j;
52213f74950SBarry Smith   PetscInt     *ai = a->i, *ailen = a->ilen;
523d0f46423SBarry Smith   PetscInt      brow, bcol, ridx, cidx, bs = A->rmap->bs, bs2 = a->bs2;
52497e567efSBarry Smith   MatScalar    *ap, *aa = a->a;
52549b5e25fSSatish Balay 
52649b5e25fSSatish Balay   PetscFunctionBegin;
52749b5e25fSSatish Balay   for (k = 0; k < m; k++) { /* loop over rows */
5289371c9d4SSatish Balay     row  = im[k];
5299371c9d4SSatish Balay     brow = row / bs;
5309371c9d4SSatish Balay     if (row < 0) {
5319371c9d4SSatish Balay       v += n;
5329371c9d4SSatish Balay       continue;
5339371c9d4SSatish Balay     } /* negative row */
53454c59aa7SJacob 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);
5359371c9d4SSatish Balay     rp   = aj + ai[brow];
5369371c9d4SSatish Balay     ap   = aa + bs2 * ai[brow];
53749b5e25fSSatish Balay     nrow = ailen[brow];
53849b5e25fSSatish Balay     for (l = 0; l < n; l++) { /* loop over columns */
5399371c9d4SSatish Balay       if (in[l] < 0) {
5409371c9d4SSatish Balay         v++;
5419371c9d4SSatish Balay         continue;
5429371c9d4SSatish Balay       } /* negative column */
54354c59aa7SJacob 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);
54449b5e25fSSatish Balay       col  = in[l];
54549b5e25fSSatish Balay       bcol = col / bs;
54649b5e25fSSatish Balay       cidx = col % bs;
54749b5e25fSSatish Balay       ridx = row % bs;
54849b5e25fSSatish Balay       high = nrow;
54949b5e25fSSatish Balay       low  = 0; /* assume unsorted */
55049b5e25fSSatish Balay       while (high - low > 5) {
55149b5e25fSSatish Balay         t = (low + high) / 2;
55249b5e25fSSatish Balay         if (rp[t] > bcol) high = t;
55349b5e25fSSatish Balay         else low = t;
55449b5e25fSSatish Balay       }
55549b5e25fSSatish Balay       for (i = low; i < high; i++) {
55649b5e25fSSatish Balay         if (rp[i] > bcol) break;
55749b5e25fSSatish Balay         if (rp[i] == bcol) {
55849b5e25fSSatish Balay           *v++ = ap[bs2 * i + bs * cidx + ridx];
55949b5e25fSSatish Balay           goto finished;
56049b5e25fSSatish Balay         }
56149b5e25fSSatish Balay       }
56297e567efSBarry Smith       *v++ = 0.0;
56349b5e25fSSatish Balay     finished:;
56449b5e25fSSatish Balay     }
56549b5e25fSSatish Balay   }
5663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56749b5e25fSSatish Balay }
56849b5e25fSSatish Balay 
569ba38deedSJacob Faibussowitsch static PetscErrorCode MatPermute_SeqSBAIJ(Mat A, IS rowp, IS colp, Mat *B)
570d71ae5a4SJacob Faibussowitsch {
571dc29a518SPierre Jolivet   Mat       C;
57257069620SPierre Jolivet   PetscBool flg = (PetscBool)(rowp == colp);
573dc29a518SPierre Jolivet 
574dc29a518SPierre Jolivet   PetscFunctionBegin;
5759566063dSJacob Faibussowitsch   PetscCall(MatConvert(A, MATSEQBAIJ, MAT_INITIAL_MATRIX, &C));
5769566063dSJacob Faibussowitsch   PetscCall(MatPermute(C, rowp, colp, B));
5779566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
57857069620SPierre Jolivet   if (!flg) PetscCall(ISEqual(rowp, colp, &flg));
57957069620SPierre Jolivet   if (flg) PetscCall(MatConvert(*B, MATSEQSBAIJ, MAT_INPLACE_MATRIX, B));
5803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
581dc29a518SPierre Jolivet }
58249b5e25fSSatish Balay 
583d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesBlocked_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is)
584d71ae5a4SJacob Faibussowitsch {
5850880e062SHong Zhang   Mat_SeqSBAIJ      *a = (Mat_SeqSBAIJ *)A->data;
586e2ee6c50SBarry Smith   PetscInt          *rp, k, low, high, t, ii, jj, row, nrow, i, col, l, rmax, N, lastcol = -1;
58713f74950SBarry Smith   PetscInt          *imax = a->imax, *ai = a->i, *ailen = a->ilen;
588d0f46423SBarry Smith   PetscInt          *aj = a->j, nonew = a->nonew, bs2 = a->bs2, bs = A->rmap->bs, stepval;
589ace3abfcSBarry Smith   PetscBool          roworiented = a->roworiented;
590dd6ea824SBarry Smith   const PetscScalar *value       = v;
591f15d580aSBarry Smith   MatScalar         *ap, *aa = a->a, *bap;
5920880e062SHong Zhang 
59349b5e25fSSatish Balay   PetscFunctionBegin;
59426fbe8dcSKarl Rupp   if (roworiented) stepval = (n - 1) * bs;
59526fbe8dcSKarl Rupp   else stepval = (m - 1) * bs;
5960880e062SHong Zhang   for (k = 0; k < m; k++) { /* loop over added rows */
5970880e062SHong Zhang     row = im[k];
5980880e062SHong Zhang     if (row < 0) continue;
5996bdcaf15SBarry 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);
6000880e062SHong Zhang     rp   = aj + ai[row];
6010880e062SHong Zhang     ap   = aa + bs2 * ai[row];
6020880e062SHong Zhang     rmax = imax[row];
6030880e062SHong Zhang     nrow = ailen[row];
6040880e062SHong Zhang     low  = 0;
605818f2c47SBarry Smith     high = nrow;
6060880e062SHong Zhang     for (l = 0; l < n; l++) { /* loop over added columns */
6070880e062SHong Zhang       if (in[l] < 0) continue;
6080880e062SHong Zhang       col = in[l];
6096bdcaf15SBarry 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);
610b98bf0e1SJed Brown       if (col < row) {
611966bd95aSPierre 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)");
612966bd95aSPierre Jolivet         continue; /* ignore lower triangular block */
613b98bf0e1SJed Brown       }
61426fbe8dcSKarl Rupp       if (roworiented) value = v + k * (stepval + bs) * bs + l * bs;
61526fbe8dcSKarl Rupp       else value = v + l * (stepval + bs) * bs + k * bs;
61626fbe8dcSKarl Rupp 
61726fbe8dcSKarl Rupp       if (col <= lastcol) low = 0;
61826fbe8dcSKarl Rupp       else high = nrow;
61926fbe8dcSKarl Rupp 
620e2ee6c50SBarry Smith       lastcol = col;
6210880e062SHong Zhang       while (high - low > 7) {
6220880e062SHong Zhang         t = (low + high) / 2;
6230880e062SHong Zhang         if (rp[t] > col) high = t;
6240880e062SHong Zhang         else low = t;
6250880e062SHong Zhang       }
6260880e062SHong Zhang       for (i = low; i < high; i++) {
6270880e062SHong Zhang         if (rp[i] > col) break;
6280880e062SHong Zhang         if (rp[i] == col) {
6290880e062SHong Zhang           bap = ap + bs2 * i;
6300880e062SHong Zhang           if (roworiented) {
6310880e062SHong Zhang             if (is == ADD_VALUES) {
6320880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
633ad540459SPierre Jolivet                 for (jj = ii; jj < bs2; jj += bs) bap[jj] += *value++;
6340880e062SHong Zhang               }
6350880e062SHong Zhang             } else {
6360880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
637ad540459SPierre Jolivet                 for (jj = ii; jj < bs2; jj += bs) bap[jj] = *value++;
6380880e062SHong Zhang               }
6390880e062SHong Zhang             }
6400880e062SHong Zhang           } else {
6410880e062SHong Zhang             if (is == ADD_VALUES) {
6420880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
643ad540459SPierre Jolivet                 for (jj = 0; jj < bs; jj++) *bap++ += *value++;
6440880e062SHong Zhang               }
6450880e062SHong Zhang             } else {
6460880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
647ad540459SPierre Jolivet                 for (jj = 0; jj < bs; jj++) *bap++ = *value++;
6480880e062SHong Zhang               }
6490880e062SHong Zhang             }
6500880e062SHong Zhang           }
6510880e062SHong Zhang           goto noinsert2;
6520880e062SHong Zhang         }
6530880e062SHong Zhang       }
6540880e062SHong Zhang       if (nonew == 1) goto noinsert2;
65508401ef6SPierre 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);
656fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
6579371c9d4SSatish Balay       N = nrow++ - 1;
6589371c9d4SSatish Balay       high++;
6590880e062SHong Zhang       /* shift up all the later entries in this row */
6609566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1));
6619566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1)));
6629566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(ap + bs2 * i, bs2));
6630880e062SHong Zhang       rp[i] = col;
6640880e062SHong Zhang       bap   = ap + bs2 * i;
6650880e062SHong Zhang       if (roworiented) {
6660880e062SHong Zhang         for (ii = 0; ii < bs; ii++, value += stepval) {
667ad540459SPierre Jolivet           for (jj = ii; jj < bs2; jj += bs) bap[jj] = *value++;
6680880e062SHong Zhang         }
6690880e062SHong Zhang       } else {
6700880e062SHong Zhang         for (ii = 0; ii < bs; ii++, value += stepval) {
671ad540459SPierre Jolivet           for (jj = 0; jj < bs; jj++) *bap++ = *value++;
6720880e062SHong Zhang         }
6730880e062SHong Zhang       }
6740880e062SHong Zhang     noinsert2:;
6750880e062SHong Zhang       low = i;
6760880e062SHong Zhang     }
6770880e062SHong Zhang     ailen[row] = nrow;
6780880e062SHong Zhang   }
6793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68049b5e25fSSatish Balay }
68149b5e25fSSatish Balay 
682ba38deedSJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_SeqSBAIJ(Mat A, MatAssemblyType mode)
683d71ae5a4SJacob Faibussowitsch {
68449b5e25fSSatish Balay   Mat_SeqSBAIJ *a      = (Mat_SeqSBAIJ *)A->data;
6858f8f2f0dSBarry Smith   PetscInt      fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax;
686d0f46423SBarry Smith   PetscInt      m = A->rmap->N, *ip, N, *ailen = a->ilen;
68713f74950SBarry Smith   PetscInt      mbs = a->mbs, bs2 = a->bs2, rmax = 0;
68849b5e25fSSatish Balay   MatScalar    *aa = a->a, *ap;
68949b5e25fSSatish Balay 
69049b5e25fSSatish Balay   PetscFunctionBegin;
691d32568d8SPierre Jolivet   if (mode == MAT_FLUSH_ASSEMBLY || (A->was_assembled && A->ass_nonzerostate == A->nonzerostate)) PetscFunctionReturn(PETSC_SUCCESS);
69249b5e25fSSatish Balay 
69349b5e25fSSatish Balay   if (m) rmax = ailen[0];
69449b5e25fSSatish Balay   for (i = 1; i < mbs; i++) {
69549b5e25fSSatish Balay     /* move each row back by the amount of empty slots (fshift) before it*/
69649b5e25fSSatish Balay     fshift += imax[i - 1] - ailen[i - 1];
69749b5e25fSSatish Balay     rmax = PetscMax(rmax, ailen[i]);
69849b5e25fSSatish Balay     if (fshift) {
699580bdb30SBarry Smith       ip = aj + ai[i];
700580bdb30SBarry Smith       ap = aa + bs2 * ai[i];
70149b5e25fSSatish Balay       N  = ailen[i];
7029566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ip - fshift, ip, N));
7039566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ap - bs2 * fshift, ap, bs2 * N));
70449b5e25fSSatish Balay     }
70549b5e25fSSatish Balay     ai[i] = ai[i - 1] + ailen[i - 1];
70649b5e25fSSatish Balay   }
70749b5e25fSSatish Balay   if (mbs) {
70849b5e25fSSatish Balay     fshift += imax[mbs - 1] - ailen[mbs - 1];
70949b5e25fSSatish Balay     ai[mbs] = ai[mbs - 1] + ailen[mbs - 1];
71049b5e25fSSatish Balay   }
71149b5e25fSSatish Balay   /* reset ilen and imax for each row */
712ad540459SPierre Jolivet   for (i = 0; i < mbs; i++) ailen[i] = imax[i] = ai[i + 1] - ai[i];
7136c6c5352SBarry Smith   a->nz = ai[mbs];
71449b5e25fSSatish Balay 
715aed4548fSBarry 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);
71626fbe8dcSKarl Rupp 
7179566063dSJacob 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));
7189566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues is %" PetscInt_FMT "\n", a->reallocs));
7199566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Most nonzeros blocks in any row is %" PetscInt_FMT "\n", rmax));
72026fbe8dcSKarl Rupp 
7218e58a170SBarry Smith   A->info.mallocs += a->reallocs;
72249b5e25fSSatish Balay   a->reallocs         = 0;
72349b5e25fSSatish Balay   A->info.nz_unneeded = (PetscReal)fshift * bs2;
724061b2667SBarry Smith   a->idiagvalid       = PETSC_FALSE;
7254dcd73b1SHong Zhang   a->rmax             = rmax;
72638702af4SBarry Smith 
72738702af4SBarry Smith   if (A->cmap->n < 65536 && A->cmap->bs == 1) {
72844e1c64aSLisandro Dalcin     if (a->jshort && a->free_jshort) {
72917803ae8SHong Zhang       /* when matrix data structure is changed, previous jshort must be replaced */
7309566063dSJacob Faibussowitsch       PetscCall(PetscFree(a->jshort));
73117803ae8SHong Zhang     }
7329566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(a->i[A->rmap->n], &a->jshort));
7336497c311SBarry Smith     for (i = 0; i < a->i[A->rmap->n]; i++) a->jshort[i] = (short)a->j[i];
73438702af4SBarry Smith     A->ops->mult   = MatMult_SeqSBAIJ_1_ushort;
73541f059aeSBarry Smith     A->ops->sor    = MatSOR_SeqSBAIJ_ushort;
7364da8f245SBarry Smith     a->free_jshort = PETSC_TRUE;
73738702af4SBarry Smith   }
7383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
73949b5e25fSSatish Balay }
74049b5e25fSSatish Balay 
74149b5e25fSSatish Balay /* Only add/insert a(i,j) with i<=j (blocks).
742da81f932SPierre Jolivet    Any a(i,j) with i>j input by user is ignored.
74349b5e25fSSatish Balay */
74449b5e25fSSatish Balay 
745d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is)
746d71ae5a4SJacob Faibussowitsch {
74749b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
748e2ee6c50SBarry Smith   PetscInt     *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N, lastcol = -1;
74913f74950SBarry Smith   PetscInt     *imax = a->imax, *ai = a->i, *ailen = a->ilen, roworiented = a->roworiented;
750d0f46423SBarry Smith   PetscInt     *aj = a->j, nonew = a->nonew, bs = A->rmap->bs, brow, bcol;
75113f74950SBarry Smith   PetscInt      ridx, cidx, bs2                 = a->bs2;
75249b5e25fSSatish Balay   MatScalar    *ap, value, *aa                  = a->a, *bap;
75349b5e25fSSatish Balay 
75449b5e25fSSatish Balay   PetscFunctionBegin;
75549b5e25fSSatish Balay   for (k = 0; k < m; k++) { /* loop over added rows */
75649b5e25fSSatish Balay     row  = im[k];           /* row number */
75749b5e25fSSatish Balay     brow = row / bs;        /* block row number */
75849b5e25fSSatish Balay     if (row < 0) continue;
7596bdcaf15SBarry 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);
76049b5e25fSSatish Balay     rp   = aj + ai[brow];       /*ptr to beginning of column value of the row block*/
76149b5e25fSSatish Balay     ap   = aa + bs2 * ai[brow]; /*ptr to beginning of element value of the row block*/
76249b5e25fSSatish Balay     rmax = imax[brow];          /* maximum space allocated for this row */
76349b5e25fSSatish Balay     nrow = ailen[brow];         /* actual length of this row */
76449b5e25fSSatish Balay     low  = 0;
7658509e838SStefano Zampini     high = nrow;
76649b5e25fSSatish Balay     for (l = 0; l < n; l++) { /* loop over added columns */
76749b5e25fSSatish Balay       if (in[l] < 0) continue;
7686bdcaf15SBarry 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);
76949b5e25fSSatish Balay       col  = in[l];
77049b5e25fSSatish Balay       bcol = col / bs; /* block col number */
77149b5e25fSSatish Balay 
772941593c8SHong Zhang       if (brow > bcol) {
773966bd95aSPierre 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)");
774966bd95aSPierre Jolivet         continue; /* ignore lower triangular values */
775941593c8SHong Zhang       }
776f4989cb3SHong Zhang 
7779371c9d4SSatish Balay       ridx = row % bs;
7789371c9d4SSatish Balay       cidx = col % bs; /*row and col index inside the block */
7798549e402SHong Zhang       if ((brow == bcol && ridx <= cidx) || (brow < bcol)) {
78049b5e25fSSatish Balay         /* element value a(k,l) */
78126fbe8dcSKarl Rupp         if (roworiented) value = v[l + k * n];
78226fbe8dcSKarl Rupp         else value = v[k + l * m];
78349b5e25fSSatish Balay 
78449b5e25fSSatish Balay         /* move pointer bap to a(k,l) quickly and add/insert value */
78526fbe8dcSKarl Rupp         if (col <= lastcol) low = 0;
7868509e838SStefano Zampini         else high = nrow;
7878509e838SStefano Zampini 
788e2ee6c50SBarry Smith         lastcol = col;
78949b5e25fSSatish Balay         while (high - low > 7) {
79049b5e25fSSatish Balay           t = (low + high) / 2;
79149b5e25fSSatish Balay           if (rp[t] > bcol) high = t;
79249b5e25fSSatish Balay           else low = t;
79349b5e25fSSatish Balay         }
79449b5e25fSSatish Balay         for (i = low; i < high; i++) {
79549b5e25fSSatish Balay           if (rp[i] > bcol) break;
79649b5e25fSSatish Balay           if (rp[i] == bcol) {
79749b5e25fSSatish Balay             bap = ap + bs2 * i + bs * cidx + ridx;
79849b5e25fSSatish Balay             if (is == ADD_VALUES) *bap += value;
79949b5e25fSSatish Balay             else *bap = value;
8008549e402SHong Zhang             /* for diag block, add/insert its symmetric element a(cidx,ridx) */
8018549e402SHong Zhang             if (brow == bcol && ridx < cidx) {
8028549e402SHong Zhang               bap = ap + bs2 * i + bs * ridx + cidx;
8038549e402SHong Zhang               if (is == ADD_VALUES) *bap += value;
8048549e402SHong Zhang               else *bap = value;
8058549e402SHong Zhang             }
80649b5e25fSSatish Balay             goto noinsert1;
80749b5e25fSSatish Balay           }
80849b5e25fSSatish Balay         }
80949b5e25fSSatish Balay 
81049b5e25fSSatish Balay         if (nonew == 1) goto noinsert1;
81108401ef6SPierre Jolivet         PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero (%" PetscInt_FMT ", %" PetscInt_FMT ") in the matrix", row, col);
812fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, brow, bcol, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
81349b5e25fSSatish Balay 
8149371c9d4SSatish Balay         N = nrow++ - 1;
8159371c9d4SSatish Balay         high++;
81649b5e25fSSatish Balay         /* shift up all the later entries in this row */
8179566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1));
8189566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1)));
8199566063dSJacob Faibussowitsch         PetscCall(PetscArrayzero(ap + bs2 * i, bs2));
82049b5e25fSSatish Balay         rp[i]                          = bcol;
82149b5e25fSSatish Balay         ap[bs2 * i + bs * cidx + ridx] = value;
8228509e838SStefano Zampini         /* for diag block, add/insert its symmetric element a(cidx,ridx) */
823ad540459SPierre Jolivet         if (brow == bcol && ridx < cidx) ap[bs2 * i + bs * ridx + cidx] = value;
82449b5e25fSSatish Balay       noinsert1:;
82549b5e25fSSatish Balay         low = i;
8268549e402SHong Zhang       }
82749b5e25fSSatish Balay     } /* end of loop over added columns */
82849b5e25fSSatish Balay     ailen[brow] = nrow;
82949b5e25fSSatish Balay   } /* end of loop over added rows */
8303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
83149b5e25fSSatish Balay }
83249b5e25fSSatish Balay 
833ba38deedSJacob Faibussowitsch static PetscErrorCode MatICCFactor_SeqSBAIJ(Mat inA, IS row, const MatFactorInfo *info)
834d71ae5a4SJacob Faibussowitsch {
8354ccecd49SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)inA->data;
83649b5e25fSSatish Balay   Mat           outA;
837ace3abfcSBarry Smith   PetscBool     row_identity;
83849b5e25fSSatish Balay 
83949b5e25fSSatish Balay   PetscFunctionBegin;
84008401ef6SPierre Jolivet   PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 is supported for in-place icc");
8419566063dSJacob Faibussowitsch   PetscCall(ISIdentity(row, &row_identity));
84228b400f6SJacob Faibussowitsch   PetscCheck(row_identity, PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix reordering is not supported");
84308401ef6SPierre 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()! */
844c84f5b01SHong Zhang 
84549b5e25fSSatish Balay   outA = inA;
8469566063dSJacob Faibussowitsch   PetscCall(PetscFree(inA->solvertype));
8479566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype));
84849b5e25fSSatish Balay 
849421480d9SBarry Smith   inA->factortype = MAT_FACTOR_ICC;
8509566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetNumericFactorization_inplace(inA, row_identity));
85149b5e25fSSatish Balay 
8529566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
8539566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
854c84f5b01SHong Zhang   a->row = row;
8559566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
8569566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
857c84f5b01SHong Zhang   a->col = row;
858c84f5b01SHong Zhang 
859c84f5b01SHong Zhang   /* Create the invert permutation so that it can be used in MatCholeskyFactorNumeric() */
8609566063dSJacob Faibussowitsch   if (a->icol) PetscCall(ISInvertPermutation(row, PETSC_DECIDE, &a->icol));
86149b5e25fSSatish Balay 
862aa624791SPierre Jolivet   if (!a->solve_work) PetscCall(PetscMalloc1(inA->rmap->N + inA->rmap->bs, &a->solve_work));
86349b5e25fSSatish Balay 
8649566063dSJacob Faibussowitsch   PetscCall(MatCholeskyFactorNumeric(outA, inA, info));
8653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
86649b5e25fSSatish Balay }
867950f1e5bSHong Zhang 
868ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat, PetscInt *indices)
869d71ae5a4SJacob Faibussowitsch {
870045c9aa0SHong Zhang   Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)mat->data;
87113f74950SBarry Smith   PetscInt      i, nz, n;
87249b5e25fSSatish Balay 
87349b5e25fSSatish Balay   PetscFunctionBegin;
8746c6c5352SBarry Smith   nz = baij->maxnz;
875d0f46423SBarry Smith   n  = mat->cmap->n;
87626fbe8dcSKarl Rupp   for (i = 0; i < nz; i++) baij->j[i] = indices[i];
87726fbe8dcSKarl Rupp 
8786c6c5352SBarry Smith   baij->nz = nz;
87926fbe8dcSKarl Rupp   for (i = 0; i < n; i++) baij->ilen[i] = baij->imax[i];
88026fbe8dcSKarl Rupp 
8819566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
8823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
88349b5e25fSSatish Balay }
88449b5e25fSSatish Balay 
88549b5e25fSSatish Balay /*@
88619585528SSatish Balay   MatSeqSBAIJSetColumnIndices - Set the column indices for all the rows
88711a5261eSBarry Smith   in a `MATSEQSBAIJ` matrix.
88849b5e25fSSatish Balay 
88949b5e25fSSatish Balay   Input Parameters:
89011a5261eSBarry Smith + mat     - the `MATSEQSBAIJ` matrix
89149b5e25fSSatish Balay - indices - the column indices
89249b5e25fSSatish Balay 
89349b5e25fSSatish Balay   Level: advanced
89449b5e25fSSatish Balay 
89549b5e25fSSatish Balay   Notes:
89649b5e25fSSatish Balay   This can be called if you have precomputed the nonzero structure of the
89749b5e25fSSatish Balay   matrix and want to provide it to the matrix object to improve the performance
89811a5261eSBarry Smith   of the `MatSetValues()` operation.
89949b5e25fSSatish Balay 
90049b5e25fSSatish Balay   You MUST have set the correct numbers of nonzeros per row in the call to
90111a5261eSBarry Smith   `MatCreateSeqSBAIJ()`, and the columns indices MUST be sorted.
90249b5e25fSSatish Balay 
9032ef1f0ffSBarry Smith   MUST be called before any calls to `MatSetValues()`
90449b5e25fSSatish Balay 
9051cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreateSeqSBAIJ`
90649b5e25fSSatish Balay @*/
907d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetColumnIndices(Mat mat, PetscInt *indices)
908d71ae5a4SJacob Faibussowitsch {
90949b5e25fSSatish Balay   PetscFunctionBegin;
9100700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9114f572ea9SToby Isaac   PetscAssertPointer(indices, 2);
912cac4c232SBarry Smith   PetscUseMethod(mat, "MatSeqSBAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices));
9133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91449b5e25fSSatish Balay }
91549b5e25fSSatish Balay 
916ba38deedSJacob Faibussowitsch static PetscErrorCode MatCopy_SeqSBAIJ(Mat A, Mat B, MatStructure str)
917d71ae5a4SJacob Faibussowitsch {
9184c7a3774SStefano Zampini   PetscBool isbaij;
9193c896bc6SHong Zhang 
9203c896bc6SHong Zhang   PetscFunctionBegin;
9219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &isbaij, MATSEQSBAIJ, MATMPISBAIJ, ""));
92228b400f6SJacob Faibussowitsch   PetscCheck(isbaij, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)B)->type_name);
9234c7a3774SStefano Zampini   /* If the two matrices have the same copy implementation and nonzero pattern, use fast copy. */
9244c7a3774SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
9253c896bc6SHong Zhang     Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
9263c896bc6SHong Zhang     Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data;
9273c896bc6SHong Zhang 
92808401ef6SPierre 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");
92908401ef6SPierre Jolivet     PetscCheck(a->mbs == b->mbs, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of rows in two matrices are different");
93008401ef6SPierre Jolivet     PetscCheck(a->bs2 == b->bs2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different block size");
9319566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(b->a, a->a, a->bs2 * a->i[a->mbs]));
9329566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)B));
9333c896bc6SHong Zhang   } else {
9349566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(A));
9359566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
9369566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(A));
9373c896bc6SHong Zhang   }
9383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9393c896bc6SHong Zhang }
9403c896bc6SHong Zhang 
941d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJGetArray_SeqSBAIJ(Mat A, PetscScalar *array[])
942d71ae5a4SJacob Faibussowitsch {
943a6ece127SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
9445fd66863SKarl Rupp 
945a6ece127SHong Zhang   PetscFunctionBegin;
946a6ece127SHong Zhang   *array = a->a;
9473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
948a6ece127SHong Zhang }
949a6ece127SHong Zhang 
950d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJRestoreArray_SeqSBAIJ(Mat A, PetscScalar *array[])
951d71ae5a4SJacob Faibussowitsch {
952a6ece127SHong Zhang   PetscFunctionBegin;
953cda14afcSprj-   *array = NULL;
9543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
955a6ece127SHong Zhang }
956a6ece127SHong Zhang 
957d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPYGetPreallocation_SeqSBAIJ(Mat Y, Mat X, PetscInt *nnz)
958d71ae5a4SJacob Faibussowitsch {
959b264fe52SHong Zhang   PetscInt      bs = Y->rmap->bs, mbs = Y->rmap->N / bs;
96052768537SHong Zhang   Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data;
96152768537SHong Zhang   Mat_SeqSBAIJ *y = (Mat_SeqSBAIJ *)Y->data;
96252768537SHong Zhang 
96352768537SHong Zhang   PetscFunctionBegin;
96452768537SHong Zhang   /* Set the number of nonzeros in the new matrix */
9659566063dSJacob Faibussowitsch   PetscCall(MatAXPYGetPreallocation_SeqX_private(mbs, x->i, x->j, y->i, y->j, nnz));
9663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
96752768537SHong Zhang }
96852768537SHong Zhang 
969ba38deedSJacob Faibussowitsch static PetscErrorCode MatAXPY_SeqSBAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str)
970d71ae5a4SJacob Faibussowitsch {
97142ee4b1aSHong Zhang   Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data, *y = (Mat_SeqSBAIJ *)Y->data;
97231ce2d13SHong Zhang   PetscInt      bs = Y->rmap->bs, bs2 = bs * bs;
973e838b9e7SJed Brown   PetscBLASInt  one = 1;
97442ee4b1aSHong Zhang 
97542ee4b1aSHong Zhang   PetscFunctionBegin;
976134adf20SPierre Jolivet   if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) {
977134adf20SPierre Jolivet     PetscBool e = x->nz == y->nz && x->mbs == y->mbs ? PETSC_TRUE : PETSC_FALSE;
978134adf20SPierre Jolivet     if (e) {
9799566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(x->i, y->i, x->mbs + 1, &e));
980134adf20SPierre Jolivet       if (e) {
9819566063dSJacob Faibussowitsch         PetscCall(PetscArraycmp(x->j, y->j, x->i[x->mbs], &e));
982134adf20SPierre Jolivet         if (e) str = SAME_NONZERO_PATTERN;
983134adf20SPierre Jolivet       }
984134adf20SPierre Jolivet     }
98554c59aa7SJacob Faibussowitsch     if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN");
986134adf20SPierre Jolivet   }
98742ee4b1aSHong Zhang   if (str == SAME_NONZERO_PATTERN) {
988f4df32b1SMatthew Knepley     PetscScalar  alpha = a;
989c5df96a5SBarry Smith     PetscBLASInt bnz;
9909566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(x->nz * bs2, &bnz));
991792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, x->a, &one, y->a, &one));
9929566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)Y));
993ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
9949566063dSJacob Faibussowitsch     PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_TRUE));
9959566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
9969566063dSJacob Faibussowitsch     PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_FALSE));
99742ee4b1aSHong Zhang   } else {
99852768537SHong Zhang     Mat       B;
99952768537SHong Zhang     PetscInt *nnz;
100054c59aa7SJacob Faibussowitsch     PetscCheck(bs == X->rmap->bs, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Matrices must have same block size");
10019566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(X));
10029566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(Y));
10039566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Y->rmap->N, &nnz));
10049566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B));
10059566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name));
10069566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, Y->rmap->n, Y->cmap->n, Y->rmap->N, Y->cmap->N));
10079566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, Y, Y));
10089566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, ((PetscObject)Y)->type_name));
10099566063dSJacob Faibussowitsch     PetscCall(MatAXPYGetPreallocation_SeqSBAIJ(Y, X, nnz));
10109566063dSJacob Faibussowitsch     PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz));
101152768537SHong Zhang 
10129566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
101352768537SHong Zhang 
10149566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
10159566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz));
10169566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(X));
10179566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(Y));
101842ee4b1aSHong Zhang   }
10193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
102042ee4b1aSHong Zhang }
102142ee4b1aSHong Zhang 
1022ba38deedSJacob Faibussowitsch static PetscErrorCode MatIsStructurallySymmetric_SeqSBAIJ(Mat A, PetscBool *flg)
1023d71ae5a4SJacob Faibussowitsch {
1024efcf0fc3SBarry Smith   PetscFunctionBegin;
1025efcf0fc3SBarry Smith   *flg = PETSC_TRUE;
10263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1027efcf0fc3SBarry Smith }
1028efcf0fc3SBarry Smith 
1029ba38deedSJacob Faibussowitsch static PetscErrorCode MatConjugate_SeqSBAIJ(Mat A)
1030d71ae5a4SJacob Faibussowitsch {
10312726fb6dSPierre Jolivet #if defined(PETSC_USE_COMPLEX)
10322726fb6dSPierre Jolivet   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
10332726fb6dSPierre Jolivet   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
10342726fb6dSPierre Jolivet   MatScalar    *aa = a->a;
10352726fb6dSPierre Jolivet 
10362726fb6dSPierre Jolivet   PetscFunctionBegin;
10372726fb6dSPierre Jolivet   for (i = 0; i < nz; i++) aa[i] = PetscConj(aa[i]);
10382726fb6dSPierre Jolivet #else
10392726fb6dSPierre Jolivet   PetscFunctionBegin;
10402726fb6dSPierre Jolivet #endif
10413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10422726fb6dSPierre Jolivet }
10432726fb6dSPierre Jolivet 
1044ba38deedSJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqSBAIJ(Mat A)
1045d71ae5a4SJacob Faibussowitsch {
104699cafbc1SBarry Smith   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
104799cafbc1SBarry Smith   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
1048dd6ea824SBarry Smith   MatScalar    *aa = a->a;
104999cafbc1SBarry Smith 
105099cafbc1SBarry Smith   PetscFunctionBegin;
105199cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]);
10523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
105399cafbc1SBarry Smith }
105499cafbc1SBarry Smith 
1055ba38deedSJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqSBAIJ(Mat A)
1056d71ae5a4SJacob Faibussowitsch {
105799cafbc1SBarry Smith   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
105899cafbc1SBarry Smith   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
1059dd6ea824SBarry Smith   MatScalar    *aa = a->a;
106099cafbc1SBarry Smith 
106199cafbc1SBarry Smith   PetscFunctionBegin;
106299cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
10633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
106499cafbc1SBarry Smith }
106599cafbc1SBarry Smith 
1066ba38deedSJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_SeqSBAIJ(Mat A, PetscInt is_n, const PetscInt is_idx[], PetscScalar diag, Vec x, Vec b)
1067d71ae5a4SJacob Faibussowitsch {
10683bededecSBarry Smith   Mat_SeqSBAIJ      *baij = (Mat_SeqSBAIJ *)A->data;
10693bededecSBarry Smith   PetscInt           i, j, k, count;
10703bededecSBarry Smith   PetscInt           bs = A->rmap->bs, bs2 = baij->bs2, row, col;
10713bededecSBarry Smith   PetscScalar        zero = 0.0;
10723bededecSBarry Smith   MatScalar         *aa;
10733bededecSBarry Smith   const PetscScalar *xx;
10743bededecSBarry Smith   PetscScalar       *bb;
107556777dd2SBarry Smith   PetscBool         *zeroed, vecs = PETSC_FALSE;
10763bededecSBarry Smith 
10773bededecSBarry Smith   PetscFunctionBegin;
1078dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
10793bededecSBarry Smith   if (x && b) {
10809566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
10819566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
108256777dd2SBarry Smith     vecs = PETSC_TRUE;
10833bededecSBarry Smith   }
10843bededecSBarry Smith 
10853bededecSBarry Smith   /* zero the columns */
10869566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(A->rmap->n, &zeroed));
10873bededecSBarry Smith   for (i = 0; i < is_n; i++) {
1088aed4548fSBarry 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]);
10893bededecSBarry Smith     zeroed[is_idx[i]] = PETSC_TRUE;
10903bededecSBarry Smith   }
109156777dd2SBarry Smith   if (vecs) {
109256777dd2SBarry Smith     for (i = 0; i < A->rmap->N; i++) {
109356777dd2SBarry Smith       row = i / bs;
109456777dd2SBarry Smith       for (j = baij->i[row]; j < baij->i[row + 1]; j++) {
109556777dd2SBarry Smith         for (k = 0; k < bs; k++) {
109656777dd2SBarry Smith           col = bs * baij->j[j] + k;
109756777dd2SBarry Smith           if (col <= i) continue;
1098835f2295SStefano Zampini           aa = baij->a + j * bs2 + (i % bs) + bs * k;
109926fbe8dcSKarl Rupp           if (!zeroed[i] && zeroed[col]) bb[i] -= aa[0] * xx[col];
110026fbe8dcSKarl Rupp           if (zeroed[i] && !zeroed[col]) bb[col] -= aa[0] * xx[i];
110156777dd2SBarry Smith         }
110256777dd2SBarry Smith       }
110356777dd2SBarry Smith     }
110426fbe8dcSKarl Rupp     for (i = 0; i < is_n; i++) bb[is_idx[i]] = diag * xx[is_idx[i]];
110556777dd2SBarry Smith   }
110656777dd2SBarry Smith 
11073bededecSBarry Smith   for (i = 0; i < A->rmap->N; i++) {
11083bededecSBarry Smith     if (!zeroed[i]) {
11093bededecSBarry Smith       row = i / bs;
11103bededecSBarry Smith       for (j = baij->i[row]; j < baij->i[row + 1]; j++) {
11113bededecSBarry Smith         for (k = 0; k < bs; k++) {
11123bededecSBarry Smith           col = bs * baij->j[j] + k;
11133bededecSBarry Smith           if (zeroed[col]) {
1114835f2295SStefano Zampini             aa    = baij->a + j * bs2 + (i % bs) + bs * k;
11153bededecSBarry Smith             aa[0] = 0.0;
11163bededecSBarry Smith           }
11173bededecSBarry Smith         }
11183bededecSBarry Smith       }
11193bededecSBarry Smith     }
11203bededecSBarry Smith   }
11219566063dSJacob Faibussowitsch   PetscCall(PetscFree(zeroed));
112256777dd2SBarry Smith   if (vecs) {
11239566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
11249566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
112556777dd2SBarry Smith   }
11263bededecSBarry Smith 
11273bededecSBarry Smith   /* zero the rows */
11283bededecSBarry Smith   for (i = 0; i < is_n; i++) {
11293bededecSBarry Smith     row   = is_idx[i];
11303bededecSBarry Smith     count = (baij->i[row / bs + 1] - baij->i[row / bs]) * bs;
1131835f2295SStefano Zampini     aa    = baij->a + baij->i[row / bs] * bs2 + (row % bs);
11323bededecSBarry Smith     for (k = 0; k < count; k++) {
11333bededecSBarry Smith       aa[0] = zero;
11343bededecSBarry Smith       aa += bs;
11353bededecSBarry Smith     }
1136dbbe0bcdSBarry Smith     if (diag != 0.0) PetscUseTypeMethod(A, setvalues, 1, &row, 1, &row, &diag, INSERT_VALUES);
11373bededecSBarry Smith   }
11389566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd_SeqSBAIJ(A, MAT_FINAL_ASSEMBLY));
11393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11403bededecSBarry Smith }
11413bededecSBarry Smith 
1142ba38deedSJacob Faibussowitsch static PetscErrorCode MatShift_SeqSBAIJ(Mat Y, PetscScalar a)
1143d71ae5a4SJacob Faibussowitsch {
11447d68702bSBarry Smith   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)Y->data;
11457d68702bSBarry Smith 
11467d68702bSBarry Smith   PetscFunctionBegin;
114748a46eb9SPierre Jolivet   if (!Y->preallocated || !aij->nz) PetscCall(MatSeqSBAIJSetPreallocation(Y, Y->rmap->bs, 1, NULL));
11489566063dSJacob Faibussowitsch   PetscCall(MatShift_Basic(Y, a));
11493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11507d68702bSBarry Smith }
11517d68702bSBarry Smith 
115217ea310bSPierre Jolivet PetscErrorCode MatEliminateZeros_SeqSBAIJ(Mat A, PetscBool keep)
115317ea310bSPierre Jolivet {
115417ea310bSPierre Jolivet   Mat_SeqSBAIJ *a      = (Mat_SeqSBAIJ *)A->data;
115517ea310bSPierre Jolivet   PetscInt      fshift = 0, fshift_prev = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax, j, k;
115617ea310bSPierre Jolivet   PetscInt      m = A->rmap->N, *ailen = a->ilen;
115717ea310bSPierre Jolivet   PetscInt      mbs = a->mbs, bs2 = a->bs2, rmax = 0;
115817ea310bSPierre Jolivet   MatScalar    *aa = a->a, *ap;
115917ea310bSPierre Jolivet   PetscBool     zero;
116017ea310bSPierre Jolivet 
116117ea310bSPierre Jolivet   PetscFunctionBegin;
116217ea310bSPierre Jolivet   PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot eliminate zeros for unassembled matrix");
116317ea310bSPierre Jolivet   if (m) rmax = ailen[0];
116417ea310bSPierre Jolivet   for (i = 1; i <= mbs; i++) {
116517ea310bSPierre Jolivet     for (k = ai[i - 1]; k < ai[i]; k++) {
116617ea310bSPierre Jolivet       zero = PETSC_TRUE;
116717ea310bSPierre Jolivet       ap   = aa + bs2 * k;
116817ea310bSPierre Jolivet       for (j = 0; j < bs2 && zero; j++) {
116917ea310bSPierre Jolivet         if (ap[j] != 0.0) zero = PETSC_FALSE;
117017ea310bSPierre Jolivet       }
117117ea310bSPierre Jolivet       if (zero && (aj[k] != i - 1 || !keep)) fshift++;
117217ea310bSPierre Jolivet       else {
117317ea310bSPierre Jolivet         if (zero && aj[k] == i - 1) PetscCall(PetscInfo(A, "Keep the diagonal block at row %" PetscInt_FMT "\n", i - 1));
117417ea310bSPierre Jolivet         aj[k - fshift] = aj[k];
117517ea310bSPierre Jolivet         PetscCall(PetscArraymove(ap - bs2 * fshift, ap, bs2));
117617ea310bSPierre Jolivet       }
117717ea310bSPierre Jolivet     }
117817ea310bSPierre Jolivet     ai[i - 1] -= fshift_prev;
117917ea310bSPierre Jolivet     fshift_prev  = fshift;
118017ea310bSPierre Jolivet     ailen[i - 1] = imax[i - 1] = ai[i] - fshift - ai[i - 1];
118117ea310bSPierre Jolivet     a->nonzerorowcnt += ((ai[i] - fshift - ai[i - 1]) > 0);
118217ea310bSPierre Jolivet     rmax = PetscMax(rmax, ailen[i - 1]);
118317ea310bSPierre Jolivet   }
118417ea310bSPierre Jolivet   if (fshift) {
118517ea310bSPierre Jolivet     if (mbs) {
118617ea310bSPierre Jolivet       ai[mbs] -= fshift;
118717ea310bSPierre Jolivet       a->nz = ai[mbs];
118817ea310bSPierre Jolivet     }
118917ea310bSPierre 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));
119017ea310bSPierre Jolivet     A->nonzerostate++;
119117ea310bSPierre Jolivet     A->info.nz_unneeded += (PetscReal)fshift;
119217ea310bSPierre Jolivet     a->rmax = rmax;
119317ea310bSPierre Jolivet     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
119417ea310bSPierre Jolivet     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
119517ea310bSPierre Jolivet   }
119617ea310bSPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
119717ea310bSPierre Jolivet }
119817ea310bSPierre Jolivet 
11993964eb88SJed Brown static struct _MatOps MatOps_Values = {MatSetValues_SeqSBAIJ,
120049b5e25fSSatish Balay                                        MatGetRow_SeqSBAIJ,
120149b5e25fSSatish Balay                                        MatRestoreRow_SeqSBAIJ,
120249b5e25fSSatish Balay                                        MatMult_SeqSBAIJ_N,
120397304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqSBAIJ_N,
1204431c96f7SBarry Smith                                        MatMult_SeqSBAIJ_N, /* transpose versions are same as non-transpose versions */
1205e005ede5SBarry Smith                                        MatMultAdd_SeqSBAIJ_N,
1206f4259b30SLisandro Dalcin                                        NULL,
1207f4259b30SLisandro Dalcin                                        NULL,
1208f4259b30SLisandro Dalcin                                        NULL,
1209f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
1210f4259b30SLisandro Dalcin                                        NULL,
1211c078aec8SLisandro Dalcin                                        MatCholeskyFactor_SeqSBAIJ,
121241f059aeSBarry Smith                                        MatSOR_SeqSBAIJ,
121349b5e25fSSatish Balay                                        MatTranspose_SeqSBAIJ,
121497304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqSBAIJ,
121549b5e25fSSatish Balay                                        MatEqual_SeqSBAIJ,
121649b5e25fSSatish Balay                                        MatGetDiagonal_SeqSBAIJ,
121749b5e25fSSatish Balay                                        MatDiagonalScale_SeqSBAIJ,
121849b5e25fSSatish Balay                                        MatNorm_SeqSBAIJ,
1219f4259b30SLisandro Dalcin                                        /* 20*/ NULL,
122049b5e25fSSatish Balay                                        MatAssemblyEnd_SeqSBAIJ,
122149b5e25fSSatish Balay                                        MatSetOption_SeqSBAIJ,
122249b5e25fSSatish Balay                                        MatZeroEntries_SeqSBAIJ,
1223f4259b30SLisandro Dalcin                                        /* 24*/ NULL,
1224f4259b30SLisandro Dalcin                                        NULL,
1225f4259b30SLisandro Dalcin                                        NULL,
1226f4259b30SLisandro Dalcin                                        NULL,
1227f4259b30SLisandro Dalcin                                        NULL,
122826cec326SBarry Smith                                        /* 29*/ MatSetUp_Seq_Hash,
1229f4259b30SLisandro Dalcin                                        NULL,
1230f4259b30SLisandro Dalcin                                        NULL,
1231f4259b30SLisandro Dalcin                                        NULL,
1232f4259b30SLisandro Dalcin                                        NULL,
1233d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqSBAIJ,
1234f4259b30SLisandro Dalcin                                        NULL,
1235f4259b30SLisandro Dalcin                                        NULL,
1236f4259b30SLisandro Dalcin                                        NULL,
1237c84f5b01SHong Zhang                                        MatICCFactor_SeqSBAIJ,
1238d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqSBAIJ,
12397dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqSBAIJ,
124049b5e25fSSatish Balay                                        MatIncreaseOverlap_SeqSBAIJ,
124149b5e25fSSatish Balay                                        MatGetValues_SeqSBAIJ,
12423c896bc6SHong Zhang                                        MatCopy_SeqSBAIJ,
1243f4259b30SLisandro Dalcin                                        /* 44*/ NULL,
124449b5e25fSSatish Balay                                        MatScale_SeqSBAIJ,
12457d68702bSBarry Smith                                        MatShift_SeqSBAIJ,
1246f4259b30SLisandro Dalcin                                        NULL,
12473bededecSBarry Smith                                        MatZeroRowsColumns_SeqSBAIJ,
1248f4259b30SLisandro Dalcin                                        /* 49*/ NULL,
124949b5e25fSSatish Balay                                        MatGetRowIJ_SeqSBAIJ,
125049b5e25fSSatish Balay                                        MatRestoreRowIJ_SeqSBAIJ,
1251f4259b30SLisandro Dalcin                                        NULL,
1252f4259b30SLisandro Dalcin                                        NULL,
1253f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
1254f4259b30SLisandro Dalcin                                        NULL,
1255f4259b30SLisandro Dalcin                                        NULL,
1256dc29a518SPierre Jolivet                                        MatPermute_SeqSBAIJ,
125749b5e25fSSatish Balay                                        MatSetValuesBlocked_SeqSBAIJ,
12587dae84e0SHong Zhang                                        /* 59*/ MatCreateSubMatrix_SeqSBAIJ,
1259f4259b30SLisandro Dalcin                                        NULL,
1260f4259b30SLisandro Dalcin                                        NULL,
1261f4259b30SLisandro Dalcin                                        NULL,
1262f4259b30SLisandro Dalcin                                        NULL,
1263f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
1264f4259b30SLisandro Dalcin                                        NULL,
1265f4259b30SLisandro Dalcin                                        NULL,
1266f4259b30SLisandro Dalcin                                        NULL,
12678bb0f5c6SPierre Jolivet                                        MatGetRowMaxAbs_SeqSBAIJ,
12688bb0f5c6SPierre Jolivet                                        /* 69*/ NULL,
126928d58a37SPierre Jolivet                                        MatConvert_MPISBAIJ_Basic,
1270f4259b30SLisandro Dalcin                                        NULL,
1271f4259b30SLisandro Dalcin                                        NULL,
12728bb0f5c6SPierre Jolivet                                        NULL,
1273f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
1274f4259b30SLisandro Dalcin                                        NULL,
1275f4259b30SLisandro Dalcin                                        NULL,
127697304618SKris Buschelman                                        MatGetInertia_SeqSBAIJ,
12775bba2384SShri Abhyankar                                        MatLoad_SeqSBAIJ,
12788bb0f5c6SPierre Jolivet                                        /* 79*/ NULL,
12796cff0a6bSPierre Jolivet                                        NULL,
1280efcf0fc3SBarry Smith                                        MatIsStructurallySymmetric_SeqSBAIJ,
1281f4259b30SLisandro Dalcin                                        NULL,
1282f4259b30SLisandro Dalcin                                        NULL,
12838bb0f5c6SPierre Jolivet                                        /* 84*/ NULL,
12848bb0f5c6SPierre Jolivet                                        NULL,
12858bb0f5c6SPierre Jolivet                                        NULL,
12868bb0f5c6SPierre Jolivet                                        NULL,
12878bb0f5c6SPierre Jolivet                                        NULL,
1288f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
1289f4259b30SLisandro Dalcin                                        NULL,
1290f4259b30SLisandro Dalcin                                        NULL,
1291f4259b30SLisandro Dalcin                                        NULL,
12928bb0f5c6SPierre Jolivet                                        MatConjugate_SeqSBAIJ,
1293f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
1294f4259b30SLisandro Dalcin                                        NULL,
129599cafbc1SBarry Smith                                        MatRealPart_SeqSBAIJ,
1296f5edf698SHong Zhang                                        MatImaginaryPart_SeqSBAIJ,
1297f5edf698SHong Zhang                                        MatGetRowUpperTriangular_SeqSBAIJ,
12988bb0f5c6SPierre Jolivet                                        /* 99*/ MatRestoreRowUpperTriangular_SeqSBAIJ,
12998bb0f5c6SPierre Jolivet                                        NULL,
13008bb0f5c6SPierre Jolivet                                        NULL,
13018bb0f5c6SPierre Jolivet                                        NULL,
13028bb0f5c6SPierre Jolivet                                        NULL,
1303421480d9SBarry Smith                                        /*104*/ NULL,
13048bb0f5c6SPierre Jolivet                                        NULL,
13058bb0f5c6SPierre Jolivet                                        NULL,
13068bb0f5c6SPierre Jolivet                                        NULL,
13078bb0f5c6SPierre Jolivet                                        NULL,
1308f4259b30SLisandro Dalcin                                        /*109*/ NULL,
1309f4259b30SLisandro Dalcin                                        NULL,
1310f4259b30SLisandro Dalcin                                        NULL,
1311f4259b30SLisandro Dalcin                                        NULL,
13128bb0f5c6SPierre Jolivet                                        NULL,
1313f4259b30SLisandro Dalcin                                        /*114*/ NULL,
1314f4259b30SLisandro Dalcin                                        NULL,
1315f4259b30SLisandro Dalcin                                        NULL,
1316f4259b30SLisandro Dalcin                                        NULL,
1317f4259b30SLisandro Dalcin                                        NULL,
1318f4259b30SLisandro Dalcin                                        /*119*/ NULL,
1319f4259b30SLisandro Dalcin                                        NULL,
1320f4259b30SLisandro Dalcin                                        NULL,
1321f4259b30SLisandro Dalcin                                        NULL,
1322f4259b30SLisandro Dalcin                                        NULL,
1323f4259b30SLisandro Dalcin                                        /*124*/ NULL,
1324f4259b30SLisandro Dalcin                                        NULL,
13258bb0f5c6SPierre Jolivet                                        MatSetBlockSizes_Default,
1326f4259b30SLisandro Dalcin                                        NULL,
1327f4259b30SLisandro Dalcin                                        NULL,
1328421480d9SBarry Smith                                        /*129*/ NULL,
13298bb0f5c6SPierre Jolivet                                        MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ,
1330f4259b30SLisandro Dalcin                                        NULL,
1331f4259b30SLisandro Dalcin                                        NULL,
1332421480d9SBarry Smith                                        NULL,
1333f4259b30SLisandro Dalcin                                        /*134*/ NULL,
1334f4259b30SLisandro Dalcin                                        NULL,
1335eede4a3fSMark Adams                                        MatEliminateZeros_SeqSBAIJ,
13364cc2b5b5SPierre Jolivet                                        NULL,
133742ce410bSJunchao Zhang                                        NULL,
1338421480d9SBarry Smith                                        /*139*/ NULL,
133942ce410bSJunchao Zhang                                        NULL,
134003db1824SAlex Lindsay                                        MatCopyHashToXAIJ_Seq_Hash,
1341c2be7ffeSStefano Zampini                                        NULL,
134203db1824SAlex Lindsay                                        NULL};
1343be1d678aSKris Buschelman 
1344ba38deedSJacob Faibussowitsch static PetscErrorCode MatStoreValues_SeqSBAIJ(Mat mat)
1345d71ae5a4SJacob Faibussowitsch {
13464afc71dfSHong Zhang   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1347d0f46423SBarry Smith   PetscInt      nz  = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2;
134849b5e25fSSatish Balay 
134949b5e25fSSatish Balay   PetscFunctionBegin;
135008401ef6SPierre Jolivet   PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
135149b5e25fSSatish Balay 
135249b5e25fSSatish Balay   /* allocate space for values if not already there */
135348a46eb9SPierre Jolivet   if (!aij->saved_values) PetscCall(PetscMalloc1(nz + 1, &aij->saved_values));
135449b5e25fSSatish Balay 
135549b5e25fSSatish Balay   /* copy values over */
13569566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz));
13573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
135849b5e25fSSatish Balay }
135949b5e25fSSatish Balay 
1360ba38deedSJacob Faibussowitsch static PetscErrorCode MatRetrieveValues_SeqSBAIJ(Mat mat)
1361d71ae5a4SJacob Faibussowitsch {
13624afc71dfSHong Zhang   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1363d0f46423SBarry Smith   PetscInt      nz  = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2;
136449b5e25fSSatish Balay 
136549b5e25fSSatish Balay   PetscFunctionBegin;
136608401ef6SPierre Jolivet   PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
136728b400f6SJacob Faibussowitsch   PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first");
136849b5e25fSSatish Balay 
136949b5e25fSSatish Balay   /* copy values over */
13709566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz));
13713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
137249b5e25fSSatish Balay }
137349b5e25fSSatish Balay 
1374f9663b93SPierre Jolivet static PetscErrorCode MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[])
1375d71ae5a4SJacob Faibussowitsch {
1376c464158bSHong Zhang   Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data;
13774dcd73b1SHong Zhang   PetscInt      i, mbs, nbs, bs2;
13782576faa2SJed Brown   PetscBool     skipallocation = PETSC_FALSE, flg = PETSC_FALSE, realalloc = PETSC_FALSE;
137949b5e25fSSatish Balay 
1380b4e2f619SBarry Smith   PetscFunctionBegin;
1381ad79cf63SBarry Smith   if (B->hash_active) {
1382ad79cf63SBarry Smith     PetscInt bs;
1383aea10558SJacob Faibussowitsch     B->ops[0] = b->cops;
1384ad79cf63SBarry Smith     PetscCall(PetscHMapIJVDestroy(&b->ht));
1385ad79cf63SBarry Smith     PetscCall(MatGetBlockSize(B, &bs));
1386ad79cf63SBarry Smith     if (bs > 1) PetscCall(PetscHSetIJDestroy(&b->bht));
1387ad79cf63SBarry Smith     PetscCall(PetscFree(b->dnz));
1388ad79cf63SBarry Smith     PetscCall(PetscFree(b->bdnz));
1389ad79cf63SBarry Smith     B->hash_active = PETSC_FALSE;
1390ad79cf63SBarry Smith   }
13912576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
1392db4efbfdSBarry Smith 
139358b7e2c1SStefano Zampini   PetscCall(MatSetBlockSize(B, bs));
13949566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
13959566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
139608401ef6SPierre 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);
13979566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs));
1398899cda47SBarry Smith 
139921940c7eSstefano_zampini   B->preallocated = PETSC_TRUE;
140021940c7eSstefano_zampini 
1401d0f46423SBarry Smith   mbs = B->rmap->N / bs;
14024dcd73b1SHong Zhang   nbs = B->cmap->n / bs;
140349b5e25fSSatish Balay   bs2 = bs * bs;
140449b5e25fSSatish Balay 
1405aed4548fSBarry 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");
140649b5e25fSSatish Balay 
1407ab93d7beSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
1408ab93d7beSBarry Smith     skipallocation = PETSC_TRUE;
1409ab93d7beSBarry Smith     nz             = 0;
1410ab93d7beSBarry Smith   }
1411ab93d7beSBarry Smith 
1412435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3;
141308401ef6SPierre Jolivet   PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz);
141449b5e25fSSatish Balay   if (nnz) {
141549b5e25fSSatish Balay     for (i = 0; i < mbs; i++) {
141608401ef6SPierre 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]);
141708401ef6SPierre 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);
141849b5e25fSSatish Balay     }
141949b5e25fSSatish Balay   }
142049b5e25fSSatish Balay 
1421db4efbfdSBarry Smith   B->ops->mult             = MatMult_SeqSBAIJ_N;
1422db4efbfdSBarry Smith   B->ops->multadd          = MatMultAdd_SeqSBAIJ_N;
1423db4efbfdSBarry Smith   B->ops->multtranspose    = MatMult_SeqSBAIJ_N;
1424db4efbfdSBarry Smith   B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N;
142526fbe8dcSKarl Rupp 
14269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL));
142749b5e25fSSatish Balay   if (!flg) {
142849b5e25fSSatish Balay     switch (bs) {
142949b5e25fSSatish Balay     case 1:
143049b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_1;
143149b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_1;
1432431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_1;
1433431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1;
143449b5e25fSSatish Balay       break;
143549b5e25fSSatish Balay     case 2:
143649b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_2;
143749b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_2;
1438431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_2;
1439431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2;
144049b5e25fSSatish Balay       break;
144149b5e25fSSatish Balay     case 3:
144249b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_3;
144349b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_3;
1444431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_3;
1445431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3;
144649b5e25fSSatish Balay       break;
144749b5e25fSSatish Balay     case 4:
144849b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_4;
144949b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_4;
1450431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_4;
1451431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4;
145249b5e25fSSatish Balay       break;
145349b5e25fSSatish Balay     case 5:
145449b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_5;
145549b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_5;
1456431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_5;
1457431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5;
145849b5e25fSSatish Balay       break;
145949b5e25fSSatish Balay     case 6:
146049b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_6;
146149b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_6;
1462431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_6;
1463431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6;
146449b5e25fSSatish Balay       break;
146549b5e25fSSatish Balay     case 7:
1466de53e5efSHong Zhang       B->ops->mult             = MatMult_SeqSBAIJ_7;
146749b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_7;
1468431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_7;
1469431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7;
147049b5e25fSSatish Balay       break;
147149b5e25fSSatish Balay     }
147249b5e25fSSatish Balay   }
147349b5e25fSSatish Balay 
147449b5e25fSSatish Balay   b->mbs = mbs;
14754dcd73b1SHong Zhang   b->nbs = nbs;
1476ab93d7beSBarry Smith   if (!skipallocation) {
14772ee49352SLisandro Dalcin     if (!b->imax) {
14789566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(mbs, &b->imax, mbs, &b->ilen));
147926fbe8dcSKarl Rupp 
1480c760cd28SBarry Smith       b->free_imax_ilen = PETSC_TRUE;
14812ee49352SLisandro Dalcin     }
148249b5e25fSSatish Balay     if (!nnz) {
1483435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
148449b5e25fSSatish Balay       else if (nz <= 0) nz = 1;
14855d2a9ed1SStefano Zampini       nz = PetscMin(nbs, nz);
148626fbe8dcSKarl Rupp       for (i = 0; i < mbs; i++) b->imax[i] = nz;
14879566063dSJacob Faibussowitsch       PetscCall(PetscIntMultError(nz, mbs, &nz));
148849b5e25fSSatish Balay     } else {
1489c73702f5SBarry Smith       PetscInt64 nz64 = 0;
14909371c9d4SSatish Balay       for (i = 0; i < mbs; i++) {
14919371c9d4SSatish Balay         b->imax[i] = nnz[i];
14929371c9d4SSatish Balay         nz64 += nnz[i];
14939371c9d4SSatish Balay       }
14949566063dSJacob Faibussowitsch       PetscCall(PetscIntCast(nz64, &nz));
149549b5e25fSSatish Balay     }
14962ee49352SLisandro Dalcin     /* b->ilen will count nonzeros in each block row so far. */
149726fbe8dcSKarl Rupp     for (i = 0; i < mbs; i++) b->ilen[i] = 0;
14986c6c5352SBarry Smith     /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */
149949b5e25fSSatish Balay 
150049b5e25fSSatish Balay     /* allocate the matrix space */
15019566063dSJacob Faibussowitsch     PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i));
15029f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(bs2 * nz, sizeof(PetscScalar), (void **)&b->a));
15039f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&b->j));
15049f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(B->rmap->n + 1, sizeof(PetscInt), (void **)&b->i));
15059f0612e4SBarry Smith     b->free_a  = PETSC_TRUE;
15069f0612e4SBarry Smith     b->free_ij = PETSC_TRUE;
15079566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->a, nz * bs2));
15089566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->j, nz));
15099f0612e4SBarry Smith     b->free_a  = PETSC_TRUE;
15109f0612e4SBarry Smith     b->free_ij = PETSC_TRUE;
151149b5e25fSSatish Balay 
151249b5e25fSSatish Balay     /* pointer to beginning of each row */
1513e60cf9a0SBarry Smith     b->i[0] = 0;
151426fbe8dcSKarl Rupp     for (i = 1; i < mbs + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1];
151526fbe8dcSKarl Rupp 
1516e811da20SHong Zhang   } else {
1517e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
1518e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
1519ab93d7beSBarry Smith   }
152049b5e25fSSatish Balay 
152149b5e25fSSatish Balay   b->bs2     = bs2;
15226c6c5352SBarry Smith   b->nz      = 0;
1523b32cb4a7SJed Brown   b->maxnz   = nz;
1524f4259b30SLisandro Dalcin   b->inew    = NULL;
1525f4259b30SLisandro Dalcin   b->jnew    = NULL;
1526f4259b30SLisandro Dalcin   b->anew    = NULL;
1527f4259b30SLisandro Dalcin   b->a2anew  = NULL;
15281a3463dfSHong Zhang   b->permute = PETSC_FALSE;
1529cb7b82ddSBarry Smith 
1530cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
1531cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
15329566063dSJacob Faibussowitsch   if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
15333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1534c464158bSHong Zhang }
1535153ea458SHong Zhang 
1536ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ(Mat B, PetscInt bs, const PetscInt ii[], const PetscInt jj[], const PetscScalar V[])
1537d71ae5a4SJacob Faibussowitsch {
15380cd7f59aSBarry Smith   PetscInt      i, j, m, nz, anz, nz_max = 0, *nnz;
1539f4259b30SLisandro Dalcin   PetscScalar  *values      = NULL;
15401c466ed6SStefano Zampini   Mat_SeqSBAIJ *b           = (Mat_SeqSBAIJ *)B->data;
15411c466ed6SStefano Zampini   PetscBool     roworiented = b->roworiented;
15421c466ed6SStefano Zampini   PetscBool     ilw         = b->ignore_ltriangular;
15430cd7f59aSBarry Smith 
154438f409ebSLisandro Dalcin   PetscFunctionBegin;
154508401ef6SPierre Jolivet   PetscCheck(bs >= 1, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_OUTOFRANGE, "Invalid block size specified, must be positive but it is %" PetscInt_FMT, bs);
15469566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(B->rmap, bs));
15479566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(B->cmap, bs));
15489566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
15499566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
15509566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs));
155138f409ebSLisandro Dalcin   m = B->rmap->n / bs;
155238f409ebSLisandro Dalcin 
1553aed4548fSBarry Smith   PetscCheck(!ii[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ii[0] must be 0 but it is %" PetscInt_FMT, ii[0]);
15549566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &nnz));
155538f409ebSLisandro Dalcin   for (i = 0; i < m; i++) {
155638f409ebSLisandro Dalcin     nz = ii[i + 1] - ii[i];
155708401ef6SPierre Jolivet     PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz);
15581c466ed6SStefano Zampini     PetscCheckSorted(nz, jj + ii[i]);
15590cd7f59aSBarry Smith     anz = 0;
15600cd7f59aSBarry Smith     for (j = 0; j < nz; j++) {
15610cd7f59aSBarry Smith       /* count only values on the diagonal or above */
15620cd7f59aSBarry Smith       if (jj[ii[i] + j] >= i) {
15630cd7f59aSBarry Smith         anz = nz - j;
15640cd7f59aSBarry Smith         break;
15650cd7f59aSBarry Smith       }
15660cd7f59aSBarry Smith     }
15671c466ed6SStefano Zampini     nz_max = PetscMax(nz_max, nz);
15680cd7f59aSBarry Smith     nnz[i] = anz;
156938f409ebSLisandro Dalcin   }
15709566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz));
15719566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
157238f409ebSLisandro Dalcin 
157338f409ebSLisandro Dalcin   values = (PetscScalar *)V;
157448a46eb9SPierre Jolivet   if (!values) PetscCall(PetscCalloc1(bs * bs * nz_max, &values));
15751c466ed6SStefano Zampini   b->ignore_ltriangular = PETSC_TRUE;
157638f409ebSLisandro Dalcin   for (i = 0; i < m; i++) {
157738f409ebSLisandro Dalcin     PetscInt        ncols = ii[i + 1] - ii[i];
157838f409ebSLisandro Dalcin     const PetscInt *icols = jj + ii[i];
15791c466ed6SStefano Zampini 
158038f409ebSLisandro Dalcin     if (!roworiented || bs == 1) {
158138f409ebSLisandro Dalcin       const PetscScalar *svals = values + (V ? (bs * bs * ii[i]) : 0);
15829566063dSJacob Faibussowitsch       PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, ncols, icols, svals, INSERT_VALUES));
158338f409ebSLisandro Dalcin     } else {
158438f409ebSLisandro Dalcin       for (j = 0; j < ncols; j++) {
158538f409ebSLisandro Dalcin         const PetscScalar *svals = values + (V ? (bs * bs * (ii[i] + j)) : 0);
15869566063dSJacob Faibussowitsch         PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, 1, &icols[j], svals, INSERT_VALUES));
158738f409ebSLisandro Dalcin       }
158838f409ebSLisandro Dalcin     }
158938f409ebSLisandro Dalcin   }
15909566063dSJacob Faibussowitsch   if (!V) PetscCall(PetscFree(values));
15919566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
15929566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
15939566063dSJacob Faibussowitsch   PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
15941c466ed6SStefano Zampini   b->ignore_ltriangular = ilw;
15953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
159638f409ebSLisandro Dalcin }
159738f409ebSLisandro Dalcin 
1598db4efbfdSBarry Smith /*
1599db4efbfdSBarry Smith    This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization
1600db4efbfdSBarry Smith */
1601d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetNumericFactorization_inplace(Mat B, PetscBool natural)
1602d71ae5a4SJacob Faibussowitsch {
1603ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
1604db4efbfdSBarry Smith   PetscInt  bs  = B->rmap->bs;
1605db4efbfdSBarry Smith 
1606db4efbfdSBarry Smith   PetscFunctionBegin;
16079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL));
1608db4efbfdSBarry Smith   if (flg) bs = 8;
1609db4efbfdSBarry Smith 
1610db4efbfdSBarry Smith   if (!natural) {
1611db4efbfdSBarry Smith     switch (bs) {
1612d71ae5a4SJacob Faibussowitsch     case 1:
1613d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_inplace;
1614d71ae5a4SJacob Faibussowitsch       break;
1615d71ae5a4SJacob Faibussowitsch     case 2:
1616d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2;
1617d71ae5a4SJacob Faibussowitsch       break;
1618d71ae5a4SJacob Faibussowitsch     case 3:
1619d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3;
1620d71ae5a4SJacob Faibussowitsch       break;
1621d71ae5a4SJacob Faibussowitsch     case 4:
1622d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4;
1623d71ae5a4SJacob Faibussowitsch       break;
1624d71ae5a4SJacob Faibussowitsch     case 5:
1625d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5;
1626d71ae5a4SJacob Faibussowitsch       break;
1627d71ae5a4SJacob Faibussowitsch     case 6:
1628d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6;
1629d71ae5a4SJacob Faibussowitsch       break;
1630d71ae5a4SJacob Faibussowitsch     case 7:
1631d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7;
1632d71ae5a4SJacob Faibussowitsch       break;
1633d71ae5a4SJacob Faibussowitsch     default:
1634d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N;
1635d71ae5a4SJacob Faibussowitsch       break;
1636db4efbfdSBarry Smith     }
1637db4efbfdSBarry Smith   } else {
1638db4efbfdSBarry Smith     switch (bs) {
1639d71ae5a4SJacob Faibussowitsch     case 1:
1640d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering_inplace;
1641d71ae5a4SJacob Faibussowitsch       break;
1642d71ae5a4SJacob Faibussowitsch     case 2:
1643d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering;
1644d71ae5a4SJacob Faibussowitsch       break;
1645d71ae5a4SJacob Faibussowitsch     case 3:
1646d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering;
1647d71ae5a4SJacob Faibussowitsch       break;
1648d71ae5a4SJacob Faibussowitsch     case 4:
1649d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering;
1650d71ae5a4SJacob Faibussowitsch       break;
1651d71ae5a4SJacob Faibussowitsch     case 5:
1652d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering;
1653d71ae5a4SJacob Faibussowitsch       break;
1654d71ae5a4SJacob Faibussowitsch     case 6:
1655d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering;
1656d71ae5a4SJacob Faibussowitsch       break;
1657d71ae5a4SJacob Faibussowitsch     case 7:
1658d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering;
1659d71ae5a4SJacob Faibussowitsch       break;
1660d71ae5a4SJacob Faibussowitsch     default:
1661d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering;
1662d71ae5a4SJacob Faibussowitsch       break;
1663db4efbfdSBarry Smith     }
1664db4efbfdSBarry Smith   }
16653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1666db4efbfdSBarry Smith }
1667db4efbfdSBarry Smith 
1668cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType, MatReuse, Mat *);
1669cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType, MatReuse, Mat *);
1670d71ae5a4SJacob Faibussowitsch static PetscErrorCode       MatFactorGetSolverType_petsc(Mat A, MatSolverType *type)
1671d71ae5a4SJacob Faibussowitsch {
16724ac6704cSBarry Smith   PetscFunctionBegin;
16734ac6704cSBarry Smith   *type = MATSOLVERPETSC;
16743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16754ac6704cSBarry Smith }
1676d769727bSBarry Smith 
1677d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A, MatFactorType ftype, Mat *B)
1678d71ae5a4SJacob Faibussowitsch {
1679d0f46423SBarry Smith   PetscInt n = A->rmap->n;
16805c9eb25fSBarry Smith 
16815c9eb25fSBarry Smith   PetscFunctionBegin;
16820e92d65fSHong Zhang #if defined(PETSC_USE_COMPLEX)
168303e5aca4SStefano Zampini   if ((ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) && A->hermitian == PETSC_BOOL3_TRUE && A->symmetric != PETSC_BOOL3_TRUE) {
168403e5aca4SStefano Zampini     PetscCall(PetscInfo(A, "Hermitian MAT_FACTOR_CHOLESKY or MAT_FACTOR_ICC are not supported. Use MAT_FACTOR_LU instead.\n"));
168503e5aca4SStefano Zampini     *B = NULL;
168603e5aca4SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
168703e5aca4SStefano Zampini   }
16880e92d65fSHong Zhang #endif
1689eb1ec7c1SStefano Zampini 
16909566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B));
16919566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*B, n, n, n, n));
1692966bd95aSPierre Jolivet   PetscCheck(ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC, PETSC_COMM_SELF, PETSC_ERR_SUP, "Factor type not supported");
16939566063dSJacob Faibussowitsch   PetscCall(MatSetType(*B, MATSEQSBAIJ));
16949566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*B, A->rmap->bs, MAT_SKIP_ALLOCATION, NULL));
169526fbe8dcSKarl Rupp 
16967b056e98SHong Zhang   (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ;
1697c6d0d4f0SHong Zhang   (*B)->ops->iccfactorsymbolic      = MatICCFactorSymbolic_SeqSBAIJ;
16989566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_CHOLESKY]));
16999566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_ICC]));
170000c67f3bSHong Zhang 
1701d5f3da31SBarry Smith   (*B)->factortype     = ftype;
1702f73b0415SBarry Smith   (*B)->canuseordering = PETSC_TRUE;
17039566063dSJacob Faibussowitsch   PetscCall(PetscFree((*B)->solvertype));
17049566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*B)->solvertype));
17059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)*B, "MatFactorGetSolverType_C", MatFactorGetSolverType_petsc));
17063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17075c9eb25fSBarry Smith }
17085c9eb25fSBarry Smith 
17098397e458SBarry Smith /*@C
17102ef1f0ffSBarry Smith   MatSeqSBAIJGetArray - gives access to the array where the numerical data for a `MATSEQSBAIJ` matrix is stored
17118397e458SBarry Smith 
17128397e458SBarry Smith   Not Collective
17138397e458SBarry Smith 
17148397e458SBarry Smith   Input Parameter:
1715fe59aa6dSJacob Faibussowitsch . A - a `MATSEQSBAIJ` matrix
17168397e458SBarry Smith 
17178397e458SBarry Smith   Output Parameter:
17188397e458SBarry Smith . array - pointer to the data
17198397e458SBarry Smith 
17208397e458SBarry Smith   Level: intermediate
17218397e458SBarry Smith 
17221cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatSeqSBAIJRestoreArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`
17238397e458SBarry Smith @*/
17245d83a8b1SBarry Smith PetscErrorCode MatSeqSBAIJGetArray(Mat A, PetscScalar *array[])
1725d71ae5a4SJacob Faibussowitsch {
17268397e458SBarry Smith   PetscFunctionBegin;
1727cac4c232SBarry Smith   PetscUseMethod(A, "MatSeqSBAIJGetArray_C", (Mat, PetscScalar **), (A, array));
17283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17298397e458SBarry Smith }
17308397e458SBarry Smith 
17318397e458SBarry Smith /*@C
17322ef1f0ffSBarry Smith   MatSeqSBAIJRestoreArray - returns access to the array where the numerical data for a `MATSEQSBAIJ` matrix is stored obtained by `MatSeqSBAIJGetArray()`
17338397e458SBarry Smith 
17348397e458SBarry Smith   Not Collective
17358397e458SBarry Smith 
17368397e458SBarry Smith   Input Parameters:
1737fe59aa6dSJacob Faibussowitsch + A     - a `MATSEQSBAIJ` matrix
1738a2b725a8SWilliam Gropp - array - pointer to the data
17398397e458SBarry Smith 
17408397e458SBarry Smith   Level: intermediate
17418397e458SBarry Smith 
17421cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatSeqSBAIJGetArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`
17438397e458SBarry Smith @*/
17445d83a8b1SBarry Smith PetscErrorCode MatSeqSBAIJRestoreArray(Mat A, PetscScalar *array[])
1745d71ae5a4SJacob Faibussowitsch {
17468397e458SBarry Smith   PetscFunctionBegin;
1747cac4c232SBarry Smith   PetscUseMethod(A, "MatSeqSBAIJRestoreArray_C", (Mat, PetscScalar **), (A, array));
17483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17498397e458SBarry Smith }
17508397e458SBarry Smith 
17510bad9183SKris Buschelman /*MC
1752fafad747SKris Buschelman   MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices,
17530bad9183SKris Buschelman   based on block compressed sparse row format.  Only the upper triangular portion of the matrix is stored.
17540bad9183SKris Buschelman 
1755828413b8SBarry Smith   For complex numbers by default this matrix is symmetric, NOT Hermitian symmetric. To make it Hermitian symmetric you
175611a5261eSBarry Smith   can call `MatSetOption`(`Mat`, `MAT_HERMITIAN`).
1757828413b8SBarry Smith 
17582ef1f0ffSBarry Smith   Options Database Key:
175911a5261eSBarry Smith   . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to `MatSetFromOptions()`
17600bad9183SKris Buschelman 
17612ef1f0ffSBarry Smith   Level: beginner
17622ef1f0ffSBarry Smith 
176395452b02SPatrick Sanan   Notes:
176495452b02SPatrick Sanan   By default if you insert values into the lower triangular part of the matrix they are simply ignored (since they are not
176511a5261eSBarry 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
17662ef1f0ffSBarry 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.
176771dad5bbSBarry Smith 
1768476417e5SBarry Smith   The number of rows in the matrix must be less than or equal to the number of columns
176971dad5bbSBarry Smith 
17701cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreateSeqSBAIJ()`, `MatType`, `MATMPISBAIJ`
17710bad9183SKris Buschelman M*/
1772d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_SeqSBAIJ(Mat B)
1773d71ae5a4SJacob Faibussowitsch {
1774a23d5eceSKris Buschelman   Mat_SeqSBAIJ *b;
177513f74950SBarry Smith   PetscMPIInt   size;
1776ace3abfcSBarry Smith   PetscBool     no_unroll = PETSC_FALSE, no_inode = PETSC_FALSE;
1777a23d5eceSKris Buschelman 
1778a23d5eceSKris Buschelman   PetscFunctionBegin;
17799566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
178008401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
1781a23d5eceSKris Buschelman 
17824dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
1783a23d5eceSKris Buschelman   B->data   = (void *)b;
1784aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
178526fbe8dcSKarl Rupp 
1786a23d5eceSKris Buschelman   B->ops->destroy    = MatDestroy_SeqSBAIJ;
1787a23d5eceSKris Buschelman   B->ops->view       = MatView_SeqSBAIJ;
1788f4259b30SLisandro Dalcin   b->row             = NULL;
1789f4259b30SLisandro Dalcin   b->icol            = NULL;
1790a23d5eceSKris Buschelman   b->reallocs        = 0;
1791f4259b30SLisandro Dalcin   b->saved_values    = NULL;
17920def2e27SBarry Smith   b->inode.limit     = 5;
17930def2e27SBarry Smith   b->inode.max_limit = 5;
1794a23d5eceSKris Buschelman 
1795a23d5eceSKris Buschelman   b->roworiented        = PETSC_TRUE;
1796a23d5eceSKris Buschelman   b->nonew              = 0;
1797f4259b30SLisandro Dalcin   b->diag               = NULL;
1798f4259b30SLisandro Dalcin   b->solve_work         = NULL;
1799f4259b30SLisandro Dalcin   b->mult_work          = NULL;
1800f4259b30SLisandro Dalcin   B->spptr              = NULL;
1801f2cbd3d5SJed Brown   B->info.nz_unneeded   = (PetscReal)b->maxnz * b->bs2;
1802a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
1803a23d5eceSKris Buschelman 
1804f4259b30SLisandro Dalcin   b->inew    = NULL;
1805f4259b30SLisandro Dalcin   b->jnew    = NULL;
1806f4259b30SLisandro Dalcin   b->anew    = NULL;
1807f4259b30SLisandro Dalcin   b->a2anew  = NULL;
1808a23d5eceSKris Buschelman   b->permute = PETSC_FALSE;
1809a23d5eceSKris Buschelman 
181071dad5bbSBarry Smith   b->ignore_ltriangular = PETSC_TRUE;
181126fbe8dcSKarl Rupp 
18129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_ignore_lower_triangular", &b->ignore_ltriangular, NULL));
1813941593c8SHong Zhang 
1814f5edf698SHong Zhang   b->getrow_utriangular = PETSC_FALSE;
181526fbe8dcSKarl Rupp 
18169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_getrow_uppertriangular", &b->getrow_utriangular, NULL));
1817f5edf698SHong Zhang 
18189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJGetArray_C", MatSeqSBAIJGetArray_SeqSBAIJ));
18199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJRestoreArray_C", MatSeqSBAIJRestoreArray_SeqSBAIJ));
18209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqSBAIJ));
18219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqSBAIJ));
18229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetColumnIndices_C", MatSeqSBAIJSetColumnIndices_SeqSBAIJ));
18239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqaij_C", MatConvert_SeqSBAIJ_SeqAIJ));
18249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqbaij_C", MatConvert_SeqSBAIJ_SeqBAIJ));
18259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocation_C", MatSeqSBAIJSetPreallocation_SeqSBAIJ));
18269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocationCSR_C", MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ));
18276214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
18289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_elemental_C", MatConvert_SeqSBAIJ_Elemental));
18296214f412SHong Zhang #endif
1830d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE))
18319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_scalapack_C", MatConvert_SBAIJ_ScaLAPACK));
1832d24d4204SJose E. Roman #endif
183323ce1328SBarry Smith 
1834b94d7dedSBarry Smith   B->symmetry_eternal            = PETSC_TRUE;
1835b94d7dedSBarry Smith   B->structural_symmetry_eternal = PETSC_TRUE;
1836b94d7dedSBarry Smith   B->symmetric                   = PETSC_BOOL3_TRUE;
1837b94d7dedSBarry Smith   B->structurally_symmetric      = PETSC_BOOL3_TRUE;
1838*b0c98d1dSPierre Jolivet #if !defined(PETSC_USE_COMPLEX)
1839b94d7dedSBarry Smith   B->hermitian = PETSC_BOOL3_TRUE;
1840eb1ec7c1SStefano Zampini #endif
184113647f61SHong Zhang 
18429566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQSBAIJ));
18430def2e27SBarry Smith 
1844d0609cedSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)B), ((PetscObject)B)->prefix, "Options for SEQSBAIJ matrix", "Mat");
18459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_no_unroll", "Do not optimize for inodes (slower)", NULL, no_unroll, &no_unroll, NULL));
184648a46eb9SPierre Jolivet   if (no_unroll) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_unroll\n"));
18479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_no_inode", "Do not optimize for inodes (slower)", NULL, no_inode, &no_inode, NULL));
18489566063dSJacob Faibussowitsch   if (no_inode) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_inode\n"));
1849e87b5d96SPierre Jolivet   PetscCall(PetscOptionsInt("-mat_inode_limit", "Do not use inodes larger than this value", NULL, b->inode.limit, &b->inode.limit, NULL));
1850d0609cedSBarry Smith   PetscOptionsEnd();
1851ace3abfcSBarry Smith   b->inode.use = (PetscBool)(!(no_unroll || no_inode));
18520def2e27SBarry Smith   if (b->inode.limit > b->inode.max_limit) b->inode.limit = b->inode.max_limit;
18533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1854a23d5eceSKris Buschelman }
1855a23d5eceSKris Buschelman 
18565d83a8b1SBarry Smith /*@
1857a23d5eceSKris Buschelman   MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block
185811a5261eSBarry Smith   compressed row) `MATSEQSBAIJ` format.  For good matrix assembly performance the
185920f4b53cSBarry Smith   user should preallocate the matrix storage by setting the parameter `nz`
186020f4b53cSBarry Smith   (or the array `nnz`).
1861a23d5eceSKris Buschelman 
1862c3339decSBarry Smith   Collective
1863a23d5eceSKris Buschelman 
1864a23d5eceSKris Buschelman   Input Parameters:
18651c4f3114SJed Brown + B   - the symmetric matrix
186611a5261eSBarry 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
186711a5261eSBarry Smith         blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with `MatCreateVecs()`
1868a23d5eceSKris Buschelman . nz  - number of block nonzeros per block row (same for all rows)
1869a23d5eceSKris Buschelman - nnz - array containing the number of block nonzeros in the upper triangular plus
18702ef1f0ffSBarry Smith         diagonal portion of each block (possibly different for each block row) or `NULL`
1871a23d5eceSKris Buschelman 
1872a23d5eceSKris Buschelman   Options Database Keys:
1873d8a51d2aSBarry Smith + -mat_no_unroll  - uses code that does not unroll the loops in the block calculations (much slower)
1874a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use (only works if a negative bs is passed in
1875a23d5eceSKris Buschelman 
1876a23d5eceSKris Buschelman   Level: intermediate
1877a23d5eceSKris Buschelman 
1878a23d5eceSKris Buschelman   Notes:
187920f4b53cSBarry Smith   Specify the preallocated storage with either `nz` or `nnz` (not both).
18802ef1f0ffSBarry Smith   Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory
1881651615e1SBarry Smith   allocation.  See [Sparse Matrices](sec_matsparse) for details.
1882a23d5eceSKris Buschelman 
188311a5261eSBarry Smith   You can call `MatGetInfo()` to get information on how effective the preallocation was;
1884aa95bbe8SBarry Smith   for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
18852ef1f0ffSBarry Smith   You can also run with the option `-info` and look for messages with the string
1886aa95bbe8SBarry Smith   malloc in them to see if additional memory allocation was needed.
1887aa95bbe8SBarry Smith 
18882ef1f0ffSBarry Smith   If the `nnz` parameter is given then the `nz` parameter is ignored
188949a6f317SBarry Smith 
18901cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()`
1891a23d5eceSKris Buschelman @*/
1892d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetPreallocation(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[])
1893d71ae5a4SJacob Faibussowitsch {
1894a23d5eceSKris Buschelman   PetscFunctionBegin;
18956ba663aaSJed Brown   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
18966ba663aaSJed Brown   PetscValidType(B, 1);
18976ba663aaSJed Brown   PetscValidLogicalCollectiveInt(B, bs, 2);
1898cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqSBAIJSetPreallocation_C", (Mat, PetscInt, PetscInt, const PetscInt[]), (B, bs, nz, nnz));
18993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1900a23d5eceSKris Buschelman }
190149b5e25fSSatish Balay 
190238f409ebSLisandro Dalcin /*@C
190311a5261eSBarry Smith   MatSeqSBAIJSetPreallocationCSR - Creates a sparse parallel matrix in `MATSEQSBAIJ` format using the given nonzero structure and (optional) numerical values
190438f409ebSLisandro Dalcin 
190538f409ebSLisandro Dalcin   Input Parameters:
19061c4f3114SJed Brown + B  - the matrix
1907eab78319SHong Zhang . bs - size of block, the blocks are ALWAYS square.
1908d8a51d2aSBarry Smith . i  - the indices into `j` for the start of each local row (indices start with zero)
1909d8a51d2aSBarry Smith . j  - the column indices for each local row (indices start with zero) these must be sorted for each row
1910d8a51d2aSBarry Smith - v  - optional values in the matrix, use `NULL` if not provided
191138f409ebSLisandro Dalcin 
1912664954b6SBarry Smith   Level: advanced
191338f409ebSLisandro Dalcin 
191438f409ebSLisandro Dalcin   Notes:
1915d8a51d2aSBarry Smith   The `i`,`j`,`v` values are COPIED with this routine; to avoid the copy use `MatCreateSeqSBAIJWithArrays()`
1916d8a51d2aSBarry Smith 
191711a5261eSBarry Smith   The order of the entries in values is specified by the `MatOption` `MAT_ROW_ORIENTED`.  For example, C programs
191811a5261eSBarry 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
191938f409ebSLisandro Dalcin   over rows within a block and the last index is over columns within a block row.  Fortran programs will likely set
192011a5261eSBarry 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
192138f409ebSLisandro Dalcin   block column and the second index is over columns within a block.
192238f409ebSLisandro Dalcin 
1923d8a51d2aSBarry Smith   Any entries provided that lie below the diagonal are ignored
19240cd7f59aSBarry Smith 
19250cd7f59aSBarry Smith   Though this routine has Preallocation() in the name it also sets the exact nonzero locations of the matrix entries
19260cd7f59aSBarry Smith   and usually the numerical values as well
1927664954b6SBarry Smith 
1928fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqSBAIJ()`, `MatSetValuesBlocked()`, `MatSeqSBAIJSetPreallocation()`
192938f409ebSLisandro Dalcin @*/
1930d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetPreallocationCSR(Mat B, PetscInt bs, const PetscInt i[], const PetscInt j[], const PetscScalar v[])
1931d71ae5a4SJacob Faibussowitsch {
193238f409ebSLisandro Dalcin   PetscFunctionBegin;
193338f409ebSLisandro Dalcin   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
193438f409ebSLisandro Dalcin   PetscValidType(B, 1);
193538f409ebSLisandro Dalcin   PetscValidLogicalCollectiveInt(B, bs, 2);
1936cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqSBAIJSetPreallocationCSR_C", (Mat, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, bs, i, j, v));
19373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
193838f409ebSLisandro Dalcin }
193938f409ebSLisandro Dalcin 
19405d83a8b1SBarry Smith /*@
19412ef1f0ffSBarry Smith   MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in (block
194211a5261eSBarry Smith   compressed row) `MATSEQSBAIJ` format.  For good matrix assembly performance the
19432ef1f0ffSBarry Smith   user should preallocate the matrix storage by setting the parameter `nz`
19442ef1f0ffSBarry Smith   (or the array `nnz`).
194549b5e25fSSatish Balay 
1946d083f849SBarry Smith   Collective
1947c464158bSHong Zhang 
1948c464158bSHong Zhang   Input Parameters:
194911a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
195011a5261eSBarry 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
1951bb7ae925SBarry Smith           blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with MatCreateVecs()
195220f4b53cSBarry Smith . m    - number of rows
195320f4b53cSBarry Smith . n    - number of columns
1954c464158bSHong Zhang . nz   - number of block nonzeros per block row (same for all rows)
1955744e8345SSatish Balay - nnz  - array containing the number of block nonzeros in the upper triangular plus
19562ef1f0ffSBarry Smith          diagonal portion of each block (possibly different for each block row) or `NULL`
1957c464158bSHong Zhang 
1958c464158bSHong Zhang   Output Parameter:
1959c464158bSHong Zhang . A - the symmetric matrix
1960c464158bSHong Zhang 
1961c464158bSHong Zhang   Options Database Keys:
1962d8a51d2aSBarry Smith + -mat_no_unroll  - uses code that does not unroll the loops in the block calculations (much slower)
1963a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use
1964c464158bSHong Zhang 
1965c464158bSHong Zhang   Level: intermediate
1966c464158bSHong Zhang 
19672ef1f0ffSBarry Smith   Notes:
196877433607SBarry Smith   It is recommended that one use `MatCreateFromOptions()` or the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`,
1969f6f02116SRichard Tran Mills   MatXXXXSetPreallocation() paradigm instead of this routine directly.
197011a5261eSBarry Smith   [MatXXXXSetPreallocation() is, for example, `MatSeqAIJSetPreallocation()`]
1971175b88e8SBarry Smith 
19726d6d819aSHong Zhang   The number of rows and columns must be divisible by blocksize.
19736d6d819aSHong Zhang   This matrix type does not support complex Hermitian operation.
1974c464158bSHong Zhang 
19752ef1f0ffSBarry Smith   Specify the preallocated storage with either `nz` or `nnz` (not both).
19762ef1f0ffSBarry Smith   Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory
1977651615e1SBarry Smith   allocation.  See [Sparse Matrices](sec_matsparse) for details.
1978c464158bSHong Zhang 
19792ef1f0ffSBarry Smith   If the `nnz` parameter is given then the `nz` parameter is ignored
198049a6f317SBarry Smith 
19811cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()`
1982c464158bSHong Zhang @*/
1983d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqSBAIJ(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A)
1984d71ae5a4SJacob Faibussowitsch {
1985c464158bSHong Zhang   PetscFunctionBegin;
19869566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
19879566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
19889566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQSBAIJ));
19899566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*A, bs, nz, (PetscInt *)nnz));
19903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
199149b5e25fSSatish Balay }
199249b5e25fSSatish Balay 
1993d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B)
1994d71ae5a4SJacob Faibussowitsch {
199549b5e25fSSatish Balay   Mat           C;
199649b5e25fSSatish Balay   Mat_SeqSBAIJ *c, *a  = (Mat_SeqSBAIJ *)A->data;
1997b40805acSSatish Balay   PetscInt      i, mbs = a->mbs, nz = a->nz, bs2 = a->bs2;
199849b5e25fSSatish Balay 
199949b5e25fSSatish Balay   PetscFunctionBegin;
200031fe6a7dSBarry Smith   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix");
200108401ef6SPierre Jolivet   PetscCheck(a->i[mbs] == nz, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupt matrix");
200249b5e25fSSatish Balay 
2003f4259b30SLisandro Dalcin   *B = NULL;
20049566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
20059566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, A->rmap->N, A->cmap->n, A->rmap->N, A->cmap->n));
20069566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(C, A, A));
20079566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATSEQSBAIJ));
2008692f9cbeSHong Zhang   c = (Mat_SeqSBAIJ *)C->data;
2009692f9cbeSHong Zhang 
2010273d9f13SBarry Smith   C->preallocated       = PETSC_TRUE;
2011d5f3da31SBarry Smith   C->factortype         = A->factortype;
2012f4259b30SLisandro Dalcin   c->row                = NULL;
2013f4259b30SLisandro Dalcin   c->icol               = NULL;
2014f4259b30SLisandro Dalcin   c->saved_values       = NULL;
2015a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
201649b5e25fSSatish Balay   C->assembled          = PETSC_TRUE;
201749b5e25fSSatish Balay 
20189566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->rmap, &C->rmap));
20199566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap, &C->cmap));
202049b5e25fSSatish Balay   c->bs2 = a->bs2;
202149b5e25fSSatish Balay   c->mbs = a->mbs;
202249b5e25fSSatish Balay   c->nbs = a->nbs;
202349b5e25fSSatish Balay 
2024c760cd28SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2025c760cd28SBarry Smith     c->imax           = a->imax;
2026c760cd28SBarry Smith     c->ilen           = a->ilen;
2027c760cd28SBarry Smith     c->free_imax_ilen = PETSC_FALSE;
2028c760cd28SBarry Smith   } else {
202957508eceSPierre Jolivet     PetscCall(PetscMalloc2(mbs + 1, &c->imax, mbs + 1, &c->ilen));
203049b5e25fSSatish Balay     for (i = 0; i < mbs; i++) {
203149b5e25fSSatish Balay       c->imax[i] = a->imax[i];
203249b5e25fSSatish Balay       c->ilen[i] = a->ilen[i];
203349b5e25fSSatish Balay     }
2034c760cd28SBarry Smith     c->free_imax_ilen = PETSC_TRUE;
2035c760cd28SBarry Smith   }
203649b5e25fSSatish Balay 
203749b5e25fSSatish Balay   /* allocate the matrix space */
20389f0612e4SBarry Smith   PetscCall(PetscShmgetAllocateArray(bs2 * nz, sizeof(PetscScalar), (void **)&c->a));
20399f0612e4SBarry Smith   c->free_a = PETSC_TRUE;
20404da8f245SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
20419f0612e4SBarry Smith     PetscCall(PetscArrayzero(c->a, bs2 * nz));
204244e1c64aSLisandro Dalcin     c->i       = a->i;
204344e1c64aSLisandro Dalcin     c->j       = a->j;
20444da8f245SBarry Smith     c->free_ij = PETSC_FALSE;
20454da8f245SBarry Smith     c->parent  = A;
20469566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)A));
20479566063dSJacob Faibussowitsch     PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
20489566063dSJacob Faibussowitsch     PetscCall(MatSetOption(C, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
20494da8f245SBarry Smith   } else {
20509f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&c->j));
20519f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(mbs + 1, sizeof(PetscInt), (void **)&c->i));
20529566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(c->i, a->i, mbs + 1));
20534da8f245SBarry Smith     c->free_ij = PETSC_TRUE;
20544da8f245SBarry Smith   }
205549b5e25fSSatish Balay   if (mbs > 0) {
205648a46eb9SPierre Jolivet     if (cpvalues != MAT_SHARE_NONZERO_PATTERN) PetscCall(PetscArraycpy(c->j, a->j, nz));
205749b5e25fSSatish Balay     if (cpvalues == MAT_COPY_VALUES) {
20589566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->a, a->a, bs2 * nz));
205949b5e25fSSatish Balay     } else {
20609566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(c->a, bs2 * nz));
206149b5e25fSSatish Balay     }
2062a1c3900fSBarry Smith     if (a->jshort) {
206344e1c64aSLisandro Dalcin       /* cannot share jshort, it is reallocated in MatAssemblyEnd_SeqSBAIJ() */
206444e1c64aSLisandro Dalcin       /* if the parent matrix is reassembled, this child matrix will never notice */
20659566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz, &c->jshort));
20669566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->jshort, a->jshort, nz));
206726fbe8dcSKarl Rupp 
20684da8f245SBarry Smith       c->free_jshort = PETSC_TRUE;
20694da8f245SBarry Smith     }
2070a1c3900fSBarry Smith   }
207149b5e25fSSatish Balay 
207249b5e25fSSatish Balay   c->roworiented = a->roworiented;
207349b5e25fSSatish Balay   c->nonew       = a->nonew;
20746c6c5352SBarry Smith   c->nz          = a->nz;
2075f2cbd3d5SJed Brown   c->maxnz       = a->nz; /* Since we allocate exactly the right amount */
2076f4259b30SLisandro Dalcin   c->solve_work  = NULL;
2077f4259b30SLisandro Dalcin   c->mult_work   = NULL;
207826fbe8dcSKarl Rupp 
207949b5e25fSSatish Balay   *B = C;
20809566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist));
20813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
208249b5e25fSSatish Balay }
208349b5e25fSSatish Balay 
2084618cc2edSLisandro Dalcin /* Used for both SeqBAIJ and SeqSBAIJ matrices */
2085618cc2edSLisandro Dalcin #define MatLoad_SeqSBAIJ_Binary MatLoad_SeqBAIJ_Binary
2086618cc2edSLisandro Dalcin 
2087d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_SeqSBAIJ(Mat mat, PetscViewer viewer)
2088d71ae5a4SJacob Faibussowitsch {
20897f489da9SVaclav Hapla   PetscBool isbinary;
20902f480046SShri Abhyankar 
20912f480046SShri Abhyankar   PetscFunctionBegin;
20929566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
209328b400f6SJacob 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);
20949566063dSJacob Faibussowitsch   PetscCall(MatLoad_SeqSBAIJ_Binary(mat, viewer));
20953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20962f480046SShri Abhyankar }
20972f480046SShri Abhyankar 
2098c75a6043SHong Zhang /*@
209911a5261eSBarry Smith   MatCreateSeqSBAIJWithArrays - Creates an sequential `MATSEQSBAIJ` matrix using matrix elements
2100c75a6043SHong Zhang   (upper triangular entries in CSR format) provided by the user.
2101c75a6043SHong Zhang 
2102d083f849SBarry Smith   Collective
2103c75a6043SHong Zhang 
2104c75a6043SHong Zhang   Input Parameters:
2105c75a6043SHong Zhang + comm - must be an MPI communicator of size 1
2106c75a6043SHong Zhang . bs   - size of block
2107c75a6043SHong Zhang . m    - number of rows
2108c75a6043SHong Zhang . n    - number of columns
2109483a2f95SBarry 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
2110c75a6043SHong Zhang . j    - column indices
2111c75a6043SHong Zhang - a    - matrix values
2112c75a6043SHong Zhang 
2113c75a6043SHong Zhang   Output Parameter:
2114c75a6043SHong Zhang . mat - the matrix
2115c75a6043SHong Zhang 
2116dfb205c3SBarry Smith   Level: advanced
2117c75a6043SHong Zhang 
2118c75a6043SHong Zhang   Notes:
21192ef1f0ffSBarry Smith   The `i`, `j`, and `a` arrays are not copied by this routine, the user must free these arrays
2120c75a6043SHong Zhang   once the matrix is destroyed
2121c75a6043SHong Zhang 
2122c75a6043SHong Zhang   You cannot set new nonzero locations into this matrix, that will generate an error.
2123c75a6043SHong Zhang 
21242ef1f0ffSBarry Smith   The `i` and `j` indices are 0 based
2125c75a6043SHong Zhang 
21262ef1f0ffSBarry Smith   When block size is greater than 1 the matrix values must be stored using the `MATSBAIJ` storage format. For block size of 1
2127dfb205c3SBarry Smith   it is the regular CSR format excluding the lower triangular elements.
2128dfb205c3SBarry Smith 
21291cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSBAIJ()`, `MatCreateSeqSBAIJ()`
2130c75a6043SHong Zhang @*/
2131d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqSBAIJWithArrays(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat)
2132d71ae5a4SJacob Faibussowitsch {
2133c75a6043SHong Zhang   PetscInt      ii;
2134c75a6043SHong Zhang   Mat_SeqSBAIJ *sbaij;
2135c75a6043SHong Zhang 
2136c75a6043SHong Zhang   PetscFunctionBegin;
213708401ef6SPierre Jolivet   PetscCheck(bs == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "block size %" PetscInt_FMT " > 1 is not supported yet", bs);
2138aed4548fSBarry Smith   PetscCheck(m == 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0");
2139c75a6043SHong Zhang 
21409566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, mat));
21419566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mat, m, n, m, n));
21429566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mat, MATSEQSBAIJ));
21439566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*mat, bs, MAT_SKIP_ALLOCATION, NULL));
2144c75a6043SHong Zhang   sbaij = (Mat_SeqSBAIJ *)(*mat)->data;
21459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(m, &sbaij->imax, m, &sbaij->ilen));
2146c75a6043SHong Zhang 
2147c75a6043SHong Zhang   sbaij->i = i;
2148c75a6043SHong Zhang   sbaij->j = j;
2149c75a6043SHong Zhang   sbaij->a = a;
215026fbe8dcSKarl Rupp 
2151c75a6043SHong Zhang   sbaij->nonew          = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2152e6b907acSBarry Smith   sbaij->free_a         = PETSC_FALSE;
2153e6b907acSBarry Smith   sbaij->free_ij        = PETSC_FALSE;
2154ddf7884eSMatthew Knepley   sbaij->free_imax_ilen = PETSC_TRUE;
2155c75a6043SHong Zhang 
2156c75a6043SHong Zhang   for (ii = 0; ii < m; ii++) {
2157c75a6043SHong Zhang     sbaij->ilen[ii] = sbaij->imax[ii] = i[ii + 1] - i[ii];
21586bdcaf15SBarry 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]);
2159c75a6043SHong Zhang   }
216076bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2161c75a6043SHong Zhang     for (ii = 0; ii < sbaij->i[m]; ii++) {
21626bdcaf15SBarry 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]);
21636bdcaf15SBarry 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]);
2164c75a6043SHong Zhang     }
216576bd3646SJed Brown   }
2166c75a6043SHong Zhang 
21679566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY));
21689566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY));
21693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2170c75a6043SHong Zhang }
2171d06b337dSHong Zhang 
2172d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
2173d71ae5a4SJacob Faibussowitsch {
217459f5e6ceSHong Zhang   PetscFunctionBegin;
21759566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPISBAIJ(comm, inmat, n, scall, outmat));
21763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
217759f5e6ceSHong Zhang }
2178