xref: /petsc/src/mat/impls/sbaij/seq/sbaij.c (revision ae1ee55146a7ad071171b861759b85940c7e5c67)
149b5e25fSSatish Balay /*
2a1373b80SHong Zhang     Defines the basic matrix operations for the SBAIJ (compressed row)
349b5e25fSSatish Balay   matrix storage format.
449b5e25fSSatish Balay */
5c6db04a5SJed Brown #include <../src/mat/impls/baij/seq/baij.h> /*I "petscmat.h" I*/
6c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/sbaij.h>
7c6db04a5SJed Brown #include <petscblaslapack.h>
849b5e25fSSatish Balay 
9c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/relax.h>
1070dcbbb9SBarry Smith #define USESHORT
11c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/relax.h>
1270dcbbb9SBarry Smith 
1326cec326SBarry Smith /* defines MatSetValues_Seq_Hash(), MatAssemblyEnd_Seq_Hash(), MatSetUp_Seq_Hash() */
1426cec326SBarry Smith #define TYPE SBAIJ
1526cec326SBarry Smith #define TYPE_SBAIJ
1626cec326SBarry Smith #define TYPE_BS
1726cec326SBarry Smith #include "../src/mat/impls/aij/seq/seqhashmatsetvalues.h"
1826cec326SBarry Smith #undef TYPE_BS
1926cec326SBarry Smith #define TYPE_BS _BS
2026cec326SBarry Smith #define TYPE_BS_ON
2126cec326SBarry Smith #include "../src/mat/impls/aij/seq/seqhashmatsetvalues.h"
2226cec326SBarry Smith #undef TYPE_BS
2326cec326SBarry Smith #undef TYPE_SBAIJ
2426cec326SBarry Smith #include "../src/mat/impls/aij/seq/seqhashmat.h"
2526cec326SBarry Smith #undef TYPE
2626cec326SBarry Smith #undef TYPE_BS_ON
2726cec326SBarry Smith 
286214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
29cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_Elemental(Mat, MatType, MatReuse, Mat *);
306214f412SHong Zhang #endif
31d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE))
32d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_SBAIJ_ScaLAPACK(Mat, MatType, MatReuse, Mat *);
33d24d4204SJose E. Roman #endif
3428d58a37SPierre Jolivet PETSC_INTERN PetscErrorCode MatConvert_MPISBAIJ_Basic(Mat, MatType, MatReuse, Mat *);
35b5b17502SBarry Smith 
36421480d9SBarry Smith MatGetDiagonalMarkers(SeqSBAIJ, A->rmap->bs)
3749b5e25fSSatish Balay 
MatGetRowIJ_SeqSBAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool blockcompressed,PetscInt * nn,const PetscInt * inia[],const PetscInt * inja[],PetscBool * done)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 
MatRestoreRowIJ_SeqSBAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool blockcompressed,PetscInt * nn,const PetscInt * ia[],const PetscInt * ja[],PetscBool * done)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 
MatDestroy_SeqSBAIJ(Mat A)124d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_SeqSBAIJ(Mat A)
125d71ae5a4SJacob Faibussowitsch {
12649b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
12749b5e25fSSatish Balay 
12849b5e25fSSatish Balay   PetscFunctionBegin;
129b4e2f619SBarry Smith   if (A->hash_active) {
130b4e2f619SBarry Smith     PetscInt bs;
131e3c72094SPierre Jolivet     A->ops[0] = a->cops;
132b4e2f619SBarry Smith     PetscCall(PetscHMapIJVDestroy(&a->ht));
133b4e2f619SBarry Smith     PetscCall(MatGetBlockSize(A, &bs));
134b4e2f619SBarry Smith     if (bs > 1) PetscCall(PetscHSetIJDestroy(&a->bht));
135b4e2f619SBarry Smith     PetscCall(PetscFree(a->dnz));
136b4e2f619SBarry Smith     PetscCall(PetscFree(a->bdnz));
137b4e2f619SBarry Smith     A->hash_active = PETSC_FALSE;
138b4e2f619SBarry Smith   }
1393ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)A, "Rows=%" PetscInt_FMT ", NZ=%" PetscInt_FMT, A->rmap->N, a->nz));
1409566063dSJacob Faibussowitsch   PetscCall(MatSeqXAIJFreeAIJ(A, &a->a, &a->j, &a->i));
141421480d9SBarry Smith   PetscCall(PetscFree(a->diag));
1429566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
1439566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
1449566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->icol));
1459566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->idiag));
1464d12350bSJunchao Zhang   PetscCall(PetscFree(a->inode.size_csr));
1479566063dSJacob Faibussowitsch   if (a->free_imax_ilen) PetscCall(PetscFree2(a->imax, a->ilen));
1489566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->solve_work));
1499566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->sor_work));
1509566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->solves_work));
1519566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->mult_work));
1529566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->saved_values));
1539566063dSJacob Faibussowitsch   if (a->free_jshort) PetscCall(PetscFree(a->jshort));
1549566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->inew));
1559566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&a->parent));
1569566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
157901853e0SKris Buschelman 
1589566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL));
1592e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJGetArray_C", NULL));
1602e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJRestoreArray_C", NULL));
1619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatStoreValues_C", NULL));
1629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatRetrieveValues_C", NULL));
1639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetColumnIndices_C", NULL));
1649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqaij_C", NULL));
1659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqbaij_C", NULL));
1669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocation_C", NULL));
1679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocationCSR_C", NULL));
1686214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_elemental_C", NULL));
1706214f412SHong Zhang #endif
171d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE))
1729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_scalapack_C", NULL));
173d24d4204SJose E. Roman #endif
1742e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL));
1753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17649b5e25fSSatish Balay }
17749b5e25fSSatish Balay 
MatSetOption_SeqSBAIJ(Mat A,MatOption op,PetscBool flg)178ba38deedSJacob Faibussowitsch static PetscErrorCode MatSetOption_SeqSBAIJ(Mat A, MatOption op, PetscBool flg)
179d71ae5a4SJacob Faibussowitsch {
180045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
18149b5e25fSSatish Balay 
18249b5e25fSSatish Balay   PetscFunctionBegin;
1834d9d31abSKris Buschelman   switch (op) {
184d71ae5a4SJacob Faibussowitsch   case MAT_ROW_ORIENTED:
185d71ae5a4SJacob Faibussowitsch     a->roworiented = flg;
186d71ae5a4SJacob Faibussowitsch     break;
187d71ae5a4SJacob Faibussowitsch   case MAT_KEEP_NONZERO_PATTERN:
188d71ae5a4SJacob Faibussowitsch     a->keepnonzeropattern = flg;
189d71ae5a4SJacob Faibussowitsch     break;
190d71ae5a4SJacob Faibussowitsch   case MAT_NEW_NONZERO_LOCATIONS:
191d71ae5a4SJacob Faibussowitsch     a->nonew = (flg ? 0 : 1);
192d71ae5a4SJacob Faibussowitsch     break;
193d71ae5a4SJacob Faibussowitsch   case MAT_NEW_NONZERO_LOCATION_ERR:
194d71ae5a4SJacob Faibussowitsch     a->nonew = (flg ? -1 : 0);
195d71ae5a4SJacob Faibussowitsch     break;
196d71ae5a4SJacob Faibussowitsch   case MAT_NEW_NONZERO_ALLOCATION_ERR:
197d71ae5a4SJacob Faibussowitsch     a->nonew = (flg ? -2 : 0);
198d71ae5a4SJacob Faibussowitsch     break;
199d71ae5a4SJacob Faibussowitsch   case MAT_UNUSED_NONZERO_LOCATION_ERR:
200d71ae5a4SJacob Faibussowitsch     a->nounused = (flg ? -1 : 0);
201d71ae5a4SJacob Faibussowitsch     break;
2029a4540c5SBarry Smith   case MAT_HERMITIAN:
203*fc2fb351SPierre Jolivet     if (PetscDefined(USE_COMPLEX) && flg) { /* disable transpose ops */
204*fc2fb351SPierre Jolivet       PetscInt bs;
205*fc2fb351SPierre Jolivet 
206*fc2fb351SPierre Jolivet       PetscCall(MatGetBlockSize(A, &bs));
20708401ef6SPierre Jolivet       PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for Hermitian with block size greater than 1");
208eb1ec7c1SStefano Zampini       A->ops->multtranspose    = NULL;
209eb1ec7c1SStefano Zampini       A->ops->multtransposeadd = NULL;
210eb1ec7c1SStefano Zampini     }
211eeffb40dSHong Zhang     break;
21277e54ba9SKris Buschelman   case MAT_SYMMETRIC:
213eb1ec7c1SStefano Zampini   case MAT_SPD:
214*fc2fb351SPierre Jolivet     if (PetscDefined(USE_COMPLEX) && flg) { /* An Hermitian and symmetric matrix has zero imaginary part (restore back transpose ops) */
215eb1ec7c1SStefano Zampini       A->ops->multtranspose    = A->ops->mult;
216eb1ec7c1SStefano Zampini       A->ops->multtransposeadd = A->ops->multadd;
217eb1ec7c1SStefano Zampini     }
218eb1ec7c1SStefano Zampini     break;
219d71ae5a4SJacob Faibussowitsch   case MAT_IGNORE_LOWER_TRIANGULAR:
220d71ae5a4SJacob Faibussowitsch     a->ignore_ltriangular = flg;
221d71ae5a4SJacob Faibussowitsch     break;
222d71ae5a4SJacob Faibussowitsch   case MAT_ERROR_LOWER_TRIANGULAR:
223d71ae5a4SJacob Faibussowitsch     a->ignore_ltriangular = flg;
224d71ae5a4SJacob Faibussowitsch     break;
225d71ae5a4SJacob Faibussowitsch   case MAT_GETROW_UPPERTRIANGULAR:
226d71ae5a4SJacob Faibussowitsch     a->getrow_utriangular = flg;
227d71ae5a4SJacob Faibussowitsch     break;
228d71ae5a4SJacob Faibussowitsch   default:
229888c827cSStefano Zampini     break;
23049b5e25fSSatish Balay   }
2313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23249b5e25fSSatish Balay }
23349b5e25fSSatish Balay 
MatGetRow_SeqSBAIJ(Mat A,PetscInt row,PetscInt * nz,PetscInt ** idx,PetscScalar ** v)234d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
235d71ae5a4SJacob Faibussowitsch {
23649b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
23749b5e25fSSatish Balay 
23849b5e25fSSatish Balay   PetscFunctionBegin;
23908401ef6SPierre 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()");
24052768537SHong Zhang 
241f5edf698SHong Zhang   /* Get the upper triangular part of the row */
2429566063dSJacob Faibussowitsch   PetscCall(MatGetRow_SeqBAIJ_private(A, row, nz, idx, v, a->i, a->j, a->a));
2433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24449b5e25fSSatish Balay }
24549b5e25fSSatish Balay 
MatRestoreRow_SeqSBAIJ(Mat A,PetscInt row,PetscInt * nz,PetscInt ** idx,PetscScalar ** v)246d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
247d71ae5a4SJacob Faibussowitsch {
24849b5e25fSSatish Balay   PetscFunctionBegin;
2499566063dSJacob Faibussowitsch   if (idx) PetscCall(PetscFree(*idx));
2509566063dSJacob Faibussowitsch   if (v) PetscCall(PetscFree(*v));
2513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25249b5e25fSSatish Balay }
25349b5e25fSSatish Balay 
MatGetRowUpperTriangular_SeqSBAIJ(Mat A)254ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetRowUpperTriangular_SeqSBAIJ(Mat A)
255d71ae5a4SJacob Faibussowitsch {
256f5edf698SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
257f5edf698SHong Zhang 
258f5edf698SHong Zhang   PetscFunctionBegin;
259f5edf698SHong Zhang   a->getrow_utriangular = PETSC_TRUE;
2603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
261f5edf698SHong Zhang }
262a323099bSStefano Zampini 
MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A)263ba38deedSJacob Faibussowitsch static PetscErrorCode MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A)
264d71ae5a4SJacob Faibussowitsch {
265f5edf698SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
266f5edf698SHong Zhang 
267f5edf698SHong Zhang   PetscFunctionBegin;
268f5edf698SHong Zhang   a->getrow_utriangular = PETSC_FALSE;
2693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
270f5edf698SHong Zhang }
271f5edf698SHong Zhang 
MatTranspose_SeqSBAIJ(Mat A,MatReuse reuse,Mat * B)272ba38deedSJacob Faibussowitsch static PetscErrorCode MatTranspose_SeqSBAIJ(Mat A, MatReuse reuse, Mat *B)
273d71ae5a4SJacob Faibussowitsch {
27449b5e25fSSatish Balay   PetscFunctionBegin;
2757fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B));
276cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX) {
2779566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A, MAT_COPY_VALUES, B));
278cf37664fSBarry Smith   } else if (reuse == MAT_REUSE_MATRIX) {
2799566063dSJacob Faibussowitsch     PetscCall(MatCopy(A, *B, SAME_NONZERO_PATTERN));
280fc4dec0aSBarry Smith   }
2813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28249b5e25fSSatish Balay }
28349b5e25fSSatish Balay 
MatView_SeqSBAIJ_ASCII(Mat A,PetscViewer viewer)284ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_ASCII(Mat A, PetscViewer viewer)
285d71ae5a4SJacob Faibussowitsch {
28649b5e25fSSatish Balay   Mat_SeqSBAIJ     *a = (Mat_SeqSBAIJ *)A->data;
287d0f46423SBarry Smith   PetscInt          i, j, bs = A->rmap->bs, k, l, bs2 = a->bs2;
288f3ef73ceSBarry Smith   PetscViewerFormat format;
289421480d9SBarry Smith   const PetscInt   *diag;
290b3a0534dSBarry Smith   const char       *matname;
29149b5e25fSSatish Balay 
29249b5e25fSSatish Balay   PetscFunctionBegin;
2939566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
294456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
295fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_MATLAB) {
296d2507d54SMatthew Knepley     Mat aij;
297ade3a672SBarry Smith 
298d5f3da31SBarry Smith     if (A->factortype && bs > 1) {
2999566063dSJacob 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"));
3003ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
30170d5e725SHong Zhang     }
3029566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &aij));
30323a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname));
30423a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)aij, matname));
30523a3927dSBarry Smith     PetscCall(MatView_SeqAIJ(aij, viewer));
3069566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&aij));
307fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
308b3a0534dSBarry Smith     Mat B;
309b3a0534dSBarry Smith 
310b3a0534dSBarry Smith     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B));
311b3a0534dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname));
312b3a0534dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)B, matname));
313b3a0534dSBarry Smith     PetscCall(MatView_SeqAIJ(B, viewer));
314b3a0534dSBarry Smith     PetscCall(MatDestroy(&B));
315c1490034SHong Zhang   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
3163ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
31749b5e25fSSatish Balay   } else {
3189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
3192c990fa1SHong Zhang     if (A->factortype) { /* for factored matrix */
32008401ef6SPierre Jolivet       PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix is factored with bs>1. Not implemented yet");
321421480d9SBarry Smith       PetscCall(MatGetDiagonalMarkers_SeqSBAIJ(A, &diag, NULL));
322121deb67SSatish Balay       for (i = 0; i < a->mbs; i++) { /* for row block i */
3239566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
3242c990fa1SHong Zhang         /* diagonal entry */
3252c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX)
3262c990fa1SHong Zhang         if (PetscImaginaryPart(a->a[diag[i]]) > 0.0) {
3279566063dSJacob 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]])));
3282c990fa1SHong Zhang         } else if (PetscImaginaryPart(a->a[diag[i]]) < 0.0) {
3299566063dSJacob 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]])));
3302c990fa1SHong Zhang         } else {
3319566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)PetscRealPart(1.0 / a->a[diag[i]])));
3322c990fa1SHong Zhang         }
3332c990fa1SHong Zhang #else
334835f2295SStefano Zampini         PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)(1 / a->a[diag[i]])));
3352c990fa1SHong Zhang #endif
3362c990fa1SHong Zhang         /* off-diagonal entries */
3372c990fa1SHong Zhang         for (k = a->i[i]; k < a->i[i + 1] - 1; k++) {
3382c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX)
339ca0704adSBarry Smith           if (PetscImaginaryPart(a->a[k]) > 0.0) {
3409566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), (double)PetscImaginaryPart(a->a[k])));
341ca0704adSBarry Smith           } else if (PetscImaginaryPart(a->a[k]) < 0.0) {
3429566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), -(double)PetscImaginaryPart(a->a[k])));
3432c990fa1SHong Zhang           } else {
3449566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k], (double)PetscRealPart(a->a[k])));
3452c990fa1SHong Zhang           }
3462c990fa1SHong Zhang #else
3479566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[k], (double)a->a[k]));
3482c990fa1SHong Zhang #endif
3492c990fa1SHong Zhang         }
3509566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
3512c990fa1SHong Zhang       }
3522c990fa1SHong Zhang 
3532c990fa1SHong Zhang     } else {                         /* for non-factored matrix */
3540c74a584SJed Brown       for (i = 0; i < a->mbs; i++) { /* for row block i */
3550c74a584SJed Brown         for (j = 0; j < bs; j++) {   /* for row bs*i + j */
3569566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i * bs + j));
3570c74a584SJed Brown           for (k = a->i[i]; k < a->i[i + 1]; k++) { /* for column block */
3580c74a584SJed Brown             for (l = 0; l < bs; l++) {              /* for column */
35949b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX)
36049b5e25fSSatish Balay               if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) > 0.0) {
3619371c9d4SSatish 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])));
36249b5e25fSSatish Balay               } else if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) < 0.0) {
3639371c9d4SSatish 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])));
36449b5e25fSSatish Balay               } else {
3659566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j])));
36649b5e25fSSatish Balay               }
36749b5e25fSSatish Balay #else
3689566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)a->a[bs2 * k + l * bs + j]));
36949b5e25fSSatish Balay #endif
37049b5e25fSSatish Balay             }
37149b5e25fSSatish Balay           }
3729566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
37349b5e25fSSatish Balay         }
37449b5e25fSSatish Balay       }
3752c990fa1SHong Zhang     }
3769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
37749b5e25fSSatish Balay   }
3789566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
3793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38049b5e25fSSatish Balay }
38149b5e25fSSatish Balay 
3829804daf3SBarry Smith #include <petscdraw.h>
MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw,void * Aa)383d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw, void *Aa)
384d71ae5a4SJacob Faibussowitsch {
38549b5e25fSSatish Balay   Mat           A = (Mat)Aa;
38649b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
3876497c311SBarry Smith   PetscInt      row, i, j, k, l, mbs = a->mbs, bs = A->rmap->bs, bs2 = a->bs2;
38849b5e25fSSatish Balay   PetscReal     xl, yl, xr, yr, x_l, x_r, y_l, y_r;
38949b5e25fSSatish Balay   MatScalar    *aa;
390b0a32e0cSBarry Smith   PetscViewer   viewer;
3916497c311SBarry Smith   int           color;
39249b5e25fSSatish Balay 
39349b5e25fSSatish Balay   PetscFunctionBegin;
3949566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
3959566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
39649b5e25fSSatish Balay 
39749b5e25fSSatish Balay   /* loop over matrix elements drawing boxes */
398383922c3SLisandro Dalcin 
399d0609cedSBarry Smith   PetscDrawCollectiveBegin(draw);
4009566063dSJacob Faibussowitsch   PetscCall(PetscDrawString(draw, .3 * (xl + xr), .3 * (yl + yr), PETSC_DRAW_BLACK, "symmetric"));
401383922c3SLisandro Dalcin   /* Blue for negative, Cyan for zero and  Red for positive */
402b0a32e0cSBarry Smith   color = PETSC_DRAW_BLUE;
40349b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
40449b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4059371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4069371c9d4SSatish Balay       y_r = y_l + 1.0;
4079371c9d4SSatish Balay       x_l = a->j[j] * bs;
4089371c9d4SSatish Balay       x_r = x_l + 1.0;
40949b5e25fSSatish Balay       aa  = a->a + j * bs2;
41049b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
41149b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
41249b5e25fSSatish Balay           if (PetscRealPart(*aa++) >= 0.) continue;
4139566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
41449b5e25fSSatish Balay         }
41549b5e25fSSatish Balay       }
41649b5e25fSSatish Balay     }
41749b5e25fSSatish Balay   }
418b0a32e0cSBarry Smith   color = PETSC_DRAW_CYAN;
41949b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
42049b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4219371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4229371c9d4SSatish Balay       y_r = y_l + 1.0;
4239371c9d4SSatish Balay       x_l = a->j[j] * bs;
4249371c9d4SSatish Balay       x_r = x_l + 1.0;
42549b5e25fSSatish Balay       aa  = a->a + j * bs2;
42649b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
42749b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
42849b5e25fSSatish Balay           if (PetscRealPart(*aa++) != 0.) continue;
4299566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
43049b5e25fSSatish Balay         }
43149b5e25fSSatish Balay       }
43249b5e25fSSatish Balay     }
43349b5e25fSSatish Balay   }
434b0a32e0cSBarry Smith   color = PETSC_DRAW_RED;
43549b5e25fSSatish Balay   for (i = 0, row = 0; i < mbs; i++, row += bs) {
43649b5e25fSSatish Balay     for (j = a->i[i]; j < a->i[i + 1]; j++) {
4379371c9d4SSatish Balay       y_l = A->rmap->N - row - 1.0;
4389371c9d4SSatish Balay       y_r = y_l + 1.0;
4399371c9d4SSatish Balay       x_l = a->j[j] * bs;
4409371c9d4SSatish Balay       x_r = x_l + 1.0;
44149b5e25fSSatish Balay       aa  = a->a + j * bs2;
44249b5e25fSSatish Balay       for (k = 0; k < bs; k++) {
44349b5e25fSSatish Balay         for (l = 0; l < bs; l++) {
44449b5e25fSSatish Balay           if (PetscRealPart(*aa++) <= 0.) continue;
4459566063dSJacob Faibussowitsch           PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color));
44649b5e25fSSatish Balay         }
44749b5e25fSSatish Balay       }
44849b5e25fSSatish Balay     }
44949b5e25fSSatish Balay   }
450d0609cedSBarry Smith   PetscDrawCollectiveEnd(draw);
4513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45249b5e25fSSatish Balay }
45349b5e25fSSatish Balay 
MatView_SeqSBAIJ_Draw(Mat A,PetscViewer viewer)454d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_Draw(Mat A, PetscViewer viewer)
455d71ae5a4SJacob Faibussowitsch {
45649b5e25fSSatish Balay   PetscReal xl, yl, xr, yr, w, h;
457b0a32e0cSBarry Smith   PetscDraw draw;
458ace3abfcSBarry Smith   PetscBool isnull;
45949b5e25fSSatish Balay 
46049b5e25fSSatish Balay   PetscFunctionBegin;
4619566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4629566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
4633ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
46449b5e25fSSatish Balay 
4659371c9d4SSatish Balay   xr = A->rmap->N;
4669371c9d4SSatish Balay   yr = A->rmap->N;
4679371c9d4SSatish Balay   h  = yr / 10.0;
4689371c9d4SSatish Balay   w  = xr / 10.0;
4699371c9d4SSatish Balay   xr += w;
4709371c9d4SSatish Balay   yr += h;
4719371c9d4SSatish Balay   xl = -w;
4729371c9d4SSatish Balay   yl = -h;
4739566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
4749566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
4759566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqSBAIJ_Draw_Zoom, A));
4769566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
4779566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
4783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47949b5e25fSSatish Balay }
48049b5e25fSSatish Balay 
481618cc2edSLisandro Dalcin /* Used for both MPIBAIJ and MPISBAIJ matrices */
482618cc2edSLisandro Dalcin #define MatView_SeqSBAIJ_Binary MatView_SeqBAIJ_Binary
483618cc2edSLisandro Dalcin 
MatView_SeqSBAIJ(Mat A,PetscViewer viewer)484d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqSBAIJ(Mat A, PetscViewer viewer)
485d71ae5a4SJacob Faibussowitsch {
4869f196a02SMartin Diehl   PetscBool isascii, isbinary, isdraw;
48749b5e25fSSatish Balay 
48849b5e25fSSatish Balay   PetscFunctionBegin;
4899f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
4909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
4919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
4929f196a02SMartin Diehl   if (isascii) {
4939566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_ASCII(A, viewer));
494618cc2edSLisandro Dalcin   } else if (isbinary) {
4959566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_Binary(A, viewer));
49649b5e25fSSatish Balay   } else if (isdraw) {
4979566063dSJacob Faibussowitsch     PetscCall(MatView_SeqSBAIJ_Draw(A, viewer));
49849b5e25fSSatish Balay   } else {
499a5e6ed63SBarry Smith     Mat         B;
500ade3a672SBarry Smith     const char *matname;
5019566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B));
50223a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname));
50323a3927dSBarry Smith     if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)B, matname));
5049566063dSJacob Faibussowitsch     PetscCall(MatView(B, viewer));
5059566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
50649b5e25fSSatish Balay   }
5073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50849b5e25fSSatish Balay }
50949b5e25fSSatish Balay 
MatGetValues_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])510d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[])
511d71ae5a4SJacob Faibussowitsch {
512045c9aa0SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
51313f74950SBarry Smith   PetscInt     *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j;
51413f74950SBarry Smith   PetscInt     *ai = a->i, *ailen = a->ilen;
515d0f46423SBarry Smith   PetscInt      brow, bcol, ridx, cidx, bs = A->rmap->bs, bs2 = a->bs2;
51697e567efSBarry Smith   MatScalar    *ap, *aa = a->a;
51749b5e25fSSatish Balay 
51849b5e25fSSatish Balay   PetscFunctionBegin;
51949b5e25fSSatish Balay   for (k = 0; k < m; k++) { /* loop over rows */
5209371c9d4SSatish Balay     row  = im[k];
5219371c9d4SSatish Balay     brow = row / bs;
5229371c9d4SSatish Balay     if (row < 0) {
5239371c9d4SSatish Balay       v += n;
5249371c9d4SSatish Balay       continue;
5259371c9d4SSatish Balay     } /* negative row */
52654c59aa7SJacob 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);
5279371c9d4SSatish Balay     rp   = aj + ai[brow];
5289371c9d4SSatish Balay     ap   = aa + bs2 * ai[brow];
52949b5e25fSSatish Balay     nrow = ailen[brow];
53049b5e25fSSatish Balay     for (l = 0; l < n; l++) { /* loop over columns */
5319371c9d4SSatish Balay       if (in[l] < 0) {
5329371c9d4SSatish Balay         v++;
5339371c9d4SSatish Balay         continue;
5349371c9d4SSatish Balay       } /* negative column */
53554c59aa7SJacob 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);
53649b5e25fSSatish Balay       col  = in[l];
53749b5e25fSSatish Balay       bcol = col / bs;
53849b5e25fSSatish Balay       cidx = col % bs;
53949b5e25fSSatish Balay       ridx = row % bs;
54049b5e25fSSatish Balay       high = nrow;
54149b5e25fSSatish Balay       low  = 0; /* assume unsorted */
54249b5e25fSSatish Balay       while (high - low > 5) {
54349b5e25fSSatish Balay         t = (low + high) / 2;
54449b5e25fSSatish Balay         if (rp[t] > bcol) high = t;
54549b5e25fSSatish Balay         else low = t;
54649b5e25fSSatish Balay       }
54749b5e25fSSatish Balay       for (i = low; i < high; i++) {
54849b5e25fSSatish Balay         if (rp[i] > bcol) break;
54949b5e25fSSatish Balay         if (rp[i] == bcol) {
55049b5e25fSSatish Balay           *v++ = ap[bs2 * i + bs * cidx + ridx];
55149b5e25fSSatish Balay           goto finished;
55249b5e25fSSatish Balay         }
55349b5e25fSSatish Balay       }
55497e567efSBarry Smith       *v++ = 0.0;
55549b5e25fSSatish Balay     finished:;
55649b5e25fSSatish Balay     }
55749b5e25fSSatish Balay   }
5583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55949b5e25fSSatish Balay }
56049b5e25fSSatish Balay 
MatPermute_SeqSBAIJ(Mat A,IS rowp,IS colp,Mat * B)561ba38deedSJacob Faibussowitsch static PetscErrorCode MatPermute_SeqSBAIJ(Mat A, IS rowp, IS colp, Mat *B)
562d71ae5a4SJacob Faibussowitsch {
563dc29a518SPierre Jolivet   Mat       C;
56457069620SPierre Jolivet   PetscBool flg = (PetscBool)(rowp == colp);
565dc29a518SPierre Jolivet 
566dc29a518SPierre Jolivet   PetscFunctionBegin;
5679566063dSJacob Faibussowitsch   PetscCall(MatConvert(A, MATSEQBAIJ, MAT_INITIAL_MATRIX, &C));
5689566063dSJacob Faibussowitsch   PetscCall(MatPermute(C, rowp, colp, B));
5699566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
57057069620SPierre Jolivet   if (!flg) PetscCall(ISEqual(rowp, colp, &flg));
57157069620SPierre Jolivet   if (flg) PetscCall(MatConvert(*B, MATSEQSBAIJ, MAT_INPLACE_MATRIX, B));
5723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
573dc29a518SPierre Jolivet }
57449b5e25fSSatish Balay 
MatSetValuesBlocked_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)575d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesBlocked_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is)
576d71ae5a4SJacob Faibussowitsch {
5770880e062SHong Zhang   Mat_SeqSBAIJ      *a = (Mat_SeqSBAIJ *)A->data;
578e2ee6c50SBarry Smith   PetscInt          *rp, k, low, high, t, ii, jj, row, nrow, i, col, l, rmax, N, lastcol = -1;
57913f74950SBarry Smith   PetscInt          *imax = a->imax, *ai = a->i, *ailen = a->ilen;
580d0f46423SBarry Smith   PetscInt          *aj = a->j, nonew = a->nonew, bs2 = a->bs2, bs = A->rmap->bs, stepval;
581ace3abfcSBarry Smith   PetscBool          roworiented = a->roworiented;
582dd6ea824SBarry Smith   const PetscScalar *value       = v;
583f15d580aSBarry Smith   MatScalar         *ap, *aa = a->a, *bap;
5840880e062SHong Zhang 
58549b5e25fSSatish Balay   PetscFunctionBegin;
58626fbe8dcSKarl Rupp   if (roworiented) stepval = (n - 1) * bs;
58726fbe8dcSKarl Rupp   else stepval = (m - 1) * bs;
5880880e062SHong Zhang   for (k = 0; k < m; k++) { /* loop over added rows */
5890880e062SHong Zhang     row = im[k];
5900880e062SHong Zhang     if (row < 0) continue;
5916bdcaf15SBarry 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);
5920880e062SHong Zhang     rp   = aj + ai[row];
5930880e062SHong Zhang     ap   = aa + bs2 * ai[row];
5940880e062SHong Zhang     rmax = imax[row];
5950880e062SHong Zhang     nrow = ailen[row];
5960880e062SHong Zhang     low  = 0;
597818f2c47SBarry Smith     high = nrow;
5980880e062SHong Zhang     for (l = 0; l < n; l++) { /* loop over added columns */
5990880e062SHong Zhang       if (in[l] < 0) continue;
6000880e062SHong Zhang       col = in[l];
6016bdcaf15SBarry 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);
602b98bf0e1SJed Brown       if (col < row) {
603966bd95aSPierre 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)");
604966bd95aSPierre Jolivet         continue; /* ignore lower triangular block */
605b98bf0e1SJed Brown       }
60626fbe8dcSKarl Rupp       if (roworiented) value = v + k * (stepval + bs) * bs + l * bs;
60726fbe8dcSKarl Rupp       else value = v + l * (stepval + bs) * bs + k * bs;
60826fbe8dcSKarl Rupp 
60926fbe8dcSKarl Rupp       if (col <= lastcol) low = 0;
61026fbe8dcSKarl Rupp       else high = nrow;
61126fbe8dcSKarl Rupp 
612e2ee6c50SBarry Smith       lastcol = col;
6130880e062SHong Zhang       while (high - low > 7) {
6140880e062SHong Zhang         t = (low + high) / 2;
6150880e062SHong Zhang         if (rp[t] > col) high = t;
6160880e062SHong Zhang         else low = t;
6170880e062SHong Zhang       }
6180880e062SHong Zhang       for (i = low; i < high; i++) {
6190880e062SHong Zhang         if (rp[i] > col) break;
6200880e062SHong Zhang         if (rp[i] == col) {
6210880e062SHong Zhang           bap = ap + bs2 * i;
6220880e062SHong Zhang           if (roworiented) {
6230880e062SHong Zhang             if (is == ADD_VALUES) {
6240880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
625ad540459SPierre Jolivet                 for (jj = ii; jj < bs2; jj += bs) bap[jj] += *value++;
6260880e062SHong Zhang               }
6270880e062SHong Zhang             } else {
6280880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
629ad540459SPierre Jolivet                 for (jj = ii; jj < bs2; jj += bs) bap[jj] = *value++;
6300880e062SHong Zhang               }
6310880e062SHong Zhang             }
6320880e062SHong Zhang           } else {
6330880e062SHong Zhang             if (is == ADD_VALUES) {
6340880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
635ad540459SPierre Jolivet                 for (jj = 0; jj < bs; jj++) *bap++ += *value++;
6360880e062SHong Zhang               }
6370880e062SHong Zhang             } else {
6380880e062SHong Zhang               for (ii = 0; ii < bs; ii++, value += stepval) {
639ad540459SPierre Jolivet                 for (jj = 0; jj < bs; jj++) *bap++ = *value++;
6400880e062SHong Zhang               }
6410880e062SHong Zhang             }
6420880e062SHong Zhang           }
6430880e062SHong Zhang           goto noinsert2;
6440880e062SHong Zhang         }
6450880e062SHong Zhang       }
6460880e062SHong Zhang       if (nonew == 1) goto noinsert2;
64708401ef6SPierre 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);
648fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
6499371c9d4SSatish Balay       N = nrow++ - 1;
6509371c9d4SSatish Balay       high++;
6510880e062SHong Zhang       /* shift up all the later entries in this row */
6529566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1));
6539566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1)));
6549566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(ap + bs2 * i, bs2));
6550880e062SHong Zhang       rp[i] = col;
6560880e062SHong Zhang       bap   = ap + bs2 * i;
6570880e062SHong Zhang       if (roworiented) {
6580880e062SHong Zhang         for (ii = 0; ii < bs; ii++, value += stepval) {
659ad540459SPierre Jolivet           for (jj = ii; jj < bs2; jj += bs) bap[jj] = *value++;
6600880e062SHong Zhang         }
6610880e062SHong Zhang       } else {
6620880e062SHong Zhang         for (ii = 0; ii < bs; ii++, value += stepval) {
663ad540459SPierre Jolivet           for (jj = 0; jj < bs; jj++) *bap++ = *value++;
6640880e062SHong Zhang         }
6650880e062SHong Zhang       }
6660880e062SHong Zhang     noinsert2:;
6670880e062SHong Zhang       low = i;
6680880e062SHong Zhang     }
6690880e062SHong Zhang     ailen[row] = nrow;
6700880e062SHong Zhang   }
6713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
67249b5e25fSSatish Balay }
67349b5e25fSSatish Balay 
MatAssemblyEnd_SeqSBAIJ(Mat A,MatAssemblyType mode)674ba38deedSJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_SeqSBAIJ(Mat A, MatAssemblyType mode)
675d71ae5a4SJacob Faibussowitsch {
67649b5e25fSSatish Balay   Mat_SeqSBAIJ *a      = (Mat_SeqSBAIJ *)A->data;
6778f8f2f0dSBarry Smith   PetscInt      fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax;
678d0f46423SBarry Smith   PetscInt      m = A->rmap->N, *ip, N, *ailen = a->ilen;
67913f74950SBarry Smith   PetscInt      mbs = a->mbs, bs2 = a->bs2, rmax = 0;
68049b5e25fSSatish Balay   MatScalar    *aa = a->a, *ap;
68149b5e25fSSatish Balay 
68249b5e25fSSatish Balay   PetscFunctionBegin;
683d32568d8SPierre Jolivet   if (mode == MAT_FLUSH_ASSEMBLY || (A->was_assembled && A->ass_nonzerostate == A->nonzerostate)) PetscFunctionReturn(PETSC_SUCCESS);
68449b5e25fSSatish Balay 
68549b5e25fSSatish Balay   if (m) rmax = ailen[0];
68649b5e25fSSatish Balay   for (i = 1; i < mbs; i++) {
68749b5e25fSSatish Balay     /* move each row back by the amount of empty slots (fshift) before it*/
68849b5e25fSSatish Balay     fshift += imax[i - 1] - ailen[i - 1];
68949b5e25fSSatish Balay     rmax = PetscMax(rmax, ailen[i]);
69049b5e25fSSatish Balay     if (fshift) {
691580bdb30SBarry Smith       ip = aj + ai[i];
692580bdb30SBarry Smith       ap = aa + bs2 * ai[i];
69349b5e25fSSatish Balay       N  = ailen[i];
6949566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ip - fshift, ip, N));
6959566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ap - bs2 * fshift, ap, bs2 * N));
69649b5e25fSSatish Balay     }
69749b5e25fSSatish Balay     ai[i] = ai[i - 1] + ailen[i - 1];
69849b5e25fSSatish Balay   }
69949b5e25fSSatish Balay   if (mbs) {
70049b5e25fSSatish Balay     fshift += imax[mbs - 1] - ailen[mbs - 1];
70149b5e25fSSatish Balay     ai[mbs] = ai[mbs - 1] + ailen[mbs - 1];
70249b5e25fSSatish Balay   }
70349b5e25fSSatish Balay   /* reset ilen and imax for each row */
704ad540459SPierre Jolivet   for (i = 0; i < mbs; i++) ailen[i] = imax[i] = ai[i + 1] - ai[i];
7056c6c5352SBarry Smith   a->nz = ai[mbs];
70649b5e25fSSatish Balay 
707aed4548fSBarry 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);
70826fbe8dcSKarl Rupp 
7099566063dSJacob 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));
7109566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues is %" PetscInt_FMT "\n", a->reallocs));
7119566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Most nonzeros blocks in any row is %" PetscInt_FMT "\n", rmax));
71226fbe8dcSKarl Rupp 
7138e58a170SBarry Smith   A->info.mallocs += a->reallocs;
71449b5e25fSSatish Balay   a->reallocs         = 0;
71549b5e25fSSatish Balay   A->info.nz_unneeded = (PetscReal)fshift * bs2;
716061b2667SBarry Smith   a->idiagvalid       = PETSC_FALSE;
7174dcd73b1SHong Zhang   a->rmax             = rmax;
71838702af4SBarry Smith 
71938702af4SBarry Smith   if (A->cmap->n < 65536 && A->cmap->bs == 1) {
72044e1c64aSLisandro Dalcin     if (a->jshort && a->free_jshort) {
72117803ae8SHong Zhang       /* when matrix data structure is changed, previous jshort must be replaced */
7229566063dSJacob Faibussowitsch       PetscCall(PetscFree(a->jshort));
72317803ae8SHong Zhang     }
7249566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(a->i[A->rmap->n], &a->jshort));
7256497c311SBarry Smith     for (i = 0; i < a->i[A->rmap->n]; i++) a->jshort[i] = (short)a->j[i];
72638702af4SBarry Smith     A->ops->mult   = MatMult_SeqSBAIJ_1_ushort;
72741f059aeSBarry Smith     A->ops->sor    = MatSOR_SeqSBAIJ_ushort;
7284da8f245SBarry Smith     a->free_jshort = PETSC_TRUE;
72938702af4SBarry Smith   }
7303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
73149b5e25fSSatish Balay }
73249b5e25fSSatish Balay 
73349b5e25fSSatish Balay /* Only add/insert a(i,j) with i<=j (blocks).
734da81f932SPierre Jolivet    Any a(i,j) with i>j input by user is ignored.
73549b5e25fSSatish Balay */
73649b5e25fSSatish Balay 
MatSetValues_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)737d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is)
738d71ae5a4SJacob Faibussowitsch {
73949b5e25fSSatish Balay   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
740e2ee6c50SBarry Smith   PetscInt     *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N, lastcol = -1;
74113f74950SBarry Smith   PetscInt     *imax = a->imax, *ai = a->i, *ailen = a->ilen, roworiented = a->roworiented;
742d0f46423SBarry Smith   PetscInt     *aj = a->j, nonew = a->nonew, bs = A->rmap->bs, brow, bcol;
74313f74950SBarry Smith   PetscInt      ridx, cidx, bs2                 = a->bs2;
74449b5e25fSSatish Balay   MatScalar    *ap, value, *aa                  = a->a, *bap;
74549b5e25fSSatish Balay 
74649b5e25fSSatish Balay   PetscFunctionBegin;
74749b5e25fSSatish Balay   for (k = 0; k < m; k++) { /* loop over added rows */
74849b5e25fSSatish Balay     row  = im[k];           /* row number */
74949b5e25fSSatish Balay     brow = row / bs;        /* block row number */
75049b5e25fSSatish Balay     if (row < 0) continue;
7516bdcaf15SBarry 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);
75249b5e25fSSatish Balay     rp   = aj + ai[brow];       /*ptr to beginning of column value of the row block*/
75349b5e25fSSatish Balay     ap   = aa + bs2 * ai[brow]; /*ptr to beginning of element value of the row block*/
75449b5e25fSSatish Balay     rmax = imax[brow];          /* maximum space allocated for this row */
75549b5e25fSSatish Balay     nrow = ailen[brow];         /* actual length of this row */
75649b5e25fSSatish Balay     low  = 0;
7578509e838SStefano Zampini     high = nrow;
75849b5e25fSSatish Balay     for (l = 0; l < n; l++) { /* loop over added columns */
75949b5e25fSSatish Balay       if (in[l] < 0) continue;
7606bdcaf15SBarry 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);
76149b5e25fSSatish Balay       col  = in[l];
76249b5e25fSSatish Balay       bcol = col / bs; /* block col number */
76349b5e25fSSatish Balay 
764941593c8SHong Zhang       if (brow > bcol) {
765966bd95aSPierre 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)");
766966bd95aSPierre Jolivet         continue; /* ignore lower triangular values */
767941593c8SHong Zhang       }
768f4989cb3SHong Zhang 
7699371c9d4SSatish Balay       ridx = row % bs;
7709371c9d4SSatish Balay       cidx = col % bs; /*row and col index inside the block */
7718549e402SHong Zhang       if ((brow == bcol && ridx <= cidx) || (brow < bcol)) {
77249b5e25fSSatish Balay         /* element value a(k,l) */
77326fbe8dcSKarl Rupp         if (roworiented) value = v[l + k * n];
77426fbe8dcSKarl Rupp         else value = v[k + l * m];
77549b5e25fSSatish Balay 
77649b5e25fSSatish Balay         /* move pointer bap to a(k,l) quickly and add/insert value */
77726fbe8dcSKarl Rupp         if (col <= lastcol) low = 0;
7788509e838SStefano Zampini         else high = nrow;
7798509e838SStefano Zampini 
780e2ee6c50SBarry Smith         lastcol = col;
78149b5e25fSSatish Balay         while (high - low > 7) {
78249b5e25fSSatish Balay           t = (low + high) / 2;
78349b5e25fSSatish Balay           if (rp[t] > bcol) high = t;
78449b5e25fSSatish Balay           else low = t;
78549b5e25fSSatish Balay         }
78649b5e25fSSatish Balay         for (i = low; i < high; i++) {
78749b5e25fSSatish Balay           if (rp[i] > bcol) break;
78849b5e25fSSatish Balay           if (rp[i] == bcol) {
78949b5e25fSSatish Balay             bap = ap + bs2 * i + bs * cidx + ridx;
79049b5e25fSSatish Balay             if (is == ADD_VALUES) *bap += value;
79149b5e25fSSatish Balay             else *bap = value;
7928549e402SHong Zhang             /* for diag block, add/insert its symmetric element a(cidx,ridx) */
7938549e402SHong Zhang             if (brow == bcol && ridx < cidx) {
7948549e402SHong Zhang               bap = ap + bs2 * i + bs * ridx + cidx;
7958549e402SHong Zhang               if (is == ADD_VALUES) *bap += value;
7968549e402SHong Zhang               else *bap = value;
7978549e402SHong Zhang             }
79849b5e25fSSatish Balay             goto noinsert1;
79949b5e25fSSatish Balay           }
80049b5e25fSSatish Balay         }
80149b5e25fSSatish Balay 
80249b5e25fSSatish Balay         if (nonew == 1) goto noinsert1;
80308401ef6SPierre Jolivet         PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero (%" PetscInt_FMT ", %" PetscInt_FMT ") in the matrix", row, col);
804fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, brow, bcol, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
80549b5e25fSSatish Balay 
8069371c9d4SSatish Balay         N = nrow++ - 1;
8079371c9d4SSatish Balay         high++;
80849b5e25fSSatish Balay         /* shift up all the later entries in this row */
8099566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1));
8109566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1)));
8119566063dSJacob Faibussowitsch         PetscCall(PetscArrayzero(ap + bs2 * i, bs2));
81249b5e25fSSatish Balay         rp[i]                          = bcol;
81349b5e25fSSatish Balay         ap[bs2 * i + bs * cidx + ridx] = value;
8148509e838SStefano Zampini         /* for diag block, add/insert its symmetric element a(cidx,ridx) */
815ad540459SPierre Jolivet         if (brow == bcol && ridx < cidx) ap[bs2 * i + bs * ridx + cidx] = value;
81649b5e25fSSatish Balay       noinsert1:;
81749b5e25fSSatish Balay         low = i;
8188549e402SHong Zhang       }
81949b5e25fSSatish Balay     } /* end of loop over added columns */
82049b5e25fSSatish Balay     ailen[brow] = nrow;
82149b5e25fSSatish Balay   } /* end of loop over added rows */
8223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82349b5e25fSSatish Balay }
82449b5e25fSSatish Balay 
MatICCFactor_SeqSBAIJ(Mat inA,IS row,const MatFactorInfo * info)825ba38deedSJacob Faibussowitsch static PetscErrorCode MatICCFactor_SeqSBAIJ(Mat inA, IS row, const MatFactorInfo *info)
826d71ae5a4SJacob Faibussowitsch {
8274ccecd49SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)inA->data;
82849b5e25fSSatish Balay   Mat           outA;
829ace3abfcSBarry Smith   PetscBool     row_identity;
83049b5e25fSSatish Balay 
83149b5e25fSSatish Balay   PetscFunctionBegin;
83208401ef6SPierre Jolivet   PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 is supported for in-place icc");
8339566063dSJacob Faibussowitsch   PetscCall(ISIdentity(row, &row_identity));
83428b400f6SJacob Faibussowitsch   PetscCheck(row_identity, PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix reordering is not supported");
83508401ef6SPierre 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()! */
836c84f5b01SHong Zhang 
83749b5e25fSSatish Balay   outA = inA;
8389566063dSJacob Faibussowitsch   PetscCall(PetscFree(inA->solvertype));
8399566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype));
84049b5e25fSSatish Balay 
841421480d9SBarry Smith   inA->factortype = MAT_FACTOR_ICC;
8429566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetNumericFactorization_inplace(inA, row_identity));
84349b5e25fSSatish Balay 
8449566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
8459566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
846c84f5b01SHong Zhang   a->row = row;
8479566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
8489566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
849c84f5b01SHong Zhang   a->col = row;
850c84f5b01SHong Zhang 
851c84f5b01SHong Zhang   /* Create the invert permutation so that it can be used in MatCholeskyFactorNumeric() */
8529566063dSJacob Faibussowitsch   if (a->icol) PetscCall(ISInvertPermutation(row, PETSC_DECIDE, &a->icol));
85349b5e25fSSatish Balay 
854aa624791SPierre Jolivet   if (!a->solve_work) PetscCall(PetscMalloc1(inA->rmap->N + inA->rmap->bs, &a->solve_work));
85549b5e25fSSatish Balay 
8569566063dSJacob Faibussowitsch   PetscCall(MatCholeskyFactorNumeric(outA, inA, info));
8573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
85849b5e25fSSatish Balay }
859950f1e5bSHong Zhang 
MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat,PetscInt * indices)860ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat, PetscInt *indices)
861d71ae5a4SJacob Faibussowitsch {
862045c9aa0SHong Zhang   Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)mat->data;
86313f74950SBarry Smith   PetscInt      i, nz, n;
86449b5e25fSSatish Balay 
86549b5e25fSSatish Balay   PetscFunctionBegin;
8666c6c5352SBarry Smith   nz = baij->maxnz;
867d0f46423SBarry Smith   n  = mat->cmap->n;
86826fbe8dcSKarl Rupp   for (i = 0; i < nz; i++) baij->j[i] = indices[i];
86926fbe8dcSKarl Rupp 
8706c6c5352SBarry Smith   baij->nz = nz;
87126fbe8dcSKarl Rupp   for (i = 0; i < n; i++) baij->ilen[i] = baij->imax[i];
87226fbe8dcSKarl Rupp 
8739566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
8743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
87549b5e25fSSatish Balay }
87649b5e25fSSatish Balay 
87749b5e25fSSatish Balay /*@
87819585528SSatish Balay   MatSeqSBAIJSetColumnIndices - Set the column indices for all the rows
87911a5261eSBarry Smith   in a `MATSEQSBAIJ` matrix.
88049b5e25fSSatish Balay 
88149b5e25fSSatish Balay   Input Parameters:
88211a5261eSBarry Smith + mat     - the `MATSEQSBAIJ` matrix
88349b5e25fSSatish Balay - indices - the column indices
88449b5e25fSSatish Balay 
88549b5e25fSSatish Balay   Level: advanced
88649b5e25fSSatish Balay 
88749b5e25fSSatish Balay   Notes:
88849b5e25fSSatish Balay   This can be called if you have precomputed the nonzero structure of the
88949b5e25fSSatish Balay   matrix and want to provide it to the matrix object to improve the performance
89011a5261eSBarry Smith   of the `MatSetValues()` operation.
89149b5e25fSSatish Balay 
89249b5e25fSSatish Balay   You MUST have set the correct numbers of nonzeros per row in the call to
89311a5261eSBarry Smith   `MatCreateSeqSBAIJ()`, and the columns indices MUST be sorted.
89449b5e25fSSatish Balay 
8952ef1f0ffSBarry Smith   MUST be called before any calls to `MatSetValues()`
89649b5e25fSSatish Balay 
8971cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreateSeqSBAIJ`
89849b5e25fSSatish Balay @*/
MatSeqSBAIJSetColumnIndices(Mat mat,PetscInt * indices)899d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetColumnIndices(Mat mat, PetscInt *indices)
900d71ae5a4SJacob Faibussowitsch {
90149b5e25fSSatish Balay   PetscFunctionBegin;
9020700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9034f572ea9SToby Isaac   PetscAssertPointer(indices, 2);
904cac4c232SBarry Smith   PetscUseMethod(mat, "MatSeqSBAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices));
9053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
90649b5e25fSSatish Balay }
90749b5e25fSSatish Balay 
MatCopy_SeqSBAIJ(Mat A,Mat B,MatStructure str)908ba38deedSJacob Faibussowitsch static PetscErrorCode MatCopy_SeqSBAIJ(Mat A, Mat B, MatStructure str)
909d71ae5a4SJacob Faibussowitsch {
9104c7a3774SStefano Zampini   PetscBool isbaij;
9113c896bc6SHong Zhang 
9123c896bc6SHong Zhang   PetscFunctionBegin;
9139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &isbaij, MATSEQSBAIJ, MATMPISBAIJ, ""));
91428b400f6SJacob Faibussowitsch   PetscCheck(isbaij, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)B)->type_name);
9154c7a3774SStefano Zampini   /* If the two matrices have the same copy implementation and nonzero pattern, use fast copy. */
9164c7a3774SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
9173c896bc6SHong Zhang     Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
9183c896bc6SHong Zhang     Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data;
9193c896bc6SHong Zhang 
92008401ef6SPierre 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");
92108401ef6SPierre Jolivet     PetscCheck(a->mbs == b->mbs, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of rows in two matrices are different");
92208401ef6SPierre Jolivet     PetscCheck(a->bs2 == b->bs2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different block size");
9239566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(b->a, a->a, a->bs2 * a->i[a->mbs]));
9249566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)B));
9253c896bc6SHong Zhang   } else {
9269566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(A));
9279566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
9289566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(A));
9293c896bc6SHong Zhang   }
9303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9313c896bc6SHong Zhang }
9323c896bc6SHong Zhang 
MatSeqSBAIJGetArray_SeqSBAIJ(Mat A,PetscScalar * array[])933d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJGetArray_SeqSBAIJ(Mat A, PetscScalar *array[])
934d71ae5a4SJacob Faibussowitsch {
935a6ece127SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
9365fd66863SKarl Rupp 
937a6ece127SHong Zhang   PetscFunctionBegin;
938a6ece127SHong Zhang   *array = a->a;
9393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
940a6ece127SHong Zhang }
941a6ece127SHong Zhang 
MatSeqSBAIJRestoreArray_SeqSBAIJ(Mat A,PetscScalar * array[])942d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJRestoreArray_SeqSBAIJ(Mat A, PetscScalar *array[])
943d71ae5a4SJacob Faibussowitsch {
944a6ece127SHong Zhang   PetscFunctionBegin;
945cda14afcSprj-   *array = NULL;
9463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
947a6ece127SHong Zhang }
948a6ece127SHong Zhang 
MatAXPYGetPreallocation_SeqSBAIJ(Mat Y,Mat X,PetscInt * nnz)949d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPYGetPreallocation_SeqSBAIJ(Mat Y, Mat X, PetscInt *nnz)
950d71ae5a4SJacob Faibussowitsch {
951b264fe52SHong Zhang   PetscInt      bs = Y->rmap->bs, mbs = Y->rmap->N / bs;
95252768537SHong Zhang   Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data;
95352768537SHong Zhang   Mat_SeqSBAIJ *y = (Mat_SeqSBAIJ *)Y->data;
95452768537SHong Zhang 
95552768537SHong Zhang   PetscFunctionBegin;
95652768537SHong Zhang   /* Set the number of nonzeros in the new matrix */
9579566063dSJacob Faibussowitsch   PetscCall(MatAXPYGetPreallocation_SeqX_private(mbs, x->i, x->j, y->i, y->j, nnz));
9583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
95952768537SHong Zhang }
96052768537SHong Zhang 
MatAXPY_SeqSBAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)961ba38deedSJacob Faibussowitsch static PetscErrorCode MatAXPY_SeqSBAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str)
962d71ae5a4SJacob Faibussowitsch {
96342ee4b1aSHong Zhang   Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data, *y = (Mat_SeqSBAIJ *)Y->data;
96431ce2d13SHong Zhang   PetscInt      bs = Y->rmap->bs, bs2 = bs * bs;
965e838b9e7SJed Brown   PetscBLASInt  one = 1;
96642ee4b1aSHong Zhang 
96742ee4b1aSHong Zhang   PetscFunctionBegin;
968134adf20SPierre Jolivet   if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) {
969134adf20SPierre Jolivet     PetscBool e = x->nz == y->nz && x->mbs == y->mbs ? PETSC_TRUE : PETSC_FALSE;
970134adf20SPierre Jolivet     if (e) {
9719566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(x->i, y->i, x->mbs + 1, &e));
972134adf20SPierre Jolivet       if (e) {
9739566063dSJacob Faibussowitsch         PetscCall(PetscArraycmp(x->j, y->j, x->i[x->mbs], &e));
974134adf20SPierre Jolivet         if (e) str = SAME_NONZERO_PATTERN;
975134adf20SPierre Jolivet       }
976134adf20SPierre Jolivet     }
97754c59aa7SJacob Faibussowitsch     if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN");
978134adf20SPierre Jolivet   }
97942ee4b1aSHong Zhang   if (str == SAME_NONZERO_PATTERN) {
980f4df32b1SMatthew Knepley     PetscScalar  alpha = a;
981c5df96a5SBarry Smith     PetscBLASInt bnz;
9829566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(x->nz * bs2, &bnz));
983792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, x->a, &one, y->a, &one));
9849566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)Y));
985ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
9869566063dSJacob Faibussowitsch     PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_TRUE));
9879566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
9889566063dSJacob Faibussowitsch     PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_FALSE));
98942ee4b1aSHong Zhang   } else {
99052768537SHong Zhang     Mat       B;
99152768537SHong Zhang     PetscInt *nnz;
99254c59aa7SJacob Faibussowitsch     PetscCheck(bs == X->rmap->bs, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Matrices must have same block size");
9939566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(X));
9949566063dSJacob Faibussowitsch     PetscCall(MatGetRowUpperTriangular(Y));
9959566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Y->rmap->N, &nnz));
9969566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B));
9979566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name));
9989566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, Y->rmap->n, Y->cmap->n, Y->rmap->N, Y->cmap->N));
9999566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, Y, Y));
10009566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, ((PetscObject)Y)->type_name));
10019566063dSJacob Faibussowitsch     PetscCall(MatAXPYGetPreallocation_SeqSBAIJ(Y, X, nnz));
10029566063dSJacob Faibussowitsch     PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz));
100352768537SHong Zhang 
10049566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
100552768537SHong Zhang 
10069566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
10079566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz));
10089566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(X));
10099566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowUpperTriangular(Y));
101042ee4b1aSHong Zhang   }
10113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
101242ee4b1aSHong Zhang }
101342ee4b1aSHong Zhang 
MatIsStructurallySymmetric_SeqSBAIJ(Mat A,PetscBool * flg)1014ba38deedSJacob Faibussowitsch static PetscErrorCode MatIsStructurallySymmetric_SeqSBAIJ(Mat A, PetscBool *flg)
1015d71ae5a4SJacob Faibussowitsch {
1016efcf0fc3SBarry Smith   PetscFunctionBegin;
1017efcf0fc3SBarry Smith   *flg = PETSC_TRUE;
10183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1019efcf0fc3SBarry Smith }
1020efcf0fc3SBarry Smith 
MatConjugate_SeqSBAIJ(Mat A)1021ba38deedSJacob Faibussowitsch static PetscErrorCode MatConjugate_SeqSBAIJ(Mat A)
1022d71ae5a4SJacob Faibussowitsch {
10232726fb6dSPierre Jolivet   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
10242726fb6dSPierre Jolivet   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
10252726fb6dSPierre Jolivet   MatScalar    *aa = a->a;
10262726fb6dSPierre Jolivet 
10272726fb6dSPierre Jolivet   PetscFunctionBegin;
10282726fb6dSPierre Jolivet   for (i = 0; i < nz; i++) aa[i] = PetscConj(aa[i]);
10293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10302726fb6dSPierre Jolivet }
10312726fb6dSPierre Jolivet 
MatRealPart_SeqSBAIJ(Mat A)1032ba38deedSJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqSBAIJ(Mat A)
1033d71ae5a4SJacob Faibussowitsch {
103499cafbc1SBarry Smith   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
103599cafbc1SBarry Smith   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
1036dd6ea824SBarry Smith   MatScalar    *aa = a->a;
103799cafbc1SBarry Smith 
103899cafbc1SBarry Smith   PetscFunctionBegin;
103999cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]);
10403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
104199cafbc1SBarry Smith }
104299cafbc1SBarry Smith 
MatImaginaryPart_SeqSBAIJ(Mat A)1043ba38deedSJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqSBAIJ(Mat A)
1044d71ae5a4SJacob Faibussowitsch {
104599cafbc1SBarry Smith   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
104699cafbc1SBarry Smith   PetscInt      i, nz = a->bs2 * a->i[a->mbs];
1047dd6ea824SBarry Smith   MatScalar    *aa = a->a;
104899cafbc1SBarry Smith 
104999cafbc1SBarry Smith   PetscFunctionBegin;
105099cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
10513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
105299cafbc1SBarry Smith }
105399cafbc1SBarry Smith 
MatZeroRowsColumns_SeqSBAIJ(Mat A,PetscInt is_n,const PetscInt is_idx[],PetscScalar diag,Vec x,Vec b)1054ba38deedSJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_SeqSBAIJ(Mat A, PetscInt is_n, const PetscInt is_idx[], PetscScalar diag, Vec x, Vec b)
1055d71ae5a4SJacob Faibussowitsch {
10563bededecSBarry Smith   Mat_SeqSBAIJ      *baij = (Mat_SeqSBAIJ *)A->data;
10573bededecSBarry Smith   PetscInt           i, j, k, count;
10583bededecSBarry Smith   PetscInt           bs = A->rmap->bs, bs2 = baij->bs2, row, col;
10593bededecSBarry Smith   PetscScalar        zero = 0.0;
10603bededecSBarry Smith   MatScalar         *aa;
10613bededecSBarry Smith   const PetscScalar *xx;
10623bededecSBarry Smith   PetscScalar       *bb;
106356777dd2SBarry Smith   PetscBool         *zeroed, vecs = PETSC_FALSE;
10643bededecSBarry Smith 
10653bededecSBarry Smith   PetscFunctionBegin;
1066dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
10673bededecSBarry Smith   if (x && b) {
10689566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
10699566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
107056777dd2SBarry Smith     vecs = PETSC_TRUE;
10713bededecSBarry Smith   }
10723bededecSBarry Smith 
10733bededecSBarry Smith   /* zero the columns */
10749566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(A->rmap->n, &zeroed));
10753bededecSBarry Smith   for (i = 0; i < is_n; i++) {
1076aed4548fSBarry 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]);
10773bededecSBarry Smith     zeroed[is_idx[i]] = PETSC_TRUE;
10783bededecSBarry Smith   }
107956777dd2SBarry Smith   if (vecs) {
108056777dd2SBarry Smith     for (i = 0; i < A->rmap->N; i++) {
108156777dd2SBarry Smith       row = i / bs;
108256777dd2SBarry Smith       for (j = baij->i[row]; j < baij->i[row + 1]; j++) {
108356777dd2SBarry Smith         for (k = 0; k < bs; k++) {
108456777dd2SBarry Smith           col = bs * baij->j[j] + k;
108556777dd2SBarry Smith           if (col <= i) continue;
1086835f2295SStefano Zampini           aa = baij->a + j * bs2 + (i % bs) + bs * k;
108726fbe8dcSKarl Rupp           if (!zeroed[i] && zeroed[col]) bb[i] -= aa[0] * xx[col];
108826fbe8dcSKarl Rupp           if (zeroed[i] && !zeroed[col]) bb[col] -= aa[0] * xx[i];
108956777dd2SBarry Smith         }
109056777dd2SBarry Smith       }
109156777dd2SBarry Smith     }
109226fbe8dcSKarl Rupp     for (i = 0; i < is_n; i++) bb[is_idx[i]] = diag * xx[is_idx[i]];
109356777dd2SBarry Smith   }
109456777dd2SBarry Smith 
10953bededecSBarry Smith   for (i = 0; i < A->rmap->N; i++) {
10963bededecSBarry Smith     if (!zeroed[i]) {
10973bededecSBarry Smith       row = i / bs;
10983bededecSBarry Smith       for (j = baij->i[row]; j < baij->i[row + 1]; j++) {
10993bededecSBarry Smith         for (k = 0; k < bs; k++) {
11003bededecSBarry Smith           col = bs * baij->j[j] + k;
11013bededecSBarry Smith           if (zeroed[col]) {
1102835f2295SStefano Zampini             aa    = baij->a + j * bs2 + (i % bs) + bs * k;
11033bededecSBarry Smith             aa[0] = 0.0;
11043bededecSBarry Smith           }
11053bededecSBarry Smith         }
11063bededecSBarry Smith       }
11073bededecSBarry Smith     }
11083bededecSBarry Smith   }
11099566063dSJacob Faibussowitsch   PetscCall(PetscFree(zeroed));
111056777dd2SBarry Smith   if (vecs) {
11119566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
11129566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
111356777dd2SBarry Smith   }
11143bededecSBarry Smith 
11153bededecSBarry Smith   /* zero the rows */
11163bededecSBarry Smith   for (i = 0; i < is_n; i++) {
11173bededecSBarry Smith     row   = is_idx[i];
11183bededecSBarry Smith     count = (baij->i[row / bs + 1] - baij->i[row / bs]) * bs;
1119835f2295SStefano Zampini     aa    = baij->a + baij->i[row / bs] * bs2 + (row % bs);
11203bededecSBarry Smith     for (k = 0; k < count; k++) {
11213bededecSBarry Smith       aa[0] = zero;
11223bededecSBarry Smith       aa += bs;
11233bededecSBarry Smith     }
1124dbbe0bcdSBarry Smith     if (diag != 0.0) PetscUseTypeMethod(A, setvalues, 1, &row, 1, &row, &diag, INSERT_VALUES);
11253bededecSBarry Smith   }
11269566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd_SeqSBAIJ(A, MAT_FINAL_ASSEMBLY));
11273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11283bededecSBarry Smith }
11293bededecSBarry Smith 
MatShift_SeqSBAIJ(Mat Y,PetscScalar a)1130ba38deedSJacob Faibussowitsch static PetscErrorCode MatShift_SeqSBAIJ(Mat Y, PetscScalar a)
1131d71ae5a4SJacob Faibussowitsch {
11327d68702bSBarry Smith   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)Y->data;
11337d68702bSBarry Smith 
11347d68702bSBarry Smith   PetscFunctionBegin;
113548a46eb9SPierre Jolivet   if (!Y->preallocated || !aij->nz) PetscCall(MatSeqSBAIJSetPreallocation(Y, Y->rmap->bs, 1, NULL));
11369566063dSJacob Faibussowitsch   PetscCall(MatShift_Basic(Y, a));
11373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11387d68702bSBarry Smith }
11397d68702bSBarry Smith 
MatEliminateZeros_SeqSBAIJ(Mat A,PetscBool keep)114017ea310bSPierre Jolivet PetscErrorCode MatEliminateZeros_SeqSBAIJ(Mat A, PetscBool keep)
114117ea310bSPierre Jolivet {
114217ea310bSPierre Jolivet   Mat_SeqSBAIJ *a      = (Mat_SeqSBAIJ *)A->data;
114317ea310bSPierre Jolivet   PetscInt      fshift = 0, fshift_prev = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax, j, k;
114417ea310bSPierre Jolivet   PetscInt      m = A->rmap->N, *ailen = a->ilen;
114517ea310bSPierre Jolivet   PetscInt      mbs = a->mbs, bs2 = a->bs2, rmax = 0;
114617ea310bSPierre Jolivet   MatScalar    *aa = a->a, *ap;
114717ea310bSPierre Jolivet   PetscBool     zero;
114817ea310bSPierre Jolivet 
114917ea310bSPierre Jolivet   PetscFunctionBegin;
115017ea310bSPierre Jolivet   PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot eliminate zeros for unassembled matrix");
115117ea310bSPierre Jolivet   if (m) rmax = ailen[0];
115217ea310bSPierre Jolivet   for (i = 1; i <= mbs; i++) {
115317ea310bSPierre Jolivet     for (k = ai[i - 1]; k < ai[i]; k++) {
115417ea310bSPierre Jolivet       zero = PETSC_TRUE;
115517ea310bSPierre Jolivet       ap   = aa + bs2 * k;
115617ea310bSPierre Jolivet       for (j = 0; j < bs2 && zero; j++) {
115717ea310bSPierre Jolivet         if (ap[j] != 0.0) zero = PETSC_FALSE;
115817ea310bSPierre Jolivet       }
115917ea310bSPierre Jolivet       if (zero && (aj[k] != i - 1 || !keep)) fshift++;
116017ea310bSPierre Jolivet       else {
116117ea310bSPierre Jolivet         if (zero && aj[k] == i - 1) PetscCall(PetscInfo(A, "Keep the diagonal block at row %" PetscInt_FMT "\n", i - 1));
116217ea310bSPierre Jolivet         aj[k - fshift] = aj[k];
116317ea310bSPierre Jolivet         PetscCall(PetscArraymove(ap - bs2 * fshift, ap, bs2));
116417ea310bSPierre Jolivet       }
116517ea310bSPierre Jolivet     }
116617ea310bSPierre Jolivet     ai[i - 1] -= fshift_prev;
116717ea310bSPierre Jolivet     fshift_prev  = fshift;
116817ea310bSPierre Jolivet     ailen[i - 1] = imax[i - 1] = ai[i] - fshift - ai[i - 1];
116917ea310bSPierre Jolivet     a->nonzerorowcnt += ((ai[i] - fshift - ai[i - 1]) > 0);
117017ea310bSPierre Jolivet     rmax = PetscMax(rmax, ailen[i - 1]);
117117ea310bSPierre Jolivet   }
117217ea310bSPierre Jolivet   if (fshift) {
117317ea310bSPierre Jolivet     if (mbs) {
117417ea310bSPierre Jolivet       ai[mbs] -= fshift;
117517ea310bSPierre Jolivet       a->nz = ai[mbs];
117617ea310bSPierre Jolivet     }
117717ea310bSPierre 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));
117817ea310bSPierre Jolivet     A->nonzerostate++;
117917ea310bSPierre Jolivet     A->info.nz_unneeded += (PetscReal)fshift;
118017ea310bSPierre Jolivet     a->rmax = rmax;
118117ea310bSPierre Jolivet     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
118217ea310bSPierre Jolivet     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
118317ea310bSPierre Jolivet   }
118417ea310bSPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
118517ea310bSPierre Jolivet }
118617ea310bSPierre Jolivet 
11873964eb88SJed Brown static struct _MatOps MatOps_Values = {MatSetValues_SeqSBAIJ,
118849b5e25fSSatish Balay                                        MatGetRow_SeqSBAIJ,
118949b5e25fSSatish Balay                                        MatRestoreRow_SeqSBAIJ,
119049b5e25fSSatish Balay                                        MatMult_SeqSBAIJ_N,
119197304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqSBAIJ_N,
1192431c96f7SBarry Smith                                        MatMult_SeqSBAIJ_N, /* transpose versions are same as non-transpose versions */
1193e005ede5SBarry Smith                                        MatMultAdd_SeqSBAIJ_N,
1194f4259b30SLisandro Dalcin                                        NULL,
1195f4259b30SLisandro Dalcin                                        NULL,
1196f4259b30SLisandro Dalcin                                        NULL,
1197f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
1198f4259b30SLisandro Dalcin                                        NULL,
1199c078aec8SLisandro Dalcin                                        MatCholeskyFactor_SeqSBAIJ,
120041f059aeSBarry Smith                                        MatSOR_SeqSBAIJ,
120149b5e25fSSatish Balay                                        MatTranspose_SeqSBAIJ,
120297304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqSBAIJ,
120349b5e25fSSatish Balay                                        MatEqual_SeqSBAIJ,
120449b5e25fSSatish Balay                                        MatGetDiagonal_SeqSBAIJ,
120549b5e25fSSatish Balay                                        MatDiagonalScale_SeqSBAIJ,
120649b5e25fSSatish Balay                                        MatNorm_SeqSBAIJ,
1207f4259b30SLisandro Dalcin                                        /* 20*/ NULL,
120849b5e25fSSatish Balay                                        MatAssemblyEnd_SeqSBAIJ,
120949b5e25fSSatish Balay                                        MatSetOption_SeqSBAIJ,
121049b5e25fSSatish Balay                                        MatZeroEntries_SeqSBAIJ,
1211f4259b30SLisandro Dalcin                                        /* 24*/ NULL,
1212f4259b30SLisandro Dalcin                                        NULL,
1213f4259b30SLisandro Dalcin                                        NULL,
1214f4259b30SLisandro Dalcin                                        NULL,
1215f4259b30SLisandro Dalcin                                        NULL,
121626cec326SBarry Smith                                        /* 29*/ MatSetUp_Seq_Hash,
1217f4259b30SLisandro Dalcin                                        NULL,
1218f4259b30SLisandro Dalcin                                        NULL,
1219f4259b30SLisandro Dalcin                                        NULL,
1220f4259b30SLisandro Dalcin                                        NULL,
1221d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqSBAIJ,
1222f4259b30SLisandro Dalcin                                        NULL,
1223f4259b30SLisandro Dalcin                                        NULL,
1224f4259b30SLisandro Dalcin                                        NULL,
1225c84f5b01SHong Zhang                                        MatICCFactor_SeqSBAIJ,
1226d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqSBAIJ,
12277dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqSBAIJ,
122849b5e25fSSatish Balay                                        MatIncreaseOverlap_SeqSBAIJ,
122949b5e25fSSatish Balay                                        MatGetValues_SeqSBAIJ,
12303c896bc6SHong Zhang                                        MatCopy_SeqSBAIJ,
1231f4259b30SLisandro Dalcin                                        /* 44*/ NULL,
123249b5e25fSSatish Balay                                        MatScale_SeqSBAIJ,
12337d68702bSBarry Smith                                        MatShift_SeqSBAIJ,
1234f4259b30SLisandro Dalcin                                        NULL,
12353bededecSBarry Smith                                        MatZeroRowsColumns_SeqSBAIJ,
1236f4259b30SLisandro Dalcin                                        /* 49*/ NULL,
123749b5e25fSSatish Balay                                        MatGetRowIJ_SeqSBAIJ,
123849b5e25fSSatish Balay                                        MatRestoreRowIJ_SeqSBAIJ,
1239f4259b30SLisandro Dalcin                                        NULL,
1240f4259b30SLisandro Dalcin                                        NULL,
1241f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
1242f4259b30SLisandro Dalcin                                        NULL,
1243f4259b30SLisandro Dalcin                                        NULL,
1244dc29a518SPierre Jolivet                                        MatPermute_SeqSBAIJ,
124549b5e25fSSatish Balay                                        MatSetValuesBlocked_SeqSBAIJ,
12467dae84e0SHong Zhang                                        /* 59*/ MatCreateSubMatrix_SeqSBAIJ,
1247f4259b30SLisandro Dalcin                                        NULL,
1248f4259b30SLisandro Dalcin                                        NULL,
1249f4259b30SLisandro Dalcin                                        NULL,
1250f4259b30SLisandro Dalcin                                        NULL,
1251f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
1252f4259b30SLisandro Dalcin                                        NULL,
1253f4259b30SLisandro Dalcin                                        NULL,
1254f4259b30SLisandro Dalcin                                        NULL,
12558bb0f5c6SPierre Jolivet                                        MatGetRowMaxAbs_SeqSBAIJ,
12568bb0f5c6SPierre Jolivet                                        /* 69*/ NULL,
125728d58a37SPierre Jolivet                                        MatConvert_MPISBAIJ_Basic,
1258f4259b30SLisandro Dalcin                                        NULL,
1259f4259b30SLisandro Dalcin                                        NULL,
12608bb0f5c6SPierre Jolivet                                        NULL,
1261f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
1262f4259b30SLisandro Dalcin                                        NULL,
1263f4259b30SLisandro Dalcin                                        NULL,
126497304618SKris Buschelman                                        MatGetInertia_SeqSBAIJ,
12655bba2384SShri Abhyankar                                        MatLoad_SeqSBAIJ,
12668bb0f5c6SPierre Jolivet                                        /* 79*/ NULL,
12676cff0a6bSPierre Jolivet                                        NULL,
1268efcf0fc3SBarry Smith                                        MatIsStructurallySymmetric_SeqSBAIJ,
1269f4259b30SLisandro Dalcin                                        NULL,
1270f4259b30SLisandro Dalcin                                        NULL,
12718bb0f5c6SPierre Jolivet                                        /* 84*/ NULL,
12728bb0f5c6SPierre Jolivet                                        NULL,
12738bb0f5c6SPierre Jolivet                                        NULL,
12748bb0f5c6SPierre Jolivet                                        NULL,
12758bb0f5c6SPierre Jolivet                                        NULL,
1276f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
1277f4259b30SLisandro Dalcin                                        NULL,
1278f4259b30SLisandro Dalcin                                        NULL,
1279f4259b30SLisandro Dalcin                                        NULL,
12808bb0f5c6SPierre Jolivet                                        MatConjugate_SeqSBAIJ,
1281f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
1282f4259b30SLisandro Dalcin                                        NULL,
128399cafbc1SBarry Smith                                        MatRealPart_SeqSBAIJ,
1284f5edf698SHong Zhang                                        MatImaginaryPart_SeqSBAIJ,
1285f5edf698SHong Zhang                                        MatGetRowUpperTriangular_SeqSBAIJ,
12868bb0f5c6SPierre Jolivet                                        /* 99*/ MatRestoreRowUpperTriangular_SeqSBAIJ,
12878bb0f5c6SPierre Jolivet                                        NULL,
12888bb0f5c6SPierre Jolivet                                        NULL,
12898bb0f5c6SPierre Jolivet                                        NULL,
12908bb0f5c6SPierre Jolivet                                        NULL,
1291421480d9SBarry Smith                                        /*104*/ NULL,
12928bb0f5c6SPierre Jolivet                                        NULL,
12938bb0f5c6SPierre Jolivet                                        NULL,
12948bb0f5c6SPierre Jolivet                                        NULL,
12958bb0f5c6SPierre Jolivet                                        NULL,
1296f4259b30SLisandro Dalcin                                        /*109*/ NULL,
1297f4259b30SLisandro Dalcin                                        NULL,
1298f4259b30SLisandro Dalcin                                        NULL,
1299f4259b30SLisandro Dalcin                                        NULL,
13008bb0f5c6SPierre Jolivet                                        NULL,
1301f4259b30SLisandro Dalcin                                        /*114*/ NULL,
1302f4259b30SLisandro Dalcin                                        NULL,
1303f4259b30SLisandro Dalcin                                        NULL,
1304f4259b30SLisandro Dalcin                                        NULL,
1305f4259b30SLisandro Dalcin                                        NULL,
1306f4259b30SLisandro Dalcin                                        /*119*/ NULL,
1307f4259b30SLisandro Dalcin                                        NULL,
1308f4259b30SLisandro Dalcin                                        NULL,
1309f4259b30SLisandro Dalcin                                        NULL,
1310f4259b30SLisandro Dalcin                                        NULL,
1311f4259b30SLisandro Dalcin                                        /*124*/ NULL,
1312f4259b30SLisandro Dalcin                                        NULL,
13138bb0f5c6SPierre Jolivet                                        MatSetBlockSizes_Default,
1314f4259b30SLisandro Dalcin                                        NULL,
1315f4259b30SLisandro Dalcin                                        NULL,
1316421480d9SBarry Smith                                        /*129*/ NULL,
13178bb0f5c6SPierre Jolivet                                        MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ,
1318f4259b30SLisandro Dalcin                                        NULL,
1319f4259b30SLisandro Dalcin                                        NULL,
1320421480d9SBarry Smith                                        NULL,
1321f4259b30SLisandro Dalcin                                        /*134*/ NULL,
1322f4259b30SLisandro Dalcin                                        NULL,
1323eede4a3fSMark Adams                                        MatEliminateZeros_SeqSBAIJ,
13244cc2b5b5SPierre Jolivet                                        NULL,
132542ce410bSJunchao Zhang                                        NULL,
1326421480d9SBarry Smith                                        /*139*/ NULL,
132742ce410bSJunchao Zhang                                        NULL,
132803db1824SAlex Lindsay                                        MatCopyHashToXAIJ_Seq_Hash,
1329c2be7ffeSStefano Zampini                                        NULL,
133003db1824SAlex Lindsay                                        NULL};
1331be1d678aSKris Buschelman 
MatStoreValues_SeqSBAIJ(Mat mat)1332ba38deedSJacob Faibussowitsch static PetscErrorCode MatStoreValues_SeqSBAIJ(Mat mat)
1333d71ae5a4SJacob Faibussowitsch {
13344afc71dfSHong Zhang   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1335d0f46423SBarry Smith   PetscInt      nz  = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2;
133649b5e25fSSatish Balay 
133749b5e25fSSatish Balay   PetscFunctionBegin;
133808401ef6SPierre Jolivet   PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
133949b5e25fSSatish Balay 
134049b5e25fSSatish Balay   /* allocate space for values if not already there */
134148a46eb9SPierre Jolivet   if (!aij->saved_values) PetscCall(PetscMalloc1(nz + 1, &aij->saved_values));
134249b5e25fSSatish Balay 
134349b5e25fSSatish Balay   /* copy values over */
13449566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz));
13453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
134649b5e25fSSatish Balay }
134749b5e25fSSatish Balay 
MatRetrieveValues_SeqSBAIJ(Mat mat)1348ba38deedSJacob Faibussowitsch static PetscErrorCode MatRetrieveValues_SeqSBAIJ(Mat mat)
1349d71ae5a4SJacob Faibussowitsch {
13504afc71dfSHong Zhang   Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1351d0f46423SBarry Smith   PetscInt      nz  = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2;
135249b5e25fSSatish Balay 
135349b5e25fSSatish Balay   PetscFunctionBegin;
135408401ef6SPierre Jolivet   PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
135528b400f6SJacob Faibussowitsch   PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first");
135649b5e25fSSatish Balay 
135749b5e25fSSatish Balay   /* copy values over */
13589566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz));
13593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
136049b5e25fSSatish Balay }
136149b5e25fSSatish Balay 
MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[])1362f9663b93SPierre Jolivet static PetscErrorCode MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[])
1363d71ae5a4SJacob Faibussowitsch {
1364c464158bSHong Zhang   Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data;
13654dcd73b1SHong Zhang   PetscInt      i, mbs, nbs, bs2;
13662576faa2SJed Brown   PetscBool     skipallocation = PETSC_FALSE, flg = PETSC_FALSE, realalloc = PETSC_FALSE;
136749b5e25fSSatish Balay 
1368b4e2f619SBarry Smith   PetscFunctionBegin;
1369ad79cf63SBarry Smith   if (B->hash_active) {
1370ad79cf63SBarry Smith     PetscInt bs;
1371aea10558SJacob Faibussowitsch     B->ops[0] = b->cops;
1372ad79cf63SBarry Smith     PetscCall(PetscHMapIJVDestroy(&b->ht));
1373ad79cf63SBarry Smith     PetscCall(MatGetBlockSize(B, &bs));
1374ad79cf63SBarry Smith     if (bs > 1) PetscCall(PetscHSetIJDestroy(&b->bht));
1375ad79cf63SBarry Smith     PetscCall(PetscFree(b->dnz));
1376ad79cf63SBarry Smith     PetscCall(PetscFree(b->bdnz));
1377ad79cf63SBarry Smith     B->hash_active = PETSC_FALSE;
1378ad79cf63SBarry Smith   }
13792576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
1380db4efbfdSBarry Smith 
138158b7e2c1SStefano Zampini   PetscCall(MatSetBlockSize(B, bs));
13829566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
13839566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
138408401ef6SPierre 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);
13859566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs));
1386899cda47SBarry Smith 
138721940c7eSstefano_zampini   B->preallocated = PETSC_TRUE;
138821940c7eSstefano_zampini 
1389d0f46423SBarry Smith   mbs = B->rmap->N / bs;
13904dcd73b1SHong Zhang   nbs = B->cmap->n / bs;
139149b5e25fSSatish Balay   bs2 = bs * bs;
139249b5e25fSSatish Balay 
1393aed4548fSBarry 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");
139449b5e25fSSatish Balay 
1395ab93d7beSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
1396ab93d7beSBarry Smith     skipallocation = PETSC_TRUE;
1397ab93d7beSBarry Smith     nz             = 0;
1398ab93d7beSBarry Smith   }
1399ab93d7beSBarry Smith 
1400435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3;
140108401ef6SPierre Jolivet   PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz);
140249b5e25fSSatish Balay   if (nnz) {
140349b5e25fSSatish Balay     for (i = 0; i < mbs; i++) {
140408401ef6SPierre 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]);
140508401ef6SPierre 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);
140649b5e25fSSatish Balay     }
140749b5e25fSSatish Balay   }
140849b5e25fSSatish Balay 
1409db4efbfdSBarry Smith   B->ops->mult             = MatMult_SeqSBAIJ_N;
1410db4efbfdSBarry Smith   B->ops->multadd          = MatMultAdd_SeqSBAIJ_N;
1411db4efbfdSBarry Smith   B->ops->multtranspose    = MatMult_SeqSBAIJ_N;
1412db4efbfdSBarry Smith   B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N;
141326fbe8dcSKarl Rupp 
14149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL));
141549b5e25fSSatish Balay   if (!flg) {
141649b5e25fSSatish Balay     switch (bs) {
141749b5e25fSSatish Balay     case 1:
141849b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_1;
141949b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_1;
1420431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_1;
1421431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1;
142249b5e25fSSatish Balay       break;
142349b5e25fSSatish Balay     case 2:
142449b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_2;
142549b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_2;
1426431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_2;
1427431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2;
142849b5e25fSSatish Balay       break;
142949b5e25fSSatish Balay     case 3:
143049b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_3;
143149b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_3;
1432431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_3;
1433431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3;
143449b5e25fSSatish Balay       break;
143549b5e25fSSatish Balay     case 4:
143649b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_4;
143749b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_4;
1438431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_4;
1439431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4;
144049b5e25fSSatish Balay       break;
144149b5e25fSSatish Balay     case 5:
144249b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_5;
144349b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_5;
1444431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_5;
1445431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5;
144649b5e25fSSatish Balay       break;
144749b5e25fSSatish Balay     case 6:
144849b5e25fSSatish Balay       B->ops->mult             = MatMult_SeqSBAIJ_6;
144949b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_6;
1450431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_6;
1451431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6;
145249b5e25fSSatish Balay       break;
145349b5e25fSSatish Balay     case 7:
1454de53e5efSHong Zhang       B->ops->mult             = MatMult_SeqSBAIJ_7;
145549b5e25fSSatish Balay       B->ops->multadd          = MatMultAdd_SeqSBAIJ_7;
1456431c96f7SBarry Smith       B->ops->multtranspose    = MatMult_SeqSBAIJ_7;
1457431c96f7SBarry Smith       B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7;
145849b5e25fSSatish Balay       break;
145949b5e25fSSatish Balay     }
146049b5e25fSSatish Balay   }
146149b5e25fSSatish Balay 
146249b5e25fSSatish Balay   b->mbs = mbs;
14634dcd73b1SHong Zhang   b->nbs = nbs;
1464ab93d7beSBarry Smith   if (!skipallocation) {
14652ee49352SLisandro Dalcin     if (!b->imax) {
14669566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(mbs, &b->imax, mbs, &b->ilen));
146726fbe8dcSKarl Rupp 
1468c760cd28SBarry Smith       b->free_imax_ilen = PETSC_TRUE;
14692ee49352SLisandro Dalcin     }
147049b5e25fSSatish Balay     if (!nnz) {
1471435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
147249b5e25fSSatish Balay       else if (nz <= 0) nz = 1;
14735d2a9ed1SStefano Zampini       nz = PetscMin(nbs, nz);
147426fbe8dcSKarl Rupp       for (i = 0; i < mbs; i++) b->imax[i] = nz;
14759566063dSJacob Faibussowitsch       PetscCall(PetscIntMultError(nz, mbs, &nz));
147649b5e25fSSatish Balay     } else {
1477c73702f5SBarry Smith       PetscInt64 nz64 = 0;
14789371c9d4SSatish Balay       for (i = 0; i < mbs; i++) {
14799371c9d4SSatish Balay         b->imax[i] = nnz[i];
14809371c9d4SSatish Balay         nz64 += nnz[i];
14819371c9d4SSatish Balay       }
14829566063dSJacob Faibussowitsch       PetscCall(PetscIntCast(nz64, &nz));
148349b5e25fSSatish Balay     }
14842ee49352SLisandro Dalcin     /* b->ilen will count nonzeros in each block row so far. */
148526fbe8dcSKarl Rupp     for (i = 0; i < mbs; i++) b->ilen[i] = 0;
14866c6c5352SBarry Smith     /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */
148749b5e25fSSatish Balay 
148849b5e25fSSatish Balay     /* allocate the matrix space */
14899566063dSJacob Faibussowitsch     PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i));
14909f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(bs2 * nz, sizeof(PetscScalar), (void **)&b->a));
14919f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&b->j));
14929f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(B->rmap->n + 1, sizeof(PetscInt), (void **)&b->i));
14939f0612e4SBarry Smith     b->free_a  = PETSC_TRUE;
14949f0612e4SBarry Smith     b->free_ij = PETSC_TRUE;
14959566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->a, nz * bs2));
14969566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->j, nz));
14979f0612e4SBarry Smith     b->free_a  = PETSC_TRUE;
14989f0612e4SBarry Smith     b->free_ij = PETSC_TRUE;
149949b5e25fSSatish Balay 
150049b5e25fSSatish Balay     /* pointer to beginning of each row */
1501e60cf9a0SBarry Smith     b->i[0] = 0;
150226fbe8dcSKarl Rupp     for (i = 1; i < mbs + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1];
150326fbe8dcSKarl Rupp 
1504e811da20SHong Zhang   } else {
1505e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
1506e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
1507ab93d7beSBarry Smith   }
150849b5e25fSSatish Balay 
150949b5e25fSSatish Balay   b->bs2     = bs2;
15106c6c5352SBarry Smith   b->nz      = 0;
1511b32cb4a7SJed Brown   b->maxnz   = nz;
1512f4259b30SLisandro Dalcin   b->inew    = NULL;
1513f4259b30SLisandro Dalcin   b->jnew    = NULL;
1514f4259b30SLisandro Dalcin   b->anew    = NULL;
1515f4259b30SLisandro Dalcin   b->a2anew  = NULL;
15161a3463dfSHong Zhang   b->permute = PETSC_FALSE;
1517cb7b82ddSBarry Smith 
1518cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
1519cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
15209566063dSJacob Faibussowitsch   if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
15213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1522c464158bSHong Zhang }
1523153ea458SHong Zhang 
MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ(Mat B,PetscInt bs,const PetscInt ii[],const PetscInt jj[],const PetscScalar V[])1524ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ(Mat B, PetscInt bs, const PetscInt ii[], const PetscInt jj[], const PetscScalar V[])
1525d71ae5a4SJacob Faibussowitsch {
15260cd7f59aSBarry Smith   PetscInt      i, j, m, nz, anz, nz_max = 0, *nnz;
1527f4259b30SLisandro Dalcin   PetscScalar  *values      = NULL;
15281c466ed6SStefano Zampini   Mat_SeqSBAIJ *b           = (Mat_SeqSBAIJ *)B->data;
15291c466ed6SStefano Zampini   PetscBool     roworiented = b->roworiented;
15301c466ed6SStefano Zampini   PetscBool     ilw         = b->ignore_ltriangular;
15310cd7f59aSBarry Smith 
153238f409ebSLisandro Dalcin   PetscFunctionBegin;
153308401ef6SPierre Jolivet   PetscCheck(bs >= 1, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_OUTOFRANGE, "Invalid block size specified, must be positive but it is %" PetscInt_FMT, bs);
15349566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(B->rmap, bs));
15359566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(B->cmap, bs));
15369566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
15379566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
15389566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs));
153938f409ebSLisandro Dalcin   m = B->rmap->n / bs;
154038f409ebSLisandro Dalcin 
1541aed4548fSBarry Smith   PetscCheck(!ii[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ii[0] must be 0 but it is %" PetscInt_FMT, ii[0]);
15429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &nnz));
154338f409ebSLisandro Dalcin   for (i = 0; i < m; i++) {
154438f409ebSLisandro Dalcin     nz = ii[i + 1] - ii[i];
154508401ef6SPierre Jolivet     PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz);
15461c466ed6SStefano Zampini     PetscCheckSorted(nz, jj + ii[i]);
15470cd7f59aSBarry Smith     anz = 0;
15480cd7f59aSBarry Smith     for (j = 0; j < nz; j++) {
15490cd7f59aSBarry Smith       /* count only values on the diagonal or above */
15500cd7f59aSBarry Smith       if (jj[ii[i] + j] >= i) {
15510cd7f59aSBarry Smith         anz = nz - j;
15520cd7f59aSBarry Smith         break;
15530cd7f59aSBarry Smith       }
15540cd7f59aSBarry Smith     }
15551c466ed6SStefano Zampini     nz_max = PetscMax(nz_max, nz);
15560cd7f59aSBarry Smith     nnz[i] = anz;
155738f409ebSLisandro Dalcin   }
15589566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz));
15599566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
156038f409ebSLisandro Dalcin 
156138f409ebSLisandro Dalcin   values = (PetscScalar *)V;
156248a46eb9SPierre Jolivet   if (!values) PetscCall(PetscCalloc1(bs * bs * nz_max, &values));
15631c466ed6SStefano Zampini   b->ignore_ltriangular = PETSC_TRUE;
156438f409ebSLisandro Dalcin   for (i = 0; i < m; i++) {
156538f409ebSLisandro Dalcin     PetscInt        ncols = ii[i + 1] - ii[i];
156638f409ebSLisandro Dalcin     const PetscInt *icols = jj + ii[i];
15671c466ed6SStefano Zampini 
156838f409ebSLisandro Dalcin     if (!roworiented || bs == 1) {
156938f409ebSLisandro Dalcin       const PetscScalar *svals = values + (V ? (bs * bs * ii[i]) : 0);
15709566063dSJacob Faibussowitsch       PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, ncols, icols, svals, INSERT_VALUES));
157138f409ebSLisandro Dalcin     } else {
157238f409ebSLisandro Dalcin       for (j = 0; j < ncols; j++) {
157338f409ebSLisandro Dalcin         const PetscScalar *svals = values + (V ? (bs * bs * (ii[i] + j)) : 0);
15749566063dSJacob Faibussowitsch         PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, 1, &icols[j], svals, INSERT_VALUES));
157538f409ebSLisandro Dalcin       }
157638f409ebSLisandro Dalcin     }
157738f409ebSLisandro Dalcin   }
15789566063dSJacob Faibussowitsch   if (!V) PetscCall(PetscFree(values));
15799566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
15809566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
15819566063dSJacob Faibussowitsch   PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
15821c466ed6SStefano Zampini   b->ignore_ltriangular = ilw;
15833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
158438f409ebSLisandro Dalcin }
158538f409ebSLisandro Dalcin 
1586db4efbfdSBarry Smith /*
1587db4efbfdSBarry Smith    This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization
1588db4efbfdSBarry Smith */
MatSeqSBAIJSetNumericFactorization_inplace(Mat B,PetscBool natural)1589d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetNumericFactorization_inplace(Mat B, PetscBool natural)
1590d71ae5a4SJacob Faibussowitsch {
1591ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
1592db4efbfdSBarry Smith   PetscInt  bs  = B->rmap->bs;
1593db4efbfdSBarry Smith 
1594db4efbfdSBarry Smith   PetscFunctionBegin;
15959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL));
1596db4efbfdSBarry Smith   if (flg) bs = 8;
1597db4efbfdSBarry Smith 
1598db4efbfdSBarry Smith   if (!natural) {
1599db4efbfdSBarry Smith     switch (bs) {
1600d71ae5a4SJacob Faibussowitsch     case 1:
1601d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_inplace;
1602d71ae5a4SJacob Faibussowitsch       break;
1603d71ae5a4SJacob Faibussowitsch     case 2:
1604d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2;
1605d71ae5a4SJacob Faibussowitsch       break;
1606d71ae5a4SJacob Faibussowitsch     case 3:
1607d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3;
1608d71ae5a4SJacob Faibussowitsch       break;
1609d71ae5a4SJacob Faibussowitsch     case 4:
1610d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4;
1611d71ae5a4SJacob Faibussowitsch       break;
1612d71ae5a4SJacob Faibussowitsch     case 5:
1613d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5;
1614d71ae5a4SJacob Faibussowitsch       break;
1615d71ae5a4SJacob Faibussowitsch     case 6:
1616d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6;
1617d71ae5a4SJacob Faibussowitsch       break;
1618d71ae5a4SJacob Faibussowitsch     case 7:
1619d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7;
1620d71ae5a4SJacob Faibussowitsch       break;
1621d71ae5a4SJacob Faibussowitsch     default:
1622d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N;
1623d71ae5a4SJacob Faibussowitsch       break;
1624db4efbfdSBarry Smith     }
1625db4efbfdSBarry Smith   } else {
1626db4efbfdSBarry Smith     switch (bs) {
1627d71ae5a4SJacob Faibussowitsch     case 1:
1628d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering_inplace;
1629d71ae5a4SJacob Faibussowitsch       break;
1630d71ae5a4SJacob Faibussowitsch     case 2:
1631d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering;
1632d71ae5a4SJacob Faibussowitsch       break;
1633d71ae5a4SJacob Faibussowitsch     case 3:
1634d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering;
1635d71ae5a4SJacob Faibussowitsch       break;
1636d71ae5a4SJacob Faibussowitsch     case 4:
1637d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering;
1638d71ae5a4SJacob Faibussowitsch       break;
1639d71ae5a4SJacob Faibussowitsch     case 5:
1640d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering;
1641d71ae5a4SJacob Faibussowitsch       break;
1642d71ae5a4SJacob Faibussowitsch     case 6:
1643d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering;
1644d71ae5a4SJacob Faibussowitsch       break;
1645d71ae5a4SJacob Faibussowitsch     case 7:
1646d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering;
1647d71ae5a4SJacob Faibussowitsch       break;
1648d71ae5a4SJacob Faibussowitsch     default:
1649d71ae5a4SJacob Faibussowitsch       B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering;
1650d71ae5a4SJacob Faibussowitsch       break;
1651db4efbfdSBarry Smith     }
1652db4efbfdSBarry Smith   }
16533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1654db4efbfdSBarry Smith }
1655db4efbfdSBarry Smith 
1656cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType, MatReuse, Mat *);
1657cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType, MatReuse, Mat *);
MatFactorGetSolverType_petsc(Mat A,MatSolverType * type)1658d71ae5a4SJacob Faibussowitsch static PetscErrorCode       MatFactorGetSolverType_petsc(Mat A, MatSolverType *type)
1659d71ae5a4SJacob Faibussowitsch {
16604ac6704cSBarry Smith   PetscFunctionBegin;
16614ac6704cSBarry Smith   *type = MATSOLVERPETSC;
16623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16634ac6704cSBarry Smith }
1664d769727bSBarry Smith 
MatGetFactor_seqsbaij_petsc(Mat A,MatFactorType ftype,Mat * B)1665d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A, MatFactorType ftype, Mat *B)
1666d71ae5a4SJacob Faibussowitsch {
1667d0f46423SBarry Smith   PetscInt n = A->rmap->n;
16685c9eb25fSBarry Smith 
16695c9eb25fSBarry Smith   PetscFunctionBegin;
1670*fc2fb351SPierre Jolivet   if (PetscDefined(USE_COMPLEX) && (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) && A->hermitian == PETSC_BOOL3_TRUE && A->symmetric != PETSC_BOOL3_TRUE) {
167103e5aca4SStefano Zampini     PetscCall(PetscInfo(A, "Hermitian MAT_FACTOR_CHOLESKY or MAT_FACTOR_ICC are not supported. Use MAT_FACTOR_LU instead.\n"));
167203e5aca4SStefano Zampini     *B = NULL;
167303e5aca4SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
167403e5aca4SStefano Zampini   }
1675eb1ec7c1SStefano Zampini 
16769566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B));
16779566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*B, n, n, n, n));
1678966bd95aSPierre Jolivet   PetscCheck(ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC, PETSC_COMM_SELF, PETSC_ERR_SUP, "Factor type not supported");
16799566063dSJacob Faibussowitsch   PetscCall(MatSetType(*B, MATSEQSBAIJ));
16809566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*B, A->rmap->bs, MAT_SKIP_ALLOCATION, NULL));
168126fbe8dcSKarl Rupp 
16827b056e98SHong Zhang   (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ;
1683c6d0d4f0SHong Zhang   (*B)->ops->iccfactorsymbolic      = MatICCFactorSymbolic_SeqSBAIJ;
16849566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_CHOLESKY]));
16859566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_ICC]));
168600c67f3bSHong Zhang 
1687d5f3da31SBarry Smith   (*B)->factortype     = ftype;
1688f73b0415SBarry Smith   (*B)->canuseordering = PETSC_TRUE;
16899566063dSJacob Faibussowitsch   PetscCall(PetscFree((*B)->solvertype));
16909566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*B)->solvertype));
16919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)*B, "MatFactorGetSolverType_C", MatFactorGetSolverType_petsc));
16923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16935c9eb25fSBarry Smith }
16945c9eb25fSBarry Smith 
16958397e458SBarry Smith /*@C
16962ef1f0ffSBarry Smith   MatSeqSBAIJGetArray - gives access to the array where the numerical data for a `MATSEQSBAIJ` matrix is stored
16978397e458SBarry Smith 
16988397e458SBarry Smith   Not Collective
16998397e458SBarry Smith 
17008397e458SBarry Smith   Input Parameter:
1701fe59aa6dSJacob Faibussowitsch . A - a `MATSEQSBAIJ` matrix
17028397e458SBarry Smith 
17038397e458SBarry Smith   Output Parameter:
17048397e458SBarry Smith . array - pointer to the data
17058397e458SBarry Smith 
17068397e458SBarry Smith   Level: intermediate
17078397e458SBarry Smith 
17081cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatSeqSBAIJRestoreArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`
17098397e458SBarry Smith @*/
MatSeqSBAIJGetArray(Mat A,PetscScalar * array[])17105d83a8b1SBarry Smith PetscErrorCode MatSeqSBAIJGetArray(Mat A, PetscScalar *array[])
1711d71ae5a4SJacob Faibussowitsch {
17128397e458SBarry Smith   PetscFunctionBegin;
1713cac4c232SBarry Smith   PetscUseMethod(A, "MatSeqSBAIJGetArray_C", (Mat, PetscScalar **), (A, array));
17143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17158397e458SBarry Smith }
17168397e458SBarry Smith 
17178397e458SBarry Smith /*@C
17182ef1f0ffSBarry Smith   MatSeqSBAIJRestoreArray - returns access to the array where the numerical data for a `MATSEQSBAIJ` matrix is stored obtained by `MatSeqSBAIJGetArray()`
17198397e458SBarry Smith 
17208397e458SBarry Smith   Not Collective
17218397e458SBarry Smith 
17228397e458SBarry Smith   Input Parameters:
1723fe59aa6dSJacob Faibussowitsch + A     - a `MATSEQSBAIJ` matrix
1724a2b725a8SWilliam Gropp - array - pointer to the data
17258397e458SBarry Smith 
17268397e458SBarry Smith   Level: intermediate
17278397e458SBarry Smith 
17281cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatSeqSBAIJGetArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`
17298397e458SBarry Smith @*/
MatSeqSBAIJRestoreArray(Mat A,PetscScalar * array[])17305d83a8b1SBarry Smith PetscErrorCode MatSeqSBAIJRestoreArray(Mat A, PetscScalar *array[])
1731d71ae5a4SJacob Faibussowitsch {
17328397e458SBarry Smith   PetscFunctionBegin;
1733cac4c232SBarry Smith   PetscUseMethod(A, "MatSeqSBAIJRestoreArray_C", (Mat, PetscScalar **), (A, array));
17343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17358397e458SBarry Smith }
17368397e458SBarry Smith 
17370bad9183SKris Buschelman /*MC
1738fafad747SKris Buschelman   MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices,
17390bad9183SKris Buschelman   based on block compressed sparse row format.  Only the upper triangular portion of the matrix is stored.
17400bad9183SKris Buschelman 
1741828413b8SBarry Smith   For complex numbers by default this matrix is symmetric, NOT Hermitian symmetric. To make it Hermitian symmetric you
174211a5261eSBarry Smith   can call `MatSetOption`(`Mat`, `MAT_HERMITIAN`).
1743828413b8SBarry Smith 
17442ef1f0ffSBarry Smith   Options Database Key:
174511a5261eSBarry Smith   . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to `MatSetFromOptions()`
17460bad9183SKris Buschelman 
17472ef1f0ffSBarry Smith   Level: beginner
17482ef1f0ffSBarry Smith 
174995452b02SPatrick Sanan   Notes:
175095452b02SPatrick Sanan   By default if you insert values into the lower triangular part of the matrix they are simply ignored (since they are not
175111a5261eSBarry 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
17522ef1f0ffSBarry 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.
175371dad5bbSBarry Smith 
1754476417e5SBarry Smith   The number of rows in the matrix must be less than or equal to the number of columns
175571dad5bbSBarry Smith 
17561cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreateSeqSBAIJ()`, `MatType`, `MATMPISBAIJ`
17570bad9183SKris Buschelman M*/
MatCreate_SeqSBAIJ(Mat B)1758d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_SeqSBAIJ(Mat B)
1759d71ae5a4SJacob Faibussowitsch {
1760a23d5eceSKris Buschelman   Mat_SeqSBAIJ *b;
176113f74950SBarry Smith   PetscMPIInt   size;
1762ace3abfcSBarry Smith   PetscBool     no_unroll = PETSC_FALSE, no_inode = PETSC_FALSE;
1763a23d5eceSKris Buschelman 
1764a23d5eceSKris Buschelman   PetscFunctionBegin;
17659566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
176608401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
1767a23d5eceSKris Buschelman 
17684dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
1769a23d5eceSKris Buschelman   B->data   = (void *)b;
1770aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
177126fbe8dcSKarl Rupp 
1772a23d5eceSKris Buschelman   B->ops->destroy    = MatDestroy_SeqSBAIJ;
1773a23d5eceSKris Buschelman   B->ops->view       = MatView_SeqSBAIJ;
1774f4259b30SLisandro Dalcin   b->row             = NULL;
1775f4259b30SLisandro Dalcin   b->icol            = NULL;
1776a23d5eceSKris Buschelman   b->reallocs        = 0;
1777f4259b30SLisandro Dalcin   b->saved_values    = NULL;
17780def2e27SBarry Smith   b->inode.limit     = 5;
17790def2e27SBarry Smith   b->inode.max_limit = 5;
1780a23d5eceSKris Buschelman 
1781a23d5eceSKris Buschelman   b->roworiented        = PETSC_TRUE;
1782a23d5eceSKris Buschelman   b->nonew              = 0;
1783f4259b30SLisandro Dalcin   b->diag               = NULL;
1784f4259b30SLisandro Dalcin   b->solve_work         = NULL;
1785f4259b30SLisandro Dalcin   b->mult_work          = NULL;
1786f4259b30SLisandro Dalcin   B->spptr              = NULL;
1787f2cbd3d5SJed Brown   B->info.nz_unneeded   = (PetscReal)b->maxnz * b->bs2;
1788a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
1789a23d5eceSKris Buschelman 
1790f4259b30SLisandro Dalcin   b->inew    = NULL;
1791f4259b30SLisandro Dalcin   b->jnew    = NULL;
1792f4259b30SLisandro Dalcin   b->anew    = NULL;
1793f4259b30SLisandro Dalcin   b->a2anew  = NULL;
1794a23d5eceSKris Buschelman   b->permute = PETSC_FALSE;
1795a23d5eceSKris Buschelman 
179671dad5bbSBarry Smith   b->ignore_ltriangular = PETSC_TRUE;
179726fbe8dcSKarl Rupp 
17989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_ignore_lower_triangular", &b->ignore_ltriangular, NULL));
1799941593c8SHong Zhang 
1800f5edf698SHong Zhang   b->getrow_utriangular = PETSC_FALSE;
180126fbe8dcSKarl Rupp 
18029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_getrow_uppertriangular", &b->getrow_utriangular, NULL));
1803f5edf698SHong Zhang 
18049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJGetArray_C", MatSeqSBAIJGetArray_SeqSBAIJ));
18059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJRestoreArray_C", MatSeqSBAIJRestoreArray_SeqSBAIJ));
18069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqSBAIJ));
18079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqSBAIJ));
18089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetColumnIndices_C", MatSeqSBAIJSetColumnIndices_SeqSBAIJ));
18099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqaij_C", MatConvert_SeqSBAIJ_SeqAIJ));
18109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqbaij_C", MatConvert_SeqSBAIJ_SeqBAIJ));
18119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocation_C", MatSeqSBAIJSetPreallocation_SeqSBAIJ));
18129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocationCSR_C", MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ));
18136214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
18149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_elemental_C", MatConvert_SeqSBAIJ_Elemental));
18156214f412SHong Zhang #endif
1816d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE))
18179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_scalapack_C", MatConvert_SBAIJ_ScaLAPACK));
1818d24d4204SJose E. Roman #endif
181923ce1328SBarry Smith 
1820b94d7dedSBarry Smith   B->symmetry_eternal            = PETSC_TRUE;
1821b94d7dedSBarry Smith   B->structural_symmetry_eternal = PETSC_TRUE;
1822b94d7dedSBarry Smith   B->symmetric                   = PETSC_BOOL3_TRUE;
1823b94d7dedSBarry Smith   B->structurally_symmetric      = PETSC_BOOL3_TRUE;
1824b0c98d1dSPierre Jolivet #if !defined(PETSC_USE_COMPLEX)
1825b94d7dedSBarry Smith   B->hermitian = PETSC_BOOL3_TRUE;
1826eb1ec7c1SStefano Zampini #endif
182713647f61SHong Zhang 
18289566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQSBAIJ));
18290def2e27SBarry Smith 
1830d0609cedSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)B), ((PetscObject)B)->prefix, "Options for SEQSBAIJ matrix", "Mat");
18319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_no_unroll", "Do not optimize for inodes (slower)", NULL, no_unroll, &no_unroll, NULL));
183248a46eb9SPierre Jolivet   if (no_unroll) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_unroll\n"));
18339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_no_inode", "Do not optimize for inodes (slower)", NULL, no_inode, &no_inode, NULL));
18349566063dSJacob Faibussowitsch   if (no_inode) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_inode\n"));
1835e87b5d96SPierre Jolivet   PetscCall(PetscOptionsInt("-mat_inode_limit", "Do not use inodes larger than this value", NULL, b->inode.limit, &b->inode.limit, NULL));
1836d0609cedSBarry Smith   PetscOptionsEnd();
1837ace3abfcSBarry Smith   b->inode.use = (PetscBool)(!(no_unroll || no_inode));
18380def2e27SBarry Smith   if (b->inode.limit > b->inode.max_limit) b->inode.limit = b->inode.max_limit;
18393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1840a23d5eceSKris Buschelman }
1841a23d5eceSKris Buschelman 
18425d83a8b1SBarry Smith /*@
1843a23d5eceSKris Buschelman   MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block
184411a5261eSBarry Smith   compressed row) `MATSEQSBAIJ` format.  For good matrix assembly performance the
184520f4b53cSBarry Smith   user should preallocate the matrix storage by setting the parameter `nz`
184620f4b53cSBarry Smith   (or the array `nnz`).
1847a23d5eceSKris Buschelman 
1848c3339decSBarry Smith   Collective
1849a23d5eceSKris Buschelman 
1850a23d5eceSKris Buschelman   Input Parameters:
18511c4f3114SJed Brown + B   - the symmetric matrix
185211a5261eSBarry 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
185311a5261eSBarry Smith         blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with `MatCreateVecs()`
1854a23d5eceSKris Buschelman . nz  - number of block nonzeros per block row (same for all rows)
1855a23d5eceSKris Buschelman - nnz - array containing the number of block nonzeros in the upper triangular plus
18562ef1f0ffSBarry Smith         diagonal portion of each block (possibly different for each block row) or `NULL`
1857a23d5eceSKris Buschelman 
1858a23d5eceSKris Buschelman   Options Database Keys:
1859d8a51d2aSBarry Smith + -mat_no_unroll  - uses code that does not unroll the loops in the block calculations (much slower)
1860a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use (only works if a negative bs is passed in
1861a23d5eceSKris Buschelman 
1862a23d5eceSKris Buschelman   Level: intermediate
1863a23d5eceSKris Buschelman 
1864a23d5eceSKris Buschelman   Notes:
186520f4b53cSBarry Smith   Specify the preallocated storage with either `nz` or `nnz` (not both).
18662ef1f0ffSBarry Smith   Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory
1867651615e1SBarry Smith   allocation.  See [Sparse Matrices](sec_matsparse) for details.
1868a23d5eceSKris Buschelman 
186911a5261eSBarry Smith   You can call `MatGetInfo()` to get information on how effective the preallocation was;
1870aa95bbe8SBarry Smith   for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
18712ef1f0ffSBarry Smith   You can also run with the option `-info` and look for messages with the string
1872aa95bbe8SBarry Smith   malloc in them to see if additional memory allocation was needed.
1873aa95bbe8SBarry Smith 
18742ef1f0ffSBarry Smith   If the `nnz` parameter is given then the `nz` parameter is ignored
187549a6f317SBarry Smith 
18761cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()`
1877a23d5eceSKris Buschelman @*/
MatSeqSBAIJSetPreallocation(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[])1878d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetPreallocation(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[])
1879d71ae5a4SJacob Faibussowitsch {
1880a23d5eceSKris Buschelman   PetscFunctionBegin;
18816ba663aaSJed Brown   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
18826ba663aaSJed Brown   PetscValidType(B, 1);
18836ba663aaSJed Brown   PetscValidLogicalCollectiveInt(B, bs, 2);
1884cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqSBAIJSetPreallocation_C", (Mat, PetscInt, PetscInt, const PetscInt[]), (B, bs, nz, nnz));
18853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1886a23d5eceSKris Buschelman }
188749b5e25fSSatish Balay 
188838f409ebSLisandro Dalcin /*@C
188911a5261eSBarry Smith   MatSeqSBAIJSetPreallocationCSR - Creates a sparse parallel matrix in `MATSEQSBAIJ` format using the given nonzero structure and (optional) numerical values
189038f409ebSLisandro Dalcin 
189138f409ebSLisandro Dalcin   Input Parameters:
18921c4f3114SJed Brown + B  - the matrix
1893eab78319SHong Zhang . bs - size of block, the blocks are ALWAYS square.
1894d8a51d2aSBarry Smith . i  - the indices into `j` for the start of each local row (indices start with zero)
1895d8a51d2aSBarry Smith . j  - the column indices for each local row (indices start with zero) these must be sorted for each row
1896d8a51d2aSBarry Smith - v  - optional values in the matrix, use `NULL` if not provided
189738f409ebSLisandro Dalcin 
1898664954b6SBarry Smith   Level: advanced
189938f409ebSLisandro Dalcin 
190038f409ebSLisandro Dalcin   Notes:
1901d8a51d2aSBarry Smith   The `i`,`j`,`v` values are COPIED with this routine; to avoid the copy use `MatCreateSeqSBAIJWithArrays()`
1902d8a51d2aSBarry Smith 
190311a5261eSBarry Smith   The order of the entries in values is specified by the `MatOption` `MAT_ROW_ORIENTED`.  For example, C programs
190411a5261eSBarry 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
190538f409ebSLisandro Dalcin   over rows within a block and the last index is over columns within a block row.  Fortran programs will likely set
190611a5261eSBarry 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
190738f409ebSLisandro Dalcin   block column and the second index is over columns within a block.
190838f409ebSLisandro Dalcin 
1909d8a51d2aSBarry Smith   Any entries provided that lie below the diagonal are ignored
19100cd7f59aSBarry Smith 
19110cd7f59aSBarry Smith   Though this routine has Preallocation() in the name it also sets the exact nonzero locations of the matrix entries
19120cd7f59aSBarry Smith   and usually the numerical values as well
1913664954b6SBarry Smith 
1914fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqSBAIJ()`, `MatSetValuesBlocked()`, `MatSeqSBAIJSetPreallocation()`
191538f409ebSLisandro Dalcin @*/
MatSeqSBAIJSetPreallocationCSR(Mat B,PetscInt bs,const PetscInt i[],const PetscInt j[],const PetscScalar v[])1916d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetPreallocationCSR(Mat B, PetscInt bs, const PetscInt i[], const PetscInt j[], const PetscScalar v[])
1917d71ae5a4SJacob Faibussowitsch {
191838f409ebSLisandro Dalcin   PetscFunctionBegin;
191938f409ebSLisandro Dalcin   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
192038f409ebSLisandro Dalcin   PetscValidType(B, 1);
192138f409ebSLisandro Dalcin   PetscValidLogicalCollectiveInt(B, bs, 2);
1922cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqSBAIJSetPreallocationCSR_C", (Mat, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, bs, i, j, v));
19233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
192438f409ebSLisandro Dalcin }
192538f409ebSLisandro Dalcin 
19265d83a8b1SBarry Smith /*@
19272ef1f0ffSBarry Smith   MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in (block
192811a5261eSBarry Smith   compressed row) `MATSEQSBAIJ` format.  For good matrix assembly performance the
19292ef1f0ffSBarry Smith   user should preallocate the matrix storage by setting the parameter `nz`
19302ef1f0ffSBarry Smith   (or the array `nnz`).
193149b5e25fSSatish Balay 
1932d083f849SBarry Smith   Collective
1933c464158bSHong Zhang 
1934c464158bSHong Zhang   Input Parameters:
193511a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
193611a5261eSBarry 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
1937bb7ae925SBarry Smith           blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with MatCreateVecs()
193820f4b53cSBarry Smith . m    - number of rows
193920f4b53cSBarry Smith . n    - number of columns
1940c464158bSHong Zhang . nz   - number of block nonzeros per block row (same for all rows)
1941744e8345SSatish Balay - nnz  - array containing the number of block nonzeros in the upper triangular plus
19422ef1f0ffSBarry Smith          diagonal portion of each block (possibly different for each block row) or `NULL`
1943c464158bSHong Zhang 
1944c464158bSHong Zhang   Output Parameter:
1945c464158bSHong Zhang . A - the symmetric matrix
1946c464158bSHong Zhang 
1947c464158bSHong Zhang   Options Database Keys:
1948d8a51d2aSBarry Smith + -mat_no_unroll  - uses code that does not unroll the loops in the block calculations (much slower)
1949a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use
1950c464158bSHong Zhang 
1951c464158bSHong Zhang   Level: intermediate
1952c464158bSHong Zhang 
19532ef1f0ffSBarry Smith   Notes:
195477433607SBarry Smith   It is recommended that one use `MatCreateFromOptions()` or the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`,
1955f6f02116SRichard Tran Mills   MatXXXXSetPreallocation() paradigm instead of this routine directly.
195611a5261eSBarry Smith   [MatXXXXSetPreallocation() is, for example, `MatSeqAIJSetPreallocation()`]
1957175b88e8SBarry Smith 
19586d6d819aSHong Zhang   The number of rows and columns must be divisible by blocksize.
19596d6d819aSHong Zhang   This matrix type does not support complex Hermitian operation.
1960c464158bSHong Zhang 
19612ef1f0ffSBarry Smith   Specify the preallocated storage with either `nz` or `nnz` (not both).
19622ef1f0ffSBarry Smith   Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory
1963651615e1SBarry Smith   allocation.  See [Sparse Matrices](sec_matsparse) for details.
1964c464158bSHong Zhang 
19652ef1f0ffSBarry Smith   If the `nnz` parameter is given then the `nz` parameter is ignored
196649a6f317SBarry Smith 
19671cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()`
1968c464158bSHong Zhang @*/
MatCreateSeqSBAIJ(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat * A)1969d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqSBAIJ(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A)
1970d71ae5a4SJacob Faibussowitsch {
1971c464158bSHong Zhang   PetscFunctionBegin;
19729566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
19739566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
19749566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQSBAIJ));
19759566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*A, bs, nz, (PetscInt *)nnz));
19763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
197749b5e25fSSatish Balay }
197849b5e25fSSatish Balay 
MatDuplicate_SeqSBAIJ(Mat A,MatDuplicateOption cpvalues,Mat * B)1979d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B)
1980d71ae5a4SJacob Faibussowitsch {
198149b5e25fSSatish Balay   Mat           C;
198249b5e25fSSatish Balay   Mat_SeqSBAIJ *c, *a  = (Mat_SeqSBAIJ *)A->data;
1983b40805acSSatish Balay   PetscInt      i, mbs = a->mbs, nz = a->nz, bs2 = a->bs2;
198449b5e25fSSatish Balay 
198549b5e25fSSatish Balay   PetscFunctionBegin;
198631fe6a7dSBarry Smith   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix");
198708401ef6SPierre Jolivet   PetscCheck(a->i[mbs] == nz, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupt matrix");
198849b5e25fSSatish Balay 
1989f4259b30SLisandro Dalcin   *B = NULL;
19909566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
19919566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, A->rmap->N, A->cmap->n, A->rmap->N, A->cmap->n));
19929566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(C, A, A));
19939566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATSEQSBAIJ));
1994692f9cbeSHong Zhang   c = (Mat_SeqSBAIJ *)C->data;
1995692f9cbeSHong Zhang 
1996273d9f13SBarry Smith   C->preallocated       = PETSC_TRUE;
1997d5f3da31SBarry Smith   C->factortype         = A->factortype;
1998f4259b30SLisandro Dalcin   c->row                = NULL;
1999f4259b30SLisandro Dalcin   c->icol               = NULL;
2000f4259b30SLisandro Dalcin   c->saved_values       = NULL;
2001a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
200249b5e25fSSatish Balay   C->assembled          = PETSC_TRUE;
200349b5e25fSSatish Balay 
20049566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->rmap, &C->rmap));
20059566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap, &C->cmap));
200649b5e25fSSatish Balay   c->bs2 = a->bs2;
200749b5e25fSSatish Balay   c->mbs = a->mbs;
200849b5e25fSSatish Balay   c->nbs = a->nbs;
200949b5e25fSSatish Balay 
2010c760cd28SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2011c760cd28SBarry Smith     c->imax           = a->imax;
2012c760cd28SBarry Smith     c->ilen           = a->ilen;
2013c760cd28SBarry Smith     c->free_imax_ilen = PETSC_FALSE;
2014c760cd28SBarry Smith   } else {
201557508eceSPierre Jolivet     PetscCall(PetscMalloc2(mbs + 1, &c->imax, mbs + 1, &c->ilen));
201649b5e25fSSatish Balay     for (i = 0; i < mbs; i++) {
201749b5e25fSSatish Balay       c->imax[i] = a->imax[i];
201849b5e25fSSatish Balay       c->ilen[i] = a->ilen[i];
201949b5e25fSSatish Balay     }
2020c760cd28SBarry Smith     c->free_imax_ilen = PETSC_TRUE;
2021c760cd28SBarry Smith   }
202249b5e25fSSatish Balay 
202349b5e25fSSatish Balay   /* allocate the matrix space */
20249f0612e4SBarry Smith   PetscCall(PetscShmgetAllocateArray(bs2 * nz, sizeof(PetscScalar), (void **)&c->a));
20259f0612e4SBarry Smith   c->free_a = PETSC_TRUE;
20264da8f245SBarry Smith   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
20279f0612e4SBarry Smith     PetscCall(PetscArrayzero(c->a, bs2 * nz));
202844e1c64aSLisandro Dalcin     c->i       = a->i;
202944e1c64aSLisandro Dalcin     c->j       = a->j;
20304da8f245SBarry Smith     c->free_ij = PETSC_FALSE;
20314da8f245SBarry Smith     c->parent  = A;
20329566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)A));
20339566063dSJacob Faibussowitsch     PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
20349566063dSJacob Faibussowitsch     PetscCall(MatSetOption(C, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
20354da8f245SBarry Smith   } else {
20369f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&c->j));
20379f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(mbs + 1, sizeof(PetscInt), (void **)&c->i));
20389566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(c->i, a->i, mbs + 1));
20394da8f245SBarry Smith     c->free_ij = PETSC_TRUE;
20404da8f245SBarry Smith   }
204149b5e25fSSatish Balay   if (mbs > 0) {
204248a46eb9SPierre Jolivet     if (cpvalues != MAT_SHARE_NONZERO_PATTERN) PetscCall(PetscArraycpy(c->j, a->j, nz));
204349b5e25fSSatish Balay     if (cpvalues == MAT_COPY_VALUES) {
20449566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->a, a->a, bs2 * nz));
204549b5e25fSSatish Balay     } else {
20469566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(c->a, bs2 * nz));
204749b5e25fSSatish Balay     }
2048a1c3900fSBarry Smith     if (a->jshort) {
204944e1c64aSLisandro Dalcin       /* cannot share jshort, it is reallocated in MatAssemblyEnd_SeqSBAIJ() */
205044e1c64aSLisandro Dalcin       /* if the parent matrix is reassembled, this child matrix will never notice */
20519566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz, &c->jshort));
20529566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->jshort, a->jshort, nz));
205326fbe8dcSKarl Rupp 
20544da8f245SBarry Smith       c->free_jshort = PETSC_TRUE;
20554da8f245SBarry Smith     }
2056a1c3900fSBarry Smith   }
205749b5e25fSSatish Balay 
205849b5e25fSSatish Balay   c->roworiented = a->roworiented;
205949b5e25fSSatish Balay   c->nonew       = a->nonew;
20606c6c5352SBarry Smith   c->nz          = a->nz;
2061f2cbd3d5SJed Brown   c->maxnz       = a->nz; /* Since we allocate exactly the right amount */
2062f4259b30SLisandro Dalcin   c->solve_work  = NULL;
2063f4259b30SLisandro Dalcin   c->mult_work   = NULL;
206426fbe8dcSKarl Rupp 
206549b5e25fSSatish Balay   *B = C;
20669566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist));
20673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
206849b5e25fSSatish Balay }
206949b5e25fSSatish Balay 
2070618cc2edSLisandro Dalcin /* Used for both SeqBAIJ and SeqSBAIJ matrices */
2071618cc2edSLisandro Dalcin #define MatLoad_SeqSBAIJ_Binary MatLoad_SeqBAIJ_Binary
2072618cc2edSLisandro Dalcin 
MatLoad_SeqSBAIJ(Mat mat,PetscViewer viewer)2073d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_SeqSBAIJ(Mat mat, PetscViewer viewer)
2074d71ae5a4SJacob Faibussowitsch {
20757f489da9SVaclav Hapla   PetscBool isbinary;
20762f480046SShri Abhyankar 
20772f480046SShri Abhyankar   PetscFunctionBegin;
20789566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
207928b400f6SJacob 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);
20809566063dSJacob Faibussowitsch   PetscCall(MatLoad_SeqSBAIJ_Binary(mat, viewer));
20813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20822f480046SShri Abhyankar }
20832f480046SShri Abhyankar 
2084c75a6043SHong Zhang /*@
208511a5261eSBarry Smith   MatCreateSeqSBAIJWithArrays - Creates an sequential `MATSEQSBAIJ` matrix using matrix elements
2086c75a6043SHong Zhang   (upper triangular entries in CSR format) provided by the user.
2087c75a6043SHong Zhang 
2088d083f849SBarry Smith   Collective
2089c75a6043SHong Zhang 
2090c75a6043SHong Zhang   Input Parameters:
2091c75a6043SHong Zhang + comm - must be an MPI communicator of size 1
2092c75a6043SHong Zhang . bs   - size of block
2093c75a6043SHong Zhang . m    - number of rows
2094c75a6043SHong Zhang . n    - number of columns
2095483a2f95SBarry 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
2096c75a6043SHong Zhang . j    - column indices
2097c75a6043SHong Zhang - a    - matrix values
2098c75a6043SHong Zhang 
2099c75a6043SHong Zhang   Output Parameter:
2100c75a6043SHong Zhang . mat - the matrix
2101c75a6043SHong Zhang 
2102dfb205c3SBarry Smith   Level: advanced
2103c75a6043SHong Zhang 
2104c75a6043SHong Zhang   Notes:
21052ef1f0ffSBarry Smith   The `i`, `j`, and `a` arrays are not copied by this routine, the user must free these arrays
2106c75a6043SHong Zhang   once the matrix is destroyed
2107c75a6043SHong Zhang 
2108c75a6043SHong Zhang   You cannot set new nonzero locations into this matrix, that will generate an error.
2109c75a6043SHong Zhang 
21102ef1f0ffSBarry Smith   The `i` and `j` indices are 0 based
2111c75a6043SHong Zhang 
21122ef1f0ffSBarry Smith   When block size is greater than 1 the matrix values must be stored using the `MATSBAIJ` storage format. For block size of 1
2113dfb205c3SBarry Smith   it is the regular CSR format excluding the lower triangular elements.
2114dfb205c3SBarry Smith 
21151cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSBAIJ()`, `MatCreateSeqSBAIJ()`
2116c75a6043SHong Zhang @*/
MatCreateSeqSBAIJWithArrays(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat * mat)2117d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqSBAIJWithArrays(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat)
2118d71ae5a4SJacob Faibussowitsch {
2119c75a6043SHong Zhang   PetscInt      ii;
2120c75a6043SHong Zhang   Mat_SeqSBAIJ *sbaij;
2121c75a6043SHong Zhang 
2122c75a6043SHong Zhang   PetscFunctionBegin;
212308401ef6SPierre Jolivet   PetscCheck(bs == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "block size %" PetscInt_FMT " > 1 is not supported yet", bs);
2124aed4548fSBarry Smith   PetscCheck(m == 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0");
2125c75a6043SHong Zhang 
21269566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, mat));
21279566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mat, m, n, m, n));
21289566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mat, MATSEQSBAIJ));
21299566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(*mat, bs, MAT_SKIP_ALLOCATION, NULL));
2130c75a6043SHong Zhang   sbaij = (Mat_SeqSBAIJ *)(*mat)->data;
21319566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(m, &sbaij->imax, m, &sbaij->ilen));
2132c75a6043SHong Zhang 
2133c75a6043SHong Zhang   sbaij->i = i;
2134c75a6043SHong Zhang   sbaij->j = j;
2135c75a6043SHong Zhang   sbaij->a = a;
213626fbe8dcSKarl Rupp 
2137c75a6043SHong Zhang   sbaij->nonew          = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2138e6b907acSBarry Smith   sbaij->free_a         = PETSC_FALSE;
2139e6b907acSBarry Smith   sbaij->free_ij        = PETSC_FALSE;
2140ddf7884eSMatthew Knepley   sbaij->free_imax_ilen = PETSC_TRUE;
2141c75a6043SHong Zhang 
2142c75a6043SHong Zhang   for (ii = 0; ii < m; ii++) {
2143c75a6043SHong Zhang     sbaij->ilen[ii] = sbaij->imax[ii] = i[ii + 1] - i[ii];
21446bdcaf15SBarry 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]);
2145c75a6043SHong Zhang   }
214676bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2147c75a6043SHong Zhang     for (ii = 0; ii < sbaij->i[m]; ii++) {
21486bdcaf15SBarry 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]);
21496bdcaf15SBarry 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]);
2150c75a6043SHong Zhang     }
215176bd3646SJed Brown   }
2152c75a6043SHong Zhang 
21539566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY));
21549566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY));
21553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2156c75a6043SHong Zhang }
2157d06b337dSHong Zhang 
MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat * outmat)2158d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
2159d71ae5a4SJacob Faibussowitsch {
216059f5e6ceSHong Zhang   PetscFunctionBegin;
21619566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPISBAIJ(comm, inmat, n, scall, outmat));
21623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
216359f5e6ceSHong Zhang }
2164