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