xref: /petsc/src/mat/impls/sbaij/seq/sbaij.c (revision 421480d92be24cdb9933c60510b8e175c0a8d034)
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 
36*421480d9SBarry 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));
141*421480d9SBarry 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;
214b94d7dedSBarry Smith       A->symmetric             = PETSC_BOOL3_FALSE;
215eb1ec7c1SStefano Zampini     }
2160f2140c7SStefano Zampini #endif
217eeffb40dSHong Zhang     break;
21877e54ba9SKris Buschelman   case MAT_SYMMETRIC:
219eb1ec7c1SStefano Zampini   case MAT_SPD:
220eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
221eb1ec7c1SStefano Zampini     if (flg) { /* An hermitian and symmetric matrix has zero imaginary part (restore back transpose ops) */
222eb1ec7c1SStefano Zampini       A->ops->multtranspose    = A->ops->mult;
223eb1ec7c1SStefano Zampini       A->ops->multtransposeadd = A->ops->multadd;
224eb1ec7c1SStefano Zampini     }
225eb1ec7c1SStefano Zampini #endif
226eb1ec7c1SStefano Zampini     break;
227d71ae5a4SJacob Faibussowitsch   case MAT_IGNORE_LOWER_TRIANGULAR:
228d71ae5a4SJacob Faibussowitsch     a->ignore_ltriangular = flg;
229d71ae5a4SJacob Faibussowitsch     break;
230d71ae5a4SJacob Faibussowitsch   case MAT_ERROR_LOWER_TRIANGULAR:
231d71ae5a4SJacob Faibussowitsch     a->ignore_ltriangular = flg;
232d71ae5a4SJacob Faibussowitsch     break;
233d71ae5a4SJacob Faibussowitsch   case MAT_GETROW_UPPERTRIANGULAR:
234d71ae5a4SJacob Faibussowitsch     a->getrow_utriangular = flg;
235d71ae5a4SJacob Faibussowitsch     break;
236d71ae5a4SJacob Faibussowitsch   default:
237888c827cSStefano Zampini     break;
23849b5e25fSSatish Balay   }
2393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24049b5e25fSSatish Balay }
24149b5e25fSSatish Balay 
242d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
243d71ae5a4SJacob Faibussowitsch {
24449b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
24549b5e25fSSatish Balay 
24649b5e25fSSatish Balay   PetscFunctionBegin;
24708401ef6SPierre 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()");
24852768537SHong Zhang 
249f5edf698SHong Zhang   /* Get the upper triangular part of the row */
2509566063dSJacob Faibussowitsch   PetscCall(MatGetRow_SeqBAIJ_private(A, row, nz, idx, v, a->i, a->j, a->a));
2513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25249b5e25fSSatish Balay }
25349b5e25fSSatish Balay 
254d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
255d71ae5a4SJacob Faibussowitsch {
25649b5e25fSSatish Balay   PetscFunctionBegin;
2579566063dSJacob Faibussowitsch   if (idx) PetscCall(PetscFree(*idx));
2589566063dSJacob Faibussowitsch   if (v) PetscCall(PetscFree(*v));
2593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26049b5e25fSSatish Balay }
26149b5e25fSSatish Balay 
262ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetRowUpperTriangular_SeqSBAIJ(Mat A)
263d71ae5a4SJacob Faibussowitsch {
264f5edf698SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
265f5edf698SHong Zhang 
266f5edf698SHong Zhang   PetscFunctionBegin;
267f5edf698SHong Zhang   a->getrow_utriangular = PETSC_TRUE;
2683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
269f5edf698SHong Zhang }
270a323099bSStefano Zampini 
271ba38deedSJacob Faibussowitsch static PetscErrorCode MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A)
272d71ae5a4SJacob Faibussowitsch {
273f5edf698SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
274f5edf698SHong Zhang 
275f5edf698SHong Zhang   PetscFunctionBegin;
276f5edf698SHong Zhang   a->getrow_utriangular = PETSC_FALSE;
2773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
278f5edf698SHong Zhang }
279f5edf698SHong Zhang 
280ba38deedSJacob Faibussowitsch static PetscErrorCode MatTranspose_SeqSBAIJ(Mat A, MatReuse reuse, Mat *B)
281d71ae5a4SJacob Faibussowitsch {
28249b5e25fSSatish Balay   PetscFunctionBegin;
2837fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B));
284cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX) {
2859566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A, MAT_COPY_VALUES, B));
286cf37664fSBarry Smith   } else if (reuse == MAT_REUSE_MATRIX) {
2879566063dSJacob Faibussowitsch     PetscCall(MatCopy(A, *B, SAME_NONZERO_PATTERN));
288fc4dec0aSBarry Smith   }
2893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29049b5e25fSSatish Balay }
29149b5e25fSSatish Balay 
292ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_ASCII(Mat A, PetscViewer viewer)
293d71ae5a4SJacob Faibussowitsch {
29449b5e25fSSatish Balay   Mat_SeqSBAIJ     *a = (Mat_SeqSBAIJ *)A->data;
295d0f46423SBarry Smith   PetscInt          i, j, bs = A->rmap->bs, k, l, bs2 = a->bs2;
296f3ef73ceSBarry Smith   PetscViewerFormat format;
297*421480d9SBarry Smith   const PetscInt   *diag;
298b3a0534dSBarry Smith   const char       *matname;
29949b5e25fSSatish Balay 
30049b5e25fSSatish Balay   PetscFunctionBegin;
3019566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
302456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
3039566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  block size is %" PetscInt_FMT "\n", bs));
304fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_MATLAB) {
305d2507d54SMatthew Knepley     Mat aij;
306ade3a672SBarry Smith 
307d5f3da31SBarry Smith     if (A->factortype && bs > 1) {
3089566063dSJacob 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"));
3093ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
31070d5e725SHong Zhang     }
3119566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &aij));
31223a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname));
31323a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)aij, matname));
31423a3927dSBarry Smith     PetscCall(MatView_SeqAIJ(aij, viewer));
3159566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&aij));
316fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
317b3a0534dSBarry Smith     Mat B;
318b3a0534dSBarry Smith 
319b3a0534dSBarry Smith     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B));
320b3a0534dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname));
321b3a0534dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)B, matname));
322b3a0534dSBarry Smith     PetscCall(MatView_SeqAIJ(B, viewer));
323b3a0534dSBarry Smith     PetscCall(MatDestroy(&B));
324c1490034SHong Zhang   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
3253ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
32649b5e25fSSatish Balay   } else {
3279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
3282c990fa1SHong Zhang     if (A->factortype) { /* for factored matrix */
32908401ef6SPierre Jolivet       PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix is factored with bs>1. Not implemented yet");
330*421480d9SBarry Smith       PetscCall(MatGetDiagonalMarkers_SeqSBAIJ(A, &diag, NULL));
331121deb67SSatish Balay       for (i = 0; i < a->mbs; i++) { /* for row block i */
3329566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
3332c990fa1SHong Zhang         /* diagonal entry */
3342c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX)
3352c990fa1SHong Zhang         if (PetscImaginaryPart(a->a[diag[i]]) > 0.0) {
3369566063dSJacob 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]])));
3372c990fa1SHong Zhang         } else if (PetscImaginaryPart(a->a[diag[i]]) < 0.0) {
3389566063dSJacob 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]])));
3392c990fa1SHong Zhang         } else {
3409566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)PetscRealPart(1.0 / a->a[diag[i]])));
3412c990fa1SHong Zhang         }
3422c990fa1SHong Zhang #else
343835f2295SStefano Zampini         PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)(1 / a->a[diag[i]])));
3442c990fa1SHong Zhang #endif
3452c990fa1SHong Zhang         /* off-diagonal entries */
3462c990fa1SHong Zhang         for (k = a->i[i]; k < a->i[i + 1] - 1; k++) {
3472c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX)
348ca0704adSBarry Smith           if (PetscImaginaryPart(a->a[k]) > 0.0) {
3499566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), (double)PetscImaginaryPart(a->a[k])));
350ca0704adSBarry Smith           } else if (PetscImaginaryPart(a->a[k]) < 0.0) {
3519566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), -(double)PetscImaginaryPart(a->a[k])));
3522c990fa1SHong Zhang           } else {
3539566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k], (double)PetscRealPart(a->a[k])));
3542c990fa1SHong Zhang           }
3552c990fa1SHong Zhang #else
3569566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[k], (double)a->a[k]));
3572c990fa1SHong Zhang #endif
3582c990fa1SHong Zhang         }
3599566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
3602c990fa1SHong Zhang       }
3612c990fa1SHong Zhang 
3622c990fa1SHong Zhang     } else {                         /* for non-factored matrix */
3630c74a584SJed Brown       for (i = 0; i < a->mbs; i++) { /* for row block i */
3640c74a584SJed Brown         for (j = 0; j < bs; j++) {   /* for row bs*i + j */
3659566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i * bs + j));
3660c74a584SJed Brown           for (k = a->i[i]; k < a->i[i + 1]; k++) { /* for column block */
3670c74a584SJed Brown             for (l = 0; l < bs; l++) {              /* for column */
36849b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX)
36949b5e25fSSatish Balay               if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) > 0.0) {
3709371c9d4SSatish 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])));
37149b5e25fSSatish Balay               } else if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) < 0.0) {
3729371c9d4SSatish 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])));
37349b5e25fSSatish Balay               } else {
3749566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j])));
37549b5e25fSSatish Balay               }
37649b5e25fSSatish Balay #else
3779566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)a->a[bs2 * k + l * bs + j]));
37849b5e25fSSatish Balay #endif
37949b5e25fSSatish Balay             }
38049b5e25fSSatish Balay           }
3819566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
38249b5e25fSSatish Balay         }
38349b5e25fSSatish Balay       }
3842c990fa1SHong Zhang     }
3859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
38649b5e25fSSatish Balay   }
3879566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
3883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38949b5e25fSSatish Balay }
39049b5e25fSSatish Balay 
3919804daf3SBarry Smith #include <petscdraw.h>
392d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw, void *Aa)
393d71ae5a4SJacob Faibussowitsch {
39449b5e25fSSatish Balay   Mat           A = (Mat)Aa;
39549b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
3966497c311SBarry Smith   PetscInt      row, i, j, k, l, mbs = a->mbs, bs = A->rmap->bs, bs2 = a->bs2;
39749b5e25fSSatish Balay   PetscReal     xl, yl, xr, yr, x_l, x_r, y_l, y_r;
39849b5e25fSSatish Balay   MatScalar    *aa;
399b0a32e0cSBarry Smith   PetscViewer   viewer;
4006497c311SBarry Smith   int           color;
40149b5e25fSSatish Balay 
40249b5e25fSSatish Balay   PetscFunctionBegin;
4039566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
4049566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
40549b5e25fSSatish Balay 
40649b5e25fSSatish Balay   /* loop over matrix elements drawing boxes */
407383922c3SLisandro Dalcin 
408d0609cedSBarry Smith   PetscDrawCollectiveBegin(draw);
4099566063dSJacob Faibussowitsch   PetscCall(PetscDrawString(draw, .3 * (xl + xr), .3 * (yl + yr), PETSC_DRAW_BLACK, "symmetric"));
410383922c3SLisandro Dalcin   /* Blue for negative, Cyan for zero and  Red for positive */
411b0a32e0cSBarry Smith   color = PETSC_DRAW_BLUE;
41249b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
41349b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4149371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4159371c9d4SSatish Balay       y_r = y_l + 1.0;
4169371c9d4SSatish Balay       x_l = a->j[j] * bs;
4179371c9d4SSatish Balay       x_r = x_l + 1.0;
41849b5e25fSSatish Balay       aa  = a->a + j * bs2;
41949b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
42049b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
42149b5e25fSSatish Balay           if (PetscRealPart(*aa++) >= 0.) continue;
4229566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
42349b5e25fSSatish Balay         }
42449b5e25fSSatish Balay       }
42549b5e25fSSatish Balay     }
42649b5e25fSSatish Balay   }
427b0a32e0cSBarry Smith   color = PETSC_DRAW_CYAN;
42849b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
42949b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4309371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4319371c9d4SSatish Balay       y_r = y_l + 1.0;
4329371c9d4SSatish Balay       x_l = a->j[j] * bs;
4339371c9d4SSatish Balay       x_r = x_l + 1.0;
43449b5e25fSSatish Balay       aa  = a->a + j * bs2;
43549b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
43649b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
43749b5e25fSSatish Balay           if (PetscRealPart(*aa++) != 0.) continue;
4389566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
43949b5e25fSSatish Balay         }
44049b5e25fSSatish Balay       }
44149b5e25fSSatish Balay     }
44249b5e25fSSatish Balay   }
443b0a32e0cSBarry Smith   color = PETSC_DRAW_RED;
44449b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
44549b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4469371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4479371c9d4SSatish Balay       y_r = y_l + 1.0;
4489371c9d4SSatish Balay       x_l = a->j[j] * bs;
4499371c9d4SSatish Balay       x_r = x_l + 1.0;
45049b5e25fSSatish Balay       aa  = a->a + j * bs2;
45149b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
45249b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
45349b5e25fSSatish Balay           if (PetscRealPart(*aa++) <= 0.) continue;
4549566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
45549b5e25fSSatish Balay         }
45649b5e25fSSatish Balay       }
45749b5e25fSSatish Balay     }
45849b5e25fSSatish Balay   }
459d0609cedSBarry Smith   PetscDrawCollectiveEnd(draw);
4603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46149b5e25fSSatish Balay }
46249b5e25fSSatish Balay 
463d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_Draw(Mat A, PetscViewer viewer)
464d71ae5a4SJacob Faibussowitsch {
46549b5e25fSSatish Balay   PetscReal xl, yl, xr, yr, w, h;
466b0a32e0cSBarry Smith   PetscDraw draw;
467ace3abfcSBarry Smith   PetscBool isnull;
46849b5e25fSSatish Balay 
46949b5e25fSSatish Balay   PetscFunctionBegin;
4709566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4719566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
4723ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
47349b5e25fSSatish Balay 
4749371c9d4SSatish Balay   xr = A->rmap->N;
4759371c9d4SSatish Balay   yr = A->rmap->N;
4769371c9d4SSatish Balay   h  = yr / 10.0;
4779371c9d4SSatish Balay   w  = xr / 10.0;
4789371c9d4SSatish Balay   xr += w;
4799371c9d4SSatish Balay   yr += h;
4809371c9d4SSatish Balay   xl = -w;
4819371c9d4SSatish Balay   yl = -h;
4829566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
4839566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
4849566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqSBAIJ_Draw_Zoom, A));
4859566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
4869566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
4873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48849b5e25fSSatish Balay }
48949b5e25fSSatish Balay 
490618cc2edSLisandro Dalcin /* Used for both MPIBAIJ and MPISBAIJ matrices */
491618cc2edSLisandro Dalcin #define MatView_SeqSBAIJ_Binary MatView_SeqBAIJ_Binary
492618cc2edSLisandro Dalcin 
493d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqSBAIJ(Mat A, PetscViewer viewer)
494d71ae5a4SJacob Faibussowitsch {
4959f196a02SMartin Diehl   PetscBool isascii, isbinary, isdraw;
49649b5e25fSSatish Balay 
49749b5e25fSSatish Balay   PetscFunctionBegin;
4989f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
4999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
5009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
5019f196a02SMartin Diehl   if (isascii) {
5029566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_ASCII(A, viewer));
503618cc2edSLisandro Dalcin   } else if (isbinary) {
5049566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_Binary(A, viewer));
50549b5e25fSSatish Balay   } else if (isdraw) {
5069566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_Draw(A, viewer));
50749b5e25fSSatish Balay   } else {
508a5e6ed63SBarry Smith     Mat         B;
509ade3a672SBarry Smith     const char *matname;
5109566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B));
51123a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname));
51223a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)B, matname));
5139566063dSJacob Faibussowitsch     PetscCall(MatView(B, viewer));
5149566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
51549b5e25fSSatish Balay   }
5163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51749b5e25fSSatish Balay }
51849b5e25fSSatish Balay 
519d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[])
520d71ae5a4SJacob Faibussowitsch {
521045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
52213f74950SBarry Smith   PetscInt     *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j;
52313f74950SBarry Smith   PetscInt     *ai = a->i, *ailen = a->ilen;
524d0f46423SBarry Smith   PetscInt      brow, bcol, ridx, cidx, bs = A->rmap->bs, bs2 = a->bs2;
52597e567efSBarry Smith   MatScalar    *ap, *aa = a->a;
52649b5e25fSSatish Balay 
52749b5e25fSSatish Balay   PetscFunctionBegin;
52849b5e25fSSatish Balay   for (k = 0; k < m; k++) { /* loop over rows */
5299371c9d4SSatish Balay     row  = im[k];
5309371c9d4SSatish Balay     brow = row / bs;
5319371c9d4SSatish Balay     if (row < 0) {
5329371c9d4SSatish Balay       v += n;
5339371c9d4SSatish Balay       continue;
5349371c9d4SSatish Balay     } /* negative row */
53554c59aa7SJacob 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);
5369371c9d4SSatish Balay     rp   = aj + ai[brow];
5379371c9d4SSatish Balay     ap   = aa + bs2 * ai[brow];
53849b5e25fSSatish Balay     nrow = ailen[brow];
53949b5e25fSSatish Balay     for (l = 0; l < n; l++) { /* loop over columns */
5409371c9d4SSatish Balay       if (in[l] < 0) {
5419371c9d4SSatish Balay         v++;
5429371c9d4SSatish Balay         continue;
5439371c9d4SSatish Balay       } /* negative column */
54454c59aa7SJacob 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);
54549b5e25fSSatish Balay       col  = in[l];
54649b5e25fSSatish Balay       bcol = col / bs;
54749b5e25fSSatish Balay       cidx = col % bs;
54849b5e25fSSatish Balay       ridx = row % bs;
54949b5e25fSSatish Balay       high = nrow;
55049b5e25fSSatish Balay       low  = 0; /* assume unsorted */
55149b5e25fSSatish Balay       while (high - low > 5) {
55249b5e25fSSatish Balay         t = (low + high) / 2;
55349b5e25fSSatish Balay         if (rp[t] > bcol) high = t;
55449b5e25fSSatish Balay         else low = t;
55549b5e25fSSatish Balay       }
55649b5e25fSSatish Balay       for (i = low; i < high; i++) {
55749b5e25fSSatish Balay         if (rp[i] > bcol) break;
55849b5e25fSSatish Balay         if (rp[i] == bcol) {
55949b5e25fSSatish Balay           *v++ = ap[bs2 * i + bs * cidx + ridx];
56049b5e25fSSatish Balay           goto finished;
56149b5e25fSSatish Balay         }
56249b5e25fSSatish Balay       }
56397e567efSBarry Smith       *v++ = 0.0;
56449b5e25fSSatish Balay     finished:;
56549b5e25fSSatish Balay     }
56649b5e25fSSatish Balay   }
5673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56849b5e25fSSatish Balay }
56949b5e25fSSatish Balay 
570ba38deedSJacob Faibussowitsch static PetscErrorCode MatPermute_SeqSBAIJ(Mat A, IS rowp, IS colp, Mat *B)
571d71ae5a4SJacob Faibussowitsch {
572dc29a518SPierre Jolivet   Mat       C;
57357069620SPierre Jolivet   PetscBool flg = (PetscBool)(rowp == colp);
574dc29a518SPierre Jolivet 
575dc29a518SPierre Jolivet   PetscFunctionBegin;
5769566063dSJacob Faibussowitsch   PetscCall(MatConvert(A, MATSEQBAIJ, MAT_INITIAL_MATRIX, &C));
5779566063dSJacob Faibussowitsch   PetscCall(MatPermute(C, rowp, colp, B));
5789566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
57957069620SPierre Jolivet   if (!flg) PetscCall(ISEqual(rowp, colp, &flg));
58057069620SPierre Jolivet   if (flg) PetscCall(MatConvert(*B, MATSEQSBAIJ, MAT_INPLACE_MATRIX, B));
5813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
582dc29a518SPierre Jolivet }
58349b5e25fSSatish Balay 
584d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesBlocked_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is)
585d71ae5a4SJacob Faibussowitsch {
5860880e062SHong Zhang   Mat_SeqSBAIJ      *a = (Mat_SeqSBAIJ *)A->data;
587e2ee6c50SBarry Smith   PetscInt          *rp, k, low, high, t, ii, jj, row, nrow, i, col, l, rmax, N, lastcol = -1;
58813f74950SBarry Smith   PetscInt          *imax = a->imax, *ai = a->i, *ailen = a->ilen;
589d0f46423SBarry Smith   PetscInt          *aj = a->j, nonew = a->nonew, bs2 = a->bs2, bs = A->rmap->bs, stepval;
590ace3abfcSBarry Smith   PetscBool          roworiented = a->roworiented;
591dd6ea824SBarry Smith   const PetscScalar *value       = v;
592f15d580aSBarry Smith   MatScalar         *ap, *aa = a->a, *bap;
5930880e062SHong Zhang 
59449b5e25fSSatish Balay   PetscFunctionBegin;
59526fbe8dcSKarl Rupp   if (roworiented) stepval = (n - 1) * bs;
59626fbe8dcSKarl Rupp   else stepval = (m - 1) * bs;
5970880e062SHong Zhang   for (k = 0; k < m; k++) { /* loop over added rows */
5980880e062SHong Zhang     row = im[k];
5990880e062SHong Zhang     if (row < 0) continue;
6006bdcaf15SBarry 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);
6010880e062SHong Zhang     rp   = aj + ai[row];
6020880e062SHong Zhang     ap   = aa + bs2 * ai[row];
6030880e062SHong Zhang     rmax = imax[row];
6040880e062SHong Zhang     nrow = ailen[row];
6050880e062SHong Zhang     low  = 0;
606818f2c47SBarry Smith     high = nrow;
6070880e062SHong Zhang     for (l = 0; l < n; l++) { /* loop over added columns */
6080880e062SHong Zhang       if (in[l] < 0) continue;
6090880e062SHong Zhang       col = in[l];
6106bdcaf15SBarry 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);
611b98bf0e1SJed Brown       if (col < row) {
612966bd95aSPierre 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)");
613966bd95aSPierre Jolivet         continue; /* ignore lower triangular block */
614b98bf0e1SJed Brown       }
61526fbe8dcSKarl Rupp       if (roworiented) value = v + k * (stepval + bs) * bs + l * bs;
61626fbe8dcSKarl Rupp       else value = v + l * (stepval + bs) * bs + k * bs;
61726fbe8dcSKarl Rupp 
61826fbe8dcSKarl Rupp       if (col <= lastcol) low = 0;
61926fbe8dcSKarl Rupp       else high = nrow;
62026fbe8dcSKarl Rupp 
621e2ee6c50SBarry Smith       lastcol = col;
6220880e062SHong Zhang       while (high - low > 7) {
6230880e062SHong Zhang         t = (low + high) / 2;
6240880e062SHong Zhang         if (rp[t] > col) high = t;
6250880e062SHong Zhang         else low = t;
6260880e062SHong Zhang       }
6270880e062SHong Zhang       for (i = low; i < high; i++) {
6280880e062SHong Zhang         if (rp[i] > col) break;
6290880e062SHong Zhang         if (rp[i] == col) {
6300880e062SHong Zhang           bap = ap + bs2 * i;
6310880e062SHong Zhang           if (roworiented) {
6320880e062SHong Zhang             if (is == ADD_VALUES) {
6330880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
634ad540459SPierre Jolivet                 for (jj = ii; jj < bs2; jj += bs) bap[jj] += *value++;
6350880e062SHong Zhang               }
6360880e062SHong Zhang             } else {
6370880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
638ad540459SPierre Jolivet                 for (jj = ii; jj < bs2; jj += bs) bap[jj] = *value++;
6390880e062SHong Zhang               }
6400880e062SHong Zhang             }
6410880e062SHong Zhang           } else {
6420880e062SHong Zhang             if (is == ADD_VALUES) {
6430880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
644ad540459SPierre Jolivet                 for (jj = 0; jj < bs; jj++) *bap++ += *value++;
6450880e062SHong Zhang               }
6460880e062SHong Zhang             } else {
6470880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
648ad540459SPierre Jolivet                 for (jj = 0; jj < bs; jj++) *bap++ = *value++;
6490880e062SHong Zhang               }
6500880e062SHong Zhang             }
6510880e062SHong Zhang           }
6520880e062SHong Zhang           goto noinsert2;
6530880e062SHong Zhang         }
6540880e062SHong Zhang       }
6550880e062SHong Zhang       if (nonew == 1) goto noinsert2;
65608401ef6SPierre 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);
657fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
6589371c9d4SSatish Balay       N = nrow++ - 1;
6599371c9d4SSatish Balay       high++;
6600880e062SHong Zhang       /* shift up all the later entries in this row */
6619566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1));
6629566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1)));
6639566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(ap + bs2 * i, bs2));
6640880e062SHong Zhang       rp[i] = col;
6650880e062SHong Zhang       bap   = ap + bs2 * i;
6660880e062SHong Zhang       if (roworiented) {
6670880e062SHong Zhang         for (ii = 0; ii < bs; ii++, value += stepval) {
668ad540459SPierre Jolivet           for (jj = ii; jj < bs2; jj += bs) bap[jj] = *value++;
6690880e062SHong Zhang         }
6700880e062SHong Zhang       } else {
6710880e062SHong Zhang         for (ii = 0; ii < bs; ii++, value += stepval) {
672ad540459SPierre Jolivet           for (jj = 0; jj < bs; jj++) *bap++ = *value++;
6730880e062SHong Zhang         }
6740880e062SHong Zhang       }
6750880e062SHong Zhang     noinsert2:;
6760880e062SHong Zhang       low = i;
6770880e062SHong Zhang     }
6780880e062SHong Zhang     ailen[row] = nrow;
6790880e062SHong Zhang   }
6803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68149b5e25fSSatish Balay }
68249b5e25fSSatish Balay 
683ba38deedSJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_SeqSBAIJ(Mat A, MatAssemblyType mode)
684d71ae5a4SJacob Faibussowitsch {
68549b5e25fSSatish Balay   Mat_SeqSBAIJ *a      = (Mat_SeqSBAIJ *)A->data;
6868f8f2f0dSBarry Smith   PetscInt      fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax;
687d0f46423SBarry Smith   PetscInt      m = A->rmap->N, *ip, N, *ailen = a->ilen;
68813f74950SBarry Smith   PetscInt      mbs = a->mbs, bs2 = a->bs2, rmax = 0;
68949b5e25fSSatish Balay   MatScalar    *aa = a->a, *ap;
69049b5e25fSSatish Balay 
69149b5e25fSSatish Balay   PetscFunctionBegin;
692d32568d8SPierre Jolivet   if (mode == MAT_FLUSH_ASSEMBLY || (A->was_assembled && A->ass_nonzerostate == A->nonzerostate)) PetscFunctionReturn(PETSC_SUCCESS);
69349b5e25fSSatish Balay 
69449b5e25fSSatish Balay   if (m) rmax = ailen[0];
69549b5e25fSSatish Balay   for (i = 1; i < mbs; i++) {
69649b5e25fSSatish Balay     /* move each row back by the amount of empty slots (fshift) before it*/
69749b5e25fSSatish Balay     fshift += imax[i - 1] - ailen[i - 1];
69849b5e25fSSatish Balay     rmax = PetscMax(rmax, ailen[i]);
69949b5e25fSSatish Balay     if (fshift) {
700580bdb30SBarry Smith       ip = aj + ai[i];
701580bdb30SBarry Smith       ap = aa + bs2 * ai[i];
70249b5e25fSSatish Balay       N  = ailen[i];
7039566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ip - fshift, ip, N));
7049566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ap - bs2 * fshift, ap, bs2 * N));
70549b5e25fSSatish Balay     }
70649b5e25fSSatish Balay     ai[i] = ai[i - 1] + ailen[i - 1];
70749b5e25fSSatish Balay   }
70849b5e25fSSatish Balay   if (mbs) {
70949b5e25fSSatish Balay     fshift += imax[mbs - 1] - ailen[mbs - 1];
71049b5e25fSSatish Balay     ai[mbs] = ai[mbs - 1] + ailen[mbs - 1];
71149b5e25fSSatish Balay   }
71249b5e25fSSatish Balay   /* reset ilen and imax for each row */
713ad540459SPierre Jolivet   for (i = 0; i < mbs; i++) ailen[i] = imax[i] = ai[i + 1] - ai[i];
7146c6c5352SBarry Smith   a->nz = ai[mbs];
71549b5e25fSSatish Balay 
716aed4548fSBarry 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);
71726fbe8dcSKarl Rupp 
7189566063dSJacob 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));
7199566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues is %" PetscInt_FMT "\n", a->reallocs));
7209566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Most nonzeros blocks in any row is %" PetscInt_FMT "\n", rmax));
72126fbe8dcSKarl Rupp 
7228e58a170SBarry Smith   A->info.mallocs += a->reallocs;
72349b5e25fSSatish Balay   a->reallocs         = 0;
72449b5e25fSSatish Balay   A->info.nz_unneeded = (PetscReal)fshift * bs2;
725061b2667SBarry Smith   a->idiagvalid       = PETSC_FALSE;
7264dcd73b1SHong Zhang   a->rmax             = rmax;
72738702af4SBarry Smith 
72838702af4SBarry Smith   if (A->cmap->n < 65536 && A->cmap->bs == 1) {
72944e1c64aSLisandro Dalcin     if (a->jshort && a->free_jshort) {
73017803ae8SHong Zhang       /* when matrix data structure is changed, previous jshort must be replaced */
7319566063dSJacob Faibussowitsch       PetscCall(PetscFree(a->jshort));
73217803ae8SHong Zhang     }
7339566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(a->i[A->rmap->n], &a->jshort));
7346497c311SBarry Smith     for (i = 0; i < a->i[A->rmap->n]; i++) a->jshort[i] = (short)a->j[i];
73538702af4SBarry Smith     A->ops->mult   = MatMult_SeqSBAIJ_1_ushort;
73641f059aeSBarry Smith     A->ops->sor    = MatSOR_SeqSBAIJ_ushort;
7374da8f245SBarry Smith     a->free_jshort = PETSC_TRUE;
73838702af4SBarry Smith   }
7393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
74049b5e25fSSatish Balay }
74149b5e25fSSatish Balay 
74249b5e25fSSatish Balay /* Only add/insert a(i,j) with i<=j (blocks).
743da81f932SPierre Jolivet    Any a(i,j) with i>j input by user is ignored.
74449b5e25fSSatish Balay */
74549b5e25fSSatish Balay 
746d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is)
747d71ae5a4SJacob Faibussowitsch {
74849b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
749e2ee6c50SBarry Smith   PetscInt     *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N, lastcol = -1;
75013f74950SBarry Smith   PetscInt     *imax = a->imax, *ai = a->i, *ailen = a->ilen, roworiented = a->roworiented;
751d0f46423SBarry Smith   PetscInt     *aj = a->j, nonew = a->nonew, bs = A->rmap->bs, brow, bcol;
75213f74950SBarry Smith   PetscInt      ridx, cidx, bs2                 = a->bs2;
75349b5e25fSSatish Balay   MatScalar    *ap, value, *aa                  = a->a, *bap;
75449b5e25fSSatish Balay 
75549b5e25fSSatish Balay   PetscFunctionBegin;
75649b5e25fSSatish Balay   for (k = 0; k < m; k++) { /* loop over added rows */
75749b5e25fSSatish Balay     row  = im[k];           /* row number */
75849b5e25fSSatish Balay     brow = row / bs;        /* block row number */
75949b5e25fSSatish Balay     if (row < 0) continue;
7606bdcaf15SBarry 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);
76149b5e25fSSatish Balay     rp   = aj + ai[brow];       /*ptr to beginning of column value of the row block*/
76249b5e25fSSatish Balay     ap   = aa + bs2 * ai[brow]; /*ptr to beginning of element value of the row block*/
76349b5e25fSSatish Balay     rmax = imax[brow];          /* maximum space allocated for this row */
76449b5e25fSSatish Balay     nrow = ailen[brow];         /* actual length of this row */
76549b5e25fSSatish Balay     low  = 0;
7668509e838SStefano Zampini     high = nrow;
76749b5e25fSSatish Balay     for (l = 0; l < n; l++) { /* loop over added columns */
76849b5e25fSSatish Balay       if (in[l] < 0) continue;
7696bdcaf15SBarry 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);
77049b5e25fSSatish Balay       col  = in[l];
77149b5e25fSSatish Balay       bcol = col / bs; /* block col number */
77249b5e25fSSatish Balay 
773941593c8SHong Zhang       if (brow > bcol) {
774966bd95aSPierre 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)");
775966bd95aSPierre Jolivet         continue; /* ignore lower triangular values */
776941593c8SHong Zhang       }
777f4989cb3SHong Zhang 
7789371c9d4SSatish Balay       ridx = row % bs;
7799371c9d4SSatish Balay       cidx = col % bs; /*row and col index inside the block */
7808549e402SHong Zhang       if ((brow == bcol && ridx <= cidx) || (brow < bcol)) {
78149b5e25fSSatish Balay         /* element value a(k,l) */
78226fbe8dcSKarl Rupp         if (roworiented) value = v[l + k * n];
78326fbe8dcSKarl Rupp         else value = v[k + l * m];
78449b5e25fSSatish Balay 
78549b5e25fSSatish Balay         /* move pointer bap to a(k,l) quickly and add/insert value */
78626fbe8dcSKarl Rupp         if (col <= lastcol) low = 0;
7878509e838SStefano Zampini         else high = nrow;
7888509e838SStefano Zampini 
789e2ee6c50SBarry Smith         lastcol = col;
79049b5e25fSSatish Balay         while (high - low > 7) {
79149b5e25fSSatish Balay           t = (low + high) / 2;
79249b5e25fSSatish Balay           if (rp[t] > bcol) high = t;
79349b5e25fSSatish Balay           else low = t;
79449b5e25fSSatish Balay         }
79549b5e25fSSatish Balay         for (i = low; i < high; i++) {
79649b5e25fSSatish Balay           if (rp[i] > bcol) break;
79749b5e25fSSatish Balay           if (rp[i] == bcol) {
79849b5e25fSSatish Balay             bap = ap + bs2 * i + bs * cidx + ridx;
79949b5e25fSSatish Balay             if (is == ADD_VALUES) *bap += value;
80049b5e25fSSatish Balay             else *bap = value;
8018549e402SHong Zhang             /* for diag block, add/insert its symmetric element a(cidx,ridx) */
8028549e402SHong Zhang             if (brow == bcol && ridx < cidx) {
8038549e402SHong Zhang               bap = ap + bs2 * i + bs * ridx + cidx;
8048549e402SHong Zhang               if (is == ADD_VALUES) *bap += value;
8058549e402SHong Zhang               else *bap = value;
8068549e402SHong Zhang             }
80749b5e25fSSatish Balay             goto noinsert1;
80849b5e25fSSatish Balay           }
80949b5e25fSSatish Balay         }
81049b5e25fSSatish Balay 
81149b5e25fSSatish Balay         if (nonew == 1) goto noinsert1;
81208401ef6SPierre Jolivet         PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero (%" PetscInt_FMT ", %" PetscInt_FMT ") in the matrix", row, col);
813fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, brow, bcol, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
81449b5e25fSSatish Balay 
8159371c9d4SSatish Balay         N = nrow++ - 1;
8169371c9d4SSatish Balay         high++;
81749b5e25fSSatish Balay         /* shift up all the later entries in this row */
8189566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1));
8199566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1)));
8209566063dSJacob Faibussowitsch         PetscCall(PetscArrayzero(ap + bs2 * i, bs2));
82149b5e25fSSatish Balay         rp[i]                          = bcol;
82249b5e25fSSatish Balay         ap[bs2 * i + bs * cidx + ridx] = value;
8238509e838SStefano Zampini         /* for diag block, add/insert its symmetric element a(cidx,ridx) */
824ad540459SPierre Jolivet         if (brow == bcol && ridx < cidx) ap[bs2 * i + bs * ridx + cidx] = value;
82549b5e25fSSatish Balay       noinsert1:;
82649b5e25fSSatish Balay         low = i;
8278549e402SHong Zhang       }
82849b5e25fSSatish Balay     } /* end of loop over added columns */
82949b5e25fSSatish Balay     ailen[brow] = nrow;
83049b5e25fSSatish Balay   } /* end of loop over added rows */
8313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
83249b5e25fSSatish Balay }
83349b5e25fSSatish Balay 
834ba38deedSJacob Faibussowitsch static PetscErrorCode MatICCFactor_SeqSBAIJ(Mat inA, IS row, const MatFactorInfo *info)
835d71ae5a4SJacob Faibussowitsch {
8364ccecd49SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)inA->data;
83749b5e25fSSatish Balay   Mat           outA;
838ace3abfcSBarry Smith   PetscBool     row_identity;
83949b5e25fSSatish Balay 
84049b5e25fSSatish Balay   PetscFunctionBegin;
84108401ef6SPierre Jolivet   PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 is supported for in-place icc");
8429566063dSJacob Faibussowitsch   PetscCall(ISIdentity(row, &row_identity));
84328b400f6SJacob Faibussowitsch   PetscCheck(row_identity, PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix reordering is not supported");
84408401ef6SPierre 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()! */
845c84f5b01SHong Zhang 
84649b5e25fSSatish Balay   outA = inA;
8479566063dSJacob Faibussowitsch   PetscCall(PetscFree(inA->solvertype));
8489566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype));
84949b5e25fSSatish Balay 
850*421480d9SBarry Smith   inA->factortype = MAT_FACTOR_ICC;
8519566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetNumericFactorization_inplace(inA, row_identity));
85249b5e25fSSatish Balay 
8539566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
8549566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
855c84f5b01SHong Zhang   a->row = row;
8569566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
8579566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
858c84f5b01SHong Zhang   a->col = row;
859c84f5b01SHong Zhang 
860c84f5b01SHong Zhang   /* Create the invert permutation so that it can be used in MatCholeskyFactorNumeric() */
8619566063dSJacob Faibussowitsch   if (a->icol) PetscCall(ISInvertPermutation(row, PETSC_DECIDE, &a->icol));
86249b5e25fSSatish Balay 
863aa624791SPierre Jolivet   if (!a->solve_work) PetscCall(PetscMalloc1(inA->rmap->N + inA->rmap->bs, &a->solve_work));
86449b5e25fSSatish Balay 
8659566063dSJacob Faibussowitsch   PetscCall(MatCholeskyFactorNumeric(outA, inA, info));
8663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
86749b5e25fSSatish Balay }
868950f1e5bSHong Zhang 
869ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat, PetscInt *indices)
870d71ae5a4SJacob Faibussowitsch {
871045c9aa0SHong Zhang   Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)mat->data;
87213f74950SBarry Smith   PetscInt      i, nz, n;
87349b5e25fSSatish Balay 
87449b5e25fSSatish Balay   PetscFunctionBegin;
8756c6c5352SBarry Smith   nz = baij->maxnz;
876d0f46423SBarry Smith   n  = mat->cmap->n;
87726fbe8dcSKarl Rupp   for (i = 0; i < nz; i++) baij->j[i] = indices[i];
87826fbe8dcSKarl Rupp 
8796c6c5352SBarry Smith   baij->nz = nz;
88026fbe8dcSKarl Rupp   for (i = 0; i < n; i++) baij->ilen[i] = baij->imax[i];
88126fbe8dcSKarl Rupp 
8829566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
8833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
88449b5e25fSSatish Balay }
88549b5e25fSSatish Balay 
88649b5e25fSSatish Balay /*@
88719585528SSatish Balay   MatSeqSBAIJSetColumnIndices - Set the column indices for all the rows
88811a5261eSBarry Smith   in a `MATSEQSBAIJ` matrix.
88949b5e25fSSatish Balay 
89049b5e25fSSatish Balay   Input Parameters:
89111a5261eSBarry Smith + mat     - the `MATSEQSBAIJ` matrix
89249b5e25fSSatish Balay - indices - the column indices
89349b5e25fSSatish Balay 
89449b5e25fSSatish Balay   Level: advanced
89549b5e25fSSatish Balay 
89649b5e25fSSatish Balay   Notes:
89749b5e25fSSatish Balay   This can be called if you have precomputed the nonzero structure of the
89849b5e25fSSatish Balay   matrix and want to provide it to the matrix object to improve the performance
89911a5261eSBarry Smith   of the `MatSetValues()` operation.
90049b5e25fSSatish Balay 
90149b5e25fSSatish Balay   You MUST have set the correct numbers of nonzeros per row in the call to
90211a5261eSBarry Smith   `MatCreateSeqSBAIJ()`, and the columns indices MUST be sorted.
90349b5e25fSSatish Balay 
9042ef1f0ffSBarry Smith   MUST be called before any calls to `MatSetValues()`
90549b5e25fSSatish Balay 
9061cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreateSeqSBAIJ`
90749b5e25fSSatish Balay @*/
908d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetColumnIndices(Mat mat, PetscInt *indices)
909d71ae5a4SJacob Faibussowitsch {
91049b5e25fSSatish Balay   PetscFunctionBegin;
9110700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9124f572ea9SToby Isaac   PetscAssertPointer(indices, 2);
913cac4c232SBarry Smith   PetscUseMethod(mat, "MatSeqSBAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices));
9143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91549b5e25fSSatish Balay }
91649b5e25fSSatish Balay 
917ba38deedSJacob Faibussowitsch static PetscErrorCode MatCopy_SeqSBAIJ(Mat A, Mat B, MatStructure str)
918d71ae5a4SJacob Faibussowitsch {
9194c7a3774SStefano Zampini   PetscBool isbaij;
9203c896bc6SHong Zhang 
9213c896bc6SHong Zhang   PetscFunctionBegin;
9229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &isbaij, MATSEQSBAIJ, MATMPISBAIJ, ""));
92328b400f6SJacob Faibussowitsch   PetscCheck(isbaij, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)B)->type_name);
9244c7a3774SStefano Zampini   /* If the two matrices have the same copy implementation and nonzero pattern, use fast copy. */
9254c7a3774SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
9263c896bc6SHong Zhang     Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
9273c896bc6SHong Zhang     Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data;
9283c896bc6SHong Zhang 
92908401ef6SPierre 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");
93008401ef6SPierre Jolivet     PetscCheck(a->mbs == b->mbs, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of rows in two matrices are different");
93108401ef6SPierre Jolivet     PetscCheck(a->bs2 == b->bs2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different block size");
9329566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(b->a, a->a, a->bs2 * a->i[a->mbs]));
9339566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)B));
9343c896bc6SHong Zhang   } else {
9359566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(A));
9369566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
9379566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(A));
9383c896bc6SHong Zhang   }
9393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9403c896bc6SHong Zhang }
9413c896bc6SHong Zhang 
942d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJGetArray_SeqSBAIJ(Mat A, PetscScalar *array[])
943d71ae5a4SJacob Faibussowitsch {
944a6ece127SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
9455fd66863SKarl Rupp 
946a6ece127SHong Zhang   PetscFunctionBegin;
947a6ece127SHong Zhang   *array = a->a;
9483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
949a6ece127SHong Zhang }
950a6ece127SHong Zhang 
951d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJRestoreArray_SeqSBAIJ(Mat A, PetscScalar *array[])
952d71ae5a4SJacob Faibussowitsch {
953a6ece127SHong Zhang   PetscFunctionBegin;
954cda14afcSprj-   *array = NULL;
9553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
956a6ece127SHong Zhang }
957a6ece127SHong Zhang 
958d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPYGetPreallocation_SeqSBAIJ(Mat Y, Mat X, PetscInt *nnz)
959d71ae5a4SJacob Faibussowitsch {
960b264fe52SHong Zhang   PetscInt      bs = Y->rmap->bs, mbs = Y->rmap->N / bs;
96152768537SHong Zhang   Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data;
96252768537SHong Zhang   Mat_SeqSBAIJ *y = (Mat_SeqSBAIJ *)Y->data;
96352768537SHong Zhang 
96452768537SHong Zhang   PetscFunctionBegin;
96552768537SHong Zhang   /* Set the number of nonzeros in the new matrix */
9669566063dSJacob Faibussowitsch   PetscCall(MatAXPYGetPreallocation_SeqX_private(mbs, x->i, x->j, y->i, y->j, nnz));
9673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
96852768537SHong Zhang }
96952768537SHong Zhang 
970ba38deedSJacob Faibussowitsch static PetscErrorCode MatAXPY_SeqSBAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str)
971d71ae5a4SJacob Faibussowitsch {
97242ee4b1aSHong Zhang   Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data, *y = (Mat_SeqSBAIJ *)Y->data;
97331ce2d13SHong Zhang   PetscInt      bs = Y->rmap->bs, bs2 = bs * bs;
974e838b9e7SJed Brown   PetscBLASInt  one = 1;
97542ee4b1aSHong Zhang 
97642ee4b1aSHong Zhang   PetscFunctionBegin;
977134adf20SPierre Jolivet   if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) {
978134adf20SPierre Jolivet     PetscBool e = x->nz == y->nz && x->mbs == y->mbs ? PETSC_TRUE : PETSC_FALSE;
979134adf20SPierre Jolivet     if (e) {
9809566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(x->i, y->i, x->mbs + 1, &e));
981134adf20SPierre Jolivet       if (e) {
9829566063dSJacob Faibussowitsch         PetscCall(PetscArraycmp(x->j, y->j, x->i[x->mbs], &e));
983134adf20SPierre Jolivet         if (e) str = SAME_NONZERO_PATTERN;
984134adf20SPierre Jolivet       }
985134adf20SPierre Jolivet     }
98654c59aa7SJacob Faibussowitsch     if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN");
987134adf20SPierre Jolivet   }
98842ee4b1aSHong Zhang   if (str == SAME_NONZERO_PATTERN) {
989f4df32b1SMatthew Knepley     PetscScalar  alpha = a;
990c5df96a5SBarry Smith     PetscBLASInt bnz;
9919566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(x->nz * bs2, &bnz));
992792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, x->a, &one, y->a, &one));
9939566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)Y));
994ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
9959566063dSJacob Faibussowitsch     PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_TRUE));
9969566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
9979566063dSJacob Faibussowitsch     PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_FALSE));
99842ee4b1aSHong Zhang   } else {
99952768537SHong Zhang     Mat       B;
100052768537SHong Zhang     PetscInt *nnz;
100154c59aa7SJacob Faibussowitsch     PetscCheck(bs == X->rmap->bs, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Matrices must have same block size");
10029566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(X));
10039566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(Y));
10049566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Y->rmap->N, &nnz));
10059566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B));
10069566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name));
10079566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, Y->rmap->n, Y->cmap->n, Y->rmap->N, Y->cmap->N));
10089566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, Y, Y));
10099566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, ((PetscObject)Y)->type_name));
10109566063dSJacob Faibussowitsch     PetscCall(MatAXPYGetPreallocation_SeqSBAIJ(Y, X, nnz));
10119566063dSJacob Faibussowitsch     PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz));
101252768537SHong Zhang 
10139566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
101452768537SHong Zhang 
10159566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
10169566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz));
10179566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(X));
10189566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(Y));
101942ee4b1aSHong Zhang   }
10203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
102142ee4b1aSHong Zhang }
102242ee4b1aSHong Zhang 
1023ba38deedSJacob Faibussowitsch static PetscErrorCode MatIsStructurallySymmetric_SeqSBAIJ(Mat A, PetscBool *flg)
1024d71ae5a4SJacob Faibussowitsch {
1025efcf0fc3SBarry Smith   PetscFunctionBegin;
1026efcf0fc3SBarry Smith   *flg = PETSC_TRUE;
10273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1028efcf0fc3SBarry Smith }
1029efcf0fc3SBarry Smith 
1030ba38deedSJacob Faibussowitsch static PetscErrorCode MatConjugate_SeqSBAIJ(Mat A)
1031d71ae5a4SJacob Faibussowitsch {
10322726fb6dSPierre Jolivet #if defined(PETSC_USE_COMPLEX)
10332726fb6dSPierre Jolivet   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
10342726fb6dSPierre Jolivet   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
10352726fb6dSPierre Jolivet   MatScalar    *aa = a->a;
10362726fb6dSPierre Jolivet 
10372726fb6dSPierre Jolivet   PetscFunctionBegin;
10382726fb6dSPierre Jolivet   for (i = 0; i < nz; i++) aa[i] = PetscConj(aa[i]);
10392726fb6dSPierre Jolivet #else
10402726fb6dSPierre Jolivet   PetscFunctionBegin;
10412726fb6dSPierre Jolivet #endif
10423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10432726fb6dSPierre Jolivet }
10442726fb6dSPierre Jolivet 
1045ba38deedSJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqSBAIJ(Mat A)
1046d71ae5a4SJacob Faibussowitsch {
104799cafbc1SBarry Smith   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
104899cafbc1SBarry Smith   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
1049dd6ea824SBarry Smith   MatScalar    *aa = a->a;
105099cafbc1SBarry Smith 
105199cafbc1SBarry Smith   PetscFunctionBegin;
105299cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]);
10533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
105499cafbc1SBarry Smith }
105599cafbc1SBarry Smith 
1056ba38deedSJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqSBAIJ(Mat A)
1057d71ae5a4SJacob Faibussowitsch {
105899cafbc1SBarry Smith   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
105999cafbc1SBarry Smith   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
1060dd6ea824SBarry Smith   MatScalar    *aa = a->a;
106199cafbc1SBarry Smith 
106299cafbc1SBarry Smith   PetscFunctionBegin;
106399cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
10643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
106599cafbc1SBarry Smith }
106699cafbc1SBarry Smith 
1067ba38deedSJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_SeqSBAIJ(Mat A, PetscInt is_n, const PetscInt is_idx[], PetscScalar diag, Vec x, Vec b)
1068d71ae5a4SJacob Faibussowitsch {
10693bededecSBarry Smith   Mat_SeqSBAIJ      *baij = (Mat_SeqSBAIJ *)A->data;
10703bededecSBarry Smith   PetscInt           i, j, k, count;
10713bededecSBarry Smith   PetscInt           bs = A->rmap->bs, bs2 = baij->bs2, row, col;
10723bededecSBarry Smith   PetscScalar        zero = 0.0;
10733bededecSBarry Smith   MatScalar         *aa;
10743bededecSBarry Smith   const PetscScalar *xx;
10753bededecSBarry Smith   PetscScalar       *bb;
107656777dd2SBarry Smith   PetscBool         *zeroed, vecs = PETSC_FALSE;
10773bededecSBarry Smith 
10783bededecSBarry Smith   PetscFunctionBegin;
1079dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
10803bededecSBarry Smith   if (x && b) {
10819566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
10829566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
108356777dd2SBarry Smith     vecs = PETSC_TRUE;
10843bededecSBarry Smith   }
10853bededecSBarry Smith 
10863bededecSBarry Smith   /* zero the columns */
10879566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(A->rmap->n, &zeroed));
10883bededecSBarry Smith   for (i = 0; i < is_n; i++) {
1089aed4548fSBarry 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]);
10903bededecSBarry Smith     zeroed[is_idx[i]] = PETSC_TRUE;
10913bededecSBarry Smith   }
109256777dd2SBarry Smith   if (vecs) {
109356777dd2SBarry Smith     for (i = 0; i < A->rmap->N; i++) {
109456777dd2SBarry Smith       row = i / bs;
109556777dd2SBarry Smith       for (j = baij->i[row]; j < baij->i[row + 1]; j++) {
109656777dd2SBarry Smith         for (k = 0; k < bs; k++) {
109756777dd2SBarry Smith           col = bs * baij->j[j] + k;
109856777dd2SBarry Smith           if (col <= i) continue;
1099835f2295SStefano Zampini           aa = baij->a + j * bs2 + (i % bs) + bs * k;
110026fbe8dcSKarl Rupp           if (!zeroed[i] && zeroed[col]) bb[i] -= aa[0] * xx[col];
110126fbe8dcSKarl Rupp           if (zeroed[i] && !zeroed[col]) bb[col] -= aa[0] * xx[i];
110256777dd2SBarry Smith         }
110356777dd2SBarry Smith       }
110456777dd2SBarry Smith     }
110526fbe8dcSKarl Rupp     for (i = 0; i < is_n; i++) bb[is_idx[i]] = diag * xx[is_idx[i]];
110656777dd2SBarry Smith   }
110756777dd2SBarry Smith 
11083bededecSBarry Smith   for (i = 0; i < A->rmap->N; i++) {
11093bededecSBarry Smith     if (!zeroed[i]) {
11103bededecSBarry Smith       row = i / bs;
11113bededecSBarry Smith       for (j = baij->i[row]; j < baij->i[row + 1]; j++) {
11123bededecSBarry Smith         for (k = 0; k < bs; k++) {
11133bededecSBarry Smith           col = bs * baij->j[j] + k;
11143bededecSBarry Smith           if (zeroed[col]) {
1115835f2295SStefano Zampini             aa    = baij->a + j * bs2 + (i % bs) + bs * k;
11163bededecSBarry Smith             aa[0] = 0.0;
11173bededecSBarry Smith           }
11183bededecSBarry Smith         }
11193bededecSBarry Smith       }
11203bededecSBarry Smith     }
11213bededecSBarry Smith   }
11229566063dSJacob Faibussowitsch   PetscCall(PetscFree(zeroed));
112356777dd2SBarry Smith   if (vecs) {
11249566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
11259566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
112656777dd2SBarry Smith   }
11273bededecSBarry Smith 
11283bededecSBarry Smith   /* zero the rows */
11293bededecSBarry Smith   for (i = 0; i < is_n; i++) {
11303bededecSBarry Smith     row   = is_idx[i];
11313bededecSBarry Smith     count = (baij->i[row / bs + 1] - baij->i[row / bs]) * bs;
1132835f2295SStefano Zampini     aa    = baij->a + baij->i[row / bs] * bs2 + (row % bs);
11333bededecSBarry Smith     for (k = 0; k < count; k++) {
11343bededecSBarry Smith       aa[0] = zero;
11353bededecSBarry Smith       aa += bs;
11363bededecSBarry Smith     }
1137dbbe0bcdSBarry Smith     if (diag != 0.0) PetscUseTypeMethod(A, setvalues, 1, &row, 1, &row, &diag, INSERT_VALUES);
11383bededecSBarry Smith   }
11399566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd_SeqSBAIJ(A, MAT_FINAL_ASSEMBLY));
11403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11413bededecSBarry Smith }
11423bededecSBarry Smith 
1143ba38deedSJacob Faibussowitsch static PetscErrorCode MatShift_SeqSBAIJ(Mat Y, PetscScalar a)
1144d71ae5a4SJacob Faibussowitsch {
11457d68702bSBarry Smith   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)Y->data;
11467d68702bSBarry Smith 
11477d68702bSBarry Smith   PetscFunctionBegin;
114848a46eb9SPierre Jolivet   if (!Y->preallocated || !aij->nz) PetscCall(MatSeqSBAIJSetPreallocation(Y, Y->rmap->bs, 1, NULL));
11499566063dSJacob Faibussowitsch   PetscCall(MatShift_Basic(Y, a));
11503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11517d68702bSBarry Smith }
11527d68702bSBarry Smith 
115317ea310bSPierre Jolivet PetscErrorCode MatEliminateZeros_SeqSBAIJ(Mat A, PetscBool keep)
115417ea310bSPierre Jolivet {
115517ea310bSPierre Jolivet   Mat_SeqSBAIJ *a      = (Mat_SeqSBAIJ *)A->data;
115617ea310bSPierre Jolivet   PetscInt      fshift = 0, fshift_prev = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax, j, k;
115717ea310bSPierre Jolivet   PetscInt      m = A->rmap->N, *ailen = a->ilen;
115817ea310bSPierre Jolivet   PetscInt      mbs = a->mbs, bs2 = a->bs2, rmax = 0;
115917ea310bSPierre Jolivet   MatScalar    *aa = a->a, *ap;
116017ea310bSPierre Jolivet   PetscBool     zero;
116117ea310bSPierre Jolivet 
116217ea310bSPierre Jolivet   PetscFunctionBegin;
116317ea310bSPierre Jolivet   PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot eliminate zeros for unassembled matrix");
116417ea310bSPierre Jolivet   if (m) rmax = ailen[0];
116517ea310bSPierre Jolivet   for (i = 1; i <= mbs; i++) {
116617ea310bSPierre Jolivet     for (k = ai[i - 1]; k < ai[i]; k++) {
116717ea310bSPierre Jolivet       zero = PETSC_TRUE;
116817ea310bSPierre Jolivet       ap   = aa + bs2 * k;
116917ea310bSPierre Jolivet       for (j = 0; j < bs2 && zero; j++) {
117017ea310bSPierre Jolivet         if (ap[j] != 0.0) zero = PETSC_FALSE;
117117ea310bSPierre Jolivet       }
117217ea310bSPierre Jolivet       if (zero && (aj[k] != i - 1 || !keep)) fshift++;
117317ea310bSPierre Jolivet       else {
117417ea310bSPierre Jolivet         if (zero && aj[k] == i - 1) PetscCall(PetscInfo(A, "Keep the diagonal block at row %" PetscInt_FMT "\n", i - 1));
117517ea310bSPierre Jolivet         aj[k - fshift] = aj[k];
117617ea310bSPierre Jolivet         PetscCall(PetscArraymove(ap - bs2 * fshift, ap, bs2));
117717ea310bSPierre Jolivet       }
117817ea310bSPierre Jolivet     }
117917ea310bSPierre Jolivet     ai[i - 1] -= fshift_prev;
118017ea310bSPierre Jolivet     fshift_prev  = fshift;
118117ea310bSPierre Jolivet     ailen[i - 1] = imax[i - 1] = ai[i] - fshift - ai[i - 1];
118217ea310bSPierre Jolivet     a->nonzerorowcnt += ((ai[i] - fshift - ai[i - 1]) > 0);
118317ea310bSPierre Jolivet     rmax = PetscMax(rmax, ailen[i - 1]);
118417ea310bSPierre Jolivet   }
118517ea310bSPierre Jolivet   if (fshift) {
118617ea310bSPierre Jolivet     if (mbs) {
118717ea310bSPierre Jolivet       ai[mbs] -= fshift;
118817ea310bSPierre Jolivet       a->nz = ai[mbs];
118917ea310bSPierre Jolivet     }
119017ea310bSPierre 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));
119117ea310bSPierre Jolivet     A->nonzerostate++;
119217ea310bSPierre Jolivet     A->info.nz_unneeded += (PetscReal)fshift;
119317ea310bSPierre Jolivet     a->rmax = rmax;
119417ea310bSPierre Jolivet     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
119517ea310bSPierre Jolivet     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
119617ea310bSPierre Jolivet   }
119717ea310bSPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
119817ea310bSPierre Jolivet }
119917ea310bSPierre Jolivet 
12003964eb88SJed Brown static struct _MatOps MatOps_Values = {MatSetValues_SeqSBAIJ,
120149b5e25fSSatish Balay                                        MatGetRow_SeqSBAIJ,
120249b5e25fSSatish Balay                                        MatRestoreRow_SeqSBAIJ,
120349b5e25fSSatish Balay                                        MatMult_SeqSBAIJ_N,
120497304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqSBAIJ_N,
1205431c96f7SBarry Smith                                        MatMult_SeqSBAIJ_N, /* transpose versions are same as non-transpose versions */
1206e005ede5SBarry Smith                                        MatMultAdd_SeqSBAIJ_N,
1207f4259b30SLisandro Dalcin                                        NULL,
1208f4259b30SLisandro Dalcin                                        NULL,
1209f4259b30SLisandro Dalcin                                        NULL,
1210f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
1211f4259b30SLisandro Dalcin                                        NULL,
1212c078aec8SLisandro Dalcin                                        MatCholeskyFactor_SeqSBAIJ,
121341f059aeSBarry Smith                                        MatSOR_SeqSBAIJ,
121449b5e25fSSatish Balay                                        MatTranspose_SeqSBAIJ,
121597304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqSBAIJ,
121649b5e25fSSatish Balay                                        MatEqual_SeqSBAIJ,
121749b5e25fSSatish Balay                                        MatGetDiagonal_SeqSBAIJ,
121849b5e25fSSatish Balay                                        MatDiagonalScale_SeqSBAIJ,
121949b5e25fSSatish Balay                                        MatNorm_SeqSBAIJ,
1220f4259b30SLisandro Dalcin                                        /* 20*/ NULL,
122149b5e25fSSatish Balay                                        MatAssemblyEnd_SeqSBAIJ,
122249b5e25fSSatish Balay                                        MatSetOption_SeqSBAIJ,
122349b5e25fSSatish Balay                                        MatZeroEntries_SeqSBAIJ,
1224f4259b30SLisandro Dalcin                                        /* 24*/ NULL,
1225f4259b30SLisandro Dalcin                                        NULL,
1226f4259b30SLisandro Dalcin                                        NULL,
1227f4259b30SLisandro Dalcin                                        NULL,
1228f4259b30SLisandro Dalcin                                        NULL,
122926cec326SBarry Smith                                        /* 29*/ MatSetUp_Seq_Hash,
1230f4259b30SLisandro Dalcin                                        NULL,
1231f4259b30SLisandro Dalcin                                        NULL,
1232f4259b30SLisandro Dalcin                                        NULL,
1233f4259b30SLisandro Dalcin                                        NULL,
1234d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqSBAIJ,
1235f4259b30SLisandro Dalcin                                        NULL,
1236f4259b30SLisandro Dalcin                                        NULL,
1237f4259b30SLisandro Dalcin                                        NULL,
1238c84f5b01SHong Zhang                                        MatICCFactor_SeqSBAIJ,
1239d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqSBAIJ,
12407dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqSBAIJ,
124149b5e25fSSatish Balay                                        MatIncreaseOverlap_SeqSBAIJ,
124249b5e25fSSatish Balay                                        MatGetValues_SeqSBAIJ,
12433c896bc6SHong Zhang                                        MatCopy_SeqSBAIJ,
1244f4259b30SLisandro Dalcin                                        /* 44*/ NULL,
124549b5e25fSSatish Balay                                        MatScale_SeqSBAIJ,
12467d68702bSBarry Smith                                        MatShift_SeqSBAIJ,
1247f4259b30SLisandro Dalcin                                        NULL,
12483bededecSBarry Smith                                        MatZeroRowsColumns_SeqSBAIJ,
1249f4259b30SLisandro Dalcin                                        /* 49*/ NULL,
125049b5e25fSSatish Balay                                        MatGetRowIJ_SeqSBAIJ,
125149b5e25fSSatish Balay                                        MatRestoreRowIJ_SeqSBAIJ,
1252f4259b30SLisandro Dalcin                                        NULL,
1253f4259b30SLisandro Dalcin                                        NULL,
1254f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
1255f4259b30SLisandro Dalcin                                        NULL,
1256f4259b30SLisandro Dalcin                                        NULL,
1257dc29a518SPierre Jolivet                                        MatPermute_SeqSBAIJ,
125849b5e25fSSatish Balay                                        MatSetValuesBlocked_SeqSBAIJ,
12597dae84e0SHong Zhang                                        /* 59*/ MatCreateSubMatrix_SeqSBAIJ,
1260f4259b30SLisandro Dalcin                                        NULL,
1261f4259b30SLisandro Dalcin                                        NULL,
1262f4259b30SLisandro Dalcin                                        NULL,
1263f4259b30SLisandro Dalcin                                        NULL,
1264f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
1265f4259b30SLisandro Dalcin                                        NULL,
1266f4259b30SLisandro Dalcin                                        NULL,
1267f4259b30SLisandro Dalcin                                        NULL,
12688bb0f5c6SPierre Jolivet                                        MatGetRowMaxAbs_SeqSBAIJ,
12698bb0f5c6SPierre Jolivet                                        /* 69*/ NULL,
127028d58a37SPierre Jolivet                                        MatConvert_MPISBAIJ_Basic,
1271f4259b30SLisandro Dalcin                                        NULL,
1272f4259b30SLisandro Dalcin                                        NULL,
12738bb0f5c6SPierre Jolivet                                        NULL,
1274f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
1275f4259b30SLisandro Dalcin                                        NULL,
1276f4259b30SLisandro Dalcin                                        NULL,
127797304618SKris Buschelman                                        MatGetInertia_SeqSBAIJ,
12785bba2384SShri Abhyankar                                        MatLoad_SeqSBAIJ,
12798bb0f5c6SPierre Jolivet                                        /* 79*/ NULL,
12806cff0a6bSPierre Jolivet                                        NULL,
1281efcf0fc3SBarry Smith                                        MatIsStructurallySymmetric_SeqSBAIJ,
1282f4259b30SLisandro Dalcin                                        NULL,
1283f4259b30SLisandro Dalcin                                        NULL,
12848bb0f5c6SPierre Jolivet                                        /* 84*/ NULL,
12858bb0f5c6SPierre Jolivet                                        NULL,
12868bb0f5c6SPierre Jolivet                                        NULL,
12878bb0f5c6SPierre Jolivet                                        NULL,
12888bb0f5c6SPierre Jolivet                                        NULL,
1289f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
1290f4259b30SLisandro Dalcin                                        NULL,
1291f4259b30SLisandro Dalcin                                        NULL,
1292f4259b30SLisandro Dalcin                                        NULL,
12938bb0f5c6SPierre Jolivet                                        MatConjugate_SeqSBAIJ,
1294f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
1295f4259b30SLisandro Dalcin                                        NULL,
129699cafbc1SBarry Smith                                        MatRealPart_SeqSBAIJ,
1297f5edf698SHong Zhang                                        MatImaginaryPart_SeqSBAIJ,
1298f5edf698SHong Zhang                                        MatGetRowUpperTriangular_SeqSBAIJ,
12998bb0f5c6SPierre Jolivet                                        /* 99*/ MatRestoreRowUpperTriangular_SeqSBAIJ,
13008bb0f5c6SPierre Jolivet                                        NULL,
13018bb0f5c6SPierre Jolivet                                        NULL,
13028bb0f5c6SPierre Jolivet                                        NULL,
13038bb0f5c6SPierre Jolivet                                        NULL,
1304*421480d9SBarry Smith                                        /*104*/ NULL,
13058bb0f5c6SPierre Jolivet                                        NULL,
13068bb0f5c6SPierre Jolivet                                        NULL,
13078bb0f5c6SPierre Jolivet                                        NULL,
13088bb0f5c6SPierre Jolivet                                        NULL,
1309f4259b30SLisandro Dalcin                                        /*109*/ NULL,
1310f4259b30SLisandro Dalcin                                        NULL,
1311f4259b30SLisandro Dalcin                                        NULL,
1312f4259b30SLisandro Dalcin                                        NULL,
13138bb0f5c6SPierre Jolivet                                        NULL,
1314f4259b30SLisandro Dalcin                                        /*114*/ NULL,
1315f4259b30SLisandro Dalcin                                        NULL,
1316f4259b30SLisandro Dalcin                                        NULL,
1317f4259b30SLisandro Dalcin                                        NULL,
1318f4259b30SLisandro Dalcin                                        NULL,
1319f4259b30SLisandro Dalcin                                        /*119*/ NULL,
1320f4259b30SLisandro Dalcin                                        NULL,
1321f4259b30SLisandro Dalcin                                        NULL,
1322f4259b30SLisandro Dalcin                                        NULL,
1323f4259b30SLisandro Dalcin                                        NULL,
1324f4259b30SLisandro Dalcin                                        /*124*/ NULL,
1325f4259b30SLisandro Dalcin                                        NULL,
13268bb0f5c6SPierre Jolivet                                        MatSetBlockSizes_Default,
1327f4259b30SLisandro Dalcin                                        NULL,
1328f4259b30SLisandro Dalcin                                        NULL,
1329*421480d9SBarry Smith                                        /*129*/ NULL,
13308bb0f5c6SPierre Jolivet                                        MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ,
1331f4259b30SLisandro Dalcin                                        NULL,
1332f4259b30SLisandro Dalcin                                        NULL,
1333*421480d9SBarry Smith                                        NULL,
1334f4259b30SLisandro Dalcin                                        /*134*/ NULL,
1335f4259b30SLisandro Dalcin                                        NULL,
1336eede4a3fSMark Adams                                        MatEliminateZeros_SeqSBAIJ,
13374cc2b5b5SPierre Jolivet                                        NULL,
133842ce410bSJunchao Zhang                                        NULL,
1339*421480d9SBarry Smith                                        /*139*/ NULL,
134042ce410bSJunchao Zhang                                        NULL,
134103db1824SAlex Lindsay                                        MatCopyHashToXAIJ_Seq_Hash,
1342c2be7ffeSStefano Zampini                                        NULL,
134303db1824SAlex Lindsay                                        NULL};
1344be1d678aSKris Buschelman 
1345ba38deedSJacob Faibussowitsch static PetscErrorCode MatStoreValues_SeqSBAIJ(Mat mat)
1346d71ae5a4SJacob Faibussowitsch {
13474afc71dfSHong Zhang   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1348d0f46423SBarry Smith   PetscInt      nz  = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2;
134949b5e25fSSatish Balay 
135049b5e25fSSatish Balay   PetscFunctionBegin;
135108401ef6SPierre Jolivet   PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
135249b5e25fSSatish Balay 
135349b5e25fSSatish Balay   /* allocate space for values if not already there */
135448a46eb9SPierre Jolivet   if (!aij->saved_values) PetscCall(PetscMalloc1(nz + 1, &aij->saved_values));
135549b5e25fSSatish Balay 
135649b5e25fSSatish Balay   /* copy values over */
13579566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz));
13583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
135949b5e25fSSatish Balay }
136049b5e25fSSatish Balay 
1361ba38deedSJacob Faibussowitsch static PetscErrorCode MatRetrieveValues_SeqSBAIJ(Mat mat)
1362d71ae5a4SJacob Faibussowitsch {
13634afc71dfSHong Zhang   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1364d0f46423SBarry Smith   PetscInt      nz  = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2;
136549b5e25fSSatish Balay 
136649b5e25fSSatish Balay   PetscFunctionBegin;
136708401ef6SPierre Jolivet   PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
136828b400f6SJacob Faibussowitsch   PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first");
136949b5e25fSSatish Balay 
137049b5e25fSSatish Balay   /* copy values over */
13719566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz));
13723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
137349b5e25fSSatish Balay }
137449b5e25fSSatish Balay 
1375f9663b93SPierre Jolivet static PetscErrorCode MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[])
1376d71ae5a4SJacob Faibussowitsch {
1377c464158bSHong Zhang   Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data;
13784dcd73b1SHong Zhang   PetscInt      i, mbs, nbs, bs2;
13792576faa2SJed Brown   PetscBool     skipallocation = PETSC_FALSE, flg = PETSC_FALSE, realalloc = PETSC_FALSE;
138049b5e25fSSatish Balay 
1381b4e2f619SBarry Smith   PetscFunctionBegin;
1382ad79cf63SBarry Smith   if (B->hash_active) {
1383ad79cf63SBarry Smith     PetscInt bs;
1384aea10558SJacob Faibussowitsch     B->ops[0] = b->cops;
1385ad79cf63SBarry Smith     PetscCall(PetscHMapIJVDestroy(&b->ht));
1386ad79cf63SBarry Smith     PetscCall(MatGetBlockSize(B, &bs));
1387ad79cf63SBarry Smith     if (bs > 1) PetscCall(PetscHSetIJDestroy(&b->bht));
1388ad79cf63SBarry Smith     PetscCall(PetscFree(b->dnz));
1389ad79cf63SBarry Smith     PetscCall(PetscFree(b->bdnz));
1390ad79cf63SBarry Smith     B->hash_active = PETSC_FALSE;
1391ad79cf63SBarry Smith   }
13922576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
1393db4efbfdSBarry Smith 
139458b7e2c1SStefano Zampini   PetscCall(MatSetBlockSize(B, bs));
13959566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
13969566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
139708401ef6SPierre 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);
13989566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs));
1399899cda47SBarry Smith 
140021940c7eSstefano_zampini   B->preallocated = PETSC_TRUE;
140121940c7eSstefano_zampini 
1402d0f46423SBarry Smith   mbs = B->rmap->N / bs;
14034dcd73b1SHong Zhang   nbs = B->cmap->n / bs;
140449b5e25fSSatish Balay   bs2 = bs * bs;
140549b5e25fSSatish Balay 
1406aed4548fSBarry 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");
140749b5e25fSSatish Balay 
1408ab93d7beSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
1409ab93d7beSBarry Smith     skipallocation = PETSC_TRUE;
1410ab93d7beSBarry Smith     nz             = 0;
1411ab93d7beSBarry Smith   }
1412ab93d7beSBarry Smith 
1413435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3;
141408401ef6SPierre Jolivet   PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz);
141549b5e25fSSatish Balay   if (nnz) {
141649b5e25fSSatish Balay     for (i = 0; i < mbs; i++) {
141708401ef6SPierre 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]);
141808401ef6SPierre 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);
141949b5e25fSSatish Balay     }
142049b5e25fSSatish Balay   }
142149b5e25fSSatish Balay 
1422db4efbfdSBarry Smith   B->ops->mult             = MatMult_SeqSBAIJ_N;
1423db4efbfdSBarry Smith   B->ops->multadd          = MatMultAdd_SeqSBAIJ_N;
1424db4efbfdSBarry Smith   B->ops->multtranspose    = MatMult_SeqSBAIJ_N;
1425db4efbfdSBarry Smith   B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N;
142626fbe8dcSKarl Rupp 
14279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL));
142849b5e25fSSatish Balay   if (!flg) {
142949b5e25fSSatish Balay     switch (bs) {
143049b5e25fSSatish Balay     case 1:
143149b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_1;
143249b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_1;
1433431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_1;
1434431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1;
143549b5e25fSSatish Balay       break;
143649b5e25fSSatish Balay     case 2:
143749b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_2;
143849b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_2;
1439431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_2;
1440431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2;
144149b5e25fSSatish Balay       break;
144249b5e25fSSatish Balay     case 3:
144349b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_3;
144449b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_3;
1445431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_3;
1446431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3;
144749b5e25fSSatish Balay       break;
144849b5e25fSSatish Balay     case 4:
144949b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_4;
145049b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_4;
1451431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_4;
1452431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4;
145349b5e25fSSatish Balay       break;
145449b5e25fSSatish Balay     case 5:
145549b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_5;
145649b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_5;
1457431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_5;
1458431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5;
145949b5e25fSSatish Balay       break;
146049b5e25fSSatish Balay     case 6:
146149b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_6;
146249b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_6;
1463431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_6;
1464431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6;
146549b5e25fSSatish Balay       break;
146649b5e25fSSatish Balay     case 7:
1467de53e5efSHong Zhang       B->ops->mult             = MatMult_SeqSBAIJ_7;
146849b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_7;
1469431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_7;
1470431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7;
147149b5e25fSSatish Balay       break;
147249b5e25fSSatish Balay     }
147349b5e25fSSatish Balay   }
147449b5e25fSSatish Balay 
147549b5e25fSSatish Balay   b->mbs = mbs;
14764dcd73b1SHong Zhang   b->nbs = nbs;
1477ab93d7beSBarry Smith   if (!skipallocation) {
14782ee49352SLisandro Dalcin     if (!b->imax) {
14799566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(mbs, &b->imax, mbs, &b->ilen));
148026fbe8dcSKarl Rupp 
1481c760cd28SBarry Smith       b->free_imax_ilen = PETSC_TRUE;
14822ee49352SLisandro Dalcin     }
148349b5e25fSSatish Balay     if (!nnz) {
1484435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
148549b5e25fSSatish Balay       else if (nz <= 0) nz = 1;
14865d2a9ed1SStefano Zampini       nz = PetscMin(nbs, nz);
148726fbe8dcSKarl Rupp       for (i = 0; i < mbs; i++) b->imax[i] = nz;
14889566063dSJacob Faibussowitsch       PetscCall(PetscIntMultError(nz, mbs, &nz));
148949b5e25fSSatish Balay     } else {
1490c73702f5SBarry Smith       PetscInt64 nz64 = 0;
14919371c9d4SSatish Balay       for (i = 0; i < mbs; i++) {
14929371c9d4SSatish Balay         b->imax[i] = nnz[i];
14939371c9d4SSatish Balay         nz64 += nnz[i];
14949371c9d4SSatish Balay       }
14959566063dSJacob Faibussowitsch       PetscCall(PetscIntCast(nz64, &nz));
149649b5e25fSSatish Balay     }
14972ee49352SLisandro Dalcin     /* b->ilen will count nonzeros in each block row so far. */
149826fbe8dcSKarl Rupp     for (i = 0; i < mbs; i++) b->ilen[i] = 0;
14996c6c5352SBarry Smith     /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */
150049b5e25fSSatish Balay 
150149b5e25fSSatish Balay     /* allocate the matrix space */
15029566063dSJacob Faibussowitsch     PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i));
15039f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(bs2 * nz, sizeof(PetscScalar), (void **)&b->a));
15049f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&b->j));
15059f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(B->rmap->n + 1, sizeof(PetscInt), (void **)&b->i));
15069f0612e4SBarry Smith     b->free_a  = PETSC_TRUE;
15079f0612e4SBarry Smith     b->free_ij = PETSC_TRUE;
15089566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->a, nz * bs2));
15099566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->j, nz));
15109f0612e4SBarry Smith     b->free_a  = PETSC_TRUE;
15119f0612e4SBarry Smith     b->free_ij = PETSC_TRUE;
151249b5e25fSSatish Balay 
151349b5e25fSSatish Balay     /* pointer to beginning of each row */
1514e60cf9a0SBarry Smith     b->i[0] = 0;
151526fbe8dcSKarl Rupp     for (i = 1; i < mbs + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1];
151626fbe8dcSKarl Rupp 
1517e811da20SHong Zhang   } else {
1518e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
1519e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
1520ab93d7beSBarry Smith   }
152149b5e25fSSatish Balay 
152249b5e25fSSatish Balay   b->bs2     = bs2;
15236c6c5352SBarry Smith   b->nz      = 0;
1524b32cb4a7SJed Brown   b->maxnz   = nz;
1525f4259b30SLisandro Dalcin   b->inew    = NULL;
1526f4259b30SLisandro Dalcin   b->jnew    = NULL;
1527f4259b30SLisandro Dalcin   b->anew    = NULL;
1528f4259b30SLisandro Dalcin   b->a2anew  = NULL;
15291a3463dfSHong Zhang   b->permute = PETSC_FALSE;
1530cb7b82ddSBarry Smith 
1531cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
1532cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
15339566063dSJacob Faibussowitsch   if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
15343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1535c464158bSHong Zhang }
1536153ea458SHong Zhang 
1537ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ(Mat B, PetscInt bs, const PetscInt ii[], const PetscInt jj[], const PetscScalar V[])
1538d71ae5a4SJacob Faibussowitsch {
15390cd7f59aSBarry Smith   PetscInt      i, j, m, nz, anz, nz_max = 0, *nnz;
1540f4259b30SLisandro Dalcin   PetscScalar  *values      = NULL;
15411c466ed6SStefano Zampini   Mat_SeqSBAIJ *b           = (Mat_SeqSBAIJ *)B->data;
15421c466ed6SStefano Zampini   PetscBool     roworiented = b->roworiented;
15431c466ed6SStefano Zampini   PetscBool     ilw         = b->ignore_ltriangular;
15440cd7f59aSBarry Smith 
154538f409ebSLisandro Dalcin   PetscFunctionBegin;
154608401ef6SPierre Jolivet   PetscCheck(bs >= 1, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_OUTOFRANGE, "Invalid block size specified, must be positive but it is %" PetscInt_FMT, bs);
15479566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(B->rmap, bs));
15489566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(B->cmap, bs));
15499566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
15509566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
15519566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs));
155238f409ebSLisandro Dalcin   m = B->rmap->n / bs;
155338f409ebSLisandro Dalcin 
1554aed4548fSBarry Smith   PetscCheck(!ii[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ii[0] must be 0 but it is %" PetscInt_FMT, ii[0]);
15559566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &nnz));
155638f409ebSLisandro Dalcin   for (i = 0; i < m; i++) {
155738f409ebSLisandro Dalcin     nz = ii[i + 1] - ii[i];
155808401ef6SPierre Jolivet     PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz);
15591c466ed6SStefano Zampini     PetscCheckSorted(nz, jj + ii[i]);
15600cd7f59aSBarry Smith     anz = 0;
15610cd7f59aSBarry Smith     for (j = 0; j < nz; j++) {
15620cd7f59aSBarry Smith       /* count only values on the diagonal or above */
15630cd7f59aSBarry Smith       if (jj[ii[i] + j] >= i) {
15640cd7f59aSBarry Smith         anz = nz - j;
15650cd7f59aSBarry Smith         break;
15660cd7f59aSBarry Smith       }
15670cd7f59aSBarry Smith     }
15681c466ed6SStefano Zampini     nz_max = PetscMax(nz_max, nz);
15690cd7f59aSBarry Smith     nnz[i] = anz;
157038f409ebSLisandro Dalcin   }
15719566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz));
15729566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
157338f409ebSLisandro Dalcin 
157438f409ebSLisandro Dalcin   values = (PetscScalar *)V;
157548a46eb9SPierre Jolivet   if (!values) PetscCall(PetscCalloc1(bs * bs * nz_max, &values));
15761c466ed6SStefano Zampini   b->ignore_ltriangular = PETSC_TRUE;
157738f409ebSLisandro Dalcin   for (i = 0; i < m; i++) {
157838f409ebSLisandro Dalcin     PetscInt        ncols = ii[i + 1] - ii[i];
157938f409ebSLisandro Dalcin     const PetscInt *icols = jj + ii[i];
15801c466ed6SStefano Zampini 
158138f409ebSLisandro Dalcin     if (!roworiented || bs == 1) {
158238f409ebSLisandro Dalcin       const PetscScalar *svals = values + (V ? (bs * bs * ii[i]) : 0);
15839566063dSJacob Faibussowitsch       PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, ncols, icols, svals, INSERT_VALUES));
158438f409ebSLisandro Dalcin     } else {
158538f409ebSLisandro Dalcin       for (j = 0; j < ncols; j++) {
158638f409ebSLisandro Dalcin         const PetscScalar *svals = values + (V ? (bs * bs * (ii[i] + j)) : 0);
15879566063dSJacob Faibussowitsch         PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, 1, &icols[j], svals, INSERT_VALUES));
158838f409ebSLisandro Dalcin       }
158938f409ebSLisandro Dalcin     }
159038f409ebSLisandro Dalcin   }
15919566063dSJacob Faibussowitsch   if (!V) PetscCall(PetscFree(values));
15929566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
15939566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
15949566063dSJacob Faibussowitsch   PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
15951c466ed6SStefano Zampini   b->ignore_ltriangular = ilw;
15963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
159738f409ebSLisandro Dalcin }
159838f409ebSLisandro Dalcin 
1599db4efbfdSBarry Smith /*
1600db4efbfdSBarry Smith    This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization
1601db4efbfdSBarry Smith */
1602d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetNumericFactorization_inplace(Mat B, PetscBool natural)
1603d71ae5a4SJacob Faibussowitsch {
1604ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
1605db4efbfdSBarry Smith   PetscInt  bs  = B->rmap->bs;
1606db4efbfdSBarry Smith 
1607db4efbfdSBarry Smith   PetscFunctionBegin;
16089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL));
1609db4efbfdSBarry Smith   if (flg) bs = 8;
1610db4efbfdSBarry Smith 
1611db4efbfdSBarry Smith   if (!natural) {
1612db4efbfdSBarry Smith     switch (bs) {
1613d71ae5a4SJacob Faibussowitsch     case 1:
1614d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_inplace;
1615d71ae5a4SJacob Faibussowitsch       break;
1616d71ae5a4SJacob Faibussowitsch     case 2:
1617d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2;
1618d71ae5a4SJacob Faibussowitsch       break;
1619d71ae5a4SJacob Faibussowitsch     case 3:
1620d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3;
1621d71ae5a4SJacob Faibussowitsch       break;
1622d71ae5a4SJacob Faibussowitsch     case 4:
1623d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4;
1624d71ae5a4SJacob Faibussowitsch       break;
1625d71ae5a4SJacob Faibussowitsch     case 5:
1626d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5;
1627d71ae5a4SJacob Faibussowitsch       break;
1628d71ae5a4SJacob Faibussowitsch     case 6:
1629d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6;
1630d71ae5a4SJacob Faibussowitsch       break;
1631d71ae5a4SJacob Faibussowitsch     case 7:
1632d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7;
1633d71ae5a4SJacob Faibussowitsch       break;
1634d71ae5a4SJacob Faibussowitsch     default:
1635d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N;
1636d71ae5a4SJacob Faibussowitsch       break;
1637db4efbfdSBarry Smith     }
1638db4efbfdSBarry Smith   } else {
1639db4efbfdSBarry Smith     switch (bs) {
1640d71ae5a4SJacob Faibussowitsch     case 1:
1641d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering_inplace;
1642d71ae5a4SJacob Faibussowitsch       break;
1643d71ae5a4SJacob Faibussowitsch     case 2:
1644d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering;
1645d71ae5a4SJacob Faibussowitsch       break;
1646d71ae5a4SJacob Faibussowitsch     case 3:
1647d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering;
1648d71ae5a4SJacob Faibussowitsch       break;
1649d71ae5a4SJacob Faibussowitsch     case 4:
1650d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering;
1651d71ae5a4SJacob Faibussowitsch       break;
1652d71ae5a4SJacob Faibussowitsch     case 5:
1653d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering;
1654d71ae5a4SJacob Faibussowitsch       break;
1655d71ae5a4SJacob Faibussowitsch     case 6:
1656d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering;
1657d71ae5a4SJacob Faibussowitsch       break;
1658d71ae5a4SJacob Faibussowitsch     case 7:
1659d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering;
1660d71ae5a4SJacob Faibussowitsch       break;
1661d71ae5a4SJacob Faibussowitsch     default:
1662d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering;
1663d71ae5a4SJacob Faibussowitsch       break;
1664db4efbfdSBarry Smith     }
1665db4efbfdSBarry Smith   }
16663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1667db4efbfdSBarry Smith }
1668db4efbfdSBarry Smith 
1669cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType, MatReuse, Mat *);
1670cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType, MatReuse, Mat *);
1671d71ae5a4SJacob Faibussowitsch static PetscErrorCode       MatFactorGetSolverType_petsc(Mat A, MatSolverType *type)
1672d71ae5a4SJacob Faibussowitsch {
16734ac6704cSBarry Smith   PetscFunctionBegin;
16744ac6704cSBarry Smith   *type = MATSOLVERPETSC;
16753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16764ac6704cSBarry Smith }
1677d769727bSBarry Smith 
1678d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A, MatFactorType ftype, Mat *B)
1679d71ae5a4SJacob Faibussowitsch {
1680d0f46423SBarry Smith   PetscInt n = A->rmap->n;
16815c9eb25fSBarry Smith 
16825c9eb25fSBarry Smith   PetscFunctionBegin;
16830e92d65fSHong Zhang #if defined(PETSC_USE_COMPLEX)
168403e5aca4SStefano Zampini   if ((ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) && A->hermitian == PETSC_BOOL3_TRUE && A->symmetric != PETSC_BOOL3_TRUE) {
168503e5aca4SStefano Zampini     PetscCall(PetscInfo(A, "Hermitian MAT_FACTOR_CHOLESKY or MAT_FACTOR_ICC are not supported. Use MAT_FACTOR_LU instead.\n"));
168603e5aca4SStefano Zampini     *B = NULL;
168703e5aca4SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
168803e5aca4SStefano Zampini   }
16890e92d65fSHong Zhang #endif
1690eb1ec7c1SStefano Zampini 
16919566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B));
16929566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*B, n, n, n, n));
1693966bd95aSPierre Jolivet   PetscCheck(ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC, PETSC_COMM_SELF, PETSC_ERR_SUP, "Factor type not supported");
16949566063dSJacob Faibussowitsch   PetscCall(MatSetType(*B, MATSEQSBAIJ));
16959566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*B, A->rmap->bs, MAT_SKIP_ALLOCATION, NULL));
169626fbe8dcSKarl Rupp 
16977b056e98SHong Zhang   (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ;
1698c6d0d4f0SHong Zhang   (*B)->ops->iccfactorsymbolic      = MatICCFactorSymbolic_SeqSBAIJ;
16999566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_CHOLESKY]));
17009566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_ICC]));
170100c67f3bSHong Zhang 
1702d5f3da31SBarry Smith   (*B)->factortype     = ftype;
1703f73b0415SBarry Smith   (*B)->canuseordering = PETSC_TRUE;
17049566063dSJacob Faibussowitsch   PetscCall(PetscFree((*B)->solvertype));
17059566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*B)->solvertype));
17069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)*B, "MatFactorGetSolverType_C", MatFactorGetSolverType_petsc));
17073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17085c9eb25fSBarry Smith }
17095c9eb25fSBarry Smith 
17108397e458SBarry Smith /*@C
17112ef1f0ffSBarry Smith   MatSeqSBAIJGetArray - gives access to the array where the numerical data for a `MATSEQSBAIJ` matrix is stored
17128397e458SBarry Smith 
17138397e458SBarry Smith   Not Collective
17148397e458SBarry Smith 
17158397e458SBarry Smith   Input Parameter:
1716fe59aa6dSJacob Faibussowitsch . A - a `MATSEQSBAIJ` matrix
17178397e458SBarry Smith 
17188397e458SBarry Smith   Output Parameter:
17198397e458SBarry Smith . array - pointer to the data
17208397e458SBarry Smith 
17218397e458SBarry Smith   Level: intermediate
17228397e458SBarry Smith 
17231cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatSeqSBAIJRestoreArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`
17248397e458SBarry Smith @*/
17255d83a8b1SBarry Smith PetscErrorCode MatSeqSBAIJGetArray(Mat A, PetscScalar *array[])
1726d71ae5a4SJacob Faibussowitsch {
17278397e458SBarry Smith   PetscFunctionBegin;
1728cac4c232SBarry Smith   PetscUseMethod(A, "MatSeqSBAIJGetArray_C", (Mat, PetscScalar **), (A, array));
17293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17308397e458SBarry Smith }
17318397e458SBarry Smith 
17328397e458SBarry Smith /*@C
17332ef1f0ffSBarry Smith   MatSeqSBAIJRestoreArray - returns access to the array where the numerical data for a `MATSEQSBAIJ` matrix is stored obtained by `MatSeqSBAIJGetArray()`
17348397e458SBarry Smith 
17358397e458SBarry Smith   Not Collective
17368397e458SBarry Smith 
17378397e458SBarry Smith   Input Parameters:
1738fe59aa6dSJacob Faibussowitsch + A     - a `MATSEQSBAIJ` matrix
1739a2b725a8SWilliam Gropp - array - pointer to the data
17408397e458SBarry Smith 
17418397e458SBarry Smith   Level: intermediate
17428397e458SBarry Smith 
17431cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatSeqSBAIJGetArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`
17448397e458SBarry Smith @*/
17455d83a8b1SBarry Smith PetscErrorCode MatSeqSBAIJRestoreArray(Mat A, PetscScalar *array[])
1746d71ae5a4SJacob Faibussowitsch {
17478397e458SBarry Smith   PetscFunctionBegin;
1748cac4c232SBarry Smith   PetscUseMethod(A, "MatSeqSBAIJRestoreArray_C", (Mat, PetscScalar **), (A, array));
17493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17508397e458SBarry Smith }
17518397e458SBarry Smith 
17520bad9183SKris Buschelman /*MC
1753fafad747SKris Buschelman   MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices,
17540bad9183SKris Buschelman   based on block compressed sparse row format.  Only the upper triangular portion of the matrix is stored.
17550bad9183SKris Buschelman 
1756828413b8SBarry Smith   For complex numbers by default this matrix is symmetric, NOT Hermitian symmetric. To make it Hermitian symmetric you
175711a5261eSBarry Smith   can call `MatSetOption`(`Mat`, `MAT_HERMITIAN`).
1758828413b8SBarry Smith 
17592ef1f0ffSBarry Smith   Options Database Key:
176011a5261eSBarry Smith   . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to `MatSetFromOptions()`
17610bad9183SKris Buschelman 
17622ef1f0ffSBarry Smith   Level: beginner
17632ef1f0ffSBarry Smith 
176495452b02SPatrick Sanan   Notes:
176595452b02SPatrick Sanan   By default if you insert values into the lower triangular part of the matrix they are simply ignored (since they are not
176611a5261eSBarry 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
17672ef1f0ffSBarry 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.
176871dad5bbSBarry Smith 
1769476417e5SBarry Smith   The number of rows in the matrix must be less than or equal to the number of columns
177071dad5bbSBarry Smith 
17711cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreateSeqSBAIJ()`, `MatType`, `MATMPISBAIJ`
17720bad9183SKris Buschelman M*/
1773d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_SeqSBAIJ(Mat B)
1774d71ae5a4SJacob Faibussowitsch {
1775a23d5eceSKris Buschelman   Mat_SeqSBAIJ *b;
177613f74950SBarry Smith   PetscMPIInt   size;
1777ace3abfcSBarry Smith   PetscBool     no_unroll = PETSC_FALSE, no_inode = PETSC_FALSE;
1778a23d5eceSKris Buschelman 
1779a23d5eceSKris Buschelman   PetscFunctionBegin;
17809566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
178108401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
1782a23d5eceSKris Buschelman 
17834dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
1784a23d5eceSKris Buschelman   B->data   = (void *)b;
1785aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
178626fbe8dcSKarl Rupp 
1787a23d5eceSKris Buschelman   B->ops->destroy    = MatDestroy_SeqSBAIJ;
1788a23d5eceSKris Buschelman   B->ops->view       = MatView_SeqSBAIJ;
1789f4259b30SLisandro Dalcin   b->row             = NULL;
1790f4259b30SLisandro Dalcin   b->icol            = NULL;
1791a23d5eceSKris Buschelman   b->reallocs        = 0;
1792f4259b30SLisandro Dalcin   b->saved_values    = NULL;
17930def2e27SBarry Smith   b->inode.limit     = 5;
17940def2e27SBarry Smith   b->inode.max_limit = 5;
1795a23d5eceSKris Buschelman 
1796a23d5eceSKris Buschelman   b->roworiented        = PETSC_TRUE;
1797a23d5eceSKris Buschelman   b->nonew              = 0;
1798f4259b30SLisandro Dalcin   b->diag               = NULL;
1799f4259b30SLisandro Dalcin   b->solve_work         = NULL;
1800f4259b30SLisandro Dalcin   b->mult_work          = NULL;
1801f4259b30SLisandro Dalcin   B->spptr              = NULL;
1802f2cbd3d5SJed Brown   B->info.nz_unneeded   = (PetscReal)b->maxnz * b->bs2;
1803a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
1804a23d5eceSKris Buschelman 
1805f4259b30SLisandro Dalcin   b->inew    = NULL;
1806f4259b30SLisandro Dalcin   b->jnew    = NULL;
1807f4259b30SLisandro Dalcin   b->anew    = NULL;
1808f4259b30SLisandro Dalcin   b->a2anew  = NULL;
1809a23d5eceSKris Buschelman   b->permute = PETSC_FALSE;
1810a23d5eceSKris Buschelman 
181171dad5bbSBarry Smith   b->ignore_ltriangular = PETSC_TRUE;
181226fbe8dcSKarl Rupp 
18139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_ignore_lower_triangular", &b->ignore_ltriangular, NULL));
1814941593c8SHong Zhang 
1815f5edf698SHong Zhang   b->getrow_utriangular = PETSC_FALSE;
181626fbe8dcSKarl Rupp 
18179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_getrow_uppertriangular", &b->getrow_utriangular, NULL));
1818f5edf698SHong Zhang 
18199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJGetArray_C", MatSeqSBAIJGetArray_SeqSBAIJ));
18209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJRestoreArray_C", MatSeqSBAIJRestoreArray_SeqSBAIJ));
18219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqSBAIJ));
18229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqSBAIJ));
18239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetColumnIndices_C", MatSeqSBAIJSetColumnIndices_SeqSBAIJ));
18249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqaij_C", MatConvert_SeqSBAIJ_SeqAIJ));
18259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqbaij_C", MatConvert_SeqSBAIJ_SeqBAIJ));
18269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocation_C", MatSeqSBAIJSetPreallocation_SeqSBAIJ));
18279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocationCSR_C", MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ));
18286214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
18299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_elemental_C", MatConvert_SeqSBAIJ_Elemental));
18306214f412SHong Zhang #endif
1831d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE))
18329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_scalapack_C", MatConvert_SBAIJ_ScaLAPACK));
1833d24d4204SJose E. Roman #endif
183423ce1328SBarry Smith 
1835b94d7dedSBarry Smith   B->symmetry_eternal            = PETSC_TRUE;
1836b94d7dedSBarry Smith   B->structural_symmetry_eternal = PETSC_TRUE;
1837b94d7dedSBarry Smith   B->symmetric                   = PETSC_BOOL3_TRUE;
1838b94d7dedSBarry Smith   B->structurally_symmetric      = PETSC_BOOL3_TRUE;
1839eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1840b94d7dedSBarry Smith   B->hermitian = PETSC_BOOL3_FALSE;
1841eb1ec7c1SStefano Zampini #else
1842b94d7dedSBarry Smith   B->hermitian = PETSC_BOOL3_TRUE;
1843eb1ec7c1SStefano Zampini #endif
184413647f61SHong Zhang 
18459566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQSBAIJ));
18460def2e27SBarry Smith 
1847d0609cedSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)B), ((PetscObject)B)->prefix, "Options for SEQSBAIJ matrix", "Mat");
18489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_no_unroll", "Do not optimize for inodes (slower)", NULL, no_unroll, &no_unroll, NULL));
184948a46eb9SPierre Jolivet   if (no_unroll) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_unroll\n"));
18509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_no_inode", "Do not optimize for inodes (slower)", NULL, no_inode, &no_inode, NULL));
18519566063dSJacob Faibussowitsch   if (no_inode) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_inode\n"));
1852e87b5d96SPierre Jolivet   PetscCall(PetscOptionsInt("-mat_inode_limit", "Do not use inodes larger than this value", NULL, b->inode.limit, &b->inode.limit, NULL));
1853d0609cedSBarry Smith   PetscOptionsEnd();
1854ace3abfcSBarry Smith   b->inode.use = (PetscBool)(!(no_unroll || no_inode));
18550def2e27SBarry Smith   if (b->inode.limit > b->inode.max_limit) b->inode.limit = b->inode.max_limit;
18563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1857a23d5eceSKris Buschelman }
1858a23d5eceSKris Buschelman 
18595d83a8b1SBarry Smith /*@
1860a23d5eceSKris Buschelman   MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block
186111a5261eSBarry Smith   compressed row) `MATSEQSBAIJ` format.  For good matrix assembly performance the
186220f4b53cSBarry Smith   user should preallocate the matrix storage by setting the parameter `nz`
186320f4b53cSBarry Smith   (or the array `nnz`).
1864a23d5eceSKris Buschelman 
1865c3339decSBarry Smith   Collective
1866a23d5eceSKris Buschelman 
1867a23d5eceSKris Buschelman   Input Parameters:
18681c4f3114SJed Brown + B   - the symmetric matrix
186911a5261eSBarry 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
187011a5261eSBarry Smith         blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with `MatCreateVecs()`
1871a23d5eceSKris Buschelman . nz  - number of block nonzeros per block row (same for all rows)
1872a23d5eceSKris Buschelman - nnz - array containing the number of block nonzeros in the upper triangular plus
18732ef1f0ffSBarry Smith         diagonal portion of each block (possibly different for each block row) or `NULL`
1874a23d5eceSKris Buschelman 
1875a23d5eceSKris Buschelman   Options Database Keys:
1876d8a51d2aSBarry Smith + -mat_no_unroll  - uses code that does not unroll the loops in the block calculations (much slower)
1877a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use (only works if a negative bs is passed in
1878a23d5eceSKris Buschelman 
1879a23d5eceSKris Buschelman   Level: intermediate
1880a23d5eceSKris Buschelman 
1881a23d5eceSKris Buschelman   Notes:
188220f4b53cSBarry Smith   Specify the preallocated storage with either `nz` or `nnz` (not both).
18832ef1f0ffSBarry Smith   Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory
1884651615e1SBarry Smith   allocation.  See [Sparse Matrices](sec_matsparse) for details.
1885a23d5eceSKris Buschelman 
188611a5261eSBarry Smith   You can call `MatGetInfo()` to get information on how effective the preallocation was;
1887aa95bbe8SBarry Smith   for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
18882ef1f0ffSBarry Smith   You can also run with the option `-info` and look for messages with the string
1889aa95bbe8SBarry Smith   malloc in them to see if additional memory allocation was needed.
1890aa95bbe8SBarry Smith 
18912ef1f0ffSBarry Smith   If the `nnz` parameter is given then the `nz` parameter is ignored
189249a6f317SBarry Smith 
18931cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()`
1894a23d5eceSKris Buschelman @*/
1895d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetPreallocation(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[])
1896d71ae5a4SJacob Faibussowitsch {
1897a23d5eceSKris Buschelman   PetscFunctionBegin;
18986ba663aaSJed Brown   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
18996ba663aaSJed Brown   PetscValidType(B, 1);
19006ba663aaSJed Brown   PetscValidLogicalCollectiveInt(B, bs, 2);
1901cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqSBAIJSetPreallocation_C", (Mat, PetscInt, PetscInt, const PetscInt[]), (B, bs, nz, nnz));
19023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1903a23d5eceSKris Buschelman }
190449b5e25fSSatish Balay 
190538f409ebSLisandro Dalcin /*@C
190611a5261eSBarry Smith   MatSeqSBAIJSetPreallocationCSR - Creates a sparse parallel matrix in `MATSEQSBAIJ` format using the given nonzero structure and (optional) numerical values
190738f409ebSLisandro Dalcin 
190838f409ebSLisandro Dalcin   Input Parameters:
19091c4f3114SJed Brown + B  - the matrix
1910eab78319SHong Zhang . bs - size of block, the blocks are ALWAYS square.
1911d8a51d2aSBarry Smith . i  - the indices into `j` for the start of each local row (indices start with zero)
1912d8a51d2aSBarry Smith . j  - the column indices for each local row (indices start with zero) these must be sorted for each row
1913d8a51d2aSBarry Smith - v  - optional values in the matrix, use `NULL` if not provided
191438f409ebSLisandro Dalcin 
1915664954b6SBarry Smith   Level: advanced
191638f409ebSLisandro Dalcin 
191738f409ebSLisandro Dalcin   Notes:
1918d8a51d2aSBarry Smith   The `i`,`j`,`v` values are COPIED with this routine; to avoid the copy use `MatCreateSeqSBAIJWithArrays()`
1919d8a51d2aSBarry Smith 
192011a5261eSBarry Smith   The order of the entries in values is specified by the `MatOption` `MAT_ROW_ORIENTED`.  For example, C programs
192111a5261eSBarry 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
192238f409ebSLisandro Dalcin   over rows within a block and the last index is over columns within a block row.  Fortran programs will likely set
192311a5261eSBarry 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
192438f409ebSLisandro Dalcin   block column and the second index is over columns within a block.
192538f409ebSLisandro Dalcin 
1926d8a51d2aSBarry Smith   Any entries provided that lie below the diagonal are ignored
19270cd7f59aSBarry Smith 
19280cd7f59aSBarry Smith   Though this routine has Preallocation() in the name it also sets the exact nonzero locations of the matrix entries
19290cd7f59aSBarry Smith   and usually the numerical values as well
1930664954b6SBarry Smith 
1931fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqSBAIJ()`, `MatSetValuesBlocked()`, `MatSeqSBAIJSetPreallocation()`
193238f409ebSLisandro Dalcin @*/
1933d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetPreallocationCSR(Mat B, PetscInt bs, const PetscInt i[], const PetscInt j[], const PetscScalar v[])
1934d71ae5a4SJacob Faibussowitsch {
193538f409ebSLisandro Dalcin   PetscFunctionBegin;
193638f409ebSLisandro Dalcin   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
193738f409ebSLisandro Dalcin   PetscValidType(B, 1);
193838f409ebSLisandro Dalcin   PetscValidLogicalCollectiveInt(B, bs, 2);
1939cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqSBAIJSetPreallocationCSR_C", (Mat, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, bs, i, j, v));
19403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
194138f409ebSLisandro Dalcin }
194238f409ebSLisandro Dalcin 
19435d83a8b1SBarry Smith /*@
19442ef1f0ffSBarry Smith   MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in (block
194511a5261eSBarry Smith   compressed row) `MATSEQSBAIJ` format.  For good matrix assembly performance the
19462ef1f0ffSBarry Smith   user should preallocate the matrix storage by setting the parameter `nz`
19472ef1f0ffSBarry Smith   (or the array `nnz`).
194849b5e25fSSatish Balay 
1949d083f849SBarry Smith   Collective
1950c464158bSHong Zhang 
1951c464158bSHong Zhang   Input Parameters:
195211a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
195311a5261eSBarry 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
1954bb7ae925SBarry Smith           blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with MatCreateVecs()
195520f4b53cSBarry Smith . m    - number of rows
195620f4b53cSBarry Smith . n    - number of columns
1957c464158bSHong Zhang . nz   - number of block nonzeros per block row (same for all rows)
1958744e8345SSatish Balay - nnz  - array containing the number of block nonzeros in the upper triangular plus
19592ef1f0ffSBarry Smith          diagonal portion of each block (possibly different for each block row) or `NULL`
1960c464158bSHong Zhang 
1961c464158bSHong Zhang   Output Parameter:
1962c464158bSHong Zhang . A - the symmetric matrix
1963c464158bSHong Zhang 
1964c464158bSHong Zhang   Options Database Keys:
1965d8a51d2aSBarry Smith + -mat_no_unroll  - uses code that does not unroll the loops in the block calculations (much slower)
1966a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use
1967c464158bSHong Zhang 
1968c464158bSHong Zhang   Level: intermediate
1969c464158bSHong Zhang 
19702ef1f0ffSBarry Smith   Notes:
197177433607SBarry Smith   It is recommended that one use `MatCreateFromOptions()` or the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`,
1972f6f02116SRichard Tran Mills   MatXXXXSetPreallocation() paradigm instead of this routine directly.
197311a5261eSBarry Smith   [MatXXXXSetPreallocation() is, for example, `MatSeqAIJSetPreallocation()`]
1974175b88e8SBarry Smith 
19756d6d819aSHong Zhang   The number of rows and columns must be divisible by blocksize.
19766d6d819aSHong Zhang   This matrix type does not support complex Hermitian operation.
1977c464158bSHong Zhang 
19782ef1f0ffSBarry Smith   Specify the preallocated storage with either `nz` or `nnz` (not both).
19792ef1f0ffSBarry Smith   Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory
1980651615e1SBarry Smith   allocation.  See [Sparse Matrices](sec_matsparse) for details.
1981c464158bSHong Zhang 
19822ef1f0ffSBarry Smith   If the `nnz` parameter is given then the `nz` parameter is ignored
198349a6f317SBarry Smith 
19841cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()`
1985c464158bSHong Zhang @*/
1986d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqSBAIJ(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A)
1987d71ae5a4SJacob Faibussowitsch {
1988c464158bSHong Zhang   PetscFunctionBegin;
19899566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
19909566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
19919566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQSBAIJ));
19929566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*A, bs, nz, (PetscInt *)nnz));
19933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
199449b5e25fSSatish Balay }
199549b5e25fSSatish Balay 
1996d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B)
1997d71ae5a4SJacob Faibussowitsch {
199849b5e25fSSatish Balay   Mat           C;
199949b5e25fSSatish Balay   Mat_SeqSBAIJ *c, *a  = (Mat_SeqSBAIJ *)A->data;
2000b40805acSSatish Balay   PetscInt      i, mbs = a->mbs, nz = a->nz, bs2 = a->bs2;
200149b5e25fSSatish Balay 
200249b5e25fSSatish Balay   PetscFunctionBegin;
200331fe6a7dSBarry Smith   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix");
200408401ef6SPierre Jolivet   PetscCheck(a->i[mbs] == nz, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupt matrix");
200549b5e25fSSatish Balay 
2006f4259b30SLisandro Dalcin   *B = NULL;
20079566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
20089566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, A->rmap->N, A->cmap->n, A->rmap->N, A->cmap->n));
20099566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(C, A, A));
20109566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATSEQSBAIJ));
2011692f9cbeSHong Zhang   c = (Mat_SeqSBAIJ *)C->data;
2012692f9cbeSHong Zhang 
2013273d9f13SBarry Smith   C->preallocated       = PETSC_TRUE;
2014d5f3da31SBarry Smith   C->factortype         = A->factortype;
2015f4259b30SLisandro Dalcin   c->row                = NULL;
2016f4259b30SLisandro Dalcin   c->icol               = NULL;
2017f4259b30SLisandro Dalcin   c->saved_values       = NULL;
2018a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
201949b5e25fSSatish Balay   C->assembled          = PETSC_TRUE;
202049b5e25fSSatish Balay 
20219566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->rmap, &C->rmap));
20229566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap, &C->cmap));
202349b5e25fSSatish Balay   c->bs2 = a->bs2;
202449b5e25fSSatish Balay   c->mbs = a->mbs;
202549b5e25fSSatish Balay   c->nbs = a->nbs;
202649b5e25fSSatish Balay 
2027c760cd28SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2028c760cd28SBarry Smith     c->imax           = a->imax;
2029c760cd28SBarry Smith     c->ilen           = a->ilen;
2030c760cd28SBarry Smith     c->free_imax_ilen = PETSC_FALSE;
2031c760cd28SBarry Smith   } else {
203257508eceSPierre Jolivet     PetscCall(PetscMalloc2(mbs + 1, &c->imax, mbs + 1, &c->ilen));
203349b5e25fSSatish Balay     for (i = 0; i < mbs; i++) {
203449b5e25fSSatish Balay       c->imax[i] = a->imax[i];
203549b5e25fSSatish Balay       c->ilen[i] = a->ilen[i];
203649b5e25fSSatish Balay     }
2037c760cd28SBarry Smith     c->free_imax_ilen = PETSC_TRUE;
2038c760cd28SBarry Smith   }
203949b5e25fSSatish Balay 
204049b5e25fSSatish Balay   /* allocate the matrix space */
20419f0612e4SBarry Smith   PetscCall(PetscShmgetAllocateArray(bs2 * nz, sizeof(PetscScalar), (void **)&c->a));
20429f0612e4SBarry Smith   c->free_a = PETSC_TRUE;
20434da8f245SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
20449f0612e4SBarry Smith     PetscCall(PetscArrayzero(c->a, bs2 * nz));
204544e1c64aSLisandro Dalcin     c->i       = a->i;
204644e1c64aSLisandro Dalcin     c->j       = a->j;
20474da8f245SBarry Smith     c->free_ij = PETSC_FALSE;
20484da8f245SBarry Smith     c->parent  = A;
20499566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)A));
20509566063dSJacob Faibussowitsch     PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
20519566063dSJacob Faibussowitsch     PetscCall(MatSetOption(C, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
20524da8f245SBarry Smith   } else {
20539f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&c->j));
20549f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(mbs + 1, sizeof(PetscInt), (void **)&c->i));
20559566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(c->i, a->i, mbs + 1));
20564da8f245SBarry Smith     c->free_ij = PETSC_TRUE;
20574da8f245SBarry Smith   }
205849b5e25fSSatish Balay   if (mbs > 0) {
205948a46eb9SPierre Jolivet     if (cpvalues != MAT_SHARE_NONZERO_PATTERN) PetscCall(PetscArraycpy(c->j, a->j, nz));
206049b5e25fSSatish Balay     if (cpvalues == MAT_COPY_VALUES) {
20619566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->a, a->a, bs2 * nz));
206249b5e25fSSatish Balay     } else {
20639566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(c->a, bs2 * nz));
206449b5e25fSSatish Balay     }
2065a1c3900fSBarry Smith     if (a->jshort) {
206644e1c64aSLisandro Dalcin       /* cannot share jshort, it is reallocated in MatAssemblyEnd_SeqSBAIJ() */
206744e1c64aSLisandro Dalcin       /* if the parent matrix is reassembled, this child matrix will never notice */
20689566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz, &c->jshort));
20699566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->jshort, a->jshort, nz));
207026fbe8dcSKarl Rupp 
20714da8f245SBarry Smith       c->free_jshort = PETSC_TRUE;
20724da8f245SBarry Smith     }
2073a1c3900fSBarry Smith   }
207449b5e25fSSatish Balay 
207549b5e25fSSatish Balay   c->roworiented = a->roworiented;
207649b5e25fSSatish Balay   c->nonew       = a->nonew;
20776c6c5352SBarry Smith   c->nz          = a->nz;
2078f2cbd3d5SJed Brown   c->maxnz       = a->nz; /* Since we allocate exactly the right amount */
2079f4259b30SLisandro Dalcin   c->solve_work  = NULL;
2080f4259b30SLisandro Dalcin   c->mult_work   = NULL;
208126fbe8dcSKarl Rupp 
208249b5e25fSSatish Balay   *B = C;
20839566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist));
20843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
208549b5e25fSSatish Balay }
208649b5e25fSSatish Balay 
2087618cc2edSLisandro Dalcin /* Used for both SeqBAIJ and SeqSBAIJ matrices */
2088618cc2edSLisandro Dalcin #define MatLoad_SeqSBAIJ_Binary MatLoad_SeqBAIJ_Binary
2089618cc2edSLisandro Dalcin 
2090d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_SeqSBAIJ(Mat mat, PetscViewer viewer)
2091d71ae5a4SJacob Faibussowitsch {
20927f489da9SVaclav Hapla   PetscBool isbinary;
20932f480046SShri Abhyankar 
20942f480046SShri Abhyankar   PetscFunctionBegin;
20959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
209628b400f6SJacob 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);
20979566063dSJacob Faibussowitsch   PetscCall(MatLoad_SeqSBAIJ_Binary(mat, viewer));
20983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20992f480046SShri Abhyankar }
21002f480046SShri Abhyankar 
2101c75a6043SHong Zhang /*@
210211a5261eSBarry Smith   MatCreateSeqSBAIJWithArrays - Creates an sequential `MATSEQSBAIJ` matrix using matrix elements
2103c75a6043SHong Zhang   (upper triangular entries in CSR format) provided by the user.
2104c75a6043SHong Zhang 
2105d083f849SBarry Smith   Collective
2106c75a6043SHong Zhang 
2107c75a6043SHong Zhang   Input Parameters:
2108c75a6043SHong Zhang + comm - must be an MPI communicator of size 1
2109c75a6043SHong Zhang . bs   - size of block
2110c75a6043SHong Zhang . m    - number of rows
2111c75a6043SHong Zhang . n    - number of columns
2112483a2f95SBarry 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
2113c75a6043SHong Zhang . j    - column indices
2114c75a6043SHong Zhang - a    - matrix values
2115c75a6043SHong Zhang 
2116c75a6043SHong Zhang   Output Parameter:
2117c75a6043SHong Zhang . mat - the matrix
2118c75a6043SHong Zhang 
2119dfb205c3SBarry Smith   Level: advanced
2120c75a6043SHong Zhang 
2121c75a6043SHong Zhang   Notes:
21222ef1f0ffSBarry Smith   The `i`, `j`, and `a` arrays are not copied by this routine, the user must free these arrays
2123c75a6043SHong Zhang   once the matrix is destroyed
2124c75a6043SHong Zhang 
2125c75a6043SHong Zhang   You cannot set new nonzero locations into this matrix, that will generate an error.
2126c75a6043SHong Zhang 
21272ef1f0ffSBarry Smith   The `i` and `j` indices are 0 based
2128c75a6043SHong Zhang 
21292ef1f0ffSBarry Smith   When block size is greater than 1 the matrix values must be stored using the `MATSBAIJ` storage format. For block size of 1
2130dfb205c3SBarry Smith   it is the regular CSR format excluding the lower triangular elements.
2131dfb205c3SBarry Smith 
21321cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSBAIJ()`, `MatCreateSeqSBAIJ()`
2133c75a6043SHong Zhang @*/
2134d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqSBAIJWithArrays(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat)
2135d71ae5a4SJacob Faibussowitsch {
2136c75a6043SHong Zhang   PetscInt      ii;
2137c75a6043SHong Zhang   Mat_SeqSBAIJ *sbaij;
2138c75a6043SHong Zhang 
2139c75a6043SHong Zhang   PetscFunctionBegin;
214008401ef6SPierre Jolivet   PetscCheck(bs == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "block size %" PetscInt_FMT " > 1 is not supported yet", bs);
2141aed4548fSBarry Smith   PetscCheck(m == 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0");
2142c75a6043SHong Zhang 
21439566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, mat));
21449566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mat, m, n, m, n));
21459566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mat, MATSEQSBAIJ));
21469566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*mat, bs, MAT_SKIP_ALLOCATION, NULL));
2147c75a6043SHong Zhang   sbaij = (Mat_SeqSBAIJ *)(*mat)->data;
21489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(m, &sbaij->imax, m, &sbaij->ilen));
2149c75a6043SHong Zhang 
2150c75a6043SHong Zhang   sbaij->i = i;
2151c75a6043SHong Zhang   sbaij->j = j;
2152c75a6043SHong Zhang   sbaij->a = a;
215326fbe8dcSKarl Rupp 
2154c75a6043SHong Zhang   sbaij->nonew          = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2155e6b907acSBarry Smith   sbaij->free_a         = PETSC_FALSE;
2156e6b907acSBarry Smith   sbaij->free_ij        = PETSC_FALSE;
2157ddf7884eSMatthew Knepley   sbaij->free_imax_ilen = PETSC_TRUE;
2158c75a6043SHong Zhang 
2159c75a6043SHong Zhang   for (ii = 0; ii < m; ii++) {
2160c75a6043SHong Zhang     sbaij->ilen[ii] = sbaij->imax[ii] = i[ii + 1] - i[ii];
21616bdcaf15SBarry 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]);
2162c75a6043SHong Zhang   }
216376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2164c75a6043SHong Zhang     for (ii = 0; ii < sbaij->i[m]; ii++) {
21656bdcaf15SBarry 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]);
21666bdcaf15SBarry 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]);
2167c75a6043SHong Zhang     }
216876bd3646SJed Brown   }
2169c75a6043SHong Zhang 
21709566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY));
21719566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY));
21723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2173c75a6043SHong Zhang }
2174d06b337dSHong Zhang 
2175d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
2176d71ae5a4SJacob Faibussowitsch {
217759f5e6ceSHong Zhang   PetscFunctionBegin;
21789566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPISBAIJ(comm, inmat, n, scall, outmat));
21793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
218059f5e6ceSHong Zhang }
2181