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 119371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A) { 124099cc6bSBarry Smith PetscBool flg; 134099cc6bSBarry Smith char type[256]; 144099cc6bSBarry Smith 154099cc6bSBarry Smith PetscFunctionBegin; 16d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)A); 179566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-mat_seqaij_type", "Matrix SeqAIJ type", "MatSeqAIJSetType", MatSeqAIJList, "seqaij", type, 256, &flg)); 189566063dSJacob Faibussowitsch if (flg) PetscCall(MatSeqAIJSetType(A, type)); 19d0609cedSBarry Smith PetscOptionsEnd(); 204099cc6bSBarry Smith PetscFunctionReturn(0); 214099cc6bSBarry Smith } 224099cc6bSBarry Smith 239371c9d4SSatish Balay PetscErrorCode MatGetColumnReductions_SeqAIJ(Mat A, PetscInt type, PetscReal *reductions) { 240716a85fSBarry Smith PetscInt i, m, n; 250716a85fSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 260716a85fSBarry Smith 270716a85fSBarry Smith PetscFunctionBegin; 289566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &m, &n)); 299566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(reductions, n)); 300716a85fSBarry Smith if (type == NORM_2) { 31ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscAbsScalar(aij->a[i] * aij->a[i]); 320716a85fSBarry Smith } else if (type == NORM_1) { 33ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]); 340716a85fSBarry Smith } else if (type == NORM_INFINITY) { 35ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]), reductions[aij->j[i]]); 36857cbf51SRichard Tran Mills } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) { 37ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscRealPart(aij->a[i]); 38857cbf51SRichard Tran Mills } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) { 39ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscImaginaryPart(aij->a[i]); 40857cbf51SRichard Tran Mills } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown reduction type"); 410716a85fSBarry Smith 420716a85fSBarry Smith if (type == NORM_2) { 43a873a8cdSSam Reynolds for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]); 44857cbf51SRichard Tran Mills } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) { 45a873a8cdSSam Reynolds for (i = 0; i < n; i++) reductions[i] /= m; 460716a85fSBarry Smith } 470716a85fSBarry Smith PetscFunctionReturn(0); 480716a85fSBarry Smith } 490716a85fSBarry Smith 509371c9d4SSatish Balay PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A, IS *is) { 513a062f41SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 523a062f41SBarry Smith PetscInt i, m = A->rmap->n, cnt = 0, bs = A->rmap->bs; 533a062f41SBarry Smith const PetscInt *jj = a->j, *ii = a->i; 543a062f41SBarry Smith PetscInt *rows; 553a062f41SBarry Smith 563a062f41SBarry Smith PetscFunctionBegin; 573a062f41SBarry Smith for (i = 0; i < m; i++) { 58ad540459SPierre Jolivet if ((ii[i] != ii[i + 1]) && ((jj[ii[i]] < bs * (i / bs)) || (jj[ii[i + 1] - 1] > bs * ((i + bs) / bs) - 1))) cnt++; 593a062f41SBarry Smith } 609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cnt, &rows)); 613a062f41SBarry Smith cnt = 0; 623a062f41SBarry Smith for (i = 0; i < m; i++) { 633a062f41SBarry Smith if ((ii[i] != ii[i + 1]) && ((jj[ii[i]] < bs * (i / bs)) || (jj[ii[i + 1] - 1] > bs * ((i + bs) / bs) - 1))) { 643a062f41SBarry Smith rows[cnt] = i; 653a062f41SBarry Smith cnt++; 663a062f41SBarry Smith } 673a062f41SBarry Smith } 689566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cnt, rows, PETSC_OWN_POINTER, is)); 693a062f41SBarry Smith PetscFunctionReturn(0); 703a062f41SBarry Smith } 713a062f41SBarry Smith 729371c9d4SSatish Balay PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A, PetscInt *nrows, PetscInt **zrows) { 736ce1633cSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 74fff043a9SJunchao Zhang const MatScalar *aa; 756ce1633cSBarry Smith PetscInt i, m = A->rmap->n, cnt = 0; 76b2db7409Sstefano_zampini const PetscInt *ii = a->i, *jj = a->j, *diag; 776ce1633cSBarry Smith PetscInt *rows; 786ce1633cSBarry Smith 796ce1633cSBarry Smith PetscFunctionBegin; 809566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 819566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 826ce1633cSBarry Smith diag = a->diag; 836ce1633cSBarry Smith for (i = 0; i < m; i++) { 84ad540459SPierre Jolivet if ((diag[i] >= ii[i + 1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) cnt++; 856ce1633cSBarry Smith } 869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cnt, &rows)); 876ce1633cSBarry Smith cnt = 0; 886ce1633cSBarry Smith for (i = 0; i < m; i++) { 89ad540459SPierre Jolivet if ((diag[i] >= ii[i + 1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) rows[cnt++] = i; 906ce1633cSBarry Smith } 91f1f41ecbSJed Brown *nrows = cnt; 92f1f41ecbSJed Brown *zrows = rows; 939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 94f1f41ecbSJed Brown PetscFunctionReturn(0); 95f1f41ecbSJed Brown } 96f1f41ecbSJed Brown 979371c9d4SSatish Balay PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A, IS *zrows) { 98f1f41ecbSJed Brown PetscInt nrows, *rows; 99f1f41ecbSJed Brown 100f1f41ecbSJed Brown PetscFunctionBegin; 1010298fd71SBarry Smith *zrows = NULL; 1029566063dSJacob Faibussowitsch PetscCall(MatFindZeroDiagonals_SeqAIJ_Private(A, &nrows, &rows)); 1039566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), nrows, rows, PETSC_OWN_POINTER, zrows)); 1046ce1633cSBarry Smith PetscFunctionReturn(0); 1056ce1633cSBarry Smith } 1066ce1633cSBarry Smith 1079371c9d4SSatish Balay PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A, IS *keptrows) { 108b3a44c85SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 109b3a44c85SBarry Smith const MatScalar *aa; 110b3a44c85SBarry Smith PetscInt m = A->rmap->n, cnt = 0; 111b3a44c85SBarry Smith const PetscInt *ii; 112b3a44c85SBarry Smith PetscInt n, i, j, *rows; 113b3a44c85SBarry Smith 114b3a44c85SBarry Smith PetscFunctionBegin; 1159566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 116f4259b30SLisandro Dalcin *keptrows = NULL; 117b3a44c85SBarry Smith ii = a->i; 118b3a44c85SBarry Smith for (i = 0; i < m; i++) { 119b3a44c85SBarry Smith n = ii[i + 1] - ii[i]; 120b3a44c85SBarry Smith if (!n) { 121b3a44c85SBarry Smith cnt++; 122b3a44c85SBarry Smith goto ok1; 123b3a44c85SBarry Smith } 1242e5835c6SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 125b3a44c85SBarry Smith if (aa[j] != 0.0) goto ok1; 126b3a44c85SBarry Smith } 127b3a44c85SBarry Smith cnt++; 128b3a44c85SBarry Smith ok1:; 129b3a44c85SBarry Smith } 1302e5835c6SStefano Zampini if (!cnt) { 1319566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 1322e5835c6SStefano Zampini PetscFunctionReturn(0); 1332e5835c6SStefano Zampini } 1349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n - cnt, &rows)); 135b3a44c85SBarry Smith cnt = 0; 136b3a44c85SBarry Smith for (i = 0; i < m; i++) { 137b3a44c85SBarry Smith n = ii[i + 1] - ii[i]; 138b3a44c85SBarry Smith if (!n) continue; 1392e5835c6SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 140b3a44c85SBarry Smith if (aa[j] != 0.0) { 141b3a44c85SBarry Smith rows[cnt++] = i; 142b3a44c85SBarry Smith break; 143b3a44c85SBarry Smith } 144b3a44c85SBarry Smith } 145b3a44c85SBarry Smith } 1469566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 1479566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cnt, rows, PETSC_OWN_POINTER, keptrows)); 148b3a44c85SBarry Smith PetscFunctionReturn(0); 149b3a44c85SBarry Smith } 150b3a44c85SBarry Smith 1519371c9d4SSatish Balay PetscErrorCode MatDiagonalSet_SeqAIJ(Mat Y, Vec D, InsertMode is) { 15279299369SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)Y->data; 15399e65526SBarry Smith PetscInt i, m = Y->rmap->n; 15499e65526SBarry Smith const PetscInt *diag; 1552e5835c6SStefano Zampini MatScalar *aa; 15699e65526SBarry Smith const PetscScalar *v; 157ace3abfcSBarry Smith PetscBool missing; 15879299369SBarry Smith 15979299369SBarry Smith PetscFunctionBegin; 16009f38230SBarry Smith if (Y->assembled) { 1619566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal_SeqAIJ(Y, &missing, NULL)); 16209f38230SBarry Smith if (!missing) { 16379299369SBarry Smith diag = aij->diag; 1649566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(D, &v)); 1659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Y, &aa)); 16679299369SBarry Smith if (is == INSERT_VALUES) { 167ad540459SPierre Jolivet for (i = 0; i < m; i++) aa[diag[i]] = v[i]; 16879299369SBarry Smith } else { 169ad540459SPierre Jolivet for (i = 0; i < m; i++) aa[diag[i]] += v[i]; 17079299369SBarry Smith } 1719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Y, &aa)); 1729566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(D, &v)); 17379299369SBarry Smith PetscFunctionReturn(0); 17479299369SBarry Smith } 1759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(Y)); 17609f38230SBarry Smith } 1779566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet_Default(Y, D, is)); 17809f38230SBarry Smith PetscFunctionReturn(0); 17909f38230SBarry Smith } 18079299369SBarry Smith 1819371c9d4SSatish Balay PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *m, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) { 182416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 18397f1f81fSBarry Smith PetscInt i, ishift; 18417ab2063SBarry Smith 1853a40ed3dSBarry Smith PetscFunctionBegin; 186f1f2ae84SBarry Smith if (m) *m = A->rmap->n; 1873a40ed3dSBarry Smith if (!ia) PetscFunctionReturn(0); 188bfeeae90SHong Zhang ishift = 0; 189b94d7dedSBarry Smith if (symmetric && A->structurally_symmetric != PETSC_BOOL3_TRUE) { 1909566063dSJacob Faibussowitsch PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n, a->i, a->j, PETSC_TRUE, ishift, oshift, (PetscInt **)ia, (PetscInt **)ja)); 191bfeeae90SHong Zhang } else if (oshift == 1) { 1921a83f524SJed Brown PetscInt *tia; 193d0f46423SBarry Smith PetscInt nz = a->i[A->rmap->n]; 1943b2fbd54SBarry Smith /* malloc space and add 1 to i and j indices */ 1959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n + 1, &tia)); 1961a83f524SJed Brown for (i = 0; i < A->rmap->n + 1; i++) tia[i] = a->i[i] + 1; 1971a83f524SJed Brown *ia = tia; 198ecc77c7aSBarry Smith if (ja) { 1991a83f524SJed Brown PetscInt *tja; 2009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz + 1, &tja)); 2011a83f524SJed Brown for (i = 0; i < nz; i++) tja[i] = a->j[i] + 1; 2021a83f524SJed Brown *ja = tja; 203ecc77c7aSBarry Smith } 2046945ee14SBarry Smith } else { 205ecc77c7aSBarry Smith *ia = a->i; 206ecc77c7aSBarry Smith if (ja) *ja = a->j; 207a2ce50c7SBarry Smith } 2083a40ed3dSBarry Smith PetscFunctionReturn(0); 209a2744918SBarry Smith } 210a2744918SBarry Smith 2119371c9d4SSatish Balay PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) { 2123a40ed3dSBarry Smith PetscFunctionBegin; 2133a40ed3dSBarry Smith if (!ia) PetscFunctionReturn(0); 214b94d7dedSBarry Smith if ((symmetric && A->structurally_symmetric != PETSC_BOOL3_TRUE) || oshift == 1) { 2159566063dSJacob Faibussowitsch PetscCall(PetscFree(*ia)); 2169566063dSJacob Faibussowitsch if (ja) PetscCall(PetscFree(*ja)); 217bcd2baecSBarry Smith } 2183a40ed3dSBarry Smith PetscFunctionReturn(0); 21917ab2063SBarry Smith } 22017ab2063SBarry Smith 2219371c9d4SSatish Balay PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) { 2223b2fbd54SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 223d0f46423SBarry Smith PetscInt i, *collengths, *cia, *cja, n = A->cmap->n, m = A->rmap->n; 22497f1f81fSBarry Smith PetscInt nz = a->i[m], row, *jj, mr, col; 2253b2fbd54SBarry Smith 2263a40ed3dSBarry Smith PetscFunctionBegin; 227899cda47SBarry Smith *nn = n; 2283a40ed3dSBarry Smith if (!ia) PetscFunctionReturn(0); 2293b2fbd54SBarry Smith if (symmetric) { 2309566063dSJacob Faibussowitsch PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n, a->i, a->j, PETSC_TRUE, 0, oshift, (PetscInt **)ia, (PetscInt **)ja)); 2313b2fbd54SBarry Smith } else { 2329566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &collengths)); 2339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &cia)); 2349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &cja)); 2353b2fbd54SBarry Smith jj = a->j; 236ad540459SPierre Jolivet for (i = 0; i < nz; i++) collengths[jj[i]]++; 2373b2fbd54SBarry Smith cia[0] = oshift; 238ad540459SPierre Jolivet for (i = 0; i < n; i++) cia[i + 1] = cia[i] + collengths[i]; 2399566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(collengths, n)); 2403b2fbd54SBarry Smith jj = a->j; 241a93ec695SBarry Smith for (row = 0; row < m; row++) { 242a93ec695SBarry Smith mr = a->i[row + 1] - a->i[row]; 243a93ec695SBarry Smith for (i = 0; i < mr; i++) { 244bfeeae90SHong Zhang col = *jj++; 2452205254eSKarl Rupp 2463b2fbd54SBarry Smith cja[cia[col] + collengths[col]++ - oshift] = row + oshift; 2473b2fbd54SBarry Smith } 2483b2fbd54SBarry Smith } 2499566063dSJacob Faibussowitsch PetscCall(PetscFree(collengths)); 2509371c9d4SSatish Balay *ia = cia; 2519371c9d4SSatish Balay *ja = cja; 2523b2fbd54SBarry Smith } 2533a40ed3dSBarry Smith PetscFunctionReturn(0); 2543b2fbd54SBarry Smith } 2553b2fbd54SBarry Smith 2569371c9d4SSatish Balay PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) { 2573a40ed3dSBarry Smith PetscFunctionBegin; 2583a40ed3dSBarry Smith if (!ia) PetscFunctionReturn(0); 2593b2fbd54SBarry Smith 2609566063dSJacob Faibussowitsch PetscCall(PetscFree(*ia)); 2619566063dSJacob Faibussowitsch PetscCall(PetscFree(*ja)); 2623a40ed3dSBarry Smith PetscFunctionReturn(0); 2633b2fbd54SBarry Smith } 2643b2fbd54SBarry Smith 2657cee066cSHong Zhang /* 2667cee066cSHong Zhang MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from 2677cee066cSHong Zhang MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output 268040ebd07SHong Zhang spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ() 2697cee066cSHong Zhang */ 2709371c9d4SSatish Balay PetscErrorCode MatGetColumnIJ_SeqAIJ_Color(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscInt *spidx[], PetscBool *done) { 2717cee066cSHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2727cee066cSHong Zhang PetscInt i, *collengths, *cia, *cja, n = A->cmap->n, m = A->rmap->n; 273071fcb05SBarry Smith PetscInt nz = a->i[m], row, mr, col, tmp; 2747cee066cSHong Zhang PetscInt *cspidx; 275071fcb05SBarry Smith const PetscInt *jj; 2767cee066cSHong Zhang 2777cee066cSHong Zhang PetscFunctionBegin; 2787cee066cSHong Zhang *nn = n; 2797cee066cSHong Zhang if (!ia) PetscFunctionReturn(0); 280625f6d37SHong Zhang 2819566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &collengths)); 2829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &cia)); 2839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &cja)); 2849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &cspidx)); 2857cee066cSHong Zhang jj = a->j; 286ad540459SPierre Jolivet for (i = 0; i < nz; i++) collengths[jj[i]]++; 2877cee066cSHong Zhang cia[0] = oshift; 288ad540459SPierre Jolivet for (i = 0; i < n; i++) cia[i + 1] = cia[i] + collengths[i]; 2899566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(collengths, n)); 2907cee066cSHong Zhang jj = a->j; 2917cee066cSHong Zhang for (row = 0; row < m; row++) { 2927cee066cSHong Zhang mr = a->i[row + 1] - a->i[row]; 2937cee066cSHong Zhang for (i = 0; i < mr; i++) { 2947cee066cSHong Zhang col = *jj++; 295071fcb05SBarry Smith tmp = cia[col] + collengths[col]++ - oshift; 296071fcb05SBarry Smith cspidx[tmp] = a->i[row] + i; /* index of a->j */ 297071fcb05SBarry Smith cja[tmp] = row + oshift; 2987cee066cSHong Zhang } 2997cee066cSHong Zhang } 3009566063dSJacob Faibussowitsch PetscCall(PetscFree(collengths)); 301071fcb05SBarry Smith *ia = cia; 302071fcb05SBarry Smith *ja = cja; 3037cee066cSHong Zhang *spidx = cspidx; 3047cee066cSHong Zhang PetscFunctionReturn(0); 3057cee066cSHong Zhang } 3067cee066cSHong Zhang 3079371c9d4SSatish Balay PetscErrorCode MatRestoreColumnIJ_SeqAIJ_Color(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscInt *spidx[], PetscBool *done) { 3087cee066cSHong Zhang PetscFunctionBegin; 3099566063dSJacob Faibussowitsch PetscCall(MatRestoreColumnIJ_SeqAIJ(A, oshift, symmetric, inodecompressed, n, ia, ja, done)); 3109566063dSJacob Faibussowitsch PetscCall(PetscFree(*spidx)); 3117cee066cSHong Zhang PetscFunctionReturn(0); 3127cee066cSHong Zhang } 3137cee066cSHong Zhang 3149371c9d4SSatish Balay PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A, PetscInt row, const PetscScalar v[]) { 31587d4246cSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 31687d4246cSBarry Smith PetscInt *ai = a->i; 317fff043a9SJunchao Zhang PetscScalar *aa; 31887d4246cSBarry Smith 31987d4246cSBarry Smith PetscFunctionBegin; 3209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 3219566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aa + ai[row], v, ai[row + 1] - ai[row])); 3229566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 32387d4246cSBarry Smith PetscFunctionReturn(0); 32487d4246cSBarry Smith } 32587d4246cSBarry Smith 326bd04181cSBarry Smith /* 327bd04181cSBarry Smith MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions 328bd04181cSBarry Smith 329bd04181cSBarry Smith - a single row of values is set with each call 330bd04181cSBarry Smith - no row or column indices are negative or (in error) larger than the number of rows or columns 331bd04181cSBarry Smith - the values are always added to the matrix, not set 332bd04181cSBarry Smith - no new locations are introduced in the nonzero structure of the matrix 333bd04181cSBarry Smith 3341f763a69SBarry Smith This does NOT assume the global column indices are sorted 335bd04181cSBarry Smith 3361f763a69SBarry Smith */ 337bd04181cSBarry Smith 338af0996ceSBarry Smith #include <petsc/private/isimpl.h> 3399371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) { 340189e4007SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3411f763a69SBarry Smith PetscInt low, high, t, row, nrow, i, col, l; 3421f763a69SBarry Smith const PetscInt *rp, *ai = a->i, *ailen = a->ilen, *aj = a->j; 3431f763a69SBarry Smith PetscInt lastcol = -1; 344fff043a9SJunchao Zhang MatScalar *ap, value, *aa; 345189e4007SBarry Smith const PetscInt *ridx = A->rmap->mapping->indices, *cidx = A->cmap->mapping->indices; 346189e4007SBarry Smith 347fff043a9SJunchao Zhang PetscFunctionBegin; 3489566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 349f38dd0b8SBarry Smith row = ridx[im[0]]; 3501f763a69SBarry Smith rp = aj + ai[row]; 3511f763a69SBarry Smith ap = aa + ai[row]; 3521f763a69SBarry Smith nrow = ailen[row]; 353189e4007SBarry Smith low = 0; 354189e4007SBarry Smith high = nrow; 355189e4007SBarry Smith for (l = 0; l < n; l++) { /* loop over added columns */ 356189e4007SBarry Smith col = cidx[in[l]]; 357f38dd0b8SBarry Smith value = v[l]; 358189e4007SBarry Smith 359189e4007SBarry Smith if (col <= lastcol) low = 0; 360189e4007SBarry Smith else high = nrow; 361189e4007SBarry Smith lastcol = col; 362189e4007SBarry Smith while (high - low > 5) { 363189e4007SBarry Smith t = (low + high) / 2; 364189e4007SBarry Smith if (rp[t] > col) high = t; 365189e4007SBarry Smith else low = t; 366189e4007SBarry Smith } 367189e4007SBarry Smith for (i = low; i < high; i++) { 368189e4007SBarry Smith if (rp[i] == col) { 3691f763a69SBarry Smith ap[i] += value; 370189e4007SBarry Smith low = i + 1; 3711f763a69SBarry Smith break; 372189e4007SBarry Smith } 373189e4007SBarry Smith } 374189e4007SBarry Smith } 3759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 376f38dd0b8SBarry Smith return 0; 377189e4007SBarry Smith } 378189e4007SBarry Smith 3799371c9d4SSatish Balay PetscErrorCode MatSetValues_SeqAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) { 380416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 381e2ee6c50SBarry Smith PetscInt *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N; 38297f1f81fSBarry Smith PetscInt *imax = a->imax, *ai = a->i, *ailen = a->ilen; 383e2ee6c50SBarry Smith PetscInt *aj = a->j, nonew = a->nonew, lastcol = -1; 384ce496241SStefano Zampini MatScalar *ap = NULL, value = 0.0, *aa; 385ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 386ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 38717ab2063SBarry Smith 3883a40ed3dSBarry Smith PetscFunctionBegin; 3899566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 39017ab2063SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 391416022c9SBarry Smith row = im[k]; 3925ef9f2a5SBarry Smith if (row < 0) continue; 3936bdcaf15SBarry 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); 394720833daSHong Zhang rp = aj + ai[row]; 395876c6284SHong Zhang if (!A->structure_only) ap = aa + ai[row]; 3969371c9d4SSatish Balay rmax = imax[row]; 3979371c9d4SSatish Balay nrow = ailen[row]; 398416022c9SBarry Smith low = 0; 399c71e6ed7SBarry Smith high = nrow; 40017ab2063SBarry Smith for (l = 0; l < n; l++) { /* loop over added columns */ 4015ef9f2a5SBarry Smith if (in[l] < 0) continue; 4026bdcaf15SBarry 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); 403bfeeae90SHong Zhang col = in[l]; 404071fcb05SBarry Smith if (v && !A->structure_only) value = roworiented ? v[l + k * n] : v[k + l * m]; 405071fcb05SBarry Smith if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue; 40636db0b34SBarry Smith 4072205254eSKarl Rupp if (col <= lastcol) low = 0; 4082205254eSKarl Rupp else high = nrow; 409e2ee6c50SBarry Smith lastcol = col; 410416022c9SBarry Smith while (high - low > 5) { 411416022c9SBarry Smith t = (low + high) / 2; 412416022c9SBarry Smith if (rp[t] > col) high = t; 413416022c9SBarry Smith else low = t; 41417ab2063SBarry Smith } 415416022c9SBarry Smith for (i = low; i < high; i++) { 41617ab2063SBarry Smith if (rp[i] > col) break; 41717ab2063SBarry Smith if (rp[i] == col) { 418876c6284SHong Zhang if (!A->structure_only) { 4190c0d7e18SFande Kong if (is == ADD_VALUES) { 4200c0d7e18SFande Kong ap[i] += value; 4210c0d7e18SFande Kong (void)PetscLogFlops(1.0); 4229371c9d4SSatish Balay } else ap[i] = value; 423720833daSHong Zhang } 424e44c0bd4SBarry Smith low = i + 1; 42517ab2063SBarry Smith goto noinsert; 42617ab2063SBarry Smith } 42717ab2063SBarry Smith } 428dcd36c23SBarry Smith if (value == 0.0 && ignorezeroentries && row != col) goto noinsert; 429c2653b3dSLois Curfman McInnes if (nonew == 1) goto noinsert; 43008401ef6SPierre 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); 431720833daSHong Zhang if (A->structure_only) { 432876c6284SHong Zhang MatSeqXAIJReallocateAIJ_structure_only(A, A->rmap->n, 1, nrow, row, col, rmax, ai, aj, rp, imax, nonew, MatScalar); 433720833daSHong Zhang } else { 434fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, A->rmap->n, 1, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 435720833daSHong Zhang } 4369371c9d4SSatish Balay N = nrow++ - 1; 4379371c9d4SSatish Balay a->nz++; 4389371c9d4SSatish Balay high++; 439416022c9SBarry Smith /* shift up all the later entries in this row */ 4409566063dSJacob Faibussowitsch PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1)); 44117ab2063SBarry Smith rp[i] = col; 442580bdb30SBarry Smith if (!A->structure_only) { 4439566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap + i + 1, ap + i, N - i + 1)); 444580bdb30SBarry Smith ap[i] = value; 445580bdb30SBarry Smith } 446416022c9SBarry Smith low = i + 1; 447e56f5c9eSBarry Smith A->nonzerostate++; 448e44c0bd4SBarry Smith noinsert:; 44917ab2063SBarry Smith } 45017ab2063SBarry Smith ailen[row] = nrow; 45117ab2063SBarry Smith } 4529566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 4533a40ed3dSBarry Smith PetscFunctionReturn(0); 45417ab2063SBarry Smith } 45517ab2063SBarry Smith 4569371c9d4SSatish Balay PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) { 45719b08ed1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 45819b08ed1SBarry Smith PetscInt *rp, k, row; 45919b08ed1SBarry Smith PetscInt *ai = a->i; 46019b08ed1SBarry Smith PetscInt *aj = a->j; 461fff043a9SJunchao Zhang MatScalar *aa, *ap; 46219b08ed1SBarry Smith 46319b08ed1SBarry Smith PetscFunctionBegin; 46428b400f6SJacob Faibussowitsch PetscCheck(!A->was_assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call on assembled matrix."); 46508401ef6SPierre 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); 466fff043a9SJunchao Zhang 4679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 46819b08ed1SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 46919b08ed1SBarry Smith row = im[k]; 47019b08ed1SBarry Smith rp = aj + ai[row]; 47119b08ed1SBarry Smith ap = aa + ai[row]; 47219b08ed1SBarry Smith 4739566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(rp, in, n * sizeof(PetscInt))); 47419b08ed1SBarry Smith if (!A->structure_only) { 47519b08ed1SBarry Smith if (v) { 4769566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(ap, v, n * sizeof(PetscScalar))); 47719b08ed1SBarry Smith v += n; 47819b08ed1SBarry Smith } else { 4799566063dSJacob Faibussowitsch PetscCall(PetscMemzero(ap, n * sizeof(PetscScalar))); 48019b08ed1SBarry Smith } 48119b08ed1SBarry Smith } 48219b08ed1SBarry Smith a->ilen[row] = n; 48319b08ed1SBarry Smith a->imax[row] = n; 48419b08ed1SBarry Smith a->i[row + 1] = a->i[row] + n; 48519b08ed1SBarry Smith a->nz += n; 48619b08ed1SBarry Smith } 4879566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 48819b08ed1SBarry Smith PetscFunctionReturn(0); 48919b08ed1SBarry Smith } 49019b08ed1SBarry Smith 49119b08ed1SBarry Smith /*@ 49219b08ed1SBarry Smith MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix. 49319b08ed1SBarry Smith 49419b08ed1SBarry Smith Input Parameters: 49511a5261eSBarry Smith + A - the `MATSEQAIJ` matrix 49619b08ed1SBarry Smith - nztotal - bound on the number of nonzeros 49719b08ed1SBarry Smith 49819b08ed1SBarry Smith Level: advanced 49919b08ed1SBarry Smith 50019b08ed1SBarry Smith Notes: 50119b08ed1SBarry 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. 50211a5261eSBarry Smith Simply call `MatSetValues()` after this call to provide the matrix entries in the usual manner. This matrix may be used 50319b08ed1SBarry Smith as always with multiple matrix assemblies. 50419b08ed1SBarry Smith 505db781477SPatrick Sanan .seealso: `MatSetOption()`, `MAT_SORTED_FULL`, `MatSetValues()`, `MatSeqAIJSetPreallocation()` 50619b08ed1SBarry Smith @*/ 50719b08ed1SBarry Smith 5089371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A, PetscInt nztotal) { 50919b08ed1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 51019b08ed1SBarry Smith 51119b08ed1SBarry Smith PetscFunctionBegin; 5129566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 5139566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 51419b08ed1SBarry Smith a->maxnz = nztotal; 515*4dfa11a4SJacob Faibussowitsch if (!a->imax) { PetscCall(PetscMalloc1(A->rmap->n, &a->imax)); } 51619b08ed1SBarry Smith if (!a->ilen) { 5179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &a->ilen)); 51819b08ed1SBarry Smith } else { 5199566063dSJacob Faibussowitsch PetscCall(PetscMemzero(a->ilen, A->rmap->n * sizeof(PetscInt))); 52019b08ed1SBarry Smith } 52119b08ed1SBarry Smith 52219b08ed1SBarry Smith /* allocate the matrix space */ 52319b08ed1SBarry Smith if (A->structure_only) { 5249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nztotal, &a->j)); 5259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n + 1, &a->i)); 52619b08ed1SBarry Smith } else { 5279566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(nztotal, &a->a, nztotal, &a->j, A->rmap->n + 1, &a->i)); 52819b08ed1SBarry Smith } 52919b08ed1SBarry Smith a->i[0] = 0; 53019b08ed1SBarry Smith if (A->structure_only) { 53119b08ed1SBarry Smith a->singlemalloc = PETSC_FALSE; 53219b08ed1SBarry Smith a->free_a = PETSC_FALSE; 53319b08ed1SBarry Smith } else { 53419b08ed1SBarry Smith a->singlemalloc = PETSC_TRUE; 53519b08ed1SBarry Smith a->free_a = PETSC_TRUE; 53619b08ed1SBarry Smith } 53719b08ed1SBarry Smith a->free_ij = PETSC_TRUE; 53819b08ed1SBarry Smith A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation; 53919b08ed1SBarry Smith A->preallocated = PETSC_TRUE; 54019b08ed1SBarry Smith PetscFunctionReturn(0); 54119b08ed1SBarry Smith } 54219b08ed1SBarry Smith 5439371c9d4SSatish Balay PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) { 544071fcb05SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 545071fcb05SBarry Smith PetscInt *rp, k, row; 546071fcb05SBarry Smith PetscInt *ai = a->i, *ailen = a->ilen; 547071fcb05SBarry Smith PetscInt *aj = a->j; 548fff043a9SJunchao Zhang MatScalar *aa, *ap; 549071fcb05SBarry Smith 550071fcb05SBarry Smith PetscFunctionBegin; 5519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 552071fcb05SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 553071fcb05SBarry Smith row = im[k]; 5546bdcaf15SBarry 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); 555071fcb05SBarry Smith rp = aj + ai[row]; 556071fcb05SBarry Smith ap = aa + ai[row]; 55748a46eb9SPierre Jolivet if (!A->was_assembled) PetscCall(PetscMemcpy(rp, in, n * sizeof(PetscInt))); 558071fcb05SBarry Smith if (!A->structure_only) { 559071fcb05SBarry Smith if (v) { 5609566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(ap, v, n * sizeof(PetscScalar))); 561071fcb05SBarry Smith v += n; 562071fcb05SBarry Smith } else { 5639566063dSJacob Faibussowitsch PetscCall(PetscMemzero(ap, n * sizeof(PetscScalar))); 564071fcb05SBarry Smith } 565071fcb05SBarry Smith } 566071fcb05SBarry Smith ailen[row] = n; 567071fcb05SBarry Smith a->nz += n; 568071fcb05SBarry Smith } 5699566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 570071fcb05SBarry Smith PetscFunctionReturn(0); 571071fcb05SBarry Smith } 572071fcb05SBarry Smith 5739371c9d4SSatish Balay PetscErrorCode MatGetValues_SeqAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[]) { 5747eb43aa7SLois Curfman McInnes Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 57597f1f81fSBarry Smith PetscInt *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j; 57697f1f81fSBarry Smith PetscInt *ai = a->i, *ailen = a->ilen; 577fff043a9SJunchao Zhang MatScalar *ap, *aa; 5787eb43aa7SLois Curfman McInnes 5793a40ed3dSBarry Smith PetscFunctionBegin; 5809566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 5817eb43aa7SLois Curfman McInnes for (k = 0; k < m; k++) { /* loop over rows */ 5827eb43aa7SLois Curfman McInnes row = im[k]; 5839371c9d4SSatish Balay if (row < 0) { 5849371c9d4SSatish Balay v += n; 5859371c9d4SSatish Balay continue; 5869371c9d4SSatish Balay } /* negative row */ 58754c59aa7SJacob 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); 5889371c9d4SSatish Balay rp = aj + ai[row]; 5899371c9d4SSatish Balay ap = aa + ai[row]; 5907eb43aa7SLois Curfman McInnes nrow = ailen[row]; 5917eb43aa7SLois Curfman McInnes for (l = 0; l < n; l++) { /* loop over columns */ 5929371c9d4SSatish Balay if (in[l] < 0) { 5939371c9d4SSatish Balay v++; 5949371c9d4SSatish Balay continue; 5959371c9d4SSatish Balay } /* negative column */ 59654c59aa7SJacob 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); 597bfeeae90SHong Zhang col = in[l]; 5989371c9d4SSatish Balay high = nrow; 5999371c9d4SSatish Balay low = 0; /* assume unsorted */ 6007eb43aa7SLois Curfman McInnes while (high - low > 5) { 6017eb43aa7SLois Curfman McInnes t = (low + high) / 2; 6027eb43aa7SLois Curfman McInnes if (rp[t] > col) high = t; 6037eb43aa7SLois Curfman McInnes else low = t; 6047eb43aa7SLois Curfman McInnes } 6057eb43aa7SLois Curfman McInnes for (i = low; i < high; i++) { 6067eb43aa7SLois Curfman McInnes if (rp[i] > col) break; 6077eb43aa7SLois Curfman McInnes if (rp[i] == col) { 608b49de8d1SLois Curfman McInnes *v++ = ap[i]; 6097eb43aa7SLois Curfman McInnes goto finished; 6107eb43aa7SLois Curfman McInnes } 6117eb43aa7SLois Curfman McInnes } 61297e567efSBarry Smith *v++ = 0.0; 6137eb43aa7SLois Curfman McInnes finished:; 6147eb43aa7SLois Curfman McInnes } 6157eb43aa7SLois Curfman McInnes } 6169566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 6173a40ed3dSBarry Smith PetscFunctionReturn(0); 6187eb43aa7SLois Curfman McInnes } 6197eb43aa7SLois Curfman McInnes 6209371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ_Binary(Mat mat, PetscViewer viewer) { 6213ea6fe3dSLisandro Dalcin Mat_SeqAIJ *A = (Mat_SeqAIJ *)mat->data; 622c898d852SStefano Zampini const PetscScalar *av; 6233ea6fe3dSLisandro Dalcin PetscInt header[4], M, N, m, nz, i; 6243ea6fe3dSLisandro Dalcin PetscInt *rowlens; 62517ab2063SBarry Smith 6263a40ed3dSBarry Smith PetscFunctionBegin; 6279566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 6282205254eSKarl Rupp 6293ea6fe3dSLisandro Dalcin M = mat->rmap->N; 6303ea6fe3dSLisandro Dalcin N = mat->cmap->N; 6313ea6fe3dSLisandro Dalcin m = mat->rmap->n; 6323ea6fe3dSLisandro Dalcin nz = A->nz; 633416022c9SBarry Smith 6343ea6fe3dSLisandro Dalcin /* write matrix header */ 6353ea6fe3dSLisandro Dalcin header[0] = MAT_FILE_CLASSID; 6369371c9d4SSatish Balay header[1] = M; 6379371c9d4SSatish Balay header[2] = N; 6389371c9d4SSatish Balay header[3] = nz; 6399566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT)); 640416022c9SBarry Smith 6413ea6fe3dSLisandro Dalcin /* fill in and store row lengths */ 6429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &rowlens)); 6433ea6fe3dSLisandro Dalcin for (i = 0; i < m; i++) rowlens[i] = A->i[i + 1] - A->i[i]; 6449566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, rowlens, m, PETSC_INT)); 6459566063dSJacob Faibussowitsch PetscCall(PetscFree(rowlens)); 6463ea6fe3dSLisandro Dalcin /* store column indices */ 6479566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, A->j, nz, PETSC_INT)); 648416022c9SBarry Smith /* store nonzero values */ 6499566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(mat, &av)); 6509566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, av, nz, PETSC_SCALAR)); 6519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(mat, &av)); 652b37d52dbSMark F. Adams 6533ea6fe3dSLisandro Dalcin /* write block size option to the viewer's .info file */ 6549566063dSJacob Faibussowitsch PetscCall(MatView_Binary_BlockSizes(mat, viewer)); 6553a40ed3dSBarry Smith PetscFunctionReturn(0); 65617ab2063SBarry Smith } 657416022c9SBarry Smith 6589371c9d4SSatish Balay static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A, PetscViewer viewer) { 6597dc0baabSHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 6607dc0baabSHong Zhang PetscInt i, k, m = A->rmap->N; 6617dc0baabSHong Zhang 6627dc0baabSHong Zhang PetscFunctionBegin; 6639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 6647dc0baabSHong Zhang for (i = 0; i < m; i++) { 6659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 66648a46eb9SPierre Jolivet for (k = a->i[i]; k < a->i[i + 1]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ") ", a->j[k])); 6679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 6687dc0baabSHong Zhang } 6699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 6707dc0baabSHong Zhang PetscFunctionReturn(0); 6717dc0baabSHong Zhang } 6727dc0baabSHong Zhang 67309573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat, PetscViewer); 674cd155464SBarry Smith 6759371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ_ASCII(Mat A, PetscViewer viewer) { 676416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 677c898d852SStefano Zampini const PetscScalar *av; 67860e0710aSBarry Smith PetscInt i, j, m = A->rmap->n; 679e060cb09SBarry Smith const char *name; 680f3ef73ceSBarry Smith PetscViewerFormat format; 68117ab2063SBarry Smith 6823a40ed3dSBarry Smith PetscFunctionBegin; 6837dc0baabSHong Zhang if (A->structure_only) { 6849566063dSJacob Faibussowitsch PetscCall(MatView_SeqAIJ_ASCII_structonly(A, viewer)); 6857dc0baabSHong Zhang PetscFunctionReturn(0); 6867dc0baabSHong Zhang } 68743e49210SHong Zhang 6889566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 6892e5835c6SStefano Zampini if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0); 6902e5835c6SStefano Zampini 691c898d852SStefano Zampini /* trigger copy to CPU if needed */ 6929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 6939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 69471c2f376SKris Buschelman if (format == PETSC_VIEWER_ASCII_MATLAB) { 69597f1f81fSBarry Smith PetscInt nofinalvalue = 0; 69660e0710aSBarry Smith if (m && ((a->i[m] == a->i[m - 1]) || (a->j[a->nz - 1] != A->cmap->n - 1))) { 697c337ccceSJed Brown /* Need a dummy value to ensure the dimension of the matrix. */ 698d00d2cf4SBarry Smith nofinalvalue = 1; 699d00d2cf4SBarry Smith } 7009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 7019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", m, A->cmap->n)); 7029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Nonzeros = %" PetscInt_FMT " \n", a->nz)); 703fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX) 7049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = zeros(%" PetscInt_FMT ",4);\n", a->nz + nofinalvalue)); 705fbfe6fa7SJed Brown #else 7069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = zeros(%" PetscInt_FMT ",3);\n", a->nz + nofinalvalue)); 707fbfe6fa7SJed Brown #endif 7089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = [\n")); 70917ab2063SBarry Smith 71017ab2063SBarry Smith for (i = 0; i < m; i++) { 71160e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 712aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 7139566063dSJacob 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]))); 71417ab2063SBarry Smith #else 7159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %18.16e\n", i + 1, a->j[j] + 1, (double)a->a[j])); 71617ab2063SBarry Smith #endif 71717ab2063SBarry Smith } 71817ab2063SBarry Smith } 719d00d2cf4SBarry Smith if (nofinalvalue) { 720c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX) 7219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %18.16e %18.16e\n", m, A->cmap->n, 0., 0.)); 722c337ccceSJed Brown #else 7239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %18.16e\n", m, A->cmap->n, 0.0)); 724c337ccceSJed Brown #endif 725d00d2cf4SBarry Smith } 7269566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)A, &name)); 7279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "];\n %s = spconvert(zzz);\n", name)); 7289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 729fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_COMMON) { 7309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 73144cd7ae7SLois Curfman McInnes for (i = 0; i < m; i++) { 7329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 73360e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 734aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 73536db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) { 7369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 73736db0b34SBarry Smith } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) { 7389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)-PetscImaginaryPart(a->a[j]))); 73936db0b34SBarry Smith } else if (PetscRealPart(a->a[j]) != 0.0) { 7409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 7416831982aSBarry Smith } 74244cd7ae7SLois Curfman McInnes #else 7439566063dSJacob Faibussowitsch if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 74444cd7ae7SLois Curfman McInnes #endif 74544cd7ae7SLois Curfman McInnes } 7469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 74744cd7ae7SLois Curfman McInnes } 7489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 749fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_SYMMODU) { 75097f1f81fSBarry Smith PetscInt nzd = 0, fshift = 1, *sptr; 7519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 7529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &sptr)); 753496be53dSLois Curfman McInnes for (i = 0; i < m; i++) { 754496be53dSLois Curfman McInnes sptr[i] = nzd + 1; 75560e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 756496be53dSLois Curfman McInnes if (a->j[j] >= i) { 757aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 75836db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++; 759496be53dSLois Curfman McInnes #else 760496be53dSLois Curfman McInnes if (a->a[j] != 0.0) nzd++; 761496be53dSLois Curfman McInnes #endif 762496be53dSLois Curfman McInnes } 763496be53dSLois Curfman McInnes } 764496be53dSLois Curfman McInnes } 7652e44a96cSLois Curfman McInnes sptr[m] = nzd + 1; 7669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT "\n\n", m, nzd)); 7672e44a96cSLois Curfman McInnes for (i = 0; i < m + 1; i += 6) { 7682205254eSKarl Rupp if (i + 4 < m) { 7699566063dSJacob 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])); 7702205254eSKarl Rupp } else if (i + 3 < m) { 7719566063dSJacob 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])); 7722205254eSKarl Rupp } else if (i + 2 < m) { 7739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2], sptr[i + 3])); 7742205254eSKarl Rupp } else if (i + 1 < m) { 7759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2])); 7762205254eSKarl Rupp } else if (i < m) { 7779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1])); 7782205254eSKarl Rupp } else { 7799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "\n", sptr[i])); 7802205254eSKarl Rupp } 781496be53dSLois Curfman McInnes } 7829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 7839566063dSJacob Faibussowitsch PetscCall(PetscFree(sptr)); 784496be53dSLois Curfman McInnes for (i = 0; i < m; i++) { 78560e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 7869566063dSJacob Faibussowitsch if (a->j[j] >= i) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " ", a->j[j] + fshift)); 787496be53dSLois Curfman McInnes } 7889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 789496be53dSLois Curfman McInnes } 7909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 791496be53dSLois Curfman McInnes for (i = 0; i < m; i++) { 79260e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 793496be53dSLois Curfman McInnes if (a->j[j] >= i) { 794aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 79548a46eb9SPierre 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]))); 796496be53dSLois Curfman McInnes #else 7979566063dSJacob Faibussowitsch if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " %18.16e ", (double)a->a[j])); 798496be53dSLois Curfman McInnes #endif 799496be53dSLois Curfman McInnes } 800496be53dSLois Curfman McInnes } 8019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 802496be53dSLois Curfman McInnes } 8039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 804fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_DENSE) { 80597f1f81fSBarry Smith PetscInt cnt = 0, jcnt; 80687828ca2SBarry Smith PetscScalar value; 80768f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX) 80868f1ed48SBarry Smith PetscBool realonly = PETSC_TRUE; 80968f1ed48SBarry Smith 81068f1ed48SBarry Smith for (i = 0; i < a->i[m]; i++) { 81168f1ed48SBarry Smith if (PetscImaginaryPart(a->a[i]) != 0.0) { 81268f1ed48SBarry Smith realonly = PETSC_FALSE; 81368f1ed48SBarry Smith break; 81468f1ed48SBarry Smith } 81568f1ed48SBarry Smith } 81668f1ed48SBarry Smith #endif 81702594712SBarry Smith 8189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 81902594712SBarry Smith for (i = 0; i < m; i++) { 82002594712SBarry Smith jcnt = 0; 821d0f46423SBarry Smith for (j = 0; j < A->cmap->n; j++) { 822e24b481bSBarry Smith if (jcnt < a->i[i + 1] - a->i[i] && j == a->j[cnt]) { 82302594712SBarry Smith value = a->a[cnt++]; 824e24b481bSBarry Smith jcnt++; 82502594712SBarry Smith } else { 82602594712SBarry Smith value = 0.0; 82702594712SBarry Smith } 828aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 82968f1ed48SBarry Smith if (realonly) { 8309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e ", (double)PetscRealPart(value))); 83168f1ed48SBarry Smith } else { 8329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e+%7.5e i ", (double)PetscRealPart(value), (double)PetscImaginaryPart(value))); 83368f1ed48SBarry Smith } 83402594712SBarry Smith #else 8359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e ", (double)value)); 83602594712SBarry Smith #endif 83702594712SBarry Smith } 8389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 83902594712SBarry Smith } 8409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 8413c215bfdSMatthew Knepley } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) { 842150b93efSMatthew G. Knepley PetscInt fshift = 1; 8439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 8443c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX) 8459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%%%%MatrixMarket matrix coordinate complex general\n")); 8463c215bfdSMatthew Knepley #else 8479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%%%%MatrixMarket matrix coordinate real general\n")); 8483c215bfdSMatthew Knepley #endif 8499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", m, A->cmap->n, a->nz)); 8503c215bfdSMatthew Knepley for (i = 0; i < m; i++) { 85160e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 8523c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX) 8539566063dSJacob 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]))); 8543c215bfdSMatthew Knepley #else 8559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %g\n", i + fshift, a->j[j] + fshift, (double)a->a[j])); 8563c215bfdSMatthew Knepley #endif 8573c215bfdSMatthew Knepley } 8583c215bfdSMatthew Knepley } 8599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 8603a40ed3dSBarry Smith } else { 8619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 862d5f3da31SBarry Smith if (A->factortype) { 86316cd7e1dSShri Abhyankar for (i = 0; i < m; i++) { 8649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 86516cd7e1dSShri Abhyankar /* L part */ 86660e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 86716cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 86816cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 8699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 87016cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 8719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)(-PetscImaginaryPart(a->a[j])))); 87216cd7e1dSShri Abhyankar } else { 8739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 87416cd7e1dSShri Abhyankar } 87516cd7e1dSShri Abhyankar #else 8769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 87716cd7e1dSShri Abhyankar #endif 87816cd7e1dSShri Abhyankar } 87916cd7e1dSShri Abhyankar /* diagonal */ 88016cd7e1dSShri Abhyankar j = a->diag[i]; 88116cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 88216cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 8839566063dSJacob 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]))); 88416cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 8859566063dSJacob 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])))); 88616cd7e1dSShri Abhyankar } else { 8879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(1.0 / a->a[j]))); 88816cd7e1dSShri Abhyankar } 88916cd7e1dSShri Abhyankar #else 8909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)(1.0 / a->a[j]))); 89116cd7e1dSShri Abhyankar #endif 89216cd7e1dSShri Abhyankar 89316cd7e1dSShri Abhyankar /* U part */ 89460e0710aSBarry Smith for (j = a->diag[i + 1] + 1; j < a->diag[i]; j++) { 89516cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 89616cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 8979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 89816cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 8999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)(-PetscImaginaryPart(a->a[j])))); 90016cd7e1dSShri Abhyankar } else { 9019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 90216cd7e1dSShri Abhyankar } 90316cd7e1dSShri Abhyankar #else 9049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 90516cd7e1dSShri Abhyankar #endif 90616cd7e1dSShri Abhyankar } 9079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 90816cd7e1dSShri Abhyankar } 90916cd7e1dSShri Abhyankar } else { 91017ab2063SBarry Smith for (i = 0; i < m; i++) { 9119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 91260e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 913aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 91436db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) > 0.0) { 9159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 91636db0b34SBarry Smith } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 9179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)-PetscImaginaryPart(a->a[j]))); 9183a40ed3dSBarry Smith } else { 9199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 92017ab2063SBarry Smith } 92117ab2063SBarry Smith #else 9229566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 92317ab2063SBarry Smith #endif 92417ab2063SBarry Smith } 9259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 92617ab2063SBarry Smith } 92716cd7e1dSShri Abhyankar } 9289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 92917ab2063SBarry Smith } 9309566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 9313a40ed3dSBarry Smith PetscFunctionReturn(0); 932416022c9SBarry Smith } 933416022c9SBarry Smith 9349804daf3SBarry Smith #include <petscdraw.h> 9359371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw, void *Aa) { 936480ef9eaSBarry Smith Mat A = (Mat)Aa; 937416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 938383922c3SLisandro Dalcin PetscInt i, j, m = A->rmap->n; 939383922c3SLisandro Dalcin int color; 940b05fc000SLisandro Dalcin PetscReal xl, yl, xr, yr, x_l, x_r, y_l, y_r; 941b0a32e0cSBarry Smith PetscViewer viewer; 942f3ef73ceSBarry Smith PetscViewerFormat format; 943fff043a9SJunchao Zhang const PetscScalar *aa; 944cddf8d76SBarry Smith 9453a40ed3dSBarry Smith PetscFunctionBegin; 9469566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer)); 9479566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 9489566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr)); 949383922c3SLisandro Dalcin 950416022c9SBarry Smith /* loop over matrix elements drawing boxes */ 9519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 952fb9695e5SSatish Balay if (format != PETSC_VIEWER_DRAW_CONTOUR) { 953d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 9540513a670SBarry Smith /* Blue for negative, Cyan for zero and Red for positive */ 955b0a32e0cSBarry Smith color = PETSC_DRAW_BLUE; 956416022c9SBarry Smith for (i = 0; i < m; i++) { 9579371c9d4SSatish Balay y_l = m - i - 1.0; 9589371c9d4SSatish Balay y_r = y_l + 1.0; 959bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 9609371c9d4SSatish Balay x_l = a->j[j]; 9619371c9d4SSatish Balay x_r = x_l + 1.0; 962fff043a9SJunchao Zhang if (PetscRealPart(aa[j]) >= 0.) continue; 9639566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 964cddf8d76SBarry Smith } 965cddf8d76SBarry Smith } 966b0a32e0cSBarry Smith color = PETSC_DRAW_CYAN; 967cddf8d76SBarry Smith for (i = 0; i < m; i++) { 9689371c9d4SSatish Balay y_l = m - i - 1.0; 9699371c9d4SSatish Balay y_r = y_l + 1.0; 970bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 9719371c9d4SSatish Balay x_l = a->j[j]; 9729371c9d4SSatish Balay x_r = x_l + 1.0; 973fff043a9SJunchao Zhang if (aa[j] != 0.) continue; 9749566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 975cddf8d76SBarry Smith } 976cddf8d76SBarry Smith } 977b0a32e0cSBarry Smith color = PETSC_DRAW_RED; 978cddf8d76SBarry Smith for (i = 0; i < m; i++) { 9799371c9d4SSatish Balay y_l = m - i - 1.0; 9809371c9d4SSatish Balay y_r = y_l + 1.0; 981bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 9829371c9d4SSatish Balay x_l = a->j[j]; 9839371c9d4SSatish Balay x_r = x_l + 1.0; 984fff043a9SJunchao Zhang if (PetscRealPart(aa[j]) <= 0.) continue; 9859566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 986416022c9SBarry Smith } 987416022c9SBarry Smith } 988d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 9890513a670SBarry Smith } else { 9900513a670SBarry Smith /* use contour shading to indicate magnitude of values */ 9910513a670SBarry Smith /* first determine max of all nonzero values */ 992b05fc000SLisandro Dalcin PetscReal minv = 0.0, maxv = 0.0; 993383922c3SLisandro Dalcin PetscInt nz = a->nz, count = 0; 994b0a32e0cSBarry Smith PetscDraw popup; 9950513a670SBarry Smith 9960513a670SBarry Smith for (i = 0; i < nz; i++) { 997fff043a9SJunchao Zhang if (PetscAbsScalar(aa[i]) > maxv) maxv = PetscAbsScalar(aa[i]); 9980513a670SBarry Smith } 999383922c3SLisandro Dalcin if (minv >= maxv) maxv = minv + PETSC_SMALL; 10009566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 10019566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, minv, maxv)); 1002383922c3SLisandro Dalcin 1003d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 10040513a670SBarry Smith for (i = 0; i < m; i++) { 1005383922c3SLisandro Dalcin y_l = m - i - 1.0; 1006383922c3SLisandro Dalcin y_r = y_l + 1.0; 1007bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 1008383922c3SLisandro Dalcin x_l = a->j[j]; 1009383922c3SLisandro Dalcin x_r = x_l + 1.0; 1010fff043a9SJunchao Zhang color = PetscDrawRealToColor(PetscAbsScalar(aa[count]), minv, maxv); 10119566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 10120513a670SBarry Smith count++; 10130513a670SBarry Smith } 10140513a670SBarry Smith } 1015d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 10160513a670SBarry Smith } 10179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 1018480ef9eaSBarry Smith PetscFunctionReturn(0); 1019480ef9eaSBarry Smith } 1020cddf8d76SBarry Smith 10219804daf3SBarry Smith #include <petscdraw.h> 10229371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ_Draw(Mat A, PetscViewer viewer) { 1023b0a32e0cSBarry Smith PetscDraw draw; 102436db0b34SBarry Smith PetscReal xr, yr, xl, yl, h, w; 1025ace3abfcSBarry Smith PetscBool isnull; 1026480ef9eaSBarry Smith 1027480ef9eaSBarry Smith PetscFunctionBegin; 10289566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 10299566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 1030480ef9eaSBarry Smith if (isnull) PetscFunctionReturn(0); 1031480ef9eaSBarry Smith 10329371c9d4SSatish Balay xr = A->cmap->n; 10339371c9d4SSatish Balay yr = A->rmap->n; 10349371c9d4SSatish Balay h = yr / 10.0; 10359371c9d4SSatish Balay w = xr / 10.0; 10369371c9d4SSatish Balay xr += w; 10379371c9d4SSatish Balay yr += h; 10389371c9d4SSatish Balay xl = -w; 10399371c9d4SSatish Balay yl = -h; 10409566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr)); 10419566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer)); 10429566063dSJacob Faibussowitsch PetscCall(PetscDrawZoom(draw, MatView_SeqAIJ_Draw_Zoom, A)); 10439566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL)); 10449566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 10453a40ed3dSBarry Smith PetscFunctionReturn(0); 1046416022c9SBarry Smith } 1047416022c9SBarry Smith 10489371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ(Mat A, PetscViewer viewer) { 1049ace3abfcSBarry Smith PetscBool iascii, isbinary, isdraw; 1050416022c9SBarry Smith 10513a40ed3dSBarry Smith PetscFunctionBegin; 10529566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 10539566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 10549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 10551baa6e33SBarry Smith if (iascii) PetscCall(MatView_SeqAIJ_ASCII(A, viewer)); 10561baa6e33SBarry Smith else if (isbinary) PetscCall(MatView_SeqAIJ_Binary(A, viewer)); 10571baa6e33SBarry Smith else if (isdraw) PetscCall(MatView_SeqAIJ_Draw(A, viewer)); 10589566063dSJacob Faibussowitsch PetscCall(MatView_SeqAIJ_Inode(A, viewer)); 10593a40ed3dSBarry Smith PetscFunctionReturn(0); 106017ab2063SBarry Smith } 106119bcc07fSBarry Smith 10629371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A, MatAssemblyType mode) { 1063416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1064580bdb30SBarry Smith PetscInt fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax; 1065d0f46423SBarry Smith PetscInt m = A->rmap->n, *ip, N, *ailen = a->ilen, rmax = 0; 106654f21887SBarry Smith MatScalar *aa = a->a, *ap; 10673447b6efSHong Zhang PetscReal ratio = 0.6; 106817ab2063SBarry Smith 10693a40ed3dSBarry Smith PetscFunctionBegin; 10703a40ed3dSBarry Smith if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 10719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 1072b215bc84SStefano Zampini if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) { 1073b215bc84SStefano Zampini /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */ 10749566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A, mode)); 1075b215bc84SStefano Zampini PetscFunctionReturn(0); 1076b215bc84SStefano Zampini } 107717ab2063SBarry Smith 107843ee02c3SBarry Smith if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 107917ab2063SBarry Smith for (i = 1; i < m; i++) { 1080416022c9SBarry Smith /* move each row back by the amount of empty slots (fshift) before it*/ 108117ab2063SBarry Smith fshift += imax[i - 1] - ailen[i - 1]; 108294a9d846SBarry Smith rmax = PetscMax(rmax, ailen[i]); 108317ab2063SBarry Smith if (fshift) { 1084bfeeae90SHong Zhang ip = aj + ai[i]; 1085bfeeae90SHong Zhang ap = aa + ai[i]; 108617ab2063SBarry Smith N = ailen[i]; 10879566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ip - fshift, ip, N)); 108848a46eb9SPierre Jolivet if (!A->structure_only) PetscCall(PetscArraymove(ap - fshift, ap, N)); 108917ab2063SBarry Smith } 109017ab2063SBarry Smith ai[i] = ai[i - 1] + ailen[i - 1]; 109117ab2063SBarry Smith } 109217ab2063SBarry Smith if (m) { 109317ab2063SBarry Smith fshift += imax[m - 1] - ailen[m - 1]; 109417ab2063SBarry Smith ai[m] = ai[m - 1] + ailen[m - 1]; 109517ab2063SBarry Smith } 10967b083b7cSBarry Smith 109717ab2063SBarry Smith /* reset ilen and imax for each row */ 10987b083b7cSBarry Smith a->nonzerorowcnt = 0; 1099396832f4SHong Zhang if (A->structure_only) { 11009566063dSJacob Faibussowitsch PetscCall(PetscFree(a->imax)); 11019566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ilen)); 1102396832f4SHong Zhang } else { /* !A->structure_only */ 110317ab2063SBarry Smith for (i = 0; i < m; i++) { 110417ab2063SBarry Smith ailen[i] = imax[i] = ai[i + 1] - ai[i]; 11057b083b7cSBarry Smith a->nonzerorowcnt += ((ai[i + 1] - ai[i]) > 0); 110617ab2063SBarry Smith } 1107396832f4SHong Zhang } 1108bfeeae90SHong Zhang a->nz = ai[m]; 1109aed4548fSBarry 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); 111017ab2063SBarry Smith 11119566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 11129566063dSJacob 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)); 11139566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues() is %" PetscInt_FMT "\n", a->reallocs)); 11149566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Maximum nonzeros in any row is %" PetscInt_FMT "\n", rmax)); 11152205254eSKarl Rupp 11168e58a170SBarry Smith A->info.mallocs += a->reallocs; 1117dd5f02e7SSatish Balay a->reallocs = 0; 11186712e2f1SBarry Smith A->info.nz_unneeded = (PetscReal)fshift; 111936db0b34SBarry Smith a->rmax = rmax; 11204e220ebcSLois Curfman McInnes 112148a46eb9SPierre Jolivet if (!A->structure_only) PetscCall(MatCheckCompressedRow(A, a->nonzerorowcnt, &a->compressedrow, a->i, m, ratio)); 11229566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A, mode)); 11233a40ed3dSBarry Smith PetscFunctionReturn(0); 112417ab2063SBarry Smith } 112517ab2063SBarry Smith 11269371c9d4SSatish Balay PetscErrorCode MatRealPart_SeqAIJ(Mat A) { 112799cafbc1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 112899cafbc1SBarry Smith PetscInt i, nz = a->nz; 11292e5835c6SStefano Zampini MatScalar *aa; 113099cafbc1SBarry Smith 113199cafbc1SBarry Smith PetscFunctionBegin; 11329566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 113399cafbc1SBarry Smith for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]); 11349566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 11359566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 113699cafbc1SBarry Smith PetscFunctionReturn(0); 113799cafbc1SBarry Smith } 113899cafbc1SBarry Smith 11399371c9d4SSatish Balay PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A) { 114099cafbc1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 114199cafbc1SBarry Smith PetscInt i, nz = a->nz; 11422e5835c6SStefano Zampini MatScalar *aa; 114399cafbc1SBarry Smith 114499cafbc1SBarry Smith PetscFunctionBegin; 11459566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 114699cafbc1SBarry Smith for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]); 11479566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 11489566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 114999cafbc1SBarry Smith PetscFunctionReturn(0); 115099cafbc1SBarry Smith } 115199cafbc1SBarry Smith 11529371c9d4SSatish Balay PetscErrorCode MatZeroEntries_SeqAIJ(Mat A) { 1153fff043a9SJunchao Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1154fff043a9SJunchao Zhang MatScalar *aa; 11553a40ed3dSBarry Smith 11563a40ed3dSBarry Smith PetscFunctionBegin; 11579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayWrite(A, &aa)); 11589566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(aa, a->i[A->rmap->n])); 11599566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayWrite(A, &aa)); 11609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 11613a40ed3dSBarry Smith PetscFunctionReturn(0); 116217ab2063SBarry Smith } 1163416022c9SBarry Smith 11649371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatResetPreallocationCOO_SeqAIJ(Mat A) { 1165cbc6b225SStefano Zampini Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1166cbc6b225SStefano Zampini 1167cbc6b225SStefano Zampini PetscFunctionBegin; 11689566063dSJacob Faibussowitsch PetscCall(PetscFree(a->perm)); 11699566063dSJacob Faibussowitsch PetscCall(PetscFree(a->jmap)); 1170cbc6b225SStefano Zampini PetscFunctionReturn(0); 1171cbc6b225SStefano Zampini } 1172cbc6b225SStefano Zampini 11739371c9d4SSatish Balay PetscErrorCode MatDestroy_SeqAIJ(Mat A) { 1174416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1175d5d45c9bSBarry Smith 11763a40ed3dSBarry Smith PetscFunctionBegin; 1177aa482453SBarry Smith #if defined(PETSC_USE_LOG) 1178c0aa6a63SJacob Faibussowitsch PetscLogObjectState((PetscObject)A, "Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT, A->rmap->n, A->cmap->n, a->nz); 117917ab2063SBarry Smith #endif 11809566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(A, &a->a, &a->j, &a->i)); 11819566063dSJacob Faibussowitsch PetscCall(MatResetPreallocationCOO_SeqAIJ(A)); 11829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 11839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 11849566063dSJacob Faibussowitsch PetscCall(PetscFree(a->diag)); 11859566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ibdiag)); 11869566063dSJacob Faibussowitsch PetscCall(PetscFree(a->imax)); 11879566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ilen)); 11889566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ipre)); 11899566063dSJacob Faibussowitsch PetscCall(PetscFree3(a->idiag, a->mdiag, a->ssor_work)); 11909566063dSJacob Faibussowitsch PetscCall(PetscFree(a->solve_work)); 11919566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 11929566063dSJacob Faibussowitsch PetscCall(PetscFree(a->saved_values)); 11939566063dSJacob Faibussowitsch PetscCall(PetscFree2(a->compressedrow.i, a->compressedrow.rindex)); 11949566063dSJacob Faibussowitsch PetscCall(MatDestroy_SeqAIJ_Inode(A)); 11959566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 1196901853e0SKris Buschelman 11976718818eSStefano Zampini /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this. 11986718818eSStefano Zampini That function is so heavily used (sometimes in an hidden way through multnumeric function pointers) 11996718818eSStefano Zampini that is hard to properly add this data to the MatProduct data. We free it here to avoid 12006718818eSStefano Zampini users reusing the matrix object with different data to incur in obscure segmentation faults 12016718818eSStefano Zampini due to different matrix sizes */ 12029566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc__ab_dense", NULL)); 12036718818eSStefano Zampini 12049566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL)); 12052e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "PetscMatlabEnginePut_C", NULL)); 12062e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "PetscMatlabEngineGet_C", NULL)); 12079566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetColumnIndices_C", NULL)); 12089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatStoreValues_C", NULL)); 12099566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatRetrieveValues_C", NULL)); 12109566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqsbaij_C", NULL)); 12119566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqbaij_C", NULL)); 12129566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijperm_C", NULL)); 12132e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijsell_C", NULL)); 12142e956fe4SStefano Zampini #if defined(PETSC_HAVE_MKL_SPARSE) 12152e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijmkl_C", NULL)); 12162e956fe4SStefano Zampini #endif 12174222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA) 12189566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijcusparse_C", NULL)); 12199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_seqaij_C", NULL)); 12209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaijcusparse_C", NULL)); 12214222ddf1SHong Zhang #endif 12223d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 12239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijkokkos_C", NULL)); 12243d0639e7SStefano Zampini #endif 12259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijcrl_C", NULL)); 1226af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 12279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_elemental_C", NULL)); 1228af8000cdSHong Zhang #endif 1229d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 12309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_scalapack_C", NULL)); 1231d24d4204SJose E. Roman #endif 123263c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 12339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_hypre_C", NULL)); 12349566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_transpose_seqaij_seqaij_C", NULL)); 123563c07aadSStefano Zampini #endif 12369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqdense_C", NULL)); 12379566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqsell_C", NULL)); 12389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_is_C", NULL)); 12399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatIsTranspose_C", NULL)); 12402e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatIsHermitianTranspose_C", NULL)); 12419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", NULL)); 12429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatResetPreallocation_C", NULL)); 12439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetPreallocationCSR_C", NULL)); 12449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatReorderForNonzeroDiagonal_C", NULL)); 12459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_is_seqaij_C", NULL)); 12469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqdense_seqaij_C", NULL)); 12479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaij_C", NULL)); 12489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJKron_C", NULL)); 12499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 12509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 12512e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL)); 12522e956fe4SStefano Zampini /* these calls do not belong here: the subclasses Duplicate/Destroy are wrong */ 12532e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaijsell_seqaij_C", NULL)); 12542e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaijperm_seqaij_C", NULL)); 12552e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijviennacl_C", NULL)); 12562e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijviennacl_seqdense_C", NULL)); 12572e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijviennacl_seqaij_C", NULL)); 12583a40ed3dSBarry Smith PetscFunctionReturn(0); 125917ab2063SBarry Smith } 126017ab2063SBarry Smith 12619371c9d4SSatish Balay PetscErrorCode MatSetOption_SeqAIJ(Mat A, MatOption op, PetscBool flg) { 1262416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 12633a40ed3dSBarry Smith 12643a40ed3dSBarry Smith PetscFunctionBegin; 1265a65d3064SKris Buschelman switch (op) { 12669371c9d4SSatish Balay case MAT_ROW_ORIENTED: a->roworiented = flg; break; 12679371c9d4SSatish Balay case MAT_KEEP_NONZERO_PATTERN: a->keepnonzeropattern = flg; break; 12689371c9d4SSatish Balay case MAT_NEW_NONZERO_LOCATIONS: a->nonew = (flg ? 0 : 1); break; 12699371c9d4SSatish Balay case MAT_NEW_NONZERO_LOCATION_ERR: a->nonew = (flg ? -1 : 0); break; 12709371c9d4SSatish Balay case MAT_NEW_NONZERO_ALLOCATION_ERR: a->nonew = (flg ? -2 : 0); break; 12719371c9d4SSatish Balay case MAT_UNUSED_NONZERO_LOCATION_ERR: a->nounused = (flg ? -1 : 0); break; 12729371c9d4SSatish Balay case MAT_IGNORE_ZERO_ENTRIES: a->ignorezeroentries = flg; break; 12733d472b54SHong Zhang case MAT_SPD: 1274b1646e73SJed Brown case MAT_SYMMETRIC: 1275b1646e73SJed Brown case MAT_STRUCTURALLY_SYMMETRIC: 1276b1646e73SJed Brown case MAT_HERMITIAN: 1277b1646e73SJed Brown case MAT_SYMMETRY_ETERNAL: 1278957cac9fSHong Zhang case MAT_STRUCTURE_ONLY: 1279b94d7dedSBarry Smith case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 1280b94d7dedSBarry Smith case MAT_SPD_ETERNAL: 1281b94d7dedSBarry Smith /* if the diagonal matrix is square it inherits some of the properties above */ 12825021d80fSJed Brown break; 12838c78258cSHong Zhang case MAT_FORCE_DIAGONAL_ENTRIES: 1284a65d3064SKris Buschelman case MAT_IGNORE_OFF_PROC_ENTRIES: 12859371c9d4SSatish Balay case MAT_USE_HASH_TABLE: PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op])); break; 12869371c9d4SSatish Balay case MAT_USE_INODES: PetscCall(MatSetOption_SeqAIJ_Inode(A, MAT_USE_INODES, flg)); break; 12879371c9d4SSatish Balay case MAT_SUBMAT_SINGLEIS: A->submat_singleis = flg; break; 1288071fcb05SBarry Smith case MAT_SORTED_FULL: 1289071fcb05SBarry Smith if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 1290071fcb05SBarry Smith else A->ops->setvalues = MatSetValues_SeqAIJ; 1291071fcb05SBarry Smith break; 12929371c9d4SSatish Balay case MAT_FORM_EXPLICIT_TRANSPOSE: A->form_explicit_transpose = flg; break; 12939371c9d4SSatish Balay default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %d", op); 1294a65d3064SKris Buschelman } 12953a40ed3dSBarry Smith PetscFunctionReturn(0); 129617ab2063SBarry Smith } 129717ab2063SBarry Smith 12989371c9d4SSatish Balay PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A, Vec v) { 1299416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1300fdc842d1SBarry Smith PetscInt i, j, n, *ai = a->i, *aj = a->j; 1301c898d852SStefano Zampini PetscScalar *x; 1302c898d852SStefano Zampini const PetscScalar *aa; 130317ab2063SBarry Smith 13043a40ed3dSBarry Smith PetscFunctionBegin; 13059566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 130608401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 13079566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 1308d5f3da31SBarry Smith if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) { 1309d3e70bfaSHong Zhang PetscInt *diag = a->diag; 13109566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 13112c990fa1SHong Zhang for (i = 0; i < n; i++) x[i] = 1.0 / aa[diag[i]]; 13129566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 13139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 131435e7444dSHong Zhang PetscFunctionReturn(0); 131535e7444dSHong Zhang } 131635e7444dSHong Zhang 13179566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 131835e7444dSHong Zhang for (i = 0; i < n; i++) { 1319fdc842d1SBarry Smith x[i] = 0.0; 132035e7444dSHong Zhang for (j = ai[i]; j < ai[i + 1]; j++) { 132135e7444dSHong Zhang if (aj[j] == i) { 132235e7444dSHong Zhang x[i] = aa[j]; 132317ab2063SBarry Smith break; 132417ab2063SBarry Smith } 132517ab2063SBarry Smith } 132617ab2063SBarry Smith } 13279566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 13289566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 13293a40ed3dSBarry Smith PetscFunctionReturn(0); 133017ab2063SBarry Smith } 133117ab2063SBarry Smith 1332c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 13339371c9d4SSatish Balay PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A, Vec xx, Vec zz, Vec yy) { 1334416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 13355f22a7b3SSebastian Grimberg const MatScalar *aa; 1336d9ca1df4SBarry Smith PetscScalar *y; 1337d9ca1df4SBarry Smith const PetscScalar *x; 1338d0f46423SBarry Smith PetscInt m = A->rmap->n; 13395c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 13405f22a7b3SSebastian Grimberg const MatScalar *v; 1341a77337e4SBarry Smith PetscScalar alpha; 1342d9ca1df4SBarry Smith PetscInt n, i, j; 1343d9ca1df4SBarry Smith const PetscInt *idx, *ii, *ridx = NULL; 13443447b6efSHong Zhang Mat_CompressedRow cprow = a->compressedrow; 1345ace3abfcSBarry Smith PetscBool usecprow = cprow.use; 13465c897100SBarry Smith #endif 134717ab2063SBarry Smith 13483a40ed3dSBarry Smith PetscFunctionBegin; 13499566063dSJacob Faibussowitsch if (zz != yy) PetscCall(VecCopy(zz, yy)); 13509566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 13519566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy, &y)); 13529566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 13535c897100SBarry Smith 13545c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 1355fff043a9SJunchao Zhang fortranmulttransposeaddaij_(&m, x, a->i, a->j, aa, y); 13565c897100SBarry Smith #else 13573447b6efSHong Zhang if (usecprow) { 13583447b6efSHong Zhang m = cprow.nrows; 13593447b6efSHong Zhang ii = cprow.i; 13607b2bb3b9SHong Zhang ridx = cprow.rindex; 13613447b6efSHong Zhang } else { 13623447b6efSHong Zhang ii = a->i; 13633447b6efSHong Zhang } 136417ab2063SBarry Smith for (i = 0; i < m; i++) { 13653447b6efSHong Zhang idx = a->j + ii[i]; 1366fff043a9SJunchao Zhang v = aa + ii[i]; 13673447b6efSHong Zhang n = ii[i + 1] - ii[i]; 13683447b6efSHong Zhang if (usecprow) { 13697b2bb3b9SHong Zhang alpha = x[ridx[i]]; 13703447b6efSHong Zhang } else { 137117ab2063SBarry Smith alpha = x[i]; 13723447b6efSHong Zhang } 137304fbf559SBarry Smith for (j = 0; j < n; j++) y[idx[j]] += alpha * v[j]; 137417ab2063SBarry Smith } 13755c897100SBarry Smith #endif 13769566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 13779566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 13789566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy, &y)); 13799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 13803a40ed3dSBarry Smith PetscFunctionReturn(0); 138117ab2063SBarry Smith } 138217ab2063SBarry Smith 13839371c9d4SSatish Balay PetscErrorCode MatMultTranspose_SeqAIJ(Mat A, Vec xx, Vec yy) { 13845c897100SBarry Smith PetscFunctionBegin; 13859566063dSJacob Faibussowitsch PetscCall(VecSet(yy, 0.0)); 13869566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd_SeqAIJ(A, xx, yy, yy)); 13875c897100SBarry Smith PetscFunctionReturn(0); 13885c897100SBarry Smith } 13895c897100SBarry Smith 1390c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 139178b84d54SShri Abhyankar 13929371c9d4SSatish Balay PetscErrorCode MatMult_SeqAIJ(Mat A, Vec xx, Vec yy) { 1393416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1394d9fead3dSBarry Smith PetscScalar *y; 139554f21887SBarry Smith const PetscScalar *x; 1396fff043a9SJunchao Zhang const MatScalar *aa, *a_a; 1397003131ecSBarry Smith PetscInt m = A->rmap->n; 13980298fd71SBarry Smith const PetscInt *aj, *ii, *ridx = NULL; 13997b083b7cSBarry Smith PetscInt n, i; 1400362ced78SSatish Balay PetscScalar sum; 1401ace3abfcSBarry Smith PetscBool usecprow = a->compressedrow.use; 140217ab2063SBarry Smith 1403b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 140497952fefSHong Zhang #pragma disjoint(*x, *y, *aa) 1405fee21e36SBarry Smith #endif 1406fee21e36SBarry Smith 14073a40ed3dSBarry Smith PetscFunctionBegin; 1408b215bc84SStefano Zampini if (a->inode.use && a->inode.checked) { 14099566063dSJacob Faibussowitsch PetscCall(MatMult_SeqAIJ_Inode(A, xx, yy)); 1410b215bc84SStefano Zampini PetscFunctionReturn(0); 1411b215bc84SStefano Zampini } 14129566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 14139566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 14149566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy, &y)); 1415416022c9SBarry Smith ii = a->i; 14164eb6d288SHong Zhang if (usecprow) { /* use compressed row format */ 14179566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(y, m)); 141897952fefSHong Zhang m = a->compressedrow.nrows; 141997952fefSHong Zhang ii = a->compressedrow.i; 142097952fefSHong Zhang ridx = a->compressedrow.rindex; 142197952fefSHong Zhang for (i = 0; i < m; i++) { 142297952fefSHong Zhang n = ii[i + 1] - ii[i]; 142397952fefSHong Zhang aj = a->j + ii[i]; 1424fff043a9SJunchao Zhang aa = a_a + ii[i]; 142597952fefSHong Zhang sum = 0.0; 1426003131ecSBarry Smith PetscSparseDensePlusDot(sum, x, aa, aj, n); 1427003131ecSBarry Smith /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 142897952fefSHong Zhang y[*ridx++] = sum; 142997952fefSHong Zhang } 143097952fefSHong Zhang } else { /* do not use compressed row format */ 1431b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ) 14323d3eaba7SBarry Smith aj = a->j; 1433fff043a9SJunchao Zhang aa = a_a; 1434b05257ddSBarry Smith fortranmultaij_(&m, x, ii, aj, aa, y); 1435b05257ddSBarry Smith #else 143617ab2063SBarry Smith for (i = 0; i < m; i++) { 1437003131ecSBarry Smith n = ii[i + 1] - ii[i]; 1438003131ecSBarry Smith aj = a->j + ii[i]; 1439fff043a9SJunchao Zhang aa = a_a + ii[i]; 144017ab2063SBarry Smith sum = 0.0; 1441003131ecSBarry Smith PetscSparseDensePlusDot(sum, x, aa, aj, n); 144217ab2063SBarry Smith y[i] = sum; 144317ab2063SBarry Smith } 14448d195f9aSBarry Smith #endif 1445b05257ddSBarry Smith } 14469566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz - a->nonzerorowcnt)); 14479566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 14489566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy, &y)); 14499566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a)); 14503a40ed3dSBarry Smith PetscFunctionReturn(0); 145117ab2063SBarry Smith } 145217ab2063SBarry Smith 14539371c9d4SSatish Balay PetscErrorCode MatMultMax_SeqAIJ(Mat A, Vec xx, Vec yy) { 1454b434eb95SMatthew G. Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1455b434eb95SMatthew G. Knepley PetscScalar *y; 1456b434eb95SMatthew G. Knepley const PetscScalar *x; 1457fff043a9SJunchao Zhang const MatScalar *aa, *a_a; 1458b434eb95SMatthew G. Knepley PetscInt m = A->rmap->n; 1459b434eb95SMatthew G. Knepley const PetscInt *aj, *ii, *ridx = NULL; 1460b434eb95SMatthew G. Knepley PetscInt n, i, nonzerorow = 0; 1461b434eb95SMatthew G. Knepley PetscScalar sum; 1462b434eb95SMatthew G. Knepley PetscBool usecprow = a->compressedrow.use; 1463b434eb95SMatthew G. Knepley 1464b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 1465b434eb95SMatthew G. Knepley #pragma disjoint(*x, *y, *aa) 1466b434eb95SMatthew G. Knepley #endif 1467b434eb95SMatthew G. Knepley 1468b434eb95SMatthew G. Knepley PetscFunctionBegin; 14699566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 14709566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 14719566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy, &y)); 1472b434eb95SMatthew G. Knepley if (usecprow) { /* use compressed row format */ 1473b434eb95SMatthew G. Knepley m = a->compressedrow.nrows; 1474b434eb95SMatthew G. Knepley ii = a->compressedrow.i; 1475b434eb95SMatthew G. Knepley ridx = a->compressedrow.rindex; 1476b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1477b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1478b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1479fff043a9SJunchao Zhang aa = a_a + ii[i]; 1480b434eb95SMatthew G. Knepley sum = 0.0; 1481b434eb95SMatthew G. Knepley nonzerorow += (n > 0); 1482b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1483b434eb95SMatthew G. Knepley /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 1484b434eb95SMatthew G. Knepley y[*ridx++] = sum; 1485b434eb95SMatthew G. Knepley } 1486b434eb95SMatthew G. Knepley } else { /* do not use compressed row format */ 14873d3eaba7SBarry Smith ii = a->i; 1488b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1489b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1490b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1491fff043a9SJunchao Zhang aa = a_a + ii[i]; 1492b434eb95SMatthew G. Knepley sum = 0.0; 1493b434eb95SMatthew G. Knepley nonzerorow += (n > 0); 1494b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1495b434eb95SMatthew G. Knepley y[i] = sum; 1496b434eb95SMatthew G. Knepley } 1497b434eb95SMatthew G. Knepley } 14989566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz - nonzerorow)); 14999566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 15009566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy, &y)); 15019566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a)); 1502b434eb95SMatthew G. Knepley PetscFunctionReturn(0); 1503b434eb95SMatthew G. Knepley } 1504b434eb95SMatthew G. Knepley 15059371c9d4SSatish Balay PetscErrorCode MatMultAddMax_SeqAIJ(Mat A, Vec xx, Vec yy, Vec zz) { 1506b434eb95SMatthew G. Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1507b434eb95SMatthew G. Knepley PetscScalar *y, *z; 1508b434eb95SMatthew G. Knepley const PetscScalar *x; 1509fff043a9SJunchao Zhang const MatScalar *aa, *a_a; 1510b434eb95SMatthew G. Knepley PetscInt m = A->rmap->n, *aj, *ii; 1511b434eb95SMatthew G. Knepley PetscInt n, i, *ridx = NULL; 1512b434eb95SMatthew G. Knepley PetscScalar sum; 1513b434eb95SMatthew G. Knepley PetscBool usecprow = a->compressedrow.use; 1514b434eb95SMatthew G. Knepley 1515b434eb95SMatthew G. Knepley PetscFunctionBegin; 15169566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 15179566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 15189566063dSJacob Faibussowitsch PetscCall(VecGetArrayPair(yy, zz, &y, &z)); 1519b434eb95SMatthew G. Knepley if (usecprow) { /* use compressed row format */ 152048a46eb9SPierre Jolivet if (zz != yy) PetscCall(PetscArraycpy(z, y, m)); 1521b434eb95SMatthew G. Knepley m = a->compressedrow.nrows; 1522b434eb95SMatthew G. Knepley ii = a->compressedrow.i; 1523b434eb95SMatthew G. Knepley ridx = a->compressedrow.rindex; 1524b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1525b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1526b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1527fff043a9SJunchao Zhang aa = a_a + ii[i]; 1528b434eb95SMatthew G. Knepley sum = y[*ridx]; 1529b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1530b434eb95SMatthew G. Knepley z[*ridx++] = sum; 1531b434eb95SMatthew G. Knepley } 1532b434eb95SMatthew G. Knepley } else { /* do not use compressed row format */ 15333d3eaba7SBarry Smith ii = a->i; 1534b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1535b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1536b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1537fff043a9SJunchao Zhang aa = a_a + ii[i]; 1538b434eb95SMatthew G. Knepley sum = y[i]; 1539b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1540b434eb95SMatthew G. Knepley z[i] = sum; 1541b434eb95SMatthew G. Knepley } 1542b434eb95SMatthew G. Knepley } 15439566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 15449566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 15459566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayPair(yy, zz, &y, &z)); 15469566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a)); 1547b434eb95SMatthew G. Knepley PetscFunctionReturn(0); 1548b434eb95SMatthew G. Knepley } 1549b434eb95SMatthew G. Knepley 1550c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h> 15519371c9d4SSatish Balay PetscErrorCode MatMultAdd_SeqAIJ(Mat A, Vec xx, Vec yy, Vec zz) { 1552416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1553f15663dcSBarry Smith PetscScalar *y, *z; 1554f15663dcSBarry Smith const PetscScalar *x; 1555fff043a9SJunchao Zhang const MatScalar *aa, *a_a; 1556d9ca1df4SBarry Smith const PetscInt *aj, *ii, *ridx = NULL; 1557d9ca1df4SBarry Smith PetscInt m = A->rmap->n, n, i; 1558362ced78SSatish Balay PetscScalar sum; 1559ace3abfcSBarry Smith PetscBool usecprow = a->compressedrow.use; 15609ea0dfa2SSatish Balay 15613a40ed3dSBarry Smith PetscFunctionBegin; 1562b215bc84SStefano Zampini if (a->inode.use && a->inode.checked) { 15639566063dSJacob Faibussowitsch PetscCall(MatMultAdd_SeqAIJ_Inode(A, xx, yy, zz)); 1564b215bc84SStefano Zampini PetscFunctionReturn(0); 1565b215bc84SStefano Zampini } 15669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 15679566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 15689566063dSJacob Faibussowitsch PetscCall(VecGetArrayPair(yy, zz, &y, &z)); 15694eb6d288SHong Zhang if (usecprow) { /* use compressed row format */ 157048a46eb9SPierre Jolivet if (zz != yy) PetscCall(PetscArraycpy(z, y, m)); 157197952fefSHong Zhang m = a->compressedrow.nrows; 157297952fefSHong Zhang ii = a->compressedrow.i; 157397952fefSHong Zhang ridx = a->compressedrow.rindex; 157497952fefSHong Zhang for (i = 0; i < m; i++) { 157597952fefSHong Zhang n = ii[i + 1] - ii[i]; 157697952fefSHong Zhang aj = a->j + ii[i]; 1577fff043a9SJunchao Zhang aa = a_a + ii[i]; 157897952fefSHong Zhang sum = y[*ridx]; 1579f15663dcSBarry Smith PetscSparseDensePlusDot(sum, x, aa, aj, n); 158097952fefSHong Zhang z[*ridx++] = sum; 158197952fefSHong Zhang } 158297952fefSHong Zhang } else { /* do not use compressed row format */ 15833d3eaba7SBarry Smith ii = a->i; 1584f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ) 15853d3eaba7SBarry Smith aj = a->j; 1586fff043a9SJunchao Zhang aa = a_a; 1587f15663dcSBarry Smith fortranmultaddaij_(&m, x, ii, aj, aa, y, z); 1588f15663dcSBarry Smith #else 158917ab2063SBarry Smith for (i = 0; i < m; i++) { 1590f15663dcSBarry Smith n = ii[i + 1] - ii[i]; 1591f15663dcSBarry Smith aj = a->j + ii[i]; 1592fff043a9SJunchao Zhang aa = a_a + ii[i]; 159317ab2063SBarry Smith sum = y[i]; 1594f15663dcSBarry Smith PetscSparseDensePlusDot(sum, x, aa, aj, n); 159517ab2063SBarry Smith z[i] = sum; 159617ab2063SBarry Smith } 159702ab625aSSatish Balay #endif 1598f15663dcSBarry Smith } 15999566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 16009566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 16019566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayPair(yy, zz, &y, &z)); 16029566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a)); 16033a40ed3dSBarry Smith PetscFunctionReturn(0); 160417ab2063SBarry Smith } 160517ab2063SBarry Smith 160617ab2063SBarry Smith /* 160717ab2063SBarry Smith Adds diagonal pointers to sparse matrix structure. 160817ab2063SBarry Smith */ 16099371c9d4SSatish Balay PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A) { 1610416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1611d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n; 1612c0c07093SJunchao Zhang PetscBool alreadySet = PETSC_TRUE; 161317ab2063SBarry Smith 16143a40ed3dSBarry Smith PetscFunctionBegin; 161509f38230SBarry Smith if (!a->diag) { 16169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &a->diag)); 1617c0c07093SJunchao Zhang alreadySet = PETSC_FALSE; 161809f38230SBarry Smith } 1619d0f46423SBarry Smith for (i = 0; i < A->rmap->n; i++) { 1620c0c07093SJunchao Zhang /* If A's diagonal is already correctly set, this fast track enables cheap and repeated MatMarkDiagonal_SeqAIJ() calls */ 1621c0c07093SJunchao Zhang if (alreadySet) { 1622c0c07093SJunchao Zhang PetscInt pos = a->diag[i]; 1623c0c07093SJunchao Zhang if (pos >= a->i[i] && pos < a->i[i + 1] && a->j[pos] == i) continue; 1624c0c07093SJunchao Zhang } 1625c0c07093SJunchao Zhang 162609f38230SBarry Smith a->diag[i] = a->i[i + 1]; 1627bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 1628bfeeae90SHong Zhang if (a->j[j] == i) { 162909f38230SBarry Smith a->diag[i] = j; 163017ab2063SBarry Smith break; 163117ab2063SBarry Smith } 163217ab2063SBarry Smith } 163317ab2063SBarry Smith } 16343a40ed3dSBarry Smith PetscFunctionReturn(0); 163517ab2063SBarry Smith } 163617ab2063SBarry Smith 16379371c9d4SSatish Balay PetscErrorCode MatShift_SeqAIJ(Mat A, PetscScalar v) { 163861ecd0c6SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 163961ecd0c6SBarry Smith const PetscInt *diag = (const PetscInt *)a->diag; 164061ecd0c6SBarry Smith const PetscInt *ii = (const PetscInt *)a->i; 164161ecd0c6SBarry Smith PetscInt i, *mdiag = NULL; 164261ecd0c6SBarry Smith PetscInt cnt = 0; /* how many diagonals are missing */ 164361ecd0c6SBarry Smith 164461ecd0c6SBarry Smith PetscFunctionBegin; 164561ecd0c6SBarry Smith if (!A->preallocated || !a->nz) { 16469566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(A, 1, NULL)); 16479566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(A, v)); 164861ecd0c6SBarry Smith PetscFunctionReturn(0); 164961ecd0c6SBarry Smith } 165061ecd0c6SBarry Smith 165161ecd0c6SBarry Smith if (a->diagonaldense) { 165261ecd0c6SBarry Smith cnt = 0; 165361ecd0c6SBarry Smith } else { 16549566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n, &mdiag)); 165561ecd0c6SBarry Smith for (i = 0; i < A->rmap->n; i++) { 1656349d3b71SJunchao Zhang if (i < A->cmap->n && diag[i] >= ii[i + 1]) { /* 'out of range' rows never have diagonals */ 165761ecd0c6SBarry Smith cnt++; 165861ecd0c6SBarry Smith mdiag[i] = 1; 165961ecd0c6SBarry Smith } 166061ecd0c6SBarry Smith } 166161ecd0c6SBarry Smith } 166261ecd0c6SBarry Smith if (!cnt) { 16639566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(A, v)); 166461ecd0c6SBarry Smith } else { 1665b6f2aa54SBarry Smith PetscScalar *olda = a->a; /* preserve pointers to current matrix nonzeros structure and values */ 1666b6f2aa54SBarry Smith PetscInt *oldj = a->j, *oldi = a->i; 166761ecd0c6SBarry Smith PetscBool singlemalloc = a->singlemalloc, free_a = a->free_a, free_ij = a->free_ij; 166861ecd0c6SBarry Smith 166961ecd0c6SBarry Smith a->a = NULL; 167061ecd0c6SBarry Smith a->j = NULL; 167161ecd0c6SBarry Smith a->i = NULL; 167261ecd0c6SBarry Smith /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */ 1673ad540459SPierre Jolivet for (i = 0; i < PetscMin(A->rmap->n, A->cmap->n); i++) a->imax[i] += mdiag[i]; 16749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A, 0, a->imax)); 167561ecd0c6SBarry Smith 167661ecd0c6SBarry Smith /* copy old values into new matrix data structure */ 167761ecd0c6SBarry Smith for (i = 0; i < A->rmap->n; i++) { 16789566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &i, a->imax[i] - mdiag[i], &oldj[oldi[i]], &olda[oldi[i]], ADD_VALUES)); 167948a46eb9SPierre Jolivet if (i < A->cmap->n) PetscCall(MatSetValue(A, i, i, v, ADD_VALUES)); 1680447d62f5SStefano Zampini } 16819566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 16829566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 168361ecd0c6SBarry Smith if (singlemalloc) { 16849566063dSJacob Faibussowitsch PetscCall(PetscFree3(olda, oldj, oldi)); 168561ecd0c6SBarry Smith } else { 16869566063dSJacob Faibussowitsch if (free_a) PetscCall(PetscFree(olda)); 16879566063dSJacob Faibussowitsch if (free_ij) PetscCall(PetscFree(oldj)); 16889566063dSJacob Faibussowitsch if (free_ij) PetscCall(PetscFree(oldi)); 168961ecd0c6SBarry Smith } 169061ecd0c6SBarry Smith } 16919566063dSJacob Faibussowitsch PetscCall(PetscFree(mdiag)); 169261ecd0c6SBarry Smith a->diagonaldense = PETSC_TRUE; 169361ecd0c6SBarry Smith PetscFunctionReturn(0); 169461ecd0c6SBarry Smith } 169561ecd0c6SBarry Smith 1696be5855fcSBarry Smith /* 1697be5855fcSBarry Smith Checks for missing diagonals 1698be5855fcSBarry Smith */ 16999371c9d4SSatish Balay PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A, PetscBool *missing, PetscInt *d) { 1700be5855fcSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 17017734d3b5SMatthew G. Knepley PetscInt *diag, *ii = a->i, i; 1702be5855fcSBarry Smith 1703be5855fcSBarry Smith PetscFunctionBegin; 170409f38230SBarry Smith *missing = PETSC_FALSE; 17057734d3b5SMatthew G. Knepley if (A->rmap->n > 0 && !ii) { 170609f38230SBarry Smith *missing = PETSC_TRUE; 170709f38230SBarry Smith if (d) *d = 0; 17089566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no entries therefore is missing diagonal\n")); 170909f38230SBarry Smith } else { 171001445905SHong Zhang PetscInt n; 171101445905SHong Zhang n = PetscMin(A->rmap->n, A->cmap->n); 1712f1e2ffcdSBarry Smith diag = a->diag; 171301445905SHong Zhang for (i = 0; i < n; i++) { 17147734d3b5SMatthew G. Knepley if (diag[i] >= ii[i + 1]) { 171509f38230SBarry Smith *missing = PETSC_TRUE; 171609f38230SBarry Smith if (d) *d = i; 17179566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix is missing diagonal number %" PetscInt_FMT "\n", i)); 1718358d2f5dSShri Abhyankar break; 171909f38230SBarry Smith } 1720be5855fcSBarry Smith } 1721be5855fcSBarry Smith } 1722be5855fcSBarry Smith PetscFunctionReturn(0); 1723be5855fcSBarry Smith } 1724be5855fcSBarry Smith 17250da83c2eSBarry Smith #include <petscblaslapack.h> 17260da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h> 17270da83c2eSBarry Smith 17280da83c2eSBarry Smith /* 17290da83c2eSBarry Smith Note that values is allocated externally by the PC and then passed into this routine 17300da83c2eSBarry Smith */ 17319371c9d4SSatish Balay PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *diag) { 17320da83c2eSBarry Smith PetscInt n = A->rmap->n, i, ncnt = 0, *indx, j, bsizemax = 0, *v_pivots; 17330da83c2eSBarry Smith PetscBool allowzeropivot, zeropivotdetected = PETSC_FALSE; 17340da83c2eSBarry Smith const PetscReal shift = 0.0; 17350da83c2eSBarry Smith PetscInt ipvt[5]; 17360da83c2eSBarry Smith PetscScalar work[25], *v_work; 17370da83c2eSBarry Smith 17380da83c2eSBarry Smith PetscFunctionBegin; 17390da83c2eSBarry Smith allowzeropivot = PetscNot(A->erroriffailure); 17400da83c2eSBarry Smith for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 174108401ef6SPierre 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); 1742ad540459SPierre Jolivet for (i = 0; i < nblocks; i++) bsizemax = PetscMax(bsizemax, bsizes[i]); 17439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsizemax, &indx)); 174448a46eb9SPierre Jolivet if (bsizemax > 7) PetscCall(PetscMalloc2(bsizemax, &v_work, bsizemax, &v_pivots)); 17450da83c2eSBarry Smith ncnt = 0; 17460da83c2eSBarry Smith for (i = 0; i < nblocks; i++) { 17470da83c2eSBarry Smith for (j = 0; j < bsizes[i]; j++) indx[j] = ncnt + j; 17489566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, bsizes[i], indx, bsizes[i], indx, diag)); 17490da83c2eSBarry Smith switch (bsizes[i]) { 17509371c9d4SSatish Balay case 1: *diag = 1.0 / (*diag); break; 17510da83c2eSBarry Smith case 2: 17529566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected)); 17530da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17549566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_2(diag)); 17550da83c2eSBarry Smith break; 17560da83c2eSBarry Smith case 3: 17579566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected)); 17580da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17599566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_3(diag)); 17600da83c2eSBarry Smith break; 17610da83c2eSBarry Smith case 4: 17629566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected)); 17630da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17649566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_4(diag)); 17650da83c2eSBarry Smith break; 17660da83c2eSBarry Smith case 5: 17679566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected)); 17680da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17699566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_5(diag)); 17700da83c2eSBarry Smith break; 17710da83c2eSBarry Smith case 6: 17729566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected)); 17730da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17749566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_6(diag)); 17750da83c2eSBarry Smith break; 17760da83c2eSBarry Smith case 7: 17779566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected)); 17780da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17799566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_7(diag)); 17800da83c2eSBarry Smith break; 17810da83c2eSBarry Smith default: 17829566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A(bsizes[i], diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected)); 17830da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17849566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_N(diag, bsizes[i])); 17850da83c2eSBarry Smith } 17860da83c2eSBarry Smith ncnt += bsizes[i]; 17870da83c2eSBarry Smith diag += bsizes[i] * bsizes[i]; 17880da83c2eSBarry Smith } 178948a46eb9SPierre Jolivet if (bsizemax > 7) PetscCall(PetscFree2(v_work, v_pivots)); 17909566063dSJacob Faibussowitsch PetscCall(PetscFree(indx)); 17910da83c2eSBarry Smith PetscFunctionReturn(0); 17920da83c2eSBarry Smith } 17930da83c2eSBarry Smith 1794422a814eSBarry Smith /* 1795422a814eSBarry Smith Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways 1796422a814eSBarry Smith */ 17979371c9d4SSatish Balay PetscErrorCode MatInvertDiagonal_SeqAIJ(Mat A, PetscScalar omega, PetscScalar fshift) { 179871f1c65dSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1799d0f46423SBarry Smith PetscInt i, *diag, m = A->rmap->n; 18002e5835c6SStefano Zampini const MatScalar *v; 180154f21887SBarry Smith PetscScalar *idiag, *mdiag; 180271f1c65dSBarry Smith 180371f1c65dSBarry Smith PetscFunctionBegin; 180471f1c65dSBarry Smith if (a->idiagvalid) PetscFunctionReturn(0); 18059566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 180671f1c65dSBarry Smith diag = a->diag; 1807*4dfa11a4SJacob Faibussowitsch if (!a->idiag) { PetscCall(PetscMalloc3(m, &a->idiag, m, &a->mdiag, m, &a->ssor_work)); } 18082e5835c6SStefano Zampini 180971f1c65dSBarry Smith mdiag = a->mdiag; 181071f1c65dSBarry Smith idiag = a->idiag; 18119566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &v)); 1812422a814eSBarry Smith if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) { 181371f1c65dSBarry Smith for (i = 0; i < m; i++) { 181471f1c65dSBarry Smith mdiag[i] = v[diag[i]]; 1815899639b0SHong Zhang if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */ 1816899639b0SHong Zhang if (PetscRealPart(fshift)) { 18179566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Zero diagonal on row %" PetscInt_FMT "\n", i)); 18187b6c816cSBarry Smith A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18197b6c816cSBarry Smith A->factorerror_zeropivot_value = 0.0; 18207b6c816cSBarry Smith A->factorerror_zeropivot_row = i; 182198921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Zero diagonal on row %" PetscInt_FMT, i); 1822899639b0SHong Zhang } 182371f1c65dSBarry Smith idiag[i] = 1.0 / v[diag[i]]; 182471f1c65dSBarry Smith } 18259566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(m)); 182671f1c65dSBarry Smith } else { 182771f1c65dSBarry Smith for (i = 0; i < m; i++) { 182871f1c65dSBarry Smith mdiag[i] = v[diag[i]]; 182971f1c65dSBarry Smith idiag[i] = omega / (fshift + v[diag[i]]); 183071f1c65dSBarry Smith } 18319566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * m)); 183271f1c65dSBarry Smith } 183371f1c65dSBarry Smith a->idiagvalid = PETSC_TRUE; 18349566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &v)); 183571f1c65dSBarry Smith PetscFunctionReturn(0); 183671f1c65dSBarry Smith } 183771f1c65dSBarry Smith 1838c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h> 18399371c9d4SSatish Balay PetscErrorCode MatSOR_SeqAIJ(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal fshift, PetscInt its, PetscInt lits, Vec xx) { 1840416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1841e6d1f457SBarry Smith PetscScalar *x, d, sum, *t, scale; 18422e5835c6SStefano Zampini const MatScalar *v, *idiag = NULL, *mdiag, *aa; 184354f21887SBarry Smith const PetscScalar *b, *bs, *xb, *ts; 18443d3eaba7SBarry Smith PetscInt n, m = A->rmap->n, i; 184597f1f81fSBarry Smith const PetscInt *idx, *diag; 184617ab2063SBarry Smith 18473a40ed3dSBarry Smith PetscFunctionBegin; 1848b215bc84SStefano Zampini if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) { 18499566063dSJacob Faibussowitsch PetscCall(MatSOR_SeqAIJ_Inode(A, bb, omega, flag, fshift, its, lits, xx)); 1850b215bc84SStefano Zampini PetscFunctionReturn(0); 1851b215bc84SStefano Zampini } 1852b965ef7fSBarry Smith its = its * lits; 185391723122SBarry Smith 185471f1c65dSBarry Smith if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */ 18559566063dSJacob Faibussowitsch if (!a->idiagvalid) PetscCall(MatInvertDiagonal_SeqAIJ(A, omega, fshift)); 185671f1c65dSBarry Smith a->fshift = fshift; 185771f1c65dSBarry Smith a->omega = omega; 1858ed480e8bSBarry Smith 185971f1c65dSBarry Smith diag = a->diag; 186071f1c65dSBarry Smith t = a->ssor_work; 1861ed480e8bSBarry Smith idiag = a->idiag; 186271f1c65dSBarry Smith mdiag = a->mdiag; 1863ed480e8bSBarry Smith 18649566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 18659566063dSJacob Faibussowitsch PetscCall(VecGetArray(xx, &x)); 18669566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(bb, &b)); 1867ed480e8bSBarry Smith /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */ 186817ab2063SBarry Smith if (flag == SOR_APPLY_UPPER) { 186917ab2063SBarry Smith /* apply (U + D/omega) to the vector */ 1870ed480e8bSBarry Smith bs = b; 187117ab2063SBarry Smith for (i = 0; i < m; i++) { 187271f1c65dSBarry Smith d = fshift + mdiag[i]; 1873416022c9SBarry Smith n = a->i[i + 1] - diag[i] - 1; 1874ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 18752e5835c6SStefano Zampini v = aa + diag[i] + 1; 187617ab2063SBarry Smith sum = b[i] * d / omega; 1877003131ecSBarry Smith PetscSparseDensePlusDot(sum, bs, v, idx, n); 187817ab2063SBarry Smith x[i] = sum; 187917ab2063SBarry Smith } 18809566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx, &x)); 18819566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb, &b)); 18829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 18839566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 18843a40ed3dSBarry Smith PetscFunctionReturn(0); 188517ab2063SBarry Smith } 1886c783ea89SBarry Smith 188708401ef6SPierre Jolivet PetscCheck(flag != SOR_APPLY_LOWER, PETSC_COMM_SELF, PETSC_ERR_SUP, "SOR_APPLY_LOWER is not implemented"); 1888f7d195e4SLawrence Mitchell if (flag & SOR_EISENSTAT) { 18894c500f23SPierre Jolivet /* Let A = L + U + D; where L is lower triangular, 1890887ee2caSBarry Smith U is upper triangular, E = D/omega; This routine applies 189117ab2063SBarry Smith 189217ab2063SBarry Smith (L + E)^{-1} A (U + E)^{-1} 189317ab2063SBarry Smith 1894887ee2caSBarry Smith to a vector efficiently using Eisenstat's trick. 189517ab2063SBarry Smith */ 189617ab2063SBarry Smith scale = (2.0 / omega) - 1.0; 189717ab2063SBarry Smith 189817ab2063SBarry Smith /* x = (E + U)^{-1} b */ 189917ab2063SBarry Smith for (i = m - 1; i >= 0; i--) { 1900416022c9SBarry Smith n = a->i[i + 1] - diag[i] - 1; 1901ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 19022e5835c6SStefano Zampini v = aa + diag[i] + 1; 190317ab2063SBarry Smith sum = b[i]; 1904e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 1905ed480e8bSBarry Smith x[i] = sum * idiag[i]; 190617ab2063SBarry Smith } 190717ab2063SBarry Smith 190817ab2063SBarry Smith /* t = b - (2*E - D)x */ 19092e5835c6SStefano Zampini v = aa; 19102205254eSKarl Rupp for (i = 0; i < m; i++) t[i] = b[i] - scale * (v[*diag++]) * x[i]; 191117ab2063SBarry Smith 191217ab2063SBarry Smith /* t = (E + L)^{-1}t */ 1913ed480e8bSBarry Smith ts = t; 1914416022c9SBarry Smith diag = a->diag; 191517ab2063SBarry Smith for (i = 0; i < m; i++) { 1916416022c9SBarry Smith n = diag[i] - a->i[i]; 1917ed480e8bSBarry Smith idx = a->j + a->i[i]; 19182e5835c6SStefano Zampini v = aa + a->i[i]; 191917ab2063SBarry Smith sum = t[i]; 1920003131ecSBarry Smith PetscSparseDenseMinusDot(sum, ts, v, idx, n); 1921ed480e8bSBarry Smith t[i] = sum * idiag[i]; 1922733d66baSBarry Smith /* x = x + t */ 1923733d66baSBarry Smith x[i] += t[i]; 192417ab2063SBarry Smith } 192517ab2063SBarry Smith 19269566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(6.0 * m - 1 + 2.0 * a->nz)); 19279566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx, &x)); 19289566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb, &b)); 19293a40ed3dSBarry Smith PetscFunctionReturn(0); 193017ab2063SBarry Smith } 193117ab2063SBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 193217ab2063SBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 193317ab2063SBarry Smith for (i = 0; i < m; i++) { 1934416022c9SBarry Smith n = diag[i] - a->i[i]; 1935ed480e8bSBarry Smith idx = a->j + a->i[i]; 19362e5835c6SStefano Zampini v = aa + a->i[i]; 193717ab2063SBarry Smith sum = b[i]; 1938e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 19395c99c7daSBarry Smith t[i] = sum; 1940ed480e8bSBarry Smith x[i] = sum * idiag[i]; 194117ab2063SBarry Smith } 19425c99c7daSBarry Smith xb = t; 19439566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 19443a40ed3dSBarry Smith } else xb = b; 194517ab2063SBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 194617ab2063SBarry Smith for (i = m - 1; i >= 0; i--) { 1947416022c9SBarry Smith n = a->i[i + 1] - diag[i] - 1; 1948ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 19492e5835c6SStefano Zampini v = aa + diag[i] + 1; 195017ab2063SBarry Smith sum = xb[i]; 1951e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 19525c99c7daSBarry Smith if (xb == b) { 1953ed480e8bSBarry Smith x[i] = sum * idiag[i]; 19545c99c7daSBarry Smith } else { 1955b19a5dc2SMark Adams x[i] = (1 - omega) * x[i] + sum * idiag[i]; /* omega in idiag */ 195617ab2063SBarry Smith } 19575c99c7daSBarry Smith } 19589566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */ 195917ab2063SBarry Smith } 196017ab2063SBarry Smith its--; 196117ab2063SBarry Smith } 196217ab2063SBarry Smith while (its--) { 196317ab2063SBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 196417ab2063SBarry Smith for (i = 0; i < m; i++) { 1965b19a5dc2SMark Adams /* lower */ 1966b19a5dc2SMark Adams n = diag[i] - a->i[i]; 1967ed480e8bSBarry Smith idx = a->j + a->i[i]; 19682e5835c6SStefano Zampini v = aa + a->i[i]; 196917ab2063SBarry Smith sum = b[i]; 1970e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 1971b19a5dc2SMark Adams t[i] = sum; /* save application of the lower-triangular part */ 1972b19a5dc2SMark Adams /* upper */ 1973b19a5dc2SMark Adams n = a->i[i + 1] - diag[i] - 1; 1974b19a5dc2SMark Adams idx = a->j + diag[i] + 1; 19752e5835c6SStefano Zampini v = aa + diag[i] + 1; 1976b19a5dc2SMark Adams PetscSparseDenseMinusDot(sum, x, v, idx, n); 1977b19a5dc2SMark Adams x[i] = (1. - omega) * x[i] + sum * idiag[i]; /* omega in idiag */ 197817ab2063SBarry Smith } 1979b19a5dc2SMark Adams xb = t; 19809566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 1981b19a5dc2SMark Adams } else xb = b; 198217ab2063SBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 198317ab2063SBarry Smith for (i = m - 1; i >= 0; i--) { 1984b19a5dc2SMark Adams sum = xb[i]; 1985b19a5dc2SMark Adams if (xb == b) { 1986b19a5dc2SMark Adams /* whole matrix (no checkpointing available) */ 1987416022c9SBarry Smith n = a->i[i + 1] - a->i[i]; 1988ed480e8bSBarry Smith idx = a->j + a->i[i]; 19892e5835c6SStefano Zampini v = aa + a->i[i]; 1990e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 1991ed480e8bSBarry Smith x[i] = (1. - omega) * x[i] + (sum + mdiag[i] * x[i]) * idiag[i]; 1992b19a5dc2SMark Adams } else { /* lower-triangular part has been saved, so only apply upper-triangular */ 1993b19a5dc2SMark Adams n = a->i[i + 1] - diag[i] - 1; 1994b19a5dc2SMark Adams idx = a->j + diag[i] + 1; 19952e5835c6SStefano Zampini v = aa + diag[i] + 1; 1996b19a5dc2SMark Adams PetscSparseDenseMinusDot(sum, x, v, idx, n); 1997b19a5dc2SMark Adams x[i] = (1. - omega) * x[i] + sum * idiag[i]; /* omega in idiag */ 199817ab2063SBarry Smith } 1999b19a5dc2SMark Adams } 2000b19a5dc2SMark Adams if (xb == b) { 20019566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 2002b19a5dc2SMark Adams } else { 20039566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */ 2004b19a5dc2SMark Adams } 200517ab2063SBarry Smith } 200617ab2063SBarry Smith } 20079566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 20089566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx, &x)); 20099566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb, &b)); 2010365a8a9eSBarry Smith PetscFunctionReturn(0); 201117ab2063SBarry Smith } 201217ab2063SBarry Smith 20139371c9d4SSatish Balay PetscErrorCode MatGetInfo_SeqAIJ(Mat A, MatInfoType flag, MatInfo *info) { 2014416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 20154e220ebcSLois Curfman McInnes 20163a40ed3dSBarry Smith PetscFunctionBegin; 20174e220ebcSLois Curfman McInnes info->block_size = 1.0; 20183966268fSBarry Smith info->nz_allocated = a->maxnz; 20193966268fSBarry Smith info->nz_used = a->nz; 20203966268fSBarry Smith info->nz_unneeded = (a->maxnz - a->nz); 20213966268fSBarry Smith info->assemblies = A->num_ass; 20223966268fSBarry Smith info->mallocs = A->info.mallocs; 2023*4dfa11a4SJacob Faibussowitsch info->memory = 0; /* REVIEW ME */ 2024d5f3da31SBarry Smith if (A->factortype) { 20254e220ebcSLois Curfman McInnes info->fill_ratio_given = A->info.fill_ratio_given; 20264e220ebcSLois Curfman McInnes info->fill_ratio_needed = A->info.fill_ratio_needed; 20274e220ebcSLois Curfman McInnes info->factor_mallocs = A->info.factor_mallocs; 20284e220ebcSLois Curfman McInnes } else { 20294e220ebcSLois Curfman McInnes info->fill_ratio_given = 0; 20304e220ebcSLois Curfman McInnes info->fill_ratio_needed = 0; 20314e220ebcSLois Curfman McInnes info->factor_mallocs = 0; 20324e220ebcSLois Curfman McInnes } 20333a40ed3dSBarry Smith PetscFunctionReturn(0); 203417ab2063SBarry Smith } 203517ab2063SBarry Smith 20369371c9d4SSatish Balay PetscErrorCode MatZeroRows_SeqAIJ(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) { 2037416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2038c7da8527SEric Chamberland PetscInt i, m = A->rmap->n - 1; 203997b48c8fSBarry Smith const PetscScalar *xx; 20402e5835c6SStefano Zampini PetscScalar *bb, *aa; 2041c7da8527SEric Chamberland PetscInt d = 0; 204217ab2063SBarry Smith 20433a40ed3dSBarry Smith PetscFunctionBegin; 204497b48c8fSBarry Smith if (x && b) { 20459566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 20469566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 204797b48c8fSBarry Smith for (i = 0; i < N; i++) { 2048aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 2049447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 205097b48c8fSBarry Smith bb[rows[i]] = diag * xx[rows[i]]; 205197b48c8fSBarry Smith } 20529566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 20539566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 205497b48c8fSBarry Smith } 205597b48c8fSBarry Smith 20569566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 2057a9817697SBarry Smith if (a->keepnonzeropattern) { 2058f1e2ffcdSBarry Smith for (i = 0; i < N; i++) { 2059aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 20609566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(&aa[a->i[rows[i]]], a->ilen[rows[i]])); 2061f1e2ffcdSBarry Smith } 2062f4df32b1SMatthew Knepley if (diag != 0.0) { 2063c7da8527SEric Chamberland for (i = 0; i < N; i++) { 2064c7da8527SEric Chamberland d = rows[i]; 2065447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 206608401ef6SPierre 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); 2067c7da8527SEric Chamberland } 2068f1e2ffcdSBarry Smith for (i = 0; i < N; i++) { 2069447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 20702e5835c6SStefano Zampini aa[a->diag[rows[i]]] = diag; 2071f1e2ffcdSBarry Smith } 2072f1e2ffcdSBarry Smith } 2073f1e2ffcdSBarry Smith } else { 2074f4df32b1SMatthew Knepley if (diag != 0.0) { 207517ab2063SBarry Smith for (i = 0; i < N; i++) { 2076aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 20777ae801bdSBarry Smith if (a->ilen[rows[i]] > 0) { 2078447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) { 2079447d62f5SStefano Zampini a->ilen[rows[i]] = 0; 2080447d62f5SStefano Zampini } else { 2081416022c9SBarry Smith a->ilen[rows[i]] = 1; 20822e5835c6SStefano Zampini aa[a->i[rows[i]]] = diag; 2083bfeeae90SHong Zhang a->j[a->i[rows[i]]] = rows[i]; 2084447d62f5SStefano Zampini } 2085447d62f5SStefano Zampini } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */ 20869566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(A, 1, &rows[i], 1, &rows[i], &diag, INSERT_VALUES)); 208717ab2063SBarry Smith } 208817ab2063SBarry Smith } 20893a40ed3dSBarry Smith } else { 209017ab2063SBarry Smith for (i = 0; i < N; i++) { 2091aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 2092416022c9SBarry Smith a->ilen[rows[i]] = 0; 209317ab2063SBarry Smith } 209417ab2063SBarry Smith } 2095e56f5c9eSBarry Smith A->nonzerostate++; 2096f1e2ffcdSBarry Smith } 20979566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 2098dbbe0bcdSBarry Smith PetscUseTypeMethod(A, assemblyend, MAT_FINAL_ASSEMBLY); 20993a40ed3dSBarry Smith PetscFunctionReturn(0); 210017ab2063SBarry Smith } 210117ab2063SBarry Smith 21029371c9d4SSatish Balay PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) { 21036e169961SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 21046e169961SBarry Smith PetscInt i, j, m = A->rmap->n - 1, d = 0; 21052b40b63fSBarry Smith PetscBool missing, *zeroed, vecs = PETSC_FALSE; 21066e169961SBarry Smith const PetscScalar *xx; 21072e5835c6SStefano Zampini PetscScalar *bb, *aa; 21086e169961SBarry Smith 21096e169961SBarry Smith PetscFunctionBegin; 21102e5835c6SStefano Zampini if (!N) PetscFunctionReturn(0); 21119566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 21126e169961SBarry Smith if (x && b) { 21139566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 21149566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 21152b40b63fSBarry Smith vecs = PETSC_TRUE; 21166e169961SBarry Smith } 21179566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n, &zeroed)); 21186e169961SBarry Smith for (i = 0; i < N; i++) { 2119aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 21209566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(&aa[a->i[rows[i]]], a->ilen[rows[i]])); 21212205254eSKarl Rupp 21226e169961SBarry Smith zeroed[rows[i]] = PETSC_TRUE; 21236e169961SBarry Smith } 21246e169961SBarry Smith for (i = 0; i < A->rmap->n; i++) { 21256e169961SBarry Smith if (!zeroed[i]) { 21266e169961SBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 21274cf107fdSStefano Zampini if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) { 21282e5835c6SStefano Zampini if (vecs) bb[i] -= aa[j] * xx[a->j[j]]; 21292e5835c6SStefano Zampini aa[j] = 0.0; 21306e169961SBarry Smith } 21316e169961SBarry Smith } 21324cf107fdSStefano Zampini } else if (vecs && i < A->cmap->N) bb[i] = diag * xx[i]; 21336e169961SBarry Smith } 21346e169961SBarry Smith if (x && b) { 21359566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 21369566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 21376e169961SBarry Smith } 21389566063dSJacob Faibussowitsch PetscCall(PetscFree(zeroed)); 21396e169961SBarry Smith if (diag != 0.0) { 21409566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal_SeqAIJ(A, &missing, &d)); 21411d5a398dSstefano_zampini if (missing) { 21421d5a398dSstefano_zampini for (i = 0; i < N; i++) { 21434cf107fdSStefano Zampini if (rows[i] >= A->cmap->N) continue; 2144aed4548fSBarry 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]); 21459566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(A, 1, &rows[i], 1, &rows[i], &diag, INSERT_VALUES)); 21461d5a398dSstefano_zampini } 21471d5a398dSstefano_zampini } else { 2148ad540459SPierre Jolivet for (i = 0; i < N; i++) aa[a->diag[rows[i]]] = diag; 21496e169961SBarry Smith } 21501d5a398dSstefano_zampini } 21519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 2152dbbe0bcdSBarry Smith PetscUseTypeMethod(A, assemblyend, MAT_FINAL_ASSEMBLY); 21536e169961SBarry Smith PetscFunctionReturn(0); 21546e169961SBarry Smith } 21556e169961SBarry Smith 21569371c9d4SSatish Balay PetscErrorCode MatGetRow_SeqAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) { 2157fff043a9SJunchao Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2158fff043a9SJunchao Zhang const PetscScalar *aa; 2159fff043a9SJunchao Zhang PetscInt *itmp; 216017ab2063SBarry Smith 21613a40ed3dSBarry Smith PetscFunctionBegin; 21629566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 2163416022c9SBarry Smith *nz = a->i[row + 1] - a->i[row]; 21642e5835c6SStefano Zampini if (v) *v = (PetscScalar *)(aa + a->i[row]); 216517ab2063SBarry Smith if (idx) { 2166bfeeae90SHong Zhang itmp = a->j + a->i[row]; 216726fbe8dcSKarl Rupp if (*nz) *idx = itmp; 2168f4259b30SLisandro Dalcin else *idx = NULL; 216917ab2063SBarry Smith } 21709566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 21713a40ed3dSBarry Smith PetscFunctionReturn(0); 217217ab2063SBarry Smith } 217317ab2063SBarry Smith 21749371c9d4SSatish Balay PetscErrorCode MatRestoreRow_SeqAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) { 21753a40ed3dSBarry Smith PetscFunctionBegin; 2176cb4a9cd9SHong Zhang if (nz) *nz = 0; 21772e5835c6SStefano Zampini if (idx) *idx = NULL; 21782e5835c6SStefano Zampini if (v) *v = NULL; 21793a40ed3dSBarry Smith PetscFunctionReturn(0); 218017ab2063SBarry Smith } 218117ab2063SBarry Smith 21829371c9d4SSatish Balay PetscErrorCode MatNorm_SeqAIJ(Mat A, NormType type, PetscReal *nrm) { 2183416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 21842e5835c6SStefano Zampini const MatScalar *v; 218536db0b34SBarry Smith PetscReal sum = 0.0; 218697f1f81fSBarry Smith PetscInt i, j; 218717ab2063SBarry Smith 21883a40ed3dSBarry Smith PetscFunctionBegin; 21899566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &v)); 219017ab2063SBarry Smith if (type == NORM_FROBENIUS) { 2191570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16) 2192570b7f6dSBarry Smith PetscBLASInt one = 1, nz = a->nz; 2193792fecdfSBarry Smith PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&nz, v, &one)); 2194570b7f6dSBarry Smith #else 2195416022c9SBarry Smith for (i = 0; i < a->nz; i++) { 21969371c9d4SSatish Balay sum += PetscRealPart(PetscConj(*v) * (*v)); 21979371c9d4SSatish Balay v++; 219817ab2063SBarry Smith } 21998f1a2a5eSBarry Smith *nrm = PetscSqrtReal(sum); 2200570b7f6dSBarry Smith #endif 22019566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 22023a40ed3dSBarry Smith } else if (type == NORM_1) { 220336db0b34SBarry Smith PetscReal *tmp; 220497f1f81fSBarry Smith PetscInt *jj = a->j; 22059566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->cmap->n + 1, &tmp)); 2206064f8208SBarry Smith *nrm = 0.0; 2207416022c9SBarry Smith for (j = 0; j < a->nz; j++) { 22089371c9d4SSatish Balay tmp[*jj++] += PetscAbsScalar(*v); 22099371c9d4SSatish Balay v++; 221017ab2063SBarry Smith } 2211d0f46423SBarry Smith for (j = 0; j < A->cmap->n; j++) { 2212064f8208SBarry Smith if (tmp[j] > *nrm) *nrm = tmp[j]; 221317ab2063SBarry Smith } 22149566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp)); 22159566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(PetscMax(a->nz - 1, 0))); 22163a40ed3dSBarry Smith } else if (type == NORM_INFINITY) { 2217064f8208SBarry Smith *nrm = 0.0; 2218d0f46423SBarry Smith for (j = 0; j < A->rmap->n; j++) { 22192e5835c6SStefano Zampini const PetscScalar *v2 = v + a->i[j]; 222017ab2063SBarry Smith sum = 0.0; 2221416022c9SBarry Smith for (i = 0; i < a->i[j + 1] - a->i[j]; i++) { 22229371c9d4SSatish Balay sum += PetscAbsScalar(*v2); 22239371c9d4SSatish Balay v2++; 222417ab2063SBarry Smith } 2225064f8208SBarry Smith if (sum > *nrm) *nrm = sum; 222617ab2063SBarry Smith } 22279566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(PetscMax(a->nz - 1, 0))); 2228f23aa3ddSBarry Smith } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for two norm"); 22299566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &v)); 22303a40ed3dSBarry Smith PetscFunctionReturn(0); 223117ab2063SBarry Smith } 223217ab2063SBarry Smith 22339371c9d4SSatish Balay PetscErrorCode MatIsTranspose_SeqAIJ(Mat A, Mat B, PetscReal tol, PetscBool *f) { 22343d3eaba7SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data, *bij = (Mat_SeqAIJ *)B->data; 223554f21887SBarry Smith PetscInt *adx, *bdx, *aii, *bii, *aptr, *bptr; 22362e5835c6SStefano Zampini const MatScalar *va, *vb; 223797f1f81fSBarry Smith PetscInt ma, na, mb, nb, i; 2238cd0d46ebSvictorle 2239cd0d46ebSvictorle PetscFunctionBegin; 22409566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &ma, &na)); 22419566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &mb, &nb)); 22425485867bSBarry Smith if (ma != nb || na != mb) { 22435485867bSBarry Smith *f = PETSC_FALSE; 22445485867bSBarry Smith PetscFunctionReturn(0); 22455485867bSBarry Smith } 22469566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &va)); 22479566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &vb)); 22489371c9d4SSatish Balay aii = aij->i; 22499371c9d4SSatish Balay bii = bij->i; 22509371c9d4SSatish Balay adx = aij->j; 22519371c9d4SSatish Balay bdx = bij->j; 22529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ma, &aptr)); 22539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mb, &bptr)); 2254cd0d46ebSvictorle for (i = 0; i < ma; i++) aptr[i] = aii[i]; 2255cd0d46ebSvictorle for (i = 0; i < mb; i++) bptr[i] = bii[i]; 2256cd0d46ebSvictorle 2257cd0d46ebSvictorle *f = PETSC_TRUE; 2258cd0d46ebSvictorle for (i = 0; i < ma; i++) { 2259cd0d46ebSvictorle while (aptr[i] < aii[i + 1]) { 226097f1f81fSBarry Smith PetscInt idc, idr; 22615485867bSBarry Smith PetscScalar vc, vr; 2262cd0d46ebSvictorle /* column/row index/value */ 22635485867bSBarry Smith idc = adx[aptr[i]]; 22645485867bSBarry Smith idr = bdx[bptr[idc]]; 22655485867bSBarry Smith vc = va[aptr[i]]; 22665485867bSBarry Smith vr = vb[bptr[idc]]; 22675485867bSBarry Smith if (i != idr || PetscAbsScalar(vc - vr) > tol) { 22685485867bSBarry Smith *f = PETSC_FALSE; 22695485867bSBarry Smith goto done; 2270cd0d46ebSvictorle } else { 22715485867bSBarry Smith aptr[i]++; 22725485867bSBarry Smith if (B || i != idc) bptr[idc]++; 2273cd0d46ebSvictorle } 2274cd0d46ebSvictorle } 2275cd0d46ebSvictorle } 2276cd0d46ebSvictorle done: 22779566063dSJacob Faibussowitsch PetscCall(PetscFree(aptr)); 22789566063dSJacob Faibussowitsch PetscCall(PetscFree(bptr)); 22799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &va)); 22809566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &vb)); 2281cd0d46ebSvictorle PetscFunctionReturn(0); 2282cd0d46ebSvictorle } 2283cd0d46ebSvictorle 22849371c9d4SSatish Balay PetscErrorCode MatIsHermitianTranspose_SeqAIJ(Mat A, Mat B, PetscReal tol, PetscBool *f) { 22853d3eaba7SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data, *bij = (Mat_SeqAIJ *)B->data; 228654f21887SBarry Smith PetscInt *adx, *bdx, *aii, *bii, *aptr, *bptr; 228754f21887SBarry Smith MatScalar *va, *vb; 22881cbb95d3SBarry Smith PetscInt ma, na, mb, nb, i; 22891cbb95d3SBarry Smith 22901cbb95d3SBarry Smith PetscFunctionBegin; 22919566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &ma, &na)); 22929566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &mb, &nb)); 22931cbb95d3SBarry Smith if (ma != nb || na != mb) { 22941cbb95d3SBarry Smith *f = PETSC_FALSE; 22951cbb95d3SBarry Smith PetscFunctionReturn(0); 22961cbb95d3SBarry Smith } 22979371c9d4SSatish Balay aii = aij->i; 22989371c9d4SSatish Balay bii = bij->i; 22999371c9d4SSatish Balay adx = aij->j; 23009371c9d4SSatish Balay bdx = bij->j; 23019371c9d4SSatish Balay va = aij->a; 23029371c9d4SSatish Balay vb = bij->a; 23039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ma, &aptr)); 23049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mb, &bptr)); 23051cbb95d3SBarry Smith for (i = 0; i < ma; i++) aptr[i] = aii[i]; 23061cbb95d3SBarry Smith for (i = 0; i < mb; i++) bptr[i] = bii[i]; 23071cbb95d3SBarry Smith 23081cbb95d3SBarry Smith *f = PETSC_TRUE; 23091cbb95d3SBarry Smith for (i = 0; i < ma; i++) { 23101cbb95d3SBarry Smith while (aptr[i] < aii[i + 1]) { 23111cbb95d3SBarry Smith PetscInt idc, idr; 23121cbb95d3SBarry Smith PetscScalar vc, vr; 23131cbb95d3SBarry Smith /* column/row index/value */ 23141cbb95d3SBarry Smith idc = adx[aptr[i]]; 23151cbb95d3SBarry Smith idr = bdx[bptr[idc]]; 23161cbb95d3SBarry Smith vc = va[aptr[i]]; 23171cbb95d3SBarry Smith vr = vb[bptr[idc]]; 23181cbb95d3SBarry Smith if (i != idr || PetscAbsScalar(vc - PetscConj(vr)) > tol) { 23191cbb95d3SBarry Smith *f = PETSC_FALSE; 23201cbb95d3SBarry Smith goto done; 23211cbb95d3SBarry Smith } else { 23221cbb95d3SBarry Smith aptr[i]++; 23231cbb95d3SBarry Smith if (B || i != idc) bptr[idc]++; 23241cbb95d3SBarry Smith } 23251cbb95d3SBarry Smith } 23261cbb95d3SBarry Smith } 23271cbb95d3SBarry Smith done: 23289566063dSJacob Faibussowitsch PetscCall(PetscFree(aptr)); 23299566063dSJacob Faibussowitsch PetscCall(PetscFree(bptr)); 23301cbb95d3SBarry Smith PetscFunctionReturn(0); 23311cbb95d3SBarry Smith } 23321cbb95d3SBarry Smith 23339371c9d4SSatish Balay PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A, PetscReal tol, PetscBool *f) { 23349e29f15eSvictorle PetscFunctionBegin; 23359566063dSJacob Faibussowitsch PetscCall(MatIsTranspose_SeqAIJ(A, A, tol, f)); 23369e29f15eSvictorle PetscFunctionReturn(0); 23379e29f15eSvictorle } 23389e29f15eSvictorle 23399371c9d4SSatish Balay PetscErrorCode MatIsHermitian_SeqAIJ(Mat A, PetscReal tol, PetscBool *f) { 23401cbb95d3SBarry Smith PetscFunctionBegin; 23419566063dSJacob Faibussowitsch PetscCall(MatIsHermitianTranspose_SeqAIJ(A, A, tol, f)); 23421cbb95d3SBarry Smith PetscFunctionReturn(0); 23431cbb95d3SBarry Smith } 23441cbb95d3SBarry Smith 23459371c9d4SSatish Balay PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A, Vec ll, Vec rr) { 2346416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2347fff8e43fSBarry Smith const PetscScalar *l, *r; 2348fff8e43fSBarry Smith PetscScalar x; 234954f21887SBarry Smith MatScalar *v; 2350fff8e43fSBarry Smith PetscInt i, j, m = A->rmap->n, n = A->cmap->n, M, nz = a->nz; 2351fff8e43fSBarry Smith const PetscInt *jj; 235217ab2063SBarry Smith 23533a40ed3dSBarry Smith PetscFunctionBegin; 235417ab2063SBarry Smith if (ll) { 23553ea7c6a1SSatish Balay /* The local size is used so that VecMPI can be passed to this routine 23563ea7c6a1SSatish Balay by MatDiagonalScale_MPIAIJ */ 23579566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ll, &m)); 235808401ef6SPierre Jolivet PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vector wrong length"); 23599566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(ll, &l)); 23609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &v)); 236117ab2063SBarry Smith for (i = 0; i < m; i++) { 236217ab2063SBarry Smith x = l[i]; 2363416022c9SBarry Smith M = a->i[i + 1] - a->i[i]; 23642205254eSKarl Rupp for (j = 0; j < M; j++) (*v++) *= x; 236517ab2063SBarry Smith } 23669566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(ll, &l)); 23679566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(nz)); 23689566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &v)); 236917ab2063SBarry Smith } 237017ab2063SBarry Smith if (rr) { 23719566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rr, &n)); 237208401ef6SPierre Jolivet PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vector wrong length"); 23739566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(rr, &r)); 23749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &v)); 23752e5835c6SStefano Zampini jj = a->j; 23762205254eSKarl Rupp for (i = 0; i < nz; i++) (*v++) *= r[*jj++]; 23779566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &v)); 23789566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(rr, &r)); 23799566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(nz)); 238017ab2063SBarry Smith } 23819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 23823a40ed3dSBarry Smith PetscFunctionReturn(0); 238317ab2063SBarry Smith } 238417ab2063SBarry Smith 23859371c9d4SSatish Balay PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A, IS isrow, IS iscol, PetscInt csize, MatReuse scall, Mat *B) { 2386db02288aSLois Curfman McInnes Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data, *c; 2387d0f46423SBarry Smith PetscInt *smap, i, k, kstart, kend, oldcols = A->cmap->n, *lens; 238897f1f81fSBarry Smith PetscInt row, mat_i, *mat_j, tcol, first, step, *mat_ilen, sum, lensi; 23895d0c19d7SBarry Smith const PetscInt *irow, *icol; 23902e5835c6SStefano Zampini const PetscScalar *aa; 23915d0c19d7SBarry Smith PetscInt nrows, ncols; 239297f1f81fSBarry Smith PetscInt *starts, *j_new, *i_new, *aj = a->j, *ai = a->i, ii, *ailen = a->ilen; 239354f21887SBarry Smith MatScalar *a_new, *mat_a; 2394416022c9SBarry Smith Mat C; 2395cdc6f3adSToby Isaac PetscBool stride; 239617ab2063SBarry Smith 23973a40ed3dSBarry Smith PetscFunctionBegin; 23989566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow, &irow)); 23999566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow, &nrows)); 24009566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol, &ncols)); 240117ab2063SBarry Smith 24029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)iscol, ISSTRIDE, &stride)); 2403ff718158SBarry Smith if (stride) { 24049566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(iscol, &first, &step)); 2405ff718158SBarry Smith } else { 2406ff718158SBarry Smith first = 0; 2407ff718158SBarry Smith step = 0; 2408ff718158SBarry Smith } 2409fee21e36SBarry Smith if (stride && step == 1) { 241002834360SBarry Smith /* special case of contiguous rows */ 24119566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nrows, &lens, nrows, &starts)); 241202834360SBarry Smith /* loop over new rows determining lens and starting points */ 241302834360SBarry Smith for (i = 0; i < nrows; i++) { 2414bfeeae90SHong Zhang kstart = ai[irow[i]]; 2415a2744918SBarry Smith kend = kstart + ailen[irow[i]]; 2416a91a9bebSLisandro Dalcin starts[i] = kstart; 241702834360SBarry Smith for (k = kstart; k < kend; k++) { 2418bfeeae90SHong Zhang if (aj[k] >= first) { 241902834360SBarry Smith starts[i] = k; 242002834360SBarry Smith break; 242102834360SBarry Smith } 242202834360SBarry Smith } 2423a2744918SBarry Smith sum = 0; 242402834360SBarry Smith while (k < kend) { 2425bfeeae90SHong Zhang if (aj[k++] >= first + ncols) break; 2426a2744918SBarry Smith sum++; 242702834360SBarry Smith } 2428a2744918SBarry Smith lens[i] = sum; 242902834360SBarry Smith } 243002834360SBarry Smith /* create submatrix */ 2431cddf8d76SBarry Smith if (scall == MAT_REUSE_MATRIX) { 243297f1f81fSBarry Smith PetscInt n_cols, n_rows; 24339566063dSJacob Faibussowitsch PetscCall(MatGetSize(*B, &n_rows, &n_cols)); 2434aed4548fSBarry Smith PetscCheck(n_rows == nrows && n_cols == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Reused submatrix wrong size"); 24359566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*B)); 243608480c60SBarry Smith C = *B; 24373a40ed3dSBarry Smith } else { 24383bef6203SJed Brown PetscInt rbs, cbs; 24399566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 24409566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, nrows, ncols, PETSC_DETERMINE, PETSC_DETERMINE)); 24419566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(isrow, &rbs)); 24429566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(iscol, &cbs)); 24439566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C, rbs, cbs)); 24449566063dSJacob Faibussowitsch PetscCall(MatSetType(C, ((PetscObject)A)->type_name)); 24459566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C, 0, lens)); 244608480c60SBarry Smith } 2447db02288aSLois Curfman McInnes c = (Mat_SeqAIJ *)C->data; 2448db02288aSLois Curfman McInnes 244902834360SBarry Smith /* loop over rows inserting into submatrix */ 2450db02288aSLois Curfman McInnes a_new = c->a; 2451db02288aSLois Curfman McInnes j_new = c->j; 2452db02288aSLois Curfman McInnes i_new = c->i; 24539566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 245402834360SBarry Smith for (i = 0; i < nrows; i++) { 2455a2744918SBarry Smith ii = starts[i]; 2456a2744918SBarry Smith lensi = lens[i]; 2457ad540459SPierre Jolivet for (k = 0; k < lensi; k++) *j_new++ = aj[ii + k] - first; 24589566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a_new, aa + starts[i], lensi)); 2459a2744918SBarry Smith a_new += lensi; 2460a2744918SBarry Smith i_new[i + 1] = i_new[i] + lensi; 2461a2744918SBarry Smith c->ilen[i] = lensi; 246202834360SBarry Smith } 24639566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 24649566063dSJacob Faibussowitsch PetscCall(PetscFree2(lens, starts)); 24653a40ed3dSBarry Smith } else { 24669566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol, &icol)); 24679566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(oldcols, &smap)); 24689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1 + nrows, &lens)); 24694dcab191SBarry Smith for (i = 0; i < ncols; i++) { 24706bdcaf15SBarry 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); 24714dcab191SBarry Smith smap[icol[i]] = i + 1; 24724dcab191SBarry Smith } 24734dcab191SBarry Smith 247402834360SBarry Smith /* determine lens of each row */ 247502834360SBarry Smith for (i = 0; i < nrows; i++) { 2476bfeeae90SHong Zhang kstart = ai[irow[i]]; 247702834360SBarry Smith kend = kstart + a->ilen[irow[i]]; 247802834360SBarry Smith lens[i] = 0; 247902834360SBarry Smith for (k = kstart; k < kend; k++) { 2480ad540459SPierre Jolivet if (smap[aj[k]]) lens[i]++; 248102834360SBarry Smith } 248202834360SBarry Smith } 248317ab2063SBarry Smith /* Create and fill new matrix */ 2484a2744918SBarry Smith if (scall == MAT_REUSE_MATRIX) { 2485ace3abfcSBarry Smith PetscBool equal; 24860f5bd95cSBarry Smith 248799141d43SSatish Balay c = (Mat_SeqAIJ *)((*B)->data); 2488aed4548fSBarry Smith PetscCheck((*B)->rmap->n == nrows && (*B)->cmap->n == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot reuse matrix. wrong size"); 24899566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(c->ilen, lens, (*B)->rmap->n, &equal)); 249028b400f6SJacob Faibussowitsch PetscCheck(equal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot reuse matrix. wrong no of nonzeros"); 24919566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->ilen, (*B)->rmap->n)); 249208480c60SBarry Smith C = *B; 24933a40ed3dSBarry Smith } else { 24943bef6203SJed Brown PetscInt rbs, cbs; 24959566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 24969566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, nrows, ncols, PETSC_DETERMINE, PETSC_DETERMINE)); 24979566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(isrow, &rbs)); 24989566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(iscol, &cbs)); 24999566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C, rbs, cbs)); 25009566063dSJacob Faibussowitsch PetscCall(MatSetType(C, ((PetscObject)A)->type_name)); 25019566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C, 0, lens)); 250208480c60SBarry Smith } 25039566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 250499141d43SSatish Balay c = (Mat_SeqAIJ *)(C->data); 250517ab2063SBarry Smith for (i = 0; i < nrows; i++) { 250699141d43SSatish Balay row = irow[i]; 2507bfeeae90SHong Zhang kstart = ai[row]; 250899141d43SSatish Balay kend = kstart + a->ilen[row]; 2509bfeeae90SHong Zhang mat_i = c->i[i]; 251099141d43SSatish Balay mat_j = c->j + mat_i; 251199141d43SSatish Balay mat_a = c->a + mat_i; 251299141d43SSatish Balay mat_ilen = c->ilen + i; 251317ab2063SBarry Smith for (k = kstart; k < kend; k++) { 2514bfeeae90SHong Zhang if ((tcol = smap[a->j[k]])) { 2515ed480e8bSBarry Smith *mat_j++ = tcol - 1; 25162e5835c6SStefano Zampini *mat_a++ = aa[k]; 251799141d43SSatish Balay (*mat_ilen)++; 251817ab2063SBarry Smith } 251917ab2063SBarry Smith } 252017ab2063SBarry Smith } 25219566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 252202834360SBarry Smith /* Free work space */ 25239566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol, &icol)); 25249566063dSJacob Faibussowitsch PetscCall(PetscFree(smap)); 25259566063dSJacob Faibussowitsch PetscCall(PetscFree(lens)); 2526cdc6f3adSToby Isaac /* sort */ 2527cdc6f3adSToby Isaac for (i = 0; i < nrows; i++) { 2528cdc6f3adSToby Isaac PetscInt ilen; 2529cdc6f3adSToby Isaac 2530cdc6f3adSToby Isaac mat_i = c->i[i]; 2531cdc6f3adSToby Isaac mat_j = c->j + mat_i; 2532cdc6f3adSToby Isaac mat_a = c->a + mat_i; 2533cdc6f3adSToby Isaac ilen = c->ilen[i]; 25349566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(ilen, mat_j, mat_a)); 2535cdc6f3adSToby Isaac } 253602834360SBarry Smith } 25378c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 25389566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(C, A->boundtocpu)); 2539305c6ccfSStefano Zampini #endif 25409566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 25419566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 254217ab2063SBarry Smith 25439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow, &irow)); 2544416022c9SBarry Smith *B = C; 25453a40ed3dSBarry Smith PetscFunctionReturn(0); 254617ab2063SBarry Smith } 254717ab2063SBarry Smith 25489371c9d4SSatish Balay PetscErrorCode MatGetMultiProcBlock_SeqAIJ(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) { 254982d44351SHong Zhang Mat B; 255082d44351SHong Zhang 255182d44351SHong Zhang PetscFunctionBegin; 2552c2d650bdSHong Zhang if (scall == MAT_INITIAL_MATRIX) { 25539566063dSJacob Faibussowitsch PetscCall(MatCreate(subComm, &B)); 25549566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->n, mat->cmap->n)); 25559566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, mat, mat)); 25569566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATSEQAIJ)); 25579566063dSJacob Faibussowitsch PetscCall(MatDuplicateNoCreate_SeqAIJ(B, mat, MAT_COPY_VALUES, PETSC_TRUE)); 255882d44351SHong Zhang *subMat = B; 2559c2d650bdSHong Zhang } else { 25609566063dSJacob Faibussowitsch PetscCall(MatCopy_SeqAIJ(mat, *subMat, SAME_NONZERO_PATTERN)); 2561c2d650bdSHong Zhang } 256282d44351SHong Zhang PetscFunctionReturn(0); 256382d44351SHong Zhang } 256482d44351SHong Zhang 25659371c9d4SSatish Balay PetscErrorCode MatILUFactor_SeqAIJ(Mat inA, IS row, IS col, const MatFactorInfo *info) { 256663b91edcSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)inA->data; 256763b91edcSBarry Smith Mat outA; 2568ace3abfcSBarry Smith PetscBool row_identity, col_identity; 256963b91edcSBarry Smith 25703a40ed3dSBarry Smith PetscFunctionBegin; 257108401ef6SPierre Jolivet PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 supported for in-place ilu"); 25721df811f5SHong Zhang 25739566063dSJacob Faibussowitsch PetscCall(ISIdentity(row, &row_identity)); 25749566063dSJacob Faibussowitsch PetscCall(ISIdentity(col, &col_identity)); 2575a871dcd8SBarry Smith 257663b91edcSBarry Smith outA = inA; 2577d5f3da31SBarry Smith outA->factortype = MAT_FACTOR_LU; 25789566063dSJacob Faibussowitsch PetscCall(PetscFree(inA->solvertype)); 25799566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype)); 25802205254eSKarl Rupp 25819566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)row)); 25829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 25832205254eSKarl Rupp 2584c3122656SLisandro Dalcin a->row = row; 25852205254eSKarl Rupp 25869566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)col)); 25879566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 25882205254eSKarl Rupp 2589c3122656SLisandro Dalcin a->col = col; 259063b91edcSBarry Smith 259136db0b34SBarry Smith /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */ 25929566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 25939566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(col, PETSC_DECIDE, &a->icol)); 2594f0ec6fceSSatish Balay 259594a9d846SBarry Smith if (!a->solve_work) { /* this matrix may have been factored before */ 25969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(inA->rmap->n + 1, &a->solve_work)); 259794a9d846SBarry Smith } 259863b91edcSBarry Smith 25999566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(inA)); 2600137fb511SHong Zhang if (row_identity && col_identity) { 26019566063dSJacob Faibussowitsch PetscCall(MatLUFactorNumeric_SeqAIJ_inplace(outA, inA, info)); 2602137fb511SHong Zhang } else { 26039566063dSJacob Faibussowitsch PetscCall(MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA, inA, info)); 2604137fb511SHong Zhang } 26053a40ed3dSBarry Smith PetscFunctionReturn(0); 2606a871dcd8SBarry Smith } 2607a871dcd8SBarry Smith 26089371c9d4SSatish Balay PetscErrorCode MatScale_SeqAIJ(Mat inA, PetscScalar alpha) { 2609f0b747eeSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)inA->data; 2610dfa0f9e5SStefano Zampini PetscScalar *v; 2611c5df96a5SBarry Smith PetscBLASInt one = 1, bnz; 26123a40ed3dSBarry Smith 26133a40ed3dSBarry Smith PetscFunctionBegin; 26149566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(inA, &v)); 26159566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(a->nz, &bnz)); 2616792fecdfSBarry Smith PetscCallBLAS("BLASscal", BLASscal_(&bnz, &alpha, v, &one)); 26179566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 26189566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(inA, &v)); 26199566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(inA)); 26203a40ed3dSBarry Smith PetscFunctionReturn(0); 2621f0b747eeSBarry Smith } 2622f0b747eeSBarry Smith 26239371c9d4SSatish Balay PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj) { 262416b64355SHong Zhang PetscInt i; 262516b64355SHong Zhang 262616b64355SHong Zhang PetscFunctionBegin; 262716b64355SHong Zhang if (!submatj->id) { /* delete data that are linked only to submats[id=0] */ 26289566063dSJacob Faibussowitsch PetscCall(PetscFree4(submatj->sbuf1, submatj->ptr, submatj->tmp, submatj->ctr)); 262916b64355SHong Zhang 263048a46eb9SPierre Jolivet for (i = 0; i < submatj->nrqr; ++i) PetscCall(PetscFree(submatj->sbuf2[i])); 26319566063dSJacob Faibussowitsch PetscCall(PetscFree3(submatj->sbuf2, submatj->req_size, submatj->req_source1)); 263216b64355SHong Zhang 263316b64355SHong Zhang if (submatj->rbuf1) { 26349566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rbuf1[0])); 26359566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rbuf1)); 263616b64355SHong Zhang } 263716b64355SHong Zhang 263848a46eb9SPierre Jolivet for (i = 0; i < submatj->nrqs; ++i) PetscCall(PetscFree(submatj->rbuf3[i])); 26399566063dSJacob Faibussowitsch PetscCall(PetscFree3(submatj->req_source2, submatj->rbuf2, submatj->rbuf3)); 26409566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->pa)); 264116b64355SHong Zhang } 264216b64355SHong Zhang 264316b64355SHong Zhang #if defined(PETSC_USE_CTABLE) 26449566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy((PetscTable *)&submatj->rmap)); 26459566063dSJacob Faibussowitsch if (submatj->cmap_loc) PetscCall(PetscFree(submatj->cmap_loc)); 26469566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rmap_loc)); 264716b64355SHong Zhang #else 26489566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rmap)); 264916b64355SHong Zhang #endif 265016b64355SHong Zhang 265116b64355SHong Zhang if (!submatj->allcolumns) { 265216b64355SHong Zhang #if defined(PETSC_USE_CTABLE) 26539566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy((PetscTable *)&submatj->cmap)); 265416b64355SHong Zhang #else 26559566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->cmap)); 265616b64355SHong Zhang #endif 265716b64355SHong Zhang } 26589566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->row2proc)); 265916b64355SHong Zhang 26609566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj)); 266116b64355SHong Zhang PetscFunctionReturn(0); 266216b64355SHong Zhang } 266316b64355SHong Zhang 26649371c9d4SSatish Balay PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C) { 266516b64355SHong Zhang Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data; 26665c39f6d9SHong Zhang Mat_SubSppt *submatj = c->submatis1; 266716b64355SHong Zhang 266816b64355SHong Zhang PetscFunctionBegin; 26699566063dSJacob Faibussowitsch PetscCall((*submatj->destroy)(C)); 26709566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrix_Private(submatj)); 267116b64355SHong Zhang PetscFunctionReturn(0); 267216b64355SHong Zhang } 267316b64355SHong Zhang 267489a1a59bSHong Zhang /* Note this has code duplication with MatDestroySubMatrices_SeqBAIJ() */ 26759371c9d4SSatish Balay PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n, Mat *mat[]) { 26762d033e1fSHong Zhang PetscInt i; 26770fb991dcSHong Zhang Mat C; 26780fb991dcSHong Zhang Mat_SeqAIJ *c; 26790fb991dcSHong Zhang Mat_SubSppt *submatj; 26802d033e1fSHong Zhang 26812d033e1fSHong Zhang PetscFunctionBegin; 26822d033e1fSHong Zhang for (i = 0; i < n; i++) { 26830fb991dcSHong Zhang C = (*mat)[i]; 26840fb991dcSHong Zhang c = (Mat_SeqAIJ *)C->data; 26850fb991dcSHong Zhang submatj = c->submatis1; 26862d033e1fSHong Zhang if (submatj) { 2687682e4c99SStefano Zampini if (--((PetscObject)C)->refct <= 0) { 268826cc229bSBarry Smith PetscCall(PetscFree(C->factorprefix)); 26899566063dSJacob Faibussowitsch PetscCall((*submatj->destroy)(C)); 26909566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrix_Private(submatj)); 26919566063dSJacob Faibussowitsch PetscCall(PetscFree(C->defaultvectype)); 26923faff063SStefano Zampini PetscCall(PetscFree(C->defaultrandtype)); 26939566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->rmap)); 26949566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->cmap)); 26959566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(&C)); 2696682e4c99SStefano Zampini } 26972d033e1fSHong Zhang } else { 26989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 26992d033e1fSHong Zhang } 27002d033e1fSHong Zhang } 270186e85357SHong Zhang 270263a75b2aSHong Zhang /* Destroy Dummy submatrices created for reuse */ 27039566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices_Dummy(n, mat)); 270463a75b2aSHong Zhang 27059566063dSJacob Faibussowitsch PetscCall(PetscFree(*mat)); 27062d033e1fSHong Zhang PetscFunctionReturn(0); 27072d033e1fSHong Zhang } 27082d033e1fSHong Zhang 27099371c9d4SSatish Balay PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[]) { 271097f1f81fSBarry Smith PetscInt i; 2711cddf8d76SBarry Smith 27123a40ed3dSBarry Smith PetscFunctionBegin; 271348a46eb9SPierre Jolivet if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n + 1, B)); 2714cddf8d76SBarry Smith 271548a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqAIJ(A, irow[i], icol[i], PETSC_DECIDE, scall, &(*B)[i])); 27163a40ed3dSBarry Smith PetscFunctionReturn(0); 2717cddf8d76SBarry Smith } 2718cddf8d76SBarry Smith 27199371c9d4SSatish Balay PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A, PetscInt is_max, IS is[], PetscInt ov) { 2720e4d965acSSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 27215d0c19d7SBarry Smith PetscInt row, i, j, k, l, m, n, *nidx, isz, val; 27225d0c19d7SBarry Smith const PetscInt *idx; 272397f1f81fSBarry Smith PetscInt start, end, *ai, *aj; 2724f1af5d2fSBarry Smith PetscBT table; 2725bbd702dbSSatish Balay 27263a40ed3dSBarry Smith PetscFunctionBegin; 2727d0f46423SBarry Smith m = A->rmap->n; 2728e4d965acSSatish Balay ai = a->i; 2729bfeeae90SHong Zhang aj = a->j; 27308a047759SSatish Balay 273108401ef6SPierre Jolivet PetscCheck(ov >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "illegal negative overlap value used"); 273206763907SSatish Balay 27339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nidx)); 27349566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(m, &table)); 273506763907SSatish Balay 2736e4d965acSSatish Balay for (i = 0; i < is_max; i++) { 2737b97fc60eSLois Curfman McInnes /* Initialize the two local arrays */ 2738e4d965acSSatish Balay isz = 0; 27399566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(m, table)); 2740e4d965acSSatish Balay 2741e4d965acSSatish Balay /* Extract the indices, assume there can be duplicate entries */ 27429566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is[i], &idx)); 27439566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is[i], &n)); 2744e4d965acSSatish Balay 2745dd097bc3SLois Curfman McInnes /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 2746e4d965acSSatish Balay for (j = 0; j < n; ++j) { 27472205254eSKarl Rupp if (!PetscBTLookupSet(table, idx[j])) nidx[isz++] = idx[j]; 27484dcbc457SBarry Smith } 27499566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is[i], &idx)); 27509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is[i])); 2751e4d965acSSatish Balay 275204a348a9SBarry Smith k = 0; 275304a348a9SBarry Smith for (j = 0; j < ov; j++) { /* for each overlap */ 275404a348a9SBarry Smith n = isz; 275506763907SSatish Balay for (; k < n; k++) { /* do only those rows in nidx[k], which are not done yet */ 2756e4d965acSSatish Balay row = nidx[k]; 2757e4d965acSSatish Balay start = ai[row]; 2758e4d965acSSatish Balay end = ai[row + 1]; 275904a348a9SBarry Smith for (l = start; l < end; l++) { 2760efb16452SHong Zhang val = aj[l]; 27612205254eSKarl Rupp if (!PetscBTLookupSet(table, val)) nidx[isz++] = val; 2762e4d965acSSatish Balay } 2763e4d965acSSatish Balay } 2764e4d965acSSatish Balay } 27659566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, isz, nidx, PETSC_COPY_VALUES, (is + i))); 2766e4d965acSSatish Balay } 27679566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&table)); 27689566063dSJacob Faibussowitsch PetscCall(PetscFree(nidx)); 27693a40ed3dSBarry Smith PetscFunctionReturn(0); 27704dcbc457SBarry Smith } 277117ab2063SBarry Smith 27720513a670SBarry Smith /* -------------------------------------------------------------- */ 27739371c9d4SSatish Balay PetscErrorCode MatPermute_SeqAIJ(Mat A, IS rowp, IS colp, Mat *B) { 27740513a670SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 27753b98c0a2SBarry Smith PetscInt i, nz = 0, m = A->rmap->n, n = A->cmap->n; 27765d0c19d7SBarry Smith const PetscInt *row, *col; 27775d0c19d7SBarry Smith PetscInt *cnew, j, *lens; 277856cd22aeSBarry Smith IS icolp, irowp; 27790298fd71SBarry Smith PetscInt *cwork = NULL; 27800298fd71SBarry Smith PetscScalar *vwork = NULL; 27810513a670SBarry Smith 27823a40ed3dSBarry Smith PetscFunctionBegin; 27839566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rowp, PETSC_DECIDE, &irowp)); 27849566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irowp, &row)); 27859566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(colp, PETSC_DECIDE, &icolp)); 27869566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icolp, &col)); 27870513a670SBarry Smith 27880513a670SBarry Smith /* determine lengths of permuted rows */ 27899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &lens)); 27902205254eSKarl Rupp for (i = 0; i < m; i++) lens[row[i]] = a->i[i + 1] - a->i[i]; 27919566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 27929566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, m, n, m, n)); 27939566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(*B, A, A)); 27949566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, ((PetscObject)A)->type_name)); 27959566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*B, 0, lens)); 27969566063dSJacob Faibussowitsch PetscCall(PetscFree(lens)); 27970513a670SBarry Smith 27989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &cnew)); 27990513a670SBarry Smith for (i = 0; i < m; i++) { 28009566063dSJacob Faibussowitsch PetscCall(MatGetRow_SeqAIJ(A, i, &nz, &cwork, &vwork)); 28012205254eSKarl Rupp for (j = 0; j < nz; j++) cnew[j] = col[cwork[j]]; 28029566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(*B, 1, &row[i], nz, cnew, vwork, INSERT_VALUES)); 28039566063dSJacob Faibussowitsch PetscCall(MatRestoreRow_SeqAIJ(A, i, &nz, &cwork, &vwork)); 28040513a670SBarry Smith } 28059566063dSJacob Faibussowitsch PetscCall(PetscFree(cnew)); 28062205254eSKarl Rupp 28073c7d62e4SBarry Smith (*B)->assembled = PETSC_FALSE; 28082205254eSKarl Rupp 28098c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 28109566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(*B, A->boundtocpu)); 28119fe5e383SStefano Zampini #endif 28129566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 28139566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 28149566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irowp, &row)); 28159566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icolp, &col)); 28169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irowp)); 28179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icolp)); 281848a46eb9SPierre Jolivet if (rowp == colp) PetscCall(MatPropagateSymmetryOptions(A, *B)); 28193a40ed3dSBarry Smith PetscFunctionReturn(0); 28200513a670SBarry Smith } 28210513a670SBarry Smith 28229371c9d4SSatish Balay PetscErrorCode MatCopy_SeqAIJ(Mat A, Mat B, MatStructure str) { 2823cb5b572fSBarry Smith PetscFunctionBegin; 282433f4a19fSKris Buschelman /* If the two matrices have the same copy implementation, use fast copy. */ 282533f4a19fSKris Buschelman if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) { 2826be6bf707SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2827be6bf707SBarry Smith Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 28282e5835c6SStefano Zampini const PetscScalar *aa; 2829be6bf707SBarry Smith 28309566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 283108401ef6SPierre 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]); 28329566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->a, aa, a->i[A->rmap->n])); 28339566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 28349566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 2835cb5b572fSBarry Smith } else { 28369566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 2837cb5b572fSBarry Smith } 2838cb5b572fSBarry Smith PetscFunctionReturn(0); 2839cb5b572fSBarry Smith } 2840cb5b572fSBarry Smith 28419371c9d4SSatish Balay PetscErrorCode MatSetUp_SeqAIJ(Mat A) { 2842273d9f13SBarry Smith PetscFunctionBegin; 28439566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A, PETSC_DEFAULT, NULL)); 2844273d9f13SBarry Smith PetscFunctionReturn(0); 2845273d9f13SBarry Smith } 2846273d9f13SBarry Smith 28479371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A, PetscScalar *array[]) { 28486c0721eeSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 28496e111a19SKarl Rupp 28506c0721eeSBarry Smith PetscFunctionBegin; 28516c0721eeSBarry Smith *array = a->a; 28526c0721eeSBarry Smith PetscFunctionReturn(0); 28536c0721eeSBarry Smith } 28546c0721eeSBarry Smith 28559371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A, PetscScalar *array[]) { 28566c0721eeSBarry Smith PetscFunctionBegin; 2857f38c1e66SStefano Zampini *array = NULL; 28586c0721eeSBarry Smith PetscFunctionReturn(0); 28596c0721eeSBarry Smith } 2860273d9f13SBarry Smith 28618229c054SShri Abhyankar /* 28628229c054SShri Abhyankar Computes the number of nonzeros per row needed for preallocation when X and Y 28638229c054SShri Abhyankar have different nonzero structure. 28648229c054SShri Abhyankar */ 28659371c9d4SSatish Balay PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m, const PetscInt *xi, const PetscInt *xj, const PetscInt *yi, const PetscInt *yj, PetscInt *nnz) { 2866b264fe52SHong Zhang PetscInt i, j, k, nzx, nzy; 2867ec7775f6SShri Abhyankar 2868ec7775f6SShri Abhyankar PetscFunctionBegin; 2869ec7775f6SShri Abhyankar /* Set the number of nonzeros in the new matrix */ 2870ec7775f6SShri Abhyankar for (i = 0; i < m; i++) { 2871b264fe52SHong Zhang const PetscInt *xjj = xj + xi[i], *yjj = yj + yi[i]; 2872b264fe52SHong Zhang nzx = xi[i + 1] - xi[i]; 2873b264fe52SHong Zhang nzy = yi[i + 1] - yi[i]; 28748af7cee1SJed Brown nnz[i] = 0; 28758af7cee1SJed Brown for (j = 0, k = 0; j < nzx; j++) { /* Point in X */ 2876b264fe52SHong Zhang for (; k < nzy && yjj[k] < xjj[j]; k++) nnz[i]++; /* Catch up to X */ 2877b264fe52SHong Zhang if (k < nzy && yjj[k] == xjj[j]) k++; /* Skip duplicate */ 28788af7cee1SJed Brown nnz[i]++; 28798af7cee1SJed Brown } 28808af7cee1SJed Brown for (; k < nzy; k++) nnz[i]++; 2881ec7775f6SShri Abhyankar } 2882ec7775f6SShri Abhyankar PetscFunctionReturn(0); 2883ec7775f6SShri Abhyankar } 2884ec7775f6SShri Abhyankar 28859371c9d4SSatish Balay PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y, Mat X, PetscInt *nnz) { 2886b264fe52SHong Zhang PetscInt m = Y->rmap->N; 2887b264fe52SHong Zhang Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data; 2888b264fe52SHong Zhang Mat_SeqAIJ *y = (Mat_SeqAIJ *)Y->data; 2889b264fe52SHong Zhang 2890b264fe52SHong Zhang PetscFunctionBegin; 2891b264fe52SHong Zhang /* Set the number of nonzeros in the new matrix */ 28929566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqX_private(m, x->i, x->j, y->i, y->j, nnz)); 2893b264fe52SHong Zhang PetscFunctionReturn(0); 2894b264fe52SHong Zhang } 2895b264fe52SHong Zhang 28969371c9d4SSatish Balay PetscErrorCode MatAXPY_SeqAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str) { 2897ac90fabeSBarry Smith Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data, *y = (Mat_SeqAIJ *)Y->data; 2898ac90fabeSBarry Smith 2899ac90fabeSBarry Smith PetscFunctionBegin; 2900134adf20SPierre Jolivet if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) { 2901134adf20SPierre Jolivet PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE; 2902134adf20SPierre Jolivet if (e) { 29039566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->i, y->i, Y->rmap->n + 1, &e)); 290481fa06acSBarry Smith if (e) { 29059566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->j, y->j, y->nz, &e)); 2906134adf20SPierre Jolivet if (e) str = SAME_NONZERO_PATTERN; 290781fa06acSBarry Smith } 290881fa06acSBarry Smith } 290954c59aa7SJacob Faibussowitsch if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN"); 291081fa06acSBarry Smith } 2911ac90fabeSBarry Smith if (str == SAME_NONZERO_PATTERN) { 29122e5835c6SStefano Zampini const PetscScalar *xa; 29132e5835c6SStefano Zampini PetscScalar *ya, alpha = a; 291481fa06acSBarry Smith PetscBLASInt one = 1, bnz; 291581fa06acSBarry Smith 29169566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(x->nz, &bnz)); 29179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Y, &ya)); 29189566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(X, &xa)); 2919792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, xa, &one, ya, &one)); 29209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(X, &xa)); 29219566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Y, &ya)); 29229566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * bnz)); 29239566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(Y)); 29249566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 2925ab784542SHong Zhang } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 29269566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 2927ac90fabeSBarry Smith } else { 29288229c054SShri Abhyankar Mat B; 29298229c054SShri Abhyankar PetscInt *nnz; 29309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Y->rmap->N, &nnz)); 29319566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B)); 29329566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name)); 29339566063dSJacob Faibussowitsch PetscCall(MatSetLayouts(B, Y->rmap, Y->cmap)); 29349566063dSJacob Faibussowitsch PetscCall(MatSetType(B, ((PetscObject)Y)->type_name)); 29359566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqAIJ(Y, X, nnz)); 29369566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz)); 29379566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 29389566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 29399bb234a9SBarry Smith PetscCall(MatSeqAIJCheckInode(Y)); 29409566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 2941ac90fabeSBarry Smith } 2942ac90fabeSBarry Smith PetscFunctionReturn(0); 2943ac90fabeSBarry Smith } 2944ac90fabeSBarry Smith 29459371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat) { 2946354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX) 2947354c94deSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2948354c94deSBarry Smith PetscInt i, nz; 2949354c94deSBarry Smith PetscScalar *a; 2950354c94deSBarry Smith 2951354c94deSBarry Smith PetscFunctionBegin; 2952354c94deSBarry Smith nz = aij->nz; 29539566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(mat, &a)); 29542205254eSKarl Rupp for (i = 0; i < nz; i++) a[i] = PetscConj(a[i]); 29559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(mat, &a)); 2956354c94deSBarry Smith #else 2957354c94deSBarry Smith PetscFunctionBegin; 2958354c94deSBarry Smith #endif 2959354c94deSBarry Smith PetscFunctionReturn(0); 2960354c94deSBarry Smith } 2961354c94deSBarry Smith 29629371c9d4SSatish Balay PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 2963e34fafa9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2964d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 2965e34fafa9SBarry Smith PetscReal atmp; 2966985db425SBarry Smith PetscScalar *x; 2967ce496241SStefano Zampini const MatScalar *aa, *av; 2968e34fafa9SBarry Smith 2969e34fafa9SBarry Smith PetscFunctionBegin; 297028b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 29719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 2972ce496241SStefano Zampini aa = av; 2973e34fafa9SBarry Smith ai = a->i; 2974e34fafa9SBarry Smith aj = a->j; 2975e34fafa9SBarry Smith 29769566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 29779566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 29789566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 297908401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 2980e34fafa9SBarry Smith for (i = 0; i < m; i++) { 29819371c9d4SSatish Balay ncols = ai[1] - ai[0]; 29829371c9d4SSatish Balay ai++; 2983e34fafa9SBarry Smith for (j = 0; j < ncols; j++) { 2984985db425SBarry Smith atmp = PetscAbsScalar(*aa); 29859371c9d4SSatish Balay if (PetscAbsScalar(x[i]) < atmp) { 29869371c9d4SSatish Balay x[i] = atmp; 29879371c9d4SSatish Balay if (idx) idx[i] = *aj; 29889371c9d4SSatish Balay } 29899371c9d4SSatish Balay aa++; 29909371c9d4SSatish Balay aj++; 2991985db425SBarry Smith } 2992985db425SBarry Smith } 29939566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 29949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 2995985db425SBarry Smith PetscFunctionReturn(0); 2996985db425SBarry Smith } 2997985db425SBarry Smith 29989371c9d4SSatish Balay PetscErrorCode MatGetRowMax_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 2999985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3000d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 3001985db425SBarry Smith PetscScalar *x; 3002ce496241SStefano Zampini const MatScalar *aa, *av; 3003985db425SBarry Smith 3004985db425SBarry Smith PetscFunctionBegin; 300528b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 30069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3007ce496241SStefano Zampini aa = av; 3008985db425SBarry Smith ai = a->i; 3009985db425SBarry Smith aj = a->j; 3010985db425SBarry Smith 30119566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 30129566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 30139566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 301408401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3015985db425SBarry Smith for (i = 0; i < m; i++) { 30169371c9d4SSatish Balay ncols = ai[1] - ai[0]; 30179371c9d4SSatish Balay ai++; 3018d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 30199371c9d4SSatish Balay x[i] = *aa; 30209371c9d4SSatish Balay if (idx) idx[i] = 0; 3021985db425SBarry Smith } else { /* row is sparse so already KNOW maximum is 0.0 or higher */ 3022985db425SBarry Smith x[i] = 0.0; 3023985db425SBarry Smith if (idx) { 3024985db425SBarry Smith for (j = 0; j < ncols; j++) { /* find first implicit 0.0 in the row */ 3025985db425SBarry Smith if (aj[j] > j) { 3026985db425SBarry Smith idx[i] = j; 3027985db425SBarry Smith break; 3028985db425SBarry Smith } 3029985db425SBarry Smith } 30301a254869SHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 30311a254869SHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3032985db425SBarry Smith } 3033985db425SBarry Smith } 3034985db425SBarry Smith for (j = 0; j < ncols; j++) { 30359371c9d4SSatish Balay if (PetscRealPart(x[i]) < PetscRealPart(*aa)) { 30369371c9d4SSatish Balay x[i] = *aa; 30379371c9d4SSatish Balay if (idx) idx[i] = *aj; 30389371c9d4SSatish Balay } 30399371c9d4SSatish Balay aa++; 30409371c9d4SSatish Balay aj++; 3041985db425SBarry Smith } 3042985db425SBarry Smith } 30439566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 30449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3045985db425SBarry Smith PetscFunctionReturn(0); 3046985db425SBarry Smith } 3047985db425SBarry Smith 30489371c9d4SSatish Balay PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 3049c87e5d42SMatthew Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3050c87e5d42SMatthew Knepley PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 3051ce496241SStefano Zampini PetscScalar *x; 3052ce496241SStefano Zampini const MatScalar *aa, *av; 3053c87e5d42SMatthew Knepley 3054c87e5d42SMatthew Knepley PetscFunctionBegin; 30559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3056ce496241SStefano Zampini aa = av; 3057c87e5d42SMatthew Knepley ai = a->i; 3058c87e5d42SMatthew Knepley aj = a->j; 3059c87e5d42SMatthew Knepley 30609566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 30619566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 30629566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 306308401ef6SPierre Jolivet PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n); 3064c87e5d42SMatthew Knepley for (i = 0; i < m; i++) { 30659371c9d4SSatish Balay ncols = ai[1] - ai[0]; 30669371c9d4SSatish Balay ai++; 3067f07e67edSHong Zhang if (ncols == A->cmap->n) { /* row is dense */ 30689371c9d4SSatish Balay x[i] = *aa; 30699371c9d4SSatish Balay if (idx) idx[i] = 0; 3070f07e67edSHong Zhang } else { /* row is sparse so already KNOW minimum is 0.0 or higher */ 3071f07e67edSHong Zhang x[i] = 0.0; 3072f07e67edSHong Zhang if (idx) { /* find first implicit 0.0 in the row */ 3073289a08f5SMatthew Knepley for (j = 0; j < ncols; j++) { 3074f07e67edSHong Zhang if (aj[j] > j) { 3075f07e67edSHong Zhang idx[i] = j; 30762205254eSKarl Rupp break; 30772205254eSKarl Rupp } 3078289a08f5SMatthew Knepley } 3079f07e67edSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3080f07e67edSHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3081f07e67edSHong Zhang } 3082289a08f5SMatthew Knepley } 3083c87e5d42SMatthew Knepley for (j = 0; j < ncols; j++) { 30849371c9d4SSatish Balay if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) { 30859371c9d4SSatish Balay x[i] = *aa; 30869371c9d4SSatish Balay if (idx) idx[i] = *aj; 30879371c9d4SSatish Balay } 30889371c9d4SSatish Balay aa++; 30899371c9d4SSatish Balay aj++; 3090c87e5d42SMatthew Knepley } 3091c87e5d42SMatthew Knepley } 30929566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 30939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3094c87e5d42SMatthew Knepley PetscFunctionReturn(0); 3095c87e5d42SMatthew Knepley } 3096c87e5d42SMatthew Knepley 30979371c9d4SSatish Balay PetscErrorCode MatGetRowMin_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 3098985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3099d9ca1df4SBarry Smith PetscInt i, j, m = A->rmap->n, ncols, n; 3100d9ca1df4SBarry Smith const PetscInt *ai, *aj; 3101985db425SBarry Smith PetscScalar *x; 3102ce496241SStefano Zampini const MatScalar *aa, *av; 3103985db425SBarry Smith 3104985db425SBarry Smith PetscFunctionBegin; 310528b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 31069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3107ce496241SStefano Zampini aa = av; 3108985db425SBarry Smith ai = a->i; 3109985db425SBarry Smith aj = a->j; 3110985db425SBarry Smith 31119566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 31129566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 31139566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 311408401ef6SPierre Jolivet PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3115985db425SBarry Smith for (i = 0; i < m; i++) { 31169371c9d4SSatish Balay ncols = ai[1] - ai[0]; 31179371c9d4SSatish Balay ai++; 3118d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 31199371c9d4SSatish Balay x[i] = *aa; 31209371c9d4SSatish Balay if (idx) idx[i] = 0; 3121985db425SBarry Smith } else { /* row is sparse so already KNOW minimum is 0.0 or lower */ 3122985db425SBarry Smith x[i] = 0.0; 3123985db425SBarry Smith if (idx) { /* find first implicit 0.0 in the row */ 3124985db425SBarry Smith for (j = 0; j < ncols; j++) { 3125985db425SBarry Smith if (aj[j] > j) { 3126985db425SBarry Smith idx[i] = j; 3127985db425SBarry Smith break; 3128985db425SBarry Smith } 3129985db425SBarry Smith } 3130fa213d2fSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3131fa213d2fSHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3132985db425SBarry Smith } 3133985db425SBarry Smith } 3134985db425SBarry Smith for (j = 0; j < ncols; j++) { 31359371c9d4SSatish Balay if (PetscRealPart(x[i]) > PetscRealPart(*aa)) { 31369371c9d4SSatish Balay x[i] = *aa; 31379371c9d4SSatish Balay if (idx) idx[i] = *aj; 31389371c9d4SSatish Balay } 31399371c9d4SSatish Balay aa++; 31409371c9d4SSatish Balay aj++; 3141e34fafa9SBarry Smith } 3142e34fafa9SBarry Smith } 31439566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 31449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3145e34fafa9SBarry Smith PetscFunctionReturn(0); 3146e34fafa9SBarry Smith } 3147bbead8a2SBarry Smith 31489371c9d4SSatish Balay PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A, const PetscScalar **values) { 3149bbead8a2SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 315033d57670SJed Brown PetscInt i, bs = PetscAbs(A->rmap->bs), mbs = A->rmap->n / bs, ipvt[5], bs2 = bs * bs, *v_pivots, ij[7], *IJ, j; 3151bbead8a2SBarry Smith MatScalar *diag, work[25], *v_work; 31520da83c2eSBarry Smith const PetscReal shift = 0.0; 31531a9391e3SHong Zhang PetscBool allowzeropivot, zeropivotdetected = PETSC_FALSE; 3154bbead8a2SBarry Smith 3155bbead8a2SBarry Smith PetscFunctionBegin; 3156a455e926SHong Zhang allowzeropivot = PetscNot(A->erroriffailure); 31574a0d0026SBarry Smith if (a->ibdiagvalid) { 31584a0d0026SBarry Smith if (values) *values = a->ibdiag; 31594a0d0026SBarry Smith PetscFunctionReturn(0); 31604a0d0026SBarry Smith } 31619566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 3162*4dfa11a4SJacob Faibussowitsch if (!a->ibdiag) { PetscCall(PetscMalloc1(bs2 * mbs, &a->ibdiag)); } 3163bbead8a2SBarry Smith diag = a->ibdiag; 3164bbead8a2SBarry Smith if (values) *values = a->ibdiag; 3165bbead8a2SBarry Smith /* factor and invert each block */ 3166bbead8a2SBarry Smith switch (bs) { 3167bbead8a2SBarry Smith case 1: 3168bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 31699566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 1, &i, 1, &i, diag + i)); 3170ec1892c8SHong Zhang if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) { 3171ec1892c8SHong Zhang if (allowzeropivot) { 31727b6c816cSBarry Smith A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 31737b6c816cSBarry Smith A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]); 31747b6c816cSBarry Smith A->factorerror_zeropivot_row = i; 31759566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n", i, (double)PetscAbsScalar(diag[i]), (double)PETSC_MACHINE_EPSILON)); 317698921bdaSJacob 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); 3177ec1892c8SHong Zhang } 3178bbead8a2SBarry Smith diag[i] = (PetscScalar)1.0 / (diag[i] + shift); 3179bbead8a2SBarry Smith } 3180bbead8a2SBarry Smith break; 3181bbead8a2SBarry Smith case 2: 3182bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 31839371c9d4SSatish Balay ij[0] = 2 * i; 31849371c9d4SSatish Balay ij[1] = 2 * i + 1; 31859566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 2, ij, 2, ij, diag)); 31869566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected)); 31877b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 31889566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_2(diag)); 3189bbead8a2SBarry Smith diag += 4; 3190bbead8a2SBarry Smith } 3191bbead8a2SBarry Smith break; 3192bbead8a2SBarry Smith case 3: 3193bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 31949371c9d4SSatish Balay ij[0] = 3 * i; 31959371c9d4SSatish Balay ij[1] = 3 * i + 1; 31969371c9d4SSatish Balay ij[2] = 3 * i + 2; 31979566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 3, ij, 3, ij, diag)); 31989566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected)); 31997b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32009566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_3(diag)); 3201bbead8a2SBarry Smith diag += 9; 3202bbead8a2SBarry Smith } 3203bbead8a2SBarry Smith break; 3204bbead8a2SBarry Smith case 4: 3205bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32069371c9d4SSatish Balay ij[0] = 4 * i; 32079371c9d4SSatish Balay ij[1] = 4 * i + 1; 32089371c9d4SSatish Balay ij[2] = 4 * i + 2; 32099371c9d4SSatish Balay ij[3] = 4 * i + 3; 32109566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 4, ij, 4, ij, diag)); 32119566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected)); 32127b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32139566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_4(diag)); 3214bbead8a2SBarry Smith diag += 16; 3215bbead8a2SBarry Smith } 3216bbead8a2SBarry Smith break; 3217bbead8a2SBarry Smith case 5: 3218bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32199371c9d4SSatish Balay ij[0] = 5 * i; 32209371c9d4SSatish Balay ij[1] = 5 * i + 1; 32219371c9d4SSatish Balay ij[2] = 5 * i + 2; 32229371c9d4SSatish Balay ij[3] = 5 * i + 3; 32239371c9d4SSatish Balay ij[4] = 5 * i + 4; 32249566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 5, ij, 5, ij, diag)); 32259566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected)); 32267b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32279566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_5(diag)); 3228bbead8a2SBarry Smith diag += 25; 3229bbead8a2SBarry Smith } 3230bbead8a2SBarry Smith break; 3231bbead8a2SBarry Smith case 6: 3232bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32339371c9d4SSatish Balay ij[0] = 6 * i; 32349371c9d4SSatish Balay ij[1] = 6 * i + 1; 32359371c9d4SSatish Balay ij[2] = 6 * i + 2; 32369371c9d4SSatish Balay ij[3] = 6 * i + 3; 32379371c9d4SSatish Balay ij[4] = 6 * i + 4; 32389371c9d4SSatish Balay ij[5] = 6 * i + 5; 32399566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 6, ij, 6, ij, diag)); 32409566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected)); 32417b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32429566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_6(diag)); 3243bbead8a2SBarry Smith diag += 36; 3244bbead8a2SBarry Smith } 3245bbead8a2SBarry Smith break; 3246bbead8a2SBarry Smith case 7: 3247bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32489371c9d4SSatish Balay ij[0] = 7 * i; 32499371c9d4SSatish Balay ij[1] = 7 * i + 1; 32509371c9d4SSatish Balay ij[2] = 7 * i + 2; 32519371c9d4SSatish Balay ij[3] = 7 * i + 3; 32529371c9d4SSatish Balay ij[4] = 7 * i + 4; 32539371c9d4SSatish Balay ij[5] = 7 * i + 5; 32549371c9d4SSatish Balay ij[5] = 7 * i + 6; 32559566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 7, ij, 7, ij, diag)); 32569566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected)); 32577b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32589566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_7(diag)); 3259bbead8a2SBarry Smith diag += 49; 3260bbead8a2SBarry Smith } 3261bbead8a2SBarry Smith break; 3262bbead8a2SBarry Smith default: 32639566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(bs, &v_work, bs, &v_pivots, bs, &IJ)); 3264bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 3265ad540459SPierre Jolivet for (j = 0; j < bs; j++) IJ[j] = bs * i + j; 32669566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, bs, IJ, bs, IJ, diag)); 32679566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A(bs, diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected)); 32687b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32699566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_N(diag, bs)); 3270bbead8a2SBarry Smith diag += bs2; 3271bbead8a2SBarry Smith } 32729566063dSJacob Faibussowitsch PetscCall(PetscFree3(v_work, v_pivots, IJ)); 3273bbead8a2SBarry Smith } 3274bbead8a2SBarry Smith a->ibdiagvalid = PETSC_TRUE; 3275bbead8a2SBarry Smith PetscFunctionReturn(0); 3276bbead8a2SBarry Smith } 3277bbead8a2SBarry Smith 32789371c9d4SSatish Balay static PetscErrorCode MatSetRandom_SeqAIJ(Mat x, PetscRandom rctx) { 327973a71a0fSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data; 3280fff043a9SJunchao Zhang PetscScalar a, *aa; 328173a71a0fSBarry Smith PetscInt m, n, i, j, col; 328273a71a0fSBarry Smith 328373a71a0fSBarry Smith PetscFunctionBegin; 328473a71a0fSBarry Smith if (!x->assembled) { 32859566063dSJacob Faibussowitsch PetscCall(MatGetSize(x, &m, &n)); 328673a71a0fSBarry Smith for (i = 0; i < m; i++) { 328773a71a0fSBarry Smith for (j = 0; j < aij->imax[i]; j++) { 32889566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx, &a)); 328973a71a0fSBarry Smith col = (PetscInt)(n * PetscRealPart(a)); 32909566063dSJacob Faibussowitsch PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES)); 329173a71a0fSBarry Smith } 329273a71a0fSBarry Smith } 3293e2ce353bSJunchao Zhang } else { 32949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayWrite(x, &aa)); 32959566063dSJacob Faibussowitsch for (i = 0; i < aij->nz; i++) PetscCall(PetscRandomGetValue(rctx, aa + i)); 32969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayWrite(x, &aa)); 3297e2ce353bSJunchao Zhang } 32989566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 32999566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 330073a71a0fSBarry Smith PetscFunctionReturn(0); 330173a71a0fSBarry Smith } 330273a71a0fSBarry Smith 3303679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */ 33049371c9d4SSatish Balay PetscErrorCode MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x, PetscInt low, PetscInt high, PetscRandom rctx) { 3305679944adSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data; 3306679944adSJunchao Zhang PetscScalar a; 3307679944adSJunchao Zhang PetscInt m, n, i, j, col, nskip; 3308679944adSJunchao Zhang 3309679944adSJunchao Zhang PetscFunctionBegin; 3310679944adSJunchao Zhang nskip = high - low; 33119566063dSJacob Faibussowitsch PetscCall(MatGetSize(x, &m, &n)); 3312679944adSJunchao Zhang n -= nskip; /* shrink number of columns where nonzeros can be set */ 3313679944adSJunchao Zhang for (i = 0; i < m; i++) { 3314679944adSJunchao Zhang for (j = 0; j < aij->imax[i]; j++) { 33159566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx, &a)); 3316679944adSJunchao Zhang col = (PetscInt)(n * PetscRealPart(a)); 3317679944adSJunchao Zhang if (col >= low) col += nskip; /* shift col rightward to skip the hole */ 33189566063dSJacob Faibussowitsch PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES)); 3319679944adSJunchao Zhang } 3320e2ce353bSJunchao Zhang } 33219566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 33229566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 3323679944adSJunchao Zhang PetscFunctionReturn(0); 3324679944adSJunchao Zhang } 3325679944adSJunchao Zhang 3326682d7d0cSBarry Smith /* -------------------------------------------------------------------*/ 33270a6ffc59SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ, 3328cb5b572fSBarry Smith MatGetRow_SeqAIJ, 3329cb5b572fSBarry Smith MatRestoreRow_SeqAIJ, 3330cb5b572fSBarry Smith MatMult_SeqAIJ, 333197304618SKris Buschelman /* 4*/ MatMultAdd_SeqAIJ, 33327c922b88SBarry Smith MatMultTranspose_SeqAIJ, 33337c922b88SBarry Smith MatMultTransposeAdd_SeqAIJ, 3334f4259b30SLisandro Dalcin NULL, 3335f4259b30SLisandro Dalcin NULL, 3336f4259b30SLisandro Dalcin NULL, 3337f4259b30SLisandro Dalcin /* 10*/ NULL, 3338cb5b572fSBarry Smith MatLUFactor_SeqAIJ, 3339f4259b30SLisandro Dalcin NULL, 334041f059aeSBarry Smith MatSOR_SeqAIJ, 334191e9d3e2SHong Zhang MatTranspose_SeqAIJ, 334297304618SKris Buschelman /*1 5*/ MatGetInfo_SeqAIJ, 3343cb5b572fSBarry Smith MatEqual_SeqAIJ, 3344cb5b572fSBarry Smith MatGetDiagonal_SeqAIJ, 3345cb5b572fSBarry Smith MatDiagonalScale_SeqAIJ, 3346cb5b572fSBarry Smith MatNorm_SeqAIJ, 3347f4259b30SLisandro Dalcin /* 20*/ NULL, 3348cb5b572fSBarry Smith MatAssemblyEnd_SeqAIJ, 3349cb5b572fSBarry Smith MatSetOption_SeqAIJ, 3350cb5b572fSBarry Smith MatZeroEntries_SeqAIJ, 3351d519adbfSMatthew Knepley /* 24*/ MatZeroRows_SeqAIJ, 3352f4259b30SLisandro Dalcin NULL, 3353f4259b30SLisandro Dalcin NULL, 3354f4259b30SLisandro Dalcin NULL, 3355f4259b30SLisandro Dalcin NULL, 33564994cf47SJed Brown /* 29*/ MatSetUp_SeqAIJ, 3357f4259b30SLisandro Dalcin NULL, 3358f4259b30SLisandro Dalcin NULL, 3359f4259b30SLisandro Dalcin NULL, 3360f4259b30SLisandro Dalcin NULL, 3361d519adbfSMatthew Knepley /* 34*/ MatDuplicate_SeqAIJ, 3362f4259b30SLisandro Dalcin NULL, 3363f4259b30SLisandro Dalcin NULL, 3364cb5b572fSBarry Smith MatILUFactor_SeqAIJ, 3365f4259b30SLisandro Dalcin NULL, 3366d519adbfSMatthew Knepley /* 39*/ MatAXPY_SeqAIJ, 33677dae84e0SHong Zhang MatCreateSubMatrices_SeqAIJ, 3368cb5b572fSBarry Smith MatIncreaseOverlap_SeqAIJ, 3369cb5b572fSBarry Smith MatGetValues_SeqAIJ, 3370cb5b572fSBarry Smith MatCopy_SeqAIJ, 3371d519adbfSMatthew Knepley /* 44*/ MatGetRowMax_SeqAIJ, 3372cb5b572fSBarry Smith MatScale_SeqAIJ, 33737d68702bSBarry Smith MatShift_SeqAIJ, 337479299369SBarry Smith MatDiagonalSet_SeqAIJ, 33756e169961SBarry Smith MatZeroRowsColumns_SeqAIJ, 337673a71a0fSBarry Smith /* 49*/ MatSetRandom_SeqAIJ, 33773b2fbd54SBarry Smith MatGetRowIJ_SeqAIJ, 33783b2fbd54SBarry Smith MatRestoreRowIJ_SeqAIJ, 33793b2fbd54SBarry Smith MatGetColumnIJ_SeqAIJ, 3380a93ec695SBarry Smith MatRestoreColumnIJ_SeqAIJ, 338193dfae19SHong Zhang /* 54*/ MatFDColoringCreate_SeqXAIJ, 3382f4259b30SLisandro Dalcin NULL, 3383f4259b30SLisandro Dalcin NULL, 3384cda55fadSBarry Smith MatPermute_SeqAIJ, 3385f4259b30SLisandro Dalcin NULL, 3386f4259b30SLisandro Dalcin /* 59*/ NULL, 3387b9b97703SBarry Smith MatDestroy_SeqAIJ, 3388b9b97703SBarry Smith MatView_SeqAIJ, 3389f4259b30SLisandro Dalcin NULL, 3390f4259b30SLisandro Dalcin NULL, 3391f4259b30SLisandro Dalcin /* 64*/ NULL, 3392321b30b9SSatish Balay MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ, 3393f4259b30SLisandro Dalcin NULL, 3394f4259b30SLisandro Dalcin NULL, 3395f4259b30SLisandro Dalcin NULL, 3396d519adbfSMatthew Knepley /* 69*/ MatGetRowMaxAbs_SeqAIJ, 3397c87e5d42SMatthew Knepley MatGetRowMinAbs_SeqAIJ, 3398f4259b30SLisandro Dalcin NULL, 3399f4259b30SLisandro Dalcin NULL, 3400f4259b30SLisandro Dalcin NULL, 3401f4259b30SLisandro Dalcin /* 74*/ NULL, 34023acb8795SBarry Smith MatFDColoringApply_AIJ, 3403f4259b30SLisandro Dalcin NULL, 3404f4259b30SLisandro Dalcin NULL, 3405f4259b30SLisandro Dalcin NULL, 34066ce1633cSBarry Smith /* 79*/ MatFindZeroDiagonals_SeqAIJ, 3407f4259b30SLisandro Dalcin NULL, 3408f4259b30SLisandro Dalcin NULL, 3409f4259b30SLisandro Dalcin NULL, 3410bc011b1eSHong Zhang MatLoad_SeqAIJ, 3411d519adbfSMatthew Knepley /* 84*/ MatIsSymmetric_SeqAIJ, 34121cbb95d3SBarry Smith MatIsHermitian_SeqAIJ, 3413f4259b30SLisandro Dalcin NULL, 3414f4259b30SLisandro Dalcin NULL, 3415f4259b30SLisandro Dalcin NULL, 3416f4259b30SLisandro Dalcin /* 89*/ NULL, 3417f4259b30SLisandro Dalcin NULL, 341826be0446SHong Zhang MatMatMultNumeric_SeqAIJ_SeqAIJ, 3419f4259b30SLisandro Dalcin NULL, 3420f4259b30SLisandro Dalcin NULL, 34218fa4b5a6SHong Zhang /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy, 3422f4259b30SLisandro Dalcin NULL, 3423f4259b30SLisandro Dalcin NULL, 34246fc122caSHong Zhang MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ, 3425f4259b30SLisandro Dalcin NULL, 34264222ddf1SHong Zhang /* 99*/ MatProductSetFromOptions_SeqAIJ, 3427f4259b30SLisandro Dalcin NULL, 3428f4259b30SLisandro Dalcin NULL, 342987d4246cSBarry Smith MatConjugate_SeqAIJ, 3430f4259b30SLisandro Dalcin NULL, 3431d519adbfSMatthew Knepley /*104*/ MatSetValuesRow_SeqAIJ, 343299cafbc1SBarry Smith MatRealPart_SeqAIJ, 3433f5edf698SHong Zhang MatImaginaryPart_SeqAIJ, 3434f4259b30SLisandro Dalcin NULL, 3435f4259b30SLisandro Dalcin NULL, 3436cbd44569SHong Zhang /*109*/ MatMatSolve_SeqAIJ, 3437f4259b30SLisandro Dalcin NULL, 34382af78befSBarry Smith MatGetRowMin_SeqAIJ, 3439f4259b30SLisandro Dalcin NULL, 3440599ef60dSHong Zhang MatMissingDiagonal_SeqAIJ, 3441f4259b30SLisandro Dalcin /*114*/ NULL, 3442f4259b30SLisandro Dalcin NULL, 3443f4259b30SLisandro Dalcin NULL, 3444f4259b30SLisandro Dalcin NULL, 3445f4259b30SLisandro Dalcin NULL, 3446f4259b30SLisandro Dalcin /*119*/ NULL, 3447f4259b30SLisandro Dalcin NULL, 3448f4259b30SLisandro Dalcin NULL, 3449f4259b30SLisandro Dalcin NULL, 3450b3a44c85SBarry Smith MatGetMultiProcBlock_SeqAIJ, 34510716a85fSBarry Smith /*124*/ MatFindNonzeroRows_SeqAIJ, 3452a873a8cdSSam Reynolds MatGetColumnReductions_SeqAIJ, 345337868618SMatthew G Knepley MatInvertBlockDiagonal_SeqAIJ, 34540da83c2eSBarry Smith MatInvertVariableBlockDiagonal_SeqAIJ, 3455f4259b30SLisandro Dalcin NULL, 3456f4259b30SLisandro Dalcin /*129*/ NULL, 3457f4259b30SLisandro Dalcin NULL, 3458f4259b30SLisandro Dalcin NULL, 345975648e8dSHong Zhang MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ, 3460b9af6bddSHong Zhang MatTransposeColoringCreate_SeqAIJ, 3461b9af6bddSHong Zhang /*134*/ MatTransColoringApplySpToDen_SeqAIJ, 34622b8ad9a3SHong Zhang MatTransColoringApplyDenToSp_SeqAIJ, 3463f4259b30SLisandro Dalcin NULL, 3464f4259b30SLisandro Dalcin NULL, 34653964eb88SJed Brown MatRARtNumeric_SeqAIJ_SeqAIJ, 3466f4259b30SLisandro Dalcin /*139*/ NULL, 3467f4259b30SLisandro Dalcin NULL, 3468f4259b30SLisandro Dalcin NULL, 34693a062f41SBarry Smith MatFDColoringSetUp_SeqXAIJ, 34709c8f2541SHong Zhang MatFindOffBlockDiagonalEntries_SeqAIJ, 34714222ddf1SHong Zhang MatCreateMPIMatConcatenateSeqMat_SeqAIJ, 34724222ddf1SHong Zhang /*145*/ MatDestroySubMatrices_SeqAIJ, 3473f4259b30SLisandro Dalcin NULL, 347472833a62Smarkadams4 NULL, 347572833a62Smarkadams4 MatCreateGraph_Simple_AIJ, 34767fb60732SBarry Smith MatFilter_AIJ, 34779371c9d4SSatish Balay /*150*/ MatTransposeSymbolic_SeqAIJ}; 347817ab2063SBarry Smith 34799371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat, PetscInt *indices) { 3480bef8e0ddSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 348197f1f81fSBarry Smith PetscInt i, nz, n; 3482bef8e0ddSBarry Smith 3483bef8e0ddSBarry Smith PetscFunctionBegin; 3484bef8e0ddSBarry Smith nz = aij->maxnz; 3485d0f46423SBarry Smith n = mat->rmap->n; 3486ad540459SPierre Jolivet for (i = 0; i < nz; i++) aij->j[i] = indices[i]; 3487bef8e0ddSBarry Smith aij->nz = nz; 3488ad540459SPierre Jolivet for (i = 0; i < n; i++) aij->ilen[i] = aij->imax[i]; 3489bef8e0ddSBarry Smith PetscFunctionReturn(0); 3490bef8e0ddSBarry Smith } 3491bef8e0ddSBarry Smith 3492a3bb6f32SFande Kong /* 3493ddea5d60SJunchao Zhang * Given a sparse matrix with global column indices, compact it by using a local column space. 3494ddea5d60SJunchao Zhang * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable() 3495ddea5d60SJunchao Zhang */ 34969371c9d4SSatish Balay PetscErrorCode MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping) { 3497a3bb6f32SFande Kong Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3498a3bb6f32SFande Kong PetscTable gid1_lid1; 3499a3bb6f32SFande Kong PetscTablePosition tpos; 350025b670f0SStefano Zampini PetscInt gid, lid, i, ec, nz = aij->nz; 350125b670f0SStefano Zampini PetscInt *garray, *jj = aij->j; 3502a3bb6f32SFande Kong 3503a3bb6f32SFande Kong PetscFunctionBegin; 3504a3bb6f32SFande Kong PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3505a3bb6f32SFande Kong PetscValidPointer(mapping, 2); 3506a3bb6f32SFande Kong /* use a table */ 35079566063dSJacob Faibussowitsch PetscCall(PetscTableCreate(mat->rmap->n, mat->cmap->N + 1, &gid1_lid1)); 3508a3bb6f32SFande Kong ec = 0; 350925b670f0SStefano Zampini for (i = 0; i < nz; i++) { 351025b670f0SStefano Zampini PetscInt data, gid1 = jj[i] + 1; 35119566063dSJacob Faibussowitsch PetscCall(PetscTableFind(gid1_lid1, gid1, &data)); 3512a3bb6f32SFande Kong if (!data) { 3513a3bb6f32SFande Kong /* one based table */ 35149566063dSJacob Faibussowitsch PetscCall(PetscTableAdd(gid1_lid1, gid1, ++ec, INSERT_VALUES)); 3515a3bb6f32SFande Kong } 3516a3bb6f32SFande Kong } 3517a3bb6f32SFande Kong /* form array of columns we need */ 35189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ec, &garray)); 35199566063dSJacob Faibussowitsch PetscCall(PetscTableGetHeadPosition(gid1_lid1, &tpos)); 3520a3bb6f32SFande Kong while (tpos) { 35219566063dSJacob Faibussowitsch PetscCall(PetscTableGetNext(gid1_lid1, &tpos, &gid, &lid)); 3522a3bb6f32SFande Kong gid--; 3523a3bb6f32SFande Kong lid--; 3524a3bb6f32SFande Kong garray[lid] = gid; 3525a3bb6f32SFande Kong } 35269566063dSJacob Faibussowitsch PetscCall(PetscSortInt(ec, garray)); /* sort, and rebuild */ 35279566063dSJacob Faibussowitsch PetscCall(PetscTableRemoveAll(gid1_lid1)); 352848a46eb9SPierre Jolivet for (i = 0; i < ec; i++) PetscCall(PetscTableAdd(gid1_lid1, garray[i] + 1, i + 1, INSERT_VALUES)); 3529a3bb6f32SFande Kong /* compact out the extra columns in B */ 353025b670f0SStefano Zampini for (i = 0; i < nz; i++) { 353125b670f0SStefano Zampini PetscInt gid1 = jj[i] + 1; 35329566063dSJacob Faibussowitsch PetscCall(PetscTableFind(gid1_lid1, gid1, &lid)); 3533a3bb6f32SFande Kong lid--; 353425b670f0SStefano Zampini jj[i] = lid; 3535a3bb6f32SFande Kong } 35369566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&mat->cmap)); 35379566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy(&gid1_lid1)); 35389566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat), ec, ec, 1, &mat->cmap)); 35399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, mat->cmap->bs, mat->cmap->n, garray, PETSC_OWN_POINTER, mapping)); 35409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*mapping, ISLOCALTOGLOBALMAPPINGHASH)); 3541a3bb6f32SFande Kong PetscFunctionReturn(0); 3542a3bb6f32SFande Kong } 3543a3bb6f32SFande Kong 3544bef8e0ddSBarry Smith /*@ 3545bef8e0ddSBarry Smith MatSeqAIJSetColumnIndices - Set the column indices for all the rows 3546bef8e0ddSBarry Smith in the matrix. 3547bef8e0ddSBarry Smith 3548bef8e0ddSBarry Smith Input Parameters: 354911a5261eSBarry Smith + mat - the `MATSEQAIJ` matrix 3550bef8e0ddSBarry Smith - indices - the column indices 3551bef8e0ddSBarry Smith 355215091d37SBarry Smith Level: advanced 355315091d37SBarry Smith 3554bef8e0ddSBarry Smith Notes: 3555bef8e0ddSBarry Smith This can be called if you have precomputed the nonzero structure of the 3556bef8e0ddSBarry Smith matrix and want to provide it to the matrix object to improve the performance 355711a5261eSBarry Smith of the `MatSetValues()` operation. 3558bef8e0ddSBarry Smith 3559bef8e0ddSBarry Smith You MUST have set the correct numbers of nonzeros per row in the call to 356011a5261eSBarry Smith `MatCreateSeqAIJ()`, and the columns indices MUST be sorted. 3561bef8e0ddSBarry Smith 356211a5261eSBarry Smith MUST be called before any calls to `MatSetValues()` 3563bef8e0ddSBarry Smith 3564b9617806SBarry Smith The indices should start with zero, not one. 3565b9617806SBarry Smith 3566bef8e0ddSBarry Smith @*/ 35679371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat, PetscInt *indices) { 3568bef8e0ddSBarry Smith PetscFunctionBegin; 35690700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3570dadcf809SJacob Faibussowitsch PetscValidIntPointer(indices, 2); 3571cac4c232SBarry Smith PetscUseMethod(mat, "MatSeqAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices)); 3572bef8e0ddSBarry Smith PetscFunctionReturn(0); 3573bef8e0ddSBarry Smith } 3574bef8e0ddSBarry Smith 3575be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/ 3576be6bf707SBarry Smith 35779371c9d4SSatish Balay PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) { 3578be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3579d0f46423SBarry Smith size_t nz = aij->i[mat->rmap->n]; 3580be6bf707SBarry Smith 3581be6bf707SBarry Smith PetscFunctionBegin; 358228b400f6SJacob Faibussowitsch PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3583be6bf707SBarry Smith 3584be6bf707SBarry Smith /* allocate space for values if not already there */ 3585*4dfa11a4SJacob Faibussowitsch if (!aij->saved_values) { PetscCall(PetscMalloc1(nz + 1, &aij->saved_values)); } 3586be6bf707SBarry Smith 3587be6bf707SBarry Smith /* copy values over */ 35889566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz)); 3589be6bf707SBarry Smith PetscFunctionReturn(0); 3590be6bf707SBarry Smith } 3591be6bf707SBarry Smith 3592be6bf707SBarry Smith /*@ 3593be6bf707SBarry Smith MatStoreValues - Stashes a copy of the matrix values; this allows, for 3594be6bf707SBarry Smith example, reuse of the linear part of a Jacobian, while recomputing the 3595be6bf707SBarry Smith nonlinear portion. 3596be6bf707SBarry Smith 359711a5261eSBarry Smith Collect on mat 3598be6bf707SBarry Smith 3599be6bf707SBarry Smith Input Parameters: 360011a5261eSBarry Smith . mat - the matrix (currently only `MATAIJ` matrices support this option) 3601be6bf707SBarry Smith 360215091d37SBarry Smith Level: advanced 360315091d37SBarry Smith 360411a5261eSBarry Smith Common Usage, with `SNESSolve()`: 3605be6bf707SBarry Smith $ Create Jacobian matrix 3606be6bf707SBarry Smith $ Set linear terms into matrix 3607be6bf707SBarry Smith $ Apply boundary conditions to matrix, at this time matrix must have 3608be6bf707SBarry Smith $ final nonzero structure (i.e. setting the nonlinear terms and applying 3609be6bf707SBarry Smith $ boundary conditions again will not change the nonzero structure 3610512a5fc5SBarry Smith $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3611be6bf707SBarry Smith $ ierr = MatStoreValues(mat); 3612be6bf707SBarry Smith $ Call SNESSetJacobian() with matrix 3613be6bf707SBarry Smith $ In your Jacobian routine 3614be6bf707SBarry Smith $ ierr = MatRetrieveValues(mat); 3615be6bf707SBarry Smith $ Set nonlinear terms in matrix 3616be6bf707SBarry Smith 3617be6bf707SBarry Smith Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself: 3618be6bf707SBarry Smith $ // build linear portion of Jacobian 3619512a5fc5SBarry Smith $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3620be6bf707SBarry Smith $ ierr = MatStoreValues(mat); 3621be6bf707SBarry Smith $ loop over nonlinear iterations 3622be6bf707SBarry Smith $ ierr = MatRetrieveValues(mat); 3623be6bf707SBarry Smith $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian 3624be6bf707SBarry Smith $ // call MatAssemblyBegin/End() on matrix 3625be6bf707SBarry Smith $ Solve linear system with Jacobian 3626be6bf707SBarry Smith $ endloop 3627be6bf707SBarry Smith 3628be6bf707SBarry Smith Notes: 3629be6bf707SBarry Smith Matrix must already be assemblied before calling this routine 363011a5261eSBarry Smith Must set the matrix option `MatSetOption`(mat,`MAT_NEW_NONZERO_LOCATIONS`,`PETSC_FALSE`); before 3631be6bf707SBarry Smith calling this routine. 3632be6bf707SBarry Smith 36330c468ba9SBarry Smith When this is called multiple times it overwrites the previous set of stored values 36340c468ba9SBarry Smith and does not allocated additional space. 36350c468ba9SBarry Smith 3636db781477SPatrick Sanan .seealso: `MatRetrieveValues()` 3637be6bf707SBarry Smith @*/ 36389371c9d4SSatish Balay PetscErrorCode MatStoreValues(Mat mat) { 3639be6bf707SBarry Smith PetscFunctionBegin; 36400700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 364128b400f6SJacob Faibussowitsch PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 364228b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3643cac4c232SBarry Smith PetscUseMethod(mat, "MatStoreValues_C", (Mat), (mat)); 3644be6bf707SBarry Smith PetscFunctionReturn(0); 3645be6bf707SBarry Smith } 3646be6bf707SBarry Smith 36479371c9d4SSatish Balay PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat) { 3648be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3649d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->n]; 3650be6bf707SBarry Smith 3651be6bf707SBarry Smith PetscFunctionBegin; 365228b400f6SJacob Faibussowitsch PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 365328b400f6SJacob Faibussowitsch PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first"); 3654be6bf707SBarry Smith /* copy values over */ 36559566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz)); 3656be6bf707SBarry Smith PetscFunctionReturn(0); 3657be6bf707SBarry Smith } 3658be6bf707SBarry Smith 3659be6bf707SBarry Smith /*@ 3660be6bf707SBarry Smith MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 3661be6bf707SBarry Smith example, reuse of the linear part of a Jacobian, while recomputing the 3662be6bf707SBarry Smith nonlinear portion. 3663be6bf707SBarry Smith 366411a5261eSBarry Smith Collect on mat 3665be6bf707SBarry Smith 3666be6bf707SBarry Smith Input Parameters: 366711a5261eSBarry Smith . mat - the matrix (currently only `MATAIJ` matrices support this option) 3668be6bf707SBarry Smith 366915091d37SBarry Smith Level: advanced 367015091d37SBarry Smith 3671db781477SPatrick Sanan .seealso: `MatStoreValues()` 3672be6bf707SBarry Smith @*/ 36739371c9d4SSatish Balay PetscErrorCode MatRetrieveValues(Mat mat) { 3674be6bf707SBarry Smith PetscFunctionBegin; 36750700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 367628b400f6SJacob Faibussowitsch PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 367728b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3678cac4c232SBarry Smith PetscUseMethod(mat, "MatRetrieveValues_C", (Mat), (mat)); 3679be6bf707SBarry Smith PetscFunctionReturn(0); 3680be6bf707SBarry Smith } 3681be6bf707SBarry Smith 3682be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/ 368317ab2063SBarry Smith /*@C 368411a5261eSBarry Smith MatCreateSeqAIJ - Creates a sparse matrix in `MATSEQAIJ` (compressed row) format 36850d15e28bSLois Curfman McInnes (the default parallel PETSc format). For good matrix assembly performance 36866e62573dSLois Curfman McInnes the user should preallocate the matrix storage by setting the parameter nz 368751c19458SBarry Smith (or the array nnz). By setting these parameters accurately, performance 36882bd5e0b2SLois Curfman McInnes during matrix assembly can be increased by more than a factor of 50. 368917ab2063SBarry Smith 3690d083f849SBarry Smith Collective 3691db81eaa0SLois Curfman McInnes 369217ab2063SBarry Smith Input Parameters: 369311a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF` 369417ab2063SBarry Smith . m - number of rows 369517ab2063SBarry Smith . n - number of columns 369617ab2063SBarry Smith . nz - number of nonzeros per row (same for all rows) 369751c19458SBarry Smith - nnz - array containing the number of nonzeros in the various rows 36980298fd71SBarry Smith (possibly different for each row) or NULL 369917ab2063SBarry Smith 370017ab2063SBarry Smith Output Parameter: 3701416022c9SBarry Smith . A - the matrix 370217ab2063SBarry Smith 370311a5261eSBarry Smith It is recommended that one use the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`, 3704f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly. 370511a5261eSBarry Smith [MatXXXXSetPreallocation() is, for example, `MatSeqAIJSetPreallocation()`] 3706175b88e8SBarry Smith 3707b259b22eSLois Curfman McInnes Notes: 370849a6f317SBarry Smith If nnz is given then nz is ignored 370949a6f317SBarry Smith 371011a5261eSBarry Smith The AIJ format, also called 371111a5261eSBarry Smith compressed row storage, is fully compatible with standard Fortran 77 37120002213bSLois Curfman McInnes storage. That is, the stored row and column indices can begin at 371344cd7ae7SLois Curfman McInnes either one (as in Fortran) or zero. See the users' manual for details. 371417ab2063SBarry Smith 371517ab2063SBarry Smith Specify the preallocated storage with either nz or nnz (not both). 371611a5261eSBarry Smith Set nz = `PETSC_DEFAULT` and nnz = NULL for PETSc to control dynamic memory 37173d323bbdSBarry Smith allocation. For large problems you MUST preallocate memory or you 37186da5968aSLois Curfman McInnes will get TERRIBLE performance, see the users' manual chapter on matrices. 371917ab2063SBarry Smith 3720682d7d0cSBarry Smith By default, this format uses inodes (identical nodes) when possible, to 37214fca80b9SLois Curfman McInnes improve numerical efficiency of matrix-vector products and solves. We 3722682d7d0cSBarry Smith search for consecutive rows with the same nonzero structure, thereby 37236c7ebb05SLois Curfman McInnes reusing matrix information to achieve increased efficiency. 37246c7ebb05SLois Curfman McInnes 37256c7ebb05SLois Curfman McInnes Options Database Keys: 3726698d4c6aSKris Buschelman + -mat_no_inode - Do not use inodes 37279db58ca8SBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 372817ab2063SBarry Smith 3729027ccd11SLois Curfman McInnes Level: intermediate 3730027ccd11SLois Curfman McInnes 373160161072SBarry Smith .seealso: [Sparse Matrix Creation](sec_matsparse), `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()` 373217ab2063SBarry Smith @*/ 37339371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A) { 37343a40ed3dSBarry Smith PetscFunctionBegin; 37359566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 37369566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, m, n)); 37379566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATSEQAIJ)); 37389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*A, nz, nnz)); 3739273d9f13SBarry Smith PetscFunctionReturn(0); 3740273d9f13SBarry Smith } 3741273d9f13SBarry Smith 3742273d9f13SBarry Smith /*@C 3743273d9f13SBarry Smith MatSeqAIJSetPreallocation - For good matrix assembly performance 3744273d9f13SBarry Smith the user should preallocate the matrix storage by setting the parameter nz 3745273d9f13SBarry Smith (or the array nnz). By setting these parameters accurately, performance 3746273d9f13SBarry Smith during matrix assembly can be increased by more than a factor of 50. 3747273d9f13SBarry Smith 3748d083f849SBarry Smith Collective 3749273d9f13SBarry Smith 3750273d9f13SBarry Smith Input Parameters: 37511c4f3114SJed Brown + B - The matrix 3752273d9f13SBarry Smith . nz - number of nonzeros per row (same for all rows) 3753273d9f13SBarry Smith - nnz - array containing the number of nonzeros in the various rows 37540298fd71SBarry Smith (possibly different for each row) or NULL 3755273d9f13SBarry Smith 3756273d9f13SBarry Smith Notes: 375749a6f317SBarry Smith If nnz is given then nz is ignored 375849a6f317SBarry Smith 375911a5261eSBarry Smith The `MATSEQAIJ` format also called 376011a5261eSBarry Smith compressed row storage, is fully compatible with standard Fortran 77 3761273d9f13SBarry Smith storage. That is, the stored row and column indices can begin at 3762273d9f13SBarry Smith either one (as in Fortran) or zero. See the users' manual for details. 3763273d9f13SBarry Smith 3764273d9f13SBarry Smith Specify the preallocated storage with either nz or nnz (not both). 376511a5261eSBarry Smith Set nz = `PETSC_DEFAULT` and nnz = NULL for PETSc to control dynamic memory 3766273d9f13SBarry Smith allocation. For large problems you MUST preallocate memory or you 3767273d9f13SBarry Smith will get TERRIBLE performance, see the users' manual chapter on matrices. 3768273d9f13SBarry Smith 376911a5261eSBarry Smith You can call `MatGetInfo()` to get information on how effective the preallocation was; 3770aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 3771aa95bbe8SBarry Smith You can also run with the option -info and look for messages with the string 3772aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 3773aa95bbe8SBarry Smith 377411a5261eSBarry Smith Developer Notes: 377511a5261eSBarry Smith Use nz of `MAT_SKIP_ALLOCATION` to not allocate any space for the matrix 3776a96a251dSBarry Smith entries or columns indices 3777a96a251dSBarry Smith 3778273d9f13SBarry Smith By default, this format uses inodes (identical nodes) when possible, to 3779273d9f13SBarry Smith improve numerical efficiency of matrix-vector products and solves. We 3780273d9f13SBarry Smith search for consecutive rows with the same nonzero structure, thereby 3781273d9f13SBarry Smith reusing matrix information to achieve increased efficiency. 3782273d9f13SBarry Smith 3783273d9f13SBarry Smith Options Database Keys: 3784698d4c6aSKris Buschelman + -mat_no_inode - Do not use inodes 378547b2e64bSBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3786273d9f13SBarry Smith 3787273d9f13SBarry Smith Level: intermediate 3788273d9f13SBarry Smith 3789db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()`, `MatGetInfo()`, 3790db781477SPatrick Sanan `MatSeqAIJSetTotalPreallocation()` 3791273d9f13SBarry Smith @*/ 37929371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocation(Mat B, PetscInt nz, const PetscInt nnz[]) { 3793a23d5eceSKris Buschelman PetscFunctionBegin; 37946ba663aaSJed Brown PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 37956ba663aaSJed Brown PetscValidType(B, 1); 3796cac4c232SBarry Smith PetscTryMethod(B, "MatSeqAIJSetPreallocation_C", (Mat, PetscInt, const PetscInt[]), (B, nz, nnz)); 3797a23d5eceSKris Buschelman PetscFunctionReturn(0); 3798a23d5eceSKris Buschelman } 3799a23d5eceSKris Buschelman 38009371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B, PetscInt nz, const PetscInt *nnz) { 3801273d9f13SBarry Smith Mat_SeqAIJ *b; 38022576faa2SJed Brown PetscBool skipallocation = PETSC_FALSE, realalloc = PETSC_FALSE; 380397f1f81fSBarry Smith PetscInt i; 3804273d9f13SBarry Smith 3805273d9f13SBarry Smith PetscFunctionBegin; 38062576faa2SJed Brown if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 3807a96a251dSBarry Smith if (nz == MAT_SKIP_ALLOCATION) { 3808c461c341SBarry Smith skipallocation = PETSC_TRUE; 3809c461c341SBarry Smith nz = 0; 3810c461c341SBarry Smith } 38119566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 38129566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 3813899cda47SBarry Smith 3814435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 381508401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz); 3816cf9c20a2SJed Brown if (PetscUnlikelyDebug(nnz)) { 3817d0f46423SBarry Smith for (i = 0; i < B->rmap->n; i++) { 381808401ef6SPierre 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]); 381908401ef6SPierre 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); 3820b73539f3SBarry Smith } 3821b73539f3SBarry Smith } 3822b73539f3SBarry Smith 3823273d9f13SBarry Smith B->preallocated = PETSC_TRUE; 38242205254eSKarl Rupp 3825273d9f13SBarry Smith b = (Mat_SeqAIJ *)B->data; 3826273d9f13SBarry Smith 3827ab93d7beSBarry Smith if (!skipallocation) { 3828*4dfa11a4SJacob Faibussowitsch if (!b->imax) { PetscCall(PetscMalloc1(B->rmap->n, &b->imax)); } 3829071fcb05SBarry Smith if (!b->ilen) { 3830071fcb05SBarry Smith /* b->ilen will count nonzeros in each row so far. */ 38319566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(B->rmap->n, &b->ilen)); 3832071fcb05SBarry Smith } else { 38339566063dSJacob Faibussowitsch PetscCall(PetscMemzero(b->ilen, B->rmap->n * sizeof(PetscInt))); 38342ee49352SLisandro Dalcin } 3835*4dfa11a4SJacob Faibussowitsch if (!b->ipre) { PetscCall(PetscMalloc1(B->rmap->n, &b->ipre)); } 3836273d9f13SBarry Smith if (!nnz) { 3837435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 3838c62bd62aSJed Brown else if (nz < 0) nz = 1; 38395d2a9ed1SStefano Zampini nz = PetscMin(nz, B->cmap->n); 3840d0f46423SBarry Smith for (i = 0; i < B->rmap->n; i++) b->imax[i] = nz; 3841d0f46423SBarry Smith nz = nz * B->rmap->n; 3842273d9f13SBarry Smith } else { 3843c73702f5SBarry Smith PetscInt64 nz64 = 0; 38449371c9d4SSatish Balay for (i = 0; i < B->rmap->n; i++) { 38459371c9d4SSatish Balay b->imax[i] = nnz[i]; 38469371c9d4SSatish Balay nz64 += nnz[i]; 38479371c9d4SSatish Balay } 38489566063dSJacob Faibussowitsch PetscCall(PetscIntCast(nz64, &nz)); 3849273d9f13SBarry Smith } 3850ab93d7beSBarry Smith 3851273d9f13SBarry Smith /* allocate the matrix space */ 385253dd7562SDmitry Karpeev /* FIXME: should B's old memory be unlogged? */ 38539566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i)); 3854396832f4SHong Zhang if (B->structure_only) { 38559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &b->j)); 38569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n + 1, &b->i)); 3857396832f4SHong Zhang } else { 38589566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(nz, &b->a, nz, &b->j, B->rmap->n + 1, &b->i)); 3859396832f4SHong Zhang } 3860bfeeae90SHong Zhang b->i[0] = 0; 3861ad540459SPierre Jolivet for (i = 1; i < B->rmap->n + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1]; 3862396832f4SHong Zhang if (B->structure_only) { 3863396832f4SHong Zhang b->singlemalloc = PETSC_FALSE; 3864396832f4SHong Zhang b->free_a = PETSC_FALSE; 3865396832f4SHong Zhang } else { 3866273d9f13SBarry Smith b->singlemalloc = PETSC_TRUE; 3867e6b907acSBarry Smith b->free_a = PETSC_TRUE; 3868396832f4SHong Zhang } 3869e6b907acSBarry Smith b->free_ij = PETSC_TRUE; 3870c461c341SBarry Smith } else { 3871e6b907acSBarry Smith b->free_a = PETSC_FALSE; 3872e6b907acSBarry Smith b->free_ij = PETSC_FALSE; 3873c461c341SBarry Smith } 3874273d9f13SBarry Smith 3875846b4da1SFande Kong if (b->ipre && nnz != b->ipre && b->imax) { 3876846b4da1SFande Kong /* reserve user-requested sparsity */ 38779566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->ipre, b->imax, B->rmap->n)); 3878846b4da1SFande Kong } 3879846b4da1SFande Kong 3880273d9f13SBarry Smith b->nz = 0; 3881273d9f13SBarry Smith b->maxnz = nz; 3882273d9f13SBarry Smith B->info.nz_unneeded = (double)b->maxnz; 38831baa6e33SBarry Smith if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 3884cb7b82ddSBarry Smith B->was_assembled = PETSC_FALSE; 3885cb7b82ddSBarry Smith B->assembled = PETSC_FALSE; 38865519a089SJose E. Roman /* We simply deem preallocation has changed nonzero state. Updating the state 38875519a089SJose E. Roman will give clients (like AIJKokkos) a chance to know something has happened. 38885519a089SJose E. Roman */ 38895519a089SJose E. Roman B->nonzerostate++; 3890273d9f13SBarry Smith PetscFunctionReturn(0); 3891273d9f13SBarry Smith } 3892273d9f13SBarry Smith 38939371c9d4SSatish Balay PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A) { 3894846b4da1SFande Kong Mat_SeqAIJ *a; 3895a5bbaf83SFande Kong PetscInt i; 3896846b4da1SFande Kong 3897846b4da1SFande Kong PetscFunctionBegin; 3898846b4da1SFande Kong PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 389914d0e64fSAlex Lindsay 390014d0e64fSAlex Lindsay /* Check local size. If zero, then return */ 390114d0e64fSAlex Lindsay if (!A->rmap->n) PetscFunctionReturn(0); 390214d0e64fSAlex Lindsay 3903846b4da1SFande Kong a = (Mat_SeqAIJ *)A->data; 39042c814fdeSFande Kong /* if no saved info, we error out */ 390528b400f6SJacob Faibussowitsch PetscCheck(a->ipre, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "No saved preallocation info "); 39062c814fdeSFande Kong 3907aed4548fSBarry 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 "); 39082c814fdeSFande Kong 39099566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->imax, a->ipre, A->rmap->n)); 39109566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(a->ilen, A->rmap->n)); 3911846b4da1SFande Kong a->i[0] = 0; 3912ad540459SPierre Jolivet for (i = 1; i < A->rmap->n + 1; i++) a->i[i] = a->i[i - 1] + a->imax[i - 1]; 3913846b4da1SFande Kong A->preallocated = PETSC_TRUE; 3914846b4da1SFande Kong a->nz = 0; 3915846b4da1SFande Kong a->maxnz = a->i[A->rmap->n]; 3916846b4da1SFande Kong A->info.nz_unneeded = (double)a->maxnz; 3917846b4da1SFande Kong A->was_assembled = PETSC_FALSE; 3918846b4da1SFande Kong A->assembled = PETSC_FALSE; 3919846b4da1SFande Kong PetscFunctionReturn(0); 3920846b4da1SFande Kong } 3921846b4da1SFande Kong 392258d36128SBarry Smith /*@ 392311a5261eSBarry Smith MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in `MATSEQAIJ` format. 3924a1661176SMatthew Knepley 3925a1661176SMatthew Knepley Input Parameters: 3926a1661176SMatthew Knepley + B - the matrix 3927a1661176SMatthew Knepley . i - the indices into j for the start of each row (starts with zero) 3928a1661176SMatthew Knepley . j - the column indices for each row (starts with zero) these must be sorted for each row 3929a1661176SMatthew Knepley - v - optional values in the matrix 3930a1661176SMatthew Knepley 3931a1661176SMatthew Knepley Level: developer 3932a1661176SMatthew Knepley 39336a9b8d82SBarry Smith Notes: 393411a5261eSBarry Smith The i,j,v values are COPIED with this routine; to avoid the copy use `MatCreateSeqAIJWithArrays()` 393558d36128SBarry Smith 39366a9b8d82SBarry Smith This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero 39376a9b8d82SBarry Smith structure will be the union of all the previous nonzero structures. 39386a9b8d82SBarry Smith 39396a9b8d82SBarry Smith Developer Notes: 39406a9b8d82SBarry 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 394111a5261eSBarry Smith then just copies the v values directly with `PetscMemcpy()`. 39426a9b8d82SBarry Smith 394311a5261eSBarry Smith This routine could also take a `PetscCopyMode` argument to allow sharing the values instead of always copying them. 39446a9b8d82SBarry Smith 3945db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatSeqAIJSetPreallocation()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MatResetPreallocation()` 3946a1661176SMatthew Knepley @*/ 39479371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B, const PetscInt i[], const PetscInt j[], const PetscScalar v[]) { 3948a1661176SMatthew Knepley PetscFunctionBegin; 39490700a824SBarry Smith PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 39506ba663aaSJed Brown PetscValidType(B, 1); 3951cac4c232SBarry Smith PetscTryMethod(B, "MatSeqAIJSetPreallocationCSR_C", (Mat, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, i, j, v)); 3952a1661176SMatthew Knepley PetscFunctionReturn(0); 3953a1661176SMatthew Knepley } 3954a1661176SMatthew Knepley 39559371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B, const PetscInt Ii[], const PetscInt J[], const PetscScalar v[]) { 3956a1661176SMatthew Knepley PetscInt i; 3957a1661176SMatthew Knepley PetscInt m, n; 3958a1661176SMatthew Knepley PetscInt nz; 39596a9b8d82SBarry Smith PetscInt *nnz; 3960a1661176SMatthew Knepley 3961a1661176SMatthew Knepley PetscFunctionBegin; 3962aed4548fSBarry Smith PetscCheck(Ii[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]); 3963779a8d59SSatish Balay 39649566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 39659566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 3966779a8d59SSatish Balay 39679566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &m, &n)); 39689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nnz)); 3969a1661176SMatthew Knepley for (i = 0; i < m; i++) { 3970b7940d39SSatish Balay nz = Ii[i + 1] - Ii[i]; 397108401ef6SPierre 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); 3972a1661176SMatthew Knepley nnz[i] = nz; 3973a1661176SMatthew Knepley } 39749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz)); 39759566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 3976a1661176SMatthew Knepley 397748a46eb9SPierre 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)); 3978a1661176SMatthew Knepley 39799566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 39809566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 3981a1661176SMatthew Knepley 39829566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 3983a1661176SMatthew Knepley PetscFunctionReturn(0); 3984a1661176SMatthew Knepley } 3985a1661176SMatthew Knepley 3986ad7e164aSPierre Jolivet /*@ 3987ad7e164aSPierre Jolivet MatSeqAIJKron - Computes C, the Kronecker product of A and B. 3988ad7e164aSPierre Jolivet 3989ad7e164aSPierre Jolivet Input Parameters: 3990ad7e164aSPierre Jolivet + A - left-hand side matrix 3991ad7e164aSPierre Jolivet . B - right-hand side matrix 399211a5261eSBarry Smith - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 3993ad7e164aSPierre Jolivet 3994ad7e164aSPierre Jolivet Output Parameter: 3995ad7e164aSPierre Jolivet . C - Kronecker product of A and B 3996ad7e164aSPierre Jolivet 3997ad7e164aSPierre Jolivet Level: intermediate 3998ad7e164aSPierre Jolivet 399911a5261eSBarry Smith Note: 400011a5261eSBarry 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()`. 4001ad7e164aSPierre Jolivet 4002db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATKAIJ`, `MatReuse` 4003ad7e164aSPierre Jolivet @*/ 40049371c9d4SSatish Balay PetscErrorCode MatSeqAIJKron(Mat A, Mat B, MatReuse reuse, Mat *C) { 4005ad7e164aSPierre Jolivet PetscFunctionBegin; 4006ad7e164aSPierre Jolivet PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4007ad7e164aSPierre Jolivet PetscValidType(A, 1); 4008ad7e164aSPierre Jolivet PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4009ad7e164aSPierre Jolivet PetscValidType(B, 2); 4010ad7e164aSPierre Jolivet PetscValidPointer(C, 4); 4011ad7e164aSPierre Jolivet if (reuse == MAT_REUSE_MATRIX) { 4012ad7e164aSPierre Jolivet PetscValidHeaderSpecific(*C, MAT_CLASSID, 4); 4013ad7e164aSPierre Jolivet PetscValidType(*C, 4); 4014ad7e164aSPierre Jolivet } 4015cac4c232SBarry Smith PetscTryMethod(A, "MatSeqAIJKron_C", (Mat, Mat, MatReuse, Mat *), (A, B, reuse, C)); 4016ad7e164aSPierre Jolivet PetscFunctionReturn(0); 4017ad7e164aSPierre Jolivet } 4018ad7e164aSPierre Jolivet 40199371c9d4SSatish Balay PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A, Mat B, MatReuse reuse, Mat *C) { 4020ad7e164aSPierre Jolivet Mat newmat; 4021ad7e164aSPierre Jolivet Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 4022ad7e164aSPierre Jolivet Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 4023ad7e164aSPierre Jolivet PetscScalar *v; 4024fff043a9SJunchao Zhang const PetscScalar *aa, *ba; 4025ad7e164aSPierre 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; 4026ad7e164aSPierre Jolivet PetscBool flg; 4027ad7e164aSPierre Jolivet 4028ad7e164aSPierre Jolivet PetscFunctionBegin; 402928b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 403028b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 403128b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 403228b400f6SJacob Faibussowitsch PetscCheck(B->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 40339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATSEQAIJ, &flg)); 403428b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatType %s", ((PetscObject)B)->type_name); 4035aed4548fSBarry Smith PetscCheck(reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatReuse %d", (int)reuse); 4036ad7e164aSPierre Jolivet if (reuse == MAT_INITIAL_MATRIX) { 40379566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(am * bm + 1, &i, a->i[am] * b->i[bm], &j)); 40389566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &newmat)); 40399566063dSJacob Faibussowitsch PetscCall(MatSetSizes(newmat, am * bm, an * bn, am * bm, an * bn)); 40409566063dSJacob Faibussowitsch PetscCall(MatSetType(newmat, MATAIJ)); 4041ad7e164aSPierre Jolivet i[0] = 0; 4042ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4043ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4044ad7e164aSPierre Jolivet i[m * bm + p + 1] = i[m * bm + p] + (a->i[m + 1] - a->i[m]) * (b->i[p + 1] - b->i[p]); 4045ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m + 1]; ++n) { 4046ad540459SPierre Jolivet for (q = b->i[p]; q < b->i[p + 1]; ++q) j[nnz++] = a->j[n] * bn + b->j[q]; 4047ad7e164aSPierre Jolivet } 4048ad7e164aSPierre Jolivet } 4049ad7e164aSPierre Jolivet } 40509566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(newmat, i, j, NULL)); 4051ad7e164aSPierre Jolivet *C = newmat; 40529566063dSJacob Faibussowitsch PetscCall(PetscFree2(i, j)); 4053ad7e164aSPierre Jolivet nnz = 0; 4054ad7e164aSPierre Jolivet } 40559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(*C, &v)); 40569566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 40579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &ba)); 4058ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4059ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4060ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m + 1]; ++n) { 4061ad540459SPierre Jolivet for (q = b->i[p]; q < b->i[p + 1]; ++q) v[nnz++] = aa[n] * ba[q]; 4062ad7e164aSPierre Jolivet } 4063ad7e164aSPierre Jolivet } 4064ad7e164aSPierre Jolivet } 40659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(*C, &v)); 40669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 40679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &ba)); 4068ad7e164aSPierre Jolivet PetscFunctionReturn(0); 4069ad7e164aSPierre Jolivet } 4070ad7e164aSPierre Jolivet 4071c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h> 4072af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h> 4073170fe5c8SBarry Smith 4074170fe5c8SBarry Smith /* 4075170fe5c8SBarry Smith Computes (B'*A')' since computing B*A directly is untenable 4076170fe5c8SBarry Smith 4077170fe5c8SBarry Smith n p p 40782da392ccSBarry Smith [ ] [ ] [ ] 40792da392ccSBarry Smith m [ A ] * n [ B ] = m [ C ] 40802da392ccSBarry Smith [ ] [ ] [ ] 4081170fe5c8SBarry Smith 4082170fe5c8SBarry Smith */ 40839371c9d4SSatish Balay PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A, Mat B, Mat C) { 4084170fe5c8SBarry Smith Mat_SeqDense *sub_a = (Mat_SeqDense *)A->data; 4085170fe5c8SBarry Smith Mat_SeqAIJ *sub_b = (Mat_SeqAIJ *)B->data; 4086170fe5c8SBarry Smith Mat_SeqDense *sub_c = (Mat_SeqDense *)C->data; 408786214ceeSStefano Zampini PetscInt i, j, n, m, q, p; 4088170fe5c8SBarry Smith const PetscInt *ii, *idx; 4089170fe5c8SBarry Smith const PetscScalar *b, *a, *a_q; 4090170fe5c8SBarry Smith PetscScalar *c, *c_q; 409186214ceeSStefano Zampini PetscInt clda = sub_c->lda; 409286214ceeSStefano Zampini PetscInt alda = sub_a->lda; 4093170fe5c8SBarry Smith 4094170fe5c8SBarry Smith PetscFunctionBegin; 4095d0f46423SBarry Smith m = A->rmap->n; 4096d0f46423SBarry Smith n = A->cmap->n; 4097d0f46423SBarry Smith p = B->cmap->n; 4098170fe5c8SBarry Smith a = sub_a->v; 4099170fe5c8SBarry Smith b = sub_b->a; 4100170fe5c8SBarry Smith c = sub_c->v; 410186214ceeSStefano Zampini if (clda == m) { 41029566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c, m * p)); 410386214ceeSStefano Zampini } else { 410486214ceeSStefano Zampini for (j = 0; j < p; j++) 41059371c9d4SSatish Balay for (i = 0; i < m; i++) c[j * clda + i] = 0.0; 410686214ceeSStefano Zampini } 4107170fe5c8SBarry Smith ii = sub_b->i; 4108170fe5c8SBarry Smith idx = sub_b->j; 4109170fe5c8SBarry Smith for (i = 0; i < n; i++) { 4110170fe5c8SBarry Smith q = ii[i + 1] - ii[i]; 4111170fe5c8SBarry Smith while (q-- > 0) { 411286214ceeSStefano Zampini c_q = c + clda * (*idx); 411386214ceeSStefano Zampini a_q = a + alda * i; 4114854c7f52SBarry Smith PetscKernelAXPY(c_q, *b, a_q, m); 4115170fe5c8SBarry Smith idx++; 4116170fe5c8SBarry Smith b++; 4117170fe5c8SBarry Smith } 4118170fe5c8SBarry Smith } 4119170fe5c8SBarry Smith PetscFunctionReturn(0); 4120170fe5c8SBarry Smith } 4121170fe5c8SBarry Smith 41229371c9d4SSatish Balay PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A, Mat B, PetscReal fill, Mat C) { 4123d0f46423SBarry Smith PetscInt m = A->rmap->n, n = B->cmap->n; 412486214ceeSStefano Zampini PetscBool cisdense; 4125170fe5c8SBarry Smith 4126170fe5c8SBarry Smith PetscFunctionBegin; 412708401ef6SPierre 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); 41289566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, m, n)); 41299566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, B)); 41309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, "")); 413148a46eb9SPierre Jolivet if (!cisdense) PetscCall(MatSetType(C, MATDENSE)); 41329566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 4133d73949e8SHong Zhang 41344222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ; 4135170fe5c8SBarry Smith PetscFunctionReturn(0); 4136170fe5c8SBarry Smith } 4137170fe5c8SBarry Smith 4138170fe5c8SBarry Smith /* ----------------------------------------------------------------*/ 41390bad9183SKris Buschelman /*MC 4140fafad747SKris Buschelman MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 41410bad9183SKris Buschelman based on compressed sparse row format. 41420bad9183SKris Buschelman 41430bad9183SKris Buschelman Options Database Keys: 41440bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 41450bad9183SKris Buschelman 41460bad9183SKris Buschelman Level: beginner 41470bad9183SKris Buschelman 41480cd7f59aSBarry Smith Notes: 414911a5261eSBarry Smith `MatSetValues()` may be called for this matrix type with a NULL argument for the numerical values, 41500cd7f59aSBarry Smith in this case the values associated with the rows and columns one passes in are set to zero 41510cd7f59aSBarry Smith in the matrix 41520cd7f59aSBarry Smith 415311a5261eSBarry Smith `MatSetOptions`(,`MAT_STRUCTURE_ONLY`,`PETSC_TRUE`) may be called for this matrix type. In this no 415411a5261eSBarry Smith space is allocated for the nonzero entries and any entries passed with `MatSetValues()` are ignored 41550cd7f59aSBarry Smith 415611a5261eSBarry Smith Developer Note: 41570cd7f59aSBarry Smith It would be nice if all matrix formats supported passing NULL in for the numerical values 41580cd7f59aSBarry Smith 4159db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MatSetFromOptions()`, `MatSetType()`, `MatCreate()`, `MatType`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 41600bad9183SKris Buschelman M*/ 41610bad9183SKris Buschelman 4162ccd284c7SBarry Smith /*MC 4163ccd284c7SBarry Smith MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 4164ccd284c7SBarry Smith 416511a5261eSBarry Smith This matrix type is identical to `MATSEQAIJ` when constructed with a single process communicator, 416611a5261eSBarry Smith and `MATMPIAIJ` otherwise. As a result, for single process communicators, 416711a5261eSBarry Smith `MatSeqAIJSetPreallocation()` is supported, and similarly `MatMPIAIJSetPreallocation()` is supported 4168ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4169ccd284c7SBarry Smith the above preallocation routines for simplicity. 4170ccd284c7SBarry Smith 4171ccd284c7SBarry Smith Options Database Keys: 417211a5261eSBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to `MatSetFromOptions()` 4173ccd284c7SBarry Smith 417411a5261eSBarry Smith Note: 417511a5261eSBarry Smith Subclasses include `MATAIJCUSPARSE`, `MATAIJPERM`, `MATAIJSELL`, `MATAIJMKL`, `MATAIJCRL`, and also automatically switches over to use inodes when 4176ccd284c7SBarry Smith enough exist. 4177ccd284c7SBarry Smith 4178ccd284c7SBarry Smith Level: beginner 4179ccd284c7SBarry Smith 4180db781477SPatrick Sanan .seealso: `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATMPIAIJ`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 4181ccd284c7SBarry Smith M*/ 4182ccd284c7SBarry Smith 4183ccd284c7SBarry Smith /*MC 4184ccd284c7SBarry Smith MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 4185ccd284c7SBarry Smith 418611a5261eSBarry Smith This matrix type is identical to `MATSEQAIJCRL` when constructed with a single process communicator, 418711a5261eSBarry Smith and `MATMPIAIJCRL` otherwise. As a result, for single process communicators, 418811a5261eSBarry Smith `MatSeqAIJSetPreallocation()` is supported, and similarly `MatMPIAIJSetPreallocation()` is supported 4189ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4190ccd284c7SBarry Smith the above preallocation routines for simplicity. 4191ccd284c7SBarry Smith 4192ccd284c7SBarry Smith Options Database Keys: 419311a5261eSBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to `MatSetFromOptions()` 4194ccd284c7SBarry Smith 4195ccd284c7SBarry Smith Level: beginner 4196ccd284c7SBarry Smith 4197c2e3fba1SPatrick Sanan .seealso: `MatCreateMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL` 4198ccd284c7SBarry Smith M*/ 4199ccd284c7SBarry Smith 42007906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat, MatType, MatReuse, Mat *); 42017906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 42027906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat, MatType, MatReuse, Mat *); 42037906f579SHong Zhang #endif 4204d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 4205d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat, MatType, MatReuse, Mat *); 4206d24d4204SJose E. Roman #endif 42077906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE) 42087906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType, MatReuse, Mat *); 42097906f579SHong Zhang #endif 42107906f579SHong Zhang 4211d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat, MatType, MatReuse, Mat *); 4212c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat, MatType, MatReuse, Mat *); 42134222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat); 42147906f579SHong Zhang 42158c778c55SBarry Smith /*@C 421611a5261eSBarry Smith MatSeqAIJGetArray - gives read/write access to the array where the data for a `MATSEQAIJ` matrix is stored 42178c778c55SBarry Smith 42188c778c55SBarry Smith Not Collective 42198c778c55SBarry Smith 42208c778c55SBarry Smith Input Parameter: 422111a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 42228c778c55SBarry Smith 42238c778c55SBarry Smith Output Parameter: 42248c778c55SBarry Smith . array - pointer to the data 42258c778c55SBarry Smith 42268c778c55SBarry Smith Level: intermediate 42278c778c55SBarry Smith 4228db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()` 42298c778c55SBarry Smith @*/ 42309371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArray(Mat A, PetscScalar **array) { 4231d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 42328c778c55SBarry Smith 42338c778c55SBarry Smith PetscFunctionBegin; 4234d67d9f35SJunchao Zhang if (aij->ops->getarray) { 42359566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarray)(A, array)); 4236d67d9f35SJunchao Zhang } else { 4237d67d9f35SJunchao Zhang *array = aij->a; 4238d67d9f35SJunchao Zhang } 4239d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4240d67d9f35SJunchao Zhang } 4241d67d9f35SJunchao Zhang 4242d67d9f35SJunchao Zhang /*@C 424311a5261eSBarry Smith MatSeqAIJRestoreArray - returns access to the array where the data for a `MATSEQAIJ` matrix is stored obtained by `MatSeqAIJGetArray()` 4244d67d9f35SJunchao Zhang 4245d67d9f35SJunchao Zhang Not Collective 4246d67d9f35SJunchao Zhang 4247d67d9f35SJunchao Zhang Input Parameters: 424811a5261eSBarry Smith + mat - a `MATSEQAIJ` matrix 4249d67d9f35SJunchao Zhang - array - pointer to the data 4250d67d9f35SJunchao Zhang 4251d67d9f35SJunchao Zhang Level: intermediate 4252d67d9f35SJunchao Zhang 4253db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayF90()` 4254d67d9f35SJunchao Zhang @*/ 42559371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArray(Mat A, PetscScalar **array) { 4256d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4257d67d9f35SJunchao Zhang 4258d67d9f35SJunchao Zhang PetscFunctionBegin; 4259d67d9f35SJunchao Zhang if (aij->ops->restorearray) { 42609566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearray)(A, array)); 4261d67d9f35SJunchao Zhang } else { 4262d67d9f35SJunchao Zhang *array = NULL; 4263d67d9f35SJunchao Zhang } 42649566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 42659566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 42668c778c55SBarry Smith PetscFunctionReturn(0); 42678c778c55SBarry Smith } 42688c778c55SBarry Smith 426921e72a00SBarry Smith /*@C 427011a5261eSBarry Smith MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a `MATSEQAIJ` matrix is stored 42718f1ea47aSStefano Zampini 42728f1ea47aSStefano Zampini Not Collective 42738f1ea47aSStefano Zampini 42748f1ea47aSStefano Zampini Input Parameter: 427511a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 42768f1ea47aSStefano Zampini 42778f1ea47aSStefano Zampini Output Parameter: 42788f1ea47aSStefano Zampini . array - pointer to the data 42798f1ea47aSStefano Zampini 42808f1ea47aSStefano Zampini Level: intermediate 42818f1ea47aSStefano Zampini 4282db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 42838f1ea47aSStefano Zampini @*/ 42849371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArrayRead(Mat A, const PetscScalar **array) { 4285d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 42868f1ea47aSStefano Zampini 42878f1ea47aSStefano Zampini PetscFunctionBegin; 4288d67d9f35SJunchao Zhang if (aij->ops->getarrayread) { 42899566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarrayread)(A, array)); 4290d67d9f35SJunchao Zhang } else { 4291d67d9f35SJunchao Zhang *array = aij->a; 4292d67d9f35SJunchao Zhang } 42938f1ea47aSStefano Zampini PetscFunctionReturn(0); 42948f1ea47aSStefano Zampini } 42958f1ea47aSStefano Zampini 42968f1ea47aSStefano Zampini /*@C 429711a5261eSBarry Smith MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from `MatSeqAIJGetArrayRead()` 42988f1ea47aSStefano Zampini 42998f1ea47aSStefano Zampini Not Collective 43008f1ea47aSStefano Zampini 43018f1ea47aSStefano Zampini Input Parameter: 430211a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 43038f1ea47aSStefano Zampini 43048f1ea47aSStefano Zampini Output Parameter: 43058f1ea47aSStefano Zampini . array - pointer to the data 43068f1ea47aSStefano Zampini 43078f1ea47aSStefano Zampini Level: intermediate 43088f1ea47aSStefano Zampini 4309db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 43108f1ea47aSStefano Zampini @*/ 43119371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArrayRead(Mat A, const PetscScalar **array) { 4312d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 43138f1ea47aSStefano Zampini 43148f1ea47aSStefano Zampini PetscFunctionBegin; 4315d67d9f35SJunchao Zhang if (aij->ops->restorearrayread) { 43169566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearrayread)(A, array)); 4317d67d9f35SJunchao Zhang } else { 4318d67d9f35SJunchao Zhang *array = NULL; 4319d67d9f35SJunchao Zhang } 4320d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4321d67d9f35SJunchao Zhang } 4322d67d9f35SJunchao Zhang 4323d67d9f35SJunchao Zhang /*@C 432411a5261eSBarry Smith MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a `MATSEQAIJ` matrix is stored 4325d67d9f35SJunchao Zhang 4326d67d9f35SJunchao Zhang Not Collective 4327d67d9f35SJunchao Zhang 4328d67d9f35SJunchao Zhang Input Parameter: 432911a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 4330d67d9f35SJunchao Zhang 4331d67d9f35SJunchao Zhang Output Parameter: 4332d67d9f35SJunchao Zhang . array - pointer to the data 4333d67d9f35SJunchao Zhang 4334d67d9f35SJunchao Zhang Level: intermediate 4335d67d9f35SJunchao Zhang 4336db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 4337d67d9f35SJunchao Zhang @*/ 43389371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArrayWrite(Mat A, PetscScalar **array) { 4339d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4340d67d9f35SJunchao Zhang 4341d67d9f35SJunchao Zhang PetscFunctionBegin; 4342d67d9f35SJunchao Zhang if (aij->ops->getarraywrite) { 43439566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarraywrite)(A, array)); 4344d67d9f35SJunchao Zhang } else { 4345d67d9f35SJunchao Zhang *array = aij->a; 4346d67d9f35SJunchao Zhang } 43479566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 43489566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 4349d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4350d67d9f35SJunchao Zhang } 4351d67d9f35SJunchao Zhang 4352d67d9f35SJunchao Zhang /*@C 4353d67d9f35SJunchao Zhang MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead 4354d67d9f35SJunchao Zhang 4355d67d9f35SJunchao Zhang Not Collective 4356d67d9f35SJunchao Zhang 4357d67d9f35SJunchao Zhang Input Parameter: 4358d67d9f35SJunchao Zhang . mat - a MATSEQAIJ matrix 4359d67d9f35SJunchao Zhang 4360d67d9f35SJunchao Zhang Output Parameter: 4361d67d9f35SJunchao Zhang . array - pointer to the data 4362d67d9f35SJunchao Zhang 4363d67d9f35SJunchao Zhang Level: intermediate 4364d67d9f35SJunchao Zhang 4365db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 4366d67d9f35SJunchao Zhang @*/ 43679371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArrayWrite(Mat A, PetscScalar **array) { 4368d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4369d67d9f35SJunchao Zhang 4370d67d9f35SJunchao Zhang PetscFunctionBegin; 4371d67d9f35SJunchao Zhang if (aij->ops->restorearraywrite) { 43729566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearraywrite)(A, array)); 4373d67d9f35SJunchao Zhang } else { 4374d67d9f35SJunchao Zhang *array = NULL; 4375d67d9f35SJunchao Zhang } 43768f1ea47aSStefano Zampini PetscFunctionReturn(0); 43778f1ea47aSStefano Zampini } 43788f1ea47aSStefano Zampini 43798f1ea47aSStefano Zampini /*@C 438011a5261eSBarry Smith MatSeqAIJGetCSRAndMemType - Get the CSR arrays and the memory type of the `MATSEQAIJ` matrix 43817ee59b9bSJunchao Zhang 43827ee59b9bSJunchao Zhang Not Collective 43837ee59b9bSJunchao Zhang 43847ee59b9bSJunchao Zhang Input Parameter: 438511a5261eSBarry Smith . mat - a matrix of type `MATSEQAIJ` or its subclasses 43867ee59b9bSJunchao Zhang 43877ee59b9bSJunchao Zhang Output Parameters: 43887ee59b9bSJunchao Zhang + i - row map array of the matrix 43897ee59b9bSJunchao Zhang . j - column index array of the matrix 43907ee59b9bSJunchao Zhang . a - data array of the matrix 43917ee59b9bSJunchao Zhang - memtype - memory type of the arrays 43927ee59b9bSJunchao Zhang 43937ee59b9bSJunchao Zhang Notes: 43947ee59b9bSJunchao Zhang Any of the output parameters can be NULL, in which case the corresponding value is not returned. 43957ee59b9bSJunchao Zhang If mat is a device matrix, the arrays are on the device. Otherwise, they are on the host. 43967ee59b9bSJunchao Zhang 43977ee59b9bSJunchao Zhang One can call this routine on a preallocated but not assembled matrix to just get the memory of the CSR underneath the matrix. 43987ee59b9bSJunchao Zhang If the matrix is assembled, the data array 'a' is guaranteed to have the latest values of the matrix. 43997ee59b9bSJunchao Zhang 44007ee59b9bSJunchao Zhang Level: Developer 44017ee59b9bSJunchao Zhang 4402db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 44037ee59b9bSJunchao Zhang @*/ 44049371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetCSRAndMemType(Mat mat, const PetscInt **i, const PetscInt **j, PetscScalar **a, PetscMemType *mtype) { 44057ee59b9bSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 44067ee59b9bSJunchao Zhang 44077ee59b9bSJunchao Zhang PetscFunctionBegin; 44087ee59b9bSJunchao Zhang PetscCheck(mat->preallocated, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "matrix is not preallocated"); 44097ee59b9bSJunchao Zhang if (aij->ops->getcsrandmemtype) { 44107ee59b9bSJunchao Zhang PetscCall((*aij->ops->getcsrandmemtype)(mat, i, j, a, mtype)); 44117ee59b9bSJunchao Zhang } else { 44127ee59b9bSJunchao Zhang if (i) *i = aij->i; 44137ee59b9bSJunchao Zhang if (j) *j = aij->j; 44147ee59b9bSJunchao Zhang if (a) *a = aij->a; 44157ee59b9bSJunchao Zhang if (mtype) *mtype = PETSC_MEMTYPE_HOST; 44167ee59b9bSJunchao Zhang } 44177ee59b9bSJunchao Zhang PetscFunctionReturn(0); 44187ee59b9bSJunchao Zhang } 44197ee59b9bSJunchao Zhang 44207ee59b9bSJunchao Zhang /*@C 442121e72a00SBarry Smith MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row 442221e72a00SBarry Smith 442321e72a00SBarry Smith Not Collective 442421e72a00SBarry Smith 442521e72a00SBarry Smith Input Parameter: 442611a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 442721e72a00SBarry Smith 442821e72a00SBarry Smith Output Parameter: 442921e72a00SBarry Smith . nz - the maximum number of nonzeros in any row 443021e72a00SBarry Smith 443121e72a00SBarry Smith Level: intermediate 443221e72a00SBarry Smith 4433db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()` 443421e72a00SBarry Smith @*/ 44359371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetMaxRowNonzeros(Mat A, PetscInt *nz) { 443621e72a00SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 443721e72a00SBarry Smith 443821e72a00SBarry Smith PetscFunctionBegin; 443921e72a00SBarry Smith *nz = aij->rmax; 444021e72a00SBarry Smith PetscFunctionReturn(0); 444121e72a00SBarry Smith } 444221e72a00SBarry Smith 44439371c9d4SSatish Balay PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[]) { 4444394ed5ebSJunchao Zhang MPI_Comm comm; 4445394ed5ebSJunchao Zhang PetscInt *i, *j; 4446394ed5ebSJunchao Zhang PetscInt M, N, row; 4447394ed5ebSJunchao Zhang PetscCount k, p, q, nneg, nnz, start, end; /* Index the coo array, so use PetscCount as their type */ 4448394ed5ebSJunchao Zhang PetscInt *Ai; /* Change to PetscCount once we use it for row pointers */ 4449394ed5ebSJunchao Zhang PetscInt *Aj; 4450394ed5ebSJunchao Zhang PetscScalar *Aa; 4451cbc6b225SStefano Zampini Mat_SeqAIJ *seqaij = (Mat_SeqAIJ *)(mat->data); 4452cbc6b225SStefano Zampini MatType rtype; 4453394ed5ebSJunchao Zhang PetscCount *perm, *jmap; 4454394ed5ebSJunchao Zhang 4455394ed5ebSJunchao Zhang PetscFunctionBegin; 44569566063dSJacob Faibussowitsch PetscCall(MatResetPreallocationCOO_SeqAIJ(mat)); 44579566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 44589566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &M, &N)); 4459e8729f6fSJunchao Zhang i = coo_i; 4460e8729f6fSJunchao Zhang j = coo_j; 44619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n, &perm)); 4462394ed5ebSJunchao Zhang for (k = 0; k < coo_n; k++) { /* Ignore entries with negative row or col indices */ 4463394ed5ebSJunchao Zhang if (j[k] < 0) i[k] = -1; 4464394ed5ebSJunchao Zhang perm[k] = k; 4465394ed5ebSJunchao Zhang } 4466394ed5ebSJunchao Zhang 4467394ed5ebSJunchao Zhang /* Sort by row */ 44689566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithIntCountArrayPair(coo_n, i, j, perm)); 44699371c9d4SSatish Balay for (k = 0; k < coo_n; k++) { 44709371c9d4SSatish Balay if (i[k] >= 0) break; 44719371c9d4SSatish Balay } /* Advance k to the first row with a non-negative index */ 4472394ed5ebSJunchao Zhang nneg = k; 44739566063dSJacob 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 */ 4474394ed5ebSJunchao Zhang nnz = 0; /* Total number of unique nonzeros to be counted */ 4475394ed5ebSJunchao Zhang jmap++; /* Inc jmap by 1 for convinience */ 4476394ed5ebSJunchao Zhang 44779566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(M + 1, &Ai)); /* CSR of A */ 44789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n - nneg, &Aj)); /* We have at most coo_n-nneg unique nonzeros */ 4479394ed5ebSJunchao Zhang 4480394ed5ebSJunchao Zhang /* In each row, sort by column, then unique column indices to get row length */ 4481394ed5ebSJunchao Zhang Ai++; /* Inc by 1 for convinience */ 4482394ed5ebSJunchao Zhang q = 0; /* q-th unique nonzero, with q starting from 0 */ 4483394ed5ebSJunchao Zhang while (k < coo_n) { 4484394ed5ebSJunchao Zhang row = i[k]; 4485394ed5ebSJunchao Zhang start = k; /* [start,end) indices for this row */ 4486394ed5ebSJunchao Zhang while (k < coo_n && i[k] == row) k++; 4487394ed5ebSJunchao Zhang end = k; 44889566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithCountArray(end - start, j + start, perm + start)); 4489394ed5ebSJunchao Zhang /* Find number of unique col entries in this row */ 4490394ed5ebSJunchao Zhang Aj[q] = j[start]; /* Log the first nonzero in this row */ 4491394ed5ebSJunchao Zhang jmap[q] = 1; /* Number of repeats of this nozero entry */ 4492394ed5ebSJunchao Zhang Ai[row] = 1; 4493394ed5ebSJunchao Zhang nnz++; 4494394ed5ebSJunchao Zhang 4495394ed5ebSJunchao Zhang for (p = start + 1; p < end; p++) { /* Scan remaining nonzero in this row */ 4496394ed5ebSJunchao Zhang if (j[p] != j[p - 1]) { /* Meet a new nonzero */ 4497394ed5ebSJunchao Zhang q++; 4498394ed5ebSJunchao Zhang jmap[q] = 1; 4499394ed5ebSJunchao Zhang Aj[q] = j[p]; 4500394ed5ebSJunchao Zhang Ai[row]++; 4501394ed5ebSJunchao Zhang nnz++; 4502394ed5ebSJunchao Zhang } else { 4503394ed5ebSJunchao Zhang jmap[q]++; 4504394ed5ebSJunchao Zhang } 4505394ed5ebSJunchao Zhang } 4506394ed5ebSJunchao Zhang q++; /* Move to next row and thus next unique nonzero */ 4507394ed5ebSJunchao Zhang } 4508394ed5ebSJunchao Zhang 4509394ed5ebSJunchao Zhang Ai--; /* Back to the beginning of Ai[] */ 4510394ed5ebSJunchao Zhang for (k = 0; k < M; k++) Ai[k + 1] += Ai[k]; 4511394ed5ebSJunchao Zhang jmap--; /* Back to the beginning of jmap[] */ 4512394ed5ebSJunchao Zhang jmap[0] = 0; 4513394ed5ebSJunchao Zhang for (k = 0; k < nnz; k++) jmap[k + 1] += jmap[k]; 4514394ed5ebSJunchao Zhang if (nnz < coo_n - nneg) { /* Realloc with actual number of unique nonzeros */ 4515394ed5ebSJunchao Zhang PetscCount *jmap_new; 4516394ed5ebSJunchao Zhang PetscInt *Aj_new; 4517394ed5ebSJunchao Zhang 45189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz + 1, &jmap_new)); 45199566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(jmap_new, jmap, nnz + 1)); 45209566063dSJacob Faibussowitsch PetscCall(PetscFree(jmap)); 4521394ed5ebSJunchao Zhang jmap = jmap_new; 4522394ed5ebSJunchao Zhang 45239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &Aj_new)); 45249566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(Aj_new, Aj, nnz)); 45259566063dSJacob Faibussowitsch PetscCall(PetscFree(Aj)); 4526394ed5ebSJunchao Zhang Aj = Aj_new; 4527394ed5ebSJunchao Zhang } 4528394ed5ebSJunchao Zhang 4529394ed5ebSJunchao Zhang if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */ 4530394ed5ebSJunchao Zhang PetscCount *perm_new; 4531cbc6b225SStefano Zampini 45329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n - nneg, &perm_new)); 45339566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(perm_new, perm + nneg, coo_n - nneg)); 45349566063dSJacob Faibussowitsch PetscCall(PetscFree(perm)); 4535394ed5ebSJunchao Zhang perm = perm_new; 4536394ed5ebSJunchao Zhang } 4537394ed5ebSJunchao Zhang 45389566063dSJacob Faibussowitsch PetscCall(MatGetRootType_Private(mat, &rtype)); 45399566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nnz, &Aa)); /* Zero the matrix */ 45409566063dSJacob Faibussowitsch PetscCall(MatSetSeqAIJWithArrays_private(PETSC_COMM_SELF, M, N, Ai, Aj, Aa, rtype, mat)); 4541394ed5ebSJunchao Zhang 4542394ed5ebSJunchao Zhang seqaij->singlemalloc = PETSC_FALSE; /* Ai, Aj and Aa are not allocated in one big malloc */ 4543394ed5ebSJunchao Zhang seqaij->free_a = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */ 4544394ed5ebSJunchao Zhang /* Record COO fields */ 4545394ed5ebSJunchao Zhang seqaij->coo_n = coo_n; 4546394ed5ebSJunchao Zhang seqaij->Atot = coo_n - nneg; /* Annz is seqaij->nz, so no need to record that again */ 4547394ed5ebSJunchao Zhang seqaij->jmap = jmap; /* of length nnz+1 */ 4548394ed5ebSJunchao Zhang seqaij->perm = perm; 4549394ed5ebSJunchao Zhang PetscFunctionReturn(0); 4550394ed5ebSJunchao Zhang } 4551394ed5ebSJunchao Zhang 45529371c9d4SSatish Balay static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A, const PetscScalar v[], InsertMode imode) { 4553394ed5ebSJunchao Zhang Mat_SeqAIJ *aseq = (Mat_SeqAIJ *)A->data; 4554394ed5ebSJunchao Zhang PetscCount i, j, Annz = aseq->nz; 4555394ed5ebSJunchao Zhang PetscCount *perm = aseq->perm, *jmap = aseq->jmap; 4556394ed5ebSJunchao Zhang PetscScalar *Aa; 4557394ed5ebSJunchao Zhang 4558394ed5ebSJunchao Zhang PetscFunctionBegin; 45599566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &Aa)); 4560394ed5ebSJunchao Zhang for (i = 0; i < Annz; i++) { 4561b6c38306SJunchao Zhang PetscScalar sum = 0.0; 4562b6c38306SJunchao Zhang for (j = jmap[i]; j < jmap[i + 1]; j++) sum += v[perm[j]]; 4563b6c38306SJunchao Zhang Aa[i] = (imode == INSERT_VALUES ? 0.0 : Aa[i]) + sum; 4564394ed5ebSJunchao Zhang } 45659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &Aa)); 4566394ed5ebSJunchao Zhang PetscFunctionReturn(0); 4567394ed5ebSJunchao Zhang } 4568394ed5ebSJunchao Zhang 456934b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 45705063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat, MatType, MatReuse, Mat *); 457102fe1965SBarry Smith #endif 45723d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 45735063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat, MatType, MatReuse, Mat *); 45743d0639e7SStefano Zampini #endif 457502fe1965SBarry Smith 45769371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B) { 4577273d9f13SBarry Smith Mat_SeqAIJ *b; 457838baddfdSBarry Smith PetscMPIInt size; 4579273d9f13SBarry Smith 4580273d9f13SBarry Smith PetscFunctionBegin; 45819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size)); 458208401ef6SPierre Jolivet PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Comm must be of size 1"); 4583273d9f13SBarry Smith 4584*4dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&b)); 45852205254eSKarl Rupp 4586b0a32e0cSBarry Smith B->data = (void *)b; 45872205254eSKarl Rupp 45889566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(B->ops, &MatOps_Values, sizeof(struct _MatOps))); 4589071fcb05SBarry Smith if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 45902205254eSKarl Rupp 4591f4259b30SLisandro Dalcin b->row = NULL; 4592f4259b30SLisandro Dalcin b->col = NULL; 4593f4259b30SLisandro Dalcin b->icol = NULL; 4594b810aeb4SBarry Smith b->reallocs = 0; 459536db0b34SBarry Smith b->ignorezeroentries = PETSC_FALSE; 4596f1e2ffcdSBarry Smith b->roworiented = PETSC_TRUE; 4597416022c9SBarry Smith b->nonew = 0; 4598f4259b30SLisandro Dalcin b->diag = NULL; 4599f4259b30SLisandro Dalcin b->solve_work = NULL; 4600f4259b30SLisandro Dalcin B->spptr = NULL; 4601f4259b30SLisandro Dalcin b->saved_values = NULL; 4602f4259b30SLisandro Dalcin b->idiag = NULL; 4603f4259b30SLisandro Dalcin b->mdiag = NULL; 4604f4259b30SLisandro Dalcin b->ssor_work = NULL; 460571f1c65dSBarry Smith b->omega = 1.0; 460671f1c65dSBarry Smith b->fshift = 0.0; 460771f1c65dSBarry Smith b->idiagvalid = PETSC_FALSE; 4608bbead8a2SBarry Smith b->ibdiagvalid = PETSC_FALSE; 4609a9817697SBarry Smith b->keepnonzeropattern = PETSC_FALSE; 461017ab2063SBarry Smith 46119566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ)); 4612b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE) 46139566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEnginePut_C", MatlabEnginePut_SeqAIJ)); 46149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEngineGet_C", MatlabEngineGet_SeqAIJ)); 4615b3866ffcSBarry Smith #endif 46169566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetColumnIndices_C", MatSeqAIJSetColumnIndices_SeqAIJ)); 46179566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqAIJ)); 46189566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqAIJ)); 46199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsbaij_C", MatConvert_SeqAIJ_SeqSBAIJ)); 46209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqbaij_C", MatConvert_SeqAIJ_SeqBAIJ)); 46219566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijperm_C", MatConvert_SeqAIJ_SeqAIJPERM)); 46229566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijsell_C", MatConvert_SeqAIJ_SeqAIJSELL)); 46239779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 46249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijmkl_C", MatConvert_SeqAIJ_SeqAIJMKL)); 4625191b95cbSRichard Tran Mills #endif 462634b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 46279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcusparse_C", MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 46289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_seqaij_C", MatProductSetFromOptions_SeqAIJ)); 46299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaijcusparse_C", MatProductSetFromOptions_SeqAIJ)); 463002fe1965SBarry Smith #endif 46313d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 46329566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijkokkos_C", MatConvert_SeqAIJ_SeqAIJKokkos)); 46333d0639e7SStefano Zampini #endif 46349566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcrl_C", MatConvert_SeqAIJ_SeqAIJCRL)); 4635af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 46369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_elemental_C", MatConvert_SeqAIJ_Elemental)); 4637af8000cdSHong Zhang #endif 4638d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 46399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_scalapack_C", MatConvert_AIJ_ScaLAPACK)); 4640d24d4204SJose E. Roman #endif 464163c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 46429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_hypre_C", MatConvert_AIJ_HYPRE)); 46439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_transpose_seqaij_seqaij_C", MatProductSetFromOptions_Transpose_AIJ_AIJ)); 464463c07aadSStefano Zampini #endif 46459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqdense_C", MatConvert_SeqAIJ_SeqDense)); 46469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsell_C", MatConvert_SeqAIJ_SeqSELL)); 46479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_is_C", MatConvert_XAIJ_IS)); 46489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsTranspose_C", MatIsTranspose_SeqAIJ)); 46499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsHermitianTranspose_C", MatIsTranspose_SeqAIJ)); 46509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocation_C", MatSeqAIJSetPreallocation_SeqAIJ)); 46519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatResetPreallocation_C", MatResetPreallocation_SeqAIJ)); 46529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocationCSR_C", MatSeqAIJSetPreallocationCSR_SeqAIJ)); 46539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatReorderForNonzeroDiagonal_C", MatReorderForNonzeroDiagonal_SeqAIJ)); 46549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_is_seqaij_C", MatProductSetFromOptions_IS_XAIJ)); 46559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqaij_C", MatProductSetFromOptions_SeqDense_SeqAIJ)); 46569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaij_C", MatProductSetFromOptions_SeqAIJ)); 46579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJKron_C", MatSeqAIJKron_SeqAIJ)); 46589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_SeqAIJ)); 46599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_SeqAIJ)); 46609566063dSJacob Faibussowitsch PetscCall(MatCreate_SeqAIJ_Inode(B)); 46619566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ)); 46629566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetTypeFromOptions(B)); /* this allows changing the matrix subtype to say MATSEQAIJPERM */ 46633a40ed3dSBarry Smith PetscFunctionReturn(0); 466417ab2063SBarry Smith } 466517ab2063SBarry Smith 4666b24902e0SBarry Smith /* 46673893b582SJunchao Zhang Given a matrix generated with MatGetFactor() duplicates all the information in A into C 4668b24902e0SBarry Smith */ 46699371c9d4SSatish Balay PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C, Mat A, MatDuplicateOption cpvalues, PetscBool mallocmatspace) { 46702a350339SBarry Smith Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data, *a = (Mat_SeqAIJ *)A->data; 4671071fcb05SBarry Smith PetscInt m = A->rmap->n, i; 467217ab2063SBarry Smith 46733a40ed3dSBarry Smith PetscFunctionBegin; 4674aed4548fSBarry Smith PetscCheck(A->assembled || cpvalues == MAT_DO_NOT_COPY_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix"); 4675273d9f13SBarry Smith 4676d5f3da31SBarry Smith C->factortype = A->factortype; 4677f4259b30SLisandro Dalcin c->row = NULL; 4678f4259b30SLisandro Dalcin c->col = NULL; 4679f4259b30SLisandro Dalcin c->icol = NULL; 46806ad4291fSHong Zhang c->reallocs = 0; 468117ab2063SBarry Smith 468269272f91SPierre Jolivet C->assembled = A->assembled; 468369272f91SPierre Jolivet C->preallocated = A->preallocated; 468417ab2063SBarry Smith 468569272f91SPierre Jolivet if (A->preallocated) { 46869566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->rmap, &C->rmap)); 46879566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->cmap, &C->cmap)); 4688eec197d1SBarry Smith 46899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &c->imax)); 46909566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->imax, a->imax, m * sizeof(PetscInt))); 46919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &c->ilen)); 46929566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->ilen, a->ilen, m * sizeof(PetscInt))); 469317ab2063SBarry Smith 469417ab2063SBarry Smith /* allocate the matrix space */ 4695f77e22a1SHong Zhang if (mallocmatspace) { 46969566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(a->i[m], &c->a, a->i[m], &c->j, m + 1, &c->i)); 46972205254eSKarl Rupp 4698f1e2ffcdSBarry Smith c->singlemalloc = PETSC_TRUE; 46992205254eSKarl Rupp 47009566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->i, a->i, m + 1)); 470117ab2063SBarry Smith if (m > 0) { 47029566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->j, a->j, a->i[m])); 4703be6bf707SBarry Smith if (cpvalues == MAT_COPY_VALUES) { 47042e5835c6SStefano Zampini const PetscScalar *aa; 47052e5835c6SStefano Zampini 47069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 47079566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->a, aa, a->i[m])); 47089566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 4709be6bf707SBarry Smith } else { 47109566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->a, a->i[m])); 471117ab2063SBarry Smith } 471208480c60SBarry Smith } 4713f77e22a1SHong Zhang } 471417ab2063SBarry Smith 47156ad4291fSHong Zhang c->ignorezeroentries = a->ignorezeroentries; 4716416022c9SBarry Smith c->roworiented = a->roworiented; 4717416022c9SBarry Smith c->nonew = a->nonew; 4718416022c9SBarry Smith if (a->diag) { 47199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &c->diag)); 47209566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->diag, a->diag, m * sizeof(PetscInt))); 4721071fcb05SBarry Smith } else c->diag = NULL; 47222205254eSKarl Rupp 4723f4259b30SLisandro Dalcin c->solve_work = NULL; 4724f4259b30SLisandro Dalcin c->saved_values = NULL; 4725f4259b30SLisandro Dalcin c->idiag = NULL; 4726f4259b30SLisandro Dalcin c->ssor_work = NULL; 4727a9817697SBarry Smith c->keepnonzeropattern = a->keepnonzeropattern; 4728e6b907acSBarry Smith c->free_a = PETSC_TRUE; 4729e6b907acSBarry Smith c->free_ij = PETSC_TRUE; 47306ad4291fSHong Zhang 4731893ad86cSHong Zhang c->rmax = a->rmax; 4732416022c9SBarry Smith c->nz = a->nz; 47338ed568f8SMatthew G Knepley c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 4734754ec7b1SSatish Balay 47356ad4291fSHong Zhang c->compressedrow.use = a->compressedrow.use; 47366ad4291fSHong Zhang c->compressedrow.nrows = a->compressedrow.nrows; 4737cd6b891eSBarry Smith if (a->compressedrow.use) { 47386ad4291fSHong Zhang i = a->compressedrow.nrows; 47399566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i + 1, &c->compressedrow.i, i, &c->compressedrow.rindex)); 47409566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.i, a->compressedrow.i, i + 1)); 47419566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.rindex, a->compressedrow.rindex, i)); 474227ea64f8SHong Zhang } else { 474327ea64f8SHong Zhang c->compressedrow.use = PETSC_FALSE; 47440298fd71SBarry Smith c->compressedrow.i = NULL; 47450298fd71SBarry Smith c->compressedrow.rindex = NULL; 47466ad4291fSHong Zhang } 4747ea632784SBarry Smith c->nonzerorowcnt = a->nonzerorowcnt; 4748e56f5c9eSBarry Smith C->nonzerostate = A->nonzerostate; 47494846f1f5SKris Buschelman 47509566063dSJacob Faibussowitsch PetscCall(MatDuplicate_SeqAIJ_Inode(A, cpvalues, &C)); 475169272f91SPierre Jolivet } 47529566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist)); 47533a40ed3dSBarry Smith PetscFunctionReturn(0); 475417ab2063SBarry Smith } 475517ab2063SBarry Smith 47569371c9d4SSatish Balay PetscErrorCode MatDuplicate_SeqAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B) { 4757b24902e0SBarry Smith PetscFunctionBegin; 47589566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 47599566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n)); 476048a46eb9SPierre Jolivet if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) PetscCall(MatSetBlockSizesFromMats(*B, A, A)); 47619566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, ((PetscObject)A)->type_name)); 47629566063dSJacob Faibussowitsch PetscCall(MatDuplicateNoCreate_SeqAIJ(*B, A, cpvalues, PETSC_TRUE)); 4763b24902e0SBarry Smith PetscFunctionReturn(0); 4764b24902e0SBarry Smith } 4765b24902e0SBarry Smith 47669371c9d4SSatish Balay PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer) { 476752f91c60SVaclav Hapla PetscBool isbinary, ishdf5; 476852f91c60SVaclav Hapla 476952f91c60SVaclav Hapla PetscFunctionBegin; 477052f91c60SVaclav Hapla PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1); 477152f91c60SVaclav Hapla PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 4772c27b3999SVaclav Hapla /* force binary viewer to load .info file if it has not yet done so */ 47739566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 47749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 47759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 477652f91c60SVaclav Hapla if (isbinary) { 47779566063dSJacob Faibussowitsch PetscCall(MatLoad_SeqAIJ_Binary(newMat, viewer)); 477852f91c60SVaclav Hapla } else if (ishdf5) { 477952f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5) 47809566063dSJacob Faibussowitsch PetscCall(MatLoad_AIJ_HDF5(newMat, viewer)); 478152f91c60SVaclav Hapla #else 478252f91c60SVaclav Hapla SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 478352f91c60SVaclav Hapla #endif 478452f91c60SVaclav Hapla } else { 478598921bdaSJacob 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); 478652f91c60SVaclav Hapla } 478752f91c60SVaclav Hapla PetscFunctionReturn(0); 478852f91c60SVaclav Hapla } 478952f91c60SVaclav Hapla 47909371c9d4SSatish Balay PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer) { 47913ea6fe3dSLisandro Dalcin Mat_SeqAIJ *a = (Mat_SeqAIJ *)mat->data; 47923ea6fe3dSLisandro Dalcin PetscInt header[4], *rowlens, M, N, nz, sum, rows, cols, i; 4793fbdbba38SShri Abhyankar 4794fbdbba38SShri Abhyankar PetscFunctionBegin; 47959566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 4796bbead8a2SBarry Smith 47973ea6fe3dSLisandro Dalcin /* read in matrix header */ 47989566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT)); 479908401ef6SPierre Jolivet PetscCheck(header[0] == MAT_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file"); 48009371c9d4SSatish Balay M = header[1]; 48019371c9d4SSatish Balay N = header[2]; 48029371c9d4SSatish Balay nz = header[3]; 480308401ef6SPierre Jolivet PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M); 480408401ef6SPierre Jolivet PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N); 480508401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Matrix stored in special format on disk, cannot load as SeqAIJ"); 4806fbdbba38SShri Abhyankar 48073ea6fe3dSLisandro Dalcin /* set block sizes from the viewer's .info file */ 48089566063dSJacob Faibussowitsch PetscCall(MatLoad_Binary_BlockSizes(mat, viewer)); 48093ea6fe3dSLisandro Dalcin /* set local and global sizes if not set already */ 48103ea6fe3dSLisandro Dalcin if (mat->rmap->n < 0) mat->rmap->n = M; 48113ea6fe3dSLisandro Dalcin if (mat->cmap->n < 0) mat->cmap->n = N; 48123ea6fe3dSLisandro Dalcin if (mat->rmap->N < 0) mat->rmap->N = M; 48133ea6fe3dSLisandro Dalcin if (mat->cmap->N < 0) mat->cmap->N = N; 48149566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->rmap)); 48159566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->cmap)); 48163ea6fe3dSLisandro Dalcin 48173ea6fe3dSLisandro Dalcin /* check if the matrix sizes are correct */ 48189566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 4819aed4548fSBarry 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); 48203ea6fe3dSLisandro Dalcin 4821fbdbba38SShri Abhyankar /* read in row lengths */ 48229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(M, &rowlens)); 48239566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, rowlens, M, NULL, PETSC_INT)); 48243ea6fe3dSLisandro Dalcin /* check if sum(rowlens) is same as nz */ 48259371c9d4SSatish Balay sum = 0; 48269371c9d4SSatish Balay for (i = 0; i < M; i++) sum += rowlens[i]; 482708401ef6SPierre 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); 48283ea6fe3dSLisandro Dalcin /* preallocate and check sizes */ 48299566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(mat, 0, rowlens)); 48309566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 4831aed4548fSBarry 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); 48323ea6fe3dSLisandro Dalcin /* store row lengths */ 48339566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->ilen, rowlens, M)); 48349566063dSJacob Faibussowitsch PetscCall(PetscFree(rowlens)); 4835fbdbba38SShri Abhyankar 48363ea6fe3dSLisandro Dalcin /* fill in "i" row pointers */ 48379371c9d4SSatish Balay a->i[0] = 0; 48389371c9d4SSatish Balay for (i = 0; i < M; i++) a->i[i + 1] = a->i[i] + a->ilen[i]; 48393ea6fe3dSLisandro Dalcin /* read in "j" column indices */ 48409566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, a->j, nz, NULL, PETSC_INT)); 48413ea6fe3dSLisandro Dalcin /* read in "a" nonzero values */ 48429566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, a->a, nz, NULL, PETSC_SCALAR)); 4843fbdbba38SShri Abhyankar 48449566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 48459566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 4846fbdbba38SShri Abhyankar PetscFunctionReturn(0); 4847fbdbba38SShri Abhyankar } 4848fbdbba38SShri Abhyankar 48499371c9d4SSatish Balay PetscErrorCode MatEqual_SeqAIJ(Mat A, Mat B, PetscBool *flg) { 48507264ac53SSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data, *b = (Mat_SeqAIJ *)B->data; 4851fff043a9SJunchao Zhang const PetscScalar *aa, *ba; 4852eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 4853eeffb40dSHong Zhang PetscInt k; 4854eeffb40dSHong Zhang #endif 48557264ac53SSatish Balay 48563a40ed3dSBarry Smith PetscFunctionBegin; 4857bfeeae90SHong Zhang /* If the matrix dimensions are not equal,or no of nonzeros */ 4858d0f46423SBarry Smith if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) || (a->nz != b->nz)) { 4859ca44d042SBarry Smith *flg = PETSC_FALSE; 4860ca44d042SBarry Smith PetscFunctionReturn(0); 4861bcd2baecSBarry Smith } 48627264ac53SSatish Balay 48637264ac53SSatish Balay /* if the a->i are the same */ 48649566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->i, b->i, A->rmap->n + 1, flg)); 4865abc0a331SBarry Smith if (!*flg) PetscFunctionReturn(0); 48667264ac53SSatish Balay 48677264ac53SSatish Balay /* if a->j are the same */ 48689566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->j, b->j, a->nz, flg)); 4869abc0a331SBarry Smith if (!*flg) PetscFunctionReturn(0); 4870bcd2baecSBarry Smith 48719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 48729566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &ba)); 4873bcd2baecSBarry Smith /* if a->a are the same */ 4874eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 4875eeffb40dSHong Zhang for (k = 0; k < a->nz; k++) { 4876fff043a9SJunchao Zhang if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) { 4877eeffb40dSHong Zhang *flg = PETSC_FALSE; 48783a40ed3dSBarry Smith PetscFunctionReturn(0); 4879eeffb40dSHong Zhang } 4880eeffb40dSHong Zhang } 4881eeffb40dSHong Zhang #else 48829566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(aa, ba, a->nz, flg)); 4883eeffb40dSHong Zhang #endif 48849566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 48859566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &ba)); 4886eeffb40dSHong Zhang PetscFunctionReturn(0); 48877264ac53SSatish Balay } 488836db0b34SBarry Smith 488905869f15SSatish Balay /*@ 489011a5261eSBarry Smith MatCreateSeqAIJWithArrays - Creates an sequential `MATSEQAIJ` matrix using matrix elements (in CSR format) 489136db0b34SBarry Smith provided by the user. 489236db0b34SBarry Smith 4893d083f849SBarry Smith Collective 489436db0b34SBarry Smith 489536db0b34SBarry Smith Input Parameters: 489636db0b34SBarry Smith + comm - must be an MPI communicator of size 1 489736db0b34SBarry Smith . m - number of rows 489836db0b34SBarry Smith . n - number of columns 4899483a2f95SBarry Smith . i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 490036db0b34SBarry Smith . j - column indices 490136db0b34SBarry Smith - a - matrix values 490236db0b34SBarry Smith 490336db0b34SBarry Smith Output Parameter: 490436db0b34SBarry Smith . mat - the matrix 490536db0b34SBarry Smith 490636db0b34SBarry Smith Level: intermediate 490736db0b34SBarry Smith 490836db0b34SBarry Smith Notes: 49090551d7c0SBarry Smith The i, j, and a arrays are not copied by this routine, the user must free these arrays 4910292fb18eSBarry Smith once the matrix is destroyed and not before 491136db0b34SBarry Smith 491236db0b34SBarry Smith You cannot set new nonzero locations into this matrix, that will generate an error. 491336db0b34SBarry Smith 4914bfeeae90SHong Zhang The i and j indices are 0 based 491536db0b34SBarry Smith 4916a4552177SSatish Balay The format which is used for the sparse matrix input, is equivalent to a 4917a4552177SSatish Balay row-major ordering.. i.e for the following matrix, the input data expected is 49188eef79e4SBarry Smith as shown 4919a4552177SSatish Balay 49208eef79e4SBarry Smith $ 1 0 0 49218eef79e4SBarry Smith $ 2 0 3 49228eef79e4SBarry Smith $ 4 5 6 49238eef79e4SBarry Smith $ 49248eef79e4SBarry Smith $ i = {0,1,3,6} [size = nrow+1 = 3+1] 49258eef79e4SBarry Smith $ j = {0,0,2,0,1,2} [size = 6]; values must be sorted for each row 49268eef79e4SBarry Smith $ v = {1,2,3,4,5,6} [size = 6] 4927a4552177SSatish Balay 4928db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateMPIAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()` 492936db0b34SBarry Smith @*/ 49309371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat) { 4931cbcfb4deSHong Zhang PetscInt ii; 493236db0b34SBarry Smith Mat_SeqAIJ *aij; 4933cbcfb4deSHong Zhang PetscInt jj; 493436db0b34SBarry Smith 493536db0b34SBarry Smith PetscFunctionBegin; 4936aed4548fSBarry Smith PetscCheck(m <= 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0"); 49379566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 49389566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 49399566063dSJacob Faibussowitsch /* PetscCall(MatSetBlockSizes(*mat,,)); */ 49409566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQAIJ)); 49419566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, MAT_SKIP_ALLOCATION, NULL)); 4942ab93d7beSBarry Smith aij = (Mat_SeqAIJ *)(*mat)->data; 49439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &aij->imax)); 49449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &aij->ilen)); 4945ab93d7beSBarry Smith 494636db0b34SBarry Smith aij->i = i; 494736db0b34SBarry Smith aij->j = j; 494836db0b34SBarry Smith aij->a = a; 494936db0b34SBarry Smith aij->singlemalloc = PETSC_FALSE; 495036db0b34SBarry Smith aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 4951e6b907acSBarry Smith aij->free_a = PETSC_FALSE; 4952e6b907acSBarry Smith aij->free_ij = PETSC_FALSE; 495336db0b34SBarry Smith 4954cbc6b225SStefano Zampini for (ii = 0, aij->nonzerorowcnt = 0, aij->rmax = 0; ii < m; ii++) { 495536db0b34SBarry Smith aij->ilen[ii] = aij->imax[ii] = i[ii + 1] - i[ii]; 495676bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4957aed4548fSBarry 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]); 49589985e31cSBarry Smith for (jj = i[ii] + 1; jj < i[ii + 1]; jj++) { 495908401ef6SPierre 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); 496008401ef6SPierre 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); 49619985e31cSBarry Smith } 496236db0b34SBarry Smith } 496376bd3646SJed Brown } 496476bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 496536db0b34SBarry Smith for (ii = 0; ii < aij->i[m]; ii++) { 496608401ef6SPierre 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]); 4967aed4548fSBarry 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]); 496836db0b34SBarry Smith } 496976bd3646SJed Brown } 497036db0b34SBarry Smith 49719566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 49729566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 497336db0b34SBarry Smith PetscFunctionReturn(0); 497436db0b34SBarry Smith } 4975cbc6b225SStefano Zampini 4976f62e3866SBarry Smith /*@ 497711a5261eSBarry Smith MatCreateSeqAIJFromTriple - Creates an sequential `MATSEQAIJ` matrix using matrix elements (in COO format) 49788a0b0e6bSVictor Minden provided by the user. 49798a0b0e6bSVictor Minden 4980d083f849SBarry Smith Collective 49818a0b0e6bSVictor Minden 49828a0b0e6bSVictor Minden Input Parameters: 49838a0b0e6bSVictor Minden + comm - must be an MPI communicator of size 1 49848a0b0e6bSVictor Minden . m - number of rows 49858a0b0e6bSVictor Minden . n - number of columns 49868a0b0e6bSVictor Minden . i - row indices 49878a0b0e6bSVictor Minden . j - column indices 49881230e6d1SVictor Minden . a - matrix values 49891230e6d1SVictor Minden . nz - number of nonzeros 499011a5261eSBarry Smith - idx - if the i and j indices start with 1 use `PETSC_TRUE` otherwise use `PETSC_FALSE` 49918a0b0e6bSVictor Minden 49928a0b0e6bSVictor Minden Output Parameter: 49938a0b0e6bSVictor Minden . mat - the matrix 49948a0b0e6bSVictor Minden 49958a0b0e6bSVictor Minden Level: intermediate 49968a0b0e6bSVictor Minden 4997f62e3866SBarry Smith Example: 4998f62e3866SBarry Smith For the following matrix, the input data expected is as shown (using 0 based indexing) 49999e99939fSJunchao Zhang .vb 50008a0b0e6bSVictor Minden 1 0 0 50018a0b0e6bSVictor Minden 2 0 3 50028a0b0e6bSVictor Minden 4 5 6 50038a0b0e6bSVictor Minden 50048a0b0e6bSVictor Minden i = {0,1,1,2,2,2} 50058a0b0e6bSVictor Minden j = {0,0,2,0,1,2} 50068a0b0e6bSVictor Minden v = {1,2,3,4,5,6} 50079e99939fSJunchao Zhang .ve 50088a0b0e6bSVictor Minden 5009db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateSeqAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()`, `MatSetValuesCOO()` 50108a0b0e6bSVictor Minden @*/ 50119371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat, PetscInt nz, PetscBool idx) { 5012d021a1c5SVictor Minden PetscInt ii, *nnz, one = 1, row, col; 50138a0b0e6bSVictor Minden 50148a0b0e6bSVictor Minden PetscFunctionBegin; 50159566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m, &nnz)); 5016ad540459SPierre Jolivet for (ii = 0; ii < nz; ii++) nnz[i[ii] - !!idx] += 1; 50179566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 50189566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 50199566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQAIJ)); 50209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, 0, nnz)); 50211230e6d1SVictor Minden for (ii = 0; ii < nz; ii++) { 50221230e6d1SVictor Minden if (idx) { 50231230e6d1SVictor Minden row = i[ii] - 1; 50241230e6d1SVictor Minden col = j[ii] - 1; 50251230e6d1SVictor Minden } else { 50261230e6d1SVictor Minden row = i[ii]; 50271230e6d1SVictor Minden col = j[ii]; 50288a0b0e6bSVictor Minden } 50299566063dSJacob Faibussowitsch PetscCall(MatSetValues(*mat, one, &row, one, &col, &a[ii], ADD_VALUES)); 50308a0b0e6bSVictor Minden } 50319566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 50329566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 50339566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 50348a0b0e6bSVictor Minden PetscFunctionReturn(0); 50358a0b0e6bSVictor Minden } 503636db0b34SBarry Smith 50379371c9d4SSatish Balay PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A) { 5038acf2f550SJed Brown Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 5039acf2f550SJed Brown 5040acf2f550SJed Brown PetscFunctionBegin; 5041acf2f550SJed Brown a->idiagvalid = PETSC_FALSE; 5042acf2f550SJed Brown a->ibdiagvalid = PETSC_FALSE; 50432205254eSKarl Rupp 50449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal_Inode(A)); 5045acf2f550SJed Brown PetscFunctionReturn(0); 5046acf2f550SJed Brown } 5047acf2f550SJed Brown 50489371c9d4SSatish Balay PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat) { 50499c8f2541SHong Zhang PetscFunctionBegin; 50509566063dSJacob Faibussowitsch PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm, inmat, n, scall, outmat)); 50519c8f2541SHong Zhang PetscFunctionReturn(0); 50529c8f2541SHong Zhang } 50539c8f2541SHong Zhang 505481824310SBarry Smith /* 505553dd7562SDmitry Karpeev Permute A into C's *local* index space using rowemb,colemb. 505653dd7562SDmitry Karpeev The embedding are supposed to be injections and the above implies that the range of rowemb is a subset 505753dd7562SDmitry Karpeev of [0,m), colemb is in [0,n). 505853dd7562SDmitry Karpeev If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A. 505953dd7562SDmitry Karpeev */ 50609371c9d4SSatish Balay PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C, IS rowemb, IS colemb, MatStructure pattern, Mat B) { 506153dd7562SDmitry Karpeev /* If making this function public, change the error returned in this function away from _PLIB. */ 506253dd7562SDmitry Karpeev Mat_SeqAIJ *Baij; 506353dd7562SDmitry Karpeev PetscBool seqaij; 506453dd7562SDmitry Karpeev PetscInt m, n, *nz, i, j, count; 506553dd7562SDmitry Karpeev PetscScalar v; 506653dd7562SDmitry Karpeev const PetscInt *rowindices, *colindices; 506753dd7562SDmitry Karpeev 506853dd7562SDmitry Karpeev PetscFunctionBegin; 506953dd7562SDmitry Karpeev if (!B) PetscFunctionReturn(0); 507053dd7562SDmitry Karpeev /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */ 50719566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)B, MATSEQAIJ, &seqaij)); 507228b400f6SJacob Faibussowitsch PetscCheck(seqaij, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is of wrong type"); 507353dd7562SDmitry Karpeev if (rowemb) { 50749566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rowemb, &m)); 507508401ef6SPierre 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); 507653dd7562SDmitry Karpeev } else { 507708401ef6SPierre Jolivet PetscCheck(C->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is row-incompatible with the target matrix"); 507853dd7562SDmitry Karpeev } 507953dd7562SDmitry Karpeev if (colemb) { 50809566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(colemb, &n)); 508108401ef6SPierre 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); 508253dd7562SDmitry Karpeev } else { 508308401ef6SPierre Jolivet PetscCheck(C->cmap->n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is col-incompatible with the target matrix"); 508453dd7562SDmitry Karpeev } 508553dd7562SDmitry Karpeev 508653dd7562SDmitry Karpeev Baij = (Mat_SeqAIJ *)(B->data); 508753dd7562SDmitry Karpeev if (pattern == DIFFERENT_NONZERO_PATTERN) { 50889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n, &nz)); 5089ad540459SPierre Jolivet for (i = 0; i < B->rmap->n; i++) nz[i] = Baij->i[i + 1] - Baij->i[i]; 50909566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(C, 0, nz)); 50919566063dSJacob Faibussowitsch PetscCall(PetscFree(nz)); 509253dd7562SDmitry Karpeev } 509348a46eb9SPierre Jolivet if (pattern == SUBSET_NONZERO_PATTERN) PetscCall(MatZeroEntries(C)); 509453dd7562SDmitry Karpeev count = 0; 509553dd7562SDmitry Karpeev rowindices = NULL; 509653dd7562SDmitry Karpeev colindices = NULL; 509748a46eb9SPierre Jolivet if (rowemb) PetscCall(ISGetIndices(rowemb, &rowindices)); 509848a46eb9SPierre Jolivet if (colemb) PetscCall(ISGetIndices(colemb, &colindices)); 509953dd7562SDmitry Karpeev for (i = 0; i < B->rmap->n; i++) { 510053dd7562SDmitry Karpeev PetscInt row; 510153dd7562SDmitry Karpeev row = i; 510253dd7562SDmitry Karpeev if (rowindices) row = rowindices[i]; 510353dd7562SDmitry Karpeev for (j = Baij->i[i]; j < Baij->i[i + 1]; j++) { 510453dd7562SDmitry Karpeev PetscInt col; 510553dd7562SDmitry Karpeev col = Baij->j[count]; 510653dd7562SDmitry Karpeev if (colindices) col = colindices[col]; 510753dd7562SDmitry Karpeev v = Baij->a[count]; 51089566063dSJacob Faibussowitsch PetscCall(MatSetValues(C, 1, &row, 1, &col, &v, INSERT_VALUES)); 510953dd7562SDmitry Karpeev ++count; 511053dd7562SDmitry Karpeev } 511153dd7562SDmitry Karpeev } 511253dd7562SDmitry Karpeev /* FIXME: set C's nonzerostate correctly. */ 511353dd7562SDmitry Karpeev /* Assembly for C is necessary. */ 511453dd7562SDmitry Karpeev C->preallocated = PETSC_TRUE; 511553dd7562SDmitry Karpeev C->assembled = PETSC_TRUE; 511653dd7562SDmitry Karpeev C->was_assembled = PETSC_FALSE; 511753dd7562SDmitry Karpeev PetscFunctionReturn(0); 511853dd7562SDmitry Karpeev } 511953dd7562SDmitry Karpeev 51204099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL; 51214099cc6bSBarry Smith 51224099cc6bSBarry Smith /*@C 512311a5261eSBarry Smith MatSeqAIJSetType - Converts a `MATSEQAIJ` matrix to a subtype 51244099cc6bSBarry Smith 512511a5261eSBarry Smith Collective on mat 51264099cc6bSBarry Smith 51274099cc6bSBarry Smith Input Parameters: 51284099cc6bSBarry Smith + mat - the matrix object 51294099cc6bSBarry Smith - matype - matrix type 51304099cc6bSBarry Smith 51314099cc6bSBarry Smith Options Database Key: 51324099cc6bSBarry Smith . -mat_seqai_type <method> - for example seqaijcrl 51334099cc6bSBarry Smith 51344099cc6bSBarry Smith Level: intermediate 51354099cc6bSBarry Smith 5136db781477SPatrick Sanan .seealso: `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat` 51374099cc6bSBarry Smith @*/ 51389371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetType(Mat mat, MatType matype) { 51394099cc6bSBarry Smith PetscBool sametype; 51405f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(Mat, MatType, MatReuse, Mat *); 51414099cc6bSBarry Smith 51424099cc6bSBarry Smith PetscFunctionBegin; 51434099cc6bSBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 51449566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, matype, &sametype)); 51454099cc6bSBarry Smith if (sametype) PetscFunctionReturn(0); 51464099cc6bSBarry Smith 51479566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(MatSeqAIJList, matype, &r)); 51485f80ce2aSJacob Faibussowitsch PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Mat type given: %s", matype); 51499566063dSJacob Faibussowitsch PetscCall((*r)(mat, matype, MAT_INPLACE_MATRIX, &mat)); 51504099cc6bSBarry Smith PetscFunctionReturn(0); 51514099cc6bSBarry Smith } 51524099cc6bSBarry Smith 51534099cc6bSBarry Smith /*@C 515411a5261eSBarry Smith MatSeqAIJRegister - - Adds a new sub-matrix type for sequential `MATSEQAIJ` matrices 51554099cc6bSBarry Smith 51564099cc6bSBarry Smith Not Collective 51574099cc6bSBarry Smith 51584099cc6bSBarry Smith Input Parameters: 515911a5261eSBarry Smith + name - name of a new user-defined matrix type, for example `MATSEQAIJCRL` 51604099cc6bSBarry Smith - function - routine to convert to subtype 51614099cc6bSBarry Smith 51624099cc6bSBarry Smith Notes: 516311a5261eSBarry Smith `MatSeqAIJRegister()` may be called multiple times to add several user-defined solvers. 51644099cc6bSBarry Smith 51654099cc6bSBarry Smith Then, your matrix can be chosen with the procedural interface at runtime via the option 51664099cc6bSBarry Smith $ -mat_seqaij_type my_mat 51674099cc6bSBarry Smith 51684099cc6bSBarry Smith Level: advanced 51694099cc6bSBarry Smith 5170db781477SPatrick Sanan .seealso: `MatSeqAIJRegisterAll()` 51714099cc6bSBarry Smith @*/ 51729371c9d4SSatish Balay PetscErrorCode MatSeqAIJRegister(const char sname[], PetscErrorCode (*function)(Mat, MatType, MatReuse, Mat *)) { 51734099cc6bSBarry Smith PetscFunctionBegin; 51749566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 51759566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&MatSeqAIJList, sname, function)); 51764099cc6bSBarry Smith PetscFunctionReturn(0); 51774099cc6bSBarry Smith } 51784099cc6bSBarry Smith 51794099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE; 51804099cc6bSBarry Smith 51814099cc6bSBarry Smith /*@C 518211a5261eSBarry Smith MatSeqAIJRegisterAll - Registers all of the matrix subtypes of `MATSSEQAIJ` 51834099cc6bSBarry Smith 51844099cc6bSBarry Smith Not Collective 51854099cc6bSBarry Smith 51864099cc6bSBarry Smith Level: advanced 51874099cc6bSBarry Smith 5188db781477SPatrick Sanan .seealso: `MatRegisterAll()`, `MatSeqAIJRegister()` 51894099cc6bSBarry Smith @*/ 51909371c9d4SSatish Balay PetscErrorCode MatSeqAIJRegisterAll(void) { 51914099cc6bSBarry Smith PetscFunctionBegin; 51924099cc6bSBarry Smith if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0); 51934099cc6bSBarry Smith MatSeqAIJRegisterAllCalled = PETSC_TRUE; 51944099cc6bSBarry Smith 51959566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCRL, MatConvert_SeqAIJ_SeqAIJCRL)); 51969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJPERM, MatConvert_SeqAIJ_SeqAIJPERM)); 51979566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJSELL, MatConvert_SeqAIJ_SeqAIJSELL)); 51989779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 51999566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJMKL, MatConvert_SeqAIJ_SeqAIJMKL)); 5200485f9817SRichard Tran Mills #endif 52015063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA) 52029566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 52035063d097SStefano Zampini #endif 52045063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 52059566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJKOKKOS, MatConvert_SeqAIJ_SeqAIJKokkos)); 52065063d097SStefano Zampini #endif 52074099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA) 52089566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL)); 52094099cc6bSBarry Smith #endif 52104099cc6bSBarry Smith PetscFunctionReturn(0); 52114099cc6bSBarry Smith } 521253dd7562SDmitry Karpeev 521353dd7562SDmitry Karpeev /* 521481824310SBarry Smith Special version for direct calls from Fortran 521581824310SBarry Smith */ 5216af0996ceSBarry Smith #include <petsc/private/fortranimpl.h> 521781824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS) 521881824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ 521981824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 522081824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij 522181824310SBarry Smith #endif 522281824310SBarry Smith 522381824310SBarry Smith /* Change these macros so can be used in void function */ 522498921bdaSJacob Faibussowitsch 522598921bdaSJacob Faibussowitsch /* Change these macros so can be used in void function */ 52269566063dSJacob Faibussowitsch /* Identical to PetscCallVoid, except it assigns to *_ierr */ 52279566063dSJacob Faibussowitsch #undef PetscCall 52289371c9d4SSatish Balay #define PetscCall(...) \ 52299371c9d4SSatish Balay do { \ 52305f80ce2aSJacob Faibussowitsch PetscErrorCode ierr_msv_mpiaij = __VA_ARGS__; \ 523198921bdaSJacob Faibussowitsch if (PetscUnlikely(ierr_msv_mpiaij)) { \ 523298921bdaSJacob Faibussowitsch *_ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr_msv_mpiaij, PETSC_ERROR_REPEAT, " "); \ 523398921bdaSJacob Faibussowitsch return; \ 523498921bdaSJacob Faibussowitsch } \ 523598921bdaSJacob Faibussowitsch } while (0) 523698921bdaSJacob Faibussowitsch 523798921bdaSJacob Faibussowitsch #undef SETERRQ 52389371c9d4SSatish Balay #define SETERRQ(comm, ierr, ...) \ 52399371c9d4SSatish Balay do { \ 524098921bdaSJacob Faibussowitsch *_ierr = PetscError(comm, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr, PETSC_ERROR_INITIAL, __VA_ARGS__); \ 524198921bdaSJacob Faibussowitsch return; \ 524298921bdaSJacob Faibussowitsch } while (0) 524381824310SBarry Smith 52449371c9d4SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA, PetscInt *mm, const PetscInt im[], PetscInt *nn, const PetscInt in[], const PetscScalar v[], InsertMode *isis, PetscErrorCode *_ierr) { 524581824310SBarry Smith Mat A = *AA; 524681824310SBarry Smith PetscInt m = *mm, n = *nn; 524781824310SBarry Smith InsertMode is = *isis; 524881824310SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 524981824310SBarry Smith PetscInt *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N; 525081824310SBarry Smith PetscInt *imax, *ai, *ailen; 525181824310SBarry Smith PetscInt *aj, nonew = a->nonew, lastcol = -1; 525254f21887SBarry Smith MatScalar *ap, value, *aa; 5253ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 5254ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 525581824310SBarry Smith 525681824310SBarry Smith PetscFunctionBegin; 52574994cf47SJed Brown MatCheckPreallocated(A, 1); 525881824310SBarry Smith imax = a->imax; 525981824310SBarry Smith ai = a->i; 526081824310SBarry Smith ailen = a->ilen; 526181824310SBarry Smith aj = a->j; 526281824310SBarry Smith aa = a->a; 526381824310SBarry Smith 526481824310SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 526581824310SBarry Smith row = im[k]; 526681824310SBarry Smith if (row < 0) continue; 52675f80ce2aSJacob Faibussowitsch PetscCheck(row < A->rmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Row too large"); 52689371c9d4SSatish Balay rp = aj + ai[row]; 52699371c9d4SSatish Balay ap = aa + ai[row]; 52709371c9d4SSatish Balay rmax = imax[row]; 52719371c9d4SSatish Balay nrow = ailen[row]; 527281824310SBarry Smith low = 0; 527381824310SBarry Smith high = nrow; 527481824310SBarry Smith for (l = 0; l < n; l++) { /* loop over added columns */ 527581824310SBarry Smith if (in[l] < 0) continue; 52765f80ce2aSJacob Faibussowitsch PetscCheck(in[l] < A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Column too large"); 527781824310SBarry Smith col = in[l]; 52782205254eSKarl Rupp if (roworiented) value = v[l + k * n]; 52792205254eSKarl Rupp else value = v[k + l * m]; 52802205254eSKarl Rupp 528181824310SBarry Smith if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 528281824310SBarry Smith 52832205254eSKarl Rupp if (col <= lastcol) low = 0; 52842205254eSKarl Rupp else high = nrow; 528581824310SBarry Smith lastcol = col; 528681824310SBarry Smith while (high - low > 5) { 528781824310SBarry Smith t = (low + high) / 2; 528881824310SBarry Smith if (rp[t] > col) high = t; 528981824310SBarry Smith else low = t; 529081824310SBarry Smith } 529181824310SBarry Smith for (i = low; i < high; i++) { 529281824310SBarry Smith if (rp[i] > col) break; 529381824310SBarry Smith if (rp[i] == col) { 529481824310SBarry Smith if (is == ADD_VALUES) ap[i] += value; 529581824310SBarry Smith else ap[i] = value; 529681824310SBarry Smith goto noinsert; 529781824310SBarry Smith } 529881824310SBarry Smith } 529981824310SBarry Smith if (value == 0.0 && ignorezeroentries) goto noinsert; 530081824310SBarry Smith if (nonew == 1) goto noinsert; 53015f80ce2aSJacob Faibussowitsch PetscCheck(nonew != -1, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero in the matrix"); 5302fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, A->rmap->n, 1, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 53039371c9d4SSatish Balay N = nrow++ - 1; 53049371c9d4SSatish Balay a->nz++; 53059371c9d4SSatish Balay high++; 530681824310SBarry Smith /* shift up all the later entries in this row */ 530781824310SBarry Smith for (ii = N; ii >= i; ii--) { 530881824310SBarry Smith rp[ii + 1] = rp[ii]; 530981824310SBarry Smith ap[ii + 1] = ap[ii]; 531081824310SBarry Smith } 531181824310SBarry Smith rp[i] = col; 531281824310SBarry Smith ap[i] = value; 5313e56f5c9eSBarry Smith A->nonzerostate++; 531481824310SBarry Smith noinsert:; 531581824310SBarry Smith low = i + 1; 531681824310SBarry Smith } 531781824310SBarry Smith ailen[row] = nrow; 531881824310SBarry Smith } 531981824310SBarry Smith PetscFunctionReturnVoid(); 532081824310SBarry Smith } 532198921bdaSJacob Faibussowitsch /* Undefining these here since they were redefined from their original definition above! No 532298921bdaSJacob Faibussowitsch * other PETSc functions should be defined past this point, as it is impossible to recover the 532398921bdaSJacob Faibussowitsch * original definitions */ 53249566063dSJacob Faibussowitsch #undef PetscCall 532598921bdaSJacob Faibussowitsch #undef SETERRQ 5326