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 19d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A) 20d71ae5a4SJacob Faibussowitsch { 214099cc6bSBarry Smith PetscBool flg; 224099cc6bSBarry Smith char type[256]; 234099cc6bSBarry Smith 244099cc6bSBarry Smith PetscFunctionBegin; 25d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)A); 269566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-mat_seqaij_type", "Matrix SeqAIJ type", "MatSeqAIJSetType", MatSeqAIJList, "seqaij", type, 256, &flg)); 279566063dSJacob Faibussowitsch if (flg) PetscCall(MatSeqAIJSetType(A, type)); 28d0609cedSBarry Smith PetscOptionsEnd(); 293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 304099cc6bSBarry Smith } 314099cc6bSBarry Smith 32d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnReductions_SeqAIJ(Mat A, PetscInt type, PetscReal *reductions) 33d71ae5a4SJacob Faibussowitsch { 340716a85fSBarry Smith PetscInt i, m, n; 350716a85fSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 360716a85fSBarry Smith 370716a85fSBarry Smith PetscFunctionBegin; 389566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &m, &n)); 399566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(reductions, n)); 400716a85fSBarry Smith if (type == NORM_2) { 41ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscAbsScalar(aij->a[i] * aij->a[i]); 420716a85fSBarry Smith } else if (type == NORM_1) { 43ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]); 440716a85fSBarry Smith } else if (type == NORM_INFINITY) { 45ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]), reductions[aij->j[i]]); 46857cbf51SRichard Tran Mills } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) { 47ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscRealPart(aij->a[i]); 48857cbf51SRichard Tran Mills } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) { 49ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscImaginaryPart(aij->a[i]); 50857cbf51SRichard Tran Mills } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown reduction type"); 510716a85fSBarry Smith 520716a85fSBarry Smith if (type == NORM_2) { 53a873a8cdSSam Reynolds for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]); 54857cbf51SRichard Tran Mills } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) { 55a873a8cdSSam Reynolds for (i = 0; i < n; i++) reductions[i] /= m; 560716a85fSBarry Smith } 573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 580716a85fSBarry Smith } 590716a85fSBarry Smith 60d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A, IS *is) 61d71ae5a4SJacob Faibussowitsch { 623a062f41SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 633a062f41SBarry Smith PetscInt i, m = A->rmap->n, cnt = 0, bs = A->rmap->bs; 643a062f41SBarry Smith const PetscInt *jj = a->j, *ii = a->i; 653a062f41SBarry Smith PetscInt *rows; 663a062f41SBarry Smith 673a062f41SBarry Smith PetscFunctionBegin; 683a062f41SBarry Smith for (i = 0; i < m; i++) { 69ad540459SPierre Jolivet if ((ii[i] != ii[i + 1]) && ((jj[ii[i]] < bs * (i / bs)) || (jj[ii[i + 1] - 1] > bs * ((i + bs) / bs) - 1))) cnt++; 703a062f41SBarry Smith } 719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cnt, &rows)); 723a062f41SBarry Smith cnt = 0; 733a062f41SBarry Smith for (i = 0; i < m; i++) { 743a062f41SBarry Smith if ((ii[i] != ii[i + 1]) && ((jj[ii[i]] < bs * (i / bs)) || (jj[ii[i + 1] - 1] > bs * ((i + bs) / bs) - 1))) { 753a062f41SBarry Smith rows[cnt] = i; 763a062f41SBarry Smith cnt++; 773a062f41SBarry Smith } 783a062f41SBarry Smith } 799566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cnt, rows, PETSC_OWN_POINTER, is)); 803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 813a062f41SBarry Smith } 823a062f41SBarry Smith 83d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A, PetscInt *nrows, PetscInt **zrows) 84d71ae5a4SJacob Faibussowitsch { 856ce1633cSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 86fff043a9SJunchao Zhang const MatScalar *aa; 876ce1633cSBarry Smith PetscInt i, m = A->rmap->n, cnt = 0; 88b2db7409Sstefano_zampini const PetscInt *ii = a->i, *jj = a->j, *diag; 896ce1633cSBarry Smith PetscInt *rows; 906ce1633cSBarry Smith 916ce1633cSBarry Smith PetscFunctionBegin; 929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 939566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 946ce1633cSBarry Smith diag = a->diag; 956ce1633cSBarry Smith for (i = 0; i < m; i++) { 96ad540459SPierre Jolivet if ((diag[i] >= ii[i + 1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) cnt++; 976ce1633cSBarry Smith } 989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cnt, &rows)); 996ce1633cSBarry Smith cnt = 0; 1006ce1633cSBarry Smith for (i = 0; i < m; i++) { 101ad540459SPierre Jolivet if ((diag[i] >= ii[i + 1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) rows[cnt++] = i; 1026ce1633cSBarry Smith } 103f1f41ecbSJed Brown *nrows = cnt; 104f1f41ecbSJed Brown *zrows = rows; 1059566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 1063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 107f1f41ecbSJed Brown } 108f1f41ecbSJed Brown 109d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A, IS *zrows) 110d71ae5a4SJacob Faibussowitsch { 111f1f41ecbSJed Brown PetscInt nrows, *rows; 112f1f41ecbSJed Brown 113f1f41ecbSJed Brown PetscFunctionBegin; 1140298fd71SBarry Smith *zrows = NULL; 1159566063dSJacob Faibussowitsch PetscCall(MatFindZeroDiagonals_SeqAIJ_Private(A, &nrows, &rows)); 1169566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), nrows, rows, PETSC_OWN_POINTER, zrows)); 1173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1186ce1633cSBarry Smith } 1196ce1633cSBarry Smith 120d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A, IS *keptrows) 121d71ae5a4SJacob Faibussowitsch { 122b3a44c85SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 123b3a44c85SBarry Smith const MatScalar *aa; 124b3a44c85SBarry Smith PetscInt m = A->rmap->n, cnt = 0; 125b3a44c85SBarry Smith const PetscInt *ii; 126b3a44c85SBarry Smith PetscInt n, i, j, *rows; 127b3a44c85SBarry Smith 128b3a44c85SBarry Smith PetscFunctionBegin; 1299566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 130f4259b30SLisandro Dalcin *keptrows = NULL; 131b3a44c85SBarry Smith ii = a->i; 132b3a44c85SBarry Smith for (i = 0; i < m; i++) { 133b3a44c85SBarry Smith n = ii[i + 1] - ii[i]; 134b3a44c85SBarry Smith if (!n) { 135b3a44c85SBarry Smith cnt++; 136b3a44c85SBarry Smith goto ok1; 137b3a44c85SBarry Smith } 1382e5835c6SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 139b3a44c85SBarry Smith if (aa[j] != 0.0) goto ok1; 140b3a44c85SBarry Smith } 141b3a44c85SBarry Smith cnt++; 142b3a44c85SBarry Smith ok1:; 143b3a44c85SBarry Smith } 1442e5835c6SStefano Zampini if (!cnt) { 1459566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 1463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1472e5835c6SStefano Zampini } 1489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n - cnt, &rows)); 149b3a44c85SBarry Smith cnt = 0; 150b3a44c85SBarry Smith for (i = 0; i < m; i++) { 151b3a44c85SBarry Smith n = ii[i + 1] - ii[i]; 152b3a44c85SBarry Smith if (!n) continue; 1532e5835c6SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 154b3a44c85SBarry Smith if (aa[j] != 0.0) { 155b3a44c85SBarry Smith rows[cnt++] = i; 156b3a44c85SBarry Smith break; 157b3a44c85SBarry Smith } 158b3a44c85SBarry Smith } 159b3a44c85SBarry Smith } 1609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 1619566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cnt, rows, PETSC_OWN_POINTER, keptrows)); 1623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 163b3a44c85SBarry Smith } 164b3a44c85SBarry Smith 165d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDiagonalSet_SeqAIJ(Mat Y, Vec D, InsertMode is) 166d71ae5a4SJacob Faibussowitsch { 16779299369SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)Y->data; 16899e65526SBarry Smith PetscInt i, m = Y->rmap->n; 16999e65526SBarry Smith const PetscInt *diag; 1702e5835c6SStefano Zampini MatScalar *aa; 17199e65526SBarry Smith const PetscScalar *v; 172ace3abfcSBarry Smith PetscBool missing; 17379299369SBarry Smith 17479299369SBarry Smith PetscFunctionBegin; 17509f38230SBarry Smith if (Y->assembled) { 1769566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal_SeqAIJ(Y, &missing, NULL)); 17709f38230SBarry Smith if (!missing) { 17879299369SBarry Smith diag = aij->diag; 1799566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(D, &v)); 1809566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Y, &aa)); 18179299369SBarry Smith if (is == INSERT_VALUES) { 182ad540459SPierre Jolivet for (i = 0; i < m; i++) aa[diag[i]] = v[i]; 18379299369SBarry Smith } else { 184ad540459SPierre Jolivet for (i = 0; i < m; i++) aa[diag[i]] += v[i]; 18579299369SBarry Smith } 1869566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Y, &aa)); 1879566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(D, &v)); 1883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18979299369SBarry Smith } 1909566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(Y)); 19109f38230SBarry Smith } 1929566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet_Default(Y, D, is)); 1933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19409f38230SBarry Smith } 19579299369SBarry Smith 196d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *m, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 197d71ae5a4SJacob Faibussowitsch { 198416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 19997f1f81fSBarry Smith PetscInt i, ishift; 20017ab2063SBarry Smith 2013a40ed3dSBarry Smith PetscFunctionBegin; 202f1f2ae84SBarry Smith if (m) *m = A->rmap->n; 2033ba16761SJacob Faibussowitsch if (!ia) PetscFunctionReturn(PETSC_SUCCESS); 204bfeeae90SHong Zhang ishift = 0; 205b94d7dedSBarry Smith if (symmetric && A->structurally_symmetric != PETSC_BOOL3_TRUE) { 2069566063dSJacob Faibussowitsch PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n, a->i, a->j, PETSC_TRUE, ishift, oshift, (PetscInt **)ia, (PetscInt **)ja)); 207bfeeae90SHong Zhang } else if (oshift == 1) { 2081a83f524SJed Brown PetscInt *tia; 209d0f46423SBarry Smith PetscInt nz = a->i[A->rmap->n]; 2103b2fbd54SBarry Smith /* malloc space and add 1 to i and j indices */ 2119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n + 1, &tia)); 2121a83f524SJed Brown for (i = 0; i < A->rmap->n + 1; i++) tia[i] = a->i[i] + 1; 2131a83f524SJed Brown *ia = tia; 214ecc77c7aSBarry Smith if (ja) { 2151a83f524SJed Brown PetscInt *tja; 2169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz + 1, &tja)); 2171a83f524SJed Brown for (i = 0; i < nz; i++) tja[i] = a->j[i] + 1; 2181a83f524SJed Brown *ja = tja; 219ecc77c7aSBarry Smith } 2206945ee14SBarry Smith } else { 221ecc77c7aSBarry Smith *ia = a->i; 222ecc77c7aSBarry Smith if (ja) *ja = a->j; 223a2ce50c7SBarry Smith } 2243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 225a2744918SBarry Smith } 226a2744918SBarry Smith 227d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 228d71ae5a4SJacob Faibussowitsch { 2293a40ed3dSBarry Smith PetscFunctionBegin; 2303ba16761SJacob Faibussowitsch if (!ia) PetscFunctionReturn(PETSC_SUCCESS); 231b94d7dedSBarry Smith if ((symmetric && A->structurally_symmetric != PETSC_BOOL3_TRUE) || oshift == 1) { 2329566063dSJacob Faibussowitsch PetscCall(PetscFree(*ia)); 2339566063dSJacob Faibussowitsch if (ja) PetscCall(PetscFree(*ja)); 234bcd2baecSBarry Smith } 2353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23617ab2063SBarry Smith } 23717ab2063SBarry Smith 238d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 239d71ae5a4SJacob Faibussowitsch { 2403b2fbd54SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 241d0f46423SBarry Smith PetscInt i, *collengths, *cia, *cja, n = A->cmap->n, m = A->rmap->n; 24297f1f81fSBarry Smith PetscInt nz = a->i[m], row, *jj, mr, col; 2433b2fbd54SBarry Smith 2443a40ed3dSBarry Smith PetscFunctionBegin; 245899cda47SBarry Smith *nn = n; 2463ba16761SJacob Faibussowitsch if (!ia) PetscFunctionReturn(PETSC_SUCCESS); 2473b2fbd54SBarry Smith if (symmetric) { 2489566063dSJacob Faibussowitsch PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n, a->i, a->j, PETSC_TRUE, 0, oshift, (PetscInt **)ia, (PetscInt **)ja)); 2493b2fbd54SBarry Smith } else { 2509566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &collengths)); 2519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &cia)); 2529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &cja)); 2533b2fbd54SBarry Smith jj = a->j; 254ad540459SPierre Jolivet for (i = 0; i < nz; i++) collengths[jj[i]]++; 2553b2fbd54SBarry Smith cia[0] = oshift; 256ad540459SPierre Jolivet for (i = 0; i < n; i++) cia[i + 1] = cia[i] + collengths[i]; 2579566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(collengths, n)); 2583b2fbd54SBarry Smith jj = a->j; 259a93ec695SBarry Smith for (row = 0; row < m; row++) { 260a93ec695SBarry Smith mr = a->i[row + 1] - a->i[row]; 261a93ec695SBarry Smith for (i = 0; i < mr; i++) { 262bfeeae90SHong Zhang col = *jj++; 2632205254eSKarl Rupp 2643b2fbd54SBarry Smith cja[cia[col] + collengths[col]++ - oshift] = row + oshift; 2653b2fbd54SBarry Smith } 2663b2fbd54SBarry Smith } 2679566063dSJacob Faibussowitsch PetscCall(PetscFree(collengths)); 2689371c9d4SSatish Balay *ia = cia; 2699371c9d4SSatish Balay *ja = cja; 2703b2fbd54SBarry Smith } 2713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2723b2fbd54SBarry Smith } 2733b2fbd54SBarry Smith 274d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 275d71ae5a4SJacob Faibussowitsch { 2763a40ed3dSBarry Smith PetscFunctionBegin; 2773ba16761SJacob Faibussowitsch if (!ia) PetscFunctionReturn(PETSC_SUCCESS); 2783b2fbd54SBarry Smith 2799566063dSJacob Faibussowitsch PetscCall(PetscFree(*ia)); 2809566063dSJacob Faibussowitsch PetscCall(PetscFree(*ja)); 2813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2823b2fbd54SBarry Smith } 2833b2fbd54SBarry Smith 2847cee066cSHong Zhang /* 2857cee066cSHong Zhang MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from 2867cee066cSHong Zhang MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output 287040ebd07SHong Zhang spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ() 2887cee066cSHong Zhang */ 289d71ae5a4SJacob 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) 290d71ae5a4SJacob Faibussowitsch { 2917cee066cSHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2927cee066cSHong Zhang PetscInt i, *collengths, *cia, *cja, n = A->cmap->n, m = A->rmap->n; 293071fcb05SBarry Smith PetscInt nz = a->i[m], row, mr, col, tmp; 2947cee066cSHong Zhang PetscInt *cspidx; 295071fcb05SBarry Smith const PetscInt *jj; 2967cee066cSHong Zhang 2977cee066cSHong Zhang PetscFunctionBegin; 2987cee066cSHong Zhang *nn = n; 2993ba16761SJacob Faibussowitsch if (!ia) PetscFunctionReturn(PETSC_SUCCESS); 300625f6d37SHong Zhang 3019566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &collengths)); 3029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &cia)); 3039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &cja)); 3049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &cspidx)); 3057cee066cSHong Zhang jj = a->j; 306ad540459SPierre Jolivet for (i = 0; i < nz; i++) collengths[jj[i]]++; 3077cee066cSHong Zhang cia[0] = oshift; 308ad540459SPierre Jolivet for (i = 0; i < n; i++) cia[i + 1] = cia[i] + collengths[i]; 3099566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(collengths, n)); 3107cee066cSHong Zhang jj = a->j; 3117cee066cSHong Zhang for (row = 0; row < m; row++) { 3127cee066cSHong Zhang mr = a->i[row + 1] - a->i[row]; 3137cee066cSHong Zhang for (i = 0; i < mr; i++) { 3147cee066cSHong Zhang col = *jj++; 315071fcb05SBarry Smith tmp = cia[col] + collengths[col]++ - oshift; 316071fcb05SBarry Smith cspidx[tmp] = a->i[row] + i; /* index of a->j */ 317071fcb05SBarry Smith cja[tmp] = row + oshift; 3187cee066cSHong Zhang } 3197cee066cSHong Zhang } 3209566063dSJacob Faibussowitsch PetscCall(PetscFree(collengths)); 321071fcb05SBarry Smith *ia = cia; 322071fcb05SBarry Smith *ja = cja; 3237cee066cSHong Zhang *spidx = cspidx; 3243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3257cee066cSHong Zhang } 3267cee066cSHong Zhang 327d71ae5a4SJacob 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) 328d71ae5a4SJacob Faibussowitsch { 3297cee066cSHong Zhang PetscFunctionBegin; 3309566063dSJacob Faibussowitsch PetscCall(MatRestoreColumnIJ_SeqAIJ(A, oshift, symmetric, inodecompressed, n, ia, ja, done)); 3319566063dSJacob Faibussowitsch PetscCall(PetscFree(*spidx)); 3323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3337cee066cSHong Zhang } 3347cee066cSHong Zhang 335d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A, PetscInt row, const PetscScalar v[]) 336d71ae5a4SJacob Faibussowitsch { 33787d4246cSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 33887d4246cSBarry Smith PetscInt *ai = a->i; 339fff043a9SJunchao Zhang PetscScalar *aa; 34087d4246cSBarry Smith 34187d4246cSBarry Smith PetscFunctionBegin; 3429566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 3439566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aa + ai[row], v, ai[row + 1] - ai[row])); 3449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 3453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34687d4246cSBarry Smith } 34787d4246cSBarry Smith 348bd04181cSBarry Smith /* 349bd04181cSBarry Smith MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions 350bd04181cSBarry Smith 351bd04181cSBarry Smith - a single row of values is set with each call 352bd04181cSBarry Smith - no row or column indices are negative or (in error) larger than the number of rows or columns 353bd04181cSBarry Smith - the values are always added to the matrix, not set 354bd04181cSBarry Smith - no new locations are introduced in the nonzero structure of the matrix 355bd04181cSBarry Smith 3561f763a69SBarry Smith This does NOT assume the global column indices are sorted 357bd04181cSBarry Smith 3581f763a69SBarry Smith */ 359bd04181cSBarry Smith 360af0996ceSBarry Smith #include <petsc/private/isimpl.h> 361d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) 362d71ae5a4SJacob Faibussowitsch { 363189e4007SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3641f763a69SBarry Smith PetscInt low, high, t, row, nrow, i, col, l; 3651f763a69SBarry Smith const PetscInt *rp, *ai = a->i, *ailen = a->ilen, *aj = a->j; 3661f763a69SBarry Smith PetscInt lastcol = -1; 367fff043a9SJunchao Zhang MatScalar *ap, value, *aa; 368189e4007SBarry Smith const PetscInt *ridx = A->rmap->mapping->indices, *cidx = A->cmap->mapping->indices; 369189e4007SBarry Smith 370fff043a9SJunchao Zhang PetscFunctionBegin; 3719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 372f38dd0b8SBarry Smith row = ridx[im[0]]; 3731f763a69SBarry Smith rp = aj + ai[row]; 3741f763a69SBarry Smith ap = aa + ai[row]; 3751f763a69SBarry Smith nrow = ailen[row]; 376189e4007SBarry Smith low = 0; 377189e4007SBarry Smith high = nrow; 378189e4007SBarry Smith for (l = 0; l < n; l++) { /* loop over added columns */ 379189e4007SBarry Smith col = cidx[in[l]]; 380f38dd0b8SBarry Smith value = v[l]; 381189e4007SBarry Smith 382189e4007SBarry Smith if (col <= lastcol) low = 0; 383189e4007SBarry Smith else high = nrow; 384189e4007SBarry Smith lastcol = col; 385189e4007SBarry Smith while (high - low > 5) { 386189e4007SBarry Smith t = (low + high) / 2; 387189e4007SBarry Smith if (rp[t] > col) high = t; 388189e4007SBarry Smith else low = t; 389189e4007SBarry Smith } 390189e4007SBarry Smith for (i = low; i < high; i++) { 391189e4007SBarry Smith if (rp[i] == col) { 3921f763a69SBarry Smith ap[i] += value; 393189e4007SBarry Smith low = i + 1; 3941f763a69SBarry Smith break; 395189e4007SBarry Smith } 396189e4007SBarry Smith } 397189e4007SBarry Smith } 3989566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 3993ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 400189e4007SBarry Smith } 401189e4007SBarry Smith 402d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValues_SeqAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) 403d71ae5a4SJacob Faibussowitsch { 404416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 405e2ee6c50SBarry Smith PetscInt *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N; 40697f1f81fSBarry Smith PetscInt *imax = a->imax, *ai = a->i, *ailen = a->ilen; 407e2ee6c50SBarry Smith PetscInt *aj = a->j, nonew = a->nonew, lastcol = -1; 408ce496241SStefano Zampini MatScalar *ap = NULL, value = 0.0, *aa; 409ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 410ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 41117ab2063SBarry Smith 4123a40ed3dSBarry Smith PetscFunctionBegin; 4139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 41417ab2063SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 415416022c9SBarry Smith row = im[k]; 4165ef9f2a5SBarry Smith if (row < 0) continue; 4176bdcaf15SBarry 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); 418720833daSHong Zhang rp = aj + ai[row]; 419876c6284SHong Zhang if (!A->structure_only) ap = aa + ai[row]; 4209371c9d4SSatish Balay rmax = imax[row]; 4219371c9d4SSatish Balay nrow = ailen[row]; 422416022c9SBarry Smith low = 0; 423c71e6ed7SBarry Smith high = nrow; 42417ab2063SBarry Smith for (l = 0; l < n; l++) { /* loop over added columns */ 4255ef9f2a5SBarry Smith if (in[l] < 0) continue; 4266bdcaf15SBarry 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); 427bfeeae90SHong Zhang col = in[l]; 428071fcb05SBarry Smith if (v && !A->structure_only) value = roworiented ? v[l + k * n] : v[k + l * m]; 429071fcb05SBarry Smith if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue; 43036db0b34SBarry Smith 4312205254eSKarl Rupp if (col <= lastcol) low = 0; 4322205254eSKarl Rupp else high = nrow; 433e2ee6c50SBarry Smith lastcol = col; 434416022c9SBarry Smith while (high - low > 5) { 435416022c9SBarry Smith t = (low + high) / 2; 436416022c9SBarry Smith if (rp[t] > col) high = t; 437416022c9SBarry Smith else low = t; 43817ab2063SBarry Smith } 439416022c9SBarry Smith for (i = low; i < high; i++) { 44017ab2063SBarry Smith if (rp[i] > col) break; 44117ab2063SBarry Smith if (rp[i] == col) { 442876c6284SHong Zhang if (!A->structure_only) { 4430c0d7e18SFande Kong if (is == ADD_VALUES) { 4440c0d7e18SFande Kong ap[i] += value; 4450c0d7e18SFande Kong (void)PetscLogFlops(1.0); 4469371c9d4SSatish Balay } else ap[i] = value; 447720833daSHong Zhang } 448e44c0bd4SBarry Smith low = i + 1; 44917ab2063SBarry Smith goto noinsert; 45017ab2063SBarry Smith } 45117ab2063SBarry Smith } 452dcd36c23SBarry Smith if (value == 0.0 && ignorezeroentries && row != col) goto noinsert; 453c2653b3dSLois Curfman McInnes if (nonew == 1) goto noinsert; 45408401ef6SPierre 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); 455720833daSHong Zhang if (A->structure_only) { 456876c6284SHong Zhang MatSeqXAIJReallocateAIJ_structure_only(A, A->rmap->n, 1, nrow, row, col, rmax, ai, aj, rp, imax, nonew, MatScalar); 457720833daSHong Zhang } else { 458fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, A->rmap->n, 1, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 459720833daSHong Zhang } 4609371c9d4SSatish Balay N = nrow++ - 1; 4619371c9d4SSatish Balay a->nz++; 4629371c9d4SSatish Balay high++; 463416022c9SBarry Smith /* shift up all the later entries in this row */ 4649566063dSJacob Faibussowitsch PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1)); 46517ab2063SBarry Smith rp[i] = col; 466580bdb30SBarry Smith if (!A->structure_only) { 4679566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap + i + 1, ap + i, N - i + 1)); 468580bdb30SBarry Smith ap[i] = value; 469580bdb30SBarry Smith } 470416022c9SBarry Smith low = i + 1; 471e56f5c9eSBarry Smith A->nonzerostate++; 472e44c0bd4SBarry Smith noinsert:; 47317ab2063SBarry Smith } 47417ab2063SBarry Smith ailen[row] = nrow; 47517ab2063SBarry Smith } 4769566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 4773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47817ab2063SBarry Smith } 47917ab2063SBarry Smith 480d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) 481d71ae5a4SJacob Faibussowitsch { 48219b08ed1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 48319b08ed1SBarry Smith PetscInt *rp, k, row; 48419b08ed1SBarry Smith PetscInt *ai = a->i; 48519b08ed1SBarry Smith PetscInt *aj = a->j; 486fff043a9SJunchao Zhang MatScalar *aa, *ap; 48719b08ed1SBarry Smith 48819b08ed1SBarry Smith PetscFunctionBegin; 48928b400f6SJacob Faibussowitsch PetscCheck(!A->was_assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call on assembled matrix."); 49008401ef6SPierre 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); 491fff043a9SJunchao Zhang 4929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 49319b08ed1SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 49419b08ed1SBarry Smith row = im[k]; 49519b08ed1SBarry Smith rp = aj + ai[row]; 49619b08ed1SBarry Smith ap = aa + ai[row]; 49719b08ed1SBarry Smith 4989566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(rp, in, n * sizeof(PetscInt))); 49919b08ed1SBarry Smith if (!A->structure_only) { 50019b08ed1SBarry Smith if (v) { 5019566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(ap, v, n * sizeof(PetscScalar))); 50219b08ed1SBarry Smith v += n; 50319b08ed1SBarry Smith } else { 5049566063dSJacob Faibussowitsch PetscCall(PetscMemzero(ap, n * sizeof(PetscScalar))); 50519b08ed1SBarry Smith } 50619b08ed1SBarry Smith } 50719b08ed1SBarry Smith a->ilen[row] = n; 50819b08ed1SBarry Smith a->imax[row] = n; 50919b08ed1SBarry Smith a->i[row + 1] = a->i[row] + n; 51019b08ed1SBarry Smith a->nz += n; 51119b08ed1SBarry Smith } 5129566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 5133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51419b08ed1SBarry Smith } 51519b08ed1SBarry Smith 51619b08ed1SBarry Smith /*@ 51719b08ed1SBarry Smith MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix. 51819b08ed1SBarry Smith 51919b08ed1SBarry Smith Input Parameters: 52011a5261eSBarry Smith + A - the `MATSEQAIJ` matrix 52119b08ed1SBarry Smith - nztotal - bound on the number of nonzeros 52219b08ed1SBarry Smith 52319b08ed1SBarry Smith Level: advanced 52419b08ed1SBarry Smith 52519b08ed1SBarry Smith Notes: 52619b08ed1SBarry 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. 52711a5261eSBarry Smith Simply call `MatSetValues()` after this call to provide the matrix entries in the usual manner. This matrix may be used 52819b08ed1SBarry Smith as always with multiple matrix assemblies. 52919b08ed1SBarry Smith 5302ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MAT_SORTED_FULL`, `MatSetValues()`, `MatSeqAIJSetPreallocation()` 53119b08ed1SBarry Smith @*/ 53219b08ed1SBarry Smith 533d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A, PetscInt nztotal) 534d71ae5a4SJacob Faibussowitsch { 53519b08ed1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 53619b08ed1SBarry Smith 53719b08ed1SBarry Smith PetscFunctionBegin; 5389566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 5399566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 54019b08ed1SBarry Smith a->maxnz = nztotal; 5414dfa11a4SJacob Faibussowitsch if (!a->imax) { PetscCall(PetscMalloc1(A->rmap->n, &a->imax)); } 54219b08ed1SBarry Smith if (!a->ilen) { 5439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &a->ilen)); 54419b08ed1SBarry Smith } else { 5459566063dSJacob Faibussowitsch PetscCall(PetscMemzero(a->ilen, A->rmap->n * sizeof(PetscInt))); 54619b08ed1SBarry Smith } 54719b08ed1SBarry Smith 54819b08ed1SBarry Smith /* allocate the matrix space */ 54919b08ed1SBarry Smith if (A->structure_only) { 5509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nztotal, &a->j)); 5519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n + 1, &a->i)); 55219b08ed1SBarry Smith } else { 5539566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(nztotal, &a->a, nztotal, &a->j, A->rmap->n + 1, &a->i)); 55419b08ed1SBarry Smith } 55519b08ed1SBarry Smith a->i[0] = 0; 55619b08ed1SBarry Smith if (A->structure_only) { 55719b08ed1SBarry Smith a->singlemalloc = PETSC_FALSE; 55819b08ed1SBarry Smith a->free_a = PETSC_FALSE; 55919b08ed1SBarry Smith } else { 56019b08ed1SBarry Smith a->singlemalloc = PETSC_TRUE; 56119b08ed1SBarry Smith a->free_a = PETSC_TRUE; 56219b08ed1SBarry Smith } 56319b08ed1SBarry Smith a->free_ij = PETSC_TRUE; 56419b08ed1SBarry Smith A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation; 56519b08ed1SBarry Smith A->preallocated = PETSC_TRUE; 5663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56719b08ed1SBarry Smith } 56819b08ed1SBarry Smith 569d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) 570d71ae5a4SJacob Faibussowitsch { 571071fcb05SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 572071fcb05SBarry Smith PetscInt *rp, k, row; 573071fcb05SBarry Smith PetscInt *ai = a->i, *ailen = a->ilen; 574071fcb05SBarry Smith PetscInt *aj = a->j; 575fff043a9SJunchao Zhang MatScalar *aa, *ap; 576071fcb05SBarry Smith 577071fcb05SBarry Smith PetscFunctionBegin; 5789566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 579071fcb05SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 580071fcb05SBarry Smith row = im[k]; 5816bdcaf15SBarry 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); 582071fcb05SBarry Smith rp = aj + ai[row]; 583071fcb05SBarry Smith ap = aa + ai[row]; 58448a46eb9SPierre Jolivet if (!A->was_assembled) PetscCall(PetscMemcpy(rp, in, n * sizeof(PetscInt))); 585071fcb05SBarry Smith if (!A->structure_only) { 586071fcb05SBarry Smith if (v) { 5879566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(ap, v, n * sizeof(PetscScalar))); 588071fcb05SBarry Smith v += n; 589071fcb05SBarry Smith } else { 5909566063dSJacob Faibussowitsch PetscCall(PetscMemzero(ap, n * sizeof(PetscScalar))); 591071fcb05SBarry Smith } 592071fcb05SBarry Smith } 593071fcb05SBarry Smith ailen[row] = n; 594071fcb05SBarry Smith a->nz += n; 595071fcb05SBarry Smith } 5969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 5973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 598071fcb05SBarry Smith } 599071fcb05SBarry Smith 600d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetValues_SeqAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[]) 601d71ae5a4SJacob Faibussowitsch { 6027eb43aa7SLois Curfman McInnes Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 60397f1f81fSBarry Smith PetscInt *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j; 60497f1f81fSBarry Smith PetscInt *ai = a->i, *ailen = a->ilen; 6054e208921SJed Brown const MatScalar *ap, *aa; 6067eb43aa7SLois Curfman McInnes 6073a40ed3dSBarry Smith PetscFunctionBegin; 6084e208921SJed Brown PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 6097eb43aa7SLois Curfman McInnes for (k = 0; k < m; k++) { /* loop over rows */ 6107eb43aa7SLois Curfman McInnes row = im[k]; 6119371c9d4SSatish Balay if (row < 0) { 6129371c9d4SSatish Balay v += n; 6139371c9d4SSatish Balay continue; 6149371c9d4SSatish Balay } /* negative row */ 61554c59aa7SJacob 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); 6169371c9d4SSatish Balay rp = aj + ai[row]; 6179371c9d4SSatish Balay ap = aa + ai[row]; 6187eb43aa7SLois Curfman McInnes nrow = ailen[row]; 6197eb43aa7SLois Curfman McInnes for (l = 0; l < n; l++) { /* loop over columns */ 6209371c9d4SSatish Balay if (in[l] < 0) { 6219371c9d4SSatish Balay v++; 6229371c9d4SSatish Balay continue; 6239371c9d4SSatish Balay } /* negative column */ 62454c59aa7SJacob 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); 625bfeeae90SHong Zhang col = in[l]; 6269371c9d4SSatish Balay high = nrow; 6279371c9d4SSatish Balay low = 0; /* assume unsorted */ 6287eb43aa7SLois Curfman McInnes while (high - low > 5) { 6297eb43aa7SLois Curfman McInnes t = (low + high) / 2; 6307eb43aa7SLois Curfman McInnes if (rp[t] > col) high = t; 6317eb43aa7SLois Curfman McInnes else low = t; 6327eb43aa7SLois Curfman McInnes } 6337eb43aa7SLois Curfman McInnes for (i = low; i < high; i++) { 6347eb43aa7SLois Curfman McInnes if (rp[i] > col) break; 6357eb43aa7SLois Curfman McInnes if (rp[i] == col) { 636b49de8d1SLois Curfman McInnes *v++ = ap[i]; 6377eb43aa7SLois Curfman McInnes goto finished; 6387eb43aa7SLois Curfman McInnes } 6397eb43aa7SLois Curfman McInnes } 64097e567efSBarry Smith *v++ = 0.0; 6417eb43aa7SLois Curfman McInnes finished:; 6427eb43aa7SLois Curfman McInnes } 6437eb43aa7SLois Curfman McInnes } 6444e208921SJed Brown PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 6453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6467eb43aa7SLois Curfman McInnes } 6477eb43aa7SLois Curfman McInnes 648d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqAIJ_Binary(Mat mat, PetscViewer viewer) 649d71ae5a4SJacob Faibussowitsch { 6503ea6fe3dSLisandro Dalcin Mat_SeqAIJ *A = (Mat_SeqAIJ *)mat->data; 651c898d852SStefano Zampini const PetscScalar *av; 6523ea6fe3dSLisandro Dalcin PetscInt header[4], M, N, m, nz, i; 6533ea6fe3dSLisandro Dalcin PetscInt *rowlens; 65417ab2063SBarry Smith 6553a40ed3dSBarry Smith PetscFunctionBegin; 6569566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 6572205254eSKarl Rupp 6583ea6fe3dSLisandro Dalcin M = mat->rmap->N; 6593ea6fe3dSLisandro Dalcin N = mat->cmap->N; 6603ea6fe3dSLisandro Dalcin m = mat->rmap->n; 6613ea6fe3dSLisandro Dalcin nz = A->nz; 662416022c9SBarry Smith 6633ea6fe3dSLisandro Dalcin /* write matrix header */ 6643ea6fe3dSLisandro Dalcin header[0] = MAT_FILE_CLASSID; 6659371c9d4SSatish Balay header[1] = M; 6669371c9d4SSatish Balay header[2] = N; 6679371c9d4SSatish Balay header[3] = nz; 6689566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT)); 669416022c9SBarry Smith 6703ea6fe3dSLisandro Dalcin /* fill in and store row lengths */ 6719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &rowlens)); 6723ea6fe3dSLisandro Dalcin for (i = 0; i < m; i++) rowlens[i] = A->i[i + 1] - A->i[i]; 6739566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, rowlens, m, PETSC_INT)); 6749566063dSJacob Faibussowitsch PetscCall(PetscFree(rowlens)); 6753ea6fe3dSLisandro Dalcin /* store column indices */ 6769566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, A->j, nz, PETSC_INT)); 677416022c9SBarry Smith /* store nonzero values */ 6789566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(mat, &av)); 6799566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, av, nz, PETSC_SCALAR)); 6809566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(mat, &av)); 681b37d52dbSMark F. Adams 6823ea6fe3dSLisandro Dalcin /* write block size option to the viewer's .info file */ 6839566063dSJacob Faibussowitsch PetscCall(MatView_Binary_BlockSizes(mat, viewer)); 6843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68517ab2063SBarry Smith } 686416022c9SBarry Smith 687d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A, PetscViewer viewer) 688d71ae5a4SJacob Faibussowitsch { 6897dc0baabSHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 6907dc0baabSHong Zhang PetscInt i, k, m = A->rmap->N; 6917dc0baabSHong Zhang 6927dc0baabSHong Zhang PetscFunctionBegin; 6939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 6947dc0baabSHong Zhang for (i = 0; i < m; i++) { 6959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 69648a46eb9SPierre Jolivet for (k = a->i[i]; k < a->i[i + 1]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ") ", a->j[k])); 6979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 6987dc0baabSHong Zhang } 6999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 7003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7017dc0baabSHong Zhang } 7027dc0baabSHong Zhang 70309573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat, PetscViewer); 704cd155464SBarry Smith 705d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqAIJ_ASCII(Mat A, PetscViewer viewer) 706d71ae5a4SJacob Faibussowitsch { 707416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 708c898d852SStefano Zampini const PetscScalar *av; 70960e0710aSBarry Smith PetscInt i, j, m = A->rmap->n; 710e060cb09SBarry Smith const char *name; 711f3ef73ceSBarry Smith PetscViewerFormat format; 71217ab2063SBarry Smith 7133a40ed3dSBarry Smith PetscFunctionBegin; 7147dc0baabSHong Zhang if (A->structure_only) { 7159566063dSJacob Faibussowitsch PetscCall(MatView_SeqAIJ_ASCII_structonly(A, viewer)); 7163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7177dc0baabSHong Zhang } 71843e49210SHong Zhang 7199566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 7203ba16761SJacob Faibussowitsch if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS); 7212e5835c6SStefano Zampini 722c898d852SStefano Zampini /* trigger copy to CPU if needed */ 7239566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 7249566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 72571c2f376SKris Buschelman if (format == PETSC_VIEWER_ASCII_MATLAB) { 72697f1f81fSBarry Smith PetscInt nofinalvalue = 0; 72760e0710aSBarry Smith if (m && ((a->i[m] == a->i[m - 1]) || (a->j[a->nz - 1] != A->cmap->n - 1))) { 728c337ccceSJed Brown /* Need a dummy value to ensure the dimension of the matrix. */ 729d00d2cf4SBarry Smith nofinalvalue = 1; 730d00d2cf4SBarry Smith } 7319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 7329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", m, A->cmap->n)); 7339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Nonzeros = %" PetscInt_FMT " \n", a->nz)); 734fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX) 7359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = zeros(%" PetscInt_FMT ",4);\n", a->nz + nofinalvalue)); 736fbfe6fa7SJed Brown #else 7379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = zeros(%" PetscInt_FMT ",3);\n", a->nz + nofinalvalue)); 738fbfe6fa7SJed Brown #endif 7399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = [\n")); 74017ab2063SBarry Smith 74117ab2063SBarry Smith for (i = 0; i < m; i++) { 74260e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 743aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 7449566063dSJacob 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]))); 74517ab2063SBarry Smith #else 7469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %18.16e\n", i + 1, a->j[j] + 1, (double)a->a[j])); 74717ab2063SBarry Smith #endif 74817ab2063SBarry Smith } 74917ab2063SBarry Smith } 750d00d2cf4SBarry Smith if (nofinalvalue) { 751c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX) 7529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %18.16e %18.16e\n", m, A->cmap->n, 0., 0.)); 753c337ccceSJed Brown #else 7549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %18.16e\n", m, A->cmap->n, 0.0)); 755c337ccceSJed Brown #endif 756d00d2cf4SBarry Smith } 7579566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)A, &name)); 7589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "];\n %s = spconvert(zzz);\n", name)); 7599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 760fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_COMMON) { 7619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 76244cd7ae7SLois Curfman McInnes for (i = 0; i < m; i++) { 7639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 76460e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 765aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 76636db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) { 7679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 76836db0b34SBarry Smith } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) { 7699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)-PetscImaginaryPart(a->a[j]))); 77036db0b34SBarry Smith } else if (PetscRealPart(a->a[j]) != 0.0) { 7719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 7726831982aSBarry Smith } 77344cd7ae7SLois Curfman McInnes #else 7749566063dSJacob Faibussowitsch if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 77544cd7ae7SLois Curfman McInnes #endif 77644cd7ae7SLois Curfman McInnes } 7779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 77844cd7ae7SLois Curfman McInnes } 7799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 780fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_SYMMODU) { 78197f1f81fSBarry Smith PetscInt nzd = 0, fshift = 1, *sptr; 7829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 7839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &sptr)); 784496be53dSLois Curfman McInnes for (i = 0; i < m; i++) { 785496be53dSLois Curfman McInnes sptr[i] = nzd + 1; 78660e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 787496be53dSLois Curfman McInnes if (a->j[j] >= i) { 788aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 78936db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++; 790496be53dSLois Curfman McInnes #else 791496be53dSLois Curfman McInnes if (a->a[j] != 0.0) nzd++; 792496be53dSLois Curfman McInnes #endif 793496be53dSLois Curfman McInnes } 794496be53dSLois Curfman McInnes } 795496be53dSLois Curfman McInnes } 7962e44a96cSLois Curfman McInnes sptr[m] = nzd + 1; 7979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT "\n\n", m, nzd)); 7982e44a96cSLois Curfman McInnes for (i = 0; i < m + 1; i += 6) { 7992205254eSKarl Rupp if (i + 4 < m) { 8009566063dSJacob 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])); 8012205254eSKarl Rupp } else if (i + 3 < m) { 8029566063dSJacob 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])); 8032205254eSKarl Rupp } else if (i + 2 < m) { 8049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2], sptr[i + 3])); 8052205254eSKarl Rupp } else if (i + 1 < m) { 8069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2])); 8072205254eSKarl Rupp } else if (i < m) { 8089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1])); 8092205254eSKarl Rupp } else { 8109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "\n", sptr[i])); 8112205254eSKarl Rupp } 812496be53dSLois Curfman McInnes } 8139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 8149566063dSJacob Faibussowitsch PetscCall(PetscFree(sptr)); 815496be53dSLois Curfman McInnes for (i = 0; i < m; i++) { 81660e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 8179566063dSJacob Faibussowitsch if (a->j[j] >= i) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " ", a->j[j] + fshift)); 818496be53dSLois Curfman McInnes } 8199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 820496be53dSLois Curfman McInnes } 8219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 822496be53dSLois Curfman McInnes for (i = 0; i < m; i++) { 82360e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 824496be53dSLois Curfman McInnes if (a->j[j] >= i) { 825aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 82648a46eb9SPierre 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]))); 827496be53dSLois Curfman McInnes #else 8289566063dSJacob Faibussowitsch if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " %18.16e ", (double)a->a[j])); 829496be53dSLois Curfman McInnes #endif 830496be53dSLois Curfman McInnes } 831496be53dSLois Curfman McInnes } 8329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 833496be53dSLois Curfman McInnes } 8349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 835fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_DENSE) { 83697f1f81fSBarry Smith PetscInt cnt = 0, jcnt; 83787828ca2SBarry Smith PetscScalar value; 83868f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX) 83968f1ed48SBarry Smith PetscBool realonly = PETSC_TRUE; 84068f1ed48SBarry Smith 84168f1ed48SBarry Smith for (i = 0; i < a->i[m]; i++) { 84268f1ed48SBarry Smith if (PetscImaginaryPart(a->a[i]) != 0.0) { 84368f1ed48SBarry Smith realonly = PETSC_FALSE; 84468f1ed48SBarry Smith break; 84568f1ed48SBarry Smith } 84668f1ed48SBarry Smith } 84768f1ed48SBarry Smith #endif 84802594712SBarry Smith 8499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 85002594712SBarry Smith for (i = 0; i < m; i++) { 85102594712SBarry Smith jcnt = 0; 852d0f46423SBarry Smith for (j = 0; j < A->cmap->n; j++) { 853e24b481bSBarry Smith if (jcnt < a->i[i + 1] - a->i[i] && j == a->j[cnt]) { 85402594712SBarry Smith value = a->a[cnt++]; 855e24b481bSBarry Smith jcnt++; 85602594712SBarry Smith } else { 85702594712SBarry Smith value = 0.0; 85802594712SBarry Smith } 859aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 86068f1ed48SBarry Smith if (realonly) { 8619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e ", (double)PetscRealPart(value))); 86268f1ed48SBarry Smith } else { 8639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e+%7.5e i ", (double)PetscRealPart(value), (double)PetscImaginaryPart(value))); 86468f1ed48SBarry Smith } 86502594712SBarry Smith #else 8669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e ", (double)value)); 86702594712SBarry Smith #endif 86802594712SBarry Smith } 8699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 87002594712SBarry Smith } 8719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 8723c215bfdSMatthew Knepley } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) { 873150b93efSMatthew G. Knepley PetscInt fshift = 1; 8749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 8753c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX) 8769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%%%%MatrixMarket matrix coordinate complex general\n")); 8773c215bfdSMatthew Knepley #else 8789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%%%%MatrixMarket matrix coordinate real general\n")); 8793c215bfdSMatthew Knepley #endif 8809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", m, A->cmap->n, a->nz)); 8813c215bfdSMatthew Knepley for (i = 0; i < m; i++) { 88260e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 8833c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX) 8849566063dSJacob 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]))); 8853c215bfdSMatthew Knepley #else 8869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %g\n", i + fshift, a->j[j] + fshift, (double)a->a[j])); 8873c215bfdSMatthew Knepley #endif 8883c215bfdSMatthew Knepley } 8893c215bfdSMatthew Knepley } 8909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 8913a40ed3dSBarry Smith } else { 8929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 893d5f3da31SBarry Smith if (A->factortype) { 89416cd7e1dSShri Abhyankar for (i = 0; i < m; i++) { 8959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 89616cd7e1dSShri Abhyankar /* L part */ 89760e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 89816cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 89916cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 9009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 90116cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 9029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)(-PetscImaginaryPart(a->a[j])))); 90316cd7e1dSShri Abhyankar } else { 9049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 90516cd7e1dSShri Abhyankar } 90616cd7e1dSShri Abhyankar #else 9079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 90816cd7e1dSShri Abhyankar #endif 90916cd7e1dSShri Abhyankar } 91016cd7e1dSShri Abhyankar /* diagonal */ 91116cd7e1dSShri Abhyankar j = a->diag[i]; 91216cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 91316cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 9149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(1.0 / a->a[j]), (double)PetscImaginaryPart(1.0 / a->a[j]))); 91516cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 9169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(1.0 / a->a[j]), (double)(-PetscImaginaryPart(1.0 / a->a[j])))); 91716cd7e1dSShri Abhyankar } else { 9189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(1.0 / a->a[j]))); 91916cd7e1dSShri Abhyankar } 92016cd7e1dSShri Abhyankar #else 9219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)(1.0 / a->a[j]))); 92216cd7e1dSShri Abhyankar #endif 92316cd7e1dSShri Abhyankar 92416cd7e1dSShri Abhyankar /* U part */ 92560e0710aSBarry Smith for (j = a->diag[i + 1] + 1; j < a->diag[i]; j++) { 92616cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 92716cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 9289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 92916cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 9309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)(-PetscImaginaryPart(a->a[j])))); 93116cd7e1dSShri Abhyankar } else { 9329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 93316cd7e1dSShri Abhyankar } 93416cd7e1dSShri Abhyankar #else 9359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 93616cd7e1dSShri Abhyankar #endif 93716cd7e1dSShri Abhyankar } 9389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 93916cd7e1dSShri Abhyankar } 94016cd7e1dSShri Abhyankar } else { 94117ab2063SBarry Smith for (i = 0; i < m; i++) { 9429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 94360e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 944aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 94536db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) > 0.0) { 9469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 94736db0b34SBarry Smith } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 9489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)-PetscImaginaryPart(a->a[j]))); 9493a40ed3dSBarry Smith } else { 9509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 95117ab2063SBarry Smith } 95217ab2063SBarry Smith #else 9539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 95417ab2063SBarry Smith #endif 95517ab2063SBarry Smith } 9569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 95717ab2063SBarry Smith } 95816cd7e1dSShri Abhyankar } 9599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 96017ab2063SBarry Smith } 9619566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 9623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 963416022c9SBarry Smith } 964416022c9SBarry Smith 9659804daf3SBarry Smith #include <petscdraw.h> 966d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw, void *Aa) 967d71ae5a4SJacob Faibussowitsch { 968480ef9eaSBarry Smith Mat A = (Mat)Aa; 969416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 970383922c3SLisandro Dalcin PetscInt i, j, m = A->rmap->n; 971383922c3SLisandro Dalcin int color; 972b05fc000SLisandro Dalcin PetscReal xl, yl, xr, yr, x_l, x_r, y_l, y_r; 973b0a32e0cSBarry Smith PetscViewer viewer; 974f3ef73ceSBarry Smith PetscViewerFormat format; 975fff043a9SJunchao Zhang const PetscScalar *aa; 976cddf8d76SBarry Smith 9773a40ed3dSBarry Smith PetscFunctionBegin; 9789566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer)); 9799566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 9809566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr)); 981383922c3SLisandro Dalcin 982416022c9SBarry Smith /* loop over matrix elements drawing boxes */ 9839566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 984fb9695e5SSatish Balay if (format != PETSC_VIEWER_DRAW_CONTOUR) { 985d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 9860513a670SBarry Smith /* Blue for negative, Cyan for zero and Red for positive */ 987b0a32e0cSBarry Smith color = PETSC_DRAW_BLUE; 988416022c9SBarry Smith for (i = 0; i < m; i++) { 9899371c9d4SSatish Balay y_l = m - i - 1.0; 9909371c9d4SSatish Balay y_r = y_l + 1.0; 991bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 9929371c9d4SSatish Balay x_l = a->j[j]; 9939371c9d4SSatish Balay x_r = x_l + 1.0; 994fff043a9SJunchao Zhang if (PetscRealPart(aa[j]) >= 0.) continue; 9959566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 996cddf8d76SBarry Smith } 997cddf8d76SBarry Smith } 998b0a32e0cSBarry Smith color = PETSC_DRAW_CYAN; 999cddf8d76SBarry Smith for (i = 0; i < m; i++) { 10009371c9d4SSatish Balay y_l = m - i - 1.0; 10019371c9d4SSatish Balay y_r = y_l + 1.0; 1002bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 10039371c9d4SSatish Balay x_l = a->j[j]; 10049371c9d4SSatish Balay x_r = x_l + 1.0; 1005fff043a9SJunchao Zhang if (aa[j] != 0.) continue; 10069566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 1007cddf8d76SBarry Smith } 1008cddf8d76SBarry Smith } 1009b0a32e0cSBarry Smith color = PETSC_DRAW_RED; 1010cddf8d76SBarry Smith for (i = 0; i < m; i++) { 10119371c9d4SSatish Balay y_l = m - i - 1.0; 10129371c9d4SSatish Balay y_r = y_l + 1.0; 1013bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 10149371c9d4SSatish Balay x_l = a->j[j]; 10159371c9d4SSatish Balay x_r = x_l + 1.0; 1016fff043a9SJunchao Zhang if (PetscRealPart(aa[j]) <= 0.) continue; 10179566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 1018416022c9SBarry Smith } 1019416022c9SBarry Smith } 1020d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 10210513a670SBarry Smith } else { 10220513a670SBarry Smith /* use contour shading to indicate magnitude of values */ 10230513a670SBarry Smith /* first determine max of all nonzero values */ 1024b05fc000SLisandro Dalcin PetscReal minv = 0.0, maxv = 0.0; 1025383922c3SLisandro Dalcin PetscInt nz = a->nz, count = 0; 1026b0a32e0cSBarry Smith PetscDraw popup; 10270513a670SBarry Smith 10280513a670SBarry Smith for (i = 0; i < nz; i++) { 1029fff043a9SJunchao Zhang if (PetscAbsScalar(aa[i]) > maxv) maxv = PetscAbsScalar(aa[i]); 10300513a670SBarry Smith } 1031383922c3SLisandro Dalcin if (minv >= maxv) maxv = minv + PETSC_SMALL; 10329566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 10339566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, minv, maxv)); 1034383922c3SLisandro Dalcin 1035d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 10360513a670SBarry Smith for (i = 0; i < m; i++) { 1037383922c3SLisandro Dalcin y_l = m - i - 1.0; 1038383922c3SLisandro Dalcin y_r = y_l + 1.0; 1039bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 1040383922c3SLisandro Dalcin x_l = a->j[j]; 1041383922c3SLisandro Dalcin x_r = x_l + 1.0; 1042fff043a9SJunchao Zhang color = PetscDrawRealToColor(PetscAbsScalar(aa[count]), minv, maxv); 10439566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 10440513a670SBarry Smith count++; 10450513a670SBarry Smith } 10460513a670SBarry Smith } 1047d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 10480513a670SBarry Smith } 10499566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 10503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1051480ef9eaSBarry Smith } 1052cddf8d76SBarry Smith 10539804daf3SBarry Smith #include <petscdraw.h> 1054d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqAIJ_Draw(Mat A, PetscViewer viewer) 1055d71ae5a4SJacob Faibussowitsch { 1056b0a32e0cSBarry Smith PetscDraw draw; 105736db0b34SBarry Smith PetscReal xr, yr, xl, yl, h, w; 1058ace3abfcSBarry Smith PetscBool isnull; 1059480ef9eaSBarry Smith 1060480ef9eaSBarry Smith PetscFunctionBegin; 10619566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 10629566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 10633ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 1064480ef9eaSBarry Smith 10659371c9d4SSatish Balay xr = A->cmap->n; 10669371c9d4SSatish Balay yr = A->rmap->n; 10679371c9d4SSatish Balay h = yr / 10.0; 10689371c9d4SSatish Balay w = xr / 10.0; 10699371c9d4SSatish Balay xr += w; 10709371c9d4SSatish Balay yr += h; 10719371c9d4SSatish Balay xl = -w; 10729371c9d4SSatish Balay yl = -h; 10739566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr)); 10749566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer)); 10759566063dSJacob Faibussowitsch PetscCall(PetscDrawZoom(draw, MatView_SeqAIJ_Draw_Zoom, A)); 10769566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL)); 10779566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 10783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1079416022c9SBarry Smith } 1080416022c9SBarry Smith 1081d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqAIJ(Mat A, PetscViewer viewer) 1082d71ae5a4SJacob Faibussowitsch { 1083ace3abfcSBarry Smith PetscBool iascii, isbinary, isdraw; 1084416022c9SBarry Smith 10853a40ed3dSBarry Smith PetscFunctionBegin; 10869566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 10879566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 10889566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 10891baa6e33SBarry Smith if (iascii) PetscCall(MatView_SeqAIJ_ASCII(A, viewer)); 10901baa6e33SBarry Smith else if (isbinary) PetscCall(MatView_SeqAIJ_Binary(A, viewer)); 10911baa6e33SBarry Smith else if (isdraw) PetscCall(MatView_SeqAIJ_Draw(A, viewer)); 10929566063dSJacob Faibussowitsch PetscCall(MatView_SeqAIJ_Inode(A, viewer)); 10933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 109417ab2063SBarry Smith } 109519bcc07fSBarry Smith 1096d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A, MatAssemblyType mode) 1097d71ae5a4SJacob Faibussowitsch { 1098416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1099580bdb30SBarry Smith PetscInt fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax; 1100d0f46423SBarry Smith PetscInt m = A->rmap->n, *ip, N, *ailen = a->ilen, rmax = 0; 110154f21887SBarry Smith MatScalar *aa = a->a, *ap; 11023447b6efSHong Zhang PetscReal ratio = 0.6; 110317ab2063SBarry Smith 11043a40ed3dSBarry Smith PetscFunctionBegin; 11053ba16761SJacob Faibussowitsch if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(PETSC_SUCCESS); 11069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 1107b215bc84SStefano Zampini if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) { 1108b215bc84SStefano Zampini /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */ 11099566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A, mode)); 11103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1111b215bc84SStefano Zampini } 111217ab2063SBarry Smith 111343ee02c3SBarry Smith if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 111417ab2063SBarry Smith for (i = 1; i < m; i++) { 1115416022c9SBarry Smith /* move each row back by the amount of empty slots (fshift) before it*/ 111617ab2063SBarry Smith fshift += imax[i - 1] - ailen[i - 1]; 111794a9d846SBarry Smith rmax = PetscMax(rmax, ailen[i]); 111817ab2063SBarry Smith if (fshift) { 1119bfeeae90SHong Zhang ip = aj + ai[i]; 1120bfeeae90SHong Zhang ap = aa + ai[i]; 112117ab2063SBarry Smith N = ailen[i]; 11229566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ip - fshift, ip, N)); 112348a46eb9SPierre Jolivet if (!A->structure_only) PetscCall(PetscArraymove(ap - fshift, ap, N)); 112417ab2063SBarry Smith } 112517ab2063SBarry Smith ai[i] = ai[i - 1] + ailen[i - 1]; 112617ab2063SBarry Smith } 112717ab2063SBarry Smith if (m) { 112817ab2063SBarry Smith fshift += imax[m - 1] - ailen[m - 1]; 112917ab2063SBarry Smith ai[m] = ai[m - 1] + ailen[m - 1]; 113017ab2063SBarry Smith } 113117ab2063SBarry Smith /* reset ilen and imax for each row */ 11327b083b7cSBarry Smith a->nonzerorowcnt = 0; 1133396832f4SHong Zhang if (A->structure_only) { 11349566063dSJacob Faibussowitsch PetscCall(PetscFree(a->imax)); 11359566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ilen)); 1136396832f4SHong Zhang } else { /* !A->structure_only */ 113717ab2063SBarry Smith for (i = 0; i < m; i++) { 113817ab2063SBarry Smith ailen[i] = imax[i] = ai[i + 1] - ai[i]; 11397b083b7cSBarry Smith a->nonzerorowcnt += ((ai[i + 1] - ai[i]) > 0); 114017ab2063SBarry Smith } 1141396832f4SHong Zhang } 1142bfeeae90SHong Zhang a->nz = ai[m]; 1143aed4548fSBarry 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); 114417ab2063SBarry Smith 11459566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 11469566063dSJacob 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)); 11479566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues() is %" PetscInt_FMT "\n", a->reallocs)); 11489566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Maximum nonzeros in any row is %" PetscInt_FMT "\n", rmax)); 11492205254eSKarl Rupp 11508e58a170SBarry Smith A->info.mallocs += a->reallocs; 1151dd5f02e7SSatish Balay a->reallocs = 0; 11526712e2f1SBarry Smith A->info.nz_unneeded = (PetscReal)fshift; 115336db0b34SBarry Smith a->rmax = rmax; 11544e220ebcSLois Curfman McInnes 115548a46eb9SPierre Jolivet if (!A->structure_only) PetscCall(MatCheckCompressedRow(A, a->nonzerorowcnt, &a->compressedrow, a->i, m, ratio)); 11569566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A, mode)); 11573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 115817ab2063SBarry Smith } 115917ab2063SBarry Smith 1160d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRealPart_SeqAIJ(Mat A) 1161d71ae5a4SJacob Faibussowitsch { 116299cafbc1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 116399cafbc1SBarry Smith PetscInt i, nz = a->nz; 11642e5835c6SStefano Zampini MatScalar *aa; 116599cafbc1SBarry Smith 116699cafbc1SBarry Smith PetscFunctionBegin; 11679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 116899cafbc1SBarry Smith for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]); 11699566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 11709566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 11713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 117299cafbc1SBarry Smith } 117399cafbc1SBarry Smith 1174d71ae5a4SJacob Faibussowitsch PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A) 1175d71ae5a4SJacob Faibussowitsch { 117699cafbc1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 117799cafbc1SBarry Smith PetscInt i, nz = a->nz; 11782e5835c6SStefano Zampini MatScalar *aa; 117999cafbc1SBarry Smith 118099cafbc1SBarry Smith PetscFunctionBegin; 11819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 118299cafbc1SBarry Smith for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]); 11839566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 11849566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 11853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 118699cafbc1SBarry Smith } 118799cafbc1SBarry Smith 1188d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_SeqAIJ(Mat A) 1189d71ae5a4SJacob Faibussowitsch { 1190fff043a9SJunchao Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1191fff043a9SJunchao Zhang MatScalar *aa; 11923a40ed3dSBarry Smith 11933a40ed3dSBarry Smith PetscFunctionBegin; 11949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayWrite(A, &aa)); 11959566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(aa, a->i[A->rmap->n])); 11969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayWrite(A, &aa)); 11979566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 11983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 119917ab2063SBarry Smith } 1200416022c9SBarry Smith 1201d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_SeqAIJ(Mat A) 1202d71ae5a4SJacob Faibussowitsch { 1203416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1204d5d45c9bSBarry Smith 12053a40ed3dSBarry Smith PetscFunctionBegin; 1206aa482453SBarry Smith #if defined(PETSC_USE_LOG) 12073ba16761SJacob Faibussowitsch PetscCall(PetscLogObjectState((PetscObject)A, "Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT, A->rmap->n, A->cmap->n, a->nz)); 120817ab2063SBarry Smith #endif 12099566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(A, &a->a, &a->j, &a->i)); 12109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 12119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 12129566063dSJacob Faibussowitsch PetscCall(PetscFree(a->diag)); 12139566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ibdiag)); 12149566063dSJacob Faibussowitsch PetscCall(PetscFree(a->imax)); 12159566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ilen)); 12169566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ipre)); 12179566063dSJacob Faibussowitsch PetscCall(PetscFree3(a->idiag, a->mdiag, a->ssor_work)); 12189566063dSJacob Faibussowitsch PetscCall(PetscFree(a->solve_work)); 12199566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 12209566063dSJacob Faibussowitsch PetscCall(PetscFree(a->saved_values)); 12219566063dSJacob Faibussowitsch PetscCall(PetscFree2(a->compressedrow.i, a->compressedrow.rindex)); 12229566063dSJacob Faibussowitsch PetscCall(MatDestroy_SeqAIJ_Inode(A)); 12239566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 1224901853e0SKris Buschelman 12256718818eSStefano Zampini /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this. 12266718818eSStefano Zampini That function is so heavily used (sometimes in an hidden way through multnumeric function pointers) 12276718818eSStefano Zampini that is hard to properly add this data to the MatProduct data. We free it here to avoid 12286718818eSStefano Zampini users reusing the matrix object with different data to incur in obscure segmentation faults 12296718818eSStefano Zampini due to different matrix sizes */ 12309566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc__ab_dense", NULL)); 12316718818eSStefano Zampini 12329566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL)); 12332e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "PetscMatlabEnginePut_C", NULL)); 12342e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "PetscMatlabEngineGet_C", NULL)); 12359566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetColumnIndices_C", NULL)); 12369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatStoreValues_C", NULL)); 12379566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatRetrieveValues_C", NULL)); 12389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqsbaij_C", NULL)); 12399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqbaij_C", NULL)); 12409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijperm_C", NULL)); 12412e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijsell_C", NULL)); 12422e956fe4SStefano Zampini #if defined(PETSC_HAVE_MKL_SPARSE) 12432e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijmkl_C", NULL)); 12442e956fe4SStefano Zampini #endif 12454222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA) 12469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijcusparse_C", NULL)); 12479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_seqaij_C", NULL)); 12489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaijcusparse_C", NULL)); 12494222ddf1SHong Zhang #endif 1250d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_HIP) 1251d5e393b6SSuyash Tandon PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijhipsparse_C", NULL)); 1252d5e393b6SSuyash Tandon PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijhipsparse_seqaij_C", NULL)); 1253d5e393b6SSuyash Tandon PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaijhipsparse_C", NULL)); 1254d5e393b6SSuyash Tandon #endif 12553d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 12569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijkokkos_C", NULL)); 12573d0639e7SStefano Zampini #endif 12589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijcrl_C", NULL)); 1259af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 12609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_elemental_C", NULL)); 1261af8000cdSHong Zhang #endif 1262d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 12639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_scalapack_C", NULL)); 1264d24d4204SJose E. Roman #endif 126563c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 12669566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_hypre_C", NULL)); 12679566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_transpose_seqaij_seqaij_C", NULL)); 126863c07aadSStefano Zampini #endif 12699566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqdense_C", NULL)); 12709566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqsell_C", NULL)); 12719566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_is_C", NULL)); 12729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatIsTranspose_C", NULL)); 12732e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatIsHermitianTranspose_C", NULL)); 12749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", NULL)); 12759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatResetPreallocation_C", NULL)); 12769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetPreallocationCSR_C", NULL)); 12779566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatReorderForNonzeroDiagonal_C", NULL)); 12789566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_is_seqaij_C", NULL)); 12799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqdense_seqaij_C", NULL)); 12809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaij_C", NULL)); 12819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJKron_C", NULL)); 12829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 12839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 12842e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL)); 12852e956fe4SStefano Zampini /* these calls do not belong here: the subclasses Duplicate/Destroy are wrong */ 12862e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaijsell_seqaij_C", NULL)); 12872e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaijperm_seqaij_C", NULL)); 12882e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijviennacl_C", NULL)); 12892e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijviennacl_seqdense_C", NULL)); 12902e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijviennacl_seqaij_C", NULL)); 12913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 129217ab2063SBarry Smith } 129317ab2063SBarry Smith 1294d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetOption_SeqAIJ(Mat A, MatOption op, PetscBool flg) 1295d71ae5a4SJacob Faibussowitsch { 1296416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 12973a40ed3dSBarry Smith 12983a40ed3dSBarry Smith PetscFunctionBegin; 1299a65d3064SKris Buschelman switch (op) { 1300d71ae5a4SJacob Faibussowitsch case MAT_ROW_ORIENTED: 1301d71ae5a4SJacob Faibussowitsch a->roworiented = flg; 1302d71ae5a4SJacob Faibussowitsch break; 1303d71ae5a4SJacob Faibussowitsch case MAT_KEEP_NONZERO_PATTERN: 1304d71ae5a4SJacob Faibussowitsch a->keepnonzeropattern = flg; 1305d71ae5a4SJacob Faibussowitsch break; 1306d71ae5a4SJacob Faibussowitsch case MAT_NEW_NONZERO_LOCATIONS: 1307d71ae5a4SJacob Faibussowitsch a->nonew = (flg ? 0 : 1); 1308d71ae5a4SJacob Faibussowitsch break; 1309d71ae5a4SJacob Faibussowitsch case MAT_NEW_NONZERO_LOCATION_ERR: 1310d71ae5a4SJacob Faibussowitsch a->nonew = (flg ? -1 : 0); 1311d71ae5a4SJacob Faibussowitsch break; 1312d71ae5a4SJacob Faibussowitsch case MAT_NEW_NONZERO_ALLOCATION_ERR: 1313d71ae5a4SJacob Faibussowitsch a->nonew = (flg ? -2 : 0); 1314d71ae5a4SJacob Faibussowitsch break; 1315d71ae5a4SJacob Faibussowitsch case MAT_UNUSED_NONZERO_LOCATION_ERR: 1316d71ae5a4SJacob Faibussowitsch a->nounused = (flg ? -1 : 0); 1317d71ae5a4SJacob Faibussowitsch break; 1318d71ae5a4SJacob Faibussowitsch case MAT_IGNORE_ZERO_ENTRIES: 1319d71ae5a4SJacob Faibussowitsch a->ignorezeroentries = flg; 1320d71ae5a4SJacob Faibussowitsch break; 13213d472b54SHong Zhang case MAT_SPD: 1322b1646e73SJed Brown case MAT_SYMMETRIC: 1323b1646e73SJed Brown case MAT_STRUCTURALLY_SYMMETRIC: 1324b1646e73SJed Brown case MAT_HERMITIAN: 1325b1646e73SJed Brown case MAT_SYMMETRY_ETERNAL: 1326957cac9fSHong Zhang case MAT_STRUCTURE_ONLY: 1327b94d7dedSBarry Smith case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 1328b94d7dedSBarry Smith case MAT_SPD_ETERNAL: 1329b94d7dedSBarry Smith /* if the diagonal matrix is square it inherits some of the properties above */ 13305021d80fSJed Brown break; 13318c78258cSHong Zhang case MAT_FORCE_DIAGONAL_ENTRIES: 1332a65d3064SKris Buschelman case MAT_IGNORE_OFF_PROC_ENTRIES: 1333d71ae5a4SJacob Faibussowitsch case MAT_USE_HASH_TABLE: 1334d71ae5a4SJacob Faibussowitsch PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op])); 1335d71ae5a4SJacob Faibussowitsch break; 1336d71ae5a4SJacob Faibussowitsch case MAT_USE_INODES: 1337d71ae5a4SJacob Faibussowitsch PetscCall(MatSetOption_SeqAIJ_Inode(A, MAT_USE_INODES, flg)); 1338d71ae5a4SJacob Faibussowitsch break; 1339d71ae5a4SJacob Faibussowitsch case MAT_SUBMAT_SINGLEIS: 1340d71ae5a4SJacob Faibussowitsch A->submat_singleis = flg; 1341d71ae5a4SJacob Faibussowitsch break; 1342071fcb05SBarry Smith case MAT_SORTED_FULL: 1343071fcb05SBarry Smith if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 1344071fcb05SBarry Smith else A->ops->setvalues = MatSetValues_SeqAIJ; 1345071fcb05SBarry Smith break; 1346d71ae5a4SJacob Faibussowitsch case MAT_FORM_EXPLICIT_TRANSPOSE: 1347d71ae5a4SJacob Faibussowitsch A->form_explicit_transpose = flg; 1348d71ae5a4SJacob Faibussowitsch break; 1349d71ae5a4SJacob Faibussowitsch default: 1350d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %d", op); 1351a65d3064SKris Buschelman } 13523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 135317ab2063SBarry Smith } 135417ab2063SBarry Smith 1355d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A, Vec v) 1356d71ae5a4SJacob Faibussowitsch { 1357416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1358fdc842d1SBarry Smith PetscInt i, j, n, *ai = a->i, *aj = a->j; 1359c898d852SStefano Zampini PetscScalar *x; 1360c898d852SStefano Zampini const PetscScalar *aa; 136117ab2063SBarry Smith 13623a40ed3dSBarry Smith PetscFunctionBegin; 13639566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 136408401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 13659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 1366d5f3da31SBarry Smith if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) { 1367d3e70bfaSHong Zhang PetscInt *diag = a->diag; 13689566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 13692c990fa1SHong Zhang for (i = 0; i < n; i++) x[i] = 1.0 / aa[diag[i]]; 13709566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 13719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 13723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 137335e7444dSHong Zhang } 137435e7444dSHong Zhang 13759566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 137635e7444dSHong Zhang for (i = 0; i < n; i++) { 1377fdc842d1SBarry Smith x[i] = 0.0; 137835e7444dSHong Zhang for (j = ai[i]; j < ai[i + 1]; j++) { 137935e7444dSHong Zhang if (aj[j] == i) { 138035e7444dSHong Zhang x[i] = aa[j]; 138117ab2063SBarry Smith break; 138217ab2063SBarry Smith } 138317ab2063SBarry Smith } 138417ab2063SBarry Smith } 13859566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 13869566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 13873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 138817ab2063SBarry Smith } 138917ab2063SBarry Smith 1390c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 1391d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A, Vec xx, Vec zz, Vec yy) 1392d71ae5a4SJacob Faibussowitsch { 1393416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 13945f22a7b3SSebastian Grimberg const MatScalar *aa; 1395d9ca1df4SBarry Smith PetscScalar *y; 1396d9ca1df4SBarry Smith const PetscScalar *x; 1397d0f46423SBarry Smith PetscInt m = A->rmap->n; 13985c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 13995f22a7b3SSebastian Grimberg const MatScalar *v; 1400a77337e4SBarry Smith PetscScalar alpha; 1401d9ca1df4SBarry Smith PetscInt n, i, j; 1402d9ca1df4SBarry Smith const PetscInt *idx, *ii, *ridx = NULL; 14033447b6efSHong Zhang Mat_CompressedRow cprow = a->compressedrow; 1404ace3abfcSBarry Smith PetscBool usecprow = cprow.use; 14055c897100SBarry Smith #endif 140617ab2063SBarry Smith 14073a40ed3dSBarry Smith PetscFunctionBegin; 14089566063dSJacob Faibussowitsch if (zz != yy) PetscCall(VecCopy(zz, yy)); 14099566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 14109566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy, &y)); 14119566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 14125c897100SBarry Smith 14135c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 1414fff043a9SJunchao Zhang fortranmulttransposeaddaij_(&m, x, a->i, a->j, aa, y); 14155c897100SBarry Smith #else 14163447b6efSHong Zhang if (usecprow) { 14173447b6efSHong Zhang m = cprow.nrows; 14183447b6efSHong Zhang ii = cprow.i; 14197b2bb3b9SHong Zhang ridx = cprow.rindex; 14203447b6efSHong Zhang } else { 14213447b6efSHong Zhang ii = a->i; 14223447b6efSHong Zhang } 142317ab2063SBarry Smith for (i = 0; i < m; i++) { 14243447b6efSHong Zhang idx = a->j + ii[i]; 1425fff043a9SJunchao Zhang v = aa + ii[i]; 14263447b6efSHong Zhang n = ii[i + 1] - ii[i]; 14273447b6efSHong Zhang if (usecprow) { 14287b2bb3b9SHong Zhang alpha = x[ridx[i]]; 14293447b6efSHong Zhang } else { 143017ab2063SBarry Smith alpha = x[i]; 14313447b6efSHong Zhang } 143204fbf559SBarry Smith for (j = 0; j < n; j++) y[idx[j]] += alpha * v[j]; 143317ab2063SBarry Smith } 14345c897100SBarry Smith #endif 14359566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 14369566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 14379566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy, &y)); 14389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 14393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 144017ab2063SBarry Smith } 144117ab2063SBarry Smith 1442d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTranspose_SeqAIJ(Mat A, Vec xx, Vec yy) 1443d71ae5a4SJacob Faibussowitsch { 14445c897100SBarry Smith PetscFunctionBegin; 14459566063dSJacob Faibussowitsch PetscCall(VecSet(yy, 0.0)); 14469566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd_SeqAIJ(A, xx, yy, yy)); 14473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14485c897100SBarry Smith } 14495c897100SBarry Smith 1450c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 145178b84d54SShri Abhyankar 1452d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMult_SeqAIJ(Mat A, Vec xx, Vec yy) 1453d71ae5a4SJacob Faibussowitsch { 1454416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1455d9fead3dSBarry Smith PetscScalar *y; 145654f21887SBarry Smith const PetscScalar *x; 1457fff043a9SJunchao Zhang const MatScalar *aa, *a_a; 1458003131ecSBarry Smith PetscInt m = A->rmap->n; 14590298fd71SBarry Smith const PetscInt *aj, *ii, *ridx = NULL; 14607b083b7cSBarry Smith PetscInt n, i; 1461362ced78SSatish Balay PetscScalar sum; 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; 148297952fefSHong Zhang for (i = 0; i < m; i++) { 148397952fefSHong Zhang n = ii[i + 1] - ii[i]; 148497952fefSHong Zhang aj = a->j + ii[i]; 1485fff043a9SJunchao Zhang aa = a_a + ii[i]; 148697952fefSHong Zhang sum = 0.0; 1487003131ecSBarry Smith PetscSparseDensePlusDot(sum, x, aa, aj, n); 1488003131ecSBarry Smith /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 148997952fefSHong Zhang y[*ridx++] = sum; 149097952fefSHong Zhang } 149197952fefSHong Zhang } else { /* do not use compressed row format */ 1492b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ) 14933d3eaba7SBarry Smith aj = a->j; 1494fff043a9SJunchao Zhang aa = a_a; 1495b05257ddSBarry Smith fortranmultaij_(&m, x, ii, aj, aa, y); 1496b05257ddSBarry Smith #else 149717ab2063SBarry Smith for (i = 0; i < m; i++) { 1498003131ecSBarry Smith n = ii[i + 1] - ii[i]; 1499003131ecSBarry Smith aj = a->j + ii[i]; 1500fff043a9SJunchao Zhang aa = a_a + ii[i]; 150117ab2063SBarry Smith 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 1514d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultMax_SeqAIJ(Mat A, Vec xx, Vec yy) 1515d71ae5a4SJacob Faibussowitsch { 1516b434eb95SMatthew G. Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1517b434eb95SMatthew G. Knepley PetscScalar *y; 1518b434eb95SMatthew G. Knepley const PetscScalar *x; 1519fff043a9SJunchao Zhang const MatScalar *aa, *a_a; 1520b434eb95SMatthew G. Knepley PetscInt m = A->rmap->n; 1521b434eb95SMatthew G. Knepley const PetscInt *aj, *ii, *ridx = NULL; 1522b434eb95SMatthew G. Knepley PetscInt n, i, nonzerorow = 0; 1523b434eb95SMatthew G. Knepley PetscScalar sum; 1524b434eb95SMatthew G. Knepley PetscBool usecprow = a->compressedrow.use; 1525b434eb95SMatthew G. Knepley 1526b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 1527b434eb95SMatthew G. Knepley #pragma disjoint(*x, *y, *aa) 1528b434eb95SMatthew G. Knepley #endif 1529b434eb95SMatthew G. Knepley 1530b434eb95SMatthew G. Knepley PetscFunctionBegin; 15319566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 15329566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 15339566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy, &y)); 1534b434eb95SMatthew G. Knepley if (usecprow) { /* use compressed row format */ 1535b434eb95SMatthew G. Knepley m = a->compressedrow.nrows; 1536b434eb95SMatthew G. Knepley ii = a->compressedrow.i; 1537b434eb95SMatthew G. Knepley ridx = a->compressedrow.rindex; 1538b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1539b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1540b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1541fff043a9SJunchao Zhang aa = a_a + ii[i]; 1542b434eb95SMatthew G. Knepley sum = 0.0; 1543b434eb95SMatthew G. Knepley nonzerorow += (n > 0); 1544b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1545b434eb95SMatthew G. Knepley /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 1546b434eb95SMatthew G. Knepley y[*ridx++] = sum; 1547b434eb95SMatthew G. Knepley } 1548b434eb95SMatthew G. Knepley } else { /* do not use compressed row format */ 15493d3eaba7SBarry Smith ii = a->i; 1550b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1551b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1552b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1553fff043a9SJunchao Zhang aa = a_a + ii[i]; 1554b434eb95SMatthew G. Knepley sum = 0.0; 1555b434eb95SMatthew G. Knepley nonzerorow += (n > 0); 1556b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1557b434eb95SMatthew G. Knepley y[i] = sum; 1558b434eb95SMatthew G. Knepley } 1559b434eb95SMatthew G. Knepley } 15609566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz - nonzerorow)); 15619566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 15629566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy, &y)); 15639566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a)); 15643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1565b434eb95SMatthew G. Knepley } 1566b434eb95SMatthew G. Knepley 1567d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultAddMax_SeqAIJ(Mat A, Vec xx, Vec yy, Vec zz) 1568d71ae5a4SJacob Faibussowitsch { 1569b434eb95SMatthew G. Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1570b434eb95SMatthew G. Knepley PetscScalar *y, *z; 1571b434eb95SMatthew G. Knepley const PetscScalar *x; 1572fff043a9SJunchao Zhang const MatScalar *aa, *a_a; 1573b434eb95SMatthew G. Knepley PetscInt m = A->rmap->n, *aj, *ii; 1574b434eb95SMatthew G. Knepley PetscInt n, i, *ridx = NULL; 1575b434eb95SMatthew G. Knepley PetscScalar sum; 1576b434eb95SMatthew G. Knepley PetscBool usecprow = a->compressedrow.use; 1577b434eb95SMatthew G. Knepley 1578b434eb95SMatthew G. Knepley PetscFunctionBegin; 15799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 15809566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 15819566063dSJacob Faibussowitsch PetscCall(VecGetArrayPair(yy, zz, &y, &z)); 1582b434eb95SMatthew G. Knepley if (usecprow) { /* use compressed row format */ 158348a46eb9SPierre Jolivet if (zz != yy) PetscCall(PetscArraycpy(z, y, m)); 1584b434eb95SMatthew G. Knepley m = a->compressedrow.nrows; 1585b434eb95SMatthew G. Knepley ii = a->compressedrow.i; 1586b434eb95SMatthew G. Knepley ridx = a->compressedrow.rindex; 1587b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1588b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1589b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1590fff043a9SJunchao Zhang aa = a_a + ii[i]; 1591b434eb95SMatthew G. Knepley sum = y[*ridx]; 1592b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1593b434eb95SMatthew G. Knepley z[*ridx++] = sum; 1594b434eb95SMatthew G. Knepley } 1595b434eb95SMatthew G. Knepley } else { /* do not use compressed row format */ 15963d3eaba7SBarry Smith ii = a->i; 1597b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1598b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1599b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1600fff043a9SJunchao Zhang aa = a_a + ii[i]; 1601b434eb95SMatthew G. Knepley sum = y[i]; 1602b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1603b434eb95SMatthew G. Knepley z[i] = sum; 1604b434eb95SMatthew G. Knepley } 1605b434eb95SMatthew G. Knepley } 16069566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 16079566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 16089566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayPair(yy, zz, &y, &z)); 16099566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a)); 16103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1611b434eb95SMatthew G. Knepley } 1612b434eb95SMatthew G. Knepley 1613c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h> 1614d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultAdd_SeqAIJ(Mat A, Vec xx, Vec yy, Vec zz) 1615d71ae5a4SJacob Faibussowitsch { 1616416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1617f15663dcSBarry Smith PetscScalar *y, *z; 1618f15663dcSBarry Smith const PetscScalar *x; 1619fff043a9SJunchao Zhang const MatScalar *aa, *a_a; 1620d9ca1df4SBarry Smith const PetscInt *aj, *ii, *ridx = NULL; 1621d9ca1df4SBarry Smith PetscInt m = A->rmap->n, n, i; 1622362ced78SSatish Balay PetscScalar sum; 1623ace3abfcSBarry Smith PetscBool usecprow = a->compressedrow.use; 16249ea0dfa2SSatish Balay 16253a40ed3dSBarry Smith PetscFunctionBegin; 1626b215bc84SStefano Zampini if (a->inode.use && a->inode.checked) { 16279566063dSJacob Faibussowitsch PetscCall(MatMultAdd_SeqAIJ_Inode(A, xx, yy, zz)); 16283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1629b215bc84SStefano Zampini } 16309566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 16319566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 16329566063dSJacob Faibussowitsch PetscCall(VecGetArrayPair(yy, zz, &y, &z)); 16334eb6d288SHong Zhang if (usecprow) { /* use compressed row format */ 163448a46eb9SPierre Jolivet if (zz != yy) PetscCall(PetscArraycpy(z, y, m)); 163597952fefSHong Zhang m = a->compressedrow.nrows; 163697952fefSHong Zhang ii = a->compressedrow.i; 163797952fefSHong Zhang ridx = a->compressedrow.rindex; 163897952fefSHong Zhang for (i = 0; i < m; i++) { 163997952fefSHong Zhang n = ii[i + 1] - ii[i]; 164097952fefSHong Zhang aj = a->j + ii[i]; 1641fff043a9SJunchao Zhang aa = a_a + ii[i]; 164297952fefSHong Zhang sum = y[*ridx]; 1643f15663dcSBarry Smith PetscSparseDensePlusDot(sum, x, aa, aj, n); 164497952fefSHong Zhang z[*ridx++] = sum; 164597952fefSHong Zhang } 164697952fefSHong Zhang } else { /* do not use compressed row format */ 16473d3eaba7SBarry Smith ii = a->i; 1648f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ) 16493d3eaba7SBarry Smith aj = a->j; 1650fff043a9SJunchao Zhang aa = a_a; 1651f15663dcSBarry Smith fortranmultaddaij_(&m, x, ii, aj, aa, y, z); 1652f15663dcSBarry Smith #else 165317ab2063SBarry Smith for (i = 0; i < m; i++) { 1654f15663dcSBarry Smith n = ii[i + 1] - ii[i]; 1655f15663dcSBarry Smith aj = a->j + ii[i]; 1656fff043a9SJunchao Zhang aa = a_a + ii[i]; 165717ab2063SBarry Smith 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 167017ab2063SBarry Smith /* 167117ab2063SBarry Smith Adds diagonal pointers to sparse matrix structure. 167217ab2063SBarry Smith */ 1673d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A) 1674d71ae5a4SJacob Faibussowitsch { 1675416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1676d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n; 1677c0c07093SJunchao Zhang PetscBool alreadySet = PETSC_TRUE; 167817ab2063SBarry Smith 16793a40ed3dSBarry Smith PetscFunctionBegin; 168009f38230SBarry Smith if (!a->diag) { 16819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &a->diag)); 1682c0c07093SJunchao Zhang alreadySet = PETSC_FALSE; 168309f38230SBarry Smith } 1684d0f46423SBarry Smith for (i = 0; i < A->rmap->n; i++) { 1685c0c07093SJunchao Zhang /* If A's diagonal is already correctly set, this fast track enables cheap and repeated MatMarkDiagonal_SeqAIJ() calls */ 1686c0c07093SJunchao Zhang if (alreadySet) { 1687c0c07093SJunchao Zhang PetscInt pos = a->diag[i]; 1688c0c07093SJunchao Zhang if (pos >= a->i[i] && pos < a->i[i + 1] && a->j[pos] == i) continue; 1689c0c07093SJunchao Zhang } 1690c0c07093SJunchao Zhang 169109f38230SBarry Smith a->diag[i] = a->i[i + 1]; 1692bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 1693bfeeae90SHong Zhang if (a->j[j] == i) { 169409f38230SBarry Smith a->diag[i] = j; 169517ab2063SBarry Smith break; 169617ab2063SBarry Smith } 169717ab2063SBarry Smith } 169817ab2063SBarry Smith } 16993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 170017ab2063SBarry Smith } 170117ab2063SBarry Smith 1702d71ae5a4SJacob Faibussowitsch PetscErrorCode MatShift_SeqAIJ(Mat A, PetscScalar v) 1703d71ae5a4SJacob Faibussowitsch { 170461ecd0c6SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 170561ecd0c6SBarry Smith const PetscInt *diag = (const PetscInt *)a->diag; 170661ecd0c6SBarry Smith const PetscInt *ii = (const PetscInt *)a->i; 170761ecd0c6SBarry Smith PetscInt i, *mdiag = NULL; 170861ecd0c6SBarry Smith PetscInt cnt = 0; /* how many diagonals are missing */ 170961ecd0c6SBarry Smith 171061ecd0c6SBarry Smith PetscFunctionBegin; 171161ecd0c6SBarry Smith if (!A->preallocated || !a->nz) { 17129566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(A, 1, NULL)); 17139566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(A, v)); 17143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 171561ecd0c6SBarry Smith } 171661ecd0c6SBarry Smith 171761ecd0c6SBarry Smith if (a->diagonaldense) { 171861ecd0c6SBarry Smith cnt = 0; 171961ecd0c6SBarry Smith } else { 17209566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n, &mdiag)); 172161ecd0c6SBarry Smith for (i = 0; i < A->rmap->n; i++) { 1722349d3b71SJunchao Zhang if (i < A->cmap->n && diag[i] >= ii[i + 1]) { /* 'out of range' rows never have diagonals */ 172361ecd0c6SBarry Smith cnt++; 172461ecd0c6SBarry Smith mdiag[i] = 1; 172561ecd0c6SBarry Smith } 172661ecd0c6SBarry Smith } 172761ecd0c6SBarry Smith } 172861ecd0c6SBarry Smith if (!cnt) { 17299566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(A, v)); 173061ecd0c6SBarry Smith } else { 1731b6f2aa54SBarry Smith PetscScalar *olda = a->a; /* preserve pointers to current matrix nonzeros structure and values */ 1732b6f2aa54SBarry Smith PetscInt *oldj = a->j, *oldi = a->i; 173361ecd0c6SBarry Smith PetscBool singlemalloc = a->singlemalloc, free_a = a->free_a, free_ij = a->free_ij; 173461ecd0c6SBarry Smith 173561ecd0c6SBarry Smith a->a = NULL; 173661ecd0c6SBarry Smith a->j = NULL; 173761ecd0c6SBarry Smith a->i = NULL; 173861ecd0c6SBarry Smith /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */ 1739ad540459SPierre Jolivet for (i = 0; i < PetscMin(A->rmap->n, A->cmap->n); i++) a->imax[i] += mdiag[i]; 17409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A, 0, a->imax)); 174161ecd0c6SBarry Smith 174261ecd0c6SBarry Smith /* copy old values into new matrix data structure */ 174361ecd0c6SBarry Smith for (i = 0; i < A->rmap->n; i++) { 17449566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &i, a->imax[i] - mdiag[i], &oldj[oldi[i]], &olda[oldi[i]], ADD_VALUES)); 174548a46eb9SPierre Jolivet if (i < A->cmap->n) PetscCall(MatSetValue(A, i, i, v, ADD_VALUES)); 1746447d62f5SStefano Zampini } 17479566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 17489566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 174961ecd0c6SBarry Smith if (singlemalloc) { 17509566063dSJacob Faibussowitsch PetscCall(PetscFree3(olda, oldj, oldi)); 175161ecd0c6SBarry Smith } else { 17529566063dSJacob Faibussowitsch if (free_a) PetscCall(PetscFree(olda)); 17539566063dSJacob Faibussowitsch if (free_ij) PetscCall(PetscFree(oldj)); 17549566063dSJacob Faibussowitsch if (free_ij) PetscCall(PetscFree(oldi)); 175561ecd0c6SBarry Smith } 175661ecd0c6SBarry Smith } 17579566063dSJacob Faibussowitsch PetscCall(PetscFree(mdiag)); 175861ecd0c6SBarry Smith a->diagonaldense = PETSC_TRUE; 17593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 176061ecd0c6SBarry Smith } 176161ecd0c6SBarry Smith 1762be5855fcSBarry Smith /* 1763be5855fcSBarry Smith Checks for missing diagonals 1764be5855fcSBarry Smith */ 1765d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A, PetscBool *missing, PetscInt *d) 1766d71ae5a4SJacob Faibussowitsch { 1767be5855fcSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 17687734d3b5SMatthew G. Knepley PetscInt *diag, *ii = a->i, i; 1769be5855fcSBarry Smith 1770be5855fcSBarry Smith PetscFunctionBegin; 177109f38230SBarry Smith *missing = PETSC_FALSE; 17727734d3b5SMatthew G. Knepley if (A->rmap->n > 0 && !ii) { 177309f38230SBarry Smith *missing = PETSC_TRUE; 177409f38230SBarry Smith if (d) *d = 0; 17759566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no entries therefore is missing diagonal\n")); 177609f38230SBarry Smith } else { 177701445905SHong Zhang PetscInt n; 177801445905SHong Zhang n = PetscMin(A->rmap->n, A->cmap->n); 1779f1e2ffcdSBarry Smith diag = a->diag; 178001445905SHong Zhang for (i = 0; i < n; i++) { 17817734d3b5SMatthew G. Knepley if (diag[i] >= ii[i + 1]) { 178209f38230SBarry Smith *missing = PETSC_TRUE; 178309f38230SBarry Smith if (d) *d = i; 17849566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix is missing diagonal number %" PetscInt_FMT "\n", i)); 1785358d2f5dSShri Abhyankar break; 178609f38230SBarry Smith } 1787be5855fcSBarry Smith } 1788be5855fcSBarry Smith } 17893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1790be5855fcSBarry Smith } 1791be5855fcSBarry Smith 17920da83c2eSBarry Smith #include <petscblaslapack.h> 17930da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h> 17940da83c2eSBarry Smith 17950da83c2eSBarry Smith /* 17960da83c2eSBarry Smith Note that values is allocated externally by the PC and then passed into this routine 17970da83c2eSBarry Smith */ 1798d71ae5a4SJacob Faibussowitsch PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *diag) 1799d71ae5a4SJacob Faibussowitsch { 18000da83c2eSBarry Smith PetscInt n = A->rmap->n, i, ncnt = 0, *indx, j, bsizemax = 0, *v_pivots; 18010da83c2eSBarry Smith PetscBool allowzeropivot, zeropivotdetected = PETSC_FALSE; 18020da83c2eSBarry Smith const PetscReal shift = 0.0; 18030da83c2eSBarry Smith PetscInt ipvt[5]; 18044e208921SJed Brown PetscCount flops = 0; 18050da83c2eSBarry Smith PetscScalar work[25], *v_work; 18060da83c2eSBarry Smith 18070da83c2eSBarry Smith PetscFunctionBegin; 18080da83c2eSBarry Smith allowzeropivot = PetscNot(A->erroriffailure); 18090da83c2eSBarry Smith for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 181008401ef6SPierre 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); 1811ad540459SPierre Jolivet for (i = 0; i < nblocks; i++) bsizemax = PetscMax(bsizemax, bsizes[i]); 18129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsizemax, &indx)); 181348a46eb9SPierre Jolivet if (bsizemax > 7) PetscCall(PetscMalloc2(bsizemax, &v_work, bsizemax, &v_pivots)); 18140da83c2eSBarry Smith ncnt = 0; 18150da83c2eSBarry Smith for (i = 0; i < nblocks; i++) { 18160da83c2eSBarry Smith for (j = 0; j < bsizes[i]; j++) indx[j] = ncnt + j; 18179566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, bsizes[i], indx, bsizes[i], indx, diag)); 18180da83c2eSBarry Smith switch (bsizes[i]) { 1819d71ae5a4SJacob Faibussowitsch case 1: 1820d71ae5a4SJacob Faibussowitsch *diag = 1.0 / (*diag); 1821d71ae5a4SJacob Faibussowitsch break; 18220da83c2eSBarry Smith case 2: 18239566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected)); 18240da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18259566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_2(diag)); 18260da83c2eSBarry Smith break; 18270da83c2eSBarry Smith case 3: 18289566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected)); 18290da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18309566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_3(diag)); 18310da83c2eSBarry Smith break; 18320da83c2eSBarry Smith case 4: 18339566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected)); 18340da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18359566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_4(diag)); 18360da83c2eSBarry Smith break; 18370da83c2eSBarry Smith case 5: 18389566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected)); 18390da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18409566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_5(diag)); 18410da83c2eSBarry Smith break; 18420da83c2eSBarry Smith case 6: 18439566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected)); 18440da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18459566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_6(diag)); 18460da83c2eSBarry Smith break; 18470da83c2eSBarry Smith case 7: 18489566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected)); 18490da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18509566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_7(diag)); 18510da83c2eSBarry Smith break; 18520da83c2eSBarry Smith default: 18539566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A(bsizes[i], diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected)); 18540da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18559566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_N(diag, bsizes[i])); 18560da83c2eSBarry Smith } 18570da83c2eSBarry Smith ncnt += bsizes[i]; 18580da83c2eSBarry Smith diag += bsizes[i] * bsizes[i]; 18594e208921SJed Brown flops += 2 * PetscPowInt(bsizes[i], 3) / 3; 18600da83c2eSBarry Smith } 18613ba16761SJacob Faibussowitsch PetscCall(PetscLogFlops(flops)); 186248a46eb9SPierre Jolivet if (bsizemax > 7) PetscCall(PetscFree2(v_work, v_pivots)); 18639566063dSJacob Faibussowitsch PetscCall(PetscFree(indx)); 18643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18650da83c2eSBarry Smith } 18660da83c2eSBarry Smith 1867422a814eSBarry Smith /* 1868422a814eSBarry Smith Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways 1869422a814eSBarry Smith */ 1870d71ae5a4SJacob Faibussowitsch PetscErrorCode MatInvertDiagonal_SeqAIJ(Mat A, PetscScalar omega, PetscScalar fshift) 1871d71ae5a4SJacob Faibussowitsch { 187271f1c65dSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1873d0f46423SBarry Smith PetscInt i, *diag, m = A->rmap->n; 18742e5835c6SStefano Zampini const MatScalar *v; 187554f21887SBarry Smith PetscScalar *idiag, *mdiag; 187671f1c65dSBarry Smith 187771f1c65dSBarry Smith PetscFunctionBegin; 18783ba16761SJacob Faibussowitsch if (a->idiagvalid) PetscFunctionReturn(PETSC_SUCCESS); 18799566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 188071f1c65dSBarry Smith diag = a->diag; 18814dfa11a4SJacob Faibussowitsch if (!a->idiag) { PetscCall(PetscMalloc3(m, &a->idiag, m, &a->mdiag, m, &a->ssor_work)); } 18822e5835c6SStefano Zampini 188371f1c65dSBarry Smith mdiag = a->mdiag; 188471f1c65dSBarry Smith idiag = a->idiag; 18859566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &v)); 1886422a814eSBarry Smith if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) { 188771f1c65dSBarry Smith for (i = 0; i < m; i++) { 188871f1c65dSBarry Smith mdiag[i] = v[diag[i]]; 1889899639b0SHong Zhang if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */ 1890899639b0SHong Zhang if (PetscRealPart(fshift)) { 18919566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Zero diagonal on row %" PetscInt_FMT "\n", i)); 18927b6c816cSBarry Smith A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18937b6c816cSBarry Smith A->factorerror_zeropivot_value = 0.0; 18947b6c816cSBarry Smith A->factorerror_zeropivot_row = i; 189598921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Zero diagonal on row %" PetscInt_FMT, i); 1896899639b0SHong Zhang } 189771f1c65dSBarry Smith idiag[i] = 1.0 / v[diag[i]]; 189871f1c65dSBarry Smith } 18999566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(m)); 190071f1c65dSBarry Smith } else { 190171f1c65dSBarry Smith for (i = 0; i < m; i++) { 190271f1c65dSBarry Smith mdiag[i] = v[diag[i]]; 190371f1c65dSBarry Smith idiag[i] = omega / (fshift + v[diag[i]]); 190471f1c65dSBarry Smith } 19059566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * m)); 190671f1c65dSBarry Smith } 190771f1c65dSBarry Smith a->idiagvalid = PETSC_TRUE; 19089566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &v)); 19093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 191071f1c65dSBarry Smith } 191171f1c65dSBarry Smith 1912c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h> 1913d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSOR_SeqAIJ(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal fshift, PetscInt its, PetscInt lits, Vec xx) 1914d71ae5a4SJacob Faibussowitsch { 1915416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1916e6d1f457SBarry Smith PetscScalar *x, d, sum, *t, scale; 19172e5835c6SStefano Zampini const MatScalar *v, *idiag = NULL, *mdiag, *aa; 191854f21887SBarry Smith const PetscScalar *b, *bs, *xb, *ts; 19193d3eaba7SBarry Smith PetscInt n, m = A->rmap->n, i; 192097f1f81fSBarry Smith const PetscInt *idx, *diag; 192117ab2063SBarry Smith 19223a40ed3dSBarry Smith PetscFunctionBegin; 1923b215bc84SStefano Zampini if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) { 19249566063dSJacob Faibussowitsch PetscCall(MatSOR_SeqAIJ_Inode(A, bb, omega, flag, fshift, its, lits, xx)); 19253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1926b215bc84SStefano Zampini } 1927b965ef7fSBarry Smith its = its * lits; 192891723122SBarry Smith 192971f1c65dSBarry Smith if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */ 19309566063dSJacob Faibussowitsch if (!a->idiagvalid) PetscCall(MatInvertDiagonal_SeqAIJ(A, omega, fshift)); 193171f1c65dSBarry Smith a->fshift = fshift; 193271f1c65dSBarry Smith a->omega = omega; 1933ed480e8bSBarry Smith 193471f1c65dSBarry Smith diag = a->diag; 193571f1c65dSBarry Smith t = a->ssor_work; 1936ed480e8bSBarry Smith idiag = a->idiag; 193771f1c65dSBarry Smith mdiag = a->mdiag; 1938ed480e8bSBarry Smith 19399566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 19409566063dSJacob Faibussowitsch PetscCall(VecGetArray(xx, &x)); 19419566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(bb, &b)); 1942ed480e8bSBarry Smith /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */ 194317ab2063SBarry Smith if (flag == SOR_APPLY_UPPER) { 194417ab2063SBarry Smith /* apply (U + D/omega) to the vector */ 1945ed480e8bSBarry Smith bs = b; 194617ab2063SBarry Smith for (i = 0; i < m; i++) { 194771f1c65dSBarry Smith d = fshift + mdiag[i]; 1948416022c9SBarry Smith n = a->i[i + 1] - diag[i] - 1; 1949ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 19502e5835c6SStefano Zampini v = aa + diag[i] + 1; 195117ab2063SBarry Smith sum = b[i] * d / omega; 1952003131ecSBarry Smith PetscSparseDensePlusDot(sum, bs, v, idx, n); 195317ab2063SBarry Smith x[i] = sum; 195417ab2063SBarry Smith } 19559566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx, &x)); 19569566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb, &b)); 19579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 19589566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 19593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 196017ab2063SBarry Smith } 1961c783ea89SBarry Smith 196208401ef6SPierre Jolivet PetscCheck(flag != SOR_APPLY_LOWER, PETSC_COMM_SELF, PETSC_ERR_SUP, "SOR_APPLY_LOWER is not implemented"); 1963f7d195e4SLawrence Mitchell if (flag & SOR_EISENSTAT) { 19644c500f23SPierre Jolivet /* Let A = L + U + D; where L is lower triangular, 1965887ee2caSBarry Smith U is upper triangular, E = D/omega; This routine applies 196617ab2063SBarry Smith 196717ab2063SBarry Smith (L + E)^{-1} A (U + E)^{-1} 196817ab2063SBarry Smith 1969887ee2caSBarry Smith to a vector efficiently using Eisenstat's trick. 197017ab2063SBarry Smith */ 197117ab2063SBarry Smith scale = (2.0 / omega) - 1.0; 197217ab2063SBarry Smith 197317ab2063SBarry Smith /* x = (E + U)^{-1} b */ 197417ab2063SBarry Smith for (i = m - 1; i >= 0; i--) { 1975416022c9SBarry Smith n = a->i[i + 1] - diag[i] - 1; 1976ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 19772e5835c6SStefano Zampini v = aa + diag[i] + 1; 197817ab2063SBarry Smith sum = b[i]; 1979e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 1980ed480e8bSBarry Smith x[i] = sum * idiag[i]; 198117ab2063SBarry Smith } 198217ab2063SBarry Smith 198317ab2063SBarry Smith /* t = b - (2*E - D)x */ 19842e5835c6SStefano Zampini v = aa; 19852205254eSKarl Rupp for (i = 0; i < m; i++) t[i] = b[i] - scale * (v[*diag++]) * x[i]; 198617ab2063SBarry Smith 198717ab2063SBarry Smith /* t = (E + L)^{-1}t */ 1988ed480e8bSBarry Smith ts = t; 1989416022c9SBarry Smith diag = a->diag; 199017ab2063SBarry Smith for (i = 0; i < m; i++) { 1991416022c9SBarry Smith n = diag[i] - a->i[i]; 1992ed480e8bSBarry Smith idx = a->j + a->i[i]; 19932e5835c6SStefano Zampini v = aa + a->i[i]; 199417ab2063SBarry Smith sum = t[i]; 1995003131ecSBarry Smith PetscSparseDenseMinusDot(sum, ts, v, idx, n); 1996ed480e8bSBarry Smith t[i] = sum * idiag[i]; 1997733d66baSBarry Smith /* x = x + t */ 1998733d66baSBarry Smith x[i] += t[i]; 199917ab2063SBarry Smith } 200017ab2063SBarry Smith 20019566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(6.0 * m - 1 + 2.0 * a->nz)); 20029566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx, &x)); 20039566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb, &b)); 20043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 200517ab2063SBarry Smith } 200617ab2063SBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 200717ab2063SBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 200817ab2063SBarry Smith for (i = 0; i < m; i++) { 2009416022c9SBarry Smith n = diag[i] - a->i[i]; 2010ed480e8bSBarry Smith idx = a->j + a->i[i]; 20112e5835c6SStefano Zampini v = aa + a->i[i]; 201217ab2063SBarry Smith sum = b[i]; 2013e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 20145c99c7daSBarry Smith t[i] = sum; 2015ed480e8bSBarry Smith x[i] = sum * idiag[i]; 201617ab2063SBarry Smith } 20175c99c7daSBarry Smith xb = t; 20189566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 20193a40ed3dSBarry Smith } else xb = b; 202017ab2063SBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 202117ab2063SBarry Smith for (i = m - 1; i >= 0; i--) { 2022416022c9SBarry Smith n = a->i[i + 1] - diag[i] - 1; 2023ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 20242e5835c6SStefano Zampini v = aa + diag[i] + 1; 202517ab2063SBarry Smith sum = xb[i]; 2026e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 20275c99c7daSBarry Smith if (xb == b) { 2028ed480e8bSBarry Smith x[i] = sum * idiag[i]; 20295c99c7daSBarry Smith } else { 2030b19a5dc2SMark Adams x[i] = (1 - omega) * x[i] + sum * idiag[i]; /* omega in idiag */ 203117ab2063SBarry Smith } 20325c99c7daSBarry Smith } 20339566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */ 203417ab2063SBarry Smith } 203517ab2063SBarry Smith its--; 203617ab2063SBarry Smith } 203717ab2063SBarry Smith while (its--) { 203817ab2063SBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 203917ab2063SBarry Smith for (i = 0; i < m; i++) { 2040b19a5dc2SMark Adams /* lower */ 2041b19a5dc2SMark Adams n = diag[i] - a->i[i]; 2042ed480e8bSBarry Smith idx = a->j + a->i[i]; 20432e5835c6SStefano Zampini v = aa + a->i[i]; 204417ab2063SBarry Smith sum = b[i]; 2045e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 2046b19a5dc2SMark Adams t[i] = sum; /* save application of the lower-triangular part */ 2047b19a5dc2SMark Adams /* upper */ 2048b19a5dc2SMark Adams n = a->i[i + 1] - diag[i] - 1; 2049b19a5dc2SMark Adams idx = a->j + diag[i] + 1; 20502e5835c6SStefano Zampini v = aa + diag[i] + 1; 2051b19a5dc2SMark Adams PetscSparseDenseMinusDot(sum, x, v, idx, n); 2052b19a5dc2SMark Adams x[i] = (1. - omega) * x[i] + sum * idiag[i]; /* omega in idiag */ 205317ab2063SBarry Smith } 2054b19a5dc2SMark Adams xb = t; 20559566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 2056b19a5dc2SMark Adams } else xb = b; 205717ab2063SBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 205817ab2063SBarry Smith for (i = m - 1; i >= 0; i--) { 2059b19a5dc2SMark Adams sum = xb[i]; 2060b19a5dc2SMark Adams if (xb == b) { 2061b19a5dc2SMark Adams /* whole matrix (no checkpointing available) */ 2062416022c9SBarry Smith n = a->i[i + 1] - a->i[i]; 2063ed480e8bSBarry Smith idx = a->j + a->i[i]; 20642e5835c6SStefano Zampini v = aa + a->i[i]; 2065e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 2066ed480e8bSBarry Smith x[i] = (1. - omega) * x[i] + (sum + mdiag[i] * x[i]) * idiag[i]; 2067b19a5dc2SMark Adams } else { /* lower-triangular part has been saved, so only apply upper-triangular */ 2068b19a5dc2SMark Adams n = a->i[i + 1] - diag[i] - 1; 2069b19a5dc2SMark Adams idx = a->j + diag[i] + 1; 20702e5835c6SStefano Zampini v = aa + diag[i] + 1; 2071b19a5dc2SMark Adams PetscSparseDenseMinusDot(sum, x, v, idx, n); 2072b19a5dc2SMark Adams x[i] = (1. - omega) * x[i] + sum * idiag[i]; /* omega in idiag */ 207317ab2063SBarry Smith } 2074b19a5dc2SMark Adams } 2075b19a5dc2SMark Adams if (xb == b) { 20769566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 2077b19a5dc2SMark Adams } else { 20789566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */ 2079b19a5dc2SMark Adams } 208017ab2063SBarry Smith } 208117ab2063SBarry Smith } 20829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 20839566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx, &x)); 20849566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb, &b)); 20853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 208617ab2063SBarry Smith } 208717ab2063SBarry Smith 2088d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetInfo_SeqAIJ(Mat A, MatInfoType flag, MatInfo *info) 2089d71ae5a4SJacob Faibussowitsch { 2090416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 20914e220ebcSLois Curfman McInnes 20923a40ed3dSBarry Smith PetscFunctionBegin; 20934e220ebcSLois Curfman McInnes info->block_size = 1.0; 20943966268fSBarry Smith info->nz_allocated = a->maxnz; 20953966268fSBarry Smith info->nz_used = a->nz; 20963966268fSBarry Smith info->nz_unneeded = (a->maxnz - a->nz); 20973966268fSBarry Smith info->assemblies = A->num_ass; 20983966268fSBarry Smith info->mallocs = A->info.mallocs; 20994dfa11a4SJacob Faibussowitsch info->memory = 0; /* REVIEW ME */ 2100d5f3da31SBarry Smith if (A->factortype) { 21014e220ebcSLois Curfman McInnes info->fill_ratio_given = A->info.fill_ratio_given; 21024e220ebcSLois Curfman McInnes info->fill_ratio_needed = A->info.fill_ratio_needed; 21034e220ebcSLois Curfman McInnes info->factor_mallocs = A->info.factor_mallocs; 21044e220ebcSLois Curfman McInnes } else { 21054e220ebcSLois Curfman McInnes info->fill_ratio_given = 0; 21064e220ebcSLois Curfman McInnes info->fill_ratio_needed = 0; 21074e220ebcSLois Curfman McInnes info->factor_mallocs = 0; 21084e220ebcSLois Curfman McInnes } 21093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 211017ab2063SBarry Smith } 211117ab2063SBarry Smith 2112d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroRows_SeqAIJ(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 2113d71ae5a4SJacob Faibussowitsch { 2114416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2115c7da8527SEric Chamberland PetscInt i, m = A->rmap->n - 1; 211697b48c8fSBarry Smith const PetscScalar *xx; 21172e5835c6SStefano Zampini PetscScalar *bb, *aa; 2118c7da8527SEric Chamberland PetscInt d = 0; 211917ab2063SBarry Smith 21203a40ed3dSBarry Smith PetscFunctionBegin; 212197b48c8fSBarry Smith if (x && b) { 21229566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 21239566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 212497b48c8fSBarry Smith for (i = 0; i < N; i++) { 2125aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 2126447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 212797b48c8fSBarry Smith bb[rows[i]] = diag * xx[rows[i]]; 212897b48c8fSBarry Smith } 21299566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 21309566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 213197b48c8fSBarry Smith } 213297b48c8fSBarry Smith 21339566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 2134a9817697SBarry Smith if (a->keepnonzeropattern) { 2135f1e2ffcdSBarry Smith for (i = 0; i < N; i++) { 2136aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 21379566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(&aa[a->i[rows[i]]], a->ilen[rows[i]])); 2138f1e2ffcdSBarry Smith } 2139f4df32b1SMatthew Knepley if (diag != 0.0) { 2140c7da8527SEric Chamberland for (i = 0; i < N; i++) { 2141c7da8527SEric Chamberland d = rows[i]; 2142447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 214308401ef6SPierre Jolivet PetscCheck(a->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); 2144c7da8527SEric Chamberland } 2145f1e2ffcdSBarry Smith for (i = 0; i < N; i++) { 2146447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 21472e5835c6SStefano Zampini aa[a->diag[rows[i]]] = diag; 2148f1e2ffcdSBarry Smith } 2149f1e2ffcdSBarry Smith } 2150f1e2ffcdSBarry Smith } else { 2151f4df32b1SMatthew Knepley if (diag != 0.0) { 215217ab2063SBarry Smith for (i = 0; i < N; i++) { 2153aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 21547ae801bdSBarry Smith if (a->ilen[rows[i]] > 0) { 2155447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) { 2156447d62f5SStefano Zampini a->ilen[rows[i]] = 0; 2157447d62f5SStefano Zampini } else { 2158416022c9SBarry Smith a->ilen[rows[i]] = 1; 21592e5835c6SStefano Zampini aa[a->i[rows[i]]] = diag; 2160bfeeae90SHong Zhang a->j[a->i[rows[i]]] = rows[i]; 2161447d62f5SStefano Zampini } 2162447d62f5SStefano Zampini } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */ 21639566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(A, 1, &rows[i], 1, &rows[i], &diag, INSERT_VALUES)); 216417ab2063SBarry Smith } 216517ab2063SBarry Smith } 21663a40ed3dSBarry Smith } else { 216717ab2063SBarry Smith for (i = 0; i < N; i++) { 2168aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 2169416022c9SBarry Smith a->ilen[rows[i]] = 0; 217017ab2063SBarry Smith } 217117ab2063SBarry Smith } 2172e56f5c9eSBarry Smith A->nonzerostate++; 2173f1e2ffcdSBarry Smith } 21749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 2175dbbe0bcdSBarry Smith PetscUseTypeMethod(A, assemblyend, MAT_FINAL_ASSEMBLY); 21763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 217717ab2063SBarry Smith } 217817ab2063SBarry Smith 2179d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 2180d71ae5a4SJacob Faibussowitsch { 21816e169961SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 21826e169961SBarry Smith PetscInt i, j, m = A->rmap->n - 1, d = 0; 21832b40b63fSBarry Smith PetscBool missing, *zeroed, vecs = PETSC_FALSE; 21846e169961SBarry Smith const PetscScalar *xx; 21852e5835c6SStefano Zampini PetscScalar *bb, *aa; 21866e169961SBarry Smith 21876e169961SBarry Smith PetscFunctionBegin; 21883ba16761SJacob Faibussowitsch if (!N) PetscFunctionReturn(PETSC_SUCCESS); 21899566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 21906e169961SBarry Smith if (x && b) { 21919566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 21929566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 21932b40b63fSBarry Smith vecs = PETSC_TRUE; 21946e169961SBarry Smith } 21959566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n, &zeroed)); 21966e169961SBarry Smith for (i = 0; i < N; i++) { 2197aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 21989566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(&aa[a->i[rows[i]]], a->ilen[rows[i]])); 21992205254eSKarl Rupp 22006e169961SBarry Smith zeroed[rows[i]] = PETSC_TRUE; 22016e169961SBarry Smith } 22026e169961SBarry Smith for (i = 0; i < A->rmap->n; i++) { 22036e169961SBarry Smith if (!zeroed[i]) { 22046e169961SBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 22054cf107fdSStefano Zampini if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) { 22062e5835c6SStefano Zampini if (vecs) bb[i] -= aa[j] * xx[a->j[j]]; 22072e5835c6SStefano Zampini aa[j] = 0.0; 22086e169961SBarry Smith } 22096e169961SBarry Smith } 22104cf107fdSStefano Zampini } else if (vecs && i < A->cmap->N) bb[i] = diag * xx[i]; 22116e169961SBarry Smith } 22126e169961SBarry Smith if (x && b) { 22139566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 22149566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 22156e169961SBarry Smith } 22169566063dSJacob Faibussowitsch PetscCall(PetscFree(zeroed)); 22176e169961SBarry Smith if (diag != 0.0) { 22189566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal_SeqAIJ(A, &missing, &d)); 22191d5a398dSstefano_zampini if (missing) { 22201d5a398dSstefano_zampini for (i = 0; i < N; i++) { 22214cf107fdSStefano Zampini if (rows[i] >= A->cmap->N) continue; 2222aed4548fSBarry 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]); 22239566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(A, 1, &rows[i], 1, &rows[i], &diag, INSERT_VALUES)); 22241d5a398dSstefano_zampini } 22251d5a398dSstefano_zampini } else { 2226ad540459SPierre Jolivet for (i = 0; i < N; i++) aa[a->diag[rows[i]]] = diag; 22276e169961SBarry Smith } 22281d5a398dSstefano_zampini } 22299566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 2230dbbe0bcdSBarry Smith PetscUseTypeMethod(A, assemblyend, MAT_FINAL_ASSEMBLY); 22313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22326e169961SBarry Smith } 22336e169961SBarry Smith 2234d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRow_SeqAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 2235d71ae5a4SJacob Faibussowitsch { 2236fff043a9SJunchao Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2237fff043a9SJunchao Zhang const PetscScalar *aa; 2238fff043a9SJunchao Zhang PetscInt *itmp; 223917ab2063SBarry Smith 22403a40ed3dSBarry Smith PetscFunctionBegin; 22419566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 2242416022c9SBarry Smith *nz = a->i[row + 1] - a->i[row]; 22432e5835c6SStefano Zampini if (v) *v = (PetscScalar *)(aa + a->i[row]); 224417ab2063SBarry Smith if (idx) { 2245bfeeae90SHong Zhang itmp = a->j + a->i[row]; 224626fbe8dcSKarl Rupp if (*nz) *idx = itmp; 2247f4259b30SLisandro Dalcin else *idx = NULL; 224817ab2063SBarry Smith } 22499566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 22503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 225117ab2063SBarry Smith } 225217ab2063SBarry Smith 2253d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreRow_SeqAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 2254d71ae5a4SJacob Faibussowitsch { 22553a40ed3dSBarry Smith PetscFunctionBegin; 2256cb4a9cd9SHong Zhang if (nz) *nz = 0; 22572e5835c6SStefano Zampini if (idx) *idx = NULL; 22582e5835c6SStefano Zampini if (v) *v = NULL; 22593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 226017ab2063SBarry Smith } 226117ab2063SBarry Smith 2262d71ae5a4SJacob Faibussowitsch PetscErrorCode MatNorm_SeqAIJ(Mat A, NormType type, PetscReal *nrm) 2263d71ae5a4SJacob Faibussowitsch { 2264416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 22652e5835c6SStefano Zampini const MatScalar *v; 226636db0b34SBarry Smith PetscReal sum = 0.0; 226797f1f81fSBarry Smith PetscInt i, j; 226817ab2063SBarry Smith 22693a40ed3dSBarry Smith PetscFunctionBegin; 22709566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &v)); 227117ab2063SBarry Smith if (type == NORM_FROBENIUS) { 2272570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16) 2273570b7f6dSBarry Smith PetscBLASInt one = 1, nz = a->nz; 2274792fecdfSBarry Smith PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&nz, v, &one)); 2275570b7f6dSBarry Smith #else 2276416022c9SBarry Smith for (i = 0; i < a->nz; i++) { 22779371c9d4SSatish Balay sum += PetscRealPart(PetscConj(*v) * (*v)); 22789371c9d4SSatish Balay v++; 227917ab2063SBarry Smith } 22808f1a2a5eSBarry Smith *nrm = PetscSqrtReal(sum); 2281570b7f6dSBarry Smith #endif 22829566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 22833a40ed3dSBarry Smith } else if (type == NORM_1) { 228436db0b34SBarry Smith PetscReal *tmp; 228597f1f81fSBarry Smith PetscInt *jj = a->j; 22869566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->cmap->n + 1, &tmp)); 2287064f8208SBarry Smith *nrm = 0.0; 2288416022c9SBarry Smith for (j = 0; j < a->nz; j++) { 22899371c9d4SSatish Balay tmp[*jj++] += PetscAbsScalar(*v); 22909371c9d4SSatish Balay v++; 229117ab2063SBarry Smith } 2292d0f46423SBarry Smith for (j = 0; j < A->cmap->n; j++) { 2293064f8208SBarry Smith if (tmp[j] > *nrm) *nrm = tmp[j]; 229417ab2063SBarry Smith } 22959566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp)); 22969566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(PetscMax(a->nz - 1, 0))); 22973a40ed3dSBarry Smith } else if (type == NORM_INFINITY) { 2298064f8208SBarry Smith *nrm = 0.0; 2299d0f46423SBarry Smith for (j = 0; j < A->rmap->n; j++) { 23002e5835c6SStefano Zampini const PetscScalar *v2 = v + a->i[j]; 230117ab2063SBarry Smith sum = 0.0; 2302416022c9SBarry Smith for (i = 0; i < a->i[j + 1] - a->i[j]; i++) { 23039371c9d4SSatish Balay sum += PetscAbsScalar(*v2); 23049371c9d4SSatish Balay v2++; 230517ab2063SBarry Smith } 2306064f8208SBarry Smith if (sum > *nrm) *nrm = sum; 230717ab2063SBarry Smith } 23089566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(PetscMax(a->nz - 1, 0))); 2309f23aa3ddSBarry Smith } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for two norm"); 23109566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &v)); 23113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 231217ab2063SBarry Smith } 231317ab2063SBarry Smith 2314d71ae5a4SJacob Faibussowitsch PetscErrorCode MatIsTranspose_SeqAIJ(Mat A, Mat B, PetscReal tol, PetscBool *f) 2315d71ae5a4SJacob Faibussowitsch { 23163d3eaba7SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data, *bij = (Mat_SeqAIJ *)B->data; 231754f21887SBarry Smith PetscInt *adx, *bdx, *aii, *bii, *aptr, *bptr; 23182e5835c6SStefano Zampini const MatScalar *va, *vb; 231997f1f81fSBarry Smith PetscInt ma, na, mb, nb, i; 2320cd0d46ebSvictorle 2321cd0d46ebSvictorle PetscFunctionBegin; 23229566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &ma, &na)); 23239566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &mb, &nb)); 23245485867bSBarry Smith if (ma != nb || na != mb) { 23255485867bSBarry Smith *f = PETSC_FALSE; 23263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23275485867bSBarry Smith } 23289566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &va)); 23299566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &vb)); 23309371c9d4SSatish Balay aii = aij->i; 23319371c9d4SSatish Balay bii = bij->i; 23329371c9d4SSatish Balay adx = aij->j; 23339371c9d4SSatish Balay bdx = bij->j; 23349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ma, &aptr)); 23359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mb, &bptr)); 2336cd0d46ebSvictorle for (i = 0; i < ma; i++) aptr[i] = aii[i]; 2337cd0d46ebSvictorle for (i = 0; i < mb; i++) bptr[i] = bii[i]; 2338cd0d46ebSvictorle 2339cd0d46ebSvictorle *f = PETSC_TRUE; 2340cd0d46ebSvictorle for (i = 0; i < ma; i++) { 2341cd0d46ebSvictorle while (aptr[i] < aii[i + 1]) { 234297f1f81fSBarry Smith PetscInt idc, idr; 23435485867bSBarry Smith PetscScalar vc, vr; 2344cd0d46ebSvictorle /* column/row index/value */ 23455485867bSBarry Smith idc = adx[aptr[i]]; 23465485867bSBarry Smith idr = bdx[bptr[idc]]; 23475485867bSBarry Smith vc = va[aptr[i]]; 23485485867bSBarry Smith vr = vb[bptr[idc]]; 23495485867bSBarry Smith if (i != idr || PetscAbsScalar(vc - vr) > tol) { 23505485867bSBarry Smith *f = PETSC_FALSE; 23515485867bSBarry Smith goto done; 2352cd0d46ebSvictorle } else { 23535485867bSBarry Smith aptr[i]++; 23545485867bSBarry Smith if (B || i != idc) bptr[idc]++; 2355cd0d46ebSvictorle } 2356cd0d46ebSvictorle } 2357cd0d46ebSvictorle } 2358cd0d46ebSvictorle done: 23599566063dSJacob Faibussowitsch PetscCall(PetscFree(aptr)); 23609566063dSJacob Faibussowitsch PetscCall(PetscFree(bptr)); 23619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &va)); 23629566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &vb)); 23633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2364cd0d46ebSvictorle } 2365cd0d46ebSvictorle 2366d71ae5a4SJacob Faibussowitsch PetscErrorCode MatIsHermitianTranspose_SeqAIJ(Mat A, Mat B, PetscReal tol, PetscBool *f) 2367d71ae5a4SJacob Faibussowitsch { 23683d3eaba7SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data, *bij = (Mat_SeqAIJ *)B->data; 236954f21887SBarry Smith PetscInt *adx, *bdx, *aii, *bii, *aptr, *bptr; 237054f21887SBarry Smith MatScalar *va, *vb; 23711cbb95d3SBarry Smith PetscInt ma, na, mb, nb, i; 23721cbb95d3SBarry Smith 23731cbb95d3SBarry Smith PetscFunctionBegin; 23749566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &ma, &na)); 23759566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &mb, &nb)); 23761cbb95d3SBarry Smith if (ma != nb || na != mb) { 23771cbb95d3SBarry Smith *f = PETSC_FALSE; 23783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23791cbb95d3SBarry Smith } 23809371c9d4SSatish Balay aii = aij->i; 23819371c9d4SSatish Balay bii = bij->i; 23829371c9d4SSatish Balay adx = aij->j; 23839371c9d4SSatish Balay bdx = bij->j; 23849371c9d4SSatish Balay va = aij->a; 23859371c9d4SSatish Balay vb = bij->a; 23869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ma, &aptr)); 23879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mb, &bptr)); 23881cbb95d3SBarry Smith for (i = 0; i < ma; i++) aptr[i] = aii[i]; 23891cbb95d3SBarry Smith for (i = 0; i < mb; i++) bptr[i] = bii[i]; 23901cbb95d3SBarry Smith 23911cbb95d3SBarry Smith *f = PETSC_TRUE; 23921cbb95d3SBarry Smith for (i = 0; i < ma; i++) { 23931cbb95d3SBarry Smith while (aptr[i] < aii[i + 1]) { 23941cbb95d3SBarry Smith PetscInt idc, idr; 23951cbb95d3SBarry Smith PetscScalar vc, vr; 23961cbb95d3SBarry Smith /* column/row index/value */ 23971cbb95d3SBarry Smith idc = adx[aptr[i]]; 23981cbb95d3SBarry Smith idr = bdx[bptr[idc]]; 23991cbb95d3SBarry Smith vc = va[aptr[i]]; 24001cbb95d3SBarry Smith vr = vb[bptr[idc]]; 24011cbb95d3SBarry Smith if (i != idr || PetscAbsScalar(vc - PetscConj(vr)) > tol) { 24021cbb95d3SBarry Smith *f = PETSC_FALSE; 24031cbb95d3SBarry Smith goto done; 24041cbb95d3SBarry Smith } else { 24051cbb95d3SBarry Smith aptr[i]++; 24061cbb95d3SBarry Smith if (B || i != idc) bptr[idc]++; 24071cbb95d3SBarry Smith } 24081cbb95d3SBarry Smith } 24091cbb95d3SBarry Smith } 24101cbb95d3SBarry Smith done: 24119566063dSJacob Faibussowitsch PetscCall(PetscFree(aptr)); 24129566063dSJacob Faibussowitsch PetscCall(PetscFree(bptr)); 24133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24141cbb95d3SBarry Smith } 24151cbb95d3SBarry Smith 2416d71ae5a4SJacob Faibussowitsch PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A, PetscReal tol, PetscBool *f) 2417d71ae5a4SJacob Faibussowitsch { 24189e29f15eSvictorle PetscFunctionBegin; 24199566063dSJacob Faibussowitsch PetscCall(MatIsTranspose_SeqAIJ(A, A, tol, f)); 24203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24219e29f15eSvictorle } 24229e29f15eSvictorle 2423d71ae5a4SJacob Faibussowitsch PetscErrorCode MatIsHermitian_SeqAIJ(Mat A, PetscReal tol, PetscBool *f) 2424d71ae5a4SJacob Faibussowitsch { 24251cbb95d3SBarry Smith PetscFunctionBegin; 24269566063dSJacob Faibussowitsch PetscCall(MatIsHermitianTranspose_SeqAIJ(A, A, tol, f)); 24273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24281cbb95d3SBarry Smith } 24291cbb95d3SBarry Smith 2430d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A, Vec ll, Vec rr) 2431d71ae5a4SJacob Faibussowitsch { 2432416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2433fff8e43fSBarry Smith const PetscScalar *l, *r; 2434fff8e43fSBarry Smith PetscScalar x; 243554f21887SBarry Smith MatScalar *v; 2436fff8e43fSBarry Smith PetscInt i, j, m = A->rmap->n, n = A->cmap->n, M, nz = a->nz; 2437fff8e43fSBarry Smith const PetscInt *jj; 243817ab2063SBarry Smith 24393a40ed3dSBarry Smith PetscFunctionBegin; 244017ab2063SBarry Smith if (ll) { 24413ea7c6a1SSatish Balay /* The local size is used so that VecMPI can be passed to this routine 24423ea7c6a1SSatish Balay by MatDiagonalScale_MPIAIJ */ 24439566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ll, &m)); 244408401ef6SPierre Jolivet PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vector wrong length"); 24459566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(ll, &l)); 24469566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &v)); 244717ab2063SBarry Smith for (i = 0; i < m; i++) { 244817ab2063SBarry Smith x = l[i]; 2449416022c9SBarry Smith M = a->i[i + 1] - a->i[i]; 24502205254eSKarl Rupp for (j = 0; j < M; j++) (*v++) *= x; 245117ab2063SBarry Smith } 24529566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(ll, &l)); 24539566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(nz)); 24549566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &v)); 245517ab2063SBarry Smith } 245617ab2063SBarry Smith if (rr) { 24579566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rr, &n)); 245808401ef6SPierre Jolivet PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vector wrong length"); 24599566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(rr, &r)); 24609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &v)); 24612e5835c6SStefano Zampini jj = a->j; 24622205254eSKarl Rupp for (i = 0; i < nz; i++) (*v++) *= r[*jj++]; 24639566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &v)); 24649566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(rr, &r)); 24659566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(nz)); 246617ab2063SBarry Smith } 24679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 24683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 246917ab2063SBarry Smith } 247017ab2063SBarry Smith 2471d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A, IS isrow, IS iscol, PetscInt csize, MatReuse scall, Mat *B) 2472d71ae5a4SJacob Faibussowitsch { 2473db02288aSLois Curfman McInnes Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data, *c; 2474d0f46423SBarry Smith PetscInt *smap, i, k, kstart, kend, oldcols = A->cmap->n, *lens; 247597f1f81fSBarry Smith PetscInt row, mat_i, *mat_j, tcol, first, step, *mat_ilen, sum, lensi; 24765d0c19d7SBarry Smith const PetscInt *irow, *icol; 24772e5835c6SStefano Zampini const PetscScalar *aa; 24785d0c19d7SBarry Smith PetscInt nrows, ncols; 247997f1f81fSBarry Smith PetscInt *starts, *j_new, *i_new, *aj = a->j, *ai = a->i, ii, *ailen = a->ilen; 2480fb3c7e2dSJunchao Zhang MatScalar *a_new, *mat_a, *c_a; 2481416022c9SBarry Smith Mat C; 2482cdc6f3adSToby Isaac PetscBool stride; 248317ab2063SBarry Smith 24843a40ed3dSBarry Smith PetscFunctionBegin; 24859566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow, &irow)); 24869566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow, &nrows)); 24879566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol, &ncols)); 248817ab2063SBarry Smith 24899566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)iscol, ISSTRIDE, &stride)); 2490ff718158SBarry Smith if (stride) { 24919566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(iscol, &first, &step)); 2492ff718158SBarry Smith } else { 2493ff718158SBarry Smith first = 0; 2494ff718158SBarry Smith step = 0; 2495ff718158SBarry Smith } 2496fee21e36SBarry Smith if (stride && step == 1) { 249702834360SBarry Smith /* special case of contiguous rows */ 24989566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nrows, &lens, nrows, &starts)); 249902834360SBarry Smith /* loop over new rows determining lens and starting points */ 250002834360SBarry Smith for (i = 0; i < nrows; i++) { 2501bfeeae90SHong Zhang kstart = ai[irow[i]]; 2502a2744918SBarry Smith kend = kstart + ailen[irow[i]]; 2503a91a9bebSLisandro Dalcin starts[i] = kstart; 250402834360SBarry Smith for (k = kstart; k < kend; k++) { 2505bfeeae90SHong Zhang if (aj[k] >= first) { 250602834360SBarry Smith starts[i] = k; 250702834360SBarry Smith break; 250802834360SBarry Smith } 250902834360SBarry Smith } 2510a2744918SBarry Smith sum = 0; 251102834360SBarry Smith while (k < kend) { 2512bfeeae90SHong Zhang if (aj[k++] >= first + ncols) break; 2513a2744918SBarry Smith sum++; 251402834360SBarry Smith } 2515a2744918SBarry Smith lens[i] = sum; 251602834360SBarry Smith } 251702834360SBarry Smith /* create submatrix */ 2518cddf8d76SBarry Smith if (scall == MAT_REUSE_MATRIX) { 251997f1f81fSBarry Smith PetscInt n_cols, n_rows; 25209566063dSJacob Faibussowitsch PetscCall(MatGetSize(*B, &n_rows, &n_cols)); 2521aed4548fSBarry Smith PetscCheck(n_rows == nrows && n_cols == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Reused submatrix wrong size"); 25229566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*B)); 252308480c60SBarry Smith C = *B; 25243a40ed3dSBarry Smith } else { 25253bef6203SJed Brown PetscInt rbs, cbs; 25269566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 25279566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, nrows, ncols, PETSC_DETERMINE, PETSC_DETERMINE)); 25289566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(isrow, &rbs)); 25299566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(iscol, &cbs)); 25309566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C, rbs, cbs)); 25319566063dSJacob Faibussowitsch PetscCall(MatSetType(C, ((PetscObject)A)->type_name)); 25329566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C, 0, lens)); 253308480c60SBarry Smith } 2534db02288aSLois Curfman McInnes c = (Mat_SeqAIJ *)C->data; 2535db02288aSLois Curfman McInnes 253602834360SBarry Smith /* loop over rows inserting into submatrix */ 2537fb3c7e2dSJunchao Zhang PetscCall(MatSeqAIJGetArrayWrite(C, &a_new)); // Not 'a_new = c->a-new', since that raw usage ignores offload state of C 2538db02288aSLois Curfman McInnes j_new = c->j; 2539db02288aSLois Curfman McInnes i_new = c->i; 25409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 254102834360SBarry Smith for (i = 0; i < nrows; i++) { 2542a2744918SBarry Smith ii = starts[i]; 2543a2744918SBarry Smith lensi = lens[i]; 2544ad540459SPierre Jolivet for (k = 0; k < lensi; k++) *j_new++ = aj[ii + k] - first; 25459566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a_new, aa + starts[i], lensi)); 2546a2744918SBarry Smith a_new += lensi; 2547a2744918SBarry Smith i_new[i + 1] = i_new[i] + lensi; 2548a2744918SBarry Smith c->ilen[i] = lensi; 254902834360SBarry Smith } 2550fb3c7e2dSJunchao Zhang PetscCall(MatSeqAIJRestoreArrayWrite(C, &a_new)); // Set C's offload state properly 25519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 25529566063dSJacob Faibussowitsch PetscCall(PetscFree2(lens, starts)); 25533a40ed3dSBarry Smith } else { 25549566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol, &icol)); 25559566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(oldcols, &smap)); 25569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1 + nrows, &lens)); 25574dcab191SBarry Smith for (i = 0; i < ncols; i++) { 25586bdcaf15SBarry 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); 25594dcab191SBarry Smith smap[icol[i]] = i + 1; 25604dcab191SBarry Smith } 25614dcab191SBarry Smith 256202834360SBarry Smith /* determine lens of each row */ 256302834360SBarry Smith for (i = 0; i < nrows; i++) { 2564bfeeae90SHong Zhang kstart = ai[irow[i]]; 256502834360SBarry Smith kend = kstart + a->ilen[irow[i]]; 256602834360SBarry Smith lens[i] = 0; 256702834360SBarry Smith for (k = kstart; k < kend; k++) { 2568ad540459SPierre Jolivet if (smap[aj[k]]) lens[i]++; 256902834360SBarry Smith } 257002834360SBarry Smith } 257117ab2063SBarry Smith /* Create and fill new matrix */ 2572a2744918SBarry Smith if (scall == MAT_REUSE_MATRIX) { 2573ace3abfcSBarry Smith PetscBool equal; 25740f5bd95cSBarry Smith 257599141d43SSatish Balay c = (Mat_SeqAIJ *)((*B)->data); 2576aed4548fSBarry Smith PetscCheck((*B)->rmap->n == nrows && (*B)->cmap->n == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot reuse matrix. wrong size"); 25779566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(c->ilen, lens, (*B)->rmap->n, &equal)); 257828b400f6SJacob Faibussowitsch PetscCheck(equal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot reuse matrix. wrong no of nonzeros"); 25799566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->ilen, (*B)->rmap->n)); 258008480c60SBarry Smith C = *B; 25813a40ed3dSBarry Smith } else { 25823bef6203SJed Brown PetscInt rbs, cbs; 25839566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 25849566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, nrows, ncols, PETSC_DETERMINE, PETSC_DETERMINE)); 25859566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(isrow, &rbs)); 25869566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(iscol, &cbs)); 25879566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C, rbs, cbs)); 25889566063dSJacob Faibussowitsch PetscCall(MatSetType(C, ((PetscObject)A)->type_name)); 25899566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C, 0, lens)); 259008480c60SBarry Smith } 25919566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 2592fb3c7e2dSJunchao Zhang 259399141d43SSatish Balay c = (Mat_SeqAIJ *)(C->data); 2594fb3c7e2dSJunchao Zhang PetscCall(MatSeqAIJGetArrayWrite(C, &c_a)); // Not 'c->a', since that raw usage ignores offload state of C 259517ab2063SBarry Smith for (i = 0; i < nrows; i++) { 259699141d43SSatish Balay row = irow[i]; 2597bfeeae90SHong Zhang kstart = ai[row]; 259899141d43SSatish Balay kend = kstart + a->ilen[row]; 2599bfeeae90SHong Zhang mat_i = c->i[i]; 260099141d43SSatish Balay mat_j = c->j + mat_i; 2601fb3c7e2dSJunchao Zhang mat_a = c_a + mat_i; 260299141d43SSatish Balay mat_ilen = c->ilen + i; 260317ab2063SBarry Smith for (k = kstart; k < kend; k++) { 2604bfeeae90SHong Zhang if ((tcol = smap[a->j[k]])) { 2605ed480e8bSBarry Smith *mat_j++ = tcol - 1; 26062e5835c6SStefano Zampini *mat_a++ = aa[k]; 260799141d43SSatish Balay (*mat_ilen)++; 260817ab2063SBarry Smith } 260917ab2063SBarry Smith } 261017ab2063SBarry Smith } 26119566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 261202834360SBarry Smith /* Free work space */ 26139566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol, &icol)); 26149566063dSJacob Faibussowitsch PetscCall(PetscFree(smap)); 26159566063dSJacob Faibussowitsch PetscCall(PetscFree(lens)); 2616cdc6f3adSToby Isaac /* sort */ 2617cdc6f3adSToby Isaac for (i = 0; i < nrows; i++) { 2618cdc6f3adSToby Isaac PetscInt ilen; 2619cdc6f3adSToby Isaac 2620cdc6f3adSToby Isaac mat_i = c->i[i]; 2621cdc6f3adSToby Isaac mat_j = c->j + mat_i; 2622fb3c7e2dSJunchao Zhang mat_a = c_a + mat_i; 2623cdc6f3adSToby Isaac ilen = c->ilen[i]; 26249566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(ilen, mat_j, mat_a)); 2625cdc6f3adSToby Isaac } 2626fb3c7e2dSJunchao Zhang PetscCall(MatSeqAIJRestoreArrayWrite(C, &c_a)); 262702834360SBarry Smith } 26288c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 26299566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(C, A->boundtocpu)); 2630305c6ccfSStefano Zampini #endif 26319566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 26329566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 263317ab2063SBarry Smith 26349566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow, &irow)); 2635416022c9SBarry Smith *B = C; 26363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 263717ab2063SBarry Smith } 263817ab2063SBarry Smith 2639d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetMultiProcBlock_SeqAIJ(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 2640d71ae5a4SJacob Faibussowitsch { 264182d44351SHong Zhang Mat B; 264282d44351SHong Zhang 264382d44351SHong Zhang PetscFunctionBegin; 2644c2d650bdSHong Zhang if (scall == MAT_INITIAL_MATRIX) { 26459566063dSJacob Faibussowitsch PetscCall(MatCreate(subComm, &B)); 26469566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->n, mat->cmap->n)); 26479566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, mat, mat)); 26489566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATSEQAIJ)); 26499566063dSJacob Faibussowitsch PetscCall(MatDuplicateNoCreate_SeqAIJ(B, mat, MAT_COPY_VALUES, PETSC_TRUE)); 265082d44351SHong Zhang *subMat = B; 2651c2d650bdSHong Zhang } else { 26529566063dSJacob Faibussowitsch PetscCall(MatCopy_SeqAIJ(mat, *subMat, SAME_NONZERO_PATTERN)); 2653c2d650bdSHong Zhang } 26543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 265582d44351SHong Zhang } 265682d44351SHong Zhang 2657d71ae5a4SJacob Faibussowitsch PetscErrorCode MatILUFactor_SeqAIJ(Mat inA, IS row, IS col, const MatFactorInfo *info) 2658d71ae5a4SJacob Faibussowitsch { 265963b91edcSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)inA->data; 266063b91edcSBarry Smith Mat outA; 2661ace3abfcSBarry Smith PetscBool row_identity, col_identity; 266263b91edcSBarry Smith 26633a40ed3dSBarry Smith PetscFunctionBegin; 266408401ef6SPierre Jolivet PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 supported for in-place ilu"); 26651df811f5SHong Zhang 26669566063dSJacob Faibussowitsch PetscCall(ISIdentity(row, &row_identity)); 26679566063dSJacob Faibussowitsch PetscCall(ISIdentity(col, &col_identity)); 2668a871dcd8SBarry Smith 266963b91edcSBarry Smith outA = inA; 2670d5f3da31SBarry Smith outA->factortype = MAT_FACTOR_LU; 26719566063dSJacob Faibussowitsch PetscCall(PetscFree(inA->solvertype)); 26729566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype)); 26732205254eSKarl Rupp 26749566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)row)); 26759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 26762205254eSKarl Rupp 2677c3122656SLisandro Dalcin a->row = row; 26782205254eSKarl Rupp 26799566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)col)); 26809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 26812205254eSKarl Rupp 2682c3122656SLisandro Dalcin a->col = col; 268363b91edcSBarry Smith 268436db0b34SBarry Smith /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */ 26859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 26869566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(col, PETSC_DECIDE, &a->icol)); 2687f0ec6fceSSatish Balay 268894a9d846SBarry Smith if (!a->solve_work) { /* this matrix may have been factored before */ 26899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(inA->rmap->n + 1, &a->solve_work)); 269094a9d846SBarry Smith } 269163b91edcSBarry Smith 26929566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(inA)); 2693137fb511SHong Zhang if (row_identity && col_identity) { 26949566063dSJacob Faibussowitsch PetscCall(MatLUFactorNumeric_SeqAIJ_inplace(outA, inA, info)); 2695137fb511SHong Zhang } else { 26969566063dSJacob Faibussowitsch PetscCall(MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA, inA, info)); 2697137fb511SHong Zhang } 26983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2699a871dcd8SBarry Smith } 2700a871dcd8SBarry Smith 2701d71ae5a4SJacob Faibussowitsch PetscErrorCode MatScale_SeqAIJ(Mat inA, PetscScalar alpha) 2702d71ae5a4SJacob Faibussowitsch { 2703f0b747eeSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)inA->data; 2704dfa0f9e5SStefano Zampini PetscScalar *v; 2705c5df96a5SBarry Smith PetscBLASInt one = 1, bnz; 27063a40ed3dSBarry Smith 27073a40ed3dSBarry Smith PetscFunctionBegin; 27089566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(inA, &v)); 27099566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(a->nz, &bnz)); 2710792fecdfSBarry Smith PetscCallBLAS("BLASscal", BLASscal_(&bnz, &alpha, v, &one)); 27119566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 27129566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(inA, &v)); 27139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(inA)); 27143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2715f0b747eeSBarry Smith } 2716f0b747eeSBarry Smith 2717d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj) 2718d71ae5a4SJacob Faibussowitsch { 271916b64355SHong Zhang PetscInt i; 272016b64355SHong Zhang 272116b64355SHong Zhang PetscFunctionBegin; 272216b64355SHong Zhang if (!submatj->id) { /* delete data that are linked only to submats[id=0] */ 27239566063dSJacob Faibussowitsch PetscCall(PetscFree4(submatj->sbuf1, submatj->ptr, submatj->tmp, submatj->ctr)); 272416b64355SHong Zhang 272548a46eb9SPierre Jolivet for (i = 0; i < submatj->nrqr; ++i) PetscCall(PetscFree(submatj->sbuf2[i])); 27269566063dSJacob Faibussowitsch PetscCall(PetscFree3(submatj->sbuf2, submatj->req_size, submatj->req_source1)); 272716b64355SHong Zhang 272816b64355SHong Zhang if (submatj->rbuf1) { 27299566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rbuf1[0])); 27309566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rbuf1)); 273116b64355SHong Zhang } 273216b64355SHong Zhang 273348a46eb9SPierre Jolivet for (i = 0; i < submatj->nrqs; ++i) PetscCall(PetscFree(submatj->rbuf3[i])); 27349566063dSJacob Faibussowitsch PetscCall(PetscFree3(submatj->req_source2, submatj->rbuf2, submatj->rbuf3)); 27359566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->pa)); 273616b64355SHong Zhang } 273716b64355SHong Zhang 273816b64355SHong Zhang #if defined(PETSC_USE_CTABLE) 2739eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&submatj->rmap)); 27409566063dSJacob Faibussowitsch if (submatj->cmap_loc) PetscCall(PetscFree(submatj->cmap_loc)); 27419566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rmap_loc)); 274216b64355SHong Zhang #else 27439566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rmap)); 274416b64355SHong Zhang #endif 274516b64355SHong Zhang 274616b64355SHong Zhang if (!submatj->allcolumns) { 274716b64355SHong Zhang #if defined(PETSC_USE_CTABLE) 2748eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDestroy((PetscHMapI *)&submatj->cmap)); 274916b64355SHong Zhang #else 27509566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->cmap)); 275116b64355SHong Zhang #endif 275216b64355SHong Zhang } 27539566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->row2proc)); 275416b64355SHong Zhang 27559566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj)); 27563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 275716b64355SHong Zhang } 275816b64355SHong Zhang 2759d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C) 2760d71ae5a4SJacob Faibussowitsch { 276116b64355SHong Zhang Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data; 27625c39f6d9SHong Zhang Mat_SubSppt *submatj = c->submatis1; 276316b64355SHong Zhang 276416b64355SHong Zhang PetscFunctionBegin; 27659566063dSJacob Faibussowitsch PetscCall((*submatj->destroy)(C)); 27669566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrix_Private(submatj)); 27673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 276816b64355SHong Zhang } 276916b64355SHong Zhang 277089a1a59bSHong Zhang /* Note this has code duplication with MatDestroySubMatrices_SeqBAIJ() */ 2771d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n, Mat *mat[]) 2772d71ae5a4SJacob Faibussowitsch { 27732d033e1fSHong Zhang PetscInt i; 27740fb991dcSHong Zhang Mat C; 27750fb991dcSHong Zhang Mat_SeqAIJ *c; 27760fb991dcSHong Zhang Mat_SubSppt *submatj; 27772d033e1fSHong Zhang 27782d033e1fSHong Zhang PetscFunctionBegin; 27792d033e1fSHong Zhang for (i = 0; i < n; i++) { 27800fb991dcSHong Zhang C = (*mat)[i]; 27810fb991dcSHong Zhang c = (Mat_SeqAIJ *)C->data; 27820fb991dcSHong Zhang submatj = c->submatis1; 27832d033e1fSHong Zhang if (submatj) { 2784682e4c99SStefano Zampini if (--((PetscObject)C)->refct <= 0) { 278526cc229bSBarry Smith PetscCall(PetscFree(C->factorprefix)); 27869566063dSJacob Faibussowitsch PetscCall((*submatj->destroy)(C)); 27879566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrix_Private(submatj)); 27889566063dSJacob Faibussowitsch PetscCall(PetscFree(C->defaultvectype)); 27893faff063SStefano Zampini PetscCall(PetscFree(C->defaultrandtype)); 27909566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->rmap)); 27919566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->cmap)); 27929566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(&C)); 2793682e4c99SStefano Zampini } 27942d033e1fSHong Zhang } else { 27959566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 27962d033e1fSHong Zhang } 27972d033e1fSHong Zhang } 279886e85357SHong Zhang 279963a75b2aSHong Zhang /* Destroy Dummy submatrices created for reuse */ 28009566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices_Dummy(n, mat)); 280163a75b2aSHong Zhang 28029566063dSJacob Faibussowitsch PetscCall(PetscFree(*mat)); 28033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28042d033e1fSHong Zhang } 28052d033e1fSHong Zhang 2806d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[]) 2807d71ae5a4SJacob Faibussowitsch { 280897f1f81fSBarry Smith PetscInt i; 2809cddf8d76SBarry Smith 28103a40ed3dSBarry Smith PetscFunctionBegin; 281148a46eb9SPierre Jolivet if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n + 1, B)); 2812cddf8d76SBarry Smith 281348a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqAIJ(A, irow[i], icol[i], PETSC_DECIDE, scall, &(*B)[i])); 28143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2815cddf8d76SBarry Smith } 2816cddf8d76SBarry Smith 2817d71ae5a4SJacob Faibussowitsch PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A, PetscInt is_max, IS is[], PetscInt ov) 2818d71ae5a4SJacob Faibussowitsch { 2819e4d965acSSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 28209a88ca10SBarry Smith PetscInt row, i, j, k, l, ll, m, n, *nidx, isz, val; 28215d0c19d7SBarry Smith const PetscInt *idx; 28229a88ca10SBarry Smith PetscInt start, end, *ai, *aj, bs = (A->rmap->bs > 0 && A->rmap->bs == A->cmap->bs) ? A->rmap->bs : 1; 2823f1af5d2fSBarry Smith PetscBT table; 2824bbd702dbSSatish Balay 28253a40ed3dSBarry Smith PetscFunctionBegin; 28269a88ca10SBarry Smith m = A->rmap->n / bs; 2827e4d965acSSatish Balay ai = a->i; 2828bfeeae90SHong Zhang aj = a->j; 28298a047759SSatish Balay 283008401ef6SPierre Jolivet PetscCheck(ov >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "illegal negative overlap value used"); 283106763907SSatish Balay 28329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nidx)); 28339566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(m, &table)); 283406763907SSatish Balay 2835e4d965acSSatish Balay for (i = 0; i < is_max; i++) { 2836b97fc60eSLois Curfman McInnes /* Initialize the two local arrays */ 2837e4d965acSSatish Balay isz = 0; 28389566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(m, table)); 2839e4d965acSSatish Balay 2840e4d965acSSatish Balay /* Extract the indices, assume there can be duplicate entries */ 28419566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is[i], &idx)); 28429566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is[i], &n)); 2843e4d965acSSatish Balay 28449a88ca10SBarry Smith if (bs > 1) { 28459a88ca10SBarry Smith /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 28469a88ca10SBarry Smith for (j = 0; j < n; ++j) { 28479a88ca10SBarry Smith if (!PetscBTLookupSet(table, idx[j] / bs)) nidx[isz++] = idx[j] / bs; 28489a88ca10SBarry Smith } 28499a88ca10SBarry Smith PetscCall(ISRestoreIndices(is[i], &idx)); 28509a88ca10SBarry Smith PetscCall(ISDestroy(&is[i])); 28519a88ca10SBarry Smith 28529a88ca10SBarry Smith k = 0; 28539a88ca10SBarry Smith for (j = 0; j < ov; j++) { /* for each overlap */ 28549a88ca10SBarry Smith n = isz; 28559a88ca10SBarry Smith for (; k < n; k++) { /* do only those rows in nidx[k], which are not done yet */ 28569a88ca10SBarry Smith for (ll = 0; ll < bs; ll++) { 28579a88ca10SBarry Smith row = bs * nidx[k] + ll; 28589a88ca10SBarry Smith start = ai[row]; 28599a88ca10SBarry Smith end = ai[row + 1]; 28609a88ca10SBarry Smith for (l = start; l < end; l++) { 28619a88ca10SBarry Smith val = aj[l] / bs; 28629a88ca10SBarry Smith if (!PetscBTLookupSet(table, val)) nidx[isz++] = val; 28639a88ca10SBarry Smith } 28649a88ca10SBarry Smith } 28659a88ca10SBarry Smith } 28669a88ca10SBarry Smith } 28679a88ca10SBarry Smith PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, isz, nidx, PETSC_COPY_VALUES, (is + i))); 28689a88ca10SBarry Smith } else { 2869dd097bc3SLois Curfman McInnes /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 2870e4d965acSSatish Balay for (j = 0; j < n; ++j) { 28712205254eSKarl Rupp if (!PetscBTLookupSet(table, idx[j])) nidx[isz++] = idx[j]; 28724dcbc457SBarry Smith } 28739566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is[i], &idx)); 28749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is[i])); 2875e4d965acSSatish Balay 287604a348a9SBarry Smith k = 0; 287704a348a9SBarry Smith for (j = 0; j < ov; j++) { /* for each overlap */ 287804a348a9SBarry Smith n = isz; 287906763907SSatish Balay for (; k < n; k++) { /* do only those rows in nidx[k], which are not done yet */ 2880e4d965acSSatish Balay row = nidx[k]; 2881e4d965acSSatish Balay start = ai[row]; 2882e4d965acSSatish Balay end = ai[row + 1]; 288304a348a9SBarry Smith for (l = start; l < end; l++) { 2884efb16452SHong Zhang val = aj[l]; 28852205254eSKarl Rupp if (!PetscBTLookupSet(table, val)) nidx[isz++] = val; 2886e4d965acSSatish Balay } 2887e4d965acSSatish Balay } 2888e4d965acSSatish Balay } 28899566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, isz, nidx, PETSC_COPY_VALUES, (is + i))); 2890e4d965acSSatish Balay } 28919a88ca10SBarry Smith } 28929566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&table)); 28939566063dSJacob Faibussowitsch PetscCall(PetscFree(nidx)); 28943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28954dcbc457SBarry Smith } 289617ab2063SBarry Smith 2897d71ae5a4SJacob Faibussowitsch PetscErrorCode MatPermute_SeqAIJ(Mat A, IS rowp, IS colp, Mat *B) 2898d71ae5a4SJacob Faibussowitsch { 28990513a670SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 29003b98c0a2SBarry Smith PetscInt i, nz = 0, m = A->rmap->n, n = A->cmap->n; 29015d0c19d7SBarry Smith const PetscInt *row, *col; 29025d0c19d7SBarry Smith PetscInt *cnew, j, *lens; 290356cd22aeSBarry Smith IS icolp, irowp; 29040298fd71SBarry Smith PetscInt *cwork = NULL; 29050298fd71SBarry Smith PetscScalar *vwork = NULL; 29060513a670SBarry Smith 29073a40ed3dSBarry Smith PetscFunctionBegin; 29089566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rowp, PETSC_DECIDE, &irowp)); 29099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irowp, &row)); 29109566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(colp, PETSC_DECIDE, &icolp)); 29119566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icolp, &col)); 29120513a670SBarry Smith 29130513a670SBarry Smith /* determine lengths of permuted rows */ 29149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &lens)); 29152205254eSKarl Rupp for (i = 0; i < m; i++) lens[row[i]] = a->i[i + 1] - a->i[i]; 29169566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 29179566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, m, n, m, n)); 29189566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(*B, A, A)); 29199566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, ((PetscObject)A)->type_name)); 29209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*B, 0, lens)); 29219566063dSJacob Faibussowitsch PetscCall(PetscFree(lens)); 29220513a670SBarry Smith 29239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &cnew)); 29240513a670SBarry Smith for (i = 0; i < m; i++) { 29259566063dSJacob Faibussowitsch PetscCall(MatGetRow_SeqAIJ(A, i, &nz, &cwork, &vwork)); 29262205254eSKarl Rupp for (j = 0; j < nz; j++) cnew[j] = col[cwork[j]]; 29279566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(*B, 1, &row[i], nz, cnew, vwork, INSERT_VALUES)); 29289566063dSJacob Faibussowitsch PetscCall(MatRestoreRow_SeqAIJ(A, i, &nz, &cwork, &vwork)); 29290513a670SBarry Smith } 29309566063dSJacob Faibussowitsch PetscCall(PetscFree(cnew)); 29312205254eSKarl Rupp 29323c7d62e4SBarry Smith (*B)->assembled = PETSC_FALSE; 29332205254eSKarl Rupp 29348c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 29359566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(*B, A->boundtocpu)); 29369fe5e383SStefano Zampini #endif 29379566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 29389566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 29399566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irowp, &row)); 29409566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icolp, &col)); 29419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irowp)); 29429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icolp)); 294348a46eb9SPierre Jolivet if (rowp == colp) PetscCall(MatPropagateSymmetryOptions(A, *B)); 29443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29450513a670SBarry Smith } 29460513a670SBarry Smith 2947d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_SeqAIJ(Mat A, Mat B, MatStructure str) 2948d71ae5a4SJacob Faibussowitsch { 2949cb5b572fSBarry Smith PetscFunctionBegin; 295033f4a19fSKris Buschelman /* If the two matrices have the same copy implementation, use fast copy. */ 295133f4a19fSKris Buschelman if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) { 2952be6bf707SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2953be6bf707SBarry Smith Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 29542e5835c6SStefano Zampini const PetscScalar *aa; 2955be6bf707SBarry Smith 29569566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 295708401ef6SPierre 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]); 29589566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->a, aa, a->i[A->rmap->n])); 29599566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 29609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 2961cb5b572fSBarry Smith } else { 29629566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 2963cb5b572fSBarry Smith } 29643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2965cb5b572fSBarry Smith } 2966cb5b572fSBarry Smith 2967d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A, PetscScalar *array[]) 2968d71ae5a4SJacob Faibussowitsch { 29696c0721eeSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 29706e111a19SKarl Rupp 29716c0721eeSBarry Smith PetscFunctionBegin; 29726c0721eeSBarry Smith *array = a->a; 29733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29746c0721eeSBarry Smith } 29756c0721eeSBarry Smith 2976d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A, PetscScalar *array[]) 2977d71ae5a4SJacob Faibussowitsch { 29786c0721eeSBarry Smith PetscFunctionBegin; 2979f38c1e66SStefano Zampini *array = NULL; 29803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29816c0721eeSBarry Smith } 2982273d9f13SBarry Smith 29838229c054SShri Abhyankar /* 29848229c054SShri Abhyankar Computes the number of nonzeros per row needed for preallocation when X and Y 29858229c054SShri Abhyankar have different nonzero structure. 29868229c054SShri Abhyankar */ 2987d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m, const PetscInt *xi, const PetscInt *xj, const PetscInt *yi, const PetscInt *yj, PetscInt *nnz) 2988d71ae5a4SJacob Faibussowitsch { 2989b264fe52SHong Zhang PetscInt i, j, k, nzx, nzy; 2990ec7775f6SShri Abhyankar 2991ec7775f6SShri Abhyankar PetscFunctionBegin; 2992ec7775f6SShri Abhyankar /* Set the number of nonzeros in the new matrix */ 2993ec7775f6SShri Abhyankar for (i = 0; i < m; i++) { 2994b264fe52SHong Zhang const PetscInt *xjj = xj + xi[i], *yjj = yj + yi[i]; 2995b264fe52SHong Zhang nzx = xi[i + 1] - xi[i]; 2996b264fe52SHong Zhang nzy = yi[i + 1] - yi[i]; 29978af7cee1SJed Brown nnz[i] = 0; 29988af7cee1SJed Brown for (j = 0, k = 0; j < nzx; j++) { /* Point in X */ 2999b264fe52SHong Zhang for (; k < nzy && yjj[k] < xjj[j]; k++) nnz[i]++; /* Catch up to X */ 3000b264fe52SHong Zhang if (k < nzy && yjj[k] == xjj[j]) k++; /* Skip duplicate */ 30018af7cee1SJed Brown nnz[i]++; 30028af7cee1SJed Brown } 30038af7cee1SJed Brown for (; k < nzy; k++) nnz[i]++; 3004ec7775f6SShri Abhyankar } 30053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3006ec7775f6SShri Abhyankar } 3007ec7775f6SShri Abhyankar 3008d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y, Mat X, PetscInt *nnz) 3009d71ae5a4SJacob Faibussowitsch { 3010b264fe52SHong Zhang PetscInt m = Y->rmap->N; 3011b264fe52SHong Zhang Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data; 3012b264fe52SHong Zhang Mat_SeqAIJ *y = (Mat_SeqAIJ *)Y->data; 3013b264fe52SHong Zhang 3014b264fe52SHong Zhang PetscFunctionBegin; 3015b264fe52SHong Zhang /* Set the number of nonzeros in the new matrix */ 30169566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqX_private(m, x->i, x->j, y->i, y->j, nnz)); 30173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3018b264fe52SHong Zhang } 3019b264fe52SHong Zhang 3020d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_SeqAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str) 3021d71ae5a4SJacob Faibussowitsch { 3022ac90fabeSBarry Smith Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data, *y = (Mat_SeqAIJ *)Y->data; 3023ac90fabeSBarry Smith 3024ac90fabeSBarry Smith PetscFunctionBegin; 3025134adf20SPierre Jolivet if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) { 3026134adf20SPierre Jolivet PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE; 3027134adf20SPierre Jolivet if (e) { 30289566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->i, y->i, Y->rmap->n + 1, &e)); 302981fa06acSBarry Smith if (e) { 30309566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->j, y->j, y->nz, &e)); 3031134adf20SPierre Jolivet if (e) str = SAME_NONZERO_PATTERN; 303281fa06acSBarry Smith } 303381fa06acSBarry Smith } 303454c59aa7SJacob Faibussowitsch if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN"); 303581fa06acSBarry Smith } 3036ac90fabeSBarry Smith if (str == SAME_NONZERO_PATTERN) { 30372e5835c6SStefano Zampini const PetscScalar *xa; 30382e5835c6SStefano Zampini PetscScalar *ya, alpha = a; 303981fa06acSBarry Smith PetscBLASInt one = 1, bnz; 304081fa06acSBarry Smith 30419566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(x->nz, &bnz)); 30429566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Y, &ya)); 30439566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(X, &xa)); 3044792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, xa, &one, ya, &one)); 30459566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(X, &xa)); 30469566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Y, &ya)); 30479566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * bnz)); 30489566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(Y)); 30499566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 3050ab784542SHong Zhang } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 30519566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 3052ac90fabeSBarry Smith } else { 30538229c054SShri Abhyankar Mat B; 30548229c054SShri Abhyankar PetscInt *nnz; 30559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Y->rmap->N, &nnz)); 30569566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B)); 30579566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name)); 30589566063dSJacob Faibussowitsch PetscCall(MatSetLayouts(B, Y->rmap, Y->cmap)); 30599566063dSJacob Faibussowitsch PetscCall(MatSetType(B, ((PetscObject)Y)->type_name)); 30609566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqAIJ(Y, X, nnz)); 30619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz)); 30629566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 30639566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 30649bb234a9SBarry Smith PetscCall(MatSeqAIJCheckInode(Y)); 30659566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 3066ac90fabeSBarry Smith } 30673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3068ac90fabeSBarry Smith } 3069ac90fabeSBarry Smith 3070d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat) 3071d71ae5a4SJacob Faibussowitsch { 3072354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX) 3073354c94deSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3074354c94deSBarry Smith PetscInt i, nz; 3075354c94deSBarry Smith PetscScalar *a; 3076354c94deSBarry Smith 3077354c94deSBarry Smith PetscFunctionBegin; 3078354c94deSBarry Smith nz = aij->nz; 30799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(mat, &a)); 30802205254eSKarl Rupp for (i = 0; i < nz; i++) a[i] = PetscConj(a[i]); 30819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(mat, &a)); 3082354c94deSBarry Smith #else 3083354c94deSBarry Smith PetscFunctionBegin; 3084354c94deSBarry Smith #endif 30853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3086354c94deSBarry Smith } 3087354c94deSBarry Smith 3088d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[]) 3089d71ae5a4SJacob Faibussowitsch { 3090e34fafa9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3091d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 3092e34fafa9SBarry Smith PetscReal atmp; 3093985db425SBarry Smith PetscScalar *x; 3094ce496241SStefano Zampini const MatScalar *aa, *av; 3095e34fafa9SBarry Smith 3096e34fafa9SBarry Smith PetscFunctionBegin; 309728b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 30989566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3099ce496241SStefano Zampini aa = av; 3100e34fafa9SBarry Smith ai = a->i; 3101e34fafa9SBarry Smith aj = a->j; 3102e34fafa9SBarry Smith 31039566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 31049566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 31059566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 310608401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3107e34fafa9SBarry Smith for (i = 0; i < m; i++) { 31089371c9d4SSatish Balay ncols = ai[1] - ai[0]; 31099371c9d4SSatish Balay ai++; 3110e34fafa9SBarry Smith for (j = 0; j < ncols; j++) { 3111985db425SBarry Smith atmp = PetscAbsScalar(*aa); 31129371c9d4SSatish Balay if (PetscAbsScalar(x[i]) < atmp) { 31139371c9d4SSatish Balay x[i] = atmp; 31149371c9d4SSatish Balay if (idx) idx[i] = *aj; 31159371c9d4SSatish Balay } 31169371c9d4SSatish Balay aa++; 31179371c9d4SSatish Balay aj++; 3118985db425SBarry Smith } 3119985db425SBarry Smith } 31209566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 31219566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 31223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3123985db425SBarry Smith } 3124985db425SBarry Smith 3125d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRowMax_SeqAIJ(Mat A, Vec v, PetscInt idx[]) 3126d71ae5a4SJacob Faibussowitsch { 3127985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3128d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 3129985db425SBarry Smith PetscScalar *x; 3130ce496241SStefano Zampini const MatScalar *aa, *av; 3131985db425SBarry Smith 3132985db425SBarry Smith PetscFunctionBegin; 313328b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 31349566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3135ce496241SStefano Zampini aa = av; 3136985db425SBarry Smith ai = a->i; 3137985db425SBarry Smith aj = a->j; 3138985db425SBarry Smith 31399566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 31409566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 31419566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 314208401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3143985db425SBarry Smith for (i = 0; i < m; i++) { 31449371c9d4SSatish Balay ncols = ai[1] - ai[0]; 31459371c9d4SSatish Balay ai++; 3146d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 31479371c9d4SSatish Balay x[i] = *aa; 31489371c9d4SSatish Balay if (idx) idx[i] = 0; 3149985db425SBarry Smith } else { /* row is sparse so already KNOW maximum is 0.0 or higher */ 3150985db425SBarry Smith x[i] = 0.0; 3151985db425SBarry Smith if (idx) { 3152985db425SBarry Smith for (j = 0; j < ncols; j++) { /* find first implicit 0.0 in the row */ 3153985db425SBarry Smith if (aj[j] > j) { 3154985db425SBarry Smith idx[i] = j; 3155985db425SBarry Smith break; 3156985db425SBarry Smith } 3157985db425SBarry Smith } 31581a254869SHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 31591a254869SHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3160985db425SBarry Smith } 3161985db425SBarry Smith } 3162985db425SBarry Smith for (j = 0; j < ncols; j++) { 31639371c9d4SSatish Balay if (PetscRealPart(x[i]) < PetscRealPart(*aa)) { 31649371c9d4SSatish Balay x[i] = *aa; 31659371c9d4SSatish Balay if (idx) idx[i] = *aj; 31669371c9d4SSatish Balay } 31679371c9d4SSatish Balay aa++; 31689371c9d4SSatish Balay aj++; 3169985db425SBarry Smith } 3170985db425SBarry Smith } 31719566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 31729566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 31733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3174985db425SBarry Smith } 3175985db425SBarry Smith 3176d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[]) 3177d71ae5a4SJacob Faibussowitsch { 3178c87e5d42SMatthew Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3179c87e5d42SMatthew Knepley PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 3180ce496241SStefano Zampini PetscScalar *x; 3181ce496241SStefano Zampini const MatScalar *aa, *av; 3182c87e5d42SMatthew Knepley 3183c87e5d42SMatthew Knepley PetscFunctionBegin; 31849566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3185ce496241SStefano Zampini aa = av; 3186c87e5d42SMatthew Knepley ai = a->i; 3187c87e5d42SMatthew Knepley aj = a->j; 3188c87e5d42SMatthew Knepley 31899566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 31909566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 31919566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 319208401ef6SPierre Jolivet PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n); 3193c87e5d42SMatthew Knepley for (i = 0; i < m; i++) { 31949371c9d4SSatish Balay ncols = ai[1] - ai[0]; 31959371c9d4SSatish Balay ai++; 3196f07e67edSHong Zhang if (ncols == A->cmap->n) { /* row is dense */ 31979371c9d4SSatish Balay x[i] = *aa; 31989371c9d4SSatish Balay if (idx) idx[i] = 0; 3199f07e67edSHong Zhang } else { /* row is sparse so already KNOW minimum is 0.0 or higher */ 3200f07e67edSHong Zhang x[i] = 0.0; 3201f07e67edSHong Zhang if (idx) { /* find first implicit 0.0 in the row */ 3202289a08f5SMatthew Knepley for (j = 0; j < ncols; j++) { 3203f07e67edSHong Zhang if (aj[j] > j) { 3204f07e67edSHong Zhang idx[i] = j; 32052205254eSKarl Rupp break; 32062205254eSKarl Rupp } 3207289a08f5SMatthew Knepley } 3208f07e67edSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3209f07e67edSHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3210f07e67edSHong Zhang } 3211289a08f5SMatthew Knepley } 3212c87e5d42SMatthew Knepley for (j = 0; j < ncols; j++) { 32139371c9d4SSatish Balay if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) { 32149371c9d4SSatish Balay x[i] = *aa; 32159371c9d4SSatish Balay if (idx) idx[i] = *aj; 32169371c9d4SSatish Balay } 32179371c9d4SSatish Balay aa++; 32189371c9d4SSatish Balay aj++; 3219c87e5d42SMatthew Knepley } 3220c87e5d42SMatthew Knepley } 32219566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 32229566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 32233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3224c87e5d42SMatthew Knepley } 3225c87e5d42SMatthew Knepley 3226d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRowMin_SeqAIJ(Mat A, Vec v, PetscInt idx[]) 3227d71ae5a4SJacob Faibussowitsch { 3228985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3229d9ca1df4SBarry Smith PetscInt i, j, m = A->rmap->n, ncols, n; 3230d9ca1df4SBarry Smith const PetscInt *ai, *aj; 3231985db425SBarry Smith PetscScalar *x; 3232ce496241SStefano Zampini const MatScalar *aa, *av; 3233985db425SBarry Smith 3234985db425SBarry Smith PetscFunctionBegin; 323528b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 32369566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3237ce496241SStefano Zampini aa = av; 3238985db425SBarry Smith ai = a->i; 3239985db425SBarry Smith aj = a->j; 3240985db425SBarry Smith 32419566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 32429566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 32439566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 324408401ef6SPierre Jolivet PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3245985db425SBarry Smith for (i = 0; i < m; i++) { 32469371c9d4SSatish Balay ncols = ai[1] - ai[0]; 32479371c9d4SSatish Balay ai++; 3248d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 32499371c9d4SSatish Balay x[i] = *aa; 32509371c9d4SSatish Balay if (idx) idx[i] = 0; 3251985db425SBarry Smith } else { /* row is sparse so already KNOW minimum is 0.0 or lower */ 3252985db425SBarry Smith x[i] = 0.0; 3253985db425SBarry Smith if (idx) { /* find first implicit 0.0 in the row */ 3254985db425SBarry Smith for (j = 0; j < ncols; j++) { 3255985db425SBarry Smith if (aj[j] > j) { 3256985db425SBarry Smith idx[i] = j; 3257985db425SBarry Smith break; 3258985db425SBarry Smith } 3259985db425SBarry Smith } 3260fa213d2fSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3261fa213d2fSHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3262985db425SBarry Smith } 3263985db425SBarry Smith } 3264985db425SBarry Smith for (j = 0; j < ncols; j++) { 32659371c9d4SSatish Balay if (PetscRealPart(x[i]) > PetscRealPart(*aa)) { 32669371c9d4SSatish Balay x[i] = *aa; 32679371c9d4SSatish Balay if (idx) idx[i] = *aj; 32689371c9d4SSatish Balay } 32699371c9d4SSatish Balay aa++; 32709371c9d4SSatish Balay aj++; 3271e34fafa9SBarry Smith } 3272e34fafa9SBarry Smith } 32739566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 32749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 32753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3276e34fafa9SBarry Smith } 3277bbead8a2SBarry Smith 3278d71ae5a4SJacob Faibussowitsch PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A, const PetscScalar **values) 3279d71ae5a4SJacob Faibussowitsch { 3280bbead8a2SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 328133d57670SJed Brown PetscInt i, bs = PetscAbs(A->rmap->bs), mbs = A->rmap->n / bs, ipvt[5], bs2 = bs * bs, *v_pivots, ij[7], *IJ, j; 3282bbead8a2SBarry Smith MatScalar *diag, work[25], *v_work; 32830da83c2eSBarry Smith const PetscReal shift = 0.0; 32841a9391e3SHong Zhang PetscBool allowzeropivot, zeropivotdetected = PETSC_FALSE; 3285bbead8a2SBarry Smith 3286bbead8a2SBarry Smith PetscFunctionBegin; 3287a455e926SHong Zhang allowzeropivot = PetscNot(A->erroriffailure); 32884a0d0026SBarry Smith if (a->ibdiagvalid) { 32894a0d0026SBarry Smith if (values) *values = a->ibdiag; 32903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32914a0d0026SBarry Smith } 32929566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 32934dfa11a4SJacob Faibussowitsch if (!a->ibdiag) { PetscCall(PetscMalloc1(bs2 * mbs, &a->ibdiag)); } 3294bbead8a2SBarry Smith diag = a->ibdiag; 3295bbead8a2SBarry Smith if (values) *values = a->ibdiag; 3296bbead8a2SBarry Smith /* factor and invert each block */ 3297bbead8a2SBarry Smith switch (bs) { 3298bbead8a2SBarry Smith case 1: 3299bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 33009566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 1, &i, 1, &i, diag + i)); 3301ec1892c8SHong Zhang if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) { 3302ec1892c8SHong Zhang if (allowzeropivot) { 33037b6c816cSBarry Smith A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33047b6c816cSBarry Smith A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]); 33057b6c816cSBarry Smith A->factorerror_zeropivot_row = i; 33069566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n", i, (double)PetscAbsScalar(diag[i]), (double)PETSC_MACHINE_EPSILON)); 330798921bdaSJacob Faibussowitsch } else SETERRQ(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); 3308ec1892c8SHong Zhang } 3309bbead8a2SBarry Smith diag[i] = (PetscScalar)1.0 / (diag[i] + shift); 3310bbead8a2SBarry Smith } 3311bbead8a2SBarry Smith break; 3312bbead8a2SBarry Smith case 2: 3313bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 33149371c9d4SSatish Balay ij[0] = 2 * i; 33159371c9d4SSatish Balay ij[1] = 2 * i + 1; 33169566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 2, ij, 2, ij, diag)); 33179566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected)); 33187b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33199566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_2(diag)); 3320bbead8a2SBarry Smith diag += 4; 3321bbead8a2SBarry Smith } 3322bbead8a2SBarry Smith break; 3323bbead8a2SBarry Smith case 3: 3324bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 33259371c9d4SSatish Balay ij[0] = 3 * i; 33269371c9d4SSatish Balay ij[1] = 3 * i + 1; 33279371c9d4SSatish Balay ij[2] = 3 * i + 2; 33289566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 3, ij, 3, ij, diag)); 33299566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected)); 33307b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33319566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_3(diag)); 3332bbead8a2SBarry Smith diag += 9; 3333bbead8a2SBarry Smith } 3334bbead8a2SBarry Smith break; 3335bbead8a2SBarry Smith case 4: 3336bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 33379371c9d4SSatish Balay ij[0] = 4 * i; 33389371c9d4SSatish Balay ij[1] = 4 * i + 1; 33399371c9d4SSatish Balay ij[2] = 4 * i + 2; 33409371c9d4SSatish Balay ij[3] = 4 * i + 3; 33419566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 4, ij, 4, ij, diag)); 33429566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected)); 33437b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33449566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_4(diag)); 3345bbead8a2SBarry Smith diag += 16; 3346bbead8a2SBarry Smith } 3347bbead8a2SBarry Smith break; 3348bbead8a2SBarry Smith case 5: 3349bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 33509371c9d4SSatish Balay ij[0] = 5 * i; 33519371c9d4SSatish Balay ij[1] = 5 * i + 1; 33529371c9d4SSatish Balay ij[2] = 5 * i + 2; 33539371c9d4SSatish Balay ij[3] = 5 * i + 3; 33549371c9d4SSatish Balay ij[4] = 5 * i + 4; 33559566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 5, ij, 5, ij, diag)); 33569566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected)); 33577b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33589566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_5(diag)); 3359bbead8a2SBarry Smith diag += 25; 3360bbead8a2SBarry Smith } 3361bbead8a2SBarry Smith break; 3362bbead8a2SBarry Smith case 6: 3363bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 33649371c9d4SSatish Balay ij[0] = 6 * i; 33659371c9d4SSatish Balay ij[1] = 6 * i + 1; 33669371c9d4SSatish Balay ij[2] = 6 * i + 2; 33679371c9d4SSatish Balay ij[3] = 6 * i + 3; 33689371c9d4SSatish Balay ij[4] = 6 * i + 4; 33699371c9d4SSatish Balay ij[5] = 6 * i + 5; 33709566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 6, ij, 6, ij, diag)); 33719566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected)); 33727b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33739566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_6(diag)); 3374bbead8a2SBarry Smith diag += 36; 3375bbead8a2SBarry Smith } 3376bbead8a2SBarry Smith break; 3377bbead8a2SBarry Smith case 7: 3378bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 33799371c9d4SSatish Balay ij[0] = 7 * i; 33809371c9d4SSatish Balay ij[1] = 7 * i + 1; 33819371c9d4SSatish Balay ij[2] = 7 * i + 2; 33829371c9d4SSatish Balay ij[3] = 7 * i + 3; 33839371c9d4SSatish Balay ij[4] = 7 * i + 4; 33849371c9d4SSatish Balay ij[5] = 7 * i + 5; 3385cdd8bf47SJunchao Zhang ij[6] = 7 * i + 6; 33869566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 7, ij, 7, ij, diag)); 33879566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected)); 33887b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33899566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_7(diag)); 3390bbead8a2SBarry Smith diag += 49; 3391bbead8a2SBarry Smith } 3392bbead8a2SBarry Smith break; 3393bbead8a2SBarry Smith default: 33949566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(bs, &v_work, bs, &v_pivots, bs, &IJ)); 3395bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 3396ad540459SPierre Jolivet for (j = 0; j < bs; j++) IJ[j] = bs * i + j; 33979566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, bs, IJ, bs, IJ, diag)); 33989566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A(bs, diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected)); 33997b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 34009566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_N(diag, bs)); 3401bbead8a2SBarry Smith diag += bs2; 3402bbead8a2SBarry Smith } 34039566063dSJacob Faibussowitsch PetscCall(PetscFree3(v_work, v_pivots, IJ)); 3404bbead8a2SBarry Smith } 3405bbead8a2SBarry Smith a->ibdiagvalid = PETSC_TRUE; 34063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3407bbead8a2SBarry Smith } 3408bbead8a2SBarry Smith 3409d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetRandom_SeqAIJ(Mat x, PetscRandom rctx) 3410d71ae5a4SJacob Faibussowitsch { 341173a71a0fSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data; 3412fff043a9SJunchao Zhang PetscScalar a, *aa; 341373a71a0fSBarry Smith PetscInt m, n, i, j, col; 341473a71a0fSBarry Smith 341573a71a0fSBarry Smith PetscFunctionBegin; 341673a71a0fSBarry Smith if (!x->assembled) { 34179566063dSJacob Faibussowitsch PetscCall(MatGetSize(x, &m, &n)); 341873a71a0fSBarry Smith for (i = 0; i < m; i++) { 341973a71a0fSBarry Smith for (j = 0; j < aij->imax[i]; j++) { 34209566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx, &a)); 342173a71a0fSBarry Smith col = (PetscInt)(n * PetscRealPart(a)); 34229566063dSJacob Faibussowitsch PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES)); 342373a71a0fSBarry Smith } 342473a71a0fSBarry Smith } 3425e2ce353bSJunchao Zhang } else { 34269566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayWrite(x, &aa)); 34279566063dSJacob Faibussowitsch for (i = 0; i < aij->nz; i++) PetscCall(PetscRandomGetValue(rctx, aa + i)); 34289566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayWrite(x, &aa)); 3429e2ce353bSJunchao Zhang } 34309566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 34319566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 34323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 343373a71a0fSBarry Smith } 343473a71a0fSBarry Smith 3435679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */ 3436d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x, PetscInt low, PetscInt high, PetscRandom rctx) 3437d71ae5a4SJacob Faibussowitsch { 3438679944adSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data; 3439679944adSJunchao Zhang PetscScalar a; 3440679944adSJunchao Zhang PetscInt m, n, i, j, col, nskip; 3441679944adSJunchao Zhang 3442679944adSJunchao Zhang PetscFunctionBegin; 3443679944adSJunchao Zhang nskip = high - low; 34449566063dSJacob Faibussowitsch PetscCall(MatGetSize(x, &m, &n)); 3445679944adSJunchao Zhang n -= nskip; /* shrink number of columns where nonzeros can be set */ 3446679944adSJunchao Zhang for (i = 0; i < m; i++) { 3447679944adSJunchao Zhang for (j = 0; j < aij->imax[i]; j++) { 34489566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx, &a)); 3449679944adSJunchao Zhang col = (PetscInt)(n * PetscRealPart(a)); 3450679944adSJunchao Zhang if (col >= low) col += nskip; /* shift col rightward to skip the hole */ 34519566063dSJacob Faibussowitsch PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES)); 3452679944adSJunchao Zhang } 3453e2ce353bSJunchao Zhang } 34549566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 34559566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 34563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3457679944adSJunchao Zhang } 3458679944adSJunchao Zhang 34590a6ffc59SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ, 3460cb5b572fSBarry Smith MatGetRow_SeqAIJ, 3461cb5b572fSBarry Smith MatRestoreRow_SeqAIJ, 3462cb5b572fSBarry Smith MatMult_SeqAIJ, 346397304618SKris Buschelman /* 4*/ MatMultAdd_SeqAIJ, 34647c922b88SBarry Smith MatMultTranspose_SeqAIJ, 34657c922b88SBarry Smith MatMultTransposeAdd_SeqAIJ, 3466f4259b30SLisandro Dalcin NULL, 3467f4259b30SLisandro Dalcin NULL, 3468f4259b30SLisandro Dalcin NULL, 3469f4259b30SLisandro Dalcin /* 10*/ NULL, 3470cb5b572fSBarry Smith MatLUFactor_SeqAIJ, 3471f4259b30SLisandro Dalcin NULL, 347241f059aeSBarry Smith MatSOR_SeqAIJ, 347391e9d3e2SHong Zhang MatTranspose_SeqAIJ, 347497304618SKris Buschelman /*1 5*/ MatGetInfo_SeqAIJ, 3475cb5b572fSBarry Smith MatEqual_SeqAIJ, 3476cb5b572fSBarry Smith MatGetDiagonal_SeqAIJ, 3477cb5b572fSBarry Smith MatDiagonalScale_SeqAIJ, 3478cb5b572fSBarry Smith MatNorm_SeqAIJ, 3479f4259b30SLisandro Dalcin /* 20*/ NULL, 3480cb5b572fSBarry Smith MatAssemblyEnd_SeqAIJ, 3481cb5b572fSBarry Smith MatSetOption_SeqAIJ, 3482cb5b572fSBarry Smith MatZeroEntries_SeqAIJ, 3483d519adbfSMatthew Knepley /* 24*/ MatZeroRows_SeqAIJ, 3484f4259b30SLisandro Dalcin NULL, 3485f4259b30SLisandro Dalcin NULL, 3486f4259b30SLisandro Dalcin NULL, 3487f4259b30SLisandro Dalcin NULL, 348826cec326SBarry Smith /* 29*/ MatSetUp_Seq_Hash, 3489f4259b30SLisandro Dalcin NULL, 3490f4259b30SLisandro Dalcin NULL, 3491f4259b30SLisandro Dalcin NULL, 3492f4259b30SLisandro Dalcin NULL, 3493d519adbfSMatthew Knepley /* 34*/ MatDuplicate_SeqAIJ, 3494f4259b30SLisandro Dalcin NULL, 3495f4259b30SLisandro Dalcin NULL, 3496cb5b572fSBarry Smith MatILUFactor_SeqAIJ, 3497f4259b30SLisandro Dalcin NULL, 3498d519adbfSMatthew Knepley /* 39*/ MatAXPY_SeqAIJ, 34997dae84e0SHong Zhang MatCreateSubMatrices_SeqAIJ, 3500cb5b572fSBarry Smith MatIncreaseOverlap_SeqAIJ, 3501cb5b572fSBarry Smith MatGetValues_SeqAIJ, 3502cb5b572fSBarry Smith MatCopy_SeqAIJ, 3503d519adbfSMatthew Knepley /* 44*/ MatGetRowMax_SeqAIJ, 3504cb5b572fSBarry Smith MatScale_SeqAIJ, 35057d68702bSBarry Smith MatShift_SeqAIJ, 350679299369SBarry Smith MatDiagonalSet_SeqAIJ, 35076e169961SBarry Smith MatZeroRowsColumns_SeqAIJ, 350873a71a0fSBarry Smith /* 49*/ MatSetRandom_SeqAIJ, 35093b2fbd54SBarry Smith MatGetRowIJ_SeqAIJ, 35103b2fbd54SBarry Smith MatRestoreRowIJ_SeqAIJ, 35113b2fbd54SBarry Smith MatGetColumnIJ_SeqAIJ, 3512a93ec695SBarry Smith MatRestoreColumnIJ_SeqAIJ, 351393dfae19SHong Zhang /* 54*/ MatFDColoringCreate_SeqXAIJ, 3514f4259b30SLisandro Dalcin NULL, 3515f4259b30SLisandro Dalcin NULL, 3516cda55fadSBarry Smith MatPermute_SeqAIJ, 3517f4259b30SLisandro Dalcin NULL, 3518f4259b30SLisandro Dalcin /* 59*/ NULL, 3519b9b97703SBarry Smith MatDestroy_SeqAIJ, 3520b9b97703SBarry Smith MatView_SeqAIJ, 3521f4259b30SLisandro Dalcin NULL, 3522f4259b30SLisandro Dalcin NULL, 3523f4259b30SLisandro Dalcin /* 64*/ NULL, 3524321b30b9SSatish Balay MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ, 3525f4259b30SLisandro Dalcin NULL, 3526f4259b30SLisandro Dalcin NULL, 3527f4259b30SLisandro Dalcin NULL, 3528d519adbfSMatthew Knepley /* 69*/ MatGetRowMaxAbs_SeqAIJ, 3529c87e5d42SMatthew Knepley MatGetRowMinAbs_SeqAIJ, 3530f4259b30SLisandro Dalcin NULL, 3531f4259b30SLisandro Dalcin NULL, 3532f4259b30SLisandro Dalcin NULL, 3533f4259b30SLisandro Dalcin /* 74*/ NULL, 35343acb8795SBarry Smith MatFDColoringApply_AIJ, 3535f4259b30SLisandro Dalcin NULL, 3536f4259b30SLisandro Dalcin NULL, 3537f4259b30SLisandro Dalcin NULL, 35386ce1633cSBarry Smith /* 79*/ MatFindZeroDiagonals_SeqAIJ, 3539f4259b30SLisandro Dalcin NULL, 3540f4259b30SLisandro Dalcin NULL, 3541f4259b30SLisandro Dalcin NULL, 3542bc011b1eSHong Zhang MatLoad_SeqAIJ, 3543d519adbfSMatthew Knepley /* 84*/ MatIsSymmetric_SeqAIJ, 35441cbb95d3SBarry Smith MatIsHermitian_SeqAIJ, 3545f4259b30SLisandro Dalcin NULL, 3546f4259b30SLisandro Dalcin NULL, 3547f4259b30SLisandro Dalcin NULL, 3548f4259b30SLisandro Dalcin /* 89*/ NULL, 3549f4259b30SLisandro Dalcin NULL, 355026be0446SHong Zhang MatMatMultNumeric_SeqAIJ_SeqAIJ, 3551f4259b30SLisandro Dalcin NULL, 3552f4259b30SLisandro Dalcin NULL, 35538fa4b5a6SHong Zhang /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy, 3554f4259b30SLisandro Dalcin NULL, 3555f4259b30SLisandro Dalcin NULL, 35566fc122caSHong Zhang MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ, 3557f4259b30SLisandro Dalcin NULL, 35584222ddf1SHong Zhang /* 99*/ MatProductSetFromOptions_SeqAIJ, 3559f4259b30SLisandro Dalcin NULL, 3560f4259b30SLisandro Dalcin NULL, 356187d4246cSBarry Smith MatConjugate_SeqAIJ, 3562f4259b30SLisandro Dalcin NULL, 3563d519adbfSMatthew Knepley /*104*/ MatSetValuesRow_SeqAIJ, 356499cafbc1SBarry Smith MatRealPart_SeqAIJ, 3565f5edf698SHong Zhang MatImaginaryPart_SeqAIJ, 3566f4259b30SLisandro Dalcin NULL, 3567f4259b30SLisandro Dalcin NULL, 3568cbd44569SHong Zhang /*109*/ MatMatSolve_SeqAIJ, 3569f4259b30SLisandro Dalcin NULL, 35702af78befSBarry Smith MatGetRowMin_SeqAIJ, 3571f4259b30SLisandro Dalcin NULL, 3572599ef60dSHong Zhang MatMissingDiagonal_SeqAIJ, 3573f4259b30SLisandro Dalcin /*114*/ NULL, 3574f4259b30SLisandro Dalcin NULL, 3575f4259b30SLisandro Dalcin NULL, 3576f4259b30SLisandro Dalcin NULL, 3577f4259b30SLisandro Dalcin NULL, 3578f4259b30SLisandro Dalcin /*119*/ NULL, 3579f4259b30SLisandro Dalcin NULL, 3580f4259b30SLisandro Dalcin NULL, 3581f4259b30SLisandro Dalcin NULL, 3582b3a44c85SBarry Smith MatGetMultiProcBlock_SeqAIJ, 35830716a85fSBarry Smith /*124*/ MatFindNonzeroRows_SeqAIJ, 3584a873a8cdSSam Reynolds MatGetColumnReductions_SeqAIJ, 358537868618SMatthew G Knepley MatInvertBlockDiagonal_SeqAIJ, 35860da83c2eSBarry Smith MatInvertVariableBlockDiagonal_SeqAIJ, 3587f4259b30SLisandro Dalcin NULL, 3588f4259b30SLisandro Dalcin /*129*/ NULL, 3589f4259b30SLisandro Dalcin NULL, 3590f4259b30SLisandro Dalcin NULL, 359175648e8dSHong Zhang MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ, 3592b9af6bddSHong Zhang MatTransposeColoringCreate_SeqAIJ, 3593b9af6bddSHong Zhang /*134*/ MatTransColoringApplySpToDen_SeqAIJ, 35942b8ad9a3SHong Zhang MatTransColoringApplyDenToSp_SeqAIJ, 3595f4259b30SLisandro Dalcin NULL, 3596f4259b30SLisandro Dalcin NULL, 35973964eb88SJed Brown MatRARtNumeric_SeqAIJ_SeqAIJ, 3598f4259b30SLisandro Dalcin /*139*/ NULL, 3599f4259b30SLisandro Dalcin NULL, 3600f4259b30SLisandro Dalcin NULL, 36013a062f41SBarry Smith MatFDColoringSetUp_SeqXAIJ, 36029c8f2541SHong Zhang MatFindOffBlockDiagonalEntries_SeqAIJ, 36034222ddf1SHong Zhang MatCreateMPIMatConcatenateSeqMat_SeqAIJ, 36044222ddf1SHong Zhang /*145*/ MatDestroySubMatrices_SeqAIJ, 3605f4259b30SLisandro Dalcin NULL, 360672833a62Smarkadams4 NULL, 360772833a62Smarkadams4 MatCreateGraph_Simple_AIJ, 36082d776b49SBarry Smith NULL, 3609dec0b466SHong Zhang /*150*/ MatTransposeSymbolic_SeqAIJ, 3610dec0b466SHong Zhang MatEliminateZeros_SeqAIJ}; 361117ab2063SBarry Smith 3612d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat, PetscInt *indices) 3613d71ae5a4SJacob Faibussowitsch { 3614bef8e0ddSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 361597f1f81fSBarry Smith PetscInt i, nz, n; 3616bef8e0ddSBarry Smith 3617bef8e0ddSBarry Smith PetscFunctionBegin; 3618bef8e0ddSBarry Smith nz = aij->maxnz; 3619d0f46423SBarry Smith n = mat->rmap->n; 3620ad540459SPierre Jolivet for (i = 0; i < nz; i++) aij->j[i] = indices[i]; 3621bef8e0ddSBarry Smith aij->nz = nz; 3622ad540459SPierre Jolivet for (i = 0; i < n; i++) aij->ilen[i] = aij->imax[i]; 36233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3624bef8e0ddSBarry Smith } 3625bef8e0ddSBarry Smith 3626a3bb6f32SFande Kong /* 3627ddea5d60SJunchao Zhang * Given a sparse matrix with global column indices, compact it by using a local column space. 3628ddea5d60SJunchao Zhang * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable() 3629ddea5d60SJunchao Zhang */ 3630d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping) 3631d71ae5a4SJacob Faibussowitsch { 3632a3bb6f32SFande Kong Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3633eec179cfSJacob Faibussowitsch PetscHMapI gid1_lid1; 3634eec179cfSJacob Faibussowitsch PetscHashIter tpos; 363525b670f0SStefano Zampini PetscInt gid, lid, i, ec, nz = aij->nz; 363625b670f0SStefano Zampini PetscInt *garray, *jj = aij->j; 3637a3bb6f32SFande Kong 3638a3bb6f32SFande Kong PetscFunctionBegin; 3639a3bb6f32SFande Kong PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3640a3bb6f32SFande Kong PetscValidPointer(mapping, 2); 3641a3bb6f32SFande Kong /* use a table */ 3642eec179cfSJacob Faibussowitsch PetscCall(PetscHMapICreateWithSize(mat->rmap->n, &gid1_lid1)); 3643a3bb6f32SFande Kong ec = 0; 364425b670f0SStefano Zampini for (i = 0; i < nz; i++) { 364525b670f0SStefano Zampini PetscInt data, gid1 = jj[i] + 1; 3646eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIGetWithDefault(gid1_lid1, gid1, 0, &data)); 3647a3bb6f32SFande Kong if (!data) { 3648a3bb6f32SFande Kong /* one based table */ 3649c76ffc5fSJacob Faibussowitsch PetscCall(PetscHMapISet(gid1_lid1, gid1, ++ec)); 3650a3bb6f32SFande Kong } 3651a3bb6f32SFande Kong } 3652a3bb6f32SFande Kong /* form array of columns we need */ 36539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ec, &garray)); 3654eec179cfSJacob Faibussowitsch PetscHashIterBegin(gid1_lid1, tpos); 3655eec179cfSJacob Faibussowitsch while (!PetscHashIterAtEnd(gid1_lid1, tpos)) { 3656eec179cfSJacob Faibussowitsch PetscHashIterGetKey(gid1_lid1, tpos, gid); 3657eec179cfSJacob Faibussowitsch PetscHashIterGetVal(gid1_lid1, tpos, lid); 3658eec179cfSJacob Faibussowitsch PetscHashIterNext(gid1_lid1, tpos); 3659a3bb6f32SFande Kong gid--; 3660a3bb6f32SFande Kong lid--; 3661a3bb6f32SFande Kong garray[lid] = gid; 3662a3bb6f32SFande Kong } 36639566063dSJacob Faibussowitsch PetscCall(PetscSortInt(ec, garray)); /* sort, and rebuild */ 3664eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIClear(gid1_lid1)); 3665c76ffc5fSJacob Faibussowitsch for (i = 0; i < ec; i++) PetscCall(PetscHMapISet(gid1_lid1, garray[i] + 1, i + 1)); 3666a3bb6f32SFande Kong /* compact out the extra columns in B */ 366725b670f0SStefano Zampini for (i = 0; i < nz; i++) { 366825b670f0SStefano Zampini PetscInt gid1 = jj[i] + 1; 3669eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIGetWithDefault(gid1_lid1, gid1, 0, &lid)); 3670a3bb6f32SFande Kong lid--; 367125b670f0SStefano Zampini jj[i] = lid; 3672a3bb6f32SFande Kong } 36739566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&mat->cmap)); 3674eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&gid1_lid1)); 36759566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat), ec, ec, 1, &mat->cmap)); 36769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, mat->cmap->bs, mat->cmap->n, garray, PETSC_OWN_POINTER, mapping)); 36779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*mapping, ISLOCALTOGLOBALMAPPINGHASH)); 36783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3679a3bb6f32SFande Kong } 3680a3bb6f32SFande Kong 3681bef8e0ddSBarry Smith /*@ 3682bef8e0ddSBarry Smith MatSeqAIJSetColumnIndices - Set the column indices for all the rows 3683bef8e0ddSBarry Smith in the matrix. 3684bef8e0ddSBarry Smith 3685bef8e0ddSBarry Smith Input Parameters: 368611a5261eSBarry Smith + mat - the `MATSEQAIJ` matrix 3687bef8e0ddSBarry Smith - indices - the column indices 3688bef8e0ddSBarry Smith 368915091d37SBarry Smith Level: advanced 369015091d37SBarry Smith 3691bef8e0ddSBarry Smith Notes: 3692bef8e0ddSBarry Smith This can be called if you have precomputed the nonzero structure of the 3693bef8e0ddSBarry Smith matrix and want to provide it to the matrix object to improve the performance 369411a5261eSBarry Smith of the `MatSetValues()` operation. 3695bef8e0ddSBarry Smith 3696bef8e0ddSBarry Smith You MUST have set the correct numbers of nonzeros per row in the call to 369711a5261eSBarry Smith `MatCreateSeqAIJ()`, and the columns indices MUST be sorted. 3698bef8e0ddSBarry Smith 369911a5261eSBarry Smith MUST be called before any calls to `MatSetValues()` 3700bef8e0ddSBarry Smith 3701b9617806SBarry Smith The indices should start with zero, not one. 3702b9617806SBarry Smith 37032ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATSEQAIJ` 3704bef8e0ddSBarry Smith @*/ 3705d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat, PetscInt *indices) 3706d71ae5a4SJacob Faibussowitsch { 3707bef8e0ddSBarry Smith PetscFunctionBegin; 37080700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3709dadcf809SJacob Faibussowitsch PetscValidIntPointer(indices, 2); 3710cac4c232SBarry Smith PetscUseMethod(mat, "MatSeqAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices)); 37113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3712bef8e0ddSBarry Smith } 3713bef8e0ddSBarry Smith 3714d71ae5a4SJacob Faibussowitsch PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) 3715d71ae5a4SJacob Faibussowitsch { 3716be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3717d0f46423SBarry Smith size_t nz = aij->i[mat->rmap->n]; 3718be6bf707SBarry Smith 3719be6bf707SBarry Smith PetscFunctionBegin; 372028b400f6SJacob Faibussowitsch PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3721be6bf707SBarry Smith 3722be6bf707SBarry Smith /* allocate space for values if not already there */ 37234dfa11a4SJacob Faibussowitsch if (!aij->saved_values) { PetscCall(PetscMalloc1(nz + 1, &aij->saved_values)); } 3724be6bf707SBarry Smith 3725be6bf707SBarry Smith /* copy values over */ 37269566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz)); 37273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3728be6bf707SBarry Smith } 3729be6bf707SBarry Smith 3730be6bf707SBarry Smith /*@ 373120f4b53cSBarry Smith MatStoreValues - Stashes a copy of the matrix values; this allows reusing of the linear part of a Jacobian, while recomputing only the 3732be6bf707SBarry Smith nonlinear portion. 3733be6bf707SBarry Smith 3734c3339decSBarry Smith Logically Collect 3735be6bf707SBarry Smith 373627430b45SBarry Smith Input Parameter: 373711a5261eSBarry Smith . mat - the matrix (currently only `MATAIJ` matrices support this option) 3738be6bf707SBarry Smith 373915091d37SBarry Smith Level: advanced 374015091d37SBarry Smith 374127430b45SBarry Smith Usage: 374227430b45SBarry Smith .vb 37432ef1f0ffSBarry Smith Using SNES 374427430b45SBarry Smith Create Jacobian matrix 374527430b45SBarry Smith Set linear terms into matrix 374627430b45SBarry Smith Apply boundary conditions to matrix, at this time matrix must have 374727430b45SBarry Smith final nonzero structure (i.e. setting the nonlinear terms and applying 374827430b45SBarry Smith boundary conditions again will not change the nonzero structure 374927430b45SBarry Smith MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 375027430b45SBarry Smith MatStoreValues(mat); 375127430b45SBarry Smith Call SNESSetJacobian() with matrix 375227430b45SBarry Smith In your Jacobian routine 375327430b45SBarry Smith MatRetrieveValues(mat); 375427430b45SBarry Smith Set nonlinear terms in matrix 3755be6bf707SBarry Smith 375627430b45SBarry Smith Without `SNESSolve()`, i.e. when you handle nonlinear solve yourself: 375727430b45SBarry Smith // build linear portion of Jacobian 375827430b45SBarry Smith MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 375927430b45SBarry Smith MatStoreValues(mat); 376027430b45SBarry Smith loop over nonlinear iterations 376127430b45SBarry Smith MatRetrieveValues(mat); 376227430b45SBarry Smith // call MatSetValues(mat,...) to set nonliner portion of Jacobian 376327430b45SBarry Smith // call MatAssemblyBegin/End() on matrix 376427430b45SBarry Smith Solve linear system with Jacobian 376527430b45SBarry Smith endloop 376627430b45SBarry Smith .ve 3767be6bf707SBarry Smith 3768be6bf707SBarry Smith Notes: 3769da81f932SPierre Jolivet Matrix must already be assembled before calling this routine 377011a5261eSBarry Smith Must set the matrix option `MatSetOption`(mat,`MAT_NEW_NONZERO_LOCATIONS`,`PETSC_FALSE`); before 3771be6bf707SBarry Smith calling this routine. 3772be6bf707SBarry Smith 37730c468ba9SBarry Smith When this is called multiple times it overwrites the previous set of stored values 37740c468ba9SBarry Smith and does not allocated additional space. 37750c468ba9SBarry Smith 37762ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `Mat`, `MatRetrieveValues()` 3777be6bf707SBarry Smith @*/ 3778d71ae5a4SJacob Faibussowitsch PetscErrorCode MatStoreValues(Mat mat) 3779d71ae5a4SJacob Faibussowitsch { 3780be6bf707SBarry Smith PetscFunctionBegin; 37810700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 378228b400f6SJacob Faibussowitsch PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 378328b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3784cac4c232SBarry Smith PetscUseMethod(mat, "MatStoreValues_C", (Mat), (mat)); 37853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3786be6bf707SBarry Smith } 3787be6bf707SBarry Smith 3788d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat) 3789d71ae5a4SJacob Faibussowitsch { 3790be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3791d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->n]; 3792be6bf707SBarry Smith 3793be6bf707SBarry Smith PetscFunctionBegin; 379428b400f6SJacob Faibussowitsch PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 379528b400f6SJacob Faibussowitsch PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first"); 3796be6bf707SBarry Smith /* copy values over */ 37979566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz)); 37983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3799be6bf707SBarry Smith } 3800be6bf707SBarry Smith 3801be6bf707SBarry Smith /*@ 380220f4b53cSBarry Smith MatRetrieveValues - Retrieves the copy of the matrix values that was stored with `MatStoreValues()` 3803be6bf707SBarry Smith 3804c3339decSBarry Smith Logically Collect 3805be6bf707SBarry Smith 38062fe279fdSBarry Smith Input Parameter: 380711a5261eSBarry Smith . mat - the matrix (currently only `MATAIJ` matrices support this option) 3808be6bf707SBarry Smith 380915091d37SBarry Smith Level: advanced 381015091d37SBarry Smith 38112ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatStoreValues()` 3812be6bf707SBarry Smith @*/ 3813d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRetrieveValues(Mat mat) 3814d71ae5a4SJacob Faibussowitsch { 3815be6bf707SBarry Smith PetscFunctionBegin; 38160700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 381728b400f6SJacob Faibussowitsch PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 381828b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3819cac4c232SBarry Smith PetscUseMethod(mat, "MatRetrieveValues_C", (Mat), (mat)); 38203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3821be6bf707SBarry Smith } 3822be6bf707SBarry Smith 382317ab2063SBarry Smith /*@C 382411a5261eSBarry Smith MatCreateSeqAIJ - Creates a sparse matrix in `MATSEQAIJ` (compressed row) format 38250d15e28bSLois Curfman McInnes (the default parallel PETSc format). For good matrix assembly performance 382620f4b53cSBarry Smith the user should preallocate the matrix storage by setting the parameter `nz` 382720f4b53cSBarry Smith (or the array `nnz`). 382817ab2063SBarry Smith 3829d083f849SBarry Smith Collective 3830db81eaa0SLois Curfman McInnes 383117ab2063SBarry Smith Input Parameters: 383211a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF` 383317ab2063SBarry Smith . m - number of rows 383417ab2063SBarry Smith . n - number of columns 383517ab2063SBarry Smith . nz - number of nonzeros per row (same for all rows) 383651c19458SBarry Smith - nnz - array containing the number of nonzeros in the various rows 38370298fd71SBarry Smith (possibly different for each row) or NULL 383817ab2063SBarry Smith 383917ab2063SBarry Smith Output Parameter: 3840416022c9SBarry Smith . A - the matrix 384117ab2063SBarry Smith 38422ef1f0ffSBarry Smith Options Database Keys: 38432ef1f0ffSBarry Smith + -mat_no_inode - Do not use inodes 38442ef1f0ffSBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 38452ef1f0ffSBarry Smith 38462ef1f0ffSBarry Smith Level: intermediate 3847175b88e8SBarry Smith 3848b259b22eSLois Curfman McInnes Notes: 38492ef1f0ffSBarry Smith If `nnz` is given then `nz` is ignored 385049a6f317SBarry Smith 38512ef1f0ffSBarry Smith The `MATSEQAIJ` format, also called 38522ef1f0ffSBarry Smith compressed row storage, is fully compatible with standard Fortran 38530002213bSLois Curfman McInnes storage. That is, the stored row and column indices can begin at 38542ef1f0ffSBarry Smith either one (as in Fortran) or zero. 385517ab2063SBarry Smith 385620f4b53cSBarry Smith Specify the preallocated storage with either `nz` or `nnz` (not both). 38572ef1f0ffSBarry Smith Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory 385820f4b53cSBarry Smith allocation. 385917ab2063SBarry Smith 3860682d7d0cSBarry Smith By default, this format uses inodes (identical nodes) when possible, to 38614fca80b9SLois Curfman McInnes improve numerical efficiency of matrix-vector products and solves. We 3862682d7d0cSBarry Smith search for consecutive rows with the same nonzero structure, thereby 38636c7ebb05SLois Curfman McInnes reusing matrix information to achieve increased efficiency. 38646c7ebb05SLois Curfman McInnes 38652ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, [Sparse Matrix Creation](sec_matsparse), `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()` 386617ab2063SBarry Smith @*/ 3867d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A) 3868d71ae5a4SJacob Faibussowitsch { 38693a40ed3dSBarry Smith PetscFunctionBegin; 38709566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 38719566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, m, n)); 38729566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATSEQAIJ)); 38739566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*A, nz, nnz)); 38743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3875273d9f13SBarry Smith } 3876273d9f13SBarry Smith 3877273d9f13SBarry Smith /*@C 3878273d9f13SBarry Smith MatSeqAIJSetPreallocation - For good matrix assembly performance 3879273d9f13SBarry Smith the user should preallocate the matrix storage by setting the parameter nz 3880273d9f13SBarry Smith (or the array nnz). By setting these parameters accurately, performance 3881273d9f13SBarry Smith during matrix assembly can be increased by more than a factor of 50. 3882273d9f13SBarry Smith 3883d083f849SBarry Smith Collective 3884273d9f13SBarry Smith 3885273d9f13SBarry Smith Input Parameters: 38861c4f3114SJed Brown + B - The matrix 3887273d9f13SBarry Smith . nz - number of nonzeros per row (same for all rows) 3888273d9f13SBarry Smith - nnz - array containing the number of nonzeros in the various rows 38890298fd71SBarry Smith (possibly different for each row) or NULL 3890273d9f13SBarry Smith 38912ef1f0ffSBarry Smith Options Database Keys: 38922ef1f0ffSBarry Smith + -mat_no_inode - Do not use inodes 38932ef1f0ffSBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 38942ef1f0ffSBarry Smith 38952ef1f0ffSBarry Smith Level: intermediate 38962ef1f0ffSBarry Smith 3897273d9f13SBarry Smith Notes: 38982ef1f0ffSBarry Smith If `nnz` is given then `nz` is ignored 389949a6f317SBarry Smith 390011a5261eSBarry Smith The `MATSEQAIJ` format also called 39012ef1f0ffSBarry Smith compressed row storage, is fully compatible with standard Fortran 3902273d9f13SBarry Smith storage. That is, the stored row and column indices can begin at 3903273d9f13SBarry Smith either one (as in Fortran) or zero. See the users' manual for details. 3904273d9f13SBarry Smith 39052ef1f0ffSBarry Smith Specify the preallocated storage with either `nz` or `nnz` (not both). 39062ef1f0ffSBarry Smith Set nz = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory 39072ef1f0ffSBarry Smith allocation. 3908273d9f13SBarry Smith 390911a5261eSBarry Smith You can call `MatGetInfo()` to get information on how effective the preallocation was; 3910aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 3911aa95bbe8SBarry Smith You can also run with the option -info and look for messages with the string 3912aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 3913aa95bbe8SBarry Smith 391411a5261eSBarry Smith Developer Notes: 391511a5261eSBarry Smith Use nz of `MAT_SKIP_ALLOCATION` to not allocate any space for the matrix 3916a96a251dSBarry Smith entries or columns indices 3917a96a251dSBarry Smith 3918273d9f13SBarry Smith By default, this format uses inodes (identical nodes) when possible, to 3919273d9f13SBarry Smith improve numerical efficiency of matrix-vector products and solves. We 3920273d9f13SBarry Smith search for consecutive rows with the same nonzero structure, thereby 3921273d9f13SBarry Smith reusing matrix information to achieve increased efficiency. 3922273d9f13SBarry Smith 39232ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()`, `MatGetInfo()`, 3924db781477SPatrick Sanan `MatSeqAIJSetTotalPreallocation()` 3925273d9f13SBarry Smith @*/ 3926d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetPreallocation(Mat B, PetscInt nz, const PetscInt nnz[]) 3927d71ae5a4SJacob Faibussowitsch { 3928a23d5eceSKris Buschelman PetscFunctionBegin; 39296ba663aaSJed Brown PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 39306ba663aaSJed Brown PetscValidType(B, 1); 3931cac4c232SBarry Smith PetscTryMethod(B, "MatSeqAIJSetPreallocation_C", (Mat, PetscInt, const PetscInt[]), (B, nz, nnz)); 39323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3933a23d5eceSKris Buschelman } 3934a23d5eceSKris Buschelman 3935d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B, PetscInt nz, const PetscInt *nnz) 3936d71ae5a4SJacob Faibussowitsch { 3937ad79cf63SBarry Smith Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 39382576faa2SJed Brown PetscBool skipallocation = PETSC_FALSE, realalloc = PETSC_FALSE; 393997f1f81fSBarry Smith PetscInt i; 3940273d9f13SBarry Smith 3941273d9f13SBarry Smith PetscFunctionBegin; 3942ad79cf63SBarry Smith if (B->hash_active) { 3943ad79cf63SBarry Smith PetscCall(PetscMemcpy(&B->ops, &b->cops, sizeof(*(B->ops)))); 3944ad79cf63SBarry Smith PetscCall(PetscHMapIJVDestroy(&b->ht)); 3945ad79cf63SBarry Smith PetscCall(PetscFree(b->dnz)); 3946ad79cf63SBarry Smith B->hash_active = PETSC_FALSE; 3947ad79cf63SBarry Smith } 39482576faa2SJed Brown if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 3949a96a251dSBarry Smith if (nz == MAT_SKIP_ALLOCATION) { 3950c461c341SBarry Smith skipallocation = PETSC_TRUE; 3951c461c341SBarry Smith nz = 0; 3952c461c341SBarry Smith } 39539566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 39549566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 3955899cda47SBarry Smith 3956435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 395708401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz); 3958cf9c20a2SJed Brown if (PetscUnlikelyDebug(nnz)) { 3959d0f46423SBarry Smith for (i = 0; i < B->rmap->n; i++) { 396008401ef6SPierre 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]); 396108401ef6SPierre 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); 3962b73539f3SBarry Smith } 3963b73539f3SBarry Smith } 3964b73539f3SBarry Smith 3965273d9f13SBarry Smith B->preallocated = PETSC_TRUE; 3966ab93d7beSBarry Smith if (!skipallocation) { 39674dfa11a4SJacob Faibussowitsch if (!b->imax) { PetscCall(PetscMalloc1(B->rmap->n, &b->imax)); } 3968071fcb05SBarry Smith if (!b->ilen) { 3969071fcb05SBarry Smith /* b->ilen will count nonzeros in each row so far. */ 39709566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(B->rmap->n, &b->ilen)); 3971071fcb05SBarry Smith } else { 39729566063dSJacob Faibussowitsch PetscCall(PetscMemzero(b->ilen, B->rmap->n * sizeof(PetscInt))); 39732ee49352SLisandro Dalcin } 3974aa624791SPierre Jolivet if (!b->ipre) PetscCall(PetscMalloc1(B->rmap->n, &b->ipre)); 3975273d9f13SBarry Smith if (!nnz) { 3976435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 3977c62bd62aSJed Brown else if (nz < 0) nz = 1; 39785d2a9ed1SStefano Zampini nz = PetscMin(nz, B->cmap->n); 3979d0f46423SBarry Smith for (i = 0; i < B->rmap->n; i++) b->imax[i] = nz; 3980d0f46423SBarry Smith nz = nz * B->rmap->n; 3981273d9f13SBarry Smith } else { 3982c73702f5SBarry Smith PetscInt64 nz64 = 0; 39839371c9d4SSatish Balay for (i = 0; i < B->rmap->n; i++) { 39849371c9d4SSatish Balay b->imax[i] = nnz[i]; 39859371c9d4SSatish Balay nz64 += nnz[i]; 39869371c9d4SSatish Balay } 39879566063dSJacob Faibussowitsch PetscCall(PetscIntCast(nz64, &nz)); 3988273d9f13SBarry Smith } 3989ab93d7beSBarry Smith 3990273d9f13SBarry Smith /* allocate the matrix space */ 399153dd7562SDmitry Karpeev /* FIXME: should B's old memory be unlogged? */ 39929566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i)); 3993396832f4SHong Zhang if (B->structure_only) { 39949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &b->j)); 39959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n + 1, &b->i)); 3996396832f4SHong Zhang } else { 39979566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(nz, &b->a, nz, &b->j, B->rmap->n + 1, &b->i)); 3998396832f4SHong Zhang } 3999bfeeae90SHong Zhang b->i[0] = 0; 4000ad540459SPierre Jolivet for (i = 1; i < B->rmap->n + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1]; 4001396832f4SHong Zhang if (B->structure_only) { 4002396832f4SHong Zhang b->singlemalloc = PETSC_FALSE; 4003396832f4SHong Zhang b->free_a = PETSC_FALSE; 4004396832f4SHong Zhang } else { 4005273d9f13SBarry Smith b->singlemalloc = PETSC_TRUE; 4006e6b907acSBarry Smith b->free_a = PETSC_TRUE; 4007396832f4SHong Zhang } 4008e6b907acSBarry Smith b->free_ij = PETSC_TRUE; 4009c461c341SBarry Smith } else { 4010e6b907acSBarry Smith b->free_a = PETSC_FALSE; 4011e6b907acSBarry Smith b->free_ij = PETSC_FALSE; 4012c461c341SBarry Smith } 4013273d9f13SBarry Smith 4014846b4da1SFande Kong if (b->ipre && nnz != b->ipre && b->imax) { 4015846b4da1SFande Kong /* reserve user-requested sparsity */ 40169566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->ipre, b->imax, B->rmap->n)); 4017846b4da1SFande Kong } 4018846b4da1SFande Kong 4019273d9f13SBarry Smith b->nz = 0; 4020273d9f13SBarry Smith b->maxnz = nz; 4021273d9f13SBarry Smith B->info.nz_unneeded = (double)b->maxnz; 40221baa6e33SBarry Smith if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 4023cb7b82ddSBarry Smith B->was_assembled = PETSC_FALSE; 4024cb7b82ddSBarry Smith B->assembled = PETSC_FALSE; 40255519a089SJose E. Roman /* We simply deem preallocation has changed nonzero state. Updating the state 40265519a089SJose E. Roman will give clients (like AIJKokkos) a chance to know something has happened. 40275519a089SJose E. Roman */ 40285519a089SJose E. Roman B->nonzerostate++; 40293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4030273d9f13SBarry Smith } 4031273d9f13SBarry Smith 4032d71ae5a4SJacob Faibussowitsch PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A) 4033d71ae5a4SJacob Faibussowitsch { 4034846b4da1SFande Kong Mat_SeqAIJ *a; 4035a5bbaf83SFande Kong PetscInt i; 4036846b4da1SFande Kong 4037846b4da1SFande Kong PetscFunctionBegin; 4038846b4da1SFande Kong PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 403914d0e64fSAlex Lindsay 404014d0e64fSAlex Lindsay /* Check local size. If zero, then return */ 40413ba16761SJacob Faibussowitsch if (!A->rmap->n) PetscFunctionReturn(PETSC_SUCCESS); 404214d0e64fSAlex Lindsay 4043846b4da1SFande Kong a = (Mat_SeqAIJ *)A->data; 40442c814fdeSFande Kong /* if no saved info, we error out */ 404528b400f6SJacob Faibussowitsch PetscCheck(a->ipre, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "No saved preallocation info "); 40462c814fdeSFande Kong 4047aed4548fSBarry Smith PetscCheck(a->i && a->j && a->a && a->imax && a->ilen, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Memory info is incomplete, and can not reset preallocation "); 40482c814fdeSFande Kong 40499566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->imax, a->ipre, A->rmap->n)); 40509566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(a->ilen, A->rmap->n)); 4051846b4da1SFande Kong a->i[0] = 0; 4052ad540459SPierre Jolivet for (i = 1; i < A->rmap->n + 1; i++) a->i[i] = a->i[i - 1] + a->imax[i - 1]; 4053846b4da1SFande Kong A->preallocated = PETSC_TRUE; 4054846b4da1SFande Kong a->nz = 0; 4055846b4da1SFande Kong a->maxnz = a->i[A->rmap->n]; 4056846b4da1SFande Kong A->info.nz_unneeded = (double)a->maxnz; 4057846b4da1SFande Kong A->was_assembled = PETSC_FALSE; 4058846b4da1SFande Kong A->assembled = PETSC_FALSE; 40593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4060846b4da1SFande Kong } 4061846b4da1SFande Kong 406258d36128SBarry Smith /*@ 406311a5261eSBarry Smith MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in `MATSEQAIJ` format. 4064a1661176SMatthew Knepley 4065a1661176SMatthew Knepley Input Parameters: 4066a1661176SMatthew Knepley + B - the matrix 4067a1661176SMatthew Knepley . i - the indices into j for the start of each row (starts with zero) 4068a1661176SMatthew Knepley . j - the column indices for each row (starts with zero) these must be sorted for each row 4069a1661176SMatthew Knepley - v - optional values in the matrix 4070a1661176SMatthew Knepley 4071a1661176SMatthew Knepley Level: developer 4072a1661176SMatthew Knepley 40736a9b8d82SBarry Smith Notes: 40742ef1f0ffSBarry Smith The `i`,`j`,`v` values are COPIED with this routine; to avoid the copy use `MatCreateSeqAIJWithArrays()` 407558d36128SBarry Smith 40766a9b8d82SBarry Smith This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero 40776a9b8d82SBarry Smith structure will be the union of all the previous nonzero structures. 40786a9b8d82SBarry Smith 40796a9b8d82SBarry Smith Developer Notes: 40802ef1f0ffSBarry 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 40812ef1f0ffSBarry Smith then just copies the `v` values directly with `PetscMemcpy()`. 40826a9b8d82SBarry Smith 408311a5261eSBarry Smith This routine could also take a `PetscCopyMode` argument to allow sharing the values instead of always copying them. 40846a9b8d82SBarry Smith 40852ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatSeqAIJSetPreallocation()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MatResetPreallocation()` 4086a1661176SMatthew Knepley @*/ 4087d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B, const PetscInt i[], const PetscInt j[], const PetscScalar v[]) 4088d71ae5a4SJacob Faibussowitsch { 4089a1661176SMatthew Knepley PetscFunctionBegin; 40900700a824SBarry Smith PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 40916ba663aaSJed Brown PetscValidType(B, 1); 4092cac4c232SBarry Smith PetscTryMethod(B, "MatSeqAIJSetPreallocationCSR_C", (Mat, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, i, j, v)); 40933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4094a1661176SMatthew Knepley } 4095a1661176SMatthew Knepley 4096d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B, const PetscInt Ii[], const PetscInt J[], const PetscScalar v[]) 4097d71ae5a4SJacob Faibussowitsch { 4098a1661176SMatthew Knepley PetscInt i; 4099a1661176SMatthew Knepley PetscInt m, n; 4100a1661176SMatthew Knepley PetscInt nz; 41016a9b8d82SBarry Smith PetscInt *nnz; 4102a1661176SMatthew Knepley 4103a1661176SMatthew Knepley PetscFunctionBegin; 4104aed4548fSBarry Smith PetscCheck(Ii[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]); 4105779a8d59SSatish Balay 41069566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 41079566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 4108779a8d59SSatish Balay 41099566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &m, &n)); 41109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nnz)); 4111a1661176SMatthew Knepley for (i = 0; i < m; i++) { 4112b7940d39SSatish Balay nz = Ii[i + 1] - Ii[i]; 411308401ef6SPierre 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); 4114a1661176SMatthew Knepley nnz[i] = nz; 4115a1661176SMatthew Knepley } 41169566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz)); 41179566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 4118a1661176SMatthew Knepley 411948a46eb9SPierre Jolivet for (i = 0; i < m; i++) PetscCall(MatSetValues_SeqAIJ(B, 1, &i, Ii[i + 1] - Ii[i], J + Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES)); 4120a1661176SMatthew Knepley 41219566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 41229566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4123a1661176SMatthew Knepley 41249566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 41253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4126a1661176SMatthew Knepley } 4127a1661176SMatthew Knepley 4128ad7e164aSPierre Jolivet /*@ 41292ef1f0ffSBarry Smith MatSeqAIJKron - Computes `C`, the Kronecker product of `A` and `B`. 4130ad7e164aSPierre Jolivet 4131ad7e164aSPierre Jolivet Input Parameters: 4132ad7e164aSPierre Jolivet + A - left-hand side matrix 4133ad7e164aSPierre Jolivet . B - right-hand side matrix 413411a5261eSBarry Smith - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 4135ad7e164aSPierre Jolivet 4136ad7e164aSPierre Jolivet Output Parameter: 41372ef1f0ffSBarry Smith . C - Kronecker product of `A` and `B` 4138ad7e164aSPierre Jolivet 4139ad7e164aSPierre Jolivet Level: intermediate 4140ad7e164aSPierre Jolivet 414111a5261eSBarry Smith Note: 414211a5261eSBarry 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()`. 4143ad7e164aSPierre Jolivet 41442ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATKAIJ`, `MatReuse` 4145ad7e164aSPierre Jolivet @*/ 4146d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJKron(Mat A, Mat B, MatReuse reuse, Mat *C) 4147d71ae5a4SJacob Faibussowitsch { 4148ad7e164aSPierre Jolivet PetscFunctionBegin; 4149ad7e164aSPierre Jolivet PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4150ad7e164aSPierre Jolivet PetscValidType(A, 1); 4151ad7e164aSPierre Jolivet PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4152ad7e164aSPierre Jolivet PetscValidType(B, 2); 4153ad7e164aSPierre Jolivet PetscValidPointer(C, 4); 4154ad7e164aSPierre Jolivet if (reuse == MAT_REUSE_MATRIX) { 4155ad7e164aSPierre Jolivet PetscValidHeaderSpecific(*C, MAT_CLASSID, 4); 4156ad7e164aSPierre Jolivet PetscValidType(*C, 4); 4157ad7e164aSPierre Jolivet } 4158cac4c232SBarry Smith PetscTryMethod(A, "MatSeqAIJKron_C", (Mat, Mat, MatReuse, Mat *), (A, B, reuse, C)); 41593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4160ad7e164aSPierre Jolivet } 4161ad7e164aSPierre Jolivet 4162d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A, Mat B, MatReuse reuse, Mat *C) 4163d71ae5a4SJacob Faibussowitsch { 4164ad7e164aSPierre Jolivet Mat newmat; 4165ad7e164aSPierre Jolivet Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 4166ad7e164aSPierre Jolivet Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 4167ad7e164aSPierre Jolivet PetscScalar *v; 4168fff043a9SJunchao Zhang const PetscScalar *aa, *ba; 4169ad7e164aSPierre 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; 4170ad7e164aSPierre Jolivet PetscBool flg; 4171ad7e164aSPierre Jolivet 4172ad7e164aSPierre Jolivet PetscFunctionBegin; 417328b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 417428b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 417528b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 417628b400f6SJacob Faibussowitsch PetscCheck(B->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 41779566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATSEQAIJ, &flg)); 417828b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatType %s", ((PetscObject)B)->type_name); 4179aed4548fSBarry Smith PetscCheck(reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatReuse %d", (int)reuse); 4180ad7e164aSPierre Jolivet if (reuse == MAT_INITIAL_MATRIX) { 41819566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(am * bm + 1, &i, a->i[am] * b->i[bm], &j)); 41829566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &newmat)); 41839566063dSJacob Faibussowitsch PetscCall(MatSetSizes(newmat, am * bm, an * bn, am * bm, an * bn)); 41849566063dSJacob Faibussowitsch PetscCall(MatSetType(newmat, MATAIJ)); 4185ad7e164aSPierre Jolivet i[0] = 0; 4186ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4187ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4188ad7e164aSPierre Jolivet i[m * bm + p + 1] = i[m * bm + p] + (a->i[m + 1] - a->i[m]) * (b->i[p + 1] - b->i[p]); 4189ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m + 1]; ++n) { 4190ad540459SPierre Jolivet for (q = b->i[p]; q < b->i[p + 1]; ++q) j[nnz++] = a->j[n] * bn + b->j[q]; 4191ad7e164aSPierre Jolivet } 4192ad7e164aSPierre Jolivet } 4193ad7e164aSPierre Jolivet } 41949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(newmat, i, j, NULL)); 4195ad7e164aSPierre Jolivet *C = newmat; 41969566063dSJacob Faibussowitsch PetscCall(PetscFree2(i, j)); 4197ad7e164aSPierre Jolivet nnz = 0; 4198ad7e164aSPierre Jolivet } 41999566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(*C, &v)); 42009566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 42019566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &ba)); 4202ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4203ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4204ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m + 1]; ++n) { 4205ad540459SPierre Jolivet for (q = b->i[p]; q < b->i[p + 1]; ++q) v[nnz++] = aa[n] * ba[q]; 4206ad7e164aSPierre Jolivet } 4207ad7e164aSPierre Jolivet } 4208ad7e164aSPierre Jolivet } 42099566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(*C, &v)); 42109566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 42119566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &ba)); 42123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4213ad7e164aSPierre Jolivet } 4214ad7e164aSPierre Jolivet 4215c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h> 4216af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h> 4217170fe5c8SBarry Smith 4218170fe5c8SBarry Smith /* 4219170fe5c8SBarry Smith Computes (B'*A')' since computing B*A directly is untenable 4220170fe5c8SBarry Smith 4221170fe5c8SBarry Smith n p p 42222da392ccSBarry Smith [ ] [ ] [ ] 42232da392ccSBarry Smith m [ A ] * n [ B ] = m [ C ] 42242da392ccSBarry Smith [ ] [ ] [ ] 4225170fe5c8SBarry Smith 4226170fe5c8SBarry Smith */ 4227d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A, Mat B, Mat C) 4228d71ae5a4SJacob Faibussowitsch { 4229170fe5c8SBarry Smith Mat_SeqDense *sub_a = (Mat_SeqDense *)A->data; 4230170fe5c8SBarry Smith Mat_SeqAIJ *sub_b = (Mat_SeqAIJ *)B->data; 4231170fe5c8SBarry Smith Mat_SeqDense *sub_c = (Mat_SeqDense *)C->data; 423286214ceeSStefano Zampini PetscInt i, j, n, m, q, p; 4233170fe5c8SBarry Smith const PetscInt *ii, *idx; 4234170fe5c8SBarry Smith const PetscScalar *b, *a, *a_q; 4235170fe5c8SBarry Smith PetscScalar *c, *c_q; 423686214ceeSStefano Zampini PetscInt clda = sub_c->lda; 423786214ceeSStefano Zampini PetscInt alda = sub_a->lda; 4238170fe5c8SBarry Smith 4239170fe5c8SBarry Smith PetscFunctionBegin; 4240d0f46423SBarry Smith m = A->rmap->n; 4241d0f46423SBarry Smith n = A->cmap->n; 4242d0f46423SBarry Smith p = B->cmap->n; 4243170fe5c8SBarry Smith a = sub_a->v; 4244170fe5c8SBarry Smith b = sub_b->a; 4245170fe5c8SBarry Smith c = sub_c->v; 424686214ceeSStefano Zampini if (clda == m) { 42479566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c, m * p)); 424886214ceeSStefano Zampini } else { 424986214ceeSStefano Zampini for (j = 0; j < p; j++) 42509371c9d4SSatish Balay for (i = 0; i < m; i++) c[j * clda + i] = 0.0; 425186214ceeSStefano Zampini } 4252170fe5c8SBarry Smith ii = sub_b->i; 4253170fe5c8SBarry Smith idx = sub_b->j; 4254170fe5c8SBarry Smith for (i = 0; i < n; i++) { 4255170fe5c8SBarry Smith q = ii[i + 1] - ii[i]; 4256170fe5c8SBarry Smith while (q-- > 0) { 425786214ceeSStefano Zampini c_q = c + clda * (*idx); 425886214ceeSStefano Zampini a_q = a + alda * i; 4259854c7f52SBarry Smith PetscKernelAXPY(c_q, *b, a_q, m); 4260170fe5c8SBarry Smith idx++; 4261170fe5c8SBarry Smith b++; 4262170fe5c8SBarry Smith } 4263170fe5c8SBarry Smith } 42643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4265170fe5c8SBarry Smith } 4266170fe5c8SBarry Smith 4267d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A, Mat B, PetscReal fill, Mat C) 4268d71ae5a4SJacob Faibussowitsch { 4269d0f46423SBarry Smith PetscInt m = A->rmap->n, n = B->cmap->n; 427086214ceeSStefano Zampini PetscBool cisdense; 4271170fe5c8SBarry Smith 4272170fe5c8SBarry Smith PetscFunctionBegin; 427308401ef6SPierre 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); 42749566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, m, n)); 42759566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, B)); 4276d5e393b6SSuyash Tandon PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, MATSEQDENSEHIP, "")); 427748a46eb9SPierre Jolivet if (!cisdense) PetscCall(MatSetType(C, MATDENSE)); 42789566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 4279d73949e8SHong Zhang 42804222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ; 42813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4282170fe5c8SBarry Smith } 4283170fe5c8SBarry Smith 42840bad9183SKris Buschelman /*MC 4285fafad747SKris Buschelman MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 42860bad9183SKris Buschelman based on compressed sparse row format. 42870bad9183SKris Buschelman 42882ef1f0ffSBarry Smith Options Database Key: 42890bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 42900bad9183SKris Buschelman 42910bad9183SKris Buschelman Level: beginner 42920bad9183SKris Buschelman 42930cd7f59aSBarry Smith Notes: 42942ef1f0ffSBarry Smith `MatSetValues()` may be called for this matrix type with a `NULL` argument for the numerical values, 42950cd7f59aSBarry Smith in this case the values associated with the rows and columns one passes in are set to zero 42960cd7f59aSBarry Smith in the matrix 42970cd7f59aSBarry Smith 429811a5261eSBarry Smith `MatSetOptions`(,`MAT_STRUCTURE_ONLY`,`PETSC_TRUE`) may be called for this matrix type. In this no 429911a5261eSBarry Smith space is allocated for the nonzero entries and any entries passed with `MatSetValues()` are ignored 43000cd7f59aSBarry Smith 430111a5261eSBarry Smith Developer Note: 43022ef1f0ffSBarry Smith It would be nice if all matrix formats supported passing `NULL` in for the numerical values 43030cd7f59aSBarry Smith 43042ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatSetFromOptions()`, `MatSetType()`, `MatCreate()`, `MatType`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 43050bad9183SKris Buschelman M*/ 43060bad9183SKris Buschelman 4307ccd284c7SBarry Smith /*MC 4308ccd284c7SBarry Smith MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 4309ccd284c7SBarry Smith 431011a5261eSBarry Smith This matrix type is identical to `MATSEQAIJ` when constructed with a single process communicator, 431111a5261eSBarry Smith and `MATMPIAIJ` otherwise. As a result, for single process communicators, 431211a5261eSBarry Smith `MatSeqAIJSetPreallocation()` is supported, and similarly `MatMPIAIJSetPreallocation()` is supported 4313ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4314ccd284c7SBarry Smith the above preallocation routines for simplicity. 4315ccd284c7SBarry Smith 43162ef1f0ffSBarry Smith Options Database Key: 431711a5261eSBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to `MatSetFromOptions()` 4318ccd284c7SBarry Smith 43192ef1f0ffSBarry Smith Level: beginner 43202ef1f0ffSBarry Smith 432111a5261eSBarry Smith Note: 432211a5261eSBarry Smith Subclasses include `MATAIJCUSPARSE`, `MATAIJPERM`, `MATAIJSELL`, `MATAIJMKL`, `MATAIJCRL`, and also automatically switches over to use inodes when 4323ccd284c7SBarry Smith enough exist. 4324ccd284c7SBarry Smith 43252ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATMPIAIJ`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 4326ccd284c7SBarry Smith M*/ 4327ccd284c7SBarry Smith 4328ccd284c7SBarry Smith /*MC 4329ccd284c7SBarry Smith MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 4330ccd284c7SBarry Smith 43312ef1f0ffSBarry Smith Options Database Key: 43322ef1f0ffSBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to `MatSetFromOptions()` 43332ef1f0ffSBarry Smith 43342ef1f0ffSBarry Smith Level: beginner 43352ef1f0ffSBarry Smith 43362ef1f0ffSBarry Smith Note: 433711a5261eSBarry Smith This matrix type is identical to `MATSEQAIJCRL` when constructed with a single process communicator, 433811a5261eSBarry Smith and `MATMPIAIJCRL` otherwise. As a result, for single process communicators, 433911a5261eSBarry Smith `MatSeqAIJSetPreallocation()` is supported, and similarly `MatMPIAIJSetPreallocation()` is supported 4340ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4341ccd284c7SBarry Smith the above preallocation routines for simplicity. 4342ccd284c7SBarry Smith 43432ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatCreateMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL` 4344ccd284c7SBarry Smith M*/ 4345ccd284c7SBarry Smith 43467906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat, MatType, MatReuse, Mat *); 43477906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 43487906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat, MatType, MatReuse, Mat *); 43497906f579SHong Zhang #endif 4350d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 4351d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat, MatType, MatReuse, Mat *); 4352d24d4204SJose E. Roman #endif 43537906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE) 43547906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType, MatReuse, Mat *); 43557906f579SHong Zhang #endif 43567906f579SHong Zhang 4357d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat, MatType, MatReuse, Mat *); 4358c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat, MatType, MatReuse, Mat *); 43594222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat); 43607906f579SHong Zhang 43618c778c55SBarry Smith /*@C 436211a5261eSBarry Smith MatSeqAIJGetArray - gives read/write access to the array where the data for a `MATSEQAIJ` matrix is stored 43638c778c55SBarry Smith 43648c778c55SBarry Smith Not Collective 43658c778c55SBarry Smith 43668c778c55SBarry Smith Input Parameter: 436711a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 43688c778c55SBarry Smith 43698c778c55SBarry Smith Output Parameter: 43708c778c55SBarry Smith . array - pointer to the data 43718c778c55SBarry Smith 43728c778c55SBarry Smith Level: intermediate 43738c778c55SBarry Smith 43740ab4885dSBarry Smith Fortran Note: 43750ab4885dSBarry Smith `MatSeqAIJGetArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatSeqAIJGetArrayF90()` 43760ab4885dSBarry Smith 43772ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()` 43788c778c55SBarry Smith @*/ 4379d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJGetArray(Mat A, PetscScalar **array) 4380d71ae5a4SJacob Faibussowitsch { 4381d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 43828c778c55SBarry Smith 43838c778c55SBarry Smith PetscFunctionBegin; 4384d67d9f35SJunchao Zhang if (aij->ops->getarray) { 43859566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarray)(A, array)); 4386d67d9f35SJunchao Zhang } else { 4387d67d9f35SJunchao Zhang *array = aij->a; 4388d67d9f35SJunchao Zhang } 43893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4390d67d9f35SJunchao Zhang } 4391d67d9f35SJunchao Zhang 4392d67d9f35SJunchao Zhang /*@C 439311a5261eSBarry Smith MatSeqAIJRestoreArray - returns access to the array where the data for a `MATSEQAIJ` matrix is stored obtained by `MatSeqAIJGetArray()` 4394d67d9f35SJunchao Zhang 4395d67d9f35SJunchao Zhang Not Collective 4396d67d9f35SJunchao Zhang 4397d67d9f35SJunchao Zhang Input Parameters: 439811a5261eSBarry Smith + mat - a `MATSEQAIJ` matrix 4399d67d9f35SJunchao Zhang - array - pointer to the data 4400d67d9f35SJunchao Zhang 4401d67d9f35SJunchao Zhang Level: intermediate 4402d67d9f35SJunchao Zhang 44030ab4885dSBarry Smith Fortran Note: 44040ab4885dSBarry Smith `MatSeqAIJRestoreArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatSeqAIJRestoreArrayF90()` 44050ab4885dSBarry Smith 44062ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayF90()` 4407d67d9f35SJunchao Zhang @*/ 4408d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJRestoreArray(Mat A, PetscScalar **array) 4409d71ae5a4SJacob Faibussowitsch { 4410d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4411d67d9f35SJunchao Zhang 4412d67d9f35SJunchao Zhang PetscFunctionBegin; 4413d67d9f35SJunchao Zhang if (aij->ops->restorearray) { 44149566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearray)(A, array)); 4415d67d9f35SJunchao Zhang } else { 4416d67d9f35SJunchao Zhang *array = NULL; 4417d67d9f35SJunchao Zhang } 44189566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 44199566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 44203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44218c778c55SBarry Smith } 44228c778c55SBarry Smith 442321e72a00SBarry Smith /*@C 442411a5261eSBarry Smith MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a `MATSEQAIJ` matrix is stored 44258f1ea47aSStefano Zampini 44260ab4885dSBarry Smith Not Collective; No Fortran Support 44278f1ea47aSStefano Zampini 44288f1ea47aSStefano Zampini Input Parameter: 442911a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 44308f1ea47aSStefano Zampini 44318f1ea47aSStefano Zampini Output Parameter: 44328f1ea47aSStefano Zampini . array - pointer to the data 44338f1ea47aSStefano Zampini 44348f1ea47aSStefano Zampini Level: intermediate 44358f1ea47aSStefano Zampini 44362ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 44378f1ea47aSStefano Zampini @*/ 4438d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJGetArrayRead(Mat A, const PetscScalar **array) 4439d71ae5a4SJacob Faibussowitsch { 4440d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 44418f1ea47aSStefano Zampini 44428f1ea47aSStefano Zampini PetscFunctionBegin; 4443d67d9f35SJunchao Zhang if (aij->ops->getarrayread) { 44449566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarrayread)(A, array)); 4445d67d9f35SJunchao Zhang } else { 4446d67d9f35SJunchao Zhang *array = aij->a; 4447d67d9f35SJunchao Zhang } 44483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44498f1ea47aSStefano Zampini } 44508f1ea47aSStefano Zampini 44518f1ea47aSStefano Zampini /*@C 445211a5261eSBarry Smith MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from `MatSeqAIJGetArrayRead()` 44538f1ea47aSStefano Zampini 44540ab4885dSBarry Smith Not Collective; No Fortran Support 44558f1ea47aSStefano Zampini 44568f1ea47aSStefano Zampini Input Parameter: 445711a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 44588f1ea47aSStefano Zampini 44598f1ea47aSStefano Zampini Output Parameter: 44608f1ea47aSStefano Zampini . array - pointer to the data 44618f1ea47aSStefano Zampini 44628f1ea47aSStefano Zampini Level: intermediate 44638f1ea47aSStefano Zampini 44642ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 44658f1ea47aSStefano Zampini @*/ 4466d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJRestoreArrayRead(Mat A, const PetscScalar **array) 4467d71ae5a4SJacob Faibussowitsch { 4468d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 44698f1ea47aSStefano Zampini 44708f1ea47aSStefano Zampini PetscFunctionBegin; 4471d67d9f35SJunchao Zhang if (aij->ops->restorearrayread) { 44729566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearrayread)(A, array)); 4473d67d9f35SJunchao Zhang } else { 4474d67d9f35SJunchao Zhang *array = NULL; 4475d67d9f35SJunchao Zhang } 44763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4477d67d9f35SJunchao Zhang } 4478d67d9f35SJunchao Zhang 4479d67d9f35SJunchao Zhang /*@C 448011a5261eSBarry Smith MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a `MATSEQAIJ` matrix is stored 4481d67d9f35SJunchao Zhang 44820ab4885dSBarry Smith Not Collective; No Fortran Support 4483d67d9f35SJunchao Zhang 4484d67d9f35SJunchao Zhang Input Parameter: 448511a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 4486d67d9f35SJunchao Zhang 4487d67d9f35SJunchao Zhang Output Parameter: 4488d67d9f35SJunchao Zhang . array - pointer to the data 4489d67d9f35SJunchao Zhang 4490d67d9f35SJunchao Zhang Level: intermediate 4491d67d9f35SJunchao Zhang 44922ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 4493d67d9f35SJunchao Zhang @*/ 4494d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJGetArrayWrite(Mat A, PetscScalar **array) 4495d71ae5a4SJacob Faibussowitsch { 4496d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4497d67d9f35SJunchao Zhang 4498d67d9f35SJunchao Zhang PetscFunctionBegin; 4499d67d9f35SJunchao Zhang if (aij->ops->getarraywrite) { 45009566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarraywrite)(A, array)); 4501d67d9f35SJunchao Zhang } else { 4502d67d9f35SJunchao Zhang *array = aij->a; 4503d67d9f35SJunchao Zhang } 45049566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 45059566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 45063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4507d67d9f35SJunchao Zhang } 4508d67d9f35SJunchao Zhang 4509d67d9f35SJunchao Zhang /*@C 4510d67d9f35SJunchao Zhang MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead 4511d67d9f35SJunchao Zhang 45120ab4885dSBarry Smith Not Collective; No Fortran Support 4513d67d9f35SJunchao Zhang 4514d67d9f35SJunchao Zhang Input Parameter: 4515d67d9f35SJunchao Zhang . mat - a MATSEQAIJ matrix 4516d67d9f35SJunchao Zhang 4517d67d9f35SJunchao Zhang Output Parameter: 4518d67d9f35SJunchao Zhang . array - pointer to the data 4519d67d9f35SJunchao Zhang 4520d67d9f35SJunchao Zhang Level: intermediate 4521d67d9f35SJunchao Zhang 45222ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 4523d67d9f35SJunchao Zhang @*/ 4524d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJRestoreArrayWrite(Mat A, PetscScalar **array) 4525d71ae5a4SJacob Faibussowitsch { 4526d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4527d67d9f35SJunchao Zhang 4528d67d9f35SJunchao Zhang PetscFunctionBegin; 4529d67d9f35SJunchao Zhang if (aij->ops->restorearraywrite) { 45309566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearraywrite)(A, array)); 4531d67d9f35SJunchao Zhang } else { 4532d67d9f35SJunchao Zhang *array = NULL; 4533d67d9f35SJunchao Zhang } 45343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 45358f1ea47aSStefano Zampini } 45368f1ea47aSStefano Zampini 45378f1ea47aSStefano Zampini /*@C 453811a5261eSBarry Smith MatSeqAIJGetCSRAndMemType - Get the CSR arrays and the memory type of the `MATSEQAIJ` matrix 45397ee59b9bSJunchao Zhang 45400ab4885dSBarry Smith Not Collective; No Fortran Support 45417ee59b9bSJunchao Zhang 45427ee59b9bSJunchao Zhang Input Parameter: 454311a5261eSBarry Smith . mat - a matrix of type `MATSEQAIJ` or its subclasses 45447ee59b9bSJunchao Zhang 45457ee59b9bSJunchao Zhang Output Parameters: 45467ee59b9bSJunchao Zhang + i - row map array of the matrix 45477ee59b9bSJunchao Zhang . j - column index array of the matrix 45487ee59b9bSJunchao Zhang . a - data array of the matrix 45497ee59b9bSJunchao Zhang - memtype - memory type of the arrays 45507ee59b9bSJunchao Zhang 45512ef1f0ffSBarry Smith Level: Developer 45522ef1f0ffSBarry Smith 45537ee59b9bSJunchao Zhang Notes: 45542ef1f0ffSBarry Smith Any of the output parameters can be `NULL`, in which case the corresponding value is not returned. 45557ee59b9bSJunchao Zhang If mat is a device matrix, the arrays are on the device. Otherwise, they are on the host. 45567ee59b9bSJunchao Zhang 45577ee59b9bSJunchao Zhang One can call this routine on a preallocated but not assembled matrix to just get the memory of the CSR underneath the matrix. 45582ef1f0ffSBarry Smith If the matrix is assembled, the data array `a` is guaranteed to have the latest values of the matrix. 45597ee59b9bSJunchao Zhang 45602ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 45617ee59b9bSJunchao Zhang @*/ 4562d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJGetCSRAndMemType(Mat mat, const PetscInt **i, const PetscInt **j, PetscScalar **a, PetscMemType *mtype) 4563d71ae5a4SJacob Faibussowitsch { 45647ee59b9bSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 45657ee59b9bSJunchao Zhang 45667ee59b9bSJunchao Zhang PetscFunctionBegin; 45677ee59b9bSJunchao Zhang PetscCheck(mat->preallocated, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "matrix is not preallocated"); 45687ee59b9bSJunchao Zhang if (aij->ops->getcsrandmemtype) { 45697ee59b9bSJunchao Zhang PetscCall((*aij->ops->getcsrandmemtype)(mat, i, j, a, mtype)); 45707ee59b9bSJunchao Zhang } else { 45717ee59b9bSJunchao Zhang if (i) *i = aij->i; 45727ee59b9bSJunchao Zhang if (j) *j = aij->j; 45737ee59b9bSJunchao Zhang if (a) *a = aij->a; 45747ee59b9bSJunchao Zhang if (mtype) *mtype = PETSC_MEMTYPE_HOST; 45757ee59b9bSJunchao Zhang } 45763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 45777ee59b9bSJunchao Zhang } 45787ee59b9bSJunchao Zhang 45797ee59b9bSJunchao Zhang /*@C 458021e72a00SBarry Smith MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row 458121e72a00SBarry Smith 458221e72a00SBarry Smith Not Collective 458321e72a00SBarry Smith 458421e72a00SBarry Smith Input Parameter: 458511a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 458621e72a00SBarry Smith 458721e72a00SBarry Smith Output Parameter: 458821e72a00SBarry Smith . nz - the maximum number of nonzeros in any row 458921e72a00SBarry Smith 459021e72a00SBarry Smith Level: intermediate 459121e72a00SBarry Smith 45922ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()` 459321e72a00SBarry Smith @*/ 4594d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJGetMaxRowNonzeros(Mat A, PetscInt *nz) 4595d71ae5a4SJacob Faibussowitsch { 459621e72a00SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 459721e72a00SBarry Smith 459821e72a00SBarry Smith PetscFunctionBegin; 459921e72a00SBarry Smith *nz = aij->rmax; 46003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 460121e72a00SBarry Smith } 460221e72a00SBarry Smith 4603*2c4ab24aSJunchao Zhang static PetscErrorCode MatCOOStructDestroy_SeqAIJ(void *data) 4604*2c4ab24aSJunchao Zhang { 4605*2c4ab24aSJunchao Zhang MatCOOStruct_SeqAIJ *coo = (MatCOOStruct_SeqAIJ *)data; 4606*2c4ab24aSJunchao Zhang PetscFunctionBegin; 4607*2c4ab24aSJunchao Zhang PetscCall(PetscFree(coo->perm)); 4608*2c4ab24aSJunchao Zhang PetscCall(PetscFree(coo->jmap)); 4609*2c4ab24aSJunchao Zhang PetscCall(PetscFree(coo)); 4610*2c4ab24aSJunchao Zhang PetscFunctionReturn(PETSC_SUCCESS); 4611*2c4ab24aSJunchao Zhang } 4612*2c4ab24aSJunchao Zhang 4613d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[]) 4614d71ae5a4SJacob Faibussowitsch { 4615394ed5ebSJunchao Zhang MPI_Comm comm; 4616394ed5ebSJunchao Zhang PetscInt *i, *j; 4617394ed5ebSJunchao Zhang PetscInt M, N, row; 4618394ed5ebSJunchao Zhang PetscCount k, p, q, nneg, nnz, start, end; /* Index the coo array, so use PetscCount as their type */ 4619394ed5ebSJunchao Zhang PetscInt *Ai; /* Change to PetscCount once we use it for row pointers */ 4620394ed5ebSJunchao Zhang PetscInt *Aj; 4621394ed5ebSJunchao Zhang PetscScalar *Aa; 4622cbc6b225SStefano Zampini Mat_SeqAIJ *seqaij = (Mat_SeqAIJ *)(mat->data); 4623cbc6b225SStefano Zampini MatType rtype; 4624394ed5ebSJunchao Zhang PetscCount *perm, *jmap; 4625*2c4ab24aSJunchao Zhang PetscContainer container; 4626*2c4ab24aSJunchao Zhang MatCOOStruct_SeqAIJ *coo; 4627394ed5ebSJunchao Zhang 4628394ed5ebSJunchao Zhang PetscFunctionBegin; 46299566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 46309566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &M, &N)); 4631e8729f6fSJunchao Zhang i = coo_i; 4632e8729f6fSJunchao Zhang j = coo_j; 46339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n, &perm)); 4634394ed5ebSJunchao Zhang for (k = 0; k < coo_n; k++) { /* Ignore entries with negative row or col indices */ 4635394ed5ebSJunchao Zhang if (j[k] < 0) i[k] = -1; 4636394ed5ebSJunchao Zhang perm[k] = k; 4637394ed5ebSJunchao Zhang } 4638394ed5ebSJunchao Zhang 4639394ed5ebSJunchao Zhang /* Sort by row */ 46409566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithIntCountArrayPair(coo_n, i, j, perm)); 46419371c9d4SSatish Balay for (k = 0; k < coo_n; k++) { 46429371c9d4SSatish Balay if (i[k] >= 0) break; 46439371c9d4SSatish Balay } /* Advance k to the first row with a non-negative index */ 4644394ed5ebSJunchao Zhang nneg = k; 46459566063dSJacob 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 */ 4646394ed5ebSJunchao Zhang nnz = 0; /* Total number of unique nonzeros to be counted */ 464735cb6cd3SPierre Jolivet jmap++; /* Inc jmap by 1 for convenience */ 4648394ed5ebSJunchao Zhang 46499566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(M + 1, &Ai)); /* CSR of A */ 46509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n - nneg, &Aj)); /* We have at most coo_n-nneg unique nonzeros */ 4651394ed5ebSJunchao Zhang 4652394ed5ebSJunchao Zhang /* In each row, sort by column, then unique column indices to get row length */ 465335cb6cd3SPierre Jolivet Ai++; /* Inc by 1 for convenience */ 4654394ed5ebSJunchao Zhang q = 0; /* q-th unique nonzero, with q starting from 0 */ 4655394ed5ebSJunchao Zhang while (k < coo_n) { 4656394ed5ebSJunchao Zhang row = i[k]; 4657394ed5ebSJunchao Zhang start = k; /* [start,end) indices for this row */ 4658394ed5ebSJunchao Zhang while (k < coo_n && i[k] == row) k++; 4659394ed5ebSJunchao Zhang end = k; 46609566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithCountArray(end - start, j + start, perm + start)); 4661394ed5ebSJunchao Zhang /* Find number of unique col entries in this row */ 4662394ed5ebSJunchao Zhang Aj[q] = j[start]; /* Log the first nonzero in this row */ 4663394ed5ebSJunchao Zhang jmap[q] = 1; /* Number of repeats of this nozero entry */ 4664394ed5ebSJunchao Zhang Ai[row] = 1; 4665394ed5ebSJunchao Zhang nnz++; 4666394ed5ebSJunchao Zhang 4667394ed5ebSJunchao Zhang for (p = start + 1; p < end; p++) { /* Scan remaining nonzero in this row */ 4668394ed5ebSJunchao Zhang if (j[p] != j[p - 1]) { /* Meet a new nonzero */ 4669394ed5ebSJunchao Zhang q++; 4670394ed5ebSJunchao Zhang jmap[q] = 1; 4671394ed5ebSJunchao Zhang Aj[q] = j[p]; 4672394ed5ebSJunchao Zhang Ai[row]++; 4673394ed5ebSJunchao Zhang nnz++; 4674394ed5ebSJunchao Zhang } else { 4675394ed5ebSJunchao Zhang jmap[q]++; 4676394ed5ebSJunchao Zhang } 4677394ed5ebSJunchao Zhang } 4678394ed5ebSJunchao Zhang q++; /* Move to next row and thus next unique nonzero */ 4679394ed5ebSJunchao Zhang } 4680394ed5ebSJunchao Zhang 4681394ed5ebSJunchao Zhang Ai--; /* Back to the beginning of Ai[] */ 4682394ed5ebSJunchao Zhang for (k = 0; k < M; k++) Ai[k + 1] += Ai[k]; 4683394ed5ebSJunchao Zhang jmap--; /* Back to the beginning of jmap[] */ 4684394ed5ebSJunchao Zhang jmap[0] = 0; 4685394ed5ebSJunchao Zhang for (k = 0; k < nnz; k++) jmap[k + 1] += jmap[k]; 4686394ed5ebSJunchao Zhang if (nnz < coo_n - nneg) { /* Realloc with actual number of unique nonzeros */ 4687394ed5ebSJunchao Zhang PetscCount *jmap_new; 4688394ed5ebSJunchao Zhang PetscInt *Aj_new; 4689394ed5ebSJunchao Zhang 46909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz + 1, &jmap_new)); 46919566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(jmap_new, jmap, nnz + 1)); 46929566063dSJacob Faibussowitsch PetscCall(PetscFree(jmap)); 4693394ed5ebSJunchao Zhang jmap = jmap_new; 4694394ed5ebSJunchao Zhang 46959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &Aj_new)); 46969566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(Aj_new, Aj, nnz)); 46979566063dSJacob Faibussowitsch PetscCall(PetscFree(Aj)); 4698394ed5ebSJunchao Zhang Aj = Aj_new; 4699394ed5ebSJunchao Zhang } 4700394ed5ebSJunchao Zhang 4701394ed5ebSJunchao Zhang if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */ 4702394ed5ebSJunchao Zhang PetscCount *perm_new; 4703cbc6b225SStefano Zampini 47049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n - nneg, &perm_new)); 47059566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(perm_new, perm + nneg, coo_n - nneg)); 47069566063dSJacob Faibussowitsch PetscCall(PetscFree(perm)); 4707394ed5ebSJunchao Zhang perm = perm_new; 4708394ed5ebSJunchao Zhang } 4709394ed5ebSJunchao Zhang 47109566063dSJacob Faibussowitsch PetscCall(MatGetRootType_Private(mat, &rtype)); 47119566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nnz, &Aa)); /* Zero the matrix */ 47129566063dSJacob Faibussowitsch PetscCall(MatSetSeqAIJWithArrays_private(PETSC_COMM_SELF, M, N, Ai, Aj, Aa, rtype, mat)); 4713394ed5ebSJunchao Zhang 4714394ed5ebSJunchao Zhang seqaij->singlemalloc = PETSC_FALSE; /* Ai, Aj and Aa are not allocated in one big malloc */ 4715394ed5ebSJunchao Zhang seqaij->free_a = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */ 4716*2c4ab24aSJunchao Zhang 4717*2c4ab24aSJunchao Zhang // Put the COO struct in a container and then attach that to the matrix 4718*2c4ab24aSJunchao Zhang PetscCall(PetscMalloc1(1, &coo)); 4719*2c4ab24aSJunchao Zhang coo->nz = nnz; 4720*2c4ab24aSJunchao Zhang coo->n = coo_n; 4721*2c4ab24aSJunchao Zhang coo->Atot = coo_n - nneg; // Annz is seqaij->nz, so no need to record that again 4722*2c4ab24aSJunchao Zhang coo->jmap = jmap; // of length nnz+1 4723*2c4ab24aSJunchao Zhang coo->perm = perm; 4724*2c4ab24aSJunchao Zhang PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 4725*2c4ab24aSJunchao Zhang PetscCall(PetscContainerSetPointer(container, coo)); 4726*2c4ab24aSJunchao Zhang PetscCall(PetscContainerSetUserDestroy(container, MatCOOStructDestroy_SeqAIJ)); 4727*2c4ab24aSJunchao Zhang PetscCall(PetscObjectCompose((PetscObject)mat, "__PETSc_MatCOOStruct_Host", (PetscObject)container)); 4728*2c4ab24aSJunchao Zhang PetscCall(PetscContainerDestroy(&container)); 47293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4730394ed5ebSJunchao Zhang } 4731394ed5ebSJunchao Zhang 4732d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A, const PetscScalar v[], InsertMode imode) 4733d71ae5a4SJacob Faibussowitsch { 4734394ed5ebSJunchao Zhang Mat_SeqAIJ *aseq = (Mat_SeqAIJ *)A->data; 4735394ed5ebSJunchao Zhang PetscCount i, j, Annz = aseq->nz; 4736*2c4ab24aSJunchao Zhang PetscCount *perm, *jmap; 4737394ed5ebSJunchao Zhang PetscScalar *Aa; 4738*2c4ab24aSJunchao Zhang PetscContainer container; 4739*2c4ab24aSJunchao Zhang MatCOOStruct_SeqAIJ *coo; 4740394ed5ebSJunchao Zhang 4741394ed5ebSJunchao Zhang PetscFunctionBegin; 4742*2c4ab24aSJunchao Zhang PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_MatCOOStruct_Host", (PetscObject *)&container)); 4743*2c4ab24aSJunchao Zhang PetscCheck(container, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not found MatCOOStruct on this matrix"); 4744*2c4ab24aSJunchao Zhang PetscCall(PetscContainerGetPointer(container, (void **)&coo)); 4745*2c4ab24aSJunchao Zhang perm = coo->perm; 4746*2c4ab24aSJunchao Zhang jmap = coo->jmap; 47479566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &Aa)); 4748394ed5ebSJunchao Zhang for (i = 0; i < Annz; i++) { 4749b6c38306SJunchao Zhang PetscScalar sum = 0.0; 4750b6c38306SJunchao Zhang for (j = jmap[i]; j < jmap[i + 1]; j++) sum += v[perm[j]]; 4751b6c38306SJunchao Zhang Aa[i] = (imode == INSERT_VALUES ? 0.0 : Aa[i]) + sum; 4752394ed5ebSJunchao Zhang } 47539566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &Aa)); 47543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4755394ed5ebSJunchao Zhang } 4756394ed5ebSJunchao Zhang 475734b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 47585063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat, MatType, MatReuse, Mat *); 475902fe1965SBarry Smith #endif 4760d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_HIP) 4761d5e393b6SSuyash Tandon PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJHIPSPARSE(Mat, MatType, MatReuse, Mat *); 4762d5e393b6SSuyash Tandon #endif 47633d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 47645063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat, MatType, MatReuse, Mat *); 47653d0639e7SStefano Zampini #endif 476602fe1965SBarry Smith 4767d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B) 4768d71ae5a4SJacob Faibussowitsch { 4769273d9f13SBarry Smith Mat_SeqAIJ *b; 477038baddfdSBarry Smith PetscMPIInt size; 4771273d9f13SBarry Smith 4772273d9f13SBarry Smith PetscFunctionBegin; 47739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size)); 477408401ef6SPierre Jolivet PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Comm must be of size 1"); 4775273d9f13SBarry Smith 47764dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&b)); 47772205254eSKarl Rupp 4778b0a32e0cSBarry Smith B->data = (void *)b; 47792205254eSKarl Rupp 47809566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(B->ops, &MatOps_Values, sizeof(struct _MatOps))); 4781071fcb05SBarry Smith if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 47822205254eSKarl Rupp 4783f4259b30SLisandro Dalcin b->row = NULL; 4784f4259b30SLisandro Dalcin b->col = NULL; 4785f4259b30SLisandro Dalcin b->icol = NULL; 4786b810aeb4SBarry Smith b->reallocs = 0; 478736db0b34SBarry Smith b->ignorezeroentries = PETSC_FALSE; 4788f1e2ffcdSBarry Smith b->roworiented = PETSC_TRUE; 4789416022c9SBarry Smith b->nonew = 0; 4790f4259b30SLisandro Dalcin b->diag = NULL; 4791f4259b30SLisandro Dalcin b->solve_work = NULL; 4792f4259b30SLisandro Dalcin B->spptr = NULL; 4793f4259b30SLisandro Dalcin b->saved_values = NULL; 4794f4259b30SLisandro Dalcin b->idiag = NULL; 4795f4259b30SLisandro Dalcin b->mdiag = NULL; 4796f4259b30SLisandro Dalcin b->ssor_work = NULL; 479771f1c65dSBarry Smith b->omega = 1.0; 479871f1c65dSBarry Smith b->fshift = 0.0; 479971f1c65dSBarry Smith b->idiagvalid = PETSC_FALSE; 4800bbead8a2SBarry Smith b->ibdiagvalid = PETSC_FALSE; 4801a9817697SBarry Smith b->keepnonzeropattern = PETSC_FALSE; 480217ab2063SBarry Smith 48039566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ)); 4804d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB) 48059566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEnginePut_C", MatlabEnginePut_SeqAIJ)); 48069566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEngineGet_C", MatlabEngineGet_SeqAIJ)); 4807b3866ffcSBarry Smith #endif 48089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetColumnIndices_C", MatSeqAIJSetColumnIndices_SeqAIJ)); 48099566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqAIJ)); 48109566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqAIJ)); 48119566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsbaij_C", MatConvert_SeqAIJ_SeqSBAIJ)); 48129566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqbaij_C", MatConvert_SeqAIJ_SeqBAIJ)); 48139566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijperm_C", MatConvert_SeqAIJ_SeqAIJPERM)); 48149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijsell_C", MatConvert_SeqAIJ_SeqAIJSELL)); 48159779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 48169566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijmkl_C", MatConvert_SeqAIJ_SeqAIJMKL)); 4817191b95cbSRichard Tran Mills #endif 481834b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 48199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcusparse_C", MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 48209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_seqaij_C", MatProductSetFromOptions_SeqAIJ)); 48219566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaijcusparse_C", MatProductSetFromOptions_SeqAIJ)); 482202fe1965SBarry Smith #endif 4823d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_HIP) 4824d5e393b6SSuyash Tandon PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijhipsparse_C", MatConvert_SeqAIJ_SeqAIJHIPSPARSE)); 4825d5e393b6SSuyash Tandon PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijhipsparse_seqaij_C", MatProductSetFromOptions_SeqAIJ)); 4826d5e393b6SSuyash Tandon PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaijhipsparse_C", MatProductSetFromOptions_SeqAIJ)); 4827d5e393b6SSuyash Tandon #endif 48283d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 48299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijkokkos_C", MatConvert_SeqAIJ_SeqAIJKokkos)); 48303d0639e7SStefano Zampini #endif 48319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcrl_C", MatConvert_SeqAIJ_SeqAIJCRL)); 4832af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 48339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_elemental_C", MatConvert_SeqAIJ_Elemental)); 4834af8000cdSHong Zhang #endif 4835d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 48369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_scalapack_C", MatConvert_AIJ_ScaLAPACK)); 4837d24d4204SJose E. Roman #endif 483863c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 48399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_hypre_C", MatConvert_AIJ_HYPRE)); 48409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_transpose_seqaij_seqaij_C", MatProductSetFromOptions_Transpose_AIJ_AIJ)); 484163c07aadSStefano Zampini #endif 48429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqdense_C", MatConvert_SeqAIJ_SeqDense)); 48439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsell_C", MatConvert_SeqAIJ_SeqSELL)); 48449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_is_C", MatConvert_XAIJ_IS)); 48459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsTranspose_C", MatIsTranspose_SeqAIJ)); 48469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsHermitianTranspose_C", MatIsTranspose_SeqAIJ)); 48479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocation_C", MatSeqAIJSetPreallocation_SeqAIJ)); 48489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatResetPreallocation_C", MatResetPreallocation_SeqAIJ)); 48499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocationCSR_C", MatSeqAIJSetPreallocationCSR_SeqAIJ)); 48509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatReorderForNonzeroDiagonal_C", MatReorderForNonzeroDiagonal_SeqAIJ)); 48519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_is_seqaij_C", MatProductSetFromOptions_IS_XAIJ)); 48529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqaij_C", MatProductSetFromOptions_SeqDense_SeqAIJ)); 48539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaij_C", MatProductSetFromOptions_SeqAIJ)); 48549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJKron_C", MatSeqAIJKron_SeqAIJ)); 48559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_SeqAIJ)); 48569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_SeqAIJ)); 48579566063dSJacob Faibussowitsch PetscCall(MatCreate_SeqAIJ_Inode(B)); 48589566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ)); 48599566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetTypeFromOptions(B)); /* this allows changing the matrix subtype to say MATSEQAIJPERM */ 48603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 486117ab2063SBarry Smith } 486217ab2063SBarry Smith 4863b24902e0SBarry Smith /* 48643893b582SJunchao Zhang Given a matrix generated with MatGetFactor() duplicates all the information in A into C 4865b24902e0SBarry Smith */ 4866d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C, Mat A, MatDuplicateOption cpvalues, PetscBool mallocmatspace) 4867d71ae5a4SJacob Faibussowitsch { 48682a350339SBarry Smith Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data, *a = (Mat_SeqAIJ *)A->data; 4869071fcb05SBarry Smith PetscInt m = A->rmap->n, i; 487017ab2063SBarry Smith 48713a40ed3dSBarry Smith PetscFunctionBegin; 4872aed4548fSBarry Smith PetscCheck(A->assembled || cpvalues == MAT_DO_NOT_COPY_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix"); 4873273d9f13SBarry Smith 4874d5f3da31SBarry Smith C->factortype = A->factortype; 4875f4259b30SLisandro Dalcin c->row = NULL; 4876f4259b30SLisandro Dalcin c->col = NULL; 4877f4259b30SLisandro Dalcin c->icol = NULL; 48786ad4291fSHong Zhang c->reallocs = 0; 487917ab2063SBarry Smith 488069272f91SPierre Jolivet C->assembled = A->assembled; 488117ab2063SBarry Smith 488269272f91SPierre Jolivet if (A->preallocated) { 48839566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->rmap, &C->rmap)); 48849566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->cmap, &C->cmap)); 4885eec197d1SBarry Smith 488631fe6a7dSBarry Smith if (!A->hash_active) { 48879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &c->imax)); 48889566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->imax, a->imax, m * sizeof(PetscInt))); 48899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &c->ilen)); 48909566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->ilen, a->ilen, m * sizeof(PetscInt))); 489117ab2063SBarry Smith 489217ab2063SBarry Smith /* allocate the matrix space */ 4893f77e22a1SHong Zhang if (mallocmatspace) { 48949566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(a->i[m], &c->a, a->i[m], &c->j, m + 1, &c->i)); 48952205254eSKarl Rupp 4896f1e2ffcdSBarry Smith c->singlemalloc = PETSC_TRUE; 48972205254eSKarl Rupp 48989566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->i, a->i, m + 1)); 489917ab2063SBarry Smith if (m > 0) { 49009566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->j, a->j, a->i[m])); 4901be6bf707SBarry Smith if (cpvalues == MAT_COPY_VALUES) { 49022e5835c6SStefano Zampini const PetscScalar *aa; 49032e5835c6SStefano Zampini 49049566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 49059566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->a, aa, a->i[m])); 49069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 4907be6bf707SBarry Smith } else { 49089566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->a, a->i[m])); 490917ab2063SBarry Smith } 491008480c60SBarry Smith } 4911f77e22a1SHong Zhang } 491231fe6a7dSBarry Smith C->preallocated = PETSC_TRUE; 491331fe6a7dSBarry Smith } else { 491431fe6a7dSBarry Smith PetscCheck(mallocmatspace, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Cannot malloc matrix memory from a non-preallocated matrix"); 491531fe6a7dSBarry Smith PetscCall(MatSetUp(C)); 491631fe6a7dSBarry Smith } 491717ab2063SBarry Smith 49186ad4291fSHong Zhang c->ignorezeroentries = a->ignorezeroentries; 4919416022c9SBarry Smith c->roworiented = a->roworiented; 4920416022c9SBarry Smith c->nonew = a->nonew; 4921416022c9SBarry Smith if (a->diag) { 49229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &c->diag)); 49239566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->diag, a->diag, m * sizeof(PetscInt))); 4924071fcb05SBarry Smith } else c->diag = NULL; 49252205254eSKarl Rupp 4926f4259b30SLisandro Dalcin c->solve_work = NULL; 4927f4259b30SLisandro Dalcin c->saved_values = NULL; 4928f4259b30SLisandro Dalcin c->idiag = NULL; 4929f4259b30SLisandro Dalcin c->ssor_work = NULL; 4930a9817697SBarry Smith c->keepnonzeropattern = a->keepnonzeropattern; 4931e6b907acSBarry Smith c->free_a = PETSC_TRUE; 4932e6b907acSBarry Smith c->free_ij = PETSC_TRUE; 49336ad4291fSHong Zhang 4934893ad86cSHong Zhang c->rmax = a->rmax; 4935416022c9SBarry Smith c->nz = a->nz; 49368ed568f8SMatthew G Knepley c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 4937754ec7b1SSatish Balay 49386ad4291fSHong Zhang c->compressedrow.use = a->compressedrow.use; 49396ad4291fSHong Zhang c->compressedrow.nrows = a->compressedrow.nrows; 4940cd6b891eSBarry Smith if (a->compressedrow.use) { 49416ad4291fSHong Zhang i = a->compressedrow.nrows; 49429566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i + 1, &c->compressedrow.i, i, &c->compressedrow.rindex)); 49439566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.i, a->compressedrow.i, i + 1)); 49449566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.rindex, a->compressedrow.rindex, i)); 494527ea64f8SHong Zhang } else { 494627ea64f8SHong Zhang c->compressedrow.use = PETSC_FALSE; 49470298fd71SBarry Smith c->compressedrow.i = NULL; 49480298fd71SBarry Smith c->compressedrow.rindex = NULL; 49496ad4291fSHong Zhang } 4950ea632784SBarry Smith c->nonzerorowcnt = a->nonzerorowcnt; 4951e56f5c9eSBarry Smith C->nonzerostate = A->nonzerostate; 49524846f1f5SKris Buschelman 49539566063dSJacob Faibussowitsch PetscCall(MatDuplicate_SeqAIJ_Inode(A, cpvalues, &C)); 495469272f91SPierre Jolivet } 49559566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist)); 49563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 495717ab2063SBarry Smith } 495817ab2063SBarry Smith 4959d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B) 4960d71ae5a4SJacob Faibussowitsch { 4961b24902e0SBarry Smith PetscFunctionBegin; 49629566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 49639566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n)); 496448a46eb9SPierre Jolivet if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) PetscCall(MatSetBlockSizesFromMats(*B, A, A)); 49659566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, ((PetscObject)A)->type_name)); 49669566063dSJacob Faibussowitsch PetscCall(MatDuplicateNoCreate_SeqAIJ(*B, A, cpvalues, PETSC_TRUE)); 49673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4968b24902e0SBarry Smith } 4969b24902e0SBarry Smith 4970d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer) 4971d71ae5a4SJacob Faibussowitsch { 497252f91c60SVaclav Hapla PetscBool isbinary, ishdf5; 497352f91c60SVaclav Hapla 497452f91c60SVaclav Hapla PetscFunctionBegin; 497552f91c60SVaclav Hapla PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1); 497652f91c60SVaclav Hapla PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 4977c27b3999SVaclav Hapla /* force binary viewer to load .info file if it has not yet done so */ 49789566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 49799566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 49809566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 498152f91c60SVaclav Hapla if (isbinary) { 49829566063dSJacob Faibussowitsch PetscCall(MatLoad_SeqAIJ_Binary(newMat, viewer)); 498352f91c60SVaclav Hapla } else if (ishdf5) { 498452f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5) 49859566063dSJacob Faibussowitsch PetscCall(MatLoad_AIJ_HDF5(newMat, viewer)); 498652f91c60SVaclav Hapla #else 498752f91c60SVaclav Hapla SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 498852f91c60SVaclav Hapla #endif 498952f91c60SVaclav Hapla } else { 499098921bdaSJacob 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); 499152f91c60SVaclav Hapla } 49923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 499352f91c60SVaclav Hapla } 499452f91c60SVaclav Hapla 4995d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer) 4996d71ae5a4SJacob Faibussowitsch { 49973ea6fe3dSLisandro Dalcin Mat_SeqAIJ *a = (Mat_SeqAIJ *)mat->data; 49983ea6fe3dSLisandro Dalcin PetscInt header[4], *rowlens, M, N, nz, sum, rows, cols, i; 4999fbdbba38SShri Abhyankar 5000fbdbba38SShri Abhyankar PetscFunctionBegin; 50019566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 5002bbead8a2SBarry Smith 50033ea6fe3dSLisandro Dalcin /* read in matrix header */ 50049566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT)); 500508401ef6SPierre Jolivet PetscCheck(header[0] == MAT_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file"); 50069371c9d4SSatish Balay M = header[1]; 50079371c9d4SSatish Balay N = header[2]; 50089371c9d4SSatish Balay nz = header[3]; 500908401ef6SPierre Jolivet PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M); 501008401ef6SPierre Jolivet PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N); 501108401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Matrix stored in special format on disk, cannot load as SeqAIJ"); 5012fbdbba38SShri Abhyankar 50133ea6fe3dSLisandro Dalcin /* set block sizes from the viewer's .info file */ 50149566063dSJacob Faibussowitsch PetscCall(MatLoad_Binary_BlockSizes(mat, viewer)); 50153ea6fe3dSLisandro Dalcin /* set local and global sizes if not set already */ 50163ea6fe3dSLisandro Dalcin if (mat->rmap->n < 0) mat->rmap->n = M; 50173ea6fe3dSLisandro Dalcin if (mat->cmap->n < 0) mat->cmap->n = N; 50183ea6fe3dSLisandro Dalcin if (mat->rmap->N < 0) mat->rmap->N = M; 50193ea6fe3dSLisandro Dalcin if (mat->cmap->N < 0) mat->cmap->N = N; 50209566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->rmap)); 50219566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->cmap)); 50223ea6fe3dSLisandro Dalcin 50233ea6fe3dSLisandro Dalcin /* check if the matrix sizes are correct */ 50249566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 5025aed4548fSBarry 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); 50263ea6fe3dSLisandro Dalcin 5027fbdbba38SShri Abhyankar /* read in row lengths */ 50289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(M, &rowlens)); 50299566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, rowlens, M, NULL, PETSC_INT)); 50303ea6fe3dSLisandro Dalcin /* check if sum(rowlens) is same as nz */ 50319371c9d4SSatish Balay sum = 0; 50329371c9d4SSatish Balay for (i = 0; i < M; i++) sum += rowlens[i]; 503308401ef6SPierre 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); 50343ea6fe3dSLisandro Dalcin /* preallocate and check sizes */ 50359566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(mat, 0, rowlens)); 50369566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 5037aed4548fSBarry 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); 50383ea6fe3dSLisandro Dalcin /* store row lengths */ 50399566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->ilen, rowlens, M)); 50409566063dSJacob Faibussowitsch PetscCall(PetscFree(rowlens)); 5041fbdbba38SShri Abhyankar 50423ea6fe3dSLisandro Dalcin /* fill in "i" row pointers */ 50439371c9d4SSatish Balay a->i[0] = 0; 50449371c9d4SSatish Balay for (i = 0; i < M; i++) a->i[i + 1] = a->i[i] + a->ilen[i]; 50453ea6fe3dSLisandro Dalcin /* read in "j" column indices */ 50469566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, a->j, nz, NULL, PETSC_INT)); 50473ea6fe3dSLisandro Dalcin /* read in "a" nonzero values */ 50489566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, a->a, nz, NULL, PETSC_SCALAR)); 5049fbdbba38SShri Abhyankar 50509566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 50519566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 50523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5053fbdbba38SShri Abhyankar } 5054fbdbba38SShri Abhyankar 5055d71ae5a4SJacob Faibussowitsch PetscErrorCode MatEqual_SeqAIJ(Mat A, Mat B, PetscBool *flg) 5056d71ae5a4SJacob Faibussowitsch { 50577264ac53SSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data, *b = (Mat_SeqAIJ *)B->data; 5058fff043a9SJunchao Zhang const PetscScalar *aa, *ba; 5059eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 5060eeffb40dSHong Zhang PetscInt k; 5061eeffb40dSHong Zhang #endif 50627264ac53SSatish Balay 50633a40ed3dSBarry Smith PetscFunctionBegin; 5064bfeeae90SHong Zhang /* If the matrix dimensions are not equal,or no of nonzeros */ 5065d0f46423SBarry Smith if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) || (a->nz != b->nz)) { 5066ca44d042SBarry Smith *flg = PETSC_FALSE; 50673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5068bcd2baecSBarry Smith } 50697264ac53SSatish Balay 50707264ac53SSatish Balay /* if the a->i are the same */ 50719566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->i, b->i, A->rmap->n + 1, flg)); 50723ba16761SJacob Faibussowitsch if (!*flg) PetscFunctionReturn(PETSC_SUCCESS); 50737264ac53SSatish Balay 50747264ac53SSatish Balay /* if a->j are the same */ 50759566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->j, b->j, a->nz, flg)); 50763ba16761SJacob Faibussowitsch if (!*flg) PetscFunctionReturn(PETSC_SUCCESS); 5077bcd2baecSBarry Smith 50789566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 50799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &ba)); 5080bcd2baecSBarry Smith /* if a->a are the same */ 5081eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 5082eeffb40dSHong Zhang for (k = 0; k < a->nz; k++) { 5083fff043a9SJunchao Zhang if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) { 5084eeffb40dSHong Zhang *flg = PETSC_FALSE; 50853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5086eeffb40dSHong Zhang } 5087eeffb40dSHong Zhang } 5088eeffb40dSHong Zhang #else 50899566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(aa, ba, a->nz, flg)); 5090eeffb40dSHong Zhang #endif 50919566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 50929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &ba)); 50933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50947264ac53SSatish Balay } 509536db0b34SBarry Smith 509605869f15SSatish Balay /*@ 509711a5261eSBarry Smith MatCreateSeqAIJWithArrays - Creates an sequential `MATSEQAIJ` matrix using matrix elements (in CSR format) 509836db0b34SBarry Smith provided by the user. 509936db0b34SBarry Smith 5100d083f849SBarry Smith Collective 510136db0b34SBarry Smith 510236db0b34SBarry Smith Input Parameters: 510336db0b34SBarry Smith + comm - must be an MPI communicator of size 1 510436db0b34SBarry Smith . m - number of rows 510536db0b34SBarry Smith . n - number of columns 5106483a2f95SBarry Smith . i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 510736db0b34SBarry Smith . j - column indices 510836db0b34SBarry Smith - a - matrix values 510936db0b34SBarry Smith 511036db0b34SBarry Smith Output Parameter: 511136db0b34SBarry Smith . mat - the matrix 511236db0b34SBarry Smith 511336db0b34SBarry Smith Level: intermediate 511436db0b34SBarry Smith 511536db0b34SBarry Smith Notes: 51162ef1f0ffSBarry Smith The `i`, `j`, and `a` arrays are not copied by this routine, the user must free these arrays 5117292fb18eSBarry Smith once the matrix is destroyed and not before 511836db0b34SBarry Smith 511936db0b34SBarry Smith You cannot set new nonzero locations into this matrix, that will generate an error. 512036db0b34SBarry Smith 51212ef1f0ffSBarry Smith The `i` and `j` indices are 0 based 512236db0b34SBarry Smith 5123a4552177SSatish Balay The format which is used for the sparse matrix input, is equivalent to a 5124a4552177SSatish Balay row-major ordering.. i.e for the following matrix, the input data expected is 51258eef79e4SBarry Smith as shown 51262ef1f0ffSBarry Smith .vb 51272ef1f0ffSBarry Smith 1 0 0 51282ef1f0ffSBarry Smith 2 0 3 51292ef1f0ffSBarry Smith 4 5 6 5130a4552177SSatish Balay 51312ef1f0ffSBarry Smith i = {0,1,3,6} [size = nrow+1 = 3+1] 51322ef1f0ffSBarry Smith j = {0,0,2,0,1,2} [size = 6]; values must be sorted for each row 51332ef1f0ffSBarry Smith v = {1,2,3,4,5,6} [size = 6] 51342ef1f0ffSBarry Smith .ve 5135a4552177SSatish Balay 51362ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateMPIAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()` 513736db0b34SBarry Smith @*/ 5138d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat) 5139d71ae5a4SJacob Faibussowitsch { 5140cbcfb4deSHong Zhang PetscInt ii; 514136db0b34SBarry Smith Mat_SeqAIJ *aij; 5142cbcfb4deSHong Zhang PetscInt jj; 514336db0b34SBarry Smith 514436db0b34SBarry Smith PetscFunctionBegin; 5145aed4548fSBarry Smith PetscCheck(m <= 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0"); 51469566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 51479566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 51489566063dSJacob Faibussowitsch /* PetscCall(MatSetBlockSizes(*mat,,)); */ 51499566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQAIJ)); 51509566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, MAT_SKIP_ALLOCATION, NULL)); 5151ab93d7beSBarry Smith aij = (Mat_SeqAIJ *)(*mat)->data; 51529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &aij->imax)); 51539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &aij->ilen)); 5154ab93d7beSBarry Smith 515536db0b34SBarry Smith aij->i = i; 515636db0b34SBarry Smith aij->j = j; 515736db0b34SBarry Smith aij->a = a; 515836db0b34SBarry Smith aij->singlemalloc = PETSC_FALSE; 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]); 5176aed4548fSBarry Smith PetscCheck(j[ii] <= n - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column index to large at location = %" PetscInt_FMT " index = %" PetscInt_FMT, ii, j[ii]); 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 52172ef1f0ffSBarry Smith Note: 5218d7547e51SJunchao Zhang Instead of using this function, users should also consider `MatSetPreallocationCOO()` and `MatSetValuesCOO()`, which allow repeated or remote entries, 5219d7547e51SJunchao Zhang and are particularly useful in iterative applications. 52208a0b0e6bSVictor Minden 52212ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateSeqAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()`, `MatSetValuesCOO()`, `MatSetPreallocationCOO()` 52228a0b0e6bSVictor Minden @*/ 5223d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat, PetscInt nz, PetscBool idx) 5224d71ae5a4SJacob Faibussowitsch { 5225d021a1c5SVictor Minden PetscInt ii, *nnz, one = 1, row, col; 52268a0b0e6bSVictor Minden 52278a0b0e6bSVictor Minden PetscFunctionBegin; 52289566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m, &nnz)); 5229ad540459SPierre Jolivet for (ii = 0; ii < nz; ii++) nnz[i[ii] - !!idx] += 1; 52309566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 52319566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 52329566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQAIJ)); 52339566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, 0, nnz)); 52341230e6d1SVictor Minden for (ii = 0; ii < nz; ii++) { 52351230e6d1SVictor Minden if (idx) { 52361230e6d1SVictor Minden row = i[ii] - 1; 52371230e6d1SVictor Minden col = j[ii] - 1; 52381230e6d1SVictor Minden } else { 52391230e6d1SVictor Minden row = i[ii]; 52401230e6d1SVictor Minden col = j[ii]; 52418a0b0e6bSVictor Minden } 52429566063dSJacob Faibussowitsch PetscCall(MatSetValues(*mat, one, &row, one, &col, &a[ii], ADD_VALUES)); 52438a0b0e6bSVictor Minden } 52449566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 52459566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 52469566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 52473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52488a0b0e6bSVictor Minden } 524936db0b34SBarry Smith 5250d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A) 5251d71ae5a4SJacob Faibussowitsch { 5252acf2f550SJed Brown Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 5253acf2f550SJed Brown 5254acf2f550SJed Brown PetscFunctionBegin; 5255acf2f550SJed Brown a->idiagvalid = PETSC_FALSE; 5256acf2f550SJed Brown a->ibdiagvalid = PETSC_FALSE; 52572205254eSKarl Rupp 52589566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal_Inode(A)); 52593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5260acf2f550SJed Brown } 5261acf2f550SJed Brown 5262d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat) 5263d71ae5a4SJacob Faibussowitsch { 52649c8f2541SHong Zhang PetscFunctionBegin; 52659566063dSJacob Faibussowitsch PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm, inmat, n, scall, outmat)); 52663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52679c8f2541SHong Zhang } 52689c8f2541SHong Zhang 526981824310SBarry Smith /* 527053dd7562SDmitry Karpeev Permute A into C's *local* index space using rowemb,colemb. 527153dd7562SDmitry Karpeev The embedding are supposed to be injections and the above implies that the range of rowemb is a subset 527253dd7562SDmitry Karpeev of [0,m), colemb is in [0,n). 527353dd7562SDmitry Karpeev If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A. 527453dd7562SDmitry Karpeev */ 5275d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C, IS rowemb, IS colemb, MatStructure pattern, Mat B) 5276d71ae5a4SJacob Faibussowitsch { 527753dd7562SDmitry Karpeev /* If making this function public, change the error returned in this function away from _PLIB. */ 527853dd7562SDmitry Karpeev Mat_SeqAIJ *Baij; 527953dd7562SDmitry Karpeev PetscBool seqaij; 528053dd7562SDmitry Karpeev PetscInt m, n, *nz, i, j, count; 528153dd7562SDmitry Karpeev PetscScalar v; 528253dd7562SDmitry Karpeev const PetscInt *rowindices, *colindices; 528353dd7562SDmitry Karpeev 528453dd7562SDmitry Karpeev PetscFunctionBegin; 52853ba16761SJacob Faibussowitsch if (!B) PetscFunctionReturn(PETSC_SUCCESS); 528653dd7562SDmitry Karpeev /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */ 52879566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)B, MATSEQAIJ, &seqaij)); 528828b400f6SJacob Faibussowitsch PetscCheck(seqaij, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is of wrong type"); 528953dd7562SDmitry Karpeev if (rowemb) { 52909566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rowemb, &m)); 529108401ef6SPierre 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); 529253dd7562SDmitry Karpeev } else { 529308401ef6SPierre Jolivet PetscCheck(C->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is row-incompatible with the target matrix"); 529453dd7562SDmitry Karpeev } 529553dd7562SDmitry Karpeev if (colemb) { 52969566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(colemb, &n)); 529708401ef6SPierre 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); 529853dd7562SDmitry Karpeev } else { 529908401ef6SPierre Jolivet PetscCheck(C->cmap->n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is col-incompatible with the target matrix"); 530053dd7562SDmitry Karpeev } 530153dd7562SDmitry Karpeev 530253dd7562SDmitry Karpeev Baij = (Mat_SeqAIJ *)(B->data); 530353dd7562SDmitry Karpeev if (pattern == DIFFERENT_NONZERO_PATTERN) { 53049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n, &nz)); 5305ad540459SPierre Jolivet for (i = 0; i < B->rmap->n; i++) nz[i] = Baij->i[i + 1] - Baij->i[i]; 53069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(C, 0, nz)); 53079566063dSJacob Faibussowitsch PetscCall(PetscFree(nz)); 530853dd7562SDmitry Karpeev } 530948a46eb9SPierre Jolivet if (pattern == SUBSET_NONZERO_PATTERN) PetscCall(MatZeroEntries(C)); 531053dd7562SDmitry Karpeev count = 0; 531153dd7562SDmitry Karpeev rowindices = NULL; 531253dd7562SDmitry Karpeev colindices = NULL; 531348a46eb9SPierre Jolivet if (rowemb) PetscCall(ISGetIndices(rowemb, &rowindices)); 531448a46eb9SPierre Jolivet if (colemb) PetscCall(ISGetIndices(colemb, &colindices)); 531553dd7562SDmitry Karpeev for (i = 0; i < B->rmap->n; i++) { 531653dd7562SDmitry Karpeev PetscInt row; 531753dd7562SDmitry Karpeev row = i; 531853dd7562SDmitry Karpeev if (rowindices) row = rowindices[i]; 531953dd7562SDmitry Karpeev for (j = Baij->i[i]; j < Baij->i[i + 1]; j++) { 532053dd7562SDmitry Karpeev PetscInt col; 532153dd7562SDmitry Karpeev col = Baij->j[count]; 532253dd7562SDmitry Karpeev if (colindices) col = colindices[col]; 532353dd7562SDmitry Karpeev v = Baij->a[count]; 53249566063dSJacob Faibussowitsch PetscCall(MatSetValues(C, 1, &row, 1, &col, &v, INSERT_VALUES)); 532553dd7562SDmitry Karpeev ++count; 532653dd7562SDmitry Karpeev } 532753dd7562SDmitry Karpeev } 532853dd7562SDmitry Karpeev /* FIXME: set C's nonzerostate correctly. */ 532953dd7562SDmitry Karpeev /* Assembly for C is necessary. */ 533053dd7562SDmitry Karpeev C->preallocated = PETSC_TRUE; 533153dd7562SDmitry Karpeev C->assembled = PETSC_TRUE; 533253dd7562SDmitry Karpeev C->was_assembled = PETSC_FALSE; 53333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 533453dd7562SDmitry Karpeev } 533553dd7562SDmitry Karpeev 5336dec0b466SHong Zhang PetscErrorCode MatEliminateZeros_SeqAIJ(Mat A) 5337dec0b466SHong Zhang { 5338dec0b466SHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 5339dec0b466SHong Zhang MatScalar *aa = a->a; 5340dec0b466SHong Zhang PetscInt m = A->rmap->n, fshift = 0, fshift_prev = 0, i, k; 5341dec0b466SHong Zhang PetscInt *ailen = a->ilen, *imax = a->imax, *ai = a->i, *aj = a->j, rmax = 0; 5342dec0b466SHong Zhang 5343dec0b466SHong Zhang PetscFunctionBegin; 5344dec0b466SHong Zhang PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot eliminate zeros for unassembled matrix"); 5345dec0b466SHong Zhang if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 5346dec0b466SHong Zhang for (i = 1; i <= m; i++) { 5347dec0b466SHong Zhang /* move each nonzero entry back by the amount of zero slots (fshift) before it*/ 5348dec0b466SHong Zhang for (k = ai[i - 1]; k < ai[i]; k++) { 5349dec0b466SHong Zhang if (aa[k] == 0 && aj[k] != i - 1) fshift++; 5350dec0b466SHong Zhang else { 5351dec0b466SHong Zhang if (aa[k] == 0 && aj[k] == i - 1) PetscCall(PetscInfo(A, "Keep the diagonal zero at row %" PetscInt_FMT "\n", i - 1)); 5352dec0b466SHong Zhang aa[k - fshift] = aa[k]; 5353dec0b466SHong Zhang aj[k - fshift] = aj[k]; 5354dec0b466SHong Zhang } 5355dec0b466SHong Zhang } 5356dec0b466SHong Zhang ai[i - 1] -= fshift_prev; // safe to update ai[i-1] now since it will not be used in the next iteration 5357dec0b466SHong Zhang fshift_prev = fshift; 5358dec0b466SHong Zhang /* reset ilen and imax for each row */ 5359dec0b466SHong Zhang ailen[i - 1] = imax[i - 1] = ai[i] - fshift - ai[i - 1]; 5360dec0b466SHong Zhang a->nonzerorowcnt += ((ai[i] - fshift - ai[i - 1]) > 0); 5361dec0b466SHong Zhang rmax = PetscMax(rmax, ailen[i - 1]); 5362dec0b466SHong Zhang } 5363dec0b466SHong Zhang if (m) { 5364dec0b466SHong Zhang ai[m] -= fshift; 5365dec0b466SHong Zhang a->nz = ai[m]; 5366dec0b466SHong Zhang } 5367dec0b466SHong 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)); 5368dec0b466SHong Zhang A->nonzerostate -= fshift; 5369dec0b466SHong Zhang A->info.nz_unneeded += (PetscReal)fshift; 5370dec0b466SHong Zhang a->rmax = rmax; 5371dec0b466SHong Zhang if (a->inode.use && a->inode.checked) PetscCall(MatSeqAIJCheckInode(A)); 5372dec0b466SHong Zhang PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 5373dec0b466SHong Zhang PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 53743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5375dec0b466SHong Zhang } 5376dec0b466SHong Zhang 53774099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL; 53784099cc6bSBarry Smith 53794099cc6bSBarry Smith /*@C 538011a5261eSBarry Smith MatSeqAIJSetType - Converts a `MATSEQAIJ` matrix to a subtype 53814099cc6bSBarry Smith 5382c3339decSBarry Smith Collective 53834099cc6bSBarry Smith 53844099cc6bSBarry Smith Input Parameters: 53854099cc6bSBarry Smith + mat - the matrix object 53864099cc6bSBarry Smith - matype - matrix type 53874099cc6bSBarry Smith 53884099cc6bSBarry Smith Options Database Key: 53894e187271SRichard Tran Mills . -mat_seqaij_type <method> - for example seqaijcrl 53904099cc6bSBarry Smith 53914099cc6bSBarry Smith Level: intermediate 53924099cc6bSBarry Smith 53932ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat` 53944099cc6bSBarry Smith @*/ 5395d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetType(Mat mat, MatType matype) 5396d71ae5a4SJacob Faibussowitsch { 53974099cc6bSBarry Smith PetscBool sametype; 53985f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(Mat, MatType, MatReuse, Mat *); 53994099cc6bSBarry Smith 54004099cc6bSBarry Smith PetscFunctionBegin; 54014099cc6bSBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 54029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, matype, &sametype)); 54033ba16761SJacob Faibussowitsch if (sametype) PetscFunctionReturn(PETSC_SUCCESS); 54044099cc6bSBarry Smith 54059566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(MatSeqAIJList, matype, &r)); 54065f80ce2aSJacob Faibussowitsch PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Mat type given: %s", matype); 54079566063dSJacob Faibussowitsch PetscCall((*r)(mat, matype, MAT_INPLACE_MATRIX, &mat)); 54083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54094099cc6bSBarry Smith } 54104099cc6bSBarry Smith 54114099cc6bSBarry Smith /*@C 541211a5261eSBarry Smith MatSeqAIJRegister - - Adds a new sub-matrix type for sequential `MATSEQAIJ` matrices 54134099cc6bSBarry Smith 54144099cc6bSBarry Smith Not Collective 54154099cc6bSBarry Smith 54164099cc6bSBarry Smith Input Parameters: 541711a5261eSBarry Smith + name - name of a new user-defined matrix type, for example `MATSEQAIJCRL` 54184099cc6bSBarry Smith - function - routine to convert to subtype 54194099cc6bSBarry Smith 54202ef1f0ffSBarry Smith Level: advanced 54212ef1f0ffSBarry Smith 54224099cc6bSBarry Smith Notes: 542311a5261eSBarry Smith `MatSeqAIJRegister()` may be called multiple times to add several user-defined solvers. 54244099cc6bSBarry Smith 54254099cc6bSBarry Smith Then, your matrix can be chosen with the procedural interface at runtime via the option 54264099cc6bSBarry Smith $ -mat_seqaij_type my_mat 54274099cc6bSBarry Smith 54282ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRegisterAll()` 54294099cc6bSBarry Smith @*/ 5430d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJRegister(const char sname[], PetscErrorCode (*function)(Mat, MatType, MatReuse, Mat *)) 5431d71ae5a4SJacob Faibussowitsch { 54324099cc6bSBarry Smith PetscFunctionBegin; 54339566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 54349566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&MatSeqAIJList, sname, function)); 54353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54364099cc6bSBarry Smith } 54374099cc6bSBarry Smith 54384099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE; 54394099cc6bSBarry Smith 54404099cc6bSBarry Smith /*@C 544111a5261eSBarry Smith MatSeqAIJRegisterAll - Registers all of the matrix subtypes of `MATSSEQAIJ` 54424099cc6bSBarry Smith 54434099cc6bSBarry Smith Not Collective 54444099cc6bSBarry Smith 54454099cc6bSBarry Smith Level: advanced 54464099cc6bSBarry Smith 54472ef1f0ffSBarry Smith Note: 54482ef1f0ffSBarry Smith This registers the versions of `MATSEQAIJ` for GPUs 54492ef1f0ffSBarry Smith 54502ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatRegisterAll()`, `MatSeqAIJRegister()` 54514099cc6bSBarry Smith @*/ 5452d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJRegisterAll(void) 5453d71ae5a4SJacob Faibussowitsch { 54544099cc6bSBarry Smith PetscFunctionBegin; 54553ba16761SJacob Faibussowitsch if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS); 54564099cc6bSBarry Smith MatSeqAIJRegisterAllCalled = PETSC_TRUE; 54574099cc6bSBarry Smith 54589566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCRL, MatConvert_SeqAIJ_SeqAIJCRL)); 54599566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJPERM, MatConvert_SeqAIJ_SeqAIJPERM)); 54609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJSELL, MatConvert_SeqAIJ_SeqAIJSELL)); 54619779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 54629566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJMKL, MatConvert_SeqAIJ_SeqAIJMKL)); 5463485f9817SRichard Tran Mills #endif 54645063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA) 54659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 54665063d097SStefano Zampini #endif 5467d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_HIP) 5468d5e393b6SSuyash Tandon PetscCall(MatSeqAIJRegister(MATSEQAIJHIPSPARSE, MatConvert_SeqAIJ_SeqAIJHIPSPARSE)); 5469d5e393b6SSuyash Tandon #endif 54705063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 54719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJKOKKOS, MatConvert_SeqAIJ_SeqAIJKokkos)); 54725063d097SStefano Zampini #endif 54734099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA) 54749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL)); 54754099cc6bSBarry Smith #endif 54763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54774099cc6bSBarry Smith } 547853dd7562SDmitry Karpeev 547953dd7562SDmitry Karpeev /* 548081824310SBarry Smith Special version for direct calls from Fortran 548181824310SBarry Smith */ 5482af0996ceSBarry Smith #include <petsc/private/fortranimpl.h> 548381824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS) 548481824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ 548581824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 548681824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij 548781824310SBarry Smith #endif 548881824310SBarry Smith 548981824310SBarry Smith /* Change these macros so can be used in void function */ 549098921bdaSJacob Faibussowitsch 549198921bdaSJacob Faibussowitsch /* Change these macros so can be used in void function */ 54929566063dSJacob Faibussowitsch /* Identical to PetscCallVoid, except it assigns to *_ierr */ 54939566063dSJacob Faibussowitsch #undef PetscCall 54949371c9d4SSatish Balay #define PetscCall(...) \ 54959371c9d4SSatish Balay do { \ 54965f80ce2aSJacob Faibussowitsch PetscErrorCode ierr_msv_mpiaij = __VA_ARGS__; \ 549798921bdaSJacob Faibussowitsch if (PetscUnlikely(ierr_msv_mpiaij)) { \ 549898921bdaSJacob Faibussowitsch *_ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr_msv_mpiaij, PETSC_ERROR_REPEAT, " "); \ 549998921bdaSJacob Faibussowitsch return; \ 550098921bdaSJacob Faibussowitsch } \ 550198921bdaSJacob Faibussowitsch } while (0) 550298921bdaSJacob Faibussowitsch 550398921bdaSJacob Faibussowitsch #undef SETERRQ 55049371c9d4SSatish Balay #define SETERRQ(comm, ierr, ...) \ 55059371c9d4SSatish Balay do { \ 550698921bdaSJacob Faibussowitsch *_ierr = PetscError(comm, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr, PETSC_ERROR_INITIAL, __VA_ARGS__); \ 550798921bdaSJacob Faibussowitsch return; \ 550898921bdaSJacob Faibussowitsch } while (0) 550981824310SBarry Smith 5510d71ae5a4SJacob Faibussowitsch PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA, PetscInt *mm, const PetscInt im[], PetscInt *nn, const PetscInt in[], const PetscScalar v[], InsertMode *isis, PetscErrorCode *_ierr) 5511d71ae5a4SJacob Faibussowitsch { 551281824310SBarry Smith Mat A = *AA; 551381824310SBarry Smith PetscInt m = *mm, n = *nn; 551481824310SBarry Smith InsertMode is = *isis; 551581824310SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 551681824310SBarry Smith PetscInt *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N; 551781824310SBarry Smith PetscInt *imax, *ai, *ailen; 551881824310SBarry Smith PetscInt *aj, nonew = a->nonew, lastcol = -1; 551954f21887SBarry Smith MatScalar *ap, value, *aa; 5520ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 5521ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 552281824310SBarry Smith 552381824310SBarry Smith PetscFunctionBegin; 55244994cf47SJed Brown MatCheckPreallocated(A, 1); 552581824310SBarry Smith imax = a->imax; 552681824310SBarry Smith ai = a->i; 552781824310SBarry Smith ailen = a->ilen; 552881824310SBarry Smith aj = a->j; 552981824310SBarry Smith aa = a->a; 553081824310SBarry Smith 553181824310SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 553281824310SBarry Smith row = im[k]; 553381824310SBarry Smith if (row < 0) continue; 55345f80ce2aSJacob Faibussowitsch PetscCheck(row < A->rmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Row too large"); 55359371c9d4SSatish Balay rp = aj + ai[row]; 55369371c9d4SSatish Balay ap = aa + ai[row]; 55379371c9d4SSatish Balay rmax = imax[row]; 55389371c9d4SSatish Balay nrow = ailen[row]; 553981824310SBarry Smith low = 0; 554081824310SBarry Smith high = nrow; 554181824310SBarry Smith for (l = 0; l < n; l++) { /* loop over added columns */ 554281824310SBarry Smith if (in[l] < 0) continue; 55435f80ce2aSJacob Faibussowitsch PetscCheck(in[l] < A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Column too large"); 554481824310SBarry Smith col = in[l]; 55452205254eSKarl Rupp if (roworiented) value = v[l + k * n]; 55462205254eSKarl Rupp else value = v[k + l * m]; 55472205254eSKarl Rupp 554881824310SBarry Smith if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 554981824310SBarry Smith 55502205254eSKarl Rupp if (col <= lastcol) low = 0; 55512205254eSKarl Rupp else high = nrow; 555281824310SBarry Smith lastcol = col; 555381824310SBarry Smith while (high - low > 5) { 555481824310SBarry Smith t = (low + high) / 2; 555581824310SBarry Smith if (rp[t] > col) high = t; 555681824310SBarry Smith else low = t; 555781824310SBarry Smith } 555881824310SBarry Smith for (i = low; i < high; i++) { 555981824310SBarry Smith if (rp[i] > col) break; 556081824310SBarry Smith if (rp[i] == col) { 556181824310SBarry Smith if (is == ADD_VALUES) ap[i] += value; 556281824310SBarry Smith else ap[i] = value; 556381824310SBarry Smith goto noinsert; 556481824310SBarry Smith } 556581824310SBarry Smith } 556681824310SBarry Smith if (value == 0.0 && ignorezeroentries) goto noinsert; 556781824310SBarry Smith if (nonew == 1) goto noinsert; 55685f80ce2aSJacob Faibussowitsch PetscCheck(nonew != -1, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero in the matrix"); 5569fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, A->rmap->n, 1, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 55709371c9d4SSatish Balay N = nrow++ - 1; 55719371c9d4SSatish Balay a->nz++; 55729371c9d4SSatish Balay high++; 557381824310SBarry Smith /* shift up all the later entries in this row */ 557481824310SBarry Smith for (ii = N; ii >= i; ii--) { 557581824310SBarry Smith rp[ii + 1] = rp[ii]; 557681824310SBarry Smith ap[ii + 1] = ap[ii]; 557781824310SBarry Smith } 557881824310SBarry Smith rp[i] = col; 557981824310SBarry Smith ap[i] = value; 5580e56f5c9eSBarry Smith A->nonzerostate++; 558181824310SBarry Smith noinsert:; 558281824310SBarry Smith low = i + 1; 558381824310SBarry Smith } 558481824310SBarry Smith ailen[row] = nrow; 558581824310SBarry Smith } 558681824310SBarry Smith PetscFunctionReturnVoid(); 558781824310SBarry Smith } 558898921bdaSJacob Faibussowitsch /* Undefining these here since they were redefined from their original definition above! No 558998921bdaSJacob Faibussowitsch * other PETSc functions should be defined past this point, as it is impossible to recover the 559098921bdaSJacob Faibussowitsch * original definitions */ 55919566063dSJacob Faibussowitsch #undef PetscCall 559298921bdaSJacob Faibussowitsch #undef SETERRQ 5593