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 31*d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)) 32d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_SBAIJ_ScaLAPACK(Mat, MatType, MatReuse, Mat *); 33d24d4204SJose E. Roman #endif 3428d58a37SPierre Jolivet PETSC_INTERN PetscErrorCode MatConvert_MPISBAIJ_Basic(Mat, MatType, MatReuse, Mat *); 35b5b17502SBarry Smith 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 219*d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)) 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 { 5449f196a02SMartin Diehl PetscBool isascii, isbinary, isdraw; 54549b5e25fSSatish Balay 54649b5e25fSSatish Balay PetscFunctionBegin; 5479f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 5489566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 5499566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 5509f196a02SMartin Diehl if (isascii) { 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) { 661966bd95aSPierre Jolivet PetscCheck(a->ignore_ltriangular, PETSC_COMM_SELF, PETSC_ERR_USER, "Lower triangular value cannot be set for sbaij format. Ignoring these values, run with -mat_ignore_lower_triangular or call MatSetOption(mat,MAT_IGNORE_LOWER_TRIANGULAR,PETSC_TRUE)"); 662966bd95aSPierre Jolivet continue; /* ignore lower triangular block */ 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) { 825966bd95aSPierre Jolivet PetscCheck(a->ignore_ltriangular, PETSC_COMM_SELF, PETSC_ERR_USER, "Lower triangular value cannot be set for sbaij format. Ignoring these values, run with -mat_ignore_lower_triangular or call MatSetOption(mat,MAT_IGNORE_LOWER_TRIANGULAR,PETSC_TRUE)"); 826966bd95aSPierre Jolivet continue; /* ignore lower triangular values */ 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, 13208bb0f5c6SPierre Jolivet MatGetRowMaxAbs_SeqSBAIJ, 13218bb0f5c6SPierre Jolivet /* 69*/ NULL, 132228d58a37SPierre Jolivet MatConvert_MPISBAIJ_Basic, 1323f4259b30SLisandro Dalcin NULL, 1324f4259b30SLisandro Dalcin NULL, 13258bb0f5c6SPierre Jolivet NULL, 1326f4259b30SLisandro Dalcin /* 74*/ NULL, 1327f4259b30SLisandro Dalcin NULL, 1328f4259b30SLisandro Dalcin NULL, 132997304618SKris Buschelman MatGetInertia_SeqSBAIJ, 13305bba2384SShri Abhyankar MatLoad_SeqSBAIJ, 13318bb0f5c6SPierre Jolivet /* 79*/ NULL, 13326cff0a6bSPierre Jolivet NULL, 1333efcf0fc3SBarry Smith MatIsStructurallySymmetric_SeqSBAIJ, 1334f4259b30SLisandro Dalcin NULL, 1335f4259b30SLisandro Dalcin NULL, 13368bb0f5c6SPierre Jolivet /* 84*/ NULL, 13378bb0f5c6SPierre Jolivet NULL, 13388bb0f5c6SPierre Jolivet NULL, 13398bb0f5c6SPierre Jolivet NULL, 13408bb0f5c6SPierre Jolivet NULL, 1341f4259b30SLisandro Dalcin /* 89*/ NULL, 1342f4259b30SLisandro Dalcin NULL, 1343f4259b30SLisandro Dalcin NULL, 1344f4259b30SLisandro Dalcin NULL, 13458bb0f5c6SPierre Jolivet MatConjugate_SeqSBAIJ, 1346f4259b30SLisandro Dalcin /* 94*/ NULL, 1347f4259b30SLisandro Dalcin NULL, 134899cafbc1SBarry Smith MatRealPart_SeqSBAIJ, 1349f5edf698SHong Zhang MatImaginaryPart_SeqSBAIJ, 1350f5edf698SHong Zhang MatGetRowUpperTriangular_SeqSBAIJ, 13518bb0f5c6SPierre Jolivet /* 99*/ MatRestoreRowUpperTriangular_SeqSBAIJ, 13528bb0f5c6SPierre Jolivet NULL, 13538bb0f5c6SPierre Jolivet NULL, 13548bb0f5c6SPierre Jolivet NULL, 13558bb0f5c6SPierre Jolivet NULL, 13568bb0f5c6SPierre Jolivet /*104*/ MatMissingDiagonal_SeqSBAIJ, 13578bb0f5c6SPierre Jolivet NULL, 13588bb0f5c6SPierre Jolivet NULL, 13598bb0f5c6SPierre Jolivet NULL, 13608bb0f5c6SPierre Jolivet NULL, 1361f4259b30SLisandro Dalcin /*109*/ NULL, 1362f4259b30SLisandro Dalcin NULL, 1363f4259b30SLisandro Dalcin NULL, 1364f4259b30SLisandro Dalcin NULL, 13658bb0f5c6SPierre Jolivet NULL, 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, 13798bb0f5c6SPierre Jolivet MatSetBlockSizes_Default, 1380f4259b30SLisandro Dalcin NULL, 1381f4259b30SLisandro Dalcin /*129*/ NULL, 1382f4259b30SLisandro Dalcin NULL, 13838bb0f5c6SPierre Jolivet MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ, 1384f4259b30SLisandro Dalcin NULL, 1385f4259b30SLisandro Dalcin NULL, 1386f4259b30SLisandro Dalcin /*134*/ NULL, 1387f4259b30SLisandro Dalcin NULL, 1388f4259b30SLisandro Dalcin NULL, 1389eede4a3fSMark Adams MatEliminateZeros_SeqSBAIJ, 13904cc2b5b5SPierre Jolivet NULL, 13918bb0f5c6SPierre Jolivet /*139*/ NULL, 139242ce410bSJunchao Zhang NULL, 139342ce410bSJunchao Zhang NULL, 139403db1824SAlex Lindsay MatCopyHashToXAIJ_Seq_Hash, 1395c2be7ffeSStefano Zampini NULL, 139603db1824SAlex Lindsay NULL}; 1397be1d678aSKris Buschelman 1398ba38deedSJacob Faibussowitsch static PetscErrorCode MatStoreValues_SeqSBAIJ(Mat mat) 1399d71ae5a4SJacob Faibussowitsch { 14004afc71dfSHong Zhang Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data; 1401d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2; 140249b5e25fSSatish Balay 140349b5e25fSSatish Balay PetscFunctionBegin; 140408401ef6SPierre Jolivet PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 140549b5e25fSSatish Balay 140649b5e25fSSatish Balay /* allocate space for values if not already there */ 140748a46eb9SPierre Jolivet if (!aij->saved_values) PetscCall(PetscMalloc1(nz + 1, &aij->saved_values)); 140849b5e25fSSatish Balay 140949b5e25fSSatish Balay /* copy values over */ 14109566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz)); 14113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 141249b5e25fSSatish Balay } 141349b5e25fSSatish Balay 1414ba38deedSJacob Faibussowitsch static PetscErrorCode MatRetrieveValues_SeqSBAIJ(Mat mat) 1415d71ae5a4SJacob Faibussowitsch { 14164afc71dfSHong Zhang Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data; 1417d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->N] * mat->rmap->bs * aij->bs2; 141849b5e25fSSatish Balay 141949b5e25fSSatish Balay PetscFunctionBegin; 142008401ef6SPierre Jolivet PetscCheck(aij->nonew == 1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 142128b400f6SJacob Faibussowitsch PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first"); 142249b5e25fSSatish Balay 142349b5e25fSSatish Balay /* copy values over */ 14249566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz)); 14253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 142649b5e25fSSatish Balay } 142749b5e25fSSatish Balay 1428f9663b93SPierre Jolivet static PetscErrorCode MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[]) 1429d71ae5a4SJacob Faibussowitsch { 1430c464158bSHong Zhang Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data; 14314dcd73b1SHong Zhang PetscInt i, mbs, nbs, bs2; 14322576faa2SJed Brown PetscBool skipallocation = PETSC_FALSE, flg = PETSC_FALSE, realalloc = PETSC_FALSE; 143349b5e25fSSatish Balay 1434b4e2f619SBarry Smith PetscFunctionBegin; 1435ad79cf63SBarry Smith if (B->hash_active) { 1436ad79cf63SBarry Smith PetscInt bs; 1437aea10558SJacob Faibussowitsch B->ops[0] = b->cops; 1438ad79cf63SBarry Smith PetscCall(PetscHMapIJVDestroy(&b->ht)); 1439ad79cf63SBarry Smith PetscCall(MatGetBlockSize(B, &bs)); 1440ad79cf63SBarry Smith if (bs > 1) PetscCall(PetscHSetIJDestroy(&b->bht)); 1441ad79cf63SBarry Smith PetscCall(PetscFree(b->dnz)); 1442ad79cf63SBarry Smith PetscCall(PetscFree(b->bdnz)); 1443ad79cf63SBarry Smith B->hash_active = PETSC_FALSE; 1444ad79cf63SBarry Smith } 14452576faa2SJed Brown if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 1446db4efbfdSBarry Smith 144758b7e2c1SStefano Zampini PetscCall(MatSetBlockSize(B, bs)); 14489566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 14499566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 145008401ef6SPierre 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); 14519566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs)); 1452899cda47SBarry Smith 145321940c7eSstefano_zampini B->preallocated = PETSC_TRUE; 145421940c7eSstefano_zampini 1455d0f46423SBarry Smith mbs = B->rmap->N / bs; 14564dcd73b1SHong Zhang nbs = B->cmap->n / bs; 145749b5e25fSSatish Balay bs2 = bs * bs; 145849b5e25fSSatish Balay 1459aed4548fSBarry 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"); 146049b5e25fSSatish Balay 1461ab93d7beSBarry Smith if (nz == MAT_SKIP_ALLOCATION) { 1462ab93d7beSBarry Smith skipallocation = PETSC_TRUE; 1463ab93d7beSBarry Smith nz = 0; 1464ab93d7beSBarry Smith } 1465ab93d7beSBarry Smith 1466435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3; 146708401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz); 146849b5e25fSSatish Balay if (nnz) { 146949b5e25fSSatish Balay for (i = 0; i < mbs; i++) { 147008401ef6SPierre 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]); 147108401ef6SPierre 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); 147249b5e25fSSatish Balay } 147349b5e25fSSatish Balay } 147449b5e25fSSatish Balay 1475db4efbfdSBarry Smith B->ops->mult = MatMult_SeqSBAIJ_N; 1476db4efbfdSBarry Smith B->ops->multadd = MatMultAdd_SeqSBAIJ_N; 1477db4efbfdSBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_N; 1478db4efbfdSBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N; 147926fbe8dcSKarl Rupp 14809566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL)); 148149b5e25fSSatish Balay if (!flg) { 148249b5e25fSSatish Balay switch (bs) { 148349b5e25fSSatish Balay case 1: 148449b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_1; 148549b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_1; 1486431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_1; 1487431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1; 148849b5e25fSSatish Balay break; 148949b5e25fSSatish Balay case 2: 149049b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_2; 149149b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_2; 1492431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_2; 1493431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2; 149449b5e25fSSatish Balay break; 149549b5e25fSSatish Balay case 3: 149649b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_3; 149749b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_3; 1498431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_3; 1499431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3; 150049b5e25fSSatish Balay break; 150149b5e25fSSatish Balay case 4: 150249b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_4; 150349b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_4; 1504431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_4; 1505431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4; 150649b5e25fSSatish Balay break; 150749b5e25fSSatish Balay case 5: 150849b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_5; 150949b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_5; 1510431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_5; 1511431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5; 151249b5e25fSSatish Balay break; 151349b5e25fSSatish Balay case 6: 151449b5e25fSSatish Balay B->ops->mult = MatMult_SeqSBAIJ_6; 151549b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_6; 1516431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_6; 1517431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6; 151849b5e25fSSatish Balay break; 151949b5e25fSSatish Balay case 7: 1520de53e5efSHong Zhang B->ops->mult = MatMult_SeqSBAIJ_7; 152149b5e25fSSatish Balay B->ops->multadd = MatMultAdd_SeqSBAIJ_7; 1522431c96f7SBarry Smith B->ops->multtranspose = MatMult_SeqSBAIJ_7; 1523431c96f7SBarry Smith B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7; 152449b5e25fSSatish Balay break; 152549b5e25fSSatish Balay } 152649b5e25fSSatish Balay } 152749b5e25fSSatish Balay 152849b5e25fSSatish Balay b->mbs = mbs; 15294dcd73b1SHong Zhang b->nbs = nbs; 1530ab93d7beSBarry Smith if (!skipallocation) { 15312ee49352SLisandro Dalcin if (!b->imax) { 15329566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(mbs, &b->imax, mbs, &b->ilen)); 153326fbe8dcSKarl Rupp 1534c760cd28SBarry Smith b->free_imax_ilen = PETSC_TRUE; 15352ee49352SLisandro Dalcin } 153649b5e25fSSatish Balay if (!nnz) { 1537435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 153849b5e25fSSatish Balay else if (nz <= 0) nz = 1; 15395d2a9ed1SStefano Zampini nz = PetscMin(nbs, nz); 154026fbe8dcSKarl Rupp for (i = 0; i < mbs; i++) b->imax[i] = nz; 15419566063dSJacob Faibussowitsch PetscCall(PetscIntMultError(nz, mbs, &nz)); 154249b5e25fSSatish Balay } else { 1543c73702f5SBarry Smith PetscInt64 nz64 = 0; 15449371c9d4SSatish Balay for (i = 0; i < mbs; i++) { 15459371c9d4SSatish Balay b->imax[i] = nnz[i]; 15469371c9d4SSatish Balay nz64 += nnz[i]; 15479371c9d4SSatish Balay } 15489566063dSJacob Faibussowitsch PetscCall(PetscIntCast(nz64, &nz)); 154949b5e25fSSatish Balay } 15502ee49352SLisandro Dalcin /* b->ilen will count nonzeros in each block row so far. */ 155126fbe8dcSKarl Rupp for (i = 0; i < mbs; i++) b->ilen[i] = 0; 15526c6c5352SBarry Smith /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */ 155349b5e25fSSatish Balay 155449b5e25fSSatish Balay /* allocate the matrix space */ 15559566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i)); 15569f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(bs2 * nz, sizeof(PetscScalar), (void **)&b->a)); 15579f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&b->j)); 15589f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(B->rmap->n + 1, sizeof(PetscInt), (void **)&b->i)); 15599f0612e4SBarry Smith b->free_a = PETSC_TRUE; 15609f0612e4SBarry Smith b->free_ij = PETSC_TRUE; 15619566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(b->a, nz * bs2)); 15629566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(b->j, nz)); 15639f0612e4SBarry Smith b->free_a = PETSC_TRUE; 15649f0612e4SBarry Smith b->free_ij = PETSC_TRUE; 156549b5e25fSSatish Balay 156649b5e25fSSatish Balay /* pointer to beginning of each row */ 1567e60cf9a0SBarry Smith b->i[0] = 0; 156826fbe8dcSKarl Rupp for (i = 1; i < mbs + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1]; 156926fbe8dcSKarl Rupp 1570e811da20SHong Zhang } else { 1571e6b907acSBarry Smith b->free_a = PETSC_FALSE; 1572e6b907acSBarry Smith b->free_ij = PETSC_FALSE; 1573ab93d7beSBarry Smith } 157449b5e25fSSatish Balay 157549b5e25fSSatish Balay b->bs2 = bs2; 15766c6c5352SBarry Smith b->nz = 0; 1577b32cb4a7SJed Brown b->maxnz = nz; 1578f4259b30SLisandro Dalcin b->inew = NULL; 1579f4259b30SLisandro Dalcin b->jnew = NULL; 1580f4259b30SLisandro Dalcin b->anew = NULL; 1581f4259b30SLisandro Dalcin b->a2anew = NULL; 15821a3463dfSHong Zhang b->permute = PETSC_FALSE; 1583cb7b82ddSBarry Smith 1584cb7b82ddSBarry Smith B->was_assembled = PETSC_FALSE; 1585cb7b82ddSBarry Smith B->assembled = PETSC_FALSE; 15869566063dSJacob Faibussowitsch if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 15873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1588c464158bSHong Zhang } 1589153ea458SHong Zhang 1590ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ(Mat B, PetscInt bs, const PetscInt ii[], const PetscInt jj[], const PetscScalar V[]) 1591d71ae5a4SJacob Faibussowitsch { 15920cd7f59aSBarry Smith PetscInt i, j, m, nz, anz, nz_max = 0, *nnz; 1593f4259b30SLisandro Dalcin PetscScalar *values = NULL; 15941c466ed6SStefano Zampini Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ *)B->data; 15951c466ed6SStefano Zampini PetscBool roworiented = b->roworiented; 15961c466ed6SStefano Zampini PetscBool ilw = b->ignore_ltriangular; 15970cd7f59aSBarry Smith 159838f409ebSLisandro Dalcin PetscFunctionBegin; 159908401ef6SPierre Jolivet PetscCheck(bs >= 1, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_OUTOFRANGE, "Invalid block size specified, must be positive but it is %" PetscInt_FMT, bs); 16009566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(B->rmap, bs)); 16019566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(B->cmap, bs)); 16029566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 16039566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 16049566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetBlockSize(B->rmap, &bs)); 160538f409ebSLisandro Dalcin m = B->rmap->n / bs; 160638f409ebSLisandro Dalcin 1607aed4548fSBarry Smith PetscCheck(!ii[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ii[0] must be 0 but it is %" PetscInt_FMT, ii[0]); 16089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nnz)); 160938f409ebSLisandro Dalcin for (i = 0; i < m; i++) { 161038f409ebSLisandro Dalcin nz = ii[i + 1] - ii[i]; 161108401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz); 16121c466ed6SStefano Zampini PetscCheckSorted(nz, jj + ii[i]); 16130cd7f59aSBarry Smith anz = 0; 16140cd7f59aSBarry Smith for (j = 0; j < nz; j++) { 16150cd7f59aSBarry Smith /* count only values on the diagonal or above */ 16160cd7f59aSBarry Smith if (jj[ii[i] + j] >= i) { 16170cd7f59aSBarry Smith anz = nz - j; 16180cd7f59aSBarry Smith break; 16190cd7f59aSBarry Smith } 16200cd7f59aSBarry Smith } 16211c466ed6SStefano Zampini nz_max = PetscMax(nz_max, nz); 16220cd7f59aSBarry Smith nnz[i] = anz; 162338f409ebSLisandro Dalcin } 16249566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, nnz)); 16259566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 162638f409ebSLisandro Dalcin 162738f409ebSLisandro Dalcin values = (PetscScalar *)V; 162848a46eb9SPierre Jolivet if (!values) PetscCall(PetscCalloc1(bs * bs * nz_max, &values)); 16291c466ed6SStefano Zampini b->ignore_ltriangular = PETSC_TRUE; 163038f409ebSLisandro Dalcin for (i = 0; i < m; i++) { 163138f409ebSLisandro Dalcin PetscInt ncols = ii[i + 1] - ii[i]; 163238f409ebSLisandro Dalcin const PetscInt *icols = jj + ii[i]; 16331c466ed6SStefano Zampini 163438f409ebSLisandro Dalcin if (!roworiented || bs == 1) { 163538f409ebSLisandro Dalcin const PetscScalar *svals = values + (V ? (bs * bs * ii[i]) : 0); 16369566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, ncols, icols, svals, INSERT_VALUES)); 163738f409ebSLisandro Dalcin } else { 163838f409ebSLisandro Dalcin for (j = 0; j < ncols; j++) { 163938f409ebSLisandro Dalcin const PetscScalar *svals = values + (V ? (bs * bs * (ii[i] + j)) : 0); 16409566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked_SeqSBAIJ(B, 1, &i, 1, &icols[j], svals, INSERT_VALUES)); 164138f409ebSLisandro Dalcin } 164238f409ebSLisandro Dalcin } 164338f409ebSLisandro Dalcin } 16449566063dSJacob Faibussowitsch if (!V) PetscCall(PetscFree(values)); 16459566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 16469566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 16479566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 16481c466ed6SStefano Zampini b->ignore_ltriangular = ilw; 16493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 165038f409ebSLisandro Dalcin } 165138f409ebSLisandro Dalcin 1652db4efbfdSBarry Smith /* 1653db4efbfdSBarry Smith This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization 1654db4efbfdSBarry Smith */ 1655d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetNumericFactorization_inplace(Mat B, PetscBool natural) 1656d71ae5a4SJacob Faibussowitsch { 1657ace3abfcSBarry Smith PetscBool flg = PETSC_FALSE; 1658db4efbfdSBarry Smith PetscInt bs = B->rmap->bs; 1659db4efbfdSBarry Smith 1660db4efbfdSBarry Smith PetscFunctionBegin; 16619566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_no_unroll", &flg, NULL)); 1662db4efbfdSBarry Smith if (flg) bs = 8; 1663db4efbfdSBarry Smith 1664db4efbfdSBarry Smith if (!natural) { 1665db4efbfdSBarry Smith switch (bs) { 1666d71ae5a4SJacob Faibussowitsch case 1: 1667d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_inplace; 1668d71ae5a4SJacob Faibussowitsch break; 1669d71ae5a4SJacob Faibussowitsch case 2: 1670d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2; 1671d71ae5a4SJacob Faibussowitsch break; 1672d71ae5a4SJacob Faibussowitsch case 3: 1673d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3; 1674d71ae5a4SJacob Faibussowitsch break; 1675d71ae5a4SJacob Faibussowitsch case 4: 1676d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4; 1677d71ae5a4SJacob Faibussowitsch break; 1678d71ae5a4SJacob Faibussowitsch case 5: 1679d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5; 1680d71ae5a4SJacob Faibussowitsch break; 1681d71ae5a4SJacob Faibussowitsch case 6: 1682d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6; 1683d71ae5a4SJacob Faibussowitsch break; 1684d71ae5a4SJacob Faibussowitsch case 7: 1685d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7; 1686d71ae5a4SJacob Faibussowitsch break; 1687d71ae5a4SJacob Faibussowitsch default: 1688d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N; 1689d71ae5a4SJacob Faibussowitsch break; 1690db4efbfdSBarry Smith } 1691db4efbfdSBarry Smith } else { 1692db4efbfdSBarry Smith switch (bs) { 1693d71ae5a4SJacob Faibussowitsch case 1: 1694d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering_inplace; 1695d71ae5a4SJacob Faibussowitsch break; 1696d71ae5a4SJacob Faibussowitsch case 2: 1697d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering; 1698d71ae5a4SJacob Faibussowitsch break; 1699d71ae5a4SJacob Faibussowitsch case 3: 1700d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering; 1701d71ae5a4SJacob Faibussowitsch break; 1702d71ae5a4SJacob Faibussowitsch case 4: 1703d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering; 1704d71ae5a4SJacob Faibussowitsch break; 1705d71ae5a4SJacob Faibussowitsch case 5: 1706d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering; 1707d71ae5a4SJacob Faibussowitsch break; 1708d71ae5a4SJacob Faibussowitsch case 6: 1709d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering; 1710d71ae5a4SJacob Faibussowitsch break; 1711d71ae5a4SJacob Faibussowitsch case 7: 1712d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering; 1713d71ae5a4SJacob Faibussowitsch break; 1714d71ae5a4SJacob Faibussowitsch default: 1715d71ae5a4SJacob Faibussowitsch B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering; 1716d71ae5a4SJacob Faibussowitsch break; 1717db4efbfdSBarry Smith } 1718db4efbfdSBarry Smith } 17193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1720db4efbfdSBarry Smith } 1721db4efbfdSBarry Smith 1722cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType, MatReuse, Mat *); 1723cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType, MatReuse, Mat *); 1724d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatFactorGetSolverType_petsc(Mat A, MatSolverType *type) 1725d71ae5a4SJacob Faibussowitsch { 17264ac6704cSBarry Smith PetscFunctionBegin; 17274ac6704cSBarry Smith *type = MATSOLVERPETSC; 17283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17294ac6704cSBarry Smith } 1730d769727bSBarry Smith 1731d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A, MatFactorType ftype, Mat *B) 1732d71ae5a4SJacob Faibussowitsch { 1733d0f46423SBarry Smith PetscInt n = A->rmap->n; 17345c9eb25fSBarry Smith 17355c9eb25fSBarry Smith PetscFunctionBegin; 17360e92d65fSHong Zhang #if defined(PETSC_USE_COMPLEX) 173703e5aca4SStefano Zampini if ((ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) && A->hermitian == PETSC_BOOL3_TRUE && A->symmetric != PETSC_BOOL3_TRUE) { 173803e5aca4SStefano Zampini PetscCall(PetscInfo(A, "Hermitian MAT_FACTOR_CHOLESKY or MAT_FACTOR_ICC are not supported. Use MAT_FACTOR_LU instead.\n")); 173903e5aca4SStefano Zampini *B = NULL; 174003e5aca4SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 174103e5aca4SStefano Zampini } 17420e92d65fSHong Zhang #endif 1743eb1ec7c1SStefano Zampini 17449566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 17459566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, n, n, n, n)); 1746966bd95aSPierre Jolivet PetscCheck(ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC, PETSC_COMM_SELF, PETSC_ERR_SUP, "Factor type not supported"); 17479566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, MATSEQSBAIJ)); 17489566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(*B, A->rmap->bs, MAT_SKIP_ALLOCATION, NULL)); 174926fbe8dcSKarl Rupp 17507b056e98SHong Zhang (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ; 1751c6d0d4f0SHong Zhang (*B)->ops->iccfactorsymbolic = MatICCFactorSymbolic_SeqSBAIJ; 17529566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_CHOLESKY])); 17539566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATORDERINGNATURAL, (char **)&(*B)->preferredordering[MAT_FACTOR_ICC])); 175400c67f3bSHong Zhang 1755d5f3da31SBarry Smith (*B)->factortype = ftype; 1756f73b0415SBarry Smith (*B)->canuseordering = PETSC_TRUE; 17579566063dSJacob Faibussowitsch PetscCall(PetscFree((*B)->solvertype)); 17589566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*B)->solvertype)); 17599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)*B, "MatFactorGetSolverType_C", MatFactorGetSolverType_petsc)); 17603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17615c9eb25fSBarry Smith } 17625c9eb25fSBarry Smith 17638397e458SBarry Smith /*@C 17642ef1f0ffSBarry Smith MatSeqSBAIJGetArray - gives access to the array where the numerical data for a `MATSEQSBAIJ` matrix is stored 17658397e458SBarry Smith 17668397e458SBarry Smith Not Collective 17678397e458SBarry Smith 17688397e458SBarry Smith Input Parameter: 1769fe59aa6dSJacob Faibussowitsch . A - a `MATSEQSBAIJ` matrix 17708397e458SBarry Smith 17718397e458SBarry Smith Output Parameter: 17728397e458SBarry Smith . array - pointer to the data 17738397e458SBarry Smith 17748397e458SBarry Smith Level: intermediate 17758397e458SBarry Smith 17761cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatSeqSBAIJRestoreArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()` 17778397e458SBarry Smith @*/ 17785d83a8b1SBarry Smith PetscErrorCode MatSeqSBAIJGetArray(Mat A, PetscScalar *array[]) 1779d71ae5a4SJacob Faibussowitsch { 17808397e458SBarry Smith PetscFunctionBegin; 1781cac4c232SBarry Smith PetscUseMethod(A, "MatSeqSBAIJGetArray_C", (Mat, PetscScalar **), (A, array)); 17823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17838397e458SBarry Smith } 17848397e458SBarry Smith 17858397e458SBarry Smith /*@C 17862ef1f0ffSBarry Smith MatSeqSBAIJRestoreArray - returns access to the array where the numerical data for a `MATSEQSBAIJ` matrix is stored obtained by `MatSeqSBAIJGetArray()` 17878397e458SBarry Smith 17888397e458SBarry Smith Not Collective 17898397e458SBarry Smith 17908397e458SBarry Smith Input Parameters: 1791fe59aa6dSJacob Faibussowitsch + A - a `MATSEQSBAIJ` matrix 1792a2b725a8SWilliam Gropp - array - pointer to the data 17938397e458SBarry Smith 17948397e458SBarry Smith Level: intermediate 17958397e458SBarry Smith 17961cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatSeqSBAIJGetArray()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()` 17978397e458SBarry Smith @*/ 17985d83a8b1SBarry Smith PetscErrorCode MatSeqSBAIJRestoreArray(Mat A, PetscScalar *array[]) 1799d71ae5a4SJacob Faibussowitsch { 18008397e458SBarry Smith PetscFunctionBegin; 1801cac4c232SBarry Smith PetscUseMethod(A, "MatSeqSBAIJRestoreArray_C", (Mat, PetscScalar **), (A, array)); 18023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18038397e458SBarry Smith } 18048397e458SBarry Smith 18050bad9183SKris Buschelman /*MC 1806fafad747SKris Buschelman MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices, 18070bad9183SKris Buschelman based on block compressed sparse row format. Only the upper triangular portion of the matrix is stored. 18080bad9183SKris Buschelman 1809828413b8SBarry Smith For complex numbers by default this matrix is symmetric, NOT Hermitian symmetric. To make it Hermitian symmetric you 181011a5261eSBarry Smith can call `MatSetOption`(`Mat`, `MAT_HERMITIAN`). 1811828413b8SBarry Smith 18122ef1f0ffSBarry Smith Options Database Key: 181311a5261eSBarry Smith . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to `MatSetFromOptions()` 18140bad9183SKris Buschelman 18152ef1f0ffSBarry Smith Level: beginner 18162ef1f0ffSBarry Smith 181795452b02SPatrick Sanan Notes: 181895452b02SPatrick Sanan By default if you insert values into the lower triangular part of the matrix they are simply ignored (since they are not 181911a5261eSBarry 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 18202ef1f0ffSBarry 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. 182171dad5bbSBarry Smith 1822476417e5SBarry Smith The number of rows in the matrix must be less than or equal to the number of columns 182371dad5bbSBarry Smith 18241cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreateSeqSBAIJ()`, `MatType`, `MATMPISBAIJ` 18250bad9183SKris Buschelman M*/ 1826d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_SeqSBAIJ(Mat B) 1827d71ae5a4SJacob Faibussowitsch { 1828a23d5eceSKris Buschelman Mat_SeqSBAIJ *b; 182913f74950SBarry Smith PetscMPIInt size; 1830ace3abfcSBarry Smith PetscBool no_unroll = PETSC_FALSE, no_inode = PETSC_FALSE; 1831a23d5eceSKris Buschelman 1832a23d5eceSKris Buschelman PetscFunctionBegin; 18339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size)); 183408401ef6SPierre Jolivet PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1"); 1835a23d5eceSKris Buschelman 18364dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&b)); 1837a23d5eceSKris Buschelman B->data = (void *)b; 1838aea10558SJacob Faibussowitsch B->ops[0] = MatOps_Values; 183926fbe8dcSKarl Rupp 1840a23d5eceSKris Buschelman B->ops->destroy = MatDestroy_SeqSBAIJ; 1841a23d5eceSKris Buschelman B->ops->view = MatView_SeqSBAIJ; 1842f4259b30SLisandro Dalcin b->row = NULL; 1843f4259b30SLisandro Dalcin b->icol = NULL; 1844a23d5eceSKris Buschelman b->reallocs = 0; 1845f4259b30SLisandro Dalcin b->saved_values = NULL; 18460def2e27SBarry Smith b->inode.limit = 5; 18470def2e27SBarry Smith b->inode.max_limit = 5; 1848a23d5eceSKris Buschelman 1849a23d5eceSKris Buschelman b->roworiented = PETSC_TRUE; 1850a23d5eceSKris Buschelman b->nonew = 0; 1851f4259b30SLisandro Dalcin b->diag = NULL; 1852f4259b30SLisandro Dalcin b->solve_work = NULL; 1853f4259b30SLisandro Dalcin b->mult_work = NULL; 1854f4259b30SLisandro Dalcin B->spptr = NULL; 1855f2cbd3d5SJed Brown B->info.nz_unneeded = (PetscReal)b->maxnz * b->bs2; 1856a9817697SBarry Smith b->keepnonzeropattern = PETSC_FALSE; 1857a23d5eceSKris Buschelman 1858f4259b30SLisandro Dalcin b->inew = NULL; 1859f4259b30SLisandro Dalcin b->jnew = NULL; 1860f4259b30SLisandro Dalcin b->anew = NULL; 1861f4259b30SLisandro Dalcin b->a2anew = NULL; 1862a23d5eceSKris Buschelman b->permute = PETSC_FALSE; 1863a23d5eceSKris Buschelman 186471dad5bbSBarry Smith b->ignore_ltriangular = PETSC_TRUE; 186526fbe8dcSKarl Rupp 18669566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_ignore_lower_triangular", &b->ignore_ltriangular, NULL)); 1867941593c8SHong Zhang 1868f5edf698SHong Zhang b->getrow_utriangular = PETSC_FALSE; 186926fbe8dcSKarl Rupp 18709566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)B)->options, ((PetscObject)B)->prefix, "-mat_getrow_uppertriangular", &b->getrow_utriangular, NULL)); 1871f5edf698SHong Zhang 18729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJGetArray_C", MatSeqSBAIJGetArray_SeqSBAIJ)); 18739566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJRestoreArray_C", MatSeqSBAIJRestoreArray_SeqSBAIJ)); 18749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqSBAIJ)); 18759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqSBAIJ)); 18769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetColumnIndices_C", MatSeqSBAIJSetColumnIndices_SeqSBAIJ)); 18779566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqaij_C", MatConvert_SeqSBAIJ_SeqAIJ)); 18789566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_seqbaij_C", MatConvert_SeqSBAIJ_SeqBAIJ)); 18799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocation_C", MatSeqSBAIJSetPreallocation_SeqSBAIJ)); 18809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqSBAIJSetPreallocationCSR_C", MatSeqSBAIJSetPreallocationCSR_SeqSBAIJ)); 18816214f412SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 18829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_elemental_C", MatConvert_SeqSBAIJ_Elemental)); 18836214f412SHong Zhang #endif 1884*d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)) 18859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqsbaij_scalapack_C", MatConvert_SBAIJ_ScaLAPACK)); 1886d24d4204SJose E. Roman #endif 188723ce1328SBarry Smith 1888b94d7dedSBarry Smith B->symmetry_eternal = PETSC_TRUE; 1889b94d7dedSBarry Smith B->structural_symmetry_eternal = PETSC_TRUE; 1890b94d7dedSBarry Smith B->symmetric = PETSC_BOOL3_TRUE; 1891b94d7dedSBarry Smith B->structurally_symmetric = PETSC_BOOL3_TRUE; 1892eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 1893b94d7dedSBarry Smith B->hermitian = PETSC_BOOL3_FALSE; 1894eb1ec7c1SStefano Zampini #else 1895b94d7dedSBarry Smith B->hermitian = PETSC_BOOL3_TRUE; 1896eb1ec7c1SStefano Zampini #endif 189713647f61SHong Zhang 18989566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQSBAIJ)); 18990def2e27SBarry Smith 1900d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)B), ((PetscObject)B)->prefix, "Options for SEQSBAIJ matrix", "Mat"); 19019566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-mat_no_unroll", "Do not optimize for inodes (slower)", NULL, no_unroll, &no_unroll, NULL)); 190248a46eb9SPierre Jolivet if (no_unroll) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_unroll\n")); 19039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-mat_no_inode", "Do not optimize for inodes (slower)", NULL, no_inode, &no_inode, NULL)); 19049566063dSJacob Faibussowitsch if (no_inode) PetscCall(PetscInfo(B, "Not using Inode routines due to -mat_no_inode\n")); 1905e87b5d96SPierre Jolivet PetscCall(PetscOptionsInt("-mat_inode_limit", "Do not use inodes larger than this value", NULL, b->inode.limit, &b->inode.limit, NULL)); 1906d0609cedSBarry Smith PetscOptionsEnd(); 1907ace3abfcSBarry Smith b->inode.use = (PetscBool)(!(no_unroll || no_inode)); 19080def2e27SBarry Smith if (b->inode.limit > b->inode.max_limit) b->inode.limit = b->inode.max_limit; 19093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1910a23d5eceSKris Buschelman } 1911a23d5eceSKris Buschelman 19125d83a8b1SBarry Smith /*@ 1913a23d5eceSKris Buschelman MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block 191411a5261eSBarry Smith compressed row) `MATSEQSBAIJ` format. For good matrix assembly performance the 191520f4b53cSBarry Smith user should preallocate the matrix storage by setting the parameter `nz` 191620f4b53cSBarry Smith (or the array `nnz`). 1917a23d5eceSKris Buschelman 1918c3339decSBarry Smith Collective 1919a23d5eceSKris Buschelman 1920a23d5eceSKris Buschelman Input Parameters: 19211c4f3114SJed Brown + B - the symmetric matrix 192211a5261eSBarry 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 192311a5261eSBarry Smith blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with `MatCreateVecs()` 1924a23d5eceSKris Buschelman . nz - number of block nonzeros per block row (same for all rows) 1925a23d5eceSKris Buschelman - nnz - array containing the number of block nonzeros in the upper triangular plus 19262ef1f0ffSBarry Smith diagonal portion of each block (possibly different for each block row) or `NULL` 1927a23d5eceSKris Buschelman 1928a23d5eceSKris Buschelman Options Database Keys: 1929d8a51d2aSBarry Smith + -mat_no_unroll - uses code that does not unroll the loops in the block calculations (much slower) 1930a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use (only works if a negative bs is passed in 1931a23d5eceSKris Buschelman 1932a23d5eceSKris Buschelman Level: intermediate 1933a23d5eceSKris Buschelman 1934a23d5eceSKris Buschelman Notes: 193520f4b53cSBarry Smith Specify the preallocated storage with either `nz` or `nnz` (not both). 19362ef1f0ffSBarry Smith Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory 1937651615e1SBarry Smith allocation. See [Sparse Matrices](sec_matsparse) for details. 1938a23d5eceSKris Buschelman 193911a5261eSBarry Smith You can call `MatGetInfo()` to get information on how effective the preallocation was; 1940aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 19412ef1f0ffSBarry Smith You can also run with the option `-info` and look for messages with the string 1942aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 1943aa95bbe8SBarry Smith 19442ef1f0ffSBarry Smith If the `nnz` parameter is given then the `nz` parameter is ignored 194549a6f317SBarry Smith 19461cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()` 1947a23d5eceSKris Buschelman @*/ 1948d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetPreallocation(Mat B, PetscInt bs, PetscInt nz, const PetscInt nnz[]) 1949d71ae5a4SJacob Faibussowitsch { 1950a23d5eceSKris Buschelman PetscFunctionBegin; 19516ba663aaSJed Brown PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 19526ba663aaSJed Brown PetscValidType(B, 1); 19536ba663aaSJed Brown PetscValidLogicalCollectiveInt(B, bs, 2); 1954cac4c232SBarry Smith PetscTryMethod(B, "MatSeqSBAIJSetPreallocation_C", (Mat, PetscInt, PetscInt, const PetscInt[]), (B, bs, nz, nnz)); 19553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1956a23d5eceSKris Buschelman } 195749b5e25fSSatish Balay 195838f409ebSLisandro Dalcin /*@C 195911a5261eSBarry Smith MatSeqSBAIJSetPreallocationCSR - Creates a sparse parallel matrix in `MATSEQSBAIJ` format using the given nonzero structure and (optional) numerical values 196038f409ebSLisandro Dalcin 196138f409ebSLisandro Dalcin Input Parameters: 19621c4f3114SJed Brown + B - the matrix 1963eab78319SHong Zhang . bs - size of block, the blocks are ALWAYS square. 1964d8a51d2aSBarry Smith . i - the indices into `j` for the start of each local row (indices start with zero) 1965d8a51d2aSBarry Smith . j - the column indices for each local row (indices start with zero) these must be sorted for each row 1966d8a51d2aSBarry Smith - v - optional values in the matrix, use `NULL` if not provided 196738f409ebSLisandro Dalcin 1968664954b6SBarry Smith Level: advanced 196938f409ebSLisandro Dalcin 197038f409ebSLisandro Dalcin Notes: 1971d8a51d2aSBarry Smith The `i`,`j`,`v` values are COPIED with this routine; to avoid the copy use `MatCreateSeqSBAIJWithArrays()` 1972d8a51d2aSBarry Smith 197311a5261eSBarry Smith The order of the entries in values is specified by the `MatOption` `MAT_ROW_ORIENTED`. For example, C programs 197411a5261eSBarry 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 197538f409ebSLisandro Dalcin over rows within a block and the last index is over columns within a block row. Fortran programs will likely set 197611a5261eSBarry 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 197738f409ebSLisandro Dalcin block column and the second index is over columns within a block. 197838f409ebSLisandro Dalcin 1979d8a51d2aSBarry Smith Any entries provided that lie below the diagonal are ignored 19800cd7f59aSBarry Smith 19810cd7f59aSBarry Smith Though this routine has Preallocation() in the name it also sets the exact nonzero locations of the matrix entries 19820cd7f59aSBarry Smith and usually the numerical values as well 1983664954b6SBarry Smith 1984fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqSBAIJ()`, `MatSetValuesBlocked()`, `MatSeqSBAIJSetPreallocation()` 198538f409ebSLisandro Dalcin @*/ 1986d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqSBAIJSetPreallocationCSR(Mat B, PetscInt bs, const PetscInt i[], const PetscInt j[], const PetscScalar v[]) 1987d71ae5a4SJacob Faibussowitsch { 198838f409ebSLisandro Dalcin PetscFunctionBegin; 198938f409ebSLisandro Dalcin PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 199038f409ebSLisandro Dalcin PetscValidType(B, 1); 199138f409ebSLisandro Dalcin PetscValidLogicalCollectiveInt(B, bs, 2); 1992cac4c232SBarry Smith PetscTryMethod(B, "MatSeqSBAIJSetPreallocationCSR_C", (Mat, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, bs, i, j, v)); 19933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 199438f409ebSLisandro Dalcin } 199538f409ebSLisandro Dalcin 19965d83a8b1SBarry Smith /*@ 19972ef1f0ffSBarry Smith MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in (block 199811a5261eSBarry Smith compressed row) `MATSEQSBAIJ` format. For good matrix assembly performance the 19992ef1f0ffSBarry Smith user should preallocate the matrix storage by setting the parameter `nz` 20002ef1f0ffSBarry Smith (or the array `nnz`). 200149b5e25fSSatish Balay 2002d083f849SBarry Smith Collective 2003c464158bSHong Zhang 2004c464158bSHong Zhang Input Parameters: 200511a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF` 200611a5261eSBarry 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 2007bb7ae925SBarry Smith blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with MatCreateVecs() 200820f4b53cSBarry Smith . m - number of rows 200920f4b53cSBarry Smith . n - number of columns 2010c464158bSHong Zhang . nz - number of block nonzeros per block row (same for all rows) 2011744e8345SSatish Balay - nnz - array containing the number of block nonzeros in the upper triangular plus 20122ef1f0ffSBarry Smith diagonal portion of each block (possibly different for each block row) or `NULL` 2013c464158bSHong Zhang 2014c464158bSHong Zhang Output Parameter: 2015c464158bSHong Zhang . A - the symmetric matrix 2016c464158bSHong Zhang 2017c464158bSHong Zhang Options Database Keys: 2018d8a51d2aSBarry Smith + -mat_no_unroll - uses code that does not unroll the loops in the block calculations (much slower) 2019a2b725a8SWilliam Gropp - -mat_block_size - size of the blocks to use 2020c464158bSHong Zhang 2021c464158bSHong Zhang Level: intermediate 2022c464158bSHong Zhang 20232ef1f0ffSBarry Smith Notes: 202477433607SBarry Smith It is recommended that one use `MatCreateFromOptions()` or the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`, 2025f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly. 202611a5261eSBarry Smith [MatXXXXSetPreallocation() is, for example, `MatSeqAIJSetPreallocation()`] 2027175b88e8SBarry Smith 20286d6d819aSHong Zhang The number of rows and columns must be divisible by blocksize. 20296d6d819aSHong Zhang This matrix type does not support complex Hermitian operation. 2030c464158bSHong Zhang 20312ef1f0ffSBarry Smith Specify the preallocated storage with either `nz` or `nnz` (not both). 20322ef1f0ffSBarry Smith Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory 2033651615e1SBarry Smith allocation. See [Sparse Matrices](sec_matsparse) for details. 2034c464158bSHong Zhang 20352ef1f0ffSBarry Smith If the `nnz` parameter is given then the `nz` parameter is ignored 203649a6f317SBarry Smith 20371cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrices](sec_matsparse), `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatCreateSBAIJ()` 2038c464158bSHong Zhang @*/ 2039d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqSBAIJ(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A) 2040d71ae5a4SJacob Faibussowitsch { 2041c464158bSHong Zhang PetscFunctionBegin; 20429566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 20439566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, m, n)); 20449566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATSEQSBAIJ)); 20459566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(*A, bs, nz, (PetscInt *)nnz)); 20463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 204749b5e25fSSatish Balay } 204849b5e25fSSatish Balay 2049d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B) 2050d71ae5a4SJacob Faibussowitsch { 205149b5e25fSSatish Balay Mat C; 205249b5e25fSSatish Balay Mat_SeqSBAIJ *c, *a = (Mat_SeqSBAIJ *)A->data; 2053b40805acSSatish Balay PetscInt i, mbs = a->mbs, nz = a->nz, bs2 = a->bs2; 205449b5e25fSSatish Balay 205549b5e25fSSatish Balay PetscFunctionBegin; 205631fe6a7dSBarry Smith PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix"); 205708401ef6SPierre Jolivet PetscCheck(a->i[mbs] == nz, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupt matrix"); 205849b5e25fSSatish Balay 2059f4259b30SLisandro Dalcin *B = NULL; 20609566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 20619566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, A->rmap->N, A->cmap->n, A->rmap->N, A->cmap->n)); 20629566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 20639566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATSEQSBAIJ)); 2064692f9cbeSHong Zhang c = (Mat_SeqSBAIJ *)C->data; 2065692f9cbeSHong Zhang 2066273d9f13SBarry Smith C->preallocated = PETSC_TRUE; 2067d5f3da31SBarry Smith C->factortype = A->factortype; 2068f4259b30SLisandro Dalcin c->row = NULL; 2069f4259b30SLisandro Dalcin c->icol = NULL; 2070f4259b30SLisandro Dalcin c->saved_values = NULL; 2071a9817697SBarry Smith c->keepnonzeropattern = a->keepnonzeropattern; 207249b5e25fSSatish Balay C->assembled = PETSC_TRUE; 207349b5e25fSSatish Balay 20749566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->rmap, &C->rmap)); 20759566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->cmap, &C->cmap)); 207649b5e25fSSatish Balay c->bs2 = a->bs2; 207749b5e25fSSatish Balay c->mbs = a->mbs; 207849b5e25fSSatish Balay c->nbs = a->nbs; 207949b5e25fSSatish Balay 2080c760cd28SBarry Smith if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { 2081c760cd28SBarry Smith c->imax = a->imax; 2082c760cd28SBarry Smith c->ilen = a->ilen; 2083c760cd28SBarry Smith c->free_imax_ilen = PETSC_FALSE; 2084c760cd28SBarry Smith } else { 208557508eceSPierre Jolivet PetscCall(PetscMalloc2(mbs + 1, &c->imax, mbs + 1, &c->ilen)); 208649b5e25fSSatish Balay for (i = 0; i < mbs; i++) { 208749b5e25fSSatish Balay c->imax[i] = a->imax[i]; 208849b5e25fSSatish Balay c->ilen[i] = a->ilen[i]; 208949b5e25fSSatish Balay } 2090c760cd28SBarry Smith c->free_imax_ilen = PETSC_TRUE; 2091c760cd28SBarry Smith } 209249b5e25fSSatish Balay 209349b5e25fSSatish Balay /* allocate the matrix space */ 20949f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(bs2 * nz, sizeof(PetscScalar), (void **)&c->a)); 20959f0612e4SBarry Smith c->free_a = PETSC_TRUE; 20964da8f245SBarry Smith if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { 20979f0612e4SBarry Smith PetscCall(PetscArrayzero(c->a, bs2 * nz)); 209844e1c64aSLisandro Dalcin c->i = a->i; 209944e1c64aSLisandro Dalcin c->j = a->j; 21004da8f245SBarry Smith c->free_ij = PETSC_FALSE; 21014da8f245SBarry Smith c->parent = A; 21029566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 21039566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 21049566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 21054da8f245SBarry Smith } else { 21069f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&c->j)); 21079f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(mbs + 1, sizeof(PetscInt), (void **)&c->i)); 21089566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->i, a->i, mbs + 1)); 21094da8f245SBarry Smith c->free_ij = PETSC_TRUE; 21104da8f245SBarry Smith } 211149b5e25fSSatish Balay if (mbs > 0) { 211248a46eb9SPierre Jolivet if (cpvalues != MAT_SHARE_NONZERO_PATTERN) PetscCall(PetscArraycpy(c->j, a->j, nz)); 211349b5e25fSSatish Balay if (cpvalues == MAT_COPY_VALUES) { 21149566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->a, a->a, bs2 * nz)); 211549b5e25fSSatish Balay } else { 21169566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->a, bs2 * nz)); 211749b5e25fSSatish Balay } 2118a1c3900fSBarry Smith if (a->jshort) { 211944e1c64aSLisandro Dalcin /* cannot share jshort, it is reallocated in MatAssemblyEnd_SeqSBAIJ() */ 212044e1c64aSLisandro Dalcin /* if the parent matrix is reassembled, this child matrix will never notice */ 21219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &c->jshort)); 21229566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->jshort, a->jshort, nz)); 212326fbe8dcSKarl Rupp 21244da8f245SBarry Smith c->free_jshort = PETSC_TRUE; 21254da8f245SBarry Smith } 2126a1c3900fSBarry Smith } 212749b5e25fSSatish Balay 212849b5e25fSSatish Balay c->roworiented = a->roworiented; 212949b5e25fSSatish Balay c->nonew = a->nonew; 213049b5e25fSSatish Balay 213149b5e25fSSatish Balay if (a->diag) { 2132c760cd28SBarry Smith if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { 2133c760cd28SBarry Smith c->diag = a->diag; 2134c760cd28SBarry Smith c->free_diag = PETSC_FALSE; 2135c760cd28SBarry Smith } else { 21369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mbs, &c->diag)); 213726fbe8dcSKarl Rupp for (i = 0; i < mbs; i++) c->diag[i] = a->diag[i]; 2138c760cd28SBarry Smith c->free_diag = PETSC_TRUE; 2139c760cd28SBarry Smith } 214044e1c64aSLisandro Dalcin } 21416c6c5352SBarry Smith c->nz = a->nz; 2142f2cbd3d5SJed Brown c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 2143f4259b30SLisandro Dalcin c->solve_work = NULL; 2144f4259b30SLisandro Dalcin c->mult_work = NULL; 214526fbe8dcSKarl Rupp 214649b5e25fSSatish Balay *B = C; 21479566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist)); 21483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 214949b5e25fSSatish Balay } 215049b5e25fSSatish Balay 2151618cc2edSLisandro Dalcin /* Used for both SeqBAIJ and SeqSBAIJ matrices */ 2152618cc2edSLisandro Dalcin #define MatLoad_SeqSBAIJ_Binary MatLoad_SeqBAIJ_Binary 2153618cc2edSLisandro Dalcin 2154d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_SeqSBAIJ(Mat mat, PetscViewer viewer) 2155d71ae5a4SJacob Faibussowitsch { 21567f489da9SVaclav Hapla PetscBool isbinary; 21572f480046SShri Abhyankar 21582f480046SShri Abhyankar PetscFunctionBegin; 21599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 216028b400f6SJacob 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); 21619566063dSJacob Faibussowitsch PetscCall(MatLoad_SeqSBAIJ_Binary(mat, viewer)); 21623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21632f480046SShri Abhyankar } 21642f480046SShri Abhyankar 2165c75a6043SHong Zhang /*@ 216611a5261eSBarry Smith MatCreateSeqSBAIJWithArrays - Creates an sequential `MATSEQSBAIJ` matrix using matrix elements 2167c75a6043SHong Zhang (upper triangular entries in CSR format) provided by the user. 2168c75a6043SHong Zhang 2169d083f849SBarry Smith Collective 2170c75a6043SHong Zhang 2171c75a6043SHong Zhang Input Parameters: 2172c75a6043SHong Zhang + comm - must be an MPI communicator of size 1 2173c75a6043SHong Zhang . bs - size of block 2174c75a6043SHong Zhang . m - number of rows 2175c75a6043SHong Zhang . n - number of columns 2176483a2f95SBarry 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 2177c75a6043SHong Zhang . j - column indices 2178c75a6043SHong Zhang - a - matrix values 2179c75a6043SHong Zhang 2180c75a6043SHong Zhang Output Parameter: 2181c75a6043SHong Zhang . mat - the matrix 2182c75a6043SHong Zhang 2183dfb205c3SBarry Smith Level: advanced 2184c75a6043SHong Zhang 2185c75a6043SHong Zhang Notes: 21862ef1f0ffSBarry Smith The `i`, `j`, and `a` arrays are not copied by this routine, the user must free these arrays 2187c75a6043SHong Zhang once the matrix is destroyed 2188c75a6043SHong Zhang 2189c75a6043SHong Zhang You cannot set new nonzero locations into this matrix, that will generate an error. 2190c75a6043SHong Zhang 21912ef1f0ffSBarry Smith The `i` and `j` indices are 0 based 2192c75a6043SHong Zhang 21932ef1f0ffSBarry Smith When block size is greater than 1 the matrix values must be stored using the `MATSBAIJ` storage format. For block size of 1 2194dfb205c3SBarry Smith it is the regular CSR format excluding the lower triangular elements. 2195dfb205c3SBarry Smith 21961cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQSBAIJ`, `MatCreate()`, `MatCreateSBAIJ()`, `MatCreateSeqSBAIJ()` 2197c75a6043SHong Zhang @*/ 2198d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqSBAIJWithArrays(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat) 2199d71ae5a4SJacob Faibussowitsch { 2200c75a6043SHong Zhang PetscInt ii; 2201c75a6043SHong Zhang Mat_SeqSBAIJ *sbaij; 2202c75a6043SHong Zhang 2203c75a6043SHong Zhang PetscFunctionBegin; 220408401ef6SPierre Jolivet PetscCheck(bs == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "block size %" PetscInt_FMT " > 1 is not supported yet", bs); 2205aed4548fSBarry Smith PetscCheck(m == 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0"); 2206c75a6043SHong Zhang 22079566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 22089566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 22099566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQSBAIJ)); 22109566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(*mat, bs, MAT_SKIP_ALLOCATION, NULL)); 2211c75a6043SHong Zhang sbaij = (Mat_SeqSBAIJ *)(*mat)->data; 22129566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(m, &sbaij->imax, m, &sbaij->ilen)); 2213c75a6043SHong Zhang 2214c75a6043SHong Zhang sbaij->i = i; 2215c75a6043SHong Zhang sbaij->j = j; 2216c75a6043SHong Zhang sbaij->a = a; 221726fbe8dcSKarl Rupp 2218c75a6043SHong Zhang sbaij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 2219e6b907acSBarry Smith sbaij->free_a = PETSC_FALSE; 2220e6b907acSBarry Smith sbaij->free_ij = PETSC_FALSE; 2221ddf7884eSMatthew Knepley sbaij->free_imax_ilen = PETSC_TRUE; 2222c75a6043SHong Zhang 2223c75a6043SHong Zhang for (ii = 0; ii < m; ii++) { 2224c75a6043SHong Zhang sbaij->ilen[ii] = sbaij->imax[ii] = i[ii + 1] - i[ii]; 22256bdcaf15SBarry 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]); 2226c75a6043SHong Zhang } 222776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 2228c75a6043SHong Zhang for (ii = 0; ii < sbaij->i[m]; ii++) { 22296bdcaf15SBarry 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]); 22306bdcaf15SBarry 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]); 2231c75a6043SHong Zhang } 223276bd3646SJed Brown } 2233c75a6043SHong Zhang 22349566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 22359566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 22363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2237c75a6043SHong Zhang } 2238d06b337dSHong Zhang 2239d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqSBAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat) 2240d71ae5a4SJacob Faibussowitsch { 224159f5e6ceSHong Zhang PetscFunctionBegin; 22429566063dSJacob Faibussowitsch PetscCall(MatCreateMPIMatConcatenateSeqMat_MPISBAIJ(comm, inmat, n, scall, outmat)); 22433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 224459f5e6ceSHong Zhang } 2245