149b5e25fSSatish Balay /* 2a1373b80SHong Zhang Defines the basic matrix operations for the SBAIJ (compressed row) 349b5e25fSSatish Balay matrix storage format. 449b5e25fSSatish Balay */ 5c6db04a5SJed Brown #include <../src/mat/impls/baij/seq/baij.h> /*I "petscmat.h" I*/ 6c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/sbaij.h> 7c6db04a5SJed Brown #include <petscblaslapack.h> 849b5e25fSSatish Balay 9c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/relax.h> 1070dcbbb9SBarry Smith #define USESHORT 11c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/relax.h> 1270dcbbb9SBarry Smith 1326cec326SBarry Smith /* defines MatSetValues_Seq_Hash(), MatAssemblyEnd_Seq_Hash(), MatSetUp_Seq_Hash() */ 1426cec326SBarry Smith #define TYPE SBAIJ 1526cec326SBarry Smith #define TYPE_SBAIJ 1626cec326SBarry Smith #define TYPE_BS 1726cec326SBarry Smith #include "../src/mat/impls/aij/seq/seqhashmatsetvalues.h" 1826cec326SBarry Smith #undef TYPE_BS 1926cec326SBarry Smith #define TYPE_BS _BS 2026cec326SBarry Smith #define TYPE_BS_ON 2126cec326SBarry Smith #include "../src/mat/impls/aij/seq/seqhashmatsetvalues.h" 2226cec326SBarry Smith #undef TYPE_BS 2326cec326SBarry Smith #undef TYPE_SBAIJ 2426cec326SBarry Smith #include "../src/mat/impls/aij/seq/seqhashmat.h" 2526cec326SBarry Smith #undef TYPE 2626cec326SBarry Smith #undef TYPE_BS_ON 2726cec326SBarry Smith 286214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 29cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_Elemental(Mat, MatType, MatReuse, Mat *); 306214f412SHong Zhang #endif 31d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 32d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_SBAIJ_ScaLAPACK(Mat, MatType, MatReuse, Mat *); 33d24d4204SJose E. Roman #endif 3428d58a37SPierre Jolivet PETSC_INTERN PetscErrorCode MatConvert_MPISBAIJ_Basic(Mat, MatType, MatReuse, Mat *); 35b5b17502SBarry Smith 3649b5e25fSSatish Balay /* 3749b5e25fSSatish Balay Checks for missing diagonals 3849b5e25fSSatish Balay */ 39ba38deedSJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_SeqSBAIJ(Mat A, PetscBool *missing, PetscInt *dd) 40d71ae5a4SJacob Faibussowitsch { 41045c9aa0SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 427734d3b5SMatthew G. Knepley PetscInt *diag, *ii = a->i, i; 4349b5e25fSSatish Balay 4449b5e25fSSatish Balay PetscFunctionBegin; 459566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqSBAIJ(A)); 462af78befSBarry Smith *missing = PETSC_FALSE; 477734d3b5SMatthew G. Knepley if (A->rmap->n > 0 && !ii) { 48358d2f5dSShri Abhyankar *missing = PETSC_TRUE; 49358d2f5dSShri Abhyankar if (dd) *dd = 0; 509566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no entries therefore is missing diagonal\n")); 51358d2f5dSShri Abhyankar } else { 52358d2f5dSShri Abhyankar diag = a->diag; 5349b5e25fSSatish Balay for (i = 0; i < a->mbs; i++) { 547734d3b5SMatthew G. Knepley if (diag[i] >= ii[i + 1]) { 552af78befSBarry Smith *missing = PETSC_TRUE; 562af78befSBarry Smith if (dd) *dd = i; 572af78befSBarry Smith break; 582af78befSBarry Smith } 5949b5e25fSSatish Balay } 60358d2f5dSShri Abhyankar } 613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6249b5e25fSSatish Balay } 6349b5e25fSSatish Balay 64d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMarkDiagonal_SeqSBAIJ(Mat A) 65d71ae5a4SJacob Faibussowitsch { 66045c9aa0SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 6748dd3d27SHong Zhang PetscInt i, j; 6849b5e25fSSatish Balay 6949b5e25fSSatish Balay PetscFunctionBegin; 7009f38230SBarry Smith if (!a->diag) { 719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(a->mbs, &a->diag)); 72c760cd28SBarry Smith a->free_diag = PETSC_TRUE; 7309f38230SBarry Smith } 7448dd3d27SHong Zhang for (i = 0; i < a->mbs; i++) { 7548dd3d27SHong Zhang a->diag[i] = a->i[i + 1]; 7648dd3d27SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 7748dd3d27SHong Zhang if (a->j[j] == i) { 7848dd3d27SHong Zhang a->diag[i] = j; 7948dd3d27SHong Zhang break; 8048dd3d27SHong Zhang } 8148dd3d27SHong Zhang } 8248dd3d27SHong Zhang } 833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8449b5e25fSSatish Balay } 8549b5e25fSSatish Balay 86d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowIJ_SeqSBAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool blockcompressed, PetscInt *nn, const PetscInt *inia[], const PetscInt *inja[], PetscBool *done) 87d71ae5a4SJacob Faibussowitsch { 88a6ece127SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 892462f5fdSStefano Zampini PetscInt i, j, n = a->mbs, nz = a->i[n], *tia, *tja, bs = A->rmap->bs, k, l, cnt; 902462f5fdSStefano Zampini PetscInt **ia = (PetscInt **)inia, **ja = (PetscInt **)inja; 9149b5e25fSSatish Balay 9249b5e25fSSatish Balay PetscFunctionBegin; 93d3e5a4abSHong Zhang *nn = n; 943ba16761SJacob Faibussowitsch if (!ia) PetscFunctionReturn(PETSC_SUCCESS); 952462f5fdSStefano Zampini if (symmetric) { 969566063dSJacob Faibussowitsch PetscCall(MatToSymmetricIJ_SeqAIJ(n, a->i, a->j, PETSC_FALSE, 0, 0, &tia, &tja)); 972462f5fdSStefano Zampini nz = tia[n]; 982462f5fdSStefano Zampini } else { 999371c9d4SSatish Balay tia = a->i; 1009371c9d4SSatish Balay tja = a->j; 1012462f5fdSStefano Zampini } 1022462f5fdSStefano Zampini 1032462f5fdSStefano Zampini if (!blockcompressed && bs > 1) { 1042462f5fdSStefano Zampini (*nn) *= bs; 1058f7157efSSatish Balay /* malloc & create the natural set of indices */ 1069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((n + 1) * bs, ia)); 1072462f5fdSStefano Zampini if (n) { 1082462f5fdSStefano Zampini (*ia)[0] = oshift; 109ad540459SPierre Jolivet for (j = 1; j < bs; j++) (*ia)[j] = (tia[1] - tia[0]) * bs + (*ia)[j - 1]; 1102462f5fdSStefano Zampini } 1112462f5fdSStefano Zampini 1122462f5fdSStefano Zampini for (i = 1; i < n; i++) { 1132462f5fdSStefano Zampini (*ia)[i * bs] = (tia[i] - tia[i - 1]) * bs + (*ia)[i * bs - 1]; 114ad540459SPierre Jolivet for (j = 1; j < bs; j++) (*ia)[i * bs + j] = (tia[i + 1] - tia[i]) * bs + (*ia)[i * bs + j - 1]; 1152462f5fdSStefano Zampini } 116ad540459SPierre Jolivet if (n) (*ia)[n * bs] = (tia[n] - tia[n - 1]) * bs + (*ia)[n * bs - 1]; 1172462f5fdSStefano Zampini 1182462f5fdSStefano Zampini if (inja) { 1199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz * bs * bs, ja)); 1202462f5fdSStefano Zampini cnt = 0; 1212462f5fdSStefano Zampini for (i = 0; i < n; i++) { 1228f7157efSSatish Balay for (j = 0; j < bs; j++) { 1232462f5fdSStefano Zampini for (k = tia[i]; k < tia[i + 1]; k++) { 124ad540459SPierre Jolivet for (l = 0; l < bs; l++) (*ja)[cnt++] = bs * tja[k] + l; 1258f7157efSSatish Balay } 1268f7157efSSatish Balay } 1278f7157efSSatish Balay } 1288f7157efSSatish Balay } 1292462f5fdSStefano Zampini 1302462f5fdSStefano Zampini if (symmetric) { /* deallocate memory allocated in MatToSymmetricIJ_SeqAIJ() */ 1319566063dSJacob Faibussowitsch PetscCall(PetscFree(tia)); 1329566063dSJacob Faibussowitsch PetscCall(PetscFree(tja)); 1332462f5fdSStefano Zampini } 1342462f5fdSStefano Zampini } else if (oshift == 1) { 1352462f5fdSStefano Zampini if (symmetric) { 1362462f5fdSStefano Zampini nz = tia[A->rmap->n / bs]; 1372462f5fdSStefano Zampini /* add 1 to i and j indices */ 1382462f5fdSStefano Zampini for (i = 0; i < A->rmap->n / bs + 1; i++) tia[i] = tia[i] + 1; 1392462f5fdSStefano Zampini *ia = tia; 1402462f5fdSStefano Zampini if (ja) { 1412462f5fdSStefano Zampini for (i = 0; i < nz; i++) tja[i] = tja[i] + 1; 1422462f5fdSStefano Zampini *ja = tja; 1432462f5fdSStefano Zampini } 1442462f5fdSStefano Zampini } else { 1452462f5fdSStefano Zampini nz = a->i[A->rmap->n / bs]; 1462462f5fdSStefano Zampini /* malloc space and add 1 to i and j indices */ 1479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n / bs + 1, ia)); 1482462f5fdSStefano Zampini for (i = 0; i < A->rmap->n / bs + 1; i++) (*ia)[i] = a->i[i] + 1; 1492462f5fdSStefano Zampini if (ja) { 1509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, ja)); 1512462f5fdSStefano Zampini for (i = 0; i < nz; i++) (*ja)[i] = a->j[i] + 1; 1522462f5fdSStefano Zampini } 1532462f5fdSStefano Zampini } 1542462f5fdSStefano Zampini } else { 1552462f5fdSStefano Zampini *ia = tia; 1562462f5fdSStefano Zampini if (ja) *ja = tja; 157a6ece127SHong Zhang } 1583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15949b5e25fSSatish Balay } 16049b5e25fSSatish Balay 161d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRowIJ_SeqSBAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool blockcompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 162d71ae5a4SJacob Faibussowitsch { 16349b5e25fSSatish Balay PetscFunctionBegin; 1643ba16761SJacob Faibussowitsch if (!ia) PetscFunctionReturn(PETSC_SUCCESS); 1652462f5fdSStefano Zampini if ((!blockcompressed && A->rmap->bs > 1) || (symmetric || oshift == 1)) { 1669566063dSJacob Faibussowitsch PetscCall(PetscFree(*ia)); 1679566063dSJacob Faibussowitsch if (ja) PetscCall(PetscFree(*ja)); 168a6ece127SHong Zhang } 1693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17049b5e25fSSatish Balay } 17149b5e25fSSatish Balay 172d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_SeqSBAIJ(Mat A) 173d71ae5a4SJacob Faibussowitsch { 17449b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 17549b5e25fSSatish Balay 17649b5e25fSSatish Balay PetscFunctionBegin; 177b4e2f619SBarry Smith if (A->hash_active) { 178b4e2f619SBarry Smith PetscInt bs; 179e3c72094SPierre Jolivet A->ops[0] = a->cops; 180b4e2f619SBarry Smith PetscCall(PetscHMapIJVDestroy(&a->ht)); 181b4e2f619SBarry Smith PetscCall(MatGetBlockSize(A, &bs)); 182b4e2f619SBarry Smith if (bs > 1) PetscCall(PetscHSetIJDestroy(&a->bht)); 183b4e2f619SBarry Smith PetscCall(PetscFree(a->dnz)); 184b4e2f619SBarry Smith PetscCall(PetscFree(a->bdnz)); 185b4e2f619SBarry Smith A->hash_active = PETSC_FALSE; 186b4e2f619SBarry Smith } 1873ba16761SJacob Faibussowitsch PetscCall(PetscLogObjectState((PetscObject)A, "Rows=%" PetscInt_FMT ", NZ=%" PetscInt_FMT, A->rmap->N, a->nz)); 1889566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(A, &a->a, &a->j, &a->i)); 1899566063dSJacob Faibussowitsch if (a->free_diag) PetscCall(PetscFree(a->diag)); 1909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 1919566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 1929566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 1939566063dSJacob Faibussowitsch PetscCall(PetscFree(a->idiag)); 1944d12350bSJunchao Zhang PetscCall(PetscFree(a->inode.size_csr)); 1959566063dSJacob Faibussowitsch if (a->free_imax_ilen) PetscCall(PetscFree2(a->imax, a->ilen)); 1969566063dSJacob Faibussowitsch PetscCall(PetscFree(a->solve_work)); 1979566063dSJacob Faibussowitsch PetscCall(PetscFree(a->sor_work)); 1989566063dSJacob Faibussowitsch PetscCall(PetscFree(a->solves_work)); 1999566063dSJacob Faibussowitsch PetscCall(PetscFree(a->mult_work)); 2009566063dSJacob Faibussowitsch PetscCall(PetscFree(a->saved_values)); 2019566063dSJacob Faibussowitsch if (a->free_jshort) PetscCall(PetscFree(a->jshort)); 2029566063dSJacob Faibussowitsch PetscCall(PetscFree(a->inew)); 2039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&a->parent)); 2049566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 205901853e0SKris Buschelman 2069566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL)); 2072e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJGetArray_C", NULL)); 2082e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJRestoreArray_C", NULL)); 2099566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatStoreValues_C", NULL)); 2109566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatRetrieveValues_C", NULL)); 2119566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetColumnIndices_C", NULL)); 2129566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqaij_C", NULL)); 2139566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_seqbaij_C", NULL)); 2149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocation_C", NULL)); 2159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqSBAIJSetPreallocationCSR_C", NULL)); 2166214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 2179566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_elemental_C", NULL)); 2186214f412SHong Zhang #endif 219d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 2209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqsbaij_scalapack_C", NULL)); 221d24d4204SJose E. Roman #endif 2222e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL)); 2233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22449b5e25fSSatish Balay } 22549b5e25fSSatish Balay 226ba38deedSJacob Faibussowitsch static PetscErrorCode MatSetOption_SeqSBAIJ(Mat A, MatOption op, PetscBool flg) 227d71ae5a4SJacob Faibussowitsch { 228045c9aa0SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 229eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 230eb1ec7c1SStefano Zampini PetscInt bs; 231eb1ec7c1SStefano Zampini #endif 23249b5e25fSSatish Balay 23349b5e25fSSatish Balay PetscFunctionBegin; 234eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 2359566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 236eb1ec7c1SStefano Zampini #endif 2374d9d31abSKris Buschelman switch (op) { 238d71ae5a4SJacob Faibussowitsch case MAT_ROW_ORIENTED: 239d71ae5a4SJacob Faibussowitsch a->roworiented = flg; 240d71ae5a4SJacob Faibussowitsch break; 241d71ae5a4SJacob Faibussowitsch case MAT_KEEP_NONZERO_PATTERN: 242d71ae5a4SJacob Faibussowitsch a->keepnonzeropattern = flg; 243d71ae5a4SJacob Faibussowitsch break; 244d71ae5a4SJacob Faibussowitsch case MAT_NEW_NONZERO_LOCATIONS: 245d71ae5a4SJacob Faibussowitsch a->nonew = (flg ? 0 : 1); 246d71ae5a4SJacob Faibussowitsch break; 247d71ae5a4SJacob Faibussowitsch case MAT_NEW_NONZERO_LOCATION_ERR: 248d71ae5a4SJacob Faibussowitsch a->nonew = (flg ? -1 : 0); 249d71ae5a4SJacob Faibussowitsch break; 250d71ae5a4SJacob Faibussowitsch case MAT_NEW_NONZERO_ALLOCATION_ERR: 251d71ae5a4SJacob Faibussowitsch a->nonew = (flg ? -2 : 0); 252d71ae5a4SJacob Faibussowitsch break; 253d71ae5a4SJacob Faibussowitsch case MAT_UNUSED_NONZERO_LOCATION_ERR: 254d71ae5a4SJacob Faibussowitsch a->nounused = (flg ? -1 : 0); 255d71ae5a4SJacob Faibussowitsch break; 2569a4540c5SBarry Smith case MAT_HERMITIAN: 257eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 258eb1ec7c1SStefano Zampini if (flg) { /* disable transpose ops */ 25908401ef6SPierre Jolivet PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for Hermitian with block size greater than 1"); 260eb1ec7c1SStefano Zampini A->ops->multtranspose = NULL; 261eb1ec7c1SStefano Zampini A->ops->multtransposeadd = NULL; 262b94d7dedSBarry Smith A->symmetric = PETSC_BOOL3_FALSE; 263eb1ec7c1SStefano Zampini } 2640f2140c7SStefano Zampini #endif 265eeffb40dSHong Zhang break; 26677e54ba9SKris Buschelman case MAT_SYMMETRIC: 267eb1ec7c1SStefano Zampini case MAT_SPD: 268eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 269eb1ec7c1SStefano Zampini if (flg) { /* An hermitian and symmetric matrix has zero imaginary part (restore back transpose ops) */ 270eb1ec7c1SStefano Zampini A->ops->multtranspose = A->ops->mult; 271eb1ec7c1SStefano Zampini A->ops->multtransposeadd = A->ops->multadd; 272eb1ec7c1SStefano Zampini } 273eb1ec7c1SStefano Zampini #endif 274eb1ec7c1SStefano Zampini break; 275d71ae5a4SJacob Faibussowitsch case MAT_IGNORE_LOWER_TRIANGULAR: 276d71ae5a4SJacob Faibussowitsch a->ignore_ltriangular = flg; 277d71ae5a4SJacob Faibussowitsch break; 278d71ae5a4SJacob Faibussowitsch case MAT_ERROR_LOWER_TRIANGULAR: 279d71ae5a4SJacob Faibussowitsch a->ignore_ltriangular = flg; 280d71ae5a4SJacob Faibussowitsch break; 281d71ae5a4SJacob Faibussowitsch case MAT_GETROW_UPPERTRIANGULAR: 282d71ae5a4SJacob Faibussowitsch a->getrow_utriangular = flg; 283d71ae5a4SJacob Faibussowitsch break; 284d71ae5a4SJacob Faibussowitsch default: 285888c827cSStefano Zampini break; 28649b5e25fSSatish Balay } 2873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28849b5e25fSSatish Balay } 28949b5e25fSSatish Balay 290d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 291d71ae5a4SJacob Faibussowitsch { 29249b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 29349b5e25fSSatish Balay 29449b5e25fSSatish Balay PetscFunctionBegin; 29508401ef6SPierre 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()"); 29652768537SHong Zhang 297f5edf698SHong Zhang /* Get the upper triangular part of the row */ 2989566063dSJacob Faibussowitsch PetscCall(MatGetRow_SeqBAIJ_private(A, row, nz, idx, v, a->i, a->j, a->a)); 2993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30049b5e25fSSatish Balay } 30149b5e25fSSatish Balay 302d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreRow_SeqSBAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 303d71ae5a4SJacob Faibussowitsch { 30449b5e25fSSatish Balay PetscFunctionBegin; 3059566063dSJacob Faibussowitsch if (idx) PetscCall(PetscFree(*idx)); 3069566063dSJacob Faibussowitsch if (v) PetscCall(PetscFree(*v)); 3073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30849b5e25fSSatish Balay } 30949b5e25fSSatish Balay 310ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetRowUpperTriangular_SeqSBAIJ(Mat A) 311d71ae5a4SJacob Faibussowitsch { 312f5edf698SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 313f5edf698SHong Zhang 314f5edf698SHong Zhang PetscFunctionBegin; 315f5edf698SHong Zhang a->getrow_utriangular = PETSC_TRUE; 3163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 317f5edf698SHong Zhang } 318a323099bSStefano Zampini 319ba38deedSJacob Faibussowitsch static PetscErrorCode MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A) 320d71ae5a4SJacob Faibussowitsch { 321f5edf698SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 322f5edf698SHong Zhang 323f5edf698SHong Zhang PetscFunctionBegin; 324f5edf698SHong Zhang a->getrow_utriangular = PETSC_FALSE; 3253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 326f5edf698SHong Zhang } 327f5edf698SHong Zhang 328ba38deedSJacob Faibussowitsch static PetscErrorCode MatTranspose_SeqSBAIJ(Mat A, MatReuse reuse, Mat *B) 329d71ae5a4SJacob Faibussowitsch { 33049b5e25fSSatish Balay PetscFunctionBegin; 3317fb60732SBarry Smith if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B)); 332cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX) { 3339566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, B)); 334cf37664fSBarry Smith } else if (reuse == MAT_REUSE_MATRIX) { 3359566063dSJacob Faibussowitsch PetscCall(MatCopy(A, *B, SAME_NONZERO_PATTERN)); 336fc4dec0aSBarry Smith } 3373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33849b5e25fSSatish Balay } 33949b5e25fSSatish Balay 340ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_ASCII(Mat A, PetscViewer viewer) 341d71ae5a4SJacob Faibussowitsch { 34249b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 343d0f46423SBarry Smith PetscInt i, j, bs = A->rmap->bs, k, l, bs2 = a->bs2; 344f3ef73ceSBarry Smith PetscViewerFormat format; 345121deb67SSatish Balay PetscInt *diag; 346b3a0534dSBarry Smith const char *matname; 34749b5e25fSSatish Balay 34849b5e25fSSatish Balay PetscFunctionBegin; 3499566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 350456192e2SBarry Smith if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 3519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " block size is %" PetscInt_FMT "\n", bs)); 352fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_MATLAB) { 353d2507d54SMatthew Knepley Mat aij; 354ade3a672SBarry Smith 355d5f3da31SBarry Smith if (A->factortype && bs > 1) { 3569566063dSJacob 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")); 3573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35870d5e725SHong Zhang } 3599566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &aij)); 36023a3927dSBarry Smith if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname)); 36123a3927dSBarry Smith if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)aij, matname)); 36223a3927dSBarry Smith PetscCall(MatView_SeqAIJ(aij, viewer)); 3639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&aij)); 364fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_COMMON) { 365b3a0534dSBarry Smith Mat B; 366b3a0534dSBarry Smith 367b3a0534dSBarry Smith PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B)); 368b3a0534dSBarry Smith if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname)); 369b3a0534dSBarry Smith if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)B, matname)); 370b3a0534dSBarry Smith PetscCall(MatView_SeqAIJ(B, viewer)); 371b3a0534dSBarry Smith PetscCall(MatDestroy(&B)); 372c1490034SHong Zhang } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 3733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 37449b5e25fSSatish Balay } else { 3759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 3762c990fa1SHong Zhang if (A->factortype) { /* for factored matrix */ 37708401ef6SPierre Jolivet PetscCheck(bs <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix is factored with bs>1. Not implemented yet"); 3782c990fa1SHong Zhang 379121deb67SSatish Balay diag = a->diag; 380121deb67SSatish Balay for (i = 0; i < a->mbs; i++) { /* for row block i */ 3819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 3822c990fa1SHong Zhang /* diagonal entry */ 3832c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX) 3842c990fa1SHong Zhang if (PetscImaginaryPart(a->a[diag[i]]) > 0.0) { 3859566063dSJacob 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]]))); 3862c990fa1SHong Zhang } else if (PetscImaginaryPart(a->a[diag[i]]) < 0.0) { 3879566063dSJacob 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]]))); 3882c990fa1SHong Zhang } else { 3899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)PetscRealPart(1.0 / a->a[diag[i]]))); 3902c990fa1SHong Zhang } 3912c990fa1SHong Zhang #else 392835f2295SStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[diag[i]], (double)(1 / a->a[diag[i]]))); 3932c990fa1SHong Zhang #endif 3942c990fa1SHong Zhang /* off-diagonal entries */ 3952c990fa1SHong Zhang for (k = a->i[i]; k < a->i[i + 1] - 1; k++) { 3962c990fa1SHong Zhang #if defined(PETSC_USE_COMPLEX) 397ca0704adSBarry Smith if (PetscImaginaryPart(a->a[k]) > 0.0) { 3989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), (double)PetscImaginaryPart(a->a[k]))); 399ca0704adSBarry Smith } else if (PetscImaginaryPart(a->a[k]) < 0.0) { 4009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i) ", bs * a->j[k], (double)PetscRealPart(a->a[k]), -(double)PetscImaginaryPart(a->a[k]))); 4012c990fa1SHong Zhang } else { 4029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k], (double)PetscRealPart(a->a[k]))); 4032c990fa1SHong Zhang } 4042c990fa1SHong Zhang #else 4059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[k], (double)a->a[k])); 4062c990fa1SHong Zhang #endif 4072c990fa1SHong Zhang } 4089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 4092c990fa1SHong Zhang } 4102c990fa1SHong Zhang 4112c990fa1SHong Zhang } else { /* for non-factored matrix */ 4120c74a584SJed Brown for (i = 0; i < a->mbs; i++) { /* for row block i */ 4130c74a584SJed Brown for (j = 0; j < bs; j++) { /* for row bs*i + j */ 4149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i * bs + j)); 4150c74a584SJed Brown for (k = a->i[i]; k < a->i[i + 1]; k++) { /* for column block */ 4160c74a584SJed Brown for (l = 0; l < bs; l++) { /* for column */ 41749b5e25fSSatish Balay #if defined(PETSC_USE_COMPLEX) 41849b5e25fSSatish Balay if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) > 0.0) { 4199371c9d4SSatish 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]))); 42049b5e25fSSatish Balay } else if (PetscImaginaryPart(a->a[bs2 * k + l * bs + j]) < 0.0) { 4219371c9d4SSatish 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]))); 42249b5e25fSSatish Balay } else { 4239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)PetscRealPart(a->a[bs2 * k + l * bs + j]))); 42449b5e25fSSatish Balay } 42549b5e25fSSatish Balay #else 4269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", bs * a->j[k] + l, (double)a->a[bs2 * k + l * bs + j])); 42749b5e25fSSatish Balay #endif 42849b5e25fSSatish Balay } 42949b5e25fSSatish Balay } 4309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 43149b5e25fSSatish Balay } 43249b5e25fSSatish Balay } 4332c990fa1SHong Zhang } 4349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 43549b5e25fSSatish Balay } 4369566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 4373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43849b5e25fSSatish Balay } 43949b5e25fSSatish Balay 4409804daf3SBarry Smith #include <petscdraw.h> 441d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw, void *Aa) 442d71ae5a4SJacob Faibussowitsch { 44349b5e25fSSatish Balay Mat A = (Mat)Aa; 44449b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 4456497c311SBarry Smith PetscInt row, i, j, k, l, mbs = a->mbs, bs = A->rmap->bs, bs2 = a->bs2; 44649b5e25fSSatish Balay PetscReal xl, yl, xr, yr, x_l, x_r, y_l, y_r; 44749b5e25fSSatish Balay MatScalar *aa; 448b0a32e0cSBarry Smith PetscViewer viewer; 4496497c311SBarry Smith int color; 45049b5e25fSSatish Balay 45149b5e25fSSatish Balay PetscFunctionBegin; 4529566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer)); 4539566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr)); 45449b5e25fSSatish Balay 45549b5e25fSSatish Balay /* loop over matrix elements drawing boxes */ 456383922c3SLisandro Dalcin 457d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 4589566063dSJacob Faibussowitsch PetscCall(PetscDrawString(draw, .3 * (xl + xr), .3 * (yl + yr), PETSC_DRAW_BLACK, "symmetric")); 459383922c3SLisandro Dalcin /* Blue for negative, Cyan for zero and Red for positive */ 460b0a32e0cSBarry Smith color = PETSC_DRAW_BLUE; 46149b5e25fSSatish Balay for (i = 0, row = 0; i < mbs; i++, row += bs) { 46249b5e25fSSatish Balay for (j = a->i[i]; j < a->i[i + 1]; j++) { 4639371c9d4SSatish Balay y_l = A->rmap->N - row - 1.0; 4649371c9d4SSatish Balay y_r = y_l + 1.0; 4659371c9d4SSatish Balay x_l = a->j[j] * bs; 4669371c9d4SSatish Balay x_r = x_l + 1.0; 46749b5e25fSSatish Balay aa = a->a + j * bs2; 46849b5e25fSSatish Balay for (k = 0; k < bs; k++) { 46949b5e25fSSatish Balay for (l = 0; l < bs; l++) { 47049b5e25fSSatish Balay if (PetscRealPart(*aa++) >= 0.) continue; 4719566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color)); 47249b5e25fSSatish Balay } 47349b5e25fSSatish Balay } 47449b5e25fSSatish Balay } 47549b5e25fSSatish Balay } 476b0a32e0cSBarry Smith color = PETSC_DRAW_CYAN; 47749b5e25fSSatish Balay for (i = 0, row = 0; i < mbs; i++, row += bs) { 47849b5e25fSSatish Balay for (j = a->i[i]; j < a->i[i + 1]; j++) { 4799371c9d4SSatish Balay y_l = A->rmap->N - row - 1.0; 4809371c9d4SSatish Balay y_r = y_l + 1.0; 4819371c9d4SSatish Balay x_l = a->j[j] * bs; 4829371c9d4SSatish Balay x_r = x_l + 1.0; 48349b5e25fSSatish Balay aa = a->a + j * bs2; 48449b5e25fSSatish Balay for (k = 0; k < bs; k++) { 48549b5e25fSSatish Balay for (l = 0; l < bs; l++) { 48649b5e25fSSatish Balay if (PetscRealPart(*aa++) != 0.) continue; 4879566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color)); 48849b5e25fSSatish Balay } 48949b5e25fSSatish Balay } 49049b5e25fSSatish Balay } 49149b5e25fSSatish Balay } 492b0a32e0cSBarry Smith color = PETSC_DRAW_RED; 49349b5e25fSSatish Balay for (i = 0, row = 0; i < mbs; i++, row += bs) { 49449b5e25fSSatish Balay for (j = a->i[i]; j < a->i[i + 1]; j++) { 4959371c9d4SSatish Balay y_l = A->rmap->N - row - 1.0; 4969371c9d4SSatish Balay y_r = y_l + 1.0; 4979371c9d4SSatish Balay x_l = a->j[j] * bs; 4989371c9d4SSatish Balay x_r = x_l + 1.0; 49949b5e25fSSatish Balay aa = a->a + j * bs2; 50049b5e25fSSatish Balay for (k = 0; k < bs; k++) { 50149b5e25fSSatish Balay for (l = 0; l < bs; l++) { 50249b5e25fSSatish Balay if (PetscRealPart(*aa++) <= 0.) continue; 5039566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l + k, y_l - l, x_r + k, y_r - l, color, color, color, color)); 50449b5e25fSSatish Balay } 50549b5e25fSSatish Balay } 50649b5e25fSSatish Balay } 50749b5e25fSSatish Balay } 508d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 5093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51049b5e25fSSatish Balay } 51149b5e25fSSatish Balay 512d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqSBAIJ_Draw(Mat A, PetscViewer viewer) 513d71ae5a4SJacob Faibussowitsch { 51449b5e25fSSatish Balay PetscReal xl, yl, xr, yr, w, h; 515b0a32e0cSBarry Smith PetscDraw draw; 516ace3abfcSBarry Smith PetscBool isnull; 51749b5e25fSSatish Balay 51849b5e25fSSatish Balay PetscFunctionBegin; 5199566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 5209566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 5213ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 52249b5e25fSSatish Balay 5239371c9d4SSatish Balay xr = A->rmap->N; 5249371c9d4SSatish Balay yr = A->rmap->N; 5259371c9d4SSatish Balay h = yr / 10.0; 5269371c9d4SSatish Balay w = xr / 10.0; 5279371c9d4SSatish Balay xr += w; 5289371c9d4SSatish Balay yr += h; 5299371c9d4SSatish Balay xl = -w; 5309371c9d4SSatish Balay yl = -h; 5319566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr)); 5329566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer)); 5339566063dSJacob Faibussowitsch PetscCall(PetscDrawZoom(draw, MatView_SeqSBAIJ_Draw_Zoom, A)); 5349566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL)); 5359566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 5363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 53749b5e25fSSatish Balay } 53849b5e25fSSatish Balay 539618cc2edSLisandro Dalcin /* Used for both MPIBAIJ and MPISBAIJ matrices */ 540618cc2edSLisandro Dalcin #define MatView_SeqSBAIJ_Binary MatView_SeqBAIJ_Binary 541618cc2edSLisandro Dalcin 542d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqSBAIJ(Mat A, PetscViewer viewer) 543d71ae5a4SJacob Faibussowitsch { 544618cc2edSLisandro Dalcin PetscBool iascii, isbinary, isdraw; 54549b5e25fSSatish Balay 54649b5e25fSSatish Balay PetscFunctionBegin; 5479566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 5489566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 5499566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 55032077d6dSBarry Smith if (iascii) { 5519566063dSJacob Faibussowitsch PetscCall(MatView_SeqSBAIJ_ASCII(A, viewer)); 552618cc2edSLisandro Dalcin } else if (isbinary) { 5539566063dSJacob Faibussowitsch PetscCall(MatView_SeqSBAIJ_Binary(A, viewer)); 55449b5e25fSSatish Balay } else if (isdraw) { 5559566063dSJacob Faibussowitsch PetscCall(MatView_SeqSBAIJ_Draw(A, viewer)); 55649b5e25fSSatish Balay } else { 557a5e6ed63SBarry Smith Mat B; 558ade3a672SBarry Smith const char *matname; 5599566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B)); 56023a3927dSBarry Smith if (((PetscObject)A)->name) PetscCall(PetscObjectGetName((PetscObject)A, &matname)); 56123a3927dSBarry Smith if (((PetscObject)A)->name) PetscCall(PetscObjectSetName((PetscObject)B, matname)); 5629566063dSJacob Faibussowitsch PetscCall(MatView(B, viewer)); 5639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 56449b5e25fSSatish Balay } 5653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56649b5e25fSSatish Balay } 56749b5e25fSSatish Balay 568d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[]) 569d71ae5a4SJacob Faibussowitsch { 570045c9aa0SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 57113f74950SBarry Smith PetscInt *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j; 57213f74950SBarry Smith PetscInt *ai = a->i, *ailen = a->ilen; 573d0f46423SBarry Smith PetscInt brow, bcol, ridx, cidx, bs = A->rmap->bs, bs2 = a->bs2; 57497e567efSBarry Smith MatScalar *ap, *aa = a->a; 57549b5e25fSSatish Balay 57649b5e25fSSatish Balay PetscFunctionBegin; 57749b5e25fSSatish Balay for (k = 0; k < m; k++) { /* loop over rows */ 5789371c9d4SSatish Balay row = im[k]; 5799371c9d4SSatish Balay brow = row / bs; 5809371c9d4SSatish Balay if (row < 0) { 5819371c9d4SSatish Balay v += n; 5829371c9d4SSatish Balay continue; 5839371c9d4SSatish Balay } /* negative row */ 58454c59aa7SJacob 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); 5859371c9d4SSatish Balay rp = aj + ai[brow]; 5869371c9d4SSatish Balay ap = aa + bs2 * ai[brow]; 58749b5e25fSSatish Balay nrow = ailen[brow]; 58849b5e25fSSatish Balay for (l = 0; l < n; l++) { /* loop over columns */ 5899371c9d4SSatish Balay if (in[l] < 0) { 5909371c9d4SSatish Balay v++; 5919371c9d4SSatish Balay continue; 5929371c9d4SSatish Balay } /* negative column */ 59354c59aa7SJacob 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); 59449b5e25fSSatish Balay col = in[l]; 59549b5e25fSSatish Balay bcol = col / bs; 59649b5e25fSSatish Balay cidx = col % bs; 59749b5e25fSSatish Balay ridx = row % bs; 59849b5e25fSSatish Balay high = nrow; 59949b5e25fSSatish Balay low = 0; /* assume unsorted */ 60049b5e25fSSatish Balay while (high - low > 5) { 60149b5e25fSSatish Balay t = (low + high) / 2; 60249b5e25fSSatish Balay if (rp[t] > bcol) high = t; 60349b5e25fSSatish Balay else low = t; 60449b5e25fSSatish Balay } 60549b5e25fSSatish Balay for (i = low; i < high; i++) { 60649b5e25fSSatish Balay if (rp[i] > bcol) break; 60749b5e25fSSatish Balay if (rp[i] == bcol) { 60849b5e25fSSatish Balay *v++ = ap[bs2 * i + bs * cidx + ridx]; 60949b5e25fSSatish Balay goto finished; 61049b5e25fSSatish Balay } 61149b5e25fSSatish Balay } 61297e567efSBarry Smith *v++ = 0.0; 61349b5e25fSSatish Balay finished:; 61449b5e25fSSatish Balay } 61549b5e25fSSatish Balay } 6163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61749b5e25fSSatish Balay } 61849b5e25fSSatish Balay 619ba38deedSJacob Faibussowitsch static PetscErrorCode MatPermute_SeqSBAIJ(Mat A, IS rowp, IS colp, Mat *B) 620d71ae5a4SJacob Faibussowitsch { 621dc29a518SPierre Jolivet Mat C; 62257069620SPierre Jolivet PetscBool flg = (PetscBool)(rowp == colp); 623dc29a518SPierre Jolivet 624dc29a518SPierre Jolivet PetscFunctionBegin; 6259566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATSEQBAIJ, MAT_INITIAL_MATRIX, &C)); 6269566063dSJacob Faibussowitsch PetscCall(MatPermute(C, rowp, colp, B)); 6279566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 62857069620SPierre Jolivet if (!flg) PetscCall(ISEqual(rowp, colp, &flg)); 62957069620SPierre Jolivet if (flg) PetscCall(MatConvert(*B, MATSEQSBAIJ, MAT_INPLACE_MATRIX, B)); 6303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 631dc29a518SPierre Jolivet } 63249b5e25fSSatish Balay 633d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesBlocked_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) 634d71ae5a4SJacob Faibussowitsch { 6350880e062SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 636e2ee6c50SBarry Smith PetscInt *rp, k, low, high, t, ii, jj, row, nrow, i, col, l, rmax, N, lastcol = -1; 63713f74950SBarry Smith PetscInt *imax = a->imax, *ai = a->i, *ailen = a->ilen; 638d0f46423SBarry Smith PetscInt *aj = a->j, nonew = a->nonew, bs2 = a->bs2, bs = A->rmap->bs, stepval; 639ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 640dd6ea824SBarry Smith const PetscScalar *value = v; 641f15d580aSBarry Smith MatScalar *ap, *aa = a->a, *bap; 6420880e062SHong Zhang 64349b5e25fSSatish Balay PetscFunctionBegin; 64426fbe8dcSKarl Rupp if (roworiented) stepval = (n - 1) * bs; 64526fbe8dcSKarl Rupp else stepval = (m - 1) * bs; 6460880e062SHong Zhang for (k = 0; k < m; k++) { /* loop over added rows */ 6470880e062SHong Zhang row = im[k]; 6480880e062SHong Zhang if (row < 0) continue; 6496bdcaf15SBarry 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); 6500880e062SHong Zhang rp = aj + ai[row]; 6510880e062SHong Zhang ap = aa + bs2 * ai[row]; 6520880e062SHong Zhang rmax = imax[row]; 6530880e062SHong Zhang nrow = ailen[row]; 6540880e062SHong Zhang low = 0; 655818f2c47SBarry Smith high = nrow; 6560880e062SHong Zhang for (l = 0; l < n; l++) { /* loop over added columns */ 6570880e062SHong Zhang if (in[l] < 0) continue; 6580880e062SHong Zhang col = in[l]; 6596bdcaf15SBarry 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); 660b98bf0e1SJed Brown if (col < row) { 66126fbe8dcSKarl Rupp if (a->ignore_ltriangular) continue; /* ignore lower triangular block */ 66226fbe8dcSKarl 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)"); 663b98bf0e1SJed Brown } 66426fbe8dcSKarl Rupp if (roworiented) value = v + k * (stepval + bs) * bs + l * bs; 66526fbe8dcSKarl Rupp else value = v + l * (stepval + bs) * bs + k * bs; 66626fbe8dcSKarl Rupp 66726fbe8dcSKarl Rupp if (col <= lastcol) low = 0; 66826fbe8dcSKarl Rupp else high = nrow; 66926fbe8dcSKarl Rupp 670e2ee6c50SBarry Smith lastcol = col; 6710880e062SHong Zhang while (high - low > 7) { 6720880e062SHong Zhang t = (low + high) / 2; 6730880e062SHong Zhang if (rp[t] > col) high = t; 6740880e062SHong Zhang else low = t; 6750880e062SHong Zhang } 6760880e062SHong Zhang for (i = low; i < high; i++) { 6770880e062SHong Zhang if (rp[i] > col) break; 6780880e062SHong Zhang if (rp[i] == col) { 6790880e062SHong Zhang bap = ap + bs2 * i; 6800880e062SHong Zhang if (roworiented) { 6810880e062SHong Zhang if (is == ADD_VALUES) { 6820880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 683ad540459SPierre Jolivet for (jj = ii; jj < bs2; jj += bs) bap[jj] += *value++; 6840880e062SHong Zhang } 6850880e062SHong Zhang } else { 6860880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 687ad540459SPierre Jolivet for (jj = ii; jj < bs2; jj += bs) bap[jj] = *value++; 6880880e062SHong Zhang } 6890880e062SHong Zhang } 6900880e062SHong Zhang } else { 6910880e062SHong Zhang if (is == ADD_VALUES) { 6920880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 693ad540459SPierre Jolivet for (jj = 0; jj < bs; jj++) *bap++ += *value++; 6940880e062SHong Zhang } 6950880e062SHong Zhang } else { 6960880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 697ad540459SPierre Jolivet for (jj = 0; jj < bs; jj++) *bap++ = *value++; 6980880e062SHong Zhang } 6990880e062SHong Zhang } 7000880e062SHong Zhang } 7010880e062SHong Zhang goto noinsert2; 7020880e062SHong Zhang } 7030880e062SHong Zhang } 7040880e062SHong Zhang if (nonew == 1) goto noinsert2; 70508401ef6SPierre 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); 706fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 7079371c9d4SSatish Balay N = nrow++ - 1; 7089371c9d4SSatish Balay high++; 7090880e062SHong Zhang /* shift up all the later entries in this row */ 7109566063dSJacob Faibussowitsch PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1)); 7119566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1))); 7129566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ap + bs2 * i, bs2)); 7130880e062SHong Zhang rp[i] = col; 7140880e062SHong Zhang bap = ap + bs2 * i; 7150880e062SHong Zhang if (roworiented) { 7160880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 717ad540459SPierre Jolivet for (jj = ii; jj < bs2; jj += bs) bap[jj] = *value++; 7180880e062SHong Zhang } 7190880e062SHong Zhang } else { 7200880e062SHong Zhang for (ii = 0; ii < bs; ii++, value += stepval) { 721ad540459SPierre Jolivet for (jj = 0; jj < bs; jj++) *bap++ = *value++; 7220880e062SHong Zhang } 7230880e062SHong Zhang } 7240880e062SHong Zhang noinsert2:; 7250880e062SHong Zhang low = i; 7260880e062SHong Zhang } 7270880e062SHong Zhang ailen[row] = nrow; 7280880e062SHong Zhang } 7293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 73049b5e25fSSatish Balay } 73149b5e25fSSatish Balay 732ba38deedSJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_SeqSBAIJ(Mat A, MatAssemblyType mode) 733d71ae5a4SJacob Faibussowitsch { 73449b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 7358f8f2f0dSBarry Smith PetscInt fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax; 736d0f46423SBarry Smith PetscInt m = A->rmap->N, *ip, N, *ailen = a->ilen; 73713f74950SBarry Smith PetscInt mbs = a->mbs, bs2 = a->bs2, rmax = 0; 73849b5e25fSSatish Balay MatScalar *aa = a->a, *ap; 73949b5e25fSSatish Balay 74049b5e25fSSatish Balay PetscFunctionBegin; 741d32568d8SPierre Jolivet if (mode == MAT_FLUSH_ASSEMBLY || (A->was_assembled && A->ass_nonzerostate == A->nonzerostate)) PetscFunctionReturn(PETSC_SUCCESS); 74249b5e25fSSatish Balay 74349b5e25fSSatish Balay if (m) rmax = ailen[0]; 74449b5e25fSSatish Balay for (i = 1; i < mbs; i++) { 74549b5e25fSSatish Balay /* move each row back by the amount of empty slots (fshift) before it*/ 74649b5e25fSSatish Balay fshift += imax[i - 1] - ailen[i - 1]; 74749b5e25fSSatish Balay rmax = PetscMax(rmax, ailen[i]); 74849b5e25fSSatish Balay if (fshift) { 749580bdb30SBarry Smith ip = aj + ai[i]; 750580bdb30SBarry Smith ap = aa + bs2 * ai[i]; 75149b5e25fSSatish Balay N = ailen[i]; 7529566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ip - fshift, ip, N)); 7539566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap - bs2 * fshift, ap, bs2 * N)); 75449b5e25fSSatish Balay } 75549b5e25fSSatish Balay ai[i] = ai[i - 1] + ailen[i - 1]; 75649b5e25fSSatish Balay } 75749b5e25fSSatish Balay if (mbs) { 75849b5e25fSSatish Balay fshift += imax[mbs - 1] - ailen[mbs - 1]; 75949b5e25fSSatish Balay ai[mbs] = ai[mbs - 1] + ailen[mbs - 1]; 76049b5e25fSSatish Balay } 76149b5e25fSSatish Balay /* reset ilen and imax for each row */ 762ad540459SPierre Jolivet for (i = 0; i < mbs; i++) ailen[i] = imax[i] = ai[i + 1] - ai[i]; 7636c6c5352SBarry Smith a->nz = ai[mbs]; 76449b5e25fSSatish Balay 765b424e231SHong Zhang /* diagonals may have moved, reset it */ 7661baa6e33SBarry Smith if (a->diag) PetscCall(PetscArraycpy(a->diag, ai, mbs)); 767aed4548fSBarry 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); 76826fbe8dcSKarl Rupp 7699566063dSJacob 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)); 7709566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues is %" PetscInt_FMT "\n", a->reallocs)); 7719566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Most nonzeros blocks in any row is %" PetscInt_FMT "\n", rmax)); 77226fbe8dcSKarl Rupp 7738e58a170SBarry Smith A->info.mallocs += a->reallocs; 77449b5e25fSSatish Balay a->reallocs = 0; 77549b5e25fSSatish Balay A->info.nz_unneeded = (PetscReal)fshift * bs2; 776061b2667SBarry Smith a->idiagvalid = PETSC_FALSE; 7774dcd73b1SHong Zhang a->rmax = rmax; 77838702af4SBarry Smith 77938702af4SBarry Smith if (A->cmap->n < 65536 && A->cmap->bs == 1) { 78044e1c64aSLisandro Dalcin if (a->jshort && a->free_jshort) { 78117803ae8SHong Zhang /* when matrix data structure is changed, previous jshort must be replaced */ 7829566063dSJacob Faibussowitsch PetscCall(PetscFree(a->jshort)); 78317803ae8SHong Zhang } 7849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(a->i[A->rmap->n], &a->jshort)); 7856497c311SBarry Smith for (i = 0; i < a->i[A->rmap->n]; i++) a->jshort[i] = (short)a->j[i]; 78638702af4SBarry Smith A->ops->mult = MatMult_SeqSBAIJ_1_ushort; 78741f059aeSBarry Smith A->ops->sor = MatSOR_SeqSBAIJ_ushort; 7884da8f245SBarry Smith a->free_jshort = PETSC_TRUE; 78938702af4SBarry Smith } 7903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 79149b5e25fSSatish Balay } 79249b5e25fSSatish Balay 79349b5e25fSSatish Balay /* Only add/insert a(i,j) with i<=j (blocks). 794da81f932SPierre Jolivet Any a(i,j) with i>j input by user is ignored. 79549b5e25fSSatish Balay */ 79649b5e25fSSatish Balay 797d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValues_SeqSBAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) 798d71ae5a4SJacob Faibussowitsch { 79949b5e25fSSatish Balay Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 800e2ee6c50SBarry Smith PetscInt *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N, lastcol = -1; 80113f74950SBarry Smith PetscInt *imax = a->imax, *ai = a->i, *ailen = a->ilen, roworiented = a->roworiented; 802d0f46423SBarry Smith PetscInt *aj = a->j, nonew = a->nonew, bs = A->rmap->bs, brow, bcol; 80313f74950SBarry Smith PetscInt ridx, cidx, bs2 = a->bs2; 80449b5e25fSSatish Balay MatScalar *ap, value, *aa = a->a, *bap; 80549b5e25fSSatish Balay 80649b5e25fSSatish Balay PetscFunctionBegin; 80749b5e25fSSatish Balay for (k = 0; k < m; k++) { /* loop over added rows */ 80849b5e25fSSatish Balay row = im[k]; /* row number */ 80949b5e25fSSatish Balay brow = row / bs; /* block row number */ 81049b5e25fSSatish Balay if (row < 0) continue; 8116bdcaf15SBarry 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); 81249b5e25fSSatish Balay rp = aj + ai[brow]; /*ptr to beginning of column value of the row block*/ 81349b5e25fSSatish Balay ap = aa + bs2 * ai[brow]; /*ptr to beginning of element value of the row block*/ 81449b5e25fSSatish Balay rmax = imax[brow]; /* maximum space allocated for this row */ 81549b5e25fSSatish Balay nrow = ailen[brow]; /* actual length of this row */ 81649b5e25fSSatish Balay low = 0; 8178509e838SStefano Zampini high = nrow; 81849b5e25fSSatish Balay for (l = 0; l < n; l++) { /* loop over added columns */ 81949b5e25fSSatish Balay if (in[l] < 0) continue; 8206bdcaf15SBarry 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); 82149b5e25fSSatish Balay col = in[l]; 82249b5e25fSSatish Balay bcol = col / bs; /* block col number */ 82349b5e25fSSatish Balay 824941593c8SHong Zhang if (brow > bcol) { 82526fbe8dcSKarl Rupp if (a->ignore_ltriangular) continue; /* ignore lower triangular values */ 82626fbe8dcSKarl 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)"); 827941593c8SHong Zhang } 828f4989cb3SHong Zhang 8299371c9d4SSatish Balay ridx = row % bs; 8309371c9d4SSatish Balay cidx = col % bs; /*row and col index inside the block */ 8318549e402SHong Zhang if ((brow == bcol && ridx <= cidx) || (brow < bcol)) { 83249b5e25fSSatish Balay /* element value a(k,l) */ 83326fbe8dcSKarl Rupp if (roworiented) value = v[l + k * n]; 83426fbe8dcSKarl Rupp else value = v[k + l * m]; 83549b5e25fSSatish Balay 83649b5e25fSSatish Balay /* move pointer bap to a(k,l) quickly and add/insert value */ 83726fbe8dcSKarl Rupp if (col <= lastcol) low = 0; 8388509e838SStefano Zampini else high = nrow; 8398509e838SStefano Zampini 840e2ee6c50SBarry Smith lastcol = col; 84149b5e25fSSatish Balay while (high - low > 7) { 84249b5e25fSSatish Balay t = (low + high) / 2; 84349b5e25fSSatish Balay if (rp[t] > bcol) high = t; 84449b5e25fSSatish Balay else low = t; 84549b5e25fSSatish Balay } 84649b5e25fSSatish Balay for (i = low; i < high; i++) { 84749b5e25fSSatish Balay if (rp[i] > bcol) break; 84849b5e25fSSatish Balay if (rp[i] == bcol) { 84949b5e25fSSatish Balay bap = ap + bs2 * i + bs * cidx + ridx; 85049b5e25fSSatish Balay if (is == ADD_VALUES) *bap += value; 85149b5e25fSSatish Balay else *bap = value; 8528549e402SHong Zhang /* for diag block, add/insert its symmetric element a(cidx,ridx) */ 8538549e402SHong Zhang if (brow == bcol && ridx < cidx) { 8548549e402SHong Zhang bap = ap + bs2 * i + bs * ridx + cidx; 8558549e402SHong Zhang if (is == ADD_VALUES) *bap += value; 8568549e402SHong Zhang else *bap = value; 8578549e402SHong Zhang } 85849b5e25fSSatish Balay goto noinsert1; 85949b5e25fSSatish Balay } 86049b5e25fSSatish Balay } 86149b5e25fSSatish Balay 86249b5e25fSSatish Balay if (nonew == 1) goto noinsert1; 86308401ef6SPierre Jolivet PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero (%" PetscInt_FMT ", %" PetscInt_FMT ") in the matrix", row, col); 864fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, a->mbs, bs2, nrow, brow, bcol, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 86549b5e25fSSatish Balay 8669371c9d4SSatish Balay N = nrow++ - 1; 8679371c9d4SSatish Balay high++; 86849b5e25fSSatish Balay /* shift up all the later entries in this row */ 8699566063dSJacob Faibussowitsch PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1)); 8709566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap + bs2 * (i + 1), ap + bs2 * i, bs2 * (N - i + 1))); 8719566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ap + bs2 * i, bs2)); 87249b5e25fSSatish Balay rp[i] = bcol; 87349b5e25fSSatish Balay ap[bs2 * i + bs * cidx + ridx] = value; 8748509e838SStefano Zampini /* for diag block, add/insert its symmetric element a(cidx,ridx) */ 875ad540459SPierre Jolivet if (brow == bcol && ridx < cidx) ap[bs2 * i + bs * ridx + cidx] = value; 87649b5e25fSSatish Balay noinsert1:; 87749b5e25fSSatish Balay low = i; 8788549e402SHong Zhang } 87949b5e25fSSatish Balay } /* end of loop over added columns */ 88049b5e25fSSatish Balay ailen[brow] = nrow; 88149b5e25fSSatish Balay } /* end of loop over added rows */ 8823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 88349b5e25fSSatish Balay } 88449b5e25fSSatish Balay 885ba38deedSJacob Faibussowitsch static PetscErrorCode MatICCFactor_SeqSBAIJ(Mat inA, IS row, const MatFactorInfo *info) 886d71ae5a4SJacob Faibussowitsch { 8874ccecd49SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)inA->data; 88849b5e25fSSatish Balay Mat outA; 889ace3abfcSBarry Smith PetscBool row_identity; 89049b5e25fSSatish Balay 89149b5e25fSSatish Balay PetscFunctionBegin; 89208401ef6SPierre Jolivet PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 is supported for in-place icc"); 8939566063dSJacob Faibussowitsch PetscCall(ISIdentity(row, &row_identity)); 89428b400f6SJacob Faibussowitsch PetscCheck(row_identity, PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix reordering is not supported"); 89508401ef6SPierre 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()! */ 896c84f5b01SHong Zhang 89749b5e25fSSatish Balay outA = inA; 898d5f3da31SBarry Smith inA->factortype = MAT_FACTOR_ICC; 8999566063dSJacob Faibussowitsch PetscCall(PetscFree(inA->solvertype)); 9009566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype)); 90149b5e25fSSatish Balay 9029566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqSBAIJ(inA)); 9039566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetNumericFactorization_inplace(inA, row_identity)); 90449b5e25fSSatish Balay 9059566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)row)); 9069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 907c84f5b01SHong Zhang a->row = row; 9089566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)row)); 9099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 910c84f5b01SHong Zhang a->col = row; 911c84f5b01SHong Zhang 912c84f5b01SHong Zhang /* Create the invert permutation so that it can be used in MatCholeskyFactorNumeric() */ 9139566063dSJacob Faibussowitsch if (a->icol) PetscCall(ISInvertPermutation(row, PETSC_DECIDE, &a->icol)); 91449b5e25fSSatish Balay 915aa624791SPierre Jolivet if (!a->solve_work) PetscCall(PetscMalloc1(inA->rmap->N + inA->rmap->bs, &a->solve_work)); 91649b5e25fSSatish Balay 9179566063dSJacob Faibussowitsch PetscCall(MatCholeskyFactorNumeric(outA, inA, info)); 9183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 91949b5e25fSSatish Balay } 920950f1e5bSHong Zhang 921ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat, PetscInt *indices) 922d71ae5a4SJacob Faibussowitsch { 923045c9aa0SHong Zhang Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)mat->data; 92413f74950SBarry Smith PetscInt i, nz, n; 92549b5e25fSSatish Balay 92649b5e25fSSatish Balay PetscFunctionBegin; 9276c6c5352SBarry Smith nz = baij->maxnz; 928d0f46423SBarry Smith n = mat->cmap->n; 92926fbe8dcSKarl Rupp for (i = 0; i < nz; i++) baij->j[i] = indices[i]; 93026fbe8dcSKarl Rupp 9316c6c5352SBarry Smith baij->nz = nz; 93226fbe8dcSKarl Rupp for (i = 0; i < n; i++) baij->ilen[i] = baij->imax[i]; 93326fbe8dcSKarl Rupp 9349566063dSJacob Faibussowitsch PetscCall(MatSetOption(mat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 9353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 93649b5e25fSSatish Balay } 93749b5e25fSSatish Balay 93849b5e25fSSatish Balay /*@ 93919585528SSatish Balay MatSeqSBAIJSetColumnIndices - Set the column indices for all the rows 94011a5261eSBarry Smith in a `MATSEQSBAIJ` matrix. 94149b5e25fSSatish Balay 94249b5e25fSSatish Balay Input Parameters: 94311a5261eSBarry Smith + mat - the `MATSEQSBAIJ` matrix 94449b5e25fSSatish Balay - indices - the column indices 94549b5e25fSSatish Balay 94649b5e25fSSatish Balay Level: advanced 94749b5e25fSSatish Balay 94849b5e25fSSatish Balay Notes: 94949b5e25fSSatish Balay This can be called if you have precomputed the nonzero structure of the 95049b5e25fSSatish Balay matrix and want to provide it to the matrix object to improve the performance 95111a5261eSBarry Smith of the `MatSetValues()` operation. 95249b5e25fSSatish Balay 95349b5e25fSSatish Balay You MUST have set the correct numbers of nonzeros per row in the call to 95411a5261eSBarry Smith `MatCreateSeqSBAIJ()`, and the columns indices MUST be sorted. 95549b5e25fSSatish Balay 9562ef1f0ffSBarry Smith MUST be called before any calls to `MatSetValues()` 95749b5e25fSSatish Balay 9581cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreateSeqSBAIJ` 95949b5e25fSSatish Balay @*/ 960d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetColumnIndices(Mat mat, PetscInt *indices) 961d71ae5a4SJacob Faibussowitsch { 96249b5e25fSSatish Balay PetscFunctionBegin; 9630700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9644f572ea9SToby Isaac PetscAssertPointer(indices, 2); 965cac4c232SBarry Smith PetscUseMethod(mat, "MatSeqSBAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices)); 9663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 96749b5e25fSSatish Balay } 96849b5e25fSSatish Balay 969ba38deedSJacob Faibussowitsch static PetscErrorCode MatCopy_SeqSBAIJ(Mat A, Mat B, MatStructure str) 970d71ae5a4SJacob Faibussowitsch { 9714c7a3774SStefano Zampini PetscBool isbaij; 9723c896bc6SHong Zhang 9733c896bc6SHong Zhang PetscFunctionBegin; 9749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &isbaij, MATSEQSBAIJ, MATMPISBAIJ, "")); 97528b400f6SJacob Faibussowitsch PetscCheck(isbaij, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)B)->type_name); 9764c7a3774SStefano Zampini /* If the two matrices have the same copy implementation and nonzero pattern, use fast copy. */ 9774c7a3774SStefano Zampini if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) { 9783c896bc6SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 9793c896bc6SHong Zhang Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data; 9803c896bc6SHong Zhang 98108401ef6SPierre 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"); 98208401ef6SPierre Jolivet PetscCheck(a->mbs == b->mbs, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of rows in two matrices are different"); 98308401ef6SPierre Jolivet PetscCheck(a->bs2 == b->bs2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different block size"); 9849566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->a, a->a, a->bs2 * a->i[a->mbs])); 9859566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 9863c896bc6SHong Zhang } else { 9879566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(A)); 9889566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 9899566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(A)); 9903c896bc6SHong Zhang } 9913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9923c896bc6SHong Zhang } 9933c896bc6SHong Zhang 994d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJGetArray_SeqSBAIJ(Mat A, PetscScalar *array[]) 995d71ae5a4SJacob Faibussowitsch { 996a6ece127SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 9975fd66863SKarl Rupp 998a6ece127SHong Zhang PetscFunctionBegin; 999a6ece127SHong Zhang *array = a->a; 10003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1001a6ece127SHong Zhang } 1002a6ece127SHong Zhang 1003d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJRestoreArray_SeqSBAIJ(Mat A, PetscScalar *array[]) 1004d71ae5a4SJacob Faibussowitsch { 1005a6ece127SHong Zhang PetscFunctionBegin; 1006cda14afcSprj- *array = NULL; 10073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1008a6ece127SHong Zhang } 1009a6ece127SHong Zhang 1010d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPYGetPreallocation_SeqSBAIJ(Mat Y, Mat X, PetscInt *nnz) 1011d71ae5a4SJacob Faibussowitsch { 1012b264fe52SHong Zhang PetscInt bs = Y->rmap->bs, mbs = Y->rmap->N / bs; 101352768537SHong Zhang Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data; 101452768537SHong Zhang Mat_SeqSBAIJ *y = (Mat_SeqSBAIJ *)Y->data; 101552768537SHong Zhang 101652768537SHong Zhang PetscFunctionBegin; 101752768537SHong Zhang /* Set the number of nonzeros in the new matrix */ 10189566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqX_private(mbs, x->i, x->j, y->i, y->j, nnz)); 10193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 102052768537SHong Zhang } 102152768537SHong Zhang 1022ba38deedSJacob Faibussowitsch static PetscErrorCode MatAXPY_SeqSBAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str) 1023d71ae5a4SJacob Faibussowitsch { 102442ee4b1aSHong Zhang Mat_SeqSBAIJ *x = (Mat_SeqSBAIJ *)X->data, *y = (Mat_SeqSBAIJ *)Y->data; 102531ce2d13SHong Zhang PetscInt bs = Y->rmap->bs, bs2 = bs * bs; 1026e838b9e7SJed Brown PetscBLASInt one = 1; 102742ee4b1aSHong Zhang 102842ee4b1aSHong Zhang PetscFunctionBegin; 1029134adf20SPierre Jolivet if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) { 1030134adf20SPierre Jolivet PetscBool e = x->nz == y->nz && x->mbs == y->mbs ? PETSC_TRUE : PETSC_FALSE; 1031134adf20SPierre Jolivet if (e) { 10329566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->i, y->i, x->mbs + 1, &e)); 1033134adf20SPierre Jolivet if (e) { 10349566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->j, y->j, x->i[x->mbs], &e)); 1035134adf20SPierre Jolivet if (e) str = SAME_NONZERO_PATTERN; 1036134adf20SPierre Jolivet } 1037134adf20SPierre Jolivet } 103854c59aa7SJacob Faibussowitsch if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN"); 1039134adf20SPierre Jolivet } 104042ee4b1aSHong Zhang if (str == SAME_NONZERO_PATTERN) { 1041f4df32b1SMatthew Knepley PetscScalar alpha = a; 1042c5df96a5SBarry Smith PetscBLASInt bnz; 10439566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(x->nz * bs2, &bnz)); 1044792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, x->a, &one, y->a, &one)); 10459566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 1046ab784542SHong Zhang } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 10479566063dSJacob Faibussowitsch PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_TRUE)); 10489566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 10499566063dSJacob Faibussowitsch PetscCall(MatSetOption(X, MAT_GETROW_UPPERTRIANGULAR, PETSC_FALSE)); 105042ee4b1aSHong Zhang } else { 105152768537SHong Zhang Mat B; 105252768537SHong Zhang PetscInt *nnz; 105354c59aa7SJacob Faibussowitsch PetscCheck(bs == X->rmap->bs, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Matrices must have same block size"); 10549566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(X)); 10559566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(Y)); 10569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Y->rmap->N, &nnz)); 10579566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B)); 10589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name)); 10599566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, Y->rmap->n, Y->cmap->n, Y->rmap->N, Y->cmap->N)); 10609566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, Y, Y)); 10619566063dSJacob Faibussowitsch PetscCall(MatSetType(B, ((PetscObject)Y)->type_name)); 10629566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqSBAIJ(Y, X, nnz)); 10639566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz)); 106452768537SHong Zhang 10659566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 106652768537SHong Zhang 10679566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 10689566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 10699566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(X)); 10709566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(Y)); 107142ee4b1aSHong Zhang } 10723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 107342ee4b1aSHong Zhang } 107442ee4b1aSHong Zhang 1075ba38deedSJacob Faibussowitsch static PetscErrorCode MatIsStructurallySymmetric_SeqSBAIJ(Mat A, PetscBool *flg) 1076d71ae5a4SJacob Faibussowitsch { 1077efcf0fc3SBarry Smith PetscFunctionBegin; 1078efcf0fc3SBarry Smith *flg = PETSC_TRUE; 10793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1080efcf0fc3SBarry Smith } 1081efcf0fc3SBarry Smith 1082ba38deedSJacob Faibussowitsch static PetscErrorCode MatConjugate_SeqSBAIJ(Mat A) 1083d71ae5a4SJacob Faibussowitsch { 10842726fb6dSPierre Jolivet #if defined(PETSC_USE_COMPLEX) 10852726fb6dSPierre Jolivet Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 10862726fb6dSPierre Jolivet PetscInt i, nz = a->bs2 * a->i[a->mbs]; 10872726fb6dSPierre Jolivet MatScalar *aa = a->a; 10882726fb6dSPierre Jolivet 10892726fb6dSPierre Jolivet PetscFunctionBegin; 10902726fb6dSPierre Jolivet for (i = 0; i < nz; i++) aa[i] = PetscConj(aa[i]); 10912726fb6dSPierre Jolivet #else 10922726fb6dSPierre Jolivet PetscFunctionBegin; 10932726fb6dSPierre Jolivet #endif 10943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10952726fb6dSPierre Jolivet } 10962726fb6dSPierre Jolivet 1097ba38deedSJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqSBAIJ(Mat A) 1098d71ae5a4SJacob Faibussowitsch { 109999cafbc1SBarry Smith Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 110099cafbc1SBarry Smith PetscInt i, nz = a->bs2 * a->i[a->mbs]; 1101dd6ea824SBarry Smith MatScalar *aa = a->a; 110299cafbc1SBarry Smith 110399cafbc1SBarry Smith PetscFunctionBegin; 110499cafbc1SBarry Smith for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]); 11053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 110699cafbc1SBarry Smith } 110799cafbc1SBarry Smith 1108ba38deedSJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqSBAIJ(Mat A) 1109d71ae5a4SJacob Faibussowitsch { 111099cafbc1SBarry Smith Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 111199cafbc1SBarry Smith PetscInt i, nz = a->bs2 * a->i[a->mbs]; 1112dd6ea824SBarry Smith MatScalar *aa = a->a; 111399cafbc1SBarry Smith 111499cafbc1SBarry Smith PetscFunctionBegin; 111599cafbc1SBarry Smith for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]); 11163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 111799cafbc1SBarry Smith } 111899cafbc1SBarry Smith 1119ba38deedSJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_SeqSBAIJ(Mat A, PetscInt is_n, const PetscInt is_idx[], PetscScalar diag, Vec x, Vec b) 1120d71ae5a4SJacob Faibussowitsch { 11213bededecSBarry Smith Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)A->data; 11223bededecSBarry Smith PetscInt i, j, k, count; 11233bededecSBarry Smith PetscInt bs = A->rmap->bs, bs2 = baij->bs2, row, col; 11243bededecSBarry Smith PetscScalar zero = 0.0; 11253bededecSBarry Smith MatScalar *aa; 11263bededecSBarry Smith const PetscScalar *xx; 11273bededecSBarry Smith PetscScalar *bb; 112856777dd2SBarry Smith PetscBool *zeroed, vecs = PETSC_FALSE; 11293bededecSBarry Smith 11303bededecSBarry Smith PetscFunctionBegin; 1131dd8e379bSPierre Jolivet /* fix right-hand side if needed */ 11323bededecSBarry Smith if (x && b) { 11339566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 11349566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 113556777dd2SBarry Smith vecs = PETSC_TRUE; 11363bededecSBarry Smith } 11373bededecSBarry Smith 11383bededecSBarry Smith /* zero the columns */ 11399566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n, &zeroed)); 11403bededecSBarry Smith for (i = 0; i < is_n; i++) { 1141aed4548fSBarry 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]); 11423bededecSBarry Smith zeroed[is_idx[i]] = PETSC_TRUE; 11433bededecSBarry Smith } 114456777dd2SBarry Smith if (vecs) { 114556777dd2SBarry Smith for (i = 0; i < A->rmap->N; i++) { 114656777dd2SBarry Smith row = i / bs; 114756777dd2SBarry Smith for (j = baij->i[row]; j < baij->i[row + 1]; j++) { 114856777dd2SBarry Smith for (k = 0; k < bs; k++) { 114956777dd2SBarry Smith col = bs * baij->j[j] + k; 115056777dd2SBarry Smith if (col <= i) continue; 1151835f2295SStefano Zampini aa = baij->a + j * bs2 + (i % bs) + bs * k; 115226fbe8dcSKarl Rupp if (!zeroed[i] && zeroed[col]) bb[i] -= aa[0] * xx[col]; 115326fbe8dcSKarl Rupp if (zeroed[i] && !zeroed[col]) bb[col] -= aa[0] * xx[i]; 115456777dd2SBarry Smith } 115556777dd2SBarry Smith } 115656777dd2SBarry Smith } 115726fbe8dcSKarl Rupp for (i = 0; i < is_n; i++) bb[is_idx[i]] = diag * xx[is_idx[i]]; 115856777dd2SBarry Smith } 115956777dd2SBarry Smith 11603bededecSBarry Smith for (i = 0; i < A->rmap->N; i++) { 11613bededecSBarry Smith if (!zeroed[i]) { 11623bededecSBarry Smith row = i / bs; 11633bededecSBarry Smith for (j = baij->i[row]; j < baij->i[row + 1]; j++) { 11643bededecSBarry Smith for (k = 0; k < bs; k++) { 11653bededecSBarry Smith col = bs * baij->j[j] + k; 11663bededecSBarry Smith if (zeroed[col]) { 1167835f2295SStefano Zampini aa = baij->a + j * bs2 + (i % bs) + bs * k; 11683bededecSBarry Smith aa[0] = 0.0; 11693bededecSBarry Smith } 11703bededecSBarry Smith } 11713bededecSBarry Smith } 11723bededecSBarry Smith } 11733bededecSBarry Smith } 11749566063dSJacob Faibussowitsch PetscCall(PetscFree(zeroed)); 117556777dd2SBarry Smith if (vecs) { 11769566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 11779566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 117856777dd2SBarry Smith } 11793bededecSBarry Smith 11803bededecSBarry Smith /* zero the rows */ 11813bededecSBarry Smith for (i = 0; i < is_n; i++) { 11823bededecSBarry Smith row = is_idx[i]; 11833bededecSBarry Smith count = (baij->i[row / bs + 1] - baij->i[row / bs]) * bs; 1184835f2295SStefano Zampini aa = baij->a + baij->i[row / bs] * bs2 + (row % bs); 11853bededecSBarry Smith for (k = 0; k < count; k++) { 11863bededecSBarry Smith aa[0] = zero; 11873bededecSBarry Smith aa += bs; 11883bededecSBarry Smith } 1189dbbe0bcdSBarry Smith if (diag != 0.0) PetscUseTypeMethod(A, setvalues, 1, &row, 1, &row, &diag, INSERT_VALUES); 11903bededecSBarry Smith } 11919566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_SeqSBAIJ(A, MAT_FINAL_ASSEMBLY)); 11923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11933bededecSBarry Smith } 11943bededecSBarry Smith 1195ba38deedSJacob Faibussowitsch static PetscErrorCode MatShift_SeqSBAIJ(Mat Y, PetscScalar a) 1196d71ae5a4SJacob Faibussowitsch { 11977d68702bSBarry Smith Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)Y->data; 11987d68702bSBarry Smith 11997d68702bSBarry Smith PetscFunctionBegin; 120048a46eb9SPierre Jolivet if (!Y->preallocated || !aij->nz) PetscCall(MatSeqSBAIJSetPreallocation(Y, Y->rmap->bs, 1, NULL)); 12019566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(Y, a)); 12023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12037d68702bSBarry Smith } 12047d68702bSBarry Smith 120517ea310bSPierre Jolivet PetscErrorCode MatEliminateZeros_SeqSBAIJ(Mat A, PetscBool keep) 120617ea310bSPierre Jolivet { 120717ea310bSPierre Jolivet Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 120817ea310bSPierre Jolivet PetscInt fshift = 0, fshift_prev = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax, j, k; 120917ea310bSPierre Jolivet PetscInt m = A->rmap->N, *ailen = a->ilen; 121017ea310bSPierre Jolivet PetscInt mbs = a->mbs, bs2 = a->bs2, rmax = 0; 121117ea310bSPierre Jolivet MatScalar *aa = a->a, *ap; 121217ea310bSPierre Jolivet PetscBool zero; 121317ea310bSPierre Jolivet 121417ea310bSPierre Jolivet PetscFunctionBegin; 121517ea310bSPierre Jolivet PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot eliminate zeros for unassembled matrix"); 121617ea310bSPierre Jolivet if (m) rmax = ailen[0]; 121717ea310bSPierre Jolivet for (i = 1; i <= mbs; i++) { 121817ea310bSPierre Jolivet for (k = ai[i - 1]; k < ai[i]; k++) { 121917ea310bSPierre Jolivet zero = PETSC_TRUE; 122017ea310bSPierre Jolivet ap = aa + bs2 * k; 122117ea310bSPierre Jolivet for (j = 0; j < bs2 && zero; j++) { 122217ea310bSPierre Jolivet if (ap[j] != 0.0) zero = PETSC_FALSE; 122317ea310bSPierre Jolivet } 122417ea310bSPierre Jolivet if (zero && (aj[k] != i - 1 || !keep)) fshift++; 122517ea310bSPierre Jolivet else { 122617ea310bSPierre Jolivet if (zero && aj[k] == i - 1) PetscCall(PetscInfo(A, "Keep the diagonal block at row %" PetscInt_FMT "\n", i - 1)); 122717ea310bSPierre Jolivet aj[k - fshift] = aj[k]; 122817ea310bSPierre Jolivet PetscCall(PetscArraymove(ap - bs2 * fshift, ap, bs2)); 122917ea310bSPierre Jolivet } 123017ea310bSPierre Jolivet } 123117ea310bSPierre Jolivet ai[i - 1] -= fshift_prev; 123217ea310bSPierre Jolivet fshift_prev = fshift; 123317ea310bSPierre Jolivet ailen[i - 1] = imax[i - 1] = ai[i] - fshift - ai[i - 1]; 123417ea310bSPierre Jolivet a->nonzerorowcnt += ((ai[i] - fshift - ai[i - 1]) > 0); 123517ea310bSPierre Jolivet rmax = PetscMax(rmax, ailen[i - 1]); 123617ea310bSPierre Jolivet } 123717ea310bSPierre Jolivet if (fshift) { 123817ea310bSPierre Jolivet if (mbs) { 123917ea310bSPierre Jolivet ai[mbs] -= fshift; 124017ea310bSPierre Jolivet a->nz = ai[mbs]; 124117ea310bSPierre Jolivet } 124217ea310bSPierre Jolivet PetscCall(PetscInfo(A, "Matrix size: %" PetscInt_FMT " X %" PetscInt_FMT "; zeros eliminated: %" PetscInt_FMT "; nonzeros left: %" PetscInt_FMT "\n", m, A->cmap->n, fshift, a->nz)); 124317ea310bSPierre Jolivet A->nonzerostate++; 124417ea310bSPierre Jolivet A->info.nz_unneeded += (PetscReal)fshift; 124517ea310bSPierre Jolivet a->rmax = rmax; 124617ea310bSPierre Jolivet PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 124717ea310bSPierre Jolivet PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 124817ea310bSPierre Jolivet } 124917ea310bSPierre Jolivet PetscFunctionReturn(PETSC_SUCCESS); 125017ea310bSPierre Jolivet } 125117ea310bSPierre Jolivet 12523964eb88SJed Brown static struct _MatOps MatOps_Values = {MatSetValues_SeqSBAIJ, 125349b5e25fSSatish Balay MatGetRow_SeqSBAIJ, 125449b5e25fSSatish Balay MatRestoreRow_SeqSBAIJ, 125549b5e25fSSatish Balay MatMult_SeqSBAIJ_N, 125697304618SKris Buschelman /* 4*/ MatMultAdd_SeqSBAIJ_N, 1257431c96f7SBarry Smith MatMult_SeqSBAIJ_N, /* transpose versions are same as non-transpose versions */ 1258e005ede5SBarry Smith MatMultAdd_SeqSBAIJ_N, 1259f4259b30SLisandro Dalcin NULL, 1260f4259b30SLisandro Dalcin NULL, 1261f4259b30SLisandro Dalcin NULL, 1262f4259b30SLisandro Dalcin /* 10*/ NULL, 1263f4259b30SLisandro Dalcin NULL, 1264c078aec8SLisandro Dalcin MatCholeskyFactor_SeqSBAIJ, 126541f059aeSBarry Smith MatSOR_SeqSBAIJ, 126649b5e25fSSatish Balay MatTranspose_SeqSBAIJ, 126797304618SKris Buschelman /* 15*/ MatGetInfo_SeqSBAIJ, 126849b5e25fSSatish Balay MatEqual_SeqSBAIJ, 126949b5e25fSSatish Balay MatGetDiagonal_SeqSBAIJ, 127049b5e25fSSatish Balay MatDiagonalScale_SeqSBAIJ, 127149b5e25fSSatish Balay MatNorm_SeqSBAIJ, 1272f4259b30SLisandro Dalcin /* 20*/ NULL, 127349b5e25fSSatish Balay MatAssemblyEnd_SeqSBAIJ, 127449b5e25fSSatish Balay MatSetOption_SeqSBAIJ, 127549b5e25fSSatish Balay MatZeroEntries_SeqSBAIJ, 1276f4259b30SLisandro Dalcin /* 24*/ NULL, 1277f4259b30SLisandro Dalcin NULL, 1278f4259b30SLisandro Dalcin NULL, 1279f4259b30SLisandro Dalcin NULL, 1280f4259b30SLisandro Dalcin NULL, 128126cec326SBarry Smith /* 29*/ MatSetUp_Seq_Hash, 1282f4259b30SLisandro Dalcin NULL, 1283f4259b30SLisandro Dalcin NULL, 1284f4259b30SLisandro Dalcin NULL, 1285f4259b30SLisandro Dalcin NULL, 1286d519adbfSMatthew Knepley /* 34*/ MatDuplicate_SeqSBAIJ, 1287f4259b30SLisandro Dalcin NULL, 1288f4259b30SLisandro Dalcin NULL, 1289f4259b30SLisandro Dalcin NULL, 1290c84f5b01SHong Zhang MatICCFactor_SeqSBAIJ, 1291d519adbfSMatthew Knepley /* 39*/ MatAXPY_SeqSBAIJ, 12927dae84e0SHong Zhang MatCreateSubMatrices_SeqSBAIJ, 129349b5e25fSSatish Balay MatIncreaseOverlap_SeqSBAIJ, 129449b5e25fSSatish Balay MatGetValues_SeqSBAIJ, 12953c896bc6SHong Zhang MatCopy_SeqSBAIJ, 1296f4259b30SLisandro Dalcin /* 44*/ NULL, 129749b5e25fSSatish Balay MatScale_SeqSBAIJ, 12987d68702bSBarry Smith MatShift_SeqSBAIJ, 1299f4259b30SLisandro Dalcin NULL, 13003bededecSBarry Smith MatZeroRowsColumns_SeqSBAIJ, 1301f4259b30SLisandro Dalcin /* 49*/ NULL, 130249b5e25fSSatish Balay MatGetRowIJ_SeqSBAIJ, 130349b5e25fSSatish Balay MatRestoreRowIJ_SeqSBAIJ, 1304f4259b30SLisandro Dalcin NULL, 1305f4259b30SLisandro Dalcin NULL, 1306f4259b30SLisandro Dalcin /* 54*/ NULL, 1307f4259b30SLisandro Dalcin NULL, 1308f4259b30SLisandro Dalcin NULL, 1309dc29a518SPierre Jolivet MatPermute_SeqSBAIJ, 131049b5e25fSSatish Balay MatSetValuesBlocked_SeqSBAIJ, 13117dae84e0SHong Zhang /* 59*/ MatCreateSubMatrix_SeqSBAIJ, 1312f4259b30SLisandro Dalcin NULL, 1313f4259b30SLisandro Dalcin NULL, 1314f4259b30SLisandro Dalcin NULL, 1315f4259b30SLisandro Dalcin NULL, 1316f4259b30SLisandro Dalcin /* 64*/ NULL, 1317f4259b30SLisandro Dalcin NULL, 1318f4259b30SLisandro Dalcin NULL, 1319f4259b30SLisandro Dalcin NULL, 1320f4259b30SLisandro Dalcin NULL, 1321d519adbfSMatthew Knepley /* 69*/ MatGetRowMaxAbs_SeqSBAIJ, 1322f4259b30SLisandro Dalcin NULL, 132328d58a37SPierre Jolivet MatConvert_MPISBAIJ_Basic, 1324f4259b30SLisandro Dalcin NULL, 1325f4259b30SLisandro Dalcin NULL, 1326f4259b30SLisandro Dalcin /* 74*/ NULL, 1327f4259b30SLisandro Dalcin NULL, 1328f4259b30SLisandro Dalcin NULL, 1329f4259b30SLisandro Dalcin NULL, 1330f4259b30SLisandro Dalcin NULL, 1331f4259b30SLisandro Dalcin /* 79*/ NULL, 1332f4259b30SLisandro Dalcin NULL, 1333f4259b30SLisandro Dalcin NULL, 133497304618SKris Buschelman MatGetInertia_SeqSBAIJ, 13355bba2384SShri Abhyankar MatLoad_SeqSBAIJ, 13366cff0a6bSPierre Jolivet /* 84*/ NULL, 13376cff0a6bSPierre Jolivet NULL, 1338efcf0fc3SBarry Smith MatIsStructurallySymmetric_SeqSBAIJ, 1339f4259b30SLisandro Dalcin NULL, 1340f4259b30SLisandro Dalcin NULL, 1341f4259b30SLisandro Dalcin /* 89*/ NULL, 1342f4259b30SLisandro Dalcin NULL, 1343f4259b30SLisandro Dalcin NULL, 1344f4259b30SLisandro Dalcin NULL, 1345f4259b30SLisandro Dalcin NULL, 1346f4259b30SLisandro Dalcin /* 94*/ NULL, 1347f4259b30SLisandro Dalcin NULL, 1348f4259b30SLisandro Dalcin NULL, 1349f4259b30SLisandro Dalcin NULL, 1350f4259b30SLisandro Dalcin NULL, 1351f4259b30SLisandro Dalcin /* 99*/ NULL, 1352f4259b30SLisandro Dalcin NULL, 1353f4259b30SLisandro Dalcin NULL, 13542726fb6dSPierre Jolivet MatConjugate_SeqSBAIJ, 1355f4259b30SLisandro Dalcin NULL, 1356f4259b30SLisandro Dalcin /*104*/ NULL, 135799cafbc1SBarry Smith MatRealPart_SeqSBAIJ, 1358f5edf698SHong Zhang MatImaginaryPart_SeqSBAIJ, 1359f5edf698SHong Zhang MatGetRowUpperTriangular_SeqSBAIJ, 13602af78befSBarry Smith MatRestoreRowUpperTriangular_SeqSBAIJ, 1361f4259b30SLisandro Dalcin /*109*/ NULL, 1362f4259b30SLisandro Dalcin NULL, 1363f4259b30SLisandro Dalcin NULL, 1364f4259b30SLisandro Dalcin NULL, 1365547795f9SHong Zhang MatMissingDiagonal_SeqSBAIJ, 1366f4259b30SLisandro Dalcin /*114*/ NULL, 1367f4259b30SLisandro Dalcin NULL, 1368f4259b30SLisandro Dalcin NULL, 1369f4259b30SLisandro Dalcin NULL, 1370f4259b30SLisandro Dalcin NULL, 1371f4259b30SLisandro Dalcin /*119*/ NULL, 1372f4259b30SLisandro Dalcin NULL, 1373f4259b30SLisandro Dalcin NULL, 1374f4259b30SLisandro Dalcin NULL, 1375f4259b30SLisandro Dalcin NULL, 1376f4259b30SLisandro Dalcin /*124*/ NULL, 1377f4259b30SLisandro Dalcin NULL, 1378f4259b30SLisandro Dalcin NULL, 1379f4259b30SLisandro Dalcin NULL, 1380f4259b30SLisandro Dalcin NULL, 1381f4259b30SLisandro Dalcin /*129*/ NULL, 1382f4259b30SLisandro Dalcin NULL, 1383f4259b30SLisandro Dalcin NULL, 1384f4259b30SLisandro Dalcin NULL, 1385f4259b30SLisandro Dalcin NULL, 1386f4259b30SLisandro Dalcin /*134*/ NULL, 1387f4259b30SLisandro Dalcin NULL, 1388f4259b30SLisandro Dalcin NULL, 1389f4259b30SLisandro Dalcin NULL, 1390f4259b30SLisandro Dalcin NULL, 139146533700Sstefano_zampini /*139*/ MatSetBlockSizes_Default, 1392f4259b30SLisandro Dalcin NULL, 1393f4259b30SLisandro Dalcin NULL, 1394f4259b30SLisandro Dalcin NULL, 1395f4259b30SLisandro Dalcin NULL, 1396d70f29a3SPierre Jolivet /*144*/ MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ, 1397d70f29a3SPierre Jolivet NULL, 1398d70f29a3SPierre Jolivet NULL, 139999a7f59eSMark Adams NULL, 140099a7f59eSMark Adams NULL, 14017fb60732SBarry Smith NULL, 1402dec0b466SHong Zhang /*150*/ NULL, 1403eede4a3fSMark Adams MatEliminateZeros_SeqSBAIJ, 14044cc2b5b5SPierre Jolivet NULL, 140542ce410bSJunchao Zhang NULL, 140642ce410bSJunchao Zhang NULL, 1407fe1fc275SAlexander /*155*/ NULL, 1408fe1fc275SAlexander MatCopyHashToXAIJ_Seq_Hash}; 1409be1d678aSKris Buschelman 1410ba38deedSJacob Faibussowitsch static PetscErrorCode MatStoreValues_SeqSBAIJ(Mat mat) 1411d71ae5a4SJacob Faibussowitsch { 14124afc71dfSHong Zhang Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data; 1413d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2; 141449b5e25fSSatish Balay 141549b5e25fSSatish Balay PetscFunctionBegin; 141608401ef6SPierre Jolivet PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 141749b5e25fSSatish Balay 141849b5e25fSSatish Balay /* allocate space for values if not already there */ 141948a46eb9SPierre Jolivet if (!aij->saved_values) PetscCall(PetscMalloc1(nz + 1, &aij->saved_values)); 142049b5e25fSSatish Balay 142149b5e25fSSatish Balay /* copy values over */ 14229566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz)); 14233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 142449b5e25fSSatish Balay } 142549b5e25fSSatish Balay 1426ba38deedSJacob Faibussowitsch static PetscErrorCode MatRetrieveValues_SeqSBAIJ(Mat mat) 1427d71ae5a4SJacob Faibussowitsch { 14284afc71dfSHong Zhang Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data; 1429d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2; 143049b5e25fSSatish Balay 143149b5e25fSSatish Balay PetscFunctionBegin; 143208401ef6SPierre Jolivet PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 143328b400f6SJacob Faibussowitsch PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first"); 143449b5e25fSSatish Balay 143549b5e25fSSatish Balay /* copy values over */ 14369566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz)); 14373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 143849b5e25fSSatish Balay } 143949b5e25fSSatish Balay 1440f9663b93SPierre Jolivet static PetscErrorCode MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[]) 1441d71ae5a4SJacob Faibussowitsch { 1442c464158bSHong Zhang Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data; 14434dcd73b1SHong Zhang PetscInt i, mbs, nbs, bs2; 14442576faa2SJed Brown PetscBool skipallocation = PETSC_FALSE, flg = PETSC_FALSE, realalloc = PETSC_FALSE; 144549b5e25fSSatish Balay 1446b4e2f619SBarry Smith PetscFunctionBegin; 1447ad79cf63SBarry Smith if (B->hash_active) { 1448ad79cf63SBarry Smith PetscInt bs; 1449aea10558SJacob Faibussowitsch B->ops[0] = b->cops; 1450ad79cf63SBarry Smith PetscCall(PetscHMapIJVDestroy(&b->ht)); 1451ad79cf63SBarry Smith PetscCall(MatGetBlockSize(B, &bs)); 1452ad79cf63SBarry Smith if (bs > 1) PetscCall(PetscHSetIJDestroy(&b->bht)); 1453ad79cf63SBarry Smith PetscCall(PetscFree(b->dnz)); 1454ad79cf63SBarry Smith PetscCall(PetscFree(b->bdnz)); 1455ad79cf63SBarry Smith B->hash_active = PETSC_FALSE; 1456ad79cf63SBarry Smith } 14572576faa2SJed Brown if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 1458db4efbfdSBarry Smith 145958b7e2c1SStefano Zampini PetscCall(MatSetBlockSize(B, bs)); 14609566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 14619566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 146208401ef6SPierre 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); 14639566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs)); 1464899cda47SBarry Smith 146521940c7eSstefano_zampini B->preallocated = PETSC_TRUE; 146621940c7eSstefano_zampini 1467d0f46423SBarry Smith mbs = B->rmap->N / bs; 14684dcd73b1SHong Zhang nbs = B->cmap->n / bs; 146949b5e25fSSatish Balay bs2 = bs * bs; 147049b5e25fSSatish Balay 1471aed4548fSBarry 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"); 147249b5e25fSSatish Balay 1473ab93d7beSBarry Smith if (nz == MAT_SKIP_ALLOCATION) { 1474ab93d7beSBarry Smith skipallocation = PETSC_TRUE; 1475ab93d7beSBarry Smith nz = 0; 1476ab93d7beSBarry Smith } 1477ab93d7beSBarry Smith 1478435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3; 147908401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz); 148049b5e25fSSatish Balay if (nnz) { 148149b5e25fSSatish Balay for (i = 0; i < mbs; i++) { 148208401ef6SPierre 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]); 148308401ef6SPierre 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); 148449b5e25fSSatish Balay } 148549b5e25fSSatish Balay } 148649b5e25fSSatish Balay 1487db4efbfdSBarry Smith B->ops->mult = MatMult_SeqSBAIJ_N; 1488db4efbfdSBarry Smith B->ops->multadd = MatMultAdd_SeqSBAIJ_N; 1489db4efbfdSBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_N; 1490db4efbfdSBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N; 149126fbe8dcSKarl Rupp 14929566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL)); 149349b5e25fSSatish Balay if (!flg) { 149449b5e25fSSatish Balay switch (bs) { 149549b5e25fSSatish Balay case 1: 149649b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_1; 149749b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_1; 1498431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_1; 1499431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1; 150049b5e25fSSatish Balay break; 150149b5e25fSSatish Balay case 2: 150249b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_2; 150349b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_2; 1504431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_2; 1505431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2; 150649b5e25fSSatish Balay break; 150749b5e25fSSatish Balay case 3: 150849b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_3; 150949b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_3; 1510431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_3; 1511431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3; 151249b5e25fSSatish Balay break; 151349b5e25fSSatish Balay case 4: 151449b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_4; 151549b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_4; 1516431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_4; 1517431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4; 151849b5e25fSSatish Balay break; 151949b5e25fSSatish Balay case 5: 152049b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_5; 152149b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_5; 1522431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_5; 1523431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5; 152449b5e25fSSatish Balay break; 152549b5e25fSSatish Balay case 6: 152649b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_6; 152749b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_6; 1528431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_6; 1529431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6; 153049b5e25fSSatish Balay break; 153149b5e25fSSatish Balay case 7: 1532de53e5efSHong Zhang B->ops->mult = MatMult_SeqSBAIJ_7; 153349b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_7; 1534431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_7; 1535431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7; 153649b5e25fSSatish Balay break; 153749b5e25fSSatish Balay } 153849b5e25fSSatish Balay } 153949b5e25fSSatish Balay 154049b5e25fSSatish Balay b->mbs = mbs; 15414dcd73b1SHong Zhang b->nbs = nbs; 1542ab93d7beSBarry Smith if (!skipallocation) { 15432ee49352SLisandro Dalcin if (!b->imax) { 15449566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(mbs, &b->imax, mbs, &b->ilen)); 154526fbe8dcSKarl Rupp 1546c760cd28SBarry Smith b->free_imax_ilen = PETSC_TRUE; 15472ee49352SLisandro Dalcin } 154849b5e25fSSatish Balay if (!nnz) { 1549435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 155049b5e25fSSatish Balay else if (nz <= 0) nz = 1; 15515d2a9ed1SStefano Zampini nz = PetscMin(nbs, nz); 155226fbe8dcSKarl Rupp for (i = 0; i < mbs; i++) b->imax[i] = nz; 15539566063dSJacob Faibussowitsch PetscCall(PetscIntMultError(nz, mbs, &nz)); 155449b5e25fSSatish Balay } else { 1555c73702f5SBarry Smith PetscInt64 nz64 = 0; 15569371c9d4SSatish Balay for (i = 0; i < mbs; i++) { 15579371c9d4SSatish Balay b->imax[i] = nnz[i]; 15589371c9d4SSatish Balay nz64 += nnz[i]; 15599371c9d4SSatish Balay } 15609566063dSJacob Faibussowitsch PetscCall(PetscIntCast(nz64, &nz)); 156149b5e25fSSatish Balay } 15622ee49352SLisandro Dalcin /* b->ilen will count nonzeros in each block row so far. */ 156326fbe8dcSKarl Rupp for (i = 0; i < mbs; i++) b->ilen[i] = 0; 15646c6c5352SBarry Smith /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */ 156549b5e25fSSatish Balay 156649b5e25fSSatish Balay /* allocate the matrix space */ 15679566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i)); 15689f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(bs2 * nz, sizeof(PetscScalar), (void **)&b->a)); 15699f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&b->j)); 15709f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(B->rmap->n + 1, sizeof(PetscInt), (void **)&b->i)); 15719f0612e4SBarry Smith b->free_a = PETSC_TRUE; 15729f0612e4SBarry Smith b->free_ij = PETSC_TRUE; 15739566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(b->a, nz * bs2)); 15749566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(b->j, nz)); 15759f0612e4SBarry Smith b->free_a = PETSC_TRUE; 15769f0612e4SBarry Smith b->free_ij = PETSC_TRUE; 157749b5e25fSSatish Balay 157849b5e25fSSatish Balay /* pointer to beginning of each row */ 1579e60cf9a0SBarry Smith b->i[0] = 0; 158026fbe8dcSKarl Rupp for (i = 1; i < mbs + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1]; 158126fbe8dcSKarl Rupp 1582e811da20SHong Zhang } else { 1583e6b907acSBarry Smith b->free_a = PETSC_FALSE; 1584e6b907acSBarry Smith b->free_ij = PETSC_FALSE; 1585ab93d7beSBarry Smith } 158649b5e25fSSatish Balay 158749b5e25fSSatish Balay b->bs2 = bs2; 15886c6c5352SBarry Smith b->nz = 0; 1589b32cb4a7SJed Brown b->maxnz = nz; 1590f4259b30SLisandro Dalcin b->inew = NULL; 1591f4259b30SLisandro Dalcin b->jnew = NULL; 1592f4259b30SLisandro Dalcin b->anew = NULL; 1593f4259b30SLisandro Dalcin b->a2anew = NULL; 15941a3463dfSHong Zhang b->permute = PETSC_FALSE; 1595cb7b82ddSBarry Smith 1596cb7b82ddSBarry Smith B->was_assembled = PETSC_FALSE; 1597cb7b82ddSBarry Smith B->assembled = PETSC_FALSE; 15989566063dSJacob Faibussowitsch if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 15993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1600c464158bSHong Zhang } 1601153ea458SHong Zhang 1602ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ(Mat B, PetscInt bs, const PetscInt ii[], const PetscInt jj[], const PetscScalar V[]) 1603d71ae5a4SJacob Faibussowitsch { 16040cd7f59aSBarry Smith PetscInt i, j, m, nz, anz, nz_max = 0, *nnz; 1605f4259b30SLisandro Dalcin PetscScalar *values = NULL; 16061c466ed6SStefano Zampini Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data; 16071c466ed6SStefano Zampini PetscBool roworiented = b->roworiented; 16081c466ed6SStefano Zampini PetscBool ilw = b->ignore_ltriangular; 16090cd7f59aSBarry Smith 161038f409ebSLisandro Dalcin PetscFunctionBegin; 161108401ef6SPierre Jolivet PetscCheck(bs >= 1, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_OUTOFRANGE, "Invalid block size specified, must be positive but it is %" PetscInt_FMT, bs); 16129566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(B->rmap, bs)); 16139566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(B->cmap, bs)); 16149566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 16159566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 16169566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs)); 161738f409ebSLisandro Dalcin m = B->rmap->n / bs; 161838f409ebSLisandro Dalcin 1619aed4548fSBarry Smith PetscCheck(!ii[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ii[0] must be 0 but it is %" PetscInt_FMT, ii[0]); 16209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nnz)); 162138f409ebSLisandro Dalcin for (i = 0; i < m; i++) { 162238f409ebSLisandro Dalcin nz = ii[i + 1] - ii[i]; 162308401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz); 16241c466ed6SStefano Zampini PetscCheckSorted(nz, jj + ii[i]); 16250cd7f59aSBarry Smith anz = 0; 16260cd7f59aSBarry Smith for (j = 0; j < nz; j++) { 16270cd7f59aSBarry Smith /* count only values on the diagonal or above */ 16280cd7f59aSBarry Smith if (jj[ii[i] + j] >= i) { 16290cd7f59aSBarry Smith anz = nz - j; 16300cd7f59aSBarry Smith break; 16310cd7f59aSBarry Smith } 16320cd7f59aSBarry Smith } 16331c466ed6SStefano Zampini nz_max = PetscMax(nz_max, nz); 16340cd7f59aSBarry Smith nnz[i] = anz; 163538f409ebSLisandro Dalcin } 16369566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz)); 16379566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 163838f409ebSLisandro Dalcin 163938f409ebSLisandro Dalcin values = (PetscScalar *)V; 164048a46eb9SPierre Jolivet if (!values) PetscCall(PetscCalloc1(bs * bs * nz_max, &values)); 16411c466ed6SStefano Zampini b->ignore_ltriangular = PETSC_TRUE; 164238f409ebSLisandro Dalcin for (i = 0; i < m; i++) { 164338f409ebSLisandro Dalcin PetscInt ncols = ii[i + 1] - ii[i]; 164438f409ebSLisandro Dalcin const PetscInt *icols = jj + ii[i]; 16451c466ed6SStefano Zampini 164638f409ebSLisandro Dalcin if (!roworiented || bs == 1) { 164738f409ebSLisandro Dalcin const PetscScalar *svals = values + (V ? (bs * bs * ii[i]) : 0); 16489566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, ncols, icols, svals, INSERT_VALUES)); 164938f409ebSLisandro Dalcin } else { 165038f409ebSLisandro Dalcin for (j = 0; j < ncols; j++) { 165138f409ebSLisandro Dalcin const PetscScalar *svals = values + (V ? (bs * bs * (ii[i] + j)) : 0); 16529566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, 1, &icols[j], svals, INSERT_VALUES)); 165338f409ebSLisandro Dalcin } 165438f409ebSLisandro Dalcin } 165538f409ebSLisandro Dalcin } 16569566063dSJacob Faibussowitsch if (!V) PetscCall(PetscFree(values)); 16579566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 16589566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 16599566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 16601c466ed6SStefano Zampini b->ignore_ltriangular = ilw; 16613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 166238f409ebSLisandro Dalcin } 166338f409ebSLisandro Dalcin 1664db4efbfdSBarry Smith /* 1665db4efbfdSBarry Smith This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization 1666db4efbfdSBarry Smith */ 1667d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetNumericFactorization_inplace(Mat B, PetscBool natural) 1668d71ae5a4SJacob Faibussowitsch { 1669ace3abfcSBarry Smith PetscBool flg = PETSC_FALSE; 1670db4efbfdSBarry Smith PetscInt bs = B->rmap->bs; 1671db4efbfdSBarry Smith 1672db4efbfdSBarry Smith PetscFunctionBegin; 16739566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL)); 1674db4efbfdSBarry Smith if (flg) bs = 8; 1675db4efbfdSBarry Smith 1676db4efbfdSBarry Smith if (!natural) { 1677db4efbfdSBarry Smith switch (bs) { 1678d71ae5a4SJacob Faibussowitsch case 1: 1679d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_inplace; 1680d71ae5a4SJacob Faibussowitsch break; 1681d71ae5a4SJacob Faibussowitsch case 2: 1682d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2; 1683d71ae5a4SJacob Faibussowitsch break; 1684d71ae5a4SJacob Faibussowitsch case 3: 1685d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3; 1686d71ae5a4SJacob Faibussowitsch break; 1687d71ae5a4SJacob Faibussowitsch case 4: 1688d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4; 1689d71ae5a4SJacob Faibussowitsch break; 1690d71ae5a4SJacob Faibussowitsch case 5: 1691d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5; 1692d71ae5a4SJacob Faibussowitsch break; 1693d71ae5a4SJacob Faibussowitsch case 6: 1694d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6; 1695d71ae5a4SJacob Faibussowitsch break; 1696d71ae5a4SJacob Faibussowitsch case 7: 1697d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7; 1698d71ae5a4SJacob Faibussowitsch break; 1699d71ae5a4SJacob Faibussowitsch default: 1700d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N; 1701d71ae5a4SJacob Faibussowitsch break; 1702db4efbfdSBarry Smith } 1703db4efbfdSBarry Smith } else { 1704db4efbfdSBarry Smith switch (bs) { 1705d71ae5a4SJacob Faibussowitsch case 1: 1706d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering_inplace; 1707d71ae5a4SJacob Faibussowitsch break; 1708d71ae5a4SJacob Faibussowitsch case 2: 1709d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering; 1710d71ae5a4SJacob Faibussowitsch break; 1711d71ae5a4SJacob Faibussowitsch case 3: 1712d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering; 1713d71ae5a4SJacob Faibussowitsch break; 1714d71ae5a4SJacob Faibussowitsch case 4: 1715d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering; 1716d71ae5a4SJacob Faibussowitsch break; 1717d71ae5a4SJacob Faibussowitsch case 5: 1718d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering; 1719d71ae5a4SJacob Faibussowitsch break; 1720d71ae5a4SJacob Faibussowitsch case 6: 1721d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering; 1722d71ae5a4SJacob Faibussowitsch break; 1723d71ae5a4SJacob Faibussowitsch case 7: 1724d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering; 1725d71ae5a4SJacob Faibussowitsch break; 1726d71ae5a4SJacob Faibussowitsch default: 1727d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering; 1728d71ae5a4SJacob Faibussowitsch break; 1729db4efbfdSBarry Smith } 1730db4efbfdSBarry Smith } 17313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1732db4efbfdSBarry Smith } 1733db4efbfdSBarry Smith 1734cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType, MatReuse, Mat *); 1735cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType, MatReuse, Mat *); 1736d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatFactorGetSolverType_petsc(Mat A, MatSolverType *type) 1737d71ae5a4SJacob Faibussowitsch { 17384ac6704cSBarry Smith PetscFunctionBegin; 17394ac6704cSBarry Smith *type = MATSOLVERPETSC; 17403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17414ac6704cSBarry Smith } 1742d769727bSBarry Smith 1743d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A, MatFactorType ftype, Mat *B) 1744d71ae5a4SJacob Faibussowitsch { 1745d0f46423SBarry Smith PetscInt n = A->rmap->n; 17465c9eb25fSBarry Smith 17475c9eb25fSBarry Smith PetscFunctionBegin; 17480e92d65fSHong Zhang #if defined(PETSC_USE_COMPLEX) 174903e5aca4SStefano Zampini if ((ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) && A->hermitian == PETSC_BOOL3_TRUE && A->symmetric != PETSC_BOOL3_TRUE) { 175003e5aca4SStefano Zampini PetscCall(PetscInfo(A, "Hermitian MAT_FACTOR_CHOLESKY or MAT_FACTOR_ICC are not supported. Use MAT_FACTOR_LU instead.\n")); 175103e5aca4SStefano Zampini *B = NULL; 175203e5aca4SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 175303e5aca4SStefano Zampini } 17540e92d65fSHong Zhang #endif 1755eb1ec7c1SStefano Zampini 17569566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 17579566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, n, n, n, n)); 17585c9eb25fSBarry Smith if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) { 17599566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, MATSEQSBAIJ)); 17609566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(*B, A->rmap->bs, MAT_SKIP_ALLOCATION, NULL)); 176126fbe8dcSKarl Rupp 17627b056e98SHong Zhang (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ; 1763c6d0d4f0SHong Zhang (*B)->ops->iccfactorsymbolic = MatICCFactorSymbolic_SeqSBAIJ; 17649566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_CHOLESKY])); 17659566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_ICC])); 1766e32f2f54SBarry Smith } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Factor type not supported"); 176700c67f3bSHong Zhang 1768d5f3da31SBarry Smith (*B)->factortype = ftype; 1769f73b0415SBarry Smith (*B)->canuseordering = PETSC_TRUE; 17709566063dSJacob Faibussowitsch PetscCall(PetscFree((*B)->solvertype)); 17719566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*B)->solvertype)); 17729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)*B, "MatFactorGetSolverType_C", MatFactorGetSolverType_petsc)); 17733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17745c9eb25fSBarry Smith } 17755c9eb25fSBarry Smith 17768397e458SBarry Smith /*@C 17772ef1f0ffSBarry Smith MatSeqSBAIJGetArray - gives access to the array where the numerical data for a `MATSEQSBAIJ` matrix is stored 17788397e458SBarry Smith 17798397e458SBarry Smith Not Collective 17808397e458SBarry Smith 17818397e458SBarry Smith Input Parameter: 1782fe59aa6dSJacob Faibussowitsch . A - a `MATSEQSBAIJ` matrix 17838397e458SBarry Smith 17848397e458SBarry Smith Output Parameter: 17858397e458SBarry Smith . array - pointer to the data 17868397e458SBarry Smith 17878397e458SBarry Smith Level: intermediate 17888397e458SBarry Smith 17891cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatSeqSBAIJRestoreArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()` 17908397e458SBarry Smith @*/ 17915d83a8b1SBarry Smith PetscErrorCode MatSeqSBAIJGetArray(Mat A, PetscScalar *array[]) 1792d71ae5a4SJacob Faibussowitsch { 17938397e458SBarry Smith PetscFunctionBegin; 1794cac4c232SBarry Smith PetscUseMethod(A, "MatSeqSBAIJGetArray_C", (Mat, PetscScalar **), (A, array)); 17953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17968397e458SBarry Smith } 17978397e458SBarry Smith 17988397e458SBarry Smith /*@C 17992ef1f0ffSBarry Smith MatSeqSBAIJRestoreArray - returns access to the array where the numerical data for a `MATSEQSBAIJ` matrix is stored obtained by `MatSeqSBAIJGetArray()` 18008397e458SBarry Smith 18018397e458SBarry Smith Not Collective 18028397e458SBarry Smith 18038397e458SBarry Smith Input Parameters: 1804fe59aa6dSJacob Faibussowitsch + A - a `MATSEQSBAIJ` matrix 1805a2b725a8SWilliam Gropp - array - pointer to the data 18068397e458SBarry Smith 18078397e458SBarry Smith Level: intermediate 18088397e458SBarry Smith 18091cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatSeqSBAIJGetArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()` 18108397e458SBarry Smith @*/ 18115d83a8b1SBarry Smith PetscErrorCode MatSeqSBAIJRestoreArray(Mat A, PetscScalar *array[]) 1812d71ae5a4SJacob Faibussowitsch { 18138397e458SBarry Smith PetscFunctionBegin; 1814cac4c232SBarry Smith PetscUseMethod(A, "MatSeqSBAIJRestoreArray_C", (Mat, PetscScalar **), (A, array)); 18153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18168397e458SBarry Smith } 18178397e458SBarry Smith 18180bad9183SKris Buschelman /*MC 1819fafad747SKris Buschelman MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices, 18200bad9183SKris Buschelman based on block compressed sparse row format. Only the upper triangular portion of the matrix is stored. 18210bad9183SKris Buschelman 1822828413b8SBarry Smith For complex numbers by default this matrix is symmetric, NOT Hermitian symmetric. To make it Hermitian symmetric you 182311a5261eSBarry Smith can call `MatSetOption`(`Mat`, `MAT_HERMITIAN`). 1824828413b8SBarry Smith 18252ef1f0ffSBarry Smith Options Database Key: 182611a5261eSBarry Smith . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to `MatSetFromOptions()` 18270bad9183SKris Buschelman 18282ef1f0ffSBarry Smith Level: beginner 18292ef1f0ffSBarry Smith 183095452b02SPatrick Sanan Notes: 183195452b02SPatrick Sanan By default if you insert values into the lower triangular part of the matrix they are simply ignored (since they are not 183211a5261eSBarry 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 18332ef1f0ffSBarry 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. 183471dad5bbSBarry Smith 1835476417e5SBarry Smith The number of rows in the matrix must be less than or equal to the number of columns 183671dad5bbSBarry Smith 18371cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreateSeqSBAIJ()`, `MatType`, `MATMPISBAIJ` 18380bad9183SKris Buschelman M*/ 1839d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_SeqSBAIJ(Mat B) 1840d71ae5a4SJacob Faibussowitsch { 1841a23d5eceSKris Buschelman Mat_SeqSBAIJ *b; 184213f74950SBarry Smith PetscMPIInt size; 1843ace3abfcSBarry Smith PetscBool no_unroll = PETSC_FALSE, no_inode = PETSC_FALSE; 1844a23d5eceSKris Buschelman 1845a23d5eceSKris Buschelman PetscFunctionBegin; 18469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size)); 184708401ef6SPierre Jolivet PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1"); 1848a23d5eceSKris Buschelman 18494dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&b)); 1850a23d5eceSKris Buschelman B->data = (void *)b; 1851aea10558SJacob Faibussowitsch B->ops[0] = MatOps_Values; 185226fbe8dcSKarl Rupp 1853a23d5eceSKris Buschelman B->ops->destroy = MatDestroy_SeqSBAIJ; 1854a23d5eceSKris Buschelman B->ops->view = MatView_SeqSBAIJ; 1855f4259b30SLisandro Dalcin b->row = NULL; 1856f4259b30SLisandro Dalcin b->icol = NULL; 1857a23d5eceSKris Buschelman b->reallocs = 0; 1858f4259b30SLisandro Dalcin b->saved_values = NULL; 18590def2e27SBarry Smith b->inode.limit = 5; 18600def2e27SBarry Smith b->inode.max_limit = 5; 1861a23d5eceSKris Buschelman 1862a23d5eceSKris Buschelman b->roworiented = PETSC_TRUE; 1863a23d5eceSKris Buschelman b->nonew = 0; 1864f4259b30SLisandro Dalcin b->diag = NULL; 1865f4259b30SLisandro Dalcin b->solve_work = NULL; 1866f4259b30SLisandro Dalcin b->mult_work = NULL; 1867f4259b30SLisandro Dalcin B->spptr = NULL; 1868f2cbd3d5SJed Brown B->info.nz_unneeded = (PetscReal)b->maxnz * b->bs2; 1869a9817697SBarry Smith b->keepnonzeropattern = PETSC_FALSE; 1870a23d5eceSKris Buschelman 1871f4259b30SLisandro Dalcin b->inew = NULL; 1872f4259b30SLisandro Dalcin b->jnew = NULL; 1873f4259b30SLisandro Dalcin b->anew = NULL; 1874f4259b30SLisandro Dalcin b->a2anew = NULL; 1875a23d5eceSKris Buschelman b->permute = PETSC_FALSE; 1876a23d5eceSKris Buschelman 187771dad5bbSBarry Smith b->ignore_ltriangular = PETSC_TRUE; 187826fbe8dcSKarl Rupp 18799566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_ignore_lower_triangular", &b->ignore_ltriangular, NULL)); 1880941593c8SHong Zhang 1881f5edf698SHong Zhang b->getrow_utriangular = PETSC_FALSE; 188226fbe8dcSKarl Rupp 18839566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_getrow_uppertriangular", &b->getrow_utriangular, NULL)); 1884f5edf698SHong Zhang 18859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJGetArray_C", MatSeqSBAIJGetArray_SeqSBAIJ)); 18869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJRestoreArray_C", MatSeqSBAIJRestoreArray_SeqSBAIJ)); 18879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqSBAIJ)); 18889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqSBAIJ)); 18899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetColumnIndices_C", MatSeqSBAIJSetColumnIndices_SeqSBAIJ)); 18909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqaij_C", MatConvert_SeqSBAIJ_SeqAIJ)); 18919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqbaij_C", MatConvert_SeqSBAIJ_SeqBAIJ)); 18929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocation_C", MatSeqSBAIJSetPreallocation_SeqSBAIJ)); 18939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocationCSR_C", MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ)); 18946214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 18959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_elemental_C", MatConvert_SeqSBAIJ_Elemental)); 18966214f412SHong Zhang #endif 1897d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 18989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_scalapack_C", MatConvert_SBAIJ_ScaLAPACK)); 1899d24d4204SJose E. Roman #endif 190023ce1328SBarry Smith 1901b94d7dedSBarry Smith B->symmetry_eternal = PETSC_TRUE; 1902b94d7dedSBarry Smith B->structural_symmetry_eternal = PETSC_TRUE; 1903b94d7dedSBarry Smith B->symmetric = PETSC_BOOL3_TRUE; 1904b94d7dedSBarry Smith B->structurally_symmetric = PETSC_BOOL3_TRUE; 1905eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 1906b94d7dedSBarry Smith B->hermitian = PETSC_BOOL3_FALSE; 1907eb1ec7c1SStefano Zampini #else 1908b94d7dedSBarry Smith B->hermitian = PETSC_BOOL3_TRUE; 1909eb1ec7c1SStefano Zampini #endif 191013647f61SHong Zhang 19119566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQSBAIJ)); 19120def2e27SBarry Smith 1913d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)B), ((PetscObject)B)->prefix, "Options for SEQSBAIJ matrix", "Mat"); 19149566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-mat_no_unroll", "Do not optimize for inodes (slower)", NULL, no_unroll, &no_unroll, NULL)); 191548a46eb9SPierre Jolivet if (no_unroll) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_unroll\n")); 19169566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-mat_no_inode", "Do not optimize for inodes (slower)", NULL, no_inode, &no_inode, NULL)); 19179566063dSJacob Faibussowitsch if (no_inode) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_inode\n")); 1918*e87b5d96SPierre Jolivet PetscCall(PetscOptionsInt("-mat_inode_limit", "Do not use inodes larger than this value", NULL, b->inode.limit, &b->inode.limit, NULL)); 1919d0609cedSBarry Smith PetscOptionsEnd(); 1920ace3abfcSBarry Smith b->inode.use = (PetscBool)(!(no_unroll || no_inode)); 19210def2e27SBarry Smith if (b->inode.limit > b->inode.max_limit) b->inode.limit = b->inode.max_limit; 19223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1923a23d5eceSKris Buschelman } 1924a23d5eceSKris Buschelman 19255d83a8b1SBarry Smith /*@ 1926a23d5eceSKris Buschelman MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block 192711a5261eSBarry Smith compressed row) `MATSEQSBAIJ` format. For good matrix assembly performance the 192820f4b53cSBarry Smith user should preallocate the matrix storage by setting the parameter `nz` 192920f4b53cSBarry Smith (or the array `nnz`). 1930a23d5eceSKris Buschelman 1931c3339decSBarry Smith Collective 1932a23d5eceSKris Buschelman 1933a23d5eceSKris Buschelman Input Parameters: 19341c4f3114SJed Brown + B - the symmetric matrix 193511a5261eSBarry 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 193611a5261eSBarry Smith blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with `MatCreateVecs()` 1937a23d5eceSKris Buschelman . nz - number of block nonzeros per block row (same for all rows) 1938a23d5eceSKris Buschelman - nnz - array containing the number of block nonzeros in the upper triangular plus 19392ef1f0ffSBarry Smith diagonal portion of each block (possibly different for each block row) or `NULL` 1940a23d5eceSKris Buschelman 1941a23d5eceSKris Buschelman Options Database Keys: 1942d8a51d2aSBarry Smith + -mat_no_unroll - uses code that does not unroll the loops in the block calculations (much slower) 1943a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use (only works if a negative bs is passed in 1944a23d5eceSKris Buschelman 1945a23d5eceSKris Buschelman Level: intermediate 1946a23d5eceSKris Buschelman 1947a23d5eceSKris Buschelman Notes: 194820f4b53cSBarry Smith Specify the preallocated storage with either `nz` or `nnz` (not both). 19492ef1f0ffSBarry Smith Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory 1950651615e1SBarry Smith allocation. See [Sparse Matrices](sec_matsparse) for details. 1951a23d5eceSKris Buschelman 195211a5261eSBarry Smith You can call `MatGetInfo()` to get information on how effective the preallocation was; 1953aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 19542ef1f0ffSBarry Smith You can also run with the option `-info` and look for messages with the string 1955aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 1956aa95bbe8SBarry Smith 19572ef1f0ffSBarry Smith If the `nnz` parameter is given then the `nz` parameter is ignored 195849a6f317SBarry Smith 19591cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()` 1960a23d5eceSKris Buschelman @*/ 1961d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetPreallocation(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[]) 1962d71ae5a4SJacob Faibussowitsch { 1963a23d5eceSKris Buschelman PetscFunctionBegin; 19646ba663aaSJed Brown PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 19656ba663aaSJed Brown PetscValidType(B, 1); 19666ba663aaSJed Brown PetscValidLogicalCollectiveInt(B, bs, 2); 1967cac4c232SBarry Smith PetscTryMethod(B, "MatSeqSBAIJSetPreallocation_C", (Mat, PetscInt, PetscInt, const PetscInt[]), (B, bs, nz, nnz)); 19683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1969a23d5eceSKris Buschelman } 197049b5e25fSSatish Balay 197138f409ebSLisandro Dalcin /*@C 197211a5261eSBarry Smith MatSeqSBAIJSetPreallocationCSR - Creates a sparse parallel matrix in `MATSEQSBAIJ` format using the given nonzero structure and (optional) numerical values 197338f409ebSLisandro Dalcin 197438f409ebSLisandro Dalcin Input Parameters: 19751c4f3114SJed Brown + B - the matrix 1976eab78319SHong Zhang . bs - size of block, the blocks are ALWAYS square. 1977d8a51d2aSBarry Smith . i - the indices into `j` for the start of each local row (indices start with zero) 1978d8a51d2aSBarry Smith . j - the column indices for each local row (indices start with zero) these must be sorted for each row 1979d8a51d2aSBarry Smith - v - optional values in the matrix, use `NULL` if not provided 198038f409ebSLisandro Dalcin 1981664954b6SBarry Smith Level: advanced 198238f409ebSLisandro Dalcin 198338f409ebSLisandro Dalcin Notes: 1984d8a51d2aSBarry Smith The `i`,`j`,`v` values are COPIED with this routine; to avoid the copy use `MatCreateSeqSBAIJWithArrays()` 1985d8a51d2aSBarry Smith 198611a5261eSBarry Smith The order of the entries in values is specified by the `MatOption` `MAT_ROW_ORIENTED`. For example, C programs 198711a5261eSBarry Smith may want to use the default `MAT_ROW_ORIENTED` = `PETSC_TRUE` and use an array v[nnz][bs][bs] where the second index is 198838f409ebSLisandro Dalcin over rows within a block and the last index is over columns within a block row. Fortran programs will likely set 198911a5261eSBarry Smith `MAT_ROW_ORIENTED` = `PETSC_FALSE` and use a Fortran array v(bs,bs,nnz) in which the first index is over rows within a 199038f409ebSLisandro Dalcin block column and the second index is over columns within a block. 199138f409ebSLisandro Dalcin 1992d8a51d2aSBarry Smith Any entries provided that lie below the diagonal are ignored 19930cd7f59aSBarry Smith 19940cd7f59aSBarry Smith Though this routine has Preallocation() in the name it also sets the exact nonzero locations of the matrix entries 19950cd7f59aSBarry Smith and usually the numerical values as well 1996664954b6SBarry Smith 1997fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqSBAIJ()`, `MatSetValuesBlocked()`, `MatSeqSBAIJSetPreallocation()` 199838f409ebSLisandro Dalcin @*/ 1999d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetPreallocationCSR(Mat B, PetscInt bs, const PetscInt i[], const PetscInt j[], const PetscScalar v[]) 2000d71ae5a4SJacob Faibussowitsch { 200138f409ebSLisandro Dalcin PetscFunctionBegin; 200238f409ebSLisandro Dalcin PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 200338f409ebSLisandro Dalcin PetscValidType(B, 1); 200438f409ebSLisandro Dalcin PetscValidLogicalCollectiveInt(B, bs, 2); 2005cac4c232SBarry Smith PetscTryMethod(B, "MatSeqSBAIJSetPreallocationCSR_C", (Mat, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, bs, i, j, v)); 20063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 200738f409ebSLisandro Dalcin } 200838f409ebSLisandro Dalcin 20095d83a8b1SBarry Smith /*@ 20102ef1f0ffSBarry Smith MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in (block 201111a5261eSBarry Smith compressed row) `MATSEQSBAIJ` format. For good matrix assembly performance the 20122ef1f0ffSBarry Smith user should preallocate the matrix storage by setting the parameter `nz` 20132ef1f0ffSBarry Smith (or the array `nnz`). 201449b5e25fSSatish Balay 2015d083f849SBarry Smith Collective 2016c464158bSHong Zhang 2017c464158bSHong Zhang Input Parameters: 201811a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF` 201911a5261eSBarry 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 2020bb7ae925SBarry Smith blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with MatCreateVecs() 202120f4b53cSBarry Smith . m - number of rows 202220f4b53cSBarry Smith . n - number of columns 2023c464158bSHong Zhang . nz - number of block nonzeros per block row (same for all rows) 2024744e8345SSatish Balay - nnz - array containing the number of block nonzeros in the upper triangular plus 20252ef1f0ffSBarry Smith diagonal portion of each block (possibly different for each block row) or `NULL` 2026c464158bSHong Zhang 2027c464158bSHong Zhang Output Parameter: 2028c464158bSHong Zhang . A - the symmetric matrix 2029c464158bSHong Zhang 2030c464158bSHong Zhang Options Database Keys: 2031d8a51d2aSBarry Smith + -mat_no_unroll - uses code that does not unroll the loops in the block calculations (much slower) 2032a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use 2033c464158bSHong Zhang 2034c464158bSHong Zhang Level: intermediate 2035c464158bSHong Zhang 20362ef1f0ffSBarry Smith Notes: 203777433607SBarry Smith It is recommended that one use `MatCreateFromOptions()` or the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`, 2038f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly. 203911a5261eSBarry Smith [MatXXXXSetPreallocation() is, for example, `MatSeqAIJSetPreallocation()`] 2040175b88e8SBarry Smith 20416d6d819aSHong Zhang The number of rows and columns must be divisible by blocksize. 20426d6d819aSHong Zhang This matrix type does not support complex Hermitian operation. 2043c464158bSHong Zhang 20442ef1f0ffSBarry Smith Specify the preallocated storage with either `nz` or `nnz` (not both). 20452ef1f0ffSBarry Smith Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory 2046651615e1SBarry Smith allocation. See [Sparse Matrices](sec_matsparse) for details. 2047c464158bSHong Zhang 20482ef1f0ffSBarry Smith If the `nnz` parameter is given then the `nz` parameter is ignored 204949a6f317SBarry Smith 20501cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()` 2051c464158bSHong Zhang @*/ 2052d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqSBAIJ(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A) 2053d71ae5a4SJacob Faibussowitsch { 2054c464158bSHong Zhang PetscFunctionBegin; 20559566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 20569566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, m, n)); 20579566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATSEQSBAIJ)); 20589566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(*A, bs, nz, (PetscInt *)nnz)); 20593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 206049b5e25fSSatish Balay } 206149b5e25fSSatish Balay 2062d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B) 2063d71ae5a4SJacob Faibussowitsch { 206449b5e25fSSatish Balay Mat C; 206549b5e25fSSatish Balay Mat_SeqSBAIJ *c, *a = (Mat_SeqSBAIJ *)A->data; 2066b40805acSSatish Balay PetscInt i, mbs = a->mbs, nz = a->nz, bs2 = a->bs2; 206749b5e25fSSatish Balay 206849b5e25fSSatish Balay PetscFunctionBegin; 206931fe6a7dSBarry Smith PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix"); 207008401ef6SPierre Jolivet PetscCheck(a->i[mbs] == nz, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupt matrix"); 207149b5e25fSSatish Balay 2072f4259b30SLisandro Dalcin *B = NULL; 20739566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 20749566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, A->rmap->N, A->cmap->n, A->rmap->N, A->cmap->n)); 20759566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 20769566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATSEQSBAIJ)); 2077692f9cbeSHong Zhang c = (Mat_SeqSBAIJ *)C->data; 2078692f9cbeSHong Zhang 2079273d9f13SBarry Smith C->preallocated = PETSC_TRUE; 2080d5f3da31SBarry Smith C->factortype = A->factortype; 2081f4259b30SLisandro Dalcin c->row = NULL; 2082f4259b30SLisandro Dalcin c->icol = NULL; 2083f4259b30SLisandro Dalcin c->saved_values = NULL; 2084a9817697SBarry Smith c->keepnonzeropattern = a->keepnonzeropattern; 208549b5e25fSSatish Balay C->assembled = PETSC_TRUE; 208649b5e25fSSatish Balay 20879566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->rmap, &C->rmap)); 20889566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->cmap, &C->cmap)); 208949b5e25fSSatish Balay c->bs2 = a->bs2; 209049b5e25fSSatish Balay c->mbs = a->mbs; 209149b5e25fSSatish Balay c->nbs = a->nbs; 209249b5e25fSSatish Balay 2093c760cd28SBarry Smith if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { 2094c760cd28SBarry Smith c->imax = a->imax; 2095c760cd28SBarry Smith c->ilen = a->ilen; 2096c760cd28SBarry Smith c->free_imax_ilen = PETSC_FALSE; 2097c760cd28SBarry Smith } else { 209857508eceSPierre Jolivet PetscCall(PetscMalloc2(mbs + 1, &c->imax, mbs + 1, &c->ilen)); 209949b5e25fSSatish Balay for (i = 0; i < mbs; i++) { 210049b5e25fSSatish Balay c->imax[i] = a->imax[i]; 210149b5e25fSSatish Balay c->ilen[i] = a->ilen[i]; 210249b5e25fSSatish Balay } 2103c760cd28SBarry Smith c->free_imax_ilen = PETSC_TRUE; 2104c760cd28SBarry Smith } 210549b5e25fSSatish Balay 210649b5e25fSSatish Balay /* allocate the matrix space */ 21079f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(bs2 * nz, sizeof(PetscScalar), (void **)&c->a)); 21089f0612e4SBarry Smith c->free_a = PETSC_TRUE; 21094da8f245SBarry Smith if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { 21109f0612e4SBarry Smith PetscCall(PetscArrayzero(c->a, bs2 * nz)); 211144e1c64aSLisandro Dalcin c->i = a->i; 211244e1c64aSLisandro Dalcin c->j = a->j; 21134da8f245SBarry Smith c->free_ij = PETSC_FALSE; 21144da8f245SBarry Smith c->parent = A; 21159566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 21169566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 21179566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 21184da8f245SBarry Smith } else { 21199f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&c->j)); 21209f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(mbs + 1, sizeof(PetscInt), (void **)&c->i)); 21219566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->i, a->i, mbs + 1)); 21224da8f245SBarry Smith c->free_ij = PETSC_TRUE; 21234da8f245SBarry Smith } 212449b5e25fSSatish Balay if (mbs > 0) { 212548a46eb9SPierre Jolivet if (cpvalues != MAT_SHARE_NONZERO_PATTERN) PetscCall(PetscArraycpy(c->j, a->j, nz)); 212649b5e25fSSatish Balay if (cpvalues == MAT_COPY_VALUES) { 21279566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->a, a->a, bs2 * nz)); 212849b5e25fSSatish Balay } else { 21299566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->a, bs2 * nz)); 213049b5e25fSSatish Balay } 2131a1c3900fSBarry Smith if (a->jshort) { 213244e1c64aSLisandro Dalcin /* cannot share jshort, it is reallocated in MatAssemblyEnd_SeqSBAIJ() */ 213344e1c64aSLisandro Dalcin /* if the parent matrix is reassembled, this child matrix will never notice */ 21349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &c->jshort)); 21359566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->jshort, a->jshort, nz)); 213626fbe8dcSKarl Rupp 21374da8f245SBarry Smith c->free_jshort = PETSC_TRUE; 21384da8f245SBarry Smith } 2139a1c3900fSBarry Smith } 214049b5e25fSSatish Balay 214149b5e25fSSatish Balay c->roworiented = a->roworiented; 214249b5e25fSSatish Balay c->nonew = a->nonew; 214349b5e25fSSatish Balay 214449b5e25fSSatish Balay if (a->diag) { 2145c760cd28SBarry Smith if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { 2146c760cd28SBarry Smith c->diag = a->diag; 2147c760cd28SBarry Smith c->free_diag = PETSC_FALSE; 2148c760cd28SBarry Smith } else { 21499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mbs, &c->diag)); 215026fbe8dcSKarl Rupp for (i = 0; i < mbs; i++) c->diag[i] = a->diag[i]; 2151c760cd28SBarry Smith c->free_diag = PETSC_TRUE; 2152c760cd28SBarry Smith } 215344e1c64aSLisandro Dalcin } 21546c6c5352SBarry Smith c->nz = a->nz; 2155f2cbd3d5SJed Brown c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 2156f4259b30SLisandro Dalcin c->solve_work = NULL; 2157f4259b30SLisandro Dalcin c->mult_work = NULL; 215826fbe8dcSKarl Rupp 215949b5e25fSSatish Balay *B = C; 21609566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist)); 21613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 216249b5e25fSSatish Balay } 216349b5e25fSSatish Balay 2164618cc2edSLisandro Dalcin /* Used for both SeqBAIJ and SeqSBAIJ matrices */ 2165618cc2edSLisandro Dalcin #define MatLoad_SeqSBAIJ_Binary MatLoad_SeqBAIJ_Binary 2166618cc2edSLisandro Dalcin 2167d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_SeqSBAIJ(Mat mat, PetscViewer viewer) 2168d71ae5a4SJacob Faibussowitsch { 21697f489da9SVaclav Hapla PetscBool isbinary; 21702f480046SShri Abhyankar 21712f480046SShri Abhyankar PetscFunctionBegin; 21729566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 217328b400f6SJacob 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); 21749566063dSJacob Faibussowitsch PetscCall(MatLoad_SeqSBAIJ_Binary(mat, viewer)); 21753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21762f480046SShri Abhyankar } 21772f480046SShri Abhyankar 2178c75a6043SHong Zhang /*@ 217911a5261eSBarry Smith MatCreateSeqSBAIJWithArrays - Creates an sequential `MATSEQSBAIJ` matrix using matrix elements 2180c75a6043SHong Zhang (upper triangular entries in CSR format) provided by the user. 2181c75a6043SHong Zhang 2182d083f849SBarry Smith Collective 2183c75a6043SHong Zhang 2184c75a6043SHong Zhang Input Parameters: 2185c75a6043SHong Zhang + comm - must be an MPI communicator of size 1 2186c75a6043SHong Zhang . bs - size of block 2187c75a6043SHong Zhang . m - number of rows 2188c75a6043SHong Zhang . n - number of columns 2189483a2f95SBarry 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 2190c75a6043SHong Zhang . j - column indices 2191c75a6043SHong Zhang - a - matrix values 2192c75a6043SHong Zhang 2193c75a6043SHong Zhang Output Parameter: 2194c75a6043SHong Zhang . mat - the matrix 2195c75a6043SHong Zhang 2196dfb205c3SBarry Smith Level: advanced 2197c75a6043SHong Zhang 2198c75a6043SHong Zhang Notes: 21992ef1f0ffSBarry Smith The `i`, `j`, and `a` arrays are not copied by this routine, the user must free these arrays 2200c75a6043SHong Zhang once the matrix is destroyed 2201c75a6043SHong Zhang 2202c75a6043SHong Zhang You cannot set new nonzero locations into this matrix, that will generate an error. 2203c75a6043SHong Zhang 22042ef1f0ffSBarry Smith The `i` and `j` indices are 0 based 2205c75a6043SHong Zhang 22062ef1f0ffSBarry Smith When block size is greater than 1 the matrix values must be stored using the `MATSBAIJ` storage format. For block size of 1 2207dfb205c3SBarry Smith it is the regular CSR format excluding the lower triangular elements. 2208dfb205c3SBarry Smith 22091cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSBAIJ()`, `MatCreateSeqSBAIJ()` 2210c75a6043SHong Zhang @*/ 2211d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqSBAIJWithArrays(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat) 2212d71ae5a4SJacob Faibussowitsch { 2213c75a6043SHong Zhang PetscInt ii; 2214c75a6043SHong Zhang Mat_SeqSBAIJ *sbaij; 2215c75a6043SHong Zhang 2216c75a6043SHong Zhang PetscFunctionBegin; 221708401ef6SPierre Jolivet PetscCheck(bs == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "block size %" PetscInt_FMT " > 1 is not supported yet", bs); 2218aed4548fSBarry Smith PetscCheck(m == 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0"); 2219c75a6043SHong Zhang 22209566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 22219566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 22229566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQSBAIJ)); 22239566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(*mat, bs, MAT_SKIP_ALLOCATION, NULL)); 2224c75a6043SHong Zhang sbaij = (Mat_SeqSBAIJ *)(*mat)->data; 22259566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(m, &sbaij->imax, m, &sbaij->ilen)); 2226c75a6043SHong Zhang 2227c75a6043SHong Zhang sbaij->i = i; 2228c75a6043SHong Zhang sbaij->j = j; 2229c75a6043SHong Zhang sbaij->a = a; 223026fbe8dcSKarl Rupp 2231c75a6043SHong Zhang sbaij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 2232e6b907acSBarry Smith sbaij->free_a = PETSC_FALSE; 2233e6b907acSBarry Smith sbaij->free_ij = PETSC_FALSE; 2234ddf7884eSMatthew Knepley sbaij->free_imax_ilen = PETSC_TRUE; 2235c75a6043SHong Zhang 2236c75a6043SHong Zhang for (ii = 0; ii < m; ii++) { 2237c75a6043SHong Zhang sbaij->ilen[ii] = sbaij->imax[ii] = i[ii + 1] - i[ii]; 22386bdcaf15SBarry 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]); 2239c75a6043SHong Zhang } 224076bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 2241c75a6043SHong Zhang for (ii = 0; ii < sbaij->i[m]; ii++) { 22426bdcaf15SBarry 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]); 22436bdcaf15SBarry 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]); 2244c75a6043SHong Zhang } 224576bd3646SJed Brown } 2246c75a6043SHong Zhang 22479566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 22489566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 22493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2250c75a6043SHong Zhang } 2251d06b337dSHong Zhang 2252d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat) 2253d71ae5a4SJacob Faibussowitsch { 225459f5e6ceSHong Zhang PetscFunctionBegin; 22559566063dSJacob Faibussowitsch PetscCall(MatCreateMPIMatConcatenateSeqMat_MPISBAIJ(comm, inmat, n, scall, outmat)); 22563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 225759f5e6ceSHong Zhang } 2258