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