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: 495*11a5261eSBarry 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. 502*11a5261eSBarry 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; 51519b08ed1SBarry Smith if (!a->imax) { 5169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &a->imax)); 5179566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A, A->rmap->n * sizeof(PetscInt))); 51819b08ed1SBarry Smith } 51919b08ed1SBarry Smith if (!a->ilen) { 5209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &a->ilen)); 5219566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A, A->rmap->n * sizeof(PetscInt))); 52219b08ed1SBarry Smith } else { 5239566063dSJacob Faibussowitsch PetscCall(PetscMemzero(a->ilen, A->rmap->n * sizeof(PetscInt))); 52419b08ed1SBarry Smith } 52519b08ed1SBarry Smith 52619b08ed1SBarry Smith /* allocate the matrix space */ 52719b08ed1SBarry Smith if (A->structure_only) { 5289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nztotal, &a->j)); 5299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n + 1, &a->i)); 5309566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A, (A->rmap->n + 1) * sizeof(PetscInt) + nztotal * sizeof(PetscInt))); 53119b08ed1SBarry Smith } else { 5329566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(nztotal, &a->a, nztotal, &a->j, A->rmap->n + 1, &a->i)); 5339566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A, (A->rmap->n + 1) * sizeof(PetscInt) + nztotal * (sizeof(PetscScalar) + sizeof(PetscInt)))); 53419b08ed1SBarry Smith } 53519b08ed1SBarry Smith a->i[0] = 0; 53619b08ed1SBarry Smith if (A->structure_only) { 53719b08ed1SBarry Smith a->singlemalloc = PETSC_FALSE; 53819b08ed1SBarry Smith a->free_a = PETSC_FALSE; 53919b08ed1SBarry Smith } else { 54019b08ed1SBarry Smith a->singlemalloc = PETSC_TRUE; 54119b08ed1SBarry Smith a->free_a = PETSC_TRUE; 54219b08ed1SBarry Smith } 54319b08ed1SBarry Smith a->free_ij = PETSC_TRUE; 54419b08ed1SBarry Smith A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation; 54519b08ed1SBarry Smith A->preallocated = PETSC_TRUE; 54619b08ed1SBarry Smith PetscFunctionReturn(0); 54719b08ed1SBarry Smith } 54819b08ed1SBarry Smith 5499371c9d4SSatish Balay PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) { 550071fcb05SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 551071fcb05SBarry Smith PetscInt *rp, k, row; 552071fcb05SBarry Smith PetscInt *ai = a->i, *ailen = a->ilen; 553071fcb05SBarry Smith PetscInt *aj = a->j; 554fff043a9SJunchao Zhang MatScalar *aa, *ap; 555071fcb05SBarry Smith 556071fcb05SBarry Smith PetscFunctionBegin; 5579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 558071fcb05SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 559071fcb05SBarry Smith row = im[k]; 5606bdcaf15SBarry 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); 561071fcb05SBarry Smith rp = aj + ai[row]; 562071fcb05SBarry Smith ap = aa + ai[row]; 56348a46eb9SPierre Jolivet if (!A->was_assembled) PetscCall(PetscMemcpy(rp, in, n * sizeof(PetscInt))); 564071fcb05SBarry Smith if (!A->structure_only) { 565071fcb05SBarry Smith if (v) { 5669566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(ap, v, n * sizeof(PetscScalar))); 567071fcb05SBarry Smith v += n; 568071fcb05SBarry Smith } else { 5699566063dSJacob Faibussowitsch PetscCall(PetscMemzero(ap, n * sizeof(PetscScalar))); 570071fcb05SBarry Smith } 571071fcb05SBarry Smith } 572071fcb05SBarry Smith ailen[row] = n; 573071fcb05SBarry Smith a->nz += n; 574071fcb05SBarry Smith } 5759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 576071fcb05SBarry Smith PetscFunctionReturn(0); 577071fcb05SBarry Smith } 578071fcb05SBarry Smith 5799371c9d4SSatish Balay PetscErrorCode MatGetValues_SeqAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[]) { 5807eb43aa7SLois Curfman McInnes Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 58197f1f81fSBarry Smith PetscInt *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j; 58297f1f81fSBarry Smith PetscInt *ai = a->i, *ailen = a->ilen; 583fff043a9SJunchao Zhang MatScalar *ap, *aa; 5847eb43aa7SLois Curfman McInnes 5853a40ed3dSBarry Smith PetscFunctionBegin; 5869566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 5877eb43aa7SLois Curfman McInnes for (k = 0; k < m; k++) { /* loop over rows */ 5887eb43aa7SLois Curfman McInnes row = im[k]; 5899371c9d4SSatish Balay if (row < 0) { 5909371c9d4SSatish Balay v += n; 5919371c9d4SSatish Balay continue; 5929371c9d4SSatish Balay } /* negative row */ 59354c59aa7SJacob 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); 5949371c9d4SSatish Balay rp = aj + ai[row]; 5959371c9d4SSatish Balay ap = aa + ai[row]; 5967eb43aa7SLois Curfman McInnes nrow = ailen[row]; 5977eb43aa7SLois Curfman McInnes for (l = 0; l < n; l++) { /* loop over columns */ 5989371c9d4SSatish Balay if (in[l] < 0) { 5999371c9d4SSatish Balay v++; 6009371c9d4SSatish Balay continue; 6019371c9d4SSatish Balay } /* negative column */ 60254c59aa7SJacob 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); 603bfeeae90SHong Zhang col = in[l]; 6049371c9d4SSatish Balay high = nrow; 6059371c9d4SSatish Balay low = 0; /* assume unsorted */ 6067eb43aa7SLois Curfman McInnes while (high - low > 5) { 6077eb43aa7SLois Curfman McInnes t = (low + high) / 2; 6087eb43aa7SLois Curfman McInnes if (rp[t] > col) high = t; 6097eb43aa7SLois Curfman McInnes else low = t; 6107eb43aa7SLois Curfman McInnes } 6117eb43aa7SLois Curfman McInnes for (i = low; i < high; i++) { 6127eb43aa7SLois Curfman McInnes if (rp[i] > col) break; 6137eb43aa7SLois Curfman McInnes if (rp[i] == col) { 614b49de8d1SLois Curfman McInnes *v++ = ap[i]; 6157eb43aa7SLois Curfman McInnes goto finished; 6167eb43aa7SLois Curfman McInnes } 6177eb43aa7SLois Curfman McInnes } 61897e567efSBarry Smith *v++ = 0.0; 6197eb43aa7SLois Curfman McInnes finished:; 6207eb43aa7SLois Curfman McInnes } 6217eb43aa7SLois Curfman McInnes } 6229566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 6233a40ed3dSBarry Smith PetscFunctionReturn(0); 6247eb43aa7SLois Curfman McInnes } 6257eb43aa7SLois Curfman McInnes 6269371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ_Binary(Mat mat, PetscViewer viewer) { 6273ea6fe3dSLisandro Dalcin Mat_SeqAIJ *A = (Mat_SeqAIJ *)mat->data; 628c898d852SStefano Zampini const PetscScalar *av; 6293ea6fe3dSLisandro Dalcin PetscInt header[4], M, N, m, nz, i; 6303ea6fe3dSLisandro Dalcin PetscInt *rowlens; 63117ab2063SBarry Smith 6323a40ed3dSBarry Smith PetscFunctionBegin; 6339566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 6342205254eSKarl Rupp 6353ea6fe3dSLisandro Dalcin M = mat->rmap->N; 6363ea6fe3dSLisandro Dalcin N = mat->cmap->N; 6373ea6fe3dSLisandro Dalcin m = mat->rmap->n; 6383ea6fe3dSLisandro Dalcin nz = A->nz; 639416022c9SBarry Smith 6403ea6fe3dSLisandro Dalcin /* write matrix header */ 6413ea6fe3dSLisandro Dalcin header[0] = MAT_FILE_CLASSID; 6429371c9d4SSatish Balay header[1] = M; 6439371c9d4SSatish Balay header[2] = N; 6449371c9d4SSatish Balay header[3] = nz; 6459566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT)); 646416022c9SBarry Smith 6473ea6fe3dSLisandro Dalcin /* fill in and store row lengths */ 6489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &rowlens)); 6493ea6fe3dSLisandro Dalcin for (i = 0; i < m; i++) rowlens[i] = A->i[i + 1] - A->i[i]; 6509566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, rowlens, m, PETSC_INT)); 6519566063dSJacob Faibussowitsch PetscCall(PetscFree(rowlens)); 6523ea6fe3dSLisandro Dalcin /* store column indices */ 6539566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, A->j, nz, PETSC_INT)); 654416022c9SBarry Smith /* store nonzero values */ 6559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(mat, &av)); 6569566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, av, nz, PETSC_SCALAR)); 6579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(mat, &av)); 658b37d52dbSMark F. Adams 6593ea6fe3dSLisandro Dalcin /* write block size option to the viewer's .info file */ 6609566063dSJacob Faibussowitsch PetscCall(MatView_Binary_BlockSizes(mat, viewer)); 6613a40ed3dSBarry Smith PetscFunctionReturn(0); 66217ab2063SBarry Smith } 663416022c9SBarry Smith 6649371c9d4SSatish Balay static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A, PetscViewer viewer) { 6657dc0baabSHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 6667dc0baabSHong Zhang PetscInt i, k, m = A->rmap->N; 6677dc0baabSHong Zhang 6687dc0baabSHong Zhang PetscFunctionBegin; 6699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 6707dc0baabSHong Zhang for (i = 0; i < m; i++) { 6719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 67248a46eb9SPierre Jolivet for (k = a->i[i]; k < a->i[i + 1]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ") ", a->j[k])); 6739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 6747dc0baabSHong Zhang } 6759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 6767dc0baabSHong Zhang PetscFunctionReturn(0); 6777dc0baabSHong Zhang } 6787dc0baabSHong Zhang 67909573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat, PetscViewer); 680cd155464SBarry Smith 6819371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ_ASCII(Mat A, PetscViewer viewer) { 682416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 683c898d852SStefano Zampini const PetscScalar *av; 68460e0710aSBarry Smith PetscInt i, j, m = A->rmap->n; 685e060cb09SBarry Smith const char *name; 686f3ef73ceSBarry Smith PetscViewerFormat format; 68717ab2063SBarry Smith 6883a40ed3dSBarry Smith PetscFunctionBegin; 6897dc0baabSHong Zhang if (A->structure_only) { 6909566063dSJacob Faibussowitsch PetscCall(MatView_SeqAIJ_ASCII_structonly(A, viewer)); 6917dc0baabSHong Zhang PetscFunctionReturn(0); 6927dc0baabSHong Zhang } 69343e49210SHong Zhang 6949566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 6952e5835c6SStefano Zampini if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0); 6962e5835c6SStefano Zampini 697c898d852SStefano Zampini /* trigger copy to CPU if needed */ 6989566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 6999566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 70071c2f376SKris Buschelman if (format == PETSC_VIEWER_ASCII_MATLAB) { 70197f1f81fSBarry Smith PetscInt nofinalvalue = 0; 70260e0710aSBarry Smith if (m && ((a->i[m] == a->i[m - 1]) || (a->j[a->nz - 1] != A->cmap->n - 1))) { 703c337ccceSJed Brown /* Need a dummy value to ensure the dimension of the matrix. */ 704d00d2cf4SBarry Smith nofinalvalue = 1; 705d00d2cf4SBarry Smith } 7069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 7079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", m, A->cmap->n)); 7089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Nonzeros = %" PetscInt_FMT " \n", a->nz)); 709fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX) 7109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = zeros(%" PetscInt_FMT ",4);\n", a->nz + nofinalvalue)); 711fbfe6fa7SJed Brown #else 7129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = zeros(%" PetscInt_FMT ",3);\n", a->nz + nofinalvalue)); 713fbfe6fa7SJed Brown #endif 7149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = [\n")); 71517ab2063SBarry Smith 71617ab2063SBarry Smith for (i = 0; i < m; i++) { 71760e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 718aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 7199566063dSJacob 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]))); 72017ab2063SBarry Smith #else 7219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %18.16e\n", i + 1, a->j[j] + 1, (double)a->a[j])); 72217ab2063SBarry Smith #endif 72317ab2063SBarry Smith } 72417ab2063SBarry Smith } 725d00d2cf4SBarry Smith if (nofinalvalue) { 726c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX) 7279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %18.16e %18.16e\n", m, A->cmap->n, 0., 0.)); 728c337ccceSJed Brown #else 7299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %18.16e\n", m, A->cmap->n, 0.0)); 730c337ccceSJed Brown #endif 731d00d2cf4SBarry Smith } 7329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)A, &name)); 7339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "];\n %s = spconvert(zzz);\n", name)); 7349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 735fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_COMMON) { 7369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 73744cd7ae7SLois Curfman McInnes for (i = 0; i < m; i++) { 7389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 73960e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 740aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 74136db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) { 7429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 74336db0b34SBarry Smith } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) { 7449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)-PetscImaginaryPart(a->a[j]))); 74536db0b34SBarry Smith } else if (PetscRealPart(a->a[j]) != 0.0) { 7469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 7476831982aSBarry Smith } 74844cd7ae7SLois Curfman McInnes #else 7499566063dSJacob Faibussowitsch if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 75044cd7ae7SLois Curfman McInnes #endif 75144cd7ae7SLois Curfman McInnes } 7529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 75344cd7ae7SLois Curfman McInnes } 7549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 755fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_SYMMODU) { 75697f1f81fSBarry Smith PetscInt nzd = 0, fshift = 1, *sptr; 7579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 7589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &sptr)); 759496be53dSLois Curfman McInnes for (i = 0; i < m; i++) { 760496be53dSLois Curfman McInnes sptr[i] = nzd + 1; 76160e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 762496be53dSLois Curfman McInnes if (a->j[j] >= i) { 763aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 76436db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++; 765496be53dSLois Curfman McInnes #else 766496be53dSLois Curfman McInnes if (a->a[j] != 0.0) nzd++; 767496be53dSLois Curfman McInnes #endif 768496be53dSLois Curfman McInnes } 769496be53dSLois Curfman McInnes } 770496be53dSLois Curfman McInnes } 7712e44a96cSLois Curfman McInnes sptr[m] = nzd + 1; 7729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT "\n\n", m, nzd)); 7732e44a96cSLois Curfman McInnes for (i = 0; i < m + 1; i += 6) { 7742205254eSKarl Rupp if (i + 4 < m) { 7759566063dSJacob 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])); 7762205254eSKarl Rupp } else if (i + 3 < m) { 7779566063dSJacob 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])); 7782205254eSKarl Rupp } else if (i + 2 < m) { 7799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2], sptr[i + 3])); 7802205254eSKarl Rupp } else if (i + 1 < m) { 7819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2])); 7822205254eSKarl Rupp } else if (i < m) { 7839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1])); 7842205254eSKarl Rupp } else { 7859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "\n", sptr[i])); 7862205254eSKarl Rupp } 787496be53dSLois Curfman McInnes } 7889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 7899566063dSJacob Faibussowitsch PetscCall(PetscFree(sptr)); 790496be53dSLois Curfman McInnes for (i = 0; i < m; i++) { 79160e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 7929566063dSJacob Faibussowitsch if (a->j[j] >= i) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " ", a->j[j] + fshift)); 793496be53dSLois Curfman McInnes } 7949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 795496be53dSLois Curfman McInnes } 7969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 797496be53dSLois Curfman McInnes for (i = 0; i < m; i++) { 79860e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 799496be53dSLois Curfman McInnes if (a->j[j] >= i) { 800aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 80148a46eb9SPierre 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]))); 802496be53dSLois Curfman McInnes #else 8039566063dSJacob Faibussowitsch if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " %18.16e ", (double)a->a[j])); 804496be53dSLois Curfman McInnes #endif 805496be53dSLois Curfman McInnes } 806496be53dSLois Curfman McInnes } 8079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 808496be53dSLois Curfman McInnes } 8099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 810fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_DENSE) { 81197f1f81fSBarry Smith PetscInt cnt = 0, jcnt; 81287828ca2SBarry Smith PetscScalar value; 81368f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX) 81468f1ed48SBarry Smith PetscBool realonly = PETSC_TRUE; 81568f1ed48SBarry Smith 81668f1ed48SBarry Smith for (i = 0; i < a->i[m]; i++) { 81768f1ed48SBarry Smith if (PetscImaginaryPart(a->a[i]) != 0.0) { 81868f1ed48SBarry Smith realonly = PETSC_FALSE; 81968f1ed48SBarry Smith break; 82068f1ed48SBarry Smith } 82168f1ed48SBarry Smith } 82268f1ed48SBarry Smith #endif 82302594712SBarry Smith 8249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 82502594712SBarry Smith for (i = 0; i < m; i++) { 82602594712SBarry Smith jcnt = 0; 827d0f46423SBarry Smith for (j = 0; j < A->cmap->n; j++) { 828e24b481bSBarry Smith if (jcnt < a->i[i + 1] - a->i[i] && j == a->j[cnt]) { 82902594712SBarry Smith value = a->a[cnt++]; 830e24b481bSBarry Smith jcnt++; 83102594712SBarry Smith } else { 83202594712SBarry Smith value = 0.0; 83302594712SBarry Smith } 834aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 83568f1ed48SBarry Smith if (realonly) { 8369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e ", (double)PetscRealPart(value))); 83768f1ed48SBarry Smith } else { 8389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e+%7.5e i ", (double)PetscRealPart(value), (double)PetscImaginaryPart(value))); 83968f1ed48SBarry Smith } 84002594712SBarry Smith #else 8419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e ", (double)value)); 84202594712SBarry Smith #endif 84302594712SBarry Smith } 8449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 84502594712SBarry Smith } 8469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 8473c215bfdSMatthew Knepley } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) { 848150b93efSMatthew G. Knepley PetscInt fshift = 1; 8499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 8503c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX) 8519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%%%%MatrixMarket matrix coordinate complex general\n")); 8523c215bfdSMatthew Knepley #else 8539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%%%%MatrixMarket matrix coordinate real general\n")); 8543c215bfdSMatthew Knepley #endif 8559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", m, A->cmap->n, a->nz)); 8563c215bfdSMatthew Knepley for (i = 0; i < m; i++) { 85760e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 8583c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX) 8599566063dSJacob 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]))); 8603c215bfdSMatthew Knepley #else 8619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %g\n", i + fshift, a->j[j] + fshift, (double)a->a[j])); 8623c215bfdSMatthew Knepley #endif 8633c215bfdSMatthew Knepley } 8643c215bfdSMatthew Knepley } 8659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 8663a40ed3dSBarry Smith } else { 8679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 868d5f3da31SBarry Smith if (A->factortype) { 86916cd7e1dSShri Abhyankar for (i = 0; i < m; i++) { 8709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 87116cd7e1dSShri Abhyankar /* L part */ 87260e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 87316cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 87416cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 8759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 87616cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 8779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)(-PetscImaginaryPart(a->a[j])))); 87816cd7e1dSShri Abhyankar } else { 8799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 88016cd7e1dSShri Abhyankar } 88116cd7e1dSShri Abhyankar #else 8829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 88316cd7e1dSShri Abhyankar #endif 88416cd7e1dSShri Abhyankar } 88516cd7e1dSShri Abhyankar /* diagonal */ 88616cd7e1dSShri Abhyankar j = a->diag[i]; 88716cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 88816cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 8899566063dSJacob 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]))); 89016cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 8919566063dSJacob 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])))); 89216cd7e1dSShri Abhyankar } else { 8939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(1.0 / a->a[j]))); 89416cd7e1dSShri Abhyankar } 89516cd7e1dSShri Abhyankar #else 8969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)(1.0 / a->a[j]))); 89716cd7e1dSShri Abhyankar #endif 89816cd7e1dSShri Abhyankar 89916cd7e1dSShri Abhyankar /* U part */ 90060e0710aSBarry Smith for (j = a->diag[i + 1] + 1; j < a->diag[i]; j++) { 90116cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 90216cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 9039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 90416cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 9059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)(-PetscImaginaryPart(a->a[j])))); 90616cd7e1dSShri Abhyankar } else { 9079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 90816cd7e1dSShri Abhyankar } 90916cd7e1dSShri Abhyankar #else 9109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 91116cd7e1dSShri Abhyankar #endif 91216cd7e1dSShri Abhyankar } 9139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 91416cd7e1dSShri Abhyankar } 91516cd7e1dSShri Abhyankar } else { 91617ab2063SBarry Smith for (i = 0; i < m; i++) { 9179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i)); 91860e0710aSBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 919aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 92036db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) > 0.0) { 9219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j]))); 92236db0b34SBarry Smith } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 9239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)-PetscImaginaryPart(a->a[j]))); 9243a40ed3dSBarry Smith } else { 9259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j]))); 92617ab2063SBarry Smith } 92717ab2063SBarry Smith #else 9289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j])); 92917ab2063SBarry Smith #endif 93017ab2063SBarry Smith } 9319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 93217ab2063SBarry Smith } 93316cd7e1dSShri Abhyankar } 9349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 93517ab2063SBarry Smith } 9369566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 9373a40ed3dSBarry Smith PetscFunctionReturn(0); 938416022c9SBarry Smith } 939416022c9SBarry Smith 9409804daf3SBarry Smith #include <petscdraw.h> 9419371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw, void *Aa) { 942480ef9eaSBarry Smith Mat A = (Mat)Aa; 943416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 944383922c3SLisandro Dalcin PetscInt i, j, m = A->rmap->n; 945383922c3SLisandro Dalcin int color; 946b05fc000SLisandro Dalcin PetscReal xl, yl, xr, yr, x_l, x_r, y_l, y_r; 947b0a32e0cSBarry Smith PetscViewer viewer; 948f3ef73ceSBarry Smith PetscViewerFormat format; 949fff043a9SJunchao Zhang const PetscScalar *aa; 950cddf8d76SBarry Smith 9513a40ed3dSBarry Smith PetscFunctionBegin; 9529566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer)); 9539566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 9549566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr)); 955383922c3SLisandro Dalcin 956416022c9SBarry Smith /* loop over matrix elements drawing boxes */ 9579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 958fb9695e5SSatish Balay if (format != PETSC_VIEWER_DRAW_CONTOUR) { 959d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 9600513a670SBarry Smith /* Blue for negative, Cyan for zero and Red for positive */ 961b0a32e0cSBarry Smith color = PETSC_DRAW_BLUE; 962416022c9SBarry Smith for (i = 0; i < m; i++) { 9639371c9d4SSatish Balay y_l = m - i - 1.0; 9649371c9d4SSatish Balay y_r = y_l + 1.0; 965bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 9669371c9d4SSatish Balay x_l = a->j[j]; 9679371c9d4SSatish Balay x_r = x_l + 1.0; 968fff043a9SJunchao Zhang if (PetscRealPart(aa[j]) >= 0.) continue; 9699566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 970cddf8d76SBarry Smith } 971cddf8d76SBarry Smith } 972b0a32e0cSBarry Smith color = PETSC_DRAW_CYAN; 973cddf8d76SBarry Smith for (i = 0; i < m; i++) { 9749371c9d4SSatish Balay y_l = m - i - 1.0; 9759371c9d4SSatish Balay y_r = y_l + 1.0; 976bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 9779371c9d4SSatish Balay x_l = a->j[j]; 9789371c9d4SSatish Balay x_r = x_l + 1.0; 979fff043a9SJunchao Zhang if (aa[j] != 0.) continue; 9809566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 981cddf8d76SBarry Smith } 982cddf8d76SBarry Smith } 983b0a32e0cSBarry Smith color = PETSC_DRAW_RED; 984cddf8d76SBarry Smith for (i = 0; i < m; i++) { 9859371c9d4SSatish Balay y_l = m - i - 1.0; 9869371c9d4SSatish Balay y_r = y_l + 1.0; 987bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 9889371c9d4SSatish Balay x_l = a->j[j]; 9899371c9d4SSatish Balay x_r = x_l + 1.0; 990fff043a9SJunchao Zhang if (PetscRealPart(aa[j]) <= 0.) continue; 9919566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 992416022c9SBarry Smith } 993416022c9SBarry Smith } 994d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 9950513a670SBarry Smith } else { 9960513a670SBarry Smith /* use contour shading to indicate magnitude of values */ 9970513a670SBarry Smith /* first determine max of all nonzero values */ 998b05fc000SLisandro Dalcin PetscReal minv = 0.0, maxv = 0.0; 999383922c3SLisandro Dalcin PetscInt nz = a->nz, count = 0; 1000b0a32e0cSBarry Smith PetscDraw popup; 10010513a670SBarry Smith 10020513a670SBarry Smith for (i = 0; i < nz; i++) { 1003fff043a9SJunchao Zhang if (PetscAbsScalar(aa[i]) > maxv) maxv = PetscAbsScalar(aa[i]); 10040513a670SBarry Smith } 1005383922c3SLisandro Dalcin if (minv >= maxv) maxv = minv + PETSC_SMALL; 10069566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 10079566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, minv, maxv)); 1008383922c3SLisandro Dalcin 1009d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 10100513a670SBarry Smith for (i = 0; i < m; i++) { 1011383922c3SLisandro Dalcin y_l = m - i - 1.0; 1012383922c3SLisandro Dalcin y_r = y_l + 1.0; 1013bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 1014383922c3SLisandro Dalcin x_l = a->j[j]; 1015383922c3SLisandro Dalcin x_r = x_l + 1.0; 1016fff043a9SJunchao Zhang color = PetscDrawRealToColor(PetscAbsScalar(aa[count]), minv, maxv); 10179566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color)); 10180513a670SBarry Smith count++; 10190513a670SBarry Smith } 10200513a670SBarry Smith } 1021d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 10220513a670SBarry Smith } 10239566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 1024480ef9eaSBarry Smith PetscFunctionReturn(0); 1025480ef9eaSBarry Smith } 1026cddf8d76SBarry Smith 10279804daf3SBarry Smith #include <petscdraw.h> 10289371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ_Draw(Mat A, PetscViewer viewer) { 1029b0a32e0cSBarry Smith PetscDraw draw; 103036db0b34SBarry Smith PetscReal xr, yr, xl, yl, h, w; 1031ace3abfcSBarry Smith PetscBool isnull; 1032480ef9eaSBarry Smith 1033480ef9eaSBarry Smith PetscFunctionBegin; 10349566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 10359566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 1036480ef9eaSBarry Smith if (isnull) PetscFunctionReturn(0); 1037480ef9eaSBarry Smith 10389371c9d4SSatish Balay xr = A->cmap->n; 10399371c9d4SSatish Balay yr = A->rmap->n; 10409371c9d4SSatish Balay h = yr / 10.0; 10419371c9d4SSatish Balay w = xr / 10.0; 10429371c9d4SSatish Balay xr += w; 10439371c9d4SSatish Balay yr += h; 10449371c9d4SSatish Balay xl = -w; 10459371c9d4SSatish Balay yl = -h; 10469566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr)); 10479566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer)); 10489566063dSJacob Faibussowitsch PetscCall(PetscDrawZoom(draw, MatView_SeqAIJ_Draw_Zoom, A)); 10499566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL)); 10509566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 10513a40ed3dSBarry Smith PetscFunctionReturn(0); 1052416022c9SBarry Smith } 1053416022c9SBarry Smith 10549371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ(Mat A, PetscViewer viewer) { 1055ace3abfcSBarry Smith PetscBool iascii, isbinary, isdraw; 1056416022c9SBarry Smith 10573a40ed3dSBarry Smith PetscFunctionBegin; 10589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 10599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 10609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 10611baa6e33SBarry Smith if (iascii) PetscCall(MatView_SeqAIJ_ASCII(A, viewer)); 10621baa6e33SBarry Smith else if (isbinary) PetscCall(MatView_SeqAIJ_Binary(A, viewer)); 10631baa6e33SBarry Smith else if (isdraw) PetscCall(MatView_SeqAIJ_Draw(A, viewer)); 10649566063dSJacob Faibussowitsch PetscCall(MatView_SeqAIJ_Inode(A, viewer)); 10653a40ed3dSBarry Smith PetscFunctionReturn(0); 106617ab2063SBarry Smith } 106719bcc07fSBarry Smith 10689371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A, MatAssemblyType mode) { 1069416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1070580bdb30SBarry Smith PetscInt fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax; 1071d0f46423SBarry Smith PetscInt m = A->rmap->n, *ip, N, *ailen = a->ilen, rmax = 0; 107254f21887SBarry Smith MatScalar *aa = a->a, *ap; 10733447b6efSHong Zhang PetscReal ratio = 0.6; 107417ab2063SBarry Smith 10753a40ed3dSBarry Smith PetscFunctionBegin; 10763a40ed3dSBarry Smith if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 10779566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 1078b215bc84SStefano Zampini if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) { 1079b215bc84SStefano Zampini /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */ 10809566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A, mode)); 1081b215bc84SStefano Zampini PetscFunctionReturn(0); 1082b215bc84SStefano Zampini } 108317ab2063SBarry Smith 108443ee02c3SBarry Smith if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 108517ab2063SBarry Smith for (i = 1; i < m; i++) { 1086416022c9SBarry Smith /* move each row back by the amount of empty slots (fshift) before it*/ 108717ab2063SBarry Smith fshift += imax[i - 1] - ailen[i - 1]; 108894a9d846SBarry Smith rmax = PetscMax(rmax, ailen[i]); 108917ab2063SBarry Smith if (fshift) { 1090bfeeae90SHong Zhang ip = aj + ai[i]; 1091bfeeae90SHong Zhang ap = aa + ai[i]; 109217ab2063SBarry Smith N = ailen[i]; 10939566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ip - fshift, ip, N)); 109448a46eb9SPierre Jolivet if (!A->structure_only) PetscCall(PetscArraymove(ap - fshift, ap, N)); 109517ab2063SBarry Smith } 109617ab2063SBarry Smith ai[i] = ai[i - 1] + ailen[i - 1]; 109717ab2063SBarry Smith } 109817ab2063SBarry Smith if (m) { 109917ab2063SBarry Smith fshift += imax[m - 1] - ailen[m - 1]; 110017ab2063SBarry Smith ai[m] = ai[m - 1] + ailen[m - 1]; 110117ab2063SBarry Smith } 11027b083b7cSBarry Smith 110317ab2063SBarry Smith /* reset ilen and imax for each row */ 11047b083b7cSBarry Smith a->nonzerorowcnt = 0; 1105396832f4SHong Zhang if (A->structure_only) { 11069566063dSJacob Faibussowitsch PetscCall(PetscFree(a->imax)); 11079566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ilen)); 1108396832f4SHong Zhang } else { /* !A->structure_only */ 110917ab2063SBarry Smith for (i = 0; i < m; i++) { 111017ab2063SBarry Smith ailen[i] = imax[i] = ai[i + 1] - ai[i]; 11117b083b7cSBarry Smith a->nonzerorowcnt += ((ai[i + 1] - ai[i]) > 0); 111217ab2063SBarry Smith } 1113396832f4SHong Zhang } 1114bfeeae90SHong Zhang a->nz = ai[m]; 1115aed4548fSBarry 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); 111617ab2063SBarry Smith 11179566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 11189566063dSJacob 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)); 11199566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues() is %" PetscInt_FMT "\n", a->reallocs)); 11209566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Maximum nonzeros in any row is %" PetscInt_FMT "\n", rmax)); 11212205254eSKarl Rupp 11228e58a170SBarry Smith A->info.mallocs += a->reallocs; 1123dd5f02e7SSatish Balay a->reallocs = 0; 11246712e2f1SBarry Smith A->info.nz_unneeded = (PetscReal)fshift; 112536db0b34SBarry Smith a->rmax = rmax; 11264e220ebcSLois Curfman McInnes 112748a46eb9SPierre Jolivet if (!A->structure_only) PetscCall(MatCheckCompressedRow(A, a->nonzerorowcnt, &a->compressedrow, a->i, m, ratio)); 11289566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A, mode)); 11293a40ed3dSBarry Smith PetscFunctionReturn(0); 113017ab2063SBarry Smith } 113117ab2063SBarry Smith 11329371c9d4SSatish Balay PetscErrorCode MatRealPart_SeqAIJ(Mat A) { 113399cafbc1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 113499cafbc1SBarry Smith PetscInt i, nz = a->nz; 11352e5835c6SStefano Zampini MatScalar *aa; 113699cafbc1SBarry Smith 113799cafbc1SBarry Smith PetscFunctionBegin; 11389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 113999cafbc1SBarry Smith for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]); 11409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 11419566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 114299cafbc1SBarry Smith PetscFunctionReturn(0); 114399cafbc1SBarry Smith } 114499cafbc1SBarry Smith 11459371c9d4SSatish Balay PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A) { 114699cafbc1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 114799cafbc1SBarry Smith PetscInt i, nz = a->nz; 11482e5835c6SStefano Zampini MatScalar *aa; 114999cafbc1SBarry Smith 115099cafbc1SBarry Smith PetscFunctionBegin; 11519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 115299cafbc1SBarry Smith for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]); 11539566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 11549566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 115599cafbc1SBarry Smith PetscFunctionReturn(0); 115699cafbc1SBarry Smith } 115799cafbc1SBarry Smith 11589371c9d4SSatish Balay PetscErrorCode MatZeroEntries_SeqAIJ(Mat A) { 1159fff043a9SJunchao Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1160fff043a9SJunchao Zhang MatScalar *aa; 11613a40ed3dSBarry Smith 11623a40ed3dSBarry Smith PetscFunctionBegin; 11639566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayWrite(A, &aa)); 11649566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(aa, a->i[A->rmap->n])); 11659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayWrite(A, &aa)); 11669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 11673a40ed3dSBarry Smith PetscFunctionReturn(0); 116817ab2063SBarry Smith } 1169416022c9SBarry Smith 11709371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatResetPreallocationCOO_SeqAIJ(Mat A) { 1171cbc6b225SStefano Zampini Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1172cbc6b225SStefano Zampini 1173cbc6b225SStefano Zampini PetscFunctionBegin; 11749566063dSJacob Faibussowitsch PetscCall(PetscFree(a->perm)); 11759566063dSJacob Faibussowitsch PetscCall(PetscFree(a->jmap)); 1176cbc6b225SStefano Zampini PetscFunctionReturn(0); 1177cbc6b225SStefano Zampini } 1178cbc6b225SStefano Zampini 11799371c9d4SSatish Balay PetscErrorCode MatDestroy_SeqAIJ(Mat A) { 1180416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1181d5d45c9bSBarry Smith 11823a40ed3dSBarry Smith PetscFunctionBegin; 1183aa482453SBarry Smith #if defined(PETSC_USE_LOG) 1184c0aa6a63SJacob Faibussowitsch PetscLogObjectState((PetscObject)A, "Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT, A->rmap->n, A->cmap->n, a->nz); 118517ab2063SBarry Smith #endif 11869566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(A, &a->a, &a->j, &a->i)); 11879566063dSJacob Faibussowitsch PetscCall(MatResetPreallocationCOO_SeqAIJ(A)); 11889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 11899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 11909566063dSJacob Faibussowitsch PetscCall(PetscFree(a->diag)); 11919566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ibdiag)); 11929566063dSJacob Faibussowitsch PetscCall(PetscFree(a->imax)); 11939566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ilen)); 11949566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ipre)); 11959566063dSJacob Faibussowitsch PetscCall(PetscFree3(a->idiag, a->mdiag, a->ssor_work)); 11969566063dSJacob Faibussowitsch PetscCall(PetscFree(a->solve_work)); 11979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 11989566063dSJacob Faibussowitsch PetscCall(PetscFree(a->saved_values)); 11999566063dSJacob Faibussowitsch PetscCall(PetscFree2(a->compressedrow.i, a->compressedrow.rindex)); 12009566063dSJacob Faibussowitsch PetscCall(MatDestroy_SeqAIJ_Inode(A)); 12019566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 1202901853e0SKris Buschelman 12036718818eSStefano Zampini /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this. 12046718818eSStefano Zampini That function is so heavily used (sometimes in an hidden way through multnumeric function pointers) 12056718818eSStefano Zampini that is hard to properly add this data to the MatProduct data. We free it here to avoid 12066718818eSStefano Zampini users reusing the matrix object with different data to incur in obscure segmentation faults 12076718818eSStefano Zampini due to different matrix sizes */ 12089566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc__ab_dense", NULL)); 12096718818eSStefano Zampini 12109566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL)); 12112e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "PetscMatlabEnginePut_C", NULL)); 12122e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "PetscMatlabEngineGet_C", NULL)); 12139566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetColumnIndices_C", NULL)); 12149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatStoreValues_C", NULL)); 12159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatRetrieveValues_C", NULL)); 12169566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqsbaij_C", NULL)); 12179566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqbaij_C", NULL)); 12189566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijperm_C", NULL)); 12192e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijsell_C", NULL)); 12202e956fe4SStefano Zampini #if defined(PETSC_HAVE_MKL_SPARSE) 12212e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijmkl_C", NULL)); 12222e956fe4SStefano Zampini #endif 12234222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA) 12249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijcusparse_C", NULL)); 12259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_seqaij_C", NULL)); 12269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaijcusparse_C", NULL)); 12274222ddf1SHong Zhang #endif 12283d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 12299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijkokkos_C", NULL)); 12303d0639e7SStefano Zampini #endif 12319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijcrl_C", NULL)); 1232af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 12339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_elemental_C", NULL)); 1234af8000cdSHong Zhang #endif 1235d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 12369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_scalapack_C", NULL)); 1237d24d4204SJose E. Roman #endif 123863c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 12399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_hypre_C", NULL)); 12409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_transpose_seqaij_seqaij_C", NULL)); 124163c07aadSStefano Zampini #endif 12429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqdense_C", NULL)); 12439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqsell_C", NULL)); 12449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_is_C", NULL)); 12459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatIsTranspose_C", NULL)); 12462e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatIsHermitianTranspose_C", NULL)); 12479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", NULL)); 12489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatResetPreallocation_C", NULL)); 12499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetPreallocationCSR_C", NULL)); 12509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatReorderForNonzeroDiagonal_C", NULL)); 12519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_is_seqaij_C", NULL)); 12529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqdense_seqaij_C", NULL)); 12539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaij_C", NULL)); 12549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJKron_C", NULL)); 12559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 12569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 12572e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL)); 12582e956fe4SStefano Zampini /* these calls do not belong here: the subclasses Duplicate/Destroy are wrong */ 12592e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaijsell_seqaij_C", NULL)); 12602e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaijperm_seqaij_C", NULL)); 12612e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijviennacl_C", NULL)); 12622e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijviennacl_seqdense_C", NULL)); 12632e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijviennacl_seqaij_C", NULL)); 12643a40ed3dSBarry Smith PetscFunctionReturn(0); 126517ab2063SBarry Smith } 126617ab2063SBarry Smith 12679371c9d4SSatish Balay PetscErrorCode MatSetOption_SeqAIJ(Mat A, MatOption op, PetscBool flg) { 1268416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 12693a40ed3dSBarry Smith 12703a40ed3dSBarry Smith PetscFunctionBegin; 1271a65d3064SKris Buschelman switch (op) { 12729371c9d4SSatish Balay case MAT_ROW_ORIENTED: a->roworiented = flg; break; 12739371c9d4SSatish Balay case MAT_KEEP_NONZERO_PATTERN: a->keepnonzeropattern = flg; break; 12749371c9d4SSatish Balay case MAT_NEW_NONZERO_LOCATIONS: a->nonew = (flg ? 0 : 1); break; 12759371c9d4SSatish Balay case MAT_NEW_NONZERO_LOCATION_ERR: a->nonew = (flg ? -1 : 0); break; 12769371c9d4SSatish Balay case MAT_NEW_NONZERO_ALLOCATION_ERR: a->nonew = (flg ? -2 : 0); break; 12779371c9d4SSatish Balay case MAT_UNUSED_NONZERO_LOCATION_ERR: a->nounused = (flg ? -1 : 0); break; 12789371c9d4SSatish Balay case MAT_IGNORE_ZERO_ENTRIES: a->ignorezeroentries = flg; break; 12793d472b54SHong Zhang case MAT_SPD: 1280b1646e73SJed Brown case MAT_SYMMETRIC: 1281b1646e73SJed Brown case MAT_STRUCTURALLY_SYMMETRIC: 1282b1646e73SJed Brown case MAT_HERMITIAN: 1283b1646e73SJed Brown case MAT_SYMMETRY_ETERNAL: 1284957cac9fSHong Zhang case MAT_STRUCTURE_ONLY: 1285b94d7dedSBarry Smith case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 1286b94d7dedSBarry Smith case MAT_SPD_ETERNAL: 1287b94d7dedSBarry Smith /* if the diagonal matrix is square it inherits some of the properties above */ 12885021d80fSJed Brown break; 12898c78258cSHong Zhang case MAT_FORCE_DIAGONAL_ENTRIES: 1290a65d3064SKris Buschelman case MAT_IGNORE_OFF_PROC_ENTRIES: 12919371c9d4SSatish Balay case MAT_USE_HASH_TABLE: PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op])); break; 12929371c9d4SSatish Balay case MAT_USE_INODES: PetscCall(MatSetOption_SeqAIJ_Inode(A, MAT_USE_INODES, flg)); break; 12939371c9d4SSatish Balay case MAT_SUBMAT_SINGLEIS: A->submat_singleis = flg; break; 1294071fcb05SBarry Smith case MAT_SORTED_FULL: 1295071fcb05SBarry Smith if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 1296071fcb05SBarry Smith else A->ops->setvalues = MatSetValues_SeqAIJ; 1297071fcb05SBarry Smith break; 12989371c9d4SSatish Balay case MAT_FORM_EXPLICIT_TRANSPOSE: A->form_explicit_transpose = flg; break; 12999371c9d4SSatish Balay default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %d", op); 1300a65d3064SKris Buschelman } 13013a40ed3dSBarry Smith PetscFunctionReturn(0); 130217ab2063SBarry Smith } 130317ab2063SBarry Smith 13049371c9d4SSatish Balay PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A, Vec v) { 1305416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1306fdc842d1SBarry Smith PetscInt i, j, n, *ai = a->i, *aj = a->j; 1307c898d852SStefano Zampini PetscScalar *x; 1308c898d852SStefano Zampini const PetscScalar *aa; 130917ab2063SBarry Smith 13103a40ed3dSBarry Smith PetscFunctionBegin; 13119566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 131208401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 13139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 1314d5f3da31SBarry Smith if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) { 1315d3e70bfaSHong Zhang PetscInt *diag = a->diag; 13169566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 13172c990fa1SHong Zhang for (i = 0; i < n; i++) x[i] = 1.0 / aa[diag[i]]; 13189566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 13199566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 132035e7444dSHong Zhang PetscFunctionReturn(0); 132135e7444dSHong Zhang } 132235e7444dSHong Zhang 13239566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 132435e7444dSHong Zhang for (i = 0; i < n; i++) { 1325fdc842d1SBarry Smith x[i] = 0.0; 132635e7444dSHong Zhang for (j = ai[i]; j < ai[i + 1]; j++) { 132735e7444dSHong Zhang if (aj[j] == i) { 132835e7444dSHong Zhang x[i] = aa[j]; 132917ab2063SBarry Smith break; 133017ab2063SBarry Smith } 133117ab2063SBarry Smith } 133217ab2063SBarry Smith } 13339566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 13349566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 13353a40ed3dSBarry Smith PetscFunctionReturn(0); 133617ab2063SBarry Smith } 133717ab2063SBarry Smith 1338c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 13399371c9d4SSatish Balay PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A, Vec xx, Vec zz, Vec yy) { 1340416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 13415f22a7b3SSebastian Grimberg const MatScalar *aa; 1342d9ca1df4SBarry Smith PetscScalar *y; 1343d9ca1df4SBarry Smith const PetscScalar *x; 1344d0f46423SBarry Smith PetscInt m = A->rmap->n; 13455c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 13465f22a7b3SSebastian Grimberg const MatScalar *v; 1347a77337e4SBarry Smith PetscScalar alpha; 1348d9ca1df4SBarry Smith PetscInt n, i, j; 1349d9ca1df4SBarry Smith const PetscInt *idx, *ii, *ridx = NULL; 13503447b6efSHong Zhang Mat_CompressedRow cprow = a->compressedrow; 1351ace3abfcSBarry Smith PetscBool usecprow = cprow.use; 13525c897100SBarry Smith #endif 135317ab2063SBarry Smith 13543a40ed3dSBarry Smith PetscFunctionBegin; 13559566063dSJacob Faibussowitsch if (zz != yy) PetscCall(VecCopy(zz, yy)); 13569566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 13579566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy, &y)); 13589566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 13595c897100SBarry Smith 13605c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 1361fff043a9SJunchao Zhang fortranmulttransposeaddaij_(&m, x, a->i, a->j, aa, y); 13625c897100SBarry Smith #else 13633447b6efSHong Zhang if (usecprow) { 13643447b6efSHong Zhang m = cprow.nrows; 13653447b6efSHong Zhang ii = cprow.i; 13667b2bb3b9SHong Zhang ridx = cprow.rindex; 13673447b6efSHong Zhang } else { 13683447b6efSHong Zhang ii = a->i; 13693447b6efSHong Zhang } 137017ab2063SBarry Smith for (i = 0; i < m; i++) { 13713447b6efSHong Zhang idx = a->j + ii[i]; 1372fff043a9SJunchao Zhang v = aa + ii[i]; 13733447b6efSHong Zhang n = ii[i + 1] - ii[i]; 13743447b6efSHong Zhang if (usecprow) { 13757b2bb3b9SHong Zhang alpha = x[ridx[i]]; 13763447b6efSHong Zhang } else { 137717ab2063SBarry Smith alpha = x[i]; 13783447b6efSHong Zhang } 137904fbf559SBarry Smith for (j = 0; j < n; j++) y[idx[j]] += alpha * v[j]; 138017ab2063SBarry Smith } 13815c897100SBarry Smith #endif 13829566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 13839566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 13849566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy, &y)); 13859566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 13863a40ed3dSBarry Smith PetscFunctionReturn(0); 138717ab2063SBarry Smith } 138817ab2063SBarry Smith 13899371c9d4SSatish Balay PetscErrorCode MatMultTranspose_SeqAIJ(Mat A, Vec xx, Vec yy) { 13905c897100SBarry Smith PetscFunctionBegin; 13919566063dSJacob Faibussowitsch PetscCall(VecSet(yy, 0.0)); 13929566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd_SeqAIJ(A, xx, yy, yy)); 13935c897100SBarry Smith PetscFunctionReturn(0); 13945c897100SBarry Smith } 13955c897100SBarry Smith 1396c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 139778b84d54SShri Abhyankar 13989371c9d4SSatish Balay PetscErrorCode MatMult_SeqAIJ(Mat A, Vec xx, Vec yy) { 1399416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1400d9fead3dSBarry Smith PetscScalar *y; 140154f21887SBarry Smith const PetscScalar *x; 1402fff043a9SJunchao Zhang const MatScalar *aa, *a_a; 1403003131ecSBarry Smith PetscInt m = A->rmap->n; 14040298fd71SBarry Smith const PetscInt *aj, *ii, *ridx = NULL; 14057b083b7cSBarry Smith PetscInt n, i; 1406362ced78SSatish Balay PetscScalar sum; 1407ace3abfcSBarry Smith PetscBool usecprow = a->compressedrow.use; 140817ab2063SBarry Smith 1409b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 141097952fefSHong Zhang #pragma disjoint(*x, *y, *aa) 1411fee21e36SBarry Smith #endif 1412fee21e36SBarry Smith 14133a40ed3dSBarry Smith PetscFunctionBegin; 1414b215bc84SStefano Zampini if (a->inode.use && a->inode.checked) { 14159566063dSJacob Faibussowitsch PetscCall(MatMult_SeqAIJ_Inode(A, xx, yy)); 1416b215bc84SStefano Zampini PetscFunctionReturn(0); 1417b215bc84SStefano Zampini } 14189566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 14199566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 14209566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy, &y)); 1421416022c9SBarry Smith ii = a->i; 14224eb6d288SHong Zhang if (usecprow) { /* use compressed row format */ 14239566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(y, m)); 142497952fefSHong Zhang m = a->compressedrow.nrows; 142597952fefSHong Zhang ii = a->compressedrow.i; 142697952fefSHong Zhang ridx = a->compressedrow.rindex; 142797952fefSHong Zhang for (i = 0; i < m; i++) { 142897952fefSHong Zhang n = ii[i + 1] - ii[i]; 142997952fefSHong Zhang aj = a->j + ii[i]; 1430fff043a9SJunchao Zhang aa = a_a + ii[i]; 143197952fefSHong Zhang sum = 0.0; 1432003131ecSBarry Smith PetscSparseDensePlusDot(sum, x, aa, aj, n); 1433003131ecSBarry Smith /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 143497952fefSHong Zhang y[*ridx++] = sum; 143597952fefSHong Zhang } 143697952fefSHong Zhang } else { /* do not use compressed row format */ 1437b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ) 14383d3eaba7SBarry Smith aj = a->j; 1439fff043a9SJunchao Zhang aa = a_a; 1440b05257ddSBarry Smith fortranmultaij_(&m, x, ii, aj, aa, y); 1441b05257ddSBarry Smith #else 144217ab2063SBarry Smith for (i = 0; i < m; i++) { 1443003131ecSBarry Smith n = ii[i + 1] - ii[i]; 1444003131ecSBarry Smith aj = a->j + ii[i]; 1445fff043a9SJunchao Zhang aa = a_a + ii[i]; 144617ab2063SBarry Smith sum = 0.0; 1447003131ecSBarry Smith PetscSparseDensePlusDot(sum, x, aa, aj, n); 144817ab2063SBarry Smith y[i] = sum; 144917ab2063SBarry Smith } 14508d195f9aSBarry Smith #endif 1451b05257ddSBarry Smith } 14529566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz - a->nonzerorowcnt)); 14539566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 14549566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy, &y)); 14559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a)); 14563a40ed3dSBarry Smith PetscFunctionReturn(0); 145717ab2063SBarry Smith } 145817ab2063SBarry Smith 14599371c9d4SSatish Balay PetscErrorCode MatMultMax_SeqAIJ(Mat A, Vec xx, Vec yy) { 1460b434eb95SMatthew G. Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1461b434eb95SMatthew G. Knepley PetscScalar *y; 1462b434eb95SMatthew G. Knepley const PetscScalar *x; 1463fff043a9SJunchao Zhang const MatScalar *aa, *a_a; 1464b434eb95SMatthew G. Knepley PetscInt m = A->rmap->n; 1465b434eb95SMatthew G. Knepley const PetscInt *aj, *ii, *ridx = NULL; 1466b434eb95SMatthew G. Knepley PetscInt n, i, nonzerorow = 0; 1467b434eb95SMatthew G. Knepley PetscScalar sum; 1468b434eb95SMatthew G. Knepley PetscBool usecprow = a->compressedrow.use; 1469b434eb95SMatthew G. Knepley 1470b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 1471b434eb95SMatthew G. Knepley #pragma disjoint(*x, *y, *aa) 1472b434eb95SMatthew G. Knepley #endif 1473b434eb95SMatthew G. Knepley 1474b434eb95SMatthew G. Knepley PetscFunctionBegin; 14759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 14769566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 14779566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy, &y)); 1478b434eb95SMatthew G. Knepley if (usecprow) { /* use compressed row format */ 1479b434eb95SMatthew G. Knepley m = a->compressedrow.nrows; 1480b434eb95SMatthew G. Knepley ii = a->compressedrow.i; 1481b434eb95SMatthew G. Knepley ridx = a->compressedrow.rindex; 1482b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1483b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1484b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1485fff043a9SJunchao Zhang aa = a_a + ii[i]; 1486b434eb95SMatthew G. Knepley sum = 0.0; 1487b434eb95SMatthew G. Knepley nonzerorow += (n > 0); 1488b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1489b434eb95SMatthew G. Knepley /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 1490b434eb95SMatthew G. Knepley y[*ridx++] = sum; 1491b434eb95SMatthew G. Knepley } 1492b434eb95SMatthew G. Knepley } else { /* do not use compressed row format */ 14933d3eaba7SBarry Smith ii = a->i; 1494b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1495b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1496b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1497fff043a9SJunchao Zhang aa = a_a + ii[i]; 1498b434eb95SMatthew G. Knepley sum = 0.0; 1499b434eb95SMatthew G. Knepley nonzerorow += (n > 0); 1500b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1501b434eb95SMatthew G. Knepley y[i] = sum; 1502b434eb95SMatthew G. Knepley } 1503b434eb95SMatthew G. Knepley } 15049566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz - nonzerorow)); 15059566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 15069566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy, &y)); 15079566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a)); 1508b434eb95SMatthew G. Knepley PetscFunctionReturn(0); 1509b434eb95SMatthew G. Knepley } 1510b434eb95SMatthew G. Knepley 15119371c9d4SSatish Balay PetscErrorCode MatMultAddMax_SeqAIJ(Mat A, Vec xx, Vec yy, Vec zz) { 1512b434eb95SMatthew G. Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1513b434eb95SMatthew G. Knepley PetscScalar *y, *z; 1514b434eb95SMatthew G. Knepley const PetscScalar *x; 1515fff043a9SJunchao Zhang const MatScalar *aa, *a_a; 1516b434eb95SMatthew G. Knepley PetscInt m = A->rmap->n, *aj, *ii; 1517b434eb95SMatthew G. Knepley PetscInt n, i, *ridx = NULL; 1518b434eb95SMatthew G. Knepley PetscScalar sum; 1519b434eb95SMatthew G. Knepley PetscBool usecprow = a->compressedrow.use; 1520b434eb95SMatthew G. Knepley 1521b434eb95SMatthew G. Knepley PetscFunctionBegin; 15229566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 15239566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 15249566063dSJacob Faibussowitsch PetscCall(VecGetArrayPair(yy, zz, &y, &z)); 1525b434eb95SMatthew G. Knepley if (usecprow) { /* use compressed row format */ 152648a46eb9SPierre Jolivet if (zz != yy) PetscCall(PetscArraycpy(z, y, m)); 1527b434eb95SMatthew G. Knepley m = a->compressedrow.nrows; 1528b434eb95SMatthew G. Knepley ii = a->compressedrow.i; 1529b434eb95SMatthew G. Knepley ridx = a->compressedrow.rindex; 1530b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1531b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1532b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1533fff043a9SJunchao Zhang aa = a_a + ii[i]; 1534b434eb95SMatthew G. Knepley sum = y[*ridx]; 1535b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1536b434eb95SMatthew G. Knepley z[*ridx++] = sum; 1537b434eb95SMatthew G. Knepley } 1538b434eb95SMatthew G. Knepley } else { /* do not use compressed row format */ 15393d3eaba7SBarry Smith ii = a->i; 1540b434eb95SMatthew G. Knepley for (i = 0; i < m; i++) { 1541b434eb95SMatthew G. Knepley n = ii[i + 1] - ii[i]; 1542b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1543fff043a9SJunchao Zhang aa = a_a + ii[i]; 1544b434eb95SMatthew G. Knepley sum = y[i]; 1545b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum, x, aa, aj, n); 1546b434eb95SMatthew G. Knepley z[i] = sum; 1547b434eb95SMatthew G. Knepley } 1548b434eb95SMatthew G. Knepley } 15499566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 15509566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 15519566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayPair(yy, zz, &y, &z)); 15529566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a)); 1553b434eb95SMatthew G. Knepley PetscFunctionReturn(0); 1554b434eb95SMatthew G. Knepley } 1555b434eb95SMatthew G. Knepley 1556c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h> 15579371c9d4SSatish Balay PetscErrorCode MatMultAdd_SeqAIJ(Mat A, Vec xx, Vec yy, Vec zz) { 1558416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1559f15663dcSBarry Smith PetscScalar *y, *z; 1560f15663dcSBarry Smith const PetscScalar *x; 1561fff043a9SJunchao Zhang const MatScalar *aa, *a_a; 1562d9ca1df4SBarry Smith const PetscInt *aj, *ii, *ridx = NULL; 1563d9ca1df4SBarry Smith PetscInt m = A->rmap->n, n, i; 1564362ced78SSatish Balay PetscScalar sum; 1565ace3abfcSBarry Smith PetscBool usecprow = a->compressedrow.use; 15669ea0dfa2SSatish Balay 15673a40ed3dSBarry Smith PetscFunctionBegin; 1568b215bc84SStefano Zampini if (a->inode.use && a->inode.checked) { 15699566063dSJacob Faibussowitsch PetscCall(MatMultAdd_SeqAIJ_Inode(A, xx, yy, zz)); 1570b215bc84SStefano Zampini PetscFunctionReturn(0); 1571b215bc84SStefano Zampini } 15729566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &a_a)); 15739566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx, &x)); 15749566063dSJacob Faibussowitsch PetscCall(VecGetArrayPair(yy, zz, &y, &z)); 15754eb6d288SHong Zhang if (usecprow) { /* use compressed row format */ 157648a46eb9SPierre Jolivet if (zz != yy) PetscCall(PetscArraycpy(z, y, m)); 157797952fefSHong Zhang m = a->compressedrow.nrows; 157897952fefSHong Zhang ii = a->compressedrow.i; 157997952fefSHong Zhang ridx = a->compressedrow.rindex; 158097952fefSHong Zhang for (i = 0; i < m; i++) { 158197952fefSHong Zhang n = ii[i + 1] - ii[i]; 158297952fefSHong Zhang aj = a->j + ii[i]; 1583fff043a9SJunchao Zhang aa = a_a + ii[i]; 158497952fefSHong Zhang sum = y[*ridx]; 1585f15663dcSBarry Smith PetscSparseDensePlusDot(sum, x, aa, aj, n); 158697952fefSHong Zhang z[*ridx++] = sum; 158797952fefSHong Zhang } 158897952fefSHong Zhang } else { /* do not use compressed row format */ 15893d3eaba7SBarry Smith ii = a->i; 1590f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ) 15913d3eaba7SBarry Smith aj = a->j; 1592fff043a9SJunchao Zhang aa = a_a; 1593f15663dcSBarry Smith fortranmultaddaij_(&m, x, ii, aj, aa, y, z); 1594f15663dcSBarry Smith #else 159517ab2063SBarry Smith for (i = 0; i < m; i++) { 1596f15663dcSBarry Smith n = ii[i + 1] - ii[i]; 1597f15663dcSBarry Smith aj = a->j + ii[i]; 1598fff043a9SJunchao Zhang aa = a_a + ii[i]; 159917ab2063SBarry Smith sum = y[i]; 1600f15663dcSBarry Smith PetscSparseDensePlusDot(sum, x, aa, aj, n); 160117ab2063SBarry Smith z[i] = sum; 160217ab2063SBarry Smith } 160302ab625aSSatish Balay #endif 1604f15663dcSBarry Smith } 16059566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 16069566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx, &x)); 16079566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayPair(yy, zz, &y, &z)); 16089566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a)); 16093a40ed3dSBarry Smith PetscFunctionReturn(0); 161017ab2063SBarry Smith } 161117ab2063SBarry Smith 161217ab2063SBarry Smith /* 161317ab2063SBarry Smith Adds diagonal pointers to sparse matrix structure. 161417ab2063SBarry Smith */ 16159371c9d4SSatish Balay PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A) { 1616416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1617d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n; 1618c0c07093SJunchao Zhang PetscBool alreadySet = PETSC_TRUE; 161917ab2063SBarry Smith 16203a40ed3dSBarry Smith PetscFunctionBegin; 162109f38230SBarry Smith if (!a->diag) { 16229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &a->diag)); 16239566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A, m * sizeof(PetscInt))); 1624c0c07093SJunchao Zhang alreadySet = PETSC_FALSE; 162509f38230SBarry Smith } 1626d0f46423SBarry Smith for (i = 0; i < A->rmap->n; i++) { 1627c0c07093SJunchao Zhang /* If A's diagonal is already correctly set, this fast track enables cheap and repeated MatMarkDiagonal_SeqAIJ() calls */ 1628c0c07093SJunchao Zhang if (alreadySet) { 1629c0c07093SJunchao Zhang PetscInt pos = a->diag[i]; 1630c0c07093SJunchao Zhang if (pos >= a->i[i] && pos < a->i[i + 1] && a->j[pos] == i) continue; 1631c0c07093SJunchao Zhang } 1632c0c07093SJunchao Zhang 163309f38230SBarry Smith a->diag[i] = a->i[i + 1]; 1634bfeeae90SHong Zhang for (j = a->i[i]; j < a->i[i + 1]; j++) { 1635bfeeae90SHong Zhang if (a->j[j] == i) { 163609f38230SBarry Smith a->diag[i] = j; 163717ab2063SBarry Smith break; 163817ab2063SBarry Smith } 163917ab2063SBarry Smith } 164017ab2063SBarry Smith } 16413a40ed3dSBarry Smith PetscFunctionReturn(0); 164217ab2063SBarry Smith } 164317ab2063SBarry Smith 16449371c9d4SSatish Balay PetscErrorCode MatShift_SeqAIJ(Mat A, PetscScalar v) { 164561ecd0c6SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 164661ecd0c6SBarry Smith const PetscInt *diag = (const PetscInt *)a->diag; 164761ecd0c6SBarry Smith const PetscInt *ii = (const PetscInt *)a->i; 164861ecd0c6SBarry Smith PetscInt i, *mdiag = NULL; 164961ecd0c6SBarry Smith PetscInt cnt = 0; /* how many diagonals are missing */ 165061ecd0c6SBarry Smith 165161ecd0c6SBarry Smith PetscFunctionBegin; 165261ecd0c6SBarry Smith if (!A->preallocated || !a->nz) { 16539566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(A, 1, NULL)); 16549566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(A, v)); 165561ecd0c6SBarry Smith PetscFunctionReturn(0); 165661ecd0c6SBarry Smith } 165761ecd0c6SBarry Smith 165861ecd0c6SBarry Smith if (a->diagonaldense) { 165961ecd0c6SBarry Smith cnt = 0; 166061ecd0c6SBarry Smith } else { 16619566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n, &mdiag)); 166261ecd0c6SBarry Smith for (i = 0; i < A->rmap->n; i++) { 1663349d3b71SJunchao Zhang if (i < A->cmap->n && diag[i] >= ii[i + 1]) { /* 'out of range' rows never have diagonals */ 166461ecd0c6SBarry Smith cnt++; 166561ecd0c6SBarry Smith mdiag[i] = 1; 166661ecd0c6SBarry Smith } 166761ecd0c6SBarry Smith } 166861ecd0c6SBarry Smith } 166961ecd0c6SBarry Smith if (!cnt) { 16709566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(A, v)); 167161ecd0c6SBarry Smith } else { 1672b6f2aa54SBarry Smith PetscScalar *olda = a->a; /* preserve pointers to current matrix nonzeros structure and values */ 1673b6f2aa54SBarry Smith PetscInt *oldj = a->j, *oldi = a->i; 167461ecd0c6SBarry Smith PetscBool singlemalloc = a->singlemalloc, free_a = a->free_a, free_ij = a->free_ij; 167561ecd0c6SBarry Smith 167661ecd0c6SBarry Smith a->a = NULL; 167761ecd0c6SBarry Smith a->j = NULL; 167861ecd0c6SBarry Smith a->i = NULL; 167961ecd0c6SBarry Smith /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */ 1680ad540459SPierre Jolivet for (i = 0; i < PetscMin(A->rmap->n, A->cmap->n); i++) a->imax[i] += mdiag[i]; 16819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A, 0, a->imax)); 168261ecd0c6SBarry Smith 168361ecd0c6SBarry Smith /* copy old values into new matrix data structure */ 168461ecd0c6SBarry Smith for (i = 0; i < A->rmap->n; i++) { 16859566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &i, a->imax[i] - mdiag[i], &oldj[oldi[i]], &olda[oldi[i]], ADD_VALUES)); 168648a46eb9SPierre Jolivet if (i < A->cmap->n) PetscCall(MatSetValue(A, i, i, v, ADD_VALUES)); 1687447d62f5SStefano Zampini } 16889566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 16899566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 169061ecd0c6SBarry Smith if (singlemalloc) { 16919566063dSJacob Faibussowitsch PetscCall(PetscFree3(olda, oldj, oldi)); 169261ecd0c6SBarry Smith } else { 16939566063dSJacob Faibussowitsch if (free_a) PetscCall(PetscFree(olda)); 16949566063dSJacob Faibussowitsch if (free_ij) PetscCall(PetscFree(oldj)); 16959566063dSJacob Faibussowitsch if (free_ij) PetscCall(PetscFree(oldi)); 169661ecd0c6SBarry Smith } 169761ecd0c6SBarry Smith } 16989566063dSJacob Faibussowitsch PetscCall(PetscFree(mdiag)); 169961ecd0c6SBarry Smith a->diagonaldense = PETSC_TRUE; 170061ecd0c6SBarry Smith PetscFunctionReturn(0); 170161ecd0c6SBarry Smith } 170261ecd0c6SBarry Smith 1703be5855fcSBarry Smith /* 1704be5855fcSBarry Smith Checks for missing diagonals 1705be5855fcSBarry Smith */ 17069371c9d4SSatish Balay PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A, PetscBool *missing, PetscInt *d) { 1707be5855fcSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 17087734d3b5SMatthew G. Knepley PetscInt *diag, *ii = a->i, i; 1709be5855fcSBarry Smith 1710be5855fcSBarry Smith PetscFunctionBegin; 171109f38230SBarry Smith *missing = PETSC_FALSE; 17127734d3b5SMatthew G. Knepley if (A->rmap->n > 0 && !ii) { 171309f38230SBarry Smith *missing = PETSC_TRUE; 171409f38230SBarry Smith if (d) *d = 0; 17159566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no entries therefore is missing diagonal\n")); 171609f38230SBarry Smith } else { 171701445905SHong Zhang PetscInt n; 171801445905SHong Zhang n = PetscMin(A->rmap->n, A->cmap->n); 1719f1e2ffcdSBarry Smith diag = a->diag; 172001445905SHong Zhang for (i = 0; i < n; i++) { 17217734d3b5SMatthew G. Knepley if (diag[i] >= ii[i + 1]) { 172209f38230SBarry Smith *missing = PETSC_TRUE; 172309f38230SBarry Smith if (d) *d = i; 17249566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix is missing diagonal number %" PetscInt_FMT "\n", i)); 1725358d2f5dSShri Abhyankar break; 172609f38230SBarry Smith } 1727be5855fcSBarry Smith } 1728be5855fcSBarry Smith } 1729be5855fcSBarry Smith PetscFunctionReturn(0); 1730be5855fcSBarry Smith } 1731be5855fcSBarry Smith 17320da83c2eSBarry Smith #include <petscblaslapack.h> 17330da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h> 17340da83c2eSBarry Smith 17350da83c2eSBarry Smith /* 17360da83c2eSBarry Smith Note that values is allocated externally by the PC and then passed into this routine 17370da83c2eSBarry Smith */ 17389371c9d4SSatish Balay PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *diag) { 17390da83c2eSBarry Smith PetscInt n = A->rmap->n, i, ncnt = 0, *indx, j, bsizemax = 0, *v_pivots; 17400da83c2eSBarry Smith PetscBool allowzeropivot, zeropivotdetected = PETSC_FALSE; 17410da83c2eSBarry Smith const PetscReal shift = 0.0; 17420da83c2eSBarry Smith PetscInt ipvt[5]; 17430da83c2eSBarry Smith PetscScalar work[25], *v_work; 17440da83c2eSBarry Smith 17450da83c2eSBarry Smith PetscFunctionBegin; 17460da83c2eSBarry Smith allowzeropivot = PetscNot(A->erroriffailure); 17470da83c2eSBarry Smith for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 174808401ef6SPierre 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); 1749ad540459SPierre Jolivet for (i = 0; i < nblocks; i++) bsizemax = PetscMax(bsizemax, bsizes[i]); 17509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsizemax, &indx)); 175148a46eb9SPierre Jolivet if (bsizemax > 7) PetscCall(PetscMalloc2(bsizemax, &v_work, bsizemax, &v_pivots)); 17520da83c2eSBarry Smith ncnt = 0; 17530da83c2eSBarry Smith for (i = 0; i < nblocks; i++) { 17540da83c2eSBarry Smith for (j = 0; j < bsizes[i]; j++) indx[j] = ncnt + j; 17559566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, bsizes[i], indx, bsizes[i], indx, diag)); 17560da83c2eSBarry Smith switch (bsizes[i]) { 17579371c9d4SSatish Balay case 1: *diag = 1.0 / (*diag); break; 17580da83c2eSBarry Smith case 2: 17599566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected)); 17600da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17619566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_2(diag)); 17620da83c2eSBarry Smith break; 17630da83c2eSBarry Smith case 3: 17649566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected)); 17650da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17669566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_3(diag)); 17670da83c2eSBarry Smith break; 17680da83c2eSBarry Smith case 4: 17699566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected)); 17700da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17719566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_4(diag)); 17720da83c2eSBarry Smith break; 17730da83c2eSBarry Smith case 5: 17749566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected)); 17750da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17769566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_5(diag)); 17770da83c2eSBarry Smith break; 17780da83c2eSBarry Smith case 6: 17799566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected)); 17800da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17819566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_6(diag)); 17820da83c2eSBarry Smith break; 17830da83c2eSBarry Smith case 7: 17849566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected)); 17850da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17869566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_7(diag)); 17870da83c2eSBarry Smith break; 17880da83c2eSBarry Smith default: 17899566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A(bsizes[i], diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected)); 17900da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 17919566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_N(diag, bsizes[i])); 17920da83c2eSBarry Smith } 17930da83c2eSBarry Smith ncnt += bsizes[i]; 17940da83c2eSBarry Smith diag += bsizes[i] * bsizes[i]; 17950da83c2eSBarry Smith } 179648a46eb9SPierre Jolivet if (bsizemax > 7) PetscCall(PetscFree2(v_work, v_pivots)); 17979566063dSJacob Faibussowitsch PetscCall(PetscFree(indx)); 17980da83c2eSBarry Smith PetscFunctionReturn(0); 17990da83c2eSBarry Smith } 18000da83c2eSBarry Smith 1801422a814eSBarry Smith /* 1802422a814eSBarry Smith Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways 1803422a814eSBarry Smith */ 18049371c9d4SSatish Balay PetscErrorCode MatInvertDiagonal_SeqAIJ(Mat A, PetscScalar omega, PetscScalar fshift) { 180571f1c65dSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1806d0f46423SBarry Smith PetscInt i, *diag, m = A->rmap->n; 18072e5835c6SStefano Zampini const MatScalar *v; 180854f21887SBarry Smith PetscScalar *idiag, *mdiag; 180971f1c65dSBarry Smith 181071f1c65dSBarry Smith PetscFunctionBegin; 181171f1c65dSBarry Smith if (a->idiagvalid) PetscFunctionReturn(0); 18129566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 181371f1c65dSBarry Smith diag = a->diag; 181471f1c65dSBarry Smith if (!a->idiag) { 18159566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(m, &a->idiag, m, &a->mdiag, m, &a->ssor_work)); 18169566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A, 3 * m * sizeof(PetscScalar))); 181771f1c65dSBarry Smith } 18182e5835c6SStefano Zampini 181971f1c65dSBarry Smith mdiag = a->mdiag; 182071f1c65dSBarry Smith idiag = a->idiag; 18219566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &v)); 1822422a814eSBarry Smith if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) { 182371f1c65dSBarry Smith for (i = 0; i < m; i++) { 182471f1c65dSBarry Smith mdiag[i] = v[diag[i]]; 1825899639b0SHong Zhang if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */ 1826899639b0SHong Zhang if (PetscRealPart(fshift)) { 18279566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Zero diagonal on row %" PetscInt_FMT "\n", i)); 18287b6c816cSBarry Smith A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18297b6c816cSBarry Smith A->factorerror_zeropivot_value = 0.0; 18307b6c816cSBarry Smith A->factorerror_zeropivot_row = i; 183198921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Zero diagonal on row %" PetscInt_FMT, i); 1832899639b0SHong Zhang } 183371f1c65dSBarry Smith idiag[i] = 1.0 / v[diag[i]]; 183471f1c65dSBarry Smith } 18359566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(m)); 183671f1c65dSBarry Smith } else { 183771f1c65dSBarry Smith for (i = 0; i < m; i++) { 183871f1c65dSBarry Smith mdiag[i] = v[diag[i]]; 183971f1c65dSBarry Smith idiag[i] = omega / (fshift + v[diag[i]]); 184071f1c65dSBarry Smith } 18419566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * m)); 184271f1c65dSBarry Smith } 184371f1c65dSBarry Smith a->idiagvalid = PETSC_TRUE; 18449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &v)); 184571f1c65dSBarry Smith PetscFunctionReturn(0); 184671f1c65dSBarry Smith } 184771f1c65dSBarry Smith 1848c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h> 18499371c9d4SSatish Balay PetscErrorCode MatSOR_SeqAIJ(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal fshift, PetscInt its, PetscInt lits, Vec xx) { 1850416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 1851e6d1f457SBarry Smith PetscScalar *x, d, sum, *t, scale; 18522e5835c6SStefano Zampini const MatScalar *v, *idiag = NULL, *mdiag, *aa; 185354f21887SBarry Smith const PetscScalar *b, *bs, *xb, *ts; 18543d3eaba7SBarry Smith PetscInt n, m = A->rmap->n, i; 185597f1f81fSBarry Smith const PetscInt *idx, *diag; 185617ab2063SBarry Smith 18573a40ed3dSBarry Smith PetscFunctionBegin; 1858b215bc84SStefano Zampini if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) { 18599566063dSJacob Faibussowitsch PetscCall(MatSOR_SeqAIJ_Inode(A, bb, omega, flag, fshift, its, lits, xx)); 1860b215bc84SStefano Zampini PetscFunctionReturn(0); 1861b215bc84SStefano Zampini } 1862b965ef7fSBarry Smith its = its * lits; 186391723122SBarry Smith 186471f1c65dSBarry Smith if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */ 18659566063dSJacob Faibussowitsch if (!a->idiagvalid) PetscCall(MatInvertDiagonal_SeqAIJ(A, omega, fshift)); 186671f1c65dSBarry Smith a->fshift = fshift; 186771f1c65dSBarry Smith a->omega = omega; 1868ed480e8bSBarry Smith 186971f1c65dSBarry Smith diag = a->diag; 187071f1c65dSBarry Smith t = a->ssor_work; 1871ed480e8bSBarry Smith idiag = a->idiag; 187271f1c65dSBarry Smith mdiag = a->mdiag; 1873ed480e8bSBarry Smith 18749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 18759566063dSJacob Faibussowitsch PetscCall(VecGetArray(xx, &x)); 18769566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(bb, &b)); 1877ed480e8bSBarry Smith /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */ 187817ab2063SBarry Smith if (flag == SOR_APPLY_UPPER) { 187917ab2063SBarry Smith /* apply (U + D/omega) to the vector */ 1880ed480e8bSBarry Smith bs = b; 188117ab2063SBarry Smith for (i = 0; i < m; i++) { 188271f1c65dSBarry Smith d = fshift + mdiag[i]; 1883416022c9SBarry Smith n = a->i[i + 1] - diag[i] - 1; 1884ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 18852e5835c6SStefano Zampini v = aa + diag[i] + 1; 188617ab2063SBarry Smith sum = b[i] * d / omega; 1887003131ecSBarry Smith PetscSparseDensePlusDot(sum, bs, v, idx, n); 188817ab2063SBarry Smith x[i] = sum; 188917ab2063SBarry Smith } 18909566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx, &x)); 18919566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb, &b)); 18929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 18939566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 18943a40ed3dSBarry Smith PetscFunctionReturn(0); 189517ab2063SBarry Smith } 1896c783ea89SBarry Smith 189708401ef6SPierre Jolivet PetscCheck(flag != SOR_APPLY_LOWER, PETSC_COMM_SELF, PETSC_ERR_SUP, "SOR_APPLY_LOWER is not implemented"); 1898f7d195e4SLawrence Mitchell if (flag & SOR_EISENSTAT) { 18994c500f23SPierre Jolivet /* Let A = L + U + D; where L is lower triangular, 1900887ee2caSBarry Smith U is upper triangular, E = D/omega; This routine applies 190117ab2063SBarry Smith 190217ab2063SBarry Smith (L + E)^{-1} A (U + E)^{-1} 190317ab2063SBarry Smith 1904887ee2caSBarry Smith to a vector efficiently using Eisenstat's trick. 190517ab2063SBarry Smith */ 190617ab2063SBarry Smith scale = (2.0 / omega) - 1.0; 190717ab2063SBarry Smith 190817ab2063SBarry Smith /* x = (E + U)^{-1} b */ 190917ab2063SBarry Smith for (i = m - 1; i >= 0; i--) { 1910416022c9SBarry Smith n = a->i[i + 1] - diag[i] - 1; 1911ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 19122e5835c6SStefano Zampini v = aa + diag[i] + 1; 191317ab2063SBarry Smith sum = b[i]; 1914e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 1915ed480e8bSBarry Smith x[i] = sum * idiag[i]; 191617ab2063SBarry Smith } 191717ab2063SBarry Smith 191817ab2063SBarry Smith /* t = b - (2*E - D)x */ 19192e5835c6SStefano Zampini v = aa; 19202205254eSKarl Rupp for (i = 0; i < m; i++) t[i] = b[i] - scale * (v[*diag++]) * x[i]; 192117ab2063SBarry Smith 192217ab2063SBarry Smith /* t = (E + L)^{-1}t */ 1923ed480e8bSBarry Smith ts = t; 1924416022c9SBarry Smith diag = a->diag; 192517ab2063SBarry Smith for (i = 0; i < m; i++) { 1926416022c9SBarry Smith n = diag[i] - a->i[i]; 1927ed480e8bSBarry Smith idx = a->j + a->i[i]; 19282e5835c6SStefano Zampini v = aa + a->i[i]; 192917ab2063SBarry Smith sum = t[i]; 1930003131ecSBarry Smith PetscSparseDenseMinusDot(sum, ts, v, idx, n); 1931ed480e8bSBarry Smith t[i] = sum * idiag[i]; 1932733d66baSBarry Smith /* x = x + t */ 1933733d66baSBarry Smith x[i] += t[i]; 193417ab2063SBarry Smith } 193517ab2063SBarry Smith 19369566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(6.0 * m - 1 + 2.0 * a->nz)); 19379566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx, &x)); 19389566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb, &b)); 19393a40ed3dSBarry Smith PetscFunctionReturn(0); 194017ab2063SBarry Smith } 194117ab2063SBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 194217ab2063SBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 194317ab2063SBarry Smith for (i = 0; i < m; i++) { 1944416022c9SBarry Smith n = diag[i] - a->i[i]; 1945ed480e8bSBarry Smith idx = a->j + a->i[i]; 19462e5835c6SStefano Zampini v = aa + a->i[i]; 194717ab2063SBarry Smith sum = b[i]; 1948e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 19495c99c7daSBarry Smith t[i] = sum; 1950ed480e8bSBarry Smith x[i] = sum * idiag[i]; 195117ab2063SBarry Smith } 19525c99c7daSBarry Smith xb = t; 19539566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 19543a40ed3dSBarry Smith } else xb = b; 195517ab2063SBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 195617ab2063SBarry Smith for (i = m - 1; i >= 0; i--) { 1957416022c9SBarry Smith n = a->i[i + 1] - diag[i] - 1; 1958ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 19592e5835c6SStefano Zampini v = aa + diag[i] + 1; 196017ab2063SBarry Smith sum = xb[i]; 1961e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 19625c99c7daSBarry Smith if (xb == b) { 1963ed480e8bSBarry Smith x[i] = sum * idiag[i]; 19645c99c7daSBarry Smith } else { 1965b19a5dc2SMark Adams x[i] = (1 - omega) * x[i] + sum * idiag[i]; /* omega in idiag */ 196617ab2063SBarry Smith } 19675c99c7daSBarry Smith } 19689566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */ 196917ab2063SBarry Smith } 197017ab2063SBarry Smith its--; 197117ab2063SBarry Smith } 197217ab2063SBarry Smith while (its--) { 197317ab2063SBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 197417ab2063SBarry Smith for (i = 0; i < m; i++) { 1975b19a5dc2SMark Adams /* lower */ 1976b19a5dc2SMark Adams n = diag[i] - a->i[i]; 1977ed480e8bSBarry Smith idx = a->j + a->i[i]; 19782e5835c6SStefano Zampini v = aa + a->i[i]; 197917ab2063SBarry Smith sum = b[i]; 1980e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 1981b19a5dc2SMark Adams t[i] = sum; /* save application of the lower-triangular part */ 1982b19a5dc2SMark Adams /* upper */ 1983b19a5dc2SMark Adams n = a->i[i + 1] - diag[i] - 1; 1984b19a5dc2SMark Adams idx = a->j + diag[i] + 1; 19852e5835c6SStefano Zampini v = aa + diag[i] + 1; 1986b19a5dc2SMark Adams PetscSparseDenseMinusDot(sum, x, v, idx, n); 1987b19a5dc2SMark Adams x[i] = (1. - omega) * x[i] + sum * idiag[i]; /* omega in idiag */ 198817ab2063SBarry Smith } 1989b19a5dc2SMark Adams xb = t; 19909566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 1991b19a5dc2SMark Adams } else xb = b; 199217ab2063SBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 199317ab2063SBarry Smith for (i = m - 1; i >= 0; i--) { 1994b19a5dc2SMark Adams sum = xb[i]; 1995b19a5dc2SMark Adams if (xb == b) { 1996b19a5dc2SMark Adams /* whole matrix (no checkpointing available) */ 1997416022c9SBarry Smith n = a->i[i + 1] - a->i[i]; 1998ed480e8bSBarry Smith idx = a->j + a->i[i]; 19992e5835c6SStefano Zampini v = aa + a->i[i]; 2000e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum, x, v, idx, n); 2001ed480e8bSBarry Smith x[i] = (1. - omega) * x[i] + (sum + mdiag[i] * x[i]) * idiag[i]; 2002b19a5dc2SMark Adams } else { /* lower-triangular part has been saved, so only apply upper-triangular */ 2003b19a5dc2SMark Adams n = a->i[i + 1] - diag[i] - 1; 2004b19a5dc2SMark Adams idx = a->j + diag[i] + 1; 20052e5835c6SStefano Zampini v = aa + diag[i] + 1; 2006b19a5dc2SMark Adams PetscSparseDenseMinusDot(sum, x, v, idx, n); 2007b19a5dc2SMark Adams x[i] = (1. - omega) * x[i] + sum * idiag[i]; /* omega in idiag */ 200817ab2063SBarry Smith } 2009b19a5dc2SMark Adams } 2010b19a5dc2SMark Adams if (xb == b) { 20119566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 2012b19a5dc2SMark Adams } else { 20139566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */ 2014b19a5dc2SMark Adams } 201517ab2063SBarry Smith } 201617ab2063SBarry Smith } 20179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 20189566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx, &x)); 20199566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb, &b)); 2020365a8a9eSBarry Smith PetscFunctionReturn(0); 202117ab2063SBarry Smith } 202217ab2063SBarry Smith 20239371c9d4SSatish Balay PetscErrorCode MatGetInfo_SeqAIJ(Mat A, MatInfoType flag, MatInfo *info) { 2024416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 20254e220ebcSLois Curfman McInnes 20263a40ed3dSBarry Smith PetscFunctionBegin; 20274e220ebcSLois Curfman McInnes info->block_size = 1.0; 20283966268fSBarry Smith info->nz_allocated = a->maxnz; 20293966268fSBarry Smith info->nz_used = a->nz; 20303966268fSBarry Smith info->nz_unneeded = (a->maxnz - a->nz); 20313966268fSBarry Smith info->assemblies = A->num_ass; 20323966268fSBarry Smith info->mallocs = A->info.mallocs; 20337adad957SLisandro Dalcin info->memory = ((PetscObject)A)->mem; 2034d5f3da31SBarry Smith if (A->factortype) { 20354e220ebcSLois Curfman McInnes info->fill_ratio_given = A->info.fill_ratio_given; 20364e220ebcSLois Curfman McInnes info->fill_ratio_needed = A->info.fill_ratio_needed; 20374e220ebcSLois Curfman McInnes info->factor_mallocs = A->info.factor_mallocs; 20384e220ebcSLois Curfman McInnes } else { 20394e220ebcSLois Curfman McInnes info->fill_ratio_given = 0; 20404e220ebcSLois Curfman McInnes info->fill_ratio_needed = 0; 20414e220ebcSLois Curfman McInnes info->factor_mallocs = 0; 20424e220ebcSLois Curfman McInnes } 20433a40ed3dSBarry Smith PetscFunctionReturn(0); 204417ab2063SBarry Smith } 204517ab2063SBarry Smith 20469371c9d4SSatish Balay PetscErrorCode MatZeroRows_SeqAIJ(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) { 2047416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2048c7da8527SEric Chamberland PetscInt i, m = A->rmap->n - 1; 204997b48c8fSBarry Smith const PetscScalar *xx; 20502e5835c6SStefano Zampini PetscScalar *bb, *aa; 2051c7da8527SEric Chamberland PetscInt d = 0; 205217ab2063SBarry Smith 20533a40ed3dSBarry Smith PetscFunctionBegin; 205497b48c8fSBarry Smith if (x && b) { 20559566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 20569566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 205797b48c8fSBarry Smith for (i = 0; i < N; i++) { 2058aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 2059447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 206097b48c8fSBarry Smith bb[rows[i]] = diag * xx[rows[i]]; 206197b48c8fSBarry Smith } 20629566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 20639566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 206497b48c8fSBarry Smith } 206597b48c8fSBarry Smith 20669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 2067a9817697SBarry Smith if (a->keepnonzeropattern) { 2068f1e2ffcdSBarry Smith for (i = 0; i < N; i++) { 2069aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 20709566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(&aa[a->i[rows[i]]], a->ilen[rows[i]])); 2071f1e2ffcdSBarry Smith } 2072f4df32b1SMatthew Knepley if (diag != 0.0) { 2073c7da8527SEric Chamberland for (i = 0; i < N; i++) { 2074c7da8527SEric Chamberland d = rows[i]; 2075447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 207608401ef6SPierre 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); 2077c7da8527SEric Chamberland } 2078f1e2ffcdSBarry Smith for (i = 0; i < N; i++) { 2079447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 20802e5835c6SStefano Zampini aa[a->diag[rows[i]]] = diag; 2081f1e2ffcdSBarry Smith } 2082f1e2ffcdSBarry Smith } 2083f1e2ffcdSBarry Smith } else { 2084f4df32b1SMatthew Knepley if (diag != 0.0) { 208517ab2063SBarry Smith for (i = 0; i < N; i++) { 2086aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 20877ae801bdSBarry Smith if (a->ilen[rows[i]] > 0) { 2088447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) { 2089447d62f5SStefano Zampini a->ilen[rows[i]] = 0; 2090447d62f5SStefano Zampini } else { 2091416022c9SBarry Smith a->ilen[rows[i]] = 1; 20922e5835c6SStefano Zampini aa[a->i[rows[i]]] = diag; 2093bfeeae90SHong Zhang a->j[a->i[rows[i]]] = rows[i]; 2094447d62f5SStefano Zampini } 2095447d62f5SStefano Zampini } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */ 20969566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(A, 1, &rows[i], 1, &rows[i], &diag, INSERT_VALUES)); 209717ab2063SBarry Smith } 209817ab2063SBarry Smith } 20993a40ed3dSBarry Smith } else { 210017ab2063SBarry Smith for (i = 0; i < N; i++) { 2101aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 2102416022c9SBarry Smith a->ilen[rows[i]] = 0; 210317ab2063SBarry Smith } 210417ab2063SBarry Smith } 2105e56f5c9eSBarry Smith A->nonzerostate++; 2106f1e2ffcdSBarry Smith } 21079566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 2108dbbe0bcdSBarry Smith PetscUseTypeMethod(A, assemblyend, MAT_FINAL_ASSEMBLY); 21093a40ed3dSBarry Smith PetscFunctionReturn(0); 211017ab2063SBarry Smith } 211117ab2063SBarry Smith 21129371c9d4SSatish Balay PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) { 21136e169961SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 21146e169961SBarry Smith PetscInt i, j, m = A->rmap->n - 1, d = 0; 21152b40b63fSBarry Smith PetscBool missing, *zeroed, vecs = PETSC_FALSE; 21166e169961SBarry Smith const PetscScalar *xx; 21172e5835c6SStefano Zampini PetscScalar *bb, *aa; 21186e169961SBarry Smith 21196e169961SBarry Smith PetscFunctionBegin; 21202e5835c6SStefano Zampini if (!N) PetscFunctionReturn(0); 21219566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 21226e169961SBarry Smith if (x && b) { 21239566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 21249566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 21252b40b63fSBarry Smith vecs = PETSC_TRUE; 21266e169961SBarry Smith } 21279566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n, &zeroed)); 21286e169961SBarry Smith for (i = 0; i < N; i++) { 2129aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]); 21309566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(&aa[a->i[rows[i]]], a->ilen[rows[i]])); 21312205254eSKarl Rupp 21326e169961SBarry Smith zeroed[rows[i]] = PETSC_TRUE; 21336e169961SBarry Smith } 21346e169961SBarry Smith for (i = 0; i < A->rmap->n; i++) { 21356e169961SBarry Smith if (!zeroed[i]) { 21366e169961SBarry Smith for (j = a->i[i]; j < a->i[i + 1]; j++) { 21374cf107fdSStefano Zampini if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) { 21382e5835c6SStefano Zampini if (vecs) bb[i] -= aa[j] * xx[a->j[j]]; 21392e5835c6SStefano Zampini aa[j] = 0.0; 21406e169961SBarry Smith } 21416e169961SBarry Smith } 21424cf107fdSStefano Zampini } else if (vecs && i < A->cmap->N) bb[i] = diag * xx[i]; 21436e169961SBarry Smith } 21446e169961SBarry Smith if (x && b) { 21459566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 21469566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 21476e169961SBarry Smith } 21489566063dSJacob Faibussowitsch PetscCall(PetscFree(zeroed)); 21496e169961SBarry Smith if (diag != 0.0) { 21509566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal_SeqAIJ(A, &missing, &d)); 21511d5a398dSstefano_zampini if (missing) { 21521d5a398dSstefano_zampini for (i = 0; i < N; i++) { 21534cf107fdSStefano Zampini if (rows[i] >= A->cmap->N) continue; 2154aed4548fSBarry 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]); 21559566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(A, 1, &rows[i], 1, &rows[i], &diag, INSERT_VALUES)); 21561d5a398dSstefano_zampini } 21571d5a398dSstefano_zampini } else { 2158ad540459SPierre Jolivet for (i = 0; i < N; i++) aa[a->diag[rows[i]]] = diag; 21596e169961SBarry Smith } 21601d5a398dSstefano_zampini } 21619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 2162dbbe0bcdSBarry Smith PetscUseTypeMethod(A, assemblyend, MAT_FINAL_ASSEMBLY); 21636e169961SBarry Smith PetscFunctionReturn(0); 21646e169961SBarry Smith } 21656e169961SBarry Smith 21669371c9d4SSatish Balay PetscErrorCode MatGetRow_SeqAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) { 2167fff043a9SJunchao Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2168fff043a9SJunchao Zhang const PetscScalar *aa; 2169fff043a9SJunchao Zhang PetscInt *itmp; 217017ab2063SBarry Smith 21713a40ed3dSBarry Smith PetscFunctionBegin; 21729566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 2173416022c9SBarry Smith *nz = a->i[row + 1] - a->i[row]; 21742e5835c6SStefano Zampini if (v) *v = (PetscScalar *)(aa + a->i[row]); 217517ab2063SBarry Smith if (idx) { 2176bfeeae90SHong Zhang itmp = a->j + a->i[row]; 217726fbe8dcSKarl Rupp if (*nz) *idx = itmp; 2178f4259b30SLisandro Dalcin else *idx = NULL; 217917ab2063SBarry Smith } 21809566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 21813a40ed3dSBarry Smith PetscFunctionReturn(0); 218217ab2063SBarry Smith } 218317ab2063SBarry Smith 21849371c9d4SSatish Balay PetscErrorCode MatRestoreRow_SeqAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) { 21853a40ed3dSBarry Smith PetscFunctionBegin; 2186cb4a9cd9SHong Zhang if (nz) *nz = 0; 21872e5835c6SStefano Zampini if (idx) *idx = NULL; 21882e5835c6SStefano Zampini if (v) *v = NULL; 21893a40ed3dSBarry Smith PetscFunctionReturn(0); 219017ab2063SBarry Smith } 219117ab2063SBarry Smith 21929371c9d4SSatish Balay PetscErrorCode MatNorm_SeqAIJ(Mat A, NormType type, PetscReal *nrm) { 2193416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 21942e5835c6SStefano Zampini const MatScalar *v; 219536db0b34SBarry Smith PetscReal sum = 0.0; 219697f1f81fSBarry Smith PetscInt i, j; 219717ab2063SBarry Smith 21983a40ed3dSBarry Smith PetscFunctionBegin; 21999566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &v)); 220017ab2063SBarry Smith if (type == NORM_FROBENIUS) { 2201570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16) 2202570b7f6dSBarry Smith PetscBLASInt one = 1, nz = a->nz; 2203792fecdfSBarry Smith PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&nz, v, &one)); 2204570b7f6dSBarry Smith #else 2205416022c9SBarry Smith for (i = 0; i < a->nz; i++) { 22069371c9d4SSatish Balay sum += PetscRealPart(PetscConj(*v) * (*v)); 22079371c9d4SSatish Balay v++; 220817ab2063SBarry Smith } 22098f1a2a5eSBarry Smith *nrm = PetscSqrtReal(sum); 2210570b7f6dSBarry Smith #endif 22119566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * a->nz)); 22123a40ed3dSBarry Smith } else if (type == NORM_1) { 221336db0b34SBarry Smith PetscReal *tmp; 221497f1f81fSBarry Smith PetscInt *jj = a->j; 22159566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->cmap->n + 1, &tmp)); 2216064f8208SBarry Smith *nrm = 0.0; 2217416022c9SBarry Smith for (j = 0; j < a->nz; j++) { 22189371c9d4SSatish Balay tmp[*jj++] += PetscAbsScalar(*v); 22199371c9d4SSatish Balay v++; 222017ab2063SBarry Smith } 2221d0f46423SBarry Smith for (j = 0; j < A->cmap->n; j++) { 2222064f8208SBarry Smith if (tmp[j] > *nrm) *nrm = tmp[j]; 222317ab2063SBarry Smith } 22249566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp)); 22259566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(PetscMax(a->nz - 1, 0))); 22263a40ed3dSBarry Smith } else if (type == NORM_INFINITY) { 2227064f8208SBarry Smith *nrm = 0.0; 2228d0f46423SBarry Smith for (j = 0; j < A->rmap->n; j++) { 22292e5835c6SStefano Zampini const PetscScalar *v2 = v + a->i[j]; 223017ab2063SBarry Smith sum = 0.0; 2231416022c9SBarry Smith for (i = 0; i < a->i[j + 1] - a->i[j]; i++) { 22329371c9d4SSatish Balay sum += PetscAbsScalar(*v2); 22339371c9d4SSatish Balay v2++; 223417ab2063SBarry Smith } 2235064f8208SBarry Smith if (sum > *nrm) *nrm = sum; 223617ab2063SBarry Smith } 22379566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(PetscMax(a->nz - 1, 0))); 2238f23aa3ddSBarry Smith } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for two norm"); 22399566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &v)); 22403a40ed3dSBarry Smith PetscFunctionReturn(0); 224117ab2063SBarry Smith } 224217ab2063SBarry Smith 22439371c9d4SSatish Balay PetscErrorCode MatIsTranspose_SeqAIJ(Mat A, Mat B, PetscReal tol, PetscBool *f) { 22443d3eaba7SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data, *bij = (Mat_SeqAIJ *)B->data; 224554f21887SBarry Smith PetscInt *adx, *bdx, *aii, *bii, *aptr, *bptr; 22462e5835c6SStefano Zampini const MatScalar *va, *vb; 224797f1f81fSBarry Smith PetscInt ma, na, mb, nb, i; 2248cd0d46ebSvictorle 2249cd0d46ebSvictorle PetscFunctionBegin; 22509566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &ma, &na)); 22519566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &mb, &nb)); 22525485867bSBarry Smith if (ma != nb || na != mb) { 22535485867bSBarry Smith *f = PETSC_FALSE; 22545485867bSBarry Smith PetscFunctionReturn(0); 22555485867bSBarry Smith } 22569566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &va)); 22579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &vb)); 22589371c9d4SSatish Balay aii = aij->i; 22599371c9d4SSatish Balay bii = bij->i; 22609371c9d4SSatish Balay adx = aij->j; 22619371c9d4SSatish Balay bdx = bij->j; 22629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ma, &aptr)); 22639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mb, &bptr)); 2264cd0d46ebSvictorle for (i = 0; i < ma; i++) aptr[i] = aii[i]; 2265cd0d46ebSvictorle for (i = 0; i < mb; i++) bptr[i] = bii[i]; 2266cd0d46ebSvictorle 2267cd0d46ebSvictorle *f = PETSC_TRUE; 2268cd0d46ebSvictorle for (i = 0; i < ma; i++) { 2269cd0d46ebSvictorle while (aptr[i] < aii[i + 1]) { 227097f1f81fSBarry Smith PetscInt idc, idr; 22715485867bSBarry Smith PetscScalar vc, vr; 2272cd0d46ebSvictorle /* column/row index/value */ 22735485867bSBarry Smith idc = adx[aptr[i]]; 22745485867bSBarry Smith idr = bdx[bptr[idc]]; 22755485867bSBarry Smith vc = va[aptr[i]]; 22765485867bSBarry Smith vr = vb[bptr[idc]]; 22775485867bSBarry Smith if (i != idr || PetscAbsScalar(vc - vr) > tol) { 22785485867bSBarry Smith *f = PETSC_FALSE; 22795485867bSBarry Smith goto done; 2280cd0d46ebSvictorle } else { 22815485867bSBarry Smith aptr[i]++; 22825485867bSBarry Smith if (B || i != idc) bptr[idc]++; 2283cd0d46ebSvictorle } 2284cd0d46ebSvictorle } 2285cd0d46ebSvictorle } 2286cd0d46ebSvictorle done: 22879566063dSJacob Faibussowitsch PetscCall(PetscFree(aptr)); 22889566063dSJacob Faibussowitsch PetscCall(PetscFree(bptr)); 22899566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &va)); 22909566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &vb)); 2291cd0d46ebSvictorle PetscFunctionReturn(0); 2292cd0d46ebSvictorle } 2293cd0d46ebSvictorle 22949371c9d4SSatish Balay PetscErrorCode MatIsHermitianTranspose_SeqAIJ(Mat A, Mat B, PetscReal tol, PetscBool *f) { 22953d3eaba7SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data, *bij = (Mat_SeqAIJ *)B->data; 229654f21887SBarry Smith PetscInt *adx, *bdx, *aii, *bii, *aptr, *bptr; 229754f21887SBarry Smith MatScalar *va, *vb; 22981cbb95d3SBarry Smith PetscInt ma, na, mb, nb, i; 22991cbb95d3SBarry Smith 23001cbb95d3SBarry Smith PetscFunctionBegin; 23019566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &ma, &na)); 23029566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &mb, &nb)); 23031cbb95d3SBarry Smith if (ma != nb || na != mb) { 23041cbb95d3SBarry Smith *f = PETSC_FALSE; 23051cbb95d3SBarry Smith PetscFunctionReturn(0); 23061cbb95d3SBarry Smith } 23079371c9d4SSatish Balay aii = aij->i; 23089371c9d4SSatish Balay bii = bij->i; 23099371c9d4SSatish Balay adx = aij->j; 23109371c9d4SSatish Balay bdx = bij->j; 23119371c9d4SSatish Balay va = aij->a; 23129371c9d4SSatish Balay vb = bij->a; 23139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ma, &aptr)); 23149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mb, &bptr)); 23151cbb95d3SBarry Smith for (i = 0; i < ma; i++) aptr[i] = aii[i]; 23161cbb95d3SBarry Smith for (i = 0; i < mb; i++) bptr[i] = bii[i]; 23171cbb95d3SBarry Smith 23181cbb95d3SBarry Smith *f = PETSC_TRUE; 23191cbb95d3SBarry Smith for (i = 0; i < ma; i++) { 23201cbb95d3SBarry Smith while (aptr[i] < aii[i + 1]) { 23211cbb95d3SBarry Smith PetscInt idc, idr; 23221cbb95d3SBarry Smith PetscScalar vc, vr; 23231cbb95d3SBarry Smith /* column/row index/value */ 23241cbb95d3SBarry Smith idc = adx[aptr[i]]; 23251cbb95d3SBarry Smith idr = bdx[bptr[idc]]; 23261cbb95d3SBarry Smith vc = va[aptr[i]]; 23271cbb95d3SBarry Smith vr = vb[bptr[idc]]; 23281cbb95d3SBarry Smith if (i != idr || PetscAbsScalar(vc - PetscConj(vr)) > tol) { 23291cbb95d3SBarry Smith *f = PETSC_FALSE; 23301cbb95d3SBarry Smith goto done; 23311cbb95d3SBarry Smith } else { 23321cbb95d3SBarry Smith aptr[i]++; 23331cbb95d3SBarry Smith if (B || i != idc) bptr[idc]++; 23341cbb95d3SBarry Smith } 23351cbb95d3SBarry Smith } 23361cbb95d3SBarry Smith } 23371cbb95d3SBarry Smith done: 23389566063dSJacob Faibussowitsch PetscCall(PetscFree(aptr)); 23399566063dSJacob Faibussowitsch PetscCall(PetscFree(bptr)); 23401cbb95d3SBarry Smith PetscFunctionReturn(0); 23411cbb95d3SBarry Smith } 23421cbb95d3SBarry Smith 23439371c9d4SSatish Balay PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A, PetscReal tol, PetscBool *f) { 23449e29f15eSvictorle PetscFunctionBegin; 23459566063dSJacob Faibussowitsch PetscCall(MatIsTranspose_SeqAIJ(A, A, tol, f)); 23469e29f15eSvictorle PetscFunctionReturn(0); 23479e29f15eSvictorle } 23489e29f15eSvictorle 23499371c9d4SSatish Balay PetscErrorCode MatIsHermitian_SeqAIJ(Mat A, PetscReal tol, PetscBool *f) { 23501cbb95d3SBarry Smith PetscFunctionBegin; 23519566063dSJacob Faibussowitsch PetscCall(MatIsHermitianTranspose_SeqAIJ(A, A, tol, f)); 23521cbb95d3SBarry Smith PetscFunctionReturn(0); 23531cbb95d3SBarry Smith } 23541cbb95d3SBarry Smith 23559371c9d4SSatish Balay PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A, Vec ll, Vec rr) { 2356416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2357fff8e43fSBarry Smith const PetscScalar *l, *r; 2358fff8e43fSBarry Smith PetscScalar x; 235954f21887SBarry Smith MatScalar *v; 2360fff8e43fSBarry Smith PetscInt i, j, m = A->rmap->n, n = A->cmap->n, M, nz = a->nz; 2361fff8e43fSBarry Smith const PetscInt *jj; 236217ab2063SBarry Smith 23633a40ed3dSBarry Smith PetscFunctionBegin; 236417ab2063SBarry Smith if (ll) { 23653ea7c6a1SSatish Balay /* The local size is used so that VecMPI can be passed to this routine 23663ea7c6a1SSatish Balay by MatDiagonalScale_MPIAIJ */ 23679566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ll, &m)); 236808401ef6SPierre Jolivet PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vector wrong length"); 23699566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(ll, &l)); 23709566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &v)); 237117ab2063SBarry Smith for (i = 0; i < m; i++) { 237217ab2063SBarry Smith x = l[i]; 2373416022c9SBarry Smith M = a->i[i + 1] - a->i[i]; 23742205254eSKarl Rupp for (j = 0; j < M; j++) (*v++) *= x; 237517ab2063SBarry Smith } 23769566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(ll, &l)); 23779566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(nz)); 23789566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &v)); 237917ab2063SBarry Smith } 238017ab2063SBarry Smith if (rr) { 23819566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rr, &n)); 238208401ef6SPierre Jolivet PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vector wrong length"); 23839566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(rr, &r)); 23849566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &v)); 23852e5835c6SStefano Zampini jj = a->j; 23862205254eSKarl Rupp for (i = 0; i < nz; i++) (*v++) *= r[*jj++]; 23879566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &v)); 23889566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(rr, &r)); 23899566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(nz)); 239017ab2063SBarry Smith } 23919566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 23923a40ed3dSBarry Smith PetscFunctionReturn(0); 239317ab2063SBarry Smith } 239417ab2063SBarry Smith 23959371c9d4SSatish Balay PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A, IS isrow, IS iscol, PetscInt csize, MatReuse scall, Mat *B) { 2396db02288aSLois Curfman McInnes Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data, *c; 2397d0f46423SBarry Smith PetscInt *smap, i, k, kstart, kend, oldcols = A->cmap->n, *lens; 239897f1f81fSBarry Smith PetscInt row, mat_i, *mat_j, tcol, first, step, *mat_ilen, sum, lensi; 23995d0c19d7SBarry Smith const PetscInt *irow, *icol; 24002e5835c6SStefano Zampini const PetscScalar *aa; 24015d0c19d7SBarry Smith PetscInt nrows, ncols; 240297f1f81fSBarry Smith PetscInt *starts, *j_new, *i_new, *aj = a->j, *ai = a->i, ii, *ailen = a->ilen; 240354f21887SBarry Smith MatScalar *a_new, *mat_a; 2404416022c9SBarry Smith Mat C; 2405cdc6f3adSToby Isaac PetscBool stride; 240617ab2063SBarry Smith 24073a40ed3dSBarry Smith PetscFunctionBegin; 24089566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow, &irow)); 24099566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow, &nrows)); 24109566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol, &ncols)); 241117ab2063SBarry Smith 24129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)iscol, ISSTRIDE, &stride)); 2413ff718158SBarry Smith if (stride) { 24149566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(iscol, &first, &step)); 2415ff718158SBarry Smith } else { 2416ff718158SBarry Smith first = 0; 2417ff718158SBarry Smith step = 0; 2418ff718158SBarry Smith } 2419fee21e36SBarry Smith if (stride && step == 1) { 242002834360SBarry Smith /* special case of contiguous rows */ 24219566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nrows, &lens, nrows, &starts)); 242202834360SBarry Smith /* loop over new rows determining lens and starting points */ 242302834360SBarry Smith for (i = 0; i < nrows; i++) { 2424bfeeae90SHong Zhang kstart = ai[irow[i]]; 2425a2744918SBarry Smith kend = kstart + ailen[irow[i]]; 2426a91a9bebSLisandro Dalcin starts[i] = kstart; 242702834360SBarry Smith for (k = kstart; k < kend; k++) { 2428bfeeae90SHong Zhang if (aj[k] >= first) { 242902834360SBarry Smith starts[i] = k; 243002834360SBarry Smith break; 243102834360SBarry Smith } 243202834360SBarry Smith } 2433a2744918SBarry Smith sum = 0; 243402834360SBarry Smith while (k < kend) { 2435bfeeae90SHong Zhang if (aj[k++] >= first + ncols) break; 2436a2744918SBarry Smith sum++; 243702834360SBarry Smith } 2438a2744918SBarry Smith lens[i] = sum; 243902834360SBarry Smith } 244002834360SBarry Smith /* create submatrix */ 2441cddf8d76SBarry Smith if (scall == MAT_REUSE_MATRIX) { 244297f1f81fSBarry Smith PetscInt n_cols, n_rows; 24439566063dSJacob Faibussowitsch PetscCall(MatGetSize(*B, &n_rows, &n_cols)); 2444aed4548fSBarry Smith PetscCheck(n_rows == nrows && n_cols == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Reused submatrix wrong size"); 24459566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*B)); 244608480c60SBarry Smith C = *B; 24473a40ed3dSBarry Smith } else { 24483bef6203SJed Brown PetscInt rbs, cbs; 24499566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 24509566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, nrows, ncols, PETSC_DETERMINE, PETSC_DETERMINE)); 24519566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(isrow, &rbs)); 24529566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(iscol, &cbs)); 24539566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C, rbs, cbs)); 24549566063dSJacob Faibussowitsch PetscCall(MatSetType(C, ((PetscObject)A)->type_name)); 24559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C, 0, lens)); 245608480c60SBarry Smith } 2457db02288aSLois Curfman McInnes c = (Mat_SeqAIJ *)C->data; 2458db02288aSLois Curfman McInnes 245902834360SBarry Smith /* loop over rows inserting into submatrix */ 2460db02288aSLois Curfman McInnes a_new = c->a; 2461db02288aSLois Curfman McInnes j_new = c->j; 2462db02288aSLois Curfman McInnes i_new = c->i; 24639566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 246402834360SBarry Smith for (i = 0; i < nrows; i++) { 2465a2744918SBarry Smith ii = starts[i]; 2466a2744918SBarry Smith lensi = lens[i]; 2467ad540459SPierre Jolivet for (k = 0; k < lensi; k++) *j_new++ = aj[ii + k] - first; 24689566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a_new, aa + starts[i], lensi)); 2469a2744918SBarry Smith a_new += lensi; 2470a2744918SBarry Smith i_new[i + 1] = i_new[i] + lensi; 2471a2744918SBarry Smith c->ilen[i] = lensi; 247202834360SBarry Smith } 24739566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 24749566063dSJacob Faibussowitsch PetscCall(PetscFree2(lens, starts)); 24753a40ed3dSBarry Smith } else { 24769566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol, &icol)); 24779566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(oldcols, &smap)); 24789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1 + nrows, &lens)); 24794dcab191SBarry Smith for (i = 0; i < ncols; i++) { 24806bdcaf15SBarry 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); 24814dcab191SBarry Smith smap[icol[i]] = i + 1; 24824dcab191SBarry Smith } 24834dcab191SBarry Smith 248402834360SBarry Smith /* determine lens of each row */ 248502834360SBarry Smith for (i = 0; i < nrows; i++) { 2486bfeeae90SHong Zhang kstart = ai[irow[i]]; 248702834360SBarry Smith kend = kstart + a->ilen[irow[i]]; 248802834360SBarry Smith lens[i] = 0; 248902834360SBarry Smith for (k = kstart; k < kend; k++) { 2490ad540459SPierre Jolivet if (smap[aj[k]]) lens[i]++; 249102834360SBarry Smith } 249202834360SBarry Smith } 249317ab2063SBarry Smith /* Create and fill new matrix */ 2494a2744918SBarry Smith if (scall == MAT_REUSE_MATRIX) { 2495ace3abfcSBarry Smith PetscBool equal; 24960f5bd95cSBarry Smith 249799141d43SSatish Balay c = (Mat_SeqAIJ *)((*B)->data); 2498aed4548fSBarry Smith PetscCheck((*B)->rmap->n == nrows && (*B)->cmap->n == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot reuse matrix. wrong size"); 24999566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(c->ilen, lens, (*B)->rmap->n, &equal)); 250028b400f6SJacob Faibussowitsch PetscCheck(equal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot reuse matrix. wrong no of nonzeros"); 25019566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->ilen, (*B)->rmap->n)); 250208480c60SBarry Smith C = *B; 25033a40ed3dSBarry Smith } else { 25043bef6203SJed Brown PetscInt rbs, cbs; 25059566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 25069566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, nrows, ncols, PETSC_DETERMINE, PETSC_DETERMINE)); 25079566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(isrow, &rbs)); 25089566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(iscol, &cbs)); 25099566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C, rbs, cbs)); 25109566063dSJacob Faibussowitsch PetscCall(MatSetType(C, ((PetscObject)A)->type_name)); 25119566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C, 0, lens)); 251208480c60SBarry Smith } 25139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 251499141d43SSatish Balay c = (Mat_SeqAIJ *)(C->data); 251517ab2063SBarry Smith for (i = 0; i < nrows; i++) { 251699141d43SSatish Balay row = irow[i]; 2517bfeeae90SHong Zhang kstart = ai[row]; 251899141d43SSatish Balay kend = kstart + a->ilen[row]; 2519bfeeae90SHong Zhang mat_i = c->i[i]; 252099141d43SSatish Balay mat_j = c->j + mat_i; 252199141d43SSatish Balay mat_a = c->a + mat_i; 252299141d43SSatish Balay mat_ilen = c->ilen + i; 252317ab2063SBarry Smith for (k = kstart; k < kend; k++) { 2524bfeeae90SHong Zhang if ((tcol = smap[a->j[k]])) { 2525ed480e8bSBarry Smith *mat_j++ = tcol - 1; 25262e5835c6SStefano Zampini *mat_a++ = aa[k]; 252799141d43SSatish Balay (*mat_ilen)++; 252817ab2063SBarry Smith } 252917ab2063SBarry Smith } 253017ab2063SBarry Smith } 25319566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 253202834360SBarry Smith /* Free work space */ 25339566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol, &icol)); 25349566063dSJacob Faibussowitsch PetscCall(PetscFree(smap)); 25359566063dSJacob Faibussowitsch PetscCall(PetscFree(lens)); 2536cdc6f3adSToby Isaac /* sort */ 2537cdc6f3adSToby Isaac for (i = 0; i < nrows; i++) { 2538cdc6f3adSToby Isaac PetscInt ilen; 2539cdc6f3adSToby Isaac 2540cdc6f3adSToby Isaac mat_i = c->i[i]; 2541cdc6f3adSToby Isaac mat_j = c->j + mat_i; 2542cdc6f3adSToby Isaac mat_a = c->a + mat_i; 2543cdc6f3adSToby Isaac ilen = c->ilen[i]; 25449566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(ilen, mat_j, mat_a)); 2545cdc6f3adSToby Isaac } 254602834360SBarry Smith } 25478c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 25489566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(C, A->boundtocpu)); 2549305c6ccfSStefano Zampini #endif 25509566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 25519566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 255217ab2063SBarry Smith 25539566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow, &irow)); 2554416022c9SBarry Smith *B = C; 25553a40ed3dSBarry Smith PetscFunctionReturn(0); 255617ab2063SBarry Smith } 255717ab2063SBarry Smith 25589371c9d4SSatish Balay PetscErrorCode MatGetMultiProcBlock_SeqAIJ(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) { 255982d44351SHong Zhang Mat B; 256082d44351SHong Zhang 256182d44351SHong Zhang PetscFunctionBegin; 2562c2d650bdSHong Zhang if (scall == MAT_INITIAL_MATRIX) { 25639566063dSJacob Faibussowitsch PetscCall(MatCreate(subComm, &B)); 25649566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->n, mat->cmap->n)); 25659566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, mat, mat)); 25669566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATSEQAIJ)); 25679566063dSJacob Faibussowitsch PetscCall(MatDuplicateNoCreate_SeqAIJ(B, mat, MAT_COPY_VALUES, PETSC_TRUE)); 256882d44351SHong Zhang *subMat = B; 2569c2d650bdSHong Zhang } else { 25709566063dSJacob Faibussowitsch PetscCall(MatCopy_SeqAIJ(mat, *subMat, SAME_NONZERO_PATTERN)); 2571c2d650bdSHong Zhang } 257282d44351SHong Zhang PetscFunctionReturn(0); 257382d44351SHong Zhang } 257482d44351SHong Zhang 25759371c9d4SSatish Balay PetscErrorCode MatILUFactor_SeqAIJ(Mat inA, IS row, IS col, const MatFactorInfo *info) { 257663b91edcSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)inA->data; 257763b91edcSBarry Smith Mat outA; 2578ace3abfcSBarry Smith PetscBool row_identity, col_identity; 257963b91edcSBarry Smith 25803a40ed3dSBarry Smith PetscFunctionBegin; 258108401ef6SPierre Jolivet PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 supported for in-place ilu"); 25821df811f5SHong Zhang 25839566063dSJacob Faibussowitsch PetscCall(ISIdentity(row, &row_identity)); 25849566063dSJacob Faibussowitsch PetscCall(ISIdentity(col, &col_identity)); 2585a871dcd8SBarry Smith 258663b91edcSBarry Smith outA = inA; 2587d5f3da31SBarry Smith outA->factortype = MAT_FACTOR_LU; 25889566063dSJacob Faibussowitsch PetscCall(PetscFree(inA->solvertype)); 25899566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype)); 25902205254eSKarl Rupp 25919566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)row)); 25929566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 25932205254eSKarl Rupp 2594c3122656SLisandro Dalcin a->row = row; 25952205254eSKarl Rupp 25969566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)col)); 25979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 25982205254eSKarl Rupp 2599c3122656SLisandro Dalcin a->col = col; 260063b91edcSBarry Smith 260136db0b34SBarry Smith /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */ 26029566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 26039566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(col, PETSC_DECIDE, &a->icol)); 26049566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)inA, (PetscObject)a->icol)); 2605f0ec6fceSSatish Balay 260694a9d846SBarry Smith if (!a->solve_work) { /* this matrix may have been factored before */ 26079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(inA->rmap->n + 1, &a->solve_work)); 26089566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n + 1) * sizeof(PetscScalar))); 260994a9d846SBarry Smith } 261063b91edcSBarry Smith 26119566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(inA)); 2612137fb511SHong Zhang if (row_identity && col_identity) { 26139566063dSJacob Faibussowitsch PetscCall(MatLUFactorNumeric_SeqAIJ_inplace(outA, inA, info)); 2614137fb511SHong Zhang } else { 26159566063dSJacob Faibussowitsch PetscCall(MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA, inA, info)); 2616137fb511SHong Zhang } 26173a40ed3dSBarry Smith PetscFunctionReturn(0); 2618a871dcd8SBarry Smith } 2619a871dcd8SBarry Smith 26209371c9d4SSatish Balay PetscErrorCode MatScale_SeqAIJ(Mat inA, PetscScalar alpha) { 2621f0b747eeSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)inA->data; 2622dfa0f9e5SStefano Zampini PetscScalar *v; 2623c5df96a5SBarry Smith PetscBLASInt one = 1, bnz; 26243a40ed3dSBarry Smith 26253a40ed3dSBarry Smith PetscFunctionBegin; 26269566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(inA, &v)); 26279566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(a->nz, &bnz)); 2628792fecdfSBarry Smith PetscCallBLAS("BLASscal", BLASscal_(&bnz, &alpha, v, &one)); 26299566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 26309566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(inA, &v)); 26319566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(inA)); 26323a40ed3dSBarry Smith PetscFunctionReturn(0); 2633f0b747eeSBarry Smith } 2634f0b747eeSBarry Smith 26359371c9d4SSatish Balay PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj) { 263616b64355SHong Zhang PetscInt i; 263716b64355SHong Zhang 263816b64355SHong Zhang PetscFunctionBegin; 263916b64355SHong Zhang if (!submatj->id) { /* delete data that are linked only to submats[id=0] */ 26409566063dSJacob Faibussowitsch PetscCall(PetscFree4(submatj->sbuf1, submatj->ptr, submatj->tmp, submatj->ctr)); 264116b64355SHong Zhang 264248a46eb9SPierre Jolivet for (i = 0; i < submatj->nrqr; ++i) PetscCall(PetscFree(submatj->sbuf2[i])); 26439566063dSJacob Faibussowitsch PetscCall(PetscFree3(submatj->sbuf2, submatj->req_size, submatj->req_source1)); 264416b64355SHong Zhang 264516b64355SHong Zhang if (submatj->rbuf1) { 26469566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rbuf1[0])); 26479566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rbuf1)); 264816b64355SHong Zhang } 264916b64355SHong Zhang 265048a46eb9SPierre Jolivet for (i = 0; i < submatj->nrqs; ++i) PetscCall(PetscFree(submatj->rbuf3[i])); 26519566063dSJacob Faibussowitsch PetscCall(PetscFree3(submatj->req_source2, submatj->rbuf2, submatj->rbuf3)); 26529566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->pa)); 265316b64355SHong Zhang } 265416b64355SHong Zhang 265516b64355SHong Zhang #if defined(PETSC_USE_CTABLE) 26569566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy((PetscTable *)&submatj->rmap)); 26579566063dSJacob Faibussowitsch if (submatj->cmap_loc) PetscCall(PetscFree(submatj->cmap_loc)); 26589566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rmap_loc)); 265916b64355SHong Zhang #else 26609566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rmap)); 266116b64355SHong Zhang #endif 266216b64355SHong Zhang 266316b64355SHong Zhang if (!submatj->allcolumns) { 266416b64355SHong Zhang #if defined(PETSC_USE_CTABLE) 26659566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy((PetscTable *)&submatj->cmap)); 266616b64355SHong Zhang #else 26679566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->cmap)); 266816b64355SHong Zhang #endif 266916b64355SHong Zhang } 26709566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->row2proc)); 267116b64355SHong Zhang 26729566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj)); 267316b64355SHong Zhang PetscFunctionReturn(0); 267416b64355SHong Zhang } 267516b64355SHong Zhang 26769371c9d4SSatish Balay PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C) { 267716b64355SHong Zhang Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data; 26785c39f6d9SHong Zhang Mat_SubSppt *submatj = c->submatis1; 267916b64355SHong Zhang 268016b64355SHong Zhang PetscFunctionBegin; 26819566063dSJacob Faibussowitsch PetscCall((*submatj->destroy)(C)); 26829566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrix_Private(submatj)); 268316b64355SHong Zhang PetscFunctionReturn(0); 268416b64355SHong Zhang } 268516b64355SHong Zhang 268689a1a59bSHong Zhang /* Note this has code duplication with MatDestroySubMatrices_SeqBAIJ() */ 26879371c9d4SSatish Balay PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n, Mat *mat[]) { 26882d033e1fSHong Zhang PetscInt i; 26890fb991dcSHong Zhang Mat C; 26900fb991dcSHong Zhang Mat_SeqAIJ *c; 26910fb991dcSHong Zhang Mat_SubSppt *submatj; 26922d033e1fSHong Zhang 26932d033e1fSHong Zhang PetscFunctionBegin; 26942d033e1fSHong Zhang for (i = 0; i < n; i++) { 26950fb991dcSHong Zhang C = (*mat)[i]; 26960fb991dcSHong Zhang c = (Mat_SeqAIJ *)C->data; 26970fb991dcSHong Zhang submatj = c->submatis1; 26982d033e1fSHong Zhang if (submatj) { 2699682e4c99SStefano Zampini if (--((PetscObject)C)->refct <= 0) { 270026cc229bSBarry Smith PetscCall(PetscFree(C->factorprefix)); 27019566063dSJacob Faibussowitsch PetscCall((*submatj->destroy)(C)); 27029566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrix_Private(submatj)); 27039566063dSJacob Faibussowitsch PetscCall(PetscFree(C->defaultvectype)); 27049566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->rmap)); 27059566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->cmap)); 27069566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(&C)); 2707682e4c99SStefano Zampini } 27082d033e1fSHong Zhang } else { 27099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 27102d033e1fSHong Zhang } 27112d033e1fSHong Zhang } 271286e85357SHong Zhang 271363a75b2aSHong Zhang /* Destroy Dummy submatrices created for reuse */ 27149566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices_Dummy(n, mat)); 271563a75b2aSHong Zhang 27169566063dSJacob Faibussowitsch PetscCall(PetscFree(*mat)); 27172d033e1fSHong Zhang PetscFunctionReturn(0); 27182d033e1fSHong Zhang } 27192d033e1fSHong Zhang 27209371c9d4SSatish Balay PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[]) { 272197f1f81fSBarry Smith PetscInt i; 2722cddf8d76SBarry Smith 27233a40ed3dSBarry Smith PetscFunctionBegin; 272448a46eb9SPierre Jolivet if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n + 1, B)); 2725cddf8d76SBarry Smith 272648a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqAIJ(A, irow[i], icol[i], PETSC_DECIDE, scall, &(*B)[i])); 27273a40ed3dSBarry Smith PetscFunctionReturn(0); 2728cddf8d76SBarry Smith } 2729cddf8d76SBarry Smith 27309371c9d4SSatish Balay PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A, PetscInt is_max, IS is[], PetscInt ov) { 2731e4d965acSSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 27325d0c19d7SBarry Smith PetscInt row, i, j, k, l, m, n, *nidx, isz, val; 27335d0c19d7SBarry Smith const PetscInt *idx; 273497f1f81fSBarry Smith PetscInt start, end, *ai, *aj; 2735f1af5d2fSBarry Smith PetscBT table; 2736bbd702dbSSatish Balay 27373a40ed3dSBarry Smith PetscFunctionBegin; 2738d0f46423SBarry Smith m = A->rmap->n; 2739e4d965acSSatish Balay ai = a->i; 2740bfeeae90SHong Zhang aj = a->j; 27418a047759SSatish Balay 274208401ef6SPierre Jolivet PetscCheck(ov >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "illegal negative overlap value used"); 274306763907SSatish Balay 27449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nidx)); 27459566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(m, &table)); 274606763907SSatish Balay 2747e4d965acSSatish Balay for (i = 0; i < is_max; i++) { 2748b97fc60eSLois Curfman McInnes /* Initialize the two local arrays */ 2749e4d965acSSatish Balay isz = 0; 27509566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(m, table)); 2751e4d965acSSatish Balay 2752e4d965acSSatish Balay /* Extract the indices, assume there can be duplicate entries */ 27539566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is[i], &idx)); 27549566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is[i], &n)); 2755e4d965acSSatish Balay 2756dd097bc3SLois Curfman McInnes /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 2757e4d965acSSatish Balay for (j = 0; j < n; ++j) { 27582205254eSKarl Rupp if (!PetscBTLookupSet(table, idx[j])) nidx[isz++] = idx[j]; 27594dcbc457SBarry Smith } 27609566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is[i], &idx)); 27619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is[i])); 2762e4d965acSSatish Balay 276304a348a9SBarry Smith k = 0; 276404a348a9SBarry Smith for (j = 0; j < ov; j++) { /* for each overlap */ 276504a348a9SBarry Smith n = isz; 276606763907SSatish Balay for (; k < n; k++) { /* do only those rows in nidx[k], which are not done yet */ 2767e4d965acSSatish Balay row = nidx[k]; 2768e4d965acSSatish Balay start = ai[row]; 2769e4d965acSSatish Balay end = ai[row + 1]; 277004a348a9SBarry Smith for (l = start; l < end; l++) { 2771efb16452SHong Zhang val = aj[l]; 27722205254eSKarl Rupp if (!PetscBTLookupSet(table, val)) nidx[isz++] = val; 2773e4d965acSSatish Balay } 2774e4d965acSSatish Balay } 2775e4d965acSSatish Balay } 27769566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, isz, nidx, PETSC_COPY_VALUES, (is + i))); 2777e4d965acSSatish Balay } 27789566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&table)); 27799566063dSJacob Faibussowitsch PetscCall(PetscFree(nidx)); 27803a40ed3dSBarry Smith PetscFunctionReturn(0); 27814dcbc457SBarry Smith } 278217ab2063SBarry Smith 27830513a670SBarry Smith /* -------------------------------------------------------------- */ 27849371c9d4SSatish Balay PetscErrorCode MatPermute_SeqAIJ(Mat A, IS rowp, IS colp, Mat *B) { 27850513a670SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 27863b98c0a2SBarry Smith PetscInt i, nz = 0, m = A->rmap->n, n = A->cmap->n; 27875d0c19d7SBarry Smith const PetscInt *row, *col; 27885d0c19d7SBarry Smith PetscInt *cnew, j, *lens; 278956cd22aeSBarry Smith IS icolp, irowp; 27900298fd71SBarry Smith PetscInt *cwork = NULL; 27910298fd71SBarry Smith PetscScalar *vwork = NULL; 27920513a670SBarry Smith 27933a40ed3dSBarry Smith PetscFunctionBegin; 27949566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rowp, PETSC_DECIDE, &irowp)); 27959566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irowp, &row)); 27969566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(colp, PETSC_DECIDE, &icolp)); 27979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icolp, &col)); 27980513a670SBarry Smith 27990513a670SBarry Smith /* determine lengths of permuted rows */ 28009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &lens)); 28012205254eSKarl Rupp for (i = 0; i < m; i++) lens[row[i]] = a->i[i + 1] - a->i[i]; 28029566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 28039566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, m, n, m, n)); 28049566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(*B, A, A)); 28059566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, ((PetscObject)A)->type_name)); 28069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*B, 0, lens)); 28079566063dSJacob Faibussowitsch PetscCall(PetscFree(lens)); 28080513a670SBarry Smith 28099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &cnew)); 28100513a670SBarry Smith for (i = 0; i < m; i++) { 28119566063dSJacob Faibussowitsch PetscCall(MatGetRow_SeqAIJ(A, i, &nz, &cwork, &vwork)); 28122205254eSKarl Rupp for (j = 0; j < nz; j++) cnew[j] = col[cwork[j]]; 28139566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(*B, 1, &row[i], nz, cnew, vwork, INSERT_VALUES)); 28149566063dSJacob Faibussowitsch PetscCall(MatRestoreRow_SeqAIJ(A, i, &nz, &cwork, &vwork)); 28150513a670SBarry Smith } 28169566063dSJacob Faibussowitsch PetscCall(PetscFree(cnew)); 28172205254eSKarl Rupp 28183c7d62e4SBarry Smith (*B)->assembled = PETSC_FALSE; 28192205254eSKarl Rupp 28208c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 28219566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(*B, A->boundtocpu)); 28229fe5e383SStefano Zampini #endif 28239566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 28249566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 28259566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irowp, &row)); 28269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icolp, &col)); 28279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irowp)); 28289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icolp)); 282948a46eb9SPierre Jolivet if (rowp == colp) PetscCall(MatPropagateSymmetryOptions(A, *B)); 28303a40ed3dSBarry Smith PetscFunctionReturn(0); 28310513a670SBarry Smith } 28320513a670SBarry Smith 28339371c9d4SSatish Balay PetscErrorCode MatCopy_SeqAIJ(Mat A, Mat B, MatStructure str) { 2834cb5b572fSBarry Smith PetscFunctionBegin; 283533f4a19fSKris Buschelman /* If the two matrices have the same copy implementation, use fast copy. */ 283633f4a19fSKris Buschelman if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) { 2837be6bf707SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2838be6bf707SBarry Smith Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 28392e5835c6SStefano Zampini const PetscScalar *aa; 2840be6bf707SBarry Smith 28419566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 284208401ef6SPierre 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]); 28439566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->a, aa, a->i[A->rmap->n])); 28449566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 28459566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 2846cb5b572fSBarry Smith } else { 28479566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 2848cb5b572fSBarry Smith } 2849cb5b572fSBarry Smith PetscFunctionReturn(0); 2850cb5b572fSBarry Smith } 2851cb5b572fSBarry Smith 28529371c9d4SSatish Balay PetscErrorCode MatSetUp_SeqAIJ(Mat A) { 2853273d9f13SBarry Smith PetscFunctionBegin; 28549566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A, PETSC_DEFAULT, NULL)); 2855273d9f13SBarry Smith PetscFunctionReturn(0); 2856273d9f13SBarry Smith } 2857273d9f13SBarry Smith 28589371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A, PetscScalar *array[]) { 28596c0721eeSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 28606e111a19SKarl Rupp 28616c0721eeSBarry Smith PetscFunctionBegin; 28626c0721eeSBarry Smith *array = a->a; 28636c0721eeSBarry Smith PetscFunctionReturn(0); 28646c0721eeSBarry Smith } 28656c0721eeSBarry Smith 28669371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A, PetscScalar *array[]) { 28676c0721eeSBarry Smith PetscFunctionBegin; 2868f38c1e66SStefano Zampini *array = NULL; 28696c0721eeSBarry Smith PetscFunctionReturn(0); 28706c0721eeSBarry Smith } 2871273d9f13SBarry Smith 28728229c054SShri Abhyankar /* 28738229c054SShri Abhyankar Computes the number of nonzeros per row needed for preallocation when X and Y 28748229c054SShri Abhyankar have different nonzero structure. 28758229c054SShri Abhyankar */ 28769371c9d4SSatish Balay PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m, const PetscInt *xi, const PetscInt *xj, const PetscInt *yi, const PetscInt *yj, PetscInt *nnz) { 2877b264fe52SHong Zhang PetscInt i, j, k, nzx, nzy; 2878ec7775f6SShri Abhyankar 2879ec7775f6SShri Abhyankar PetscFunctionBegin; 2880ec7775f6SShri Abhyankar /* Set the number of nonzeros in the new matrix */ 2881ec7775f6SShri Abhyankar for (i = 0; i < m; i++) { 2882b264fe52SHong Zhang const PetscInt *xjj = xj + xi[i], *yjj = yj + yi[i]; 2883b264fe52SHong Zhang nzx = xi[i + 1] - xi[i]; 2884b264fe52SHong Zhang nzy = yi[i + 1] - yi[i]; 28858af7cee1SJed Brown nnz[i] = 0; 28868af7cee1SJed Brown for (j = 0, k = 0; j < nzx; j++) { /* Point in X */ 2887b264fe52SHong Zhang for (; k < nzy && yjj[k] < xjj[j]; k++) nnz[i]++; /* Catch up to X */ 2888b264fe52SHong Zhang if (k < nzy && yjj[k] == xjj[j]) k++; /* Skip duplicate */ 28898af7cee1SJed Brown nnz[i]++; 28908af7cee1SJed Brown } 28918af7cee1SJed Brown for (; k < nzy; k++) nnz[i]++; 2892ec7775f6SShri Abhyankar } 2893ec7775f6SShri Abhyankar PetscFunctionReturn(0); 2894ec7775f6SShri Abhyankar } 2895ec7775f6SShri Abhyankar 28969371c9d4SSatish Balay PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y, Mat X, PetscInt *nnz) { 2897b264fe52SHong Zhang PetscInt m = Y->rmap->N; 2898b264fe52SHong Zhang Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data; 2899b264fe52SHong Zhang Mat_SeqAIJ *y = (Mat_SeqAIJ *)Y->data; 2900b264fe52SHong Zhang 2901b264fe52SHong Zhang PetscFunctionBegin; 2902b264fe52SHong Zhang /* Set the number of nonzeros in the new matrix */ 29039566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqX_private(m, x->i, x->j, y->i, y->j, nnz)); 2904b264fe52SHong Zhang PetscFunctionReturn(0); 2905b264fe52SHong Zhang } 2906b264fe52SHong Zhang 29079371c9d4SSatish Balay PetscErrorCode MatAXPY_SeqAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str) { 2908ac90fabeSBarry Smith Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data, *y = (Mat_SeqAIJ *)Y->data; 2909ac90fabeSBarry Smith 2910ac90fabeSBarry Smith PetscFunctionBegin; 2911134adf20SPierre Jolivet if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) { 2912134adf20SPierre Jolivet PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE; 2913134adf20SPierre Jolivet if (e) { 29149566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->i, y->i, Y->rmap->n + 1, &e)); 291581fa06acSBarry Smith if (e) { 29169566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->j, y->j, y->nz, &e)); 2917134adf20SPierre Jolivet if (e) str = SAME_NONZERO_PATTERN; 291881fa06acSBarry Smith } 291981fa06acSBarry Smith } 292054c59aa7SJacob Faibussowitsch if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN"); 292181fa06acSBarry Smith } 2922ac90fabeSBarry Smith if (str == SAME_NONZERO_PATTERN) { 29232e5835c6SStefano Zampini const PetscScalar *xa; 29242e5835c6SStefano Zampini PetscScalar *ya, alpha = a; 292581fa06acSBarry Smith PetscBLASInt one = 1, bnz; 292681fa06acSBarry Smith 29279566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(x->nz, &bnz)); 29289566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Y, &ya)); 29299566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(X, &xa)); 2930792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, xa, &one, ya, &one)); 29319566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(X, &xa)); 29329566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Y, &ya)); 29339566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * bnz)); 29349566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(Y)); 29359566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 2936ab784542SHong Zhang } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 29379566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 2938ac90fabeSBarry Smith } else { 29398229c054SShri Abhyankar Mat B; 29408229c054SShri Abhyankar PetscInt *nnz; 29419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Y->rmap->N, &nnz)); 29429566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B)); 29439566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name)); 29449566063dSJacob Faibussowitsch PetscCall(MatSetLayouts(B, Y->rmap, Y->cmap)); 29459566063dSJacob Faibussowitsch PetscCall(MatSetType(B, ((PetscObject)Y)->type_name)); 29469566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqAIJ(Y, X, nnz)); 29479566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz)); 29489566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 29499566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 29509bb234a9SBarry Smith PetscCall(MatSeqAIJCheckInode(Y)); 29519566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 2952ac90fabeSBarry Smith } 2953ac90fabeSBarry Smith PetscFunctionReturn(0); 2954ac90fabeSBarry Smith } 2955ac90fabeSBarry Smith 29569371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat) { 2957354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX) 2958354c94deSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2959354c94deSBarry Smith PetscInt i, nz; 2960354c94deSBarry Smith PetscScalar *a; 2961354c94deSBarry Smith 2962354c94deSBarry Smith PetscFunctionBegin; 2963354c94deSBarry Smith nz = aij->nz; 29649566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(mat, &a)); 29652205254eSKarl Rupp for (i = 0; i < nz; i++) a[i] = PetscConj(a[i]); 29669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(mat, &a)); 2967354c94deSBarry Smith #else 2968354c94deSBarry Smith PetscFunctionBegin; 2969354c94deSBarry Smith #endif 2970354c94deSBarry Smith PetscFunctionReturn(0); 2971354c94deSBarry Smith } 2972354c94deSBarry Smith 29739371c9d4SSatish Balay PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 2974e34fafa9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2975d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 2976e34fafa9SBarry Smith PetscReal atmp; 2977985db425SBarry Smith PetscScalar *x; 2978ce496241SStefano Zampini const MatScalar *aa, *av; 2979e34fafa9SBarry Smith 2980e34fafa9SBarry Smith PetscFunctionBegin; 298128b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 29829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 2983ce496241SStefano Zampini aa = av; 2984e34fafa9SBarry Smith ai = a->i; 2985e34fafa9SBarry Smith aj = a->j; 2986e34fafa9SBarry Smith 29879566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 29889566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 29899566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 299008401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 2991e34fafa9SBarry Smith for (i = 0; i < m; i++) { 29929371c9d4SSatish Balay ncols = ai[1] - ai[0]; 29939371c9d4SSatish Balay ai++; 2994e34fafa9SBarry Smith for (j = 0; j < ncols; j++) { 2995985db425SBarry Smith atmp = PetscAbsScalar(*aa); 29969371c9d4SSatish Balay if (PetscAbsScalar(x[i]) < atmp) { 29979371c9d4SSatish Balay x[i] = atmp; 29989371c9d4SSatish Balay if (idx) idx[i] = *aj; 29999371c9d4SSatish Balay } 30009371c9d4SSatish Balay aa++; 30019371c9d4SSatish Balay aj++; 3002985db425SBarry Smith } 3003985db425SBarry Smith } 30049566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 30059566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3006985db425SBarry Smith PetscFunctionReturn(0); 3007985db425SBarry Smith } 3008985db425SBarry Smith 30099371c9d4SSatish Balay PetscErrorCode MatGetRowMax_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 3010985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3011d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 3012985db425SBarry Smith PetscScalar *x; 3013ce496241SStefano Zampini const MatScalar *aa, *av; 3014985db425SBarry Smith 3015985db425SBarry Smith PetscFunctionBegin; 301628b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 30179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3018ce496241SStefano Zampini aa = av; 3019985db425SBarry Smith ai = a->i; 3020985db425SBarry Smith aj = a->j; 3021985db425SBarry Smith 30229566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 30239566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 30249566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 302508401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3026985db425SBarry Smith for (i = 0; i < m; i++) { 30279371c9d4SSatish Balay ncols = ai[1] - ai[0]; 30289371c9d4SSatish Balay ai++; 3029d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 30309371c9d4SSatish Balay x[i] = *aa; 30319371c9d4SSatish Balay if (idx) idx[i] = 0; 3032985db425SBarry Smith } else { /* row is sparse so already KNOW maximum is 0.0 or higher */ 3033985db425SBarry Smith x[i] = 0.0; 3034985db425SBarry Smith if (idx) { 3035985db425SBarry Smith for (j = 0; j < ncols; j++) { /* find first implicit 0.0 in the row */ 3036985db425SBarry Smith if (aj[j] > j) { 3037985db425SBarry Smith idx[i] = j; 3038985db425SBarry Smith break; 3039985db425SBarry Smith } 3040985db425SBarry Smith } 30411a254869SHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 30421a254869SHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3043985db425SBarry Smith } 3044985db425SBarry Smith } 3045985db425SBarry Smith for (j = 0; j < ncols; j++) { 30469371c9d4SSatish Balay if (PetscRealPart(x[i]) < PetscRealPart(*aa)) { 30479371c9d4SSatish Balay x[i] = *aa; 30489371c9d4SSatish Balay if (idx) idx[i] = *aj; 30499371c9d4SSatish Balay } 30509371c9d4SSatish Balay aa++; 30519371c9d4SSatish Balay aj++; 3052985db425SBarry Smith } 3053985db425SBarry Smith } 30549566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 30559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3056985db425SBarry Smith PetscFunctionReturn(0); 3057985db425SBarry Smith } 3058985db425SBarry Smith 30599371c9d4SSatish Balay PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 3060c87e5d42SMatthew Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3061c87e5d42SMatthew Knepley PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 3062ce496241SStefano Zampini PetscScalar *x; 3063ce496241SStefano Zampini const MatScalar *aa, *av; 3064c87e5d42SMatthew Knepley 3065c87e5d42SMatthew Knepley PetscFunctionBegin; 30669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3067ce496241SStefano Zampini aa = av; 3068c87e5d42SMatthew Knepley ai = a->i; 3069c87e5d42SMatthew Knepley aj = a->j; 3070c87e5d42SMatthew Knepley 30719566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 30729566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 30739566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 307408401ef6SPierre Jolivet PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n); 3075c87e5d42SMatthew Knepley for (i = 0; i < m; i++) { 30769371c9d4SSatish Balay ncols = ai[1] - ai[0]; 30779371c9d4SSatish Balay ai++; 3078f07e67edSHong Zhang if (ncols == A->cmap->n) { /* row is dense */ 30799371c9d4SSatish Balay x[i] = *aa; 30809371c9d4SSatish Balay if (idx) idx[i] = 0; 3081f07e67edSHong Zhang } else { /* row is sparse so already KNOW minimum is 0.0 or higher */ 3082f07e67edSHong Zhang x[i] = 0.0; 3083f07e67edSHong Zhang if (idx) { /* find first implicit 0.0 in the row */ 3084289a08f5SMatthew Knepley for (j = 0; j < ncols; j++) { 3085f07e67edSHong Zhang if (aj[j] > j) { 3086f07e67edSHong Zhang idx[i] = j; 30872205254eSKarl Rupp break; 30882205254eSKarl Rupp } 3089289a08f5SMatthew Knepley } 3090f07e67edSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3091f07e67edSHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3092f07e67edSHong Zhang } 3093289a08f5SMatthew Knepley } 3094c87e5d42SMatthew Knepley for (j = 0; j < ncols; j++) { 30959371c9d4SSatish Balay if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) { 30969371c9d4SSatish Balay x[i] = *aa; 30979371c9d4SSatish Balay if (idx) idx[i] = *aj; 30989371c9d4SSatish Balay } 30999371c9d4SSatish Balay aa++; 31009371c9d4SSatish Balay aj++; 3101c87e5d42SMatthew Knepley } 3102c87e5d42SMatthew Knepley } 31039566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 31049566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3105c87e5d42SMatthew Knepley PetscFunctionReturn(0); 3106c87e5d42SMatthew Knepley } 3107c87e5d42SMatthew Knepley 31089371c9d4SSatish Balay PetscErrorCode MatGetRowMin_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 3109985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3110d9ca1df4SBarry Smith PetscInt i, j, m = A->rmap->n, ncols, n; 3111d9ca1df4SBarry Smith const PetscInt *ai, *aj; 3112985db425SBarry Smith PetscScalar *x; 3113ce496241SStefano Zampini const MatScalar *aa, *av; 3114985db425SBarry Smith 3115985db425SBarry Smith PetscFunctionBegin; 311628b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 31179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3118ce496241SStefano Zampini aa = av; 3119985db425SBarry Smith ai = a->i; 3120985db425SBarry Smith aj = a->j; 3121985db425SBarry Smith 31229566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 31239566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 31249566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 312508401ef6SPierre Jolivet PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3126985db425SBarry Smith for (i = 0; i < m; i++) { 31279371c9d4SSatish Balay ncols = ai[1] - ai[0]; 31289371c9d4SSatish Balay ai++; 3129d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 31309371c9d4SSatish Balay x[i] = *aa; 31319371c9d4SSatish Balay if (idx) idx[i] = 0; 3132985db425SBarry Smith } else { /* row is sparse so already KNOW minimum is 0.0 or lower */ 3133985db425SBarry Smith x[i] = 0.0; 3134985db425SBarry Smith if (idx) { /* find first implicit 0.0 in the row */ 3135985db425SBarry Smith for (j = 0; j < ncols; j++) { 3136985db425SBarry Smith if (aj[j] > j) { 3137985db425SBarry Smith idx[i] = j; 3138985db425SBarry Smith break; 3139985db425SBarry Smith } 3140985db425SBarry Smith } 3141fa213d2fSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3142fa213d2fSHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3143985db425SBarry Smith } 3144985db425SBarry Smith } 3145985db425SBarry Smith for (j = 0; j < ncols; j++) { 31469371c9d4SSatish Balay if (PetscRealPart(x[i]) > PetscRealPart(*aa)) { 31479371c9d4SSatish Balay x[i] = *aa; 31489371c9d4SSatish Balay if (idx) idx[i] = *aj; 31499371c9d4SSatish Balay } 31509371c9d4SSatish Balay aa++; 31519371c9d4SSatish Balay aj++; 3152e34fafa9SBarry Smith } 3153e34fafa9SBarry Smith } 31549566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 31559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3156e34fafa9SBarry Smith PetscFunctionReturn(0); 3157e34fafa9SBarry Smith } 3158bbead8a2SBarry Smith 31599371c9d4SSatish Balay PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A, const PetscScalar **values) { 3160bbead8a2SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 316133d57670SJed Brown PetscInt i, bs = PetscAbs(A->rmap->bs), mbs = A->rmap->n / bs, ipvt[5], bs2 = bs * bs, *v_pivots, ij[7], *IJ, j; 3162bbead8a2SBarry Smith MatScalar *diag, work[25], *v_work; 31630da83c2eSBarry Smith const PetscReal shift = 0.0; 31641a9391e3SHong Zhang PetscBool allowzeropivot, zeropivotdetected = PETSC_FALSE; 3165bbead8a2SBarry Smith 3166bbead8a2SBarry Smith PetscFunctionBegin; 3167a455e926SHong Zhang allowzeropivot = PetscNot(A->erroriffailure); 31684a0d0026SBarry Smith if (a->ibdiagvalid) { 31694a0d0026SBarry Smith if (values) *values = a->ibdiag; 31704a0d0026SBarry Smith PetscFunctionReturn(0); 31714a0d0026SBarry Smith } 31729566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 3173bbead8a2SBarry Smith if (!a->ibdiag) { 31749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bs2 * mbs, &a->ibdiag)); 31759566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A, bs2 * mbs * sizeof(PetscScalar))); 3176bbead8a2SBarry Smith } 3177bbead8a2SBarry Smith diag = a->ibdiag; 3178bbead8a2SBarry Smith if (values) *values = a->ibdiag; 3179bbead8a2SBarry Smith /* factor and invert each block */ 3180bbead8a2SBarry Smith switch (bs) { 3181bbead8a2SBarry Smith case 1: 3182bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 31839566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 1, &i, 1, &i, diag + i)); 3184ec1892c8SHong Zhang if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) { 3185ec1892c8SHong Zhang if (allowzeropivot) { 31867b6c816cSBarry Smith A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 31877b6c816cSBarry Smith A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]); 31887b6c816cSBarry Smith A->factorerror_zeropivot_row = i; 31899566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n", i, (double)PetscAbsScalar(diag[i]), (double)PETSC_MACHINE_EPSILON)); 319098921bdaSJacob 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); 3191ec1892c8SHong Zhang } 3192bbead8a2SBarry Smith diag[i] = (PetscScalar)1.0 / (diag[i] + shift); 3193bbead8a2SBarry Smith } 3194bbead8a2SBarry Smith break; 3195bbead8a2SBarry Smith case 2: 3196bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 31979371c9d4SSatish Balay ij[0] = 2 * i; 31989371c9d4SSatish Balay ij[1] = 2 * i + 1; 31999566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 2, ij, 2, ij, diag)); 32009566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected)); 32017b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32029566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_2(diag)); 3203bbead8a2SBarry Smith diag += 4; 3204bbead8a2SBarry Smith } 3205bbead8a2SBarry Smith break; 3206bbead8a2SBarry Smith case 3: 3207bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32089371c9d4SSatish Balay ij[0] = 3 * i; 32099371c9d4SSatish Balay ij[1] = 3 * i + 1; 32109371c9d4SSatish Balay ij[2] = 3 * i + 2; 32119566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 3, ij, 3, ij, diag)); 32129566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected)); 32137b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32149566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_3(diag)); 3215bbead8a2SBarry Smith diag += 9; 3216bbead8a2SBarry Smith } 3217bbead8a2SBarry Smith break; 3218bbead8a2SBarry Smith case 4: 3219bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32209371c9d4SSatish Balay ij[0] = 4 * i; 32219371c9d4SSatish Balay ij[1] = 4 * i + 1; 32229371c9d4SSatish Balay ij[2] = 4 * i + 2; 32239371c9d4SSatish Balay ij[3] = 4 * i + 3; 32249566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 4, ij, 4, ij, diag)); 32259566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected)); 32267b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32279566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_4(diag)); 3228bbead8a2SBarry Smith diag += 16; 3229bbead8a2SBarry Smith } 3230bbead8a2SBarry Smith break; 3231bbead8a2SBarry Smith case 5: 3232bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32339371c9d4SSatish Balay ij[0] = 5 * i; 32349371c9d4SSatish Balay ij[1] = 5 * i + 1; 32359371c9d4SSatish Balay ij[2] = 5 * i + 2; 32369371c9d4SSatish Balay ij[3] = 5 * i + 3; 32379371c9d4SSatish Balay ij[4] = 5 * i + 4; 32389566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 5, ij, 5, ij, diag)); 32399566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected)); 32407b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32419566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_5(diag)); 3242bbead8a2SBarry Smith diag += 25; 3243bbead8a2SBarry Smith } 3244bbead8a2SBarry Smith break; 3245bbead8a2SBarry Smith case 6: 3246bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32479371c9d4SSatish Balay ij[0] = 6 * i; 32489371c9d4SSatish Balay ij[1] = 6 * i + 1; 32499371c9d4SSatish Balay ij[2] = 6 * i + 2; 32509371c9d4SSatish Balay ij[3] = 6 * i + 3; 32519371c9d4SSatish Balay ij[4] = 6 * i + 4; 32529371c9d4SSatish Balay ij[5] = 6 * i + 5; 32539566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 6, ij, 6, ij, diag)); 32549566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected)); 32557b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32569566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_6(diag)); 3257bbead8a2SBarry Smith diag += 36; 3258bbead8a2SBarry Smith } 3259bbead8a2SBarry Smith break; 3260bbead8a2SBarry Smith case 7: 3261bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32629371c9d4SSatish Balay ij[0] = 7 * i; 32639371c9d4SSatish Balay ij[1] = 7 * i + 1; 32649371c9d4SSatish Balay ij[2] = 7 * i + 2; 32659371c9d4SSatish Balay ij[3] = 7 * i + 3; 32669371c9d4SSatish Balay ij[4] = 7 * i + 4; 32679371c9d4SSatish Balay ij[5] = 7 * i + 5; 32689371c9d4SSatish Balay ij[5] = 7 * i + 6; 32699566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 7, ij, 7, ij, diag)); 32709566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected)); 32717b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32729566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_7(diag)); 3273bbead8a2SBarry Smith diag += 49; 3274bbead8a2SBarry Smith } 3275bbead8a2SBarry Smith break; 3276bbead8a2SBarry Smith default: 32779566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(bs, &v_work, bs, &v_pivots, bs, &IJ)); 3278bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 3279ad540459SPierre Jolivet for (j = 0; j < bs; j++) IJ[j] = bs * i + j; 32809566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, bs, IJ, bs, IJ, diag)); 32819566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A(bs, diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected)); 32827b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32839566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_N(diag, bs)); 3284bbead8a2SBarry Smith diag += bs2; 3285bbead8a2SBarry Smith } 32869566063dSJacob Faibussowitsch PetscCall(PetscFree3(v_work, v_pivots, IJ)); 3287bbead8a2SBarry Smith } 3288bbead8a2SBarry Smith a->ibdiagvalid = PETSC_TRUE; 3289bbead8a2SBarry Smith PetscFunctionReturn(0); 3290bbead8a2SBarry Smith } 3291bbead8a2SBarry Smith 32929371c9d4SSatish Balay static PetscErrorCode MatSetRandom_SeqAIJ(Mat x, PetscRandom rctx) { 329373a71a0fSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data; 3294fff043a9SJunchao Zhang PetscScalar a, *aa; 329573a71a0fSBarry Smith PetscInt m, n, i, j, col; 329673a71a0fSBarry Smith 329773a71a0fSBarry Smith PetscFunctionBegin; 329873a71a0fSBarry Smith if (!x->assembled) { 32999566063dSJacob Faibussowitsch PetscCall(MatGetSize(x, &m, &n)); 330073a71a0fSBarry Smith for (i = 0; i < m; i++) { 330173a71a0fSBarry Smith for (j = 0; j < aij->imax[i]; j++) { 33029566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx, &a)); 330373a71a0fSBarry Smith col = (PetscInt)(n * PetscRealPart(a)); 33049566063dSJacob Faibussowitsch PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES)); 330573a71a0fSBarry Smith } 330673a71a0fSBarry Smith } 3307e2ce353bSJunchao Zhang } else { 33089566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayWrite(x, &aa)); 33099566063dSJacob Faibussowitsch for (i = 0; i < aij->nz; i++) PetscCall(PetscRandomGetValue(rctx, aa + i)); 33109566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayWrite(x, &aa)); 3311e2ce353bSJunchao Zhang } 33129566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 33139566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 331473a71a0fSBarry Smith PetscFunctionReturn(0); 331573a71a0fSBarry Smith } 331673a71a0fSBarry Smith 3317679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */ 33189371c9d4SSatish Balay PetscErrorCode MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x, PetscInt low, PetscInt high, PetscRandom rctx) { 3319679944adSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data; 3320679944adSJunchao Zhang PetscScalar a; 3321679944adSJunchao Zhang PetscInt m, n, i, j, col, nskip; 3322679944adSJunchao Zhang 3323679944adSJunchao Zhang PetscFunctionBegin; 3324679944adSJunchao Zhang nskip = high - low; 33259566063dSJacob Faibussowitsch PetscCall(MatGetSize(x, &m, &n)); 3326679944adSJunchao Zhang n -= nskip; /* shrink number of columns where nonzeros can be set */ 3327679944adSJunchao Zhang for (i = 0; i < m; i++) { 3328679944adSJunchao Zhang for (j = 0; j < aij->imax[i]; j++) { 33299566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx, &a)); 3330679944adSJunchao Zhang col = (PetscInt)(n * PetscRealPart(a)); 3331679944adSJunchao Zhang if (col >= low) col += nskip; /* shift col rightward to skip the hole */ 33329566063dSJacob Faibussowitsch PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES)); 3333679944adSJunchao Zhang } 3334e2ce353bSJunchao Zhang } 33359566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 33369566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 3337679944adSJunchao Zhang PetscFunctionReturn(0); 3338679944adSJunchao Zhang } 3339679944adSJunchao Zhang 3340682d7d0cSBarry Smith /* -------------------------------------------------------------------*/ 33410a6ffc59SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ, 3342cb5b572fSBarry Smith MatGetRow_SeqAIJ, 3343cb5b572fSBarry Smith MatRestoreRow_SeqAIJ, 3344cb5b572fSBarry Smith MatMult_SeqAIJ, 334597304618SKris Buschelman /* 4*/ MatMultAdd_SeqAIJ, 33467c922b88SBarry Smith MatMultTranspose_SeqAIJ, 33477c922b88SBarry Smith MatMultTransposeAdd_SeqAIJ, 3348f4259b30SLisandro Dalcin NULL, 3349f4259b30SLisandro Dalcin NULL, 3350f4259b30SLisandro Dalcin NULL, 3351f4259b30SLisandro Dalcin /* 10*/ NULL, 3352cb5b572fSBarry Smith MatLUFactor_SeqAIJ, 3353f4259b30SLisandro Dalcin NULL, 335441f059aeSBarry Smith MatSOR_SeqAIJ, 335591e9d3e2SHong Zhang MatTranspose_SeqAIJ, 335697304618SKris Buschelman /*1 5*/ MatGetInfo_SeqAIJ, 3357cb5b572fSBarry Smith MatEqual_SeqAIJ, 3358cb5b572fSBarry Smith MatGetDiagonal_SeqAIJ, 3359cb5b572fSBarry Smith MatDiagonalScale_SeqAIJ, 3360cb5b572fSBarry Smith MatNorm_SeqAIJ, 3361f4259b30SLisandro Dalcin /* 20*/ NULL, 3362cb5b572fSBarry Smith MatAssemblyEnd_SeqAIJ, 3363cb5b572fSBarry Smith MatSetOption_SeqAIJ, 3364cb5b572fSBarry Smith MatZeroEntries_SeqAIJ, 3365d519adbfSMatthew Knepley /* 24*/ MatZeroRows_SeqAIJ, 3366f4259b30SLisandro Dalcin NULL, 3367f4259b30SLisandro Dalcin NULL, 3368f4259b30SLisandro Dalcin NULL, 3369f4259b30SLisandro Dalcin NULL, 33704994cf47SJed Brown /* 29*/ MatSetUp_SeqAIJ, 3371f4259b30SLisandro Dalcin NULL, 3372f4259b30SLisandro Dalcin NULL, 3373f4259b30SLisandro Dalcin NULL, 3374f4259b30SLisandro Dalcin NULL, 3375d519adbfSMatthew Knepley /* 34*/ MatDuplicate_SeqAIJ, 3376f4259b30SLisandro Dalcin NULL, 3377f4259b30SLisandro Dalcin NULL, 3378cb5b572fSBarry Smith MatILUFactor_SeqAIJ, 3379f4259b30SLisandro Dalcin NULL, 3380d519adbfSMatthew Knepley /* 39*/ MatAXPY_SeqAIJ, 33817dae84e0SHong Zhang MatCreateSubMatrices_SeqAIJ, 3382cb5b572fSBarry Smith MatIncreaseOverlap_SeqAIJ, 3383cb5b572fSBarry Smith MatGetValues_SeqAIJ, 3384cb5b572fSBarry Smith MatCopy_SeqAIJ, 3385d519adbfSMatthew Knepley /* 44*/ MatGetRowMax_SeqAIJ, 3386cb5b572fSBarry Smith MatScale_SeqAIJ, 33877d68702bSBarry Smith MatShift_SeqAIJ, 338879299369SBarry Smith MatDiagonalSet_SeqAIJ, 33896e169961SBarry Smith MatZeroRowsColumns_SeqAIJ, 339073a71a0fSBarry Smith /* 49*/ MatSetRandom_SeqAIJ, 33913b2fbd54SBarry Smith MatGetRowIJ_SeqAIJ, 33923b2fbd54SBarry Smith MatRestoreRowIJ_SeqAIJ, 33933b2fbd54SBarry Smith MatGetColumnIJ_SeqAIJ, 3394a93ec695SBarry Smith MatRestoreColumnIJ_SeqAIJ, 339593dfae19SHong Zhang /* 54*/ MatFDColoringCreate_SeqXAIJ, 3396f4259b30SLisandro Dalcin NULL, 3397f4259b30SLisandro Dalcin NULL, 3398cda55fadSBarry Smith MatPermute_SeqAIJ, 3399f4259b30SLisandro Dalcin NULL, 3400f4259b30SLisandro Dalcin /* 59*/ NULL, 3401b9b97703SBarry Smith MatDestroy_SeqAIJ, 3402b9b97703SBarry Smith MatView_SeqAIJ, 3403f4259b30SLisandro Dalcin NULL, 3404f4259b30SLisandro Dalcin NULL, 3405f4259b30SLisandro Dalcin /* 64*/ NULL, 3406321b30b9SSatish Balay MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ, 3407f4259b30SLisandro Dalcin NULL, 3408f4259b30SLisandro Dalcin NULL, 3409f4259b30SLisandro Dalcin NULL, 3410d519adbfSMatthew Knepley /* 69*/ MatGetRowMaxAbs_SeqAIJ, 3411c87e5d42SMatthew Knepley MatGetRowMinAbs_SeqAIJ, 3412f4259b30SLisandro Dalcin NULL, 3413f4259b30SLisandro Dalcin NULL, 3414f4259b30SLisandro Dalcin NULL, 3415f4259b30SLisandro Dalcin /* 74*/ NULL, 34163acb8795SBarry Smith MatFDColoringApply_AIJ, 3417f4259b30SLisandro Dalcin NULL, 3418f4259b30SLisandro Dalcin NULL, 3419f4259b30SLisandro Dalcin NULL, 34206ce1633cSBarry Smith /* 79*/ MatFindZeroDiagonals_SeqAIJ, 3421f4259b30SLisandro Dalcin NULL, 3422f4259b30SLisandro Dalcin NULL, 3423f4259b30SLisandro Dalcin NULL, 3424bc011b1eSHong Zhang MatLoad_SeqAIJ, 3425d519adbfSMatthew Knepley /* 84*/ MatIsSymmetric_SeqAIJ, 34261cbb95d3SBarry Smith MatIsHermitian_SeqAIJ, 3427f4259b30SLisandro Dalcin NULL, 3428f4259b30SLisandro Dalcin NULL, 3429f4259b30SLisandro Dalcin NULL, 3430f4259b30SLisandro Dalcin /* 89*/ NULL, 3431f4259b30SLisandro Dalcin NULL, 343226be0446SHong Zhang MatMatMultNumeric_SeqAIJ_SeqAIJ, 3433f4259b30SLisandro Dalcin NULL, 3434f4259b30SLisandro Dalcin NULL, 34358fa4b5a6SHong Zhang /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy, 3436f4259b30SLisandro Dalcin NULL, 3437f4259b30SLisandro Dalcin NULL, 34386fc122caSHong Zhang MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ, 3439f4259b30SLisandro Dalcin NULL, 34404222ddf1SHong Zhang /* 99*/ MatProductSetFromOptions_SeqAIJ, 3441f4259b30SLisandro Dalcin NULL, 3442f4259b30SLisandro Dalcin NULL, 344387d4246cSBarry Smith MatConjugate_SeqAIJ, 3444f4259b30SLisandro Dalcin NULL, 3445d519adbfSMatthew Knepley /*104*/ MatSetValuesRow_SeqAIJ, 344699cafbc1SBarry Smith MatRealPart_SeqAIJ, 3447f5edf698SHong Zhang MatImaginaryPart_SeqAIJ, 3448f4259b30SLisandro Dalcin NULL, 3449f4259b30SLisandro Dalcin NULL, 3450cbd44569SHong Zhang /*109*/ MatMatSolve_SeqAIJ, 3451f4259b30SLisandro Dalcin NULL, 34522af78befSBarry Smith MatGetRowMin_SeqAIJ, 3453f4259b30SLisandro Dalcin NULL, 3454599ef60dSHong Zhang MatMissingDiagonal_SeqAIJ, 3455f4259b30SLisandro Dalcin /*114*/ NULL, 3456f4259b30SLisandro Dalcin NULL, 3457f4259b30SLisandro Dalcin NULL, 3458f4259b30SLisandro Dalcin NULL, 3459f4259b30SLisandro Dalcin NULL, 3460f4259b30SLisandro Dalcin /*119*/ NULL, 3461f4259b30SLisandro Dalcin NULL, 3462f4259b30SLisandro Dalcin NULL, 3463f4259b30SLisandro Dalcin NULL, 3464b3a44c85SBarry Smith MatGetMultiProcBlock_SeqAIJ, 34650716a85fSBarry Smith /*124*/ MatFindNonzeroRows_SeqAIJ, 3466a873a8cdSSam Reynolds MatGetColumnReductions_SeqAIJ, 346737868618SMatthew G Knepley MatInvertBlockDiagonal_SeqAIJ, 34680da83c2eSBarry Smith MatInvertVariableBlockDiagonal_SeqAIJ, 3469f4259b30SLisandro Dalcin NULL, 3470f4259b30SLisandro Dalcin /*129*/ NULL, 3471f4259b30SLisandro Dalcin NULL, 3472f4259b30SLisandro Dalcin NULL, 347375648e8dSHong Zhang MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ, 3474b9af6bddSHong Zhang MatTransposeColoringCreate_SeqAIJ, 3475b9af6bddSHong Zhang /*134*/ MatTransColoringApplySpToDen_SeqAIJ, 34762b8ad9a3SHong Zhang MatTransColoringApplyDenToSp_SeqAIJ, 3477f4259b30SLisandro Dalcin NULL, 3478f4259b30SLisandro Dalcin NULL, 34793964eb88SJed Brown MatRARtNumeric_SeqAIJ_SeqAIJ, 3480f4259b30SLisandro Dalcin /*139*/ NULL, 3481f4259b30SLisandro Dalcin NULL, 3482f4259b30SLisandro Dalcin NULL, 34833a062f41SBarry Smith MatFDColoringSetUp_SeqXAIJ, 34849c8f2541SHong Zhang MatFindOffBlockDiagonalEntries_SeqAIJ, 34854222ddf1SHong Zhang MatCreateMPIMatConcatenateSeqMat_SeqAIJ, 34864222ddf1SHong Zhang /*145*/ MatDestroySubMatrices_SeqAIJ, 3487f4259b30SLisandro Dalcin NULL, 348872833a62Smarkadams4 NULL, 348972833a62Smarkadams4 MatCreateGraph_Simple_AIJ, 34907fb60732SBarry Smith MatFilter_AIJ, 34919371c9d4SSatish Balay /*150*/ MatTransposeSymbolic_SeqAIJ}; 349217ab2063SBarry Smith 34939371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat, PetscInt *indices) { 3494bef8e0ddSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 349597f1f81fSBarry Smith PetscInt i, nz, n; 3496bef8e0ddSBarry Smith 3497bef8e0ddSBarry Smith PetscFunctionBegin; 3498bef8e0ddSBarry Smith nz = aij->maxnz; 3499d0f46423SBarry Smith n = mat->rmap->n; 3500ad540459SPierre Jolivet for (i = 0; i < nz; i++) aij->j[i] = indices[i]; 3501bef8e0ddSBarry Smith aij->nz = nz; 3502ad540459SPierre Jolivet for (i = 0; i < n; i++) aij->ilen[i] = aij->imax[i]; 3503bef8e0ddSBarry Smith PetscFunctionReturn(0); 3504bef8e0ddSBarry Smith } 3505bef8e0ddSBarry Smith 3506a3bb6f32SFande Kong /* 3507ddea5d60SJunchao Zhang * Given a sparse matrix with global column indices, compact it by using a local column space. 3508ddea5d60SJunchao Zhang * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable() 3509ddea5d60SJunchao Zhang */ 35109371c9d4SSatish Balay PetscErrorCode MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping) { 3511a3bb6f32SFande Kong Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3512a3bb6f32SFande Kong PetscTable gid1_lid1; 3513a3bb6f32SFande Kong PetscTablePosition tpos; 351425b670f0SStefano Zampini PetscInt gid, lid, i, ec, nz = aij->nz; 351525b670f0SStefano Zampini PetscInt *garray, *jj = aij->j; 3516a3bb6f32SFande Kong 3517a3bb6f32SFande Kong PetscFunctionBegin; 3518a3bb6f32SFande Kong PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3519a3bb6f32SFande Kong PetscValidPointer(mapping, 2); 3520a3bb6f32SFande Kong /* use a table */ 35219566063dSJacob Faibussowitsch PetscCall(PetscTableCreate(mat->rmap->n, mat->cmap->N + 1, &gid1_lid1)); 3522a3bb6f32SFande Kong ec = 0; 352325b670f0SStefano Zampini for (i = 0; i < nz; i++) { 352425b670f0SStefano Zampini PetscInt data, gid1 = jj[i] + 1; 35259566063dSJacob Faibussowitsch PetscCall(PetscTableFind(gid1_lid1, gid1, &data)); 3526a3bb6f32SFande Kong if (!data) { 3527a3bb6f32SFande Kong /* one based table */ 35289566063dSJacob Faibussowitsch PetscCall(PetscTableAdd(gid1_lid1, gid1, ++ec, INSERT_VALUES)); 3529a3bb6f32SFande Kong } 3530a3bb6f32SFande Kong } 3531a3bb6f32SFande Kong /* form array of columns we need */ 35329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ec, &garray)); 35339566063dSJacob Faibussowitsch PetscCall(PetscTableGetHeadPosition(gid1_lid1, &tpos)); 3534a3bb6f32SFande Kong while (tpos) { 35359566063dSJacob Faibussowitsch PetscCall(PetscTableGetNext(gid1_lid1, &tpos, &gid, &lid)); 3536a3bb6f32SFande Kong gid--; 3537a3bb6f32SFande Kong lid--; 3538a3bb6f32SFande Kong garray[lid] = gid; 3539a3bb6f32SFande Kong } 35409566063dSJacob Faibussowitsch PetscCall(PetscSortInt(ec, garray)); /* sort, and rebuild */ 35419566063dSJacob Faibussowitsch PetscCall(PetscTableRemoveAll(gid1_lid1)); 354248a46eb9SPierre Jolivet for (i = 0; i < ec; i++) PetscCall(PetscTableAdd(gid1_lid1, garray[i] + 1, i + 1, INSERT_VALUES)); 3543a3bb6f32SFande Kong /* compact out the extra columns in B */ 354425b670f0SStefano Zampini for (i = 0; i < nz; i++) { 354525b670f0SStefano Zampini PetscInt gid1 = jj[i] + 1; 35469566063dSJacob Faibussowitsch PetscCall(PetscTableFind(gid1_lid1, gid1, &lid)); 3547a3bb6f32SFande Kong lid--; 354825b670f0SStefano Zampini jj[i] = lid; 3549a3bb6f32SFande Kong } 35509566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&mat->cmap)); 35519566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy(&gid1_lid1)); 35529566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat), ec, ec, 1, &mat->cmap)); 35539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, mat->cmap->bs, mat->cmap->n, garray, PETSC_OWN_POINTER, mapping)); 35549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*mapping, ISLOCALTOGLOBALMAPPINGHASH)); 3555a3bb6f32SFande Kong PetscFunctionReturn(0); 3556a3bb6f32SFande Kong } 3557a3bb6f32SFande Kong 3558bef8e0ddSBarry Smith /*@ 3559bef8e0ddSBarry Smith MatSeqAIJSetColumnIndices - Set the column indices for all the rows 3560bef8e0ddSBarry Smith in the matrix. 3561bef8e0ddSBarry Smith 3562bef8e0ddSBarry Smith Input Parameters: 3563*11a5261eSBarry Smith + mat - the `MATSEQAIJ` matrix 3564bef8e0ddSBarry Smith - indices - the column indices 3565bef8e0ddSBarry Smith 356615091d37SBarry Smith Level: advanced 356715091d37SBarry Smith 3568bef8e0ddSBarry Smith Notes: 3569bef8e0ddSBarry Smith This can be called if you have precomputed the nonzero structure of the 3570bef8e0ddSBarry Smith matrix and want to provide it to the matrix object to improve the performance 3571*11a5261eSBarry Smith of the `MatSetValues()` operation. 3572bef8e0ddSBarry Smith 3573bef8e0ddSBarry Smith You MUST have set the correct numbers of nonzeros per row in the call to 3574*11a5261eSBarry Smith `MatCreateSeqAIJ()`, and the columns indices MUST be sorted. 3575bef8e0ddSBarry Smith 3576*11a5261eSBarry Smith MUST be called before any calls to `MatSetValues()` 3577bef8e0ddSBarry Smith 3578b9617806SBarry Smith The indices should start with zero, not one. 3579b9617806SBarry Smith 3580bef8e0ddSBarry Smith @*/ 35819371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat, PetscInt *indices) { 3582bef8e0ddSBarry Smith PetscFunctionBegin; 35830700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3584dadcf809SJacob Faibussowitsch PetscValidIntPointer(indices, 2); 3585cac4c232SBarry Smith PetscUseMethod(mat, "MatSeqAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices)); 3586bef8e0ddSBarry Smith PetscFunctionReturn(0); 3587bef8e0ddSBarry Smith } 3588bef8e0ddSBarry Smith 3589be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/ 3590be6bf707SBarry Smith 35919371c9d4SSatish Balay PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) { 3592be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3593d0f46423SBarry Smith size_t nz = aij->i[mat->rmap->n]; 3594be6bf707SBarry Smith 3595be6bf707SBarry Smith PetscFunctionBegin; 359628b400f6SJacob Faibussowitsch PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3597be6bf707SBarry Smith 3598be6bf707SBarry Smith /* allocate space for values if not already there */ 3599be6bf707SBarry Smith if (!aij->saved_values) { 36009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz + 1, &aij->saved_values)); 36019566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)mat, (nz + 1) * sizeof(PetscScalar))); 3602be6bf707SBarry Smith } 3603be6bf707SBarry Smith 3604be6bf707SBarry Smith /* copy values over */ 36059566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz)); 3606be6bf707SBarry Smith PetscFunctionReturn(0); 3607be6bf707SBarry Smith } 3608be6bf707SBarry Smith 3609be6bf707SBarry Smith /*@ 3610be6bf707SBarry Smith MatStoreValues - Stashes a copy of the matrix values; this allows, for 3611be6bf707SBarry Smith example, reuse of the linear part of a Jacobian, while recomputing the 3612be6bf707SBarry Smith nonlinear portion. 3613be6bf707SBarry Smith 3614*11a5261eSBarry Smith Collect on mat 3615be6bf707SBarry Smith 3616be6bf707SBarry Smith Input Parameters: 3617*11a5261eSBarry Smith . mat - the matrix (currently only `MATAIJ` matrices support this option) 3618be6bf707SBarry Smith 361915091d37SBarry Smith Level: advanced 362015091d37SBarry Smith 3621*11a5261eSBarry Smith Common Usage, with `SNESSolve()`: 3622be6bf707SBarry Smith $ Create Jacobian matrix 3623be6bf707SBarry Smith $ Set linear terms into matrix 3624be6bf707SBarry Smith $ Apply boundary conditions to matrix, at this time matrix must have 3625be6bf707SBarry Smith $ final nonzero structure (i.e. setting the nonlinear terms and applying 3626be6bf707SBarry Smith $ boundary conditions again will not change the nonzero structure 3627512a5fc5SBarry Smith $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3628be6bf707SBarry Smith $ ierr = MatStoreValues(mat); 3629be6bf707SBarry Smith $ Call SNESSetJacobian() with matrix 3630be6bf707SBarry Smith $ In your Jacobian routine 3631be6bf707SBarry Smith $ ierr = MatRetrieveValues(mat); 3632be6bf707SBarry Smith $ Set nonlinear terms in matrix 3633be6bf707SBarry Smith 3634be6bf707SBarry Smith Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself: 3635be6bf707SBarry Smith $ // build linear portion of Jacobian 3636512a5fc5SBarry Smith $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3637be6bf707SBarry Smith $ ierr = MatStoreValues(mat); 3638be6bf707SBarry Smith $ loop over nonlinear iterations 3639be6bf707SBarry Smith $ ierr = MatRetrieveValues(mat); 3640be6bf707SBarry Smith $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian 3641be6bf707SBarry Smith $ // call MatAssemblyBegin/End() on matrix 3642be6bf707SBarry Smith $ Solve linear system with Jacobian 3643be6bf707SBarry Smith $ endloop 3644be6bf707SBarry Smith 3645be6bf707SBarry Smith Notes: 3646be6bf707SBarry Smith Matrix must already be assemblied before calling this routine 3647*11a5261eSBarry Smith Must set the matrix option `MatSetOption`(mat,`MAT_NEW_NONZERO_LOCATIONS`,`PETSC_FALSE`); before 3648be6bf707SBarry Smith calling this routine. 3649be6bf707SBarry Smith 36500c468ba9SBarry Smith When this is called multiple times it overwrites the previous set of stored values 36510c468ba9SBarry Smith and does not allocated additional space. 36520c468ba9SBarry Smith 3653db781477SPatrick Sanan .seealso: `MatRetrieveValues()` 3654be6bf707SBarry Smith @*/ 36559371c9d4SSatish Balay PetscErrorCode MatStoreValues(Mat mat) { 3656be6bf707SBarry Smith PetscFunctionBegin; 36570700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 365828b400f6SJacob Faibussowitsch PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 365928b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3660cac4c232SBarry Smith PetscUseMethod(mat, "MatStoreValues_C", (Mat), (mat)); 3661be6bf707SBarry Smith PetscFunctionReturn(0); 3662be6bf707SBarry Smith } 3663be6bf707SBarry Smith 36649371c9d4SSatish Balay PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat) { 3665be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3666d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->n]; 3667be6bf707SBarry Smith 3668be6bf707SBarry Smith PetscFunctionBegin; 366928b400f6SJacob Faibussowitsch PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 367028b400f6SJacob Faibussowitsch PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first"); 3671be6bf707SBarry Smith /* copy values over */ 36729566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz)); 3673be6bf707SBarry Smith PetscFunctionReturn(0); 3674be6bf707SBarry Smith } 3675be6bf707SBarry Smith 3676be6bf707SBarry Smith /*@ 3677be6bf707SBarry Smith MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 3678be6bf707SBarry Smith example, reuse of the linear part of a Jacobian, while recomputing the 3679be6bf707SBarry Smith nonlinear portion. 3680be6bf707SBarry Smith 3681*11a5261eSBarry Smith Collect on mat 3682be6bf707SBarry Smith 3683be6bf707SBarry Smith Input Parameters: 3684*11a5261eSBarry Smith . mat - the matrix (currently only `MATAIJ` matrices support this option) 3685be6bf707SBarry Smith 368615091d37SBarry Smith Level: advanced 368715091d37SBarry Smith 3688db781477SPatrick Sanan .seealso: `MatStoreValues()` 3689be6bf707SBarry Smith @*/ 36909371c9d4SSatish Balay PetscErrorCode MatRetrieveValues(Mat mat) { 3691be6bf707SBarry Smith PetscFunctionBegin; 36920700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 369328b400f6SJacob Faibussowitsch PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 369428b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3695cac4c232SBarry Smith PetscUseMethod(mat, "MatRetrieveValues_C", (Mat), (mat)); 3696be6bf707SBarry Smith PetscFunctionReturn(0); 3697be6bf707SBarry Smith } 3698be6bf707SBarry Smith 3699be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/ 370017ab2063SBarry Smith /*@C 3701*11a5261eSBarry Smith MatCreateSeqAIJ - Creates a sparse matrix in `MATSEQAIJ` (compressed row) format 37020d15e28bSLois Curfman McInnes (the default parallel PETSc format). For good matrix assembly performance 37036e62573dSLois Curfman McInnes the user should preallocate the matrix storage by setting the parameter nz 370451c19458SBarry Smith (or the array nnz). By setting these parameters accurately, performance 37052bd5e0b2SLois Curfman McInnes during matrix assembly can be increased by more than a factor of 50. 370617ab2063SBarry Smith 3707d083f849SBarry Smith Collective 3708db81eaa0SLois Curfman McInnes 370917ab2063SBarry Smith Input Parameters: 3710*11a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF` 371117ab2063SBarry Smith . m - number of rows 371217ab2063SBarry Smith . n - number of columns 371317ab2063SBarry Smith . nz - number of nonzeros per row (same for all rows) 371451c19458SBarry Smith - nnz - array containing the number of nonzeros in the various rows 37150298fd71SBarry Smith (possibly different for each row) or NULL 371617ab2063SBarry Smith 371717ab2063SBarry Smith Output Parameter: 3718416022c9SBarry Smith . A - the matrix 371917ab2063SBarry Smith 3720*11a5261eSBarry Smith It is recommended that one use the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`, 3721f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly. 3722*11a5261eSBarry Smith [MatXXXXSetPreallocation() is, for example, `MatSeqAIJSetPreallocation()`] 3723175b88e8SBarry Smith 3724b259b22eSLois Curfman McInnes Notes: 372549a6f317SBarry Smith If nnz is given then nz is ignored 372649a6f317SBarry Smith 3727*11a5261eSBarry Smith The AIJ format, also called 3728*11a5261eSBarry Smith compressed row storage, is fully compatible with standard Fortran 77 37290002213bSLois Curfman McInnes storage. That is, the stored row and column indices can begin at 373044cd7ae7SLois Curfman McInnes either one (as in Fortran) or zero. See the users' manual for details. 373117ab2063SBarry Smith 373217ab2063SBarry Smith Specify the preallocated storage with either nz or nnz (not both). 3733*11a5261eSBarry Smith Set nz = `PETSC_DEFAULT` and nnz = NULL for PETSc to control dynamic memory 37343d323bbdSBarry Smith allocation. For large problems you MUST preallocate memory or you 37356da5968aSLois Curfman McInnes will get TERRIBLE performance, see the users' manual chapter on matrices. 373617ab2063SBarry Smith 3737682d7d0cSBarry Smith By default, this format uses inodes (identical nodes) when possible, to 37384fca80b9SLois Curfman McInnes improve numerical efficiency of matrix-vector products and solves. We 3739682d7d0cSBarry Smith search for consecutive rows with the same nonzero structure, thereby 37406c7ebb05SLois Curfman McInnes reusing matrix information to achieve increased efficiency. 37416c7ebb05SLois Curfman McInnes 37426c7ebb05SLois Curfman McInnes Options Database Keys: 3743698d4c6aSKris Buschelman + -mat_no_inode - Do not use inodes 37449db58ca8SBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 374517ab2063SBarry Smith 3746027ccd11SLois Curfman McInnes Level: intermediate 3747027ccd11SLois Curfman McInnes 3748db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()` 374917ab2063SBarry Smith @*/ 37509371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A) { 37513a40ed3dSBarry Smith PetscFunctionBegin; 37529566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 37539566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, m, n)); 37549566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATSEQAIJ)); 37559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*A, nz, nnz)); 3756273d9f13SBarry Smith PetscFunctionReturn(0); 3757273d9f13SBarry Smith } 3758273d9f13SBarry Smith 3759273d9f13SBarry Smith /*@C 3760273d9f13SBarry Smith MatSeqAIJSetPreallocation - For good matrix assembly performance 3761273d9f13SBarry Smith the user should preallocate the matrix storage by setting the parameter nz 3762273d9f13SBarry Smith (or the array nnz). By setting these parameters accurately, performance 3763273d9f13SBarry Smith during matrix assembly can be increased by more than a factor of 50. 3764273d9f13SBarry Smith 3765d083f849SBarry Smith Collective 3766273d9f13SBarry Smith 3767273d9f13SBarry Smith Input Parameters: 37681c4f3114SJed Brown + B - The matrix 3769273d9f13SBarry Smith . nz - number of nonzeros per row (same for all rows) 3770273d9f13SBarry Smith - nnz - array containing the number of nonzeros in the various rows 37710298fd71SBarry Smith (possibly different for each row) or NULL 3772273d9f13SBarry Smith 3773273d9f13SBarry Smith Notes: 377449a6f317SBarry Smith If nnz is given then nz is ignored 377549a6f317SBarry Smith 3776*11a5261eSBarry Smith The `MATSEQAIJ` format also called 3777*11a5261eSBarry Smith compressed row storage, is fully compatible with standard Fortran 77 3778273d9f13SBarry Smith storage. That is, the stored row and column indices can begin at 3779273d9f13SBarry Smith either one (as in Fortran) or zero. See the users' manual for details. 3780273d9f13SBarry Smith 3781273d9f13SBarry Smith Specify the preallocated storage with either nz or nnz (not both). 3782*11a5261eSBarry Smith Set nz = `PETSC_DEFAULT` and nnz = NULL for PETSc to control dynamic memory 3783273d9f13SBarry Smith allocation. For large problems you MUST preallocate memory or you 3784273d9f13SBarry Smith will get TERRIBLE performance, see the users' manual chapter on matrices. 3785273d9f13SBarry Smith 3786*11a5261eSBarry Smith You can call `MatGetInfo()` to get information on how effective the preallocation was; 3787aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 3788aa95bbe8SBarry Smith You can also run with the option -info and look for messages with the string 3789aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 3790aa95bbe8SBarry Smith 3791*11a5261eSBarry Smith Developer Notes: 3792*11a5261eSBarry Smith Use nz of `MAT_SKIP_ALLOCATION` to not allocate any space for the matrix 3793a96a251dSBarry Smith entries or columns indices 3794a96a251dSBarry Smith 3795273d9f13SBarry Smith By default, this format uses inodes (identical nodes) when possible, to 3796273d9f13SBarry Smith improve numerical efficiency of matrix-vector products and solves. We 3797273d9f13SBarry Smith search for consecutive rows with the same nonzero structure, thereby 3798273d9f13SBarry Smith reusing matrix information to achieve increased efficiency. 3799273d9f13SBarry Smith 3800273d9f13SBarry Smith Options Database Keys: 3801698d4c6aSKris Buschelman + -mat_no_inode - Do not use inodes 380247b2e64bSBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3803273d9f13SBarry Smith 3804273d9f13SBarry Smith Level: intermediate 3805273d9f13SBarry Smith 3806db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()`, `MatGetInfo()`, 3807db781477SPatrick Sanan `MatSeqAIJSetTotalPreallocation()` 3808273d9f13SBarry Smith @*/ 38099371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocation(Mat B, PetscInt nz, const PetscInt nnz[]) { 3810a23d5eceSKris Buschelman PetscFunctionBegin; 38116ba663aaSJed Brown PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 38126ba663aaSJed Brown PetscValidType(B, 1); 3813cac4c232SBarry Smith PetscTryMethod(B, "MatSeqAIJSetPreallocation_C", (Mat, PetscInt, const PetscInt[]), (B, nz, nnz)); 3814a23d5eceSKris Buschelman PetscFunctionReturn(0); 3815a23d5eceSKris Buschelman } 3816a23d5eceSKris Buschelman 38179371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B, PetscInt nz, const PetscInt *nnz) { 3818273d9f13SBarry Smith Mat_SeqAIJ *b; 38192576faa2SJed Brown PetscBool skipallocation = PETSC_FALSE, realalloc = PETSC_FALSE; 382097f1f81fSBarry Smith PetscInt i; 3821273d9f13SBarry Smith 3822273d9f13SBarry Smith PetscFunctionBegin; 38232576faa2SJed Brown if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 3824a96a251dSBarry Smith if (nz == MAT_SKIP_ALLOCATION) { 3825c461c341SBarry Smith skipallocation = PETSC_TRUE; 3826c461c341SBarry Smith nz = 0; 3827c461c341SBarry Smith } 38289566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 38299566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 3830899cda47SBarry Smith 3831435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 383208401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz); 3833cf9c20a2SJed Brown if (PetscUnlikelyDebug(nnz)) { 3834d0f46423SBarry Smith for (i = 0; i < B->rmap->n; i++) { 383508401ef6SPierre 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]); 383608401ef6SPierre 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); 3837b73539f3SBarry Smith } 3838b73539f3SBarry Smith } 3839b73539f3SBarry Smith 3840273d9f13SBarry Smith B->preallocated = PETSC_TRUE; 38412205254eSKarl Rupp 3842273d9f13SBarry Smith b = (Mat_SeqAIJ *)B->data; 3843273d9f13SBarry Smith 3844ab93d7beSBarry Smith if (!skipallocation) { 38452ee49352SLisandro Dalcin if (!b->imax) { 38469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n, &b->imax)); 38479566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, B->rmap->n * sizeof(PetscInt))); 3848071fcb05SBarry Smith } 3849071fcb05SBarry Smith if (!b->ilen) { 3850071fcb05SBarry Smith /* b->ilen will count nonzeros in each row so far. */ 38519566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(B->rmap->n, &b->ilen)); 38529566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, B->rmap->n * sizeof(PetscInt))); 3853071fcb05SBarry Smith } else { 38549566063dSJacob Faibussowitsch PetscCall(PetscMemzero(b->ilen, B->rmap->n * sizeof(PetscInt))); 38552ee49352SLisandro Dalcin } 3856846b4da1SFande Kong if (!b->ipre) { 38579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n, &b->ipre)); 38589566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, B->rmap->n * sizeof(PetscInt))); 3859846b4da1SFande Kong } 3860273d9f13SBarry Smith if (!nnz) { 3861435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 3862c62bd62aSJed Brown else if (nz < 0) nz = 1; 38635d2a9ed1SStefano Zampini nz = PetscMin(nz, B->cmap->n); 3864d0f46423SBarry Smith for (i = 0; i < B->rmap->n; i++) b->imax[i] = nz; 3865d0f46423SBarry Smith nz = nz * B->rmap->n; 3866273d9f13SBarry Smith } else { 3867c73702f5SBarry Smith PetscInt64 nz64 = 0; 38689371c9d4SSatish Balay for (i = 0; i < B->rmap->n; i++) { 38699371c9d4SSatish Balay b->imax[i] = nnz[i]; 38709371c9d4SSatish Balay nz64 += nnz[i]; 38719371c9d4SSatish Balay } 38729566063dSJacob Faibussowitsch PetscCall(PetscIntCast(nz64, &nz)); 3873273d9f13SBarry Smith } 3874ab93d7beSBarry Smith 3875273d9f13SBarry Smith /* allocate the matrix space */ 387653dd7562SDmitry Karpeev /* FIXME: should B's old memory be unlogged? */ 38779566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i)); 3878396832f4SHong Zhang if (B->structure_only) { 38799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &b->j)); 38809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n + 1, &b->i)); 38819566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, (B->rmap->n + 1) * sizeof(PetscInt) + nz * sizeof(PetscInt))); 3882396832f4SHong Zhang } else { 38839566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(nz, &b->a, nz, &b->j, B->rmap->n + 1, &b->i)); 38849566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, (B->rmap->n + 1) * sizeof(PetscInt) + nz * (sizeof(PetscScalar) + sizeof(PetscInt)))); 3885396832f4SHong Zhang } 3886bfeeae90SHong Zhang b->i[0] = 0; 3887ad540459SPierre Jolivet for (i = 1; i < B->rmap->n + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1]; 3888396832f4SHong Zhang if (B->structure_only) { 3889396832f4SHong Zhang b->singlemalloc = PETSC_FALSE; 3890396832f4SHong Zhang b->free_a = PETSC_FALSE; 3891396832f4SHong Zhang } else { 3892273d9f13SBarry Smith b->singlemalloc = PETSC_TRUE; 3893e6b907acSBarry Smith b->free_a = PETSC_TRUE; 3894396832f4SHong Zhang } 3895e6b907acSBarry Smith b->free_ij = PETSC_TRUE; 3896c461c341SBarry Smith } else { 3897e6b907acSBarry Smith b->free_a = PETSC_FALSE; 3898e6b907acSBarry Smith b->free_ij = PETSC_FALSE; 3899c461c341SBarry Smith } 3900273d9f13SBarry Smith 3901846b4da1SFande Kong if (b->ipre && nnz != b->ipre && b->imax) { 3902846b4da1SFande Kong /* reserve user-requested sparsity */ 39039566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->ipre, b->imax, B->rmap->n)); 3904846b4da1SFande Kong } 3905846b4da1SFande Kong 3906273d9f13SBarry Smith b->nz = 0; 3907273d9f13SBarry Smith b->maxnz = nz; 3908273d9f13SBarry Smith B->info.nz_unneeded = (double)b->maxnz; 39091baa6e33SBarry Smith if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 3910cb7b82ddSBarry Smith B->was_assembled = PETSC_FALSE; 3911cb7b82ddSBarry Smith B->assembled = PETSC_FALSE; 39125519a089SJose E. Roman /* We simply deem preallocation has changed nonzero state. Updating the state 39135519a089SJose E. Roman will give clients (like AIJKokkos) a chance to know something has happened. 39145519a089SJose E. Roman */ 39155519a089SJose E. Roman B->nonzerostate++; 3916273d9f13SBarry Smith PetscFunctionReturn(0); 3917273d9f13SBarry Smith } 3918273d9f13SBarry Smith 39199371c9d4SSatish Balay PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A) { 3920846b4da1SFande Kong Mat_SeqAIJ *a; 3921a5bbaf83SFande Kong PetscInt i; 3922846b4da1SFande Kong 3923846b4da1SFande Kong PetscFunctionBegin; 3924846b4da1SFande Kong PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 392514d0e64fSAlex Lindsay 392614d0e64fSAlex Lindsay /* Check local size. If zero, then return */ 392714d0e64fSAlex Lindsay if (!A->rmap->n) PetscFunctionReturn(0); 392814d0e64fSAlex Lindsay 3929846b4da1SFande Kong a = (Mat_SeqAIJ *)A->data; 39302c814fdeSFande Kong /* if no saved info, we error out */ 393128b400f6SJacob Faibussowitsch PetscCheck(a->ipre, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "No saved preallocation info "); 39322c814fdeSFande Kong 3933aed4548fSBarry 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 "); 39342c814fdeSFande Kong 39359566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->imax, a->ipre, A->rmap->n)); 39369566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(a->ilen, A->rmap->n)); 3937846b4da1SFande Kong a->i[0] = 0; 3938ad540459SPierre Jolivet for (i = 1; i < A->rmap->n + 1; i++) a->i[i] = a->i[i - 1] + a->imax[i - 1]; 3939846b4da1SFande Kong A->preallocated = PETSC_TRUE; 3940846b4da1SFande Kong a->nz = 0; 3941846b4da1SFande Kong a->maxnz = a->i[A->rmap->n]; 3942846b4da1SFande Kong A->info.nz_unneeded = (double)a->maxnz; 3943846b4da1SFande Kong A->was_assembled = PETSC_FALSE; 3944846b4da1SFande Kong A->assembled = PETSC_FALSE; 3945846b4da1SFande Kong PetscFunctionReturn(0); 3946846b4da1SFande Kong } 3947846b4da1SFande Kong 394858d36128SBarry Smith /*@ 3949*11a5261eSBarry Smith MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in `MATSEQAIJ` format. 3950a1661176SMatthew Knepley 3951a1661176SMatthew Knepley Input Parameters: 3952a1661176SMatthew Knepley + B - the matrix 3953a1661176SMatthew Knepley . i - the indices into j for the start of each row (starts with zero) 3954a1661176SMatthew Knepley . j - the column indices for each row (starts with zero) these must be sorted for each row 3955a1661176SMatthew Knepley - v - optional values in the matrix 3956a1661176SMatthew Knepley 3957a1661176SMatthew Knepley Level: developer 3958a1661176SMatthew Knepley 39596a9b8d82SBarry Smith Notes: 3960*11a5261eSBarry Smith The i,j,v values are COPIED with this routine; to avoid the copy use `MatCreateSeqAIJWithArrays()` 396158d36128SBarry Smith 39626a9b8d82SBarry Smith This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero 39636a9b8d82SBarry Smith structure will be the union of all the previous nonzero structures. 39646a9b8d82SBarry Smith 39656a9b8d82SBarry Smith Developer Notes: 39666a9b8d82SBarry 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 3967*11a5261eSBarry Smith then just copies the v values directly with `PetscMemcpy()`. 39686a9b8d82SBarry Smith 3969*11a5261eSBarry Smith This routine could also take a `PetscCopyMode` argument to allow sharing the values instead of always copying them. 39706a9b8d82SBarry Smith 3971db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatSeqAIJSetPreallocation()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MatResetPreallocation()` 3972a1661176SMatthew Knepley @*/ 39739371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B, const PetscInt i[], const PetscInt j[], const PetscScalar v[]) { 3974a1661176SMatthew Knepley PetscFunctionBegin; 39750700a824SBarry Smith PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 39766ba663aaSJed Brown PetscValidType(B, 1); 3977cac4c232SBarry Smith PetscTryMethod(B, "MatSeqAIJSetPreallocationCSR_C", (Mat, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, i, j, v)); 3978a1661176SMatthew Knepley PetscFunctionReturn(0); 3979a1661176SMatthew Knepley } 3980a1661176SMatthew Knepley 39819371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B, const PetscInt Ii[], const PetscInt J[], const PetscScalar v[]) { 3982a1661176SMatthew Knepley PetscInt i; 3983a1661176SMatthew Knepley PetscInt m, n; 3984a1661176SMatthew Knepley PetscInt nz; 39856a9b8d82SBarry Smith PetscInt *nnz; 3986a1661176SMatthew Knepley 3987a1661176SMatthew Knepley PetscFunctionBegin; 3988aed4548fSBarry Smith PetscCheck(Ii[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]); 3989779a8d59SSatish Balay 39909566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 39919566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 3992779a8d59SSatish Balay 39939566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &m, &n)); 39949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nnz)); 3995a1661176SMatthew Knepley for (i = 0; i < m; i++) { 3996b7940d39SSatish Balay nz = Ii[i + 1] - Ii[i]; 399708401ef6SPierre 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); 3998a1661176SMatthew Knepley nnz[i] = nz; 3999a1661176SMatthew Knepley } 40009566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz)); 40019566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 4002a1661176SMatthew Knepley 400348a46eb9SPierre 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)); 4004a1661176SMatthew Knepley 40059566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 40069566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4007a1661176SMatthew Knepley 40089566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 4009a1661176SMatthew Knepley PetscFunctionReturn(0); 4010a1661176SMatthew Knepley } 4011a1661176SMatthew Knepley 4012ad7e164aSPierre Jolivet /*@ 4013ad7e164aSPierre Jolivet MatSeqAIJKron - Computes C, the Kronecker product of A and B. 4014ad7e164aSPierre Jolivet 4015ad7e164aSPierre Jolivet Input Parameters: 4016ad7e164aSPierre Jolivet + A - left-hand side matrix 4017ad7e164aSPierre Jolivet . B - right-hand side matrix 4018*11a5261eSBarry Smith - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 4019ad7e164aSPierre Jolivet 4020ad7e164aSPierre Jolivet Output Parameter: 4021ad7e164aSPierre Jolivet . C - Kronecker product of A and B 4022ad7e164aSPierre Jolivet 4023ad7e164aSPierre Jolivet Level: intermediate 4024ad7e164aSPierre Jolivet 4025*11a5261eSBarry Smith Note: 4026*11a5261eSBarry 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()`. 4027ad7e164aSPierre Jolivet 4028db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATKAIJ`, `MatReuse` 4029ad7e164aSPierre Jolivet @*/ 40309371c9d4SSatish Balay PetscErrorCode MatSeqAIJKron(Mat A, Mat B, MatReuse reuse, Mat *C) { 4031ad7e164aSPierre Jolivet PetscFunctionBegin; 4032ad7e164aSPierre Jolivet PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4033ad7e164aSPierre Jolivet PetscValidType(A, 1); 4034ad7e164aSPierre Jolivet PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4035ad7e164aSPierre Jolivet PetscValidType(B, 2); 4036ad7e164aSPierre Jolivet PetscValidPointer(C, 4); 4037ad7e164aSPierre Jolivet if (reuse == MAT_REUSE_MATRIX) { 4038ad7e164aSPierre Jolivet PetscValidHeaderSpecific(*C, MAT_CLASSID, 4); 4039ad7e164aSPierre Jolivet PetscValidType(*C, 4); 4040ad7e164aSPierre Jolivet } 4041cac4c232SBarry Smith PetscTryMethod(A, "MatSeqAIJKron_C", (Mat, Mat, MatReuse, Mat *), (A, B, reuse, C)); 4042ad7e164aSPierre Jolivet PetscFunctionReturn(0); 4043ad7e164aSPierre Jolivet } 4044ad7e164aSPierre Jolivet 40459371c9d4SSatish Balay PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A, Mat B, MatReuse reuse, Mat *C) { 4046ad7e164aSPierre Jolivet Mat newmat; 4047ad7e164aSPierre Jolivet Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 4048ad7e164aSPierre Jolivet Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 4049ad7e164aSPierre Jolivet PetscScalar *v; 4050fff043a9SJunchao Zhang const PetscScalar *aa, *ba; 4051ad7e164aSPierre 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; 4052ad7e164aSPierre Jolivet PetscBool flg; 4053ad7e164aSPierre Jolivet 4054ad7e164aSPierre Jolivet PetscFunctionBegin; 405528b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 405628b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 405728b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 405828b400f6SJacob Faibussowitsch PetscCheck(B->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 40599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATSEQAIJ, &flg)); 406028b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatType %s", ((PetscObject)B)->type_name); 4061aed4548fSBarry Smith PetscCheck(reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatReuse %d", (int)reuse); 4062ad7e164aSPierre Jolivet if (reuse == MAT_INITIAL_MATRIX) { 40639566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(am * bm + 1, &i, a->i[am] * b->i[bm], &j)); 40649566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &newmat)); 40659566063dSJacob Faibussowitsch PetscCall(MatSetSizes(newmat, am * bm, an * bn, am * bm, an * bn)); 40669566063dSJacob Faibussowitsch PetscCall(MatSetType(newmat, MATAIJ)); 4067ad7e164aSPierre Jolivet i[0] = 0; 4068ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4069ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4070ad7e164aSPierre Jolivet i[m * bm + p + 1] = i[m * bm + p] + (a->i[m + 1] - a->i[m]) * (b->i[p + 1] - b->i[p]); 4071ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m + 1]; ++n) { 4072ad540459SPierre Jolivet for (q = b->i[p]; q < b->i[p + 1]; ++q) j[nnz++] = a->j[n] * bn + b->j[q]; 4073ad7e164aSPierre Jolivet } 4074ad7e164aSPierre Jolivet } 4075ad7e164aSPierre Jolivet } 40769566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(newmat, i, j, NULL)); 4077ad7e164aSPierre Jolivet *C = newmat; 40789566063dSJacob Faibussowitsch PetscCall(PetscFree2(i, j)); 4079ad7e164aSPierre Jolivet nnz = 0; 4080ad7e164aSPierre Jolivet } 40819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(*C, &v)); 40829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 40839566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &ba)); 4084ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4085ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4086ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m + 1]; ++n) { 4087ad540459SPierre Jolivet for (q = b->i[p]; q < b->i[p + 1]; ++q) v[nnz++] = aa[n] * ba[q]; 4088ad7e164aSPierre Jolivet } 4089ad7e164aSPierre Jolivet } 4090ad7e164aSPierre Jolivet } 40919566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(*C, &v)); 40929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 40939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &ba)); 4094ad7e164aSPierre Jolivet PetscFunctionReturn(0); 4095ad7e164aSPierre Jolivet } 4096ad7e164aSPierre Jolivet 4097c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h> 4098af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h> 4099170fe5c8SBarry Smith 4100170fe5c8SBarry Smith /* 4101170fe5c8SBarry Smith Computes (B'*A')' since computing B*A directly is untenable 4102170fe5c8SBarry Smith 4103170fe5c8SBarry Smith n p p 41042da392ccSBarry Smith [ ] [ ] [ ] 41052da392ccSBarry Smith m [ A ] * n [ B ] = m [ C ] 41062da392ccSBarry Smith [ ] [ ] [ ] 4107170fe5c8SBarry Smith 4108170fe5c8SBarry Smith */ 41099371c9d4SSatish Balay PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A, Mat B, Mat C) { 4110170fe5c8SBarry Smith Mat_SeqDense *sub_a = (Mat_SeqDense *)A->data; 4111170fe5c8SBarry Smith Mat_SeqAIJ *sub_b = (Mat_SeqAIJ *)B->data; 4112170fe5c8SBarry Smith Mat_SeqDense *sub_c = (Mat_SeqDense *)C->data; 411386214ceeSStefano Zampini PetscInt i, j, n, m, q, p; 4114170fe5c8SBarry Smith const PetscInt *ii, *idx; 4115170fe5c8SBarry Smith const PetscScalar *b, *a, *a_q; 4116170fe5c8SBarry Smith PetscScalar *c, *c_q; 411786214ceeSStefano Zampini PetscInt clda = sub_c->lda; 411886214ceeSStefano Zampini PetscInt alda = sub_a->lda; 4119170fe5c8SBarry Smith 4120170fe5c8SBarry Smith PetscFunctionBegin; 4121d0f46423SBarry Smith m = A->rmap->n; 4122d0f46423SBarry Smith n = A->cmap->n; 4123d0f46423SBarry Smith p = B->cmap->n; 4124170fe5c8SBarry Smith a = sub_a->v; 4125170fe5c8SBarry Smith b = sub_b->a; 4126170fe5c8SBarry Smith c = sub_c->v; 412786214ceeSStefano Zampini if (clda == m) { 41289566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c, m * p)); 412986214ceeSStefano Zampini } else { 413086214ceeSStefano Zampini for (j = 0; j < p; j++) 41319371c9d4SSatish Balay for (i = 0; i < m; i++) c[j * clda + i] = 0.0; 413286214ceeSStefano Zampini } 4133170fe5c8SBarry Smith ii = sub_b->i; 4134170fe5c8SBarry Smith idx = sub_b->j; 4135170fe5c8SBarry Smith for (i = 0; i < n; i++) { 4136170fe5c8SBarry Smith q = ii[i + 1] - ii[i]; 4137170fe5c8SBarry Smith while (q-- > 0) { 413886214ceeSStefano Zampini c_q = c + clda * (*idx); 413986214ceeSStefano Zampini a_q = a + alda * i; 4140854c7f52SBarry Smith PetscKernelAXPY(c_q, *b, a_q, m); 4141170fe5c8SBarry Smith idx++; 4142170fe5c8SBarry Smith b++; 4143170fe5c8SBarry Smith } 4144170fe5c8SBarry Smith } 4145170fe5c8SBarry Smith PetscFunctionReturn(0); 4146170fe5c8SBarry Smith } 4147170fe5c8SBarry Smith 41489371c9d4SSatish Balay PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A, Mat B, PetscReal fill, Mat C) { 4149d0f46423SBarry Smith PetscInt m = A->rmap->n, n = B->cmap->n; 415086214ceeSStefano Zampini PetscBool cisdense; 4151170fe5c8SBarry Smith 4152170fe5c8SBarry Smith PetscFunctionBegin; 415308401ef6SPierre 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); 41549566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, m, n)); 41559566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, B)); 41569566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, "")); 415748a46eb9SPierre Jolivet if (!cisdense) PetscCall(MatSetType(C, MATDENSE)); 41589566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 4159d73949e8SHong Zhang 41604222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ; 4161170fe5c8SBarry Smith PetscFunctionReturn(0); 4162170fe5c8SBarry Smith } 4163170fe5c8SBarry Smith 4164170fe5c8SBarry Smith /* ----------------------------------------------------------------*/ 41650bad9183SKris Buschelman /*MC 4166fafad747SKris Buschelman MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 41670bad9183SKris Buschelman based on compressed sparse row format. 41680bad9183SKris Buschelman 41690bad9183SKris Buschelman Options Database Keys: 41700bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 41710bad9183SKris Buschelman 41720bad9183SKris Buschelman Level: beginner 41730bad9183SKris Buschelman 41740cd7f59aSBarry Smith Notes: 4175*11a5261eSBarry Smith `MatSetValues()` may be called for this matrix type with a NULL argument for the numerical values, 41760cd7f59aSBarry Smith in this case the values associated with the rows and columns one passes in are set to zero 41770cd7f59aSBarry Smith in the matrix 41780cd7f59aSBarry Smith 4179*11a5261eSBarry Smith `MatSetOptions`(,`MAT_STRUCTURE_ONLY`,`PETSC_TRUE`) may be called for this matrix type. In this no 4180*11a5261eSBarry Smith space is allocated for the nonzero entries and any entries passed with `MatSetValues()` are ignored 41810cd7f59aSBarry Smith 4182*11a5261eSBarry Smith Developer Note: 41830cd7f59aSBarry Smith It would be nice if all matrix formats supported passing NULL in for the numerical values 41840cd7f59aSBarry Smith 4185db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MatSetFromOptions()`, `MatSetType()`, `MatCreate()`, `MatType`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 41860bad9183SKris Buschelman M*/ 41870bad9183SKris Buschelman 4188ccd284c7SBarry Smith /*MC 4189ccd284c7SBarry Smith MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 4190ccd284c7SBarry Smith 4191*11a5261eSBarry Smith This matrix type is identical to `MATSEQAIJ` when constructed with a single process communicator, 4192*11a5261eSBarry Smith and `MATMPIAIJ` otherwise. As a result, for single process communicators, 4193*11a5261eSBarry Smith `MatSeqAIJSetPreallocation()` is supported, and similarly `MatMPIAIJSetPreallocation()` is supported 4194ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4195ccd284c7SBarry Smith the above preallocation routines for simplicity. 4196ccd284c7SBarry Smith 4197ccd284c7SBarry Smith Options Database Keys: 4198*11a5261eSBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to `MatSetFromOptions()` 4199ccd284c7SBarry Smith 4200*11a5261eSBarry Smith Note: 4201*11a5261eSBarry Smith Subclasses include `MATAIJCUSPARSE`, `MATAIJPERM`, `MATAIJSELL`, `MATAIJMKL`, `MATAIJCRL`, and also automatically switches over to use inodes when 4202ccd284c7SBarry Smith enough exist. 4203ccd284c7SBarry Smith 4204ccd284c7SBarry Smith Level: beginner 4205ccd284c7SBarry Smith 4206db781477SPatrick Sanan .seealso: `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATMPIAIJ`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 4207ccd284c7SBarry Smith M*/ 4208ccd284c7SBarry Smith 4209ccd284c7SBarry Smith /*MC 4210ccd284c7SBarry Smith MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 4211ccd284c7SBarry Smith 4212*11a5261eSBarry Smith This matrix type is identical to `MATSEQAIJCRL` when constructed with a single process communicator, 4213*11a5261eSBarry Smith and `MATMPIAIJCRL` otherwise. As a result, for single process communicators, 4214*11a5261eSBarry Smith `MatSeqAIJSetPreallocation()` is supported, and similarly `MatMPIAIJSetPreallocation()` is supported 4215ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4216ccd284c7SBarry Smith the above preallocation routines for simplicity. 4217ccd284c7SBarry Smith 4218ccd284c7SBarry Smith Options Database Keys: 4219*11a5261eSBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to `MatSetFromOptions()` 4220ccd284c7SBarry Smith 4221ccd284c7SBarry Smith Level: beginner 4222ccd284c7SBarry Smith 4223c2e3fba1SPatrick Sanan .seealso: `MatCreateMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL` 4224ccd284c7SBarry Smith M*/ 4225ccd284c7SBarry Smith 42267906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat, MatType, MatReuse, Mat *); 42277906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 42287906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat, MatType, MatReuse, Mat *); 42297906f579SHong Zhang #endif 4230d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 4231d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat, MatType, MatReuse, Mat *); 4232d24d4204SJose E. Roman #endif 42337906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE) 42347906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType, MatReuse, Mat *); 42357906f579SHong Zhang #endif 42367906f579SHong Zhang 4237d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat, MatType, MatReuse, Mat *); 4238c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat, MatType, MatReuse, Mat *); 42394222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat); 42407906f579SHong Zhang 42418c778c55SBarry Smith /*@C 4242*11a5261eSBarry Smith MatSeqAIJGetArray - gives read/write access to the array where the data for a `MATSEQAIJ` matrix is stored 42438c778c55SBarry Smith 42448c778c55SBarry Smith Not Collective 42458c778c55SBarry Smith 42468c778c55SBarry Smith Input Parameter: 4247*11a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 42488c778c55SBarry Smith 42498c778c55SBarry Smith Output Parameter: 42508c778c55SBarry Smith . array - pointer to the data 42518c778c55SBarry Smith 42528c778c55SBarry Smith Level: intermediate 42538c778c55SBarry Smith 4254db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()` 42558c778c55SBarry Smith @*/ 42569371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArray(Mat A, PetscScalar **array) { 4257d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 42588c778c55SBarry Smith 42598c778c55SBarry Smith PetscFunctionBegin; 4260d67d9f35SJunchao Zhang if (aij->ops->getarray) { 42619566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarray)(A, array)); 4262d67d9f35SJunchao Zhang } else { 4263d67d9f35SJunchao Zhang *array = aij->a; 4264d67d9f35SJunchao Zhang } 4265d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4266d67d9f35SJunchao Zhang } 4267d67d9f35SJunchao Zhang 4268d67d9f35SJunchao Zhang /*@C 4269*11a5261eSBarry Smith MatSeqAIJRestoreArray - returns access to the array where the data for a `MATSEQAIJ` matrix is stored obtained by `MatSeqAIJGetArray()` 4270d67d9f35SJunchao Zhang 4271d67d9f35SJunchao Zhang Not Collective 4272d67d9f35SJunchao Zhang 4273d67d9f35SJunchao Zhang Input Parameters: 4274*11a5261eSBarry Smith + mat - a `MATSEQAIJ` matrix 4275d67d9f35SJunchao Zhang - array - pointer to the data 4276d67d9f35SJunchao Zhang 4277d67d9f35SJunchao Zhang Level: intermediate 4278d67d9f35SJunchao Zhang 4279db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayF90()` 4280d67d9f35SJunchao Zhang @*/ 42819371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArray(Mat A, PetscScalar **array) { 4282d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4283d67d9f35SJunchao Zhang 4284d67d9f35SJunchao Zhang PetscFunctionBegin; 4285d67d9f35SJunchao Zhang if (aij->ops->restorearray) { 42869566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearray)(A, array)); 4287d67d9f35SJunchao Zhang } else { 4288d67d9f35SJunchao Zhang *array = NULL; 4289d67d9f35SJunchao Zhang } 42909566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 42919566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 42928c778c55SBarry Smith PetscFunctionReturn(0); 42938c778c55SBarry Smith } 42948c778c55SBarry Smith 429521e72a00SBarry Smith /*@C 4296*11a5261eSBarry Smith MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a `MATSEQAIJ` matrix is stored 42978f1ea47aSStefano Zampini 42988f1ea47aSStefano Zampini Not Collective 42998f1ea47aSStefano Zampini 43008f1ea47aSStefano Zampini Input Parameter: 4301*11a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 43028f1ea47aSStefano Zampini 43038f1ea47aSStefano Zampini Output Parameter: 43048f1ea47aSStefano Zampini . array - pointer to the data 43058f1ea47aSStefano Zampini 43068f1ea47aSStefano Zampini Level: intermediate 43078f1ea47aSStefano Zampini 4308db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 43098f1ea47aSStefano Zampini @*/ 43109371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArrayRead(Mat A, const PetscScalar **array) { 4311d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 43128f1ea47aSStefano Zampini 43138f1ea47aSStefano Zampini PetscFunctionBegin; 4314d67d9f35SJunchao Zhang if (aij->ops->getarrayread) { 43159566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarrayread)(A, array)); 4316d67d9f35SJunchao Zhang } else { 4317d67d9f35SJunchao Zhang *array = aij->a; 4318d67d9f35SJunchao Zhang } 43198f1ea47aSStefano Zampini PetscFunctionReturn(0); 43208f1ea47aSStefano Zampini } 43218f1ea47aSStefano Zampini 43228f1ea47aSStefano Zampini /*@C 4323*11a5261eSBarry Smith MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from `MatSeqAIJGetArrayRead()` 43248f1ea47aSStefano Zampini 43258f1ea47aSStefano Zampini Not Collective 43268f1ea47aSStefano Zampini 43278f1ea47aSStefano Zampini Input Parameter: 4328*11a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 43298f1ea47aSStefano Zampini 43308f1ea47aSStefano Zampini Output Parameter: 43318f1ea47aSStefano Zampini . array - pointer to the data 43328f1ea47aSStefano Zampini 43338f1ea47aSStefano Zampini Level: intermediate 43348f1ea47aSStefano Zampini 4335db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 43368f1ea47aSStefano Zampini @*/ 43379371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArrayRead(Mat A, const PetscScalar **array) { 4338d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 43398f1ea47aSStefano Zampini 43408f1ea47aSStefano Zampini PetscFunctionBegin; 4341d67d9f35SJunchao Zhang if (aij->ops->restorearrayread) { 43429566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearrayread)(A, array)); 4343d67d9f35SJunchao Zhang } else { 4344d67d9f35SJunchao Zhang *array = NULL; 4345d67d9f35SJunchao Zhang } 4346d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4347d67d9f35SJunchao Zhang } 4348d67d9f35SJunchao Zhang 4349d67d9f35SJunchao Zhang /*@C 4350*11a5261eSBarry Smith MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a `MATSEQAIJ` matrix is stored 4351d67d9f35SJunchao Zhang 4352d67d9f35SJunchao Zhang Not Collective 4353d67d9f35SJunchao Zhang 4354d67d9f35SJunchao Zhang Input Parameter: 4355*11a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 4356d67d9f35SJunchao Zhang 4357d67d9f35SJunchao Zhang Output Parameter: 4358d67d9f35SJunchao Zhang . array - pointer to the data 4359d67d9f35SJunchao Zhang 4360d67d9f35SJunchao Zhang Level: intermediate 4361d67d9f35SJunchao Zhang 4362db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 4363d67d9f35SJunchao Zhang @*/ 43649371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArrayWrite(Mat A, PetscScalar **array) { 4365d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4366d67d9f35SJunchao Zhang 4367d67d9f35SJunchao Zhang PetscFunctionBegin; 4368d67d9f35SJunchao Zhang if (aij->ops->getarraywrite) { 43699566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarraywrite)(A, array)); 4370d67d9f35SJunchao Zhang } else { 4371d67d9f35SJunchao Zhang *array = aij->a; 4372d67d9f35SJunchao Zhang } 43739566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 43749566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 4375d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4376d67d9f35SJunchao Zhang } 4377d67d9f35SJunchao Zhang 4378d67d9f35SJunchao Zhang /*@C 4379d67d9f35SJunchao Zhang MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead 4380d67d9f35SJunchao Zhang 4381d67d9f35SJunchao Zhang Not Collective 4382d67d9f35SJunchao Zhang 4383d67d9f35SJunchao Zhang Input Parameter: 4384d67d9f35SJunchao Zhang . mat - a MATSEQAIJ matrix 4385d67d9f35SJunchao Zhang 4386d67d9f35SJunchao Zhang Output Parameter: 4387d67d9f35SJunchao Zhang . array - pointer to the data 4388d67d9f35SJunchao Zhang 4389d67d9f35SJunchao Zhang Level: intermediate 4390d67d9f35SJunchao Zhang 4391db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 4392d67d9f35SJunchao Zhang @*/ 43939371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArrayWrite(Mat A, PetscScalar **array) { 4394d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4395d67d9f35SJunchao Zhang 4396d67d9f35SJunchao Zhang PetscFunctionBegin; 4397d67d9f35SJunchao Zhang if (aij->ops->restorearraywrite) { 43989566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearraywrite)(A, array)); 4399d67d9f35SJunchao Zhang } else { 4400d67d9f35SJunchao Zhang *array = NULL; 4401d67d9f35SJunchao Zhang } 44028f1ea47aSStefano Zampini PetscFunctionReturn(0); 44038f1ea47aSStefano Zampini } 44048f1ea47aSStefano Zampini 44058f1ea47aSStefano Zampini /*@C 4406*11a5261eSBarry Smith MatSeqAIJGetCSRAndMemType - Get the CSR arrays and the memory type of the `MATSEQAIJ` matrix 44077ee59b9bSJunchao Zhang 44087ee59b9bSJunchao Zhang Not Collective 44097ee59b9bSJunchao Zhang 44107ee59b9bSJunchao Zhang Input Parameter: 4411*11a5261eSBarry Smith . mat - a matrix of type `MATSEQAIJ` or its subclasses 44127ee59b9bSJunchao Zhang 44137ee59b9bSJunchao Zhang Output Parameters: 44147ee59b9bSJunchao Zhang + i - row map array of the matrix 44157ee59b9bSJunchao Zhang . j - column index array of the matrix 44167ee59b9bSJunchao Zhang . a - data array of the matrix 44177ee59b9bSJunchao Zhang - memtype - memory type of the arrays 44187ee59b9bSJunchao Zhang 44197ee59b9bSJunchao Zhang Notes: 44207ee59b9bSJunchao Zhang Any of the output parameters can be NULL, in which case the corresponding value is not returned. 44217ee59b9bSJunchao Zhang If mat is a device matrix, the arrays are on the device. Otherwise, they are on the host. 44227ee59b9bSJunchao Zhang 44237ee59b9bSJunchao Zhang One can call this routine on a preallocated but not assembled matrix to just get the memory of the CSR underneath the matrix. 44247ee59b9bSJunchao Zhang If the matrix is assembled, the data array 'a' is guaranteed to have the latest values of the matrix. 44257ee59b9bSJunchao Zhang 44267ee59b9bSJunchao Zhang Level: Developer 44277ee59b9bSJunchao Zhang 4428db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 44297ee59b9bSJunchao Zhang @*/ 44309371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetCSRAndMemType(Mat mat, const PetscInt **i, const PetscInt **j, PetscScalar **a, PetscMemType *mtype) { 44317ee59b9bSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 44327ee59b9bSJunchao Zhang 44337ee59b9bSJunchao Zhang PetscFunctionBegin; 44347ee59b9bSJunchao Zhang PetscCheck(mat->preallocated, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "matrix is not preallocated"); 44357ee59b9bSJunchao Zhang if (aij->ops->getcsrandmemtype) { 44367ee59b9bSJunchao Zhang PetscCall((*aij->ops->getcsrandmemtype)(mat, i, j, a, mtype)); 44377ee59b9bSJunchao Zhang } else { 44387ee59b9bSJunchao Zhang if (i) *i = aij->i; 44397ee59b9bSJunchao Zhang if (j) *j = aij->j; 44407ee59b9bSJunchao Zhang if (a) *a = aij->a; 44417ee59b9bSJunchao Zhang if (mtype) *mtype = PETSC_MEMTYPE_HOST; 44427ee59b9bSJunchao Zhang } 44437ee59b9bSJunchao Zhang PetscFunctionReturn(0); 44447ee59b9bSJunchao Zhang } 44457ee59b9bSJunchao Zhang 44467ee59b9bSJunchao Zhang /*@C 444721e72a00SBarry Smith MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row 444821e72a00SBarry Smith 444921e72a00SBarry Smith Not Collective 445021e72a00SBarry Smith 445121e72a00SBarry Smith Input Parameter: 4452*11a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 445321e72a00SBarry Smith 445421e72a00SBarry Smith Output Parameter: 445521e72a00SBarry Smith . nz - the maximum number of nonzeros in any row 445621e72a00SBarry Smith 445721e72a00SBarry Smith Level: intermediate 445821e72a00SBarry Smith 4459db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()` 446021e72a00SBarry Smith @*/ 44619371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetMaxRowNonzeros(Mat A, PetscInt *nz) { 446221e72a00SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 446321e72a00SBarry Smith 446421e72a00SBarry Smith PetscFunctionBegin; 446521e72a00SBarry Smith *nz = aij->rmax; 446621e72a00SBarry Smith PetscFunctionReturn(0); 446721e72a00SBarry Smith } 446821e72a00SBarry Smith 44699371c9d4SSatish Balay PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[]) { 4470394ed5ebSJunchao Zhang MPI_Comm comm; 4471394ed5ebSJunchao Zhang PetscInt *i, *j; 4472394ed5ebSJunchao Zhang PetscInt M, N, row; 4473394ed5ebSJunchao Zhang PetscCount k, p, q, nneg, nnz, start, end; /* Index the coo array, so use PetscCount as their type */ 4474394ed5ebSJunchao Zhang PetscInt *Ai; /* Change to PetscCount once we use it for row pointers */ 4475394ed5ebSJunchao Zhang PetscInt *Aj; 4476394ed5ebSJunchao Zhang PetscScalar *Aa; 4477cbc6b225SStefano Zampini Mat_SeqAIJ *seqaij = (Mat_SeqAIJ *)(mat->data); 4478cbc6b225SStefano Zampini MatType rtype; 4479394ed5ebSJunchao Zhang PetscCount *perm, *jmap; 4480394ed5ebSJunchao Zhang 4481394ed5ebSJunchao Zhang PetscFunctionBegin; 44829566063dSJacob Faibussowitsch PetscCall(MatResetPreallocationCOO_SeqAIJ(mat)); 44839566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 44849566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &M, &N)); 4485e8729f6fSJunchao Zhang i = coo_i; 4486e8729f6fSJunchao Zhang j = coo_j; 44879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n, &perm)); 4488394ed5ebSJunchao Zhang for (k = 0; k < coo_n; k++) { /* Ignore entries with negative row or col indices */ 4489394ed5ebSJunchao Zhang if (j[k] < 0) i[k] = -1; 4490394ed5ebSJunchao Zhang perm[k] = k; 4491394ed5ebSJunchao Zhang } 4492394ed5ebSJunchao Zhang 4493394ed5ebSJunchao Zhang /* Sort by row */ 44949566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithIntCountArrayPair(coo_n, i, j, perm)); 44959371c9d4SSatish Balay for (k = 0; k < coo_n; k++) { 44969371c9d4SSatish Balay if (i[k] >= 0) break; 44979371c9d4SSatish Balay } /* Advance k to the first row with a non-negative index */ 4498394ed5ebSJunchao Zhang nneg = k; 44999566063dSJacob 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 */ 4500394ed5ebSJunchao Zhang nnz = 0; /* Total number of unique nonzeros to be counted */ 4501394ed5ebSJunchao Zhang jmap++; /* Inc jmap by 1 for convinience */ 4502394ed5ebSJunchao Zhang 45039566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(M + 1, &Ai)); /* CSR of A */ 45049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n - nneg, &Aj)); /* We have at most coo_n-nneg unique nonzeros */ 4505394ed5ebSJunchao Zhang 4506394ed5ebSJunchao Zhang /* In each row, sort by column, then unique column indices to get row length */ 4507394ed5ebSJunchao Zhang Ai++; /* Inc by 1 for convinience */ 4508394ed5ebSJunchao Zhang q = 0; /* q-th unique nonzero, with q starting from 0 */ 4509394ed5ebSJunchao Zhang while (k < coo_n) { 4510394ed5ebSJunchao Zhang row = i[k]; 4511394ed5ebSJunchao Zhang start = k; /* [start,end) indices for this row */ 4512394ed5ebSJunchao Zhang while (k < coo_n && i[k] == row) k++; 4513394ed5ebSJunchao Zhang end = k; 45149566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithCountArray(end - start, j + start, perm + start)); 4515394ed5ebSJunchao Zhang /* Find number of unique col entries in this row */ 4516394ed5ebSJunchao Zhang Aj[q] = j[start]; /* Log the first nonzero in this row */ 4517394ed5ebSJunchao Zhang jmap[q] = 1; /* Number of repeats of this nozero entry */ 4518394ed5ebSJunchao Zhang Ai[row] = 1; 4519394ed5ebSJunchao Zhang nnz++; 4520394ed5ebSJunchao Zhang 4521394ed5ebSJunchao Zhang for (p = start + 1; p < end; p++) { /* Scan remaining nonzero in this row */ 4522394ed5ebSJunchao Zhang if (j[p] != j[p - 1]) { /* Meet a new nonzero */ 4523394ed5ebSJunchao Zhang q++; 4524394ed5ebSJunchao Zhang jmap[q] = 1; 4525394ed5ebSJunchao Zhang Aj[q] = j[p]; 4526394ed5ebSJunchao Zhang Ai[row]++; 4527394ed5ebSJunchao Zhang nnz++; 4528394ed5ebSJunchao Zhang } else { 4529394ed5ebSJunchao Zhang jmap[q]++; 4530394ed5ebSJunchao Zhang } 4531394ed5ebSJunchao Zhang } 4532394ed5ebSJunchao Zhang q++; /* Move to next row and thus next unique nonzero */ 4533394ed5ebSJunchao Zhang } 4534394ed5ebSJunchao Zhang 4535394ed5ebSJunchao Zhang Ai--; /* Back to the beginning of Ai[] */ 4536394ed5ebSJunchao Zhang for (k = 0; k < M; k++) Ai[k + 1] += Ai[k]; 4537394ed5ebSJunchao Zhang jmap--; /* Back to the beginning of jmap[] */ 4538394ed5ebSJunchao Zhang jmap[0] = 0; 4539394ed5ebSJunchao Zhang for (k = 0; k < nnz; k++) jmap[k + 1] += jmap[k]; 4540394ed5ebSJunchao Zhang if (nnz < coo_n - nneg) { /* Realloc with actual number of unique nonzeros */ 4541394ed5ebSJunchao Zhang PetscCount *jmap_new; 4542394ed5ebSJunchao Zhang PetscInt *Aj_new; 4543394ed5ebSJunchao Zhang 45449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz + 1, &jmap_new)); 45459566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(jmap_new, jmap, nnz + 1)); 45469566063dSJacob Faibussowitsch PetscCall(PetscFree(jmap)); 4547394ed5ebSJunchao Zhang jmap = jmap_new; 4548394ed5ebSJunchao Zhang 45499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &Aj_new)); 45509566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(Aj_new, Aj, nnz)); 45519566063dSJacob Faibussowitsch PetscCall(PetscFree(Aj)); 4552394ed5ebSJunchao Zhang Aj = Aj_new; 4553394ed5ebSJunchao Zhang } 4554394ed5ebSJunchao Zhang 4555394ed5ebSJunchao Zhang if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */ 4556394ed5ebSJunchao Zhang PetscCount *perm_new; 4557cbc6b225SStefano Zampini 45589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n - nneg, &perm_new)); 45599566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(perm_new, perm + nneg, coo_n - nneg)); 45609566063dSJacob Faibussowitsch PetscCall(PetscFree(perm)); 4561394ed5ebSJunchao Zhang perm = perm_new; 4562394ed5ebSJunchao Zhang } 4563394ed5ebSJunchao Zhang 45649566063dSJacob Faibussowitsch PetscCall(MatGetRootType_Private(mat, &rtype)); 45659566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nnz, &Aa)); /* Zero the matrix */ 45669566063dSJacob Faibussowitsch PetscCall(MatSetSeqAIJWithArrays_private(PETSC_COMM_SELF, M, N, Ai, Aj, Aa, rtype, mat)); 4567394ed5ebSJunchao Zhang 4568394ed5ebSJunchao Zhang seqaij->singlemalloc = PETSC_FALSE; /* Ai, Aj and Aa are not allocated in one big malloc */ 4569394ed5ebSJunchao Zhang seqaij->free_a = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */ 4570394ed5ebSJunchao Zhang /* Record COO fields */ 4571394ed5ebSJunchao Zhang seqaij->coo_n = coo_n; 4572394ed5ebSJunchao Zhang seqaij->Atot = coo_n - nneg; /* Annz is seqaij->nz, so no need to record that again */ 4573394ed5ebSJunchao Zhang seqaij->jmap = jmap; /* of length nnz+1 */ 4574394ed5ebSJunchao Zhang seqaij->perm = perm; 4575394ed5ebSJunchao Zhang PetscFunctionReturn(0); 4576394ed5ebSJunchao Zhang } 4577394ed5ebSJunchao Zhang 45789371c9d4SSatish Balay static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A, const PetscScalar v[], InsertMode imode) { 4579394ed5ebSJunchao Zhang Mat_SeqAIJ *aseq = (Mat_SeqAIJ *)A->data; 4580394ed5ebSJunchao Zhang PetscCount i, j, Annz = aseq->nz; 4581394ed5ebSJunchao Zhang PetscCount *perm = aseq->perm, *jmap = aseq->jmap; 4582394ed5ebSJunchao Zhang PetscScalar *Aa; 4583394ed5ebSJunchao Zhang 4584394ed5ebSJunchao Zhang PetscFunctionBegin; 45859566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &Aa)); 4586394ed5ebSJunchao Zhang for (i = 0; i < Annz; i++) { 4587b6c38306SJunchao Zhang PetscScalar sum = 0.0; 4588b6c38306SJunchao Zhang for (j = jmap[i]; j < jmap[i + 1]; j++) sum += v[perm[j]]; 4589b6c38306SJunchao Zhang Aa[i] = (imode == INSERT_VALUES ? 0.0 : Aa[i]) + sum; 4590394ed5ebSJunchao Zhang } 45919566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &Aa)); 4592394ed5ebSJunchao Zhang PetscFunctionReturn(0); 4593394ed5ebSJunchao Zhang } 4594394ed5ebSJunchao Zhang 459534b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 45965063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat, MatType, MatReuse, Mat *); 459702fe1965SBarry Smith #endif 45983d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 45995063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat, MatType, MatReuse, Mat *); 46003d0639e7SStefano Zampini #endif 460102fe1965SBarry Smith 46029371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B) { 4603273d9f13SBarry Smith Mat_SeqAIJ *b; 460438baddfdSBarry Smith PetscMPIInt size; 4605273d9f13SBarry Smith 4606273d9f13SBarry Smith PetscFunctionBegin; 46079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size)); 460808401ef6SPierre Jolivet PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Comm must be of size 1"); 4609273d9f13SBarry Smith 46109566063dSJacob Faibussowitsch PetscCall(PetscNewLog(B, &b)); 46112205254eSKarl Rupp 4612b0a32e0cSBarry Smith B->data = (void *)b; 46132205254eSKarl Rupp 46149566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(B->ops, &MatOps_Values, sizeof(struct _MatOps))); 4615071fcb05SBarry Smith if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 46162205254eSKarl Rupp 4617f4259b30SLisandro Dalcin b->row = NULL; 4618f4259b30SLisandro Dalcin b->col = NULL; 4619f4259b30SLisandro Dalcin b->icol = NULL; 4620b810aeb4SBarry Smith b->reallocs = 0; 462136db0b34SBarry Smith b->ignorezeroentries = PETSC_FALSE; 4622f1e2ffcdSBarry Smith b->roworiented = PETSC_TRUE; 4623416022c9SBarry Smith b->nonew = 0; 4624f4259b30SLisandro Dalcin b->diag = NULL; 4625f4259b30SLisandro Dalcin b->solve_work = NULL; 4626f4259b30SLisandro Dalcin B->spptr = NULL; 4627f4259b30SLisandro Dalcin b->saved_values = NULL; 4628f4259b30SLisandro Dalcin b->idiag = NULL; 4629f4259b30SLisandro Dalcin b->mdiag = NULL; 4630f4259b30SLisandro Dalcin b->ssor_work = NULL; 463171f1c65dSBarry Smith b->omega = 1.0; 463271f1c65dSBarry Smith b->fshift = 0.0; 463371f1c65dSBarry Smith b->idiagvalid = PETSC_FALSE; 4634bbead8a2SBarry Smith b->ibdiagvalid = PETSC_FALSE; 4635a9817697SBarry Smith b->keepnonzeropattern = PETSC_FALSE; 463617ab2063SBarry Smith 46379566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ)); 4638b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE) 46399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEnginePut_C", MatlabEnginePut_SeqAIJ)); 46409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEngineGet_C", MatlabEngineGet_SeqAIJ)); 4641b3866ffcSBarry Smith #endif 46429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetColumnIndices_C", MatSeqAIJSetColumnIndices_SeqAIJ)); 46439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqAIJ)); 46449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqAIJ)); 46459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsbaij_C", MatConvert_SeqAIJ_SeqSBAIJ)); 46469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqbaij_C", MatConvert_SeqAIJ_SeqBAIJ)); 46479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijperm_C", MatConvert_SeqAIJ_SeqAIJPERM)); 46489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijsell_C", MatConvert_SeqAIJ_SeqAIJSELL)); 46499779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 46509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijmkl_C", MatConvert_SeqAIJ_SeqAIJMKL)); 4651191b95cbSRichard Tran Mills #endif 465234b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 46539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcusparse_C", MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 46549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_seqaij_C", MatProductSetFromOptions_SeqAIJ)); 46559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaijcusparse_C", MatProductSetFromOptions_SeqAIJ)); 465602fe1965SBarry Smith #endif 46573d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 46589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijkokkos_C", MatConvert_SeqAIJ_SeqAIJKokkos)); 46593d0639e7SStefano Zampini #endif 46609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcrl_C", MatConvert_SeqAIJ_SeqAIJCRL)); 4661af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 46629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_elemental_C", MatConvert_SeqAIJ_Elemental)); 4663af8000cdSHong Zhang #endif 4664d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 46659566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_scalapack_C", MatConvert_AIJ_ScaLAPACK)); 4666d24d4204SJose E. Roman #endif 466763c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 46689566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_hypre_C", MatConvert_AIJ_HYPRE)); 46699566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_transpose_seqaij_seqaij_C", MatProductSetFromOptions_Transpose_AIJ_AIJ)); 467063c07aadSStefano Zampini #endif 46719566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqdense_C", MatConvert_SeqAIJ_SeqDense)); 46729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsell_C", MatConvert_SeqAIJ_SeqSELL)); 46739566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_is_C", MatConvert_XAIJ_IS)); 46749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsTranspose_C", MatIsTranspose_SeqAIJ)); 46759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsHermitianTranspose_C", MatIsTranspose_SeqAIJ)); 46769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocation_C", MatSeqAIJSetPreallocation_SeqAIJ)); 46779566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatResetPreallocation_C", MatResetPreallocation_SeqAIJ)); 46789566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocationCSR_C", MatSeqAIJSetPreallocationCSR_SeqAIJ)); 46799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatReorderForNonzeroDiagonal_C", MatReorderForNonzeroDiagonal_SeqAIJ)); 46809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_is_seqaij_C", MatProductSetFromOptions_IS_XAIJ)); 46819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqaij_C", MatProductSetFromOptions_SeqDense_SeqAIJ)); 46829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaij_C", MatProductSetFromOptions_SeqAIJ)); 46839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJKron_C", MatSeqAIJKron_SeqAIJ)); 46849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_SeqAIJ)); 46859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_SeqAIJ)); 46869566063dSJacob Faibussowitsch PetscCall(MatCreate_SeqAIJ_Inode(B)); 46879566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ)); 46889566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetTypeFromOptions(B)); /* this allows changing the matrix subtype to say MATSEQAIJPERM */ 46893a40ed3dSBarry Smith PetscFunctionReturn(0); 469017ab2063SBarry Smith } 469117ab2063SBarry Smith 4692b24902e0SBarry Smith /* 46933893b582SJunchao Zhang Given a matrix generated with MatGetFactor() duplicates all the information in A into C 4694b24902e0SBarry Smith */ 46959371c9d4SSatish Balay PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C, Mat A, MatDuplicateOption cpvalues, PetscBool mallocmatspace) { 46962a350339SBarry Smith Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data, *a = (Mat_SeqAIJ *)A->data; 4697071fcb05SBarry Smith PetscInt m = A->rmap->n, i; 469817ab2063SBarry Smith 46993a40ed3dSBarry Smith PetscFunctionBegin; 4700aed4548fSBarry Smith PetscCheck(A->assembled || cpvalues == MAT_DO_NOT_COPY_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix"); 4701273d9f13SBarry Smith 4702d5f3da31SBarry Smith C->factortype = A->factortype; 4703f4259b30SLisandro Dalcin c->row = NULL; 4704f4259b30SLisandro Dalcin c->col = NULL; 4705f4259b30SLisandro Dalcin c->icol = NULL; 47066ad4291fSHong Zhang c->reallocs = 0; 470717ab2063SBarry Smith 470869272f91SPierre Jolivet C->assembled = A->assembled; 470969272f91SPierre Jolivet C->preallocated = A->preallocated; 471017ab2063SBarry Smith 471169272f91SPierre Jolivet if (A->preallocated) { 47129566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->rmap, &C->rmap)); 47139566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->cmap, &C->cmap)); 4714eec197d1SBarry Smith 47159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &c->imax)); 47169566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->imax, a->imax, m * sizeof(PetscInt))); 47179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &c->ilen)); 47189566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->ilen, a->ilen, m * sizeof(PetscInt))); 47199566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, 2 * m * sizeof(PetscInt))); 472017ab2063SBarry Smith 472117ab2063SBarry Smith /* allocate the matrix space */ 4722f77e22a1SHong Zhang if (mallocmatspace) { 47239566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(a->i[m], &c->a, a->i[m], &c->j, m + 1, &c->i)); 47249566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, a->i[m] * (sizeof(PetscScalar) + sizeof(PetscInt)) + (m + 1) * sizeof(PetscInt))); 47252205254eSKarl Rupp 4726f1e2ffcdSBarry Smith c->singlemalloc = PETSC_TRUE; 47272205254eSKarl Rupp 47289566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->i, a->i, m + 1)); 472917ab2063SBarry Smith if (m > 0) { 47309566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->j, a->j, a->i[m])); 4731be6bf707SBarry Smith if (cpvalues == MAT_COPY_VALUES) { 47322e5835c6SStefano Zampini const PetscScalar *aa; 47332e5835c6SStefano Zampini 47349566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 47359566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->a, aa, a->i[m])); 47369566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 4737be6bf707SBarry Smith } else { 47389566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->a, a->i[m])); 473917ab2063SBarry Smith } 474008480c60SBarry Smith } 4741f77e22a1SHong Zhang } 474217ab2063SBarry Smith 47436ad4291fSHong Zhang c->ignorezeroentries = a->ignorezeroentries; 4744416022c9SBarry Smith c->roworiented = a->roworiented; 4745416022c9SBarry Smith c->nonew = a->nonew; 4746416022c9SBarry Smith if (a->diag) { 47479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &c->diag)); 47489566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->diag, a->diag, m * sizeof(PetscInt))); 47499566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, (m + 1) * sizeof(PetscInt))); 4750071fcb05SBarry Smith } else c->diag = NULL; 47512205254eSKarl Rupp 4752f4259b30SLisandro Dalcin c->solve_work = NULL; 4753f4259b30SLisandro Dalcin c->saved_values = NULL; 4754f4259b30SLisandro Dalcin c->idiag = NULL; 4755f4259b30SLisandro Dalcin c->ssor_work = NULL; 4756a9817697SBarry Smith c->keepnonzeropattern = a->keepnonzeropattern; 4757e6b907acSBarry Smith c->free_a = PETSC_TRUE; 4758e6b907acSBarry Smith c->free_ij = PETSC_TRUE; 47596ad4291fSHong Zhang 4760893ad86cSHong Zhang c->rmax = a->rmax; 4761416022c9SBarry Smith c->nz = a->nz; 47628ed568f8SMatthew G Knepley c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 4763754ec7b1SSatish Balay 47646ad4291fSHong Zhang c->compressedrow.use = a->compressedrow.use; 47656ad4291fSHong Zhang c->compressedrow.nrows = a->compressedrow.nrows; 4766cd6b891eSBarry Smith if (a->compressedrow.use) { 47676ad4291fSHong Zhang i = a->compressedrow.nrows; 47689566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i + 1, &c->compressedrow.i, i, &c->compressedrow.rindex)); 47699566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.i, a->compressedrow.i, i + 1)); 47709566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.rindex, a->compressedrow.rindex, i)); 477127ea64f8SHong Zhang } else { 477227ea64f8SHong Zhang c->compressedrow.use = PETSC_FALSE; 47730298fd71SBarry Smith c->compressedrow.i = NULL; 47740298fd71SBarry Smith c->compressedrow.rindex = NULL; 47756ad4291fSHong Zhang } 4776ea632784SBarry Smith c->nonzerorowcnt = a->nonzerorowcnt; 4777e56f5c9eSBarry Smith C->nonzerostate = A->nonzerostate; 47784846f1f5SKris Buschelman 47799566063dSJacob Faibussowitsch PetscCall(MatDuplicate_SeqAIJ_Inode(A, cpvalues, &C)); 478069272f91SPierre Jolivet } 47819566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist)); 47823a40ed3dSBarry Smith PetscFunctionReturn(0); 478317ab2063SBarry Smith } 478417ab2063SBarry Smith 47859371c9d4SSatish Balay PetscErrorCode MatDuplicate_SeqAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B) { 4786b24902e0SBarry Smith PetscFunctionBegin; 47879566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 47889566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n)); 478948a46eb9SPierre Jolivet if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) PetscCall(MatSetBlockSizesFromMats(*B, A, A)); 47909566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, ((PetscObject)A)->type_name)); 47919566063dSJacob Faibussowitsch PetscCall(MatDuplicateNoCreate_SeqAIJ(*B, A, cpvalues, PETSC_TRUE)); 4792b24902e0SBarry Smith PetscFunctionReturn(0); 4793b24902e0SBarry Smith } 4794b24902e0SBarry Smith 47959371c9d4SSatish Balay PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer) { 479652f91c60SVaclav Hapla PetscBool isbinary, ishdf5; 479752f91c60SVaclav Hapla 479852f91c60SVaclav Hapla PetscFunctionBegin; 479952f91c60SVaclav Hapla PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1); 480052f91c60SVaclav Hapla PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 4801c27b3999SVaclav Hapla /* force binary viewer to load .info file if it has not yet done so */ 48029566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 48039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 48049566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 480552f91c60SVaclav Hapla if (isbinary) { 48069566063dSJacob Faibussowitsch PetscCall(MatLoad_SeqAIJ_Binary(newMat, viewer)); 480752f91c60SVaclav Hapla } else if (ishdf5) { 480852f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5) 48099566063dSJacob Faibussowitsch PetscCall(MatLoad_AIJ_HDF5(newMat, viewer)); 481052f91c60SVaclav Hapla #else 481152f91c60SVaclav Hapla SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 481252f91c60SVaclav Hapla #endif 481352f91c60SVaclav Hapla } else { 481498921bdaSJacob 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); 481552f91c60SVaclav Hapla } 481652f91c60SVaclav Hapla PetscFunctionReturn(0); 481752f91c60SVaclav Hapla } 481852f91c60SVaclav Hapla 48199371c9d4SSatish Balay PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer) { 48203ea6fe3dSLisandro Dalcin Mat_SeqAIJ *a = (Mat_SeqAIJ *)mat->data; 48213ea6fe3dSLisandro Dalcin PetscInt header[4], *rowlens, M, N, nz, sum, rows, cols, i; 4822fbdbba38SShri Abhyankar 4823fbdbba38SShri Abhyankar PetscFunctionBegin; 48249566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 4825bbead8a2SBarry Smith 48263ea6fe3dSLisandro Dalcin /* read in matrix header */ 48279566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT)); 482808401ef6SPierre Jolivet PetscCheck(header[0] == MAT_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file"); 48299371c9d4SSatish Balay M = header[1]; 48309371c9d4SSatish Balay N = header[2]; 48319371c9d4SSatish Balay nz = header[3]; 483208401ef6SPierre Jolivet PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M); 483308401ef6SPierre Jolivet PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N); 483408401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Matrix stored in special format on disk, cannot load as SeqAIJ"); 4835fbdbba38SShri Abhyankar 48363ea6fe3dSLisandro Dalcin /* set block sizes from the viewer's .info file */ 48379566063dSJacob Faibussowitsch PetscCall(MatLoad_Binary_BlockSizes(mat, viewer)); 48383ea6fe3dSLisandro Dalcin /* set local and global sizes if not set already */ 48393ea6fe3dSLisandro Dalcin if (mat->rmap->n < 0) mat->rmap->n = M; 48403ea6fe3dSLisandro Dalcin if (mat->cmap->n < 0) mat->cmap->n = N; 48413ea6fe3dSLisandro Dalcin if (mat->rmap->N < 0) mat->rmap->N = M; 48423ea6fe3dSLisandro Dalcin if (mat->cmap->N < 0) mat->cmap->N = N; 48439566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->rmap)); 48449566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->cmap)); 48453ea6fe3dSLisandro Dalcin 48463ea6fe3dSLisandro Dalcin /* check if the matrix sizes are correct */ 48479566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 4848aed4548fSBarry 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); 48493ea6fe3dSLisandro Dalcin 4850fbdbba38SShri Abhyankar /* read in row lengths */ 48519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(M, &rowlens)); 48529566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, rowlens, M, NULL, PETSC_INT)); 48533ea6fe3dSLisandro Dalcin /* check if sum(rowlens) is same as nz */ 48549371c9d4SSatish Balay sum = 0; 48559371c9d4SSatish Balay for (i = 0; i < M; i++) sum += rowlens[i]; 485608401ef6SPierre 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); 48573ea6fe3dSLisandro Dalcin /* preallocate and check sizes */ 48589566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(mat, 0, rowlens)); 48599566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 4860aed4548fSBarry 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); 48613ea6fe3dSLisandro Dalcin /* store row lengths */ 48629566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->ilen, rowlens, M)); 48639566063dSJacob Faibussowitsch PetscCall(PetscFree(rowlens)); 4864fbdbba38SShri Abhyankar 48653ea6fe3dSLisandro Dalcin /* fill in "i" row pointers */ 48669371c9d4SSatish Balay a->i[0] = 0; 48679371c9d4SSatish Balay for (i = 0; i < M; i++) a->i[i + 1] = a->i[i] + a->ilen[i]; 48683ea6fe3dSLisandro Dalcin /* read in "j" column indices */ 48699566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, a->j, nz, NULL, PETSC_INT)); 48703ea6fe3dSLisandro Dalcin /* read in "a" nonzero values */ 48719566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, a->a, nz, NULL, PETSC_SCALAR)); 4872fbdbba38SShri Abhyankar 48739566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 48749566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 4875fbdbba38SShri Abhyankar PetscFunctionReturn(0); 4876fbdbba38SShri Abhyankar } 4877fbdbba38SShri Abhyankar 48789371c9d4SSatish Balay PetscErrorCode MatEqual_SeqAIJ(Mat A, Mat B, PetscBool *flg) { 48797264ac53SSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data, *b = (Mat_SeqAIJ *)B->data; 4880fff043a9SJunchao Zhang const PetscScalar *aa, *ba; 4881eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 4882eeffb40dSHong Zhang PetscInt k; 4883eeffb40dSHong Zhang #endif 48847264ac53SSatish Balay 48853a40ed3dSBarry Smith PetscFunctionBegin; 4886bfeeae90SHong Zhang /* If the matrix dimensions are not equal,or no of nonzeros */ 4887d0f46423SBarry Smith if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) || (a->nz != b->nz)) { 4888ca44d042SBarry Smith *flg = PETSC_FALSE; 4889ca44d042SBarry Smith PetscFunctionReturn(0); 4890bcd2baecSBarry Smith } 48917264ac53SSatish Balay 48927264ac53SSatish Balay /* if the a->i are the same */ 48939566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->i, b->i, A->rmap->n + 1, flg)); 4894abc0a331SBarry Smith if (!*flg) PetscFunctionReturn(0); 48957264ac53SSatish Balay 48967264ac53SSatish Balay /* if a->j are the same */ 48979566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->j, b->j, a->nz, flg)); 4898abc0a331SBarry Smith if (!*flg) PetscFunctionReturn(0); 4899bcd2baecSBarry Smith 49009566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 49019566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &ba)); 4902bcd2baecSBarry Smith /* if a->a are the same */ 4903eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 4904eeffb40dSHong Zhang for (k = 0; k < a->nz; k++) { 4905fff043a9SJunchao Zhang if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) { 4906eeffb40dSHong Zhang *flg = PETSC_FALSE; 49073a40ed3dSBarry Smith PetscFunctionReturn(0); 4908eeffb40dSHong Zhang } 4909eeffb40dSHong Zhang } 4910eeffb40dSHong Zhang #else 49119566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(aa, ba, a->nz, flg)); 4912eeffb40dSHong Zhang #endif 49139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 49149566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &ba)); 4915eeffb40dSHong Zhang PetscFunctionReturn(0); 49167264ac53SSatish Balay } 491736db0b34SBarry Smith 491805869f15SSatish Balay /*@ 4919*11a5261eSBarry Smith MatCreateSeqAIJWithArrays - Creates an sequential `MATSEQAIJ` matrix using matrix elements (in CSR format) 492036db0b34SBarry Smith provided by the user. 492136db0b34SBarry Smith 4922d083f849SBarry Smith Collective 492336db0b34SBarry Smith 492436db0b34SBarry Smith Input Parameters: 492536db0b34SBarry Smith + comm - must be an MPI communicator of size 1 492636db0b34SBarry Smith . m - number of rows 492736db0b34SBarry Smith . n - number of columns 4928483a2f95SBarry Smith . i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 492936db0b34SBarry Smith . j - column indices 493036db0b34SBarry Smith - a - matrix values 493136db0b34SBarry Smith 493236db0b34SBarry Smith Output Parameter: 493336db0b34SBarry Smith . mat - the matrix 493436db0b34SBarry Smith 493536db0b34SBarry Smith Level: intermediate 493636db0b34SBarry Smith 493736db0b34SBarry Smith Notes: 49380551d7c0SBarry Smith The i, j, and a arrays are not copied by this routine, the user must free these arrays 4939292fb18eSBarry Smith once the matrix is destroyed and not before 494036db0b34SBarry Smith 494136db0b34SBarry Smith You cannot set new nonzero locations into this matrix, that will generate an error. 494236db0b34SBarry Smith 4943bfeeae90SHong Zhang The i and j indices are 0 based 494436db0b34SBarry Smith 4945a4552177SSatish Balay The format which is used for the sparse matrix input, is equivalent to a 4946a4552177SSatish Balay row-major ordering.. i.e for the following matrix, the input data expected is 49478eef79e4SBarry Smith as shown 4948a4552177SSatish Balay 49498eef79e4SBarry Smith $ 1 0 0 49508eef79e4SBarry Smith $ 2 0 3 49518eef79e4SBarry Smith $ 4 5 6 49528eef79e4SBarry Smith $ 49538eef79e4SBarry Smith $ i = {0,1,3,6} [size = nrow+1 = 3+1] 49548eef79e4SBarry Smith $ j = {0,0,2,0,1,2} [size = 6]; values must be sorted for each row 49558eef79e4SBarry Smith $ v = {1,2,3,4,5,6} [size = 6] 4956a4552177SSatish Balay 4957db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateMPIAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()` 495836db0b34SBarry Smith @*/ 49599371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat) { 4960cbcfb4deSHong Zhang PetscInt ii; 496136db0b34SBarry Smith Mat_SeqAIJ *aij; 4962cbcfb4deSHong Zhang PetscInt jj; 496336db0b34SBarry Smith 496436db0b34SBarry Smith PetscFunctionBegin; 4965aed4548fSBarry Smith PetscCheck(m <= 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0"); 49669566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 49679566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 49689566063dSJacob Faibussowitsch /* PetscCall(MatSetBlockSizes(*mat,,)); */ 49699566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQAIJ)); 49709566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, MAT_SKIP_ALLOCATION, NULL)); 4971ab93d7beSBarry Smith aij = (Mat_SeqAIJ *)(*mat)->data; 49729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &aij->imax)); 49739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &aij->ilen)); 4974ab93d7beSBarry Smith 497536db0b34SBarry Smith aij->i = i; 497636db0b34SBarry Smith aij->j = j; 497736db0b34SBarry Smith aij->a = a; 497836db0b34SBarry Smith aij->singlemalloc = PETSC_FALSE; 497936db0b34SBarry Smith aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 4980e6b907acSBarry Smith aij->free_a = PETSC_FALSE; 4981e6b907acSBarry Smith aij->free_ij = PETSC_FALSE; 498236db0b34SBarry Smith 4983cbc6b225SStefano Zampini for (ii = 0, aij->nonzerorowcnt = 0, aij->rmax = 0; ii < m; ii++) { 498436db0b34SBarry Smith aij->ilen[ii] = aij->imax[ii] = i[ii + 1] - i[ii]; 498576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4986aed4548fSBarry 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]); 49879985e31cSBarry Smith for (jj = i[ii] + 1; jj < i[ii + 1]; jj++) { 498808401ef6SPierre 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); 498908401ef6SPierre 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); 49909985e31cSBarry Smith } 499136db0b34SBarry Smith } 499276bd3646SJed Brown } 499376bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 499436db0b34SBarry Smith for (ii = 0; ii < aij->i[m]; ii++) { 499508401ef6SPierre 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]); 4996aed4548fSBarry 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]); 499736db0b34SBarry Smith } 499876bd3646SJed Brown } 499936db0b34SBarry Smith 50009566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 50019566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 500236db0b34SBarry Smith PetscFunctionReturn(0); 500336db0b34SBarry Smith } 5004cbc6b225SStefano Zampini 5005f62e3866SBarry Smith /*@ 5006*11a5261eSBarry Smith MatCreateSeqAIJFromTriple - Creates an sequential `MATSEQAIJ` matrix using matrix elements (in COO format) 50078a0b0e6bSVictor Minden provided by the user. 50088a0b0e6bSVictor Minden 5009d083f849SBarry Smith Collective 50108a0b0e6bSVictor Minden 50118a0b0e6bSVictor Minden Input Parameters: 50128a0b0e6bSVictor Minden + comm - must be an MPI communicator of size 1 50138a0b0e6bSVictor Minden . m - number of rows 50148a0b0e6bSVictor Minden . n - number of columns 50158a0b0e6bSVictor Minden . i - row indices 50168a0b0e6bSVictor Minden . j - column indices 50171230e6d1SVictor Minden . a - matrix values 50181230e6d1SVictor Minden . nz - number of nonzeros 5019*11a5261eSBarry Smith - idx - if the i and j indices start with 1 use `PETSC_TRUE` otherwise use `PETSC_FALSE` 50208a0b0e6bSVictor Minden 50218a0b0e6bSVictor Minden Output Parameter: 50228a0b0e6bSVictor Minden . mat - the matrix 50238a0b0e6bSVictor Minden 50248a0b0e6bSVictor Minden Level: intermediate 50258a0b0e6bSVictor Minden 5026f62e3866SBarry Smith Example: 5027f62e3866SBarry Smith For the following matrix, the input data expected is as shown (using 0 based indexing) 50289e99939fSJunchao Zhang .vb 50298a0b0e6bSVictor Minden 1 0 0 50308a0b0e6bSVictor Minden 2 0 3 50318a0b0e6bSVictor Minden 4 5 6 50328a0b0e6bSVictor Minden 50338a0b0e6bSVictor Minden i = {0,1,1,2,2,2} 50348a0b0e6bSVictor Minden j = {0,0,2,0,1,2} 50358a0b0e6bSVictor Minden v = {1,2,3,4,5,6} 50369e99939fSJunchao Zhang .ve 50378a0b0e6bSVictor Minden 5038db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateSeqAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()`, `MatSetValuesCOO()` 50398a0b0e6bSVictor Minden @*/ 50409371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat, PetscInt nz, PetscBool idx) { 5041d021a1c5SVictor Minden PetscInt ii, *nnz, one = 1, row, col; 50428a0b0e6bSVictor Minden 50438a0b0e6bSVictor Minden PetscFunctionBegin; 50449566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m, &nnz)); 5045ad540459SPierre Jolivet for (ii = 0; ii < nz; ii++) nnz[i[ii] - !!idx] += 1; 50469566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 50479566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 50489566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQAIJ)); 50499566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, 0, nnz)); 50501230e6d1SVictor Minden for (ii = 0; ii < nz; ii++) { 50511230e6d1SVictor Minden if (idx) { 50521230e6d1SVictor Minden row = i[ii] - 1; 50531230e6d1SVictor Minden col = j[ii] - 1; 50541230e6d1SVictor Minden } else { 50551230e6d1SVictor Minden row = i[ii]; 50561230e6d1SVictor Minden col = j[ii]; 50578a0b0e6bSVictor Minden } 50589566063dSJacob Faibussowitsch PetscCall(MatSetValues(*mat, one, &row, one, &col, &a[ii], ADD_VALUES)); 50598a0b0e6bSVictor Minden } 50609566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 50619566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 50629566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 50638a0b0e6bSVictor Minden PetscFunctionReturn(0); 50648a0b0e6bSVictor Minden } 506536db0b34SBarry Smith 50669371c9d4SSatish Balay PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A) { 5067acf2f550SJed Brown Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 5068acf2f550SJed Brown 5069acf2f550SJed Brown PetscFunctionBegin; 5070acf2f550SJed Brown a->idiagvalid = PETSC_FALSE; 5071acf2f550SJed Brown a->ibdiagvalid = PETSC_FALSE; 50722205254eSKarl Rupp 50739566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal_Inode(A)); 5074acf2f550SJed Brown PetscFunctionReturn(0); 5075acf2f550SJed Brown } 5076acf2f550SJed Brown 50779371c9d4SSatish Balay PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat) { 50789c8f2541SHong Zhang PetscFunctionBegin; 50799566063dSJacob Faibussowitsch PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm, inmat, n, scall, outmat)); 50809c8f2541SHong Zhang PetscFunctionReturn(0); 50819c8f2541SHong Zhang } 50829c8f2541SHong Zhang 508381824310SBarry Smith /* 508453dd7562SDmitry Karpeev Permute A into C's *local* index space using rowemb,colemb. 508553dd7562SDmitry Karpeev The embedding are supposed to be injections and the above implies that the range of rowemb is a subset 508653dd7562SDmitry Karpeev of [0,m), colemb is in [0,n). 508753dd7562SDmitry Karpeev If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A. 508853dd7562SDmitry Karpeev */ 50899371c9d4SSatish Balay PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C, IS rowemb, IS colemb, MatStructure pattern, Mat B) { 509053dd7562SDmitry Karpeev /* If making this function public, change the error returned in this function away from _PLIB. */ 509153dd7562SDmitry Karpeev Mat_SeqAIJ *Baij; 509253dd7562SDmitry Karpeev PetscBool seqaij; 509353dd7562SDmitry Karpeev PetscInt m, n, *nz, i, j, count; 509453dd7562SDmitry Karpeev PetscScalar v; 509553dd7562SDmitry Karpeev const PetscInt *rowindices, *colindices; 509653dd7562SDmitry Karpeev 509753dd7562SDmitry Karpeev PetscFunctionBegin; 509853dd7562SDmitry Karpeev if (!B) PetscFunctionReturn(0); 509953dd7562SDmitry Karpeev /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */ 51009566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)B, MATSEQAIJ, &seqaij)); 510128b400f6SJacob Faibussowitsch PetscCheck(seqaij, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is of wrong type"); 510253dd7562SDmitry Karpeev if (rowemb) { 51039566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rowemb, &m)); 510408401ef6SPierre 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); 510553dd7562SDmitry Karpeev } else { 510608401ef6SPierre Jolivet PetscCheck(C->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is row-incompatible with the target matrix"); 510753dd7562SDmitry Karpeev } 510853dd7562SDmitry Karpeev if (colemb) { 51099566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(colemb, &n)); 511008401ef6SPierre 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); 511153dd7562SDmitry Karpeev } else { 511208401ef6SPierre Jolivet PetscCheck(C->cmap->n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is col-incompatible with the target matrix"); 511353dd7562SDmitry Karpeev } 511453dd7562SDmitry Karpeev 511553dd7562SDmitry Karpeev Baij = (Mat_SeqAIJ *)(B->data); 511653dd7562SDmitry Karpeev if (pattern == DIFFERENT_NONZERO_PATTERN) { 51179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n, &nz)); 5118ad540459SPierre Jolivet for (i = 0; i < B->rmap->n; i++) nz[i] = Baij->i[i + 1] - Baij->i[i]; 51199566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(C, 0, nz)); 51209566063dSJacob Faibussowitsch PetscCall(PetscFree(nz)); 512153dd7562SDmitry Karpeev } 512248a46eb9SPierre Jolivet if (pattern == SUBSET_NONZERO_PATTERN) PetscCall(MatZeroEntries(C)); 512353dd7562SDmitry Karpeev count = 0; 512453dd7562SDmitry Karpeev rowindices = NULL; 512553dd7562SDmitry Karpeev colindices = NULL; 512648a46eb9SPierre Jolivet if (rowemb) PetscCall(ISGetIndices(rowemb, &rowindices)); 512748a46eb9SPierre Jolivet if (colemb) PetscCall(ISGetIndices(colemb, &colindices)); 512853dd7562SDmitry Karpeev for (i = 0; i < B->rmap->n; i++) { 512953dd7562SDmitry Karpeev PetscInt row; 513053dd7562SDmitry Karpeev row = i; 513153dd7562SDmitry Karpeev if (rowindices) row = rowindices[i]; 513253dd7562SDmitry Karpeev for (j = Baij->i[i]; j < Baij->i[i + 1]; j++) { 513353dd7562SDmitry Karpeev PetscInt col; 513453dd7562SDmitry Karpeev col = Baij->j[count]; 513553dd7562SDmitry Karpeev if (colindices) col = colindices[col]; 513653dd7562SDmitry Karpeev v = Baij->a[count]; 51379566063dSJacob Faibussowitsch PetscCall(MatSetValues(C, 1, &row, 1, &col, &v, INSERT_VALUES)); 513853dd7562SDmitry Karpeev ++count; 513953dd7562SDmitry Karpeev } 514053dd7562SDmitry Karpeev } 514153dd7562SDmitry Karpeev /* FIXME: set C's nonzerostate correctly. */ 514253dd7562SDmitry Karpeev /* Assembly for C is necessary. */ 514353dd7562SDmitry Karpeev C->preallocated = PETSC_TRUE; 514453dd7562SDmitry Karpeev C->assembled = PETSC_TRUE; 514553dd7562SDmitry Karpeev C->was_assembled = PETSC_FALSE; 514653dd7562SDmitry Karpeev PetscFunctionReturn(0); 514753dd7562SDmitry Karpeev } 514853dd7562SDmitry Karpeev 51494099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL; 51504099cc6bSBarry Smith 51514099cc6bSBarry Smith /*@C 5152*11a5261eSBarry Smith MatSeqAIJSetType - Converts a `MATSEQAIJ` matrix to a subtype 51534099cc6bSBarry Smith 5154*11a5261eSBarry Smith Collective on mat 51554099cc6bSBarry Smith 51564099cc6bSBarry Smith Input Parameters: 51574099cc6bSBarry Smith + mat - the matrix object 51584099cc6bSBarry Smith - matype - matrix type 51594099cc6bSBarry Smith 51604099cc6bSBarry Smith Options Database Key: 51614099cc6bSBarry Smith . -mat_seqai_type <method> - for example seqaijcrl 51624099cc6bSBarry Smith 51634099cc6bSBarry Smith Level: intermediate 51644099cc6bSBarry Smith 5165db781477SPatrick Sanan .seealso: `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat` 51664099cc6bSBarry Smith @*/ 51679371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetType(Mat mat, MatType matype) { 51684099cc6bSBarry Smith PetscBool sametype; 51695f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(Mat, MatType, MatReuse, Mat *); 51704099cc6bSBarry Smith 51714099cc6bSBarry Smith PetscFunctionBegin; 51724099cc6bSBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 51739566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, matype, &sametype)); 51744099cc6bSBarry Smith if (sametype) PetscFunctionReturn(0); 51754099cc6bSBarry Smith 51769566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(MatSeqAIJList, matype, &r)); 51775f80ce2aSJacob Faibussowitsch PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Mat type given: %s", matype); 51789566063dSJacob Faibussowitsch PetscCall((*r)(mat, matype, MAT_INPLACE_MATRIX, &mat)); 51794099cc6bSBarry Smith PetscFunctionReturn(0); 51804099cc6bSBarry Smith } 51814099cc6bSBarry Smith 51824099cc6bSBarry Smith /*@C 5183*11a5261eSBarry Smith MatSeqAIJRegister - - Adds a new sub-matrix type for sequential `MATSEQAIJ` matrices 51844099cc6bSBarry Smith 51854099cc6bSBarry Smith Not Collective 51864099cc6bSBarry Smith 51874099cc6bSBarry Smith Input Parameters: 5188*11a5261eSBarry Smith + name - name of a new user-defined matrix type, for example `MATSEQAIJCRL` 51894099cc6bSBarry Smith - function - routine to convert to subtype 51904099cc6bSBarry Smith 51914099cc6bSBarry Smith Notes: 5192*11a5261eSBarry Smith `MatSeqAIJRegister()` may be called multiple times to add several user-defined solvers. 51934099cc6bSBarry Smith 51944099cc6bSBarry Smith Then, your matrix can be chosen with the procedural interface at runtime via the option 51954099cc6bSBarry Smith $ -mat_seqaij_type my_mat 51964099cc6bSBarry Smith 51974099cc6bSBarry Smith Level: advanced 51984099cc6bSBarry Smith 5199db781477SPatrick Sanan .seealso: `MatSeqAIJRegisterAll()` 52004099cc6bSBarry Smith @*/ 52019371c9d4SSatish Balay PetscErrorCode MatSeqAIJRegister(const char sname[], PetscErrorCode (*function)(Mat, MatType, MatReuse, Mat *)) { 52024099cc6bSBarry Smith PetscFunctionBegin; 52039566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 52049566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&MatSeqAIJList, sname, function)); 52054099cc6bSBarry Smith PetscFunctionReturn(0); 52064099cc6bSBarry Smith } 52074099cc6bSBarry Smith 52084099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE; 52094099cc6bSBarry Smith 52104099cc6bSBarry Smith /*@C 5211*11a5261eSBarry Smith MatSeqAIJRegisterAll - Registers all of the matrix subtypes of `MATSSEQAIJ` 52124099cc6bSBarry Smith 52134099cc6bSBarry Smith Not Collective 52144099cc6bSBarry Smith 52154099cc6bSBarry Smith Level: advanced 52164099cc6bSBarry Smith 5217db781477SPatrick Sanan .seealso: `MatRegisterAll()`, `MatSeqAIJRegister()` 52184099cc6bSBarry Smith @*/ 52199371c9d4SSatish Balay PetscErrorCode MatSeqAIJRegisterAll(void) { 52204099cc6bSBarry Smith PetscFunctionBegin; 52214099cc6bSBarry Smith if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0); 52224099cc6bSBarry Smith MatSeqAIJRegisterAllCalled = PETSC_TRUE; 52234099cc6bSBarry Smith 52249566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCRL, MatConvert_SeqAIJ_SeqAIJCRL)); 52259566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJPERM, MatConvert_SeqAIJ_SeqAIJPERM)); 52269566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJSELL, MatConvert_SeqAIJ_SeqAIJSELL)); 52279779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 52289566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJMKL, MatConvert_SeqAIJ_SeqAIJMKL)); 5229485f9817SRichard Tran Mills #endif 52305063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA) 52319566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 52325063d097SStefano Zampini #endif 52335063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 52349566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJKOKKOS, MatConvert_SeqAIJ_SeqAIJKokkos)); 52355063d097SStefano Zampini #endif 52364099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA) 52379566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL)); 52384099cc6bSBarry Smith #endif 52394099cc6bSBarry Smith PetscFunctionReturn(0); 52404099cc6bSBarry Smith } 524153dd7562SDmitry Karpeev 524253dd7562SDmitry Karpeev /* 524381824310SBarry Smith Special version for direct calls from Fortran 524481824310SBarry Smith */ 5245af0996ceSBarry Smith #include <petsc/private/fortranimpl.h> 524681824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS) 524781824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ 524881824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 524981824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij 525081824310SBarry Smith #endif 525181824310SBarry Smith 525281824310SBarry Smith /* Change these macros so can be used in void function */ 525398921bdaSJacob Faibussowitsch 525498921bdaSJacob Faibussowitsch /* Change these macros so can be used in void function */ 52559566063dSJacob Faibussowitsch /* Identical to PetscCallVoid, except it assigns to *_ierr */ 52569566063dSJacob Faibussowitsch #undef PetscCall 52579371c9d4SSatish Balay #define PetscCall(...) \ 52589371c9d4SSatish Balay do { \ 52595f80ce2aSJacob Faibussowitsch PetscErrorCode ierr_msv_mpiaij = __VA_ARGS__; \ 526098921bdaSJacob Faibussowitsch if (PetscUnlikely(ierr_msv_mpiaij)) { \ 526198921bdaSJacob Faibussowitsch *_ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr_msv_mpiaij, PETSC_ERROR_REPEAT, " "); \ 526298921bdaSJacob Faibussowitsch return; \ 526398921bdaSJacob Faibussowitsch } \ 526498921bdaSJacob Faibussowitsch } while (0) 526598921bdaSJacob Faibussowitsch 526698921bdaSJacob Faibussowitsch #undef SETERRQ 52679371c9d4SSatish Balay #define SETERRQ(comm, ierr, ...) \ 52689371c9d4SSatish Balay do { \ 526998921bdaSJacob Faibussowitsch *_ierr = PetscError(comm, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr, PETSC_ERROR_INITIAL, __VA_ARGS__); \ 527098921bdaSJacob Faibussowitsch return; \ 527198921bdaSJacob Faibussowitsch } while (0) 527281824310SBarry Smith 52739371c9d4SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA, PetscInt *mm, const PetscInt im[], PetscInt *nn, const PetscInt in[], const PetscScalar v[], InsertMode *isis, PetscErrorCode *_ierr) { 527481824310SBarry Smith Mat A = *AA; 527581824310SBarry Smith PetscInt m = *mm, n = *nn; 527681824310SBarry Smith InsertMode is = *isis; 527781824310SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 527881824310SBarry Smith PetscInt *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N; 527981824310SBarry Smith PetscInt *imax, *ai, *ailen; 528081824310SBarry Smith PetscInt *aj, nonew = a->nonew, lastcol = -1; 528154f21887SBarry Smith MatScalar *ap, value, *aa; 5282ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 5283ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 528481824310SBarry Smith 528581824310SBarry Smith PetscFunctionBegin; 52864994cf47SJed Brown MatCheckPreallocated(A, 1); 528781824310SBarry Smith imax = a->imax; 528881824310SBarry Smith ai = a->i; 528981824310SBarry Smith ailen = a->ilen; 529081824310SBarry Smith aj = a->j; 529181824310SBarry Smith aa = a->a; 529281824310SBarry Smith 529381824310SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 529481824310SBarry Smith row = im[k]; 529581824310SBarry Smith if (row < 0) continue; 52965f80ce2aSJacob Faibussowitsch PetscCheck(row < A->rmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Row too large"); 52979371c9d4SSatish Balay rp = aj + ai[row]; 52989371c9d4SSatish Balay ap = aa + ai[row]; 52999371c9d4SSatish Balay rmax = imax[row]; 53009371c9d4SSatish Balay nrow = ailen[row]; 530181824310SBarry Smith low = 0; 530281824310SBarry Smith high = nrow; 530381824310SBarry Smith for (l = 0; l < n; l++) { /* loop over added columns */ 530481824310SBarry Smith if (in[l] < 0) continue; 53055f80ce2aSJacob Faibussowitsch PetscCheck(in[l] < A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Column too large"); 530681824310SBarry Smith col = in[l]; 53072205254eSKarl Rupp if (roworiented) value = v[l + k * n]; 53082205254eSKarl Rupp else value = v[k + l * m]; 53092205254eSKarl Rupp 531081824310SBarry Smith if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 531181824310SBarry Smith 53122205254eSKarl Rupp if (col <= lastcol) low = 0; 53132205254eSKarl Rupp else high = nrow; 531481824310SBarry Smith lastcol = col; 531581824310SBarry Smith while (high - low > 5) { 531681824310SBarry Smith t = (low + high) / 2; 531781824310SBarry Smith if (rp[t] > col) high = t; 531881824310SBarry Smith else low = t; 531981824310SBarry Smith } 532081824310SBarry Smith for (i = low; i < high; i++) { 532181824310SBarry Smith if (rp[i] > col) break; 532281824310SBarry Smith if (rp[i] == col) { 532381824310SBarry Smith if (is == ADD_VALUES) ap[i] += value; 532481824310SBarry Smith else ap[i] = value; 532581824310SBarry Smith goto noinsert; 532681824310SBarry Smith } 532781824310SBarry Smith } 532881824310SBarry Smith if (value == 0.0 && ignorezeroentries) goto noinsert; 532981824310SBarry Smith if (nonew == 1) goto noinsert; 53305f80ce2aSJacob Faibussowitsch PetscCheck(nonew != -1, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero in the matrix"); 5331fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, A->rmap->n, 1, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 53329371c9d4SSatish Balay N = nrow++ - 1; 53339371c9d4SSatish Balay a->nz++; 53349371c9d4SSatish Balay high++; 533581824310SBarry Smith /* shift up all the later entries in this row */ 533681824310SBarry Smith for (ii = N; ii >= i; ii--) { 533781824310SBarry Smith rp[ii + 1] = rp[ii]; 533881824310SBarry Smith ap[ii + 1] = ap[ii]; 533981824310SBarry Smith } 534081824310SBarry Smith rp[i] = col; 534181824310SBarry Smith ap[i] = value; 5342e56f5c9eSBarry Smith A->nonzerostate++; 534381824310SBarry Smith noinsert:; 534481824310SBarry Smith low = i + 1; 534581824310SBarry Smith } 534681824310SBarry Smith ailen[row] = nrow; 534781824310SBarry Smith } 534881824310SBarry Smith PetscFunctionReturnVoid(); 534981824310SBarry Smith } 535098921bdaSJacob Faibussowitsch /* Undefining these here since they were redefined from their original definition above! No 535198921bdaSJacob Faibussowitsch * other PETSc functions should be defined past this point, as it is impossible to recover the 535298921bdaSJacob Faibussowitsch * original definitions */ 53539566063dSJacob Faibussowitsch #undef PetscCall 535498921bdaSJacob Faibussowitsch #undef SETERRQ 5355