149b5e25fSSatish Balay 249b5e25fSSatish Balay /* 3a1373b80SHong Zhang Defines the basic matrix operations for the SBAIJ (compressed row) 449b5e25fSSatish Balay matrix storage format. 549b5e25fSSatish Balay */ 6c6db04a5SJed Brown #include <../src/mat/impls/baij/seq/baij.h> /*I "petscmat.h" I*/ 7c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/sbaij.h> 8c6db04a5SJed Brown #include <petscblaslapack.h> 949b5e25fSSatish Balay 10c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/relax.h> 1170dcbbb9SBarry Smith #define USESHORT 12c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/relax.h> 1370dcbbb9SBarry Smith 146214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 15cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_Elemental(Mat, MatType, MatReuse, Mat *); 166214f412SHong Zhang #endif 17d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 18d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_SBAIJ_ScaLAPACK(Mat, MatType, MatReuse, Mat *); 19d24d4204SJose E. Roman #endif 2028d58a37SPierre Jolivet PETSC_INTERN PetscErrorCode MatConvert_MPISBAIJ_Basic(Mat, MatType, MatReuse, Mat *); 21b5b17502SBarry Smith 2249b5e25fSSatish Balay /* 2349b5e25fSSatish Balay Checks for missing diagonals 2449b5e25fSSatish Balay */ 259371c9d4SSatish Balay PetscErrorCode MatMissingDiagonal_SeqSBAIJ(Mat A, PetscBool *missing, PetscInt *dd) { 26045c9aa0SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 277734d3b5SMatthew G. Knepley PetscInt *diag, *ii = a->i, i; 2849b5e25fSSatish Balay 2949b5e25fSSatish Balay PetscFunctionBegin; 309566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqSBAIJ(A)); 312af78befSBarry Smith *missing = PETSC_FALSE; 327734d3b5SMatthew G. Knepley if (A->rmap->n > 0 && !ii) { 33358d2f5dSShri Abhyankar *missing = PETSC_TRUE; 34358d2f5dSShri Abhyankar if (dd) *dd = 0; 359566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no entries therefore is missing diagonal\n")); 36358d2f5dSShri Abhyankar } else { 37358d2f5dSShri Abhyankar diag = a->diag; 3849b5e25fSSatish Balay for (i = 0; i < a->mbs; i++) { 397734d3b5SMatthew G. Knepley if (diag[i] >= ii[i + 1]) { 402af78befSBarry Smith *missing = PETSC_TRUE; 412af78befSBarry Smith if (dd) *dd = i; 422af78befSBarry Smith break; 432af78befSBarry Smith } 4449b5e25fSSatish Balay } 45358d2f5dSShri Abhyankar } 4649b5e25fSSatish Balay PetscFunctionReturn(0); 4749b5e25fSSatish Balay } 4849b5e25fSSatish Balay 499371c9d4SSatish Balay PetscErrorCode MatMarkDiagonal_SeqSBAIJ(Mat A) { 50045c9aa0SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 5148dd3d27SHong Zhang PetscInt i, j; 5249b5e25fSSatish Balay 5349b5e25fSSatish Balay PetscFunctionBegin; 5409f38230SBarry Smith if (!a->diag) { 559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(a->mbs, &a->diag)); 56c760cd28SBarry Smith a->free_diag = PETSC_TRUE; 5709f38230SBarry Smith } 5848dd3d27SHong Zhang for (i = 0; i < a->mbs; i++) { 5948dd3d27SHong Zhang a->diag[i] = a->i[i + 1]; 6048dd3d27SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 6148dd3d27SHong Zhang if (a->j[j] == i) { 6248dd3d27SHong Zhang a->diag[i] = j; 6348dd3d27SHong Zhang break; 6448dd3d27SHong Zhang } 6548dd3d27SHong Zhang } 6648dd3d27SHong Zhang } 6749b5e25fSSatish Balay PetscFunctionReturn(0); 6849b5e25fSSatish Balay } 6949b5e25fSSatish Balay 709371c9d4SSatish Balay static PetscErrorCode MatGetRowIJ_SeqSBAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool blockcompressed, PetscInt *nn, const PetscInt *inia[], const PetscInt *inja[], PetscBool *done) { 71a6ece127SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 722462f5fdSStefano Zampini PetscInt i, j, n = a->mbs, nz = a->i[n], *tia, *tja, bs = A->rmap->bs, k, l, cnt; 732462f5fdSStefano Zampini PetscInt **ia = (PetscInt **)inia, **ja = (PetscInt **)inja; 7449b5e25fSSatish Balay 7549b5e25fSSatish Balay PetscFunctionBegin; 76d3e5a4abSHong Zhang *nn = n; 77a1373b80SHong Zhang if (!ia) PetscFunctionReturn(0); 782462f5fdSStefano Zampini if (symmetric) { 799566063dSJacob Faibussowitsch PetscCall(MatToSymmetricIJ_SeqAIJ(n, a->i, a->j, PETSC_FALSE, 0, 0, &tia, &tja)); 802462f5fdSStefano Zampini nz = tia[n]; 812462f5fdSStefano Zampini } else { 829371c9d4SSatish Balay tia = a->i; 839371c9d4SSatish Balay tja = a->j; 842462f5fdSStefano Zampini } 852462f5fdSStefano Zampini 862462f5fdSStefano Zampini if (!blockcompressed && bs > 1) { 872462f5fdSStefano Zampini (*nn) *= bs; 888f7157efSSatish Balay /* malloc & create the natural set of indices */ 899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((n + 1) * bs, ia)); 902462f5fdSStefano Zampini if (n) { 912462f5fdSStefano Zampini (*ia)[0] = oshift; 92ad540459SPierre Jolivet for (j = 1; j < bs; j++) (*ia)[j] = (tia[1] - tia[0]) * bs + (*ia)[j - 1]; 932462f5fdSStefano Zampini } 942462f5fdSStefano Zampini 952462f5fdSStefano Zampini for (i = 1; i < n; i++) { 962462f5fdSStefano Zampini (*ia)[i * bs] = (tia[i] - tia[i - 1]) * bs + (*ia)[i * bs - 1]; 97ad540459SPierre Jolivet for (j = 1; j < bs; j++) (*ia)[i * bs + j] = (tia[i + 1] - tia[i]) * bs + (*ia)[i * bs + j - 1]; 982462f5fdSStefano Zampini } 99ad540459SPierre Jolivet if (n) (*ia)[n * bs] = (tia[n] - tia[n - 1]) * bs + (*ia)[n * bs - 1]; 1002462f5fdSStefano Zampini 1012462f5fdSStefano Zampini if (inja) { 1029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz * bs * bs, ja)); 1032462f5fdSStefano Zampini cnt = 0; 1042462f5fdSStefano Zampini for (i = 0; i < n; i++) { 1058f7157efSSatish Balay for (j = 0; j < bs; j++) { 1062462f5fdSStefano Zampini for (k = tia[i]; k < tia[i + 1]; k++) { 107ad540459SPierre Jolivet for (l = 0; l < bs; l++) (*ja)[cnt++] = bs * tja[k] + l; 1088f7157efSSatish Balay } 1098f7157efSSatish Balay } 1108f7157efSSatish Balay } 1118f7157efSSatish Balay } 1122462f5fdSStefano Zampini 1132462f5fdSStefano Zampini if (symmetric) { /* deallocate memory allocated in MatToSymmetricIJ_SeqAIJ() */ 1149566063dSJacob Faibussowitsch PetscCall(PetscFree(tia)); 1159566063dSJacob Faibussowitsch PetscCall(PetscFree(tja)); 1162462f5fdSStefano Zampini } 1172462f5fdSStefano Zampini } else if (oshift == 1) { 1182462f5fdSStefano Zampini if (symmetric) { 1192462f5fdSStefano Zampini nz = tia[A->rmap->n / bs]; 1202462f5fdSStefano Zampini /* add 1 to i and j indices */ 1212462f5fdSStefano Zampini for (i = 0; i < A->rmap->n / bs + 1; i++) tia[i] = tia[i] + 1; 1222462f5fdSStefano Zampini *ia = tia; 1232462f5fdSStefano Zampini if (ja) { 1242462f5fdSStefano Zampini for (i = 0; i < nz; i++) tja[i] = tja[i] + 1; 1252462f5fdSStefano Zampini *ja = tja; 1262462f5fdSStefano Zampini } 1272462f5fdSStefano Zampini } else { 1282462f5fdSStefano Zampini nz = a->i[A->rmap->n / bs]; 1292462f5fdSStefano Zampini /* malloc space and add 1 to i and j indices */ 1309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n / bs + 1, ia)); 1312462f5fdSStefano Zampini for (i = 0; i < A->rmap->n / bs + 1; i++) (*ia)[i] = a->i[i] + 1; 1322462f5fdSStefano Zampini if (ja) { 1339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, ja)); 1342462f5fdSStefano Zampini for (i = 0; i < nz; i++) (*ja)[i] = a->j[i] + 1; 1352462f5fdSStefano Zampini } 1362462f5fdSStefano Zampini } 1372462f5fdSStefano Zampini } else { 1382462f5fdSStefano Zampini *ia = tia; 1392462f5fdSStefano Zampini if (ja) *ja = tja; 140a6ece127SHong Zhang } 14149b5e25fSSatish Balay PetscFunctionReturn(0); 14249b5e25fSSatish Balay } 14349b5e25fSSatish Balay 1449371c9d4SSatish Balay static PetscErrorCode MatRestoreRowIJ_SeqSBAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool blockcompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) { 14549b5e25fSSatish Balay PetscFunctionBegin; 14649b5e25fSSatish Balay if (!ia) PetscFunctionReturn(0); 1472462f5fdSStefano Zampini if ((!blockcompressed && A->rmap->bs > 1) || (symmetric || oshift == 1)) { 1489566063dSJacob Faibussowitsch PetscCall(PetscFree(*ia)); 1499566063dSJacob Faibussowitsch if (ja) PetscCall(PetscFree(*ja)); 150a6ece127SHong Zhang } 151a6ece127SHong Zhang PetscFunctionReturn(0); 15249b5e25fSSatish Balay } 15349b5e25fSSatish Balay 1549371c9d4SSatish Balay PetscErrorCode MatDestroy_SeqSBAIJ(Mat A) { 15549b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 15649b5e25fSSatish Balay 15749b5e25fSSatish Balay PetscFunctionBegin; 158a9f03627SSatish Balay #if defined(PETSC_USE_LOG) 159c0aa6a63SJacob Faibussowitsch PetscLogObjectState((PetscObject)A, "Rows=%" PetscInt_FMT ", NZ=%" PetscInt_FMT, A->rmap->N, a->nz); 160a9f03627SSatish Balay #endif 1619566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(A, &a->a, &a->j, &a->i)); 1629566063dSJacob Faibussowitsch if (a->free_diag) PetscCall(PetscFree(a->diag)); 1639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 1649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 1659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 1669566063dSJacob Faibussowitsch PetscCall(PetscFree(a->idiag)); 1679566063dSJacob Faibussowitsch PetscCall(PetscFree(a->inode.size)); 1689566063dSJacob Faibussowitsch if (a->free_imax_ilen) PetscCall(PetscFree2(a->imax, a->ilen)); 1699566063dSJacob Faibussowitsch PetscCall(PetscFree(a->solve_work)); 1709566063dSJacob Faibussowitsch PetscCall(PetscFree(a->sor_work)); 1719566063dSJacob Faibussowitsch PetscCall(PetscFree(a->solves_work)); 1729566063dSJacob Faibussowitsch PetscCall(PetscFree(a->mult_work)); 1739566063dSJacob Faibussowitsch PetscCall(PetscFree(a->saved_values)); 1749566063dSJacob Faibussowitsch if (a->free_jshort) PetscCall(PetscFree(a->jshort)); 1759566063dSJacob Faibussowitsch PetscCall(PetscFree(a->inew)); 1769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&a->parent)); 1779566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 178901853e0SKris Buschelman 1799566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL)); 1802e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJGetArray_C", NULL)); 1812e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJRestoreArray_C", NULL)); 1829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatStoreValues_C", NULL)); 1839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatRetrieveValues_C", NULL)); 1849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetColumnIndices_C", NULL)); 1859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqaij_C", NULL)); 1869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqbaij_C", NULL)); 1879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocation_C", NULL)); 1889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocationCSR_C", NULL)); 1896214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 1909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_elemental_C", NULL)); 1916214f412SHong Zhang #endif 192d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 1939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_scalapack_C", NULL)); 194d24d4204SJose E. Roman #endif 1952e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL)); 19649b5e25fSSatish Balay PetscFunctionReturn(0); 19749b5e25fSSatish Balay } 19849b5e25fSSatish Balay 1999371c9d4SSatish Balay PetscErrorCode MatSetOption_SeqSBAIJ(Mat A, MatOption op, PetscBool flg) { 200045c9aa0SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 201eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 202eb1ec7c1SStefano Zampini PetscInt bs; 203eb1ec7c1SStefano Zampini #endif 20449b5e25fSSatish Balay 20549b5e25fSSatish Balay PetscFunctionBegin; 206eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 2079566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 208eb1ec7c1SStefano Zampini #endif 2094d9d31abSKris Buschelman switch (op) { 2109371c9d4SSatish Balay case MAT_ROW_ORIENTED: a->roworiented = flg; break; 2119371c9d4SSatish Balay case MAT_KEEP_NONZERO_PATTERN: a->keepnonzeropattern = flg; break; 2129371c9d4SSatish Balay case MAT_NEW_NONZERO_LOCATIONS: a->nonew = (flg ? 0 : 1); break; 2139371c9d4SSatish Balay case MAT_NEW_NONZERO_LOCATION_ERR: a->nonew = (flg ? -1 : 0); break; 2149371c9d4SSatish Balay case MAT_NEW_NONZERO_ALLOCATION_ERR: a->nonew = (flg ? -2 : 0); break; 2159371c9d4SSatish Balay case MAT_UNUSED_NONZERO_LOCATION_ERR: a->nounused = (flg ? -1 : 0); break; 2168c78258cSHong Zhang case MAT_FORCE_DIAGONAL_ENTRIES: 2174d9d31abSKris Buschelman case MAT_IGNORE_OFF_PROC_ENTRIES: 2184d9d31abSKris Buschelman case MAT_USE_HASH_TABLE: 2199371c9d4SSatish Balay case MAT_SORTED_FULL: PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op])); break; 2209a4540c5SBarry Smith case MAT_HERMITIAN: 221eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 222eb1ec7c1SStefano Zampini if (flg) { /* disable transpose ops */ 22308401ef6SPierre Jolivet PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for Hermitian with block size greater than 1"); 224eb1ec7c1SStefano Zampini A->ops->multtranspose = NULL; 225eb1ec7c1SStefano Zampini A->ops->multtransposeadd = NULL; 226b94d7dedSBarry Smith A->symmetric = PETSC_BOOL3_FALSE; 227eb1ec7c1SStefano Zampini } 2280f2140c7SStefano Zampini #endif 229eeffb40dSHong Zhang break; 23077e54ba9SKris Buschelman case MAT_SYMMETRIC: 231eb1ec7c1SStefano Zampini case MAT_SPD: 232eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 233eb1ec7c1SStefano Zampini if (flg) { /* An hermitian and symmetric matrix has zero imaginary part (restore back transpose ops) */ 234eb1ec7c1SStefano Zampini A->ops->multtranspose = A->ops->mult; 235eb1ec7c1SStefano Zampini A->ops->multtransposeadd = A->ops->multadd; 236eb1ec7c1SStefano Zampini } 237eb1ec7c1SStefano Zampini #endif 238eb1ec7c1SStefano Zampini break; 239eb1ec7c1SStefano Zampini /* These options are handled directly by MatSetOption() */ 24077e54ba9SKris Buschelman case MAT_STRUCTURALLY_SYMMETRIC: 2419a4540c5SBarry Smith case MAT_SYMMETRY_ETERNAL: 242b94d7dedSBarry Smith case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 243672ba085SHong Zhang case MAT_STRUCTURE_ONLY: 244b94d7dedSBarry Smith case MAT_SPD_ETERNAL: 2454dcd73b1SHong Zhang /* These options are handled directly by MatSetOption() */ 246290bbb0aSBarry Smith break; 2479371c9d4SSatish Balay case MAT_IGNORE_LOWER_TRIANGULAR: a->ignore_ltriangular = flg; break; 2489371c9d4SSatish Balay case MAT_ERROR_LOWER_TRIANGULAR: a->ignore_ltriangular = flg; break; 2499371c9d4SSatish Balay case MAT_GETROW_UPPERTRIANGULAR: a->getrow_utriangular = flg; break; 2509371c9d4SSatish Balay case MAT_SUBMAT_SINGLEIS: break; 2519371c9d4SSatish Balay default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %d", op); 25249b5e25fSSatish Balay } 25349b5e25fSSatish Balay PetscFunctionReturn(0); 25449b5e25fSSatish Balay } 25549b5e25fSSatish Balay 2569371c9d4SSatish Balay PetscErrorCode MatGetRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) { 25749b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 25849b5e25fSSatish Balay 25949b5e25fSSatish Balay PetscFunctionBegin; 26008401ef6SPierre 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()"); 26152768537SHong Zhang 262f5edf698SHong Zhang /* Get the upper triangular part of the row */ 2639566063dSJacob Faibussowitsch PetscCall(MatGetRow_SeqBAIJ_private(A, row, nz, idx, v, a->i, a->j, a->a)); 26449b5e25fSSatish Balay PetscFunctionReturn(0); 26549b5e25fSSatish Balay } 26649b5e25fSSatish Balay 2679371c9d4SSatish Balay PetscErrorCode MatRestoreRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) { 26849b5e25fSSatish Balay PetscFunctionBegin; 269cb4a9cd9SHong Zhang if (nz) *nz = 0; 2709566063dSJacob Faibussowitsch if (idx) PetscCall(PetscFree(*idx)); 2719566063dSJacob Faibussowitsch if (v) PetscCall(PetscFree(*v)); 27249b5e25fSSatish Balay PetscFunctionReturn(0); 27349b5e25fSSatish Balay } 27449b5e25fSSatish Balay 2759371c9d4SSatish Balay PetscErrorCode MatGetRowUpperTriangular_SeqSBAIJ(Mat A) { 276f5edf698SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 277f5edf698SHong Zhang 278f5edf698SHong Zhang PetscFunctionBegin; 279f5edf698SHong Zhang a->getrow_utriangular = PETSC_TRUE; 280f5edf698SHong Zhang PetscFunctionReturn(0); 281f5edf698SHong Zhang } 282a323099bSStefano Zampini 2839371c9d4SSatish Balay PetscErrorCode MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A) { 284f5edf698SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 285f5edf698SHong Zhang 286f5edf698SHong Zhang PetscFunctionBegin; 287f5edf698SHong Zhang a->getrow_utriangular = PETSC_FALSE; 288f5edf698SHong Zhang PetscFunctionReturn(0); 289f5edf698SHong Zhang } 290f5edf698SHong Zhang 2919371c9d4SSatish Balay PetscErrorCode MatTranspose_SeqSBAIJ(Mat A, MatReuse reuse, Mat *B) { 29249b5e25fSSatish Balay PetscFunctionBegin; 2937fb60732SBarry Smith if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B)); 294cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX) { 2959566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, B)); 296cf37664fSBarry Smith } else if (reuse == MAT_REUSE_MATRIX) { 2979566063dSJacob Faibussowitsch PetscCall(MatCopy(A, *B, SAME_NONZERO_PATTERN)); 298fc4dec0aSBarry Smith } 2998115998fSBarry Smith PetscFunctionReturn(0); 30049b5e25fSSatish Balay } 30149b5e25fSSatish Balay 3029371c9d4SSatish Balay PetscErrorCode MatView_SeqSBAIJ_ASCII(Mat A, PetscViewer viewer) { 30349b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 304d0f46423SBarry Smith PetscInt i, j, bs = A->rmap->bs, k, l, bs2 = a->bs2; 305f3ef73ceSBarry Smith PetscViewerFormat format; 306121deb67SSatish Balay PetscInt *diag; 30749b5e25fSSatish Balay 30849b5e25fSSatish Balay PetscFunctionBegin; 3099566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 310456192e2SBarry Smith if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 3119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " block size is %" PetscInt_FMT "\n", bs)); 312fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_MATLAB) { 313d2507d54SMatthew Knepley Mat aij; 314ade3a672SBarry Smith const char *matname; 315ade3a672SBarry Smith 316d5f3da31SBarry Smith if (A->factortype && bs > 1) { 3179566063dSJacob 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")); 31870d5e725SHong Zhang PetscFunctionReturn(0); 31970d5e725SHong Zhang } 3209566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &aij)); 3219566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)A, &matname)); 3229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)aij, matname)); 3239566063dSJacob Faibussowitsch PetscCall(MatView(aij, viewer)); 3249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&aij)); 325fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_COMMON) { 3269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 32749b5e25fSSatish Balay for (i = 0; i < a->mbs; i++) { 32849b5e25fSSatish Balay for (j = 0; j < bs; j++) { 3299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i * bs + j)); 33049b5e25fSSatish Balay for (k = a->i[i]; k < a->i[i + 1]; k++) { 33149b5e25fSSatish Balay for (l = 0; l < bs; l++) { 33249b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX) 33349b5e25fSSatish Balay if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) > 0.0 && PetscRealPart(a->a[bs2 * k + l * bs + j]) != 0.0) { 3349371c9d4SSatish 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]))); 33549b5e25fSSatish Balay } else if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) < 0.0 && PetscRealPart(a->a[bs2 * k + l * bs + j]) != 0.0) { 3369371c9d4SSatish 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]))); 33749b5e25fSSatish Balay } else if (PetscRealPart(a->a[bs2 * k + l * bs + j]) != 0.0) { 3389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j]))); 33949b5e25fSSatish Balay } 34049b5e25fSSatish Balay #else 34148a46eb9SPierre Jolivet if (a->a[bs2 * k + l * bs + j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)a->a[bs2 * k + l * bs + j])); 34249b5e25fSSatish Balay #endif 34349b5e25fSSatish Balay } 34449b5e25fSSatish Balay } 3459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 34649b5e25fSSatish Balay } 34749b5e25fSSatish Balay } 3489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 349c1490034SHong Zhang } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 350c1490034SHong Zhang PetscFunctionReturn(0); 35149b5e25fSSatish Balay } else { 3529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 3532c990fa1SHong Zhang if (A->factortype) { /* for factored matrix */ 35408401ef6SPierre Jolivet PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix is factored with bs>1. Not implemented yet"); 3552c990fa1SHong Zhang 356121deb67SSatish Balay diag = a->diag; 357121deb67SSatish Balay for (i = 0; i < a->mbs; i++) { /* for row block i */ 3589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 3592c990fa1SHong Zhang /* diagonal entry */ 3602c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX) 3612c990fa1SHong Zhang if (PetscImaginaryPart(a->a[diag[i]]) > 0.0) { 3629566063dSJacob 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]]))); 3632c990fa1SHong Zhang } else if (PetscImaginaryPart(a->a[diag[i]]) < 0.0) { 3649566063dSJacob 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]]))); 3652c990fa1SHong Zhang } else { 3669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)PetscRealPart(1.0 / a->a[diag[i]]))); 3672c990fa1SHong Zhang } 3682c990fa1SHong Zhang #else 3699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)(1.0 / a->a[diag[i]]))); 3702c990fa1SHong Zhang #endif 3712c990fa1SHong Zhang /* off-diagonal entries */ 3722c990fa1SHong Zhang for (k = a->i[i]; k < a->i[i + 1] - 1; k++) { 3732c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX) 374ca0704adSBarry Smith if (PetscImaginaryPart(a->a[k]) > 0.0) { 3759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), (double)PetscImaginaryPart(a->a[k]))); 376ca0704adSBarry Smith } else if (PetscImaginaryPart(a->a[k]) < 0.0) { 3779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), -(double)PetscImaginaryPart(a->a[k]))); 3782c990fa1SHong Zhang } else { 3799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k], (double)PetscRealPart(a->a[k]))); 3802c990fa1SHong Zhang } 3812c990fa1SHong Zhang #else 3829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[k], (double)a->a[k])); 3832c990fa1SHong Zhang #endif 3842c990fa1SHong Zhang } 3859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 3862c990fa1SHong Zhang } 3872c990fa1SHong Zhang 3882c990fa1SHong Zhang } else { /* for non-factored matrix */ 3890c74a584SJed Brown for (i = 0; i < a->mbs; i++) { /* for row block i */ 3900c74a584SJed Brown for (j = 0; j < bs; j++) { /* for row bs*i + j */ 3919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i * bs + j)); 3920c74a584SJed Brown for (k = a->i[i]; k < a->i[i + 1]; k++) { /* for column block */ 3930c74a584SJed Brown for (l = 0; l < bs; l++) { /* for column */ 39449b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX) 39549b5e25fSSatish Balay if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) > 0.0) { 3969371c9d4SSatish 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]))); 39749b5e25fSSatish Balay } else if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) < 0.0) { 3989371c9d4SSatish 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]))); 39949b5e25fSSatish Balay } else { 4009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j]))); 40149b5e25fSSatish Balay } 40249b5e25fSSatish Balay #else 4039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)a->a[bs2 * k + l * bs + j])); 40449b5e25fSSatish Balay #endif 40549b5e25fSSatish Balay } 40649b5e25fSSatish Balay } 4079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 40849b5e25fSSatish Balay } 40949b5e25fSSatish Balay } 4102c990fa1SHong Zhang } 4119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 41249b5e25fSSatish Balay } 4139566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 41449b5e25fSSatish Balay PetscFunctionReturn(0); 41549b5e25fSSatish Balay } 41649b5e25fSSatish Balay 4179804daf3SBarry Smith #include <petscdraw.h> 4189371c9d4SSatish Balay static PetscErrorCode MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw, void *Aa) { 41949b5e25fSSatish Balay Mat A = (Mat)Aa; 42049b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 421d0f46423SBarry Smith PetscInt row, i, j, k, l, mbs = a->mbs, color, bs = A->rmap->bs, bs2 = a->bs2; 42249b5e25fSSatish Balay PetscReal xl, yl, xr, yr, x_l, x_r, y_l, y_r; 42349b5e25fSSatish Balay MatScalar *aa; 424b0a32e0cSBarry Smith PetscViewer viewer; 42549b5e25fSSatish Balay 42649b5e25fSSatish Balay PetscFunctionBegin; 4279566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer)); 4289566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr)); 42949b5e25fSSatish Balay 43049b5e25fSSatish Balay /* loop over matrix elements drawing boxes */ 431383922c3SLisandro Dalcin 432d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 4339566063dSJacob Faibussowitsch PetscCall(PetscDrawString(draw, .3 * (xl + xr), .3 * (yl + yr), PETSC_DRAW_BLACK, "symmetric")); 434383922c3SLisandro Dalcin /* Blue for negative, Cyan for zero and Red for positive */ 435b0a32e0cSBarry Smith color = PETSC_DRAW_BLUE; 43649b5e25fSSatish Balay for (i = 0, row = 0; i < mbs; i++, row += bs) { 43749b5e25fSSatish Balay for (j = a->i[i]; j < a->i[i + 1]; j++) { 4389371c9d4SSatish Balay y_l = A->rmap->N - row - 1.0; 4399371c9d4SSatish Balay y_r = y_l + 1.0; 4409371c9d4SSatish Balay x_l = a->j[j] * bs; 4419371c9d4SSatish Balay x_r = x_l + 1.0; 44249b5e25fSSatish Balay aa = a->a + j * bs2; 44349b5e25fSSatish Balay for (k = 0; k < bs; k++) { 44449b5e25fSSatish Balay for (l = 0; l < bs; l++) { 44549b5e25fSSatish Balay if (PetscRealPart(*aa++) >= 0.) continue; 4469566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color)); 44749b5e25fSSatish Balay } 44849b5e25fSSatish Balay } 44949b5e25fSSatish Balay } 45049b5e25fSSatish Balay } 451b0a32e0cSBarry Smith color = PETSC_DRAW_CYAN; 45249b5e25fSSatish Balay for (i = 0, row = 0; i < mbs; i++, row += bs) { 45349b5e25fSSatish Balay for (j = a->i[i]; j < a->i[i + 1]; j++) { 4549371c9d4SSatish Balay y_l = A->rmap->N - row - 1.0; 4559371c9d4SSatish Balay y_r = y_l + 1.0; 4569371c9d4SSatish Balay x_l = a->j[j] * bs; 4579371c9d4SSatish Balay x_r = x_l + 1.0; 45849b5e25fSSatish Balay aa = a->a + j * bs2; 45949b5e25fSSatish Balay for (k = 0; k < bs; k++) { 46049b5e25fSSatish Balay for (l = 0; l < bs; l++) { 46149b5e25fSSatish Balay if (PetscRealPart(*aa++) != 0.) continue; 4629566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color)); 46349b5e25fSSatish Balay } 46449b5e25fSSatish Balay } 46549b5e25fSSatish Balay } 46649b5e25fSSatish Balay } 467b0a32e0cSBarry Smith color = PETSC_DRAW_RED; 46849b5e25fSSatish Balay for (i = 0, row = 0; i < mbs; i++, row += bs) { 46949b5e25fSSatish Balay for (j = a->i[i]; j < a->i[i + 1]; j++) { 4709371c9d4SSatish Balay y_l = A->rmap->N - row - 1.0; 4719371c9d4SSatish Balay y_r = y_l + 1.0; 4729371c9d4SSatish Balay x_l = a->j[j] * bs; 4739371c9d4SSatish Balay x_r = x_l + 1.0; 47449b5e25fSSatish Balay aa = a->a + j * bs2; 47549b5e25fSSatish Balay for (k = 0; k < bs; k++) { 47649b5e25fSSatish Balay for (l = 0; l < bs; l++) { 47749b5e25fSSatish Balay if (PetscRealPart(*aa++) <= 0.) continue; 4789566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color)); 47949b5e25fSSatish Balay } 48049b5e25fSSatish Balay } 48149b5e25fSSatish Balay } 48249b5e25fSSatish Balay } 483d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 48449b5e25fSSatish Balay PetscFunctionReturn(0); 48549b5e25fSSatish Balay } 48649b5e25fSSatish Balay 4879371c9d4SSatish Balay static PetscErrorCode MatView_SeqSBAIJ_Draw(Mat A, PetscViewer viewer) { 48849b5e25fSSatish Balay PetscReal xl, yl, xr, yr, w, h; 489b0a32e0cSBarry Smith PetscDraw draw; 490ace3abfcSBarry Smith PetscBool isnull; 49149b5e25fSSatish Balay 49249b5e25fSSatish Balay PetscFunctionBegin; 4939566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 4949566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 495383922c3SLisandro Dalcin if (isnull) PetscFunctionReturn(0); 49649b5e25fSSatish Balay 4979371c9d4SSatish Balay xr = A->rmap->N; 4989371c9d4SSatish Balay yr = A->rmap->N; 4999371c9d4SSatish Balay h = yr / 10.0; 5009371c9d4SSatish Balay w = xr / 10.0; 5019371c9d4SSatish Balay xr += w; 5029371c9d4SSatish Balay yr += h; 5039371c9d4SSatish Balay xl = -w; 5049371c9d4SSatish Balay yl = -h; 5059566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr)); 5069566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer)); 5079566063dSJacob Faibussowitsch PetscCall(PetscDrawZoom(draw, MatView_SeqSBAIJ_Draw_Zoom, A)); 5089566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL)); 5099566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 51049b5e25fSSatish Balay PetscFunctionReturn(0); 51149b5e25fSSatish Balay } 51249b5e25fSSatish Balay 513618cc2edSLisandro Dalcin /* Used for both MPIBAIJ and MPISBAIJ matrices */ 514618cc2edSLisandro Dalcin #define MatView_SeqSBAIJ_Binary MatView_SeqBAIJ_Binary 515618cc2edSLisandro Dalcin 5169371c9d4SSatish Balay PetscErrorCode MatView_SeqSBAIJ(Mat A, PetscViewer viewer) { 517618cc2edSLisandro Dalcin PetscBool iascii, isbinary, isdraw; 51849b5e25fSSatish Balay 51949b5e25fSSatish Balay PetscFunctionBegin; 5209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 5219566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 5229566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 52332077d6dSBarry Smith if (iascii) { 5249566063dSJacob Faibussowitsch PetscCall(MatView_SeqSBAIJ_ASCII(A, viewer)); 525618cc2edSLisandro Dalcin } else if (isbinary) { 5269566063dSJacob Faibussowitsch PetscCall(MatView_SeqSBAIJ_Binary(A, viewer)); 52749b5e25fSSatish Balay } else if (isdraw) { 5289566063dSJacob Faibussowitsch PetscCall(MatView_SeqSBAIJ_Draw(A, viewer)); 52949b5e25fSSatish Balay } else { 530a5e6ed63SBarry Smith Mat B; 531ade3a672SBarry Smith const char *matname; 5329566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B)); 5339566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)A, &matname)); 5349566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)B, matname)); 5359566063dSJacob Faibussowitsch PetscCall(MatView(B, viewer)); 5369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 53749b5e25fSSatish Balay } 53849b5e25fSSatish Balay PetscFunctionReturn(0); 53949b5e25fSSatish Balay } 54049b5e25fSSatish Balay 5419371c9d4SSatish Balay PetscErrorCode MatGetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[]) { 542045c9aa0SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 54313f74950SBarry Smith PetscInt *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j; 54413f74950SBarry Smith PetscInt *ai = a->i, *ailen = a->ilen; 545d0f46423SBarry Smith PetscInt brow, bcol, ridx, cidx, bs = A->rmap->bs, bs2 = a->bs2; 54697e567efSBarry Smith MatScalar *ap, *aa = a->a; 54749b5e25fSSatish Balay 54849b5e25fSSatish Balay PetscFunctionBegin; 54949b5e25fSSatish Balay for (k = 0; k < m; k++) { /* loop over rows */ 5509371c9d4SSatish Balay row = im[k]; 5519371c9d4SSatish Balay brow = row / bs; 5529371c9d4SSatish Balay if (row < 0) { 5539371c9d4SSatish Balay v += n; 5549371c9d4SSatish Balay continue; 5559371c9d4SSatish Balay } /* negative row */ 55654c59aa7SJacob 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); 5579371c9d4SSatish Balay rp = aj + ai[brow]; 5589371c9d4SSatish Balay ap = aa + bs2 * ai[brow]; 55949b5e25fSSatish Balay nrow = ailen[brow]; 56049b5e25fSSatish Balay for (l = 0; l < n; l++) { /* loop over columns */ 5619371c9d4SSatish Balay if (in[l] < 0) { 5629371c9d4SSatish Balay v++; 5639371c9d4SSatish Balay continue; 5649371c9d4SSatish Balay } /* negative column */ 56554c59aa7SJacob 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); 56649b5e25fSSatish Balay col = in[l]; 56749b5e25fSSatish Balay bcol = col / bs; 56849b5e25fSSatish Balay cidx = col % bs; 56949b5e25fSSatish Balay ridx = row % bs; 57049b5e25fSSatish Balay high = nrow; 57149b5e25fSSatish Balay low = 0; /* assume unsorted */ 57249b5e25fSSatish Balay while (high - low > 5) { 57349b5e25fSSatish Balay t = (low + high) / 2; 57449b5e25fSSatish Balay if (rp[t] > bcol) high = t; 57549b5e25fSSatish Balay else low = t; 57649b5e25fSSatish Balay } 57749b5e25fSSatish Balay for (i = low; i < high; i++) { 57849b5e25fSSatish Balay if (rp[i] > bcol) break; 57949b5e25fSSatish Balay if (rp[i] == bcol) { 58049b5e25fSSatish Balay *v++ = ap[bs2 * i + bs * cidx + ridx]; 58149b5e25fSSatish Balay goto finished; 58249b5e25fSSatish Balay } 58349b5e25fSSatish Balay } 58497e567efSBarry Smith *v++ = 0.0; 58549b5e25fSSatish Balay finished:; 58649b5e25fSSatish Balay } 58749b5e25fSSatish Balay } 58849b5e25fSSatish Balay PetscFunctionReturn(0); 58949b5e25fSSatish Balay } 59049b5e25fSSatish Balay 5919371c9d4SSatish Balay PetscErrorCode MatPermute_SeqSBAIJ(Mat A, IS rowp, IS colp, Mat *B) { 592dc29a518SPierre Jolivet Mat C; 593dc29a518SPierre Jolivet 594dc29a518SPierre Jolivet PetscFunctionBegin; 5959566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATSEQBAIJ, MAT_INITIAL_MATRIX, &C)); 5969566063dSJacob Faibussowitsch PetscCall(MatPermute(C, rowp, colp, B)); 5979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 59848a46eb9SPierre Jolivet if (rowp == colp) PetscCall(MatConvert(*B, MATSEQSBAIJ, MAT_INPLACE_MATRIX, B)); 599dc29a518SPierre Jolivet PetscFunctionReturn(0); 600dc29a518SPierre Jolivet } 60149b5e25fSSatish Balay 6029371c9d4SSatish Balay PetscErrorCode MatSetValuesBlocked_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) { 6030880e062SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 604e2ee6c50SBarry Smith PetscInt *rp, k, low, high, t, ii, jj, row, nrow, i, col, l, rmax, N, lastcol = -1; 60513f74950SBarry Smith PetscInt *imax = a->imax, *ai = a->i, *ailen = a->ilen; 606d0f46423SBarry Smith PetscInt *aj = a->j, nonew = a->nonew, bs2 = a->bs2, bs = A->rmap->bs, stepval; 607ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 608dd6ea824SBarry Smith const PetscScalar *value = v; 609f15d580aSBarry Smith MatScalar *ap, *aa = a->a, *bap; 6100880e062SHong Zhang 61149b5e25fSSatish Balay PetscFunctionBegin; 61226fbe8dcSKarl Rupp if (roworiented) stepval = (n - 1) * bs; 61326fbe8dcSKarl Rupp else stepval = (m - 1) * bs; 61426fbe8dcSKarl Rupp 6150880e062SHong Zhang for (k = 0; k < m; k++) { /* loop over added rows */ 6160880e062SHong Zhang row = im[k]; 6170880e062SHong Zhang if (row < 0) continue; 6186bdcaf15SBarry 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); 6190880e062SHong Zhang rp = aj + ai[row]; 6200880e062SHong Zhang ap = aa + bs2 * ai[row]; 6210880e062SHong Zhang rmax = imax[row]; 6220880e062SHong Zhang nrow = ailen[row]; 6230880e062SHong Zhang low = 0; 624818f2c47SBarry Smith high = nrow; 6250880e062SHong Zhang for (l = 0; l < n; l++) { /* loop over added columns */ 6260880e062SHong Zhang if (in[l] < 0) continue; 6270880e062SHong Zhang col = in[l]; 6286bdcaf15SBarry 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); 629b98bf0e1SJed Brown if (col < row) { 63026fbe8dcSKarl Rupp if (a->ignore_ltriangular) continue; /* ignore lower triangular block */ 63126fbe8dcSKarl Rupp else SETERRQ(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)"); 632b98bf0e1SJed Brown } 63326fbe8dcSKarl Rupp if (roworiented) value = v + k * (stepval + bs) * bs + l * bs; 63426fbe8dcSKarl Rupp else value = v + l * (stepval + bs) * bs + k * bs; 63526fbe8dcSKarl Rupp 63626fbe8dcSKarl Rupp if (col <= lastcol) low = 0; 63726fbe8dcSKarl Rupp else high = nrow; 63826fbe8dcSKarl Rupp 639e2ee6c50SBarry Smith lastcol = col; 6400880e062SHong Zhang while (high - low > 7) { 6410880e062SHong Zhang t = (low + high) / 2; 6420880e062SHong Zhang if (rp[t] > col) high = t; 6430880e062SHong Zhang else low = t; 6440880e062SHong Zhang } 6450880e062SHong Zhang for (i = low; i < high; i++) { 6460880e062SHong Zhang if (rp[i] > col) break; 6470880e062SHong Zhang if (rp[i] == col) { 6480880e062SHong Zhang bap = ap + bs2 * i; 6490880e062SHong Zhang if (roworiented) { 6500880e062SHong Zhang if (is == ADD_VALUES) { 6510880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 652ad540459SPierre Jolivet for (jj = ii; jj < bs2; jj += bs) bap[jj] += *value++; 6530880e062SHong Zhang } 6540880e062SHong Zhang } else { 6550880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 656ad540459SPierre Jolivet for (jj = ii; jj < bs2; jj += bs) bap[jj] = *value++; 6570880e062SHong Zhang } 6580880e062SHong Zhang } 6590880e062SHong Zhang } else { 6600880e062SHong Zhang if (is == ADD_VALUES) { 6610880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 662ad540459SPierre Jolivet for (jj = 0; jj < bs; jj++) *bap++ += *value++; 6630880e062SHong Zhang } 6640880e062SHong Zhang } else { 6650880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 666ad540459SPierre Jolivet for (jj = 0; jj < bs; jj++) *bap++ = *value++; 6670880e062SHong Zhang } 6680880e062SHong Zhang } 6690880e062SHong Zhang } 6700880e062SHong Zhang goto noinsert2; 6710880e062SHong Zhang } 6720880e062SHong Zhang } 6730880e062SHong Zhang if (nonew == 1) goto noinsert2; 67408401ef6SPierre 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); 675fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 6769371c9d4SSatish Balay N = nrow++ - 1; 6779371c9d4SSatish Balay high++; 6780880e062SHong Zhang /* shift up all the later entries in this row */ 6799566063dSJacob Faibussowitsch PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1)); 6809566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1))); 6819566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ap + bs2 * i, bs2)); 6820880e062SHong Zhang rp[i] = col; 6830880e062SHong Zhang bap = ap + bs2 * i; 6840880e062SHong Zhang if (roworiented) { 6850880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 686ad540459SPierre Jolivet for (jj = ii; jj < bs2; jj += bs) bap[jj] = *value++; 6870880e062SHong Zhang } 6880880e062SHong Zhang } else { 6890880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 690ad540459SPierre Jolivet for (jj = 0; jj < bs; jj++) *bap++ = *value++; 6910880e062SHong Zhang } 6920880e062SHong Zhang } 6930880e062SHong Zhang noinsert2:; 6940880e062SHong Zhang low = i; 6950880e062SHong Zhang } 6960880e062SHong Zhang ailen[row] = nrow; 6970880e062SHong Zhang } 6980880e062SHong Zhang PetscFunctionReturn(0); 69949b5e25fSSatish Balay } 70049b5e25fSSatish Balay 70164831d72SBarry Smith /* 70264831d72SBarry Smith This is not yet used 70364831d72SBarry Smith */ 7049371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_SeqSBAIJ_SeqAIJ_Inode(Mat A) { 7050def2e27SBarry Smith Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 7060def2e27SBarry Smith const PetscInt *ai = a->i, *aj = a->j, *cols; 7070def2e27SBarry Smith PetscInt i = 0, j, blk_size, m = A->rmap->n, node_count = 0, nzx, nzy, *ns, row, nz, cnt, cnt2, *counts; 708ace3abfcSBarry Smith PetscBool flag; 7090def2e27SBarry Smith 7100def2e27SBarry Smith PetscFunctionBegin; 7119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &ns)); 7120def2e27SBarry Smith while (i < m) { 7130def2e27SBarry Smith nzx = ai[i + 1] - ai[i]; /* Number of nonzeros */ 7140def2e27SBarry Smith /* Limits the number of elements in a node to 'a->inode.limit' */ 7150def2e27SBarry Smith for (j = i + 1, blk_size = 1; j < m && blk_size < a->inode.limit; ++j, ++blk_size) { 7160def2e27SBarry Smith nzy = ai[j + 1] - ai[j]; 7170def2e27SBarry Smith if (nzy != (nzx - j + i)) break; 7189566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(aj + ai[i] + j - i, aj + ai[j], nzy, &flag)); 7190def2e27SBarry Smith if (!flag) break; 7200def2e27SBarry Smith } 7210def2e27SBarry Smith ns[node_count++] = blk_size; 72226fbe8dcSKarl Rupp 7230def2e27SBarry Smith i = j; 7240def2e27SBarry Smith } 7250def2e27SBarry Smith if (!a->inode.size && m && node_count > .9 * m) { 7269566063dSJacob Faibussowitsch PetscCall(PetscFree(ns)); 7279566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Found %" PetscInt_FMT " nodes out of %" PetscInt_FMT " rows. Not using Inode routines\n", node_count, m)); 7280def2e27SBarry Smith } else { 7290def2e27SBarry Smith a->inode.node_count = node_count; 73026fbe8dcSKarl Rupp 7319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(node_count, &a->inode.size)); 7329566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->inode.size, ns, node_count)); 7339566063dSJacob Faibussowitsch PetscCall(PetscFree(ns)); 7349566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Found %" PetscInt_FMT " nodes of %" PetscInt_FMT ". Limit used: %" PetscInt_FMT ". Using Inode routines\n", node_count, m, a->inode.limit)); 7350def2e27SBarry Smith 7360def2e27SBarry Smith /* count collections of adjacent columns in each inode */ 7370def2e27SBarry Smith row = 0; 7380def2e27SBarry Smith cnt = 0; 7390def2e27SBarry Smith for (i = 0; i < node_count; i++) { 7400def2e27SBarry Smith cols = aj + ai[row] + a->inode.size[i]; 7410def2e27SBarry Smith nz = ai[row + 1] - ai[row] - a->inode.size[i]; 7420def2e27SBarry Smith for (j = 1; j < nz; j++) { 74326fbe8dcSKarl Rupp if (cols[j] != cols[j - 1] + 1) cnt++; 7440def2e27SBarry Smith } 7450def2e27SBarry Smith cnt++; 7460def2e27SBarry Smith row += a->inode.size[i]; 7470def2e27SBarry Smith } 7489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * cnt, &counts)); 7490def2e27SBarry Smith cnt = 0; 7500def2e27SBarry Smith row = 0; 7510def2e27SBarry Smith for (i = 0; i < node_count; i++) { 7520def2e27SBarry Smith cols = aj + ai[row] + a->inode.size[i]; 7530def2e27SBarry Smith counts[2 * cnt] = cols[0]; 7540def2e27SBarry Smith nz = ai[row + 1] - ai[row] - a->inode.size[i]; 7550def2e27SBarry Smith cnt2 = 1; 7560def2e27SBarry Smith for (j = 1; j < nz; j++) { 7570def2e27SBarry Smith if (cols[j] != cols[j - 1] + 1) { 7580def2e27SBarry Smith counts[2 * (cnt++) + 1] = cnt2; 7590def2e27SBarry Smith counts[2 * cnt] = cols[j]; 7600def2e27SBarry Smith cnt2 = 1; 7610def2e27SBarry Smith } else cnt2++; 7620def2e27SBarry Smith } 7630def2e27SBarry Smith counts[2 * (cnt++) + 1] = cnt2; 7640def2e27SBarry Smith row += a->inode.size[i]; 7650def2e27SBarry Smith } 7669566063dSJacob Faibussowitsch PetscCall(PetscIntView(2 * cnt, counts, NULL)); 7670def2e27SBarry Smith } 76838702af4SBarry Smith PetscFunctionReturn(0); 76938702af4SBarry Smith } 77038702af4SBarry Smith 7719371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_SeqSBAIJ(Mat A, MatAssemblyType mode) { 77249b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 7738f8f2f0dSBarry Smith PetscInt fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax; 774d0f46423SBarry Smith PetscInt m = A->rmap->N, *ip, N, *ailen = a->ilen; 77513f74950SBarry Smith PetscInt mbs = a->mbs, bs2 = a->bs2, rmax = 0; 77649b5e25fSSatish Balay MatScalar *aa = a->a, *ap; 77749b5e25fSSatish Balay 77849b5e25fSSatish Balay PetscFunctionBegin; 77949b5e25fSSatish Balay if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 78049b5e25fSSatish Balay 78149b5e25fSSatish Balay if (m) rmax = ailen[0]; 78249b5e25fSSatish Balay for (i = 1; i < mbs; i++) { 78349b5e25fSSatish Balay /* move each row back by the amount of empty slots (fshift) before it*/ 78449b5e25fSSatish Balay fshift += imax[i - 1] - ailen[i - 1]; 78549b5e25fSSatish Balay rmax = PetscMax(rmax, ailen[i]); 78649b5e25fSSatish Balay if (fshift) { 787580bdb30SBarry Smith ip = aj + ai[i]; 788580bdb30SBarry Smith ap = aa + bs2 * ai[i]; 78949b5e25fSSatish Balay N = ailen[i]; 7909566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ip - fshift, ip, N)); 7919566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap - bs2 * fshift, ap, bs2 * N)); 79249b5e25fSSatish Balay } 79349b5e25fSSatish Balay ai[i] = ai[i - 1] + ailen[i - 1]; 79449b5e25fSSatish Balay } 79549b5e25fSSatish Balay if (mbs) { 79649b5e25fSSatish Balay fshift += imax[mbs - 1] - ailen[mbs - 1]; 79749b5e25fSSatish Balay ai[mbs] = ai[mbs - 1] + ailen[mbs - 1]; 79849b5e25fSSatish Balay } 79949b5e25fSSatish Balay /* reset ilen and imax for each row */ 800ad540459SPierre Jolivet for (i = 0; i < mbs; i++) ailen[i] = imax[i] = ai[i + 1] - ai[i]; 8016c6c5352SBarry Smith a->nz = ai[mbs]; 80249b5e25fSSatish Balay 803b424e231SHong Zhang /* diagonals may have moved, reset it */ 8041baa6e33SBarry Smith if (a->diag) PetscCall(PetscArraycpy(a->diag, ai, mbs)); 805aed4548fSBarry 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); 80626fbe8dcSKarl Rupp 8079566063dSJacob 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)); 8089566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues is %" PetscInt_FMT "\n", a->reallocs)); 8099566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Most nonzeros blocks in any row is %" PetscInt_FMT "\n", rmax)); 81026fbe8dcSKarl Rupp 8118e58a170SBarry Smith A->info.mallocs += a->reallocs; 81249b5e25fSSatish Balay a->reallocs = 0; 81349b5e25fSSatish Balay A->info.nz_unneeded = (PetscReal)fshift * bs2; 814061b2667SBarry Smith a->idiagvalid = PETSC_FALSE; 8154dcd73b1SHong Zhang a->rmax = rmax; 81638702af4SBarry Smith 81738702af4SBarry Smith if (A->cmap->n < 65536 && A->cmap->bs == 1) { 81844e1c64aSLisandro Dalcin if (a->jshort && a->free_jshort) { 81917803ae8SHong Zhang /* when matrix data structure is changed, previous jshort must be replaced */ 8209566063dSJacob Faibussowitsch PetscCall(PetscFree(a->jshort)); 82117803ae8SHong Zhang } 8229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(a->i[A->rmap->n], &a->jshort)); 82338702af4SBarry Smith for (i = 0; i < a->i[A->rmap->n]; i++) a->jshort[i] = a->j[i]; 82438702af4SBarry Smith A->ops->mult = MatMult_SeqSBAIJ_1_ushort; 82541f059aeSBarry Smith A->ops->sor = MatSOR_SeqSBAIJ_ushort; 8264da8f245SBarry Smith a->free_jshort = PETSC_TRUE; 82738702af4SBarry Smith } 82849b5e25fSSatish Balay PetscFunctionReturn(0); 82949b5e25fSSatish Balay } 83049b5e25fSSatish Balay 83149b5e25fSSatish Balay /* 83249b5e25fSSatish Balay This function returns an array of flags which indicate the locations of contiguous 83349b5e25fSSatish Balay blocks that should be zeroed. for eg: if bs = 3 and is = [0,1,2,3,5,6,7,8,9] 834a5b23f4aSJose E. Roman then the resulting sizes = [3,1,1,3,1] corresponding to sets [(0,1,2),(3),(5),(6,7,8),(9)] 83549b5e25fSSatish Balay Assume: sizes should be long enough to hold all the values. 83649b5e25fSSatish Balay */ 8379371c9d4SSatish Balay PetscErrorCode MatZeroRows_SeqSBAIJ_Check_Blocks(PetscInt idx[], PetscInt n, PetscInt bs, PetscInt sizes[], PetscInt *bs_max) { 83813f74950SBarry Smith PetscInt i, j, k, row; 839ace3abfcSBarry Smith PetscBool flg; 84049b5e25fSSatish Balay 84149b5e25fSSatish Balay PetscFunctionBegin; 84249b5e25fSSatish Balay for (i = 0, j = 0; i < n; j++) { 84349b5e25fSSatish Balay row = idx[i]; 844a5b23f4aSJose E. Roman if (row % bs != 0) { /* Not the beginning of a block */ 84549b5e25fSSatish Balay sizes[j] = 1; 84649b5e25fSSatish Balay i++; 84749b5e25fSSatish Balay } else if (i + bs > n) { /* Beginning of a block, but complete block doesn't exist (at idx end) */ 84849b5e25fSSatish Balay sizes[j] = 1; /* Also makes sure at least 'bs' values exist for next else */ 84949b5e25fSSatish Balay i++; 8506aad120cSJose E. Roman } else { /* Beginning of the block, so check if the complete block exists */ 85149b5e25fSSatish Balay flg = PETSC_TRUE; 85249b5e25fSSatish Balay for (k = 1; k < bs; k++) { 85349b5e25fSSatish Balay if (row + k != idx[i + k]) { /* break in the block */ 85449b5e25fSSatish Balay flg = PETSC_FALSE; 85549b5e25fSSatish Balay break; 85649b5e25fSSatish Balay } 85749b5e25fSSatish Balay } 858abc0a331SBarry Smith if (flg) { /* No break in the bs */ 85949b5e25fSSatish Balay sizes[j] = bs; 86049b5e25fSSatish Balay i += bs; 86149b5e25fSSatish Balay } else { 86249b5e25fSSatish Balay sizes[j] = 1; 86349b5e25fSSatish Balay i++; 86449b5e25fSSatish Balay } 86549b5e25fSSatish Balay } 86649b5e25fSSatish Balay } 86749b5e25fSSatish Balay *bs_max = j; 86849b5e25fSSatish Balay PetscFunctionReturn(0); 86949b5e25fSSatish Balay } 87049b5e25fSSatish Balay 87149b5e25fSSatish Balay /* Only add/insert a(i,j) with i<=j (blocks). 87249b5e25fSSatish Balay Any a(i,j) with i>j input by user is ingored. 87349b5e25fSSatish Balay */ 87449b5e25fSSatish Balay 8759371c9d4SSatish Balay PetscErrorCode MatSetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) { 87649b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 877e2ee6c50SBarry Smith PetscInt *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N, lastcol = -1; 87813f74950SBarry Smith PetscInt *imax = a->imax, *ai = a->i, *ailen = a->ilen, roworiented = a->roworiented; 879d0f46423SBarry Smith PetscInt *aj = a->j, nonew = a->nonew, bs = A->rmap->bs, brow, bcol; 88013f74950SBarry Smith PetscInt ridx, cidx, bs2 = a->bs2; 88149b5e25fSSatish Balay MatScalar *ap, value, *aa = a->a, *bap; 88249b5e25fSSatish Balay 88349b5e25fSSatish Balay PetscFunctionBegin; 88449b5e25fSSatish Balay for (k = 0; k < m; k++) { /* loop over added rows */ 88549b5e25fSSatish Balay row = im[k]; /* row number */ 88649b5e25fSSatish Balay brow = row / bs; /* block row number */ 88749b5e25fSSatish Balay if (row < 0) continue; 8886bdcaf15SBarry 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); 88949b5e25fSSatish Balay rp = aj + ai[brow]; /*ptr to beginning of column value of the row block*/ 89049b5e25fSSatish Balay ap = aa + bs2 * ai[brow]; /*ptr to beginning of element value of the row block*/ 89149b5e25fSSatish Balay rmax = imax[brow]; /* maximum space allocated for this row */ 89249b5e25fSSatish Balay nrow = ailen[brow]; /* actual length of this row */ 89349b5e25fSSatish Balay low = 0; 8948509e838SStefano Zampini high = nrow; 89549b5e25fSSatish Balay for (l = 0; l < n; l++) { /* loop over added columns */ 89649b5e25fSSatish Balay if (in[l] < 0) continue; 8976bdcaf15SBarry 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); 89849b5e25fSSatish Balay col = in[l]; 89949b5e25fSSatish Balay bcol = col / bs; /* block col number */ 90049b5e25fSSatish Balay 901941593c8SHong Zhang if (brow > bcol) { 90226fbe8dcSKarl Rupp if (a->ignore_ltriangular) continue; /* ignore lower triangular values */ 90326fbe8dcSKarl Rupp else SETERRQ(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)"); 904941593c8SHong Zhang } 905f4989cb3SHong Zhang 9069371c9d4SSatish Balay ridx = row % bs; 9079371c9d4SSatish Balay cidx = col % bs; /*row and col index inside the block */ 9088549e402SHong Zhang if ((brow == bcol && ridx <= cidx) || (brow < bcol)) { 90949b5e25fSSatish Balay /* element value a(k,l) */ 91026fbe8dcSKarl Rupp if (roworiented) value = v[l + k * n]; 91126fbe8dcSKarl Rupp else value = v[k + l * m]; 91249b5e25fSSatish Balay 91349b5e25fSSatish Balay /* move pointer bap to a(k,l) quickly and add/insert value */ 91426fbe8dcSKarl Rupp if (col <= lastcol) low = 0; 9158509e838SStefano Zampini else high = nrow; 9168509e838SStefano Zampini 917e2ee6c50SBarry Smith lastcol = col; 91849b5e25fSSatish Balay while (high - low > 7) { 91949b5e25fSSatish Balay t = (low + high) / 2; 92049b5e25fSSatish Balay if (rp[t] > bcol) high = t; 92149b5e25fSSatish Balay else low = t; 92249b5e25fSSatish Balay } 92349b5e25fSSatish Balay for (i = low; i < high; i++) { 92449b5e25fSSatish Balay if (rp[i] > bcol) break; 92549b5e25fSSatish Balay if (rp[i] == bcol) { 92649b5e25fSSatish Balay bap = ap + bs2 * i + bs * cidx + ridx; 92749b5e25fSSatish Balay if (is == ADD_VALUES) *bap += value; 92849b5e25fSSatish Balay else *bap = value; 9298549e402SHong Zhang /* for diag block, add/insert its symmetric element a(cidx,ridx) */ 9308549e402SHong Zhang if (brow == bcol && ridx < cidx) { 9318549e402SHong Zhang bap = ap + bs2 * i + bs * ridx + cidx; 9328549e402SHong Zhang if (is == ADD_VALUES) *bap += value; 9338549e402SHong Zhang else *bap = value; 9348549e402SHong Zhang } 93549b5e25fSSatish Balay goto noinsert1; 93649b5e25fSSatish Balay } 93749b5e25fSSatish Balay } 93849b5e25fSSatish Balay 93949b5e25fSSatish Balay if (nonew == 1) goto noinsert1; 94008401ef6SPierre Jolivet PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero (%" PetscInt_FMT ", %" PetscInt_FMT ") in the matrix", row, col); 941fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, brow, bcol, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 94249b5e25fSSatish Balay 9439371c9d4SSatish Balay N = nrow++ - 1; 9449371c9d4SSatish Balay high++; 94549b5e25fSSatish Balay /* shift up all the later entries in this row */ 9469566063dSJacob Faibussowitsch PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1)); 9479566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1))); 9489566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ap + bs2 * i, bs2)); 94949b5e25fSSatish Balay rp[i] = bcol; 95049b5e25fSSatish Balay ap[bs2 * i + bs * cidx + ridx] = value; 9518509e838SStefano Zampini /* for diag block, add/insert its symmetric element a(cidx,ridx) */ 952ad540459SPierre Jolivet if (brow == bcol && ridx < cidx) ap[bs2 * i + bs * ridx + cidx] = value; 953e56f5c9eSBarry Smith A->nonzerostate++; 95449b5e25fSSatish Balay noinsert1:; 95549b5e25fSSatish Balay low = i; 9568549e402SHong Zhang } 95749b5e25fSSatish Balay } /* end of loop over added columns */ 95849b5e25fSSatish Balay ailen[brow] = nrow; 95949b5e25fSSatish Balay } /* end of loop over added rows */ 96049b5e25fSSatish Balay PetscFunctionReturn(0); 96149b5e25fSSatish Balay } 96249b5e25fSSatish Balay 9639371c9d4SSatish Balay PetscErrorCode MatICCFactor_SeqSBAIJ(Mat inA, IS row, const MatFactorInfo *info) { 9644ccecd49SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)inA->data; 96549b5e25fSSatish Balay Mat outA; 966ace3abfcSBarry Smith PetscBool row_identity; 96749b5e25fSSatish Balay 96849b5e25fSSatish Balay PetscFunctionBegin; 96908401ef6SPierre Jolivet PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 is supported for in-place icc"); 9709566063dSJacob Faibussowitsch PetscCall(ISIdentity(row, &row_identity)); 97128b400f6SJacob Faibussowitsch PetscCheck(row_identity, PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix reordering is not supported"); 97208401ef6SPierre 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()! */ 973c84f5b01SHong Zhang 97449b5e25fSSatish Balay outA = inA; 975d5f3da31SBarry Smith inA->factortype = MAT_FACTOR_ICC; 9769566063dSJacob Faibussowitsch PetscCall(PetscFree(inA->solvertype)); 9779566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype)); 97849b5e25fSSatish Balay 9799566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqSBAIJ(inA)); 9809566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetNumericFactorization_inplace(inA, row_identity)); 98149b5e25fSSatish Balay 9829566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)row)); 9839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 984c84f5b01SHong Zhang a->row = row; 9859566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)row)); 9869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 987c84f5b01SHong Zhang a->col = row; 988c84f5b01SHong Zhang 989c84f5b01SHong Zhang /* Create the invert permutation so that it can be used in MatCholeskyFactorNumeric() */ 9909566063dSJacob Faibussowitsch if (a->icol) PetscCall(ISInvertPermutation(row, PETSC_DECIDE, &a->icol)); 99149b5e25fSSatish Balay 992*4dfa11a4SJacob Faibussowitsch if (!a->solve_work) { PetscCall(PetscMalloc1(inA->rmap->N + inA->rmap->bs, &a->solve_work)); } 99349b5e25fSSatish Balay 9949566063dSJacob Faibussowitsch PetscCall(MatCholeskyFactorNumeric(outA, inA, info)); 99549b5e25fSSatish Balay PetscFunctionReturn(0); 99649b5e25fSSatish Balay } 997950f1e5bSHong Zhang 9989371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat, PetscInt *indices) { 999045c9aa0SHong Zhang Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)mat->data; 100013f74950SBarry Smith PetscInt i, nz, n; 100149b5e25fSSatish Balay 100249b5e25fSSatish Balay PetscFunctionBegin; 10036c6c5352SBarry Smith nz = baij->maxnz; 1004d0f46423SBarry Smith n = mat->cmap->n; 100526fbe8dcSKarl Rupp for (i = 0; i < nz; i++) baij->j[i] = indices[i]; 100626fbe8dcSKarl Rupp 10076c6c5352SBarry Smith baij->nz = nz; 100826fbe8dcSKarl Rupp for (i = 0; i < n; i++) baij->ilen[i] = baij->imax[i]; 100926fbe8dcSKarl Rupp 10109566063dSJacob Faibussowitsch PetscCall(MatSetOption(mat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 101149b5e25fSSatish Balay PetscFunctionReturn(0); 101249b5e25fSSatish Balay } 101349b5e25fSSatish Balay 101449b5e25fSSatish Balay /*@ 101519585528SSatish Balay MatSeqSBAIJSetColumnIndices - Set the column indices for all the rows 101611a5261eSBarry Smith in a `MATSEQSBAIJ` matrix. 101749b5e25fSSatish Balay 101849b5e25fSSatish Balay Input Parameters: 101911a5261eSBarry Smith + mat - the `MATSEQSBAIJ` matrix 102049b5e25fSSatish Balay - indices - the column indices 102149b5e25fSSatish Balay 102249b5e25fSSatish Balay Level: advanced 102349b5e25fSSatish Balay 102449b5e25fSSatish Balay Notes: 102549b5e25fSSatish Balay This can be called if you have precomputed the nonzero structure of the 102649b5e25fSSatish Balay matrix and want to provide it to the matrix object to improve the performance 102711a5261eSBarry Smith of the `MatSetValues()` operation. 102849b5e25fSSatish Balay 102949b5e25fSSatish Balay You MUST have set the correct numbers of nonzeros per row in the call to 103011a5261eSBarry Smith `MatCreateSeqSBAIJ()`, and the columns indices MUST be sorted. 103149b5e25fSSatish Balay 1032ab9f2c04SSatish Balay MUST be called before any calls to MatSetValues() 103349b5e25fSSatish Balay 103411a5261eSBarry Smith .seealso: `MATSEQSBAIJ`, `MatCreateSeqSBAIJ` 103549b5e25fSSatish Balay @*/ 10369371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetColumnIndices(Mat mat, PetscInt *indices) { 103749b5e25fSSatish Balay PetscFunctionBegin; 10380700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1039dadcf809SJacob Faibussowitsch PetscValidIntPointer(indices, 2); 1040cac4c232SBarry Smith PetscUseMethod(mat, "MatSeqSBAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices)); 104149b5e25fSSatish Balay PetscFunctionReturn(0); 104249b5e25fSSatish Balay } 104349b5e25fSSatish Balay 10449371c9d4SSatish Balay PetscErrorCode MatCopy_SeqSBAIJ(Mat A, Mat B, MatStructure str) { 10454c7a3774SStefano Zampini PetscBool isbaij; 10463c896bc6SHong Zhang 10473c896bc6SHong Zhang PetscFunctionBegin; 10489566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &isbaij, MATSEQSBAIJ, MATMPISBAIJ, "")); 104928b400f6SJacob Faibussowitsch PetscCheck(isbaij, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)B)->type_name); 10504c7a3774SStefano Zampini /* If the two matrices have the same copy implementation and nonzero pattern, use fast copy. */ 10514c7a3774SStefano Zampini if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) { 10523c896bc6SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 10533c896bc6SHong Zhang Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data; 10543c896bc6SHong Zhang 105508401ef6SPierre 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"); 105608401ef6SPierre Jolivet PetscCheck(a->mbs == b->mbs, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of rows in two matrices are different"); 105708401ef6SPierre Jolivet PetscCheck(a->bs2 == b->bs2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different block size"); 10589566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->a, a->a, a->bs2 * a->i[a->mbs])); 10599566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 10603c896bc6SHong Zhang } else { 10619566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(A)); 10629566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 10639566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(A)); 10643c896bc6SHong Zhang } 10653c896bc6SHong Zhang PetscFunctionReturn(0); 10663c896bc6SHong Zhang } 10673c896bc6SHong Zhang 10689371c9d4SSatish Balay PetscErrorCode MatSetUp_SeqSBAIJ(Mat A) { 1069273d9f13SBarry Smith PetscFunctionBegin; 10709566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(A, A->rmap->bs, PETSC_DEFAULT, NULL)); 1071273d9f13SBarry Smith PetscFunctionReturn(0); 1072273d9f13SBarry Smith } 1073273d9f13SBarry Smith 10749371c9d4SSatish Balay static PetscErrorCode MatSeqSBAIJGetArray_SeqSBAIJ(Mat A, PetscScalar *array[]) { 1075a6ece127SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 10765fd66863SKarl Rupp 1077a6ece127SHong Zhang PetscFunctionBegin; 1078a6ece127SHong Zhang *array = a->a; 1079a6ece127SHong Zhang PetscFunctionReturn(0); 1080a6ece127SHong Zhang } 1081a6ece127SHong Zhang 10829371c9d4SSatish Balay static PetscErrorCode MatSeqSBAIJRestoreArray_SeqSBAIJ(Mat A, PetscScalar *array[]) { 1083a6ece127SHong Zhang PetscFunctionBegin; 1084cda14afcSprj- *array = NULL; 1085a6ece127SHong Zhang PetscFunctionReturn(0); 1086a6ece127SHong Zhang } 1087a6ece127SHong Zhang 10889371c9d4SSatish Balay PetscErrorCode MatAXPYGetPreallocation_SeqSBAIJ(Mat Y, Mat X, PetscInt *nnz) { 1089b264fe52SHong Zhang PetscInt bs = Y->rmap->bs, mbs = Y->rmap->N / bs; 109052768537SHong Zhang Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data; 109152768537SHong Zhang Mat_SeqSBAIJ *y = (Mat_SeqSBAIJ *)Y->data; 109252768537SHong Zhang 109352768537SHong Zhang PetscFunctionBegin; 109452768537SHong Zhang /* Set the number of nonzeros in the new matrix */ 10959566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqX_private(mbs, x->i, x->j, y->i, y->j, nnz)); 109652768537SHong Zhang PetscFunctionReturn(0); 109752768537SHong Zhang } 109852768537SHong Zhang 10999371c9d4SSatish Balay PetscErrorCode MatAXPY_SeqSBAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str) { 110042ee4b1aSHong Zhang Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data, *y = (Mat_SeqSBAIJ *)Y->data; 110131ce2d13SHong Zhang PetscInt bs = Y->rmap->bs, bs2 = bs * bs; 1102e838b9e7SJed Brown PetscBLASInt one = 1; 110342ee4b1aSHong Zhang 110442ee4b1aSHong Zhang PetscFunctionBegin; 1105134adf20SPierre Jolivet if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) { 1106134adf20SPierre Jolivet PetscBool e = x->nz == y->nz && x->mbs == y->mbs ? PETSC_TRUE : PETSC_FALSE; 1107134adf20SPierre Jolivet if (e) { 11089566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->i, y->i, x->mbs + 1, &e)); 1109134adf20SPierre Jolivet if (e) { 11109566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->j, y->j, x->i[x->mbs], &e)); 1111134adf20SPierre Jolivet if (e) str = SAME_NONZERO_PATTERN; 1112134adf20SPierre Jolivet } 1113134adf20SPierre Jolivet } 111454c59aa7SJacob Faibussowitsch if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN"); 1115134adf20SPierre Jolivet } 111642ee4b1aSHong Zhang if (str == SAME_NONZERO_PATTERN) { 1117f4df32b1SMatthew Knepley PetscScalar alpha = a; 1118c5df96a5SBarry Smith PetscBLASInt bnz; 11199566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(x->nz * bs2, &bnz)); 1120792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, x->a, &one, y->a, &one)); 11219566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 1122ab784542SHong Zhang } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 11239566063dSJacob Faibussowitsch PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_TRUE)); 11249566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 11259566063dSJacob Faibussowitsch PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_FALSE)); 112642ee4b1aSHong Zhang } else { 112752768537SHong Zhang Mat B; 112852768537SHong Zhang PetscInt *nnz; 112954c59aa7SJacob Faibussowitsch PetscCheck(bs == X->rmap->bs, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Matrices must have same block size"); 11309566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(X)); 11319566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(Y)); 11329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Y->rmap->N, &nnz)); 11339566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B)); 11349566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name)); 11359566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, Y->rmap->n, Y->cmap->n, Y->rmap->N, Y->cmap->N)); 11369566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, Y, Y)); 11379566063dSJacob Faibussowitsch PetscCall(MatSetType(B, ((PetscObject)Y)->type_name)); 11389566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqSBAIJ(Y, X, nnz)); 11399566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz)); 114052768537SHong Zhang 11419566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 114252768537SHong Zhang 11439566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 11449566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 11459566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(X)); 11469566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(Y)); 114742ee4b1aSHong Zhang } 114842ee4b1aSHong Zhang PetscFunctionReturn(0); 114942ee4b1aSHong Zhang } 115042ee4b1aSHong Zhang 11519371c9d4SSatish Balay PetscErrorCode MatIsSymmetric_SeqSBAIJ(Mat A, PetscReal tol, PetscBool *flg) { 1152efcf0fc3SBarry Smith PetscFunctionBegin; 1153efcf0fc3SBarry Smith *flg = PETSC_TRUE; 1154efcf0fc3SBarry Smith PetscFunctionReturn(0); 1155efcf0fc3SBarry Smith } 1156efcf0fc3SBarry Smith 11579371c9d4SSatish Balay PetscErrorCode MatIsStructurallySymmetric_SeqSBAIJ(Mat A, PetscBool *flg) { 1158efcf0fc3SBarry Smith PetscFunctionBegin; 1159efcf0fc3SBarry Smith *flg = PETSC_TRUE; 1160efcf0fc3SBarry Smith PetscFunctionReturn(0); 1161efcf0fc3SBarry Smith } 1162efcf0fc3SBarry Smith 11639371c9d4SSatish Balay PetscErrorCode MatIsHermitian_SeqSBAIJ(Mat A, PetscReal tol, PetscBool *flg) { 1164efcf0fc3SBarry Smith PetscFunctionBegin; 1165efcf0fc3SBarry Smith *flg = PETSC_FALSE; 1166efcf0fc3SBarry Smith PetscFunctionReturn(0); 1167efcf0fc3SBarry Smith } 1168efcf0fc3SBarry Smith 11699371c9d4SSatish Balay PetscErrorCode MatConjugate_SeqSBAIJ(Mat A) { 11702726fb6dSPierre Jolivet #if defined(PETSC_USE_COMPLEX) 11712726fb6dSPierre Jolivet Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 11722726fb6dSPierre Jolivet PetscInt i, nz = a->bs2 * a->i[a->mbs]; 11732726fb6dSPierre Jolivet MatScalar *aa = a->a; 11742726fb6dSPierre Jolivet 11752726fb6dSPierre Jolivet PetscFunctionBegin; 11762726fb6dSPierre Jolivet for (i = 0; i < nz; i++) aa[i] = PetscConj(aa[i]); 11772726fb6dSPierre Jolivet #else 11782726fb6dSPierre Jolivet PetscFunctionBegin; 11792726fb6dSPierre Jolivet #endif 11802726fb6dSPierre Jolivet PetscFunctionReturn(0); 11812726fb6dSPierre Jolivet } 11822726fb6dSPierre Jolivet 11839371c9d4SSatish Balay PetscErrorCode MatRealPart_SeqSBAIJ(Mat A) { 118499cafbc1SBarry Smith Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 118599cafbc1SBarry Smith PetscInt i, nz = a->bs2 * a->i[a->mbs]; 1186dd6ea824SBarry Smith MatScalar *aa = a->a; 118799cafbc1SBarry Smith 118899cafbc1SBarry Smith PetscFunctionBegin; 118999cafbc1SBarry Smith for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]); 119099cafbc1SBarry Smith PetscFunctionReturn(0); 119199cafbc1SBarry Smith } 119299cafbc1SBarry Smith 11939371c9d4SSatish Balay PetscErrorCode MatImaginaryPart_SeqSBAIJ(Mat A) { 119499cafbc1SBarry Smith Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 119599cafbc1SBarry Smith PetscInt i, nz = a->bs2 * a->i[a->mbs]; 1196dd6ea824SBarry Smith MatScalar *aa = a->a; 119799cafbc1SBarry Smith 119899cafbc1SBarry Smith PetscFunctionBegin; 119999cafbc1SBarry Smith for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]); 120099cafbc1SBarry Smith PetscFunctionReturn(0); 120199cafbc1SBarry Smith } 120299cafbc1SBarry Smith 12039371c9d4SSatish Balay PetscErrorCode MatZeroRowsColumns_SeqSBAIJ(Mat A, PetscInt is_n, const PetscInt is_idx[], PetscScalar diag, Vec x, Vec b) { 12043bededecSBarry Smith Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)A->data; 12053bededecSBarry Smith PetscInt i, j, k, count; 12063bededecSBarry Smith PetscInt bs = A->rmap->bs, bs2 = baij->bs2, row, col; 12073bededecSBarry Smith PetscScalar zero = 0.0; 12083bededecSBarry Smith MatScalar *aa; 12093bededecSBarry Smith const PetscScalar *xx; 12103bededecSBarry Smith PetscScalar *bb; 121156777dd2SBarry Smith PetscBool *zeroed, vecs = PETSC_FALSE; 12123bededecSBarry Smith 12133bededecSBarry Smith PetscFunctionBegin; 12143bededecSBarry Smith /* fix right hand side if needed */ 12153bededecSBarry Smith if (x && b) { 12169566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 12179566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 121856777dd2SBarry Smith vecs = PETSC_TRUE; 12193bededecSBarry Smith } 12203bededecSBarry Smith 12213bededecSBarry Smith /* zero the columns */ 12229566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n, &zeroed)); 12233bededecSBarry Smith for (i = 0; i < is_n; i++) { 1224aed4548fSBarry 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]); 12253bededecSBarry Smith zeroed[is_idx[i]] = PETSC_TRUE; 12263bededecSBarry Smith } 122756777dd2SBarry Smith if (vecs) { 122856777dd2SBarry Smith for (i = 0; i < A->rmap->N; i++) { 122956777dd2SBarry Smith row = i / bs; 123056777dd2SBarry Smith for (j = baij->i[row]; j < baij->i[row + 1]; j++) { 123156777dd2SBarry Smith for (k = 0; k < bs; k++) { 123256777dd2SBarry Smith col = bs * baij->j[j] + k; 123356777dd2SBarry Smith if (col <= i) continue; 123456777dd2SBarry Smith aa = ((MatScalar *)(baij->a)) + j * bs2 + (i % bs) + bs * k; 123526fbe8dcSKarl Rupp if (!zeroed[i] && zeroed[col]) bb[i] -= aa[0] * xx[col]; 123626fbe8dcSKarl Rupp if (zeroed[i] && !zeroed[col]) bb[col] -= aa[0] * xx[i]; 123756777dd2SBarry Smith } 123856777dd2SBarry Smith } 123956777dd2SBarry Smith } 124026fbe8dcSKarl Rupp for (i = 0; i < is_n; i++) bb[is_idx[i]] = diag * xx[is_idx[i]]; 124156777dd2SBarry Smith } 124256777dd2SBarry Smith 12433bededecSBarry Smith for (i = 0; i < A->rmap->N; i++) { 12443bededecSBarry Smith if (!zeroed[i]) { 12453bededecSBarry Smith row = i / bs; 12463bededecSBarry Smith for (j = baij->i[row]; j < baij->i[row + 1]; j++) { 12473bededecSBarry Smith for (k = 0; k < bs; k++) { 12483bededecSBarry Smith col = bs * baij->j[j] + k; 12493bededecSBarry Smith if (zeroed[col]) { 12503bededecSBarry Smith aa = ((MatScalar *)(baij->a)) + j * bs2 + (i % bs) + bs * k; 12513bededecSBarry Smith aa[0] = 0.0; 12523bededecSBarry Smith } 12533bededecSBarry Smith } 12543bededecSBarry Smith } 12553bededecSBarry Smith } 12563bededecSBarry Smith } 12579566063dSJacob Faibussowitsch PetscCall(PetscFree(zeroed)); 125856777dd2SBarry Smith if (vecs) { 12599566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 12609566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 126156777dd2SBarry Smith } 12623bededecSBarry Smith 12633bededecSBarry Smith /* zero the rows */ 12643bededecSBarry Smith for (i = 0; i < is_n; i++) { 12653bededecSBarry Smith row = is_idx[i]; 12663bededecSBarry Smith count = (baij->i[row / bs + 1] - baij->i[row / bs]) * bs; 12673bededecSBarry Smith aa = ((MatScalar *)(baij->a)) + baij->i[row / bs] * bs2 + (row % bs); 12683bededecSBarry Smith for (k = 0; k < count; k++) { 12693bededecSBarry Smith aa[0] = zero; 12703bededecSBarry Smith aa += bs; 12713bededecSBarry Smith } 1272dbbe0bcdSBarry Smith if (diag != 0.0) PetscUseTypeMethod(A, setvalues, 1, &row, 1, &row, &diag, INSERT_VALUES); 12733bededecSBarry Smith } 12749566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_SeqSBAIJ(A, MAT_FINAL_ASSEMBLY)); 12753bededecSBarry Smith PetscFunctionReturn(0); 12763bededecSBarry Smith } 12773bededecSBarry Smith 12789371c9d4SSatish Balay PetscErrorCode MatShift_SeqSBAIJ(Mat Y, PetscScalar a) { 12797d68702bSBarry Smith Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)Y->data; 12807d68702bSBarry Smith 12817d68702bSBarry Smith PetscFunctionBegin; 128248a46eb9SPierre Jolivet if (!Y->preallocated || !aij->nz) PetscCall(MatSeqSBAIJSetPreallocation(Y, Y->rmap->bs, 1, NULL)); 12839566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(Y, a)); 12847d68702bSBarry Smith PetscFunctionReturn(0); 12857d68702bSBarry Smith } 12867d68702bSBarry Smith 128749b5e25fSSatish Balay /* -------------------------------------------------------------------*/ 12883964eb88SJed Brown static struct _MatOps MatOps_Values = {MatSetValues_SeqSBAIJ, 128949b5e25fSSatish Balay MatGetRow_SeqSBAIJ, 129049b5e25fSSatish Balay MatRestoreRow_SeqSBAIJ, 129149b5e25fSSatish Balay MatMult_SeqSBAIJ_N, 129297304618SKris Buschelman /* 4*/ MatMultAdd_SeqSBAIJ_N, 1293431c96f7SBarry Smith MatMult_SeqSBAIJ_N, /* transpose versions are same as non-transpose versions */ 1294e005ede5SBarry Smith MatMultAdd_SeqSBAIJ_N, 1295f4259b30SLisandro Dalcin NULL, 1296f4259b30SLisandro Dalcin NULL, 1297f4259b30SLisandro Dalcin NULL, 1298f4259b30SLisandro Dalcin /* 10*/ NULL, 1299f4259b30SLisandro Dalcin NULL, 1300c078aec8SLisandro Dalcin MatCholeskyFactor_SeqSBAIJ, 130141f059aeSBarry Smith MatSOR_SeqSBAIJ, 130249b5e25fSSatish Balay MatTranspose_SeqSBAIJ, 130397304618SKris Buschelman /* 15*/ MatGetInfo_SeqSBAIJ, 130449b5e25fSSatish Balay MatEqual_SeqSBAIJ, 130549b5e25fSSatish Balay MatGetDiagonal_SeqSBAIJ, 130649b5e25fSSatish Balay MatDiagonalScale_SeqSBAIJ, 130749b5e25fSSatish Balay MatNorm_SeqSBAIJ, 1308f4259b30SLisandro Dalcin /* 20*/ NULL, 130949b5e25fSSatish Balay MatAssemblyEnd_SeqSBAIJ, 131049b5e25fSSatish Balay MatSetOption_SeqSBAIJ, 131149b5e25fSSatish Balay MatZeroEntries_SeqSBAIJ, 1312f4259b30SLisandro Dalcin /* 24*/ NULL, 1313f4259b30SLisandro Dalcin NULL, 1314f4259b30SLisandro Dalcin NULL, 1315f4259b30SLisandro Dalcin NULL, 1316f4259b30SLisandro Dalcin NULL, 13174994cf47SJed Brown /* 29*/ MatSetUp_SeqSBAIJ, 1318f4259b30SLisandro Dalcin NULL, 1319f4259b30SLisandro Dalcin NULL, 1320f4259b30SLisandro Dalcin NULL, 1321f4259b30SLisandro Dalcin NULL, 1322d519adbfSMatthew Knepley /* 34*/ MatDuplicate_SeqSBAIJ, 1323f4259b30SLisandro Dalcin NULL, 1324f4259b30SLisandro Dalcin NULL, 1325f4259b30SLisandro Dalcin NULL, 1326c84f5b01SHong Zhang MatICCFactor_SeqSBAIJ, 1327d519adbfSMatthew Knepley /* 39*/ MatAXPY_SeqSBAIJ, 13287dae84e0SHong Zhang MatCreateSubMatrices_SeqSBAIJ, 132949b5e25fSSatish Balay MatIncreaseOverlap_SeqSBAIJ, 133049b5e25fSSatish Balay MatGetValues_SeqSBAIJ, 13313c896bc6SHong Zhang MatCopy_SeqSBAIJ, 1332f4259b30SLisandro Dalcin /* 44*/ NULL, 133349b5e25fSSatish Balay MatScale_SeqSBAIJ, 13347d68702bSBarry Smith MatShift_SeqSBAIJ, 1335f4259b30SLisandro Dalcin NULL, 13363bededecSBarry Smith MatZeroRowsColumns_SeqSBAIJ, 1337f4259b30SLisandro Dalcin /* 49*/ NULL, 133849b5e25fSSatish Balay MatGetRowIJ_SeqSBAIJ, 133949b5e25fSSatish Balay MatRestoreRowIJ_SeqSBAIJ, 1340f4259b30SLisandro Dalcin NULL, 1341f4259b30SLisandro Dalcin NULL, 1342f4259b30SLisandro Dalcin /* 54*/ NULL, 1343f4259b30SLisandro Dalcin NULL, 1344f4259b30SLisandro Dalcin NULL, 1345dc29a518SPierre Jolivet MatPermute_SeqSBAIJ, 134649b5e25fSSatish Balay MatSetValuesBlocked_SeqSBAIJ, 13477dae84e0SHong Zhang /* 59*/ MatCreateSubMatrix_SeqSBAIJ, 1348f4259b30SLisandro Dalcin NULL, 1349f4259b30SLisandro Dalcin NULL, 1350f4259b30SLisandro Dalcin NULL, 1351f4259b30SLisandro Dalcin NULL, 1352f4259b30SLisandro Dalcin /* 64*/ NULL, 1353f4259b30SLisandro Dalcin NULL, 1354f4259b30SLisandro Dalcin NULL, 1355f4259b30SLisandro Dalcin NULL, 1356f4259b30SLisandro Dalcin NULL, 1357d519adbfSMatthew Knepley /* 69*/ MatGetRowMaxAbs_SeqSBAIJ, 1358f4259b30SLisandro Dalcin NULL, 135928d58a37SPierre Jolivet MatConvert_MPISBAIJ_Basic, 1360f4259b30SLisandro Dalcin NULL, 1361f4259b30SLisandro Dalcin NULL, 1362f4259b30SLisandro Dalcin /* 74*/ NULL, 1363f4259b30SLisandro Dalcin NULL, 1364f4259b30SLisandro Dalcin NULL, 1365f4259b30SLisandro Dalcin NULL, 1366f4259b30SLisandro Dalcin NULL, 1367f4259b30SLisandro Dalcin /* 79*/ NULL, 1368f4259b30SLisandro Dalcin NULL, 1369f4259b30SLisandro Dalcin NULL, 137097304618SKris Buschelman MatGetInertia_SeqSBAIJ, 13715bba2384SShri Abhyankar MatLoad_SeqSBAIJ, 1372d519adbfSMatthew Knepley /* 84*/ MatIsSymmetric_SeqSBAIJ, 1373865e5f61SKris Buschelman MatIsHermitian_SeqSBAIJ, 1374efcf0fc3SBarry Smith MatIsStructurallySymmetric_SeqSBAIJ, 1375f4259b30SLisandro Dalcin NULL, 1376f4259b30SLisandro Dalcin NULL, 1377f4259b30SLisandro Dalcin /* 89*/ NULL, 1378f4259b30SLisandro Dalcin NULL, 1379f4259b30SLisandro Dalcin NULL, 1380f4259b30SLisandro Dalcin NULL, 1381f4259b30SLisandro Dalcin NULL, 1382f4259b30SLisandro Dalcin /* 94*/ NULL, 1383f4259b30SLisandro Dalcin NULL, 1384f4259b30SLisandro Dalcin NULL, 1385f4259b30SLisandro Dalcin NULL, 1386f4259b30SLisandro Dalcin NULL, 1387f4259b30SLisandro Dalcin /* 99*/ NULL, 1388f4259b30SLisandro Dalcin NULL, 1389f4259b30SLisandro Dalcin NULL, 13902726fb6dSPierre Jolivet MatConjugate_SeqSBAIJ, 1391f4259b30SLisandro Dalcin NULL, 1392f4259b30SLisandro Dalcin /*104*/ NULL, 139399cafbc1SBarry Smith MatRealPart_SeqSBAIJ, 1394f5edf698SHong Zhang MatImaginaryPart_SeqSBAIJ, 1395f5edf698SHong Zhang MatGetRowUpperTriangular_SeqSBAIJ, 13962af78befSBarry Smith MatRestoreRowUpperTriangular_SeqSBAIJ, 1397f4259b30SLisandro Dalcin /*109*/ NULL, 1398f4259b30SLisandro Dalcin NULL, 1399f4259b30SLisandro Dalcin NULL, 1400f4259b30SLisandro Dalcin NULL, 1401547795f9SHong Zhang MatMissingDiagonal_SeqSBAIJ, 1402f4259b30SLisandro Dalcin /*114*/ NULL, 1403f4259b30SLisandro Dalcin NULL, 1404f4259b30SLisandro Dalcin NULL, 1405f4259b30SLisandro Dalcin NULL, 1406f4259b30SLisandro Dalcin NULL, 1407f4259b30SLisandro Dalcin /*119*/ NULL, 1408f4259b30SLisandro Dalcin NULL, 1409f4259b30SLisandro Dalcin NULL, 1410f4259b30SLisandro Dalcin NULL, 1411f4259b30SLisandro Dalcin NULL, 1412f4259b30SLisandro Dalcin /*124*/ NULL, 1413f4259b30SLisandro Dalcin NULL, 1414f4259b30SLisandro Dalcin NULL, 1415f4259b30SLisandro Dalcin NULL, 1416f4259b30SLisandro Dalcin NULL, 1417f4259b30SLisandro Dalcin /*129*/ NULL, 1418f4259b30SLisandro Dalcin NULL, 1419f4259b30SLisandro Dalcin NULL, 1420f4259b30SLisandro Dalcin NULL, 1421f4259b30SLisandro Dalcin NULL, 1422f4259b30SLisandro Dalcin /*134*/ NULL, 1423f4259b30SLisandro Dalcin NULL, 1424f4259b30SLisandro Dalcin NULL, 1425f4259b30SLisandro Dalcin NULL, 1426f4259b30SLisandro Dalcin NULL, 142746533700Sstefano_zampini /*139*/ MatSetBlockSizes_Default, 1428f4259b30SLisandro Dalcin NULL, 1429f4259b30SLisandro Dalcin NULL, 1430f4259b30SLisandro Dalcin NULL, 1431f4259b30SLisandro Dalcin NULL, 1432d70f29a3SPierre Jolivet /*144*/ MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ, 1433d70f29a3SPierre Jolivet NULL, 1434d70f29a3SPierre Jolivet NULL, 143599a7f59eSMark Adams NULL, 143699a7f59eSMark Adams NULL, 14377fb60732SBarry Smith NULL, 14389371c9d4SSatish Balay /*150*/ NULL}; 1439be1d678aSKris Buschelman 14409371c9d4SSatish Balay PetscErrorCode MatStoreValues_SeqSBAIJ(Mat mat) { 14414afc71dfSHong Zhang Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data; 1442d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2; 144349b5e25fSSatish Balay 144449b5e25fSSatish Balay PetscFunctionBegin; 144508401ef6SPierre Jolivet PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 144649b5e25fSSatish Balay 144749b5e25fSSatish Balay /* allocate space for values if not already there */ 144848a46eb9SPierre Jolivet if (!aij->saved_values) PetscCall(PetscMalloc1(nz + 1, &aij->saved_values)); 144949b5e25fSSatish Balay 145049b5e25fSSatish Balay /* copy values over */ 14519566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz)); 145249b5e25fSSatish Balay PetscFunctionReturn(0); 145349b5e25fSSatish Balay } 145449b5e25fSSatish Balay 14559371c9d4SSatish Balay PetscErrorCode MatRetrieveValues_SeqSBAIJ(Mat mat) { 14564afc71dfSHong Zhang Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data; 1457d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2; 145849b5e25fSSatish Balay 145949b5e25fSSatish Balay PetscFunctionBegin; 146008401ef6SPierre Jolivet PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 146128b400f6SJacob Faibussowitsch PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first"); 146249b5e25fSSatish Balay 146349b5e25fSSatish Balay /* copy values over */ 14649566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz)); 146549b5e25fSSatish Balay PetscFunctionReturn(0); 146649b5e25fSSatish Balay } 146749b5e25fSSatish Balay 14689371c9d4SSatish Balay static PetscErrorCode MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B, PetscInt bs, PetscInt nz, PetscInt *nnz) { 1469c464158bSHong Zhang Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data; 14704dcd73b1SHong Zhang PetscInt i, mbs, nbs, bs2; 14712576faa2SJed Brown PetscBool skipallocation = PETSC_FALSE, flg = PETSC_FALSE, realalloc = PETSC_FALSE; 147249b5e25fSSatish Balay 147349b5e25fSSatish Balay PetscFunctionBegin; 14742576faa2SJed Brown if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 1475db4efbfdSBarry Smith 14769566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B, PetscAbs(bs))); 14779566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 14789566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 147908401ef6SPierre 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); 14809566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs)); 1481899cda47SBarry Smith 148221940c7eSstefano_zampini B->preallocated = PETSC_TRUE; 148321940c7eSstefano_zampini 1484d0f46423SBarry Smith mbs = B->rmap->N / bs; 14854dcd73b1SHong Zhang nbs = B->cmap->n / bs; 148649b5e25fSSatish Balay bs2 = bs * bs; 148749b5e25fSSatish Balay 1488aed4548fSBarry 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"); 148949b5e25fSSatish Balay 1490ab93d7beSBarry Smith if (nz == MAT_SKIP_ALLOCATION) { 1491ab93d7beSBarry Smith skipallocation = PETSC_TRUE; 1492ab93d7beSBarry Smith nz = 0; 1493ab93d7beSBarry Smith } 1494ab93d7beSBarry Smith 1495435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3; 149608401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz); 149749b5e25fSSatish Balay if (nnz) { 149849b5e25fSSatish Balay for (i = 0; i < mbs; i++) { 149908401ef6SPierre 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]); 150008401ef6SPierre 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); 150149b5e25fSSatish Balay } 150249b5e25fSSatish Balay } 150349b5e25fSSatish Balay 1504db4efbfdSBarry Smith B->ops->mult = MatMult_SeqSBAIJ_N; 1505db4efbfdSBarry Smith B->ops->multadd = MatMultAdd_SeqSBAIJ_N; 1506db4efbfdSBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_N; 1507db4efbfdSBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N; 150826fbe8dcSKarl Rupp 15099566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL)); 151049b5e25fSSatish Balay if (!flg) { 151149b5e25fSSatish Balay switch (bs) { 151249b5e25fSSatish Balay case 1: 151349b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_1; 151449b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_1; 1515431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_1; 1516431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1; 151749b5e25fSSatish Balay break; 151849b5e25fSSatish Balay case 2: 151949b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_2; 152049b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_2; 1521431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_2; 1522431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2; 152349b5e25fSSatish Balay break; 152449b5e25fSSatish Balay case 3: 152549b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_3; 152649b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_3; 1527431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_3; 1528431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3; 152949b5e25fSSatish Balay break; 153049b5e25fSSatish Balay case 4: 153149b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_4; 153249b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_4; 1533431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_4; 1534431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4; 153549b5e25fSSatish Balay break; 153649b5e25fSSatish Balay case 5: 153749b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_5; 153849b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_5; 1539431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_5; 1540431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5; 154149b5e25fSSatish Balay break; 154249b5e25fSSatish Balay case 6: 154349b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_6; 154449b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_6; 1545431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_6; 1546431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6; 154749b5e25fSSatish Balay break; 154849b5e25fSSatish Balay case 7: 1549de53e5efSHong Zhang B->ops->mult = MatMult_SeqSBAIJ_7; 155049b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_7; 1551431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_7; 1552431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7; 155349b5e25fSSatish Balay break; 155449b5e25fSSatish Balay } 155549b5e25fSSatish Balay } 155649b5e25fSSatish Balay 155749b5e25fSSatish Balay b->mbs = mbs; 15584dcd73b1SHong Zhang b->nbs = nbs; 1559ab93d7beSBarry Smith if (!skipallocation) { 15602ee49352SLisandro Dalcin if (!b->imax) { 15619566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(mbs, &b->imax, mbs, &b->ilen)); 156226fbe8dcSKarl Rupp 1563c760cd28SBarry Smith b->free_imax_ilen = PETSC_TRUE; 15642ee49352SLisandro Dalcin } 156549b5e25fSSatish Balay if (!nnz) { 1566435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 156749b5e25fSSatish Balay else if (nz <= 0) nz = 1; 15685d2a9ed1SStefano Zampini nz = PetscMin(nbs, nz); 156926fbe8dcSKarl Rupp for (i = 0; i < mbs; i++) b->imax[i] = nz; 15709566063dSJacob Faibussowitsch PetscCall(PetscIntMultError(nz, mbs, &nz)); 157149b5e25fSSatish Balay } else { 1572c73702f5SBarry Smith PetscInt64 nz64 = 0; 15739371c9d4SSatish Balay for (i = 0; i < mbs; i++) { 15749371c9d4SSatish Balay b->imax[i] = nnz[i]; 15759371c9d4SSatish Balay nz64 += nnz[i]; 15769371c9d4SSatish Balay } 15779566063dSJacob Faibussowitsch PetscCall(PetscIntCast(nz64, &nz)); 157849b5e25fSSatish Balay } 15792ee49352SLisandro Dalcin /* b->ilen will count nonzeros in each block row so far. */ 158026fbe8dcSKarl Rupp for (i = 0; i < mbs; i++) b->ilen[i] = 0; 15816c6c5352SBarry Smith /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */ 158249b5e25fSSatish Balay 158349b5e25fSSatish Balay /* allocate the matrix space */ 15849566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i)); 15859566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(bs2 * nz, &b->a, nz, &b->j, B->rmap->N + 1, &b->i)); 15869566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(b->a, nz * bs2)); 15879566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(b->j, nz)); 158826fbe8dcSKarl Rupp 158949b5e25fSSatish Balay b->singlemalloc = PETSC_TRUE; 159049b5e25fSSatish Balay 159149b5e25fSSatish Balay /* pointer to beginning of each row */ 1592e60cf9a0SBarry Smith b->i[0] = 0; 159326fbe8dcSKarl Rupp for (i = 1; i < mbs + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1]; 159426fbe8dcSKarl Rupp 1595e6b907acSBarry Smith b->free_a = PETSC_TRUE; 1596e6b907acSBarry Smith b->free_ij = PETSC_TRUE; 1597e811da20SHong Zhang } else { 1598e6b907acSBarry Smith b->free_a = PETSC_FALSE; 1599e6b907acSBarry Smith b->free_ij = PETSC_FALSE; 1600ab93d7beSBarry Smith } 160149b5e25fSSatish Balay 160249b5e25fSSatish Balay b->bs2 = bs2; 16036c6c5352SBarry Smith b->nz = 0; 1604b32cb4a7SJed Brown b->maxnz = nz; 1605f4259b30SLisandro Dalcin b->inew = NULL; 1606f4259b30SLisandro Dalcin b->jnew = NULL; 1607f4259b30SLisandro Dalcin b->anew = NULL; 1608f4259b30SLisandro Dalcin b->a2anew = NULL; 16091a3463dfSHong Zhang b->permute = PETSC_FALSE; 1610cb7b82ddSBarry Smith 1611cb7b82ddSBarry Smith B->was_assembled = PETSC_FALSE; 1612cb7b82ddSBarry Smith B->assembled = PETSC_FALSE; 16139566063dSJacob Faibussowitsch if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 1614c464158bSHong Zhang PetscFunctionReturn(0); 1615c464158bSHong Zhang } 1616153ea458SHong Zhang 16179371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ(Mat B, PetscInt bs, const PetscInt ii[], const PetscInt jj[], const PetscScalar V[]) { 16180cd7f59aSBarry Smith PetscInt i, j, m, nz, anz, nz_max = 0, *nnz; 1619f4259b30SLisandro Dalcin PetscScalar *values = NULL; 162038f409ebSLisandro Dalcin PetscBool roworiented = ((Mat_SeqSBAIJ *)B->data)->roworiented; 16210cd7f59aSBarry Smith 162238f409ebSLisandro Dalcin PetscFunctionBegin; 162308401ef6SPierre Jolivet PetscCheck(bs >= 1, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_OUTOFRANGE, "Invalid block size specified, must be positive but it is %" PetscInt_FMT, bs); 16249566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(B->rmap, bs)); 16259566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(B->cmap, bs)); 16269566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 16279566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 16289566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs)); 162938f409ebSLisandro Dalcin m = B->rmap->n / bs; 163038f409ebSLisandro Dalcin 1631aed4548fSBarry Smith PetscCheck(!ii[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ii[0] must be 0 but it is %" PetscInt_FMT, ii[0]); 16329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nnz)); 163338f409ebSLisandro Dalcin for (i = 0; i < m; i++) { 163438f409ebSLisandro Dalcin nz = ii[i + 1] - ii[i]; 163508401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz); 16360cd7f59aSBarry Smith anz = 0; 16370cd7f59aSBarry Smith for (j = 0; j < nz; j++) { 16380cd7f59aSBarry Smith /* count only values on the diagonal or above */ 16390cd7f59aSBarry Smith if (jj[ii[i] + j] >= i) { 16400cd7f59aSBarry Smith anz = nz - j; 16410cd7f59aSBarry Smith break; 16420cd7f59aSBarry Smith } 16430cd7f59aSBarry Smith } 16440cd7f59aSBarry Smith nz_max = PetscMax(nz_max, anz); 16450cd7f59aSBarry Smith nnz[i] = anz; 164638f409ebSLisandro Dalcin } 16479566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz)); 16489566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 164938f409ebSLisandro Dalcin 165038f409ebSLisandro Dalcin values = (PetscScalar *)V; 165148a46eb9SPierre Jolivet if (!values) PetscCall(PetscCalloc1(bs * bs * nz_max, &values)); 165238f409ebSLisandro Dalcin for (i = 0; i < m; i++) { 165338f409ebSLisandro Dalcin PetscInt ncols = ii[i + 1] - ii[i]; 165438f409ebSLisandro Dalcin const PetscInt *icols = jj + ii[i]; 165538f409ebSLisandro Dalcin if (!roworiented || bs == 1) { 165638f409ebSLisandro Dalcin const PetscScalar *svals = values + (V ? (bs * bs * ii[i]) : 0); 16579566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, ncols, icols, svals, INSERT_VALUES)); 165838f409ebSLisandro Dalcin } else { 165938f409ebSLisandro Dalcin for (j = 0; j < ncols; j++) { 166038f409ebSLisandro Dalcin const PetscScalar *svals = values + (V ? (bs * bs * (ii[i] + j)) : 0); 16619566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, 1, &icols[j], svals, INSERT_VALUES)); 166238f409ebSLisandro Dalcin } 166338f409ebSLisandro Dalcin } 166438f409ebSLisandro Dalcin } 16659566063dSJacob Faibussowitsch if (!V) PetscCall(PetscFree(values)); 16669566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 16679566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 16689566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 166938f409ebSLisandro Dalcin PetscFunctionReturn(0); 167038f409ebSLisandro Dalcin } 167138f409ebSLisandro Dalcin 1672db4efbfdSBarry Smith /* 1673db4efbfdSBarry Smith This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization 1674db4efbfdSBarry Smith */ 16759371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetNumericFactorization_inplace(Mat B, PetscBool natural) { 1676ace3abfcSBarry Smith PetscBool flg = PETSC_FALSE; 1677db4efbfdSBarry Smith PetscInt bs = B->rmap->bs; 1678db4efbfdSBarry Smith 1679db4efbfdSBarry Smith PetscFunctionBegin; 16809566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL)); 1681db4efbfdSBarry Smith if (flg) bs = 8; 1682db4efbfdSBarry Smith 1683db4efbfdSBarry Smith if (!natural) { 1684db4efbfdSBarry Smith switch (bs) { 16859371c9d4SSatish Balay case 1: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_inplace; break; 16869371c9d4SSatish Balay case 2: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2; break; 16879371c9d4SSatish Balay case 3: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3; break; 16889371c9d4SSatish Balay case 4: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4; break; 16899371c9d4SSatish Balay case 5: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5; break; 16909371c9d4SSatish Balay case 6: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6; break; 16919371c9d4SSatish Balay case 7: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7; break; 16929371c9d4SSatish Balay default: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N; break; 1693db4efbfdSBarry Smith } 1694db4efbfdSBarry Smith } else { 1695db4efbfdSBarry Smith switch (bs) { 16969371c9d4SSatish Balay case 1: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering_inplace; break; 16979371c9d4SSatish Balay case 2: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering; break; 16989371c9d4SSatish Balay case 3: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering; break; 16999371c9d4SSatish Balay case 4: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering; break; 17009371c9d4SSatish Balay case 5: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering; break; 17019371c9d4SSatish Balay case 6: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering; break; 17029371c9d4SSatish Balay case 7: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering; break; 17039371c9d4SSatish Balay default: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering; break; 1704db4efbfdSBarry Smith } 1705db4efbfdSBarry Smith } 1706db4efbfdSBarry Smith PetscFunctionReturn(0); 1707db4efbfdSBarry Smith } 1708db4efbfdSBarry Smith 1709cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType, MatReuse, Mat *); 1710cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType, MatReuse, Mat *); 17119371c9d4SSatish Balay static PetscErrorCode MatFactorGetSolverType_petsc(Mat A, MatSolverType *type) { 17124ac6704cSBarry Smith PetscFunctionBegin; 17134ac6704cSBarry Smith *type = MATSOLVERPETSC; 17144ac6704cSBarry Smith PetscFunctionReturn(0); 17154ac6704cSBarry Smith } 1716d769727bSBarry Smith 17179371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A, MatFactorType ftype, Mat *B) { 1718d0f46423SBarry Smith PetscInt n = A->rmap->n; 17195c9eb25fSBarry Smith 17205c9eb25fSBarry Smith PetscFunctionBegin; 17210e92d65fSHong Zhang #if defined(PETSC_USE_COMPLEX) 1722b94d7dedSBarry Smith PetscCheck(A->hermitian != PETSC_BOOL3_TRUE || A->symmetric == PETSC_BOOL3_TRUE || (ftype != MAT_FACTOR_CHOLESKY && ftype != MAT_FACTOR_ICC), PETSC_COMM_SELF, PETSC_ERR_SUP, "Hermitian CHOLESKY or ICC Factor is not supported"); 17230e92d65fSHong Zhang #endif 1724eb1ec7c1SStefano Zampini 17259566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 17269566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, n, n, n, n)); 17275c9eb25fSBarry Smith if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) { 17289566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, MATSEQSBAIJ)); 17299566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(*B, A->rmap->bs, MAT_SKIP_ALLOCATION, NULL)); 173026fbe8dcSKarl Rupp 17317b056e98SHong Zhang (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ; 1732c6d0d4f0SHong Zhang (*B)->ops->iccfactorsymbolic = MatICCFactorSymbolic_SeqSBAIJ; 17339566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_CHOLESKY])); 17349566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_ICC])); 1735e32f2f54SBarry Smith } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Factor type not supported"); 173600c67f3bSHong Zhang 1737d5f3da31SBarry Smith (*B)->factortype = ftype; 1738f73b0415SBarry Smith (*B)->canuseordering = PETSC_TRUE; 17399566063dSJacob Faibussowitsch PetscCall(PetscFree((*B)->solvertype)); 17409566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*B)->solvertype)); 17419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)*B, "MatFactorGetSolverType_C", MatFactorGetSolverType_petsc)); 17425c9eb25fSBarry Smith PetscFunctionReturn(0); 17435c9eb25fSBarry Smith } 17445c9eb25fSBarry Smith 17458397e458SBarry Smith /*@C 174611a5261eSBarry Smith MatSeqSBAIJGetArray - gives access to the array where the data for a `MATSEQSBAIJ` matrix is stored 17478397e458SBarry Smith 17488397e458SBarry Smith Not Collective 17498397e458SBarry Smith 17508397e458SBarry Smith Input Parameter: 175111a5261eSBarry Smith . mat - a `MATSEQSBAIJ` matrix 17528397e458SBarry Smith 17538397e458SBarry Smith Output Parameter: 17548397e458SBarry Smith . array - pointer to the data 17558397e458SBarry Smith 17568397e458SBarry Smith Level: intermediate 17578397e458SBarry Smith 175811a5261eSBarry Smith .seealso: `MATSEQSBAIJ`, `MatSeqSBAIJRestoreArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()` 17598397e458SBarry Smith @*/ 17609371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJGetArray(Mat A, PetscScalar **array) { 17618397e458SBarry Smith PetscFunctionBegin; 1762cac4c232SBarry Smith PetscUseMethod(A, "MatSeqSBAIJGetArray_C", (Mat, PetscScalar **), (A, array)); 17638397e458SBarry Smith PetscFunctionReturn(0); 17648397e458SBarry Smith } 17658397e458SBarry Smith 17668397e458SBarry Smith /*@C 176711a5261eSBarry Smith MatSeqSBAIJRestoreArray - returns access to the array where the data for a `MATSEQSBAIJ` matrix is stored obtained by `MatSeqSBAIJGetArray()` 17688397e458SBarry Smith 17698397e458SBarry Smith Not Collective 17708397e458SBarry Smith 17718397e458SBarry Smith Input Parameters: 1772a2b725a8SWilliam Gropp + mat - a MATSEQSBAIJ matrix 1773a2b725a8SWilliam Gropp - array - pointer to the data 17748397e458SBarry Smith 17758397e458SBarry Smith Level: intermediate 17768397e458SBarry Smith 177711a5261eSBarry Smith .seealso: `MATSEQSBAIJ`, `MatSeqSBAIJGetArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()` 17788397e458SBarry Smith @*/ 17799371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJRestoreArray(Mat A, PetscScalar **array) { 17808397e458SBarry Smith PetscFunctionBegin; 1781cac4c232SBarry Smith PetscUseMethod(A, "MatSeqSBAIJRestoreArray_C", (Mat, PetscScalar **), (A, array)); 17828397e458SBarry Smith PetscFunctionReturn(0); 17838397e458SBarry Smith } 17848397e458SBarry Smith 17850bad9183SKris Buschelman /*MC 1786fafad747SKris Buschelman MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices, 17870bad9183SKris Buschelman based on block compressed sparse row format. Only the upper triangular portion of the matrix is stored. 17880bad9183SKris Buschelman 1789828413b8SBarry Smith For complex numbers by default this matrix is symmetric, NOT Hermitian symmetric. To make it Hermitian symmetric you 179011a5261eSBarry Smith can call `MatSetOption`(`Mat`, `MAT_HERMITIAN`). 1791828413b8SBarry Smith 17920bad9183SKris Buschelman Options Database Keys: 179311a5261eSBarry Smith . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to `MatSetFromOptions()` 17940bad9183SKris Buschelman 179595452b02SPatrick Sanan Notes: 179695452b02SPatrick Sanan By default if you insert values into the lower triangular part of the matrix they are simply ignored (since they are not 179711a5261eSBarry 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 179871dad5bbSBarry 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. 179971dad5bbSBarry Smith 1800476417e5SBarry Smith The number of rows in the matrix must be less than or equal to the number of columns 180171dad5bbSBarry Smith 18020bad9183SKris Buschelman Level: beginner 18030bad9183SKris Buschelman 180411a5261eSBarry Smith .seealso: `MATSEQSBAIJ`, `MatCreateSeqSBAIJ()`, `MatType`, `MATMPISBAIJ` 18050bad9183SKris Buschelman M*/ 18069371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_SeqSBAIJ(Mat B) { 1807a23d5eceSKris Buschelman Mat_SeqSBAIJ *b; 180813f74950SBarry Smith PetscMPIInt size; 1809ace3abfcSBarry Smith PetscBool no_unroll = PETSC_FALSE, no_inode = PETSC_FALSE; 1810a23d5eceSKris Buschelman 1811a23d5eceSKris Buschelman PetscFunctionBegin; 18129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size)); 181308401ef6SPierre Jolivet PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1"); 1814a23d5eceSKris Buschelman 1815*4dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&b)); 1816a23d5eceSKris Buschelman B->data = (void *)b; 18179566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(B->ops, &MatOps_Values, sizeof(struct _MatOps))); 181826fbe8dcSKarl Rupp 1819a23d5eceSKris Buschelman B->ops->destroy = MatDestroy_SeqSBAIJ; 1820a23d5eceSKris Buschelman B->ops->view = MatView_SeqSBAIJ; 1821f4259b30SLisandro Dalcin b->row = NULL; 1822f4259b30SLisandro Dalcin b->icol = NULL; 1823a23d5eceSKris Buschelman b->reallocs = 0; 1824f4259b30SLisandro Dalcin b->saved_values = NULL; 18250def2e27SBarry Smith b->inode.limit = 5; 18260def2e27SBarry Smith b->inode.max_limit = 5; 1827a23d5eceSKris Buschelman 1828a23d5eceSKris Buschelman b->roworiented = PETSC_TRUE; 1829a23d5eceSKris Buschelman b->nonew = 0; 1830f4259b30SLisandro Dalcin b->diag = NULL; 1831f4259b30SLisandro Dalcin b->solve_work = NULL; 1832f4259b30SLisandro Dalcin b->mult_work = NULL; 1833f4259b30SLisandro Dalcin B->spptr = NULL; 1834f2cbd3d5SJed Brown B->info.nz_unneeded = (PetscReal)b->maxnz * b->bs2; 1835a9817697SBarry Smith b->keepnonzeropattern = PETSC_FALSE; 1836a23d5eceSKris Buschelman 1837f4259b30SLisandro Dalcin b->inew = NULL; 1838f4259b30SLisandro Dalcin b->jnew = NULL; 1839f4259b30SLisandro Dalcin b->anew = NULL; 1840f4259b30SLisandro Dalcin b->a2anew = NULL; 1841a23d5eceSKris Buschelman b->permute = PETSC_FALSE; 1842a23d5eceSKris Buschelman 184371dad5bbSBarry Smith b->ignore_ltriangular = PETSC_TRUE; 184426fbe8dcSKarl Rupp 18459566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_ignore_lower_triangular", &b->ignore_ltriangular, NULL)); 1846941593c8SHong Zhang 1847f5edf698SHong Zhang b->getrow_utriangular = PETSC_FALSE; 184826fbe8dcSKarl Rupp 18499566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_getrow_uppertriangular", &b->getrow_utriangular, NULL)); 1850f5edf698SHong Zhang 18519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJGetArray_C", MatSeqSBAIJGetArray_SeqSBAIJ)); 18529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJRestoreArray_C", MatSeqSBAIJRestoreArray_SeqSBAIJ)); 18539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqSBAIJ)); 18549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqSBAIJ)); 18559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetColumnIndices_C", MatSeqSBAIJSetColumnIndices_SeqSBAIJ)); 18569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqaij_C", MatConvert_SeqSBAIJ_SeqAIJ)); 18579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqbaij_C", MatConvert_SeqSBAIJ_SeqBAIJ)); 18589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocation_C", MatSeqSBAIJSetPreallocation_SeqSBAIJ)); 18599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocationCSR_C", MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ)); 18606214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 18619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_elemental_C", MatConvert_SeqSBAIJ_Elemental)); 18626214f412SHong Zhang #endif 1863d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 18649566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_scalapack_C", MatConvert_SBAIJ_ScaLAPACK)); 1865d24d4204SJose E. Roman #endif 186623ce1328SBarry Smith 1867b94d7dedSBarry Smith B->symmetry_eternal = PETSC_TRUE; 1868b94d7dedSBarry Smith B->structural_symmetry_eternal = PETSC_TRUE; 1869b94d7dedSBarry Smith B->symmetric = PETSC_BOOL3_TRUE; 1870b94d7dedSBarry Smith B->structurally_symmetric = PETSC_BOOL3_TRUE; 1871eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 1872b94d7dedSBarry Smith B->hermitian = PETSC_BOOL3_FALSE; 1873eb1ec7c1SStefano Zampini #else 1874b94d7dedSBarry Smith B->hermitian = PETSC_BOOL3_TRUE; 1875eb1ec7c1SStefano Zampini #endif 187613647f61SHong Zhang 18779566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQSBAIJ)); 18780def2e27SBarry Smith 1879d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)B), ((PetscObject)B)->prefix, "Options for SEQSBAIJ matrix", "Mat"); 18809566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-mat_no_unroll", "Do not optimize for inodes (slower)", NULL, no_unroll, &no_unroll, NULL)); 188148a46eb9SPierre Jolivet if (no_unroll) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_unroll\n")); 18829566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-mat_no_inode", "Do not optimize for inodes (slower)", NULL, no_inode, &no_inode, NULL)); 18839566063dSJacob Faibussowitsch if (no_inode) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_inode\n")); 18849566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-mat_inode_limit", "Do not use inodes larger then this value", NULL, b->inode.limit, &b->inode.limit, NULL)); 1885d0609cedSBarry Smith PetscOptionsEnd(); 1886ace3abfcSBarry Smith b->inode.use = (PetscBool)(!(no_unroll || no_inode)); 18870def2e27SBarry Smith if (b->inode.limit > b->inode.max_limit) b->inode.limit = b->inode.max_limit; 1888a23d5eceSKris Buschelman PetscFunctionReturn(0); 1889a23d5eceSKris Buschelman } 1890a23d5eceSKris Buschelman 1891a23d5eceSKris Buschelman /*@C 1892a23d5eceSKris Buschelman MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block 189311a5261eSBarry Smith compressed row) `MATSEQSBAIJ` format. For good matrix assembly performance the 1894a23d5eceSKris Buschelman user should preallocate the matrix storage by setting the parameter nz 1895a23d5eceSKris Buschelman (or the array nnz). By setting these parameters accurately, performance 1896a23d5eceSKris Buschelman during matrix assembly can be increased by more than a factor of 50. 1897a23d5eceSKris Buschelman 1898a23d5eceSKris Buschelman Collective on Mat 1899a23d5eceSKris Buschelman 1900a23d5eceSKris Buschelman Input Parameters: 19011c4f3114SJed Brown + B - the symmetric matrix 190211a5261eSBarry 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 190311a5261eSBarry Smith blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with `MatCreateVecs()` 1904a23d5eceSKris Buschelman . nz - number of block nonzeros per block row (same for all rows) 1905a23d5eceSKris Buschelman - nnz - array containing the number of block nonzeros in the upper triangular plus 19060298fd71SBarry Smith diagonal portion of each block (possibly different for each block row) or NULL 1907a23d5eceSKris Buschelman 1908a23d5eceSKris Buschelman Options Database Keys: 1909a2b725a8SWilliam Gropp + -mat_no_unroll - uses code that does not unroll the loops in the 1910a23d5eceSKris Buschelman block calculations (much slower) 1911a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use (only works if a negative bs is passed in 1912a23d5eceSKris Buschelman 1913a23d5eceSKris Buschelman Level: intermediate 1914a23d5eceSKris Buschelman 1915a23d5eceSKris Buschelman Notes: 1916a23d5eceSKris Buschelman Specify the preallocated storage with either nz or nnz (not both). 191711a5261eSBarry Smith Set nz = `PETSC_DEFAULT` and nnz = NULL for PETSc to control dynamic memory 1918651615e1SBarry Smith allocation. See [Sparse Matrices](sec_matsparse) for details. 1919a23d5eceSKris Buschelman 192011a5261eSBarry Smith You can call `MatGetInfo()` to get information on how effective the preallocation was; 1921aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 1922aa95bbe8SBarry Smith You can also run with the option -info and look for messages with the string 1923aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 1924aa95bbe8SBarry Smith 192549a6f317SBarry Smith If the nnz parameter is given then the nz parameter is ignored 192649a6f317SBarry Smith 1927651615e1SBarry Smith .seealso: [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()` 1928a23d5eceSKris Buschelman @*/ 19299371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetPreallocation(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[]) { 1930a23d5eceSKris Buschelman PetscFunctionBegin; 19316ba663aaSJed Brown PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 19326ba663aaSJed Brown PetscValidType(B, 1); 19336ba663aaSJed Brown PetscValidLogicalCollectiveInt(B, bs, 2); 1934cac4c232SBarry Smith PetscTryMethod(B, "MatSeqSBAIJSetPreallocation_C", (Mat, PetscInt, PetscInt, const PetscInt[]), (B, bs, nz, nnz)); 1935a23d5eceSKris Buschelman PetscFunctionReturn(0); 1936a23d5eceSKris Buschelman } 193749b5e25fSSatish Balay 193838f409ebSLisandro Dalcin /*@C 193911a5261eSBarry Smith MatSeqSBAIJSetPreallocationCSR - Creates a sparse parallel matrix in `MATSEQSBAIJ` format using the given nonzero structure and (optional) numerical values 194038f409ebSLisandro Dalcin 194138f409ebSLisandro Dalcin Input Parameters: 19421c4f3114SJed Brown + B - the matrix 1943eab78319SHong Zhang . bs - size of block, the blocks are ALWAYS square. 194438f409ebSLisandro Dalcin . i - the indices into j for the start of each local row (starts with zero) 194538f409ebSLisandro Dalcin . j - the column indices for each local row (starts with zero) these must be sorted for each row 194638f409ebSLisandro Dalcin - v - optional values in the matrix 194738f409ebSLisandro Dalcin 1948664954b6SBarry Smith Level: advanced 194938f409ebSLisandro Dalcin 195038f409ebSLisandro Dalcin Notes: 195111a5261eSBarry Smith The order of the entries in values is specified by the `MatOption` `MAT_ROW_ORIENTED`. For example, C programs 195211a5261eSBarry 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 195338f409ebSLisandro Dalcin over rows within a block and the last index is over columns within a block row. Fortran programs will likely set 195411a5261eSBarry 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 195538f409ebSLisandro Dalcin block column and the second index is over columns within a block. 195638f409ebSLisandro Dalcin 195750c5228eSBarry Smith Any entries below the diagonal are ignored 19580cd7f59aSBarry Smith 19590cd7f59aSBarry Smith Though this routine has Preallocation() in the name it also sets the exact nonzero locations of the matrix entries 19600cd7f59aSBarry Smith and usually the numerical values as well 1961664954b6SBarry Smith 196211a5261eSBarry Smith .seealso: `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqSBAIJ()`, `MatSetValuesBlocked()`, `MatSeqSBAIJSetPreallocation()`, `MATSEQSBAIJ` 196338f409ebSLisandro Dalcin @*/ 19649371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetPreallocationCSR(Mat B, PetscInt bs, const PetscInt i[], const PetscInt j[], const PetscScalar v[]) { 196538f409ebSLisandro Dalcin PetscFunctionBegin; 196638f409ebSLisandro Dalcin PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 196738f409ebSLisandro Dalcin PetscValidType(B, 1); 196838f409ebSLisandro Dalcin PetscValidLogicalCollectiveInt(B, bs, 2); 1969cac4c232SBarry Smith PetscTryMethod(B, "MatSeqSBAIJSetPreallocationCSR_C", (Mat, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, bs, i, j, v)); 197038f409ebSLisandro Dalcin PetscFunctionReturn(0); 197138f409ebSLisandro Dalcin } 197238f409ebSLisandro Dalcin 1973c464158bSHong Zhang /*@C 1974c464158bSHong Zhang MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in block AIJ (block 197511a5261eSBarry Smith compressed row) `MATSEQSBAIJ` format. For good matrix assembly performance the 1976c464158bSHong Zhang user should preallocate the matrix storage by setting the parameter nz 1977c464158bSHong Zhang (or the array nnz). By setting these parameters accurately, performance 1978c464158bSHong Zhang during matrix assembly can be increased by more than a factor of 50. 197949b5e25fSSatish Balay 1980d083f849SBarry Smith Collective 1981c464158bSHong Zhang 1982c464158bSHong Zhang Input Parameters: 198311a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF` 198411a5261eSBarry 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 1985bb7ae925SBarry Smith blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with MatCreateVecs() 1986c464158bSHong Zhang . m - number of rows, or number of columns 1987c464158bSHong Zhang . nz - number of block nonzeros per block row (same for all rows) 1988744e8345SSatish Balay - nnz - array containing the number of block nonzeros in the upper triangular plus 19890298fd71SBarry Smith diagonal portion of each block (possibly different for each block row) or NULL 1990c464158bSHong Zhang 1991c464158bSHong Zhang Output Parameter: 1992c464158bSHong Zhang . A - the symmetric matrix 1993c464158bSHong Zhang 1994c464158bSHong Zhang Options Database Keys: 1995a2b725a8SWilliam Gropp + -mat_no_unroll - uses code that does not unroll the loops in the 1996c464158bSHong Zhang block calculations (much slower) 1997a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use 1998c464158bSHong Zhang 1999c464158bSHong Zhang Level: intermediate 2000c464158bSHong Zhang 200111a5261eSBarry Smith It is recommended that one use the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`, 2002f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly. 200311a5261eSBarry Smith [MatXXXXSetPreallocation() is, for example, `MatSeqAIJSetPreallocation()`] 2004175b88e8SBarry Smith 2005c464158bSHong Zhang Notes: 20066d6d819aSHong Zhang The number of rows and columns must be divisible by blocksize. 20076d6d819aSHong Zhang This matrix type does not support complex Hermitian operation. 2008c464158bSHong Zhang 2009c464158bSHong Zhang Specify the preallocated storage with either nz or nnz (not both). 201011a5261eSBarry Smith Set nz = `PETSC_DEFAULT` and nnz = NULL for PETSc to control dynamic memory 2011651615e1SBarry Smith allocation. See [Sparse Matrices](sec_matsparse) for details. 2012c464158bSHong Zhang 201349a6f317SBarry Smith If the nnz parameter is given then the nz parameter is ignored 201449a6f317SBarry Smith 2015651615e1SBarry Smith .seealso: [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()` 2016c464158bSHong Zhang @*/ 20179371c9d4SSatish Balay PetscErrorCode MatCreateSeqSBAIJ(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A) { 2018c464158bSHong Zhang PetscFunctionBegin; 20199566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 20209566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, m, n)); 20219566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATSEQSBAIJ)); 20229566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(*A, bs, nz, (PetscInt *)nnz)); 202349b5e25fSSatish Balay PetscFunctionReturn(0); 202449b5e25fSSatish Balay } 202549b5e25fSSatish Balay 20269371c9d4SSatish Balay PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B) { 202749b5e25fSSatish Balay Mat C; 202849b5e25fSSatish Balay Mat_SeqSBAIJ *c, *a = (Mat_SeqSBAIJ *)A->data; 2029b40805acSSatish Balay PetscInt i, mbs = a->mbs, nz = a->nz, bs2 = a->bs2; 203049b5e25fSSatish Balay 203149b5e25fSSatish Balay PetscFunctionBegin; 203208401ef6SPierre Jolivet PetscCheck(a->i[mbs] == nz, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupt matrix"); 203349b5e25fSSatish Balay 2034f4259b30SLisandro Dalcin *B = NULL; 20359566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 20369566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, A->rmap->N, A->cmap->n, A->rmap->N, A->cmap->n)); 20379566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 20389566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATSEQSBAIJ)); 2039692f9cbeSHong Zhang c = (Mat_SeqSBAIJ *)C->data; 2040692f9cbeSHong Zhang 2041273d9f13SBarry Smith C->preallocated = PETSC_TRUE; 2042d5f3da31SBarry Smith C->factortype = A->factortype; 2043f4259b30SLisandro Dalcin c->row = NULL; 2044f4259b30SLisandro Dalcin c->icol = NULL; 2045f4259b30SLisandro Dalcin c->saved_values = NULL; 2046a9817697SBarry Smith c->keepnonzeropattern = a->keepnonzeropattern; 204749b5e25fSSatish Balay C->assembled = PETSC_TRUE; 204849b5e25fSSatish Balay 20499566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->rmap, &C->rmap)); 20509566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->cmap, &C->cmap)); 205149b5e25fSSatish Balay c->bs2 = a->bs2; 205249b5e25fSSatish Balay c->mbs = a->mbs; 205349b5e25fSSatish Balay c->nbs = a->nbs; 205449b5e25fSSatish Balay 2055c760cd28SBarry Smith if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { 2056c760cd28SBarry Smith c->imax = a->imax; 2057c760cd28SBarry Smith c->ilen = a->ilen; 2058c760cd28SBarry Smith c->free_imax_ilen = PETSC_FALSE; 2059c760cd28SBarry Smith } else { 20609566063dSJacob Faibussowitsch PetscCall(PetscMalloc2((mbs + 1), &c->imax, (mbs + 1), &c->ilen)); 206149b5e25fSSatish Balay for (i = 0; i < mbs; i++) { 206249b5e25fSSatish Balay c->imax[i] = a->imax[i]; 206349b5e25fSSatish Balay c->ilen[i] = a->ilen[i]; 206449b5e25fSSatish Balay } 2065c760cd28SBarry Smith c->free_imax_ilen = PETSC_TRUE; 2066c760cd28SBarry Smith } 206749b5e25fSSatish Balay 206849b5e25fSSatish Balay /* allocate the matrix space */ 20694da8f245SBarry Smith if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { 20709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bs2 * nz, &c->a)); 207144e1c64aSLisandro Dalcin c->i = a->i; 207244e1c64aSLisandro Dalcin c->j = a->j; 20734da8f245SBarry Smith c->singlemalloc = PETSC_FALSE; 207444e1c64aSLisandro Dalcin c->free_a = PETSC_TRUE; 20754da8f245SBarry Smith c->free_ij = PETSC_FALSE; 20764da8f245SBarry Smith c->parent = A; 20779566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 20789566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 20799566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 20804da8f245SBarry Smith } else { 20819566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(bs2 * nz, &c->a, nz, &c->j, mbs + 1, &c->i)); 20829566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->i, a->i, mbs + 1)); 20834da8f245SBarry Smith c->singlemalloc = PETSC_TRUE; 208444e1c64aSLisandro Dalcin c->free_a = PETSC_TRUE; 20854da8f245SBarry Smith c->free_ij = PETSC_TRUE; 20864da8f245SBarry Smith } 208749b5e25fSSatish Balay if (mbs > 0) { 208848a46eb9SPierre Jolivet if (cpvalues != MAT_SHARE_NONZERO_PATTERN) PetscCall(PetscArraycpy(c->j, a->j, nz)); 208949b5e25fSSatish Balay if (cpvalues == MAT_COPY_VALUES) { 20909566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->a, a->a, bs2 * nz)); 209149b5e25fSSatish Balay } else { 20929566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->a, bs2 * nz)); 209349b5e25fSSatish Balay } 2094a1c3900fSBarry Smith if (a->jshort) { 209544e1c64aSLisandro Dalcin /* cannot share jshort, it is reallocated in MatAssemblyEnd_SeqSBAIJ() */ 209644e1c64aSLisandro Dalcin /* if the parent matrix is reassembled, this child matrix will never notice */ 20979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &c->jshort)); 20989566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->jshort, a->jshort, nz)); 209926fbe8dcSKarl Rupp 21004da8f245SBarry Smith c->free_jshort = PETSC_TRUE; 21014da8f245SBarry Smith } 2102a1c3900fSBarry Smith } 210349b5e25fSSatish Balay 210449b5e25fSSatish Balay c->roworiented = a->roworiented; 210549b5e25fSSatish Balay c->nonew = a->nonew; 210649b5e25fSSatish Balay 210749b5e25fSSatish Balay if (a->diag) { 2108c760cd28SBarry Smith if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { 2109c760cd28SBarry Smith c->diag = a->diag; 2110c760cd28SBarry Smith c->free_diag = PETSC_FALSE; 2111c760cd28SBarry Smith } else { 21129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mbs, &c->diag)); 211326fbe8dcSKarl Rupp for (i = 0; i < mbs; i++) c->diag[i] = a->diag[i]; 2114c760cd28SBarry Smith c->free_diag = PETSC_TRUE; 2115c760cd28SBarry Smith } 211644e1c64aSLisandro Dalcin } 21176c6c5352SBarry Smith c->nz = a->nz; 2118f2cbd3d5SJed Brown c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 2119f4259b30SLisandro Dalcin c->solve_work = NULL; 2120f4259b30SLisandro Dalcin c->mult_work = NULL; 212126fbe8dcSKarl Rupp 212249b5e25fSSatish Balay *B = C; 21239566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist)); 212449b5e25fSSatish Balay PetscFunctionReturn(0); 212549b5e25fSSatish Balay } 212649b5e25fSSatish Balay 2127618cc2edSLisandro Dalcin /* Used for both SeqBAIJ and SeqSBAIJ matrices */ 2128618cc2edSLisandro Dalcin #define MatLoad_SeqSBAIJ_Binary MatLoad_SeqBAIJ_Binary 2129618cc2edSLisandro Dalcin 21309371c9d4SSatish Balay PetscErrorCode MatLoad_SeqSBAIJ(Mat mat, PetscViewer viewer) { 21317f489da9SVaclav Hapla PetscBool isbinary; 21322f480046SShri Abhyankar 21332f480046SShri Abhyankar PetscFunctionBegin; 21349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 213528b400f6SJacob 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); 21369566063dSJacob Faibussowitsch PetscCall(MatLoad_SeqSBAIJ_Binary(mat, viewer)); 21372f480046SShri Abhyankar PetscFunctionReturn(0); 21382f480046SShri Abhyankar } 21392f480046SShri Abhyankar 2140c75a6043SHong Zhang /*@ 214111a5261eSBarry Smith MatCreateSeqSBAIJWithArrays - Creates an sequential `MATSEQSBAIJ` matrix using matrix elements 2142c75a6043SHong Zhang (upper triangular entries in CSR format) provided by the user. 2143c75a6043SHong Zhang 2144d083f849SBarry Smith Collective 2145c75a6043SHong Zhang 2146c75a6043SHong Zhang Input Parameters: 2147c75a6043SHong Zhang + comm - must be an MPI communicator of size 1 2148c75a6043SHong Zhang . bs - size of block 2149c75a6043SHong Zhang . m - number of rows 2150c75a6043SHong Zhang . n - number of columns 2151483a2f95SBarry 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 2152c75a6043SHong Zhang . j - column indices 2153c75a6043SHong Zhang - a - matrix values 2154c75a6043SHong Zhang 2155c75a6043SHong Zhang Output Parameter: 2156c75a6043SHong Zhang . mat - the matrix 2157c75a6043SHong Zhang 2158dfb205c3SBarry Smith Level: advanced 2159c75a6043SHong Zhang 2160c75a6043SHong Zhang Notes: 2161c75a6043SHong Zhang The i, j, and a arrays are not copied by this routine, the user must free these arrays 2162c75a6043SHong Zhang once the matrix is destroyed 2163c75a6043SHong Zhang 2164c75a6043SHong Zhang You cannot set new nonzero locations into this matrix, that will generate an error. 2165c75a6043SHong Zhang 2166c75a6043SHong Zhang The i and j indices are 0 based 2167c75a6043SHong Zhang 216811a5261eSBarry Smith When block size is greater than 1 the matrix values must be stored using the SBAIJ storage format (see the SBAIJ source code to determine this). For block size of 1 2169dfb205c3SBarry Smith it is the regular CSR format excluding the lower triangular elements. 2170dfb205c3SBarry Smith 217111a5261eSBarry Smith .seealso: `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSBAIJ()`, `MatCreateSeqSBAIJ()` 2172c75a6043SHong Zhang @*/ 21739371c9d4SSatish Balay PetscErrorCode MatCreateSeqSBAIJWithArrays(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat) { 2174c75a6043SHong Zhang PetscInt ii; 2175c75a6043SHong Zhang Mat_SeqSBAIJ *sbaij; 2176c75a6043SHong Zhang 2177c75a6043SHong Zhang PetscFunctionBegin; 217808401ef6SPierre Jolivet PetscCheck(bs == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "block size %" PetscInt_FMT " > 1 is not supported yet", bs); 2179aed4548fSBarry Smith PetscCheck(m == 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0"); 2180c75a6043SHong Zhang 21819566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 21829566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 21839566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQSBAIJ)); 21849566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(*mat, bs, MAT_SKIP_ALLOCATION, NULL)); 2185c75a6043SHong Zhang sbaij = (Mat_SeqSBAIJ *)(*mat)->data; 21869566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(m, &sbaij->imax, m, &sbaij->ilen)); 2187c75a6043SHong Zhang 2188c75a6043SHong Zhang sbaij->i = i; 2189c75a6043SHong Zhang sbaij->j = j; 2190c75a6043SHong Zhang sbaij->a = a; 219126fbe8dcSKarl Rupp 2192c75a6043SHong Zhang sbaij->singlemalloc = PETSC_FALSE; 2193c75a6043SHong Zhang sbaij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 2194e6b907acSBarry Smith sbaij->free_a = PETSC_FALSE; 2195e6b907acSBarry Smith sbaij->free_ij = PETSC_FALSE; 2196ddf7884eSMatthew Knepley sbaij->free_imax_ilen = PETSC_TRUE; 2197c75a6043SHong Zhang 2198c75a6043SHong Zhang for (ii = 0; ii < m; ii++) { 2199c75a6043SHong Zhang sbaij->ilen[ii] = sbaij->imax[ii] = i[ii + 1] - i[ii]; 22006bdcaf15SBarry 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]); 2201c75a6043SHong Zhang } 220276bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 2203c75a6043SHong Zhang for (ii = 0; ii < sbaij->i[m]; ii++) { 22046bdcaf15SBarry 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]); 22056bdcaf15SBarry 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]); 2206c75a6043SHong Zhang } 220776bd3646SJed Brown } 2208c75a6043SHong Zhang 22099566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 22109566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 2211c75a6043SHong Zhang PetscFunctionReturn(0); 2212c75a6043SHong Zhang } 2213d06b337dSHong Zhang 22149371c9d4SSatish Balay PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat) { 221559f5e6ceSHong Zhang PetscFunctionBegin; 22169566063dSJacob Faibussowitsch PetscCall(MatCreateMPIMatConcatenateSeqMat_MPISBAIJ(comm, inmat, n, scall, outmat)); 221759f5e6ceSHong Zhang PetscFunctionReturn(0); 221859f5e6ceSHong Zhang } 2219