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)); 569566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A, a->mbs * sizeof(PetscInt))); 57c760cd28SBarry Smith a->free_diag = PETSC_TRUE; 5809f38230SBarry Smith } 5948dd3d27SHong Zhang for (i = 0; i < a->mbs; i++) { 6048dd3d27SHong Zhang a->diag[i] = a->i[i + 1]; 6148dd3d27SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 6248dd3d27SHong Zhang if (a->j[j] == i) { 6348dd3d27SHong Zhang a->diag[i] = j; 6448dd3d27SHong Zhang break; 6548dd3d27SHong Zhang } 6648dd3d27SHong Zhang } 6748dd3d27SHong Zhang } 6849b5e25fSSatish Balay PetscFunctionReturn(0); 6949b5e25fSSatish Balay } 7049b5e25fSSatish Balay 719371c9d4SSatish Balay static PetscErrorCode MatGetRowIJ_SeqSBAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool blockcompressed, PetscInt *nn, const PetscInt *inia[], const PetscInt *inja[], PetscBool *done) { 72a6ece127SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 732462f5fdSStefano Zampini PetscInt i, j, n = a->mbs, nz = a->i[n], *tia, *tja, bs = A->rmap->bs, k, l, cnt; 742462f5fdSStefano Zampini PetscInt **ia = (PetscInt **)inia, **ja = (PetscInt **)inja; 7549b5e25fSSatish Balay 7649b5e25fSSatish Balay PetscFunctionBegin; 77d3e5a4abSHong Zhang *nn = n; 78a1373b80SHong Zhang if (!ia) PetscFunctionReturn(0); 792462f5fdSStefano Zampini if (symmetric) { 809566063dSJacob Faibussowitsch PetscCall(MatToSymmetricIJ_SeqAIJ(n, a->i, a->j, PETSC_FALSE, 0, 0, &tia, &tja)); 812462f5fdSStefano Zampini nz = tia[n]; 822462f5fdSStefano Zampini } else { 839371c9d4SSatish Balay tia = a->i; 849371c9d4SSatish Balay tja = a->j; 852462f5fdSStefano Zampini } 862462f5fdSStefano Zampini 872462f5fdSStefano Zampini if (!blockcompressed && bs > 1) { 882462f5fdSStefano Zampini (*nn) *= bs; 898f7157efSSatish Balay /* malloc & create the natural set of indices */ 909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((n + 1) * bs, ia)); 912462f5fdSStefano Zampini if (n) { 922462f5fdSStefano Zampini (*ia)[0] = oshift; 939371c9d4SSatish Balay for (j = 1; j < bs; j++) { (*ia)[j] = (tia[1] - tia[0]) * bs + (*ia)[j - 1]; } 942462f5fdSStefano Zampini } 952462f5fdSStefano Zampini 962462f5fdSStefano Zampini for (i = 1; i < n; i++) { 972462f5fdSStefano Zampini (*ia)[i * bs] = (tia[i] - tia[i - 1]) * bs + (*ia)[i * bs - 1]; 989371c9d4SSatish Balay for (j = 1; j < bs; j++) { (*ia)[i * bs + j] = (tia[i + 1] - tia[i]) * bs + (*ia)[i * bs + j - 1]; } 992462f5fdSStefano Zampini } 1009371c9d4SSatish Balay if (n) { (*ia)[n * bs] = (tia[n] - tia[n - 1]) * bs + (*ia)[n * bs - 1]; } 1012462f5fdSStefano Zampini 1022462f5fdSStefano Zampini if (inja) { 1039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz * bs * bs, ja)); 1042462f5fdSStefano Zampini cnt = 0; 1052462f5fdSStefano Zampini for (i = 0; i < n; i++) { 1068f7157efSSatish Balay for (j = 0; j < bs; j++) { 1072462f5fdSStefano Zampini for (k = tia[i]; k < tia[i + 1]; k++) { 1089371c9d4SSatish Balay for (l = 0; l < bs; l++) { (*ja)[cnt++] = bs * tja[k] + l; } 1098f7157efSSatish Balay } 1108f7157efSSatish Balay } 1118f7157efSSatish Balay } 1128f7157efSSatish Balay } 1132462f5fdSStefano Zampini 1142462f5fdSStefano Zampini if (symmetric) { /* deallocate memory allocated in MatToSymmetricIJ_SeqAIJ() */ 1159566063dSJacob Faibussowitsch PetscCall(PetscFree(tia)); 1169566063dSJacob Faibussowitsch PetscCall(PetscFree(tja)); 1172462f5fdSStefano Zampini } 1182462f5fdSStefano Zampini } else if (oshift == 1) { 1192462f5fdSStefano Zampini if (symmetric) { 1202462f5fdSStefano Zampini nz = tia[A->rmap->n / bs]; 1212462f5fdSStefano Zampini /* add 1 to i and j indices */ 1222462f5fdSStefano Zampini for (i = 0; i < A->rmap->n / bs + 1; i++) tia[i] = tia[i] + 1; 1232462f5fdSStefano Zampini *ia = tia; 1242462f5fdSStefano Zampini if (ja) { 1252462f5fdSStefano Zampini for (i = 0; i < nz; i++) tja[i] = tja[i] + 1; 1262462f5fdSStefano Zampini *ja = tja; 1272462f5fdSStefano Zampini } 1282462f5fdSStefano Zampini } else { 1292462f5fdSStefano Zampini nz = a->i[A->rmap->n / bs]; 1302462f5fdSStefano Zampini /* malloc space and add 1 to i and j indices */ 1319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n / bs + 1, ia)); 1322462f5fdSStefano Zampini for (i = 0; i < A->rmap->n / bs + 1; i++) (*ia)[i] = a->i[i] + 1; 1332462f5fdSStefano Zampini if (ja) { 1349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, ja)); 1352462f5fdSStefano Zampini for (i = 0; i < nz; i++) (*ja)[i] = a->j[i] + 1; 1362462f5fdSStefano Zampini } 1372462f5fdSStefano Zampini } 1382462f5fdSStefano Zampini } else { 1392462f5fdSStefano Zampini *ia = tia; 1402462f5fdSStefano Zampini if (ja) *ja = tja; 141a6ece127SHong Zhang } 14249b5e25fSSatish Balay PetscFunctionReturn(0); 14349b5e25fSSatish Balay } 14449b5e25fSSatish Balay 1459371c9d4SSatish Balay static PetscErrorCode MatRestoreRowIJ_SeqSBAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool blockcompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) { 14649b5e25fSSatish Balay PetscFunctionBegin; 14749b5e25fSSatish Balay if (!ia) PetscFunctionReturn(0); 1482462f5fdSStefano Zampini if ((!blockcompressed && A->rmap->bs > 1) || (symmetric || oshift == 1)) { 1499566063dSJacob Faibussowitsch PetscCall(PetscFree(*ia)); 1509566063dSJacob Faibussowitsch if (ja) PetscCall(PetscFree(*ja)); 151a6ece127SHong Zhang } 152a6ece127SHong Zhang PetscFunctionReturn(0); 15349b5e25fSSatish Balay } 15449b5e25fSSatish Balay 1559371c9d4SSatish Balay PetscErrorCode MatDestroy_SeqSBAIJ(Mat A) { 15649b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 15749b5e25fSSatish Balay 15849b5e25fSSatish Balay PetscFunctionBegin; 159a9f03627SSatish Balay #if defined(PETSC_USE_LOG) 160c0aa6a63SJacob Faibussowitsch PetscLogObjectState((PetscObject)A, "Rows=%" PetscInt_FMT ", NZ=%" PetscInt_FMT, A->rmap->N, a->nz); 161a9f03627SSatish Balay #endif 1629566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(A, &a->a, &a->j, &a->i)); 1639566063dSJacob Faibussowitsch if (a->free_diag) PetscCall(PetscFree(a->diag)); 1649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 1659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 1669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 1679566063dSJacob Faibussowitsch PetscCall(PetscFree(a->idiag)); 1689566063dSJacob Faibussowitsch PetscCall(PetscFree(a->inode.size)); 1699566063dSJacob Faibussowitsch if (a->free_imax_ilen) PetscCall(PetscFree2(a->imax, a->ilen)); 1709566063dSJacob Faibussowitsch PetscCall(PetscFree(a->solve_work)); 1719566063dSJacob Faibussowitsch PetscCall(PetscFree(a->sor_work)); 1729566063dSJacob Faibussowitsch PetscCall(PetscFree(a->solves_work)); 1739566063dSJacob Faibussowitsch PetscCall(PetscFree(a->mult_work)); 1749566063dSJacob Faibussowitsch PetscCall(PetscFree(a->saved_values)); 1759566063dSJacob Faibussowitsch if (a->free_jshort) PetscCall(PetscFree(a->jshort)); 1769566063dSJacob Faibussowitsch PetscCall(PetscFree(a->inew)); 1779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&a->parent)); 1789566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 179901853e0SKris Buschelman 1809566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL)); 1812e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJGetArray_C", NULL)); 1822e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJRestoreArray_C", NULL)); 1839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatStoreValues_C", NULL)); 1849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatRetrieveValues_C", NULL)); 1859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetColumnIndices_C", NULL)); 1869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqaij_C", NULL)); 1879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqbaij_C", NULL)); 1889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocation_C", NULL)); 1899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocationCSR_C", NULL)); 1906214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 1919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_elemental_C", NULL)); 1926214f412SHong Zhang #endif 193d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 1949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_scalapack_C", NULL)); 195d24d4204SJose E. Roman #endif 1962e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL)); 19749b5e25fSSatish Balay PetscFunctionReturn(0); 19849b5e25fSSatish Balay } 19949b5e25fSSatish Balay 2009371c9d4SSatish Balay PetscErrorCode MatSetOption_SeqSBAIJ(Mat A, MatOption op, PetscBool flg) { 201045c9aa0SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 202eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 203eb1ec7c1SStefano Zampini PetscInt bs; 204eb1ec7c1SStefano Zampini #endif 20549b5e25fSSatish Balay 20649b5e25fSSatish Balay PetscFunctionBegin; 207eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 2089566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 209eb1ec7c1SStefano Zampini #endif 2104d9d31abSKris Buschelman switch (op) { 2119371c9d4SSatish Balay case MAT_ROW_ORIENTED: a->roworiented = flg; break; 2129371c9d4SSatish Balay case MAT_KEEP_NONZERO_PATTERN: a->keepnonzeropattern = flg; break; 2139371c9d4SSatish Balay case MAT_NEW_NONZERO_LOCATIONS: a->nonew = (flg ? 0 : 1); break; 2149371c9d4SSatish Balay case MAT_NEW_NONZERO_LOCATION_ERR: a->nonew = (flg ? -1 : 0); break; 2159371c9d4SSatish Balay case MAT_NEW_NONZERO_ALLOCATION_ERR: a->nonew = (flg ? -2 : 0); break; 2169371c9d4SSatish Balay case MAT_UNUSED_NONZERO_LOCATION_ERR: a->nounused = (flg ? -1 : 0); break; 2178c78258cSHong Zhang case MAT_FORCE_DIAGONAL_ENTRIES: 2184d9d31abSKris Buschelman case MAT_IGNORE_OFF_PROC_ENTRIES: 2194d9d31abSKris Buschelman case MAT_USE_HASH_TABLE: 2209371c9d4SSatish Balay case MAT_SORTED_FULL: PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op])); break; 2219a4540c5SBarry Smith case MAT_HERMITIAN: 222eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 223eb1ec7c1SStefano Zampini if (flg) { /* disable transpose ops */ 22408401ef6SPierre Jolivet PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for Hermitian with block size greater than 1"); 225eb1ec7c1SStefano Zampini A->ops->multtranspose = NULL; 226eb1ec7c1SStefano Zampini A->ops->multtransposeadd = NULL; 227b94d7dedSBarry Smith A->symmetric = PETSC_BOOL3_FALSE; 228eb1ec7c1SStefano Zampini } 2290f2140c7SStefano Zampini #endif 230eeffb40dSHong Zhang break; 23177e54ba9SKris Buschelman case MAT_SYMMETRIC: 232eb1ec7c1SStefano Zampini case MAT_SPD: 233eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 234eb1ec7c1SStefano Zampini if (flg) { /* An hermitian and symmetric matrix has zero imaginary part (restore back transpose ops) */ 235eb1ec7c1SStefano Zampini A->ops->multtranspose = A->ops->mult; 236eb1ec7c1SStefano Zampini A->ops->multtransposeadd = A->ops->multadd; 237eb1ec7c1SStefano Zampini } 238eb1ec7c1SStefano Zampini #endif 239eb1ec7c1SStefano Zampini break; 240eb1ec7c1SStefano Zampini /* These options are handled directly by MatSetOption() */ 24177e54ba9SKris Buschelman case MAT_STRUCTURALLY_SYMMETRIC: 2429a4540c5SBarry Smith case MAT_SYMMETRY_ETERNAL: 243b94d7dedSBarry Smith case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 244672ba085SHong Zhang case MAT_STRUCTURE_ONLY: 245b94d7dedSBarry Smith case MAT_SPD_ETERNAL: 2464dcd73b1SHong Zhang /* These options are handled directly by MatSetOption() */ 247290bbb0aSBarry Smith break; 2489371c9d4SSatish Balay case MAT_IGNORE_LOWER_TRIANGULAR: a->ignore_ltriangular = flg; break; 2499371c9d4SSatish Balay case MAT_ERROR_LOWER_TRIANGULAR: a->ignore_ltriangular = flg; break; 2509371c9d4SSatish Balay case MAT_GETROW_UPPERTRIANGULAR: a->getrow_utriangular = flg; break; 2519371c9d4SSatish Balay case MAT_SUBMAT_SINGLEIS: break; 2529371c9d4SSatish Balay default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %d", op); 25349b5e25fSSatish Balay } 25449b5e25fSSatish Balay PetscFunctionReturn(0); 25549b5e25fSSatish Balay } 25649b5e25fSSatish Balay 2579371c9d4SSatish Balay PetscErrorCode MatGetRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) { 25849b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 25949b5e25fSSatish Balay 26049b5e25fSSatish Balay PetscFunctionBegin; 26108401ef6SPierre 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()"); 26252768537SHong Zhang 263f5edf698SHong Zhang /* Get the upper triangular part of the row */ 2649566063dSJacob Faibussowitsch PetscCall(MatGetRow_SeqBAIJ_private(A, row, nz, idx, v, a->i, a->j, a->a)); 26549b5e25fSSatish Balay PetscFunctionReturn(0); 26649b5e25fSSatish Balay } 26749b5e25fSSatish Balay 2689371c9d4SSatish Balay PetscErrorCode MatRestoreRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) { 26949b5e25fSSatish Balay PetscFunctionBegin; 270cb4a9cd9SHong Zhang if (nz) *nz = 0; 2719566063dSJacob Faibussowitsch if (idx) PetscCall(PetscFree(*idx)); 2729566063dSJacob Faibussowitsch if (v) PetscCall(PetscFree(*v)); 27349b5e25fSSatish Balay PetscFunctionReturn(0); 27449b5e25fSSatish Balay } 27549b5e25fSSatish Balay 2769371c9d4SSatish Balay PetscErrorCode MatGetRowUpperTriangular_SeqSBAIJ(Mat A) { 277f5edf698SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 278f5edf698SHong Zhang 279f5edf698SHong Zhang PetscFunctionBegin; 280f5edf698SHong Zhang a->getrow_utriangular = PETSC_TRUE; 281f5edf698SHong Zhang PetscFunctionReturn(0); 282f5edf698SHong Zhang } 283a323099bSStefano Zampini 2849371c9d4SSatish Balay PetscErrorCode MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A) { 285f5edf698SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 286f5edf698SHong Zhang 287f5edf698SHong Zhang PetscFunctionBegin; 288f5edf698SHong Zhang a->getrow_utriangular = PETSC_FALSE; 289f5edf698SHong Zhang PetscFunctionReturn(0); 290f5edf698SHong Zhang } 291f5edf698SHong Zhang 2929371c9d4SSatish Balay PetscErrorCode MatTranspose_SeqSBAIJ(Mat A, MatReuse reuse, Mat *B) { 29349b5e25fSSatish Balay PetscFunctionBegin; 2947fb60732SBarry Smith if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B)); 295cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX) { 2969566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, B)); 297cf37664fSBarry Smith } else if (reuse == MAT_REUSE_MATRIX) { 2989566063dSJacob Faibussowitsch PetscCall(MatCopy(A, *B, SAME_NONZERO_PATTERN)); 299fc4dec0aSBarry Smith } 3008115998fSBarry Smith PetscFunctionReturn(0); 30149b5e25fSSatish Balay } 30249b5e25fSSatish Balay 3039371c9d4SSatish Balay PetscErrorCode MatView_SeqSBAIJ_ASCII(Mat A, PetscViewer viewer) { 30449b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 305d0f46423SBarry Smith PetscInt i, j, bs = A->rmap->bs, k, l, bs2 = a->bs2; 306f3ef73ceSBarry Smith PetscViewerFormat format; 307121deb67SSatish Balay PetscInt *diag; 30849b5e25fSSatish Balay 30949b5e25fSSatish Balay PetscFunctionBegin; 3109566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 311456192e2SBarry Smith if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 3129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " block size is %" PetscInt_FMT "\n", bs)); 313fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_MATLAB) { 314d2507d54SMatthew Knepley Mat aij; 315ade3a672SBarry Smith const char *matname; 316ade3a672SBarry Smith 317d5f3da31SBarry Smith if (A->factortype && bs > 1) { 3189566063dSJacob 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")); 31970d5e725SHong Zhang PetscFunctionReturn(0); 32070d5e725SHong Zhang } 3219566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &aij)); 3229566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)A, &matname)); 3239566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)aij, matname)); 3249566063dSJacob Faibussowitsch PetscCall(MatView(aij, viewer)); 3259566063dSJacob Faibussowitsch PetscCall(MatDestroy(&aij)); 326fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_COMMON) { 3279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 32849b5e25fSSatish Balay for (i = 0; i < a->mbs; i++) { 32949b5e25fSSatish Balay for (j = 0; j < bs; j++) { 3309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i * bs + j)); 33149b5e25fSSatish Balay for (k = a->i[i]; k < a->i[i + 1]; k++) { 33249b5e25fSSatish Balay for (l = 0; l < bs; l++) { 33349b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX) 33449b5e25fSSatish Balay if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) > 0.0 && PetscRealPart(a->a[bs2 * k + l * bs + j]) != 0.0) { 3359371c9d4SSatish 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]))); 33649b5e25fSSatish Balay } else if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) < 0.0 && PetscRealPart(a->a[bs2 * k + l * bs + j]) != 0.0) { 3379371c9d4SSatish 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]))); 33849b5e25fSSatish Balay } else if (PetscRealPart(a->a[bs2 * k + l * bs + j]) != 0.0) { 3399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j]))); 34049b5e25fSSatish Balay } 34149b5e25fSSatish Balay #else 342*48a46eb9SPierre 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])); 34349b5e25fSSatish Balay #endif 34449b5e25fSSatish Balay } 34549b5e25fSSatish Balay } 3469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 34749b5e25fSSatish Balay } 34849b5e25fSSatish Balay } 3499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 350c1490034SHong Zhang } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 351c1490034SHong Zhang PetscFunctionReturn(0); 35249b5e25fSSatish Balay } else { 3539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 3542c990fa1SHong Zhang if (A->factortype) { /* for factored matrix */ 35508401ef6SPierre Jolivet PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix is factored with bs>1. Not implemented yet"); 3562c990fa1SHong Zhang 357121deb67SSatish Balay diag = a->diag; 358121deb67SSatish Balay for (i = 0; i < a->mbs; i++) { /* for row block i */ 3599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 3602c990fa1SHong Zhang /* diagonal entry */ 3612c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX) 3622c990fa1SHong Zhang if (PetscImaginaryPart(a->a[diag[i]]) > 0.0) { 3639566063dSJacob 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]]))); 3642c990fa1SHong Zhang } else if (PetscImaginaryPart(a->a[diag[i]]) < 0.0) { 3659566063dSJacob 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]]))); 3662c990fa1SHong Zhang } else { 3679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)PetscRealPart(1.0 / a->a[diag[i]]))); 3682c990fa1SHong Zhang } 3692c990fa1SHong Zhang #else 3709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)(1.0 / a->a[diag[i]]))); 3712c990fa1SHong Zhang #endif 3722c990fa1SHong Zhang /* off-diagonal entries */ 3732c990fa1SHong Zhang for (k = a->i[i]; k < a->i[i + 1] - 1; k++) { 3742c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX) 375ca0704adSBarry Smith if (PetscImaginaryPart(a->a[k]) > 0.0) { 3769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), (double)PetscImaginaryPart(a->a[k]))); 377ca0704adSBarry Smith } else if (PetscImaginaryPart(a->a[k]) < 0.0) { 3789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), -(double)PetscImaginaryPart(a->a[k]))); 3792c990fa1SHong Zhang } else { 3809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k], (double)PetscRealPart(a->a[k]))); 3812c990fa1SHong Zhang } 3822c990fa1SHong Zhang #else 3839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[k], (double)a->a[k])); 3842c990fa1SHong Zhang #endif 3852c990fa1SHong Zhang } 3869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 3872c990fa1SHong Zhang } 3882c990fa1SHong Zhang 3892c990fa1SHong Zhang } else { /* for non-factored matrix */ 3900c74a584SJed Brown for (i = 0; i < a->mbs; i++) { /* for row block i */ 3910c74a584SJed Brown for (j = 0; j < bs; j++) { /* for row bs*i + j */ 3929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i * bs + j)); 3930c74a584SJed Brown for (k = a->i[i]; k < a->i[i + 1]; k++) { /* for column block */ 3940c74a584SJed Brown for (l = 0; l < bs; l++) { /* for column */ 39549b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX) 39649b5e25fSSatish Balay if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) > 0.0) { 3979371c9d4SSatish 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]))); 39849b5e25fSSatish Balay } else if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) < 0.0) { 3999371c9d4SSatish 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]))); 40049b5e25fSSatish Balay } else { 4019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j]))); 40249b5e25fSSatish Balay } 40349b5e25fSSatish Balay #else 4049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)a->a[bs2 * k + l * bs + j])); 40549b5e25fSSatish Balay #endif 40649b5e25fSSatish Balay } 40749b5e25fSSatish Balay } 4089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 40949b5e25fSSatish Balay } 41049b5e25fSSatish Balay } 4112c990fa1SHong Zhang } 4129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 41349b5e25fSSatish Balay } 4149566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 41549b5e25fSSatish Balay PetscFunctionReturn(0); 41649b5e25fSSatish Balay } 41749b5e25fSSatish Balay 4189804daf3SBarry Smith #include <petscdraw.h> 4199371c9d4SSatish Balay static PetscErrorCode MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw, void *Aa) { 42049b5e25fSSatish Balay Mat A = (Mat)Aa; 42149b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 422d0f46423SBarry Smith PetscInt row, i, j, k, l, mbs = a->mbs, color, bs = A->rmap->bs, bs2 = a->bs2; 42349b5e25fSSatish Balay PetscReal xl, yl, xr, yr, x_l, x_r, y_l, y_r; 42449b5e25fSSatish Balay MatScalar *aa; 425b0a32e0cSBarry Smith PetscViewer viewer; 42649b5e25fSSatish Balay 42749b5e25fSSatish Balay PetscFunctionBegin; 4289566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer)); 4299566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr)); 43049b5e25fSSatish Balay 43149b5e25fSSatish Balay /* loop over matrix elements drawing boxes */ 432383922c3SLisandro Dalcin 433d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 4349566063dSJacob Faibussowitsch PetscCall(PetscDrawString(draw, .3 * (xl + xr), .3 * (yl + yr), PETSC_DRAW_BLACK, "symmetric")); 435383922c3SLisandro Dalcin /* Blue for negative, Cyan for zero and Red for positive */ 436b0a32e0cSBarry Smith color = PETSC_DRAW_BLUE; 43749b5e25fSSatish Balay for (i = 0, row = 0; i < mbs; i++, row += bs) { 43849b5e25fSSatish Balay for (j = a->i[i]; j < a->i[i + 1]; j++) { 4399371c9d4SSatish Balay y_l = A->rmap->N - row - 1.0; 4409371c9d4SSatish Balay y_r = y_l + 1.0; 4419371c9d4SSatish Balay x_l = a->j[j] * bs; 4429371c9d4SSatish Balay x_r = x_l + 1.0; 44349b5e25fSSatish Balay aa = a->a + j * bs2; 44449b5e25fSSatish Balay for (k = 0; k < bs; k++) { 44549b5e25fSSatish Balay for (l = 0; l < bs; l++) { 44649b5e25fSSatish Balay if (PetscRealPart(*aa++) >= 0.) continue; 4479566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color)); 44849b5e25fSSatish Balay } 44949b5e25fSSatish Balay } 45049b5e25fSSatish Balay } 45149b5e25fSSatish Balay } 452b0a32e0cSBarry Smith color = PETSC_DRAW_CYAN; 45349b5e25fSSatish Balay for (i = 0, row = 0; i < mbs; i++, row += bs) { 45449b5e25fSSatish Balay for (j = a->i[i]; j < a->i[i + 1]; j++) { 4559371c9d4SSatish Balay y_l = A->rmap->N - row - 1.0; 4569371c9d4SSatish Balay y_r = y_l + 1.0; 4579371c9d4SSatish Balay x_l = a->j[j] * bs; 4589371c9d4SSatish Balay x_r = x_l + 1.0; 45949b5e25fSSatish Balay aa = a->a + j * bs2; 46049b5e25fSSatish Balay for (k = 0; k < bs; k++) { 46149b5e25fSSatish Balay for (l = 0; l < bs; l++) { 46249b5e25fSSatish Balay if (PetscRealPart(*aa++) != 0.) continue; 4639566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color)); 46449b5e25fSSatish Balay } 46549b5e25fSSatish Balay } 46649b5e25fSSatish Balay } 46749b5e25fSSatish Balay } 468b0a32e0cSBarry Smith color = PETSC_DRAW_RED; 46949b5e25fSSatish Balay for (i = 0, row = 0; i < mbs; i++, row += bs) { 47049b5e25fSSatish Balay for (j = a->i[i]; j < a->i[i + 1]; j++) { 4719371c9d4SSatish Balay y_l = A->rmap->N - row - 1.0; 4729371c9d4SSatish Balay y_r = y_l + 1.0; 4739371c9d4SSatish Balay x_l = a->j[j] * bs; 4749371c9d4SSatish Balay x_r = x_l + 1.0; 47549b5e25fSSatish Balay aa = a->a + j * bs2; 47649b5e25fSSatish Balay for (k = 0; k < bs; k++) { 47749b5e25fSSatish Balay for (l = 0; l < bs; l++) { 47849b5e25fSSatish Balay if (PetscRealPart(*aa++) <= 0.) continue; 4799566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color)); 48049b5e25fSSatish Balay } 48149b5e25fSSatish Balay } 48249b5e25fSSatish Balay } 48349b5e25fSSatish Balay } 484d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 48549b5e25fSSatish Balay PetscFunctionReturn(0); 48649b5e25fSSatish Balay } 48749b5e25fSSatish Balay 4889371c9d4SSatish Balay static PetscErrorCode MatView_SeqSBAIJ_Draw(Mat A, PetscViewer viewer) { 48949b5e25fSSatish Balay PetscReal xl, yl, xr, yr, w, h; 490b0a32e0cSBarry Smith PetscDraw draw; 491ace3abfcSBarry Smith PetscBool isnull; 49249b5e25fSSatish Balay 49349b5e25fSSatish Balay PetscFunctionBegin; 4949566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 4959566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 496383922c3SLisandro Dalcin if (isnull) PetscFunctionReturn(0); 49749b5e25fSSatish Balay 4989371c9d4SSatish Balay xr = A->rmap->N; 4999371c9d4SSatish Balay yr = A->rmap->N; 5009371c9d4SSatish Balay h = yr / 10.0; 5019371c9d4SSatish Balay w = xr / 10.0; 5029371c9d4SSatish Balay xr += w; 5039371c9d4SSatish Balay yr += h; 5049371c9d4SSatish Balay xl = -w; 5059371c9d4SSatish Balay yl = -h; 5069566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr)); 5079566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer)); 5089566063dSJacob Faibussowitsch PetscCall(PetscDrawZoom(draw, MatView_SeqSBAIJ_Draw_Zoom, A)); 5099566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL)); 5109566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 51149b5e25fSSatish Balay PetscFunctionReturn(0); 51249b5e25fSSatish Balay } 51349b5e25fSSatish Balay 514618cc2edSLisandro Dalcin /* Used for both MPIBAIJ and MPISBAIJ matrices */ 515618cc2edSLisandro Dalcin #define MatView_SeqSBAIJ_Binary MatView_SeqBAIJ_Binary 516618cc2edSLisandro Dalcin 5179371c9d4SSatish Balay PetscErrorCode MatView_SeqSBAIJ(Mat A, PetscViewer viewer) { 518618cc2edSLisandro Dalcin PetscBool iascii, isbinary, isdraw; 51949b5e25fSSatish Balay 52049b5e25fSSatish Balay PetscFunctionBegin; 5219566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 5229566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 5239566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 52432077d6dSBarry Smith if (iascii) { 5259566063dSJacob Faibussowitsch PetscCall(MatView_SeqSBAIJ_ASCII(A, viewer)); 526618cc2edSLisandro Dalcin } else if (isbinary) { 5279566063dSJacob Faibussowitsch PetscCall(MatView_SeqSBAIJ_Binary(A, viewer)); 52849b5e25fSSatish Balay } else if (isdraw) { 5299566063dSJacob Faibussowitsch PetscCall(MatView_SeqSBAIJ_Draw(A, viewer)); 53049b5e25fSSatish Balay } else { 531a5e6ed63SBarry Smith Mat B; 532ade3a672SBarry Smith const char *matname; 5339566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B)); 5349566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)A, &matname)); 5359566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)B, matname)); 5369566063dSJacob Faibussowitsch PetscCall(MatView(B, viewer)); 5379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 53849b5e25fSSatish Balay } 53949b5e25fSSatish Balay PetscFunctionReturn(0); 54049b5e25fSSatish Balay } 54149b5e25fSSatish Balay 5429371c9d4SSatish Balay PetscErrorCode MatGetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[]) { 543045c9aa0SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 54413f74950SBarry Smith PetscInt *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j; 54513f74950SBarry Smith PetscInt *ai = a->i, *ailen = a->ilen; 546d0f46423SBarry Smith PetscInt brow, bcol, ridx, cidx, bs = A->rmap->bs, bs2 = a->bs2; 54797e567efSBarry Smith MatScalar *ap, *aa = a->a; 54849b5e25fSSatish Balay 54949b5e25fSSatish Balay PetscFunctionBegin; 55049b5e25fSSatish Balay for (k = 0; k < m; k++) { /* loop over rows */ 5519371c9d4SSatish Balay row = im[k]; 5529371c9d4SSatish Balay brow = row / bs; 5539371c9d4SSatish Balay if (row < 0) { 5549371c9d4SSatish Balay v += n; 5559371c9d4SSatish Balay continue; 5569371c9d4SSatish Balay } /* negative row */ 55754c59aa7SJacob 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); 5589371c9d4SSatish Balay rp = aj + ai[brow]; 5599371c9d4SSatish Balay ap = aa + bs2 * ai[brow]; 56049b5e25fSSatish Balay nrow = ailen[brow]; 56149b5e25fSSatish Balay for (l = 0; l < n; l++) { /* loop over columns */ 5629371c9d4SSatish Balay if (in[l] < 0) { 5639371c9d4SSatish Balay v++; 5649371c9d4SSatish Balay continue; 5659371c9d4SSatish Balay } /* negative column */ 56654c59aa7SJacob 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); 56749b5e25fSSatish Balay col = in[l]; 56849b5e25fSSatish Balay bcol = col / bs; 56949b5e25fSSatish Balay cidx = col % bs; 57049b5e25fSSatish Balay ridx = row % bs; 57149b5e25fSSatish Balay high = nrow; 57249b5e25fSSatish Balay low = 0; /* assume unsorted */ 57349b5e25fSSatish Balay while (high - low > 5) { 57449b5e25fSSatish Balay t = (low + high) / 2; 57549b5e25fSSatish Balay if (rp[t] > bcol) high = t; 57649b5e25fSSatish Balay else low = t; 57749b5e25fSSatish Balay } 57849b5e25fSSatish Balay for (i = low; i < high; i++) { 57949b5e25fSSatish Balay if (rp[i] > bcol) break; 58049b5e25fSSatish Balay if (rp[i] == bcol) { 58149b5e25fSSatish Balay *v++ = ap[bs2 * i + bs * cidx + ridx]; 58249b5e25fSSatish Balay goto finished; 58349b5e25fSSatish Balay } 58449b5e25fSSatish Balay } 58597e567efSBarry Smith *v++ = 0.0; 58649b5e25fSSatish Balay finished:; 58749b5e25fSSatish Balay } 58849b5e25fSSatish Balay } 58949b5e25fSSatish Balay PetscFunctionReturn(0); 59049b5e25fSSatish Balay } 59149b5e25fSSatish Balay 5929371c9d4SSatish Balay PetscErrorCode MatPermute_SeqSBAIJ(Mat A, IS rowp, IS colp, Mat *B) { 593dc29a518SPierre Jolivet Mat C; 594dc29a518SPierre Jolivet 595dc29a518SPierre Jolivet PetscFunctionBegin; 5969566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATSEQBAIJ, MAT_INITIAL_MATRIX, &C)); 5979566063dSJacob Faibussowitsch PetscCall(MatPermute(C, rowp, colp, B)); 5989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 599*48a46eb9SPierre Jolivet if (rowp == colp) PetscCall(MatConvert(*B, MATSEQSBAIJ, MAT_INPLACE_MATRIX, B)); 600dc29a518SPierre Jolivet PetscFunctionReturn(0); 601dc29a518SPierre Jolivet } 60249b5e25fSSatish Balay 6039371c9d4SSatish Balay PetscErrorCode MatSetValuesBlocked_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) { 6040880e062SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 605e2ee6c50SBarry Smith PetscInt *rp, k, low, high, t, ii, jj, row, nrow, i, col, l, rmax, N, lastcol = -1; 60613f74950SBarry Smith PetscInt *imax = a->imax, *ai = a->i, *ailen = a->ilen; 607d0f46423SBarry Smith PetscInt *aj = a->j, nonew = a->nonew, bs2 = a->bs2, bs = A->rmap->bs, stepval; 608ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 609dd6ea824SBarry Smith const PetscScalar *value = v; 610f15d580aSBarry Smith MatScalar *ap, *aa = a->a, *bap; 6110880e062SHong Zhang 61249b5e25fSSatish Balay PetscFunctionBegin; 61326fbe8dcSKarl Rupp if (roworiented) stepval = (n - 1) * bs; 61426fbe8dcSKarl Rupp else stepval = (m - 1) * bs; 61526fbe8dcSKarl Rupp 6160880e062SHong Zhang for (k = 0; k < m; k++) { /* loop over added rows */ 6170880e062SHong Zhang row = im[k]; 6180880e062SHong Zhang if (row < 0) continue; 6196bdcaf15SBarry 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); 6200880e062SHong Zhang rp = aj + ai[row]; 6210880e062SHong Zhang ap = aa + bs2 * ai[row]; 6220880e062SHong Zhang rmax = imax[row]; 6230880e062SHong Zhang nrow = ailen[row]; 6240880e062SHong Zhang low = 0; 625818f2c47SBarry Smith high = nrow; 6260880e062SHong Zhang for (l = 0; l < n; l++) { /* loop over added columns */ 6270880e062SHong Zhang if (in[l] < 0) continue; 6280880e062SHong Zhang col = in[l]; 6296bdcaf15SBarry 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); 630b98bf0e1SJed Brown if (col < row) { 63126fbe8dcSKarl Rupp if (a->ignore_ltriangular) continue; /* ignore lower triangular block */ 63226fbe8dcSKarl 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)"); 633b98bf0e1SJed Brown } 63426fbe8dcSKarl Rupp if (roworiented) value = v + k * (stepval + bs) * bs + l * bs; 63526fbe8dcSKarl Rupp else value = v + l * (stepval + bs) * bs + k * bs; 63626fbe8dcSKarl Rupp 63726fbe8dcSKarl Rupp if (col <= lastcol) low = 0; 63826fbe8dcSKarl Rupp else high = nrow; 63926fbe8dcSKarl Rupp 640e2ee6c50SBarry Smith lastcol = col; 6410880e062SHong Zhang while (high - low > 7) { 6420880e062SHong Zhang t = (low + high) / 2; 6430880e062SHong Zhang if (rp[t] > col) high = t; 6440880e062SHong Zhang else low = t; 6450880e062SHong Zhang } 6460880e062SHong Zhang for (i = low; i < high; i++) { 6470880e062SHong Zhang if (rp[i] > col) break; 6480880e062SHong Zhang if (rp[i] == col) { 6490880e062SHong Zhang bap = ap + bs2 * i; 6500880e062SHong Zhang if (roworiented) { 6510880e062SHong Zhang if (is == ADD_VALUES) { 6520880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 6539371c9d4SSatish Balay for (jj = ii; jj < bs2; jj += bs) { bap[jj] += *value++; } 6540880e062SHong Zhang } 6550880e062SHong Zhang } else { 6560880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 6579371c9d4SSatish Balay for (jj = ii; jj < bs2; jj += bs) { bap[jj] = *value++; } 6580880e062SHong Zhang } 6590880e062SHong Zhang } 6600880e062SHong Zhang } else { 6610880e062SHong Zhang if (is == ADD_VALUES) { 6620880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 6639371c9d4SSatish Balay for (jj = 0; jj < bs; jj++) { *bap++ += *value++; } 6640880e062SHong Zhang } 6650880e062SHong Zhang } else { 6660880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 6679371c9d4SSatish Balay for (jj = 0; jj < bs; jj++) { *bap++ = *value++; } 6680880e062SHong Zhang } 6690880e062SHong Zhang } 6700880e062SHong Zhang } 6710880e062SHong Zhang goto noinsert2; 6720880e062SHong Zhang } 6730880e062SHong Zhang } 6740880e062SHong Zhang if (nonew == 1) goto noinsert2; 67508401ef6SPierre 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); 676fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 6779371c9d4SSatish Balay N = nrow++ - 1; 6789371c9d4SSatish Balay high++; 6790880e062SHong Zhang /* shift up all the later entries in this row */ 6809566063dSJacob Faibussowitsch PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1)); 6819566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1))); 6829566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ap + bs2 * i, bs2)); 6830880e062SHong Zhang rp[i] = col; 6840880e062SHong Zhang bap = ap + bs2 * i; 6850880e062SHong Zhang if (roworiented) { 6860880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 6879371c9d4SSatish Balay for (jj = ii; jj < bs2; jj += bs) { bap[jj] = *value++; } 6880880e062SHong Zhang } 6890880e062SHong Zhang } else { 6900880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 6919371c9d4SSatish Balay for (jj = 0; jj < bs; jj++) { *bap++ = *value++; } 6920880e062SHong Zhang } 6930880e062SHong Zhang } 6940880e062SHong Zhang noinsert2:; 6950880e062SHong Zhang low = i; 6960880e062SHong Zhang } 6970880e062SHong Zhang ailen[row] = nrow; 6980880e062SHong Zhang } 6990880e062SHong Zhang PetscFunctionReturn(0); 70049b5e25fSSatish Balay } 70149b5e25fSSatish Balay 70264831d72SBarry Smith /* 70364831d72SBarry Smith This is not yet used 70464831d72SBarry Smith */ 7059371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_SeqSBAIJ_SeqAIJ_Inode(Mat A) { 7060def2e27SBarry Smith Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 7070def2e27SBarry Smith const PetscInt *ai = a->i, *aj = a->j, *cols; 7080def2e27SBarry Smith PetscInt i = 0, j, blk_size, m = A->rmap->n, node_count = 0, nzx, nzy, *ns, row, nz, cnt, cnt2, *counts; 709ace3abfcSBarry Smith PetscBool flag; 7100def2e27SBarry Smith 7110def2e27SBarry Smith PetscFunctionBegin; 7129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &ns)); 7130def2e27SBarry Smith while (i < m) { 7140def2e27SBarry Smith nzx = ai[i + 1] - ai[i]; /* Number of nonzeros */ 7150def2e27SBarry Smith /* Limits the number of elements in a node to 'a->inode.limit' */ 7160def2e27SBarry Smith for (j = i + 1, blk_size = 1; j < m && blk_size < a->inode.limit; ++j, ++blk_size) { 7170def2e27SBarry Smith nzy = ai[j + 1] - ai[j]; 7180def2e27SBarry Smith if (nzy != (nzx - j + i)) break; 7199566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(aj + ai[i] + j - i, aj + ai[j], nzy, &flag)); 7200def2e27SBarry Smith if (!flag) break; 7210def2e27SBarry Smith } 7220def2e27SBarry Smith ns[node_count++] = blk_size; 72326fbe8dcSKarl Rupp 7240def2e27SBarry Smith i = j; 7250def2e27SBarry Smith } 7260def2e27SBarry Smith if (!a->inode.size && m && node_count > .9 * m) { 7279566063dSJacob Faibussowitsch PetscCall(PetscFree(ns)); 7289566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Found %" PetscInt_FMT " nodes out of %" PetscInt_FMT " rows. Not using Inode routines\n", node_count, m)); 7290def2e27SBarry Smith } else { 7300def2e27SBarry Smith a->inode.node_count = node_count; 73126fbe8dcSKarl Rupp 7329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(node_count, &a->inode.size)); 7339566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A, node_count * sizeof(PetscInt))); 7349566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->inode.size, ns, node_count)); 7359566063dSJacob Faibussowitsch PetscCall(PetscFree(ns)); 7369566063dSJacob 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)); 7370def2e27SBarry Smith 7380def2e27SBarry Smith /* count collections of adjacent columns in each inode */ 7390def2e27SBarry Smith row = 0; 7400def2e27SBarry Smith cnt = 0; 7410def2e27SBarry Smith for (i = 0; i < node_count; i++) { 7420def2e27SBarry Smith cols = aj + ai[row] + a->inode.size[i]; 7430def2e27SBarry Smith nz = ai[row + 1] - ai[row] - a->inode.size[i]; 7440def2e27SBarry Smith for (j = 1; j < nz; j++) { 74526fbe8dcSKarl Rupp if (cols[j] != cols[j - 1] + 1) cnt++; 7460def2e27SBarry Smith } 7470def2e27SBarry Smith cnt++; 7480def2e27SBarry Smith row += a->inode.size[i]; 7490def2e27SBarry Smith } 7509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * cnt, &counts)); 7510def2e27SBarry Smith cnt = 0; 7520def2e27SBarry Smith row = 0; 7530def2e27SBarry Smith for (i = 0; i < node_count; i++) { 7540def2e27SBarry Smith cols = aj + ai[row] + a->inode.size[i]; 7550def2e27SBarry Smith counts[2 * cnt] = cols[0]; 7560def2e27SBarry Smith nz = ai[row + 1] - ai[row] - a->inode.size[i]; 7570def2e27SBarry Smith cnt2 = 1; 7580def2e27SBarry Smith for (j = 1; j < nz; j++) { 7590def2e27SBarry Smith if (cols[j] != cols[j - 1] + 1) { 7600def2e27SBarry Smith counts[2 * (cnt++) + 1] = cnt2; 7610def2e27SBarry Smith counts[2 * cnt] = cols[j]; 7620def2e27SBarry Smith cnt2 = 1; 7630def2e27SBarry Smith } else cnt2++; 7640def2e27SBarry Smith } 7650def2e27SBarry Smith counts[2 * (cnt++) + 1] = cnt2; 7660def2e27SBarry Smith row += a->inode.size[i]; 7670def2e27SBarry Smith } 7689566063dSJacob Faibussowitsch PetscCall(PetscIntView(2 * cnt, counts, NULL)); 7690def2e27SBarry Smith } 77038702af4SBarry Smith PetscFunctionReturn(0); 77138702af4SBarry Smith } 77238702af4SBarry Smith 7739371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_SeqSBAIJ(Mat A, MatAssemblyType mode) { 77449b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 7758f8f2f0dSBarry Smith PetscInt fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax; 776d0f46423SBarry Smith PetscInt m = A->rmap->N, *ip, N, *ailen = a->ilen; 77713f74950SBarry Smith PetscInt mbs = a->mbs, bs2 = a->bs2, rmax = 0; 77849b5e25fSSatish Balay MatScalar *aa = a->a, *ap; 77949b5e25fSSatish Balay 78049b5e25fSSatish Balay PetscFunctionBegin; 78149b5e25fSSatish Balay if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 78249b5e25fSSatish Balay 78349b5e25fSSatish Balay if (m) rmax = ailen[0]; 78449b5e25fSSatish Balay for (i = 1; i < mbs; i++) { 78549b5e25fSSatish Balay /* move each row back by the amount of empty slots (fshift) before it*/ 78649b5e25fSSatish Balay fshift += imax[i - 1] - ailen[i - 1]; 78749b5e25fSSatish Balay rmax = PetscMax(rmax, ailen[i]); 78849b5e25fSSatish Balay if (fshift) { 789580bdb30SBarry Smith ip = aj + ai[i]; 790580bdb30SBarry Smith ap = aa + bs2 * ai[i]; 79149b5e25fSSatish Balay N = ailen[i]; 7929566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ip - fshift, ip, N)); 7939566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap - bs2 * fshift, ap, bs2 * N)); 79449b5e25fSSatish Balay } 79549b5e25fSSatish Balay ai[i] = ai[i - 1] + ailen[i - 1]; 79649b5e25fSSatish Balay } 79749b5e25fSSatish Balay if (mbs) { 79849b5e25fSSatish Balay fshift += imax[mbs - 1] - ailen[mbs - 1]; 79949b5e25fSSatish Balay ai[mbs] = ai[mbs - 1] + ailen[mbs - 1]; 80049b5e25fSSatish Balay } 80149b5e25fSSatish Balay /* reset ilen and imax for each row */ 8029371c9d4SSatish Balay for (i = 0; i < mbs; i++) { ailen[i] = imax[i] = ai[i + 1] - ai[i]; } 8036c6c5352SBarry Smith a->nz = ai[mbs]; 80449b5e25fSSatish Balay 805b424e231SHong Zhang /* diagonals may have moved, reset it */ 8061baa6e33SBarry Smith if (a->diag) PetscCall(PetscArraycpy(a->diag, ai, mbs)); 807aed4548fSBarry 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); 80826fbe8dcSKarl Rupp 8099566063dSJacob 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)); 8109566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues is %" PetscInt_FMT "\n", a->reallocs)); 8119566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Most nonzeros blocks in any row is %" PetscInt_FMT "\n", rmax)); 81226fbe8dcSKarl Rupp 8138e58a170SBarry Smith A->info.mallocs += a->reallocs; 81449b5e25fSSatish Balay a->reallocs = 0; 81549b5e25fSSatish Balay A->info.nz_unneeded = (PetscReal)fshift * bs2; 816061b2667SBarry Smith a->idiagvalid = PETSC_FALSE; 8174dcd73b1SHong Zhang a->rmax = rmax; 81838702af4SBarry Smith 81938702af4SBarry Smith if (A->cmap->n < 65536 && A->cmap->bs == 1) { 82044e1c64aSLisandro Dalcin if (a->jshort && a->free_jshort) { 82117803ae8SHong Zhang /* when matrix data structure is changed, previous jshort must be replaced */ 8229566063dSJacob Faibussowitsch PetscCall(PetscFree(a->jshort)); 82317803ae8SHong Zhang } 8249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(a->i[A->rmap->n], &a->jshort)); 8259566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A, a->i[A->rmap->n] * sizeof(unsigned short))); 82638702af4SBarry Smith for (i = 0; i < a->i[A->rmap->n]; i++) a->jshort[i] = a->j[i]; 82738702af4SBarry Smith A->ops->mult = MatMult_SeqSBAIJ_1_ushort; 82841f059aeSBarry Smith A->ops->sor = MatSOR_SeqSBAIJ_ushort; 8294da8f245SBarry Smith a->free_jshort = PETSC_TRUE; 83038702af4SBarry Smith } 83149b5e25fSSatish Balay PetscFunctionReturn(0); 83249b5e25fSSatish Balay } 83349b5e25fSSatish Balay 83449b5e25fSSatish Balay /* 83549b5e25fSSatish Balay This function returns an array of flags which indicate the locations of contiguous 83649b5e25fSSatish Balay blocks that should be zeroed. for eg: if bs = 3 and is = [0,1,2,3,5,6,7,8,9] 837a5b23f4aSJose E. Roman then the resulting sizes = [3,1,1,3,1] corresponding to sets [(0,1,2),(3),(5),(6,7,8),(9)] 83849b5e25fSSatish Balay Assume: sizes should be long enough to hold all the values. 83949b5e25fSSatish Balay */ 8409371c9d4SSatish Balay PetscErrorCode MatZeroRows_SeqSBAIJ_Check_Blocks(PetscInt idx[], PetscInt n, PetscInt bs, PetscInt sizes[], PetscInt *bs_max) { 84113f74950SBarry Smith PetscInt i, j, k, row; 842ace3abfcSBarry Smith PetscBool flg; 84349b5e25fSSatish Balay 84449b5e25fSSatish Balay PetscFunctionBegin; 84549b5e25fSSatish Balay for (i = 0, j = 0; i < n; j++) { 84649b5e25fSSatish Balay row = idx[i]; 847a5b23f4aSJose E. Roman if (row % bs != 0) { /* Not the beginning of a block */ 84849b5e25fSSatish Balay sizes[j] = 1; 84949b5e25fSSatish Balay i++; 85049b5e25fSSatish Balay } else if (i + bs > n) { /* Beginning of a block, but complete block doesn't exist (at idx end) */ 85149b5e25fSSatish Balay sizes[j] = 1; /* Also makes sure at least 'bs' values exist for next else */ 85249b5e25fSSatish Balay i++; 8536aad120cSJose E. Roman } else { /* Beginning of the block, so check if the complete block exists */ 85449b5e25fSSatish Balay flg = PETSC_TRUE; 85549b5e25fSSatish Balay for (k = 1; k < bs; k++) { 85649b5e25fSSatish Balay if (row + k != idx[i + k]) { /* break in the block */ 85749b5e25fSSatish Balay flg = PETSC_FALSE; 85849b5e25fSSatish Balay break; 85949b5e25fSSatish Balay } 86049b5e25fSSatish Balay } 861abc0a331SBarry Smith if (flg) { /* No break in the bs */ 86249b5e25fSSatish Balay sizes[j] = bs; 86349b5e25fSSatish Balay i += bs; 86449b5e25fSSatish Balay } else { 86549b5e25fSSatish Balay sizes[j] = 1; 86649b5e25fSSatish Balay i++; 86749b5e25fSSatish Balay } 86849b5e25fSSatish Balay } 86949b5e25fSSatish Balay } 87049b5e25fSSatish Balay *bs_max = j; 87149b5e25fSSatish Balay PetscFunctionReturn(0); 87249b5e25fSSatish Balay } 87349b5e25fSSatish Balay 87449b5e25fSSatish Balay /* Only add/insert a(i,j) with i<=j (blocks). 87549b5e25fSSatish Balay Any a(i,j) with i>j input by user is ingored. 87649b5e25fSSatish Balay */ 87749b5e25fSSatish Balay 8789371c9d4SSatish Balay PetscErrorCode MatSetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) { 87949b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 880e2ee6c50SBarry Smith PetscInt *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N, lastcol = -1; 88113f74950SBarry Smith PetscInt *imax = a->imax, *ai = a->i, *ailen = a->ilen, roworiented = a->roworiented; 882d0f46423SBarry Smith PetscInt *aj = a->j, nonew = a->nonew, bs = A->rmap->bs, brow, bcol; 88313f74950SBarry Smith PetscInt ridx, cidx, bs2 = a->bs2; 88449b5e25fSSatish Balay MatScalar *ap, value, *aa = a->a, *bap; 88549b5e25fSSatish Balay 88649b5e25fSSatish Balay PetscFunctionBegin; 88749b5e25fSSatish Balay for (k = 0; k < m; k++) { /* loop over added rows */ 88849b5e25fSSatish Balay row = im[k]; /* row number */ 88949b5e25fSSatish Balay brow = row / bs; /* block row number */ 89049b5e25fSSatish Balay if (row < 0) continue; 8916bdcaf15SBarry 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); 89249b5e25fSSatish Balay rp = aj + ai[brow]; /*ptr to beginning of column value of the row block*/ 89349b5e25fSSatish Balay ap = aa + bs2 * ai[brow]; /*ptr to beginning of element value of the row block*/ 89449b5e25fSSatish Balay rmax = imax[brow]; /* maximum space allocated for this row */ 89549b5e25fSSatish Balay nrow = ailen[brow]; /* actual length of this row */ 89649b5e25fSSatish Balay low = 0; 8978509e838SStefano Zampini high = nrow; 89849b5e25fSSatish Balay for (l = 0; l < n; l++) { /* loop over added columns */ 89949b5e25fSSatish Balay if (in[l] < 0) continue; 9006bdcaf15SBarry 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); 90149b5e25fSSatish Balay col = in[l]; 90249b5e25fSSatish Balay bcol = col / bs; /* block col number */ 90349b5e25fSSatish Balay 904941593c8SHong Zhang if (brow > bcol) { 90526fbe8dcSKarl Rupp if (a->ignore_ltriangular) continue; /* ignore lower triangular values */ 90626fbe8dcSKarl 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)"); 907941593c8SHong Zhang } 908f4989cb3SHong Zhang 9099371c9d4SSatish Balay ridx = row % bs; 9109371c9d4SSatish Balay cidx = col % bs; /*row and col index inside the block */ 9118549e402SHong Zhang if ((brow == bcol && ridx <= cidx) || (brow < bcol)) { 91249b5e25fSSatish Balay /* element value a(k,l) */ 91326fbe8dcSKarl Rupp if (roworiented) value = v[l + k * n]; 91426fbe8dcSKarl Rupp else value = v[k + l * m]; 91549b5e25fSSatish Balay 91649b5e25fSSatish Balay /* move pointer bap to a(k,l) quickly and add/insert value */ 91726fbe8dcSKarl Rupp if (col <= lastcol) low = 0; 9188509e838SStefano Zampini else high = nrow; 9198509e838SStefano Zampini 920e2ee6c50SBarry Smith lastcol = col; 92149b5e25fSSatish Balay while (high - low > 7) { 92249b5e25fSSatish Balay t = (low + high) / 2; 92349b5e25fSSatish Balay if (rp[t] > bcol) high = t; 92449b5e25fSSatish Balay else low = t; 92549b5e25fSSatish Balay } 92649b5e25fSSatish Balay for (i = low; i < high; i++) { 92749b5e25fSSatish Balay if (rp[i] > bcol) break; 92849b5e25fSSatish Balay if (rp[i] == bcol) { 92949b5e25fSSatish Balay bap = ap + bs2 * i + bs * cidx + ridx; 93049b5e25fSSatish Balay if (is == ADD_VALUES) *bap += value; 93149b5e25fSSatish Balay else *bap = value; 9328549e402SHong Zhang /* for diag block, add/insert its symmetric element a(cidx,ridx) */ 9338549e402SHong Zhang if (brow == bcol && ridx < cidx) { 9348549e402SHong Zhang bap = ap + bs2 * i + bs * ridx + cidx; 9358549e402SHong Zhang if (is == ADD_VALUES) *bap += value; 9368549e402SHong Zhang else *bap = value; 9378549e402SHong Zhang } 93849b5e25fSSatish Balay goto noinsert1; 93949b5e25fSSatish Balay } 94049b5e25fSSatish Balay } 94149b5e25fSSatish Balay 94249b5e25fSSatish Balay if (nonew == 1) goto noinsert1; 94308401ef6SPierre Jolivet PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero (%" PetscInt_FMT ", %" PetscInt_FMT ") in the matrix", row, col); 944fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, brow, bcol, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 94549b5e25fSSatish Balay 9469371c9d4SSatish Balay N = nrow++ - 1; 9479371c9d4SSatish Balay high++; 94849b5e25fSSatish Balay /* shift up all the later entries in this row */ 9499566063dSJacob Faibussowitsch PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1)); 9509566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1))); 9519566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ap + bs2 * i, bs2)); 95249b5e25fSSatish Balay rp[i] = bcol; 95349b5e25fSSatish Balay ap[bs2 * i + bs * cidx + ridx] = value; 9548509e838SStefano Zampini /* for diag block, add/insert its symmetric element a(cidx,ridx) */ 9559371c9d4SSatish Balay if (brow == bcol && ridx < cidx) { ap[bs2 * i + bs * ridx + cidx] = value; } 956e56f5c9eSBarry Smith A->nonzerostate++; 95749b5e25fSSatish Balay noinsert1:; 95849b5e25fSSatish Balay low = i; 9598549e402SHong Zhang } 96049b5e25fSSatish Balay } /* end of loop over added columns */ 96149b5e25fSSatish Balay ailen[brow] = nrow; 96249b5e25fSSatish Balay } /* end of loop over added rows */ 96349b5e25fSSatish Balay PetscFunctionReturn(0); 96449b5e25fSSatish Balay } 96549b5e25fSSatish Balay 9669371c9d4SSatish Balay PetscErrorCode MatICCFactor_SeqSBAIJ(Mat inA, IS row, const MatFactorInfo *info) { 9674ccecd49SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)inA->data; 96849b5e25fSSatish Balay Mat outA; 969ace3abfcSBarry Smith PetscBool row_identity; 97049b5e25fSSatish Balay 97149b5e25fSSatish Balay PetscFunctionBegin; 97208401ef6SPierre Jolivet PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 is supported for in-place icc"); 9739566063dSJacob Faibussowitsch PetscCall(ISIdentity(row, &row_identity)); 97428b400f6SJacob Faibussowitsch PetscCheck(row_identity, PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix reordering is not supported"); 97508401ef6SPierre 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()! */ 976c84f5b01SHong Zhang 97749b5e25fSSatish Balay outA = inA; 978d5f3da31SBarry Smith inA->factortype = MAT_FACTOR_ICC; 9799566063dSJacob Faibussowitsch PetscCall(PetscFree(inA->solvertype)); 9809566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype)); 98149b5e25fSSatish Balay 9829566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqSBAIJ(inA)); 9839566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetNumericFactorization_inplace(inA, row_identity)); 98449b5e25fSSatish Balay 9859566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)row)); 9869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 987c84f5b01SHong Zhang a->row = row; 9889566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)row)); 9899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 990c84f5b01SHong Zhang a->col = row; 991c84f5b01SHong Zhang 992c84f5b01SHong Zhang /* Create the invert permutation so that it can be used in MatCholeskyFactorNumeric() */ 9939566063dSJacob Faibussowitsch if (a->icol) PetscCall(ISInvertPermutation(row, PETSC_DECIDE, &a->icol)); 9949566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)inA, (PetscObject)a->icol)); 99549b5e25fSSatish Balay 99649b5e25fSSatish Balay if (!a->solve_work) { 9979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(inA->rmap->N + inA->rmap->bs, &a->solve_work)); 9989566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)inA, (inA->rmap->N + inA->rmap->bs) * sizeof(PetscScalar))); 99949b5e25fSSatish Balay } 100049b5e25fSSatish Balay 10019566063dSJacob Faibussowitsch PetscCall(MatCholeskyFactorNumeric(outA, inA, info)); 100249b5e25fSSatish Balay PetscFunctionReturn(0); 100349b5e25fSSatish Balay } 1004950f1e5bSHong Zhang 10059371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat, PetscInt *indices) { 1006045c9aa0SHong Zhang Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)mat->data; 100713f74950SBarry Smith PetscInt i, nz, n; 100849b5e25fSSatish Balay 100949b5e25fSSatish Balay PetscFunctionBegin; 10106c6c5352SBarry Smith nz = baij->maxnz; 1011d0f46423SBarry Smith n = mat->cmap->n; 101226fbe8dcSKarl Rupp for (i = 0; i < nz; i++) baij->j[i] = indices[i]; 101326fbe8dcSKarl Rupp 10146c6c5352SBarry Smith baij->nz = nz; 101526fbe8dcSKarl Rupp for (i = 0; i < n; i++) baij->ilen[i] = baij->imax[i]; 101626fbe8dcSKarl Rupp 10179566063dSJacob Faibussowitsch PetscCall(MatSetOption(mat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 101849b5e25fSSatish Balay PetscFunctionReturn(0); 101949b5e25fSSatish Balay } 102049b5e25fSSatish Balay 102149b5e25fSSatish Balay /*@ 102219585528SSatish Balay MatSeqSBAIJSetColumnIndices - Set the column indices for all the rows 102349b5e25fSSatish Balay in the matrix. 102449b5e25fSSatish Balay 102549b5e25fSSatish Balay Input Parameters: 102619585528SSatish Balay + mat - the SeqSBAIJ matrix 102749b5e25fSSatish Balay - indices - the column indices 102849b5e25fSSatish Balay 102949b5e25fSSatish Balay Level: advanced 103049b5e25fSSatish Balay 103149b5e25fSSatish Balay Notes: 103249b5e25fSSatish Balay This can be called if you have precomputed the nonzero structure of the 103349b5e25fSSatish Balay matrix and want to provide it to the matrix object to improve the performance 103449b5e25fSSatish Balay of the MatSetValues() operation. 103549b5e25fSSatish Balay 103649b5e25fSSatish Balay You MUST have set the correct numbers of nonzeros per row in the call to 1037d1be2dadSMatthew Knepley MatCreateSeqSBAIJ(), and the columns indices MUST be sorted. 103849b5e25fSSatish Balay 1039ab9f2c04SSatish Balay MUST be called before any calls to MatSetValues() 104049b5e25fSSatish Balay 1041db781477SPatrick Sanan .seealso: `MatCreateSeqSBAIJ` 104249b5e25fSSatish Balay @*/ 10439371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetColumnIndices(Mat mat, PetscInt *indices) { 104449b5e25fSSatish Balay PetscFunctionBegin; 10450700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1046dadcf809SJacob Faibussowitsch PetscValidIntPointer(indices, 2); 1047cac4c232SBarry Smith PetscUseMethod(mat, "MatSeqSBAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices)); 104849b5e25fSSatish Balay PetscFunctionReturn(0); 104949b5e25fSSatish Balay } 105049b5e25fSSatish Balay 10519371c9d4SSatish Balay PetscErrorCode MatCopy_SeqSBAIJ(Mat A, Mat B, MatStructure str) { 10524c7a3774SStefano Zampini PetscBool isbaij; 10533c896bc6SHong Zhang 10543c896bc6SHong Zhang PetscFunctionBegin; 10559566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &isbaij, MATSEQSBAIJ, MATMPISBAIJ, "")); 105628b400f6SJacob Faibussowitsch PetscCheck(isbaij, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)B)->type_name); 10574c7a3774SStefano Zampini /* If the two matrices have the same copy implementation and nonzero pattern, use fast copy. */ 10584c7a3774SStefano Zampini if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) { 10593c896bc6SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 10603c896bc6SHong Zhang Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data; 10613c896bc6SHong Zhang 106208401ef6SPierre 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"); 106308401ef6SPierre Jolivet PetscCheck(a->mbs == b->mbs, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of rows in two matrices are different"); 106408401ef6SPierre Jolivet PetscCheck(a->bs2 == b->bs2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different block size"); 10659566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->a, a->a, a->bs2 * a->i[a->mbs])); 10669566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 10673c896bc6SHong Zhang } else { 10689566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(A)); 10699566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 10709566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(A)); 10713c896bc6SHong Zhang } 10723c896bc6SHong Zhang PetscFunctionReturn(0); 10733c896bc6SHong Zhang } 10743c896bc6SHong Zhang 10759371c9d4SSatish Balay PetscErrorCode MatSetUp_SeqSBAIJ(Mat A) { 1076273d9f13SBarry Smith PetscFunctionBegin; 10779566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(A, A->rmap->bs, PETSC_DEFAULT, NULL)); 1078273d9f13SBarry Smith PetscFunctionReturn(0); 1079273d9f13SBarry Smith } 1080273d9f13SBarry Smith 10819371c9d4SSatish Balay static PetscErrorCode MatSeqSBAIJGetArray_SeqSBAIJ(Mat A, PetscScalar *array[]) { 1082a6ece127SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 10835fd66863SKarl Rupp 1084a6ece127SHong Zhang PetscFunctionBegin; 1085a6ece127SHong Zhang *array = a->a; 1086a6ece127SHong Zhang PetscFunctionReturn(0); 1087a6ece127SHong Zhang } 1088a6ece127SHong Zhang 10899371c9d4SSatish Balay static PetscErrorCode MatSeqSBAIJRestoreArray_SeqSBAIJ(Mat A, PetscScalar *array[]) { 1090a6ece127SHong Zhang PetscFunctionBegin; 1091cda14afcSprj- *array = NULL; 1092a6ece127SHong Zhang PetscFunctionReturn(0); 1093a6ece127SHong Zhang } 1094a6ece127SHong Zhang 10959371c9d4SSatish Balay PetscErrorCode MatAXPYGetPreallocation_SeqSBAIJ(Mat Y, Mat X, PetscInt *nnz) { 1096b264fe52SHong Zhang PetscInt bs = Y->rmap->bs, mbs = Y->rmap->N / bs; 109752768537SHong Zhang Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data; 109852768537SHong Zhang Mat_SeqSBAIJ *y = (Mat_SeqSBAIJ *)Y->data; 109952768537SHong Zhang 110052768537SHong Zhang PetscFunctionBegin; 110152768537SHong Zhang /* Set the number of nonzeros in the new matrix */ 11029566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqX_private(mbs, x->i, x->j, y->i, y->j, nnz)); 110352768537SHong Zhang PetscFunctionReturn(0); 110452768537SHong Zhang } 110552768537SHong Zhang 11069371c9d4SSatish Balay PetscErrorCode MatAXPY_SeqSBAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str) { 110742ee4b1aSHong Zhang Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data, *y = (Mat_SeqSBAIJ *)Y->data; 110831ce2d13SHong Zhang PetscInt bs = Y->rmap->bs, bs2 = bs * bs; 1109e838b9e7SJed Brown PetscBLASInt one = 1; 111042ee4b1aSHong Zhang 111142ee4b1aSHong Zhang PetscFunctionBegin; 1112134adf20SPierre Jolivet if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) { 1113134adf20SPierre Jolivet PetscBool e = x->nz == y->nz && x->mbs == y->mbs ? PETSC_TRUE : PETSC_FALSE; 1114134adf20SPierre Jolivet if (e) { 11159566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->i, y->i, x->mbs + 1, &e)); 1116134adf20SPierre Jolivet if (e) { 11179566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->j, y->j, x->i[x->mbs], &e)); 1118134adf20SPierre Jolivet if (e) str = SAME_NONZERO_PATTERN; 1119134adf20SPierre Jolivet } 1120134adf20SPierre Jolivet } 112154c59aa7SJacob Faibussowitsch if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN"); 1122134adf20SPierre Jolivet } 112342ee4b1aSHong Zhang if (str == SAME_NONZERO_PATTERN) { 1124f4df32b1SMatthew Knepley PetscScalar alpha = a; 1125c5df96a5SBarry Smith PetscBLASInt bnz; 11269566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(x->nz * bs2, &bnz)); 1127792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, x->a, &one, y->a, &one)); 11289566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 1129ab784542SHong Zhang } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 11309566063dSJacob Faibussowitsch PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_TRUE)); 11319566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 11329566063dSJacob Faibussowitsch PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_FALSE)); 113342ee4b1aSHong Zhang } else { 113452768537SHong Zhang Mat B; 113552768537SHong Zhang PetscInt *nnz; 113654c59aa7SJacob Faibussowitsch PetscCheck(bs == X->rmap->bs, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Matrices must have same block size"); 11379566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(X)); 11389566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(Y)); 11399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Y->rmap->N, &nnz)); 11409566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B)); 11419566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name)); 11429566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, Y->rmap->n, Y->cmap->n, Y->rmap->N, Y->cmap->N)); 11439566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, Y, Y)); 11449566063dSJacob Faibussowitsch PetscCall(MatSetType(B, ((PetscObject)Y)->type_name)); 11459566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqSBAIJ(Y, X, nnz)); 11469566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz)); 114752768537SHong Zhang 11489566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 114952768537SHong Zhang 11509566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 11519566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 11529566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(X)); 11539566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(Y)); 115442ee4b1aSHong Zhang } 115542ee4b1aSHong Zhang PetscFunctionReturn(0); 115642ee4b1aSHong Zhang } 115742ee4b1aSHong Zhang 11589371c9d4SSatish Balay PetscErrorCode MatIsSymmetric_SeqSBAIJ(Mat A, PetscReal tol, PetscBool *flg) { 1159efcf0fc3SBarry Smith PetscFunctionBegin; 1160efcf0fc3SBarry Smith *flg = PETSC_TRUE; 1161efcf0fc3SBarry Smith PetscFunctionReturn(0); 1162efcf0fc3SBarry Smith } 1163efcf0fc3SBarry Smith 11649371c9d4SSatish Balay PetscErrorCode MatIsStructurallySymmetric_SeqSBAIJ(Mat A, PetscBool *flg) { 1165efcf0fc3SBarry Smith PetscFunctionBegin; 1166efcf0fc3SBarry Smith *flg = PETSC_TRUE; 1167efcf0fc3SBarry Smith PetscFunctionReturn(0); 1168efcf0fc3SBarry Smith } 1169efcf0fc3SBarry Smith 11709371c9d4SSatish Balay PetscErrorCode MatIsHermitian_SeqSBAIJ(Mat A, PetscReal tol, PetscBool *flg) { 1171efcf0fc3SBarry Smith PetscFunctionBegin; 1172efcf0fc3SBarry Smith *flg = PETSC_FALSE; 1173efcf0fc3SBarry Smith PetscFunctionReturn(0); 1174efcf0fc3SBarry Smith } 1175efcf0fc3SBarry Smith 11769371c9d4SSatish Balay PetscErrorCode MatConjugate_SeqSBAIJ(Mat A) { 11772726fb6dSPierre Jolivet #if defined(PETSC_USE_COMPLEX) 11782726fb6dSPierre Jolivet Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 11792726fb6dSPierre Jolivet PetscInt i, nz = a->bs2 * a->i[a->mbs]; 11802726fb6dSPierre Jolivet MatScalar *aa = a->a; 11812726fb6dSPierre Jolivet 11822726fb6dSPierre Jolivet PetscFunctionBegin; 11832726fb6dSPierre Jolivet for (i = 0; i < nz; i++) aa[i] = PetscConj(aa[i]); 11842726fb6dSPierre Jolivet #else 11852726fb6dSPierre Jolivet PetscFunctionBegin; 11862726fb6dSPierre Jolivet #endif 11872726fb6dSPierre Jolivet PetscFunctionReturn(0); 11882726fb6dSPierre Jolivet } 11892726fb6dSPierre Jolivet 11909371c9d4SSatish Balay PetscErrorCode MatRealPart_SeqSBAIJ(Mat A) { 119199cafbc1SBarry Smith Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 119299cafbc1SBarry Smith PetscInt i, nz = a->bs2 * a->i[a->mbs]; 1193dd6ea824SBarry Smith MatScalar *aa = a->a; 119499cafbc1SBarry Smith 119599cafbc1SBarry Smith PetscFunctionBegin; 119699cafbc1SBarry Smith for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]); 119799cafbc1SBarry Smith PetscFunctionReturn(0); 119899cafbc1SBarry Smith } 119999cafbc1SBarry Smith 12009371c9d4SSatish Balay PetscErrorCode MatImaginaryPart_SeqSBAIJ(Mat A) { 120199cafbc1SBarry Smith Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 120299cafbc1SBarry Smith PetscInt i, nz = a->bs2 * a->i[a->mbs]; 1203dd6ea824SBarry Smith MatScalar *aa = a->a; 120499cafbc1SBarry Smith 120599cafbc1SBarry Smith PetscFunctionBegin; 120699cafbc1SBarry Smith for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]); 120799cafbc1SBarry Smith PetscFunctionReturn(0); 120899cafbc1SBarry Smith } 120999cafbc1SBarry Smith 12109371c9d4SSatish Balay PetscErrorCode MatZeroRowsColumns_SeqSBAIJ(Mat A, PetscInt is_n, const PetscInt is_idx[], PetscScalar diag, Vec x, Vec b) { 12113bededecSBarry Smith Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)A->data; 12123bededecSBarry Smith PetscInt i, j, k, count; 12133bededecSBarry Smith PetscInt bs = A->rmap->bs, bs2 = baij->bs2, row, col; 12143bededecSBarry Smith PetscScalar zero = 0.0; 12153bededecSBarry Smith MatScalar *aa; 12163bededecSBarry Smith const PetscScalar *xx; 12173bededecSBarry Smith PetscScalar *bb; 121856777dd2SBarry Smith PetscBool *zeroed, vecs = PETSC_FALSE; 12193bededecSBarry Smith 12203bededecSBarry Smith PetscFunctionBegin; 12213bededecSBarry Smith /* fix right hand side if needed */ 12223bededecSBarry Smith if (x && b) { 12239566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 12249566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 122556777dd2SBarry Smith vecs = PETSC_TRUE; 12263bededecSBarry Smith } 12273bededecSBarry Smith 12283bededecSBarry Smith /* zero the columns */ 12299566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n, &zeroed)); 12303bededecSBarry Smith for (i = 0; i < is_n; i++) { 1231aed4548fSBarry 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]); 12323bededecSBarry Smith zeroed[is_idx[i]] = PETSC_TRUE; 12333bededecSBarry Smith } 123456777dd2SBarry Smith if (vecs) { 123556777dd2SBarry Smith for (i = 0; i < A->rmap->N; i++) { 123656777dd2SBarry Smith row = i / bs; 123756777dd2SBarry Smith for (j = baij->i[row]; j < baij->i[row + 1]; j++) { 123856777dd2SBarry Smith for (k = 0; k < bs; k++) { 123956777dd2SBarry Smith col = bs * baij->j[j] + k; 124056777dd2SBarry Smith if (col <= i) continue; 124156777dd2SBarry Smith aa = ((MatScalar *)(baij->a)) + j * bs2 + (i % bs) + bs * k; 124226fbe8dcSKarl Rupp if (!zeroed[i] && zeroed[col]) bb[i] -= aa[0] * xx[col]; 124326fbe8dcSKarl Rupp if (zeroed[i] && !zeroed[col]) bb[col] -= aa[0] * xx[i]; 124456777dd2SBarry Smith } 124556777dd2SBarry Smith } 124656777dd2SBarry Smith } 124726fbe8dcSKarl Rupp for (i = 0; i < is_n; i++) bb[is_idx[i]] = diag * xx[is_idx[i]]; 124856777dd2SBarry Smith } 124956777dd2SBarry Smith 12503bededecSBarry Smith for (i = 0; i < A->rmap->N; i++) { 12513bededecSBarry Smith if (!zeroed[i]) { 12523bededecSBarry Smith row = i / bs; 12533bededecSBarry Smith for (j = baij->i[row]; j < baij->i[row + 1]; j++) { 12543bededecSBarry Smith for (k = 0; k < bs; k++) { 12553bededecSBarry Smith col = bs * baij->j[j] + k; 12563bededecSBarry Smith if (zeroed[col]) { 12573bededecSBarry Smith aa = ((MatScalar *)(baij->a)) + j * bs2 + (i % bs) + bs * k; 12583bededecSBarry Smith aa[0] = 0.0; 12593bededecSBarry Smith } 12603bededecSBarry Smith } 12613bededecSBarry Smith } 12623bededecSBarry Smith } 12633bededecSBarry Smith } 12649566063dSJacob Faibussowitsch PetscCall(PetscFree(zeroed)); 126556777dd2SBarry Smith if (vecs) { 12669566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 12679566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 126856777dd2SBarry Smith } 12693bededecSBarry Smith 12703bededecSBarry Smith /* zero the rows */ 12713bededecSBarry Smith for (i = 0; i < is_n; i++) { 12723bededecSBarry Smith row = is_idx[i]; 12733bededecSBarry Smith count = (baij->i[row / bs + 1] - baij->i[row / bs]) * bs; 12743bededecSBarry Smith aa = ((MatScalar *)(baij->a)) + baij->i[row / bs] * bs2 + (row % bs); 12753bededecSBarry Smith for (k = 0; k < count; k++) { 12763bededecSBarry Smith aa[0] = zero; 12773bededecSBarry Smith aa += bs; 12783bededecSBarry Smith } 1279dbbe0bcdSBarry Smith if (diag != 0.0) PetscUseTypeMethod(A, setvalues, 1, &row, 1, &row, &diag, INSERT_VALUES); 12803bededecSBarry Smith } 12819566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_SeqSBAIJ(A, MAT_FINAL_ASSEMBLY)); 12823bededecSBarry Smith PetscFunctionReturn(0); 12833bededecSBarry Smith } 12843bededecSBarry Smith 12859371c9d4SSatish Balay PetscErrorCode MatShift_SeqSBAIJ(Mat Y, PetscScalar a) { 12867d68702bSBarry Smith Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)Y->data; 12877d68702bSBarry Smith 12887d68702bSBarry Smith PetscFunctionBegin; 1289*48a46eb9SPierre Jolivet if (!Y->preallocated || !aij->nz) PetscCall(MatSeqSBAIJSetPreallocation(Y, Y->rmap->bs, 1, NULL)); 12909566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(Y, a)); 12917d68702bSBarry Smith PetscFunctionReturn(0); 12927d68702bSBarry Smith } 12937d68702bSBarry Smith 129449b5e25fSSatish Balay /* -------------------------------------------------------------------*/ 12953964eb88SJed Brown static struct _MatOps MatOps_Values = {MatSetValues_SeqSBAIJ, 129649b5e25fSSatish Balay MatGetRow_SeqSBAIJ, 129749b5e25fSSatish Balay MatRestoreRow_SeqSBAIJ, 129849b5e25fSSatish Balay MatMult_SeqSBAIJ_N, 129997304618SKris Buschelman /* 4*/ MatMultAdd_SeqSBAIJ_N, 1300431c96f7SBarry Smith MatMult_SeqSBAIJ_N, /* transpose versions are same as non-transpose versions */ 1301e005ede5SBarry Smith MatMultAdd_SeqSBAIJ_N, 1302f4259b30SLisandro Dalcin NULL, 1303f4259b30SLisandro Dalcin NULL, 1304f4259b30SLisandro Dalcin NULL, 1305f4259b30SLisandro Dalcin /* 10*/ NULL, 1306f4259b30SLisandro Dalcin NULL, 1307c078aec8SLisandro Dalcin MatCholeskyFactor_SeqSBAIJ, 130841f059aeSBarry Smith MatSOR_SeqSBAIJ, 130949b5e25fSSatish Balay MatTranspose_SeqSBAIJ, 131097304618SKris Buschelman /* 15*/ MatGetInfo_SeqSBAIJ, 131149b5e25fSSatish Balay MatEqual_SeqSBAIJ, 131249b5e25fSSatish Balay MatGetDiagonal_SeqSBAIJ, 131349b5e25fSSatish Balay MatDiagonalScale_SeqSBAIJ, 131449b5e25fSSatish Balay MatNorm_SeqSBAIJ, 1315f4259b30SLisandro Dalcin /* 20*/ NULL, 131649b5e25fSSatish Balay MatAssemblyEnd_SeqSBAIJ, 131749b5e25fSSatish Balay MatSetOption_SeqSBAIJ, 131849b5e25fSSatish Balay MatZeroEntries_SeqSBAIJ, 1319f4259b30SLisandro Dalcin /* 24*/ NULL, 1320f4259b30SLisandro Dalcin NULL, 1321f4259b30SLisandro Dalcin NULL, 1322f4259b30SLisandro Dalcin NULL, 1323f4259b30SLisandro Dalcin NULL, 13244994cf47SJed Brown /* 29*/ MatSetUp_SeqSBAIJ, 1325f4259b30SLisandro Dalcin NULL, 1326f4259b30SLisandro Dalcin NULL, 1327f4259b30SLisandro Dalcin NULL, 1328f4259b30SLisandro Dalcin NULL, 1329d519adbfSMatthew Knepley /* 34*/ MatDuplicate_SeqSBAIJ, 1330f4259b30SLisandro Dalcin NULL, 1331f4259b30SLisandro Dalcin NULL, 1332f4259b30SLisandro Dalcin NULL, 1333c84f5b01SHong Zhang MatICCFactor_SeqSBAIJ, 1334d519adbfSMatthew Knepley /* 39*/ MatAXPY_SeqSBAIJ, 13357dae84e0SHong Zhang MatCreateSubMatrices_SeqSBAIJ, 133649b5e25fSSatish Balay MatIncreaseOverlap_SeqSBAIJ, 133749b5e25fSSatish Balay MatGetValues_SeqSBAIJ, 13383c896bc6SHong Zhang MatCopy_SeqSBAIJ, 1339f4259b30SLisandro Dalcin /* 44*/ NULL, 134049b5e25fSSatish Balay MatScale_SeqSBAIJ, 13417d68702bSBarry Smith MatShift_SeqSBAIJ, 1342f4259b30SLisandro Dalcin NULL, 13433bededecSBarry Smith MatZeroRowsColumns_SeqSBAIJ, 1344f4259b30SLisandro Dalcin /* 49*/ NULL, 134549b5e25fSSatish Balay MatGetRowIJ_SeqSBAIJ, 134649b5e25fSSatish Balay MatRestoreRowIJ_SeqSBAIJ, 1347f4259b30SLisandro Dalcin NULL, 1348f4259b30SLisandro Dalcin NULL, 1349f4259b30SLisandro Dalcin /* 54*/ NULL, 1350f4259b30SLisandro Dalcin NULL, 1351f4259b30SLisandro Dalcin NULL, 1352dc29a518SPierre Jolivet MatPermute_SeqSBAIJ, 135349b5e25fSSatish Balay MatSetValuesBlocked_SeqSBAIJ, 13547dae84e0SHong Zhang /* 59*/ MatCreateSubMatrix_SeqSBAIJ, 1355f4259b30SLisandro Dalcin NULL, 1356f4259b30SLisandro Dalcin NULL, 1357f4259b30SLisandro Dalcin NULL, 1358f4259b30SLisandro Dalcin NULL, 1359f4259b30SLisandro Dalcin /* 64*/ NULL, 1360f4259b30SLisandro Dalcin NULL, 1361f4259b30SLisandro Dalcin NULL, 1362f4259b30SLisandro Dalcin NULL, 1363f4259b30SLisandro Dalcin NULL, 1364d519adbfSMatthew Knepley /* 69*/ MatGetRowMaxAbs_SeqSBAIJ, 1365f4259b30SLisandro Dalcin NULL, 136628d58a37SPierre Jolivet MatConvert_MPISBAIJ_Basic, 1367f4259b30SLisandro Dalcin NULL, 1368f4259b30SLisandro Dalcin NULL, 1369f4259b30SLisandro Dalcin /* 74*/ NULL, 1370f4259b30SLisandro Dalcin NULL, 1371f4259b30SLisandro Dalcin NULL, 1372f4259b30SLisandro Dalcin NULL, 1373f4259b30SLisandro Dalcin NULL, 1374f4259b30SLisandro Dalcin /* 79*/ NULL, 1375f4259b30SLisandro Dalcin NULL, 1376f4259b30SLisandro Dalcin NULL, 137797304618SKris Buschelman MatGetInertia_SeqSBAIJ, 13785bba2384SShri Abhyankar MatLoad_SeqSBAIJ, 1379d519adbfSMatthew Knepley /* 84*/ MatIsSymmetric_SeqSBAIJ, 1380865e5f61SKris Buschelman MatIsHermitian_SeqSBAIJ, 1381efcf0fc3SBarry Smith MatIsStructurallySymmetric_SeqSBAIJ, 1382f4259b30SLisandro Dalcin NULL, 1383f4259b30SLisandro Dalcin NULL, 1384f4259b30SLisandro Dalcin /* 89*/ NULL, 1385f4259b30SLisandro Dalcin NULL, 1386f4259b30SLisandro Dalcin NULL, 1387f4259b30SLisandro Dalcin NULL, 1388f4259b30SLisandro Dalcin NULL, 1389f4259b30SLisandro Dalcin /* 94*/ NULL, 1390f4259b30SLisandro Dalcin NULL, 1391f4259b30SLisandro Dalcin NULL, 1392f4259b30SLisandro Dalcin NULL, 1393f4259b30SLisandro Dalcin NULL, 1394f4259b30SLisandro Dalcin /* 99*/ NULL, 1395f4259b30SLisandro Dalcin NULL, 1396f4259b30SLisandro Dalcin NULL, 13972726fb6dSPierre Jolivet MatConjugate_SeqSBAIJ, 1398f4259b30SLisandro Dalcin NULL, 1399f4259b30SLisandro Dalcin /*104*/ NULL, 140099cafbc1SBarry Smith MatRealPart_SeqSBAIJ, 1401f5edf698SHong Zhang MatImaginaryPart_SeqSBAIJ, 1402f5edf698SHong Zhang MatGetRowUpperTriangular_SeqSBAIJ, 14032af78befSBarry Smith MatRestoreRowUpperTriangular_SeqSBAIJ, 1404f4259b30SLisandro Dalcin /*109*/ NULL, 1405f4259b30SLisandro Dalcin NULL, 1406f4259b30SLisandro Dalcin NULL, 1407f4259b30SLisandro Dalcin NULL, 1408547795f9SHong Zhang MatMissingDiagonal_SeqSBAIJ, 1409f4259b30SLisandro Dalcin /*114*/ NULL, 1410f4259b30SLisandro Dalcin NULL, 1411f4259b30SLisandro Dalcin NULL, 1412f4259b30SLisandro Dalcin NULL, 1413f4259b30SLisandro Dalcin NULL, 1414f4259b30SLisandro Dalcin /*119*/ NULL, 1415f4259b30SLisandro Dalcin NULL, 1416f4259b30SLisandro Dalcin NULL, 1417f4259b30SLisandro Dalcin NULL, 1418f4259b30SLisandro Dalcin NULL, 1419f4259b30SLisandro Dalcin /*124*/ NULL, 1420f4259b30SLisandro Dalcin NULL, 1421f4259b30SLisandro Dalcin NULL, 1422f4259b30SLisandro Dalcin NULL, 1423f4259b30SLisandro Dalcin NULL, 1424f4259b30SLisandro Dalcin /*129*/ NULL, 1425f4259b30SLisandro Dalcin NULL, 1426f4259b30SLisandro Dalcin NULL, 1427f4259b30SLisandro Dalcin NULL, 1428f4259b30SLisandro Dalcin NULL, 1429f4259b30SLisandro Dalcin /*134*/ NULL, 1430f4259b30SLisandro Dalcin NULL, 1431f4259b30SLisandro Dalcin NULL, 1432f4259b30SLisandro Dalcin NULL, 1433f4259b30SLisandro Dalcin NULL, 143446533700Sstefano_zampini /*139*/ MatSetBlockSizes_Default, 1435f4259b30SLisandro Dalcin NULL, 1436f4259b30SLisandro Dalcin NULL, 1437f4259b30SLisandro Dalcin NULL, 1438f4259b30SLisandro Dalcin NULL, 1439d70f29a3SPierre Jolivet /*144*/ MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ, 1440d70f29a3SPierre Jolivet NULL, 1441d70f29a3SPierre Jolivet NULL, 144299a7f59eSMark Adams NULL, 144399a7f59eSMark Adams NULL, 14447fb60732SBarry Smith NULL, 14459371c9d4SSatish Balay /*150*/ NULL}; 1446be1d678aSKris Buschelman 14479371c9d4SSatish Balay PetscErrorCode MatStoreValues_SeqSBAIJ(Mat mat) { 14484afc71dfSHong Zhang Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data; 1449d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2; 145049b5e25fSSatish Balay 145149b5e25fSSatish Balay PetscFunctionBegin; 145208401ef6SPierre Jolivet PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 145349b5e25fSSatish Balay 145449b5e25fSSatish Balay /* allocate space for values if not already there */ 1455*48a46eb9SPierre Jolivet if (!aij->saved_values) PetscCall(PetscMalloc1(nz + 1, &aij->saved_values)); 145649b5e25fSSatish Balay 145749b5e25fSSatish Balay /* copy values over */ 14589566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz)); 145949b5e25fSSatish Balay PetscFunctionReturn(0); 146049b5e25fSSatish Balay } 146149b5e25fSSatish Balay 14629371c9d4SSatish Balay PetscErrorCode MatRetrieveValues_SeqSBAIJ(Mat mat) { 14634afc71dfSHong Zhang Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data; 1464d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2; 146549b5e25fSSatish Balay 146649b5e25fSSatish Balay PetscFunctionBegin; 146708401ef6SPierre Jolivet PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 146828b400f6SJacob Faibussowitsch PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first"); 146949b5e25fSSatish Balay 147049b5e25fSSatish Balay /* copy values over */ 14719566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz)); 147249b5e25fSSatish Balay PetscFunctionReturn(0); 147349b5e25fSSatish Balay } 147449b5e25fSSatish Balay 14759371c9d4SSatish Balay static PetscErrorCode MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B, PetscInt bs, PetscInt nz, PetscInt *nnz) { 1476c464158bSHong Zhang Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data; 14774dcd73b1SHong Zhang PetscInt i, mbs, nbs, bs2; 14782576faa2SJed Brown PetscBool skipallocation = PETSC_FALSE, flg = PETSC_FALSE, realalloc = PETSC_FALSE; 147949b5e25fSSatish Balay 148049b5e25fSSatish Balay PetscFunctionBegin; 14812576faa2SJed Brown if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 1482db4efbfdSBarry Smith 14839566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B, PetscAbs(bs))); 14849566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 14859566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 148608401ef6SPierre 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); 14879566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs)); 1488899cda47SBarry Smith 148921940c7eSstefano_zampini B->preallocated = PETSC_TRUE; 149021940c7eSstefano_zampini 1491d0f46423SBarry Smith mbs = B->rmap->N / bs; 14924dcd73b1SHong Zhang nbs = B->cmap->n / bs; 149349b5e25fSSatish Balay bs2 = bs * bs; 149449b5e25fSSatish Balay 1495aed4548fSBarry 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"); 149649b5e25fSSatish Balay 1497ab93d7beSBarry Smith if (nz == MAT_SKIP_ALLOCATION) { 1498ab93d7beSBarry Smith skipallocation = PETSC_TRUE; 1499ab93d7beSBarry Smith nz = 0; 1500ab93d7beSBarry Smith } 1501ab93d7beSBarry Smith 1502435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3; 150308401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz); 150449b5e25fSSatish Balay if (nnz) { 150549b5e25fSSatish Balay for (i = 0; i < mbs; i++) { 150608401ef6SPierre 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]); 150708401ef6SPierre 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); 150849b5e25fSSatish Balay } 150949b5e25fSSatish Balay } 151049b5e25fSSatish Balay 1511db4efbfdSBarry Smith B->ops->mult = MatMult_SeqSBAIJ_N; 1512db4efbfdSBarry Smith B->ops->multadd = MatMultAdd_SeqSBAIJ_N; 1513db4efbfdSBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_N; 1514db4efbfdSBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N; 151526fbe8dcSKarl Rupp 15169566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL)); 151749b5e25fSSatish Balay if (!flg) { 151849b5e25fSSatish Balay switch (bs) { 151949b5e25fSSatish Balay case 1: 152049b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_1; 152149b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_1; 1522431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_1; 1523431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1; 152449b5e25fSSatish Balay break; 152549b5e25fSSatish Balay case 2: 152649b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_2; 152749b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_2; 1528431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_2; 1529431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2; 153049b5e25fSSatish Balay break; 153149b5e25fSSatish Balay case 3: 153249b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_3; 153349b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_3; 1534431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_3; 1535431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3; 153649b5e25fSSatish Balay break; 153749b5e25fSSatish Balay case 4: 153849b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_4; 153949b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_4; 1540431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_4; 1541431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4; 154249b5e25fSSatish Balay break; 154349b5e25fSSatish Balay case 5: 154449b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_5; 154549b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_5; 1546431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_5; 1547431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5; 154849b5e25fSSatish Balay break; 154949b5e25fSSatish Balay case 6: 155049b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_6; 155149b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_6; 1552431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_6; 1553431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6; 155449b5e25fSSatish Balay break; 155549b5e25fSSatish Balay case 7: 1556de53e5efSHong Zhang B->ops->mult = MatMult_SeqSBAIJ_7; 155749b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_7; 1558431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_7; 1559431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7; 156049b5e25fSSatish Balay break; 156149b5e25fSSatish Balay } 156249b5e25fSSatish Balay } 156349b5e25fSSatish Balay 156449b5e25fSSatish Balay b->mbs = mbs; 15654dcd73b1SHong Zhang b->nbs = nbs; 1566ab93d7beSBarry Smith if (!skipallocation) { 15672ee49352SLisandro Dalcin if (!b->imax) { 15689566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(mbs, &b->imax, mbs, &b->ilen)); 156926fbe8dcSKarl Rupp 1570c760cd28SBarry Smith b->free_imax_ilen = PETSC_TRUE; 157126fbe8dcSKarl Rupp 15729566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, 2 * mbs * sizeof(PetscInt))); 15732ee49352SLisandro Dalcin } 157449b5e25fSSatish Balay if (!nnz) { 1575435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 157649b5e25fSSatish Balay else if (nz <= 0) nz = 1; 15775d2a9ed1SStefano Zampini nz = PetscMin(nbs, nz); 157826fbe8dcSKarl Rupp for (i = 0; i < mbs; i++) b->imax[i] = nz; 15799566063dSJacob Faibussowitsch PetscCall(PetscIntMultError(nz, mbs, &nz)); 158049b5e25fSSatish Balay } else { 1581c73702f5SBarry Smith PetscInt64 nz64 = 0; 15829371c9d4SSatish Balay for (i = 0; i < mbs; i++) { 15839371c9d4SSatish Balay b->imax[i] = nnz[i]; 15849371c9d4SSatish Balay nz64 += nnz[i]; 15859371c9d4SSatish Balay } 15869566063dSJacob Faibussowitsch PetscCall(PetscIntCast(nz64, &nz)); 158749b5e25fSSatish Balay } 15882ee49352SLisandro Dalcin /* b->ilen will count nonzeros in each block row so far. */ 158926fbe8dcSKarl Rupp for (i = 0; i < mbs; i++) b->ilen[i] = 0; 15906c6c5352SBarry Smith /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */ 159149b5e25fSSatish Balay 159249b5e25fSSatish Balay /* allocate the matrix space */ 15939566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i)); 15949566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(bs2 * nz, &b->a, nz, &b->j, B->rmap->N + 1, &b->i)); 15959566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, (B->rmap->N + 1) * sizeof(PetscInt) + nz * (bs2 * sizeof(PetscScalar) + sizeof(PetscInt)))); 15969566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(b->a, nz * bs2)); 15979566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(b->j, nz)); 159826fbe8dcSKarl Rupp 159949b5e25fSSatish Balay b->singlemalloc = PETSC_TRUE; 160049b5e25fSSatish Balay 160149b5e25fSSatish Balay /* pointer to beginning of each row */ 1602e60cf9a0SBarry Smith b->i[0] = 0; 160326fbe8dcSKarl Rupp for (i = 1; i < mbs + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1]; 160426fbe8dcSKarl Rupp 1605e6b907acSBarry Smith b->free_a = PETSC_TRUE; 1606e6b907acSBarry Smith b->free_ij = PETSC_TRUE; 1607e811da20SHong Zhang } else { 1608e6b907acSBarry Smith b->free_a = PETSC_FALSE; 1609e6b907acSBarry Smith b->free_ij = PETSC_FALSE; 1610ab93d7beSBarry Smith } 161149b5e25fSSatish Balay 161249b5e25fSSatish Balay b->bs2 = bs2; 16136c6c5352SBarry Smith b->nz = 0; 1614b32cb4a7SJed Brown b->maxnz = nz; 1615f4259b30SLisandro Dalcin b->inew = NULL; 1616f4259b30SLisandro Dalcin b->jnew = NULL; 1617f4259b30SLisandro Dalcin b->anew = NULL; 1618f4259b30SLisandro Dalcin b->a2anew = NULL; 16191a3463dfSHong Zhang b->permute = PETSC_FALSE; 1620cb7b82ddSBarry Smith 1621cb7b82ddSBarry Smith B->was_assembled = PETSC_FALSE; 1622cb7b82ddSBarry Smith B->assembled = PETSC_FALSE; 16239566063dSJacob Faibussowitsch if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 1624c464158bSHong Zhang PetscFunctionReturn(0); 1625c464158bSHong Zhang } 1626153ea458SHong Zhang 16279371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ(Mat B, PetscInt bs, const PetscInt ii[], const PetscInt jj[], const PetscScalar V[]) { 16280cd7f59aSBarry Smith PetscInt i, j, m, nz, anz, nz_max = 0, *nnz; 1629f4259b30SLisandro Dalcin PetscScalar *values = NULL; 163038f409ebSLisandro Dalcin PetscBool roworiented = ((Mat_SeqSBAIJ *)B->data)->roworiented; 16310cd7f59aSBarry Smith 163238f409ebSLisandro Dalcin PetscFunctionBegin; 163308401ef6SPierre Jolivet PetscCheck(bs >= 1, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_OUTOFRANGE, "Invalid block size specified, must be positive but it is %" PetscInt_FMT, bs); 16349566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(B->rmap, bs)); 16359566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(B->cmap, bs)); 16369566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 16379566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 16389566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs)); 163938f409ebSLisandro Dalcin m = B->rmap->n / bs; 164038f409ebSLisandro Dalcin 1641aed4548fSBarry Smith PetscCheck(!ii[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ii[0] must be 0 but it is %" PetscInt_FMT, ii[0]); 16429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nnz)); 164338f409ebSLisandro Dalcin for (i = 0; i < m; i++) { 164438f409ebSLisandro Dalcin nz = ii[i + 1] - ii[i]; 164508401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz); 16460cd7f59aSBarry Smith anz = 0; 16470cd7f59aSBarry Smith for (j = 0; j < nz; j++) { 16480cd7f59aSBarry Smith /* count only values on the diagonal or above */ 16490cd7f59aSBarry Smith if (jj[ii[i] + j] >= i) { 16500cd7f59aSBarry Smith anz = nz - j; 16510cd7f59aSBarry Smith break; 16520cd7f59aSBarry Smith } 16530cd7f59aSBarry Smith } 16540cd7f59aSBarry Smith nz_max = PetscMax(nz_max, anz); 16550cd7f59aSBarry Smith nnz[i] = anz; 165638f409ebSLisandro Dalcin } 16579566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz)); 16589566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 165938f409ebSLisandro Dalcin 166038f409ebSLisandro Dalcin values = (PetscScalar *)V; 1661*48a46eb9SPierre Jolivet if (!values) PetscCall(PetscCalloc1(bs * bs * nz_max, &values)); 166238f409ebSLisandro Dalcin for (i = 0; i < m; i++) { 166338f409ebSLisandro Dalcin PetscInt ncols = ii[i + 1] - ii[i]; 166438f409ebSLisandro Dalcin const PetscInt *icols = jj + ii[i]; 166538f409ebSLisandro Dalcin if (!roworiented || bs == 1) { 166638f409ebSLisandro Dalcin const PetscScalar *svals = values + (V ? (bs * bs * ii[i]) : 0); 16679566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, ncols, icols, svals, INSERT_VALUES)); 166838f409ebSLisandro Dalcin } else { 166938f409ebSLisandro Dalcin for (j = 0; j < ncols; j++) { 167038f409ebSLisandro Dalcin const PetscScalar *svals = values + (V ? (bs * bs * (ii[i] + j)) : 0); 16719566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, 1, &icols[j], svals, INSERT_VALUES)); 167238f409ebSLisandro Dalcin } 167338f409ebSLisandro Dalcin } 167438f409ebSLisandro Dalcin } 16759566063dSJacob Faibussowitsch if (!V) PetscCall(PetscFree(values)); 16769566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 16779566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 16789566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 167938f409ebSLisandro Dalcin PetscFunctionReturn(0); 168038f409ebSLisandro Dalcin } 168138f409ebSLisandro Dalcin 1682db4efbfdSBarry Smith /* 1683db4efbfdSBarry Smith This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization 1684db4efbfdSBarry Smith */ 16859371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetNumericFactorization_inplace(Mat B, PetscBool natural) { 1686ace3abfcSBarry Smith PetscBool flg = PETSC_FALSE; 1687db4efbfdSBarry Smith PetscInt bs = B->rmap->bs; 1688db4efbfdSBarry Smith 1689db4efbfdSBarry Smith PetscFunctionBegin; 16909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL)); 1691db4efbfdSBarry Smith if (flg) bs = 8; 1692db4efbfdSBarry Smith 1693db4efbfdSBarry Smith if (!natural) { 1694db4efbfdSBarry Smith switch (bs) { 16959371c9d4SSatish Balay case 1: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_inplace; break; 16969371c9d4SSatish Balay case 2: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2; break; 16979371c9d4SSatish Balay case 3: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3; break; 16989371c9d4SSatish Balay case 4: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4; break; 16999371c9d4SSatish Balay case 5: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5; break; 17009371c9d4SSatish Balay case 6: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6; break; 17019371c9d4SSatish Balay case 7: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7; break; 17029371c9d4SSatish Balay default: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N; break; 1703db4efbfdSBarry Smith } 1704db4efbfdSBarry Smith } else { 1705db4efbfdSBarry Smith switch (bs) { 17069371c9d4SSatish Balay case 1: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering_inplace; break; 17079371c9d4SSatish Balay case 2: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering; break; 17089371c9d4SSatish Balay case 3: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering; break; 17099371c9d4SSatish Balay case 4: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering; break; 17109371c9d4SSatish Balay case 5: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering; break; 17119371c9d4SSatish Balay case 6: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering; break; 17129371c9d4SSatish Balay case 7: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering; break; 17139371c9d4SSatish Balay default: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering; break; 1714db4efbfdSBarry Smith } 1715db4efbfdSBarry Smith } 1716db4efbfdSBarry Smith PetscFunctionReturn(0); 1717db4efbfdSBarry Smith } 1718db4efbfdSBarry Smith 1719cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType, MatReuse, Mat *); 1720cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType, MatReuse, Mat *); 17219371c9d4SSatish Balay static PetscErrorCode MatFactorGetSolverType_petsc(Mat A, MatSolverType *type) { 17224ac6704cSBarry Smith PetscFunctionBegin; 17234ac6704cSBarry Smith *type = MATSOLVERPETSC; 17244ac6704cSBarry Smith PetscFunctionReturn(0); 17254ac6704cSBarry Smith } 1726d769727bSBarry Smith 17279371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A, MatFactorType ftype, Mat *B) { 1728d0f46423SBarry Smith PetscInt n = A->rmap->n; 17295c9eb25fSBarry Smith 17305c9eb25fSBarry Smith PetscFunctionBegin; 17310e92d65fSHong Zhang #if defined(PETSC_USE_COMPLEX) 1732b94d7dedSBarry 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"); 17330e92d65fSHong Zhang #endif 1734eb1ec7c1SStefano Zampini 17359566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 17369566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, n, n, n, n)); 17375c9eb25fSBarry Smith if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) { 17389566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, MATSEQSBAIJ)); 17399566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(*B, A->rmap->bs, MAT_SKIP_ALLOCATION, NULL)); 174026fbe8dcSKarl Rupp 17417b056e98SHong Zhang (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ; 1742c6d0d4f0SHong Zhang (*B)->ops->iccfactorsymbolic = MatICCFactorSymbolic_SeqSBAIJ; 17439566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_CHOLESKY])); 17449566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_ICC])); 1745e32f2f54SBarry Smith } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Factor type not supported"); 174600c67f3bSHong Zhang 1747d5f3da31SBarry Smith (*B)->factortype = ftype; 1748f73b0415SBarry Smith (*B)->canuseordering = PETSC_TRUE; 17499566063dSJacob Faibussowitsch PetscCall(PetscFree((*B)->solvertype)); 17509566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*B)->solvertype)); 17519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)*B, "MatFactorGetSolverType_C", MatFactorGetSolverType_petsc)); 17525c9eb25fSBarry Smith PetscFunctionReturn(0); 17535c9eb25fSBarry Smith } 17545c9eb25fSBarry Smith 17558397e458SBarry Smith /*@C 17568397e458SBarry Smith MatSeqSBAIJGetArray - gives access to the array where the data for a MATSEQSBAIJ matrix is stored 17578397e458SBarry Smith 17588397e458SBarry Smith Not Collective 17598397e458SBarry Smith 17608397e458SBarry Smith Input Parameter: 17618397e458SBarry Smith . mat - a MATSEQSBAIJ matrix 17628397e458SBarry Smith 17638397e458SBarry Smith Output Parameter: 17648397e458SBarry Smith . array - pointer to the data 17658397e458SBarry Smith 17668397e458SBarry Smith Level: intermediate 17678397e458SBarry Smith 1768db781477SPatrick Sanan .seealso: `MatSeqSBAIJRestoreArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()` 17698397e458SBarry Smith @*/ 17709371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJGetArray(Mat A, PetscScalar **array) { 17718397e458SBarry Smith PetscFunctionBegin; 1772cac4c232SBarry Smith PetscUseMethod(A, "MatSeqSBAIJGetArray_C", (Mat, PetscScalar **), (A, array)); 17738397e458SBarry Smith PetscFunctionReturn(0); 17748397e458SBarry Smith } 17758397e458SBarry Smith 17768397e458SBarry Smith /*@C 17778397e458SBarry Smith MatSeqSBAIJRestoreArray - returns access to the array where the data for a MATSEQSBAIJ matrix is stored obtained by MatSeqSBAIJGetArray() 17788397e458SBarry Smith 17798397e458SBarry Smith Not Collective 17808397e458SBarry Smith 17818397e458SBarry Smith Input Parameters: 1782a2b725a8SWilliam Gropp + mat - a MATSEQSBAIJ matrix 1783a2b725a8SWilliam Gropp - array - pointer to the data 17848397e458SBarry Smith 17858397e458SBarry Smith Level: intermediate 17868397e458SBarry Smith 1787db781477SPatrick Sanan .seealso: `MatSeqSBAIJGetArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()` 17888397e458SBarry Smith @*/ 17899371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJRestoreArray(Mat A, PetscScalar **array) { 17908397e458SBarry Smith PetscFunctionBegin; 1791cac4c232SBarry Smith PetscUseMethod(A, "MatSeqSBAIJRestoreArray_C", (Mat, PetscScalar **), (A, array)); 17928397e458SBarry Smith PetscFunctionReturn(0); 17938397e458SBarry Smith } 17948397e458SBarry Smith 17950bad9183SKris Buschelman /*MC 1796fafad747SKris Buschelman MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices, 17970bad9183SKris Buschelman based on block compressed sparse row format. Only the upper triangular portion of the matrix is stored. 17980bad9183SKris Buschelman 1799828413b8SBarry Smith For complex numbers by default this matrix is symmetric, NOT Hermitian symmetric. To make it Hermitian symmetric you 1800eb1ec7c1SStefano Zampini can call MatSetOption(Mat, MAT_HERMITIAN). 1801828413b8SBarry Smith 18020bad9183SKris Buschelman Options Database Keys: 18030bad9183SKris Buschelman . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to MatSetFromOptions() 18040bad9183SKris Buschelman 180595452b02SPatrick Sanan Notes: 180695452b02SPatrick Sanan By default if you insert values into the lower triangular part of the matrix they are simply ignored (since they are not 180771dad5bbSBarry 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 180871dad5bbSBarry 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. 180971dad5bbSBarry Smith 1810476417e5SBarry Smith The number of rows in the matrix must be less than or equal to the number of columns 181171dad5bbSBarry Smith 18120bad9183SKris Buschelman Level: beginner 18130bad9183SKris Buschelman 1814db781477SPatrick Sanan .seealso: `MatCreateSeqSBAIJ()`, `MatType`, `MATMPISBAIJ` 18150bad9183SKris Buschelman M*/ 18169371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_SeqSBAIJ(Mat B) { 1817a23d5eceSKris Buschelman Mat_SeqSBAIJ *b; 181813f74950SBarry Smith PetscMPIInt size; 1819ace3abfcSBarry Smith PetscBool no_unroll = PETSC_FALSE, no_inode = PETSC_FALSE; 1820a23d5eceSKris Buschelman 1821a23d5eceSKris Buschelman PetscFunctionBegin; 18229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size)); 182308401ef6SPierre Jolivet PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1"); 1824a23d5eceSKris Buschelman 18259566063dSJacob Faibussowitsch PetscCall(PetscNewLog(B, &b)); 1826a23d5eceSKris Buschelman B->data = (void *)b; 18279566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(B->ops, &MatOps_Values, sizeof(struct _MatOps))); 182826fbe8dcSKarl Rupp 1829a23d5eceSKris Buschelman B->ops->destroy = MatDestroy_SeqSBAIJ; 1830a23d5eceSKris Buschelman B->ops->view = MatView_SeqSBAIJ; 1831f4259b30SLisandro Dalcin b->row = NULL; 1832f4259b30SLisandro Dalcin b->icol = NULL; 1833a23d5eceSKris Buschelman b->reallocs = 0; 1834f4259b30SLisandro Dalcin b->saved_values = NULL; 18350def2e27SBarry Smith b->inode.limit = 5; 18360def2e27SBarry Smith b->inode.max_limit = 5; 1837a23d5eceSKris Buschelman 1838a23d5eceSKris Buschelman b->roworiented = PETSC_TRUE; 1839a23d5eceSKris Buschelman b->nonew = 0; 1840f4259b30SLisandro Dalcin b->diag = NULL; 1841f4259b30SLisandro Dalcin b->solve_work = NULL; 1842f4259b30SLisandro Dalcin b->mult_work = NULL; 1843f4259b30SLisandro Dalcin B->spptr = NULL; 1844f2cbd3d5SJed Brown B->info.nz_unneeded = (PetscReal)b->maxnz * b->bs2; 1845a9817697SBarry Smith b->keepnonzeropattern = PETSC_FALSE; 1846a23d5eceSKris Buschelman 1847f4259b30SLisandro Dalcin b->inew = NULL; 1848f4259b30SLisandro Dalcin b->jnew = NULL; 1849f4259b30SLisandro Dalcin b->anew = NULL; 1850f4259b30SLisandro Dalcin b->a2anew = NULL; 1851a23d5eceSKris Buschelman b->permute = PETSC_FALSE; 1852a23d5eceSKris Buschelman 185371dad5bbSBarry Smith b->ignore_ltriangular = PETSC_TRUE; 185426fbe8dcSKarl Rupp 18559566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_ignore_lower_triangular", &b->ignore_ltriangular, NULL)); 1856941593c8SHong Zhang 1857f5edf698SHong Zhang b->getrow_utriangular = PETSC_FALSE; 185826fbe8dcSKarl Rupp 18599566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_getrow_uppertriangular", &b->getrow_utriangular, NULL)); 1860f5edf698SHong Zhang 18619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJGetArray_C", MatSeqSBAIJGetArray_SeqSBAIJ)); 18629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJRestoreArray_C", MatSeqSBAIJRestoreArray_SeqSBAIJ)); 18639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqSBAIJ)); 18649566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqSBAIJ)); 18659566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetColumnIndices_C", MatSeqSBAIJSetColumnIndices_SeqSBAIJ)); 18669566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqaij_C", MatConvert_SeqSBAIJ_SeqAIJ)); 18679566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqbaij_C", MatConvert_SeqSBAIJ_SeqBAIJ)); 18689566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocation_C", MatSeqSBAIJSetPreallocation_SeqSBAIJ)); 18699566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocationCSR_C", MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ)); 18706214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 18719566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_elemental_C", MatConvert_SeqSBAIJ_Elemental)); 18726214f412SHong Zhang #endif 1873d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 18749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_scalapack_C", MatConvert_SBAIJ_ScaLAPACK)); 1875d24d4204SJose E. Roman #endif 187623ce1328SBarry Smith 1877b94d7dedSBarry Smith B->symmetry_eternal = PETSC_TRUE; 1878b94d7dedSBarry Smith B->structural_symmetry_eternal = PETSC_TRUE; 1879b94d7dedSBarry Smith B->symmetric = PETSC_BOOL3_TRUE; 1880b94d7dedSBarry Smith B->structurally_symmetric = PETSC_BOOL3_TRUE; 1881eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 1882b94d7dedSBarry Smith B->hermitian = PETSC_BOOL3_FALSE; 1883eb1ec7c1SStefano Zampini #else 1884b94d7dedSBarry Smith B->hermitian = PETSC_BOOL3_TRUE; 1885eb1ec7c1SStefano Zampini #endif 188613647f61SHong Zhang 18879566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQSBAIJ)); 18880def2e27SBarry Smith 1889d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)B), ((PetscObject)B)->prefix, "Options for SEQSBAIJ matrix", "Mat"); 18909566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-mat_no_unroll", "Do not optimize for inodes (slower)", NULL, no_unroll, &no_unroll, NULL)); 1891*48a46eb9SPierre Jolivet if (no_unroll) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_unroll\n")); 18929566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-mat_no_inode", "Do not optimize for inodes (slower)", NULL, no_inode, &no_inode, NULL)); 18939566063dSJacob Faibussowitsch if (no_inode) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_inode\n")); 18949566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-mat_inode_limit", "Do not use inodes larger then this value", NULL, b->inode.limit, &b->inode.limit, NULL)); 1895d0609cedSBarry Smith PetscOptionsEnd(); 1896ace3abfcSBarry Smith b->inode.use = (PetscBool)(!(no_unroll || no_inode)); 18970def2e27SBarry Smith if (b->inode.limit > b->inode.max_limit) b->inode.limit = b->inode.max_limit; 1898a23d5eceSKris Buschelman PetscFunctionReturn(0); 1899a23d5eceSKris Buschelman } 1900a23d5eceSKris Buschelman 1901a23d5eceSKris Buschelman /*@C 1902a23d5eceSKris Buschelman MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block 1903a23d5eceSKris Buschelman compressed row) format. For good matrix assembly performance the 1904a23d5eceSKris Buschelman user should preallocate the matrix storage by setting the parameter nz 1905a23d5eceSKris Buschelman (or the array nnz). By setting these parameters accurately, performance 1906a23d5eceSKris Buschelman during matrix assembly can be increased by more than a factor of 50. 1907a23d5eceSKris Buschelman 1908a23d5eceSKris Buschelman Collective on Mat 1909a23d5eceSKris Buschelman 1910a23d5eceSKris Buschelman Input Parameters: 19111c4f3114SJed Brown + B - the symmetric matrix 1912bb7ae925SBarry 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 1913bb7ae925SBarry Smith blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with MatCreateVecs() 1914a23d5eceSKris Buschelman . nz - number of block nonzeros per block row (same for all rows) 1915a23d5eceSKris Buschelman - nnz - array containing the number of block nonzeros in the upper triangular plus 19160298fd71SBarry Smith diagonal portion of each block (possibly different for each block row) or NULL 1917a23d5eceSKris Buschelman 1918a23d5eceSKris Buschelman Options Database Keys: 1919a2b725a8SWilliam Gropp + -mat_no_unroll - uses code that does not unroll the loops in the 1920a23d5eceSKris Buschelman block calculations (much slower) 1921a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use (only works if a negative bs is passed in 1922a23d5eceSKris Buschelman 1923a23d5eceSKris Buschelman Level: intermediate 1924a23d5eceSKris Buschelman 1925a23d5eceSKris Buschelman Notes: 1926a23d5eceSKris Buschelman Specify the preallocated storage with either nz or nnz (not both). 19270298fd71SBarry Smith Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 1928a7f22e61SSatish Balay allocation. See Users-Manual: ch_mat for details. 1929a23d5eceSKris Buschelman 1930aa95bbe8SBarry Smith You can call MatGetInfo() to get information on how effective the preallocation was; 1931aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 1932aa95bbe8SBarry Smith You can also run with the option -info and look for messages with the string 1933aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 1934aa95bbe8SBarry Smith 193549a6f317SBarry Smith If the nnz parameter is given then the nz parameter is ignored 193649a6f317SBarry Smith 1937db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()` 1938a23d5eceSKris Buschelman @*/ 19399371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetPreallocation(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[]) { 1940a23d5eceSKris Buschelman PetscFunctionBegin; 19416ba663aaSJed Brown PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 19426ba663aaSJed Brown PetscValidType(B, 1); 19436ba663aaSJed Brown PetscValidLogicalCollectiveInt(B, bs, 2); 1944cac4c232SBarry Smith PetscTryMethod(B, "MatSeqSBAIJSetPreallocation_C", (Mat, PetscInt, PetscInt, const PetscInt[]), (B, bs, nz, nnz)); 1945a23d5eceSKris Buschelman PetscFunctionReturn(0); 1946a23d5eceSKris Buschelman } 194749b5e25fSSatish Balay 194838f409ebSLisandro Dalcin /*@C 1949664954b6SBarry Smith MatSeqSBAIJSetPreallocationCSR - Creates a sparse parallel matrix in SBAIJ format using the given nonzero structure and (optional) numerical values 195038f409ebSLisandro Dalcin 195138f409ebSLisandro Dalcin Input Parameters: 19521c4f3114SJed Brown + B - the matrix 1953eab78319SHong Zhang . bs - size of block, the blocks are ALWAYS square. 195438f409ebSLisandro Dalcin . i - the indices into j for the start of each local row (starts with zero) 195538f409ebSLisandro Dalcin . j - the column indices for each local row (starts with zero) these must be sorted for each row 195638f409ebSLisandro Dalcin - v - optional values in the matrix 195738f409ebSLisandro Dalcin 1958664954b6SBarry Smith Level: advanced 195938f409ebSLisandro Dalcin 196038f409ebSLisandro Dalcin Notes: 196138f409ebSLisandro Dalcin The order of the entries in values is specified by the MatOption MAT_ROW_ORIENTED. For example, C programs 196238f409ebSLisandro Dalcin may want to use the default MAT_ROW_ORIENTED=PETSC_TRUE and use an array v[nnz][bs][bs] where the second index is 196338f409ebSLisandro Dalcin over rows within a block and the last index is over columns within a block row. Fortran programs will likely set 196438f409ebSLisandro Dalcin MAT_ROW_ORIENTED=PETSC_FALSE and use a Fortran array v(bs,bs,nnz) in which the first index is over rows within a 196538f409ebSLisandro Dalcin block column and the second index is over columns within a block. 196638f409ebSLisandro Dalcin 196750c5228eSBarry Smith Any entries below the diagonal are ignored 19680cd7f59aSBarry Smith 19690cd7f59aSBarry Smith Though this routine has Preallocation() in the name it also sets the exact nonzero locations of the matrix entries 19700cd7f59aSBarry Smith and usually the numerical values as well 1971664954b6SBarry Smith 1972db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqSBAIJ()`, `MatSetValuesBlocked()`, `MatSeqSBAIJSetPreallocation()`, `MATSEQSBAIJ` 197338f409ebSLisandro Dalcin @*/ 19749371c9d4SSatish Balay PetscErrorCode MatSeqSBAIJSetPreallocationCSR(Mat B, PetscInt bs, const PetscInt i[], const PetscInt j[], const PetscScalar v[]) { 197538f409ebSLisandro Dalcin PetscFunctionBegin; 197638f409ebSLisandro Dalcin PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 197738f409ebSLisandro Dalcin PetscValidType(B, 1); 197838f409ebSLisandro Dalcin PetscValidLogicalCollectiveInt(B, bs, 2); 1979cac4c232SBarry Smith PetscTryMethod(B, "MatSeqSBAIJSetPreallocationCSR_C", (Mat, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, bs, i, j, v)); 198038f409ebSLisandro Dalcin PetscFunctionReturn(0); 198138f409ebSLisandro Dalcin } 198238f409ebSLisandro Dalcin 1983c464158bSHong Zhang /*@C 1984c464158bSHong Zhang MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in block AIJ (block 1985c464158bSHong Zhang compressed row) format. For good matrix assembly performance the 1986c464158bSHong Zhang user should preallocate the matrix storage by setting the parameter nz 1987c464158bSHong Zhang (or the array nnz). By setting these parameters accurately, performance 1988c464158bSHong Zhang during matrix assembly can be increased by more than a factor of 50. 198949b5e25fSSatish Balay 1990d083f849SBarry Smith Collective 1991c464158bSHong Zhang 1992c464158bSHong Zhang Input Parameters: 1993c464158bSHong Zhang + comm - MPI communicator, set to PETSC_COMM_SELF 1994bb7ae925SBarry 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 1995bb7ae925SBarry Smith blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with MatCreateVecs() 1996c464158bSHong Zhang . m - number of rows, or number of columns 1997c464158bSHong Zhang . nz - number of block nonzeros per block row (same for all rows) 1998744e8345SSatish Balay - nnz - array containing the number of block nonzeros in the upper triangular plus 19990298fd71SBarry Smith diagonal portion of each block (possibly different for each block row) or NULL 2000c464158bSHong Zhang 2001c464158bSHong Zhang Output Parameter: 2002c464158bSHong Zhang . A - the symmetric matrix 2003c464158bSHong Zhang 2004c464158bSHong Zhang Options Database Keys: 2005a2b725a8SWilliam Gropp + -mat_no_unroll - uses code that does not unroll the loops in the 2006c464158bSHong Zhang block calculations (much slower) 2007a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use 2008c464158bSHong Zhang 2009c464158bSHong Zhang Level: intermediate 2010c464158bSHong Zhang 2011175b88e8SBarry Smith It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 2012f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly. 2013175b88e8SBarry Smith [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 2014175b88e8SBarry Smith 2015c464158bSHong Zhang Notes: 20166d6d819aSHong Zhang The number of rows and columns must be divisible by blocksize. 20176d6d819aSHong Zhang This matrix type does not support complex Hermitian operation. 2018c464158bSHong Zhang 2019c464158bSHong Zhang Specify the preallocated storage with either nz or nnz (not both). 20200298fd71SBarry Smith Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 2021a7f22e61SSatish Balay allocation. See Users-Manual: ch_mat for details. 2022c464158bSHong Zhang 202349a6f317SBarry Smith If the nnz parameter is given then the nz parameter is ignored 202449a6f317SBarry Smith 2025db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()` 2026c464158bSHong Zhang @*/ 20279371c9d4SSatish Balay PetscErrorCode MatCreateSeqSBAIJ(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A) { 2028c464158bSHong Zhang PetscFunctionBegin; 20299566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 20309566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, m, n)); 20319566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATSEQSBAIJ)); 20329566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(*A, bs, nz, (PetscInt *)nnz)); 203349b5e25fSSatish Balay PetscFunctionReturn(0); 203449b5e25fSSatish Balay } 203549b5e25fSSatish Balay 20369371c9d4SSatish Balay PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B) { 203749b5e25fSSatish Balay Mat C; 203849b5e25fSSatish Balay Mat_SeqSBAIJ *c, *a = (Mat_SeqSBAIJ *)A->data; 2039b40805acSSatish Balay PetscInt i, mbs = a->mbs, nz = a->nz, bs2 = a->bs2; 204049b5e25fSSatish Balay 204149b5e25fSSatish Balay PetscFunctionBegin; 204208401ef6SPierre Jolivet PetscCheck(a->i[mbs] == nz, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupt matrix"); 204349b5e25fSSatish Balay 2044f4259b30SLisandro Dalcin *B = NULL; 20459566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 20469566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, A->rmap->N, A->cmap->n, A->rmap->N, A->cmap->n)); 20479566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 20489566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATSEQSBAIJ)); 2049692f9cbeSHong Zhang c = (Mat_SeqSBAIJ *)C->data; 2050692f9cbeSHong Zhang 2051273d9f13SBarry Smith C->preallocated = PETSC_TRUE; 2052d5f3da31SBarry Smith C->factortype = A->factortype; 2053f4259b30SLisandro Dalcin c->row = NULL; 2054f4259b30SLisandro Dalcin c->icol = NULL; 2055f4259b30SLisandro Dalcin c->saved_values = NULL; 2056a9817697SBarry Smith c->keepnonzeropattern = a->keepnonzeropattern; 205749b5e25fSSatish Balay C->assembled = PETSC_TRUE; 205849b5e25fSSatish Balay 20599566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->rmap, &C->rmap)); 20609566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->cmap, &C->cmap)); 206149b5e25fSSatish Balay c->bs2 = a->bs2; 206249b5e25fSSatish Balay c->mbs = a->mbs; 206349b5e25fSSatish Balay c->nbs = a->nbs; 206449b5e25fSSatish Balay 2065c760cd28SBarry Smith if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { 2066c760cd28SBarry Smith c->imax = a->imax; 2067c760cd28SBarry Smith c->ilen = a->ilen; 2068c760cd28SBarry Smith c->free_imax_ilen = PETSC_FALSE; 2069c760cd28SBarry Smith } else { 20709566063dSJacob Faibussowitsch PetscCall(PetscMalloc2((mbs + 1), &c->imax, (mbs + 1), &c->ilen)); 20719566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, 2 * (mbs + 1) * sizeof(PetscInt))); 207249b5e25fSSatish Balay for (i = 0; i < mbs; i++) { 207349b5e25fSSatish Balay c->imax[i] = a->imax[i]; 207449b5e25fSSatish Balay c->ilen[i] = a->ilen[i]; 207549b5e25fSSatish Balay } 2076c760cd28SBarry Smith c->free_imax_ilen = PETSC_TRUE; 2077c760cd28SBarry Smith } 207849b5e25fSSatish Balay 207949b5e25fSSatish Balay /* allocate the matrix space */ 20804da8f245SBarry Smith if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { 20819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bs2 * nz, &c->a)); 20829566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, nz * bs2 * sizeof(MatScalar))); 208344e1c64aSLisandro Dalcin c->i = a->i; 208444e1c64aSLisandro Dalcin c->j = a->j; 20854da8f245SBarry Smith c->singlemalloc = PETSC_FALSE; 208644e1c64aSLisandro Dalcin c->free_a = PETSC_TRUE; 20874da8f245SBarry Smith c->free_ij = PETSC_FALSE; 20884da8f245SBarry Smith c->parent = A; 20899566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 20909566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 20919566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 20924da8f245SBarry Smith } else { 20939566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(bs2 * nz, &c->a, nz, &c->j, mbs + 1, &c->i)); 20949566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->i, a->i, mbs + 1)); 20959566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, (mbs + 1) * sizeof(PetscInt) + nz * (bs2 * sizeof(MatScalar) + sizeof(PetscInt)))); 20964da8f245SBarry Smith c->singlemalloc = PETSC_TRUE; 209744e1c64aSLisandro Dalcin c->free_a = PETSC_TRUE; 20984da8f245SBarry Smith c->free_ij = PETSC_TRUE; 20994da8f245SBarry Smith } 210049b5e25fSSatish Balay if (mbs > 0) { 2101*48a46eb9SPierre Jolivet if (cpvalues != MAT_SHARE_NONZERO_PATTERN) PetscCall(PetscArraycpy(c->j, a->j, nz)); 210249b5e25fSSatish Balay if (cpvalues == MAT_COPY_VALUES) { 21039566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->a, a->a, bs2 * nz)); 210449b5e25fSSatish Balay } else { 21059566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->a, bs2 * nz)); 210649b5e25fSSatish Balay } 2107a1c3900fSBarry Smith if (a->jshort) { 210844e1c64aSLisandro Dalcin /* cannot share jshort, it is reallocated in MatAssemblyEnd_SeqSBAIJ() */ 210944e1c64aSLisandro Dalcin /* if the parent matrix is reassembled, this child matrix will never notice */ 21109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &c->jshort)); 21119566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, nz * sizeof(unsigned short))); 21129566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->jshort, a->jshort, nz)); 211326fbe8dcSKarl Rupp 21144da8f245SBarry Smith c->free_jshort = PETSC_TRUE; 21154da8f245SBarry Smith } 2116a1c3900fSBarry Smith } 211749b5e25fSSatish Balay 211849b5e25fSSatish Balay c->roworiented = a->roworiented; 211949b5e25fSSatish Balay c->nonew = a->nonew; 212049b5e25fSSatish Balay 212149b5e25fSSatish Balay if (a->diag) { 2122c760cd28SBarry Smith if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { 2123c760cd28SBarry Smith c->diag = a->diag; 2124c760cd28SBarry Smith c->free_diag = PETSC_FALSE; 2125c760cd28SBarry Smith } else { 21269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mbs, &c->diag)); 21279566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, mbs * sizeof(PetscInt))); 212826fbe8dcSKarl Rupp for (i = 0; i < mbs; i++) c->diag[i] = a->diag[i]; 2129c760cd28SBarry Smith c->free_diag = PETSC_TRUE; 2130c760cd28SBarry Smith } 213144e1c64aSLisandro Dalcin } 21326c6c5352SBarry Smith c->nz = a->nz; 2133f2cbd3d5SJed Brown c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 2134f4259b30SLisandro Dalcin c->solve_work = NULL; 2135f4259b30SLisandro Dalcin c->mult_work = NULL; 213626fbe8dcSKarl Rupp 213749b5e25fSSatish Balay *B = C; 21389566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist)); 213949b5e25fSSatish Balay PetscFunctionReturn(0); 214049b5e25fSSatish Balay } 214149b5e25fSSatish Balay 2142618cc2edSLisandro Dalcin /* Used for both SeqBAIJ and SeqSBAIJ matrices */ 2143618cc2edSLisandro Dalcin #define MatLoad_SeqSBAIJ_Binary MatLoad_SeqBAIJ_Binary 2144618cc2edSLisandro Dalcin 21459371c9d4SSatish Balay PetscErrorCode MatLoad_SeqSBAIJ(Mat mat, PetscViewer viewer) { 21467f489da9SVaclav Hapla PetscBool isbinary; 21472f480046SShri Abhyankar 21482f480046SShri Abhyankar PetscFunctionBegin; 21499566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 215028b400f6SJacob 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); 21519566063dSJacob Faibussowitsch PetscCall(MatLoad_SeqSBAIJ_Binary(mat, viewer)); 21522f480046SShri Abhyankar PetscFunctionReturn(0); 21532f480046SShri Abhyankar } 21542f480046SShri Abhyankar 2155c75a6043SHong Zhang /*@ 2156c75a6043SHong Zhang MatCreateSeqSBAIJWithArrays - Creates an sequential SBAIJ matrix using matrix elements 2157c75a6043SHong Zhang (upper triangular entries in CSR format) provided by the user. 2158c75a6043SHong Zhang 2159d083f849SBarry Smith Collective 2160c75a6043SHong Zhang 2161c75a6043SHong Zhang Input Parameters: 2162c75a6043SHong Zhang + comm - must be an MPI communicator of size 1 2163c75a6043SHong Zhang . bs - size of block 2164c75a6043SHong Zhang . m - number of rows 2165c75a6043SHong Zhang . n - number of columns 2166483a2f95SBarry 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 2167c75a6043SHong Zhang . j - column indices 2168c75a6043SHong Zhang - a - matrix values 2169c75a6043SHong Zhang 2170c75a6043SHong Zhang Output Parameter: 2171c75a6043SHong Zhang . mat - the matrix 2172c75a6043SHong Zhang 2173dfb205c3SBarry Smith Level: advanced 2174c75a6043SHong Zhang 2175c75a6043SHong Zhang Notes: 2176c75a6043SHong Zhang The i, j, and a arrays are not copied by this routine, the user must free these arrays 2177c75a6043SHong Zhang once the matrix is destroyed 2178c75a6043SHong Zhang 2179c75a6043SHong Zhang You cannot set new nonzero locations into this matrix, that will generate an error. 2180c75a6043SHong Zhang 2181c75a6043SHong Zhang The i and j indices are 0 based 2182c75a6043SHong Zhang 2183dfb205c3SBarry Smith When block size is greater than 1 the matrix values must be stored using the SBAIJ storage format (see the SBAIJ code to determine this). For block size of 1 2184dfb205c3SBarry Smith it is the regular CSR format excluding the lower triangular elements. 2185dfb205c3SBarry Smith 2186db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSBAIJ()`, `MatCreateSeqSBAIJ()` 2187c75a6043SHong Zhang 2188c75a6043SHong Zhang @*/ 21899371c9d4SSatish Balay PetscErrorCode MatCreateSeqSBAIJWithArrays(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat) { 2190c75a6043SHong Zhang PetscInt ii; 2191c75a6043SHong Zhang Mat_SeqSBAIJ *sbaij; 2192c75a6043SHong Zhang 2193c75a6043SHong Zhang PetscFunctionBegin; 219408401ef6SPierre Jolivet PetscCheck(bs == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "block size %" PetscInt_FMT " > 1 is not supported yet", bs); 2195aed4548fSBarry Smith PetscCheck(m == 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0"); 2196c75a6043SHong Zhang 21979566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 21989566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 21999566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQSBAIJ)); 22009566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(*mat, bs, MAT_SKIP_ALLOCATION, NULL)); 2201c75a6043SHong Zhang sbaij = (Mat_SeqSBAIJ *)(*mat)->data; 22029566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(m, &sbaij->imax, m, &sbaij->ilen)); 22039566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)*mat, 2 * m * sizeof(PetscInt))); 2204c75a6043SHong Zhang 2205c75a6043SHong Zhang sbaij->i = i; 2206c75a6043SHong Zhang sbaij->j = j; 2207c75a6043SHong Zhang sbaij->a = a; 220826fbe8dcSKarl Rupp 2209c75a6043SHong Zhang sbaij->singlemalloc = PETSC_FALSE; 2210c75a6043SHong Zhang sbaij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 2211e6b907acSBarry Smith sbaij->free_a = PETSC_FALSE; 2212e6b907acSBarry Smith sbaij->free_ij = PETSC_FALSE; 2213ddf7884eSMatthew Knepley sbaij->free_imax_ilen = PETSC_TRUE; 2214c75a6043SHong Zhang 2215c75a6043SHong Zhang for (ii = 0; ii < m; ii++) { 2216c75a6043SHong Zhang sbaij->ilen[ii] = sbaij->imax[ii] = i[ii + 1] - i[ii]; 22176bdcaf15SBarry 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]); 2218c75a6043SHong Zhang } 221976bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 2220c75a6043SHong Zhang for (ii = 0; ii < sbaij->i[m]; ii++) { 22216bdcaf15SBarry 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]); 22226bdcaf15SBarry 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]); 2223c75a6043SHong Zhang } 222476bd3646SJed Brown } 2225c75a6043SHong Zhang 22269566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 22279566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 2228c75a6043SHong Zhang PetscFunctionReturn(0); 2229c75a6043SHong Zhang } 2230d06b337dSHong Zhang 22319371c9d4SSatish Balay PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat) { 223259f5e6ceSHong Zhang PetscFunctionBegin; 22339566063dSJacob Faibussowitsch PetscCall(MatCreateMPIMatConcatenateSeqMat_MPISBAIJ(comm, inmat, n, scall, outmat)); 223459f5e6ceSHong Zhang PetscFunctionReturn(0); 223559f5e6ceSHong Zhang } 2236