1d5d45c9bSBarry Smith /* 23369ce9aSBarry Smith Defines the basic matrix operations for the AIJ (compressed row) 3d5d45c9bSBarry Smith matrix storage format. 4d5d45c9bSBarry Smith */ 53369ce9aSBarry Smith 6c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h> /*I "petscmat.h" I*/ 7c6db04a5SJed Brown #include <petscblaslapack.h> 8c6db04a5SJed Brown #include <petscbt.h> 9af0996ceSBarry Smith #include <petsc/private/kernels/blocktranspose.h> 100716a85fSBarry Smith 119371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A) { 124099cc6bSBarry Smith PetscBool flg; 134099cc6bSBarry Smith char type[256]; 144099cc6bSBarry Smith 154099cc6bSBarry Smith PetscFunctionBegin; 16d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)A); 179566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-mat_seqaij_type", "Matrix SeqAIJ type", "MatSeqAIJSetType", MatSeqAIJList, "seqaij", type, 256, &flg)); 189566063dSJacob Faibussowitsch if (flg) PetscCall(MatSeqAIJSetType(A, type)); 19d0609cedSBarry Smith PetscOptionsEnd(); 204099cc6bSBarry Smith PetscFunctionReturn(0); 214099cc6bSBarry Smith } 224099cc6bSBarry Smith 239371c9d4SSatish Balay PetscErrorCode MatGetColumnReductions_SeqAIJ(Mat A, PetscInt type, PetscReal *reductions) { 240716a85fSBarry Smith PetscInt i, m, n; 250716a85fSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 260716a85fSBarry Smith 270716a85fSBarry Smith PetscFunctionBegin; 289566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &m, &n)); 299566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(reductions, n)); 300716a85fSBarry Smith if (type == NORM_2) { 31ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscAbsScalar(aij->a[i] * aij->a[i]); 320716a85fSBarry Smith } else if (type == NORM_1) { 33ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]); 340716a85fSBarry Smith } else if (type == NORM_INFINITY) { 35ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]), reductions[aij->j[i]]); 36857cbf51SRichard Tran Mills } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) { 37ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscRealPart(aij->a[i]); 38857cbf51SRichard Tran Mills } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) { 39ad540459SPierre Jolivet for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscImaginaryPart(aij->a[i]); 40857cbf51SRichard Tran Mills } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown reduction type"); 410716a85fSBarry Smith 420716a85fSBarry Smith if (type == NORM_2) { 43a873a8cdSSam Reynolds for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]); 44857cbf51SRichard Tran Mills } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) { 45a873a8cdSSam Reynolds for (i = 0; i < n; i++) reductions[i] /= m; 460716a85fSBarry Smith } 470716a85fSBarry Smith PetscFunctionReturn(0); 480716a85fSBarry Smith } 490716a85fSBarry Smith 509371c9d4SSatish Balay PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A, IS *is) { 513a062f41SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 523a062f41SBarry Smith PetscInt i, m = A->rmap->n, cnt = 0, bs = A->rmap->bs; 533a062f41SBarry Smith const PetscInt *jj = a->j, *ii = a->i; 543a062f41SBarry Smith PetscInt *rows; 553a062f41SBarry Smith 563a062f41SBarry Smith PetscFunctionBegin; 573a062f41SBarry Smith for (i = 0; i < m; i++) { 58ad540459SPierre Jolivet if ((ii[i] != ii[i + 1]) && ((jj[ii[i]] < bs * (i / bs)) || (jj[ii[i + 1] - 1] > bs * ((i + bs) / bs) - 1))) cnt++; 593a062f41SBarry Smith } 609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cnt, &rows)); 613a062f41SBarry Smith cnt = 0; 623a062f41SBarry Smith for (i = 0; i < m; i++) { 633a062f41SBarry Smith if ((ii[i] != ii[i + 1]) && ((jj[ii[i]] < bs * (i / bs)) || (jj[ii[i + 1] - 1] > bs * ((i + bs) / bs) - 1))) { 643a062f41SBarry Smith rows[cnt] = i; 653a062f41SBarry Smith cnt++; 663a062f41SBarry Smith } 673a062f41SBarry Smith } 689566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cnt, rows, PETSC_OWN_POINTER, is)); 693a062f41SBarry Smith PetscFunctionReturn(0); 703a062f41SBarry Smith } 713a062f41SBarry Smith 729371c9d4SSatish Balay PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A, PetscInt *nrows, PetscInt **zrows) { 736ce1633cSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 74fff043a9SJunchao Zhang const MatScalar *aa; 756ce1633cSBarry Smith PetscInt i, m = A->rmap->n, cnt = 0; 76b2db7409Sstefano_zampini const PetscInt *ii = a->i, *jj = a->j, *diag; 776ce1633cSBarry Smith PetscInt *rows; 786ce1633cSBarry Smith 796ce1633cSBarry Smith PetscFunctionBegin; 809566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 819566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 826ce1633cSBarry Smith diag = a->diag; 836ce1633cSBarry Smith for (i = 0; i < m; i++) { 84ad540459SPierre Jolivet if ((diag[i] >= ii[i + 1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) cnt++; 856ce1633cSBarry Smith } 869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cnt, &rows)); 876ce1633cSBarry Smith cnt = 0; 886ce1633cSBarry Smith for (i = 0; i < m; i++) { 89ad540459SPierre Jolivet if ((diag[i] >= ii[i + 1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) rows[cnt++] = i; 906ce1633cSBarry Smith } 91f1f41ecbSJed Brown *nrows = cnt; 92f1f41ecbSJed Brown *zrows = rows; 939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 94f1f41ecbSJed Brown PetscFunctionReturn(0); 95f1f41ecbSJed Brown } 96f1f41ecbSJed Brown 979371c9d4SSatish Balay PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A, IS *zrows) { 98f1f41ecbSJed Brown PetscInt nrows, *rows; 99f1f41ecbSJed Brown 100f1f41ecbSJed Brown PetscFunctionBegin; 1010298fd71SBarry Smith *zrows = NULL; 1029566063dSJacob Faibussowitsch PetscCall(MatFindZeroDiagonals_SeqAIJ_Private(A, &nrows, &rows)); 1039566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), nrows, rows, PETSC_OWN_POINTER, zrows)); 1046ce1633cSBarry Smith PetscFunctionReturn(0); 1056ce1633cSBarry Smith } 1066ce1633cSBarry Smith 1079371c9d4SSatish Balay PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A, IS *keptrows) { 108b3a44c85SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 109b3a44c85SBarry Smith const MatScalar *aa; 110b3a44c85SBarry Smith PetscInt m = A->rmap->n, cnt = 0; 111b3a44c85SBarry Smith const PetscInt *ii; 112b3a44c85SBarry Smith PetscInt n, i, j, *rows; 113b3a44c85SBarry Smith 114b3a44c85SBarry Smith PetscFunctionBegin; 1159566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 116f4259b30SLisandro Dalcin *keptrows = NULL; 117b3a44c85SBarry Smith ii = a->i; 118b3a44c85SBarry Smith for (i = 0; i < m; i++) { 119b3a44c85SBarry Smith n = ii[i + 1] - ii[i]; 120b3a44c85SBarry Smith if (!n) { 121b3a44c85SBarry Smith cnt++; 122b3a44c85SBarry Smith goto ok1; 123b3a44c85SBarry Smith } 1242e5835c6SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 125b3a44c85SBarry Smith if (aa[j] != 0.0) goto ok1; 126b3a44c85SBarry Smith } 127b3a44c85SBarry Smith cnt++; 128b3a44c85SBarry Smith ok1:; 129b3a44c85SBarry Smith } 1302e5835c6SStefano Zampini if (!cnt) { 1319566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 1322e5835c6SStefano Zampini PetscFunctionReturn(0); 1332e5835c6SStefano Zampini } 1349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n - cnt, &rows)); 135b3a44c85SBarry Smith cnt = 0; 136b3a44c85SBarry Smith for (i = 0; i < m; i++) { 137b3a44c85SBarry Smith n = ii[i + 1] - ii[i]; 138b3a44c85SBarry Smith if (!n) continue; 1392e5835c6SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 140b3a44c85SBarry Smith if (aa[j] != 0.0) { 141b3a44c85SBarry Smith rows[cnt++] = i; 142b3a44c85SBarry Smith break; 143b3a44c85SBarry Smith } 144b3a44c85SBarry Smith } 145b3a44c85SBarry Smith } 1469566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 1479566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cnt, rows, PETSC_OWN_POINTER, keptrows)); 148b3a44c85SBarry Smith PetscFunctionReturn(0); 149b3a44c85SBarry Smith } 150b3a44c85SBarry Smith 1519371c9d4SSatish Balay PetscErrorCode MatDiagonalSet_SeqAIJ(Mat Y, Vec D, InsertMode is) { 15279299369SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)Y->data; 15399e65526SBarry Smith PetscInt i, m = Y->rmap->n; 15499e65526SBarry Smith const PetscInt *diag; 1552e5835c6SStefano Zampini MatScalar *aa; 15699e65526SBarry Smith const PetscScalar *v; 157ace3abfcSBarry Smith PetscBool missing; 15879299369SBarry Smith 15979299369SBarry Smith PetscFunctionBegin; 16009f38230SBarry Smith if (Y->assembled) { 1619566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal_SeqAIJ(Y, &missing, NULL)); 16209f38230SBarry Smith if (!missing) { 16379299369SBarry Smith diag = aij->diag; 1649566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(D, &v)); 1659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Y, &aa)); 16679299369SBarry Smith if (is == INSERT_VALUES) { 167ad540459SPierre Jolivet for (i = 0; i < m; i++) aa[diag[i]] = v[i]; 16879299369SBarry Smith } else { 169ad540459SPierre Jolivet for (i = 0; i < m; i++) aa[diag[i]] += v[i]; 17079299369SBarry Smith } 1719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Y, &aa)); 1729566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(D, &v)); 17379299369SBarry Smith PetscFunctionReturn(0); 17479299369SBarry Smith } 1759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(Y)); 17609f38230SBarry Smith } 1779566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet_Default(Y, D, is)); 17809f38230SBarry Smith PetscFunctionReturn(0); 17909f38230SBarry Smith } 18079299369SBarry Smith 1819371c9d4SSatish Balay PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *m, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) { 182416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 18397f1f81fSBarry Smith PetscInt i, ishift; 18417ab2063SBarry Smith 1853a40ed3dSBarry Smith PetscFunctionBegin; 186f1f2ae84SBarry Smith if (m) *m = A->rmap->n; 1873a40ed3dSBarry Smith if (!ia) PetscFunctionReturn(0); 188bfeeae90SHong Zhang ishift = 0; 189b94d7dedSBarry Smith if (symmetric && A->structurally_symmetric != PETSC_BOOL3_TRUE) { 1909566063dSJacob Faibussowitsch PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n, a->i, a->j, PETSC_TRUE, ishift, oshift, (PetscInt **)ia, (PetscInt **)ja)); 191bfeeae90SHong Zhang } else if (oshift == 1) { 1921a83f524SJed Brown PetscInt *tia; 193d0f46423SBarry Smith PetscInt nz = a->i[A->rmap->n]; 1943b2fbd54SBarry Smith /* malloc space and add 1 to i and j indices */ 1959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n + 1, &tia)); 1961a83f524SJed Brown for (i = 0; i < A->rmap->n + 1; i++) tia[i] = a->i[i] + 1; 1971a83f524SJed Brown *ia = tia; 198ecc77c7aSBarry Smith if (ja) { 1991a83f524SJed Brown PetscInt *tja; 2009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz + 1, &tja)); 2011a83f524SJed Brown for (i = 0; i < nz; i++) tja[i] = a->j[i] + 1; 2021a83f524SJed Brown *ja = tja; 203ecc77c7aSBarry Smith } 2046945ee14SBarry Smith } else { 205ecc77c7aSBarry Smith *ia = a->i; 206ecc77c7aSBarry Smith if (ja) *ja = a->j; 207a2ce50c7SBarry Smith } 2083a40ed3dSBarry Smith PetscFunctionReturn(0); 209a2744918SBarry Smith } 210a2744918SBarry Smith 2119371c9d4SSatish Balay PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) { 2123a40ed3dSBarry Smith PetscFunctionBegin; 2133a40ed3dSBarry Smith if (!ia) PetscFunctionReturn(0); 214b94d7dedSBarry Smith if ((symmetric && A->structurally_symmetric != PETSC_BOOL3_TRUE) || oshift == 1) { 2159566063dSJacob Faibussowitsch PetscCall(PetscFree(*ia)); 2169566063dSJacob Faibussowitsch if (ja) PetscCall(PetscFree(*ja)); 217bcd2baecSBarry Smith } 2183a40ed3dSBarry Smith PetscFunctionReturn(0); 21917ab2063SBarry Smith } 22017ab2063SBarry Smith 2219371c9d4SSatish Balay PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) { 2223b2fbd54SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 223d0f46423SBarry Smith PetscInt i, *collengths, *cia, *cja, n = A->cmap->n, m = A->rmap->n; 22497f1f81fSBarry Smith PetscInt nz = a->i[m], row, *jj, mr, col; 2253b2fbd54SBarry Smith 2263a40ed3dSBarry Smith PetscFunctionBegin; 227899cda47SBarry Smith *nn = n; 2283a40ed3dSBarry Smith if (!ia) PetscFunctionReturn(0); 2293b2fbd54SBarry Smith if (symmetric) { 2309566063dSJacob Faibussowitsch PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n, a->i, a->j, PETSC_TRUE, 0, oshift, (PetscInt **)ia, (PetscInt **)ja)); 2313b2fbd54SBarry Smith } else { 2329566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &collengths)); 2339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &cia)); 2349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &cja)); 2353b2fbd54SBarry Smith jj = a->j; 236ad540459SPierre Jolivet for (i = 0; i < nz; i++) collengths[jj[i]]++; 2373b2fbd54SBarry Smith cia[0] = oshift; 238ad540459SPierre Jolivet for (i = 0; i < n; i++) cia[i + 1] = cia[i] + collengths[i]; 2399566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(collengths, n)); 2403b2fbd54SBarry Smith jj = a->j; 241a93ec695SBarry Smith for (row = 0; row < m; row++) { 242a93ec695SBarry Smith mr = a->i[row + 1] - a->i[row]; 243a93ec695SBarry Smith for (i = 0; i < mr; i++) { 244bfeeae90SHong Zhang col = *jj++; 2452205254eSKarl Rupp 2463b2fbd54SBarry Smith cja[cia[col] + collengths[col]++ - oshift] = row + oshift; 2473b2fbd54SBarry Smith } 2483b2fbd54SBarry Smith } 2499566063dSJacob Faibussowitsch PetscCall(PetscFree(collengths)); 2509371c9d4SSatish Balay *ia = cia; 2519371c9d4SSatish Balay *ja = cja; 2523b2fbd54SBarry Smith } 2533a40ed3dSBarry Smith PetscFunctionReturn(0); 2543b2fbd54SBarry Smith } 2553b2fbd54SBarry Smith 2569371c9d4SSatish Balay PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) { 2573a40ed3dSBarry Smith PetscFunctionBegin; 2583a40ed3dSBarry Smith if (!ia) PetscFunctionReturn(0); 2593b2fbd54SBarry Smith 2609566063dSJacob Faibussowitsch PetscCall(PetscFree(*ia)); 2619566063dSJacob Faibussowitsch PetscCall(PetscFree(*ja)); 2623a40ed3dSBarry Smith PetscFunctionReturn(0); 2633b2fbd54SBarry Smith } 2643b2fbd54SBarry Smith 2657cee066cSHong Zhang /* 2667cee066cSHong Zhang MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from 2677cee066cSHong Zhang MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output 268040ebd07SHong Zhang spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ() 2697cee066cSHong Zhang */ 2709371c9d4SSatish Balay PetscErrorCode MatGetColumnIJ_SeqAIJ_Color(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscInt *spidx[], PetscBool *done) { 2717cee066cSHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2727cee066cSHong Zhang PetscInt i, *collengths, *cia, *cja, n = A->cmap->n, m = A->rmap->n; 273071fcb05SBarry Smith PetscInt nz = a->i[m], row, mr, col, tmp; 2747cee066cSHong Zhang PetscInt *cspidx; 275071fcb05SBarry Smith const PetscInt *jj; 2767cee066cSHong Zhang 2777cee066cSHong Zhang PetscFunctionBegin; 2787cee066cSHong Zhang *nn = n; 2797cee066cSHong Zhang if (!ia) PetscFunctionReturn(0); 280625f6d37SHong Zhang 2819566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &collengths)); 2829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &cia)); 2839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &cja)); 2849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &cspidx)); 2857cee066cSHong Zhang jj = a->j; 286ad540459SPierre Jolivet for (i = 0; i < nz; i++) collengths[jj[i]]++; 2877cee066cSHong Zhang cia[0] = oshift; 288ad540459SPierre Jolivet for (i = 0; i < n; i++) cia[i + 1] = cia[i] + collengths[i]; 2899566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(collengths, n)); 2907cee066cSHong Zhang jj = a->j; 2917cee066cSHong Zhang for (row = 0; row < m; row++) { 2927cee066cSHong Zhang mr = a->i[row + 1] - a->i[row]; 2937cee066cSHong Zhang for (i = 0; i < mr; i++) { 2947cee066cSHong Zhang col = *jj++; 295071fcb05SBarry Smith tmp = cia[col] + collengths[col]++ - oshift; 296071fcb05SBarry Smith cspidx[tmp] = a->i[row] + i; /* index of a->j */ 297071fcb05SBarry Smith cja[tmp] = row + oshift; 2987cee066cSHong Zhang } 2997cee066cSHong Zhang } 3009566063dSJacob Faibussowitsch PetscCall(PetscFree(collengths)); 301071fcb05SBarry Smith *ia = cia; 302071fcb05SBarry Smith *ja = cja; 3037cee066cSHong Zhang *spidx = cspidx; 3047cee066cSHong Zhang PetscFunctionReturn(0); 3057cee066cSHong Zhang } 3067cee066cSHong Zhang 3079371c9d4SSatish Balay PetscErrorCode MatRestoreColumnIJ_SeqAIJ_Color(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscInt *spidx[], PetscBool *done) { 3087cee066cSHong Zhang PetscFunctionBegin; 3099566063dSJacob Faibussowitsch PetscCall(MatRestoreColumnIJ_SeqAIJ(A, oshift, symmetric, inodecompressed, n, ia, ja, done)); 3109566063dSJacob Faibussowitsch PetscCall(PetscFree(*spidx)); 3117cee066cSHong Zhang PetscFunctionReturn(0); 3127cee066cSHong Zhang } 3137cee066cSHong Zhang 3149371c9d4SSatish Balay PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A, PetscInt row, const PetscScalar v[]) { 31587d4246cSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 31687d4246cSBarry Smith PetscInt *ai = a->i; 317fff043a9SJunchao Zhang PetscScalar *aa; 31887d4246cSBarry Smith 31987d4246cSBarry Smith PetscFunctionBegin; 3209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 3219566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aa + ai[row], v, ai[row + 1] - ai[row])); 3229566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 32387d4246cSBarry Smith PetscFunctionReturn(0); 32487d4246cSBarry Smith } 32587d4246cSBarry Smith 326bd04181cSBarry Smith /* 327bd04181cSBarry Smith MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions 328bd04181cSBarry Smith 329bd04181cSBarry Smith - a single row of values is set with each call 330bd04181cSBarry Smith - no row or column indices are negative or (in error) larger than the number of rows or columns 331bd04181cSBarry Smith - the values are always added to the matrix, not set 332bd04181cSBarry Smith - no new locations are introduced in the nonzero structure of the matrix 333bd04181cSBarry Smith 3341f763a69SBarry Smith This does NOT assume the global column indices are sorted 335bd04181cSBarry Smith 3361f763a69SBarry Smith */ 337bd04181cSBarry Smith 338af0996ceSBarry Smith #include <petsc/private/isimpl.h> 3399371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) { 340189e4007SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3411f763a69SBarry Smith PetscInt low, high, t, row, nrow, i, col, l; 3421f763a69SBarry Smith const PetscInt *rp, *ai = a->i, *ailen = a->ilen, *aj = a->j; 3431f763a69SBarry Smith PetscInt lastcol = -1; 344fff043a9SJunchao Zhang MatScalar *ap, value, *aa; 345189e4007SBarry Smith const PetscInt *ridx = A->rmap->mapping->indices, *cidx = A->cmap->mapping->indices; 346189e4007SBarry Smith 347fff043a9SJunchao Zhang PetscFunctionBegin; 3489566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 349f38dd0b8SBarry Smith row = ridx[im[0]]; 3501f763a69SBarry Smith rp = aj + ai[row]; 3511f763a69SBarry Smith ap = aa + ai[row]; 3521f763a69SBarry Smith nrow = ailen[row]; 353189e4007SBarry Smith low = 0; 354189e4007SBarry Smith high = nrow; 355189e4007SBarry Smith for (l = 0; l < n; l++) { /* loop over added columns */ 356189e4007SBarry Smith col = cidx[in[l]]; 357f38dd0b8SBarry Smith value = v[l]; 358189e4007SBarry Smith 359189e4007SBarry Smith if (col <= lastcol) low = 0; 360189e4007SBarry Smith else high = nrow; 361189e4007SBarry Smith lastcol = col; 362189e4007SBarry Smith while (high - low > 5) { 363189e4007SBarry Smith t = (low + high) / 2; 364189e4007SBarry Smith if (rp[t] > col) high = t; 365189e4007SBarry Smith else low = t; 366189e4007SBarry Smith } 367189e4007SBarry Smith for (i = low; i < high; i++) { 368189e4007SBarry Smith if (rp[i] == col) { 3691f763a69SBarry Smith ap[i] += value; 370189e4007SBarry Smith low = i + 1; 3711f763a69SBarry Smith break; 372189e4007SBarry Smith } 373189e4007SBarry Smith } 374189e4007SBarry Smith } 3759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 376f38dd0b8SBarry Smith return 0; 377189e4007SBarry Smith } 378189e4007SBarry Smith 3799371c9d4SSatish Balay PetscErrorCode MatSetValues_SeqAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) { 380416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 381e2ee6c50SBarry Smith PetscInt *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N; 38297f1f81fSBarry Smith PetscInt *imax = a->imax, *ai = a->i, *ailen = a->ilen; 383e2ee6c50SBarry Smith PetscInt *aj = a->j, nonew = a->nonew, lastcol = -1; 384ce496241SStefano Zampini MatScalar *ap = NULL, value = 0.0, *aa; 385ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 386ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 38717ab2063SBarry Smith 3883a40ed3dSBarry Smith PetscFunctionBegin; 3899566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 39017ab2063SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 391416022c9SBarry Smith row = im[k]; 3925ef9f2a5SBarry Smith if (row < 0) continue; 3936bdcaf15SBarry Smith PetscCheck(row < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, row, A->rmap->n - 1); 394720833daSHong Zhang rp = aj + ai[row]; 395876c6284SHong Zhang if (!A->structure_only) ap = aa + ai[row]; 3969371c9d4SSatish Balay rmax = imax[row]; 3979371c9d4SSatish Balay nrow = ailen[row]; 398416022c9SBarry Smith low = 0; 399c71e6ed7SBarry Smith high = nrow; 40017ab2063SBarry Smith for (l = 0; l < n; l++) { /* loop over added columns */ 4015ef9f2a5SBarry Smith if (in[l] < 0) continue; 4026bdcaf15SBarry Smith PetscCheck(in[l] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, in[l], A->cmap->n - 1); 403bfeeae90SHong Zhang col = in[l]; 404071fcb05SBarry Smith if (v && !A->structure_only) value = roworiented ? v[l + k * n] : v[k + l * m]; 405071fcb05SBarry Smith if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue; 40636db0b34SBarry Smith 4072205254eSKarl Rupp if (col <= lastcol) low = 0; 4082205254eSKarl Rupp else high = nrow; 409e2ee6c50SBarry Smith lastcol = col; 410416022c9SBarry Smith while (high - low > 5) { 411416022c9SBarry Smith t = (low + high) / 2; 412416022c9SBarry Smith if (rp[t] > col) high = t; 413416022c9SBarry Smith else low = t; 41417ab2063SBarry Smith } 415416022c9SBarry Smith for (i = low; i < high; i++) { 41617ab2063SBarry Smith if (rp[i] > col) break; 41717ab2063SBarry Smith if (rp[i] == col) { 418876c6284SHong Zhang if (!A->structure_only) { 4190c0d7e18SFande Kong if (is == ADD_VALUES) { 4200c0d7e18SFande Kong ap[i] += value; 4210c0d7e18SFande Kong (void)PetscLogFlops(1.0); 4229371c9d4SSatish Balay } else ap[i] = value; 423720833daSHong Zhang } 424e44c0bd4SBarry Smith low = i + 1; 42517ab2063SBarry Smith goto noinsert; 42617ab2063SBarry Smith } 42717ab2063SBarry Smith } 428dcd36c23SBarry Smith if (value == 0.0 && ignorezeroentries && row != col) goto noinsert; 429c2653b3dSLois Curfman McInnes if (nonew == 1) goto noinsert; 43008401ef6SPierre Jolivet PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero at (%" PetscInt_FMT ",%" PetscInt_FMT ") in the matrix", row, col); 431720833daSHong Zhang if (A->structure_only) { 432876c6284SHong Zhang MatSeqXAIJReallocateAIJ_structure_only(A, A->rmap->n, 1, nrow, row, col, rmax, ai, aj, rp, imax, nonew, MatScalar); 433720833daSHong Zhang } else { 434fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, A->rmap->n, 1, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 435720833daSHong Zhang } 4369371c9d4SSatish Balay N = nrow++ - 1; 4379371c9d4SSatish Balay a->nz++; 4389371c9d4SSatish Balay high++; 439416022c9SBarry Smith /* shift up all the later entries in this row */ 4409566063dSJacob Faibussowitsch PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1)); 44117ab2063SBarry Smith rp[i] = col; 442580bdb30SBarry Smith if (!A->structure_only) { 4439566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap + i + 1, ap + i, N - i + 1)); 444580bdb30SBarry Smith ap[i] = value; 445580bdb30SBarry Smith } 446416022c9SBarry Smith low = i + 1; 447e56f5c9eSBarry Smith A->nonzerostate++; 448e44c0bd4SBarry Smith noinsert:; 44917ab2063SBarry Smith } 45017ab2063SBarry Smith ailen[row] = nrow; 45117ab2063SBarry Smith } 4529566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 4533a40ed3dSBarry Smith PetscFunctionReturn(0); 45417ab2063SBarry Smith } 45517ab2063SBarry Smith 4569371c9d4SSatish Balay PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) { 45719b08ed1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 45819b08ed1SBarry Smith PetscInt *rp, k, row; 45919b08ed1SBarry Smith PetscInt *ai = a->i; 46019b08ed1SBarry Smith PetscInt *aj = a->j; 461fff043a9SJunchao Zhang MatScalar *aa, *ap; 46219b08ed1SBarry Smith 46319b08ed1SBarry Smith PetscFunctionBegin; 46428b400f6SJacob Faibussowitsch PetscCheck(!A->was_assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call on assembled matrix."); 46508401ef6SPierre Jolivet PetscCheck(m * n + a->nz <= a->maxnz, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of entries in matrix will be larger than maximum nonzeros allocated for %" PetscInt_FMT " in MatSeqAIJSetTotalPreallocation()", a->maxnz); 466fff043a9SJunchao Zhang 4679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &aa)); 46819b08ed1SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 46919b08ed1SBarry Smith row = im[k]; 47019b08ed1SBarry Smith rp = aj + ai[row]; 47119b08ed1SBarry Smith ap = aa + ai[row]; 47219b08ed1SBarry Smith 4739566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(rp, in, n * sizeof(PetscInt))); 47419b08ed1SBarry Smith if (!A->structure_only) { 47519b08ed1SBarry Smith if (v) { 4769566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(ap, v, n * sizeof(PetscScalar))); 47719b08ed1SBarry Smith v += n; 47819b08ed1SBarry Smith } else { 4799566063dSJacob Faibussowitsch PetscCall(PetscMemzero(ap, n * sizeof(PetscScalar))); 48019b08ed1SBarry Smith } 48119b08ed1SBarry Smith } 48219b08ed1SBarry Smith a->ilen[row] = n; 48319b08ed1SBarry Smith a->imax[row] = n; 48419b08ed1SBarry Smith a->i[row + 1] = a->i[row] + n; 48519b08ed1SBarry Smith a->nz += n; 48619b08ed1SBarry Smith } 4879566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &aa)); 48819b08ed1SBarry Smith PetscFunctionReturn(0); 48919b08ed1SBarry Smith } 49019b08ed1SBarry Smith 49119b08ed1SBarry Smith /*@ 49219b08ed1SBarry Smith MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix. 49319b08ed1SBarry Smith 49419b08ed1SBarry Smith Input Parameters: 49511a5261eSBarry Smith + A - the `MATSEQAIJ` matrix 49619b08ed1SBarry Smith - nztotal - bound on the number of nonzeros 49719b08ed1SBarry Smith 49819b08ed1SBarry Smith Level: advanced 49919b08ed1SBarry Smith 50019b08ed1SBarry Smith Notes: 50119b08ed1SBarry Smith This can be called if you will be provided the matrix row by row (from row zero) with sorted column indices for each row. 50211a5261eSBarry Smith Simply call `MatSetValues()` after this call to provide the matrix entries in the usual manner. This matrix may be used 50319b08ed1SBarry Smith as always with multiple matrix assemblies. 50419b08ed1SBarry Smith 505db781477SPatrick Sanan .seealso: `MatSetOption()`, `MAT_SORTED_FULL`, `MatSetValues()`, `MatSeqAIJSetPreallocation()` 50619b08ed1SBarry Smith @*/ 50719b08ed1SBarry Smith 5089371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A, PetscInt nztotal) { 50919b08ed1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 51019b08ed1SBarry Smith 51119b08ed1SBarry Smith PetscFunctionBegin; 5129566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 5139566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 51419b08ed1SBarry Smith a->maxnz = nztotal; 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)); 2704*3faff063SStefano Zampini PetscCall(PetscFree(C->defaultrandtype)); 27059566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->rmap)); 27069566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->cmap)); 27079566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(&C)); 2708682e4c99SStefano Zampini } 27092d033e1fSHong Zhang } else { 27109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 27112d033e1fSHong Zhang } 27122d033e1fSHong Zhang } 271386e85357SHong Zhang 271463a75b2aSHong Zhang /* Destroy Dummy submatrices created for reuse */ 27159566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices_Dummy(n, mat)); 271663a75b2aSHong Zhang 27179566063dSJacob Faibussowitsch PetscCall(PetscFree(*mat)); 27182d033e1fSHong Zhang PetscFunctionReturn(0); 27192d033e1fSHong Zhang } 27202d033e1fSHong Zhang 27219371c9d4SSatish Balay PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[]) { 272297f1f81fSBarry Smith PetscInt i; 2723cddf8d76SBarry Smith 27243a40ed3dSBarry Smith PetscFunctionBegin; 272548a46eb9SPierre Jolivet if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n + 1, B)); 2726cddf8d76SBarry Smith 272748a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqAIJ(A, irow[i], icol[i], PETSC_DECIDE, scall, &(*B)[i])); 27283a40ed3dSBarry Smith PetscFunctionReturn(0); 2729cddf8d76SBarry Smith } 2730cddf8d76SBarry Smith 27319371c9d4SSatish Balay PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A, PetscInt is_max, IS is[], PetscInt ov) { 2732e4d965acSSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 27335d0c19d7SBarry Smith PetscInt row, i, j, k, l, m, n, *nidx, isz, val; 27345d0c19d7SBarry Smith const PetscInt *idx; 273597f1f81fSBarry Smith PetscInt start, end, *ai, *aj; 2736f1af5d2fSBarry Smith PetscBT table; 2737bbd702dbSSatish Balay 27383a40ed3dSBarry Smith PetscFunctionBegin; 2739d0f46423SBarry Smith m = A->rmap->n; 2740e4d965acSSatish Balay ai = a->i; 2741bfeeae90SHong Zhang aj = a->j; 27428a047759SSatish Balay 274308401ef6SPierre Jolivet PetscCheck(ov >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "illegal negative overlap value used"); 274406763907SSatish Balay 27459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nidx)); 27469566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(m, &table)); 274706763907SSatish Balay 2748e4d965acSSatish Balay for (i = 0; i < is_max; i++) { 2749b97fc60eSLois Curfman McInnes /* Initialize the two local arrays */ 2750e4d965acSSatish Balay isz = 0; 27519566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(m, table)); 2752e4d965acSSatish Balay 2753e4d965acSSatish Balay /* Extract the indices, assume there can be duplicate entries */ 27549566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is[i], &idx)); 27559566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is[i], &n)); 2756e4d965acSSatish Balay 2757dd097bc3SLois Curfman McInnes /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 2758e4d965acSSatish Balay for (j = 0; j < n; ++j) { 27592205254eSKarl Rupp if (!PetscBTLookupSet(table, idx[j])) nidx[isz++] = idx[j]; 27604dcbc457SBarry Smith } 27619566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is[i], &idx)); 27629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is[i])); 2763e4d965acSSatish Balay 276404a348a9SBarry Smith k = 0; 276504a348a9SBarry Smith for (j = 0; j < ov; j++) { /* for each overlap */ 276604a348a9SBarry Smith n = isz; 276706763907SSatish Balay for (; k < n; k++) { /* do only those rows in nidx[k], which are not done yet */ 2768e4d965acSSatish Balay row = nidx[k]; 2769e4d965acSSatish Balay start = ai[row]; 2770e4d965acSSatish Balay end = ai[row + 1]; 277104a348a9SBarry Smith for (l = start; l < end; l++) { 2772efb16452SHong Zhang val = aj[l]; 27732205254eSKarl Rupp if (!PetscBTLookupSet(table, val)) nidx[isz++] = val; 2774e4d965acSSatish Balay } 2775e4d965acSSatish Balay } 2776e4d965acSSatish Balay } 27779566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, isz, nidx, PETSC_COPY_VALUES, (is + i))); 2778e4d965acSSatish Balay } 27799566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&table)); 27809566063dSJacob Faibussowitsch PetscCall(PetscFree(nidx)); 27813a40ed3dSBarry Smith PetscFunctionReturn(0); 27824dcbc457SBarry Smith } 278317ab2063SBarry Smith 27840513a670SBarry Smith /* -------------------------------------------------------------- */ 27859371c9d4SSatish Balay PetscErrorCode MatPermute_SeqAIJ(Mat A, IS rowp, IS colp, Mat *B) { 27860513a670SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 27873b98c0a2SBarry Smith PetscInt i, nz = 0, m = A->rmap->n, n = A->cmap->n; 27885d0c19d7SBarry Smith const PetscInt *row, *col; 27895d0c19d7SBarry Smith PetscInt *cnew, j, *lens; 279056cd22aeSBarry Smith IS icolp, irowp; 27910298fd71SBarry Smith PetscInt *cwork = NULL; 27920298fd71SBarry Smith PetscScalar *vwork = NULL; 27930513a670SBarry Smith 27943a40ed3dSBarry Smith PetscFunctionBegin; 27959566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rowp, PETSC_DECIDE, &irowp)); 27969566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irowp, &row)); 27979566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(colp, PETSC_DECIDE, &icolp)); 27989566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icolp, &col)); 27990513a670SBarry Smith 28000513a670SBarry Smith /* determine lengths of permuted rows */ 28019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &lens)); 28022205254eSKarl Rupp for (i = 0; i < m; i++) lens[row[i]] = a->i[i + 1] - a->i[i]; 28039566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 28049566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, m, n, m, n)); 28059566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(*B, A, A)); 28069566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, ((PetscObject)A)->type_name)); 28079566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*B, 0, lens)); 28089566063dSJacob Faibussowitsch PetscCall(PetscFree(lens)); 28090513a670SBarry Smith 28109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &cnew)); 28110513a670SBarry Smith for (i = 0; i < m; i++) { 28129566063dSJacob Faibussowitsch PetscCall(MatGetRow_SeqAIJ(A, i, &nz, &cwork, &vwork)); 28132205254eSKarl Rupp for (j = 0; j < nz; j++) cnew[j] = col[cwork[j]]; 28149566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(*B, 1, &row[i], nz, cnew, vwork, INSERT_VALUES)); 28159566063dSJacob Faibussowitsch PetscCall(MatRestoreRow_SeqAIJ(A, i, &nz, &cwork, &vwork)); 28160513a670SBarry Smith } 28179566063dSJacob Faibussowitsch PetscCall(PetscFree(cnew)); 28182205254eSKarl Rupp 28193c7d62e4SBarry Smith (*B)->assembled = PETSC_FALSE; 28202205254eSKarl Rupp 28218c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 28229566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(*B, A->boundtocpu)); 28239fe5e383SStefano Zampini #endif 28249566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 28259566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 28269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irowp, &row)); 28279566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icolp, &col)); 28289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irowp)); 28299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icolp)); 283048a46eb9SPierre Jolivet if (rowp == colp) PetscCall(MatPropagateSymmetryOptions(A, *B)); 28313a40ed3dSBarry Smith PetscFunctionReturn(0); 28320513a670SBarry Smith } 28330513a670SBarry Smith 28349371c9d4SSatish Balay PetscErrorCode MatCopy_SeqAIJ(Mat A, Mat B, MatStructure str) { 2835cb5b572fSBarry Smith PetscFunctionBegin; 283633f4a19fSKris Buschelman /* If the two matrices have the same copy implementation, use fast copy. */ 283733f4a19fSKris Buschelman if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) { 2838be6bf707SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2839be6bf707SBarry Smith Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 28402e5835c6SStefano Zampini const PetscScalar *aa; 2841be6bf707SBarry Smith 28429566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 284308401ef6SPierre 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]); 28449566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->a, aa, a->i[A->rmap->n])); 28459566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 28469566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 2847cb5b572fSBarry Smith } else { 28489566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 2849cb5b572fSBarry Smith } 2850cb5b572fSBarry Smith PetscFunctionReturn(0); 2851cb5b572fSBarry Smith } 2852cb5b572fSBarry Smith 28539371c9d4SSatish Balay PetscErrorCode MatSetUp_SeqAIJ(Mat A) { 2854273d9f13SBarry Smith PetscFunctionBegin; 28559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A, PETSC_DEFAULT, NULL)); 2856273d9f13SBarry Smith PetscFunctionReturn(0); 2857273d9f13SBarry Smith } 2858273d9f13SBarry Smith 28599371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A, PetscScalar *array[]) { 28606c0721eeSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 28616e111a19SKarl Rupp 28626c0721eeSBarry Smith PetscFunctionBegin; 28636c0721eeSBarry Smith *array = a->a; 28646c0721eeSBarry Smith PetscFunctionReturn(0); 28656c0721eeSBarry Smith } 28666c0721eeSBarry Smith 28679371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A, PetscScalar *array[]) { 28686c0721eeSBarry Smith PetscFunctionBegin; 2869f38c1e66SStefano Zampini *array = NULL; 28706c0721eeSBarry Smith PetscFunctionReturn(0); 28716c0721eeSBarry Smith } 2872273d9f13SBarry Smith 28738229c054SShri Abhyankar /* 28748229c054SShri Abhyankar Computes the number of nonzeros per row needed for preallocation when X and Y 28758229c054SShri Abhyankar have different nonzero structure. 28768229c054SShri Abhyankar */ 28779371c9d4SSatish Balay PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m, const PetscInt *xi, const PetscInt *xj, const PetscInt *yi, const PetscInt *yj, PetscInt *nnz) { 2878b264fe52SHong Zhang PetscInt i, j, k, nzx, nzy; 2879ec7775f6SShri Abhyankar 2880ec7775f6SShri Abhyankar PetscFunctionBegin; 2881ec7775f6SShri Abhyankar /* Set the number of nonzeros in the new matrix */ 2882ec7775f6SShri Abhyankar for (i = 0; i < m; i++) { 2883b264fe52SHong Zhang const PetscInt *xjj = xj + xi[i], *yjj = yj + yi[i]; 2884b264fe52SHong Zhang nzx = xi[i + 1] - xi[i]; 2885b264fe52SHong Zhang nzy = yi[i + 1] - yi[i]; 28868af7cee1SJed Brown nnz[i] = 0; 28878af7cee1SJed Brown for (j = 0, k = 0; j < nzx; j++) { /* Point in X */ 2888b264fe52SHong Zhang for (; k < nzy && yjj[k] < xjj[j]; k++) nnz[i]++; /* Catch up to X */ 2889b264fe52SHong Zhang if (k < nzy && yjj[k] == xjj[j]) k++; /* Skip duplicate */ 28908af7cee1SJed Brown nnz[i]++; 28918af7cee1SJed Brown } 28928af7cee1SJed Brown for (; k < nzy; k++) nnz[i]++; 2893ec7775f6SShri Abhyankar } 2894ec7775f6SShri Abhyankar PetscFunctionReturn(0); 2895ec7775f6SShri Abhyankar } 2896ec7775f6SShri Abhyankar 28979371c9d4SSatish Balay PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y, Mat X, PetscInt *nnz) { 2898b264fe52SHong Zhang PetscInt m = Y->rmap->N; 2899b264fe52SHong Zhang Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data; 2900b264fe52SHong Zhang Mat_SeqAIJ *y = (Mat_SeqAIJ *)Y->data; 2901b264fe52SHong Zhang 2902b264fe52SHong Zhang PetscFunctionBegin; 2903b264fe52SHong Zhang /* Set the number of nonzeros in the new matrix */ 29049566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqX_private(m, x->i, x->j, y->i, y->j, nnz)); 2905b264fe52SHong Zhang PetscFunctionReturn(0); 2906b264fe52SHong Zhang } 2907b264fe52SHong Zhang 29089371c9d4SSatish Balay PetscErrorCode MatAXPY_SeqAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str) { 2909ac90fabeSBarry Smith Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data, *y = (Mat_SeqAIJ *)Y->data; 2910ac90fabeSBarry Smith 2911ac90fabeSBarry Smith PetscFunctionBegin; 2912134adf20SPierre Jolivet if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) { 2913134adf20SPierre Jolivet PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE; 2914134adf20SPierre Jolivet if (e) { 29159566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->i, y->i, Y->rmap->n + 1, &e)); 291681fa06acSBarry Smith if (e) { 29179566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->j, y->j, y->nz, &e)); 2918134adf20SPierre Jolivet if (e) str = SAME_NONZERO_PATTERN; 291981fa06acSBarry Smith } 292081fa06acSBarry Smith } 292154c59aa7SJacob Faibussowitsch if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN"); 292281fa06acSBarry Smith } 2923ac90fabeSBarry Smith if (str == SAME_NONZERO_PATTERN) { 29242e5835c6SStefano Zampini const PetscScalar *xa; 29252e5835c6SStefano Zampini PetscScalar *ya, alpha = a; 292681fa06acSBarry Smith PetscBLASInt one = 1, bnz; 292781fa06acSBarry Smith 29289566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(x->nz, &bnz)); 29299566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Y, &ya)); 29309566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(X, &xa)); 2931792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, xa, &one, ya, &one)); 29329566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(X, &xa)); 29339566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Y, &ya)); 29349566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * bnz)); 29359566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(Y)); 29369566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 2937ab784542SHong Zhang } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 29389566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 2939ac90fabeSBarry Smith } else { 29408229c054SShri Abhyankar Mat B; 29418229c054SShri Abhyankar PetscInt *nnz; 29429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Y->rmap->N, &nnz)); 29439566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B)); 29449566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name)); 29459566063dSJacob Faibussowitsch PetscCall(MatSetLayouts(B, Y->rmap, Y->cmap)); 29469566063dSJacob Faibussowitsch PetscCall(MatSetType(B, ((PetscObject)Y)->type_name)); 29479566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqAIJ(Y, X, nnz)); 29489566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz)); 29499566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 29509566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 29519bb234a9SBarry Smith PetscCall(MatSeqAIJCheckInode(Y)); 29529566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 2953ac90fabeSBarry Smith } 2954ac90fabeSBarry Smith PetscFunctionReturn(0); 2955ac90fabeSBarry Smith } 2956ac90fabeSBarry Smith 29579371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat) { 2958354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX) 2959354c94deSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2960354c94deSBarry Smith PetscInt i, nz; 2961354c94deSBarry Smith PetscScalar *a; 2962354c94deSBarry Smith 2963354c94deSBarry Smith PetscFunctionBegin; 2964354c94deSBarry Smith nz = aij->nz; 29659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(mat, &a)); 29662205254eSKarl Rupp for (i = 0; i < nz; i++) a[i] = PetscConj(a[i]); 29679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(mat, &a)); 2968354c94deSBarry Smith #else 2969354c94deSBarry Smith PetscFunctionBegin; 2970354c94deSBarry Smith #endif 2971354c94deSBarry Smith PetscFunctionReturn(0); 2972354c94deSBarry Smith } 2973354c94deSBarry Smith 29749371c9d4SSatish Balay PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 2975e34fafa9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2976d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 2977e34fafa9SBarry Smith PetscReal atmp; 2978985db425SBarry Smith PetscScalar *x; 2979ce496241SStefano Zampini const MatScalar *aa, *av; 2980e34fafa9SBarry Smith 2981e34fafa9SBarry Smith PetscFunctionBegin; 298228b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 29839566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 2984ce496241SStefano Zampini aa = av; 2985e34fafa9SBarry Smith ai = a->i; 2986e34fafa9SBarry Smith aj = a->j; 2987e34fafa9SBarry Smith 29889566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 29899566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 29909566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 299108401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 2992e34fafa9SBarry Smith for (i = 0; i < m; i++) { 29939371c9d4SSatish Balay ncols = ai[1] - ai[0]; 29949371c9d4SSatish Balay ai++; 2995e34fafa9SBarry Smith for (j = 0; j < ncols; j++) { 2996985db425SBarry Smith atmp = PetscAbsScalar(*aa); 29979371c9d4SSatish Balay if (PetscAbsScalar(x[i]) < atmp) { 29989371c9d4SSatish Balay x[i] = atmp; 29999371c9d4SSatish Balay if (idx) idx[i] = *aj; 30009371c9d4SSatish Balay } 30019371c9d4SSatish Balay aa++; 30029371c9d4SSatish Balay aj++; 3003985db425SBarry Smith } 3004985db425SBarry Smith } 30059566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 30069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3007985db425SBarry Smith PetscFunctionReturn(0); 3008985db425SBarry Smith } 3009985db425SBarry Smith 30109371c9d4SSatish Balay PetscErrorCode MatGetRowMax_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 3011985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3012d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 3013985db425SBarry Smith PetscScalar *x; 3014ce496241SStefano Zampini const MatScalar *aa, *av; 3015985db425SBarry Smith 3016985db425SBarry Smith PetscFunctionBegin; 301728b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 30189566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3019ce496241SStefano Zampini aa = av; 3020985db425SBarry Smith ai = a->i; 3021985db425SBarry Smith aj = a->j; 3022985db425SBarry Smith 30239566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 30249566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 30259566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 302608401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3027985db425SBarry Smith for (i = 0; i < m; i++) { 30289371c9d4SSatish Balay ncols = ai[1] - ai[0]; 30299371c9d4SSatish Balay ai++; 3030d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 30319371c9d4SSatish Balay x[i] = *aa; 30329371c9d4SSatish Balay if (idx) idx[i] = 0; 3033985db425SBarry Smith } else { /* row is sparse so already KNOW maximum is 0.0 or higher */ 3034985db425SBarry Smith x[i] = 0.0; 3035985db425SBarry Smith if (idx) { 3036985db425SBarry Smith for (j = 0; j < ncols; j++) { /* find first implicit 0.0 in the row */ 3037985db425SBarry Smith if (aj[j] > j) { 3038985db425SBarry Smith idx[i] = j; 3039985db425SBarry Smith break; 3040985db425SBarry Smith } 3041985db425SBarry Smith } 30421a254869SHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 30431a254869SHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3044985db425SBarry Smith } 3045985db425SBarry Smith } 3046985db425SBarry Smith for (j = 0; j < ncols; j++) { 30479371c9d4SSatish Balay if (PetscRealPart(x[i]) < PetscRealPart(*aa)) { 30489371c9d4SSatish Balay x[i] = *aa; 30499371c9d4SSatish Balay if (idx) idx[i] = *aj; 30509371c9d4SSatish Balay } 30519371c9d4SSatish Balay aa++; 30529371c9d4SSatish Balay aj++; 3053985db425SBarry Smith } 3054985db425SBarry Smith } 30559566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 30569566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3057985db425SBarry Smith PetscFunctionReturn(0); 3058985db425SBarry Smith } 3059985db425SBarry Smith 30609371c9d4SSatish Balay PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 3061c87e5d42SMatthew Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3062c87e5d42SMatthew Knepley PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 3063ce496241SStefano Zampini PetscScalar *x; 3064ce496241SStefano Zampini const MatScalar *aa, *av; 3065c87e5d42SMatthew Knepley 3066c87e5d42SMatthew Knepley PetscFunctionBegin; 30679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3068ce496241SStefano Zampini aa = av; 3069c87e5d42SMatthew Knepley ai = a->i; 3070c87e5d42SMatthew Knepley aj = a->j; 3071c87e5d42SMatthew Knepley 30729566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 30739566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 30749566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 307508401ef6SPierre Jolivet PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n); 3076c87e5d42SMatthew Knepley for (i = 0; i < m; i++) { 30779371c9d4SSatish Balay ncols = ai[1] - ai[0]; 30789371c9d4SSatish Balay ai++; 3079f07e67edSHong Zhang if (ncols == A->cmap->n) { /* row is dense */ 30809371c9d4SSatish Balay x[i] = *aa; 30819371c9d4SSatish Balay if (idx) idx[i] = 0; 3082f07e67edSHong Zhang } else { /* row is sparse so already KNOW minimum is 0.0 or higher */ 3083f07e67edSHong Zhang x[i] = 0.0; 3084f07e67edSHong Zhang if (idx) { /* find first implicit 0.0 in the row */ 3085289a08f5SMatthew Knepley for (j = 0; j < ncols; j++) { 3086f07e67edSHong Zhang if (aj[j] > j) { 3087f07e67edSHong Zhang idx[i] = j; 30882205254eSKarl Rupp break; 30892205254eSKarl Rupp } 3090289a08f5SMatthew Knepley } 3091f07e67edSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3092f07e67edSHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3093f07e67edSHong Zhang } 3094289a08f5SMatthew Knepley } 3095c87e5d42SMatthew Knepley for (j = 0; j < ncols; j++) { 30969371c9d4SSatish Balay if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) { 30979371c9d4SSatish Balay x[i] = *aa; 30989371c9d4SSatish Balay if (idx) idx[i] = *aj; 30999371c9d4SSatish Balay } 31009371c9d4SSatish Balay aa++; 31019371c9d4SSatish Balay aj++; 3102c87e5d42SMatthew Knepley } 3103c87e5d42SMatthew Knepley } 31049566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 31059566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3106c87e5d42SMatthew Knepley PetscFunctionReturn(0); 3107c87e5d42SMatthew Knepley } 3108c87e5d42SMatthew Knepley 31099371c9d4SSatish Balay PetscErrorCode MatGetRowMin_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 3110985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3111d9ca1df4SBarry Smith PetscInt i, j, m = A->rmap->n, ncols, n; 3112d9ca1df4SBarry Smith const PetscInt *ai, *aj; 3113985db425SBarry Smith PetscScalar *x; 3114ce496241SStefano Zampini const MatScalar *aa, *av; 3115985db425SBarry Smith 3116985db425SBarry Smith PetscFunctionBegin; 311728b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 31189566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3119ce496241SStefano Zampini aa = av; 3120985db425SBarry Smith ai = a->i; 3121985db425SBarry Smith aj = a->j; 3122985db425SBarry Smith 31239566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 31249566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 31259566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 312608401ef6SPierre Jolivet PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3127985db425SBarry Smith for (i = 0; i < m; i++) { 31289371c9d4SSatish Balay ncols = ai[1] - ai[0]; 31299371c9d4SSatish Balay ai++; 3130d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 31319371c9d4SSatish Balay x[i] = *aa; 31329371c9d4SSatish Balay if (idx) idx[i] = 0; 3133985db425SBarry Smith } else { /* row is sparse so already KNOW minimum is 0.0 or lower */ 3134985db425SBarry Smith x[i] = 0.0; 3135985db425SBarry Smith if (idx) { /* find first implicit 0.0 in the row */ 3136985db425SBarry Smith for (j = 0; j < ncols; j++) { 3137985db425SBarry Smith if (aj[j] > j) { 3138985db425SBarry Smith idx[i] = j; 3139985db425SBarry Smith break; 3140985db425SBarry Smith } 3141985db425SBarry Smith } 3142fa213d2fSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3143fa213d2fSHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3144985db425SBarry Smith } 3145985db425SBarry Smith } 3146985db425SBarry Smith for (j = 0; j < ncols; j++) { 31479371c9d4SSatish Balay if (PetscRealPart(x[i]) > PetscRealPart(*aa)) { 31489371c9d4SSatish Balay x[i] = *aa; 31499371c9d4SSatish Balay if (idx) idx[i] = *aj; 31509371c9d4SSatish Balay } 31519371c9d4SSatish Balay aa++; 31529371c9d4SSatish Balay aj++; 3153e34fafa9SBarry Smith } 3154e34fafa9SBarry Smith } 31559566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 31569566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3157e34fafa9SBarry Smith PetscFunctionReturn(0); 3158e34fafa9SBarry Smith } 3159bbead8a2SBarry Smith 31609371c9d4SSatish Balay PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A, const PetscScalar **values) { 3161bbead8a2SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 316233d57670SJed Brown PetscInt i, bs = PetscAbs(A->rmap->bs), mbs = A->rmap->n / bs, ipvt[5], bs2 = bs * bs, *v_pivots, ij[7], *IJ, j; 3163bbead8a2SBarry Smith MatScalar *diag, work[25], *v_work; 31640da83c2eSBarry Smith const PetscReal shift = 0.0; 31651a9391e3SHong Zhang PetscBool allowzeropivot, zeropivotdetected = PETSC_FALSE; 3166bbead8a2SBarry Smith 3167bbead8a2SBarry Smith PetscFunctionBegin; 3168a455e926SHong Zhang allowzeropivot = PetscNot(A->erroriffailure); 31694a0d0026SBarry Smith if (a->ibdiagvalid) { 31704a0d0026SBarry Smith if (values) *values = a->ibdiag; 31714a0d0026SBarry Smith PetscFunctionReturn(0); 31724a0d0026SBarry Smith } 31739566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 3174bbead8a2SBarry Smith if (!a->ibdiag) { 31759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bs2 * mbs, &a->ibdiag)); 31769566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A, bs2 * mbs * sizeof(PetscScalar))); 3177bbead8a2SBarry Smith } 3178bbead8a2SBarry Smith diag = a->ibdiag; 3179bbead8a2SBarry Smith if (values) *values = a->ibdiag; 3180bbead8a2SBarry Smith /* factor and invert each block */ 3181bbead8a2SBarry Smith switch (bs) { 3182bbead8a2SBarry Smith case 1: 3183bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 31849566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 1, &i, 1, &i, diag + i)); 3185ec1892c8SHong Zhang if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) { 3186ec1892c8SHong Zhang if (allowzeropivot) { 31877b6c816cSBarry Smith A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 31887b6c816cSBarry Smith A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]); 31897b6c816cSBarry Smith A->factorerror_zeropivot_row = i; 31909566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n", i, (double)PetscAbsScalar(diag[i]), (double)PETSC_MACHINE_EPSILON)); 319198921bdaSJacob 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); 3192ec1892c8SHong Zhang } 3193bbead8a2SBarry Smith diag[i] = (PetscScalar)1.0 / (diag[i] + shift); 3194bbead8a2SBarry Smith } 3195bbead8a2SBarry Smith break; 3196bbead8a2SBarry Smith case 2: 3197bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 31989371c9d4SSatish Balay ij[0] = 2 * i; 31999371c9d4SSatish Balay ij[1] = 2 * i + 1; 32009566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 2, ij, 2, ij, diag)); 32019566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected)); 32027b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32039566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_2(diag)); 3204bbead8a2SBarry Smith diag += 4; 3205bbead8a2SBarry Smith } 3206bbead8a2SBarry Smith break; 3207bbead8a2SBarry Smith case 3: 3208bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32099371c9d4SSatish Balay ij[0] = 3 * i; 32109371c9d4SSatish Balay ij[1] = 3 * i + 1; 32119371c9d4SSatish Balay ij[2] = 3 * i + 2; 32129566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 3, ij, 3, ij, diag)); 32139566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected)); 32147b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32159566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_3(diag)); 3216bbead8a2SBarry Smith diag += 9; 3217bbead8a2SBarry Smith } 3218bbead8a2SBarry Smith break; 3219bbead8a2SBarry Smith case 4: 3220bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32219371c9d4SSatish Balay ij[0] = 4 * i; 32229371c9d4SSatish Balay ij[1] = 4 * i + 1; 32239371c9d4SSatish Balay ij[2] = 4 * i + 2; 32249371c9d4SSatish Balay ij[3] = 4 * i + 3; 32259566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 4, ij, 4, ij, diag)); 32269566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected)); 32277b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32289566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_4(diag)); 3229bbead8a2SBarry Smith diag += 16; 3230bbead8a2SBarry Smith } 3231bbead8a2SBarry Smith break; 3232bbead8a2SBarry Smith case 5: 3233bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32349371c9d4SSatish Balay ij[0] = 5 * i; 32359371c9d4SSatish Balay ij[1] = 5 * i + 1; 32369371c9d4SSatish Balay ij[2] = 5 * i + 2; 32379371c9d4SSatish Balay ij[3] = 5 * i + 3; 32389371c9d4SSatish Balay ij[4] = 5 * i + 4; 32399566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 5, ij, 5, ij, diag)); 32409566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected)); 32417b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32429566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_5(diag)); 3243bbead8a2SBarry Smith diag += 25; 3244bbead8a2SBarry Smith } 3245bbead8a2SBarry Smith break; 3246bbead8a2SBarry Smith case 6: 3247bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32489371c9d4SSatish Balay ij[0] = 6 * i; 32499371c9d4SSatish Balay ij[1] = 6 * i + 1; 32509371c9d4SSatish Balay ij[2] = 6 * i + 2; 32519371c9d4SSatish Balay ij[3] = 6 * i + 3; 32529371c9d4SSatish Balay ij[4] = 6 * i + 4; 32539371c9d4SSatish Balay ij[5] = 6 * i + 5; 32549566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 6, ij, 6, ij, diag)); 32559566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected)); 32567b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32579566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_6(diag)); 3258bbead8a2SBarry Smith diag += 36; 3259bbead8a2SBarry Smith } 3260bbead8a2SBarry Smith break; 3261bbead8a2SBarry Smith case 7: 3262bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32639371c9d4SSatish Balay ij[0] = 7 * i; 32649371c9d4SSatish Balay ij[1] = 7 * i + 1; 32659371c9d4SSatish Balay ij[2] = 7 * i + 2; 32669371c9d4SSatish Balay ij[3] = 7 * i + 3; 32679371c9d4SSatish Balay ij[4] = 7 * i + 4; 32689371c9d4SSatish Balay ij[5] = 7 * i + 5; 32699371c9d4SSatish Balay ij[5] = 7 * i + 6; 32709566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 7, ij, 7, ij, diag)); 32719566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected)); 32727b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32739566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_7(diag)); 3274bbead8a2SBarry Smith diag += 49; 3275bbead8a2SBarry Smith } 3276bbead8a2SBarry Smith break; 3277bbead8a2SBarry Smith default: 32789566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(bs, &v_work, bs, &v_pivots, bs, &IJ)); 3279bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 3280ad540459SPierre Jolivet for (j = 0; j < bs; j++) IJ[j] = bs * i + j; 32819566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, bs, IJ, bs, IJ, diag)); 32829566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A(bs, diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected)); 32837b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32849566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_N(diag, bs)); 3285bbead8a2SBarry Smith diag += bs2; 3286bbead8a2SBarry Smith } 32879566063dSJacob Faibussowitsch PetscCall(PetscFree3(v_work, v_pivots, IJ)); 3288bbead8a2SBarry Smith } 3289bbead8a2SBarry Smith a->ibdiagvalid = PETSC_TRUE; 3290bbead8a2SBarry Smith PetscFunctionReturn(0); 3291bbead8a2SBarry Smith } 3292bbead8a2SBarry Smith 32939371c9d4SSatish Balay static PetscErrorCode MatSetRandom_SeqAIJ(Mat x, PetscRandom rctx) { 329473a71a0fSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data; 3295fff043a9SJunchao Zhang PetscScalar a, *aa; 329673a71a0fSBarry Smith PetscInt m, n, i, j, col; 329773a71a0fSBarry Smith 329873a71a0fSBarry Smith PetscFunctionBegin; 329973a71a0fSBarry Smith if (!x->assembled) { 33009566063dSJacob Faibussowitsch PetscCall(MatGetSize(x, &m, &n)); 330173a71a0fSBarry Smith for (i = 0; i < m; i++) { 330273a71a0fSBarry Smith for (j = 0; j < aij->imax[i]; j++) { 33039566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx, &a)); 330473a71a0fSBarry Smith col = (PetscInt)(n * PetscRealPart(a)); 33059566063dSJacob Faibussowitsch PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES)); 330673a71a0fSBarry Smith } 330773a71a0fSBarry Smith } 3308e2ce353bSJunchao Zhang } else { 33099566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayWrite(x, &aa)); 33109566063dSJacob Faibussowitsch for (i = 0; i < aij->nz; i++) PetscCall(PetscRandomGetValue(rctx, aa + i)); 33119566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayWrite(x, &aa)); 3312e2ce353bSJunchao Zhang } 33139566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 33149566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 331573a71a0fSBarry Smith PetscFunctionReturn(0); 331673a71a0fSBarry Smith } 331773a71a0fSBarry Smith 3318679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */ 33199371c9d4SSatish Balay PetscErrorCode MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x, PetscInt low, PetscInt high, PetscRandom rctx) { 3320679944adSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data; 3321679944adSJunchao Zhang PetscScalar a; 3322679944adSJunchao Zhang PetscInt m, n, i, j, col, nskip; 3323679944adSJunchao Zhang 3324679944adSJunchao Zhang PetscFunctionBegin; 3325679944adSJunchao Zhang nskip = high - low; 33269566063dSJacob Faibussowitsch PetscCall(MatGetSize(x, &m, &n)); 3327679944adSJunchao Zhang n -= nskip; /* shrink number of columns where nonzeros can be set */ 3328679944adSJunchao Zhang for (i = 0; i < m; i++) { 3329679944adSJunchao Zhang for (j = 0; j < aij->imax[i]; j++) { 33309566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx, &a)); 3331679944adSJunchao Zhang col = (PetscInt)(n * PetscRealPart(a)); 3332679944adSJunchao Zhang if (col >= low) col += nskip; /* shift col rightward to skip the hole */ 33339566063dSJacob Faibussowitsch PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES)); 3334679944adSJunchao Zhang } 3335e2ce353bSJunchao Zhang } 33369566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 33379566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 3338679944adSJunchao Zhang PetscFunctionReturn(0); 3339679944adSJunchao Zhang } 3340679944adSJunchao Zhang 3341682d7d0cSBarry Smith /* -------------------------------------------------------------------*/ 33420a6ffc59SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ, 3343cb5b572fSBarry Smith MatGetRow_SeqAIJ, 3344cb5b572fSBarry Smith MatRestoreRow_SeqAIJ, 3345cb5b572fSBarry Smith MatMult_SeqAIJ, 334697304618SKris Buschelman /* 4*/ MatMultAdd_SeqAIJ, 33477c922b88SBarry Smith MatMultTranspose_SeqAIJ, 33487c922b88SBarry Smith MatMultTransposeAdd_SeqAIJ, 3349f4259b30SLisandro Dalcin NULL, 3350f4259b30SLisandro Dalcin NULL, 3351f4259b30SLisandro Dalcin NULL, 3352f4259b30SLisandro Dalcin /* 10*/ NULL, 3353cb5b572fSBarry Smith MatLUFactor_SeqAIJ, 3354f4259b30SLisandro Dalcin NULL, 335541f059aeSBarry Smith MatSOR_SeqAIJ, 335691e9d3e2SHong Zhang MatTranspose_SeqAIJ, 335797304618SKris Buschelman /*1 5*/ MatGetInfo_SeqAIJ, 3358cb5b572fSBarry Smith MatEqual_SeqAIJ, 3359cb5b572fSBarry Smith MatGetDiagonal_SeqAIJ, 3360cb5b572fSBarry Smith MatDiagonalScale_SeqAIJ, 3361cb5b572fSBarry Smith MatNorm_SeqAIJ, 3362f4259b30SLisandro Dalcin /* 20*/ NULL, 3363cb5b572fSBarry Smith MatAssemblyEnd_SeqAIJ, 3364cb5b572fSBarry Smith MatSetOption_SeqAIJ, 3365cb5b572fSBarry Smith MatZeroEntries_SeqAIJ, 3366d519adbfSMatthew Knepley /* 24*/ MatZeroRows_SeqAIJ, 3367f4259b30SLisandro Dalcin NULL, 3368f4259b30SLisandro Dalcin NULL, 3369f4259b30SLisandro Dalcin NULL, 3370f4259b30SLisandro Dalcin NULL, 33714994cf47SJed Brown /* 29*/ MatSetUp_SeqAIJ, 3372f4259b30SLisandro Dalcin NULL, 3373f4259b30SLisandro Dalcin NULL, 3374f4259b30SLisandro Dalcin NULL, 3375f4259b30SLisandro Dalcin NULL, 3376d519adbfSMatthew Knepley /* 34*/ MatDuplicate_SeqAIJ, 3377f4259b30SLisandro Dalcin NULL, 3378f4259b30SLisandro Dalcin NULL, 3379cb5b572fSBarry Smith MatILUFactor_SeqAIJ, 3380f4259b30SLisandro Dalcin NULL, 3381d519adbfSMatthew Knepley /* 39*/ MatAXPY_SeqAIJ, 33827dae84e0SHong Zhang MatCreateSubMatrices_SeqAIJ, 3383cb5b572fSBarry Smith MatIncreaseOverlap_SeqAIJ, 3384cb5b572fSBarry Smith MatGetValues_SeqAIJ, 3385cb5b572fSBarry Smith MatCopy_SeqAIJ, 3386d519adbfSMatthew Knepley /* 44*/ MatGetRowMax_SeqAIJ, 3387cb5b572fSBarry Smith MatScale_SeqAIJ, 33887d68702bSBarry Smith MatShift_SeqAIJ, 338979299369SBarry Smith MatDiagonalSet_SeqAIJ, 33906e169961SBarry Smith MatZeroRowsColumns_SeqAIJ, 339173a71a0fSBarry Smith /* 49*/ MatSetRandom_SeqAIJ, 33923b2fbd54SBarry Smith MatGetRowIJ_SeqAIJ, 33933b2fbd54SBarry Smith MatRestoreRowIJ_SeqAIJ, 33943b2fbd54SBarry Smith MatGetColumnIJ_SeqAIJ, 3395a93ec695SBarry Smith MatRestoreColumnIJ_SeqAIJ, 339693dfae19SHong Zhang /* 54*/ MatFDColoringCreate_SeqXAIJ, 3397f4259b30SLisandro Dalcin NULL, 3398f4259b30SLisandro Dalcin NULL, 3399cda55fadSBarry Smith MatPermute_SeqAIJ, 3400f4259b30SLisandro Dalcin NULL, 3401f4259b30SLisandro Dalcin /* 59*/ NULL, 3402b9b97703SBarry Smith MatDestroy_SeqAIJ, 3403b9b97703SBarry Smith MatView_SeqAIJ, 3404f4259b30SLisandro Dalcin NULL, 3405f4259b30SLisandro Dalcin NULL, 3406f4259b30SLisandro Dalcin /* 64*/ NULL, 3407321b30b9SSatish Balay MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ, 3408f4259b30SLisandro Dalcin NULL, 3409f4259b30SLisandro Dalcin NULL, 3410f4259b30SLisandro Dalcin NULL, 3411d519adbfSMatthew Knepley /* 69*/ MatGetRowMaxAbs_SeqAIJ, 3412c87e5d42SMatthew Knepley MatGetRowMinAbs_SeqAIJ, 3413f4259b30SLisandro Dalcin NULL, 3414f4259b30SLisandro Dalcin NULL, 3415f4259b30SLisandro Dalcin NULL, 3416f4259b30SLisandro Dalcin /* 74*/ NULL, 34173acb8795SBarry Smith MatFDColoringApply_AIJ, 3418f4259b30SLisandro Dalcin NULL, 3419f4259b30SLisandro Dalcin NULL, 3420f4259b30SLisandro Dalcin NULL, 34216ce1633cSBarry Smith /* 79*/ MatFindZeroDiagonals_SeqAIJ, 3422f4259b30SLisandro Dalcin NULL, 3423f4259b30SLisandro Dalcin NULL, 3424f4259b30SLisandro Dalcin NULL, 3425bc011b1eSHong Zhang MatLoad_SeqAIJ, 3426d519adbfSMatthew Knepley /* 84*/ MatIsSymmetric_SeqAIJ, 34271cbb95d3SBarry Smith MatIsHermitian_SeqAIJ, 3428f4259b30SLisandro Dalcin NULL, 3429f4259b30SLisandro Dalcin NULL, 3430f4259b30SLisandro Dalcin NULL, 3431f4259b30SLisandro Dalcin /* 89*/ NULL, 3432f4259b30SLisandro Dalcin NULL, 343326be0446SHong Zhang MatMatMultNumeric_SeqAIJ_SeqAIJ, 3434f4259b30SLisandro Dalcin NULL, 3435f4259b30SLisandro Dalcin NULL, 34368fa4b5a6SHong Zhang /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy, 3437f4259b30SLisandro Dalcin NULL, 3438f4259b30SLisandro Dalcin NULL, 34396fc122caSHong Zhang MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ, 3440f4259b30SLisandro Dalcin NULL, 34414222ddf1SHong Zhang /* 99*/ MatProductSetFromOptions_SeqAIJ, 3442f4259b30SLisandro Dalcin NULL, 3443f4259b30SLisandro Dalcin NULL, 344487d4246cSBarry Smith MatConjugate_SeqAIJ, 3445f4259b30SLisandro Dalcin NULL, 3446d519adbfSMatthew Knepley /*104*/ MatSetValuesRow_SeqAIJ, 344799cafbc1SBarry Smith MatRealPart_SeqAIJ, 3448f5edf698SHong Zhang MatImaginaryPart_SeqAIJ, 3449f4259b30SLisandro Dalcin NULL, 3450f4259b30SLisandro Dalcin NULL, 3451cbd44569SHong Zhang /*109*/ MatMatSolve_SeqAIJ, 3452f4259b30SLisandro Dalcin NULL, 34532af78befSBarry Smith MatGetRowMin_SeqAIJ, 3454f4259b30SLisandro Dalcin NULL, 3455599ef60dSHong Zhang MatMissingDiagonal_SeqAIJ, 3456f4259b30SLisandro Dalcin /*114*/ NULL, 3457f4259b30SLisandro Dalcin NULL, 3458f4259b30SLisandro Dalcin NULL, 3459f4259b30SLisandro Dalcin NULL, 3460f4259b30SLisandro Dalcin NULL, 3461f4259b30SLisandro Dalcin /*119*/ NULL, 3462f4259b30SLisandro Dalcin NULL, 3463f4259b30SLisandro Dalcin NULL, 3464f4259b30SLisandro Dalcin NULL, 3465b3a44c85SBarry Smith MatGetMultiProcBlock_SeqAIJ, 34660716a85fSBarry Smith /*124*/ MatFindNonzeroRows_SeqAIJ, 3467a873a8cdSSam Reynolds MatGetColumnReductions_SeqAIJ, 346837868618SMatthew G Knepley MatInvertBlockDiagonal_SeqAIJ, 34690da83c2eSBarry Smith MatInvertVariableBlockDiagonal_SeqAIJ, 3470f4259b30SLisandro Dalcin NULL, 3471f4259b30SLisandro Dalcin /*129*/ NULL, 3472f4259b30SLisandro Dalcin NULL, 3473f4259b30SLisandro Dalcin NULL, 347475648e8dSHong Zhang MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ, 3475b9af6bddSHong Zhang MatTransposeColoringCreate_SeqAIJ, 3476b9af6bddSHong Zhang /*134*/ MatTransColoringApplySpToDen_SeqAIJ, 34772b8ad9a3SHong Zhang MatTransColoringApplyDenToSp_SeqAIJ, 3478f4259b30SLisandro Dalcin NULL, 3479f4259b30SLisandro Dalcin NULL, 34803964eb88SJed Brown MatRARtNumeric_SeqAIJ_SeqAIJ, 3481f4259b30SLisandro Dalcin /*139*/ NULL, 3482f4259b30SLisandro Dalcin NULL, 3483f4259b30SLisandro Dalcin NULL, 34843a062f41SBarry Smith MatFDColoringSetUp_SeqXAIJ, 34859c8f2541SHong Zhang MatFindOffBlockDiagonalEntries_SeqAIJ, 34864222ddf1SHong Zhang MatCreateMPIMatConcatenateSeqMat_SeqAIJ, 34874222ddf1SHong Zhang /*145*/ MatDestroySubMatrices_SeqAIJ, 3488f4259b30SLisandro Dalcin NULL, 348972833a62Smarkadams4 NULL, 349072833a62Smarkadams4 MatCreateGraph_Simple_AIJ, 34917fb60732SBarry Smith MatFilter_AIJ, 34929371c9d4SSatish Balay /*150*/ MatTransposeSymbolic_SeqAIJ}; 349317ab2063SBarry Smith 34949371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat, PetscInt *indices) { 3495bef8e0ddSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 349697f1f81fSBarry Smith PetscInt i, nz, n; 3497bef8e0ddSBarry Smith 3498bef8e0ddSBarry Smith PetscFunctionBegin; 3499bef8e0ddSBarry Smith nz = aij->maxnz; 3500d0f46423SBarry Smith n = mat->rmap->n; 3501ad540459SPierre Jolivet for (i = 0; i < nz; i++) aij->j[i] = indices[i]; 3502bef8e0ddSBarry Smith aij->nz = nz; 3503ad540459SPierre Jolivet for (i = 0; i < n; i++) aij->ilen[i] = aij->imax[i]; 3504bef8e0ddSBarry Smith PetscFunctionReturn(0); 3505bef8e0ddSBarry Smith } 3506bef8e0ddSBarry Smith 3507a3bb6f32SFande Kong /* 3508ddea5d60SJunchao Zhang * Given a sparse matrix with global column indices, compact it by using a local column space. 3509ddea5d60SJunchao Zhang * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable() 3510ddea5d60SJunchao Zhang */ 35119371c9d4SSatish Balay PetscErrorCode MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping) { 3512a3bb6f32SFande Kong Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3513a3bb6f32SFande Kong PetscTable gid1_lid1; 3514a3bb6f32SFande Kong PetscTablePosition tpos; 351525b670f0SStefano Zampini PetscInt gid, lid, i, ec, nz = aij->nz; 351625b670f0SStefano Zampini PetscInt *garray, *jj = aij->j; 3517a3bb6f32SFande Kong 3518a3bb6f32SFande Kong PetscFunctionBegin; 3519a3bb6f32SFande Kong PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3520a3bb6f32SFande Kong PetscValidPointer(mapping, 2); 3521a3bb6f32SFande Kong /* use a table */ 35229566063dSJacob Faibussowitsch PetscCall(PetscTableCreate(mat->rmap->n, mat->cmap->N + 1, &gid1_lid1)); 3523a3bb6f32SFande Kong ec = 0; 352425b670f0SStefano Zampini for (i = 0; i < nz; i++) { 352525b670f0SStefano Zampini PetscInt data, gid1 = jj[i] + 1; 35269566063dSJacob Faibussowitsch PetscCall(PetscTableFind(gid1_lid1, gid1, &data)); 3527a3bb6f32SFande Kong if (!data) { 3528a3bb6f32SFande Kong /* one based table */ 35299566063dSJacob Faibussowitsch PetscCall(PetscTableAdd(gid1_lid1, gid1, ++ec, INSERT_VALUES)); 3530a3bb6f32SFande Kong } 3531a3bb6f32SFande Kong } 3532a3bb6f32SFande Kong /* form array of columns we need */ 35339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ec, &garray)); 35349566063dSJacob Faibussowitsch PetscCall(PetscTableGetHeadPosition(gid1_lid1, &tpos)); 3535a3bb6f32SFande Kong while (tpos) { 35369566063dSJacob Faibussowitsch PetscCall(PetscTableGetNext(gid1_lid1, &tpos, &gid, &lid)); 3537a3bb6f32SFande Kong gid--; 3538a3bb6f32SFande Kong lid--; 3539a3bb6f32SFande Kong garray[lid] = gid; 3540a3bb6f32SFande Kong } 35419566063dSJacob Faibussowitsch PetscCall(PetscSortInt(ec, garray)); /* sort, and rebuild */ 35429566063dSJacob Faibussowitsch PetscCall(PetscTableRemoveAll(gid1_lid1)); 354348a46eb9SPierre Jolivet for (i = 0; i < ec; i++) PetscCall(PetscTableAdd(gid1_lid1, garray[i] + 1, i + 1, INSERT_VALUES)); 3544a3bb6f32SFande Kong /* compact out the extra columns in B */ 354525b670f0SStefano Zampini for (i = 0; i < nz; i++) { 354625b670f0SStefano Zampini PetscInt gid1 = jj[i] + 1; 35479566063dSJacob Faibussowitsch PetscCall(PetscTableFind(gid1_lid1, gid1, &lid)); 3548a3bb6f32SFande Kong lid--; 354925b670f0SStefano Zampini jj[i] = lid; 3550a3bb6f32SFande Kong } 35519566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&mat->cmap)); 35529566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy(&gid1_lid1)); 35539566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat), ec, ec, 1, &mat->cmap)); 35549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, mat->cmap->bs, mat->cmap->n, garray, PETSC_OWN_POINTER, mapping)); 35559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*mapping, ISLOCALTOGLOBALMAPPINGHASH)); 3556a3bb6f32SFande Kong PetscFunctionReturn(0); 3557a3bb6f32SFande Kong } 3558a3bb6f32SFande Kong 3559bef8e0ddSBarry Smith /*@ 3560bef8e0ddSBarry Smith MatSeqAIJSetColumnIndices - Set the column indices for all the rows 3561bef8e0ddSBarry Smith in the matrix. 3562bef8e0ddSBarry Smith 3563bef8e0ddSBarry Smith Input Parameters: 356411a5261eSBarry Smith + mat - the `MATSEQAIJ` matrix 3565bef8e0ddSBarry Smith - indices - the column indices 3566bef8e0ddSBarry Smith 356715091d37SBarry Smith Level: advanced 356815091d37SBarry Smith 3569bef8e0ddSBarry Smith Notes: 3570bef8e0ddSBarry Smith This can be called if you have precomputed the nonzero structure of the 3571bef8e0ddSBarry Smith matrix and want to provide it to the matrix object to improve the performance 357211a5261eSBarry Smith of the `MatSetValues()` operation. 3573bef8e0ddSBarry Smith 3574bef8e0ddSBarry Smith You MUST have set the correct numbers of nonzeros per row in the call to 357511a5261eSBarry Smith `MatCreateSeqAIJ()`, and the columns indices MUST be sorted. 3576bef8e0ddSBarry Smith 357711a5261eSBarry Smith MUST be called before any calls to `MatSetValues()` 3578bef8e0ddSBarry Smith 3579b9617806SBarry Smith The indices should start with zero, not one. 3580b9617806SBarry Smith 3581bef8e0ddSBarry Smith @*/ 35829371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat, PetscInt *indices) { 3583bef8e0ddSBarry Smith PetscFunctionBegin; 35840700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3585dadcf809SJacob Faibussowitsch PetscValidIntPointer(indices, 2); 3586cac4c232SBarry Smith PetscUseMethod(mat, "MatSeqAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices)); 3587bef8e0ddSBarry Smith PetscFunctionReturn(0); 3588bef8e0ddSBarry Smith } 3589bef8e0ddSBarry Smith 3590be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/ 3591be6bf707SBarry Smith 35929371c9d4SSatish Balay PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) { 3593be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3594d0f46423SBarry Smith size_t nz = aij->i[mat->rmap->n]; 3595be6bf707SBarry Smith 3596be6bf707SBarry Smith PetscFunctionBegin; 359728b400f6SJacob Faibussowitsch PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3598be6bf707SBarry Smith 3599be6bf707SBarry Smith /* allocate space for values if not already there */ 3600be6bf707SBarry Smith if (!aij->saved_values) { 36019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz + 1, &aij->saved_values)); 36029566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)mat, (nz + 1) * sizeof(PetscScalar))); 3603be6bf707SBarry Smith } 3604be6bf707SBarry Smith 3605be6bf707SBarry Smith /* copy values over */ 36069566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz)); 3607be6bf707SBarry Smith PetscFunctionReturn(0); 3608be6bf707SBarry Smith } 3609be6bf707SBarry Smith 3610be6bf707SBarry Smith /*@ 3611be6bf707SBarry Smith MatStoreValues - Stashes a copy of the matrix values; this allows, for 3612be6bf707SBarry Smith example, reuse of the linear part of a Jacobian, while recomputing the 3613be6bf707SBarry Smith nonlinear portion. 3614be6bf707SBarry Smith 361511a5261eSBarry Smith Collect on mat 3616be6bf707SBarry Smith 3617be6bf707SBarry Smith Input Parameters: 361811a5261eSBarry Smith . mat - the matrix (currently only `MATAIJ` matrices support this option) 3619be6bf707SBarry Smith 362015091d37SBarry Smith Level: advanced 362115091d37SBarry Smith 362211a5261eSBarry Smith Common Usage, with `SNESSolve()`: 3623be6bf707SBarry Smith $ Create Jacobian matrix 3624be6bf707SBarry Smith $ Set linear terms into matrix 3625be6bf707SBarry Smith $ Apply boundary conditions to matrix, at this time matrix must have 3626be6bf707SBarry Smith $ final nonzero structure (i.e. setting the nonlinear terms and applying 3627be6bf707SBarry Smith $ boundary conditions again will not change the nonzero structure 3628512a5fc5SBarry Smith $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3629be6bf707SBarry Smith $ ierr = MatStoreValues(mat); 3630be6bf707SBarry Smith $ Call SNESSetJacobian() with matrix 3631be6bf707SBarry Smith $ In your Jacobian routine 3632be6bf707SBarry Smith $ ierr = MatRetrieveValues(mat); 3633be6bf707SBarry Smith $ Set nonlinear terms in matrix 3634be6bf707SBarry Smith 3635be6bf707SBarry Smith Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself: 3636be6bf707SBarry Smith $ // build linear portion of Jacobian 3637512a5fc5SBarry Smith $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3638be6bf707SBarry Smith $ ierr = MatStoreValues(mat); 3639be6bf707SBarry Smith $ loop over nonlinear iterations 3640be6bf707SBarry Smith $ ierr = MatRetrieveValues(mat); 3641be6bf707SBarry Smith $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian 3642be6bf707SBarry Smith $ // call MatAssemblyBegin/End() on matrix 3643be6bf707SBarry Smith $ Solve linear system with Jacobian 3644be6bf707SBarry Smith $ endloop 3645be6bf707SBarry Smith 3646be6bf707SBarry Smith Notes: 3647be6bf707SBarry Smith Matrix must already be assemblied before calling this routine 364811a5261eSBarry Smith Must set the matrix option `MatSetOption`(mat,`MAT_NEW_NONZERO_LOCATIONS`,`PETSC_FALSE`); before 3649be6bf707SBarry Smith calling this routine. 3650be6bf707SBarry Smith 36510c468ba9SBarry Smith When this is called multiple times it overwrites the previous set of stored values 36520c468ba9SBarry Smith and does not allocated additional space. 36530c468ba9SBarry Smith 3654db781477SPatrick Sanan .seealso: `MatRetrieveValues()` 3655be6bf707SBarry Smith @*/ 36569371c9d4SSatish Balay PetscErrorCode MatStoreValues(Mat mat) { 3657be6bf707SBarry Smith PetscFunctionBegin; 36580700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 365928b400f6SJacob Faibussowitsch PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 366028b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3661cac4c232SBarry Smith PetscUseMethod(mat, "MatStoreValues_C", (Mat), (mat)); 3662be6bf707SBarry Smith PetscFunctionReturn(0); 3663be6bf707SBarry Smith } 3664be6bf707SBarry Smith 36659371c9d4SSatish Balay PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat) { 3666be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3667d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->n]; 3668be6bf707SBarry Smith 3669be6bf707SBarry Smith PetscFunctionBegin; 367028b400f6SJacob Faibussowitsch PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 367128b400f6SJacob Faibussowitsch PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first"); 3672be6bf707SBarry Smith /* copy values over */ 36739566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz)); 3674be6bf707SBarry Smith PetscFunctionReturn(0); 3675be6bf707SBarry Smith } 3676be6bf707SBarry Smith 3677be6bf707SBarry Smith /*@ 3678be6bf707SBarry Smith MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 3679be6bf707SBarry Smith example, reuse of the linear part of a Jacobian, while recomputing the 3680be6bf707SBarry Smith nonlinear portion. 3681be6bf707SBarry Smith 368211a5261eSBarry Smith Collect on mat 3683be6bf707SBarry Smith 3684be6bf707SBarry Smith Input Parameters: 368511a5261eSBarry Smith . mat - the matrix (currently only `MATAIJ` matrices support this option) 3686be6bf707SBarry Smith 368715091d37SBarry Smith Level: advanced 368815091d37SBarry Smith 3689db781477SPatrick Sanan .seealso: `MatStoreValues()` 3690be6bf707SBarry Smith @*/ 36919371c9d4SSatish Balay PetscErrorCode MatRetrieveValues(Mat mat) { 3692be6bf707SBarry Smith PetscFunctionBegin; 36930700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 369428b400f6SJacob Faibussowitsch PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 369528b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3696cac4c232SBarry Smith PetscUseMethod(mat, "MatRetrieveValues_C", (Mat), (mat)); 3697be6bf707SBarry Smith PetscFunctionReturn(0); 3698be6bf707SBarry Smith } 3699be6bf707SBarry Smith 3700be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/ 370117ab2063SBarry Smith /*@C 370211a5261eSBarry Smith MatCreateSeqAIJ - Creates a sparse matrix in `MATSEQAIJ` (compressed row) format 37030d15e28bSLois Curfman McInnes (the default parallel PETSc format). For good matrix assembly performance 37046e62573dSLois Curfman McInnes the user should preallocate the matrix storage by setting the parameter nz 370551c19458SBarry Smith (or the array nnz). By setting these parameters accurately, performance 37062bd5e0b2SLois Curfman McInnes during matrix assembly can be increased by more than a factor of 50. 370717ab2063SBarry Smith 3708d083f849SBarry Smith Collective 3709db81eaa0SLois Curfman McInnes 371017ab2063SBarry Smith Input Parameters: 371111a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF` 371217ab2063SBarry Smith . m - number of rows 371317ab2063SBarry Smith . n - number of columns 371417ab2063SBarry Smith . nz - number of nonzeros per row (same for all rows) 371551c19458SBarry Smith - nnz - array containing the number of nonzeros in the various rows 37160298fd71SBarry Smith (possibly different for each row) or NULL 371717ab2063SBarry Smith 371817ab2063SBarry Smith Output Parameter: 3719416022c9SBarry Smith . A - the matrix 372017ab2063SBarry Smith 372111a5261eSBarry Smith It is recommended that one use the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`, 3722f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly. 372311a5261eSBarry Smith [MatXXXXSetPreallocation() is, for example, `MatSeqAIJSetPreallocation()`] 3724175b88e8SBarry Smith 3725b259b22eSLois Curfman McInnes Notes: 372649a6f317SBarry Smith If nnz is given then nz is ignored 372749a6f317SBarry Smith 372811a5261eSBarry Smith The AIJ format, also called 372911a5261eSBarry Smith compressed row storage, is fully compatible with standard Fortran 77 37300002213bSLois Curfman McInnes storage. That is, the stored row and column indices can begin at 373144cd7ae7SLois Curfman McInnes either one (as in Fortran) or zero. See the users' manual for details. 373217ab2063SBarry Smith 373317ab2063SBarry Smith Specify the preallocated storage with either nz or nnz (not both). 373411a5261eSBarry Smith Set nz = `PETSC_DEFAULT` and nnz = NULL for PETSc to control dynamic memory 37353d323bbdSBarry Smith allocation. For large problems you MUST preallocate memory or you 37366da5968aSLois Curfman McInnes will get TERRIBLE performance, see the users' manual chapter on matrices. 373717ab2063SBarry Smith 3738682d7d0cSBarry Smith By default, this format uses inodes (identical nodes) when possible, to 37394fca80b9SLois Curfman McInnes improve numerical efficiency of matrix-vector products and solves. We 3740682d7d0cSBarry Smith search for consecutive rows with the same nonzero structure, thereby 37416c7ebb05SLois Curfman McInnes reusing matrix information to achieve increased efficiency. 37426c7ebb05SLois Curfman McInnes 37436c7ebb05SLois Curfman McInnes Options Database Keys: 3744698d4c6aSKris Buschelman + -mat_no_inode - Do not use inodes 37459db58ca8SBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 374617ab2063SBarry Smith 3747027ccd11SLois Curfman McInnes Level: intermediate 3748027ccd11SLois Curfman McInnes 3749db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()` 375017ab2063SBarry Smith @*/ 37519371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A) { 37523a40ed3dSBarry Smith PetscFunctionBegin; 37539566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 37549566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, m, n)); 37559566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATSEQAIJ)); 37569566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*A, nz, nnz)); 3757273d9f13SBarry Smith PetscFunctionReturn(0); 3758273d9f13SBarry Smith } 3759273d9f13SBarry Smith 3760273d9f13SBarry Smith /*@C 3761273d9f13SBarry Smith MatSeqAIJSetPreallocation - For good matrix assembly performance 3762273d9f13SBarry Smith the user should preallocate the matrix storage by setting the parameter nz 3763273d9f13SBarry Smith (or the array nnz). By setting these parameters accurately, performance 3764273d9f13SBarry Smith during matrix assembly can be increased by more than a factor of 50. 3765273d9f13SBarry Smith 3766d083f849SBarry Smith Collective 3767273d9f13SBarry Smith 3768273d9f13SBarry Smith Input Parameters: 37691c4f3114SJed Brown + B - The matrix 3770273d9f13SBarry Smith . nz - number of nonzeros per row (same for all rows) 3771273d9f13SBarry Smith - nnz - array containing the number of nonzeros in the various rows 37720298fd71SBarry Smith (possibly different for each row) or NULL 3773273d9f13SBarry Smith 3774273d9f13SBarry Smith Notes: 377549a6f317SBarry Smith If nnz is given then nz is ignored 377649a6f317SBarry Smith 377711a5261eSBarry Smith The `MATSEQAIJ` format also called 377811a5261eSBarry Smith compressed row storage, is fully compatible with standard Fortran 77 3779273d9f13SBarry Smith storage. That is, the stored row and column indices can begin at 3780273d9f13SBarry Smith either one (as in Fortran) or zero. See the users' manual for details. 3781273d9f13SBarry Smith 3782273d9f13SBarry Smith Specify the preallocated storage with either nz or nnz (not both). 378311a5261eSBarry Smith Set nz = `PETSC_DEFAULT` and nnz = NULL for PETSc to control dynamic memory 3784273d9f13SBarry Smith allocation. For large problems you MUST preallocate memory or you 3785273d9f13SBarry Smith will get TERRIBLE performance, see the users' manual chapter on matrices. 3786273d9f13SBarry Smith 378711a5261eSBarry Smith You can call `MatGetInfo()` to get information on how effective the preallocation was; 3788aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 3789aa95bbe8SBarry Smith You can also run with the option -info and look for messages with the string 3790aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 3791aa95bbe8SBarry Smith 379211a5261eSBarry Smith Developer Notes: 379311a5261eSBarry Smith Use nz of `MAT_SKIP_ALLOCATION` to not allocate any space for the matrix 3794a96a251dSBarry Smith entries or columns indices 3795a96a251dSBarry Smith 3796273d9f13SBarry Smith By default, this format uses inodes (identical nodes) when possible, to 3797273d9f13SBarry Smith improve numerical efficiency of matrix-vector products and solves. We 3798273d9f13SBarry Smith search for consecutive rows with the same nonzero structure, thereby 3799273d9f13SBarry Smith reusing matrix information to achieve increased efficiency. 3800273d9f13SBarry Smith 3801273d9f13SBarry Smith Options Database Keys: 3802698d4c6aSKris Buschelman + -mat_no_inode - Do not use inodes 380347b2e64bSBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3804273d9f13SBarry Smith 3805273d9f13SBarry Smith Level: intermediate 3806273d9f13SBarry Smith 3807db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()`, `MatGetInfo()`, 3808db781477SPatrick Sanan `MatSeqAIJSetTotalPreallocation()` 3809273d9f13SBarry Smith @*/ 38109371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocation(Mat B, PetscInt nz, const PetscInt nnz[]) { 3811a23d5eceSKris Buschelman PetscFunctionBegin; 38126ba663aaSJed Brown PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 38136ba663aaSJed Brown PetscValidType(B, 1); 3814cac4c232SBarry Smith PetscTryMethod(B, "MatSeqAIJSetPreallocation_C", (Mat, PetscInt, const PetscInt[]), (B, nz, nnz)); 3815a23d5eceSKris Buschelman PetscFunctionReturn(0); 3816a23d5eceSKris Buschelman } 3817a23d5eceSKris Buschelman 38189371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B, PetscInt nz, const PetscInt *nnz) { 3819273d9f13SBarry Smith Mat_SeqAIJ *b; 38202576faa2SJed Brown PetscBool skipallocation = PETSC_FALSE, realalloc = PETSC_FALSE; 382197f1f81fSBarry Smith PetscInt i; 3822273d9f13SBarry Smith 3823273d9f13SBarry Smith PetscFunctionBegin; 38242576faa2SJed Brown if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 3825a96a251dSBarry Smith if (nz == MAT_SKIP_ALLOCATION) { 3826c461c341SBarry Smith skipallocation = PETSC_TRUE; 3827c461c341SBarry Smith nz = 0; 3828c461c341SBarry Smith } 38299566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 38309566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 3831899cda47SBarry Smith 3832435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 383308401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz); 3834cf9c20a2SJed Brown if (PetscUnlikelyDebug(nnz)) { 3835d0f46423SBarry Smith for (i = 0; i < B->rmap->n; i++) { 383608401ef6SPierre 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]); 383708401ef6SPierre 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); 3838b73539f3SBarry Smith } 3839b73539f3SBarry Smith } 3840b73539f3SBarry Smith 3841273d9f13SBarry Smith B->preallocated = PETSC_TRUE; 38422205254eSKarl Rupp 3843273d9f13SBarry Smith b = (Mat_SeqAIJ *)B->data; 3844273d9f13SBarry Smith 3845ab93d7beSBarry Smith if (!skipallocation) { 38462ee49352SLisandro Dalcin if (!b->imax) { 38479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n, &b->imax)); 38489566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, B->rmap->n * sizeof(PetscInt))); 3849071fcb05SBarry Smith } 3850071fcb05SBarry Smith if (!b->ilen) { 3851071fcb05SBarry Smith /* b->ilen will count nonzeros in each row so far. */ 38529566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(B->rmap->n, &b->ilen)); 38539566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, B->rmap->n * sizeof(PetscInt))); 3854071fcb05SBarry Smith } else { 38559566063dSJacob Faibussowitsch PetscCall(PetscMemzero(b->ilen, B->rmap->n * sizeof(PetscInt))); 38562ee49352SLisandro Dalcin } 3857846b4da1SFande Kong if (!b->ipre) { 38589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n, &b->ipre)); 38599566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, B->rmap->n * sizeof(PetscInt))); 3860846b4da1SFande Kong } 3861273d9f13SBarry Smith if (!nnz) { 3862435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 3863c62bd62aSJed Brown else if (nz < 0) nz = 1; 38645d2a9ed1SStefano Zampini nz = PetscMin(nz, B->cmap->n); 3865d0f46423SBarry Smith for (i = 0; i < B->rmap->n; i++) b->imax[i] = nz; 3866d0f46423SBarry Smith nz = nz * B->rmap->n; 3867273d9f13SBarry Smith } else { 3868c73702f5SBarry Smith PetscInt64 nz64 = 0; 38699371c9d4SSatish Balay for (i = 0; i < B->rmap->n; i++) { 38709371c9d4SSatish Balay b->imax[i] = nnz[i]; 38719371c9d4SSatish Balay nz64 += nnz[i]; 38729371c9d4SSatish Balay } 38739566063dSJacob Faibussowitsch PetscCall(PetscIntCast(nz64, &nz)); 3874273d9f13SBarry Smith } 3875ab93d7beSBarry Smith 3876273d9f13SBarry Smith /* allocate the matrix space */ 387753dd7562SDmitry Karpeev /* FIXME: should B's old memory be unlogged? */ 38789566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i)); 3879396832f4SHong Zhang if (B->structure_only) { 38809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &b->j)); 38819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n + 1, &b->i)); 38829566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, (B->rmap->n + 1) * sizeof(PetscInt) + nz * sizeof(PetscInt))); 3883396832f4SHong Zhang } else { 38849566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(nz, &b->a, nz, &b->j, B->rmap->n + 1, &b->i)); 38859566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, (B->rmap->n + 1) * sizeof(PetscInt) + nz * (sizeof(PetscScalar) + sizeof(PetscInt)))); 3886396832f4SHong Zhang } 3887bfeeae90SHong Zhang b->i[0] = 0; 3888ad540459SPierre Jolivet for (i = 1; i < B->rmap->n + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1]; 3889396832f4SHong Zhang if (B->structure_only) { 3890396832f4SHong Zhang b->singlemalloc = PETSC_FALSE; 3891396832f4SHong Zhang b->free_a = PETSC_FALSE; 3892396832f4SHong Zhang } else { 3893273d9f13SBarry Smith b->singlemalloc = PETSC_TRUE; 3894e6b907acSBarry Smith b->free_a = PETSC_TRUE; 3895396832f4SHong Zhang } 3896e6b907acSBarry Smith b->free_ij = PETSC_TRUE; 3897c461c341SBarry Smith } else { 3898e6b907acSBarry Smith b->free_a = PETSC_FALSE; 3899e6b907acSBarry Smith b->free_ij = PETSC_FALSE; 3900c461c341SBarry Smith } 3901273d9f13SBarry Smith 3902846b4da1SFande Kong if (b->ipre && nnz != b->ipre && b->imax) { 3903846b4da1SFande Kong /* reserve user-requested sparsity */ 39049566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->ipre, b->imax, B->rmap->n)); 3905846b4da1SFande Kong } 3906846b4da1SFande Kong 3907273d9f13SBarry Smith b->nz = 0; 3908273d9f13SBarry Smith b->maxnz = nz; 3909273d9f13SBarry Smith B->info.nz_unneeded = (double)b->maxnz; 39101baa6e33SBarry Smith if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 3911cb7b82ddSBarry Smith B->was_assembled = PETSC_FALSE; 3912cb7b82ddSBarry Smith B->assembled = PETSC_FALSE; 39135519a089SJose E. Roman /* We simply deem preallocation has changed nonzero state. Updating the state 39145519a089SJose E. Roman will give clients (like AIJKokkos) a chance to know something has happened. 39155519a089SJose E. Roman */ 39165519a089SJose E. Roman B->nonzerostate++; 3917273d9f13SBarry Smith PetscFunctionReturn(0); 3918273d9f13SBarry Smith } 3919273d9f13SBarry Smith 39209371c9d4SSatish Balay PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A) { 3921846b4da1SFande Kong Mat_SeqAIJ *a; 3922a5bbaf83SFande Kong PetscInt i; 3923846b4da1SFande Kong 3924846b4da1SFande Kong PetscFunctionBegin; 3925846b4da1SFande Kong PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 392614d0e64fSAlex Lindsay 392714d0e64fSAlex Lindsay /* Check local size. If zero, then return */ 392814d0e64fSAlex Lindsay if (!A->rmap->n) PetscFunctionReturn(0); 392914d0e64fSAlex Lindsay 3930846b4da1SFande Kong a = (Mat_SeqAIJ *)A->data; 39312c814fdeSFande Kong /* if no saved info, we error out */ 393228b400f6SJacob Faibussowitsch PetscCheck(a->ipre, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "No saved preallocation info "); 39332c814fdeSFande Kong 3934aed4548fSBarry 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 "); 39352c814fdeSFande Kong 39369566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->imax, a->ipre, A->rmap->n)); 39379566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(a->ilen, A->rmap->n)); 3938846b4da1SFande Kong a->i[0] = 0; 3939ad540459SPierre Jolivet for (i = 1; i < A->rmap->n + 1; i++) a->i[i] = a->i[i - 1] + a->imax[i - 1]; 3940846b4da1SFande Kong A->preallocated = PETSC_TRUE; 3941846b4da1SFande Kong a->nz = 0; 3942846b4da1SFande Kong a->maxnz = a->i[A->rmap->n]; 3943846b4da1SFande Kong A->info.nz_unneeded = (double)a->maxnz; 3944846b4da1SFande Kong A->was_assembled = PETSC_FALSE; 3945846b4da1SFande Kong A->assembled = PETSC_FALSE; 3946846b4da1SFande Kong PetscFunctionReturn(0); 3947846b4da1SFande Kong } 3948846b4da1SFande Kong 394958d36128SBarry Smith /*@ 395011a5261eSBarry Smith MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in `MATSEQAIJ` format. 3951a1661176SMatthew Knepley 3952a1661176SMatthew Knepley Input Parameters: 3953a1661176SMatthew Knepley + B - the matrix 3954a1661176SMatthew Knepley . i - the indices into j for the start of each row (starts with zero) 3955a1661176SMatthew Knepley . j - the column indices for each row (starts with zero) these must be sorted for each row 3956a1661176SMatthew Knepley - v - optional values in the matrix 3957a1661176SMatthew Knepley 3958a1661176SMatthew Knepley Level: developer 3959a1661176SMatthew Knepley 39606a9b8d82SBarry Smith Notes: 396111a5261eSBarry Smith The i,j,v values are COPIED with this routine; to avoid the copy use `MatCreateSeqAIJWithArrays()` 396258d36128SBarry Smith 39636a9b8d82SBarry Smith This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero 39646a9b8d82SBarry Smith structure will be the union of all the previous nonzero structures. 39656a9b8d82SBarry Smith 39666a9b8d82SBarry Smith Developer Notes: 39676a9b8d82SBarry 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 396811a5261eSBarry Smith then just copies the v values directly with `PetscMemcpy()`. 39696a9b8d82SBarry Smith 397011a5261eSBarry Smith This routine could also take a `PetscCopyMode` argument to allow sharing the values instead of always copying them. 39716a9b8d82SBarry Smith 3972db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatSeqAIJSetPreallocation()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MatResetPreallocation()` 3973a1661176SMatthew Knepley @*/ 39749371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B, const PetscInt i[], const PetscInt j[], const PetscScalar v[]) { 3975a1661176SMatthew Knepley PetscFunctionBegin; 39760700a824SBarry Smith PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 39776ba663aaSJed Brown PetscValidType(B, 1); 3978cac4c232SBarry Smith PetscTryMethod(B, "MatSeqAIJSetPreallocationCSR_C", (Mat, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, i, j, v)); 3979a1661176SMatthew Knepley PetscFunctionReturn(0); 3980a1661176SMatthew Knepley } 3981a1661176SMatthew Knepley 39829371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B, const PetscInt Ii[], const PetscInt J[], const PetscScalar v[]) { 3983a1661176SMatthew Knepley PetscInt i; 3984a1661176SMatthew Knepley PetscInt m, n; 3985a1661176SMatthew Knepley PetscInt nz; 39866a9b8d82SBarry Smith PetscInt *nnz; 3987a1661176SMatthew Knepley 3988a1661176SMatthew Knepley PetscFunctionBegin; 3989aed4548fSBarry Smith PetscCheck(Ii[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]); 3990779a8d59SSatish Balay 39919566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 39929566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 3993779a8d59SSatish Balay 39949566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &m, &n)); 39959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nnz)); 3996a1661176SMatthew Knepley for (i = 0; i < m; i++) { 3997b7940d39SSatish Balay nz = Ii[i + 1] - Ii[i]; 399808401ef6SPierre 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); 3999a1661176SMatthew Knepley nnz[i] = nz; 4000a1661176SMatthew Knepley } 40019566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz)); 40029566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 4003a1661176SMatthew Knepley 400448a46eb9SPierre 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)); 4005a1661176SMatthew Knepley 40069566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 40079566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4008a1661176SMatthew Knepley 40099566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 4010a1661176SMatthew Knepley PetscFunctionReturn(0); 4011a1661176SMatthew Knepley } 4012a1661176SMatthew Knepley 4013ad7e164aSPierre Jolivet /*@ 4014ad7e164aSPierre Jolivet MatSeqAIJKron - Computes C, the Kronecker product of A and B. 4015ad7e164aSPierre Jolivet 4016ad7e164aSPierre Jolivet Input Parameters: 4017ad7e164aSPierre Jolivet + A - left-hand side matrix 4018ad7e164aSPierre Jolivet . B - right-hand side matrix 401911a5261eSBarry Smith - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 4020ad7e164aSPierre Jolivet 4021ad7e164aSPierre Jolivet Output Parameter: 4022ad7e164aSPierre Jolivet . C - Kronecker product of A and B 4023ad7e164aSPierre Jolivet 4024ad7e164aSPierre Jolivet Level: intermediate 4025ad7e164aSPierre Jolivet 402611a5261eSBarry Smith Note: 402711a5261eSBarry 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()`. 4028ad7e164aSPierre Jolivet 4029db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATKAIJ`, `MatReuse` 4030ad7e164aSPierre Jolivet @*/ 40319371c9d4SSatish Balay PetscErrorCode MatSeqAIJKron(Mat A, Mat B, MatReuse reuse, Mat *C) { 4032ad7e164aSPierre Jolivet PetscFunctionBegin; 4033ad7e164aSPierre Jolivet PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4034ad7e164aSPierre Jolivet PetscValidType(A, 1); 4035ad7e164aSPierre Jolivet PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4036ad7e164aSPierre Jolivet PetscValidType(B, 2); 4037ad7e164aSPierre Jolivet PetscValidPointer(C, 4); 4038ad7e164aSPierre Jolivet if (reuse == MAT_REUSE_MATRIX) { 4039ad7e164aSPierre Jolivet PetscValidHeaderSpecific(*C, MAT_CLASSID, 4); 4040ad7e164aSPierre Jolivet PetscValidType(*C, 4); 4041ad7e164aSPierre Jolivet } 4042cac4c232SBarry Smith PetscTryMethod(A, "MatSeqAIJKron_C", (Mat, Mat, MatReuse, Mat *), (A, B, reuse, C)); 4043ad7e164aSPierre Jolivet PetscFunctionReturn(0); 4044ad7e164aSPierre Jolivet } 4045ad7e164aSPierre Jolivet 40469371c9d4SSatish Balay PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A, Mat B, MatReuse reuse, Mat *C) { 4047ad7e164aSPierre Jolivet Mat newmat; 4048ad7e164aSPierre Jolivet Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 4049ad7e164aSPierre Jolivet Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 4050ad7e164aSPierre Jolivet PetscScalar *v; 4051fff043a9SJunchao Zhang const PetscScalar *aa, *ba; 4052ad7e164aSPierre 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; 4053ad7e164aSPierre Jolivet PetscBool flg; 4054ad7e164aSPierre Jolivet 4055ad7e164aSPierre Jolivet PetscFunctionBegin; 405628b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 405728b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 405828b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 405928b400f6SJacob Faibussowitsch PetscCheck(B->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 40609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATSEQAIJ, &flg)); 406128b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatType %s", ((PetscObject)B)->type_name); 4062aed4548fSBarry Smith PetscCheck(reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatReuse %d", (int)reuse); 4063ad7e164aSPierre Jolivet if (reuse == MAT_INITIAL_MATRIX) { 40649566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(am * bm + 1, &i, a->i[am] * b->i[bm], &j)); 40659566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &newmat)); 40669566063dSJacob Faibussowitsch PetscCall(MatSetSizes(newmat, am * bm, an * bn, am * bm, an * bn)); 40679566063dSJacob Faibussowitsch PetscCall(MatSetType(newmat, MATAIJ)); 4068ad7e164aSPierre Jolivet i[0] = 0; 4069ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4070ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4071ad7e164aSPierre Jolivet i[m * bm + p + 1] = i[m * bm + p] + (a->i[m + 1] - a->i[m]) * (b->i[p + 1] - b->i[p]); 4072ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m + 1]; ++n) { 4073ad540459SPierre Jolivet for (q = b->i[p]; q < b->i[p + 1]; ++q) j[nnz++] = a->j[n] * bn + b->j[q]; 4074ad7e164aSPierre Jolivet } 4075ad7e164aSPierre Jolivet } 4076ad7e164aSPierre Jolivet } 40779566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(newmat, i, j, NULL)); 4078ad7e164aSPierre Jolivet *C = newmat; 40799566063dSJacob Faibussowitsch PetscCall(PetscFree2(i, j)); 4080ad7e164aSPierre Jolivet nnz = 0; 4081ad7e164aSPierre Jolivet } 40829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(*C, &v)); 40839566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 40849566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &ba)); 4085ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4086ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4087ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m + 1]; ++n) { 4088ad540459SPierre Jolivet for (q = b->i[p]; q < b->i[p + 1]; ++q) v[nnz++] = aa[n] * ba[q]; 4089ad7e164aSPierre Jolivet } 4090ad7e164aSPierre Jolivet } 4091ad7e164aSPierre Jolivet } 40929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(*C, &v)); 40939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 40949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &ba)); 4095ad7e164aSPierre Jolivet PetscFunctionReturn(0); 4096ad7e164aSPierre Jolivet } 4097ad7e164aSPierre Jolivet 4098c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h> 4099af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h> 4100170fe5c8SBarry Smith 4101170fe5c8SBarry Smith /* 4102170fe5c8SBarry Smith Computes (B'*A')' since computing B*A directly is untenable 4103170fe5c8SBarry Smith 4104170fe5c8SBarry Smith n p p 41052da392ccSBarry Smith [ ] [ ] [ ] 41062da392ccSBarry Smith m [ A ] * n [ B ] = m [ C ] 41072da392ccSBarry Smith [ ] [ ] [ ] 4108170fe5c8SBarry Smith 4109170fe5c8SBarry Smith */ 41109371c9d4SSatish Balay PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A, Mat B, Mat C) { 4111170fe5c8SBarry Smith Mat_SeqDense *sub_a = (Mat_SeqDense *)A->data; 4112170fe5c8SBarry Smith Mat_SeqAIJ *sub_b = (Mat_SeqAIJ *)B->data; 4113170fe5c8SBarry Smith Mat_SeqDense *sub_c = (Mat_SeqDense *)C->data; 411486214ceeSStefano Zampini PetscInt i, j, n, m, q, p; 4115170fe5c8SBarry Smith const PetscInt *ii, *idx; 4116170fe5c8SBarry Smith const PetscScalar *b, *a, *a_q; 4117170fe5c8SBarry Smith PetscScalar *c, *c_q; 411886214ceeSStefano Zampini PetscInt clda = sub_c->lda; 411986214ceeSStefano Zampini PetscInt alda = sub_a->lda; 4120170fe5c8SBarry Smith 4121170fe5c8SBarry Smith PetscFunctionBegin; 4122d0f46423SBarry Smith m = A->rmap->n; 4123d0f46423SBarry Smith n = A->cmap->n; 4124d0f46423SBarry Smith p = B->cmap->n; 4125170fe5c8SBarry Smith a = sub_a->v; 4126170fe5c8SBarry Smith b = sub_b->a; 4127170fe5c8SBarry Smith c = sub_c->v; 412886214ceeSStefano Zampini if (clda == m) { 41299566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c, m * p)); 413086214ceeSStefano Zampini } else { 413186214ceeSStefano Zampini for (j = 0; j < p; j++) 41329371c9d4SSatish Balay for (i = 0; i < m; i++) c[j * clda + i] = 0.0; 413386214ceeSStefano Zampini } 4134170fe5c8SBarry Smith ii = sub_b->i; 4135170fe5c8SBarry Smith idx = sub_b->j; 4136170fe5c8SBarry Smith for (i = 0; i < n; i++) { 4137170fe5c8SBarry Smith q = ii[i + 1] - ii[i]; 4138170fe5c8SBarry Smith while (q-- > 0) { 413986214ceeSStefano Zampini c_q = c + clda * (*idx); 414086214ceeSStefano Zampini a_q = a + alda * i; 4141854c7f52SBarry Smith PetscKernelAXPY(c_q, *b, a_q, m); 4142170fe5c8SBarry Smith idx++; 4143170fe5c8SBarry Smith b++; 4144170fe5c8SBarry Smith } 4145170fe5c8SBarry Smith } 4146170fe5c8SBarry Smith PetscFunctionReturn(0); 4147170fe5c8SBarry Smith } 4148170fe5c8SBarry Smith 41499371c9d4SSatish Balay PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A, Mat B, PetscReal fill, Mat C) { 4150d0f46423SBarry Smith PetscInt m = A->rmap->n, n = B->cmap->n; 415186214ceeSStefano Zampini PetscBool cisdense; 4152170fe5c8SBarry Smith 4153170fe5c8SBarry Smith PetscFunctionBegin; 415408401ef6SPierre 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); 41559566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, m, n)); 41569566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, B)); 41579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, "")); 415848a46eb9SPierre Jolivet if (!cisdense) PetscCall(MatSetType(C, MATDENSE)); 41599566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 4160d73949e8SHong Zhang 41614222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ; 4162170fe5c8SBarry Smith PetscFunctionReturn(0); 4163170fe5c8SBarry Smith } 4164170fe5c8SBarry Smith 4165170fe5c8SBarry Smith /* ----------------------------------------------------------------*/ 41660bad9183SKris Buschelman /*MC 4167fafad747SKris Buschelman MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 41680bad9183SKris Buschelman based on compressed sparse row format. 41690bad9183SKris Buschelman 41700bad9183SKris Buschelman Options Database Keys: 41710bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 41720bad9183SKris Buschelman 41730bad9183SKris Buschelman Level: beginner 41740bad9183SKris Buschelman 41750cd7f59aSBarry Smith Notes: 417611a5261eSBarry Smith `MatSetValues()` may be called for this matrix type with a NULL argument for the numerical values, 41770cd7f59aSBarry Smith in this case the values associated with the rows and columns one passes in are set to zero 41780cd7f59aSBarry Smith in the matrix 41790cd7f59aSBarry Smith 418011a5261eSBarry Smith `MatSetOptions`(,`MAT_STRUCTURE_ONLY`,`PETSC_TRUE`) may be called for this matrix type. In this no 418111a5261eSBarry Smith space is allocated for the nonzero entries and any entries passed with `MatSetValues()` are ignored 41820cd7f59aSBarry Smith 418311a5261eSBarry Smith Developer Note: 41840cd7f59aSBarry Smith It would be nice if all matrix formats supported passing NULL in for the numerical values 41850cd7f59aSBarry Smith 4186db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MatSetFromOptions()`, `MatSetType()`, `MatCreate()`, `MatType`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 41870bad9183SKris Buschelman M*/ 41880bad9183SKris Buschelman 4189ccd284c7SBarry Smith /*MC 4190ccd284c7SBarry Smith MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 4191ccd284c7SBarry Smith 419211a5261eSBarry Smith This matrix type is identical to `MATSEQAIJ` when constructed with a single process communicator, 419311a5261eSBarry Smith and `MATMPIAIJ` otherwise. As a result, for single process communicators, 419411a5261eSBarry Smith `MatSeqAIJSetPreallocation()` is supported, and similarly `MatMPIAIJSetPreallocation()` is supported 4195ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4196ccd284c7SBarry Smith the above preallocation routines for simplicity. 4197ccd284c7SBarry Smith 4198ccd284c7SBarry Smith Options Database Keys: 419911a5261eSBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to `MatSetFromOptions()` 4200ccd284c7SBarry Smith 420111a5261eSBarry Smith Note: 420211a5261eSBarry Smith Subclasses include `MATAIJCUSPARSE`, `MATAIJPERM`, `MATAIJSELL`, `MATAIJMKL`, `MATAIJCRL`, and also automatically switches over to use inodes when 4203ccd284c7SBarry Smith enough exist. 4204ccd284c7SBarry Smith 4205ccd284c7SBarry Smith Level: beginner 4206ccd284c7SBarry Smith 4207db781477SPatrick Sanan .seealso: `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATMPIAIJ`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 4208ccd284c7SBarry Smith M*/ 4209ccd284c7SBarry Smith 4210ccd284c7SBarry Smith /*MC 4211ccd284c7SBarry Smith MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 4212ccd284c7SBarry Smith 421311a5261eSBarry Smith This matrix type is identical to `MATSEQAIJCRL` when constructed with a single process communicator, 421411a5261eSBarry Smith and `MATMPIAIJCRL` otherwise. As a result, for single process communicators, 421511a5261eSBarry Smith `MatSeqAIJSetPreallocation()` is supported, and similarly `MatMPIAIJSetPreallocation()` is supported 4216ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4217ccd284c7SBarry Smith the above preallocation routines for simplicity. 4218ccd284c7SBarry Smith 4219ccd284c7SBarry Smith Options Database Keys: 422011a5261eSBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to `MatSetFromOptions()` 4221ccd284c7SBarry Smith 4222ccd284c7SBarry Smith Level: beginner 4223ccd284c7SBarry Smith 4224c2e3fba1SPatrick Sanan .seealso: `MatCreateMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL` 4225ccd284c7SBarry Smith M*/ 4226ccd284c7SBarry Smith 42277906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat, MatType, MatReuse, Mat *); 42287906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 42297906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat, MatType, MatReuse, Mat *); 42307906f579SHong Zhang #endif 4231d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 4232d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat, MatType, MatReuse, Mat *); 4233d24d4204SJose E. Roman #endif 42347906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE) 42357906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType, MatReuse, Mat *); 42367906f579SHong Zhang #endif 42377906f579SHong Zhang 4238d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat, MatType, MatReuse, Mat *); 4239c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat, MatType, MatReuse, Mat *); 42404222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat); 42417906f579SHong Zhang 42428c778c55SBarry Smith /*@C 424311a5261eSBarry Smith MatSeqAIJGetArray - gives read/write access to the array where the data for a `MATSEQAIJ` matrix is stored 42448c778c55SBarry Smith 42458c778c55SBarry Smith Not Collective 42468c778c55SBarry Smith 42478c778c55SBarry Smith Input Parameter: 424811a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 42498c778c55SBarry Smith 42508c778c55SBarry Smith Output Parameter: 42518c778c55SBarry Smith . array - pointer to the data 42528c778c55SBarry Smith 42538c778c55SBarry Smith Level: intermediate 42548c778c55SBarry Smith 4255db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()` 42568c778c55SBarry Smith @*/ 42579371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArray(Mat A, PetscScalar **array) { 4258d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 42598c778c55SBarry Smith 42608c778c55SBarry Smith PetscFunctionBegin; 4261d67d9f35SJunchao Zhang if (aij->ops->getarray) { 42629566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarray)(A, array)); 4263d67d9f35SJunchao Zhang } else { 4264d67d9f35SJunchao Zhang *array = aij->a; 4265d67d9f35SJunchao Zhang } 4266d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4267d67d9f35SJunchao Zhang } 4268d67d9f35SJunchao Zhang 4269d67d9f35SJunchao Zhang /*@C 427011a5261eSBarry Smith MatSeqAIJRestoreArray - returns access to the array where the data for a `MATSEQAIJ` matrix is stored obtained by `MatSeqAIJGetArray()` 4271d67d9f35SJunchao Zhang 4272d67d9f35SJunchao Zhang Not Collective 4273d67d9f35SJunchao Zhang 4274d67d9f35SJunchao Zhang Input Parameters: 427511a5261eSBarry Smith + mat - a `MATSEQAIJ` matrix 4276d67d9f35SJunchao Zhang - array - pointer to the data 4277d67d9f35SJunchao Zhang 4278d67d9f35SJunchao Zhang Level: intermediate 4279d67d9f35SJunchao Zhang 4280db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayF90()` 4281d67d9f35SJunchao Zhang @*/ 42829371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArray(Mat A, PetscScalar **array) { 4283d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4284d67d9f35SJunchao Zhang 4285d67d9f35SJunchao Zhang PetscFunctionBegin; 4286d67d9f35SJunchao Zhang if (aij->ops->restorearray) { 42879566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearray)(A, array)); 4288d67d9f35SJunchao Zhang } else { 4289d67d9f35SJunchao Zhang *array = NULL; 4290d67d9f35SJunchao Zhang } 42919566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 42929566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 42938c778c55SBarry Smith PetscFunctionReturn(0); 42948c778c55SBarry Smith } 42958c778c55SBarry Smith 429621e72a00SBarry Smith /*@C 429711a5261eSBarry Smith MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a `MATSEQAIJ` matrix is stored 42988f1ea47aSStefano Zampini 42998f1ea47aSStefano Zampini Not Collective 43008f1ea47aSStefano Zampini 43018f1ea47aSStefano Zampini Input Parameter: 430211a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 43038f1ea47aSStefano Zampini 43048f1ea47aSStefano Zampini Output Parameter: 43058f1ea47aSStefano Zampini . array - pointer to the data 43068f1ea47aSStefano Zampini 43078f1ea47aSStefano Zampini Level: intermediate 43088f1ea47aSStefano Zampini 4309db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 43108f1ea47aSStefano Zampini @*/ 43119371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArrayRead(Mat A, const PetscScalar **array) { 4312d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 43138f1ea47aSStefano Zampini 43148f1ea47aSStefano Zampini PetscFunctionBegin; 4315d67d9f35SJunchao Zhang if (aij->ops->getarrayread) { 43169566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarrayread)(A, array)); 4317d67d9f35SJunchao Zhang } else { 4318d67d9f35SJunchao Zhang *array = aij->a; 4319d67d9f35SJunchao Zhang } 43208f1ea47aSStefano Zampini PetscFunctionReturn(0); 43218f1ea47aSStefano Zampini } 43228f1ea47aSStefano Zampini 43238f1ea47aSStefano Zampini /*@C 432411a5261eSBarry Smith MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from `MatSeqAIJGetArrayRead()` 43258f1ea47aSStefano Zampini 43268f1ea47aSStefano Zampini Not Collective 43278f1ea47aSStefano Zampini 43288f1ea47aSStefano Zampini Input Parameter: 432911a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 43308f1ea47aSStefano Zampini 43318f1ea47aSStefano Zampini Output Parameter: 43328f1ea47aSStefano Zampini . array - pointer to the data 43338f1ea47aSStefano Zampini 43348f1ea47aSStefano Zampini Level: intermediate 43358f1ea47aSStefano Zampini 4336db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 43378f1ea47aSStefano Zampini @*/ 43389371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArrayRead(Mat A, const PetscScalar **array) { 4339d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 43408f1ea47aSStefano Zampini 43418f1ea47aSStefano Zampini PetscFunctionBegin; 4342d67d9f35SJunchao Zhang if (aij->ops->restorearrayread) { 43439566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearrayread)(A, array)); 4344d67d9f35SJunchao Zhang } else { 4345d67d9f35SJunchao Zhang *array = NULL; 4346d67d9f35SJunchao Zhang } 4347d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4348d67d9f35SJunchao Zhang } 4349d67d9f35SJunchao Zhang 4350d67d9f35SJunchao Zhang /*@C 435111a5261eSBarry Smith MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a `MATSEQAIJ` matrix is stored 4352d67d9f35SJunchao Zhang 4353d67d9f35SJunchao Zhang Not Collective 4354d67d9f35SJunchao Zhang 4355d67d9f35SJunchao Zhang Input Parameter: 435611a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 4357d67d9f35SJunchao Zhang 4358d67d9f35SJunchao Zhang Output Parameter: 4359d67d9f35SJunchao Zhang . array - pointer to the data 4360d67d9f35SJunchao Zhang 4361d67d9f35SJunchao Zhang Level: intermediate 4362d67d9f35SJunchao Zhang 4363db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 4364d67d9f35SJunchao Zhang @*/ 43659371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArrayWrite(Mat A, PetscScalar **array) { 4366d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4367d67d9f35SJunchao Zhang 4368d67d9f35SJunchao Zhang PetscFunctionBegin; 4369d67d9f35SJunchao Zhang if (aij->ops->getarraywrite) { 43709566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarraywrite)(A, array)); 4371d67d9f35SJunchao Zhang } else { 4372d67d9f35SJunchao Zhang *array = aij->a; 4373d67d9f35SJunchao Zhang } 43749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 43759566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 4376d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4377d67d9f35SJunchao Zhang } 4378d67d9f35SJunchao Zhang 4379d67d9f35SJunchao Zhang /*@C 4380d67d9f35SJunchao Zhang MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead 4381d67d9f35SJunchao Zhang 4382d67d9f35SJunchao Zhang Not Collective 4383d67d9f35SJunchao Zhang 4384d67d9f35SJunchao Zhang Input Parameter: 4385d67d9f35SJunchao Zhang . mat - a MATSEQAIJ matrix 4386d67d9f35SJunchao Zhang 4387d67d9f35SJunchao Zhang Output Parameter: 4388d67d9f35SJunchao Zhang . array - pointer to the data 4389d67d9f35SJunchao Zhang 4390d67d9f35SJunchao Zhang Level: intermediate 4391d67d9f35SJunchao Zhang 4392db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 4393d67d9f35SJunchao Zhang @*/ 43949371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArrayWrite(Mat A, PetscScalar **array) { 4395d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4396d67d9f35SJunchao Zhang 4397d67d9f35SJunchao Zhang PetscFunctionBegin; 4398d67d9f35SJunchao Zhang if (aij->ops->restorearraywrite) { 43999566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearraywrite)(A, array)); 4400d67d9f35SJunchao Zhang } else { 4401d67d9f35SJunchao Zhang *array = NULL; 4402d67d9f35SJunchao Zhang } 44038f1ea47aSStefano Zampini PetscFunctionReturn(0); 44048f1ea47aSStefano Zampini } 44058f1ea47aSStefano Zampini 44068f1ea47aSStefano Zampini /*@C 440711a5261eSBarry Smith MatSeqAIJGetCSRAndMemType - Get the CSR arrays and the memory type of the `MATSEQAIJ` matrix 44087ee59b9bSJunchao Zhang 44097ee59b9bSJunchao Zhang Not Collective 44107ee59b9bSJunchao Zhang 44117ee59b9bSJunchao Zhang Input Parameter: 441211a5261eSBarry Smith . mat - a matrix of type `MATSEQAIJ` or its subclasses 44137ee59b9bSJunchao Zhang 44147ee59b9bSJunchao Zhang Output Parameters: 44157ee59b9bSJunchao Zhang + i - row map array of the matrix 44167ee59b9bSJunchao Zhang . j - column index array of the matrix 44177ee59b9bSJunchao Zhang . a - data array of the matrix 44187ee59b9bSJunchao Zhang - memtype - memory type of the arrays 44197ee59b9bSJunchao Zhang 44207ee59b9bSJunchao Zhang Notes: 44217ee59b9bSJunchao Zhang Any of the output parameters can be NULL, in which case the corresponding value is not returned. 44227ee59b9bSJunchao Zhang If mat is a device matrix, the arrays are on the device. Otherwise, they are on the host. 44237ee59b9bSJunchao Zhang 44247ee59b9bSJunchao Zhang One can call this routine on a preallocated but not assembled matrix to just get the memory of the CSR underneath the matrix. 44257ee59b9bSJunchao Zhang If the matrix is assembled, the data array 'a' is guaranteed to have the latest values of the matrix. 44267ee59b9bSJunchao Zhang 44277ee59b9bSJunchao Zhang Level: Developer 44287ee59b9bSJunchao Zhang 4429db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 44307ee59b9bSJunchao Zhang @*/ 44319371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetCSRAndMemType(Mat mat, const PetscInt **i, const PetscInt **j, PetscScalar **a, PetscMemType *mtype) { 44327ee59b9bSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 44337ee59b9bSJunchao Zhang 44347ee59b9bSJunchao Zhang PetscFunctionBegin; 44357ee59b9bSJunchao Zhang PetscCheck(mat->preallocated, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "matrix is not preallocated"); 44367ee59b9bSJunchao Zhang if (aij->ops->getcsrandmemtype) { 44377ee59b9bSJunchao Zhang PetscCall((*aij->ops->getcsrandmemtype)(mat, i, j, a, mtype)); 44387ee59b9bSJunchao Zhang } else { 44397ee59b9bSJunchao Zhang if (i) *i = aij->i; 44407ee59b9bSJunchao Zhang if (j) *j = aij->j; 44417ee59b9bSJunchao Zhang if (a) *a = aij->a; 44427ee59b9bSJunchao Zhang if (mtype) *mtype = PETSC_MEMTYPE_HOST; 44437ee59b9bSJunchao Zhang } 44447ee59b9bSJunchao Zhang PetscFunctionReturn(0); 44457ee59b9bSJunchao Zhang } 44467ee59b9bSJunchao Zhang 44477ee59b9bSJunchao Zhang /*@C 444821e72a00SBarry Smith MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row 444921e72a00SBarry Smith 445021e72a00SBarry Smith Not Collective 445121e72a00SBarry Smith 445221e72a00SBarry Smith Input Parameter: 445311a5261eSBarry Smith . mat - a `MATSEQAIJ` matrix 445421e72a00SBarry Smith 445521e72a00SBarry Smith Output Parameter: 445621e72a00SBarry Smith . nz - the maximum number of nonzeros in any row 445721e72a00SBarry Smith 445821e72a00SBarry Smith Level: intermediate 445921e72a00SBarry Smith 4460db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()` 446121e72a00SBarry Smith @*/ 44629371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetMaxRowNonzeros(Mat A, PetscInt *nz) { 446321e72a00SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 446421e72a00SBarry Smith 446521e72a00SBarry Smith PetscFunctionBegin; 446621e72a00SBarry Smith *nz = aij->rmax; 446721e72a00SBarry Smith PetscFunctionReturn(0); 446821e72a00SBarry Smith } 446921e72a00SBarry Smith 44709371c9d4SSatish Balay PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[]) { 4471394ed5ebSJunchao Zhang MPI_Comm comm; 4472394ed5ebSJunchao Zhang PetscInt *i, *j; 4473394ed5ebSJunchao Zhang PetscInt M, N, row; 4474394ed5ebSJunchao Zhang PetscCount k, p, q, nneg, nnz, start, end; /* Index the coo array, so use PetscCount as their type */ 4475394ed5ebSJunchao Zhang PetscInt *Ai; /* Change to PetscCount once we use it for row pointers */ 4476394ed5ebSJunchao Zhang PetscInt *Aj; 4477394ed5ebSJunchao Zhang PetscScalar *Aa; 4478cbc6b225SStefano Zampini Mat_SeqAIJ *seqaij = (Mat_SeqAIJ *)(mat->data); 4479cbc6b225SStefano Zampini MatType rtype; 4480394ed5ebSJunchao Zhang PetscCount *perm, *jmap; 4481394ed5ebSJunchao Zhang 4482394ed5ebSJunchao Zhang PetscFunctionBegin; 44839566063dSJacob Faibussowitsch PetscCall(MatResetPreallocationCOO_SeqAIJ(mat)); 44849566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 44859566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &M, &N)); 4486e8729f6fSJunchao Zhang i = coo_i; 4487e8729f6fSJunchao Zhang j = coo_j; 44889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n, &perm)); 4489394ed5ebSJunchao Zhang for (k = 0; k < coo_n; k++) { /* Ignore entries with negative row or col indices */ 4490394ed5ebSJunchao Zhang if (j[k] < 0) i[k] = -1; 4491394ed5ebSJunchao Zhang perm[k] = k; 4492394ed5ebSJunchao Zhang } 4493394ed5ebSJunchao Zhang 4494394ed5ebSJunchao Zhang /* Sort by row */ 44959566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithIntCountArrayPair(coo_n, i, j, perm)); 44969371c9d4SSatish Balay for (k = 0; k < coo_n; k++) { 44979371c9d4SSatish Balay if (i[k] >= 0) break; 44989371c9d4SSatish Balay } /* Advance k to the first row with a non-negative index */ 4499394ed5ebSJunchao Zhang nneg = k; 45009566063dSJacob 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 */ 4501394ed5ebSJunchao Zhang nnz = 0; /* Total number of unique nonzeros to be counted */ 4502394ed5ebSJunchao Zhang jmap++; /* Inc jmap by 1 for convinience */ 4503394ed5ebSJunchao Zhang 45049566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(M + 1, &Ai)); /* CSR of A */ 45059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n - nneg, &Aj)); /* We have at most coo_n-nneg unique nonzeros */ 4506394ed5ebSJunchao Zhang 4507394ed5ebSJunchao Zhang /* In each row, sort by column, then unique column indices to get row length */ 4508394ed5ebSJunchao Zhang Ai++; /* Inc by 1 for convinience */ 4509394ed5ebSJunchao Zhang q = 0; /* q-th unique nonzero, with q starting from 0 */ 4510394ed5ebSJunchao Zhang while (k < coo_n) { 4511394ed5ebSJunchao Zhang row = i[k]; 4512394ed5ebSJunchao Zhang start = k; /* [start,end) indices for this row */ 4513394ed5ebSJunchao Zhang while (k < coo_n && i[k] == row) k++; 4514394ed5ebSJunchao Zhang end = k; 45159566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithCountArray(end - start, j + start, perm + start)); 4516394ed5ebSJunchao Zhang /* Find number of unique col entries in this row */ 4517394ed5ebSJunchao Zhang Aj[q] = j[start]; /* Log the first nonzero in this row */ 4518394ed5ebSJunchao Zhang jmap[q] = 1; /* Number of repeats of this nozero entry */ 4519394ed5ebSJunchao Zhang Ai[row] = 1; 4520394ed5ebSJunchao Zhang nnz++; 4521394ed5ebSJunchao Zhang 4522394ed5ebSJunchao Zhang for (p = start + 1; p < end; p++) { /* Scan remaining nonzero in this row */ 4523394ed5ebSJunchao Zhang if (j[p] != j[p - 1]) { /* Meet a new nonzero */ 4524394ed5ebSJunchao Zhang q++; 4525394ed5ebSJunchao Zhang jmap[q] = 1; 4526394ed5ebSJunchao Zhang Aj[q] = j[p]; 4527394ed5ebSJunchao Zhang Ai[row]++; 4528394ed5ebSJunchao Zhang nnz++; 4529394ed5ebSJunchao Zhang } else { 4530394ed5ebSJunchao Zhang jmap[q]++; 4531394ed5ebSJunchao Zhang } 4532394ed5ebSJunchao Zhang } 4533394ed5ebSJunchao Zhang q++; /* Move to next row and thus next unique nonzero */ 4534394ed5ebSJunchao Zhang } 4535394ed5ebSJunchao Zhang 4536394ed5ebSJunchao Zhang Ai--; /* Back to the beginning of Ai[] */ 4537394ed5ebSJunchao Zhang for (k = 0; k < M; k++) Ai[k + 1] += Ai[k]; 4538394ed5ebSJunchao Zhang jmap--; /* Back to the beginning of jmap[] */ 4539394ed5ebSJunchao Zhang jmap[0] = 0; 4540394ed5ebSJunchao Zhang for (k = 0; k < nnz; k++) jmap[k + 1] += jmap[k]; 4541394ed5ebSJunchao Zhang if (nnz < coo_n - nneg) { /* Realloc with actual number of unique nonzeros */ 4542394ed5ebSJunchao Zhang PetscCount *jmap_new; 4543394ed5ebSJunchao Zhang PetscInt *Aj_new; 4544394ed5ebSJunchao Zhang 45459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz + 1, &jmap_new)); 45469566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(jmap_new, jmap, nnz + 1)); 45479566063dSJacob Faibussowitsch PetscCall(PetscFree(jmap)); 4548394ed5ebSJunchao Zhang jmap = jmap_new; 4549394ed5ebSJunchao Zhang 45509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &Aj_new)); 45519566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(Aj_new, Aj, nnz)); 45529566063dSJacob Faibussowitsch PetscCall(PetscFree(Aj)); 4553394ed5ebSJunchao Zhang Aj = Aj_new; 4554394ed5ebSJunchao Zhang } 4555394ed5ebSJunchao Zhang 4556394ed5ebSJunchao Zhang if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */ 4557394ed5ebSJunchao Zhang PetscCount *perm_new; 4558cbc6b225SStefano Zampini 45599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n - nneg, &perm_new)); 45609566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(perm_new, perm + nneg, coo_n - nneg)); 45619566063dSJacob Faibussowitsch PetscCall(PetscFree(perm)); 4562394ed5ebSJunchao Zhang perm = perm_new; 4563394ed5ebSJunchao Zhang } 4564394ed5ebSJunchao Zhang 45659566063dSJacob Faibussowitsch PetscCall(MatGetRootType_Private(mat, &rtype)); 45669566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nnz, &Aa)); /* Zero the matrix */ 45679566063dSJacob Faibussowitsch PetscCall(MatSetSeqAIJWithArrays_private(PETSC_COMM_SELF, M, N, Ai, Aj, Aa, rtype, mat)); 4568394ed5ebSJunchao Zhang 4569394ed5ebSJunchao Zhang seqaij->singlemalloc = PETSC_FALSE; /* Ai, Aj and Aa are not allocated in one big malloc */ 4570394ed5ebSJunchao Zhang seqaij->free_a = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */ 4571394ed5ebSJunchao Zhang /* Record COO fields */ 4572394ed5ebSJunchao Zhang seqaij->coo_n = coo_n; 4573394ed5ebSJunchao Zhang seqaij->Atot = coo_n - nneg; /* Annz is seqaij->nz, so no need to record that again */ 4574394ed5ebSJunchao Zhang seqaij->jmap = jmap; /* of length nnz+1 */ 4575394ed5ebSJunchao Zhang seqaij->perm = perm; 4576394ed5ebSJunchao Zhang PetscFunctionReturn(0); 4577394ed5ebSJunchao Zhang } 4578394ed5ebSJunchao Zhang 45799371c9d4SSatish Balay static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A, const PetscScalar v[], InsertMode imode) { 4580394ed5ebSJunchao Zhang Mat_SeqAIJ *aseq = (Mat_SeqAIJ *)A->data; 4581394ed5ebSJunchao Zhang PetscCount i, j, Annz = aseq->nz; 4582394ed5ebSJunchao Zhang PetscCount *perm = aseq->perm, *jmap = aseq->jmap; 4583394ed5ebSJunchao Zhang PetscScalar *Aa; 4584394ed5ebSJunchao Zhang 4585394ed5ebSJunchao Zhang PetscFunctionBegin; 45869566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &Aa)); 4587394ed5ebSJunchao Zhang for (i = 0; i < Annz; i++) { 4588b6c38306SJunchao Zhang PetscScalar sum = 0.0; 4589b6c38306SJunchao Zhang for (j = jmap[i]; j < jmap[i + 1]; j++) sum += v[perm[j]]; 4590b6c38306SJunchao Zhang Aa[i] = (imode == INSERT_VALUES ? 0.0 : Aa[i]) + sum; 4591394ed5ebSJunchao Zhang } 45929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &Aa)); 4593394ed5ebSJunchao Zhang PetscFunctionReturn(0); 4594394ed5ebSJunchao Zhang } 4595394ed5ebSJunchao Zhang 459634b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 45975063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat, MatType, MatReuse, Mat *); 459802fe1965SBarry Smith #endif 45993d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 46005063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat, MatType, MatReuse, Mat *); 46013d0639e7SStefano Zampini #endif 460202fe1965SBarry Smith 46039371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B) { 4604273d9f13SBarry Smith Mat_SeqAIJ *b; 460538baddfdSBarry Smith PetscMPIInt size; 4606273d9f13SBarry Smith 4607273d9f13SBarry Smith PetscFunctionBegin; 46089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size)); 460908401ef6SPierre Jolivet PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Comm must be of size 1"); 4610273d9f13SBarry Smith 46119566063dSJacob Faibussowitsch PetscCall(PetscNewLog(B, &b)); 46122205254eSKarl Rupp 4613b0a32e0cSBarry Smith B->data = (void *)b; 46142205254eSKarl Rupp 46159566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(B->ops, &MatOps_Values, sizeof(struct _MatOps))); 4616071fcb05SBarry Smith if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 46172205254eSKarl Rupp 4618f4259b30SLisandro Dalcin b->row = NULL; 4619f4259b30SLisandro Dalcin b->col = NULL; 4620f4259b30SLisandro Dalcin b->icol = NULL; 4621b810aeb4SBarry Smith b->reallocs = 0; 462236db0b34SBarry Smith b->ignorezeroentries = PETSC_FALSE; 4623f1e2ffcdSBarry Smith b->roworiented = PETSC_TRUE; 4624416022c9SBarry Smith b->nonew = 0; 4625f4259b30SLisandro Dalcin b->diag = NULL; 4626f4259b30SLisandro Dalcin b->solve_work = NULL; 4627f4259b30SLisandro Dalcin B->spptr = NULL; 4628f4259b30SLisandro Dalcin b->saved_values = NULL; 4629f4259b30SLisandro Dalcin b->idiag = NULL; 4630f4259b30SLisandro Dalcin b->mdiag = NULL; 4631f4259b30SLisandro Dalcin b->ssor_work = NULL; 463271f1c65dSBarry Smith b->omega = 1.0; 463371f1c65dSBarry Smith b->fshift = 0.0; 463471f1c65dSBarry Smith b->idiagvalid = PETSC_FALSE; 4635bbead8a2SBarry Smith b->ibdiagvalid = PETSC_FALSE; 4636a9817697SBarry Smith b->keepnonzeropattern = PETSC_FALSE; 463717ab2063SBarry Smith 46389566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ)); 4639b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE) 46409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEnginePut_C", MatlabEnginePut_SeqAIJ)); 46419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEngineGet_C", MatlabEngineGet_SeqAIJ)); 4642b3866ffcSBarry Smith #endif 46439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetColumnIndices_C", MatSeqAIJSetColumnIndices_SeqAIJ)); 46449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqAIJ)); 46459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqAIJ)); 46469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsbaij_C", MatConvert_SeqAIJ_SeqSBAIJ)); 46479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqbaij_C", MatConvert_SeqAIJ_SeqBAIJ)); 46489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijperm_C", MatConvert_SeqAIJ_SeqAIJPERM)); 46499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijsell_C", MatConvert_SeqAIJ_SeqAIJSELL)); 46509779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 46519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijmkl_C", MatConvert_SeqAIJ_SeqAIJMKL)); 4652191b95cbSRichard Tran Mills #endif 465334b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 46549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcusparse_C", MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 46559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_seqaij_C", MatProductSetFromOptions_SeqAIJ)); 46569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaijcusparse_C", MatProductSetFromOptions_SeqAIJ)); 465702fe1965SBarry Smith #endif 46583d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 46599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijkokkos_C", MatConvert_SeqAIJ_SeqAIJKokkos)); 46603d0639e7SStefano Zampini #endif 46619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcrl_C", MatConvert_SeqAIJ_SeqAIJCRL)); 4662af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 46639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_elemental_C", MatConvert_SeqAIJ_Elemental)); 4664af8000cdSHong Zhang #endif 4665d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 46669566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_scalapack_C", MatConvert_AIJ_ScaLAPACK)); 4667d24d4204SJose E. Roman #endif 466863c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 46699566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_hypre_C", MatConvert_AIJ_HYPRE)); 46709566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_transpose_seqaij_seqaij_C", MatProductSetFromOptions_Transpose_AIJ_AIJ)); 467163c07aadSStefano Zampini #endif 46729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqdense_C", MatConvert_SeqAIJ_SeqDense)); 46739566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsell_C", MatConvert_SeqAIJ_SeqSELL)); 46749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_is_C", MatConvert_XAIJ_IS)); 46759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsTranspose_C", MatIsTranspose_SeqAIJ)); 46769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsHermitianTranspose_C", MatIsTranspose_SeqAIJ)); 46779566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocation_C", MatSeqAIJSetPreallocation_SeqAIJ)); 46789566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatResetPreallocation_C", MatResetPreallocation_SeqAIJ)); 46799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocationCSR_C", MatSeqAIJSetPreallocationCSR_SeqAIJ)); 46809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatReorderForNonzeroDiagonal_C", MatReorderForNonzeroDiagonal_SeqAIJ)); 46819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_is_seqaij_C", MatProductSetFromOptions_IS_XAIJ)); 46829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqaij_C", MatProductSetFromOptions_SeqDense_SeqAIJ)); 46839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaij_C", MatProductSetFromOptions_SeqAIJ)); 46849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJKron_C", MatSeqAIJKron_SeqAIJ)); 46859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_SeqAIJ)); 46869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_SeqAIJ)); 46879566063dSJacob Faibussowitsch PetscCall(MatCreate_SeqAIJ_Inode(B)); 46889566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ)); 46899566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetTypeFromOptions(B)); /* this allows changing the matrix subtype to say MATSEQAIJPERM */ 46903a40ed3dSBarry Smith PetscFunctionReturn(0); 469117ab2063SBarry Smith } 469217ab2063SBarry Smith 4693b24902e0SBarry Smith /* 46943893b582SJunchao Zhang Given a matrix generated with MatGetFactor() duplicates all the information in A into C 4695b24902e0SBarry Smith */ 46969371c9d4SSatish Balay PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C, Mat A, MatDuplicateOption cpvalues, PetscBool mallocmatspace) { 46972a350339SBarry Smith Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data, *a = (Mat_SeqAIJ *)A->data; 4698071fcb05SBarry Smith PetscInt m = A->rmap->n, i; 469917ab2063SBarry Smith 47003a40ed3dSBarry Smith PetscFunctionBegin; 4701aed4548fSBarry Smith PetscCheck(A->assembled || cpvalues == MAT_DO_NOT_COPY_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix"); 4702273d9f13SBarry Smith 4703d5f3da31SBarry Smith C->factortype = A->factortype; 4704f4259b30SLisandro Dalcin c->row = NULL; 4705f4259b30SLisandro Dalcin c->col = NULL; 4706f4259b30SLisandro Dalcin c->icol = NULL; 47076ad4291fSHong Zhang c->reallocs = 0; 470817ab2063SBarry Smith 470969272f91SPierre Jolivet C->assembled = A->assembled; 471069272f91SPierre Jolivet C->preallocated = A->preallocated; 471117ab2063SBarry Smith 471269272f91SPierre Jolivet if (A->preallocated) { 47139566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->rmap, &C->rmap)); 47149566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->cmap, &C->cmap)); 4715eec197d1SBarry Smith 47169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &c->imax)); 47179566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->imax, a->imax, m * sizeof(PetscInt))); 47189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &c->ilen)); 47199566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->ilen, a->ilen, m * sizeof(PetscInt))); 47209566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, 2 * m * sizeof(PetscInt))); 472117ab2063SBarry Smith 472217ab2063SBarry Smith /* allocate the matrix space */ 4723f77e22a1SHong Zhang if (mallocmatspace) { 47249566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(a->i[m], &c->a, a->i[m], &c->j, m + 1, &c->i)); 47259566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, a->i[m] * (sizeof(PetscScalar) + sizeof(PetscInt)) + (m + 1) * sizeof(PetscInt))); 47262205254eSKarl Rupp 4727f1e2ffcdSBarry Smith c->singlemalloc = PETSC_TRUE; 47282205254eSKarl Rupp 47299566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->i, a->i, m + 1)); 473017ab2063SBarry Smith if (m > 0) { 47319566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->j, a->j, a->i[m])); 4732be6bf707SBarry Smith if (cpvalues == MAT_COPY_VALUES) { 47332e5835c6SStefano Zampini const PetscScalar *aa; 47342e5835c6SStefano Zampini 47359566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 47369566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->a, aa, a->i[m])); 47379566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 4738be6bf707SBarry Smith } else { 47399566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->a, a->i[m])); 474017ab2063SBarry Smith } 474108480c60SBarry Smith } 4742f77e22a1SHong Zhang } 474317ab2063SBarry Smith 47446ad4291fSHong Zhang c->ignorezeroentries = a->ignorezeroentries; 4745416022c9SBarry Smith c->roworiented = a->roworiented; 4746416022c9SBarry Smith c->nonew = a->nonew; 4747416022c9SBarry Smith if (a->diag) { 47489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &c->diag)); 47499566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->diag, a->diag, m * sizeof(PetscInt))); 47509566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, (m + 1) * sizeof(PetscInt))); 4751071fcb05SBarry Smith } else c->diag = NULL; 47522205254eSKarl Rupp 4753f4259b30SLisandro Dalcin c->solve_work = NULL; 4754f4259b30SLisandro Dalcin c->saved_values = NULL; 4755f4259b30SLisandro Dalcin c->idiag = NULL; 4756f4259b30SLisandro Dalcin c->ssor_work = NULL; 4757a9817697SBarry Smith c->keepnonzeropattern = a->keepnonzeropattern; 4758e6b907acSBarry Smith c->free_a = PETSC_TRUE; 4759e6b907acSBarry Smith c->free_ij = PETSC_TRUE; 47606ad4291fSHong Zhang 4761893ad86cSHong Zhang c->rmax = a->rmax; 4762416022c9SBarry Smith c->nz = a->nz; 47638ed568f8SMatthew G Knepley c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 4764754ec7b1SSatish Balay 47656ad4291fSHong Zhang c->compressedrow.use = a->compressedrow.use; 47666ad4291fSHong Zhang c->compressedrow.nrows = a->compressedrow.nrows; 4767cd6b891eSBarry Smith if (a->compressedrow.use) { 47686ad4291fSHong Zhang i = a->compressedrow.nrows; 47699566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i + 1, &c->compressedrow.i, i, &c->compressedrow.rindex)); 47709566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.i, a->compressedrow.i, i + 1)); 47719566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.rindex, a->compressedrow.rindex, i)); 477227ea64f8SHong Zhang } else { 477327ea64f8SHong Zhang c->compressedrow.use = PETSC_FALSE; 47740298fd71SBarry Smith c->compressedrow.i = NULL; 47750298fd71SBarry Smith c->compressedrow.rindex = NULL; 47766ad4291fSHong Zhang } 4777ea632784SBarry Smith c->nonzerorowcnt = a->nonzerorowcnt; 4778e56f5c9eSBarry Smith C->nonzerostate = A->nonzerostate; 47794846f1f5SKris Buschelman 47809566063dSJacob Faibussowitsch PetscCall(MatDuplicate_SeqAIJ_Inode(A, cpvalues, &C)); 478169272f91SPierre Jolivet } 47829566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist)); 47833a40ed3dSBarry Smith PetscFunctionReturn(0); 478417ab2063SBarry Smith } 478517ab2063SBarry Smith 47869371c9d4SSatish Balay PetscErrorCode MatDuplicate_SeqAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B) { 4787b24902e0SBarry Smith PetscFunctionBegin; 47889566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 47899566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n)); 479048a46eb9SPierre Jolivet if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) PetscCall(MatSetBlockSizesFromMats(*B, A, A)); 47919566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, ((PetscObject)A)->type_name)); 47929566063dSJacob Faibussowitsch PetscCall(MatDuplicateNoCreate_SeqAIJ(*B, A, cpvalues, PETSC_TRUE)); 4793b24902e0SBarry Smith PetscFunctionReturn(0); 4794b24902e0SBarry Smith } 4795b24902e0SBarry Smith 47969371c9d4SSatish Balay PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer) { 479752f91c60SVaclav Hapla PetscBool isbinary, ishdf5; 479852f91c60SVaclav Hapla 479952f91c60SVaclav Hapla PetscFunctionBegin; 480052f91c60SVaclav Hapla PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1); 480152f91c60SVaclav Hapla PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 4802c27b3999SVaclav Hapla /* force binary viewer to load .info file if it has not yet done so */ 48039566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 48049566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 48059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 480652f91c60SVaclav Hapla if (isbinary) { 48079566063dSJacob Faibussowitsch PetscCall(MatLoad_SeqAIJ_Binary(newMat, viewer)); 480852f91c60SVaclav Hapla } else if (ishdf5) { 480952f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5) 48109566063dSJacob Faibussowitsch PetscCall(MatLoad_AIJ_HDF5(newMat, viewer)); 481152f91c60SVaclav Hapla #else 481252f91c60SVaclav Hapla SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 481352f91c60SVaclav Hapla #endif 481452f91c60SVaclav Hapla } else { 481598921bdaSJacob 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); 481652f91c60SVaclav Hapla } 481752f91c60SVaclav Hapla PetscFunctionReturn(0); 481852f91c60SVaclav Hapla } 481952f91c60SVaclav Hapla 48209371c9d4SSatish Balay PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer) { 48213ea6fe3dSLisandro Dalcin Mat_SeqAIJ *a = (Mat_SeqAIJ *)mat->data; 48223ea6fe3dSLisandro Dalcin PetscInt header[4], *rowlens, M, N, nz, sum, rows, cols, i; 4823fbdbba38SShri Abhyankar 4824fbdbba38SShri Abhyankar PetscFunctionBegin; 48259566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 4826bbead8a2SBarry Smith 48273ea6fe3dSLisandro Dalcin /* read in matrix header */ 48289566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT)); 482908401ef6SPierre Jolivet PetscCheck(header[0] == MAT_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file"); 48309371c9d4SSatish Balay M = header[1]; 48319371c9d4SSatish Balay N = header[2]; 48329371c9d4SSatish Balay nz = header[3]; 483308401ef6SPierre Jolivet PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M); 483408401ef6SPierre Jolivet PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N); 483508401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Matrix stored in special format on disk, cannot load as SeqAIJ"); 4836fbdbba38SShri Abhyankar 48373ea6fe3dSLisandro Dalcin /* set block sizes from the viewer's .info file */ 48389566063dSJacob Faibussowitsch PetscCall(MatLoad_Binary_BlockSizes(mat, viewer)); 48393ea6fe3dSLisandro Dalcin /* set local and global sizes if not set already */ 48403ea6fe3dSLisandro Dalcin if (mat->rmap->n < 0) mat->rmap->n = M; 48413ea6fe3dSLisandro Dalcin if (mat->cmap->n < 0) mat->cmap->n = N; 48423ea6fe3dSLisandro Dalcin if (mat->rmap->N < 0) mat->rmap->N = M; 48433ea6fe3dSLisandro Dalcin if (mat->cmap->N < 0) mat->cmap->N = N; 48449566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->rmap)); 48459566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->cmap)); 48463ea6fe3dSLisandro Dalcin 48473ea6fe3dSLisandro Dalcin /* check if the matrix sizes are correct */ 48489566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 4849aed4548fSBarry 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); 48503ea6fe3dSLisandro Dalcin 4851fbdbba38SShri Abhyankar /* read in row lengths */ 48529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(M, &rowlens)); 48539566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, rowlens, M, NULL, PETSC_INT)); 48543ea6fe3dSLisandro Dalcin /* check if sum(rowlens) is same as nz */ 48559371c9d4SSatish Balay sum = 0; 48569371c9d4SSatish Balay for (i = 0; i < M; i++) sum += rowlens[i]; 485708401ef6SPierre 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); 48583ea6fe3dSLisandro Dalcin /* preallocate and check sizes */ 48599566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(mat, 0, rowlens)); 48609566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 4861aed4548fSBarry 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); 48623ea6fe3dSLisandro Dalcin /* store row lengths */ 48639566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->ilen, rowlens, M)); 48649566063dSJacob Faibussowitsch PetscCall(PetscFree(rowlens)); 4865fbdbba38SShri Abhyankar 48663ea6fe3dSLisandro Dalcin /* fill in "i" row pointers */ 48679371c9d4SSatish Balay a->i[0] = 0; 48689371c9d4SSatish Balay for (i = 0; i < M; i++) a->i[i + 1] = a->i[i] + a->ilen[i]; 48693ea6fe3dSLisandro Dalcin /* read in "j" column indices */ 48709566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, a->j, nz, NULL, PETSC_INT)); 48713ea6fe3dSLisandro Dalcin /* read in "a" nonzero values */ 48729566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, a->a, nz, NULL, PETSC_SCALAR)); 4873fbdbba38SShri Abhyankar 48749566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 48759566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 4876fbdbba38SShri Abhyankar PetscFunctionReturn(0); 4877fbdbba38SShri Abhyankar } 4878fbdbba38SShri Abhyankar 48799371c9d4SSatish Balay PetscErrorCode MatEqual_SeqAIJ(Mat A, Mat B, PetscBool *flg) { 48807264ac53SSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data, *b = (Mat_SeqAIJ *)B->data; 4881fff043a9SJunchao Zhang const PetscScalar *aa, *ba; 4882eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 4883eeffb40dSHong Zhang PetscInt k; 4884eeffb40dSHong Zhang #endif 48857264ac53SSatish Balay 48863a40ed3dSBarry Smith PetscFunctionBegin; 4887bfeeae90SHong Zhang /* If the matrix dimensions are not equal,or no of nonzeros */ 4888d0f46423SBarry Smith if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) || (a->nz != b->nz)) { 4889ca44d042SBarry Smith *flg = PETSC_FALSE; 4890ca44d042SBarry Smith PetscFunctionReturn(0); 4891bcd2baecSBarry Smith } 48927264ac53SSatish Balay 48937264ac53SSatish Balay /* if the a->i are the same */ 48949566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->i, b->i, A->rmap->n + 1, flg)); 4895abc0a331SBarry Smith if (!*flg) PetscFunctionReturn(0); 48967264ac53SSatish Balay 48977264ac53SSatish Balay /* if a->j are the same */ 48989566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->j, b->j, a->nz, flg)); 4899abc0a331SBarry Smith if (!*flg) PetscFunctionReturn(0); 4900bcd2baecSBarry Smith 49019566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 49029566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &ba)); 4903bcd2baecSBarry Smith /* if a->a are the same */ 4904eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 4905eeffb40dSHong Zhang for (k = 0; k < a->nz; k++) { 4906fff043a9SJunchao Zhang if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) { 4907eeffb40dSHong Zhang *flg = PETSC_FALSE; 49083a40ed3dSBarry Smith PetscFunctionReturn(0); 4909eeffb40dSHong Zhang } 4910eeffb40dSHong Zhang } 4911eeffb40dSHong Zhang #else 49129566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(aa, ba, a->nz, flg)); 4913eeffb40dSHong Zhang #endif 49149566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 49159566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &ba)); 4916eeffb40dSHong Zhang PetscFunctionReturn(0); 49177264ac53SSatish Balay } 491836db0b34SBarry Smith 491905869f15SSatish Balay /*@ 492011a5261eSBarry Smith MatCreateSeqAIJWithArrays - Creates an sequential `MATSEQAIJ` matrix using matrix elements (in CSR format) 492136db0b34SBarry Smith provided by the user. 492236db0b34SBarry Smith 4923d083f849SBarry Smith Collective 492436db0b34SBarry Smith 492536db0b34SBarry Smith Input Parameters: 492636db0b34SBarry Smith + comm - must be an MPI communicator of size 1 492736db0b34SBarry Smith . m - number of rows 492836db0b34SBarry Smith . n - number of columns 4929483a2f95SBarry Smith . i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 493036db0b34SBarry Smith . j - column indices 493136db0b34SBarry Smith - a - matrix values 493236db0b34SBarry Smith 493336db0b34SBarry Smith Output Parameter: 493436db0b34SBarry Smith . mat - the matrix 493536db0b34SBarry Smith 493636db0b34SBarry Smith Level: intermediate 493736db0b34SBarry Smith 493836db0b34SBarry Smith Notes: 49390551d7c0SBarry Smith The i, j, and a arrays are not copied by this routine, the user must free these arrays 4940292fb18eSBarry Smith once the matrix is destroyed and not before 494136db0b34SBarry Smith 494236db0b34SBarry Smith You cannot set new nonzero locations into this matrix, that will generate an error. 494336db0b34SBarry Smith 4944bfeeae90SHong Zhang The i and j indices are 0 based 494536db0b34SBarry Smith 4946a4552177SSatish Balay The format which is used for the sparse matrix input, is equivalent to a 4947a4552177SSatish Balay row-major ordering.. i.e for the following matrix, the input data expected is 49488eef79e4SBarry Smith as shown 4949a4552177SSatish Balay 49508eef79e4SBarry Smith $ 1 0 0 49518eef79e4SBarry Smith $ 2 0 3 49528eef79e4SBarry Smith $ 4 5 6 49538eef79e4SBarry Smith $ 49548eef79e4SBarry Smith $ i = {0,1,3,6} [size = nrow+1 = 3+1] 49558eef79e4SBarry Smith $ j = {0,0,2,0,1,2} [size = 6]; values must be sorted for each row 49568eef79e4SBarry Smith $ v = {1,2,3,4,5,6} [size = 6] 4957a4552177SSatish Balay 4958db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateMPIAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()` 495936db0b34SBarry Smith @*/ 49609371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat) { 4961cbcfb4deSHong Zhang PetscInt ii; 496236db0b34SBarry Smith Mat_SeqAIJ *aij; 4963cbcfb4deSHong Zhang PetscInt jj; 496436db0b34SBarry Smith 496536db0b34SBarry Smith PetscFunctionBegin; 4966aed4548fSBarry Smith PetscCheck(m <= 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0"); 49679566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 49689566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 49699566063dSJacob Faibussowitsch /* PetscCall(MatSetBlockSizes(*mat,,)); */ 49709566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQAIJ)); 49719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, MAT_SKIP_ALLOCATION, NULL)); 4972ab93d7beSBarry Smith aij = (Mat_SeqAIJ *)(*mat)->data; 49739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &aij->imax)); 49749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &aij->ilen)); 4975ab93d7beSBarry Smith 497636db0b34SBarry Smith aij->i = i; 497736db0b34SBarry Smith aij->j = j; 497836db0b34SBarry Smith aij->a = a; 497936db0b34SBarry Smith aij->singlemalloc = PETSC_FALSE; 498036db0b34SBarry Smith aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 4981e6b907acSBarry Smith aij->free_a = PETSC_FALSE; 4982e6b907acSBarry Smith aij->free_ij = PETSC_FALSE; 498336db0b34SBarry Smith 4984cbc6b225SStefano Zampini for (ii = 0, aij->nonzerorowcnt = 0, aij->rmax = 0; ii < m; ii++) { 498536db0b34SBarry Smith aij->ilen[ii] = aij->imax[ii] = i[ii + 1] - i[ii]; 498676bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4987aed4548fSBarry 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]); 49889985e31cSBarry Smith for (jj = i[ii] + 1; jj < i[ii + 1]; jj++) { 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 not sorted", jj - i[ii], j[jj], ii); 499008401ef6SPierre 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); 49919985e31cSBarry Smith } 499236db0b34SBarry Smith } 499376bd3646SJed Brown } 499476bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 499536db0b34SBarry Smith for (ii = 0; ii < aij->i[m]; ii++) { 499608401ef6SPierre 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]); 4997aed4548fSBarry 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]); 499836db0b34SBarry Smith } 499976bd3646SJed Brown } 500036db0b34SBarry Smith 50019566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 50029566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 500336db0b34SBarry Smith PetscFunctionReturn(0); 500436db0b34SBarry Smith } 5005cbc6b225SStefano Zampini 5006f62e3866SBarry Smith /*@ 500711a5261eSBarry Smith MatCreateSeqAIJFromTriple - Creates an sequential `MATSEQAIJ` matrix using matrix elements (in COO format) 50088a0b0e6bSVictor Minden provided by the user. 50098a0b0e6bSVictor Minden 5010d083f849SBarry Smith Collective 50118a0b0e6bSVictor Minden 50128a0b0e6bSVictor Minden Input Parameters: 50138a0b0e6bSVictor Minden + comm - must be an MPI communicator of size 1 50148a0b0e6bSVictor Minden . m - number of rows 50158a0b0e6bSVictor Minden . n - number of columns 50168a0b0e6bSVictor Minden . i - row indices 50178a0b0e6bSVictor Minden . j - column indices 50181230e6d1SVictor Minden . a - matrix values 50191230e6d1SVictor Minden . nz - number of nonzeros 502011a5261eSBarry Smith - idx - if the i and j indices start with 1 use `PETSC_TRUE` otherwise use `PETSC_FALSE` 50218a0b0e6bSVictor Minden 50228a0b0e6bSVictor Minden Output Parameter: 50238a0b0e6bSVictor Minden . mat - the matrix 50248a0b0e6bSVictor Minden 50258a0b0e6bSVictor Minden Level: intermediate 50268a0b0e6bSVictor Minden 5027f62e3866SBarry Smith Example: 5028f62e3866SBarry Smith For the following matrix, the input data expected is as shown (using 0 based indexing) 50299e99939fSJunchao Zhang .vb 50308a0b0e6bSVictor Minden 1 0 0 50318a0b0e6bSVictor Minden 2 0 3 50328a0b0e6bSVictor Minden 4 5 6 50338a0b0e6bSVictor Minden 50348a0b0e6bSVictor Minden i = {0,1,1,2,2,2} 50358a0b0e6bSVictor Minden j = {0,0,2,0,1,2} 50368a0b0e6bSVictor Minden v = {1,2,3,4,5,6} 50379e99939fSJunchao Zhang .ve 50388a0b0e6bSVictor Minden 5039db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateSeqAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()`, `MatSetValuesCOO()` 50408a0b0e6bSVictor Minden @*/ 50419371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat, PetscInt nz, PetscBool idx) { 5042d021a1c5SVictor Minden PetscInt ii, *nnz, one = 1, row, col; 50438a0b0e6bSVictor Minden 50448a0b0e6bSVictor Minden PetscFunctionBegin; 50459566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m, &nnz)); 5046ad540459SPierre Jolivet for (ii = 0; ii < nz; ii++) nnz[i[ii] - !!idx] += 1; 50479566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 50489566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 50499566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQAIJ)); 50509566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, 0, nnz)); 50511230e6d1SVictor Minden for (ii = 0; ii < nz; ii++) { 50521230e6d1SVictor Minden if (idx) { 50531230e6d1SVictor Minden row = i[ii] - 1; 50541230e6d1SVictor Minden col = j[ii] - 1; 50551230e6d1SVictor Minden } else { 50561230e6d1SVictor Minden row = i[ii]; 50571230e6d1SVictor Minden col = j[ii]; 50588a0b0e6bSVictor Minden } 50599566063dSJacob Faibussowitsch PetscCall(MatSetValues(*mat, one, &row, one, &col, &a[ii], ADD_VALUES)); 50608a0b0e6bSVictor Minden } 50619566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 50629566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 50639566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 50648a0b0e6bSVictor Minden PetscFunctionReturn(0); 50658a0b0e6bSVictor Minden } 506636db0b34SBarry Smith 50679371c9d4SSatish Balay PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A) { 5068acf2f550SJed Brown Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 5069acf2f550SJed Brown 5070acf2f550SJed Brown PetscFunctionBegin; 5071acf2f550SJed Brown a->idiagvalid = PETSC_FALSE; 5072acf2f550SJed Brown a->ibdiagvalid = PETSC_FALSE; 50732205254eSKarl Rupp 50749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal_Inode(A)); 5075acf2f550SJed Brown PetscFunctionReturn(0); 5076acf2f550SJed Brown } 5077acf2f550SJed Brown 50789371c9d4SSatish Balay PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat) { 50799c8f2541SHong Zhang PetscFunctionBegin; 50809566063dSJacob Faibussowitsch PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm, inmat, n, scall, outmat)); 50819c8f2541SHong Zhang PetscFunctionReturn(0); 50829c8f2541SHong Zhang } 50839c8f2541SHong Zhang 508481824310SBarry Smith /* 508553dd7562SDmitry Karpeev Permute A into C's *local* index space using rowemb,colemb. 508653dd7562SDmitry Karpeev The embedding are supposed to be injections and the above implies that the range of rowemb is a subset 508753dd7562SDmitry Karpeev of [0,m), colemb is in [0,n). 508853dd7562SDmitry Karpeev If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A. 508953dd7562SDmitry Karpeev */ 50909371c9d4SSatish Balay PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C, IS rowemb, IS colemb, MatStructure pattern, Mat B) { 509153dd7562SDmitry Karpeev /* If making this function public, change the error returned in this function away from _PLIB. */ 509253dd7562SDmitry Karpeev Mat_SeqAIJ *Baij; 509353dd7562SDmitry Karpeev PetscBool seqaij; 509453dd7562SDmitry Karpeev PetscInt m, n, *nz, i, j, count; 509553dd7562SDmitry Karpeev PetscScalar v; 509653dd7562SDmitry Karpeev const PetscInt *rowindices, *colindices; 509753dd7562SDmitry Karpeev 509853dd7562SDmitry Karpeev PetscFunctionBegin; 509953dd7562SDmitry Karpeev if (!B) PetscFunctionReturn(0); 510053dd7562SDmitry Karpeev /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */ 51019566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)B, MATSEQAIJ, &seqaij)); 510228b400f6SJacob Faibussowitsch PetscCheck(seqaij, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is of wrong type"); 510353dd7562SDmitry Karpeev if (rowemb) { 51049566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rowemb, &m)); 510508401ef6SPierre 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); 510653dd7562SDmitry Karpeev } else { 510708401ef6SPierre Jolivet PetscCheck(C->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is row-incompatible with the target matrix"); 510853dd7562SDmitry Karpeev } 510953dd7562SDmitry Karpeev if (colemb) { 51109566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(colemb, &n)); 511108401ef6SPierre 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); 511253dd7562SDmitry Karpeev } else { 511308401ef6SPierre Jolivet PetscCheck(C->cmap->n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is col-incompatible with the target matrix"); 511453dd7562SDmitry Karpeev } 511553dd7562SDmitry Karpeev 511653dd7562SDmitry Karpeev Baij = (Mat_SeqAIJ *)(B->data); 511753dd7562SDmitry Karpeev if (pattern == DIFFERENT_NONZERO_PATTERN) { 51189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n, &nz)); 5119ad540459SPierre Jolivet for (i = 0; i < B->rmap->n; i++) nz[i] = Baij->i[i + 1] - Baij->i[i]; 51209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(C, 0, nz)); 51219566063dSJacob Faibussowitsch PetscCall(PetscFree(nz)); 512253dd7562SDmitry Karpeev } 512348a46eb9SPierre Jolivet if (pattern == SUBSET_NONZERO_PATTERN) PetscCall(MatZeroEntries(C)); 512453dd7562SDmitry Karpeev count = 0; 512553dd7562SDmitry Karpeev rowindices = NULL; 512653dd7562SDmitry Karpeev colindices = NULL; 512748a46eb9SPierre Jolivet if (rowemb) PetscCall(ISGetIndices(rowemb, &rowindices)); 512848a46eb9SPierre Jolivet if (colemb) PetscCall(ISGetIndices(colemb, &colindices)); 512953dd7562SDmitry Karpeev for (i = 0; i < B->rmap->n; i++) { 513053dd7562SDmitry Karpeev PetscInt row; 513153dd7562SDmitry Karpeev row = i; 513253dd7562SDmitry Karpeev if (rowindices) row = rowindices[i]; 513353dd7562SDmitry Karpeev for (j = Baij->i[i]; j < Baij->i[i + 1]; j++) { 513453dd7562SDmitry Karpeev PetscInt col; 513553dd7562SDmitry Karpeev col = Baij->j[count]; 513653dd7562SDmitry Karpeev if (colindices) col = colindices[col]; 513753dd7562SDmitry Karpeev v = Baij->a[count]; 51389566063dSJacob Faibussowitsch PetscCall(MatSetValues(C, 1, &row, 1, &col, &v, INSERT_VALUES)); 513953dd7562SDmitry Karpeev ++count; 514053dd7562SDmitry Karpeev } 514153dd7562SDmitry Karpeev } 514253dd7562SDmitry Karpeev /* FIXME: set C's nonzerostate correctly. */ 514353dd7562SDmitry Karpeev /* Assembly for C is necessary. */ 514453dd7562SDmitry Karpeev C->preallocated = PETSC_TRUE; 514553dd7562SDmitry Karpeev C->assembled = PETSC_TRUE; 514653dd7562SDmitry Karpeev C->was_assembled = PETSC_FALSE; 514753dd7562SDmitry Karpeev PetscFunctionReturn(0); 514853dd7562SDmitry Karpeev } 514953dd7562SDmitry Karpeev 51504099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL; 51514099cc6bSBarry Smith 51524099cc6bSBarry Smith /*@C 515311a5261eSBarry Smith MatSeqAIJSetType - Converts a `MATSEQAIJ` matrix to a subtype 51544099cc6bSBarry Smith 515511a5261eSBarry Smith Collective on mat 51564099cc6bSBarry Smith 51574099cc6bSBarry Smith Input Parameters: 51584099cc6bSBarry Smith + mat - the matrix object 51594099cc6bSBarry Smith - matype - matrix type 51604099cc6bSBarry Smith 51614099cc6bSBarry Smith Options Database Key: 51624099cc6bSBarry Smith . -mat_seqai_type <method> - for example seqaijcrl 51634099cc6bSBarry Smith 51644099cc6bSBarry Smith Level: intermediate 51654099cc6bSBarry Smith 5166db781477SPatrick Sanan .seealso: `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat` 51674099cc6bSBarry Smith @*/ 51689371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetType(Mat mat, MatType matype) { 51694099cc6bSBarry Smith PetscBool sametype; 51705f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(Mat, MatType, MatReuse, Mat *); 51714099cc6bSBarry Smith 51724099cc6bSBarry Smith PetscFunctionBegin; 51734099cc6bSBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 51749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, matype, &sametype)); 51754099cc6bSBarry Smith if (sametype) PetscFunctionReturn(0); 51764099cc6bSBarry Smith 51779566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(MatSeqAIJList, matype, &r)); 51785f80ce2aSJacob Faibussowitsch PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Mat type given: %s", matype); 51799566063dSJacob Faibussowitsch PetscCall((*r)(mat, matype, MAT_INPLACE_MATRIX, &mat)); 51804099cc6bSBarry Smith PetscFunctionReturn(0); 51814099cc6bSBarry Smith } 51824099cc6bSBarry Smith 51834099cc6bSBarry Smith /*@C 518411a5261eSBarry Smith MatSeqAIJRegister - - Adds a new sub-matrix type for sequential `MATSEQAIJ` matrices 51854099cc6bSBarry Smith 51864099cc6bSBarry Smith Not Collective 51874099cc6bSBarry Smith 51884099cc6bSBarry Smith Input Parameters: 518911a5261eSBarry Smith + name - name of a new user-defined matrix type, for example `MATSEQAIJCRL` 51904099cc6bSBarry Smith - function - routine to convert to subtype 51914099cc6bSBarry Smith 51924099cc6bSBarry Smith Notes: 519311a5261eSBarry Smith `MatSeqAIJRegister()` may be called multiple times to add several user-defined solvers. 51944099cc6bSBarry Smith 51954099cc6bSBarry Smith Then, your matrix can be chosen with the procedural interface at runtime via the option 51964099cc6bSBarry Smith $ -mat_seqaij_type my_mat 51974099cc6bSBarry Smith 51984099cc6bSBarry Smith Level: advanced 51994099cc6bSBarry Smith 5200db781477SPatrick Sanan .seealso: `MatSeqAIJRegisterAll()` 52014099cc6bSBarry Smith @*/ 52029371c9d4SSatish Balay PetscErrorCode MatSeqAIJRegister(const char sname[], PetscErrorCode (*function)(Mat, MatType, MatReuse, Mat *)) { 52034099cc6bSBarry Smith PetscFunctionBegin; 52049566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 52059566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&MatSeqAIJList, sname, function)); 52064099cc6bSBarry Smith PetscFunctionReturn(0); 52074099cc6bSBarry Smith } 52084099cc6bSBarry Smith 52094099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE; 52104099cc6bSBarry Smith 52114099cc6bSBarry Smith /*@C 521211a5261eSBarry Smith MatSeqAIJRegisterAll - Registers all of the matrix subtypes of `MATSSEQAIJ` 52134099cc6bSBarry Smith 52144099cc6bSBarry Smith Not Collective 52154099cc6bSBarry Smith 52164099cc6bSBarry Smith Level: advanced 52174099cc6bSBarry Smith 5218db781477SPatrick Sanan .seealso: `MatRegisterAll()`, `MatSeqAIJRegister()` 52194099cc6bSBarry Smith @*/ 52209371c9d4SSatish Balay PetscErrorCode MatSeqAIJRegisterAll(void) { 52214099cc6bSBarry Smith PetscFunctionBegin; 52224099cc6bSBarry Smith if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0); 52234099cc6bSBarry Smith MatSeqAIJRegisterAllCalled = PETSC_TRUE; 52244099cc6bSBarry Smith 52259566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCRL, MatConvert_SeqAIJ_SeqAIJCRL)); 52269566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJPERM, MatConvert_SeqAIJ_SeqAIJPERM)); 52279566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJSELL, MatConvert_SeqAIJ_SeqAIJSELL)); 52289779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 52299566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJMKL, MatConvert_SeqAIJ_SeqAIJMKL)); 5230485f9817SRichard Tran Mills #endif 52315063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA) 52329566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 52335063d097SStefano Zampini #endif 52345063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 52359566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJKOKKOS, MatConvert_SeqAIJ_SeqAIJKokkos)); 52365063d097SStefano Zampini #endif 52374099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA) 52389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL)); 52394099cc6bSBarry Smith #endif 52404099cc6bSBarry Smith PetscFunctionReturn(0); 52414099cc6bSBarry Smith } 524253dd7562SDmitry Karpeev 524353dd7562SDmitry Karpeev /* 524481824310SBarry Smith Special version for direct calls from Fortran 524581824310SBarry Smith */ 5246af0996ceSBarry Smith #include <petsc/private/fortranimpl.h> 524781824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS) 524881824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ 524981824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 525081824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij 525181824310SBarry Smith #endif 525281824310SBarry Smith 525381824310SBarry Smith /* Change these macros so can be used in void function */ 525498921bdaSJacob Faibussowitsch 525598921bdaSJacob Faibussowitsch /* Change these macros so can be used in void function */ 52569566063dSJacob Faibussowitsch /* Identical to PetscCallVoid, except it assigns to *_ierr */ 52579566063dSJacob Faibussowitsch #undef PetscCall 52589371c9d4SSatish Balay #define PetscCall(...) \ 52599371c9d4SSatish Balay do { \ 52605f80ce2aSJacob Faibussowitsch PetscErrorCode ierr_msv_mpiaij = __VA_ARGS__; \ 526198921bdaSJacob Faibussowitsch if (PetscUnlikely(ierr_msv_mpiaij)) { \ 526298921bdaSJacob Faibussowitsch *_ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr_msv_mpiaij, PETSC_ERROR_REPEAT, " "); \ 526398921bdaSJacob Faibussowitsch return; \ 526498921bdaSJacob Faibussowitsch } \ 526598921bdaSJacob Faibussowitsch } while (0) 526698921bdaSJacob Faibussowitsch 526798921bdaSJacob Faibussowitsch #undef SETERRQ 52689371c9d4SSatish Balay #define SETERRQ(comm, ierr, ...) \ 52699371c9d4SSatish Balay do { \ 527098921bdaSJacob Faibussowitsch *_ierr = PetscError(comm, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr, PETSC_ERROR_INITIAL, __VA_ARGS__); \ 527198921bdaSJacob Faibussowitsch return; \ 527298921bdaSJacob Faibussowitsch } while (0) 527381824310SBarry Smith 52749371c9d4SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA, PetscInt *mm, const PetscInt im[], PetscInt *nn, const PetscInt in[], const PetscScalar v[], InsertMode *isis, PetscErrorCode *_ierr) { 527581824310SBarry Smith Mat A = *AA; 527681824310SBarry Smith PetscInt m = *mm, n = *nn; 527781824310SBarry Smith InsertMode is = *isis; 527881824310SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 527981824310SBarry Smith PetscInt *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N; 528081824310SBarry Smith PetscInt *imax, *ai, *ailen; 528181824310SBarry Smith PetscInt *aj, nonew = a->nonew, lastcol = -1; 528254f21887SBarry Smith MatScalar *ap, value, *aa; 5283ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 5284ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 528581824310SBarry Smith 528681824310SBarry Smith PetscFunctionBegin; 52874994cf47SJed Brown MatCheckPreallocated(A, 1); 528881824310SBarry Smith imax = a->imax; 528981824310SBarry Smith ai = a->i; 529081824310SBarry Smith ailen = a->ilen; 529181824310SBarry Smith aj = a->j; 529281824310SBarry Smith aa = a->a; 529381824310SBarry Smith 529481824310SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 529581824310SBarry Smith row = im[k]; 529681824310SBarry Smith if (row < 0) continue; 52975f80ce2aSJacob Faibussowitsch PetscCheck(row < A->rmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Row too large"); 52989371c9d4SSatish Balay rp = aj + ai[row]; 52999371c9d4SSatish Balay ap = aa + ai[row]; 53009371c9d4SSatish Balay rmax = imax[row]; 53019371c9d4SSatish Balay nrow = ailen[row]; 530281824310SBarry Smith low = 0; 530381824310SBarry Smith high = nrow; 530481824310SBarry Smith for (l = 0; l < n; l++) { /* loop over added columns */ 530581824310SBarry Smith if (in[l] < 0) continue; 53065f80ce2aSJacob Faibussowitsch PetscCheck(in[l] < A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Column too large"); 530781824310SBarry Smith col = in[l]; 53082205254eSKarl Rupp if (roworiented) value = v[l + k * n]; 53092205254eSKarl Rupp else value = v[k + l * m]; 53102205254eSKarl Rupp 531181824310SBarry Smith if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 531281824310SBarry Smith 53132205254eSKarl Rupp if (col <= lastcol) low = 0; 53142205254eSKarl Rupp else high = nrow; 531581824310SBarry Smith lastcol = col; 531681824310SBarry Smith while (high - low > 5) { 531781824310SBarry Smith t = (low + high) / 2; 531881824310SBarry Smith if (rp[t] > col) high = t; 531981824310SBarry Smith else low = t; 532081824310SBarry Smith } 532181824310SBarry Smith for (i = low; i < high; i++) { 532281824310SBarry Smith if (rp[i] > col) break; 532381824310SBarry Smith if (rp[i] == col) { 532481824310SBarry Smith if (is == ADD_VALUES) ap[i] += value; 532581824310SBarry Smith else ap[i] = value; 532681824310SBarry Smith goto noinsert; 532781824310SBarry Smith } 532881824310SBarry Smith } 532981824310SBarry Smith if (value == 0.0 && ignorezeroentries) goto noinsert; 533081824310SBarry Smith if (nonew == 1) goto noinsert; 53315f80ce2aSJacob Faibussowitsch PetscCheck(nonew != -1, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero in the matrix"); 5332fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, A->rmap->n, 1, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 53339371c9d4SSatish Balay N = nrow++ - 1; 53349371c9d4SSatish Balay a->nz++; 53359371c9d4SSatish Balay high++; 533681824310SBarry Smith /* shift up all the later entries in this row */ 533781824310SBarry Smith for (ii = N; ii >= i; ii--) { 533881824310SBarry Smith rp[ii + 1] = rp[ii]; 533981824310SBarry Smith ap[ii + 1] = ap[ii]; 534081824310SBarry Smith } 534181824310SBarry Smith rp[i] = col; 534281824310SBarry Smith ap[i] = value; 5343e56f5c9eSBarry Smith A->nonzerostate++; 534481824310SBarry Smith noinsert:; 534581824310SBarry Smith low = i + 1; 534681824310SBarry Smith } 534781824310SBarry Smith ailen[row] = nrow; 534881824310SBarry Smith } 534981824310SBarry Smith PetscFunctionReturnVoid(); 535081824310SBarry Smith } 535198921bdaSJacob Faibussowitsch /* Undefining these here since they were redefined from their original definition above! No 535298921bdaSJacob Faibussowitsch * other PETSc functions should be defined past this point, as it is impossible to recover the 535398921bdaSJacob Faibussowitsch * original definitions */ 53549566063dSJacob Faibussowitsch #undef PetscCall 535598921bdaSJacob Faibussowitsch #undef SETERRQ 5356