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