1d5d45c9bSBarry Smith /* 23369ce9aSBarry Smith Defines the basic matrix operations for the AIJ (compressed row) 3d5d45c9bSBarry Smith matrix storage format. 4d5d45c9bSBarry Smith */ 53369ce9aSBarry Smith 6c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h> /*I "petscmat.h" I*/ 7c6db04a5SJed Brown #include <petscblaslapack.h> 8c6db04a5SJed Brown #include <petscbt.h> 9af0996ceSBarry Smith #include <petsc/private/kernels/blocktranspose.h> 100716a85fSBarry Smith 1126cec326SBarry Smith /* defines MatSetValues_Seq_Hash(), MatAssemblyEnd_Seq_Hash(), MatSetUp_Seq_Hash() */ 1226cec326SBarry Smith #define TYPE AIJ 1326cec326SBarry Smith #define TYPE_BS 1426cec326SBarry Smith #include "../src/mat/impls/aij/seq/seqhashmatsetvalues.h" 1526cec326SBarry Smith #include "../src/mat/impls/aij/seq/seqhashmat.h" 1626cec326SBarry Smith #undef TYPE 1726cec326SBarry Smith #undef TYPE_BS 1826cec326SBarry Smith 19*421480d9SBarry Smith MatGetDiagonalMarkers(SeqAIJ, 1) 20*421480d9SBarry Smith 21ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A) 22d71ae5a4SJacob Faibussowitsch { 234099cc6bSBarry Smith PetscBool flg; 244099cc6bSBarry Smith char type[256]; 254099cc6bSBarry Smith 264099cc6bSBarry Smith PetscFunctionBegin; 27d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)A); 289566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-mat_seqaij_type", "Matrix SeqAIJ type", "MatSeqAIJSetType", MatSeqAIJList, "seqaij", type, 256, &flg)); 299566063dSJacob Faibussowitsch if (flg) PetscCall(MatSeqAIJSetType(A, type)); 30d0609cedSBarry Smith PetscOptionsEnd(); 313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 324099cc6bSBarry Smith } 334099cc6bSBarry Smith 34ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetColumnReductions_SeqAIJ(Mat A, PetscInt type, PetscReal *reductions) 35d71ae5a4SJacob Faibussowitsch { 360716a85fSBarry Smith PetscInt i, m, n; 370716a85fSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 380716a85fSBarry Smith 390716a85fSBarry Smith PetscFunctionBegin; 409566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &m, &n)); 419566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(reductions, n)); 420716a85fSBarry Smith if (type == NORM_2) { 43ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscAbsScalar(aij->a[i] * aij->a[i]); 440716a85fSBarry Smith } else if (type == NORM_1) { 45ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]); 460716a85fSBarry Smith } else if (type == NORM_INFINITY) { 47ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]), reductions[aij->j[i]]); 48857cbf51SRichard Tran Mills } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) { 49ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscRealPart(aij->a[i]); 50857cbf51SRichard Tran Mills } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) { 51ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscImaginaryPart(aij->a[i]); 526adde796SStefano Zampini } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type"); 530716a85fSBarry Smith 540716a85fSBarry Smith if (type == NORM_2) { 55a873a8cdSSam Reynolds for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]); 56857cbf51SRichard Tran Mills } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) { 57a873a8cdSSam Reynolds for (i = 0; i < n; i++) reductions[i] /= m; 580716a85fSBarry Smith } 593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 600716a85fSBarry Smith } 610716a85fSBarry Smith 62ba38deedSJacob Faibussowitsch static PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A, IS *is) 63d71ae5a4SJacob Faibussowitsch { 643a062f41SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 653a062f41SBarry Smith PetscInt i, m = A->rmap->n, cnt = 0, bs = A->rmap->bs; 663a062f41SBarry Smith const PetscInt *jj = a->j, *ii = a->i; 673a062f41SBarry Smith PetscInt *rows; 683a062f41SBarry Smith 693a062f41SBarry Smith PetscFunctionBegin; 703a062f41SBarry Smith for (i = 0; i < m; i++) { 71ad540459SPierre Jolivet if ((ii[i] != ii[i + 1]) && ((jj[ii[i]] < bs * (i / bs)) || (jj[ii[i + 1] - 1] > bs * ((i + bs) / bs) - 1))) cnt++; 723a062f41SBarry Smith } 739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cnt, &rows)); 743a062f41SBarry Smith cnt = 0; 753a062f41SBarry Smith for (i = 0; i < m; i++) { 763a062f41SBarry Smith if ((ii[i] != ii[i + 1]) && ((jj[ii[i]] < bs * (i / bs)) || (jj[ii[i + 1] - 1] > bs * ((i + bs) / bs) - 1))) { 773a062f41SBarry Smith rows[cnt] = i; 783a062f41SBarry Smith cnt++; 793a062f41SBarry Smith } 803a062f41SBarry Smith } 819566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cnt, rows, PETSC_OWN_POINTER, is)); 823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 833a062f41SBarry Smith } 843a062f41SBarry Smith 85d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A, PetscInt *nrows, PetscInt **zrows) 86d71ae5a4SJacob Faibussowitsch { 876ce1633cSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 88fff043a9SJunchao Zhang const MatScalar *aa; 896ce1633cSBarry Smith PetscInt i, m = A->rmap->n, cnt = 0; 90b2db7409Sstefano_zampini const PetscInt *ii = a->i, *jj = a->j, *diag; 916ce1633cSBarry Smith PetscInt *rows; 926ce1633cSBarry Smith 936ce1633cSBarry Smith PetscFunctionBegin; 949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 95*421480d9SBarry Smith PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, NULL)); 966ce1633cSBarry Smith for (i = 0; i < m; i++) { 97ad540459SPierre Jolivet if ((diag[i] >= ii[i + 1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) cnt++; 986ce1633cSBarry Smith } 999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cnt, &rows)); 1006ce1633cSBarry Smith cnt = 0; 1016ce1633cSBarry Smith for (i = 0; i < m; i++) { 102ad540459SPierre Jolivet if ((diag[i] >= ii[i + 1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) rows[cnt++] = i; 1036ce1633cSBarry Smith } 104f1f41ecbSJed Brown *nrows = cnt; 105f1f41ecbSJed Brown *zrows = rows; 1069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 1073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 108f1f41ecbSJed Brown } 109f1f41ecbSJed Brown 110ba38deedSJacob Faibussowitsch static PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A, IS *zrows) 111d71ae5a4SJacob Faibussowitsch { 112f1f41ecbSJed Brown PetscInt nrows, *rows; 113f1f41ecbSJed Brown 114f1f41ecbSJed Brown PetscFunctionBegin; 1150298fd71SBarry Smith *zrows = NULL; 1169566063dSJacob Faibussowitsch PetscCall(MatFindZeroDiagonals_SeqAIJ_Private(A, &nrows, &rows)); 1179566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), nrows, rows, PETSC_OWN_POINTER, zrows)); 1183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1196ce1633cSBarry Smith } 1206ce1633cSBarry Smith 121ba38deedSJacob Faibussowitsch static PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A, IS *keptrows) 122d71ae5a4SJacob Faibussowitsch { 123b3a44c85SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 124b3a44c85SBarry Smith const MatScalar *aa; 125b3a44c85SBarry Smith PetscInt m = A->rmap->n, cnt = 0; 126b3a44c85SBarry Smith const PetscInt *ii; 127b3a44c85SBarry Smith PetscInt n, i, j, *rows; 128b3a44c85SBarry Smith 129b3a44c85SBarry Smith PetscFunctionBegin; 1309566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 131f4259b30SLisandro Dalcin *keptrows = NULL; 132b3a44c85SBarry Smith ii = a->i; 133b3a44c85SBarry Smith for (i = 0; i < m; i++) { 134b3a44c85SBarry Smith n = ii[i + 1] - ii[i]; 135b3a44c85SBarry Smith if (!n) { 136b3a44c85SBarry Smith cnt++; 137b3a44c85SBarry Smith goto ok1; 138b3a44c85SBarry Smith } 1392e5835c6SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 140b3a44c85SBarry Smith if (aa[j] != 0.0) goto ok1; 141b3a44c85SBarry Smith } 142b3a44c85SBarry Smith cnt++; 143b3a44c85SBarry Smith ok1:; 144b3a44c85SBarry Smith } 1452e5835c6SStefano Zampini if (!cnt) { 1469566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 1473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1482e5835c6SStefano Zampini } 1499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n - cnt, &rows)); 150b3a44c85SBarry Smith cnt = 0; 151b3a44c85SBarry Smith for (i = 0; i < m; i++) { 152b3a44c85SBarry Smith n = ii[i + 1] - ii[i]; 153b3a44c85SBarry Smith if (!n) continue; 1542e5835c6SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 155b3a44c85SBarry Smith if (aa[j] != 0.0) { 156b3a44c85SBarry Smith rows[cnt++] = i; 157b3a44c85SBarry Smith break; 158b3a44c85SBarry Smith } 159b3a44c85SBarry Smith } 160b3a44c85SBarry Smith } 1619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 1629566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cnt, rows, PETSC_OWN_POINTER, keptrows)); 1633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 164b3a44c85SBarry Smith } 165b3a44c85SBarry Smith 166d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDiagonalSet_SeqAIJ(Mat Y, Vec D, InsertMode is) 167d71ae5a4SJacob Faibussowitsch { 16899e65526SBarry Smith PetscInt i, m = Y->rmap->n; 16999e65526SBarry Smith const PetscInt *diag; 1702e5835c6SStefano Zampini MatScalar *aa; 17199e65526SBarry Smith const PetscScalar *v; 172*421480d9SBarry Smith PetscBool diagDense; 17379299369SBarry Smith 17479299369SBarry Smith PetscFunctionBegin; 17509f38230SBarry Smith if (Y->assembled) { 176*421480d9SBarry Smith PetscCall(MatGetDiagonalMarkers_SeqAIJ(Y, &diag, &diagDense)); 177*421480d9SBarry Smith if (diagDense) { 1789566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(D, &v)); 1799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Y, &aa)); 18079299369SBarry Smith if (is == INSERT_VALUES) { 181ad540459SPierre Jolivet for (i = 0; i < m; i++) aa[diag[i]] = v[i]; 18279299369SBarry Smith } else { 183ad540459SPierre Jolivet for (i = 0; i < m; i++) aa[diag[i]] += v[i]; 18479299369SBarry Smith } 1859566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Y, &aa)); 1869566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(D, &v)); 1873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18879299369SBarry Smith } 18909f38230SBarry Smith } 1909566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet_Default(Y, D, is)); 1913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19209f38230SBarry Smith } 19379299369SBarry Smith 194d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *m, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 195d71ae5a4SJacob Faibussowitsch { 196416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 19797f1f81fSBarry Smith PetscInt i, ishift; 19817ab2063SBarry Smith 1993a40ed3dSBarry Smith PetscFunctionBegin; 200f1f2ae84SBarry Smith if (m) *m = A->rmap->n; 2013ba16761SJacob Faibussowitsch if (!ia) PetscFunctionReturn(PETSC_SUCCESS); 202bfeeae90SHong Zhang ishift = 0; 203b94d7dedSBarry Smith if (symmetric && A->structurally_symmetric != PETSC_BOOL3_TRUE) { 2049566063dSJacob Faibussowitsch PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n, a->i, a->j, PETSC_TRUE, ishift, oshift, (PetscInt **)ia, (PetscInt **)ja)); 205bfeeae90SHong Zhang } else if (oshift == 1) { 2061a83f524SJed Brown PetscInt *tia; 207d0f46423SBarry Smith PetscInt nz = a->i[A->rmap->n]; 2083b2fbd54SBarry Smith /* malloc space and add 1 to i and j indices */ 2099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n + 1, &tia)); 2101a83f524SJed Brown for (i = 0; i < A->rmap->n + 1; i++) tia[i] = a->i[i] + 1; 2111a83f524SJed Brown *ia = tia; 212ecc77c7aSBarry Smith if (ja) { 2131a83f524SJed Brown PetscInt *tja; 2149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz + 1, &tja)); 2151a83f524SJed Brown for (i = 0; i < nz; i++) tja[i] = a->j[i] + 1; 2161a83f524SJed Brown *ja = tja; 217ecc77c7aSBarry Smith } 2186945ee14SBarry Smith } else { 219ecc77c7aSBarry Smith *ia = a->i; 220ecc77c7aSBarry Smith if (ja) *ja = a->j; 221a2ce50c7SBarry Smith } 2223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 223a2744918SBarry Smith } 224a2744918SBarry Smith 225d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 226d71ae5a4SJacob Faibussowitsch { 2273a40ed3dSBarry Smith PetscFunctionBegin; 2283ba16761SJacob Faibussowitsch if (!ia) PetscFunctionReturn(PETSC_SUCCESS); 229b94d7dedSBarry Smith if ((symmetric && A->structurally_symmetric != PETSC_BOOL3_TRUE) || oshift == 1) { 2309566063dSJacob Faibussowitsch PetscCall(PetscFree(*ia)); 2319566063dSJacob Faibussowitsch if (ja) PetscCall(PetscFree(*ja)); 232bcd2baecSBarry Smith } 2333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23417ab2063SBarry Smith } 23517ab2063SBarry Smith 236d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 237d71ae5a4SJacob Faibussowitsch { 2383b2fbd54SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 239d0f46423SBarry Smith PetscInt i, *collengths, *cia, *cja, n = A->cmap->n, m = A->rmap->n; 24097f1f81fSBarry Smith PetscInt nz = a->i[m], row, *jj, mr, col; 2413b2fbd54SBarry Smith 2423a40ed3dSBarry Smith PetscFunctionBegin; 243899cda47SBarry Smith *nn = n; 2443ba16761SJacob Faibussowitsch if (!ia) PetscFunctionReturn(PETSC_SUCCESS); 2453b2fbd54SBarry Smith if (symmetric) { 2469566063dSJacob Faibussowitsch PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n, a->i, a->j, PETSC_TRUE, 0, oshift, (PetscInt **)ia, (PetscInt **)ja)); 2473b2fbd54SBarry Smith } else { 2489566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &collengths)); 2499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &cia)); 2509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &cja)); 2513b2fbd54SBarry Smith jj = a->j; 252ad540459SPierre Jolivet for (i = 0; i < nz; i++) collengths[jj[i]]++; 2533b2fbd54SBarry Smith cia[0] = oshift; 254ad540459SPierre Jolivet for (i = 0; i < n; i++) cia[i + 1] = cia[i] + collengths[i]; 2559566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(collengths, n)); 2563b2fbd54SBarry Smith jj = a->j; 257a93ec695SBarry Smith for (row = 0; row < m; row++) { 258a93ec695SBarry Smith mr = a->i[row + 1] - a->i[row]; 259a93ec695SBarry Smith for (i = 0; i < mr; i++) { 260bfeeae90SHong Zhang col = *jj++; 2612205254eSKarl Rupp 2623b2fbd54SBarry Smith cja[cia[col] + collengths[col]++ - oshift] = row + oshift; 2633b2fbd54SBarry Smith } 2643b2fbd54SBarry Smith } 2659566063dSJacob Faibussowitsch PetscCall(PetscFree(collengths)); 2669371c9d4SSatish Balay *ia = cia; 2679371c9d4SSatish Balay *ja = cja; 2683b2fbd54SBarry Smith } 2693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2703b2fbd54SBarry Smith } 2713b2fbd54SBarry Smith 272d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 273d71ae5a4SJacob Faibussowitsch { 2743a40ed3dSBarry Smith PetscFunctionBegin; 2753ba16761SJacob Faibussowitsch if (!ia) PetscFunctionReturn(PETSC_SUCCESS); 2763b2fbd54SBarry Smith 2779566063dSJacob Faibussowitsch PetscCall(PetscFree(*ia)); 2789566063dSJacob Faibussowitsch PetscCall(PetscFree(*ja)); 2793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2803b2fbd54SBarry Smith } 2813b2fbd54SBarry Smith 2827cee066cSHong Zhang /* 2837cee066cSHong Zhang MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from 2847cee066cSHong Zhang MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output 285040ebd07SHong Zhang spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ() 2867cee066cSHong Zhang */ 287d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnIJ_SeqAIJ_Color(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscInt *spidx[], PetscBool *done) 288d71ae5a4SJacob Faibussowitsch { 2897cee066cSHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2907cee066cSHong Zhang PetscInt i, *collengths, *cia, *cja, n = A->cmap->n, m = A->rmap->n; 291071fcb05SBarry Smith PetscInt nz = a->i[m], row, mr, col, tmp; 2927cee066cSHong Zhang PetscInt *cspidx; 293071fcb05SBarry Smith const PetscInt *jj; 2947cee066cSHong Zhang 2957cee066cSHong Zhang PetscFunctionBegin; 2967cee066cSHong Zhang *nn = n; 2973ba16761SJacob Faibussowitsch if (!ia) PetscFunctionReturn(PETSC_SUCCESS); 298625f6d37SHong Zhang 2999566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &collengths)); 3009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &cia)); 3019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &cja)); 3029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &cspidx)); 3037cee066cSHong Zhang jj = a->j; 304ad540459SPierre Jolivet for (i = 0; i < nz; i++) collengths[jj[i]]++; 3057cee066cSHong Zhang cia[0] = oshift; 306ad540459SPierre Jolivet for (i = 0; i < n; i++) cia[i + 1] = cia[i] + collengths[i]; 3079566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(collengths, n)); 3087cee066cSHong Zhang jj = a->j; 3097cee066cSHong Zhang for (row = 0; row < m; row++) { 3107cee066cSHong Zhang mr = a->i[row + 1] - a->i[row]; 3117cee066cSHong Zhang for (i = 0; i < mr; i++) { 3127cee066cSHong Zhang col = *jj++; 313071fcb05SBarry Smith tmp = cia[col] + collengths[col]++ - oshift; 314071fcb05SBarry Smith cspidx[tmp] = a->i[row] + i; /* index of a->j */ 315071fcb05SBarry Smith cja[tmp] = row + oshift; 3167cee066cSHong Zhang } 3177cee066cSHong Zhang } 3189566063dSJacob Faibussowitsch PetscCall(PetscFree(collengths)); 319071fcb05SBarry Smith *ia = cia; 320071fcb05SBarry Smith *ja = cja; 3217cee066cSHong Zhang *spidx = cspidx; 3223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3237cee066cSHong Zhang } 3247cee066cSHong Zhang 325d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreColumnIJ_SeqAIJ_Color(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscInt *spidx[], PetscBool *done) 326d71ae5a4SJacob Faibussowitsch { 3277cee066cSHong Zhang PetscFunctionBegin; 3289566063dSJacob Faibussowitsch PetscCall(MatRestoreColumnIJ_SeqAIJ(A, oshift, symmetric, inodecompressed, n, ia, ja, done)); 3299566063dSJacob Faibussowitsch PetscCall(PetscFree(*spidx)); 3303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3317cee066cSHong Zhang } 3327cee066cSHong Zhang 333ba38deedSJacob Faibussowitsch static PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A, PetscInt row, const PetscScalar v[]) 334d71ae5a4SJacob Faibussowitsch { 33587d4246cSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 33687d4246cSBarry Smith PetscInt *ai = a->i; 337fff043a9SJunchao Zhang PetscScalar *aa; 33887d4246cSBarry Smith 33987d4246cSBarry Smith PetscFunctionBegin; 3409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 3419566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aa + ai[row], v, ai[row + 1] - ai[row])); 3429566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 3433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34487d4246cSBarry Smith } 34587d4246cSBarry Smith 346bd04181cSBarry Smith /* 347bd04181cSBarry Smith MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions 348bd04181cSBarry Smith 349bd04181cSBarry Smith - a single row of values is set with each call 350bd04181cSBarry Smith - no row or column indices are negative or (in error) larger than the number of rows or columns 351bd04181cSBarry Smith - the values are always added to the matrix, not set 352bd04181cSBarry Smith - no new locations are introduced in the nonzero structure of the matrix 353bd04181cSBarry Smith 3541f763a69SBarry Smith This does NOT assume the global column indices are sorted 355bd04181cSBarry Smith 3561f763a69SBarry Smith */ 357bd04181cSBarry Smith 358af0996ceSBarry Smith #include <petsc/private/isimpl.h> 359d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) 360d71ae5a4SJacob Faibussowitsch { 361189e4007SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3621f763a69SBarry Smith PetscInt low, high, t, row, nrow, i, col, l; 3631f763a69SBarry Smith const PetscInt *rp, *ai = a->i, *ailen = a->ilen, *aj = a->j; 3641f763a69SBarry Smith PetscInt lastcol = -1; 365fff043a9SJunchao Zhang MatScalar *ap, value, *aa; 366189e4007SBarry Smith const PetscInt *ridx = A->rmap->mapping->indices, *cidx = A->cmap->mapping->indices; 367189e4007SBarry Smith 368fff043a9SJunchao Zhang PetscFunctionBegin; 3699566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 370f38dd0b8SBarry Smith row = ridx[im[0]]; 3711f763a69SBarry Smith rp = aj + ai[row]; 3721f763a69SBarry Smith ap = aa + ai[row]; 3731f763a69SBarry Smith nrow = ailen[row]; 374189e4007SBarry Smith low = 0; 375189e4007SBarry Smith high = nrow; 376189e4007SBarry Smith for (l = 0; l < n; l++) { /* loop over added columns */ 377189e4007SBarry Smith col = cidx[in[l]]; 378f38dd0b8SBarry Smith value = v[l]; 379189e4007SBarry Smith 380189e4007SBarry Smith if (col <= lastcol) low = 0; 381189e4007SBarry Smith else high = nrow; 382189e4007SBarry Smith lastcol = col; 383189e4007SBarry Smith while (high - low > 5) { 384189e4007SBarry Smith t = (low + high) / 2; 385189e4007SBarry Smith if (rp[t] > col) high = t; 386189e4007SBarry Smith else low = t; 387189e4007SBarry Smith } 388189e4007SBarry Smith for (i = low; i < high; i++) { 389189e4007SBarry Smith if (rp[i] == col) { 3901f763a69SBarry Smith ap[i] += value; 391189e4007SBarry Smith low = i + 1; 3921f763a69SBarry Smith break; 393189e4007SBarry Smith } 394189e4007SBarry Smith } 395189e4007SBarry Smith } 3969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 3973ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 398189e4007SBarry Smith } 399189e4007SBarry Smith 400d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValues_SeqAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) 401d71ae5a4SJacob Faibussowitsch { 402416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 403e2ee6c50SBarry Smith PetscInt *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N; 40497f1f81fSBarry Smith PetscInt *imax = a->imax, *ai = a->i, *ailen = a->ilen; 405e2ee6c50SBarry Smith PetscInt *aj = a->j, nonew = a->nonew, lastcol = -1; 406ce496241SStefano Zampini MatScalar *ap = NULL, value = 0.0, *aa; 407ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 408ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 40917ab2063SBarry Smith 4103a40ed3dSBarry Smith PetscFunctionBegin; 4119566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 41217ab2063SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 413416022c9SBarry Smith row = im[k]; 4145ef9f2a5SBarry Smith if (row < 0) continue; 4156bdcaf15SBarry 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); 4168e3a54c0SPierre Jolivet rp = PetscSafePointerPlusOffset(aj, ai[row]); 4178e3a54c0SPierre Jolivet if (!A->structure_only) ap = PetscSafePointerPlusOffset(aa, ai[row]); 4189371c9d4SSatish Balay rmax = imax[row]; 4199371c9d4SSatish Balay nrow = ailen[row]; 420416022c9SBarry Smith low = 0; 421c71e6ed7SBarry Smith high = nrow; 42217ab2063SBarry Smith for (l = 0; l < n; l++) { /* loop over added columns */ 4235ef9f2a5SBarry Smith if (in[l] < 0) continue; 4246bdcaf15SBarry 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); 425bfeeae90SHong Zhang col = in[l]; 426071fcb05SBarry Smith if (v && !A->structure_only) value = roworiented ? v[l + k * n] : v[k + l * m]; 427071fcb05SBarry Smith if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue; 42836db0b34SBarry Smith 4292205254eSKarl Rupp if (col <= lastcol) low = 0; 4302205254eSKarl Rupp else high = nrow; 431e2ee6c50SBarry Smith lastcol = col; 432416022c9SBarry Smith while (high - low > 5) { 433416022c9SBarry Smith t = (low + high) / 2; 434416022c9SBarry Smith if (rp[t] > col) high = t; 435416022c9SBarry Smith else low = t; 43617ab2063SBarry Smith } 437416022c9SBarry Smith for (i = low; i < high; i++) { 43817ab2063SBarry Smith if (rp[i] > col) break; 43917ab2063SBarry Smith if (rp[i] == col) { 440876c6284SHong Zhang if (!A->structure_only) { 4410c0d7e18SFande Kong if (is == ADD_VALUES) { 4420c0d7e18SFande Kong ap[i] += value; 4430c0d7e18SFande Kong (void)PetscLogFlops(1.0); 4449371c9d4SSatish Balay } else ap[i] = value; 445720833daSHong Zhang } 446e44c0bd4SBarry Smith low = i + 1; 44717ab2063SBarry Smith goto noinsert; 44817ab2063SBarry Smith } 44917ab2063SBarry Smith } 450dcd36c23SBarry Smith if (value == 0.0 && ignorezeroentries && row != col) goto noinsert; 451c2653b3dSLois Curfman McInnes if (nonew == 1) goto noinsert; 45208401ef6SPierre Jolivet PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero at (%" PetscInt_FMT ",%" PetscInt_FMT ") in the matrix", row, col); 453720833daSHong Zhang if (A->structure_only) { 454876c6284SHong Zhang MatSeqXAIJReallocateAIJ_structure_only(A, A->rmap->n, 1, nrow, row, col, rmax, ai, aj, rp, imax, nonew, MatScalar); 455720833daSHong Zhang } else { 456fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, A->rmap->n, 1, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 457720833daSHong Zhang } 4589371c9d4SSatish Balay N = nrow++ - 1; 4599371c9d4SSatish Balay a->nz++; 4609371c9d4SSatish Balay high++; 461416022c9SBarry Smith /* shift up all the later entries in this row */ 4629566063dSJacob Faibussowitsch PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1)); 46317ab2063SBarry Smith rp[i] = col; 464580bdb30SBarry Smith if (!A->structure_only) { 4659566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap + i + 1, ap + i, N - i + 1)); 466580bdb30SBarry Smith ap[i] = value; 467580bdb30SBarry Smith } 468416022c9SBarry Smith low = i + 1; 469e44c0bd4SBarry Smith noinsert:; 47017ab2063SBarry Smith } 47117ab2063SBarry Smith ailen[row] = nrow; 47217ab2063SBarry Smith } 4739566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 4743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47517ab2063SBarry Smith } 47617ab2063SBarry Smith 477ba38deedSJacob Faibussowitsch static PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) 478d71ae5a4SJacob Faibussowitsch { 47919b08ed1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 48019b08ed1SBarry Smith PetscInt *rp, k, row; 48119b08ed1SBarry Smith PetscInt *ai = a->i; 48219b08ed1SBarry Smith PetscInt *aj = a->j; 483fff043a9SJunchao Zhang MatScalar *aa, *ap; 48419b08ed1SBarry Smith 48519b08ed1SBarry Smith PetscFunctionBegin; 48628b400f6SJacob Faibussowitsch PetscCheck(!A->was_assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call on assembled matrix."); 48708401ef6SPierre Jolivet PetscCheck(m * n + a->nz <= a->maxnz, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of entries in matrix will be larger than maximum nonzeros allocated for %" PetscInt_FMT " in MatSeqAIJSetTotalPreallocation()", a->maxnz); 488fff043a9SJunchao Zhang 4899566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 49019b08ed1SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 49119b08ed1SBarry Smith row = im[k]; 49219b08ed1SBarry Smith rp = aj + ai[row]; 4938e3a54c0SPierre Jolivet ap = PetscSafePointerPlusOffset(aa, ai[row]); 49419b08ed1SBarry Smith 4959566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(rp, in, n * sizeof(PetscInt))); 49619b08ed1SBarry Smith if (!A->structure_only) { 49719b08ed1SBarry Smith if (v) { 4989566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(ap, v, n * sizeof(PetscScalar))); 49919b08ed1SBarry Smith v += n; 50019b08ed1SBarry Smith } else { 5019566063dSJacob Faibussowitsch PetscCall(PetscMemzero(ap, n * sizeof(PetscScalar))); 50219b08ed1SBarry Smith } 50319b08ed1SBarry Smith } 50419b08ed1SBarry Smith a->ilen[row] = n; 50519b08ed1SBarry Smith a->imax[row] = n; 50619b08ed1SBarry Smith a->i[row + 1] = a->i[row] + n; 50719b08ed1SBarry Smith a->nz += n; 50819b08ed1SBarry Smith } 5099566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 5103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51119b08ed1SBarry Smith } 51219b08ed1SBarry Smith 51319b08ed1SBarry Smith /*@ 51419b08ed1SBarry Smith MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix. 51519b08ed1SBarry Smith 51619b08ed1SBarry Smith Input Parameters: 51711a5261eSBarry Smith + A - the `MATSEQAIJ` matrix 51819b08ed1SBarry Smith - nztotal - bound on the number of nonzeros 51919b08ed1SBarry Smith 52019b08ed1SBarry Smith Level: advanced 52119b08ed1SBarry Smith 52219b08ed1SBarry Smith Notes: 52319b08ed1SBarry Smith This can be called if you will be provided the matrix row by row (from row zero) with sorted column indices for each row. 52411a5261eSBarry Smith Simply call `MatSetValues()` after this call to provide the matrix entries in the usual manner. This matrix may be used 52519b08ed1SBarry Smith as always with multiple matrix assemblies. 52619b08ed1SBarry Smith 5271cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MAT_SORTED_FULL`, `MatSetValues()`, `MatSeqAIJSetPreallocation()` 52819b08ed1SBarry Smith @*/ 529d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A, PetscInt nztotal) 530d71ae5a4SJacob Faibussowitsch { 53119b08ed1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 53219b08ed1SBarry Smith 53319b08ed1SBarry Smith PetscFunctionBegin; 5349566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 5359566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 53619b08ed1SBarry Smith a->maxnz = nztotal; 5373a7d0413SPierre Jolivet if (!a->imax) PetscCall(PetscMalloc1(A->rmap->n, &a->imax)); 53819b08ed1SBarry Smith if (!a->ilen) { 5399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &a->ilen)); 54019b08ed1SBarry Smith } else { 5419566063dSJacob Faibussowitsch PetscCall(PetscMemzero(a->ilen, A->rmap->n * sizeof(PetscInt))); 54219b08ed1SBarry Smith } 54319b08ed1SBarry Smith 54419b08ed1SBarry Smith /* allocate the matrix space */ 5459f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(A->rmap->n + 1, sizeof(PetscInt), (void **)&a->i)); 5469f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(nztotal, sizeof(PetscInt), (void **)&a->j)); 5479f0612e4SBarry Smith a->free_ij = PETSC_TRUE; 54819b08ed1SBarry Smith if (A->structure_only) { 54919b08ed1SBarry Smith a->free_a = PETSC_FALSE; 55019b08ed1SBarry Smith } else { 5519f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(nztotal, sizeof(PetscScalar), (void **)&a->a)); 55219b08ed1SBarry Smith a->free_a = PETSC_TRUE; 55319b08ed1SBarry Smith } 5549f0612e4SBarry Smith a->i[0] = 0; 55519b08ed1SBarry Smith A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation; 55619b08ed1SBarry Smith A->preallocated = PETSC_TRUE; 5573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55819b08ed1SBarry Smith } 55919b08ed1SBarry Smith 560ba38deedSJacob Faibussowitsch static PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) 561d71ae5a4SJacob Faibussowitsch { 562071fcb05SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 563071fcb05SBarry Smith PetscInt *rp, k, row; 564071fcb05SBarry Smith PetscInt *ai = a->i, *ailen = a->ilen; 565071fcb05SBarry Smith PetscInt *aj = a->j; 566fff043a9SJunchao Zhang MatScalar *aa, *ap; 567071fcb05SBarry Smith 568071fcb05SBarry Smith PetscFunctionBegin; 5699566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 570071fcb05SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 571071fcb05SBarry Smith row = im[k]; 5726bdcaf15SBarry Smith PetscCheck(n <= a->imax[row], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Preallocation for row %" PetscInt_FMT " does not match number of columns provided", n); 573071fcb05SBarry Smith rp = aj + ai[row]; 574071fcb05SBarry Smith ap = aa + ai[row]; 57548a46eb9SPierre Jolivet if (!A->was_assembled) PetscCall(PetscMemcpy(rp, in, n * sizeof(PetscInt))); 576071fcb05SBarry Smith if (!A->structure_only) { 577071fcb05SBarry Smith if (v) { 5789566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(ap, v, n * sizeof(PetscScalar))); 579071fcb05SBarry Smith v += n; 580071fcb05SBarry Smith } else { 5819566063dSJacob Faibussowitsch PetscCall(PetscMemzero(ap, n * sizeof(PetscScalar))); 582071fcb05SBarry Smith } 583071fcb05SBarry Smith } 584071fcb05SBarry Smith ailen[row] = n; 585071fcb05SBarry Smith a->nz += n; 586071fcb05SBarry Smith } 5879566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 5883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 589071fcb05SBarry Smith } 590071fcb05SBarry Smith 591ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetValues_SeqAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[]) 592d71ae5a4SJacob Faibussowitsch { 5937eb43aa7SLois Curfman McInnes Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 59497f1f81fSBarry Smith PetscInt *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j; 59597f1f81fSBarry Smith PetscInt *ai = a->i, *ailen = a->ilen; 5964e208921SJed Brown const MatScalar *ap, *aa; 5977eb43aa7SLois Curfman McInnes 5983a40ed3dSBarry Smith PetscFunctionBegin; 5994e208921SJed Brown PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 6007eb43aa7SLois Curfman McInnes for (k = 0; k < m; k++) { /* loop over rows */ 6017eb43aa7SLois Curfman McInnes row = im[k]; 6029371c9d4SSatish Balay if (row < 0) { 6039371c9d4SSatish Balay v += n; 6049371c9d4SSatish Balay continue; 6059371c9d4SSatish Balay } /* negative row */ 60654c59aa7SJacob 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); 6078e3a54c0SPierre Jolivet rp = PetscSafePointerPlusOffset(aj, ai[row]); 6088e3a54c0SPierre Jolivet ap = PetscSafePointerPlusOffset(aa, ai[row]); 6097eb43aa7SLois Curfman McInnes nrow = ailen[row]; 6107eb43aa7SLois Curfman McInnes for (l = 0; l < n; l++) { /* loop over columns */ 6119371c9d4SSatish Balay if (in[l] < 0) { 6129371c9d4SSatish Balay v++; 6139371c9d4SSatish Balay continue; 6149371c9d4SSatish Balay } /* negative column */ 61554c59aa7SJacob 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); 616bfeeae90SHong Zhang col = in[l]; 6179371c9d4SSatish Balay high = nrow; 6189371c9d4SSatish Balay low = 0; /* assume unsorted */ 6197eb43aa7SLois Curfman McInnes while (high - low > 5) { 6207eb43aa7SLois Curfman McInnes t = (low + high) / 2; 6217eb43aa7SLois Curfman McInnes if (rp[t] > col) high = t; 6227eb43aa7SLois Curfman McInnes else low = t; 6237eb43aa7SLois Curfman McInnes } 6247eb43aa7SLois Curfman McInnes for (i = low; i < high; i++) { 6257eb43aa7SLois Curfman McInnes if (rp[i] > col) break; 6267eb43aa7SLois Curfman McInnes if (rp[i] == col) { 627b49de8d1SLois Curfman McInnes *v++ = ap[i]; 6287eb43aa7SLois Curfman McInnes goto finished; 6297eb43aa7SLois Curfman McInnes } 6307eb43aa7SLois Curfman McInnes } 63197e567efSBarry Smith *v++ = 0.0; 6327eb43aa7SLois Curfman McInnes finished:; 6337eb43aa7SLois Curfman McInnes } 6347eb43aa7SLois Curfman McInnes } 6354e208921SJed Brown PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 6363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6377eb43aa7SLois Curfman McInnes } 6387eb43aa7SLois Curfman McInnes 639ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_SeqAIJ_Binary(Mat mat, PetscViewer viewer) 640d71ae5a4SJacob Faibussowitsch { 6413ea6fe3dSLisandro Dalcin Mat_SeqAIJ *A = (Mat_SeqAIJ *)mat->data; 642c898d852SStefano Zampini const PetscScalar *av; 6433ea6fe3dSLisandro Dalcin PetscInt header[4], M, N, m, nz, i; 6443ea6fe3dSLisandro Dalcin PetscInt *rowlens; 64517ab2063SBarry Smith 6463a40ed3dSBarry Smith PetscFunctionBegin; 6479566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 6482205254eSKarl Rupp 6493ea6fe3dSLisandro Dalcin M = mat->rmap->N; 6503ea6fe3dSLisandro Dalcin N = mat->cmap->N; 6513ea6fe3dSLisandro Dalcin m = mat->rmap->n; 6523ea6fe3dSLisandro Dalcin nz = A->nz; 653416022c9SBarry Smith 6543ea6fe3dSLisandro Dalcin /* write matrix header */ 6553ea6fe3dSLisandro Dalcin header[0] = MAT_FILE_CLASSID; 6569371c9d4SSatish Balay header[1] = M; 6579371c9d4SSatish Balay header[2] = N; 6589371c9d4SSatish Balay header[3] = nz; 6599566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT)); 660416022c9SBarry Smith 6613ea6fe3dSLisandro Dalcin /* fill in and store row lengths */ 6629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &rowlens)); 6633ea6fe3dSLisandro Dalcin for (i = 0; i < m; i++) rowlens[i] = A->i[i + 1] - A->i[i]; 664e457bb90SBarry Smith if (PetscDefined(USE_DEBUG)) { 665e457bb90SBarry Smith PetscInt mnz = 0; 666e457bb90SBarry Smith 667e457bb90SBarry Smith for (i = 0; i < m; i++) mnz += rowlens[i]; 668e457bb90SBarry Smith PetscCheck(nz == mnz, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Row lens %" PetscInt_FMT " do not sum to nz %" PetscInt_FMT, mnz, nz); 669e457bb90SBarry Smith } 6709566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, rowlens, m, PETSC_INT)); 6719566063dSJacob Faibussowitsch PetscCall(PetscFree(rowlens)); 6723ea6fe3dSLisandro Dalcin /* store column indices */ 6739566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, A->j, nz, PETSC_INT)); 674416022c9SBarry Smith /* store nonzero values */ 6759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(mat, &av)); 6769566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, av, nz, PETSC_SCALAR)); 6779566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(mat, &av)); 678b37d52dbSMark F. Adams 6793ea6fe3dSLisandro Dalcin /* write block size option to the viewer's .info file */ 6809566063dSJacob Faibussowitsch PetscCall(MatView_Binary_BlockSizes(mat, viewer)); 6813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68217ab2063SBarry Smith } 683416022c9SBarry Smith 684d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A, PetscViewer viewer) 685d71ae5a4SJacob Faibussowitsch { 6867dc0baabSHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 6877dc0baabSHong Zhang PetscInt i, k, m = A->rmap->N; 6887dc0baabSHong Zhang 6897dc0baabSHong Zhang PetscFunctionBegin; 6909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 6917dc0baabSHong Zhang for (i = 0; i < m; i++) { 6929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 69348a46eb9SPierre Jolivet for (k = a->i[i]; k < a->i[i + 1]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ") ", a->j[k])); 6949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 6957dc0baabSHong Zhang } 6969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 6973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6987dc0baabSHong Zhang } 6997dc0baabSHong Zhang 700ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_SeqAIJ_ASCII(Mat A, PetscViewer viewer) 701d71ae5a4SJacob Faibussowitsch { 702416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 703c898d852SStefano Zampini const PetscScalar *av; 70460e0710aSBarry Smith PetscInt i, j, m = A->rmap->n; 705e060cb09SBarry Smith const char *name; 706f3ef73ceSBarry Smith PetscViewerFormat format; 70717ab2063SBarry Smith 7083a40ed3dSBarry Smith PetscFunctionBegin; 7097dc0baabSHong Zhang if (A->structure_only) { 7109566063dSJacob Faibussowitsch PetscCall(MatView_SeqAIJ_ASCII_structonly(A, viewer)); 7113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7127dc0baabSHong Zhang } 71343e49210SHong Zhang 7149566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 715bd6a2ce3SJunchao Zhang // By petsc's rule, even PETSC_VIEWER_ASCII_INFO_DETAIL doesn't print matrix entries 7163ba16761SJacob Faibussowitsch if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS); 7172e5835c6SStefano Zampini 718c898d852SStefano Zampini /* trigger copy to CPU if needed */ 7199566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 7209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 72171c2f376SKris Buschelman if (format == PETSC_VIEWER_ASCII_MATLAB) { 72297f1f81fSBarry Smith PetscInt nofinalvalue = 0; 72360e0710aSBarry Smith if (m && ((a->i[m] == a->i[m - 1]) || (a->j[a->nz - 1] != A->cmap->n - 1))) { 724c337ccceSJed Brown /* Need a dummy value to ensure the dimension of the matrix. */ 725d00d2cf4SBarry Smith nofinalvalue = 1; 726d00d2cf4SBarry Smith } 7279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 7289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", m, A->cmap->n)); 7299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Nonzeros = %" PetscInt_FMT " \n", a->nz)); 730fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX) 7319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = zeros(%" PetscInt_FMT ",4);\n", a->nz + nofinalvalue)); 732fbfe6fa7SJed Brown #else 7339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = zeros(%" PetscInt_FMT ",3);\n", a->nz + nofinalvalue)); 734fbfe6fa7SJed Brown #endif 7359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = [\n")); 73617ab2063SBarry Smith 73717ab2063SBarry Smith for (i = 0; i < m; i++) { 73860e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 739aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 7409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %18.16e %18.16e\n", i + 1, a->j[j] + 1, (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 74117ab2063SBarry Smith #else 7429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %18.16e\n", i + 1, a->j[j] + 1, (double)a->a[j])); 74317ab2063SBarry Smith #endif 74417ab2063SBarry Smith } 74517ab2063SBarry Smith } 746d00d2cf4SBarry Smith if (nofinalvalue) { 747c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX) 7489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %18.16e %18.16e\n", m, A->cmap->n, 0., 0.)); 749c337ccceSJed Brown #else 7509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %18.16e\n", m, A->cmap->n, 0.0)); 751c337ccceSJed Brown #endif 752d00d2cf4SBarry Smith } 7539566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)A, &name)); 7549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "];\n %s = spconvert(zzz);\n", name)); 7559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 756fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_COMMON) { 7579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 75844cd7ae7SLois Curfman McInnes for (i = 0; i < m; i++) { 7599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 76060e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 761aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 76236db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) { 7639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 76436db0b34SBarry Smith } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) { 7659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)-PetscImaginaryPart(a->a[j]))); 76636db0b34SBarry Smith } else if (PetscRealPart(a->a[j]) != 0.0) { 7679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 7686831982aSBarry Smith } 76944cd7ae7SLois Curfman McInnes #else 7709566063dSJacob Faibussowitsch if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 77144cd7ae7SLois Curfman McInnes #endif 77244cd7ae7SLois Curfman McInnes } 7739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 77444cd7ae7SLois Curfman McInnes } 7759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 776fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_SYMMODU) { 77797f1f81fSBarry Smith PetscInt nzd = 0, fshift = 1, *sptr; 7789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 7799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &sptr)); 780496be53dSLois Curfman McInnes for (i = 0; i < m; i++) { 781496be53dSLois Curfman McInnes sptr[i] = nzd + 1; 78260e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 783496be53dSLois Curfman McInnes if (a->j[j] >= i) { 784aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 78536db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++; 786496be53dSLois Curfman McInnes #else 787496be53dSLois Curfman McInnes if (a->a[j] != 0.0) nzd++; 788496be53dSLois Curfman McInnes #endif 789496be53dSLois Curfman McInnes } 790496be53dSLois Curfman McInnes } 791496be53dSLois Curfman McInnes } 7922e44a96cSLois Curfman McInnes sptr[m] = nzd + 1; 7939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT "\n\n", m, nzd)); 7942e44a96cSLois Curfman McInnes for (i = 0; i < m + 1; i += 6) { 7952205254eSKarl Rupp if (i + 4 < m) { 7969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2], sptr[i + 3], sptr[i + 4], sptr[i + 5])); 7972205254eSKarl Rupp } else if (i + 3 < m) { 7989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2], sptr[i + 3], sptr[i + 4])); 7992205254eSKarl Rupp } else if (i + 2 < m) { 8009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2], sptr[i + 3])); 8012205254eSKarl Rupp } else if (i + 1 < m) { 8029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2])); 8032205254eSKarl Rupp } else if (i < m) { 8049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1])); 8052205254eSKarl Rupp } else { 8069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "\n", sptr[i])); 8072205254eSKarl Rupp } 808496be53dSLois Curfman McInnes } 8099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 8109566063dSJacob Faibussowitsch PetscCall(PetscFree(sptr)); 811496be53dSLois Curfman McInnes for (i = 0; i < m; i++) { 81260e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 8139566063dSJacob Faibussowitsch if (a->j[j] >= i) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " ", a->j[j] + fshift)); 814496be53dSLois Curfman McInnes } 8159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 816496be53dSLois Curfman McInnes } 8179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 818496be53dSLois Curfman McInnes for (i = 0; i < m; i++) { 81960e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 820496be53dSLois Curfman McInnes if (a->j[j] >= i) { 821aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 82248a46eb9SPierre Jolivet if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " %18.16e %18.16e ", (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 823496be53dSLois Curfman McInnes #else 8249566063dSJacob Faibussowitsch if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " %18.16e ", (double)a->a[j])); 825496be53dSLois Curfman McInnes #endif 826496be53dSLois Curfman McInnes } 827496be53dSLois Curfman McInnes } 8289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 829496be53dSLois Curfman McInnes } 8309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 831fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_DENSE) { 83297f1f81fSBarry Smith PetscInt cnt = 0, jcnt; 83387828ca2SBarry Smith PetscScalar value; 83468f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX) 83568f1ed48SBarry Smith PetscBool realonly = PETSC_TRUE; 83668f1ed48SBarry Smith 83768f1ed48SBarry Smith for (i = 0; i < a->i[m]; i++) { 83868f1ed48SBarry Smith if (PetscImaginaryPart(a->a[i]) != 0.0) { 83968f1ed48SBarry Smith realonly = PETSC_FALSE; 84068f1ed48SBarry Smith break; 84168f1ed48SBarry Smith } 84268f1ed48SBarry Smith } 84368f1ed48SBarry Smith #endif 84402594712SBarry Smith 8459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 84602594712SBarry Smith for (i = 0; i < m; i++) { 84702594712SBarry Smith jcnt = 0; 848d0f46423SBarry Smith for (j = 0; j < A->cmap->n; j++) { 849e24b481bSBarry Smith if (jcnt < a->i[i + 1] - a->i[i] && j == a->j[cnt]) { 85002594712SBarry Smith value = a->a[cnt++]; 851e24b481bSBarry Smith jcnt++; 85202594712SBarry Smith } else { 85302594712SBarry Smith value = 0.0; 85402594712SBarry Smith } 855aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 85668f1ed48SBarry Smith if (realonly) { 8579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e ", (double)PetscRealPart(value))); 85868f1ed48SBarry Smith } else { 8599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e+%7.5e i ", (double)PetscRealPart(value), (double)PetscImaginaryPart(value))); 86068f1ed48SBarry Smith } 86102594712SBarry Smith #else 8629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e ", (double)value)); 86302594712SBarry Smith #endif 86402594712SBarry Smith } 8659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 86602594712SBarry Smith } 8679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 8683c215bfdSMatthew Knepley } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) { 869150b93efSMatthew G. Knepley PetscInt fshift = 1; 8709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 8713c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX) 8729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%%%%MatrixMarket matrix coordinate complex general\n")); 8733c215bfdSMatthew Knepley #else 8749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%%%%MatrixMarket matrix coordinate real general\n")); 8753c215bfdSMatthew Knepley #endif 8769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", m, A->cmap->n, a->nz)); 8773c215bfdSMatthew Knepley for (i = 0; i < m; i++) { 87860e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 8793c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX) 8809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %g %g\n", i + fshift, a->j[j] + fshift, (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 8813c215bfdSMatthew Knepley #else 8829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %g\n", i + fshift, a->j[j] + fshift, (double)a->a[j])); 8833c215bfdSMatthew Knepley #endif 8843c215bfdSMatthew Knepley } 8853c215bfdSMatthew Knepley } 8869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 8873a40ed3dSBarry Smith } else { 8889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 889d5f3da31SBarry Smith if (A->factortype) { 890*421480d9SBarry Smith const PetscInt *adiag; 891*421480d9SBarry Smith 892*421480d9SBarry Smith PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &adiag, NULL)); 89316cd7e1dSShri Abhyankar for (i = 0; i < m; i++) { 8949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 89516cd7e1dSShri Abhyankar /* L part */ 89660e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 89716cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 89816cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 8999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 90016cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 9019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)(-PetscImaginaryPart(a->a[j])))); 90216cd7e1dSShri Abhyankar } else { 9039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 90416cd7e1dSShri Abhyankar } 90516cd7e1dSShri Abhyankar #else 9069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 90716cd7e1dSShri Abhyankar #endif 90816cd7e1dSShri Abhyankar } 90916cd7e1dSShri Abhyankar /* diagonal */ 910*421480d9SBarry Smith j = adiag[i]; 91116cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 91216cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 913835f2295SStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(1 / a->a[j]), (double)PetscImaginaryPart(1 / a->a[j]))); 91416cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 915835f2295SStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(1 / a->a[j]), (double)(-PetscImaginaryPart(1 / a->a[j])))); 91616cd7e1dSShri Abhyankar } else { 917835f2295SStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(1 / a->a[j]))); 91816cd7e1dSShri Abhyankar } 91916cd7e1dSShri Abhyankar #else 920835f2295SStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)(1 / a->a[j]))); 92116cd7e1dSShri Abhyankar #endif 92216cd7e1dSShri Abhyankar 92316cd7e1dSShri Abhyankar /* U part */ 924*421480d9SBarry Smith for (j = adiag[i + 1] + 1; j < adiag[i]; j++) { 92516cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 92616cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 9279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 92816cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 9299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)(-PetscImaginaryPart(a->a[j])))); 93016cd7e1dSShri Abhyankar } else { 9319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 93216cd7e1dSShri Abhyankar } 93316cd7e1dSShri Abhyankar #else 9349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 93516cd7e1dSShri Abhyankar #endif 93616cd7e1dSShri Abhyankar } 9379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 93816cd7e1dSShri Abhyankar } 93916cd7e1dSShri Abhyankar } else { 94017ab2063SBarry Smith for (i = 0; i < m; i++) { 9419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 94260e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 943aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 94436db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) > 0.0) { 9459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 94636db0b34SBarry Smith } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 9479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)-PetscImaginaryPart(a->a[j]))); 9483a40ed3dSBarry Smith } else { 9499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 95017ab2063SBarry Smith } 95117ab2063SBarry Smith #else 9529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 95317ab2063SBarry Smith #endif 95417ab2063SBarry Smith } 9559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 95617ab2063SBarry Smith } 95716cd7e1dSShri Abhyankar } 9589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 95917ab2063SBarry Smith } 9609566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 9613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 962416022c9SBarry Smith } 963416022c9SBarry Smith 9649804daf3SBarry Smith #include <petscdraw.h> 965ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw, void *Aa) 966d71ae5a4SJacob Faibussowitsch { 967480ef9eaSBarry Smith Mat A = (Mat)Aa; 968416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 969383922c3SLisandro Dalcin PetscInt i, j, m = A->rmap->n; 970383922c3SLisandro Dalcin int color; 971b05fc000SLisandro Dalcin PetscReal xl, yl, xr, yr, x_l, x_r, y_l, y_r; 972b0a32e0cSBarry Smith PetscViewer viewer; 973f3ef73ceSBarry Smith PetscViewerFormat format; 974fff043a9SJunchao Zhang const PetscScalar *aa; 975cddf8d76SBarry Smith 9763a40ed3dSBarry Smith PetscFunctionBegin; 9779566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer)); 9789566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 9799566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr)); 980383922c3SLisandro Dalcin 981416022c9SBarry Smith /* loop over matrix elements drawing boxes */ 9829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 983fb9695e5SSatish Balay if (format != PETSC_VIEWER_DRAW_CONTOUR) { 984d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 9850513a670SBarry Smith /* Blue for negative, Cyan for zero and Red for positive */ 986b0a32e0cSBarry Smith color = PETSC_DRAW_BLUE; 987416022c9SBarry Smith for (i = 0; i < m; i++) { 9889371c9d4SSatish Balay y_l = m - i - 1.0; 9899371c9d4SSatish Balay y_r = y_l + 1.0; 990bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 9919371c9d4SSatish Balay x_l = a->j[j]; 9929371c9d4SSatish Balay x_r = x_l + 1.0; 993fff043a9SJunchao Zhang if (PetscRealPart(aa[j]) >= 0.) continue; 9949566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 995cddf8d76SBarry Smith } 996cddf8d76SBarry Smith } 997b0a32e0cSBarry Smith color = PETSC_DRAW_CYAN; 998cddf8d76SBarry Smith for (i = 0; i < m; i++) { 9999371c9d4SSatish Balay y_l = m - i - 1.0; 10009371c9d4SSatish Balay y_r = y_l + 1.0; 1001bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 10029371c9d4SSatish Balay x_l = a->j[j]; 10039371c9d4SSatish Balay x_r = x_l + 1.0; 1004fff043a9SJunchao Zhang if (aa[j] != 0.) continue; 10059566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 1006cddf8d76SBarry Smith } 1007cddf8d76SBarry Smith } 1008b0a32e0cSBarry Smith color = PETSC_DRAW_RED; 1009cddf8d76SBarry Smith for (i = 0; i < m; i++) { 10109371c9d4SSatish Balay y_l = m - i - 1.0; 10119371c9d4SSatish Balay y_r = y_l + 1.0; 1012bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 10139371c9d4SSatish Balay x_l = a->j[j]; 10149371c9d4SSatish Balay x_r = x_l + 1.0; 1015fff043a9SJunchao Zhang if (PetscRealPart(aa[j]) <= 0.) continue; 10169566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 1017416022c9SBarry Smith } 1018416022c9SBarry Smith } 1019d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 10200513a670SBarry Smith } else { 10210513a670SBarry Smith /* use contour shading to indicate magnitude of values */ 10220513a670SBarry Smith /* first determine max of all nonzero values */ 1023b05fc000SLisandro Dalcin PetscReal minv = 0.0, maxv = 0.0; 1024383922c3SLisandro Dalcin PetscInt nz = a->nz, count = 0; 1025b0a32e0cSBarry Smith PetscDraw popup; 10260513a670SBarry Smith 10270513a670SBarry Smith for (i = 0; i < nz; i++) { 1028fff043a9SJunchao Zhang if (PetscAbsScalar(aa[i]) > maxv) maxv = PetscAbsScalar(aa[i]); 10290513a670SBarry Smith } 1030383922c3SLisandro Dalcin if (minv >= maxv) maxv = minv + PETSC_SMALL; 10319566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 10329566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, minv, maxv)); 1033383922c3SLisandro Dalcin 1034d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 10350513a670SBarry Smith for (i = 0; i < m; i++) { 1036383922c3SLisandro Dalcin y_l = m - i - 1.0; 1037383922c3SLisandro Dalcin y_r = y_l + 1.0; 1038bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 1039383922c3SLisandro Dalcin x_l = a->j[j]; 1040383922c3SLisandro Dalcin x_r = x_l + 1.0; 1041fff043a9SJunchao Zhang color = PetscDrawRealToColor(PetscAbsScalar(aa[count]), minv, maxv); 10429566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 10430513a670SBarry Smith count++; 10440513a670SBarry Smith } 10450513a670SBarry Smith } 1046d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 10470513a670SBarry Smith } 10489566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 10493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1050480ef9eaSBarry Smith } 1051cddf8d76SBarry Smith 10529804daf3SBarry Smith #include <petscdraw.h> 1053ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_SeqAIJ_Draw(Mat A, PetscViewer viewer) 1054d71ae5a4SJacob Faibussowitsch { 1055b0a32e0cSBarry Smith PetscDraw draw; 105636db0b34SBarry Smith PetscReal xr, yr, xl, yl, h, w; 1057ace3abfcSBarry Smith PetscBool isnull; 1058480ef9eaSBarry Smith 1059480ef9eaSBarry Smith PetscFunctionBegin; 10609566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 10619566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 10623ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 1063480ef9eaSBarry Smith 10649371c9d4SSatish Balay xr = A->cmap->n; 10659371c9d4SSatish Balay yr = A->rmap->n; 10669371c9d4SSatish Balay h = yr / 10.0; 10679371c9d4SSatish Balay w = xr / 10.0; 10689371c9d4SSatish Balay xr += w; 10699371c9d4SSatish Balay yr += h; 10709371c9d4SSatish Balay xl = -w; 10719371c9d4SSatish Balay yl = -h; 10729566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr)); 10739566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer)); 10749566063dSJacob Faibussowitsch PetscCall(PetscDrawZoom(draw, MatView_SeqAIJ_Draw_Zoom, A)); 10759566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL)); 10769566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 10773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1078416022c9SBarry Smith } 1079416022c9SBarry Smith 1080d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqAIJ(Mat A, PetscViewer viewer) 1081d71ae5a4SJacob Faibussowitsch { 10829f196a02SMartin Diehl PetscBool isascii, isbinary, isdraw; 1083416022c9SBarry Smith 10843a40ed3dSBarry Smith PetscFunctionBegin; 10859f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 10869566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 10879566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 10889f196a02SMartin Diehl if (isascii) PetscCall(MatView_SeqAIJ_ASCII(A, viewer)); 10891baa6e33SBarry Smith else if (isbinary) PetscCall(MatView_SeqAIJ_Binary(A, viewer)); 10901baa6e33SBarry Smith else if (isdraw) PetscCall(MatView_SeqAIJ_Draw(A, viewer)); 10919566063dSJacob Faibussowitsch PetscCall(MatView_SeqAIJ_Inode(A, viewer)); 10923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 109317ab2063SBarry Smith } 109419bcc07fSBarry Smith 1095d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A, MatAssemblyType mode) 1096d71ae5a4SJacob Faibussowitsch { 1097416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1098580bdb30SBarry Smith PetscInt fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax; 109907425a8dSBarry Smith PetscInt m = A->rmap->n, *ip, N, *ailen = a->ilen, rmax = 0; 110054f21887SBarry Smith MatScalar *aa = a->a, *ap; 11013447b6efSHong Zhang PetscReal ratio = 0.6; 110217ab2063SBarry Smith 11033a40ed3dSBarry Smith PetscFunctionBegin; 11043ba16761SJacob Faibussowitsch if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(PETSC_SUCCESS); 1105b215bc84SStefano Zampini if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) { 110655a7f34eSJunchao Zhang /* we need to respect users asking to use or not the inodes routine in between matrix assemblies, e.g., via MatSetOption(A, MAT_USE_INODES, val) */ 110755a7f34eSJunchao Zhang PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A, mode)); /* read the sparsity pattern */ 11083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1109b215bc84SStefano Zampini } 111017ab2063SBarry Smith 111143ee02c3SBarry Smith if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 111217ab2063SBarry Smith for (i = 1; i < m; i++) { 1113416022c9SBarry Smith /* move each row back by the amount of empty slots (fshift) before it*/ 111417ab2063SBarry Smith fshift += imax[i - 1] - ailen[i - 1]; 111594a9d846SBarry Smith rmax = PetscMax(rmax, ailen[i]); 111617ab2063SBarry Smith if (fshift) { 1117bfeeae90SHong Zhang ip = aj + ai[i]; 1118bfeeae90SHong Zhang ap = aa + ai[i]; 111917ab2063SBarry Smith N = ailen[i]; 11209566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ip - fshift, ip, N)); 112148a46eb9SPierre Jolivet if (!A->structure_only) PetscCall(PetscArraymove(ap - fshift, ap, N)); 112217ab2063SBarry Smith } 112317ab2063SBarry Smith ai[i] = ai[i - 1] + ailen[i - 1]; 112417ab2063SBarry Smith } 112517ab2063SBarry Smith if (m) { 112617ab2063SBarry Smith fshift += imax[m - 1] - ailen[m - 1]; 112717ab2063SBarry Smith ai[m] = ai[m - 1] + ailen[m - 1]; 112817ab2063SBarry Smith } 112917ab2063SBarry Smith /* reset ilen and imax for each row */ 11307b083b7cSBarry Smith a->nonzerorowcnt = 0; 1131396832f4SHong Zhang if (A->structure_only) { 11329566063dSJacob Faibussowitsch PetscCall(PetscFree(a->imax)); 11339566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ilen)); 1134396832f4SHong Zhang } else { /* !A->structure_only */ 113517ab2063SBarry Smith for (i = 0; i < m; i++) { 113617ab2063SBarry Smith ailen[i] = imax[i] = ai[i + 1] - ai[i]; 11377b083b7cSBarry Smith a->nonzerorowcnt += ((ai[i + 1] - ai[i]) > 0); 113817ab2063SBarry Smith } 1139396832f4SHong Zhang } 1140bfeeae90SHong Zhang a->nz = ai[m]; 1141aed4548fSBarry Smith PetscCheck(!fshift || a->nounused != -1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unused space detected in matrix: %" PetscInt_FMT " X %" PetscInt_FMT ", %" PetscInt_FMT " unneeded", m, A->cmap->n, fshift); 11429566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix size: %" PetscInt_FMT " X %" PetscInt_FMT "; storage space: %" PetscInt_FMT " unneeded,%" PetscInt_FMT " used\n", m, A->cmap->n, fshift, a->nz)); 11439566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues() is %" PetscInt_FMT "\n", a->reallocs)); 11449566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Maximum nonzeros in any row is %" PetscInt_FMT "\n", rmax)); 11452205254eSKarl Rupp 11468e58a170SBarry Smith A->info.mallocs += a->reallocs; 1147dd5f02e7SSatish Balay a->reallocs = 0; 11486712e2f1SBarry Smith A->info.nz_unneeded = (PetscReal)fshift; 114936db0b34SBarry Smith a->rmax = rmax; 11504e220ebcSLois Curfman McInnes 115148a46eb9SPierre Jolivet if (!A->structure_only) PetscCall(MatCheckCompressedRow(A, a->nonzerorowcnt, &a->compressedrow, a->i, m, ratio)); 11529566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A, mode)); 11533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 115417ab2063SBarry Smith } 115517ab2063SBarry Smith 1156ba38deedSJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqAIJ(Mat A) 1157d71ae5a4SJacob Faibussowitsch { 115899cafbc1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 115999cafbc1SBarry Smith PetscInt i, nz = a->nz; 11602e5835c6SStefano Zampini MatScalar *aa; 116199cafbc1SBarry Smith 116299cafbc1SBarry Smith PetscFunctionBegin; 11639566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 116499cafbc1SBarry Smith for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]); 11659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 11663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 116799cafbc1SBarry Smith } 116899cafbc1SBarry Smith 1169ba38deedSJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A) 1170d71ae5a4SJacob Faibussowitsch { 117199cafbc1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 117299cafbc1SBarry Smith PetscInt i, nz = a->nz; 11732e5835c6SStefano Zampini MatScalar *aa; 117499cafbc1SBarry Smith 117599cafbc1SBarry Smith PetscFunctionBegin; 11769566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 117799cafbc1SBarry Smith for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]); 11789566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 11793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 118099cafbc1SBarry Smith } 118199cafbc1SBarry Smith 1182d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_SeqAIJ(Mat A) 1183d71ae5a4SJacob Faibussowitsch { 1184fff043a9SJunchao Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1185fff043a9SJunchao Zhang MatScalar *aa; 11863a40ed3dSBarry Smith 11873a40ed3dSBarry Smith PetscFunctionBegin; 11889566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayWrite(A, &aa)); 11899566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(aa, a->i[A->rmap->n])); 11909566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayWrite(A, &aa)); 11913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 119217ab2063SBarry Smith } 1193416022c9SBarry Smith 1194674b392bSAlexander static PetscErrorCode MatReset_SeqAIJ(Mat A) 1195d71ae5a4SJacob Faibussowitsch { 1196416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1197d5d45c9bSBarry Smith 11983a40ed3dSBarry Smith PetscFunctionBegin; 1199b4e2f619SBarry Smith if (A->hash_active) { 1200e3c72094SPierre Jolivet A->ops[0] = a->cops; 1201b4e2f619SBarry Smith PetscCall(PetscHMapIJVDestroy(&a->ht)); 1202b4e2f619SBarry Smith PetscCall(PetscFree(a->dnz)); 1203b4e2f619SBarry Smith A->hash_active = PETSC_FALSE; 1204b4e2f619SBarry Smith } 1205b4e2f619SBarry Smith 12063ba16761SJacob Faibussowitsch PetscCall(PetscLogObjectState((PetscObject)A, "Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT, A->rmap->n, A->cmap->n, a->nz)); 12079566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(A, &a->a, &a->j, &a->i)); 12089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 12099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 12109566063dSJacob Faibussowitsch PetscCall(PetscFree(a->diag)); 12119566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ibdiag)); 12129566063dSJacob Faibussowitsch PetscCall(PetscFree(a->imax)); 12139566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ilen)); 12149566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ipre)); 12159566063dSJacob Faibussowitsch PetscCall(PetscFree3(a->idiag, a->mdiag, a->ssor_work)); 12169566063dSJacob Faibussowitsch PetscCall(PetscFree(a->solve_work)); 12179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 12189566063dSJacob Faibussowitsch PetscCall(PetscFree(a->saved_values)); 1219820d003aSStefano Zampini a->compressedrow.use = PETSC_FALSE; 12209566063dSJacob Faibussowitsch PetscCall(PetscFree2(a->compressedrow.i, a->compressedrow.rindex)); 12219566063dSJacob Faibussowitsch PetscCall(MatDestroy_SeqAIJ_Inode(A)); 1222674b392bSAlexander PetscFunctionReturn(PETSC_SUCCESS); 1223674b392bSAlexander } 1224674b392bSAlexander 1225674b392bSAlexander static PetscErrorCode MatResetHash_SeqAIJ(Mat A) 1226674b392bSAlexander { 1227674b392bSAlexander PetscFunctionBegin; 1228674b392bSAlexander PetscCall(MatReset_SeqAIJ(A)); 1229674b392bSAlexander PetscCall(MatCreate_SeqAIJ_Inode(A)); 1230674b392bSAlexander PetscCall(MatSetUp_Seq_Hash(A)); 1231674b392bSAlexander A->nonzerostate++; 1232674b392bSAlexander PetscFunctionReturn(PETSC_SUCCESS); 1233674b392bSAlexander } 1234674b392bSAlexander 1235674b392bSAlexander PetscErrorCode MatDestroy_SeqAIJ(Mat A) 1236674b392bSAlexander { 1237674b392bSAlexander PetscFunctionBegin; 1238674b392bSAlexander PetscCall(MatReset_SeqAIJ(A)); 12399566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 1240901853e0SKris Buschelman 12416718818eSStefano Zampini /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this. 12426718818eSStefano Zampini That function is so heavily used (sometimes in an hidden way through multnumeric function pointers) 12436718818eSStefano Zampini that is hard to properly add this data to the MatProduct data. We free it here to avoid 12446718818eSStefano Zampini users reusing the matrix object with different data to incur in obscure segmentation faults 12456718818eSStefano Zampini due to different matrix sizes */ 12469566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc__ab_dense", NULL)); 12476718818eSStefano Zampini 12489566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL)); 12492e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "PetscMatlabEnginePut_C", NULL)); 12502e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "PetscMatlabEngineGet_C", NULL)); 12519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetColumnIndices_C", NULL)); 12529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatStoreValues_C", NULL)); 12539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatRetrieveValues_C", NULL)); 12549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqsbaij_C", NULL)); 12559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqbaij_C", NULL)); 12569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijperm_C", NULL)); 12572e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijsell_C", NULL)); 12582e956fe4SStefano Zampini #if defined(PETSC_HAVE_MKL_SPARSE) 12592e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijmkl_C", NULL)); 12602e956fe4SStefano Zampini #endif 12614222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA) 12629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijcusparse_C", NULL)); 12639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_seqaij_C", NULL)); 12649566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaijcusparse_C", NULL)); 12654222ddf1SHong Zhang #endif 1266d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_HIP) 1267d5e393b6SSuyash Tandon PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijhipsparse_C", NULL)); 1268d5e393b6SSuyash Tandon PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijhipsparse_seqaij_C", NULL)); 1269d5e393b6SSuyash Tandon PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaijhipsparse_C", NULL)); 1270d5e393b6SSuyash Tandon #endif 12713d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 12729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijkokkos_C", NULL)); 12733d0639e7SStefano Zampini #endif 12749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijcrl_C", NULL)); 1275af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 12769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_elemental_C", NULL)); 1277af8000cdSHong Zhang #endif 1278d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)) 12799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_scalapack_C", NULL)); 1280d24d4204SJose E. Roman #endif 128163c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 12829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_hypre_C", NULL)); 12839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_transpose_seqaij_seqaij_C", NULL)); 128463c07aadSStefano Zampini #endif 12859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqdense_C", NULL)); 12869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqsell_C", NULL)); 12879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_is_C", NULL)); 12889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatIsTranspose_C", NULL)); 12892e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatIsHermitianTranspose_C", NULL)); 12909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", NULL)); 12919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatResetPreallocation_C", NULL)); 1292674b392bSAlexander PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatResetHash_C", NULL)); 12939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetPreallocationCSR_C", NULL)); 12949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatReorderForNonzeroDiagonal_C", NULL)); 12959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_is_seqaij_C", NULL)); 12969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqdense_seqaij_C", NULL)); 12979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaij_C", NULL)); 12989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJKron_C", NULL)); 12999566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 13009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 13012e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL)); 13022e956fe4SStefano Zampini /* these calls do not belong here: the subclasses Duplicate/Destroy are wrong */ 13032e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaijsell_seqaij_C", NULL)); 13042e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaijperm_seqaij_C", NULL)); 13052e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijviennacl_C", NULL)); 13062e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijviennacl_seqdense_C", NULL)); 13072e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijviennacl_seqaij_C", NULL)); 13083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 130917ab2063SBarry Smith } 131017ab2063SBarry Smith 1311d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetOption_SeqAIJ(Mat A, MatOption op, PetscBool flg) 1312d71ae5a4SJacob Faibussowitsch { 1313416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 13143a40ed3dSBarry Smith 13153a40ed3dSBarry Smith PetscFunctionBegin; 1316a65d3064SKris Buschelman switch (op) { 1317d71ae5a4SJacob Faibussowitsch case MAT_ROW_ORIENTED: 1318d71ae5a4SJacob Faibussowitsch a->roworiented = flg; 1319d71ae5a4SJacob Faibussowitsch break; 1320d71ae5a4SJacob Faibussowitsch case MAT_KEEP_NONZERO_PATTERN: 1321d71ae5a4SJacob Faibussowitsch a->keepnonzeropattern = flg; 1322d71ae5a4SJacob Faibussowitsch break; 1323d71ae5a4SJacob Faibussowitsch case MAT_NEW_NONZERO_LOCATIONS: 1324d71ae5a4SJacob Faibussowitsch a->nonew = (flg ? 0 : 1); 1325d71ae5a4SJacob Faibussowitsch break; 1326d71ae5a4SJacob Faibussowitsch case MAT_NEW_NONZERO_LOCATION_ERR: 1327d71ae5a4SJacob Faibussowitsch a->nonew = (flg ? -1 : 0); 1328d71ae5a4SJacob Faibussowitsch break; 1329d71ae5a4SJacob Faibussowitsch case MAT_NEW_NONZERO_ALLOCATION_ERR: 1330d71ae5a4SJacob Faibussowitsch a->nonew = (flg ? -2 : 0); 1331d71ae5a4SJacob Faibussowitsch break; 1332d71ae5a4SJacob Faibussowitsch case MAT_UNUSED_NONZERO_LOCATION_ERR: 1333d71ae5a4SJacob Faibussowitsch a->nounused = (flg ? -1 : 0); 1334d71ae5a4SJacob Faibussowitsch break; 1335d71ae5a4SJacob Faibussowitsch case MAT_IGNORE_ZERO_ENTRIES: 1336d71ae5a4SJacob Faibussowitsch a->ignorezeroentries = flg; 1337d71ae5a4SJacob Faibussowitsch break; 1338d71ae5a4SJacob Faibussowitsch case MAT_USE_INODES: 1339d71ae5a4SJacob Faibussowitsch PetscCall(MatSetOption_SeqAIJ_Inode(A, MAT_USE_INODES, flg)); 1340d71ae5a4SJacob Faibussowitsch break; 1341d71ae5a4SJacob Faibussowitsch case MAT_SUBMAT_SINGLEIS: 1342d71ae5a4SJacob Faibussowitsch A->submat_singleis = flg; 1343d71ae5a4SJacob Faibussowitsch break; 1344071fcb05SBarry Smith case MAT_SORTED_FULL: 1345071fcb05SBarry Smith if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 1346071fcb05SBarry Smith else A->ops->setvalues = MatSetValues_SeqAIJ; 1347071fcb05SBarry Smith break; 1348d71ae5a4SJacob Faibussowitsch case MAT_FORM_EXPLICIT_TRANSPOSE: 1349d71ae5a4SJacob Faibussowitsch A->form_explicit_transpose = flg; 1350d71ae5a4SJacob Faibussowitsch break; 1351d71ae5a4SJacob Faibussowitsch default: 1352888c827cSStefano Zampini break; 1353a65d3064SKris Buschelman } 13543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 135517ab2063SBarry Smith } 135617ab2063SBarry Smith 13579ee18893SBarry Smith PETSC_INTERN PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A, Vec v) 1358d71ae5a4SJacob Faibussowitsch { 1359416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1360*421480d9SBarry Smith PetscInt n, *ai = a->i; 1361c898d852SStefano Zampini PetscScalar *x; 1362c898d852SStefano Zampini const PetscScalar *aa; 1363*421480d9SBarry Smith const PetscInt *diag; 1364*421480d9SBarry Smith PetscBool diagDense; 136517ab2063SBarry Smith 13663a40ed3dSBarry Smith PetscFunctionBegin; 13679566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 136808401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 13699566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 1370d5f3da31SBarry Smith if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) { 1371*421480d9SBarry Smith PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, NULL)); 13729566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 1373*421480d9SBarry Smith for (PetscInt i = 0; i < n; i++) x[i] = 1.0 / aa[diag[i]]; 13749566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 13759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 13763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 137735e7444dSHong Zhang } 137835e7444dSHong Zhang 1379*421480d9SBarry Smith PetscCheck(A->factortype == MAT_FACTOR_NONE, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for factor matrices that are not ILU or LU"); 1380*421480d9SBarry Smith PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, &diagDense)); 13819566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 1382*421480d9SBarry Smith if (diagDense) { 1383*421480d9SBarry Smith for (PetscInt i = 0; i < n; i++) x[i] = aa[diag[i]]; 1384*421480d9SBarry Smith } else { 1385*421480d9SBarry Smith for (PetscInt i = 0; i < n; i++) x[i] = (diag[i] == ai[i + 1]) ? 0.0 : aa[diag[i]]; 138617ab2063SBarry Smith } 13879566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 13889566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 13893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 139017ab2063SBarry Smith } 139117ab2063SBarry Smith 1392c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 1393d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A, Vec xx, Vec zz, Vec yy) 1394d71ae5a4SJacob Faibussowitsch { 1395416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 13965f22a7b3SSebastian Grimberg const MatScalar *aa; 1397d9ca1df4SBarry Smith PetscScalar *y; 1398d9ca1df4SBarry Smith const PetscScalar *x; 1399d0f46423SBarry Smith PetscInt m = A->rmap->n; 14005c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 14015f22a7b3SSebastian Grimberg const MatScalar *v; 1402a77337e4SBarry Smith PetscScalar alpha; 1403d9ca1df4SBarry Smith PetscInt n, i, j; 1404d9ca1df4SBarry Smith const PetscInt *idx, *ii, *ridx = NULL; 14053447b6efSHong Zhang Mat_CompressedRow cprow = a->compressedrow; 1406ace3abfcSBarry Smith PetscBool usecprow = cprow.use; 14075c897100SBarry Smith #endif 140817ab2063SBarry Smith 14093a40ed3dSBarry Smith PetscFunctionBegin; 14109566063dSJacob Faibussowitsch if (zz != yy) PetscCall(VecCopy(zz, yy)); 14119566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 14129566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy, &y)); 14139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 14145c897100SBarry Smith 14155c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 1416fff043a9SJunchao Zhang fortranmulttransposeaddaij_(&m, x, a->i, a->j, aa, y); 14175c897100SBarry Smith #else 14183447b6efSHong Zhang if (usecprow) { 14193447b6efSHong Zhang m = cprow.nrows; 14203447b6efSHong Zhang ii = cprow.i; 14217b2bb3b9SHong Zhang ridx = cprow.rindex; 14223447b6efSHong Zhang } else { 14233447b6efSHong Zhang ii = a->i; 14243447b6efSHong Zhang } 142517ab2063SBarry Smith for (i = 0; i < m; i++) { 14263447b6efSHong Zhang idx = a->j + ii[i]; 1427fff043a9SJunchao Zhang v = aa + ii[i]; 14283447b6efSHong Zhang n = ii[i + 1] - ii[i]; 14293447b6efSHong Zhang if (usecprow) { 14307b2bb3b9SHong Zhang alpha = x[ridx[i]]; 14313447b6efSHong Zhang } else { 143217ab2063SBarry Smith alpha = x[i]; 14333447b6efSHong Zhang } 143404fbf559SBarry Smith for (j = 0; j < n; j++) y[idx[j]] += alpha * v[j]; 143517ab2063SBarry Smith } 14365c897100SBarry Smith #endif 14379566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 14389566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 14399566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy, &y)); 14409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 14413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 144217ab2063SBarry Smith } 144317ab2063SBarry Smith 1444d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTranspose_SeqAIJ(Mat A, Vec xx, Vec yy) 1445d71ae5a4SJacob Faibussowitsch { 14465c897100SBarry Smith PetscFunctionBegin; 14479566063dSJacob Faibussowitsch PetscCall(VecSet(yy, 0.0)); 14489566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd_SeqAIJ(A, xx, yy, yy)); 14493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14505c897100SBarry Smith } 14515c897100SBarry Smith 1452c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 145378b84d54SShri Abhyankar 1454d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMult_SeqAIJ(Mat A, Vec xx, Vec yy) 1455d71ae5a4SJacob Faibussowitsch { 1456416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1457d9fead3dSBarry Smith PetscScalar *y; 145854f21887SBarry Smith const PetscScalar *x; 14595914357eSBarry Smith const MatScalar *a_a; 1460003131ecSBarry Smith PetscInt m = A->rmap->n; 14615914357eSBarry Smith const PetscInt *ii, *ridx = NULL; 1462ace3abfcSBarry Smith PetscBool usecprow = a->compressedrow.use; 146317ab2063SBarry Smith 1464b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 146597952fefSHong Zhang #pragma disjoint(*x, *y, *aa) 1466fee21e36SBarry Smith #endif 1467fee21e36SBarry Smith 14683a40ed3dSBarry Smith PetscFunctionBegin; 1469b215bc84SStefano Zampini if (a->inode.use && a->inode.checked) { 14709566063dSJacob Faibussowitsch PetscCall(MatMult_SeqAIJ_Inode(A, xx, yy)); 14713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1472b215bc84SStefano Zampini } 14739566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 14749566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 14759566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy, &y)); 1476416022c9SBarry Smith ii = a->i; 14774eb6d288SHong Zhang if (usecprow) { /* use compressed row format */ 14789566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(y, m)); 147997952fefSHong Zhang m = a->compressedrow.nrows; 148097952fefSHong Zhang ii = a->compressedrow.i; 148197952fefSHong Zhang ridx = a->compressedrow.rindex; 14825914357eSBarry Smith PetscPragmaUseOMPKernels(parallel for) 14835914357eSBarry Smith for (PetscInt i = 0; i < m; i++) { 14845914357eSBarry Smith PetscInt n = ii[i + 1] - ii[i]; 14855914357eSBarry Smith const PetscInt *aj = a->j + ii[i]; 14865914357eSBarry Smith const PetscScalar *aa = a_a + ii[i]; 14875914357eSBarry Smith PetscScalar sum = 0.0; 1488003131ecSBarry Smith PetscSparseDensePlusDot(sum, x, aa, aj, n); 1489003131ecSBarry Smith /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 1490c9a1b032SJunchao Zhang y[ridx[i]] = sum; 149197952fefSHong Zhang } 149297952fefSHong Zhang } else { /* do not use compressed row format */ 1493b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ) 14945914357eSBarry Smith fortranmultaij_(&m, x, ii, a->j, a_a, y); 1495b05257ddSBarry Smith #else 14965914357eSBarry Smith PetscPragmaUseOMPKernels(parallel for) 14975914357eSBarry Smith for (PetscInt i = 0; i < m; i++) { 14985914357eSBarry Smith PetscInt n = ii[i + 1] - ii[i]; 14995914357eSBarry Smith const PetscInt *aj = a->j + ii[i]; 15005914357eSBarry Smith const PetscScalar *aa = a_a + ii[i]; 15015914357eSBarry Smith PetscScalar sum = 0.0; 1502003131ecSBarry Smith PetscSparseDensePlusDot(sum, x, aa, aj, n); 150317ab2063SBarry Smith y[i] = sum; 150417ab2063SBarry Smith } 15058d195f9aSBarry Smith #endif 1506b05257ddSBarry Smith } 15079566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz - a->nonzerorowcnt)); 15089566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 15099566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy, &y)); 15109566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a)); 15113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 151217ab2063SBarry Smith } 151317ab2063SBarry Smith 1514ba38deedSJacob Faibussowitsch // HACK!!!!! Used by src/mat/tests/ex170.c 1515ba38deedSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatMultMax_SeqAIJ(Mat A, Vec xx, Vec yy) 1516d71ae5a4SJacob Faibussowitsch { 1517b434eb95SMatthew G. Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1518b434eb95SMatthew G. Knepley PetscScalar *y; 1519b434eb95SMatthew G. Knepley const PetscScalar *x; 1520fff043a9SJunchao Zhang const MatScalar *aa, *a_a; 1521b434eb95SMatthew G. Knepley PetscInt m = A->rmap->n; 1522b434eb95SMatthew G. Knepley const PetscInt *aj, *ii, *ridx = NULL; 1523b434eb95SMatthew G. Knepley PetscInt n, i, nonzerorow = 0; 1524b434eb95SMatthew G. Knepley PetscScalar sum; 1525b434eb95SMatthew G. Knepley PetscBool usecprow = a->compressedrow.use; 1526b434eb95SMatthew G. Knepley 1527b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 1528b434eb95SMatthew G. Knepley #pragma disjoint(*x, *y, *aa) 1529b434eb95SMatthew G. Knepley #endif 1530b434eb95SMatthew G. Knepley 1531b434eb95SMatthew G. Knepley PetscFunctionBegin; 15329566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 15339566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 15349566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy, &y)); 1535b434eb95SMatthew G. Knepley if (usecprow) { /* use compressed row format */ 1536b434eb95SMatthew G. Knepley m = a->compressedrow.nrows; 1537b434eb95SMatthew G. Knepley ii = a->compressedrow.i; 1538b434eb95SMatthew G. Knepley ridx = a->compressedrow.rindex; 1539b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1540b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1541b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1542fff043a9SJunchao Zhang aa = a_a + ii[i]; 1543b434eb95SMatthew G. Knepley sum = 0.0; 1544b434eb95SMatthew G. Knepley nonzerorow += (n > 0); 1545b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1546b434eb95SMatthew G. Knepley /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 1547b434eb95SMatthew G. Knepley y[*ridx++] = sum; 1548b434eb95SMatthew G. Knepley } 1549b434eb95SMatthew G. Knepley } else { /* do not use compressed row format */ 15503d3eaba7SBarry Smith ii = a->i; 1551b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1552b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1553b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1554fff043a9SJunchao Zhang aa = a_a + ii[i]; 1555b434eb95SMatthew G. Knepley sum = 0.0; 1556b434eb95SMatthew G. Knepley nonzerorow += (n > 0); 1557b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1558b434eb95SMatthew G. Knepley y[i] = sum; 1559b434eb95SMatthew G. Knepley } 1560b434eb95SMatthew G. Knepley } 15619566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz - nonzerorow)); 15629566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 15639566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy, &y)); 15649566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a)); 15653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1566b434eb95SMatthew G. Knepley } 1567b434eb95SMatthew G. Knepley 1568ba38deedSJacob Faibussowitsch // HACK!!!!! Used by src/mat/tests/ex170.c 1569ba38deedSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatMultAddMax_SeqAIJ(Mat A, Vec xx, Vec yy, Vec zz) 1570d71ae5a4SJacob Faibussowitsch { 1571b434eb95SMatthew G. Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1572b434eb95SMatthew G. Knepley PetscScalar *y, *z; 1573b434eb95SMatthew G. Knepley const PetscScalar *x; 1574fff043a9SJunchao Zhang const MatScalar *aa, *a_a; 1575b434eb95SMatthew G. Knepley PetscInt m = A->rmap->n, *aj, *ii; 1576b434eb95SMatthew G. Knepley PetscInt n, i, *ridx = NULL; 1577b434eb95SMatthew G. Knepley PetscScalar sum; 1578b434eb95SMatthew G. Knepley PetscBool usecprow = a->compressedrow.use; 1579b434eb95SMatthew G. Knepley 1580b434eb95SMatthew G. Knepley PetscFunctionBegin; 15819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 15829566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 15839566063dSJacob Faibussowitsch PetscCall(VecGetArrayPair(yy, zz, &y, &z)); 1584b434eb95SMatthew G. Knepley if (usecprow) { /* use compressed row format */ 158548a46eb9SPierre Jolivet if (zz != yy) PetscCall(PetscArraycpy(z, y, m)); 1586b434eb95SMatthew G. Knepley m = a->compressedrow.nrows; 1587b434eb95SMatthew G. Knepley ii = a->compressedrow.i; 1588b434eb95SMatthew G. Knepley ridx = a->compressedrow.rindex; 1589b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1590b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1591b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1592fff043a9SJunchao Zhang aa = a_a + ii[i]; 1593b434eb95SMatthew G. Knepley sum = y[*ridx]; 1594b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1595b434eb95SMatthew G. Knepley z[*ridx++] = sum; 1596b434eb95SMatthew G. Knepley } 1597b434eb95SMatthew G. Knepley } else { /* do not use compressed row format */ 15983d3eaba7SBarry Smith ii = a->i; 1599b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1600b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1601b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1602fff043a9SJunchao Zhang aa = a_a + ii[i]; 1603b434eb95SMatthew G. Knepley sum = y[i]; 1604b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1605b434eb95SMatthew G. Knepley z[i] = sum; 1606b434eb95SMatthew G. Knepley } 1607b434eb95SMatthew G. Knepley } 16089566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 16099566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 16109566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayPair(yy, zz, &y, &z)); 16119566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a)); 16123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1613b434eb95SMatthew G. Knepley } 1614b434eb95SMatthew G. Knepley 1615c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h> 1616d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultAdd_SeqAIJ(Mat A, Vec xx, Vec yy, Vec zz) 1617d71ae5a4SJacob Faibussowitsch { 1618416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1619f15663dcSBarry Smith PetscScalar *y, *z; 1620f15663dcSBarry Smith const PetscScalar *x; 16215914357eSBarry Smith const MatScalar *a_a; 16225914357eSBarry Smith const PetscInt *ii, *ridx = NULL; 16235914357eSBarry Smith PetscInt m = A->rmap->n; 1624ace3abfcSBarry Smith PetscBool usecprow = a->compressedrow.use; 16259ea0dfa2SSatish Balay 16263a40ed3dSBarry Smith PetscFunctionBegin; 1627b215bc84SStefano Zampini if (a->inode.use && a->inode.checked) { 16289566063dSJacob Faibussowitsch PetscCall(MatMultAdd_SeqAIJ_Inode(A, xx, yy, zz)); 16293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1630b215bc84SStefano Zampini } 16319566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 16329566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 16339566063dSJacob Faibussowitsch PetscCall(VecGetArrayPair(yy, zz, &y, &z)); 16344eb6d288SHong Zhang if (usecprow) { /* use compressed row format */ 163548a46eb9SPierre Jolivet if (zz != yy) PetscCall(PetscArraycpy(z, y, m)); 163697952fefSHong Zhang m = a->compressedrow.nrows; 163797952fefSHong Zhang ii = a->compressedrow.i; 163897952fefSHong Zhang ridx = a->compressedrow.rindex; 16395914357eSBarry Smith for (PetscInt i = 0; i < m; i++) { 16405914357eSBarry Smith PetscInt n = ii[i + 1] - ii[i]; 16415914357eSBarry Smith const PetscInt *aj = a->j + ii[i]; 16425914357eSBarry Smith const PetscScalar *aa = a_a + ii[i]; 16435914357eSBarry Smith PetscScalar sum = y[*ridx]; 1644f15663dcSBarry Smith PetscSparseDensePlusDot(sum, x, aa, aj, n); 164597952fefSHong Zhang z[*ridx++] = sum; 164697952fefSHong Zhang } 164797952fefSHong Zhang } else { /* do not use compressed row format */ 16483d3eaba7SBarry Smith ii = a->i; 1649f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ) 16505914357eSBarry Smith fortranmultaddaij_(&m, x, ii, a->j, a_a, y, z); 1651f15663dcSBarry Smith #else 16525914357eSBarry Smith PetscPragmaUseOMPKernels(parallel for) 16535914357eSBarry Smith for (PetscInt i = 0; i < m; i++) { 16545914357eSBarry Smith PetscInt n = ii[i + 1] - ii[i]; 16555914357eSBarry Smith const PetscInt *aj = a->j + ii[i]; 16565914357eSBarry Smith const PetscScalar *aa = a_a + ii[i]; 16575914357eSBarry Smith PetscScalar sum = y[i]; 1658f15663dcSBarry Smith PetscSparseDensePlusDot(sum, x, aa, aj, n); 165917ab2063SBarry Smith z[i] = sum; 166017ab2063SBarry Smith } 166102ab625aSSatish Balay #endif 1662f15663dcSBarry Smith } 16639566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 16649566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 16659566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayPair(yy, zz, &y, &z)); 16669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a)); 16673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 166817ab2063SBarry Smith } 166917ab2063SBarry Smith 1670ba38deedSJacob Faibussowitsch static PetscErrorCode MatShift_SeqAIJ(Mat A, PetscScalar v) 1671d71ae5a4SJacob Faibussowitsch { 167261ecd0c6SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1673*421480d9SBarry Smith const PetscInt *diag; 167461ecd0c6SBarry Smith const PetscInt *ii = (const PetscInt *)a->i; 1675*421480d9SBarry Smith PetscBool diagDense; 167661ecd0c6SBarry Smith 167761ecd0c6SBarry Smith PetscFunctionBegin; 167861ecd0c6SBarry Smith if (!A->preallocated || !a->nz) { 16799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(A, 1, NULL)); 16809566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(A, v)); 16813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 168261ecd0c6SBarry Smith } 168361ecd0c6SBarry Smith 1684*421480d9SBarry Smith PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, &diagDense)); 1685*421480d9SBarry Smith if (diagDense) { 16869566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(A, v)); 168761ecd0c6SBarry Smith } else { 1688b6f2aa54SBarry Smith PetscScalar *olda = a->a; /* preserve pointers to current matrix nonzeros structure and values */ 1689b6f2aa54SBarry Smith PetscInt *oldj = a->j, *oldi = a->i; 16909f0612e4SBarry Smith PetscBool free_a = a->free_a, free_ij = a->free_ij; 16916ea2a7edSJunchao Zhang const PetscScalar *Aa; 169207425a8dSBarry Smith PetscInt *mdiag = NULL; 16936ea2a7edSJunchao Zhang 169407425a8dSBarry Smith PetscCall(PetscCalloc1(A->rmap->n, &mdiag)); 169507425a8dSBarry Smith for (PetscInt i = 0; i < A->rmap->n; i++) { 169607425a8dSBarry Smith if (i < A->cmap->n && diag[i] >= ii[i + 1]) { /* 'out of range' rows never have diagonals */ 169707425a8dSBarry Smith mdiag[i] = 1; 169807425a8dSBarry Smith } 169907425a8dSBarry Smith } 17006ea2a7edSJunchao Zhang PetscCall(MatSeqAIJGetArrayRead(A, &Aa)); // sync the host 17016ea2a7edSJunchao Zhang PetscCall(MatSeqAIJRestoreArrayRead(A, &Aa)); 170261ecd0c6SBarry Smith 170361ecd0c6SBarry Smith a->a = NULL; 170461ecd0c6SBarry Smith a->j = NULL; 170561ecd0c6SBarry Smith a->i = NULL; 170661ecd0c6SBarry Smith /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */ 170707425a8dSBarry Smith for (PetscInt i = 0; i < PetscMin(A->rmap->n, A->cmap->n); i++) a->imax[i] += mdiag[i]; 17089566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A, 0, a->imax)); 170961ecd0c6SBarry Smith 171061ecd0c6SBarry Smith /* copy old values into new matrix data structure */ 171107425a8dSBarry Smith for (PetscInt i = 0; i < A->rmap->n; i++) { 17129566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &i, a->imax[i] - mdiag[i], &oldj[oldi[i]], &olda[oldi[i]], ADD_VALUES)); 171348a46eb9SPierre Jolivet if (i < A->cmap->n) PetscCall(MatSetValue(A, i, i, v, ADD_VALUES)); 1714447d62f5SStefano Zampini } 17159566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 17169566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 17179f0612e4SBarry Smith if (free_a) PetscCall(PetscShmgetDeallocateArray((void **)&olda)); 17189f0612e4SBarry Smith if (free_ij) PetscCall(PetscShmgetDeallocateArray((void **)&oldj)); 17199f0612e4SBarry Smith if (free_ij) PetscCall(PetscShmgetDeallocateArray((void **)&oldi)); 17209566063dSJacob Faibussowitsch PetscCall(PetscFree(mdiag)); 1721be5855fcSBarry Smith } 17223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1723be5855fcSBarry Smith } 1724be5855fcSBarry Smith 17250da83c2eSBarry Smith #include <petscblaslapack.h> 17260da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h> 17270da83c2eSBarry Smith 17280da83c2eSBarry Smith /* 17290da83c2eSBarry Smith Note that values is allocated externally by the PC and then passed into this routine 17300da83c2eSBarry Smith */ 1731ba38deedSJacob Faibussowitsch static PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *diag) 1732d71ae5a4SJacob Faibussowitsch { 17330da83c2eSBarry Smith PetscInt n = A->rmap->n, i, ncnt = 0, *indx, j, bsizemax = 0, *v_pivots; 17340da83c2eSBarry Smith PetscBool allowzeropivot, zeropivotdetected = PETSC_FALSE; 17350da83c2eSBarry Smith const PetscReal shift = 0.0; 17360da83c2eSBarry Smith PetscInt ipvt[5]; 17374e208921SJed Brown PetscCount flops = 0; 17380da83c2eSBarry Smith PetscScalar work[25], *v_work; 17390da83c2eSBarry Smith 17400da83c2eSBarry Smith PetscFunctionBegin; 17410da83c2eSBarry Smith allowzeropivot = PetscNot(A->erroriffailure); 17420da83c2eSBarry Smith for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 174308401ef6SPierre Jolivet PetscCheck(ncnt == n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total blocksizes %" PetscInt_FMT " doesn't match number matrix rows %" PetscInt_FMT, ncnt, n); 1744ad540459SPierre Jolivet for (i = 0; i < nblocks; i++) bsizemax = PetscMax(bsizemax, bsizes[i]); 17459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsizemax, &indx)); 174648a46eb9SPierre Jolivet if (bsizemax > 7) PetscCall(PetscMalloc2(bsizemax, &v_work, bsizemax, &v_pivots)); 17470da83c2eSBarry Smith ncnt = 0; 17480da83c2eSBarry Smith for (i = 0; i < nblocks; i++) { 17490da83c2eSBarry Smith for (j = 0; j < bsizes[i]; j++) indx[j] = ncnt + j; 17509566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, bsizes[i], indx, bsizes[i], indx, diag)); 17510da83c2eSBarry Smith switch (bsizes[i]) { 1752d71ae5a4SJacob Faibussowitsch case 1: 1753d71ae5a4SJacob Faibussowitsch *diag = 1.0 / (*diag); 1754d71ae5a4SJacob Faibussowitsch break; 17550da83c2eSBarry Smith case 2: 17569566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected)); 17570da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17589566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_2(diag)); 17590da83c2eSBarry Smith break; 17600da83c2eSBarry Smith case 3: 17619566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected)); 17620da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17639566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_3(diag)); 17640da83c2eSBarry Smith break; 17650da83c2eSBarry Smith case 4: 17669566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected)); 17670da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17689566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_4(diag)); 17690da83c2eSBarry Smith break; 17700da83c2eSBarry Smith case 5: 17719566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected)); 17720da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17739566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_5(diag)); 17740da83c2eSBarry Smith break; 17750da83c2eSBarry Smith case 6: 17769566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected)); 17770da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17789566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_6(diag)); 17790da83c2eSBarry Smith break; 17800da83c2eSBarry Smith case 7: 17819566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected)); 17820da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17839566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_7(diag)); 17840da83c2eSBarry Smith break; 17850da83c2eSBarry Smith default: 17869566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A(bsizes[i], diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected)); 17870da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17889566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_N(diag, bsizes[i])); 17890da83c2eSBarry Smith } 17900da83c2eSBarry Smith ncnt += bsizes[i]; 17910da83c2eSBarry Smith diag += bsizes[i] * bsizes[i]; 1792baa50dc0SBrad Aagaard flops += 2 * PetscPowInt64(bsizes[i], 3) / 3; 17930da83c2eSBarry Smith } 17943ba16761SJacob Faibussowitsch PetscCall(PetscLogFlops(flops)); 179548a46eb9SPierre Jolivet if (bsizemax > 7) PetscCall(PetscFree2(v_work, v_pivots)); 17969566063dSJacob Faibussowitsch PetscCall(PetscFree(indx)); 17973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17980da83c2eSBarry Smith } 17990da83c2eSBarry Smith 1800422a814eSBarry Smith /* 1801422a814eSBarry Smith Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways 1802422a814eSBarry Smith */ 180307425a8dSBarry Smith static PetscErrorCode MatInvertDiagonalForSOR_SeqAIJ(Mat A, PetscScalar omega, PetscScalar fshift) 1804d71ae5a4SJacob Faibussowitsch { 180571f1c65dSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1806*421480d9SBarry Smith PetscInt i, m = A->rmap->n; 18072e5835c6SStefano Zampini const MatScalar *v; 180854f21887SBarry Smith PetscScalar *idiag, *mdiag; 1809*421480d9SBarry Smith PetscBool diagDense; 1810*421480d9SBarry Smith const PetscInt *diag; 181171f1c65dSBarry Smith 181271f1c65dSBarry Smith PetscFunctionBegin; 181307425a8dSBarry Smith if (a->idiagState == ((PetscObject)A)->state && a->omega == omega && a->fshift == fshift) PetscFunctionReturn(PETSC_SUCCESS); 1814*421480d9SBarry Smith PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, &diagDense)); 1815*421480d9SBarry Smith PetscCheck(diagDense, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix must have all diagonal locations to invert them"); 18163a7d0413SPierre Jolivet if (!a->idiag) PetscCall(PetscMalloc3(m, &a->idiag, m, &a->mdiag, m, &a->ssor_work)); 18172e5835c6SStefano Zampini 181871f1c65dSBarry Smith mdiag = a->mdiag; 181971f1c65dSBarry Smith idiag = a->idiag; 18209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &v)); 1821422a814eSBarry Smith if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) { 182271f1c65dSBarry Smith for (i = 0; i < m; i++) { 182371f1c65dSBarry Smith mdiag[i] = v[diag[i]]; 1824899639b0SHong Zhang if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */ 1825966bd95aSPierre Jolivet PetscCheck(PetscRealPart(fshift), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Zero diagonal on row %" PetscInt_FMT, i); 18269566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Zero diagonal on row %" PetscInt_FMT "\n", i)); 18277b6c816cSBarry Smith A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18287b6c816cSBarry Smith A->factorerror_zeropivot_value = 0.0; 18297b6c816cSBarry Smith A->factorerror_zeropivot_row = i; 1830899639b0SHong Zhang } 183171f1c65dSBarry Smith idiag[i] = 1.0 / v[diag[i]]; 183271f1c65dSBarry Smith } 18339566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(m)); 183471f1c65dSBarry Smith } else { 183571f1c65dSBarry Smith for (i = 0; i < m; i++) { 183671f1c65dSBarry Smith mdiag[i] = v[diag[i]]; 183771f1c65dSBarry Smith idiag[i] = omega / (fshift + v[diag[i]]); 183871f1c65dSBarry Smith } 18399566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * m)); 184071f1c65dSBarry Smith } 18419566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &v)); 184207425a8dSBarry Smith a->idiagState = ((PetscObject)A)->state; 184307425a8dSBarry Smith a->omega = omega; 184407425a8dSBarry Smith a->fshift = fshift; 18453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 184671f1c65dSBarry Smith } 184771f1c65dSBarry Smith 1848d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSOR_SeqAIJ(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal fshift, PetscInt its, PetscInt lits, Vec xx) 1849d71ae5a4SJacob Faibussowitsch { 1850416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1851e6d1f457SBarry Smith PetscScalar *x, d, sum, *t, scale; 18522e5835c6SStefano Zampini const MatScalar *v, *idiag = NULL, *mdiag, *aa; 185354f21887SBarry Smith const PetscScalar *b, *bs, *xb, *ts; 18543d3eaba7SBarry Smith PetscInt n, m = A->rmap->n, i; 185597f1f81fSBarry Smith const PetscInt *idx, *diag; 185617ab2063SBarry Smith 18573a40ed3dSBarry Smith PetscFunctionBegin; 1858b215bc84SStefano Zampini if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) { 18599566063dSJacob Faibussowitsch PetscCall(MatSOR_SeqAIJ_Inode(A, bb, omega, flag, fshift, its, lits, xx)); 18603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1861b215bc84SStefano Zampini } 1862b965ef7fSBarry Smith its = its * lits; 186307425a8dSBarry Smith PetscCall(MatInvertDiagonalForSOR_SeqAIJ(A, omega, fshift)); 1864*421480d9SBarry Smith PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, NULL)); 186571f1c65dSBarry Smith t = a->ssor_work; 1866ed480e8bSBarry Smith idiag = a->idiag; 186771f1c65dSBarry Smith mdiag = a->mdiag; 1868ed480e8bSBarry Smith 18699566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 18709566063dSJacob Faibussowitsch PetscCall(VecGetArray(xx, &x)); 18719566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(bb, &b)); 1872ed480e8bSBarry Smith /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */ 187317ab2063SBarry Smith if (flag == SOR_APPLY_UPPER) { 187417ab2063SBarry Smith /* apply (U + D/omega) to the vector */ 1875ed480e8bSBarry Smith bs = b; 187617ab2063SBarry Smith for (i = 0; i < m; i++) { 187771f1c65dSBarry Smith d = fshift + mdiag[i]; 1878416022c9SBarry Smith n = a->i[i + 1] - diag[i] - 1; 1879ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 18802e5835c6SStefano Zampini v = aa + diag[i] + 1; 188117ab2063SBarry Smith sum = b[i] * d / omega; 1882003131ecSBarry Smith PetscSparseDensePlusDot(sum, bs, v, idx, n); 188317ab2063SBarry Smith x[i] = sum; 188417ab2063SBarry Smith } 18859566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx, &x)); 18869566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb, &b)); 18879566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 18889566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 18893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 189017ab2063SBarry Smith } 1891c783ea89SBarry Smith 189208401ef6SPierre Jolivet PetscCheck(flag != SOR_APPLY_LOWER, PETSC_COMM_SELF, PETSC_ERR_SUP, "SOR_APPLY_LOWER is not implemented"); 1893f7d195e4SLawrence Mitchell if (flag & SOR_EISENSTAT) { 18944c500f23SPierre Jolivet /* Let A = L + U + D; where L is lower triangular, 1895887ee2caSBarry Smith U is upper triangular, E = D/omega; This routine applies 189617ab2063SBarry Smith 189717ab2063SBarry Smith (L + E)^{-1} A (U + E)^{-1} 189817ab2063SBarry Smith 1899887ee2caSBarry Smith to a vector efficiently using Eisenstat's trick. 190017ab2063SBarry Smith */ 190117ab2063SBarry Smith scale = (2.0 / omega) - 1.0; 190217ab2063SBarry Smith 190317ab2063SBarry Smith /* x = (E + U)^{-1} b */ 190417ab2063SBarry Smith for (i = m - 1; i >= 0; i--) { 1905416022c9SBarry Smith n = a->i[i + 1] - diag[i] - 1; 1906ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 19072e5835c6SStefano Zampini v = aa + diag[i] + 1; 190817ab2063SBarry Smith sum = b[i]; 1909e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 1910ed480e8bSBarry Smith x[i] = sum * idiag[i]; 191117ab2063SBarry Smith } 191217ab2063SBarry Smith 191317ab2063SBarry Smith /* t = b - (2*E - D)x */ 19142e5835c6SStefano Zampini v = aa; 19152205254eSKarl Rupp for (i = 0; i < m; i++) t[i] = b[i] - scale * (v[*diag++]) * x[i]; 191617ab2063SBarry Smith 191717ab2063SBarry Smith /* t = (E + L)^{-1}t */ 1918ed480e8bSBarry Smith ts = t; 1919416022c9SBarry Smith diag = a->diag; 192017ab2063SBarry Smith for (i = 0; i < m; i++) { 1921416022c9SBarry Smith n = diag[i] - a->i[i]; 1922ed480e8bSBarry Smith idx = a->j + a->i[i]; 19232e5835c6SStefano Zampini v = aa + a->i[i]; 192417ab2063SBarry Smith sum = t[i]; 1925003131ecSBarry Smith PetscSparseDenseMinusDot(sum, ts, v, idx, n); 1926ed480e8bSBarry Smith t[i] = sum * idiag[i]; 1927733d66baSBarry Smith /* x = x + t */ 1928733d66baSBarry Smith x[i] += t[i]; 192917ab2063SBarry Smith } 193017ab2063SBarry Smith 19319566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(6.0 * m - 1 + 2.0 * a->nz)); 19329566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx, &x)); 19339566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb, &b)); 19343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 193517ab2063SBarry Smith } 193617ab2063SBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 193717ab2063SBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 193817ab2063SBarry Smith for (i = 0; i < m; i++) { 1939416022c9SBarry Smith n = diag[i] - a->i[i]; 1940ed480e8bSBarry Smith idx = a->j + a->i[i]; 19412e5835c6SStefano Zampini v = aa + a->i[i]; 194217ab2063SBarry Smith sum = b[i]; 1943e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 19445c99c7daSBarry Smith t[i] = sum; 1945ed480e8bSBarry Smith x[i] = sum * idiag[i]; 194617ab2063SBarry Smith } 19475c99c7daSBarry Smith xb = t; 19489566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 19493a40ed3dSBarry Smith } else xb = b; 195017ab2063SBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 195117ab2063SBarry Smith for (i = m - 1; i >= 0; i--) { 1952416022c9SBarry Smith n = a->i[i + 1] - diag[i] - 1; 1953ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 19542e5835c6SStefano Zampini v = aa + diag[i] + 1; 195517ab2063SBarry Smith sum = xb[i]; 1956e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 19575c99c7daSBarry Smith if (xb == b) { 1958ed480e8bSBarry Smith x[i] = sum * idiag[i]; 19595c99c7daSBarry Smith } else { 1960b19a5dc2SMark Adams x[i] = (1 - omega) * x[i] + sum * idiag[i]; /* omega in idiag */ 196117ab2063SBarry Smith } 19625c99c7daSBarry Smith } 19639566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */ 196417ab2063SBarry Smith } 196517ab2063SBarry Smith its--; 196617ab2063SBarry Smith } 196717ab2063SBarry Smith while (its--) { 196817ab2063SBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 196917ab2063SBarry Smith for (i = 0; i < m; i++) { 1970b19a5dc2SMark Adams /* lower */ 1971b19a5dc2SMark Adams n = diag[i] - a->i[i]; 1972ed480e8bSBarry Smith idx = a->j + a->i[i]; 19732e5835c6SStefano Zampini v = aa + a->i[i]; 197417ab2063SBarry Smith sum = b[i]; 1975e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 1976b19a5dc2SMark Adams t[i] = sum; /* save application of the lower-triangular part */ 1977b19a5dc2SMark Adams /* upper */ 1978b19a5dc2SMark Adams n = a->i[i + 1] - diag[i] - 1; 1979b19a5dc2SMark Adams idx = a->j + diag[i] + 1; 19802e5835c6SStefano Zampini v = aa + diag[i] + 1; 1981b19a5dc2SMark Adams PetscSparseDenseMinusDot(sum, x, v, idx, n); 1982b19a5dc2SMark Adams x[i] = (1. - omega) * x[i] + sum * idiag[i]; /* omega in idiag */ 198317ab2063SBarry Smith } 1984b19a5dc2SMark Adams xb = t; 19859566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 1986b19a5dc2SMark Adams } else xb = b; 198717ab2063SBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 198817ab2063SBarry Smith for (i = m - 1; i >= 0; i--) { 1989b19a5dc2SMark Adams sum = xb[i]; 1990b19a5dc2SMark Adams if (xb == b) { 1991b19a5dc2SMark Adams /* whole matrix (no checkpointing available) */ 1992416022c9SBarry Smith n = a->i[i + 1] - a->i[i]; 1993ed480e8bSBarry Smith idx = a->j + a->i[i]; 19942e5835c6SStefano Zampini v = aa + a->i[i]; 1995e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 1996ed480e8bSBarry Smith x[i] = (1. - omega) * x[i] + (sum + mdiag[i] * x[i]) * idiag[i]; 1997b19a5dc2SMark Adams } else { /* lower-triangular part has been saved, so only apply upper-triangular */ 1998b19a5dc2SMark Adams n = a->i[i + 1] - diag[i] - 1; 1999b19a5dc2SMark Adams idx = a->j + diag[i] + 1; 20002e5835c6SStefano Zampini v = aa + diag[i] + 1; 2001b19a5dc2SMark Adams PetscSparseDenseMinusDot(sum, x, v, idx, n); 2002b19a5dc2SMark Adams x[i] = (1. - omega) * x[i] + sum * idiag[i]; /* omega in idiag */ 200317ab2063SBarry Smith } 2004b19a5dc2SMark Adams } 2005b19a5dc2SMark Adams if (xb == b) { 20069566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 2007b19a5dc2SMark Adams } else { 20089566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */ 2009b19a5dc2SMark Adams } 201017ab2063SBarry Smith } 201117ab2063SBarry Smith } 20129566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 20139566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx, &x)); 20149566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb, &b)); 20153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 201617ab2063SBarry Smith } 201717ab2063SBarry Smith 2018ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetInfo_SeqAIJ(Mat A, MatInfoType flag, MatInfo *info) 2019d71ae5a4SJacob Faibussowitsch { 2020416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 20214e220ebcSLois Curfman McInnes 20223a40ed3dSBarry Smith PetscFunctionBegin; 20234e220ebcSLois Curfman McInnes info->block_size = 1.0; 20243966268fSBarry Smith info->nz_allocated = a->maxnz; 20253966268fSBarry Smith info->nz_used = a->nz; 20263966268fSBarry Smith info->nz_unneeded = (a->maxnz - a->nz); 20273966268fSBarry Smith info->assemblies = A->num_ass; 20283966268fSBarry Smith info->mallocs = A->info.mallocs; 20294dfa11a4SJacob Faibussowitsch info->memory = 0; /* REVIEW ME */ 2030d5f3da31SBarry Smith if (A->factortype) { 20314e220ebcSLois Curfman McInnes info->fill_ratio_given = A->info.fill_ratio_given; 20324e220ebcSLois Curfman McInnes info->fill_ratio_needed = A->info.fill_ratio_needed; 20334e220ebcSLois Curfman McInnes info->factor_mallocs = A->info.factor_mallocs; 20344e220ebcSLois Curfman McInnes } else { 20354e220ebcSLois Curfman McInnes info->fill_ratio_given = 0; 20364e220ebcSLois Curfman McInnes info->fill_ratio_needed = 0; 20374e220ebcSLois Curfman McInnes info->factor_mallocs = 0; 20384e220ebcSLois Curfman McInnes } 20393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 204017ab2063SBarry Smith } 204117ab2063SBarry Smith 2042*421480d9SBarry Smith static PetscErrorCode MatZeroRows_SeqAIJ(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diagv, Vec x, Vec b) 2043d71ae5a4SJacob Faibussowitsch { 2044416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2045c7da8527SEric Chamberland PetscInt i, m = A->rmap->n - 1; 204697b48c8fSBarry Smith const PetscScalar *xx; 20472e5835c6SStefano Zampini PetscScalar *bb, *aa; 2048c7da8527SEric Chamberland PetscInt d = 0; 2049*421480d9SBarry Smith const PetscInt *diag; 205017ab2063SBarry Smith 20513a40ed3dSBarry Smith PetscFunctionBegin; 205297b48c8fSBarry Smith if (x && b) { 20539566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 20549566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 205597b48c8fSBarry Smith for (i = 0; i < N; i++) { 2056aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 2057447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 2058*421480d9SBarry Smith bb[rows[i]] = diagv * xx[rows[i]]; 205997b48c8fSBarry Smith } 20609566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 20619566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 206297b48c8fSBarry Smith } 206397b48c8fSBarry Smith 2064*421480d9SBarry Smith PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, NULL)); 20659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 2066a9817697SBarry Smith if (a->keepnonzeropattern) { 2067f1e2ffcdSBarry Smith for (i = 0; i < N; i++) { 2068aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 20699566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(&aa[a->i[rows[i]]], a->ilen[rows[i]])); 2070f1e2ffcdSBarry Smith } 2071*421480d9SBarry Smith if (diagv != 0.0) { 2072c7da8527SEric Chamberland for (i = 0; i < N; i++) { 2073c7da8527SEric Chamberland d = rows[i]; 2074*421480d9SBarry Smith if (d >= A->cmap->n) continue; 2075*421480d9SBarry Smith PetscCheck(diag[d] < a->i[d + 1], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix is missing diagonal entry in the zeroed row %" PetscInt_FMT, d); 2076c7da8527SEric Chamberland } 2077f1e2ffcdSBarry Smith for (i = 0; i < N; i++) { 2078447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 2079*421480d9SBarry Smith aa[diag[rows[i]]] = diagv; 2080f1e2ffcdSBarry Smith } 2081f1e2ffcdSBarry Smith } 2082f1e2ffcdSBarry Smith } else { 2083*421480d9SBarry Smith if (diagv != 0.0) { 208417ab2063SBarry Smith for (i = 0; i < N; i++) { 2085aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 20867ae801bdSBarry Smith if (a->ilen[rows[i]] > 0) { 2087447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) { 2088447d62f5SStefano Zampini a->ilen[rows[i]] = 0; 2089447d62f5SStefano Zampini } else { 2090416022c9SBarry Smith a->ilen[rows[i]] = 1; 2091*421480d9SBarry Smith aa[a->i[rows[i]]] = diagv; 2092bfeeae90SHong Zhang a->j[a->i[rows[i]]] = rows[i]; 2093447d62f5SStefano Zampini } 2094447d62f5SStefano Zampini } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */ 2095*421480d9SBarry Smith PetscCall(MatSetValues_SeqAIJ(A, 1, &rows[i], 1, &rows[i], &diagv, INSERT_VALUES)); 209617ab2063SBarry Smith } 209717ab2063SBarry Smith } 20983a40ed3dSBarry Smith } else { 209917ab2063SBarry Smith for (i = 0; i < N; i++) { 2100aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 2101416022c9SBarry Smith a->ilen[rows[i]] = 0; 210217ab2063SBarry Smith } 210317ab2063SBarry Smith } 2104e56f5c9eSBarry Smith A->nonzerostate++; 2105f1e2ffcdSBarry Smith } 21069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 2107dbbe0bcdSBarry Smith PetscUseTypeMethod(A, assemblyend, MAT_FINAL_ASSEMBLY); 21083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 210917ab2063SBarry Smith } 211017ab2063SBarry Smith 2111*421480d9SBarry Smith static PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diagv, Vec x, Vec b) 2112d71ae5a4SJacob Faibussowitsch { 21136e169961SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 21146e169961SBarry Smith PetscInt i, j, m = A->rmap->n - 1, d = 0; 2115*421480d9SBarry Smith PetscBool *zeroed, vecs = PETSC_FALSE; 21166e169961SBarry Smith const PetscScalar *xx; 21172e5835c6SStefano Zampini PetscScalar *bb, *aa; 2118*421480d9SBarry Smith const PetscInt *diag; 2119*421480d9SBarry Smith PetscBool diagDense; 21206e169961SBarry Smith 21216e169961SBarry Smith PetscFunctionBegin; 21223ba16761SJacob Faibussowitsch if (!N) PetscFunctionReturn(PETSC_SUCCESS); 2123*421480d9SBarry Smith PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, &diagDense)); 21249566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 21256e169961SBarry Smith if (x && b) { 21269566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 21279566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 21282b40b63fSBarry Smith vecs = PETSC_TRUE; 21296e169961SBarry Smith } 21309566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n, &zeroed)); 21316e169961SBarry Smith for (i = 0; i < N; i++) { 2132aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 21338e3a54c0SPierre Jolivet PetscCall(PetscArrayzero(PetscSafePointerPlusOffset(aa, a->i[rows[i]]), a->ilen[rows[i]])); 21342205254eSKarl Rupp 21356e169961SBarry Smith zeroed[rows[i]] = PETSC_TRUE; 21366e169961SBarry Smith } 21376e169961SBarry Smith for (i = 0; i < A->rmap->n; i++) { 21386e169961SBarry Smith if (!zeroed[i]) { 21396e169961SBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 21404cf107fdSStefano Zampini if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) { 21412e5835c6SStefano Zampini if (vecs) bb[i] -= aa[j] * xx[a->j[j]]; 21422e5835c6SStefano Zampini aa[j] = 0.0; 21436e169961SBarry Smith } 21446e169961SBarry Smith } 2145*421480d9SBarry Smith } else if (vecs && i < A->cmap->N) bb[i] = diagv * xx[i]; 21466e169961SBarry Smith } 21476e169961SBarry Smith if (x && b) { 21489566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 21499566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 21506e169961SBarry Smith } 21519566063dSJacob Faibussowitsch PetscCall(PetscFree(zeroed)); 2152*421480d9SBarry Smith if (diagv != 0.0) { 2153*421480d9SBarry Smith if (!diagDense) { 21541d5a398dSstefano_zampini for (i = 0; i < N; i++) { 21554cf107fdSStefano Zampini if (rows[i] >= A->cmap->N) continue; 2156aed4548fSBarry Smith PetscCheck(!a->nonew || rows[i] < d, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix is missing diagonal entry in row %" PetscInt_FMT " (%" PetscInt_FMT ")", d, rows[i]); 2157*421480d9SBarry Smith PetscCall(MatSetValues_SeqAIJ(A, 1, &rows[i], 1, &rows[i], &diagv, INSERT_VALUES)); 21581d5a398dSstefano_zampini } 21591d5a398dSstefano_zampini } else { 2160*421480d9SBarry Smith for (i = 0; i < N; i++) aa[diag[rows[i]]] = diagv; 21616e169961SBarry Smith } 21621d5a398dSstefano_zampini } 21639566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 2164dbbe0bcdSBarry Smith PetscUseTypeMethod(A, assemblyend, MAT_FINAL_ASSEMBLY); 21653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21666e169961SBarry Smith } 21676e169961SBarry Smith 2168d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRow_SeqAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 2169d71ae5a4SJacob Faibussowitsch { 2170fff043a9SJunchao Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2171fff043a9SJunchao Zhang const PetscScalar *aa; 217217ab2063SBarry Smith 21733a40ed3dSBarry Smith PetscFunctionBegin; 21749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 2175416022c9SBarry Smith *nz = a->i[row + 1] - a->i[row]; 21768e3a54c0SPierre Jolivet if (v) *v = PetscSafePointerPlusOffset((PetscScalar *)aa, a->i[row]); 217717ab2063SBarry Smith if (idx) { 21785c0db29aSPierre Jolivet if (*nz && a->j) *idx = a->j + a->i[row]; 2179f4259b30SLisandro Dalcin else *idx = NULL; 218017ab2063SBarry Smith } 21819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 21823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 218317ab2063SBarry Smith } 218417ab2063SBarry Smith 2185d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreRow_SeqAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 2186d71ae5a4SJacob Faibussowitsch { 21873a40ed3dSBarry Smith PetscFunctionBegin; 21883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 218917ab2063SBarry Smith } 219017ab2063SBarry Smith 2191ba38deedSJacob Faibussowitsch static PetscErrorCode MatNorm_SeqAIJ(Mat A, NormType type, PetscReal *nrm) 2192d71ae5a4SJacob Faibussowitsch { 2193416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 21942e5835c6SStefano Zampini const MatScalar *v; 219536db0b34SBarry Smith PetscReal sum = 0.0; 219697f1f81fSBarry Smith PetscInt i, j; 219717ab2063SBarry Smith 21983a40ed3dSBarry Smith PetscFunctionBegin; 21999566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &v)); 220017ab2063SBarry Smith if (type == NORM_FROBENIUS) { 2201570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16) 2202570b7f6dSBarry Smith PetscBLASInt one = 1, nz = a->nz; 2203792fecdfSBarry Smith PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&nz, v, &one)); 2204570b7f6dSBarry Smith #else 2205416022c9SBarry Smith for (i = 0; i < a->nz; i++) { 22069371c9d4SSatish Balay sum += PetscRealPart(PetscConj(*v) * (*v)); 22079371c9d4SSatish Balay v++; 220817ab2063SBarry Smith } 22098f1a2a5eSBarry Smith *nrm = PetscSqrtReal(sum); 2210570b7f6dSBarry Smith #endif 22119566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 22123a40ed3dSBarry Smith } else if (type == NORM_1) { 221336db0b34SBarry Smith PetscReal *tmp; 221497f1f81fSBarry Smith PetscInt *jj = a->j; 22159566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->cmap->n + 1, &tmp)); 2216064f8208SBarry Smith *nrm = 0.0; 2217416022c9SBarry Smith for (j = 0; j < a->nz; j++) { 22189371c9d4SSatish Balay tmp[*jj++] += PetscAbsScalar(*v); 22199371c9d4SSatish Balay v++; 222017ab2063SBarry Smith } 2221d0f46423SBarry Smith for (j = 0; j < A->cmap->n; j++) { 2222064f8208SBarry Smith if (tmp[j] > *nrm) *nrm = tmp[j]; 222317ab2063SBarry Smith } 22249566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp)); 22259566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(PetscMax(a->nz - 1, 0))); 22263a40ed3dSBarry Smith } else if (type == NORM_INFINITY) { 2227064f8208SBarry Smith *nrm = 0.0; 2228d0f46423SBarry Smith for (j = 0; j < A->rmap->n; j++) { 22298e3a54c0SPierre Jolivet const PetscScalar *v2 = PetscSafePointerPlusOffset(v, a->i[j]); 223017ab2063SBarry Smith sum = 0.0; 2231416022c9SBarry Smith for (i = 0; i < a->i[j + 1] - a->i[j]; i++) { 22329371c9d4SSatish Balay sum += PetscAbsScalar(*v2); 22339371c9d4SSatish Balay v2++; 223417ab2063SBarry Smith } 2235064f8208SBarry Smith if (sum > *nrm) *nrm = sum; 223617ab2063SBarry Smith } 22379566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(PetscMax(a->nz - 1, 0))); 2238f23aa3ddSBarry Smith } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for two norm"); 22399566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &v)); 22403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 224117ab2063SBarry Smith } 224217ab2063SBarry Smith 2243ba38deedSJacob Faibussowitsch static PetscErrorCode MatIsTranspose_SeqAIJ(Mat A, Mat B, PetscReal tol, PetscBool *f) 2244d71ae5a4SJacob Faibussowitsch { 22453d3eaba7SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data, *bij = (Mat_SeqAIJ *)B->data; 224654f21887SBarry Smith PetscInt *adx, *bdx, *aii, *bii, *aptr, *bptr; 22472e5835c6SStefano Zampini const MatScalar *va, *vb; 224897f1f81fSBarry Smith PetscInt ma, na, mb, nb, i; 2249cd0d46ebSvictorle 2250cd0d46ebSvictorle PetscFunctionBegin; 22519566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &ma, &na)); 22529566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &mb, &nb)); 22535485867bSBarry Smith if (ma != nb || na != mb) { 22545485867bSBarry Smith *f = PETSC_FALSE; 22553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22565485867bSBarry Smith } 22579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &va)); 22589566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &vb)); 22599371c9d4SSatish Balay aii = aij->i; 22609371c9d4SSatish Balay bii = bij->i; 22619371c9d4SSatish Balay adx = aij->j; 22629371c9d4SSatish Balay bdx = bij->j; 22639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ma, &aptr)); 22649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mb, &bptr)); 2265cd0d46ebSvictorle for (i = 0; i < ma; i++) aptr[i] = aii[i]; 2266cd0d46ebSvictorle for (i = 0; i < mb; i++) bptr[i] = bii[i]; 2267cd0d46ebSvictorle 2268cd0d46ebSvictorle *f = PETSC_TRUE; 2269cd0d46ebSvictorle for (i = 0; i < ma; i++) { 2270cd0d46ebSvictorle while (aptr[i] < aii[i + 1]) { 227197f1f81fSBarry Smith PetscInt idc, idr; 22725485867bSBarry Smith PetscScalar vc, vr; 2273cd0d46ebSvictorle /* column/row index/value */ 22745485867bSBarry Smith idc = adx[aptr[i]]; 22755485867bSBarry Smith idr = bdx[bptr[idc]]; 22765485867bSBarry Smith vc = va[aptr[i]]; 22775485867bSBarry Smith vr = vb[bptr[idc]]; 22785485867bSBarry Smith if (i != idr || PetscAbsScalar(vc - vr) > tol) { 22795485867bSBarry Smith *f = PETSC_FALSE; 22805485867bSBarry Smith goto done; 2281cd0d46ebSvictorle } else { 22825485867bSBarry Smith aptr[i]++; 22835485867bSBarry Smith if (B || i != idc) bptr[idc]++; 2284cd0d46ebSvictorle } 2285cd0d46ebSvictorle } 2286cd0d46ebSvictorle } 2287cd0d46ebSvictorle done: 22889566063dSJacob Faibussowitsch PetscCall(PetscFree(aptr)); 22899566063dSJacob Faibussowitsch PetscCall(PetscFree(bptr)); 22909566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &va)); 22919566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &vb)); 22923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2293cd0d46ebSvictorle } 2294cd0d46ebSvictorle 2295ba38deedSJacob Faibussowitsch static PetscErrorCode MatIsHermitianTranspose_SeqAIJ(Mat A, Mat B, PetscReal tol, PetscBool *f) 2296d71ae5a4SJacob Faibussowitsch { 22973d3eaba7SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data, *bij = (Mat_SeqAIJ *)B->data; 229854f21887SBarry Smith PetscInt *adx, *bdx, *aii, *bii, *aptr, *bptr; 229954f21887SBarry Smith MatScalar *va, *vb; 23001cbb95d3SBarry Smith PetscInt ma, na, mb, nb, i; 23011cbb95d3SBarry Smith 23021cbb95d3SBarry Smith PetscFunctionBegin; 23039566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &ma, &na)); 23049566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &mb, &nb)); 23051cbb95d3SBarry Smith if (ma != nb || na != mb) { 23061cbb95d3SBarry Smith *f = PETSC_FALSE; 23073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23081cbb95d3SBarry Smith } 23099371c9d4SSatish Balay aii = aij->i; 23109371c9d4SSatish Balay bii = bij->i; 23119371c9d4SSatish Balay adx = aij->j; 23129371c9d4SSatish Balay bdx = bij->j; 23139371c9d4SSatish Balay va = aij->a; 23149371c9d4SSatish Balay vb = bij->a; 23159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ma, &aptr)); 23169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mb, &bptr)); 23171cbb95d3SBarry Smith for (i = 0; i < ma; i++) aptr[i] = aii[i]; 23181cbb95d3SBarry Smith for (i = 0; i < mb; i++) bptr[i] = bii[i]; 23191cbb95d3SBarry Smith 23201cbb95d3SBarry Smith *f = PETSC_TRUE; 23211cbb95d3SBarry Smith for (i = 0; i < ma; i++) { 23221cbb95d3SBarry Smith while (aptr[i] < aii[i + 1]) { 23231cbb95d3SBarry Smith PetscInt idc, idr; 23241cbb95d3SBarry Smith PetscScalar vc, vr; 23251cbb95d3SBarry Smith /* column/row index/value */ 23261cbb95d3SBarry Smith idc = adx[aptr[i]]; 23271cbb95d3SBarry Smith idr = bdx[bptr[idc]]; 23281cbb95d3SBarry Smith vc = va[aptr[i]]; 23291cbb95d3SBarry Smith vr = vb[bptr[idc]]; 23301cbb95d3SBarry Smith if (i != idr || PetscAbsScalar(vc - PetscConj(vr)) > tol) { 23311cbb95d3SBarry Smith *f = PETSC_FALSE; 23321cbb95d3SBarry Smith goto done; 23331cbb95d3SBarry Smith } else { 23341cbb95d3SBarry Smith aptr[i]++; 23351cbb95d3SBarry Smith if (B || i != idc) bptr[idc]++; 23361cbb95d3SBarry Smith } 23371cbb95d3SBarry Smith } 23381cbb95d3SBarry Smith } 23391cbb95d3SBarry Smith done: 23409566063dSJacob Faibussowitsch PetscCall(PetscFree(aptr)); 23419566063dSJacob Faibussowitsch PetscCall(PetscFree(bptr)); 23423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23431cbb95d3SBarry Smith } 23441cbb95d3SBarry Smith 2345d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A, Vec ll, Vec rr) 2346d71ae5a4SJacob Faibussowitsch { 2347416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2348fff8e43fSBarry Smith const PetscScalar *l, *r; 2349fff8e43fSBarry Smith PetscScalar x; 235054f21887SBarry Smith MatScalar *v; 2351fff8e43fSBarry Smith PetscInt i, j, m = A->rmap->n, n = A->cmap->n, M, nz = a->nz; 2352fff8e43fSBarry Smith const PetscInt *jj; 235317ab2063SBarry Smith 23543a40ed3dSBarry Smith PetscFunctionBegin; 235517ab2063SBarry Smith if (ll) { 23563ea7c6a1SSatish Balay /* The local size is used so that VecMPI can be passed to this routine 23573ea7c6a1SSatish Balay by MatDiagonalScale_MPIAIJ */ 23589566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ll, &m)); 235908401ef6SPierre Jolivet PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vector wrong length"); 23609566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(ll, &l)); 23619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &v)); 236217ab2063SBarry Smith for (i = 0; i < m; i++) { 236317ab2063SBarry Smith x = l[i]; 2364416022c9SBarry Smith M = a->i[i + 1] - a->i[i]; 23652205254eSKarl Rupp for (j = 0; j < M; j++) (*v++) *= x; 236617ab2063SBarry Smith } 23679566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(ll, &l)); 23689566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(nz)); 23699566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &v)); 237017ab2063SBarry Smith } 237117ab2063SBarry Smith if (rr) { 23729566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rr, &n)); 237308401ef6SPierre Jolivet PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vector wrong length"); 23749566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(rr, &r)); 23759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &v)); 23762e5835c6SStefano Zampini jj = a->j; 23772205254eSKarl Rupp for (i = 0; i < nz; i++) (*v++) *= r[*jj++]; 23789566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &v)); 23799566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(rr, &r)); 23809566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(nz)); 238117ab2063SBarry Smith } 23823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 238317ab2063SBarry Smith } 238417ab2063SBarry Smith 2385d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A, IS isrow, IS iscol, PetscInt csize, MatReuse scall, Mat *B) 2386d71ae5a4SJacob Faibussowitsch { 2387db02288aSLois Curfman McInnes Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data, *c; 2388d0f46423SBarry Smith PetscInt *smap, i, k, kstart, kend, oldcols = A->cmap->n, *lens; 238997f1f81fSBarry Smith PetscInt row, mat_i, *mat_j, tcol, first, step, *mat_ilen, sum, lensi; 23905d0c19d7SBarry Smith const PetscInt *irow, *icol; 23912e5835c6SStefano Zampini const PetscScalar *aa; 23925d0c19d7SBarry Smith PetscInt nrows, ncols; 239397f1f81fSBarry Smith PetscInt *starts, *j_new, *i_new, *aj = a->j, *ai = a->i, ii, *ailen = a->ilen; 2394fb3c7e2dSJunchao Zhang MatScalar *a_new, *mat_a, *c_a; 2395416022c9SBarry Smith Mat C; 2396cdc6f3adSToby Isaac PetscBool stride; 239717ab2063SBarry Smith 23983a40ed3dSBarry Smith PetscFunctionBegin; 23999566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow, &irow)); 24009566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow, &nrows)); 24019566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol, &ncols)); 240217ab2063SBarry Smith 24039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)iscol, ISSTRIDE, &stride)); 2404ff718158SBarry Smith if (stride) { 24059566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(iscol, &first, &step)); 2406ff718158SBarry Smith } else { 2407ff718158SBarry Smith first = 0; 2408ff718158SBarry Smith step = 0; 2409ff718158SBarry Smith } 2410fee21e36SBarry Smith if (stride && step == 1) { 241102834360SBarry Smith /* special case of contiguous rows */ 24129566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nrows, &lens, nrows, &starts)); 241302834360SBarry Smith /* loop over new rows determining lens and starting points */ 241402834360SBarry Smith for (i = 0; i < nrows; i++) { 2415bfeeae90SHong Zhang kstart = ai[irow[i]]; 2416a2744918SBarry Smith kend = kstart + ailen[irow[i]]; 2417a91a9bebSLisandro Dalcin starts[i] = kstart; 241802834360SBarry Smith for (k = kstart; k < kend; k++) { 2419bfeeae90SHong Zhang if (aj[k] >= first) { 242002834360SBarry Smith starts[i] = k; 242102834360SBarry Smith break; 242202834360SBarry Smith } 242302834360SBarry Smith } 2424a2744918SBarry Smith sum = 0; 242502834360SBarry Smith while (k < kend) { 2426bfeeae90SHong Zhang if (aj[k++] >= first + ncols) break; 2427a2744918SBarry Smith sum++; 242802834360SBarry Smith } 2429a2744918SBarry Smith lens[i] = sum; 243002834360SBarry Smith } 243102834360SBarry Smith /* create submatrix */ 2432cddf8d76SBarry Smith if (scall == MAT_REUSE_MATRIX) { 243397f1f81fSBarry Smith PetscInt n_cols, n_rows; 24349566063dSJacob Faibussowitsch PetscCall(MatGetSize(*B, &n_rows, &n_cols)); 2435aed4548fSBarry Smith PetscCheck(n_rows == nrows && n_cols == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Reused submatrix wrong size"); 24369566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*B)); 243708480c60SBarry Smith C = *B; 24383a40ed3dSBarry Smith } else { 24393bef6203SJed Brown PetscInt rbs, cbs; 24409566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 24419566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, nrows, ncols, PETSC_DETERMINE, PETSC_DETERMINE)); 24429566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(isrow, &rbs)); 24439566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(iscol, &cbs)); 24449566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C, rbs, cbs)); 24459566063dSJacob Faibussowitsch PetscCall(MatSetType(C, ((PetscObject)A)->type_name)); 24469566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C, 0, lens)); 244708480c60SBarry Smith } 2448db02288aSLois Curfman McInnes c = (Mat_SeqAIJ *)C->data; 2449db02288aSLois Curfman McInnes 245002834360SBarry Smith /* loop over rows inserting into submatrix */ 2451fb3c7e2dSJunchao Zhang PetscCall(MatSeqAIJGetArrayWrite(C, &a_new)); // Not 'a_new = c->a-new', since that raw usage ignores offload state of C 2452db02288aSLois Curfman McInnes j_new = c->j; 2453db02288aSLois Curfman McInnes i_new = c->i; 24549566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 245502834360SBarry Smith for (i = 0; i < nrows; i++) { 2456a2744918SBarry Smith ii = starts[i]; 2457a2744918SBarry Smith lensi = lens[i]; 2458810441c8SPierre Jolivet if (lensi) { 2459ad540459SPierre Jolivet for (k = 0; k < lensi; k++) *j_new++ = aj[ii + k] - first; 24609566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a_new, aa + starts[i], lensi)); 2461a2744918SBarry Smith a_new += lensi; 2462810441c8SPierre Jolivet } 2463a2744918SBarry Smith i_new[i + 1] = i_new[i] + lensi; 2464a2744918SBarry Smith c->ilen[i] = lensi; 246502834360SBarry Smith } 2466fb3c7e2dSJunchao Zhang PetscCall(MatSeqAIJRestoreArrayWrite(C, &a_new)); // Set C's offload state properly 24679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 24689566063dSJacob Faibussowitsch PetscCall(PetscFree2(lens, starts)); 24693a40ed3dSBarry Smith } else { 24709566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol, &icol)); 24719566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(oldcols, &smap)); 24729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1 + nrows, &lens)); 24734dcab191SBarry Smith for (i = 0; i < ncols; i++) { 24746bdcaf15SBarry Smith PetscCheck(icol[i] < oldcols, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Requesting column beyond largest column icol[%" PetscInt_FMT "] %" PetscInt_FMT " >= A->cmap->n %" PetscInt_FMT, i, icol[i], oldcols); 24754dcab191SBarry Smith smap[icol[i]] = i + 1; 24764dcab191SBarry Smith } 24774dcab191SBarry Smith 247802834360SBarry Smith /* determine lens of each row */ 247902834360SBarry Smith for (i = 0; i < nrows; i++) { 2480bfeeae90SHong Zhang kstart = ai[irow[i]]; 248102834360SBarry Smith kend = kstart + a->ilen[irow[i]]; 248202834360SBarry Smith lens[i] = 0; 248302834360SBarry Smith for (k = kstart; k < kend; k++) { 2484ad540459SPierre Jolivet if (smap[aj[k]]) lens[i]++; 248502834360SBarry Smith } 248602834360SBarry Smith } 248717ab2063SBarry Smith /* Create and fill new matrix */ 2488a2744918SBarry Smith if (scall == MAT_REUSE_MATRIX) { 2489ace3abfcSBarry Smith PetscBool equal; 24900f5bd95cSBarry Smith 249199141d43SSatish Balay c = (Mat_SeqAIJ *)((*B)->data); 2492aed4548fSBarry Smith PetscCheck((*B)->rmap->n == nrows && (*B)->cmap->n == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot reuse matrix. wrong size"); 24939566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(c->ilen, lens, (*B)->rmap->n, &equal)); 2494fdfbdca6SPierre Jolivet PetscCheck(equal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot reuse matrix. wrong number of nonzeros"); 24959566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->ilen, (*B)->rmap->n)); 249608480c60SBarry Smith C = *B; 24973a40ed3dSBarry Smith } else { 24983bef6203SJed Brown PetscInt rbs, cbs; 24999566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 25009566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, nrows, ncols, PETSC_DETERMINE, PETSC_DETERMINE)); 25019566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(isrow, &rbs)); 25029566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(iscol, &cbs)); 250337a5e0faSPierre Jolivet if (rbs > 1 || cbs > 1) PetscCall(MatSetBlockSizes(C, rbs, cbs)); 25049566063dSJacob Faibussowitsch PetscCall(MatSetType(C, ((PetscObject)A)->type_name)); 25059566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C, 0, lens)); 250608480c60SBarry Smith } 25079566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 2508fb3c7e2dSJunchao Zhang 2509f4f49eeaSPierre Jolivet c = (Mat_SeqAIJ *)C->data; 2510fb3c7e2dSJunchao Zhang PetscCall(MatSeqAIJGetArrayWrite(C, &c_a)); // Not 'c->a', since that raw usage ignores offload state of C 251117ab2063SBarry Smith for (i = 0; i < nrows; i++) { 251299141d43SSatish Balay row = irow[i]; 2513bfeeae90SHong Zhang kstart = ai[row]; 251499141d43SSatish Balay kend = kstart + a->ilen[row]; 2515bfeeae90SHong Zhang mat_i = c->i[i]; 25168e3a54c0SPierre Jolivet mat_j = PetscSafePointerPlusOffset(c->j, mat_i); 25178e3a54c0SPierre Jolivet mat_a = PetscSafePointerPlusOffset(c_a, mat_i); 251899141d43SSatish Balay mat_ilen = c->ilen + i; 251917ab2063SBarry Smith for (k = kstart; k < kend; k++) { 2520bfeeae90SHong Zhang if ((tcol = smap[a->j[k]])) { 2521ed480e8bSBarry Smith *mat_j++ = tcol - 1; 25222e5835c6SStefano Zampini *mat_a++ = aa[k]; 252399141d43SSatish Balay (*mat_ilen)++; 252417ab2063SBarry Smith } 252517ab2063SBarry Smith } 252617ab2063SBarry Smith } 25279566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 252802834360SBarry Smith /* Free work space */ 25299566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol, &icol)); 25309566063dSJacob Faibussowitsch PetscCall(PetscFree(smap)); 25319566063dSJacob Faibussowitsch PetscCall(PetscFree(lens)); 2532cdc6f3adSToby Isaac /* sort */ 2533cdc6f3adSToby Isaac for (i = 0; i < nrows; i++) { 2534cdc6f3adSToby Isaac PetscInt ilen; 2535cdc6f3adSToby Isaac 2536cdc6f3adSToby Isaac mat_i = c->i[i]; 25378e3a54c0SPierre Jolivet mat_j = PetscSafePointerPlusOffset(c->j, mat_i); 25388e3a54c0SPierre Jolivet mat_a = PetscSafePointerPlusOffset(c_a, mat_i); 2539cdc6f3adSToby Isaac ilen = c->ilen[i]; 25409566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(ilen, mat_j, mat_a)); 2541cdc6f3adSToby Isaac } 2542fb3c7e2dSJunchao Zhang PetscCall(MatSeqAIJRestoreArrayWrite(C, &c_a)); 254302834360SBarry Smith } 25448c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 25459566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(C, A->boundtocpu)); 2546305c6ccfSStefano Zampini #endif 25479566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 25489566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 254917ab2063SBarry Smith 25509566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow, &irow)); 2551416022c9SBarry Smith *B = C; 25523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 255317ab2063SBarry Smith } 255417ab2063SBarry Smith 2555ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetMultiProcBlock_SeqAIJ(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 2556d71ae5a4SJacob Faibussowitsch { 255782d44351SHong Zhang Mat B; 255882d44351SHong Zhang 255982d44351SHong Zhang PetscFunctionBegin; 2560c2d650bdSHong Zhang if (scall == MAT_INITIAL_MATRIX) { 25619566063dSJacob Faibussowitsch PetscCall(MatCreate(subComm, &B)); 25629566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->n, mat->cmap->n)); 25639566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, mat, mat)); 25649566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATSEQAIJ)); 25659566063dSJacob Faibussowitsch PetscCall(MatDuplicateNoCreate_SeqAIJ(B, mat, MAT_COPY_VALUES, PETSC_TRUE)); 256682d44351SHong Zhang *subMat = B; 2567c2d650bdSHong Zhang } else { 25689566063dSJacob Faibussowitsch PetscCall(MatCopy_SeqAIJ(mat, *subMat, SAME_NONZERO_PATTERN)); 2569c2d650bdSHong Zhang } 25703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 257182d44351SHong Zhang } 257282d44351SHong Zhang 2573ba38deedSJacob Faibussowitsch static PetscErrorCode MatILUFactor_SeqAIJ(Mat inA, IS row, IS col, const MatFactorInfo *info) 2574d71ae5a4SJacob Faibussowitsch { 257563b91edcSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)inA->data; 257663b91edcSBarry Smith Mat outA; 2577ace3abfcSBarry Smith PetscBool row_identity, col_identity; 257863b91edcSBarry Smith 25793a40ed3dSBarry Smith PetscFunctionBegin; 258008401ef6SPierre Jolivet PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 supported for in-place ilu"); 25811df811f5SHong Zhang 25829566063dSJacob Faibussowitsch PetscCall(ISIdentity(row, &row_identity)); 25839566063dSJacob Faibussowitsch PetscCall(ISIdentity(col, &col_identity)); 2584a871dcd8SBarry Smith 258563b91edcSBarry Smith outA = inA; 25869566063dSJacob Faibussowitsch PetscCall(PetscFree(inA->solvertype)); 25879566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype)); 25882205254eSKarl Rupp 25899566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)row)); 25909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 25912205254eSKarl Rupp 2592c3122656SLisandro Dalcin a->row = row; 25932205254eSKarl Rupp 25949566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)col)); 25959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 25962205254eSKarl Rupp 2597c3122656SLisandro Dalcin a->col = col; 259863b91edcSBarry Smith 259936db0b34SBarry Smith /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */ 26009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 26019566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(col, PETSC_DECIDE, &a->icol)); 2602f0ec6fceSSatish Balay 260394a9d846SBarry Smith if (!a->solve_work) { /* this matrix may have been factored before */ 260484648c2dSPierre Jolivet PetscCall(PetscMalloc1(inA->rmap->n, &a->solve_work)); 260594a9d846SBarry Smith } 260663b91edcSBarry Smith 2607137fb511SHong Zhang if (row_identity && col_identity) { 26089566063dSJacob Faibussowitsch PetscCall(MatLUFactorNumeric_SeqAIJ_inplace(outA, inA, info)); 2609137fb511SHong Zhang } else { 26109566063dSJacob Faibussowitsch PetscCall(MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA, inA, info)); 2611137fb511SHong Zhang } 2612*421480d9SBarry Smith outA->factortype = MAT_FACTOR_LU; 26133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2614a871dcd8SBarry Smith } 2615a871dcd8SBarry Smith 2616d71ae5a4SJacob Faibussowitsch PetscErrorCode MatScale_SeqAIJ(Mat inA, PetscScalar alpha) 2617d71ae5a4SJacob Faibussowitsch { 2618f0b747eeSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)inA->data; 2619dfa0f9e5SStefano Zampini PetscScalar *v; 2620c5df96a5SBarry Smith PetscBLASInt one = 1, bnz; 26213a40ed3dSBarry Smith 26223a40ed3dSBarry Smith PetscFunctionBegin; 26239566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(inA, &v)); 26249566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(a->nz, &bnz)); 2625792fecdfSBarry Smith PetscCallBLAS("BLASscal", BLASscal_(&bnz, &alpha, v, &one)); 26269566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 26279566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(inA, &v)); 26283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2629f0b747eeSBarry Smith } 2630f0b747eeSBarry Smith 2631d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj) 2632d71ae5a4SJacob Faibussowitsch { 263316b64355SHong Zhang PetscInt i; 263416b64355SHong Zhang 263516b64355SHong Zhang PetscFunctionBegin; 263616b64355SHong Zhang if (!submatj->id) { /* delete data that are linked only to submats[id=0] */ 26379566063dSJacob Faibussowitsch PetscCall(PetscFree4(submatj->sbuf1, submatj->ptr, submatj->tmp, submatj->ctr)); 263816b64355SHong Zhang 263948a46eb9SPierre Jolivet for (i = 0; i < submatj->nrqr; ++i) PetscCall(PetscFree(submatj->sbuf2[i])); 26409566063dSJacob Faibussowitsch PetscCall(PetscFree3(submatj->sbuf2, submatj->req_size, submatj->req_source1)); 264116b64355SHong Zhang 264216b64355SHong Zhang if (submatj->rbuf1) { 26439566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rbuf1[0])); 26449566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rbuf1)); 264516b64355SHong Zhang } 264616b64355SHong Zhang 264748a46eb9SPierre Jolivet for (i = 0; i < submatj->nrqs; ++i) PetscCall(PetscFree(submatj->rbuf3[i])); 26489566063dSJacob Faibussowitsch PetscCall(PetscFree3(submatj->req_source2, submatj->rbuf2, submatj->rbuf3)); 26499566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->pa)); 265016b64355SHong Zhang } 265116b64355SHong Zhang 265216b64355SHong Zhang #if defined(PETSC_USE_CTABLE) 2653eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&submatj->rmap)); 26549566063dSJacob Faibussowitsch if (submatj->cmap_loc) PetscCall(PetscFree(submatj->cmap_loc)); 26559566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rmap_loc)); 265616b64355SHong Zhang #else 26579566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rmap)); 265816b64355SHong Zhang #endif 265916b64355SHong Zhang 266016b64355SHong Zhang if (!submatj->allcolumns) { 266116b64355SHong Zhang #if defined(PETSC_USE_CTABLE) 2662835f2295SStefano Zampini PetscCall(PetscHMapIDestroy(&submatj->cmap)); 266316b64355SHong Zhang #else 26649566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->cmap)); 266516b64355SHong Zhang #endif 266616b64355SHong Zhang } 26679566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->row2proc)); 266816b64355SHong Zhang 26699566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj)); 26703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 267116b64355SHong Zhang } 267216b64355SHong Zhang 2673d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C) 2674d71ae5a4SJacob Faibussowitsch { 267516b64355SHong Zhang Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data; 26765c39f6d9SHong Zhang Mat_SubSppt *submatj = c->submatis1; 267716b64355SHong Zhang 267816b64355SHong Zhang PetscFunctionBegin; 26799566063dSJacob Faibussowitsch PetscCall((*submatj->destroy)(C)); 26809566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrix_Private(submatj)); 26813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 268216b64355SHong Zhang } 268316b64355SHong Zhang 268489a1a59bSHong Zhang /* Note this has code duplication with MatDestroySubMatrices_SeqBAIJ() */ 2685ba38deedSJacob Faibussowitsch static PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n, Mat *mat[]) 2686d71ae5a4SJacob Faibussowitsch { 26872d033e1fSHong Zhang PetscInt i; 26880fb991dcSHong Zhang Mat C; 26890fb991dcSHong Zhang Mat_SeqAIJ *c; 26900fb991dcSHong Zhang Mat_SubSppt *submatj; 26912d033e1fSHong Zhang 26922d033e1fSHong Zhang PetscFunctionBegin; 26932d033e1fSHong Zhang for (i = 0; i < n; i++) { 26940fb991dcSHong Zhang C = (*mat)[i]; 26950fb991dcSHong Zhang c = (Mat_SeqAIJ *)C->data; 26960fb991dcSHong Zhang submatj = c->submatis1; 26972d033e1fSHong Zhang if (submatj) { 2698682e4c99SStefano Zampini if (--((PetscObject)C)->refct <= 0) { 269926cc229bSBarry Smith PetscCall(PetscFree(C->factorprefix)); 27009566063dSJacob Faibussowitsch PetscCall((*submatj->destroy)(C)); 27019566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrix_Private(submatj)); 27029566063dSJacob Faibussowitsch PetscCall(PetscFree(C->defaultvectype)); 27033faff063SStefano Zampini PetscCall(PetscFree(C->defaultrandtype)); 27049566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->rmap)); 27059566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->cmap)); 27069566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(&C)); 2707682e4c99SStefano Zampini } 27082d033e1fSHong Zhang } else { 27099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 27102d033e1fSHong Zhang } 27112d033e1fSHong Zhang } 271286e85357SHong Zhang 271363a75b2aSHong Zhang /* Destroy Dummy submatrices created for reuse */ 27149566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices_Dummy(n, mat)); 271563a75b2aSHong Zhang 27169566063dSJacob Faibussowitsch PetscCall(PetscFree(*mat)); 27173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27182d033e1fSHong Zhang } 27192d033e1fSHong Zhang 2720ba38deedSJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[]) 2721d71ae5a4SJacob Faibussowitsch { 272297f1f81fSBarry Smith PetscInt i; 2723cddf8d76SBarry Smith 27243a40ed3dSBarry Smith PetscFunctionBegin; 272548a46eb9SPierre Jolivet if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n + 1, B)); 2726cddf8d76SBarry Smith 272748a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqAIJ(A, irow[i], icol[i], PETSC_DECIDE, scall, &(*B)[i])); 27283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2729cddf8d76SBarry Smith } 2730cddf8d76SBarry Smith 2731ba38deedSJacob Faibussowitsch static PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A, PetscInt is_max, IS is[], PetscInt ov) 2732d71ae5a4SJacob Faibussowitsch { 2733e4d965acSSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 27349a88ca10SBarry Smith PetscInt row, i, j, k, l, ll, m, n, *nidx, isz, val; 27355d0c19d7SBarry Smith const PetscInt *idx; 273658b7e2c1SStefano Zampini PetscInt start, end, *ai, *aj, bs = A->rmap->bs == A->cmap->bs ? A->rmap->bs : 1; 2737f1af5d2fSBarry Smith PetscBT table; 2738bbd702dbSSatish Balay 27393a40ed3dSBarry Smith PetscFunctionBegin; 27409a88ca10SBarry Smith m = A->rmap->n / bs; 2741e4d965acSSatish Balay ai = a->i; 2742bfeeae90SHong Zhang aj = a->j; 27438a047759SSatish Balay 274408401ef6SPierre Jolivet PetscCheck(ov >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "illegal negative overlap value used"); 274506763907SSatish Balay 27469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nidx)); 27479566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(m, &table)); 274806763907SSatish Balay 2749e4d965acSSatish Balay for (i = 0; i < is_max; i++) { 2750b97fc60eSLois Curfman McInnes /* Initialize the two local arrays */ 2751e4d965acSSatish Balay isz = 0; 27529566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(m, table)); 2753e4d965acSSatish Balay 2754e4d965acSSatish Balay /* Extract the indices, assume there can be duplicate entries */ 27559566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is[i], &idx)); 27569566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is[i], &n)); 2757e4d965acSSatish Balay 27589a88ca10SBarry Smith if (bs > 1) { 27599a88ca10SBarry Smith /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 27609a88ca10SBarry Smith for (j = 0; j < n; ++j) { 27619a88ca10SBarry Smith if (!PetscBTLookupSet(table, idx[j] / bs)) nidx[isz++] = idx[j] / bs; 27629a88ca10SBarry Smith } 27639a88ca10SBarry Smith PetscCall(ISRestoreIndices(is[i], &idx)); 27649a88ca10SBarry Smith PetscCall(ISDestroy(&is[i])); 27659a88ca10SBarry Smith 27669a88ca10SBarry Smith k = 0; 27679a88ca10SBarry Smith for (j = 0; j < ov; j++) { /* for each overlap */ 27689a88ca10SBarry Smith n = isz; 27699a88ca10SBarry Smith for (; k < n; k++) { /* do only those rows in nidx[k], which are not done yet */ 27709a88ca10SBarry Smith for (ll = 0; ll < bs; ll++) { 27719a88ca10SBarry Smith row = bs * nidx[k] + ll; 27729a88ca10SBarry Smith start = ai[row]; 27739a88ca10SBarry Smith end = ai[row + 1]; 27749a88ca10SBarry Smith for (l = start; l < end; l++) { 27759a88ca10SBarry Smith val = aj[l] / bs; 27769a88ca10SBarry Smith if (!PetscBTLookupSet(table, val)) nidx[isz++] = val; 27779a88ca10SBarry Smith } 27789a88ca10SBarry Smith } 27799a88ca10SBarry Smith } 27809a88ca10SBarry Smith } 278157508eceSPierre Jolivet PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, isz, nidx, PETSC_COPY_VALUES, is + i)); 27829a88ca10SBarry Smith } else { 2783dd097bc3SLois Curfman McInnes /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 2784e4d965acSSatish Balay for (j = 0; j < n; ++j) { 27852205254eSKarl Rupp if (!PetscBTLookupSet(table, idx[j])) nidx[isz++] = idx[j]; 27864dcbc457SBarry Smith } 27879566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is[i], &idx)); 27889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is[i])); 2789e4d965acSSatish Balay 279004a348a9SBarry Smith k = 0; 279104a348a9SBarry Smith for (j = 0; j < ov; j++) { /* for each overlap */ 279204a348a9SBarry Smith n = isz; 279306763907SSatish Balay for (; k < n; k++) { /* do only those rows in nidx[k], which are not done yet */ 2794e4d965acSSatish Balay row = nidx[k]; 2795e4d965acSSatish Balay start = ai[row]; 2796e4d965acSSatish Balay end = ai[row + 1]; 279704a348a9SBarry Smith for (l = start; l < end; l++) { 2798efb16452SHong Zhang val = aj[l]; 27992205254eSKarl Rupp if (!PetscBTLookupSet(table, val)) nidx[isz++] = val; 2800e4d965acSSatish Balay } 2801e4d965acSSatish Balay } 2802e4d965acSSatish Balay } 280357508eceSPierre Jolivet PetscCall(ISCreateGeneral(PETSC_COMM_SELF, isz, nidx, PETSC_COPY_VALUES, is + i)); 2804e4d965acSSatish Balay } 28059a88ca10SBarry Smith } 28069566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&table)); 28079566063dSJacob Faibussowitsch PetscCall(PetscFree(nidx)); 28083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28094dcbc457SBarry Smith } 281017ab2063SBarry Smith 2811ba38deedSJacob Faibussowitsch static PetscErrorCode MatPermute_SeqAIJ(Mat A, IS rowp, IS colp, Mat *B) 2812d71ae5a4SJacob Faibussowitsch { 28130513a670SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 28143b98c0a2SBarry Smith PetscInt i, nz = 0, m = A->rmap->n, n = A->cmap->n; 28155d0c19d7SBarry Smith const PetscInt *row, *col; 28165d0c19d7SBarry Smith PetscInt *cnew, j, *lens; 281756cd22aeSBarry Smith IS icolp, irowp; 28180298fd71SBarry Smith PetscInt *cwork = NULL; 28190298fd71SBarry Smith PetscScalar *vwork = NULL; 28200513a670SBarry Smith 28213a40ed3dSBarry Smith PetscFunctionBegin; 28229566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rowp, PETSC_DECIDE, &irowp)); 28239566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irowp, &row)); 28249566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(colp, PETSC_DECIDE, &icolp)); 28259566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icolp, &col)); 28260513a670SBarry Smith 28270513a670SBarry Smith /* determine lengths of permuted rows */ 28289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &lens)); 28292205254eSKarl Rupp for (i = 0; i < m; i++) lens[row[i]] = a->i[i + 1] - a->i[i]; 28309566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 28319566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, m, n, m, n)); 28329566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(*B, A, A)); 28339566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, ((PetscObject)A)->type_name)); 28349566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*B, 0, lens)); 28359566063dSJacob Faibussowitsch PetscCall(PetscFree(lens)); 28360513a670SBarry Smith 28379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &cnew)); 28380513a670SBarry Smith for (i = 0; i < m; i++) { 28399566063dSJacob Faibussowitsch PetscCall(MatGetRow_SeqAIJ(A, i, &nz, &cwork, &vwork)); 28402205254eSKarl Rupp for (j = 0; j < nz; j++) cnew[j] = col[cwork[j]]; 28419566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(*B, 1, &row[i], nz, cnew, vwork, INSERT_VALUES)); 28429566063dSJacob Faibussowitsch PetscCall(MatRestoreRow_SeqAIJ(A, i, &nz, &cwork, &vwork)); 28430513a670SBarry Smith } 28449566063dSJacob Faibussowitsch PetscCall(PetscFree(cnew)); 28452205254eSKarl Rupp 28463c7d62e4SBarry Smith (*B)->assembled = PETSC_FALSE; 28472205254eSKarl Rupp 28488c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 28499566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(*B, A->boundtocpu)); 28509fe5e383SStefano Zampini #endif 28519566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 28529566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 28539566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irowp, &row)); 28549566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icolp, &col)); 28559566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irowp)); 28569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icolp)); 285748a46eb9SPierre Jolivet if (rowp == colp) PetscCall(MatPropagateSymmetryOptions(A, *B)); 28583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28590513a670SBarry Smith } 28600513a670SBarry Smith 2861d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_SeqAIJ(Mat A, Mat B, MatStructure str) 2862d71ae5a4SJacob Faibussowitsch { 2863cb5b572fSBarry Smith PetscFunctionBegin; 286433f4a19fSKris Buschelman /* If the two matrices have the same copy implementation, use fast copy. */ 286533f4a19fSKris Buschelman if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) { 2866be6bf707SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2867be6bf707SBarry Smith Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 28682e5835c6SStefano Zampini const PetscScalar *aa; 28693ac85a22SJunchao Zhang PetscScalar *bb; 2870be6bf707SBarry Smith 28719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 28723ac85a22SJunchao Zhang PetscCall(MatSeqAIJGetArrayWrite(B, &bb)); 28733ac85a22SJunchao Zhang 287408401ef6SPierre Jolivet PetscCheck(a->i[A->rmap->n] == b->i[B->rmap->n], PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of nonzeros in two matrices are different %" PetscInt_FMT " != %" PetscInt_FMT, a->i[A->rmap->n], b->i[B->rmap->n]); 28753ac85a22SJunchao Zhang PetscCall(PetscArraycpy(bb, aa, a->i[A->rmap->n])); 28769566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 28779566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 28783ac85a22SJunchao Zhang PetscCall(MatSeqAIJRestoreArrayWrite(B, &bb)); 2879cb5b572fSBarry Smith } else { 28809566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 2881cb5b572fSBarry Smith } 28823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2883cb5b572fSBarry Smith } 2884cb5b572fSBarry Smith 2885d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A, PetscScalar *array[]) 2886d71ae5a4SJacob Faibussowitsch { 28876c0721eeSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 28886e111a19SKarl Rupp 28896c0721eeSBarry Smith PetscFunctionBegin; 28906c0721eeSBarry Smith *array = a->a; 28913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28926c0721eeSBarry Smith } 28936c0721eeSBarry Smith 2894d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A, PetscScalar *array[]) 2895d71ae5a4SJacob Faibussowitsch { 28966c0721eeSBarry Smith PetscFunctionBegin; 2897f38c1e66SStefano Zampini *array = NULL; 28983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28996c0721eeSBarry Smith } 2900273d9f13SBarry Smith 29018229c054SShri Abhyankar /* 29028229c054SShri Abhyankar Computes the number of nonzeros per row needed for preallocation when X and Y 29038229c054SShri Abhyankar have different nonzero structure. 29048229c054SShri Abhyankar */ 2905d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m, const PetscInt *xi, const PetscInt *xj, const PetscInt *yi, const PetscInt *yj, PetscInt *nnz) 2906d71ae5a4SJacob Faibussowitsch { 2907b264fe52SHong Zhang PetscInt i, j, k, nzx, nzy; 2908ec7775f6SShri Abhyankar 2909ec7775f6SShri Abhyankar PetscFunctionBegin; 2910ec7775f6SShri Abhyankar /* Set the number of nonzeros in the new matrix */ 2911ec7775f6SShri Abhyankar for (i = 0; i < m; i++) { 29128e3a54c0SPierre Jolivet const PetscInt *xjj = PetscSafePointerPlusOffset(xj, xi[i]), *yjj = PetscSafePointerPlusOffset(yj, yi[i]); 2913b264fe52SHong Zhang nzx = xi[i + 1] - xi[i]; 2914b264fe52SHong Zhang nzy = yi[i + 1] - yi[i]; 29158af7cee1SJed Brown nnz[i] = 0; 29168af7cee1SJed Brown for (j = 0, k = 0; j < nzx; j++) { /* Point in X */ 2917b264fe52SHong Zhang for (; k < nzy && yjj[k] < xjj[j]; k++) nnz[i]++; /* Catch up to X */ 2918b264fe52SHong Zhang if (k < nzy && yjj[k] == xjj[j]) k++; /* Skip duplicate */ 29198af7cee1SJed Brown nnz[i]++; 29208af7cee1SJed Brown } 29218af7cee1SJed Brown for (; k < nzy; k++) nnz[i]++; 2922ec7775f6SShri Abhyankar } 29233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2924ec7775f6SShri Abhyankar } 2925ec7775f6SShri Abhyankar 2926d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y, Mat X, PetscInt *nnz) 2927d71ae5a4SJacob Faibussowitsch { 2928b264fe52SHong Zhang PetscInt m = Y->rmap->N; 2929b264fe52SHong Zhang Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data; 2930b264fe52SHong Zhang Mat_SeqAIJ *y = (Mat_SeqAIJ *)Y->data; 2931b264fe52SHong Zhang 2932b264fe52SHong Zhang PetscFunctionBegin; 2933b264fe52SHong Zhang /* Set the number of nonzeros in the new matrix */ 29349566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqX_private(m, x->i, x->j, y->i, y->j, nnz)); 29353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2936b264fe52SHong Zhang } 2937b264fe52SHong Zhang 2938d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_SeqAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str) 2939d71ae5a4SJacob Faibussowitsch { 2940ac90fabeSBarry Smith Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data, *y = (Mat_SeqAIJ *)Y->data; 2941ac90fabeSBarry Smith 2942ac90fabeSBarry Smith PetscFunctionBegin; 2943134adf20SPierre Jolivet if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) { 2944134adf20SPierre Jolivet PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE; 2945134adf20SPierre Jolivet if (e) { 29469566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->i, y->i, Y->rmap->n + 1, &e)); 294781fa06acSBarry Smith if (e) { 29489566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->j, y->j, y->nz, &e)); 2949134adf20SPierre Jolivet if (e) str = SAME_NONZERO_PATTERN; 295081fa06acSBarry Smith } 295181fa06acSBarry Smith } 295254c59aa7SJacob Faibussowitsch if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN"); 295381fa06acSBarry Smith } 2954ac90fabeSBarry Smith if (str == SAME_NONZERO_PATTERN) { 29552e5835c6SStefano Zampini const PetscScalar *xa; 29562e5835c6SStefano Zampini PetscScalar *ya, alpha = a; 295781fa06acSBarry Smith PetscBLASInt one = 1, bnz; 295881fa06acSBarry Smith 29599566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(x->nz, &bnz)); 29609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Y, &ya)); 29619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(X, &xa)); 2962792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, xa, &one, ya, &one)); 29639566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(X, &xa)); 29649566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Y, &ya)); 29659566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * bnz)); 29669566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 2967ab784542SHong Zhang } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 29689566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 2969ac90fabeSBarry Smith } else { 29708229c054SShri Abhyankar Mat B; 29718229c054SShri Abhyankar PetscInt *nnz; 29729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Y->rmap->N, &nnz)); 29739566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B)); 29749566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name)); 29759566063dSJacob Faibussowitsch PetscCall(MatSetLayouts(B, Y->rmap, Y->cmap)); 29769566063dSJacob Faibussowitsch PetscCall(MatSetType(B, ((PetscObject)Y)->type_name)); 29779566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqAIJ(Y, X, nnz)); 29789566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz)); 29799566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 29809566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 29819bb234a9SBarry Smith PetscCall(MatSeqAIJCheckInode(Y)); 29829566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 2983ac90fabeSBarry Smith } 29843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2985ac90fabeSBarry Smith } 2986ac90fabeSBarry Smith 2987d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat) 2988d71ae5a4SJacob Faibussowitsch { 2989354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX) 2990354c94deSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2991354c94deSBarry Smith PetscInt i, nz; 2992354c94deSBarry Smith PetscScalar *a; 2993354c94deSBarry Smith 2994354c94deSBarry Smith PetscFunctionBegin; 2995354c94deSBarry Smith nz = aij->nz; 29969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(mat, &a)); 29972205254eSKarl Rupp for (i = 0; i < nz; i++) a[i] = PetscConj(a[i]); 29989566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(mat, &a)); 2999354c94deSBarry Smith #else 3000354c94deSBarry Smith PetscFunctionBegin; 3001354c94deSBarry Smith #endif 30023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3003354c94deSBarry Smith } 3004354c94deSBarry Smith 3005ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[]) 3006d71ae5a4SJacob Faibussowitsch { 3007e34fafa9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3008d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 3009e34fafa9SBarry Smith PetscReal atmp; 3010985db425SBarry Smith PetscScalar *x; 3011ce496241SStefano Zampini const MatScalar *aa, *av; 3012e34fafa9SBarry Smith 3013e34fafa9SBarry Smith PetscFunctionBegin; 301428b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 30159566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3016ce496241SStefano Zampini aa = av; 3017e34fafa9SBarry Smith ai = a->i; 3018e34fafa9SBarry Smith aj = a->j; 3019e34fafa9SBarry Smith 30209566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 30219566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 302208401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3023e34fafa9SBarry Smith for (i = 0; i < m; i++) { 30249371c9d4SSatish Balay ncols = ai[1] - ai[0]; 30259371c9d4SSatish Balay ai++; 302662e5df07SMark Adams x[i] = 0; 3027e34fafa9SBarry Smith for (j = 0; j < ncols; j++) { 3028985db425SBarry Smith atmp = PetscAbsScalar(*aa); 30299371c9d4SSatish Balay if (PetscAbsScalar(x[i]) < atmp) { 30309371c9d4SSatish Balay x[i] = atmp; 30319371c9d4SSatish Balay if (idx) idx[i] = *aj; 30329371c9d4SSatish Balay } 30339371c9d4SSatish Balay aa++; 30349371c9d4SSatish Balay aj++; 3035985db425SBarry Smith } 3036985db425SBarry Smith } 30379566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 30389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 30393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3040985db425SBarry Smith } 3041985db425SBarry Smith 3042eede4a3fSMark Adams static PetscErrorCode MatGetRowSumAbs_SeqAIJ(Mat A, Vec v) 3043eede4a3fSMark Adams { 3044eede4a3fSMark Adams Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3045eede4a3fSMark Adams PetscInt i, j, m = A->rmap->n, *ai, ncols, n; 3046eede4a3fSMark Adams PetscScalar *x; 3047eede4a3fSMark Adams const MatScalar *aa, *av; 3048eede4a3fSMark Adams 3049eede4a3fSMark Adams PetscFunctionBegin; 3050eede4a3fSMark Adams PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3051eede4a3fSMark Adams PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3052eede4a3fSMark Adams aa = av; 3053eede4a3fSMark Adams ai = a->i; 3054eede4a3fSMark Adams 3055eede4a3fSMark Adams PetscCall(VecGetArrayWrite(v, &x)); 3056eede4a3fSMark Adams PetscCall(VecGetLocalSize(v, &n)); 3057eede4a3fSMark Adams PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3058eede4a3fSMark Adams for (i = 0; i < m; i++) { 3059eede4a3fSMark Adams ncols = ai[1] - ai[0]; 3060eede4a3fSMark Adams ai++; 306162e5df07SMark Adams x[i] = 0; 3062eede4a3fSMark Adams for (j = 0; j < ncols; j++) { 3063eede4a3fSMark Adams x[i] += PetscAbsScalar(*aa); 3064eede4a3fSMark Adams aa++; 3065eede4a3fSMark Adams } 3066eede4a3fSMark Adams } 3067eede4a3fSMark Adams PetscCall(VecRestoreArrayWrite(v, &x)); 3068eede4a3fSMark Adams PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3069eede4a3fSMark Adams PetscFunctionReturn(PETSC_SUCCESS); 3070eede4a3fSMark Adams } 3071eede4a3fSMark Adams 3072ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetRowMax_SeqAIJ(Mat A, Vec v, PetscInt idx[]) 3073d71ae5a4SJacob Faibussowitsch { 3074985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3075d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 3076985db425SBarry Smith PetscScalar *x; 3077ce496241SStefano Zampini const MatScalar *aa, *av; 3078985db425SBarry Smith 3079985db425SBarry Smith PetscFunctionBegin; 308028b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 30819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3082ce496241SStefano Zampini aa = av; 3083985db425SBarry Smith ai = a->i; 3084985db425SBarry Smith aj = a->j; 3085985db425SBarry Smith 30869566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 30879566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 308808401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3089985db425SBarry Smith for (i = 0; i < m; i++) { 30909371c9d4SSatish Balay ncols = ai[1] - ai[0]; 30919371c9d4SSatish Balay ai++; 3092d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 30939371c9d4SSatish Balay x[i] = *aa; 30949371c9d4SSatish Balay if (idx) idx[i] = 0; 3095985db425SBarry Smith } else { /* row is sparse so already KNOW maximum is 0.0 or higher */ 3096985db425SBarry Smith x[i] = 0.0; 3097985db425SBarry Smith if (idx) { 3098985db425SBarry Smith for (j = 0; j < ncols; j++) { /* find first implicit 0.0 in the row */ 3099985db425SBarry Smith if (aj[j] > j) { 3100985db425SBarry Smith idx[i] = j; 3101985db425SBarry Smith break; 3102985db425SBarry Smith } 3103985db425SBarry Smith } 31041a254869SHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 31051a254869SHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3106985db425SBarry Smith } 3107985db425SBarry Smith } 3108985db425SBarry Smith for (j = 0; j < ncols; j++) { 31099371c9d4SSatish Balay if (PetscRealPart(x[i]) < PetscRealPart(*aa)) { 31109371c9d4SSatish Balay x[i] = *aa; 31119371c9d4SSatish Balay if (idx) idx[i] = *aj; 31129371c9d4SSatish Balay } 31139371c9d4SSatish Balay aa++; 31149371c9d4SSatish Balay aj++; 3115985db425SBarry Smith } 3116985db425SBarry Smith } 31179566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 31189566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 31193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3120985db425SBarry Smith } 3121985db425SBarry Smith 3122ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[]) 3123d71ae5a4SJacob Faibussowitsch { 3124c87e5d42SMatthew Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3125c87e5d42SMatthew Knepley PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 3126ce496241SStefano Zampini PetscScalar *x; 3127ce496241SStefano Zampini const MatScalar *aa, *av; 3128c87e5d42SMatthew Knepley 3129c87e5d42SMatthew Knepley PetscFunctionBegin; 31309566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3131ce496241SStefano Zampini aa = av; 3132c87e5d42SMatthew Knepley ai = a->i; 3133c87e5d42SMatthew Knepley aj = a->j; 3134c87e5d42SMatthew Knepley 31359566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 31369566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 313708401ef6SPierre Jolivet PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n); 3138c87e5d42SMatthew Knepley for (i = 0; i < m; i++) { 31399371c9d4SSatish Balay ncols = ai[1] - ai[0]; 31409371c9d4SSatish Balay ai++; 3141f07e67edSHong Zhang if (ncols == A->cmap->n) { /* row is dense */ 31429371c9d4SSatish Balay x[i] = *aa; 31439371c9d4SSatish Balay if (idx) idx[i] = 0; 3144f07e67edSHong Zhang } else { /* row is sparse so already KNOW minimum is 0.0 or higher */ 3145f07e67edSHong Zhang x[i] = 0.0; 3146f07e67edSHong Zhang if (idx) { /* find first implicit 0.0 in the row */ 3147289a08f5SMatthew Knepley for (j = 0; j < ncols; j++) { 3148f07e67edSHong Zhang if (aj[j] > j) { 3149f07e67edSHong Zhang idx[i] = j; 31502205254eSKarl Rupp break; 31512205254eSKarl Rupp } 3152289a08f5SMatthew Knepley } 3153f07e67edSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3154f07e67edSHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3155f07e67edSHong Zhang } 3156289a08f5SMatthew Knepley } 3157c87e5d42SMatthew Knepley for (j = 0; j < ncols; j++) { 31589371c9d4SSatish Balay if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) { 31599371c9d4SSatish Balay x[i] = *aa; 31609371c9d4SSatish Balay if (idx) idx[i] = *aj; 31619371c9d4SSatish Balay } 31629371c9d4SSatish Balay aa++; 31639371c9d4SSatish Balay aj++; 3164c87e5d42SMatthew Knepley } 3165c87e5d42SMatthew Knepley } 31669566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 31679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 31683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3169c87e5d42SMatthew Knepley } 3170c87e5d42SMatthew Knepley 3171ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetRowMin_SeqAIJ(Mat A, Vec v, PetscInt idx[]) 3172d71ae5a4SJacob Faibussowitsch { 3173985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3174d9ca1df4SBarry Smith PetscInt i, j, m = A->rmap->n, ncols, n; 3175d9ca1df4SBarry Smith const PetscInt *ai, *aj; 3176985db425SBarry Smith PetscScalar *x; 3177ce496241SStefano Zampini const MatScalar *aa, *av; 3178985db425SBarry Smith 3179985db425SBarry Smith PetscFunctionBegin; 318028b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 31819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3182ce496241SStefano Zampini aa = av; 3183985db425SBarry Smith ai = a->i; 3184985db425SBarry Smith aj = a->j; 3185985db425SBarry Smith 31869566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 31879566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 318808401ef6SPierre Jolivet PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3189985db425SBarry Smith for (i = 0; i < m; i++) { 31909371c9d4SSatish Balay ncols = ai[1] - ai[0]; 31919371c9d4SSatish Balay ai++; 3192d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 31939371c9d4SSatish Balay x[i] = *aa; 31949371c9d4SSatish Balay if (idx) idx[i] = 0; 3195985db425SBarry Smith } else { /* row is sparse so already KNOW minimum is 0.0 or lower */ 3196985db425SBarry Smith x[i] = 0.0; 3197985db425SBarry Smith if (idx) { /* find first implicit 0.0 in the row */ 3198985db425SBarry Smith for (j = 0; j < ncols; j++) { 3199985db425SBarry Smith if (aj[j] > j) { 3200985db425SBarry Smith idx[i] = j; 3201985db425SBarry Smith break; 3202985db425SBarry Smith } 3203985db425SBarry Smith } 3204fa213d2fSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3205fa213d2fSHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3206985db425SBarry Smith } 3207985db425SBarry Smith } 3208985db425SBarry Smith for (j = 0; j < ncols; j++) { 32099371c9d4SSatish Balay if (PetscRealPart(x[i]) > PetscRealPart(*aa)) { 32109371c9d4SSatish Balay x[i] = *aa; 32119371c9d4SSatish Balay if (idx) idx[i] = *aj; 32129371c9d4SSatish Balay } 32139371c9d4SSatish Balay aa++; 32149371c9d4SSatish Balay aj++; 3215e34fafa9SBarry Smith } 3216e34fafa9SBarry Smith } 32179566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 32189566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 32193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3220e34fafa9SBarry Smith } 3221bbead8a2SBarry Smith 3222ba38deedSJacob Faibussowitsch static PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A, const PetscScalar **values) 3223d71ae5a4SJacob Faibussowitsch { 3224bbead8a2SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 322558b7e2c1SStefano Zampini PetscInt i, bs = A->rmap->bs, mbs = A->rmap->n / bs, ipvt[5], bs2 = bs * bs, *v_pivots, ij[7], *IJ, j; 3226bbead8a2SBarry Smith MatScalar *diag, work[25], *v_work; 32270da83c2eSBarry Smith const PetscReal shift = 0.0; 32281a9391e3SHong Zhang PetscBool allowzeropivot, zeropivotdetected = PETSC_FALSE; 3229bbead8a2SBarry Smith 3230bbead8a2SBarry Smith PetscFunctionBegin; 3231a455e926SHong Zhang allowzeropivot = PetscNot(A->erroriffailure); 32324a0d0026SBarry Smith if (a->ibdiagvalid) { 32334a0d0026SBarry Smith if (values) *values = a->ibdiag; 32343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32354a0d0026SBarry Smith } 32363a7d0413SPierre Jolivet if (!a->ibdiag) PetscCall(PetscMalloc1(bs2 * mbs, &a->ibdiag)); 3237bbead8a2SBarry Smith diag = a->ibdiag; 3238bbead8a2SBarry Smith if (values) *values = a->ibdiag; 3239bbead8a2SBarry Smith /* factor and invert each block */ 3240bbead8a2SBarry Smith switch (bs) { 3241bbead8a2SBarry Smith case 1: 3242bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32439566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 1, &i, 1, &i, diag + i)); 3244ec1892c8SHong Zhang if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) { 3245966bd95aSPierre Jolivet PetscCheck(allowzeropivot, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g", i, (double)PetscAbsScalar(diag[i]), (double)PETSC_MACHINE_EPSILON); 32467b6c816cSBarry Smith A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32477b6c816cSBarry Smith A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]); 32487b6c816cSBarry Smith A->factorerror_zeropivot_row = i; 32499566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n", i, (double)PetscAbsScalar(diag[i]), (double)PETSC_MACHINE_EPSILON)); 3250ec1892c8SHong Zhang } 3251bbead8a2SBarry Smith diag[i] = (PetscScalar)1.0 / (diag[i] + shift); 3252bbead8a2SBarry Smith } 3253bbead8a2SBarry Smith break; 3254bbead8a2SBarry Smith case 2: 3255bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32569371c9d4SSatish Balay ij[0] = 2 * i; 32579371c9d4SSatish Balay ij[1] = 2 * i + 1; 32589566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 2, ij, 2, ij, diag)); 32599566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected)); 32607b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32619566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_2(diag)); 3262bbead8a2SBarry Smith diag += 4; 3263bbead8a2SBarry Smith } 3264bbead8a2SBarry Smith break; 3265bbead8a2SBarry Smith case 3: 3266bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32679371c9d4SSatish Balay ij[0] = 3 * i; 32689371c9d4SSatish Balay ij[1] = 3 * i + 1; 32699371c9d4SSatish Balay ij[2] = 3 * i + 2; 32709566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 3, ij, 3, ij, diag)); 32719566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected)); 32727b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32739566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_3(diag)); 3274bbead8a2SBarry Smith diag += 9; 3275bbead8a2SBarry Smith } 3276bbead8a2SBarry Smith break; 3277bbead8a2SBarry Smith case 4: 3278bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32799371c9d4SSatish Balay ij[0] = 4 * i; 32809371c9d4SSatish Balay ij[1] = 4 * i + 1; 32819371c9d4SSatish Balay ij[2] = 4 * i + 2; 32829371c9d4SSatish Balay ij[3] = 4 * i + 3; 32839566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 4, ij, 4, ij, diag)); 32849566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected)); 32857b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32869566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_4(diag)); 3287bbead8a2SBarry Smith diag += 16; 3288bbead8a2SBarry Smith } 3289bbead8a2SBarry Smith break; 3290bbead8a2SBarry Smith case 5: 3291bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32929371c9d4SSatish Balay ij[0] = 5 * i; 32939371c9d4SSatish Balay ij[1] = 5 * i + 1; 32949371c9d4SSatish Balay ij[2] = 5 * i + 2; 32959371c9d4SSatish Balay ij[3] = 5 * i + 3; 32969371c9d4SSatish Balay ij[4] = 5 * i + 4; 32979566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 5, ij, 5, ij, diag)); 32989566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected)); 32997b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33009566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_5(diag)); 3301bbead8a2SBarry Smith diag += 25; 3302bbead8a2SBarry Smith } 3303bbead8a2SBarry Smith break; 3304bbead8a2SBarry Smith case 6: 3305bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 33069371c9d4SSatish Balay ij[0] = 6 * i; 33079371c9d4SSatish Balay ij[1] = 6 * i + 1; 33089371c9d4SSatish Balay ij[2] = 6 * i + 2; 33099371c9d4SSatish Balay ij[3] = 6 * i + 3; 33109371c9d4SSatish Balay ij[4] = 6 * i + 4; 33119371c9d4SSatish Balay ij[5] = 6 * i + 5; 33129566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 6, ij, 6, ij, diag)); 33139566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected)); 33147b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33159566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_6(diag)); 3316bbead8a2SBarry Smith diag += 36; 3317bbead8a2SBarry Smith } 3318bbead8a2SBarry Smith break; 3319bbead8a2SBarry Smith case 7: 3320bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 33219371c9d4SSatish Balay ij[0] = 7 * i; 33229371c9d4SSatish Balay ij[1] = 7 * i + 1; 33239371c9d4SSatish Balay ij[2] = 7 * i + 2; 33249371c9d4SSatish Balay ij[3] = 7 * i + 3; 33259371c9d4SSatish Balay ij[4] = 7 * i + 4; 33269371c9d4SSatish Balay ij[5] = 7 * i + 5; 3327cdd8bf47SJunchao Zhang ij[6] = 7 * i + 6; 33289566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 7, ij, 7, ij, diag)); 33299566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected)); 33307b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33319566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_7(diag)); 3332bbead8a2SBarry Smith diag += 49; 3333bbead8a2SBarry Smith } 3334bbead8a2SBarry Smith break; 3335bbead8a2SBarry Smith default: 33369566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(bs, &v_work, bs, &v_pivots, bs, &IJ)); 3337bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 3338ad540459SPierre Jolivet for (j = 0; j < bs; j++) IJ[j] = bs * i + j; 33399566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, bs, IJ, bs, IJ, diag)); 33409566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A(bs, diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected)); 33417b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33429566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_N(diag, bs)); 3343bbead8a2SBarry Smith diag += bs2; 3344bbead8a2SBarry Smith } 33459566063dSJacob Faibussowitsch PetscCall(PetscFree3(v_work, v_pivots, IJ)); 3346bbead8a2SBarry Smith } 3347bbead8a2SBarry Smith a->ibdiagvalid = PETSC_TRUE; 33483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3349bbead8a2SBarry Smith } 3350bbead8a2SBarry Smith 3351d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetRandom_SeqAIJ(Mat x, PetscRandom rctx) 3352d71ae5a4SJacob Faibussowitsch { 335373a71a0fSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data; 3354fff043a9SJunchao Zhang PetscScalar a, *aa; 335573a71a0fSBarry Smith PetscInt m, n, i, j, col; 335673a71a0fSBarry Smith 335773a71a0fSBarry Smith PetscFunctionBegin; 335873a71a0fSBarry Smith if (!x->assembled) { 33599566063dSJacob Faibussowitsch PetscCall(MatGetSize(x, &m, &n)); 336073a71a0fSBarry Smith for (i = 0; i < m; i++) { 336173a71a0fSBarry Smith for (j = 0; j < aij->imax[i]; j++) { 33629566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx, &a)); 336373a71a0fSBarry Smith col = (PetscInt)(n * PetscRealPart(a)); 33649566063dSJacob Faibussowitsch PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES)); 336573a71a0fSBarry Smith } 336673a71a0fSBarry Smith } 3367e2ce353bSJunchao Zhang } else { 33689566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayWrite(x, &aa)); 33699566063dSJacob Faibussowitsch for (i = 0; i < aij->nz; i++) PetscCall(PetscRandomGetValue(rctx, aa + i)); 33709566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayWrite(x, &aa)); 3371e2ce353bSJunchao Zhang } 33729566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 33739566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 33743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 337573a71a0fSBarry Smith } 337673a71a0fSBarry Smith 3377679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */ 3378d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x, PetscInt low, PetscInt high, PetscRandom rctx) 3379d71ae5a4SJacob Faibussowitsch { 3380679944adSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data; 3381679944adSJunchao Zhang PetscScalar a; 3382679944adSJunchao Zhang PetscInt m, n, i, j, col, nskip; 3383679944adSJunchao Zhang 3384679944adSJunchao Zhang PetscFunctionBegin; 3385679944adSJunchao Zhang nskip = high - low; 33869566063dSJacob Faibussowitsch PetscCall(MatGetSize(x, &m, &n)); 3387679944adSJunchao Zhang n -= nskip; /* shrink number of columns where nonzeros can be set */ 3388679944adSJunchao Zhang for (i = 0; i < m; i++) { 3389679944adSJunchao Zhang for (j = 0; j < aij->imax[i]; j++) { 33909566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx, &a)); 3391679944adSJunchao Zhang col = (PetscInt)(n * PetscRealPart(a)); 3392679944adSJunchao Zhang if (col >= low) col += nskip; /* shift col rightward to skip the hole */ 33939566063dSJacob Faibussowitsch PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES)); 3394679944adSJunchao Zhang } 3395e2ce353bSJunchao Zhang } 33969566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 33979566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 33983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3399679944adSJunchao Zhang } 3400679944adSJunchao Zhang 34010a6ffc59SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ, 3402cb5b572fSBarry Smith MatGetRow_SeqAIJ, 3403cb5b572fSBarry Smith MatRestoreRow_SeqAIJ, 3404cb5b572fSBarry Smith MatMult_SeqAIJ, 340597304618SKris Buschelman /* 4*/ MatMultAdd_SeqAIJ, 34067c922b88SBarry Smith MatMultTranspose_SeqAIJ, 34077c922b88SBarry Smith MatMultTransposeAdd_SeqAIJ, 3408f4259b30SLisandro Dalcin NULL, 3409f4259b30SLisandro Dalcin NULL, 3410f4259b30SLisandro Dalcin NULL, 3411f4259b30SLisandro Dalcin /* 10*/ NULL, 3412cb5b572fSBarry Smith MatLUFactor_SeqAIJ, 3413f4259b30SLisandro Dalcin NULL, 341441f059aeSBarry Smith MatSOR_SeqAIJ, 341591e9d3e2SHong Zhang MatTranspose_SeqAIJ, 341697304618SKris Buschelman /* 15*/ MatGetInfo_SeqAIJ, 3417cb5b572fSBarry Smith MatEqual_SeqAIJ, 3418cb5b572fSBarry Smith MatGetDiagonal_SeqAIJ, 3419cb5b572fSBarry Smith MatDiagonalScale_SeqAIJ, 3420cb5b572fSBarry Smith MatNorm_SeqAIJ, 3421f4259b30SLisandro Dalcin /* 20*/ NULL, 3422cb5b572fSBarry Smith MatAssemblyEnd_SeqAIJ, 3423cb5b572fSBarry Smith MatSetOption_SeqAIJ, 3424cb5b572fSBarry Smith MatZeroEntries_SeqAIJ, 3425d519adbfSMatthew Knepley /* 24*/ MatZeroRows_SeqAIJ, 3426f4259b30SLisandro Dalcin NULL, 3427f4259b30SLisandro Dalcin NULL, 3428f4259b30SLisandro Dalcin NULL, 3429f4259b30SLisandro Dalcin NULL, 343026cec326SBarry Smith /* 29*/ MatSetUp_Seq_Hash, 3431f4259b30SLisandro Dalcin NULL, 3432f4259b30SLisandro Dalcin NULL, 3433f4259b30SLisandro Dalcin NULL, 3434f4259b30SLisandro Dalcin NULL, 3435d519adbfSMatthew Knepley /* 34*/ MatDuplicate_SeqAIJ, 3436f4259b30SLisandro Dalcin NULL, 3437f4259b30SLisandro Dalcin NULL, 3438cb5b572fSBarry Smith MatILUFactor_SeqAIJ, 3439f4259b30SLisandro Dalcin NULL, 3440d519adbfSMatthew Knepley /* 39*/ MatAXPY_SeqAIJ, 34417dae84e0SHong Zhang MatCreateSubMatrices_SeqAIJ, 3442cb5b572fSBarry Smith MatIncreaseOverlap_SeqAIJ, 3443cb5b572fSBarry Smith MatGetValues_SeqAIJ, 3444cb5b572fSBarry Smith MatCopy_SeqAIJ, 3445d519adbfSMatthew Knepley /* 44*/ MatGetRowMax_SeqAIJ, 3446cb5b572fSBarry Smith MatScale_SeqAIJ, 34477d68702bSBarry Smith MatShift_SeqAIJ, 344879299369SBarry Smith MatDiagonalSet_SeqAIJ, 34496e169961SBarry Smith MatZeroRowsColumns_SeqAIJ, 345073a71a0fSBarry Smith /* 49*/ MatSetRandom_SeqAIJ, 34513b2fbd54SBarry Smith MatGetRowIJ_SeqAIJ, 34523b2fbd54SBarry Smith MatRestoreRowIJ_SeqAIJ, 34533b2fbd54SBarry Smith MatGetColumnIJ_SeqAIJ, 3454a93ec695SBarry Smith MatRestoreColumnIJ_SeqAIJ, 345593dfae19SHong Zhang /* 54*/ MatFDColoringCreate_SeqXAIJ, 3456f4259b30SLisandro Dalcin NULL, 3457f4259b30SLisandro Dalcin NULL, 3458cda55fadSBarry Smith MatPermute_SeqAIJ, 3459f4259b30SLisandro Dalcin NULL, 3460f4259b30SLisandro Dalcin /* 59*/ NULL, 3461b9b97703SBarry Smith MatDestroy_SeqAIJ, 3462b9b97703SBarry Smith MatView_SeqAIJ, 3463f4259b30SLisandro Dalcin NULL, 3464f4259b30SLisandro Dalcin NULL, 34658bb0f5c6SPierre Jolivet /* 64*/ MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ, 3466f4259b30SLisandro Dalcin NULL, 3467f4259b30SLisandro Dalcin NULL, 3468f4259b30SLisandro Dalcin NULL, 34698bb0f5c6SPierre Jolivet MatGetRowMaxAbs_SeqAIJ, 34708bb0f5c6SPierre Jolivet /* 69*/ MatGetRowMinAbs_SeqAIJ, 3471f4259b30SLisandro Dalcin NULL, 3472f4259b30SLisandro Dalcin NULL, 34733acb8795SBarry Smith MatFDColoringApply_AIJ, 3474f4259b30SLisandro Dalcin NULL, 34758bb0f5c6SPierre Jolivet /* 74*/ MatFindZeroDiagonals_SeqAIJ, 3476f4259b30SLisandro Dalcin NULL, 3477f4259b30SLisandro Dalcin NULL, 3478f4259b30SLisandro Dalcin NULL, 3479bc011b1eSHong Zhang MatLoad_SeqAIJ, 34808bb0f5c6SPierre Jolivet /* 79*/ NULL, 34818bb0f5c6SPierre Jolivet NULL, 34828bb0f5c6SPierre Jolivet NULL, 34838bb0f5c6SPierre Jolivet NULL, 34848bb0f5c6SPierre Jolivet NULL, 34856cff0a6bSPierre Jolivet /* 84*/ NULL, 348626be0446SHong Zhang MatMatMultNumeric_SeqAIJ_SeqAIJ, 34878bb0f5c6SPierre Jolivet MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy, 3488f4259b30SLisandro Dalcin NULL, 34896fc122caSHong Zhang MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ, 34908bb0f5c6SPierre Jolivet /* 90*/ NULL, 34918bb0f5c6SPierre Jolivet MatProductSetFromOptions_SeqAIJ, 3492f4259b30SLisandro Dalcin NULL, 3493f4259b30SLisandro Dalcin NULL, 349487d4246cSBarry Smith MatConjugate_SeqAIJ, 34958bb0f5c6SPierre Jolivet /* 94*/ NULL, 34968bb0f5c6SPierre Jolivet MatSetValuesRow_SeqAIJ, 349799cafbc1SBarry Smith MatRealPart_SeqAIJ, 3498f5edf698SHong Zhang MatImaginaryPart_SeqAIJ, 3499f4259b30SLisandro Dalcin NULL, 35008bb0f5c6SPierre Jolivet /* 99*/ NULL, 35018bb0f5c6SPierre Jolivet MatMatSolve_SeqAIJ, 3502f4259b30SLisandro Dalcin NULL, 35032af78befSBarry Smith MatGetRowMin_SeqAIJ, 3504f4259b30SLisandro Dalcin NULL, 3505*421480d9SBarry Smith /*104*/ NULL, 3506f4259b30SLisandro Dalcin NULL, 3507f4259b30SLisandro Dalcin NULL, 3508f4259b30SLisandro Dalcin NULL, 3509f4259b30SLisandro Dalcin NULL, 35108bb0f5c6SPierre Jolivet /*109*/ NULL, 3511f4259b30SLisandro Dalcin NULL, 3512f4259b30SLisandro Dalcin NULL, 3513f4259b30SLisandro Dalcin NULL, 3514*421480d9SBarry Smith MatGetMultiProcBlock_SeqAIJ, 3515*421480d9SBarry Smith /*114*/ MatFindNonzeroRows_SeqAIJ, 3516a873a8cdSSam Reynolds MatGetColumnReductions_SeqAIJ, 351737868618SMatthew G Knepley MatInvertBlockDiagonal_SeqAIJ, 35180da83c2eSBarry Smith MatInvertVariableBlockDiagonal_SeqAIJ, 3519f4259b30SLisandro Dalcin NULL, 3520*421480d9SBarry Smith /*119*/ NULL, 3521f4259b30SLisandro Dalcin NULL, 352275648e8dSHong Zhang MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ, 3523b9af6bddSHong Zhang MatTransposeColoringCreate_SeqAIJ, 3524*421480d9SBarry Smith MatTransColoringApplySpToDen_SeqAIJ, 3525*421480d9SBarry Smith /*124*/ MatTransColoringApplyDenToSp_SeqAIJ, 35263964eb88SJed Brown MatRARtNumeric_SeqAIJ_SeqAIJ, 35278bb0f5c6SPierre Jolivet NULL, 35288bb0f5c6SPierre Jolivet NULL, 3529*421480d9SBarry Smith MatFDColoringSetUp_SeqXAIJ, 3530*421480d9SBarry Smith /*129*/ MatFindOffBlockDiagonalEntries_SeqAIJ, 35318bb0f5c6SPierre Jolivet MatCreateMPIMatConcatenateSeqMat_SeqAIJ, 35328bb0f5c6SPierre Jolivet MatDestroySubMatrices_SeqAIJ, 35338bb0f5c6SPierre Jolivet NULL, 3534*421480d9SBarry Smith NULL, 3535*421480d9SBarry Smith /*134*/ MatCreateGraph_Simple_AIJ, 35368bb0f5c6SPierre Jolivet MatTransposeSymbolic_SeqAIJ, 35378bb0f5c6SPierre Jolivet MatEliminateZeros_SeqAIJ, 35388bb0f5c6SPierre Jolivet MatGetRowSumAbs_SeqAIJ, 3539f4259b30SLisandro Dalcin NULL, 3540*421480d9SBarry Smith /*139*/ NULL, 3541f4259b30SLisandro Dalcin NULL, 354203db1824SAlex Lindsay MatCopyHashToXAIJ_Seq_Hash, 3543c2be7ffeSStefano Zampini NULL, 354403db1824SAlex Lindsay NULL}; 354517ab2063SBarry Smith 3546ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat, PetscInt *indices) 3547d71ae5a4SJacob Faibussowitsch { 3548bef8e0ddSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 354997f1f81fSBarry Smith PetscInt i, nz, n; 3550bef8e0ddSBarry Smith 3551bef8e0ddSBarry Smith PetscFunctionBegin; 3552bef8e0ddSBarry Smith nz = aij->maxnz; 3553d0f46423SBarry Smith n = mat->rmap->n; 3554ad540459SPierre Jolivet for (i = 0; i < nz; i++) aij->j[i] = indices[i]; 3555bef8e0ddSBarry Smith aij->nz = nz; 3556ad540459SPierre Jolivet for (i = 0; i < n; i++) aij->ilen[i] = aij->imax[i]; 35573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3558bef8e0ddSBarry Smith } 3559bef8e0ddSBarry Smith 3560a3bb6f32SFande Kong /* 3561ddea5d60SJunchao Zhang * Given a sparse matrix with global column indices, compact it by using a local column space. 3562ddea5d60SJunchao Zhang * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable() 3563ddea5d60SJunchao Zhang */ 3564d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping) 3565d71ae5a4SJacob Faibussowitsch { 3566a3bb6f32SFande Kong Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3567eec179cfSJacob Faibussowitsch PetscHMapI gid1_lid1; 3568eec179cfSJacob Faibussowitsch PetscHashIter tpos; 356925b670f0SStefano Zampini PetscInt gid, lid, i, ec, nz = aij->nz; 357025b670f0SStefano Zampini PetscInt *garray, *jj = aij->j; 3571a3bb6f32SFande Kong 3572a3bb6f32SFande Kong PetscFunctionBegin; 3573a3bb6f32SFande Kong PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 35744f572ea9SToby Isaac PetscAssertPointer(mapping, 2); 3575a3bb6f32SFande Kong /* use a table */ 3576eec179cfSJacob Faibussowitsch PetscCall(PetscHMapICreateWithSize(mat->rmap->n, &gid1_lid1)); 3577a3bb6f32SFande Kong ec = 0; 357825b670f0SStefano Zampini for (i = 0; i < nz; i++) { 357925b670f0SStefano Zampini PetscInt data, gid1 = jj[i] + 1; 3580eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIGetWithDefault(gid1_lid1, gid1, 0, &data)); 3581a3bb6f32SFande Kong if (!data) { 3582a3bb6f32SFande Kong /* one based table */ 3583c76ffc5fSJacob Faibussowitsch PetscCall(PetscHMapISet(gid1_lid1, gid1, ++ec)); 3584a3bb6f32SFande Kong } 3585a3bb6f32SFande Kong } 3586a3bb6f32SFande Kong /* form array of columns we need */ 35879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ec, &garray)); 3588eec179cfSJacob Faibussowitsch PetscHashIterBegin(gid1_lid1, tpos); 3589eec179cfSJacob Faibussowitsch while (!PetscHashIterAtEnd(gid1_lid1, tpos)) { 3590eec179cfSJacob Faibussowitsch PetscHashIterGetKey(gid1_lid1, tpos, gid); 3591eec179cfSJacob Faibussowitsch PetscHashIterGetVal(gid1_lid1, tpos, lid); 3592eec179cfSJacob Faibussowitsch PetscHashIterNext(gid1_lid1, tpos); 3593a3bb6f32SFande Kong gid--; 3594a3bb6f32SFande Kong lid--; 3595a3bb6f32SFande Kong garray[lid] = gid; 3596a3bb6f32SFande Kong } 35979566063dSJacob Faibussowitsch PetscCall(PetscSortInt(ec, garray)); /* sort, and rebuild */ 3598eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIClear(gid1_lid1)); 3599c76ffc5fSJacob Faibussowitsch for (i = 0; i < ec; i++) PetscCall(PetscHMapISet(gid1_lid1, garray[i] + 1, i + 1)); 3600a3bb6f32SFande Kong /* compact out the extra columns in B */ 360125b670f0SStefano Zampini for (i = 0; i < nz; i++) { 360225b670f0SStefano Zampini PetscInt gid1 = jj[i] + 1; 3603eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIGetWithDefault(gid1_lid1, gid1, 0, &lid)); 3604a3bb6f32SFande Kong lid--; 360525b670f0SStefano Zampini jj[i] = lid; 3606a3bb6f32SFande Kong } 36079566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&mat->cmap)); 3608eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&gid1_lid1)); 36099566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat), ec, ec, 1, &mat->cmap)); 36109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, mat->cmap->bs, mat->cmap->n, garray, PETSC_OWN_POINTER, mapping)); 36119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*mapping, ISLOCALTOGLOBALMAPPINGHASH)); 36123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3613a3bb6f32SFande Kong } 3614a3bb6f32SFande Kong 3615bef8e0ddSBarry Smith /*@ 3616bef8e0ddSBarry Smith MatSeqAIJSetColumnIndices - Set the column indices for all the rows 3617bef8e0ddSBarry Smith in the matrix. 3618bef8e0ddSBarry Smith 3619bef8e0ddSBarry Smith Input Parameters: 362011a5261eSBarry Smith + mat - the `MATSEQAIJ` matrix 3621bef8e0ddSBarry Smith - indices - the column indices 3622bef8e0ddSBarry Smith 362315091d37SBarry Smith Level: advanced 362415091d37SBarry Smith 3625bef8e0ddSBarry Smith Notes: 3626bef8e0ddSBarry Smith This can be called if you have precomputed the nonzero structure of the 3627bef8e0ddSBarry Smith matrix and want to provide it to the matrix object to improve the performance 362811a5261eSBarry Smith of the `MatSetValues()` operation. 3629bef8e0ddSBarry Smith 3630bef8e0ddSBarry Smith You MUST have set the correct numbers of nonzeros per row in the call to 363111a5261eSBarry Smith `MatCreateSeqAIJ()`, and the columns indices MUST be sorted. 3632bef8e0ddSBarry Smith 363311a5261eSBarry Smith MUST be called before any calls to `MatSetValues()` 3634bef8e0ddSBarry Smith 3635b9617806SBarry Smith The indices should start with zero, not one. 3636b9617806SBarry Smith 36371cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQAIJ` 3638bef8e0ddSBarry Smith @*/ 3639d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat, PetscInt *indices) 3640d71ae5a4SJacob Faibussowitsch { 3641bef8e0ddSBarry Smith PetscFunctionBegin; 36420700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 36434f572ea9SToby Isaac PetscAssertPointer(indices, 2); 3644cac4c232SBarry Smith PetscUseMethod(mat, "MatSeqAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices)); 36453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3646bef8e0ddSBarry Smith } 3647bef8e0ddSBarry Smith 3648ba38deedSJacob Faibussowitsch static PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) 3649d71ae5a4SJacob Faibussowitsch { 3650be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3651d0f46423SBarry Smith size_t nz = aij->i[mat->rmap->n]; 3652be6bf707SBarry Smith 3653be6bf707SBarry Smith PetscFunctionBegin; 365428b400f6SJacob Faibussowitsch PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3655be6bf707SBarry Smith 3656be6bf707SBarry Smith /* allocate space for values if not already there */ 36573a7d0413SPierre Jolivet if (!aij->saved_values) PetscCall(PetscMalloc1(nz + 1, &aij->saved_values)); 3658be6bf707SBarry Smith 3659be6bf707SBarry Smith /* copy values over */ 36609566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz)); 36613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3662be6bf707SBarry Smith } 3663be6bf707SBarry Smith 3664be6bf707SBarry Smith /*@ 366520f4b53cSBarry Smith MatStoreValues - Stashes a copy of the matrix values; this allows reusing of the linear part of a Jacobian, while recomputing only the 3666be6bf707SBarry Smith nonlinear portion. 3667be6bf707SBarry Smith 3668c3339decSBarry Smith Logically Collect 3669be6bf707SBarry Smith 367027430b45SBarry Smith Input Parameter: 367111a5261eSBarry Smith . mat - the matrix (currently only `MATAIJ` matrices support this option) 3672be6bf707SBarry Smith 367315091d37SBarry Smith Level: advanced 367415091d37SBarry Smith 36752920cce0SJacob Faibussowitsch Example Usage: 367627430b45SBarry Smith .vb 36772ef1f0ffSBarry Smith Using SNES 367827430b45SBarry Smith Create Jacobian matrix 367927430b45SBarry Smith Set linear terms into matrix 368027430b45SBarry Smith Apply boundary conditions to matrix, at this time matrix must have 368127430b45SBarry Smith final nonzero structure (i.e. setting the nonlinear terms and applying 368227430b45SBarry Smith boundary conditions again will not change the nonzero structure 368327430b45SBarry Smith MatSetOption(mat, MAT_NEW_NONZERO_LOCATIONS, PETSC_FALSE); 368427430b45SBarry Smith MatStoreValues(mat); 368527430b45SBarry Smith Call SNESSetJacobian() with matrix 368627430b45SBarry Smith In your Jacobian routine 368727430b45SBarry Smith MatRetrieveValues(mat); 368827430b45SBarry Smith Set nonlinear terms in matrix 3689be6bf707SBarry Smith 369027430b45SBarry Smith Without `SNESSolve()`, i.e. when you handle nonlinear solve yourself: 369127430b45SBarry Smith // build linear portion of Jacobian 369227430b45SBarry Smith MatSetOption(mat, MAT_NEW_NONZERO_LOCATIONS, PETSC_FALSE); 369327430b45SBarry Smith MatStoreValues(mat); 369427430b45SBarry Smith loop over nonlinear iterations 369527430b45SBarry Smith MatRetrieveValues(mat); 369627430b45SBarry Smith // call MatSetValues(mat,...) to set nonliner portion of Jacobian 369727430b45SBarry Smith // call MatAssemblyBegin/End() on matrix 369827430b45SBarry Smith Solve linear system with Jacobian 369927430b45SBarry Smith endloop 370027430b45SBarry Smith .ve 3701be6bf707SBarry Smith 3702be6bf707SBarry Smith Notes: 3703da81f932SPierre Jolivet Matrix must already be assembled before calling this routine 370411a5261eSBarry Smith Must set the matrix option `MatSetOption`(mat,`MAT_NEW_NONZERO_LOCATIONS`,`PETSC_FALSE`); before 3705be6bf707SBarry Smith calling this routine. 3706be6bf707SBarry Smith 37070c468ba9SBarry Smith When this is called multiple times it overwrites the previous set of stored values 37080c468ba9SBarry Smith and does not allocated additional space. 37090c468ba9SBarry Smith 3710fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `MatRetrieveValues()` 3711be6bf707SBarry Smith @*/ 3712d71ae5a4SJacob Faibussowitsch PetscErrorCode MatStoreValues(Mat mat) 3713d71ae5a4SJacob Faibussowitsch { 3714be6bf707SBarry Smith PetscFunctionBegin; 37150700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 371628b400f6SJacob Faibussowitsch PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 371728b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3718cac4c232SBarry Smith PetscUseMethod(mat, "MatStoreValues_C", (Mat), (mat)); 37193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3720be6bf707SBarry Smith } 3721be6bf707SBarry Smith 3722ba38deedSJacob Faibussowitsch static PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat) 3723d71ae5a4SJacob Faibussowitsch { 3724be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3725d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->n]; 3726be6bf707SBarry Smith 3727be6bf707SBarry Smith PetscFunctionBegin; 372828b400f6SJacob Faibussowitsch PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 372928b400f6SJacob Faibussowitsch PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first"); 3730be6bf707SBarry Smith /* copy values over */ 37319566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz)); 37323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3733be6bf707SBarry Smith } 3734be6bf707SBarry Smith 3735be6bf707SBarry Smith /*@ 373620f4b53cSBarry Smith MatRetrieveValues - Retrieves the copy of the matrix values that was stored with `MatStoreValues()` 3737be6bf707SBarry Smith 3738c3339decSBarry Smith Logically Collect 3739be6bf707SBarry Smith 37402fe279fdSBarry Smith Input Parameter: 374111a5261eSBarry Smith . mat - the matrix (currently only `MATAIJ` matrices support this option) 3742be6bf707SBarry Smith 374315091d37SBarry Smith Level: advanced 374415091d37SBarry Smith 37451cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatStoreValues()` 3746be6bf707SBarry Smith @*/ 3747d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRetrieveValues(Mat mat) 3748d71ae5a4SJacob Faibussowitsch { 3749be6bf707SBarry Smith PetscFunctionBegin; 37500700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 375128b400f6SJacob Faibussowitsch PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 375228b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3753cac4c232SBarry Smith PetscUseMethod(mat, "MatRetrieveValues_C", (Mat), (mat)); 37543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3755be6bf707SBarry Smith } 3756be6bf707SBarry Smith 37575d83a8b1SBarry Smith /*@ 375811a5261eSBarry Smith MatCreateSeqAIJ - Creates a sparse matrix in `MATSEQAIJ` (compressed row) format 37590d15e28bSLois Curfman McInnes (the default parallel PETSc format). For good matrix assembly performance 376020f4b53cSBarry Smith the user should preallocate the matrix storage by setting the parameter `nz` 376120f4b53cSBarry Smith (or the array `nnz`). 376217ab2063SBarry Smith 3763d083f849SBarry Smith Collective 3764db81eaa0SLois Curfman McInnes 376517ab2063SBarry Smith Input Parameters: 376611a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF` 376717ab2063SBarry Smith . m - number of rows 376817ab2063SBarry Smith . n - number of columns 376917ab2063SBarry Smith . nz - number of nonzeros per row (same for all rows) 377051c19458SBarry Smith - nnz - array containing the number of nonzeros in the various rows 37710298fd71SBarry Smith (possibly different for each row) or NULL 377217ab2063SBarry Smith 377317ab2063SBarry Smith Output Parameter: 3774416022c9SBarry Smith . A - the matrix 377517ab2063SBarry Smith 37762ef1f0ffSBarry Smith Options Database Keys: 37772ef1f0ffSBarry Smith + -mat_no_inode - Do not use inodes 37782ef1f0ffSBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 37792ef1f0ffSBarry Smith 37802ef1f0ffSBarry Smith Level: intermediate 3781175b88e8SBarry Smith 3782b259b22eSLois Curfman McInnes Notes: 378377433607SBarry Smith It is recommend to use `MatCreateFromOptions()` instead of this routine 378477433607SBarry Smith 37852ef1f0ffSBarry Smith If `nnz` is given then `nz` is ignored 378649a6f317SBarry Smith 37872ef1f0ffSBarry Smith The `MATSEQAIJ` format, also called 37882ef1f0ffSBarry Smith compressed row storage, is fully compatible with standard Fortran 37890002213bSLois Curfman McInnes storage. That is, the stored row and column indices can begin at 37902ef1f0ffSBarry Smith either one (as in Fortran) or zero. 379117ab2063SBarry Smith 379220f4b53cSBarry Smith Specify the preallocated storage with either `nz` or `nnz` (not both). 37932ef1f0ffSBarry Smith Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory 379420f4b53cSBarry Smith allocation. 379517ab2063SBarry Smith 3796682d7d0cSBarry Smith By default, this format uses inodes (identical nodes) when possible, to 37974fca80b9SLois Curfman McInnes improve numerical efficiency of matrix-vector products and solves. We 3798682d7d0cSBarry Smith search for consecutive rows with the same nonzero structure, thereby 37996c7ebb05SLois Curfman McInnes reusing matrix information to achieve increased efficiency. 38006c7ebb05SLois Curfman McInnes 38011cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrix Creation](sec_matsparse), `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()` 380217ab2063SBarry Smith @*/ 3803d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A) 3804d71ae5a4SJacob Faibussowitsch { 38053a40ed3dSBarry Smith PetscFunctionBegin; 38069566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 38079566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, m, n)); 38089566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATSEQAIJ)); 38099566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*A, nz, nnz)); 38103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3811273d9f13SBarry Smith } 3812273d9f13SBarry Smith 38135d83a8b1SBarry Smith /*@ 3814273d9f13SBarry Smith MatSeqAIJSetPreallocation - For good matrix assembly performance 3815273d9f13SBarry Smith the user should preallocate the matrix storage by setting the parameter nz 3816273d9f13SBarry Smith (or the array nnz). By setting these parameters accurately, performance 3817273d9f13SBarry Smith during matrix assembly can be increased by more than a factor of 50. 3818273d9f13SBarry Smith 3819d083f849SBarry Smith Collective 3820273d9f13SBarry Smith 3821273d9f13SBarry Smith Input Parameters: 38221c4f3114SJed Brown + B - The matrix 3823273d9f13SBarry Smith . nz - number of nonzeros per row (same for all rows) 3824273d9f13SBarry Smith - nnz - array containing the number of nonzeros in the various rows 38250298fd71SBarry Smith (possibly different for each row) or NULL 3826273d9f13SBarry Smith 38272ef1f0ffSBarry Smith Options Database Keys: 38282ef1f0ffSBarry Smith + -mat_no_inode - Do not use inodes 38292ef1f0ffSBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 38302ef1f0ffSBarry Smith 38312ef1f0ffSBarry Smith Level: intermediate 38322ef1f0ffSBarry Smith 3833273d9f13SBarry Smith Notes: 38342ef1f0ffSBarry Smith If `nnz` is given then `nz` is ignored 383549a6f317SBarry Smith 383611a5261eSBarry Smith The `MATSEQAIJ` format also called 38372ef1f0ffSBarry Smith compressed row storage, is fully compatible with standard Fortran 3838273d9f13SBarry Smith storage. That is, the stored row and column indices can begin at 3839273d9f13SBarry Smith either one (as in Fortran) or zero. See the users' manual for details. 3840273d9f13SBarry Smith 38412ef1f0ffSBarry Smith Specify the preallocated storage with either `nz` or `nnz` (not both). 38422ef1f0ffSBarry Smith Set nz = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory 38432ef1f0ffSBarry Smith allocation. 3844273d9f13SBarry Smith 384511a5261eSBarry Smith You can call `MatGetInfo()` to get information on how effective the preallocation was; 3846aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 3847aa95bbe8SBarry Smith You can also run with the option -info and look for messages with the string 3848aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 3849aa95bbe8SBarry Smith 385011a5261eSBarry Smith Developer Notes: 385111a5261eSBarry Smith Use nz of `MAT_SKIP_ALLOCATION` to not allocate any space for the matrix 3852a96a251dSBarry Smith entries or columns indices 3853a96a251dSBarry Smith 3854273d9f13SBarry Smith By default, this format uses inodes (identical nodes) when possible, to 3855273d9f13SBarry Smith improve numerical efficiency of matrix-vector products and solves. We 3856273d9f13SBarry Smith search for consecutive rows with the same nonzero structure, thereby 3857273d9f13SBarry Smith reusing matrix information to achieve increased efficiency. 3858273d9f13SBarry Smith 38591cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()`, `MatGetInfo()`, 3860db781477SPatrick Sanan `MatSeqAIJSetTotalPreallocation()` 3861273d9f13SBarry Smith @*/ 3862d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetPreallocation(Mat B, PetscInt nz, const PetscInt nnz[]) 3863d71ae5a4SJacob Faibussowitsch { 3864a23d5eceSKris Buschelman PetscFunctionBegin; 38656ba663aaSJed Brown PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 38666ba663aaSJed Brown PetscValidType(B, 1); 3867cac4c232SBarry Smith PetscTryMethod(B, "MatSeqAIJSetPreallocation_C", (Mat, PetscInt, const PetscInt[]), (B, nz, nnz)); 38683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3869a23d5eceSKris Buschelman } 3870a23d5eceSKris Buschelman 3871d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B, PetscInt nz, const PetscInt *nnz) 3872d71ae5a4SJacob Faibussowitsch { 3873ad79cf63SBarry Smith Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 38742576faa2SJed Brown PetscBool skipallocation = PETSC_FALSE, realalloc = PETSC_FALSE; 387597f1f81fSBarry Smith PetscInt i; 3876273d9f13SBarry Smith 3877273d9f13SBarry Smith PetscFunctionBegin; 3878ad79cf63SBarry Smith if (B->hash_active) { 3879aea10558SJacob Faibussowitsch B->ops[0] = b->cops; 3880ad79cf63SBarry Smith PetscCall(PetscHMapIJVDestroy(&b->ht)); 3881ad79cf63SBarry Smith PetscCall(PetscFree(b->dnz)); 3882ad79cf63SBarry Smith B->hash_active = PETSC_FALSE; 3883ad79cf63SBarry Smith } 38842576faa2SJed Brown if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 3885a96a251dSBarry Smith if (nz == MAT_SKIP_ALLOCATION) { 3886c461c341SBarry Smith skipallocation = PETSC_TRUE; 3887c461c341SBarry Smith nz = 0; 3888c461c341SBarry Smith } 38899566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 38909566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 3891899cda47SBarry Smith 3892435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 389308401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz); 38949f0612e4SBarry Smith if (nnz) { 3895d0f46423SBarry Smith for (i = 0; i < B->rmap->n; i++) { 389608401ef6SPierre 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]); 389708401ef6SPierre Jolivet PetscCheck(nnz[i] <= B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nnz cannot be greater than row length: local row %" PetscInt_FMT " value %" PetscInt_FMT " rowlength %" PetscInt_FMT, i, nnz[i], B->cmap->n); 3898b73539f3SBarry Smith } 3899b73539f3SBarry Smith } 3900b73539f3SBarry Smith 3901273d9f13SBarry Smith B->preallocated = PETSC_TRUE; 3902ab93d7beSBarry Smith if (!skipallocation) { 39033a7d0413SPierre Jolivet if (!b->imax) PetscCall(PetscMalloc1(B->rmap->n, &b->imax)); 3904071fcb05SBarry Smith if (!b->ilen) { 3905071fcb05SBarry Smith /* b->ilen will count nonzeros in each row so far. */ 39069566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(B->rmap->n, &b->ilen)); 3907071fcb05SBarry Smith } else { 39089566063dSJacob Faibussowitsch PetscCall(PetscMemzero(b->ilen, B->rmap->n * sizeof(PetscInt))); 39092ee49352SLisandro Dalcin } 3910aa624791SPierre Jolivet if (!b->ipre) PetscCall(PetscMalloc1(B->rmap->n, &b->ipre)); 3911273d9f13SBarry Smith if (!nnz) { 3912435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 3913c62bd62aSJed Brown else if (nz < 0) nz = 1; 39145d2a9ed1SStefano Zampini nz = PetscMin(nz, B->cmap->n); 3915d0f46423SBarry Smith for (i = 0; i < B->rmap->n; i++) b->imax[i] = nz; 3916c43c4a61SBarry Smith PetscCall(PetscIntMultError(nz, B->rmap->n, &nz)); 3917273d9f13SBarry Smith } else { 3918c73702f5SBarry Smith PetscInt64 nz64 = 0; 39199371c9d4SSatish Balay for (i = 0; i < B->rmap->n; i++) { 39209371c9d4SSatish Balay b->imax[i] = nnz[i]; 39219371c9d4SSatish Balay nz64 += nnz[i]; 39229371c9d4SSatish Balay } 39239566063dSJacob Faibussowitsch PetscCall(PetscIntCast(nz64, &nz)); 3924273d9f13SBarry Smith } 3925ab93d7beSBarry Smith 3926273d9f13SBarry Smith /* allocate the matrix space */ 39279566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i)); 39289f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&b->j)); 39299f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(B->rmap->n + 1, sizeof(PetscInt), (void **)&b->i)); 39309f0612e4SBarry Smith b->free_ij = PETSC_TRUE; 3931396832f4SHong Zhang if (B->structure_only) { 39329f0612e4SBarry Smith b->free_a = PETSC_FALSE; 3933396832f4SHong Zhang } else { 39349f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscScalar), (void **)&b->a)); 39359f0612e4SBarry Smith b->free_a = PETSC_TRUE; 3936396832f4SHong Zhang } 3937bfeeae90SHong Zhang b->i[0] = 0; 3938ad540459SPierre Jolivet for (i = 1; i < B->rmap->n + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1]; 3939c461c341SBarry Smith } else { 3940e6b907acSBarry Smith b->free_a = PETSC_FALSE; 3941e6b907acSBarry Smith b->free_ij = PETSC_FALSE; 3942c461c341SBarry Smith } 3943273d9f13SBarry Smith 3944846b4da1SFande Kong if (b->ipre && nnz != b->ipre && b->imax) { 3945846b4da1SFande Kong /* reserve user-requested sparsity */ 39469566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->ipre, b->imax, B->rmap->n)); 3947846b4da1SFande Kong } 3948846b4da1SFande Kong 3949273d9f13SBarry Smith b->nz = 0; 3950273d9f13SBarry Smith b->maxnz = nz; 3951273d9f13SBarry Smith B->info.nz_unneeded = (double)b->maxnz; 39521baa6e33SBarry Smith if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 3953cb7b82ddSBarry Smith B->was_assembled = PETSC_FALSE; 3954cb7b82ddSBarry Smith B->assembled = PETSC_FALSE; 39555519a089SJose E. Roman /* We simply deem preallocation has changed nonzero state. Updating the state 39565519a089SJose E. Roman will give clients (like AIJKokkos) a chance to know something has happened. 39575519a089SJose E. Roman */ 39585519a089SJose E. Roman B->nonzerostate++; 39593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3960273d9f13SBarry Smith } 3961273d9f13SBarry Smith 39624c51d546SAlexander PetscErrorCode MatResetPreallocation_SeqAIJ_Private(Mat A, PetscBool *memoryreset) 3963d71ae5a4SJacob Faibussowitsch { 3964846b4da1SFande Kong Mat_SeqAIJ *a; 3965a5bbaf83SFande Kong PetscInt i; 39661f14be2bSBarry Smith PetscBool skipreset; 3967846b4da1SFande Kong 3968846b4da1SFande Kong PetscFunctionBegin; 3969846b4da1SFande Kong PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 397014d0e64fSAlex Lindsay 39714c51d546SAlexander PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()"); 39724c51d546SAlexander if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 39734c51d546SAlexander 397414d0e64fSAlex Lindsay /* Check local size. If zero, then return */ 39753ba16761SJacob Faibussowitsch if (!A->rmap->n) PetscFunctionReturn(PETSC_SUCCESS); 397614d0e64fSAlex Lindsay 3977846b4da1SFande Kong a = (Mat_SeqAIJ *)A->data; 39782c814fdeSFande Kong /* if no saved info, we error out */ 397928b400f6SJacob Faibussowitsch PetscCheck(a->ipre, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "No saved preallocation info "); 39802c814fdeSFande Kong 39811f14be2bSBarry Smith PetscCheck(a->i && a->imax && a->ilen, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Memory info is incomplete, and cannot reset preallocation "); 39822c814fdeSFande Kong 39831f14be2bSBarry Smith PetscCall(PetscArraycmp(a->ipre, a->ilen, A->rmap->n, &skipreset)); 39844c51d546SAlexander if (skipreset) PetscCall(MatZeroEntries(A)); 39854c51d546SAlexander else { 39869566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->imax, a->ipre, A->rmap->n)); 39879566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(a->ilen, A->rmap->n)); 3988846b4da1SFande Kong a->i[0] = 0; 3989ad540459SPierre Jolivet for (i = 1; i < A->rmap->n + 1; i++) a->i[i] = a->i[i - 1] + a->imax[i - 1]; 3990846b4da1SFande Kong A->preallocated = PETSC_TRUE; 3991846b4da1SFande Kong a->nz = 0; 3992846b4da1SFande Kong a->maxnz = a->i[A->rmap->n]; 3993846b4da1SFande Kong A->info.nz_unneeded = (double)a->maxnz; 3994846b4da1SFande Kong A->was_assembled = PETSC_FALSE; 3995846b4da1SFande Kong A->assembled = PETSC_FALSE; 3996b3a35320SAlex Lindsay A->nonzerostate++; 3997b3a35320SAlex Lindsay /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */ 3998b3a35320SAlex Lindsay PetscCall(PetscObjectStateIncrease((PetscObject)A)); 39991f14be2bSBarry Smith } 40004c51d546SAlexander if (memoryreset) *memoryreset = (PetscBool)!skipreset; 40014c51d546SAlexander PetscFunctionReturn(PETSC_SUCCESS); 40024c51d546SAlexander } 40034c51d546SAlexander 40044c51d546SAlexander static PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A) 40054c51d546SAlexander { 40064c51d546SAlexander PetscFunctionBegin; 40074c51d546SAlexander PetscCall(MatResetPreallocation_SeqAIJ_Private(A, NULL)); 40083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4009846b4da1SFande Kong } 4010846b4da1SFande Kong 401158d36128SBarry Smith /*@ 401211a5261eSBarry Smith MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in `MATSEQAIJ` format. 4013a1661176SMatthew Knepley 4014a1661176SMatthew Knepley Input Parameters: 4015a1661176SMatthew Knepley + B - the matrix 4016d8a51d2aSBarry Smith . i - the indices into `j` for the start of each row (indices start with zero) 4017d8a51d2aSBarry Smith . j - the column indices for each row (indices start with zero) these must be sorted for each row 4018d8a51d2aSBarry Smith - v - optional values in the matrix, use `NULL` if not provided 4019a1661176SMatthew Knepley 4020a1661176SMatthew Knepley Level: developer 4021a1661176SMatthew Knepley 40226a9b8d82SBarry Smith Notes: 40232ef1f0ffSBarry Smith The `i`,`j`,`v` values are COPIED with this routine; to avoid the copy use `MatCreateSeqAIJWithArrays()` 402458d36128SBarry Smith 40256a9b8d82SBarry Smith This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero 40266a9b8d82SBarry Smith structure will be the union of all the previous nonzero structures. 40276a9b8d82SBarry Smith 40286a9b8d82SBarry Smith Developer Notes: 40292ef1f0ffSBarry Smith An optimization could be added to the implementation where it checks if the `i`, and `j` are identical to the current `i` and `j` and 40302ef1f0ffSBarry Smith then just copies the `v` values directly with `PetscMemcpy()`. 40316a9b8d82SBarry Smith 403211a5261eSBarry Smith This routine could also take a `PetscCopyMode` argument to allow sharing the values instead of always copying them. 40336a9b8d82SBarry Smith 4034fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatSeqAIJSetPreallocation()`, `MATSEQAIJ`, `MatResetPreallocation()` 4035a1661176SMatthew Knepley @*/ 4036d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B, const PetscInt i[], const PetscInt j[], const PetscScalar v[]) 4037d71ae5a4SJacob Faibussowitsch { 4038a1661176SMatthew Knepley PetscFunctionBegin; 40390700a824SBarry Smith PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 40406ba663aaSJed Brown PetscValidType(B, 1); 4041cac4c232SBarry Smith PetscTryMethod(B, "MatSeqAIJSetPreallocationCSR_C", (Mat, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, i, j, v)); 40423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4043a1661176SMatthew Knepley } 4044a1661176SMatthew Knepley 4045ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B, const PetscInt Ii[], const PetscInt J[], const PetscScalar v[]) 4046d71ae5a4SJacob Faibussowitsch { 4047a1661176SMatthew Knepley PetscInt i; 4048a1661176SMatthew Knepley PetscInt m, n; 4049a1661176SMatthew Knepley PetscInt nz; 40506a9b8d82SBarry Smith PetscInt *nnz; 4051a1661176SMatthew Knepley 4052a1661176SMatthew Knepley PetscFunctionBegin; 4053aed4548fSBarry Smith PetscCheck(Ii[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]); 4054779a8d59SSatish Balay 40559566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 40569566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 4057779a8d59SSatish Balay 40589566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &m, &n)); 40599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nnz)); 4060a1661176SMatthew Knepley for (i = 0; i < m; i++) { 4061b7940d39SSatish Balay nz = Ii[i + 1] - Ii[i]; 406208401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz); 4063a1661176SMatthew Knepley nnz[i] = nz; 4064a1661176SMatthew Knepley } 40659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz)); 40669566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 4067a1661176SMatthew Knepley 40688e3a54c0SPierre Jolivet for (i = 0; i < m; i++) PetscCall(MatSetValues_SeqAIJ(B, 1, &i, Ii[i + 1] - Ii[i], J + Ii[i], PetscSafePointerPlusOffset(v, Ii[i]), INSERT_VALUES)); 4069a1661176SMatthew Knepley 40709566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 40719566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4072a1661176SMatthew Knepley 40739566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 40743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4075a1661176SMatthew Knepley } 4076a1661176SMatthew Knepley 4077ad7e164aSPierre Jolivet /*@ 40782ef1f0ffSBarry Smith MatSeqAIJKron - Computes `C`, the Kronecker product of `A` and `B`. 4079ad7e164aSPierre Jolivet 4080ad7e164aSPierre Jolivet Input Parameters: 4081ad7e164aSPierre Jolivet + A - left-hand side matrix 4082ad7e164aSPierre Jolivet . B - right-hand side matrix 408311a5261eSBarry Smith - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 4084ad7e164aSPierre Jolivet 4085ad7e164aSPierre Jolivet Output Parameter: 40862ef1f0ffSBarry Smith . C - Kronecker product of `A` and `B` 4087ad7e164aSPierre Jolivet 4088ad7e164aSPierre Jolivet Level: intermediate 4089ad7e164aSPierre Jolivet 409011a5261eSBarry Smith Note: 409111a5261eSBarry Smith `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the product matrix has not changed from that last call to `MatSeqAIJKron()`. 4092ad7e164aSPierre Jolivet 40931cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATKAIJ`, `MatReuse` 4094ad7e164aSPierre Jolivet @*/ 4095d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJKron(Mat A, Mat B, MatReuse reuse, Mat *C) 4096d71ae5a4SJacob Faibussowitsch { 4097ad7e164aSPierre Jolivet PetscFunctionBegin; 4098ad7e164aSPierre Jolivet PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4099ad7e164aSPierre Jolivet PetscValidType(A, 1); 4100ad7e164aSPierre Jolivet PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4101ad7e164aSPierre Jolivet PetscValidType(B, 2); 41024f572ea9SToby Isaac PetscAssertPointer(C, 4); 4103ad7e164aSPierre Jolivet if (reuse == MAT_REUSE_MATRIX) { 4104ad7e164aSPierre Jolivet PetscValidHeaderSpecific(*C, MAT_CLASSID, 4); 4105ad7e164aSPierre Jolivet PetscValidType(*C, 4); 4106ad7e164aSPierre Jolivet } 4107cac4c232SBarry Smith PetscTryMethod(A, "MatSeqAIJKron_C", (Mat, Mat, MatReuse, Mat *), (A, B, reuse, C)); 41083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4109ad7e164aSPierre Jolivet } 4110ad7e164aSPierre Jolivet 4111ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A, Mat B, MatReuse reuse, Mat *C) 4112d71ae5a4SJacob Faibussowitsch { 4113ad7e164aSPierre Jolivet Mat newmat; 4114ad7e164aSPierre Jolivet Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 4115ad7e164aSPierre Jolivet Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 4116ad7e164aSPierre Jolivet PetscScalar *v; 4117fff043a9SJunchao Zhang const PetscScalar *aa, *ba; 4118ad7e164aSPierre Jolivet PetscInt *i, *j, m, n, p, q, nnz = 0, am = A->rmap->n, bm = B->rmap->n, an = A->cmap->n, bn = B->cmap->n; 4119ad7e164aSPierre Jolivet PetscBool flg; 4120ad7e164aSPierre Jolivet 4121ad7e164aSPierre Jolivet PetscFunctionBegin; 412228b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 412328b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 412428b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 412528b400f6SJacob Faibussowitsch PetscCheck(B->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 41269566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATSEQAIJ, &flg)); 412728b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatType %s", ((PetscObject)B)->type_name); 4128aed4548fSBarry Smith PetscCheck(reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatReuse %d", (int)reuse); 4129ad7e164aSPierre Jolivet if (reuse == MAT_INITIAL_MATRIX) { 41309566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(am * bm + 1, &i, a->i[am] * b->i[bm], &j)); 41319566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &newmat)); 41329566063dSJacob Faibussowitsch PetscCall(MatSetSizes(newmat, am * bm, an * bn, am * bm, an * bn)); 41339566063dSJacob Faibussowitsch PetscCall(MatSetType(newmat, MATAIJ)); 4134ad7e164aSPierre Jolivet i[0] = 0; 4135ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4136ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4137ad7e164aSPierre Jolivet i[m * bm + p + 1] = i[m * bm + p] + (a->i[m + 1] - a->i[m]) * (b->i[p + 1] - b->i[p]); 4138ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m + 1]; ++n) { 4139ad540459SPierre Jolivet for (q = b->i[p]; q < b->i[p + 1]; ++q) j[nnz++] = a->j[n] * bn + b->j[q]; 4140ad7e164aSPierre Jolivet } 4141ad7e164aSPierre Jolivet } 4142ad7e164aSPierre Jolivet } 41439566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(newmat, i, j, NULL)); 4144ad7e164aSPierre Jolivet *C = newmat; 41459566063dSJacob Faibussowitsch PetscCall(PetscFree2(i, j)); 4146ad7e164aSPierre Jolivet nnz = 0; 4147ad7e164aSPierre Jolivet } 41489566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(*C, &v)); 41499566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 41509566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &ba)); 4151ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4152ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4153ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m + 1]; ++n) { 4154ad540459SPierre Jolivet for (q = b->i[p]; q < b->i[p + 1]; ++q) v[nnz++] = aa[n] * ba[q]; 4155ad7e164aSPierre Jolivet } 4156ad7e164aSPierre Jolivet } 4157ad7e164aSPierre Jolivet } 41589566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(*C, &v)); 41599566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 41609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &ba)); 41613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4162ad7e164aSPierre Jolivet } 4163ad7e164aSPierre Jolivet 4164c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h> 4165af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h> 4166170fe5c8SBarry Smith 4167170fe5c8SBarry Smith /* 4168170fe5c8SBarry Smith Computes (B'*A')' since computing B*A directly is untenable 4169170fe5c8SBarry Smith 4170170fe5c8SBarry Smith n p p 41712da392ccSBarry Smith [ ] [ ] [ ] 41722da392ccSBarry Smith m [ A ] * n [ B ] = m [ C ] 41732da392ccSBarry Smith [ ] [ ] [ ] 4174170fe5c8SBarry Smith 4175170fe5c8SBarry Smith */ 4176d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A, Mat B, Mat C) 4177d71ae5a4SJacob Faibussowitsch { 4178170fe5c8SBarry Smith Mat_SeqDense *sub_a = (Mat_SeqDense *)A->data; 4179170fe5c8SBarry Smith Mat_SeqAIJ *sub_b = (Mat_SeqAIJ *)B->data; 4180170fe5c8SBarry Smith Mat_SeqDense *sub_c = (Mat_SeqDense *)C->data; 418186214ceeSStefano Zampini PetscInt i, j, n, m, q, p; 4182170fe5c8SBarry Smith const PetscInt *ii, *idx; 4183170fe5c8SBarry Smith const PetscScalar *b, *a, *a_q; 4184170fe5c8SBarry Smith PetscScalar *c, *c_q; 418586214ceeSStefano Zampini PetscInt clda = sub_c->lda; 418686214ceeSStefano Zampini PetscInt alda = sub_a->lda; 4187170fe5c8SBarry Smith 4188170fe5c8SBarry Smith PetscFunctionBegin; 4189d0f46423SBarry Smith m = A->rmap->n; 4190d0f46423SBarry Smith n = A->cmap->n; 4191d0f46423SBarry Smith p = B->cmap->n; 4192170fe5c8SBarry Smith a = sub_a->v; 4193170fe5c8SBarry Smith b = sub_b->a; 4194170fe5c8SBarry Smith c = sub_c->v; 419586214ceeSStefano Zampini if (clda == m) { 41969566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c, m * p)); 419786214ceeSStefano Zampini } else { 419886214ceeSStefano Zampini for (j = 0; j < p; j++) 41999371c9d4SSatish Balay for (i = 0; i < m; i++) c[j * clda + i] = 0.0; 420086214ceeSStefano Zampini } 4201170fe5c8SBarry Smith ii = sub_b->i; 4202170fe5c8SBarry Smith idx = sub_b->j; 4203170fe5c8SBarry Smith for (i = 0; i < n; i++) { 4204170fe5c8SBarry Smith q = ii[i + 1] - ii[i]; 4205170fe5c8SBarry Smith while (q-- > 0) { 420686214ceeSStefano Zampini c_q = c + clda * (*idx); 420786214ceeSStefano Zampini a_q = a + alda * i; 4208854c7f52SBarry Smith PetscKernelAXPY(c_q, *b, a_q, m); 4209170fe5c8SBarry Smith idx++; 4210170fe5c8SBarry Smith b++; 4211170fe5c8SBarry Smith } 4212170fe5c8SBarry Smith } 42133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4214170fe5c8SBarry Smith } 4215170fe5c8SBarry Smith 4216d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A, Mat B, PetscReal fill, Mat C) 4217d71ae5a4SJacob Faibussowitsch { 4218d0f46423SBarry Smith PetscInt m = A->rmap->n, n = B->cmap->n; 421986214ceeSStefano Zampini PetscBool cisdense; 4220170fe5c8SBarry Smith 4221170fe5c8SBarry Smith PetscFunctionBegin; 422208401ef6SPierre Jolivet PetscCheck(A->cmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "A->cmap->n %" PetscInt_FMT " != B->rmap->n %" PetscInt_FMT, A->cmap->n, B->rmap->n); 42239566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, m, n)); 42249566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, B)); 4225d5e393b6SSuyash Tandon PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, MATSEQDENSEHIP, "")); 422648a46eb9SPierre Jolivet if (!cisdense) PetscCall(MatSetType(C, MATDENSE)); 42279566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 4228d73949e8SHong Zhang 42294222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ; 42303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4231170fe5c8SBarry Smith } 4232170fe5c8SBarry Smith 42330bad9183SKris Buschelman /*MC 4234fafad747SKris Buschelman MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 42350bad9183SKris Buschelman based on compressed sparse row format. 42360bad9183SKris Buschelman 42372ef1f0ffSBarry Smith Options Database Key: 42380bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 42390bad9183SKris Buschelman 42400bad9183SKris Buschelman Level: beginner 42410bad9183SKris Buschelman 42420cd7f59aSBarry Smith Notes: 42432ef1f0ffSBarry Smith `MatSetValues()` may be called for this matrix type with a `NULL` argument for the numerical values, 42440cd7f59aSBarry Smith in this case the values associated with the rows and columns one passes in are set to zero 42450cd7f59aSBarry Smith in the matrix 42460cd7f59aSBarry Smith 424711a5261eSBarry Smith `MatSetOptions`(,`MAT_STRUCTURE_ONLY`,`PETSC_TRUE`) may be called for this matrix type. In this no 424811a5261eSBarry Smith space is allocated for the nonzero entries and any entries passed with `MatSetValues()` are ignored 42490cd7f59aSBarry Smith 425011a5261eSBarry Smith Developer Note: 42512ef1f0ffSBarry Smith It would be nice if all matrix formats supported passing `NULL` in for the numerical values 42520cd7f59aSBarry Smith 42531cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatSetFromOptions()`, `MatSetType()`, `MatCreate()`, `MatType`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 42540bad9183SKris Buschelman M*/ 42550bad9183SKris Buschelman 4256ccd284c7SBarry Smith /*MC 4257ccd284c7SBarry Smith MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 4258ccd284c7SBarry Smith 425911a5261eSBarry Smith This matrix type is identical to `MATSEQAIJ` when constructed with a single process communicator, 426011a5261eSBarry Smith and `MATMPIAIJ` otherwise. As a result, for single process communicators, 426111a5261eSBarry Smith `MatSeqAIJSetPreallocation()` is supported, and similarly `MatMPIAIJSetPreallocation()` is supported 4262ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4263ccd284c7SBarry Smith the above preallocation routines for simplicity. 4264ccd284c7SBarry Smith 42652ef1f0ffSBarry Smith Options Database Key: 426611a5261eSBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to `MatSetFromOptions()` 4267ccd284c7SBarry Smith 42682ef1f0ffSBarry Smith Level: beginner 42692ef1f0ffSBarry Smith 427011a5261eSBarry Smith Note: 427111a5261eSBarry Smith Subclasses include `MATAIJCUSPARSE`, `MATAIJPERM`, `MATAIJSELL`, `MATAIJMKL`, `MATAIJCRL`, and also automatically switches over to use inodes when 4272ccd284c7SBarry Smith enough exist. 4273ccd284c7SBarry Smith 42741cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATMPIAIJ`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 4275ccd284c7SBarry Smith M*/ 4276ccd284c7SBarry Smith 4277ccd284c7SBarry Smith /*MC 4278ccd284c7SBarry Smith MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 4279ccd284c7SBarry Smith 42802ef1f0ffSBarry Smith Options Database Key: 42812ef1f0ffSBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to `MatSetFromOptions()` 42822ef1f0ffSBarry Smith 42832ef1f0ffSBarry Smith Level: beginner 42842ef1f0ffSBarry Smith 42852ef1f0ffSBarry Smith Note: 428611a5261eSBarry Smith This matrix type is identical to `MATSEQAIJCRL` when constructed with a single process communicator, 428711a5261eSBarry Smith and `MATMPIAIJCRL` otherwise. As a result, for single process communicators, 428811a5261eSBarry Smith `MatSeqAIJSetPreallocation()` is supported, and similarly `MatMPIAIJSetPreallocation()` is supported 4289ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4290ccd284c7SBarry Smith the above preallocation routines for simplicity. 4291ccd284c7SBarry Smith 42921cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL` 4293ccd284c7SBarry Smith M*/ 4294ccd284c7SBarry Smith 42957906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat, MatType, MatReuse, Mat *); 42967906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 42977906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat, MatType, MatReuse, Mat *); 42987906f579SHong Zhang #endif 4299d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)) 4300d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat, MatType, MatReuse, Mat *); 4301d24d4204SJose E. Roman #endif 43027906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE) 43037906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType, MatReuse, Mat *); 43047906f579SHong Zhang #endif 43057906f579SHong Zhang 4306d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat, MatType, MatReuse, Mat *); 4307c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat, MatType, MatReuse, Mat *); 43084222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat); 43097906f579SHong Zhang 43108c778c55SBarry Smith /*@C 431111a5261eSBarry Smith MatSeqAIJGetArray - gives read/write access to the array where the data for a `MATSEQAIJ` matrix is stored 43128c778c55SBarry Smith 43138c778c55SBarry Smith Not Collective 43148c778c55SBarry Smith 43158c778c55SBarry Smith Input Parameter: 4316fe59aa6dSJacob Faibussowitsch . A - a `MATSEQAIJ` matrix 43178c778c55SBarry Smith 43188c778c55SBarry Smith Output Parameter: 43198c778c55SBarry Smith . array - pointer to the data 43208c778c55SBarry Smith 43218c778c55SBarry Smith Level: intermediate 43228c778c55SBarry Smith 4323ce78bad3SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArray()` 43248c778c55SBarry Smith @*/ 43255d83a8b1SBarry Smith PetscErrorCode MatSeqAIJGetArray(Mat A, PetscScalar *array[]) 4326d71ae5a4SJacob Faibussowitsch { 4327d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 43288c778c55SBarry Smith 43298c778c55SBarry Smith PetscFunctionBegin; 4330d67d9f35SJunchao Zhang if (aij->ops->getarray) { 43319566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarray)(A, array)); 4332d67d9f35SJunchao Zhang } else { 4333d67d9f35SJunchao Zhang *array = aij->a; 4334d67d9f35SJunchao Zhang } 43353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4336d67d9f35SJunchao Zhang } 4337d67d9f35SJunchao Zhang 4338d67d9f35SJunchao Zhang /*@C 433911a5261eSBarry Smith MatSeqAIJRestoreArray - returns access to the array where the data for a `MATSEQAIJ` matrix is stored obtained by `MatSeqAIJGetArray()` 4340d67d9f35SJunchao Zhang 4341d67d9f35SJunchao Zhang Not Collective 4342d67d9f35SJunchao Zhang 4343d67d9f35SJunchao Zhang Input Parameters: 4344fe59aa6dSJacob Faibussowitsch + A - a `MATSEQAIJ` matrix 4345d67d9f35SJunchao Zhang - array - pointer to the data 4346d67d9f35SJunchao Zhang 4347d67d9f35SJunchao Zhang Level: intermediate 4348d67d9f35SJunchao Zhang 4349ce78bad3SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArray()` 4350d67d9f35SJunchao Zhang @*/ 43515d83a8b1SBarry Smith PetscErrorCode MatSeqAIJRestoreArray(Mat A, PetscScalar *array[]) 4352d71ae5a4SJacob Faibussowitsch { 4353d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4354d67d9f35SJunchao Zhang 4355d67d9f35SJunchao Zhang PetscFunctionBegin; 4356d67d9f35SJunchao Zhang if (aij->ops->restorearray) { 43579566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearray)(A, array)); 4358d67d9f35SJunchao Zhang } else { 4359d67d9f35SJunchao Zhang *array = NULL; 4360d67d9f35SJunchao Zhang } 43619566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 43623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43638c778c55SBarry Smith } 43648c778c55SBarry Smith 436521e72a00SBarry Smith /*@C 436611a5261eSBarry Smith MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a `MATSEQAIJ` matrix is stored 43678f1ea47aSStefano Zampini 43680ab4885dSBarry Smith Not Collective; No Fortran Support 43698f1ea47aSStefano Zampini 43708f1ea47aSStefano Zampini Input Parameter: 4371fe59aa6dSJacob Faibussowitsch . A - a `MATSEQAIJ` matrix 43728f1ea47aSStefano Zampini 43738f1ea47aSStefano Zampini Output Parameter: 43748f1ea47aSStefano Zampini . array - pointer to the data 43758f1ea47aSStefano Zampini 43768f1ea47aSStefano Zampini Level: intermediate 43778f1ea47aSStefano Zampini 43781cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 43798f1ea47aSStefano Zampini @*/ 43805d83a8b1SBarry Smith PetscErrorCode MatSeqAIJGetArrayRead(Mat A, const PetscScalar *array[]) 4381d71ae5a4SJacob Faibussowitsch { 4382d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 43838f1ea47aSStefano Zampini 43848f1ea47aSStefano Zampini PetscFunctionBegin; 4385d67d9f35SJunchao Zhang if (aij->ops->getarrayread) { 43869566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarrayread)(A, array)); 4387d67d9f35SJunchao Zhang } else { 4388d67d9f35SJunchao Zhang *array = aij->a; 4389d67d9f35SJunchao Zhang } 43903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43918f1ea47aSStefano Zampini } 43928f1ea47aSStefano Zampini 43938f1ea47aSStefano Zampini /*@C 439411a5261eSBarry Smith MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from `MatSeqAIJGetArrayRead()` 43958f1ea47aSStefano Zampini 43960ab4885dSBarry Smith Not Collective; No Fortran Support 43978f1ea47aSStefano Zampini 43988f1ea47aSStefano Zampini Input Parameter: 4399fe59aa6dSJacob Faibussowitsch . A - a `MATSEQAIJ` matrix 44008f1ea47aSStefano Zampini 44018f1ea47aSStefano Zampini Output Parameter: 44028f1ea47aSStefano Zampini . array - pointer to the data 44038f1ea47aSStefano Zampini 44048f1ea47aSStefano Zampini Level: intermediate 44058f1ea47aSStefano Zampini 44061cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 44078f1ea47aSStefano Zampini @*/ 44085d83a8b1SBarry Smith PetscErrorCode MatSeqAIJRestoreArrayRead(Mat A, const PetscScalar *array[]) 4409d71ae5a4SJacob Faibussowitsch { 4410d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 44118f1ea47aSStefano Zampini 44128f1ea47aSStefano Zampini PetscFunctionBegin; 4413d67d9f35SJunchao Zhang if (aij->ops->restorearrayread) { 44149566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearrayread)(A, array)); 4415d67d9f35SJunchao Zhang } else { 4416d67d9f35SJunchao Zhang *array = NULL; 4417d67d9f35SJunchao Zhang } 44183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4419d67d9f35SJunchao Zhang } 4420d67d9f35SJunchao Zhang 4421d67d9f35SJunchao Zhang /*@C 442211a5261eSBarry Smith MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a `MATSEQAIJ` matrix is stored 4423d67d9f35SJunchao Zhang 44240ab4885dSBarry Smith Not Collective; No Fortran Support 4425d67d9f35SJunchao Zhang 4426d67d9f35SJunchao Zhang Input Parameter: 4427fe59aa6dSJacob Faibussowitsch . A - a `MATSEQAIJ` matrix 4428d67d9f35SJunchao Zhang 4429d67d9f35SJunchao Zhang Output Parameter: 4430d67d9f35SJunchao Zhang . array - pointer to the data 4431d67d9f35SJunchao Zhang 4432d67d9f35SJunchao Zhang Level: intermediate 4433d67d9f35SJunchao Zhang 44341cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 4435d67d9f35SJunchao Zhang @*/ 44365d83a8b1SBarry Smith PetscErrorCode MatSeqAIJGetArrayWrite(Mat A, PetscScalar *array[]) 4437d71ae5a4SJacob Faibussowitsch { 4438d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4439d67d9f35SJunchao Zhang 4440d67d9f35SJunchao Zhang PetscFunctionBegin; 4441d67d9f35SJunchao Zhang if (aij->ops->getarraywrite) { 44429566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarraywrite)(A, array)); 4443d67d9f35SJunchao Zhang } else { 4444d67d9f35SJunchao Zhang *array = aij->a; 4445d67d9f35SJunchao Zhang } 44469566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 44473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4448d67d9f35SJunchao Zhang } 4449d67d9f35SJunchao Zhang 4450d67d9f35SJunchao Zhang /*@C 4451d67d9f35SJunchao Zhang MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead 4452d67d9f35SJunchao Zhang 44530ab4885dSBarry Smith Not Collective; No Fortran Support 4454d67d9f35SJunchao Zhang 4455d67d9f35SJunchao Zhang Input Parameter: 4456fe59aa6dSJacob Faibussowitsch . A - a MATSEQAIJ matrix 4457d67d9f35SJunchao Zhang 4458d67d9f35SJunchao Zhang Output Parameter: 4459d67d9f35SJunchao Zhang . array - pointer to the data 4460d67d9f35SJunchao Zhang 4461d67d9f35SJunchao Zhang Level: intermediate 4462d67d9f35SJunchao Zhang 44631cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 4464d67d9f35SJunchao Zhang @*/ 44655d83a8b1SBarry Smith PetscErrorCode MatSeqAIJRestoreArrayWrite(Mat A, PetscScalar *array[]) 4466d71ae5a4SJacob Faibussowitsch { 4467d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4468d67d9f35SJunchao Zhang 4469d67d9f35SJunchao Zhang PetscFunctionBegin; 4470d67d9f35SJunchao Zhang if (aij->ops->restorearraywrite) { 44719566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearraywrite)(A, array)); 4472d67d9f35SJunchao Zhang } else { 4473d67d9f35SJunchao Zhang *array = NULL; 4474d67d9f35SJunchao Zhang } 44753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44768f1ea47aSStefano Zampini } 44778f1ea47aSStefano Zampini 44788f1ea47aSStefano Zampini /*@C 447911a5261eSBarry Smith MatSeqAIJGetCSRAndMemType - Get the CSR arrays and the memory type of the `MATSEQAIJ` matrix 44807ee59b9bSJunchao Zhang 44810ab4885dSBarry Smith Not Collective; No Fortran Support 44827ee59b9bSJunchao Zhang 44837ee59b9bSJunchao Zhang Input Parameter: 448411a5261eSBarry Smith . mat - a matrix of type `MATSEQAIJ` or its subclasses 44857ee59b9bSJunchao Zhang 44867ee59b9bSJunchao Zhang Output Parameters: 44877ee59b9bSJunchao Zhang + i - row map array of the matrix 44887ee59b9bSJunchao Zhang . j - column index array of the matrix 44897ee59b9bSJunchao Zhang . a - data array of the matrix 4490fe59aa6dSJacob Faibussowitsch - mtype - memory type of the arrays 44917ee59b9bSJunchao Zhang 4492fe59aa6dSJacob Faibussowitsch Level: developer 44932ef1f0ffSBarry Smith 44947ee59b9bSJunchao Zhang Notes: 44952ef1f0ffSBarry Smith Any of the output parameters can be `NULL`, in which case the corresponding value is not returned. 44967ee59b9bSJunchao Zhang If mat is a device matrix, the arrays are on the device. Otherwise, they are on the host. 44977ee59b9bSJunchao Zhang 44987ee59b9bSJunchao Zhang One can call this routine on a preallocated but not assembled matrix to just get the memory of the CSR underneath the matrix. 44992ef1f0ffSBarry Smith If the matrix is assembled, the data array `a` is guaranteed to have the latest values of the matrix. 45007ee59b9bSJunchao Zhang 45011cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 45027ee59b9bSJunchao Zhang @*/ 45035d83a8b1SBarry Smith PetscErrorCode MatSeqAIJGetCSRAndMemType(Mat mat, const PetscInt *i[], const PetscInt *j[], PetscScalar *a[], PetscMemType *mtype) 4504d71ae5a4SJacob Faibussowitsch { 45057ee59b9bSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 45067ee59b9bSJunchao Zhang 45077ee59b9bSJunchao Zhang PetscFunctionBegin; 45087ee59b9bSJunchao Zhang PetscCheck(mat->preallocated, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "matrix is not preallocated"); 45097ee59b9bSJunchao Zhang if (aij->ops->getcsrandmemtype) { 45107ee59b9bSJunchao Zhang PetscCall((*aij->ops->getcsrandmemtype)(mat, i, j, a, mtype)); 45117ee59b9bSJunchao Zhang } else { 45127ee59b9bSJunchao Zhang if (i) *i = aij->i; 45137ee59b9bSJunchao Zhang if (j) *j = aij->j; 45147ee59b9bSJunchao Zhang if (a) *a = aij->a; 45157ee59b9bSJunchao Zhang if (mtype) *mtype = PETSC_MEMTYPE_HOST; 45167ee59b9bSJunchao Zhang } 45173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 45187ee59b9bSJunchao Zhang } 45197ee59b9bSJunchao Zhang 4520cc4c1da9SBarry Smith /*@ 452121e72a00SBarry Smith MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row 452221e72a00SBarry Smith 452321e72a00SBarry Smith Not Collective 452421e72a00SBarry Smith 452521e72a00SBarry Smith Input Parameter: 4526fe59aa6dSJacob Faibussowitsch . A - a `MATSEQAIJ` matrix 452721e72a00SBarry Smith 452821e72a00SBarry Smith Output Parameter: 452921e72a00SBarry Smith . nz - the maximum number of nonzeros in any row 453021e72a00SBarry Smith 453121e72a00SBarry Smith Level: intermediate 453221e72a00SBarry Smith 4533ce78bad3SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArray()` 453421e72a00SBarry Smith @*/ 4535d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJGetMaxRowNonzeros(Mat A, PetscInt *nz) 4536d71ae5a4SJacob Faibussowitsch { 453721e72a00SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 453821e72a00SBarry Smith 453921e72a00SBarry Smith PetscFunctionBegin; 454021e72a00SBarry Smith *nz = aij->rmax; 45413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 454221e72a00SBarry Smith } 454321e72a00SBarry Smith 454449abdd8aSBarry Smith static PetscErrorCode MatCOOStructDestroy_SeqAIJ(void **data) 45452c4ab24aSJunchao Zhang { 454649abdd8aSBarry Smith MatCOOStruct_SeqAIJ *coo = (MatCOOStruct_SeqAIJ *)*data; 45474d86920dSPierre Jolivet 45482c4ab24aSJunchao Zhang PetscFunctionBegin; 45492c4ab24aSJunchao Zhang PetscCall(PetscFree(coo->perm)); 45502c4ab24aSJunchao Zhang PetscCall(PetscFree(coo->jmap)); 45512c4ab24aSJunchao Zhang PetscCall(PetscFree(coo)); 45522c4ab24aSJunchao Zhang PetscFunctionReturn(PETSC_SUCCESS); 45532c4ab24aSJunchao Zhang } 45542c4ab24aSJunchao Zhang 4555d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[]) 4556d71ae5a4SJacob Faibussowitsch { 4557394ed5ebSJunchao Zhang MPI_Comm comm; 4558394ed5ebSJunchao Zhang PetscInt *i, *j; 45590d88f7f4SJunchao Zhang PetscInt M, N, row, iprev; 4560394ed5ebSJunchao Zhang PetscCount k, p, q, nneg, nnz, start, end; /* Index the coo array, so use PetscCount as their type */ 4561394ed5ebSJunchao Zhang PetscInt *Ai; /* Change to PetscCount once we use it for row pointers */ 4562394ed5ebSJunchao Zhang PetscInt *Aj; 4563394ed5ebSJunchao Zhang PetscScalar *Aa; 4564f4f49eeaSPierre Jolivet Mat_SeqAIJ *seqaij = (Mat_SeqAIJ *)mat->data; 4565cbc6b225SStefano Zampini MatType rtype; 4566394ed5ebSJunchao Zhang PetscCount *perm, *jmap; 45672c4ab24aSJunchao Zhang MatCOOStruct_SeqAIJ *coo; 45680d88f7f4SJunchao Zhang PetscBool isorted; 45699f0612e4SBarry Smith PetscBool hypre; 4570394ed5ebSJunchao Zhang 4571394ed5ebSJunchao Zhang PetscFunctionBegin; 45729566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 45739566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &M, &N)); 4574e8729f6fSJunchao Zhang i = coo_i; 4575e8729f6fSJunchao Zhang j = coo_j; 45769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n, &perm)); 45770d88f7f4SJunchao Zhang 45780d88f7f4SJunchao Zhang /* Ignore entries with negative row or col indices; at the same time, check if i[] is already sorted (e.g., MatConvert_AlJ_HYPRE results in this case) */ 45790d88f7f4SJunchao Zhang isorted = PETSC_TRUE; 45800d88f7f4SJunchao Zhang iprev = PETSC_INT_MIN; 45810d88f7f4SJunchao Zhang for (k = 0; k < coo_n; k++) { 4582394ed5ebSJunchao Zhang if (j[k] < 0) i[k] = -1; 45830d88f7f4SJunchao Zhang if (isorted) { 45840d88f7f4SJunchao Zhang if (i[k] < iprev) isorted = PETSC_FALSE; 45850d88f7f4SJunchao Zhang else iprev = i[k]; 45860d88f7f4SJunchao Zhang } 4587394ed5ebSJunchao Zhang perm[k] = k; 4588394ed5ebSJunchao Zhang } 4589394ed5ebSJunchao Zhang 45900d88f7f4SJunchao Zhang /* Sort by row if not already */ 45910d88f7f4SJunchao Zhang if (!isorted) PetscCall(PetscSortIntWithIntCountArrayPair(coo_n, i, j, perm)); 45922b35a777SBarry Smith PetscCheck(coo_n == 0 || i[coo_n - 1] < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "COO row index %" PetscInt_FMT " is >= the matrix row size %" PetscInt_FMT, i[coo_n - 1], M); 4593651b1cf9SStefano Zampini 4594651b1cf9SStefano Zampini /* Advance k to the first row with a non-negative index */ 4595651b1cf9SStefano Zampini for (k = 0; k < coo_n; k++) 45969371c9d4SSatish Balay if (i[k] >= 0) break; 4597394ed5ebSJunchao Zhang nneg = k; 45989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n - nneg + 1, &jmap)); /* +1 to make a CSR-like data structure. jmap[i] originally is the number of repeats for i-th nonzero */ 4599394ed5ebSJunchao Zhang nnz = 0; /* Total number of unique nonzeros to be counted */ 460035cb6cd3SPierre Jolivet jmap++; /* Inc jmap by 1 for convenience */ 4601394ed5ebSJunchao Zhang 46029f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(M + 1, sizeof(PetscInt), (void **)&Ai)); /* CSR of A */ 46039f0612e4SBarry Smith PetscCall(PetscArrayzero(Ai, M + 1)); 46049f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(coo_n - nneg, sizeof(PetscInt), (void **)&Aj)); /* We have at most coo_n-nneg unique nonzeros */ 4605394ed5ebSJunchao Zhang 460621fb621cSStefano Zampini PetscCall(PetscStrcmp("_internal_COO_mat_for_hypre", ((PetscObject)mat)->name, &hypre)); 4607651b1cf9SStefano Zampini 4608394ed5ebSJunchao Zhang /* In each row, sort by column, then unique column indices to get row length */ 460935cb6cd3SPierre Jolivet Ai++; /* Inc by 1 for convenience */ 4610394ed5ebSJunchao Zhang q = 0; /* q-th unique nonzero, with q starting from 0 */ 4611394ed5ebSJunchao Zhang while (k < coo_n) { 46120d88f7f4SJunchao Zhang PetscBool strictly_sorted; // this row is strictly sorted? 46130d88f7f4SJunchao Zhang PetscInt jprev; 46140d88f7f4SJunchao Zhang 46150d88f7f4SJunchao Zhang /* get [start,end) indices for this row; also check if cols in this row are strictly sorted */ 4616394ed5ebSJunchao Zhang row = i[k]; 46170d88f7f4SJunchao Zhang start = k; 46180d88f7f4SJunchao Zhang jprev = PETSC_INT_MIN; 46190d88f7f4SJunchao Zhang strictly_sorted = PETSC_TRUE; 46200d88f7f4SJunchao Zhang while (k < coo_n && i[k] == row) { 46210d88f7f4SJunchao Zhang if (strictly_sorted) { 46220d88f7f4SJunchao Zhang if (j[k] <= jprev) strictly_sorted = PETSC_FALSE; 46230d88f7f4SJunchao Zhang else jprev = j[k]; 46240d88f7f4SJunchao Zhang } 46250d88f7f4SJunchao Zhang k++; 46260d88f7f4SJunchao Zhang } 4627394ed5ebSJunchao Zhang end = k; 46280d88f7f4SJunchao Zhang 4629651b1cf9SStefano Zampini /* hack for HYPRE: swap min column to diag so that diagonal values will go first */ 4630651b1cf9SStefano Zampini if (hypre) { 46311690c2aeSBarry Smith PetscInt minj = PETSC_INT_MAX; 4632651b1cf9SStefano Zampini PetscBool hasdiag = PETSC_FALSE; 46330d88f7f4SJunchao Zhang 46340d88f7f4SJunchao Zhang if (strictly_sorted) { // fast path to swap the first and the diag 46350d88f7f4SJunchao Zhang PetscCount tmp; 46360d88f7f4SJunchao Zhang for (p = start; p < end; p++) { 46370d88f7f4SJunchao Zhang if (j[p] == row && p != start) { 46381c265611SJunchao Zhang j[p] = j[start]; // swap j[], so that the diagonal value will go first (manipulated by perm[]) 46390d88f7f4SJunchao Zhang j[start] = row; 46400d88f7f4SJunchao Zhang tmp = perm[start]; 46411c265611SJunchao Zhang perm[start] = perm[p]; // also swap perm[] so we can save the call to PetscSortIntWithCountArray() below 46420d88f7f4SJunchao Zhang perm[p] = tmp; 46430d88f7f4SJunchao Zhang break; 46440d88f7f4SJunchao Zhang } 46450d88f7f4SJunchao Zhang } 46460d88f7f4SJunchao Zhang } else { 4647651b1cf9SStefano Zampini for (p = start; p < end; p++) { 4648651b1cf9SStefano Zampini hasdiag = (PetscBool)(hasdiag || (j[p] == row)); 4649651b1cf9SStefano Zampini minj = PetscMin(minj, j[p]); 4650651b1cf9SStefano Zampini } 46510d88f7f4SJunchao Zhang 4652651b1cf9SStefano Zampini if (hasdiag) { 4653651b1cf9SStefano Zampini for (p = start; p < end; p++) { 4654651b1cf9SStefano Zampini if (j[p] == minj) j[p] = row; 4655651b1cf9SStefano Zampini else if (j[p] == row) j[p] = minj; 4656651b1cf9SStefano Zampini } 4657651b1cf9SStefano Zampini } 4658651b1cf9SStefano Zampini } 46590d88f7f4SJunchao Zhang } 46601c265611SJunchao Zhang // sort by columns in a row. perm[] indicates their original order 46610d88f7f4SJunchao Zhang if (!strictly_sorted) PetscCall(PetscSortIntWithCountArray(end - start, j + start, perm + start)); 46628551dd9cSJunchao Zhang PetscCheck(end == start || j[end - 1] < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "COO column index %" PetscInt_FMT " is >= the matrix column size %" PetscInt_FMT, j[end - 1], N); 4663651b1cf9SStefano Zampini 46640d88f7f4SJunchao Zhang if (strictly_sorted) { // fast path to set Aj[], jmap[], Ai[], nnz, q 46650d88f7f4SJunchao Zhang for (p = start; p < end; p++, q++) { 46660d88f7f4SJunchao Zhang Aj[q] = j[p]; 46670d88f7f4SJunchao Zhang jmap[q] = 1; 46680d88f7f4SJunchao Zhang } 46696497c311SBarry Smith PetscCall(PetscIntCast(end - start, Ai + row)); 46700d88f7f4SJunchao Zhang nnz += Ai[row]; // q is already advanced 46710d88f7f4SJunchao Zhang } else { 4672394ed5ebSJunchao Zhang /* Find number of unique col entries in this row */ 4673394ed5ebSJunchao Zhang Aj[q] = j[start]; /* Log the first nonzero in this row */ 4674651b1cf9SStefano Zampini jmap[q] = 1; /* Number of repeats of this nonzero entry */ 4675394ed5ebSJunchao Zhang Ai[row] = 1; 4676394ed5ebSJunchao Zhang nnz++; 4677394ed5ebSJunchao Zhang 4678394ed5ebSJunchao Zhang for (p = start + 1; p < end; p++) { /* Scan remaining nonzero in this row */ 4679394ed5ebSJunchao Zhang if (j[p] != j[p - 1]) { /* Meet a new nonzero */ 4680394ed5ebSJunchao Zhang q++; 4681394ed5ebSJunchao Zhang jmap[q] = 1; 4682394ed5ebSJunchao Zhang Aj[q] = j[p]; 4683394ed5ebSJunchao Zhang Ai[row]++; 4684394ed5ebSJunchao Zhang nnz++; 4685394ed5ebSJunchao Zhang } else { 4686394ed5ebSJunchao Zhang jmap[q]++; 4687394ed5ebSJunchao Zhang } 4688394ed5ebSJunchao Zhang } 4689394ed5ebSJunchao Zhang q++; /* Move to next row and thus next unique nonzero */ 4690394ed5ebSJunchao Zhang } 46910d88f7f4SJunchao Zhang } 46920d88f7f4SJunchao Zhang 4693394ed5ebSJunchao Zhang Ai--; /* Back to the beginning of Ai[] */ 4694394ed5ebSJunchao Zhang for (k = 0; k < M; k++) Ai[k + 1] += Ai[k]; 46950d88f7f4SJunchao Zhang jmap--; // Back to the beginning of jmap[] 4696394ed5ebSJunchao Zhang jmap[0] = 0; 4697394ed5ebSJunchao Zhang for (k = 0; k < nnz; k++) jmap[k + 1] += jmap[k]; 46980d88f7f4SJunchao Zhang 46999f0612e4SBarry Smith if (nnz < coo_n - nneg) { /* Reallocate with actual number of unique nonzeros */ 4700394ed5ebSJunchao Zhang PetscCount *jmap_new; 4701394ed5ebSJunchao Zhang PetscInt *Aj_new; 4702394ed5ebSJunchao Zhang 47039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz + 1, &jmap_new)); 47049566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(jmap_new, jmap, nnz + 1)); 47059566063dSJacob Faibussowitsch PetscCall(PetscFree(jmap)); 4706394ed5ebSJunchao Zhang jmap = jmap_new; 4707394ed5ebSJunchao Zhang 47089f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(nnz, sizeof(PetscInt), (void **)&Aj_new)); 47099566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(Aj_new, Aj, nnz)); 47109f0612e4SBarry Smith PetscCall(PetscShmgetDeallocateArray((void **)&Aj)); 4711394ed5ebSJunchao Zhang Aj = Aj_new; 4712394ed5ebSJunchao Zhang } 4713394ed5ebSJunchao Zhang 4714394ed5ebSJunchao Zhang if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */ 4715394ed5ebSJunchao Zhang PetscCount *perm_new; 4716cbc6b225SStefano Zampini 47179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n - nneg, &perm_new)); 47189566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(perm_new, perm + nneg, coo_n - nneg)); 47199566063dSJacob Faibussowitsch PetscCall(PetscFree(perm)); 4720394ed5ebSJunchao Zhang perm = perm_new; 4721394ed5ebSJunchao Zhang } 4722394ed5ebSJunchao Zhang 47239566063dSJacob Faibussowitsch PetscCall(MatGetRootType_Private(mat, &rtype)); 47249f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(nnz, sizeof(PetscScalar), (void **)&Aa)); 47259f0612e4SBarry Smith PetscCall(PetscArrayzero(Aa, nnz)); 47269566063dSJacob Faibussowitsch PetscCall(MatSetSeqAIJWithArrays_private(PETSC_COMM_SELF, M, N, Ai, Aj, Aa, rtype, mat)); 4727394ed5ebSJunchao Zhang 4728394ed5ebSJunchao Zhang seqaij->free_a = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */ 47292c4ab24aSJunchao Zhang 47302c4ab24aSJunchao Zhang // Put the COO struct in a container and then attach that to the matrix 47312c4ab24aSJunchao Zhang PetscCall(PetscMalloc1(1, &coo)); 47326497c311SBarry Smith PetscCall(PetscIntCast(nnz, &coo->nz)); 47332c4ab24aSJunchao Zhang coo->n = coo_n; 47342c4ab24aSJunchao Zhang coo->Atot = coo_n - nneg; // Annz is seqaij->nz, so no need to record that again 47352c4ab24aSJunchao Zhang coo->jmap = jmap; // of length nnz+1 47362c4ab24aSJunchao Zhang coo->perm = perm; 473703e76207SPierre Jolivet PetscCall(PetscObjectContainerCompose((PetscObject)mat, "__PETSc_MatCOOStruct_Host", coo, MatCOOStructDestroy_SeqAIJ)); 47383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4739394ed5ebSJunchao Zhang } 4740394ed5ebSJunchao Zhang 4741d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A, const PetscScalar v[], InsertMode imode) 4742d71ae5a4SJacob Faibussowitsch { 4743394ed5ebSJunchao Zhang Mat_SeqAIJ *aseq = (Mat_SeqAIJ *)A->data; 4744394ed5ebSJunchao Zhang PetscCount i, j, Annz = aseq->nz; 47452c4ab24aSJunchao Zhang PetscCount *perm, *jmap; 4746394ed5ebSJunchao Zhang PetscScalar *Aa; 47472c4ab24aSJunchao Zhang PetscContainer container; 47482c4ab24aSJunchao Zhang MatCOOStruct_SeqAIJ *coo; 4749394ed5ebSJunchao Zhang 4750394ed5ebSJunchao Zhang PetscFunctionBegin; 47512c4ab24aSJunchao Zhang PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_MatCOOStruct_Host", (PetscObject *)&container)); 47522c4ab24aSJunchao Zhang PetscCheck(container, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not found MatCOOStruct on this matrix"); 47532c4ab24aSJunchao Zhang PetscCall(PetscContainerGetPointer(container, (void **)&coo)); 47542c4ab24aSJunchao Zhang perm = coo->perm; 47552c4ab24aSJunchao Zhang jmap = coo->jmap; 47569566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &Aa)); 4757394ed5ebSJunchao Zhang for (i = 0; i < Annz; i++) { 4758b6c38306SJunchao Zhang PetscScalar sum = 0.0; 4759b6c38306SJunchao Zhang for (j = jmap[i]; j < jmap[i + 1]; j++) sum += v[perm[j]]; 4760b6c38306SJunchao Zhang Aa[i] = (imode == INSERT_VALUES ? 0.0 : Aa[i]) + sum; 4761394ed5ebSJunchao Zhang } 47629566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &Aa)); 47633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4764394ed5ebSJunchao Zhang } 4765394ed5ebSJunchao Zhang 476634b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 47675063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat, MatType, MatReuse, Mat *); 476802fe1965SBarry Smith #endif 4769d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_HIP) 4770d5e393b6SSuyash Tandon PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJHIPSPARSE(Mat, MatType, MatReuse, Mat *); 4771d5e393b6SSuyash Tandon #endif 47723d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 47735063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat, MatType, MatReuse, Mat *); 47743d0639e7SStefano Zampini #endif 477502fe1965SBarry Smith 4776d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B) 4777d71ae5a4SJacob Faibussowitsch { 4778273d9f13SBarry Smith Mat_SeqAIJ *b; 477938baddfdSBarry Smith PetscMPIInt size; 4780273d9f13SBarry Smith 4781273d9f13SBarry Smith PetscFunctionBegin; 47829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size)); 478308401ef6SPierre Jolivet PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Comm must be of size 1"); 4784273d9f13SBarry Smith 47854dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&b)); 47862205254eSKarl Rupp 4787b0a32e0cSBarry Smith B->data = (void *)b; 4788aea10558SJacob Faibussowitsch B->ops[0] = MatOps_Values; 4789071fcb05SBarry Smith if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 47902205254eSKarl Rupp 4791f4259b30SLisandro Dalcin b->row = NULL; 4792f4259b30SLisandro Dalcin b->col = NULL; 4793f4259b30SLisandro Dalcin b->icol = NULL; 4794b810aeb4SBarry Smith b->reallocs = 0; 479536db0b34SBarry Smith b->ignorezeroentries = PETSC_FALSE; 4796f1e2ffcdSBarry Smith b->roworiented = PETSC_TRUE; 4797416022c9SBarry Smith b->nonew = 0; 4798f4259b30SLisandro Dalcin b->diag = NULL; 4799f4259b30SLisandro Dalcin b->solve_work = NULL; 4800f4259b30SLisandro Dalcin B->spptr = NULL; 4801f4259b30SLisandro Dalcin b->saved_values = NULL; 4802f4259b30SLisandro Dalcin b->idiag = NULL; 4803f4259b30SLisandro Dalcin b->mdiag = NULL; 4804f4259b30SLisandro Dalcin b->ssor_work = NULL; 480571f1c65dSBarry Smith b->omega = 1.0; 480671f1c65dSBarry Smith b->fshift = 0.0; 4807bbead8a2SBarry Smith b->ibdiagvalid = PETSC_FALSE; 4808a9817697SBarry Smith b->keepnonzeropattern = PETSC_FALSE; 480917ab2063SBarry Smith 48109566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ)); 4811d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB) 48129566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEnginePut_C", MatlabEnginePut_SeqAIJ)); 48139566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEngineGet_C", MatlabEngineGet_SeqAIJ)); 4814b3866ffcSBarry Smith #endif 48159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetColumnIndices_C", MatSeqAIJSetColumnIndices_SeqAIJ)); 48169566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqAIJ)); 48179566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqAIJ)); 48189566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsbaij_C", MatConvert_SeqAIJ_SeqSBAIJ)); 48199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqbaij_C", MatConvert_SeqAIJ_SeqBAIJ)); 48209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijperm_C", MatConvert_SeqAIJ_SeqAIJPERM)); 48219566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijsell_C", MatConvert_SeqAIJ_SeqAIJSELL)); 48229779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 48239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijmkl_C", MatConvert_SeqAIJ_SeqAIJMKL)); 4824191b95cbSRichard Tran Mills #endif 482534b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 48269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcusparse_C", MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 48279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_seqaij_C", MatProductSetFromOptions_SeqAIJ)); 48289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaijcusparse_C", MatProductSetFromOptions_SeqAIJ)); 482902fe1965SBarry Smith #endif 4830d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_HIP) 4831d5e393b6SSuyash Tandon PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijhipsparse_C", MatConvert_SeqAIJ_SeqAIJHIPSPARSE)); 4832d5e393b6SSuyash Tandon PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijhipsparse_seqaij_C", MatProductSetFromOptions_SeqAIJ)); 4833d5e393b6SSuyash Tandon PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaijhipsparse_C", MatProductSetFromOptions_SeqAIJ)); 4834d5e393b6SSuyash Tandon #endif 48353d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 48369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijkokkos_C", MatConvert_SeqAIJ_SeqAIJKokkos)); 48373d0639e7SStefano Zampini #endif 48389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcrl_C", MatConvert_SeqAIJ_SeqAIJCRL)); 4839af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 48409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_elemental_C", MatConvert_SeqAIJ_Elemental)); 4841af8000cdSHong Zhang #endif 4842d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)) 48439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_scalapack_C", MatConvert_AIJ_ScaLAPACK)); 4844d24d4204SJose E. Roman #endif 484563c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 48469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_hypre_C", MatConvert_AIJ_HYPRE)); 48479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_transpose_seqaij_seqaij_C", MatProductSetFromOptions_Transpose_AIJ_AIJ)); 484863c07aadSStefano Zampini #endif 48499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqdense_C", MatConvert_SeqAIJ_SeqDense)); 48509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsell_C", MatConvert_SeqAIJ_SeqSELL)); 48519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_is_C", MatConvert_XAIJ_IS)); 48529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsTranspose_C", MatIsTranspose_SeqAIJ)); 485314e4dea2SJose E. Roman PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsHermitianTranspose_C", MatIsHermitianTranspose_SeqAIJ)); 48549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocation_C", MatSeqAIJSetPreallocation_SeqAIJ)); 48559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatResetPreallocation_C", MatResetPreallocation_SeqAIJ)); 4856674b392bSAlexander PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatResetHash_C", MatResetHash_SeqAIJ)); 48579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocationCSR_C", MatSeqAIJSetPreallocationCSR_SeqAIJ)); 48589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatReorderForNonzeroDiagonal_C", MatReorderForNonzeroDiagonal_SeqAIJ)); 48599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_is_seqaij_C", MatProductSetFromOptions_IS_XAIJ)); 48609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqaij_C", MatProductSetFromOptions_SeqDense_SeqAIJ)); 48619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaij_C", MatProductSetFromOptions_SeqAIJ)); 48629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJKron_C", MatSeqAIJKron_SeqAIJ)); 48639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_SeqAIJ)); 48649566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_SeqAIJ)); 48659566063dSJacob Faibussowitsch PetscCall(MatCreate_SeqAIJ_Inode(B)); 48669566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ)); 48679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetTypeFromOptions(B)); /* this allows changing the matrix subtype to say MATSEQAIJPERM */ 48683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 486917ab2063SBarry Smith } 487017ab2063SBarry Smith 4871b24902e0SBarry Smith /* 48723893b582SJunchao Zhang Given a matrix generated with MatGetFactor() duplicates all the information in A into C 4873b24902e0SBarry Smith */ 4874d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C, Mat A, MatDuplicateOption cpvalues, PetscBool mallocmatspace) 4875d71ae5a4SJacob Faibussowitsch { 48762a350339SBarry Smith Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data, *a = (Mat_SeqAIJ *)A->data; 4877071fcb05SBarry Smith PetscInt m = A->rmap->n, i; 487817ab2063SBarry Smith 48793a40ed3dSBarry Smith PetscFunctionBegin; 4880aed4548fSBarry Smith PetscCheck(A->assembled || cpvalues == MAT_DO_NOT_COPY_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix"); 4881273d9f13SBarry Smith 4882d5f3da31SBarry Smith C->factortype = A->factortype; 4883f4259b30SLisandro Dalcin c->row = NULL; 4884f4259b30SLisandro Dalcin c->col = NULL; 4885f4259b30SLisandro Dalcin c->icol = NULL; 48866ad4291fSHong Zhang c->reallocs = 0; 488769272f91SPierre Jolivet C->assembled = A->assembled; 488817ab2063SBarry Smith 488969272f91SPierre Jolivet if (A->preallocated) { 48909566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->rmap, &C->rmap)); 48919566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->cmap, &C->cmap)); 4892eec197d1SBarry Smith 489331fe6a7dSBarry Smith if (!A->hash_active) { 48949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &c->imax)); 48959566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->imax, a->imax, m * sizeof(PetscInt))); 48969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &c->ilen)); 48979566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->ilen, a->ilen, m * sizeof(PetscInt))); 489817ab2063SBarry Smith 489917ab2063SBarry Smith /* allocate the matrix space */ 4900f77e22a1SHong Zhang if (mallocmatspace) { 49019f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(a->i[m], sizeof(PetscScalar), (void **)&c->a)); 49029f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(a->i[m], sizeof(PetscInt), (void **)&c->j)); 49039f0612e4SBarry Smith PetscCall(PetscShmgetAllocateArray(m + 1, sizeof(PetscInt), (void **)&c->i)); 49049566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->i, a->i, m + 1)); 49059f0612e4SBarry Smith c->free_a = PETSC_TRUE; 49069f0612e4SBarry Smith c->free_ij = PETSC_TRUE; 490717ab2063SBarry Smith if (m > 0) { 49089566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->j, a->j, a->i[m])); 4909be6bf707SBarry Smith if (cpvalues == MAT_COPY_VALUES) { 49102e5835c6SStefano Zampini const PetscScalar *aa; 49112e5835c6SStefano Zampini 49129566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 49139566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->a, aa, a->i[m])); 49149566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 4915be6bf707SBarry Smith } else { 49169566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->a, a->i[m])); 491717ab2063SBarry Smith } 491808480c60SBarry Smith } 4919f77e22a1SHong Zhang } 492031fe6a7dSBarry Smith C->preallocated = PETSC_TRUE; 492131fe6a7dSBarry Smith } else { 492231fe6a7dSBarry Smith PetscCheck(mallocmatspace, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Cannot malloc matrix memory from a non-preallocated matrix"); 492331fe6a7dSBarry Smith PetscCall(MatSetUp(C)); 492431fe6a7dSBarry Smith } 492517ab2063SBarry Smith 49266ad4291fSHong Zhang c->ignorezeroentries = a->ignorezeroentries; 4927416022c9SBarry Smith c->roworiented = a->roworiented; 4928416022c9SBarry Smith c->nonew = a->nonew; 4929f4259b30SLisandro Dalcin c->solve_work = NULL; 4930f4259b30SLisandro Dalcin c->saved_values = NULL; 4931f4259b30SLisandro Dalcin c->idiag = NULL; 4932f4259b30SLisandro Dalcin c->ssor_work = NULL; 4933a9817697SBarry Smith c->keepnonzeropattern = a->keepnonzeropattern; 49346ad4291fSHong Zhang 4935893ad86cSHong Zhang c->rmax = a->rmax; 4936416022c9SBarry Smith c->nz = a->nz; 49378ed568f8SMatthew G Knepley c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 4938754ec7b1SSatish Balay 49396ad4291fSHong Zhang c->compressedrow.use = a->compressedrow.use; 49406ad4291fSHong Zhang c->compressedrow.nrows = a->compressedrow.nrows; 4941cd6b891eSBarry Smith if (a->compressedrow.use) { 49426ad4291fSHong Zhang i = a->compressedrow.nrows; 49439566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i + 1, &c->compressedrow.i, i, &c->compressedrow.rindex)); 49449566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.i, a->compressedrow.i, i + 1)); 49459566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.rindex, a->compressedrow.rindex, i)); 494627ea64f8SHong Zhang } else { 494727ea64f8SHong Zhang c->compressedrow.use = PETSC_FALSE; 49480298fd71SBarry Smith c->compressedrow.i = NULL; 49490298fd71SBarry Smith c->compressedrow.rindex = NULL; 49506ad4291fSHong Zhang } 4951ea632784SBarry Smith c->nonzerorowcnt = a->nonzerorowcnt; 4952e56f5c9eSBarry Smith C->nonzerostate = A->nonzerostate; 49534846f1f5SKris Buschelman 49549566063dSJacob Faibussowitsch PetscCall(MatDuplicate_SeqAIJ_Inode(A, cpvalues, &C)); 495569272f91SPierre Jolivet } 49569566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist)); 49573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 495817ab2063SBarry Smith } 495917ab2063SBarry Smith 4960d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B) 4961d71ae5a4SJacob Faibussowitsch { 4962b24902e0SBarry Smith PetscFunctionBegin; 49639566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 49649566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n)); 496548a46eb9SPierre Jolivet if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) PetscCall(MatSetBlockSizesFromMats(*B, A, A)); 49669566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, ((PetscObject)A)->type_name)); 49679566063dSJacob Faibussowitsch PetscCall(MatDuplicateNoCreate_SeqAIJ(*B, A, cpvalues, PETSC_TRUE)); 49683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4969b24902e0SBarry Smith } 4970b24902e0SBarry Smith 4971d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer) 4972d71ae5a4SJacob Faibussowitsch { 497352f91c60SVaclav Hapla PetscBool isbinary, ishdf5; 497452f91c60SVaclav Hapla 497552f91c60SVaclav Hapla PetscFunctionBegin; 497652f91c60SVaclav Hapla PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1); 497752f91c60SVaclav Hapla PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 4978c27b3999SVaclav Hapla /* force binary viewer to load .info file if it has not yet done so */ 49799566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 49809566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 49819566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 498252f91c60SVaclav Hapla if (isbinary) { 49839566063dSJacob Faibussowitsch PetscCall(MatLoad_SeqAIJ_Binary(newMat, viewer)); 498452f91c60SVaclav Hapla } else if (ishdf5) { 498552f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5) 49869566063dSJacob Faibussowitsch PetscCall(MatLoad_AIJ_HDF5(newMat, viewer)); 498752f91c60SVaclav Hapla #else 498852f91c60SVaclav Hapla SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 498952f91c60SVaclav Hapla #endif 499052f91c60SVaclav Hapla } else { 499198921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "Viewer type %s not yet supported for reading %s matrices", ((PetscObject)viewer)->type_name, ((PetscObject)newMat)->type_name); 499252f91c60SVaclav Hapla } 49933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 499452f91c60SVaclav Hapla } 499552f91c60SVaclav Hapla 4996d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer) 4997d71ae5a4SJacob Faibussowitsch { 49983ea6fe3dSLisandro Dalcin Mat_SeqAIJ *a = (Mat_SeqAIJ *)mat->data; 49993ea6fe3dSLisandro Dalcin PetscInt header[4], *rowlens, M, N, nz, sum, rows, cols, i; 5000fbdbba38SShri Abhyankar 5001fbdbba38SShri Abhyankar PetscFunctionBegin; 50029566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 5003bbead8a2SBarry Smith 50043ea6fe3dSLisandro Dalcin /* read in matrix header */ 50059566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT)); 500608401ef6SPierre Jolivet PetscCheck(header[0] == MAT_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file"); 50079371c9d4SSatish Balay M = header[1]; 50089371c9d4SSatish Balay N = header[2]; 50099371c9d4SSatish Balay nz = header[3]; 501008401ef6SPierre Jolivet PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M); 501108401ef6SPierre Jolivet PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N); 501208401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Matrix stored in special format on disk, cannot load as SeqAIJ"); 5013fbdbba38SShri Abhyankar 50143ea6fe3dSLisandro Dalcin /* set block sizes from the viewer's .info file */ 50159566063dSJacob Faibussowitsch PetscCall(MatLoad_Binary_BlockSizes(mat, viewer)); 50163ea6fe3dSLisandro Dalcin /* set local and global sizes if not set already */ 50173ea6fe3dSLisandro Dalcin if (mat->rmap->n < 0) mat->rmap->n = M; 50183ea6fe3dSLisandro Dalcin if (mat->cmap->n < 0) mat->cmap->n = N; 50193ea6fe3dSLisandro Dalcin if (mat->rmap->N < 0) mat->rmap->N = M; 50203ea6fe3dSLisandro Dalcin if (mat->cmap->N < 0) mat->cmap->N = N; 50219566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->rmap)); 50229566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->cmap)); 50233ea6fe3dSLisandro Dalcin 50243ea6fe3dSLisandro Dalcin /* check if the matrix sizes are correct */ 50259566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 5026aed4548fSBarry Smith PetscCheck(M == rows && N == cols, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different sizes (%" PetscInt_FMT ", %" PetscInt_FMT ") than the input matrix (%" PetscInt_FMT ", %" PetscInt_FMT ")", M, N, rows, cols); 50273ea6fe3dSLisandro Dalcin 5028fbdbba38SShri Abhyankar /* read in row lengths */ 50299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(M, &rowlens)); 50309566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, rowlens, M, NULL, PETSC_INT)); 50313ea6fe3dSLisandro Dalcin /* check if sum(rowlens) is same as nz */ 50329371c9d4SSatish Balay sum = 0; 50339371c9d4SSatish Balay for (i = 0; i < M; i++) sum += rowlens[i]; 503408401ef6SPierre Jolivet PetscCheck(sum == nz, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Inconsistent matrix data in file: nonzeros = %" PetscInt_FMT ", sum-row-lengths = %" PetscInt_FMT, nz, sum); 50353ea6fe3dSLisandro Dalcin /* preallocate and check sizes */ 50369566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(mat, 0, rowlens)); 50379566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 5038aed4548fSBarry Smith PetscCheck(M == rows && N == cols, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%" PetscInt_FMT ", %" PetscInt_FMT ") than the input matrix (%" PetscInt_FMT ", %" PetscInt_FMT ")", M, N, rows, cols); 50393ea6fe3dSLisandro Dalcin /* store row lengths */ 50409566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->ilen, rowlens, M)); 50419566063dSJacob Faibussowitsch PetscCall(PetscFree(rowlens)); 5042fbdbba38SShri Abhyankar 50433ea6fe3dSLisandro Dalcin /* fill in "i" row pointers */ 50449371c9d4SSatish Balay a->i[0] = 0; 50459371c9d4SSatish Balay for (i = 0; i < M; i++) a->i[i + 1] = a->i[i] + a->ilen[i]; 50463ea6fe3dSLisandro Dalcin /* read in "j" column indices */ 50479566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, a->j, nz, NULL, PETSC_INT)); 50483ea6fe3dSLisandro Dalcin /* read in "a" nonzero values */ 50499566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, a->a, nz, NULL, PETSC_SCALAR)); 5050fbdbba38SShri Abhyankar 50519566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 50529566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 50533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5054fbdbba38SShri Abhyankar } 5055fbdbba38SShri Abhyankar 5056d71ae5a4SJacob Faibussowitsch PetscErrorCode MatEqual_SeqAIJ(Mat A, Mat B, PetscBool *flg) 5057d71ae5a4SJacob Faibussowitsch { 50587264ac53SSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data, *b = (Mat_SeqAIJ *)B->data; 5059fff043a9SJunchao Zhang const PetscScalar *aa, *ba; 5060eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 5061eeffb40dSHong Zhang PetscInt k; 5062eeffb40dSHong Zhang #endif 50637264ac53SSatish Balay 50643a40ed3dSBarry Smith PetscFunctionBegin; 5065bfeeae90SHong Zhang /* If the matrix dimensions are not equal,or no of nonzeros */ 5066d0f46423SBarry Smith if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) || (a->nz != b->nz)) { 5067ca44d042SBarry Smith *flg = PETSC_FALSE; 50683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5069bcd2baecSBarry Smith } 50707264ac53SSatish Balay 50717264ac53SSatish Balay /* if the a->i are the same */ 50729566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->i, b->i, A->rmap->n + 1, flg)); 50733ba16761SJacob Faibussowitsch if (!*flg) PetscFunctionReturn(PETSC_SUCCESS); 50747264ac53SSatish Balay 50757264ac53SSatish Balay /* if a->j are the same */ 50769566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->j, b->j, a->nz, flg)); 50773ba16761SJacob Faibussowitsch if (!*flg) PetscFunctionReturn(PETSC_SUCCESS); 5078bcd2baecSBarry Smith 50799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 50809566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &ba)); 5081bcd2baecSBarry Smith /* if a->a are the same */ 5082eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 5083eeffb40dSHong Zhang for (k = 0; k < a->nz; k++) { 5084fff043a9SJunchao Zhang if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) { 5085eeffb40dSHong Zhang *flg = PETSC_FALSE; 50863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5087eeffb40dSHong Zhang } 5088eeffb40dSHong Zhang } 5089eeffb40dSHong Zhang #else 50909566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(aa, ba, a->nz, flg)); 5091eeffb40dSHong Zhang #endif 50929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 50939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &ba)); 50943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50957264ac53SSatish Balay } 509636db0b34SBarry Smith 509705869f15SSatish Balay /*@ 509811a5261eSBarry Smith MatCreateSeqAIJWithArrays - Creates an sequential `MATSEQAIJ` matrix using matrix elements (in CSR format) 509936db0b34SBarry Smith provided by the user. 510036db0b34SBarry Smith 5101d083f849SBarry Smith Collective 510236db0b34SBarry Smith 510336db0b34SBarry Smith Input Parameters: 510436db0b34SBarry Smith + comm - must be an MPI communicator of size 1 510536db0b34SBarry Smith . m - number of rows 510636db0b34SBarry Smith . n - number of columns 5107483a2f95SBarry Smith . i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 510836db0b34SBarry Smith . j - column indices 510936db0b34SBarry Smith - a - matrix values 511036db0b34SBarry Smith 511136db0b34SBarry Smith Output Parameter: 511236db0b34SBarry Smith . mat - the matrix 511336db0b34SBarry Smith 511436db0b34SBarry Smith Level: intermediate 511536db0b34SBarry Smith 511636db0b34SBarry Smith Notes: 51172ef1f0ffSBarry Smith The `i`, `j`, and `a` arrays are not copied by this routine, the user must free these arrays 5118292fb18eSBarry Smith once the matrix is destroyed and not before 511936db0b34SBarry Smith 512036db0b34SBarry Smith You cannot set new nonzero locations into this matrix, that will generate an error. 512136db0b34SBarry Smith 51222ef1f0ffSBarry Smith The `i` and `j` indices are 0 based 512336db0b34SBarry Smith 5124a4552177SSatish Balay The format which is used for the sparse matrix input, is equivalent to a 5125a4552177SSatish Balay row-major ordering.. i.e for the following matrix, the input data expected is 51268eef79e4SBarry Smith as shown 51272ef1f0ffSBarry Smith .vb 51282ef1f0ffSBarry Smith 1 0 0 51292ef1f0ffSBarry Smith 2 0 3 51302ef1f0ffSBarry Smith 4 5 6 5131a4552177SSatish Balay 51322ef1f0ffSBarry Smith i = {0,1,3,6} [size = nrow+1 = 3+1] 51332ef1f0ffSBarry Smith j = {0,0,2,0,1,2} [size = 6]; values must be sorted for each row 51342ef1f0ffSBarry Smith v = {1,2,3,4,5,6} [size = 6] 51352ef1f0ffSBarry Smith .ve 5136a4552177SSatish Balay 51371cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateMPIAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()` 513836db0b34SBarry Smith @*/ 5139d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat) 5140d71ae5a4SJacob Faibussowitsch { 5141cbcfb4deSHong Zhang PetscInt ii; 514236db0b34SBarry Smith Mat_SeqAIJ *aij; 5143cbcfb4deSHong Zhang PetscInt jj; 514436db0b34SBarry Smith 514536db0b34SBarry Smith PetscFunctionBegin; 5146aed4548fSBarry Smith PetscCheck(m <= 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0"); 51479566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 51489566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 51499566063dSJacob Faibussowitsch /* PetscCall(MatSetBlockSizes(*mat,,)); */ 51509566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQAIJ)); 51519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, MAT_SKIP_ALLOCATION, NULL)); 5152ab93d7beSBarry Smith aij = (Mat_SeqAIJ *)(*mat)->data; 51539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &aij->imax)); 51549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &aij->ilen)); 5155ab93d7beSBarry Smith 515636db0b34SBarry Smith aij->i = i; 515736db0b34SBarry Smith aij->j = j; 515836db0b34SBarry Smith aij->a = a; 515936db0b34SBarry Smith aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 5160e6b907acSBarry Smith aij->free_a = PETSC_FALSE; 5161e6b907acSBarry Smith aij->free_ij = PETSC_FALSE; 516236db0b34SBarry Smith 5163cbc6b225SStefano Zampini for (ii = 0, aij->nonzerorowcnt = 0, aij->rmax = 0; ii < m; ii++) { 516436db0b34SBarry Smith aij->ilen[ii] = aij->imax[ii] = i[ii + 1] - i[ii]; 516576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 5166aed4548fSBarry Smith PetscCheck(i[ii + 1] - i[ii] >= 0, 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]); 51679985e31cSBarry Smith for (jj = i[ii] + 1; jj < i[ii + 1]; jj++) { 516808401ef6SPierre Jolivet PetscCheck(j[jj] >= j[jj - 1], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column entry number %" PetscInt_FMT " (actual column %" PetscInt_FMT ") in row %" PetscInt_FMT " is not sorted", jj - i[ii], j[jj], ii); 516908401ef6SPierre Jolivet PetscCheck(j[jj] != j[jj - 1], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column entry number %" PetscInt_FMT " (actual column %" PetscInt_FMT ") in row %" PetscInt_FMT " is identical to previous entry", jj - i[ii], j[jj], ii); 51709985e31cSBarry Smith } 517136db0b34SBarry Smith } 517276bd3646SJed Brown } 517376bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 517436db0b34SBarry Smith for (ii = 0; ii < aij->i[m]; ii++) { 517508401ef6SPierre Jolivet PetscCheck(j[ii] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative column index at location = %" PetscInt_FMT " index = %" PetscInt_FMT, ii, j[ii]); 5176da0802e2SStefano Zampini PetscCheck(j[ii] <= n - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column index to large at location = %" PetscInt_FMT " index = %" PetscInt_FMT " last column = %" PetscInt_FMT, ii, j[ii], n - 1); 517736db0b34SBarry Smith } 517876bd3646SJed Brown } 517936db0b34SBarry Smith 51809566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 51819566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 51823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 518336db0b34SBarry Smith } 5184cbc6b225SStefano Zampini 5185f62e3866SBarry Smith /*@ 518611a5261eSBarry Smith MatCreateSeqAIJFromTriple - Creates an sequential `MATSEQAIJ` matrix using matrix elements (in COO format) 51878a0b0e6bSVictor Minden provided by the user. 51888a0b0e6bSVictor Minden 5189d083f849SBarry Smith Collective 51908a0b0e6bSVictor Minden 51918a0b0e6bSVictor Minden Input Parameters: 51928a0b0e6bSVictor Minden + comm - must be an MPI communicator of size 1 51938a0b0e6bSVictor Minden . m - number of rows 51948a0b0e6bSVictor Minden . n - number of columns 51958a0b0e6bSVictor Minden . i - row indices 51968a0b0e6bSVictor Minden . j - column indices 51971230e6d1SVictor Minden . a - matrix values 51981230e6d1SVictor Minden . nz - number of nonzeros 51992ef1f0ffSBarry Smith - idx - if the `i` and `j` indices start with 1 use `PETSC_TRUE` otherwise use `PETSC_FALSE` 52008a0b0e6bSVictor Minden 52018a0b0e6bSVictor Minden Output Parameter: 52028a0b0e6bSVictor Minden . mat - the matrix 52038a0b0e6bSVictor Minden 52048a0b0e6bSVictor Minden Level: intermediate 52058a0b0e6bSVictor Minden 5206f62e3866SBarry Smith Example: 5207f62e3866SBarry Smith For the following matrix, the input data expected is as shown (using 0 based indexing) 52089e99939fSJunchao Zhang .vb 52098a0b0e6bSVictor Minden 1 0 0 52108a0b0e6bSVictor Minden 2 0 3 52118a0b0e6bSVictor Minden 4 5 6 52128a0b0e6bSVictor Minden 52138a0b0e6bSVictor Minden i = {0,1,1,2,2,2} 52148a0b0e6bSVictor Minden j = {0,0,2,0,1,2} 52158a0b0e6bSVictor Minden v = {1,2,3,4,5,6} 52169e99939fSJunchao Zhang .ve 5217fe59aa6dSJacob Faibussowitsch 52182ef1f0ffSBarry Smith Note: 5219d7547e51SJunchao Zhang Instead of using this function, users should also consider `MatSetPreallocationCOO()` and `MatSetValuesCOO()`, which allow repeated or remote entries, 5220d7547e51SJunchao Zhang and are particularly useful in iterative applications. 52218a0b0e6bSVictor Minden 52221cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateSeqAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()`, `MatSetValuesCOO()`, `MatSetPreallocationCOO()` 52238a0b0e6bSVictor Minden @*/ 5224ce78bad3SBarry Smith PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat, PetscCount nz, PetscBool idx) 5225d71ae5a4SJacob Faibussowitsch { 5226d021a1c5SVictor Minden PetscInt ii, *nnz, one = 1, row, col; 52278a0b0e6bSVictor Minden 52288a0b0e6bSVictor Minden PetscFunctionBegin; 52299566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m, &nnz)); 5230ad540459SPierre Jolivet for (ii = 0; ii < nz; ii++) nnz[i[ii] - !!idx] += 1; 52319566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 52329566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 52339566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQAIJ)); 52349566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, 0, nnz)); 52351230e6d1SVictor Minden for (ii = 0; ii < nz; ii++) { 52361230e6d1SVictor Minden if (idx) { 52371230e6d1SVictor Minden row = i[ii] - 1; 52381230e6d1SVictor Minden col = j[ii] - 1; 52391230e6d1SVictor Minden } else { 52401230e6d1SVictor Minden row = i[ii]; 52411230e6d1SVictor Minden col = j[ii]; 52428a0b0e6bSVictor Minden } 52439566063dSJacob Faibussowitsch PetscCall(MatSetValues(*mat, one, &row, one, &col, &a[ii], ADD_VALUES)); 52448a0b0e6bSVictor Minden } 52459566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 52469566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 52479566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 52483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52498a0b0e6bSVictor Minden } 525036db0b34SBarry Smith 5251d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat) 5252d71ae5a4SJacob Faibussowitsch { 52539c8f2541SHong Zhang PetscFunctionBegin; 52549566063dSJacob Faibussowitsch PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm, inmat, n, scall, outmat)); 52553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52569c8f2541SHong Zhang } 52579c8f2541SHong Zhang 525881824310SBarry Smith /* 525953dd7562SDmitry Karpeev Permute A into C's *local* index space using rowemb,colemb. 526053dd7562SDmitry Karpeev The embedding are supposed to be injections and the above implies that the range of rowemb is a subset 526153dd7562SDmitry Karpeev of [0,m), colemb is in [0,n). 526253dd7562SDmitry Karpeev If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A. 526353dd7562SDmitry Karpeev */ 5264d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C, IS rowemb, IS colemb, MatStructure pattern, Mat B) 5265d71ae5a4SJacob Faibussowitsch { 526653dd7562SDmitry Karpeev /* If making this function public, change the error returned in this function away from _PLIB. */ 526753dd7562SDmitry Karpeev Mat_SeqAIJ *Baij; 526853dd7562SDmitry Karpeev PetscBool seqaij; 526953dd7562SDmitry Karpeev PetscInt m, n, *nz, i, j, count; 527053dd7562SDmitry Karpeev PetscScalar v; 527153dd7562SDmitry Karpeev const PetscInt *rowindices, *colindices; 527253dd7562SDmitry Karpeev 527353dd7562SDmitry Karpeev PetscFunctionBegin; 52743ba16761SJacob Faibussowitsch if (!B) PetscFunctionReturn(PETSC_SUCCESS); 527553dd7562SDmitry Karpeev /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */ 52769566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)B, MATSEQAIJ, &seqaij)); 527728b400f6SJacob Faibussowitsch PetscCheck(seqaij, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is of wrong type"); 527853dd7562SDmitry Karpeev if (rowemb) { 52799566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rowemb, &m)); 528008401ef6SPierre Jolivet PetscCheck(m == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Row IS of size %" PetscInt_FMT " is incompatible with matrix row size %" PetscInt_FMT, m, B->rmap->n); 528153dd7562SDmitry Karpeev } else { 528208401ef6SPierre Jolivet PetscCheck(C->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is row-incompatible with the target matrix"); 528353dd7562SDmitry Karpeev } 528453dd7562SDmitry Karpeev if (colemb) { 52859566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(colemb, &n)); 528608401ef6SPierre Jolivet PetscCheck(n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Diag col IS of size %" PetscInt_FMT " is incompatible with input matrix col size %" PetscInt_FMT, n, B->cmap->n); 528753dd7562SDmitry Karpeev } else { 528808401ef6SPierre Jolivet PetscCheck(C->cmap->n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is col-incompatible with the target matrix"); 528953dd7562SDmitry Karpeev } 529053dd7562SDmitry Karpeev 5291f4f49eeaSPierre Jolivet Baij = (Mat_SeqAIJ *)B->data; 529253dd7562SDmitry Karpeev if (pattern == DIFFERENT_NONZERO_PATTERN) { 52939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n, &nz)); 5294ad540459SPierre Jolivet for (i = 0; i < B->rmap->n; i++) nz[i] = Baij->i[i + 1] - Baij->i[i]; 52959566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(C, 0, nz)); 52969566063dSJacob Faibussowitsch PetscCall(PetscFree(nz)); 529753dd7562SDmitry Karpeev } 529848a46eb9SPierre Jolivet if (pattern == SUBSET_NONZERO_PATTERN) PetscCall(MatZeroEntries(C)); 529953dd7562SDmitry Karpeev count = 0; 530053dd7562SDmitry Karpeev rowindices = NULL; 530153dd7562SDmitry Karpeev colindices = NULL; 530248a46eb9SPierre Jolivet if (rowemb) PetscCall(ISGetIndices(rowemb, &rowindices)); 530348a46eb9SPierre Jolivet if (colemb) PetscCall(ISGetIndices(colemb, &colindices)); 530453dd7562SDmitry Karpeev for (i = 0; i < B->rmap->n; i++) { 530553dd7562SDmitry Karpeev PetscInt row; 530653dd7562SDmitry Karpeev row = i; 530753dd7562SDmitry Karpeev if (rowindices) row = rowindices[i]; 530853dd7562SDmitry Karpeev for (j = Baij->i[i]; j < Baij->i[i + 1]; j++) { 530953dd7562SDmitry Karpeev PetscInt col; 531053dd7562SDmitry Karpeev col = Baij->j[count]; 531153dd7562SDmitry Karpeev if (colindices) col = colindices[col]; 531253dd7562SDmitry Karpeev v = Baij->a[count]; 53139566063dSJacob Faibussowitsch PetscCall(MatSetValues(C, 1, &row, 1, &col, &v, INSERT_VALUES)); 531453dd7562SDmitry Karpeev ++count; 531553dd7562SDmitry Karpeev } 531653dd7562SDmitry Karpeev } 531753dd7562SDmitry Karpeev /* FIXME: set C's nonzerostate correctly. */ 531853dd7562SDmitry Karpeev /* Assembly for C is necessary. */ 531953dd7562SDmitry Karpeev C->preallocated = PETSC_TRUE; 532053dd7562SDmitry Karpeev C->assembled = PETSC_TRUE; 532153dd7562SDmitry Karpeev C->was_assembled = PETSC_FALSE; 53223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 532353dd7562SDmitry Karpeev } 532453dd7562SDmitry Karpeev 532558c11ad4SPierre Jolivet PetscErrorCode MatEliminateZeros_SeqAIJ(Mat A, PetscBool keep) 5326dec0b466SHong Zhang { 5327dec0b466SHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 5328dec0b466SHong Zhang MatScalar *aa = a->a; 5329dec0b466SHong Zhang PetscInt m = A->rmap->n, fshift = 0, fshift_prev = 0, i, k; 5330dec0b466SHong Zhang PetscInt *ailen = a->ilen, *imax = a->imax, *ai = a->i, *aj = a->j, rmax = 0; 5331dec0b466SHong Zhang 5332dec0b466SHong Zhang PetscFunctionBegin; 5333dec0b466SHong Zhang PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot eliminate zeros for unassembled matrix"); 5334dec0b466SHong Zhang if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 5335dec0b466SHong Zhang for (i = 1; i <= m; i++) { 5336dec0b466SHong Zhang /* move each nonzero entry back by the amount of zero slots (fshift) before it*/ 5337dec0b466SHong Zhang for (k = ai[i - 1]; k < ai[i]; k++) { 533858c11ad4SPierre Jolivet if (aa[k] == 0 && (aj[k] != i - 1 || !keep)) fshift++; 5339dec0b466SHong Zhang else { 5340dec0b466SHong Zhang if (aa[k] == 0 && aj[k] == i - 1) PetscCall(PetscInfo(A, "Keep the diagonal zero at row %" PetscInt_FMT "\n", i - 1)); 5341dec0b466SHong Zhang aa[k - fshift] = aa[k]; 5342dec0b466SHong Zhang aj[k - fshift] = aj[k]; 5343dec0b466SHong Zhang } 5344dec0b466SHong Zhang } 5345dec0b466SHong Zhang ai[i - 1] -= fshift_prev; // safe to update ai[i-1] now since it will not be used in the next iteration 5346dec0b466SHong Zhang fshift_prev = fshift; 5347dec0b466SHong Zhang /* reset ilen and imax for each row */ 5348dec0b466SHong Zhang ailen[i - 1] = imax[i - 1] = ai[i] - fshift - ai[i - 1]; 5349dec0b466SHong Zhang a->nonzerorowcnt += ((ai[i] - fshift - ai[i - 1]) > 0); 5350dec0b466SHong Zhang rmax = PetscMax(rmax, ailen[i - 1]); 5351dec0b466SHong Zhang } 5352312eded4SPierre Jolivet if (fshift) { 5353dec0b466SHong Zhang if (m) { 5354dec0b466SHong Zhang ai[m] -= fshift; 5355dec0b466SHong Zhang a->nz = ai[m]; 5356dec0b466SHong Zhang } 5357dec0b466SHong Zhang 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)); 5358312eded4SPierre Jolivet A->nonzerostate++; 5359dec0b466SHong Zhang A->info.nz_unneeded += (PetscReal)fshift; 5360dec0b466SHong Zhang a->rmax = rmax; 5361dec0b466SHong Zhang if (a->inode.use && a->inode.checked) PetscCall(MatSeqAIJCheckInode(A)); 5362dec0b466SHong Zhang PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 5363dec0b466SHong Zhang PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 5364312eded4SPierre Jolivet } 53653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5366dec0b466SHong Zhang } 5367dec0b466SHong Zhang 53684099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL; 53694099cc6bSBarry Smith 5370cc4c1da9SBarry Smith /*@ 537111a5261eSBarry Smith MatSeqAIJSetType - Converts a `MATSEQAIJ` matrix to a subtype 53724099cc6bSBarry Smith 5373c3339decSBarry Smith Collective 53744099cc6bSBarry Smith 53754099cc6bSBarry Smith Input Parameters: 53764099cc6bSBarry Smith + mat - the matrix object 53774099cc6bSBarry Smith - matype - matrix type 53784099cc6bSBarry Smith 53794099cc6bSBarry Smith Options Database Key: 53804e187271SRichard Tran Mills . -mat_seqaij_type <method> - for example seqaijcrl 53814099cc6bSBarry Smith 53824099cc6bSBarry Smith Level: intermediate 53834099cc6bSBarry Smith 5384fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType` 53854099cc6bSBarry Smith @*/ 5386d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetType(Mat mat, MatType matype) 5387d71ae5a4SJacob Faibussowitsch { 53884099cc6bSBarry Smith PetscBool sametype; 53895f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(Mat, MatType, MatReuse, Mat *); 53904099cc6bSBarry Smith 53914099cc6bSBarry Smith PetscFunctionBegin; 53924099cc6bSBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 53939566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, matype, &sametype)); 53943ba16761SJacob Faibussowitsch if (sametype) PetscFunctionReturn(PETSC_SUCCESS); 53954099cc6bSBarry Smith 53969566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(MatSeqAIJList, matype, &r)); 53976adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Mat type given: %s", matype); 53989566063dSJacob Faibussowitsch PetscCall((*r)(mat, matype, MAT_INPLACE_MATRIX, &mat)); 53993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54004099cc6bSBarry Smith } 54014099cc6bSBarry Smith 54024099cc6bSBarry Smith /*@C 540311a5261eSBarry Smith MatSeqAIJRegister - - Adds a new sub-matrix type for sequential `MATSEQAIJ` matrices 54044099cc6bSBarry Smith 5405cc4c1da9SBarry Smith Not Collective, No Fortran Support 54064099cc6bSBarry Smith 54074099cc6bSBarry Smith Input Parameters: 5408fe59aa6dSJacob Faibussowitsch + sname - name of a new user-defined matrix type, for example `MATSEQAIJCRL` 54094099cc6bSBarry Smith - function - routine to convert to subtype 54104099cc6bSBarry Smith 54112ef1f0ffSBarry Smith Level: advanced 54122ef1f0ffSBarry Smith 54134099cc6bSBarry Smith Notes: 541411a5261eSBarry Smith `MatSeqAIJRegister()` may be called multiple times to add several user-defined solvers. 54154099cc6bSBarry Smith 54164099cc6bSBarry Smith Then, your matrix can be chosen with the procedural interface at runtime via the option 5417b44f4de4SBarry Smith .vb 5418b44f4de4SBarry Smith -mat_seqaij_type my_mat 5419b44f4de4SBarry Smith .ve 54204099cc6bSBarry Smith 54211cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRegisterAll()` 54224099cc6bSBarry Smith @*/ 5423d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJRegister(const char sname[], PetscErrorCode (*function)(Mat, MatType, MatReuse, Mat *)) 5424d71ae5a4SJacob Faibussowitsch { 54254099cc6bSBarry Smith PetscFunctionBegin; 54269566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 54279566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&MatSeqAIJList, sname, function)); 54283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54294099cc6bSBarry Smith } 54304099cc6bSBarry Smith 54314099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE; 54324099cc6bSBarry Smith 54334099cc6bSBarry Smith /*@C 543411a5261eSBarry Smith MatSeqAIJRegisterAll - Registers all of the matrix subtypes of `MATSSEQAIJ` 54354099cc6bSBarry Smith 54364099cc6bSBarry Smith Not Collective 54374099cc6bSBarry Smith 54384099cc6bSBarry Smith Level: advanced 54394099cc6bSBarry Smith 54402ef1f0ffSBarry Smith Note: 54412ef1f0ffSBarry Smith This registers the versions of `MATSEQAIJ` for GPUs 54422ef1f0ffSBarry Smith 54431cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatRegisterAll()`, `MatSeqAIJRegister()` 54444099cc6bSBarry Smith @*/ 5445d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJRegisterAll(void) 5446d71ae5a4SJacob Faibussowitsch { 54474099cc6bSBarry Smith PetscFunctionBegin; 54483ba16761SJacob Faibussowitsch if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS); 54494099cc6bSBarry Smith MatSeqAIJRegisterAllCalled = PETSC_TRUE; 54504099cc6bSBarry Smith 54519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCRL, MatConvert_SeqAIJ_SeqAIJCRL)); 54529566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJPERM, MatConvert_SeqAIJ_SeqAIJPERM)); 54539566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJSELL, MatConvert_SeqAIJ_SeqAIJSELL)); 54549779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 54559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJMKL, MatConvert_SeqAIJ_SeqAIJMKL)); 5456485f9817SRichard Tran Mills #endif 54575063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA) 54589566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 54595063d097SStefano Zampini #endif 5460d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_HIP) 5461d5e393b6SSuyash Tandon PetscCall(MatSeqAIJRegister(MATSEQAIJHIPSPARSE, MatConvert_SeqAIJ_SeqAIJHIPSPARSE)); 5462d5e393b6SSuyash Tandon #endif 54635063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 54649566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJKOKKOS, MatConvert_SeqAIJ_SeqAIJKokkos)); 54655063d097SStefano Zampini #endif 54664099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA) 54679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL)); 54684099cc6bSBarry Smith #endif 54693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54704099cc6bSBarry Smith } 547153dd7562SDmitry Karpeev 547253dd7562SDmitry Karpeev /* 547381824310SBarry Smith Special version for direct calls from Fortran 547481824310SBarry Smith */ 547581824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS) 547681824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ 547781824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 547881824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij 547981824310SBarry Smith #endif 548081824310SBarry Smith 548181824310SBarry Smith /* Change these macros so can be used in void function */ 548298921bdaSJacob Faibussowitsch 548398921bdaSJacob Faibussowitsch /* Change these macros so can be used in void function */ 54849566063dSJacob Faibussowitsch /* Identical to PetscCallVoid, except it assigns to *_ierr */ 54859566063dSJacob Faibussowitsch #undef PetscCall 54869371c9d4SSatish Balay #define PetscCall(...) \ 54879371c9d4SSatish Balay do { \ 54885f80ce2aSJacob Faibussowitsch PetscErrorCode ierr_msv_mpiaij = __VA_ARGS__; \ 548998921bdaSJacob Faibussowitsch if (PetscUnlikely(ierr_msv_mpiaij)) { \ 549098921bdaSJacob Faibussowitsch *_ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr_msv_mpiaij, PETSC_ERROR_REPEAT, " "); \ 549198921bdaSJacob Faibussowitsch return; \ 549298921bdaSJacob Faibussowitsch } \ 549398921bdaSJacob Faibussowitsch } while (0) 549498921bdaSJacob Faibussowitsch 549598921bdaSJacob Faibussowitsch #undef SETERRQ 54969371c9d4SSatish Balay #define SETERRQ(comm, ierr, ...) \ 54979371c9d4SSatish Balay do { \ 549898921bdaSJacob Faibussowitsch *_ierr = PetscError(comm, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr, PETSC_ERROR_INITIAL, __VA_ARGS__); \ 549998921bdaSJacob Faibussowitsch return; \ 550098921bdaSJacob Faibussowitsch } while (0) 550181824310SBarry Smith 5502d71ae5a4SJacob Faibussowitsch PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA, PetscInt *mm, const PetscInt im[], PetscInt *nn, const PetscInt in[], const PetscScalar v[], InsertMode *isis, PetscErrorCode *_ierr) 5503d71ae5a4SJacob Faibussowitsch { 550481824310SBarry Smith Mat A = *AA; 550581824310SBarry Smith PetscInt m = *mm, n = *nn; 550681824310SBarry Smith InsertMode is = *isis; 550781824310SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 550881824310SBarry Smith PetscInt *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N; 550981824310SBarry Smith PetscInt *imax, *ai, *ailen; 551081824310SBarry Smith PetscInt *aj, nonew = a->nonew, lastcol = -1; 551154f21887SBarry Smith MatScalar *ap, value, *aa; 5512ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 5513ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 551481824310SBarry Smith 551581824310SBarry Smith PetscFunctionBegin; 55164994cf47SJed Brown MatCheckPreallocated(A, 1); 551781824310SBarry Smith imax = a->imax; 551881824310SBarry Smith ai = a->i; 551981824310SBarry Smith ailen = a->ilen; 552081824310SBarry Smith aj = a->j; 552181824310SBarry Smith aa = a->a; 552281824310SBarry Smith 552381824310SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 552481824310SBarry Smith row = im[k]; 552581824310SBarry Smith if (row < 0) continue; 55265f80ce2aSJacob Faibussowitsch PetscCheck(row < A->rmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Row too large"); 55279371c9d4SSatish Balay rp = aj + ai[row]; 55289371c9d4SSatish Balay ap = aa + ai[row]; 55299371c9d4SSatish Balay rmax = imax[row]; 55309371c9d4SSatish Balay nrow = ailen[row]; 553181824310SBarry Smith low = 0; 553281824310SBarry Smith high = nrow; 553381824310SBarry Smith for (l = 0; l < n; l++) { /* loop over added columns */ 553481824310SBarry Smith if (in[l] < 0) continue; 55355f80ce2aSJacob Faibussowitsch PetscCheck(in[l] < A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Column too large"); 553681824310SBarry Smith col = in[l]; 55372205254eSKarl Rupp if (roworiented) value = v[l + k * n]; 55382205254eSKarl Rupp else value = v[k + l * m]; 55392205254eSKarl Rupp 554081824310SBarry Smith if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 554181824310SBarry Smith 55422205254eSKarl Rupp if (col <= lastcol) low = 0; 55432205254eSKarl Rupp else high = nrow; 554481824310SBarry Smith lastcol = col; 554581824310SBarry Smith while (high - low > 5) { 554681824310SBarry Smith t = (low + high) / 2; 554781824310SBarry Smith if (rp[t] > col) high = t; 554881824310SBarry Smith else low = t; 554981824310SBarry Smith } 555081824310SBarry Smith for (i = low; i < high; i++) { 555181824310SBarry Smith if (rp[i] > col) break; 555281824310SBarry Smith if (rp[i] == col) { 555381824310SBarry Smith if (is == ADD_VALUES) ap[i] += value; 555481824310SBarry Smith else ap[i] = value; 555581824310SBarry Smith goto noinsert; 555681824310SBarry Smith } 555781824310SBarry Smith } 555881824310SBarry Smith if (value == 0.0 && ignorezeroentries) goto noinsert; 555981824310SBarry Smith if (nonew == 1) goto noinsert; 55605f80ce2aSJacob Faibussowitsch PetscCheck(nonew != -1, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero in the matrix"); 5561fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, A->rmap->n, 1, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 55629371c9d4SSatish Balay N = nrow++ - 1; 55639371c9d4SSatish Balay a->nz++; 55649371c9d4SSatish Balay high++; 556581824310SBarry Smith /* shift up all the later entries in this row */ 556681824310SBarry Smith for (ii = N; ii >= i; ii--) { 556781824310SBarry Smith rp[ii + 1] = rp[ii]; 556881824310SBarry Smith ap[ii + 1] = ap[ii]; 556981824310SBarry Smith } 557081824310SBarry Smith rp[i] = col; 557181824310SBarry Smith ap[i] = value; 557281824310SBarry Smith noinsert:; 557381824310SBarry Smith low = i + 1; 557481824310SBarry Smith } 557581824310SBarry Smith ailen[row] = nrow; 557681824310SBarry Smith } 557781824310SBarry Smith PetscFunctionReturnVoid(); 557881824310SBarry Smith } 557998921bdaSJacob Faibussowitsch /* Undefining these here since they were redefined from their original definition above! No 558098921bdaSJacob Faibussowitsch * other PETSc functions should be defined past this point, as it is impossible to recover the 558198921bdaSJacob Faibussowitsch * original definitions */ 55829566063dSJacob Faibussowitsch #undef PetscCall 558398921bdaSJacob Faibussowitsch #undef SETERRQ 5584