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) { 319371c9d4SSatish Balay 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) { 339371c9d4SSatish Balay for (i = 0; i < aij->i[m]; i++) { reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]); } 340716a85fSBarry Smith } else if (type == NORM_INFINITY) { 359371c9d4SSatish Balay 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) { 379371c9d4SSatish Balay 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) { 399371c9d4SSatish Balay 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++) { 589371c9d4SSatish Balay 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++) { 849371c9d4SSatish Balay 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++) { 899371c9d4SSatish Balay 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) { 1679371c9d4SSatish Balay for (i = 0; i < m; i++) { aa[diag[i]] = v[i]; } 16879299369SBarry Smith } else { 1699371c9d4SSatish Balay 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; 2369371c9d4SSatish Balay for (i = 0; i < nz; i++) { collengths[jj[i]]++; } 2373b2fbd54SBarry Smith cia[0] = oshift; 2389371c9d4SSatish Balay 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; 2869371c9d4SSatish Balay for (i = 0; i < nz; i++) { collengths[jj[i]]++; } 2877cee066cSHong Zhang cia[0] = oshift; 2889371c9d4SSatish Balay 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: 49519b08ed1SBarry Smith + A - the SeqAIJ 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. 50219b08ed1SBarry 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]; 563*48a46eb9SPierre 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)); 672*48a46eb9SPierre 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) 801*48a46eb9SPierre 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)); 1094*48a46eb9SPierre 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 1127*48a46eb9SPierre 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 */ 1526*48a46eb9SPierre 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 */ 1576*48a46eb9SPierre 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 */ 16809371c9d4SSatish Balay 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)); 1686*48a46eb9SPierre 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); 17499371c9d4SSatish Balay for (i = 0; i < nblocks; i++) { bsizemax = PetscMax(bsizemax, bsizes[i]); } 17509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsizemax, &indx)); 1751*48a46eb9SPierre 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 } 1796*48a46eb9SPierre 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 { 21589371c9d4SSatish Balay 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]; 24679371c9d4SSatish Balay 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++) { 24909371c9d4SSatish Balay 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 2642*48a46eb9SPierre 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 2650*48a46eb9SPierre Jolivet for (i = 0; i < submatj->nrqs; ++i) PetscCall(PetscFree(submatj->rbuf3[i])); 26519566063dSJacob Faibussowitsch PetscCall(PetscFree3(submatj->req_source2, submatj->rbuf2, submatj->rbuf3)); 26529566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->pa)); 265316b64355SHong Zhang } 265416b64355SHong Zhang 265516b64355SHong Zhang #if defined(PETSC_USE_CTABLE) 26569566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy((PetscTable *)&submatj->rmap)); 26579566063dSJacob Faibussowitsch if (submatj->cmap_loc) PetscCall(PetscFree(submatj->cmap_loc)); 26589566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rmap_loc)); 265916b64355SHong Zhang #else 26609566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rmap)); 266116b64355SHong Zhang #endif 266216b64355SHong Zhang 266316b64355SHong Zhang if (!submatj->allcolumns) { 266416b64355SHong Zhang #if defined(PETSC_USE_CTABLE) 26659566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy((PetscTable *)&submatj->cmap)); 266616b64355SHong Zhang #else 26679566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->cmap)); 266816b64355SHong Zhang #endif 266916b64355SHong Zhang } 26709566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->row2proc)); 267116b64355SHong Zhang 26729566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj)); 267316b64355SHong Zhang PetscFunctionReturn(0); 267416b64355SHong Zhang } 267516b64355SHong Zhang 26769371c9d4SSatish Balay PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C) { 267716b64355SHong Zhang Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data; 26785c39f6d9SHong Zhang Mat_SubSppt *submatj = c->submatis1; 267916b64355SHong Zhang 268016b64355SHong Zhang PetscFunctionBegin; 26819566063dSJacob Faibussowitsch PetscCall((*submatj->destroy)(C)); 26829566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrix_Private(submatj)); 268316b64355SHong Zhang PetscFunctionReturn(0); 268416b64355SHong Zhang } 268516b64355SHong Zhang 268689a1a59bSHong Zhang /* Note this has code duplication with MatDestroySubMatrices_SeqBAIJ() */ 26879371c9d4SSatish Balay PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n, Mat *mat[]) { 26882d033e1fSHong Zhang PetscInt i; 26890fb991dcSHong Zhang Mat C; 26900fb991dcSHong Zhang Mat_SeqAIJ *c; 26910fb991dcSHong Zhang Mat_SubSppt *submatj; 26922d033e1fSHong Zhang 26932d033e1fSHong Zhang PetscFunctionBegin; 26942d033e1fSHong Zhang for (i = 0; i < n; i++) { 26950fb991dcSHong Zhang C = (*mat)[i]; 26960fb991dcSHong Zhang c = (Mat_SeqAIJ *)C->data; 26970fb991dcSHong Zhang submatj = c->submatis1; 26982d033e1fSHong Zhang if (submatj) { 2699682e4c99SStefano Zampini if (--((PetscObject)C)->refct <= 0) { 270026cc229bSBarry Smith PetscCall(PetscFree(C->factorprefix)); 27019566063dSJacob Faibussowitsch PetscCall((*submatj->destroy)(C)); 27029566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrix_Private(submatj)); 27039566063dSJacob Faibussowitsch PetscCall(PetscFree(C->defaultvectype)); 27049566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->rmap)); 27059566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->cmap)); 27069566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(&C)); 2707682e4c99SStefano Zampini } 27082d033e1fSHong Zhang } else { 27099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 27102d033e1fSHong Zhang } 27112d033e1fSHong Zhang } 271286e85357SHong Zhang 271363a75b2aSHong Zhang /* Destroy Dummy submatrices created for reuse */ 27149566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices_Dummy(n, mat)); 271563a75b2aSHong Zhang 27169566063dSJacob Faibussowitsch PetscCall(PetscFree(*mat)); 27172d033e1fSHong Zhang PetscFunctionReturn(0); 27182d033e1fSHong Zhang } 27192d033e1fSHong Zhang 27209371c9d4SSatish Balay PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[]) { 272197f1f81fSBarry Smith PetscInt i; 2722cddf8d76SBarry Smith 27233a40ed3dSBarry Smith PetscFunctionBegin; 2724*48a46eb9SPierre Jolivet if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n + 1, B)); 2725cddf8d76SBarry Smith 2726*48a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqAIJ(A, irow[i], icol[i], PETSC_DECIDE, scall, &(*B)[i])); 27273a40ed3dSBarry Smith PetscFunctionReturn(0); 2728cddf8d76SBarry Smith } 2729cddf8d76SBarry Smith 27309371c9d4SSatish Balay PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A, PetscInt is_max, IS is[], PetscInt ov) { 2731e4d965acSSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 27325d0c19d7SBarry Smith PetscInt row, i, j, k, l, m, n, *nidx, isz, val; 27335d0c19d7SBarry Smith const PetscInt *idx; 273497f1f81fSBarry Smith PetscInt start, end, *ai, *aj; 2735f1af5d2fSBarry Smith PetscBT table; 2736bbd702dbSSatish Balay 27373a40ed3dSBarry Smith PetscFunctionBegin; 2738d0f46423SBarry Smith m = A->rmap->n; 2739e4d965acSSatish Balay ai = a->i; 2740bfeeae90SHong Zhang aj = a->j; 27418a047759SSatish Balay 274208401ef6SPierre Jolivet PetscCheck(ov >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "illegal negative overlap value used"); 274306763907SSatish Balay 27449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nidx)); 27459566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(m, &table)); 274606763907SSatish Balay 2747e4d965acSSatish Balay for (i = 0; i < is_max; i++) { 2748b97fc60eSLois Curfman McInnes /* Initialize the two local arrays */ 2749e4d965acSSatish Balay isz = 0; 27509566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(m, table)); 2751e4d965acSSatish Balay 2752e4d965acSSatish Balay /* Extract the indices, assume there can be duplicate entries */ 27539566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is[i], &idx)); 27549566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is[i], &n)); 2755e4d965acSSatish Balay 2756dd097bc3SLois Curfman McInnes /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 2757e4d965acSSatish Balay for (j = 0; j < n; ++j) { 27582205254eSKarl Rupp if (!PetscBTLookupSet(table, idx[j])) nidx[isz++] = idx[j]; 27594dcbc457SBarry Smith } 27609566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is[i], &idx)); 27619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is[i])); 2762e4d965acSSatish Balay 276304a348a9SBarry Smith k = 0; 276404a348a9SBarry Smith for (j = 0; j < ov; j++) { /* for each overlap */ 276504a348a9SBarry Smith n = isz; 276606763907SSatish Balay for (; k < n; k++) { /* do only those rows in nidx[k], which are not done yet */ 2767e4d965acSSatish Balay row = nidx[k]; 2768e4d965acSSatish Balay start = ai[row]; 2769e4d965acSSatish Balay end = ai[row + 1]; 277004a348a9SBarry Smith for (l = start; l < end; l++) { 2771efb16452SHong Zhang val = aj[l]; 27722205254eSKarl Rupp if (!PetscBTLookupSet(table, val)) nidx[isz++] = val; 2773e4d965acSSatish Balay } 2774e4d965acSSatish Balay } 2775e4d965acSSatish Balay } 27769566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, isz, nidx, PETSC_COPY_VALUES, (is + i))); 2777e4d965acSSatish Balay } 27789566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&table)); 27799566063dSJacob Faibussowitsch PetscCall(PetscFree(nidx)); 27803a40ed3dSBarry Smith PetscFunctionReturn(0); 27814dcbc457SBarry Smith } 278217ab2063SBarry Smith 27830513a670SBarry Smith /* -------------------------------------------------------------- */ 27849371c9d4SSatish Balay PetscErrorCode MatPermute_SeqAIJ(Mat A, IS rowp, IS colp, Mat *B) { 27850513a670SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 27863b98c0a2SBarry Smith PetscInt i, nz = 0, m = A->rmap->n, n = A->cmap->n; 27875d0c19d7SBarry Smith const PetscInt *row, *col; 27885d0c19d7SBarry Smith PetscInt *cnew, j, *lens; 278956cd22aeSBarry Smith IS icolp, irowp; 27900298fd71SBarry Smith PetscInt *cwork = NULL; 27910298fd71SBarry Smith PetscScalar *vwork = NULL; 27920513a670SBarry Smith 27933a40ed3dSBarry Smith PetscFunctionBegin; 27949566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rowp, PETSC_DECIDE, &irowp)); 27959566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irowp, &row)); 27969566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(colp, PETSC_DECIDE, &icolp)); 27979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icolp, &col)); 27980513a670SBarry Smith 27990513a670SBarry Smith /* determine lengths of permuted rows */ 28009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &lens)); 28012205254eSKarl Rupp for (i = 0; i < m; i++) lens[row[i]] = a->i[i + 1] - a->i[i]; 28029566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 28039566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, m, n, m, n)); 28049566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(*B, A, A)); 28059566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, ((PetscObject)A)->type_name)); 28069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*B, 0, lens)); 28079566063dSJacob Faibussowitsch PetscCall(PetscFree(lens)); 28080513a670SBarry Smith 28099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &cnew)); 28100513a670SBarry Smith for (i = 0; i < m; i++) { 28119566063dSJacob Faibussowitsch PetscCall(MatGetRow_SeqAIJ(A, i, &nz, &cwork, &vwork)); 28122205254eSKarl Rupp for (j = 0; j < nz; j++) cnew[j] = col[cwork[j]]; 28139566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(*B, 1, &row[i], nz, cnew, vwork, INSERT_VALUES)); 28149566063dSJacob Faibussowitsch PetscCall(MatRestoreRow_SeqAIJ(A, i, &nz, &cwork, &vwork)); 28150513a670SBarry Smith } 28169566063dSJacob Faibussowitsch PetscCall(PetscFree(cnew)); 28172205254eSKarl Rupp 28183c7d62e4SBarry Smith (*B)->assembled = PETSC_FALSE; 28192205254eSKarl Rupp 28208c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 28219566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(*B, A->boundtocpu)); 28229fe5e383SStefano Zampini #endif 28239566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 28249566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 28259566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irowp, &row)); 28269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icolp, &col)); 28279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irowp)); 28289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icolp)); 2829*48a46eb9SPierre Jolivet if (rowp == colp) PetscCall(MatPropagateSymmetryOptions(A, *B)); 28303a40ed3dSBarry Smith PetscFunctionReturn(0); 28310513a670SBarry Smith } 28320513a670SBarry Smith 28339371c9d4SSatish Balay PetscErrorCode MatCopy_SeqAIJ(Mat A, Mat B, MatStructure str) { 2834cb5b572fSBarry Smith PetscFunctionBegin; 283533f4a19fSKris Buschelman /* If the two matrices have the same copy implementation, use fast copy. */ 283633f4a19fSKris Buschelman if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) { 2837be6bf707SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2838be6bf707SBarry Smith Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 28392e5835c6SStefano Zampini const PetscScalar *aa; 2840be6bf707SBarry Smith 28419566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 284208401ef6SPierre Jolivet PetscCheck(a->i[A->rmap->n] == b->i[B->rmap->n], PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of nonzeros in two matrices are different %" PetscInt_FMT " != %" PetscInt_FMT, a->i[A->rmap->n], b->i[B->rmap->n]); 28439566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->a, aa, a->i[A->rmap->n])); 28449566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 28459566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 2846cb5b572fSBarry Smith } else { 28479566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 2848cb5b572fSBarry Smith } 2849cb5b572fSBarry Smith PetscFunctionReturn(0); 2850cb5b572fSBarry Smith } 2851cb5b572fSBarry Smith 28529371c9d4SSatish Balay PetscErrorCode MatSetUp_SeqAIJ(Mat A) { 2853273d9f13SBarry Smith PetscFunctionBegin; 28549566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A, PETSC_DEFAULT, NULL)); 2855273d9f13SBarry Smith PetscFunctionReturn(0); 2856273d9f13SBarry Smith } 2857273d9f13SBarry Smith 28589371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A, PetscScalar *array[]) { 28596c0721eeSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 28606e111a19SKarl Rupp 28616c0721eeSBarry Smith PetscFunctionBegin; 28626c0721eeSBarry Smith *array = a->a; 28636c0721eeSBarry Smith PetscFunctionReturn(0); 28646c0721eeSBarry Smith } 28656c0721eeSBarry Smith 28669371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A, PetscScalar *array[]) { 28676c0721eeSBarry Smith PetscFunctionBegin; 2868f38c1e66SStefano Zampini *array = NULL; 28696c0721eeSBarry Smith PetscFunctionReturn(0); 28706c0721eeSBarry Smith } 2871273d9f13SBarry Smith 28728229c054SShri Abhyankar /* 28738229c054SShri Abhyankar Computes the number of nonzeros per row needed for preallocation when X and Y 28748229c054SShri Abhyankar have different nonzero structure. 28758229c054SShri Abhyankar */ 28769371c9d4SSatish Balay PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m, const PetscInt *xi, const PetscInt *xj, const PetscInt *yi, const PetscInt *yj, PetscInt *nnz) { 2877b264fe52SHong Zhang PetscInt i, j, k, nzx, nzy; 2878ec7775f6SShri Abhyankar 2879ec7775f6SShri Abhyankar PetscFunctionBegin; 2880ec7775f6SShri Abhyankar /* Set the number of nonzeros in the new matrix */ 2881ec7775f6SShri Abhyankar for (i = 0; i < m; i++) { 2882b264fe52SHong Zhang const PetscInt *xjj = xj + xi[i], *yjj = yj + yi[i]; 2883b264fe52SHong Zhang nzx = xi[i + 1] - xi[i]; 2884b264fe52SHong Zhang nzy = yi[i + 1] - yi[i]; 28858af7cee1SJed Brown nnz[i] = 0; 28868af7cee1SJed Brown for (j = 0, k = 0; j < nzx; j++) { /* Point in X */ 2887b264fe52SHong Zhang for (; k < nzy && yjj[k] < xjj[j]; k++) nnz[i]++; /* Catch up to X */ 2888b264fe52SHong Zhang if (k < nzy && yjj[k] == xjj[j]) k++; /* Skip duplicate */ 28898af7cee1SJed Brown nnz[i]++; 28908af7cee1SJed Brown } 28918af7cee1SJed Brown for (; k < nzy; k++) nnz[i]++; 2892ec7775f6SShri Abhyankar } 2893ec7775f6SShri Abhyankar PetscFunctionReturn(0); 2894ec7775f6SShri Abhyankar } 2895ec7775f6SShri Abhyankar 28969371c9d4SSatish Balay PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y, Mat X, PetscInt *nnz) { 2897b264fe52SHong Zhang PetscInt m = Y->rmap->N; 2898b264fe52SHong Zhang Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data; 2899b264fe52SHong Zhang Mat_SeqAIJ *y = (Mat_SeqAIJ *)Y->data; 2900b264fe52SHong Zhang 2901b264fe52SHong Zhang PetscFunctionBegin; 2902b264fe52SHong Zhang /* Set the number of nonzeros in the new matrix */ 29039566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqX_private(m, x->i, x->j, y->i, y->j, nnz)); 2904b264fe52SHong Zhang PetscFunctionReturn(0); 2905b264fe52SHong Zhang } 2906b264fe52SHong Zhang 29079371c9d4SSatish Balay PetscErrorCode MatAXPY_SeqAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str) { 2908ac90fabeSBarry Smith Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data, *y = (Mat_SeqAIJ *)Y->data; 2909ac90fabeSBarry Smith 2910ac90fabeSBarry Smith PetscFunctionBegin; 2911134adf20SPierre Jolivet if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) { 2912134adf20SPierre Jolivet PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE; 2913134adf20SPierre Jolivet if (e) { 29149566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->i, y->i, Y->rmap->n + 1, &e)); 291581fa06acSBarry Smith if (e) { 29169566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->j, y->j, y->nz, &e)); 2917134adf20SPierre Jolivet if (e) str = SAME_NONZERO_PATTERN; 291881fa06acSBarry Smith } 291981fa06acSBarry Smith } 292054c59aa7SJacob Faibussowitsch if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN"); 292181fa06acSBarry Smith } 2922ac90fabeSBarry Smith if (str == SAME_NONZERO_PATTERN) { 29232e5835c6SStefano Zampini const PetscScalar *xa; 29242e5835c6SStefano Zampini PetscScalar *ya, alpha = a; 292581fa06acSBarry Smith PetscBLASInt one = 1, bnz; 292681fa06acSBarry Smith 29279566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(x->nz, &bnz)); 29289566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Y, &ya)); 29299566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(X, &xa)); 2930792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, xa, &one, ya, &one)); 29319566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(X, &xa)); 29329566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Y, &ya)); 29339566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0 * bnz)); 29349566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(Y)); 29359566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 2936ab784542SHong Zhang } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 29379566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 2938ac90fabeSBarry Smith } else { 29398229c054SShri Abhyankar Mat B; 29408229c054SShri Abhyankar PetscInt *nnz; 29419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Y->rmap->N, &nnz)); 29429566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B)); 29439566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name)); 29449566063dSJacob Faibussowitsch PetscCall(MatSetLayouts(B, Y->rmap, Y->cmap)); 29459566063dSJacob Faibussowitsch PetscCall(MatSetType(B, ((PetscObject)Y)->type_name)); 29469566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqAIJ(Y, X, nnz)); 29479566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz)); 29489566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 29499566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 29509bb234a9SBarry Smith PetscCall(MatSeqAIJCheckInode(Y)); 29519566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 2952ac90fabeSBarry Smith } 2953ac90fabeSBarry Smith PetscFunctionReturn(0); 2954ac90fabeSBarry Smith } 2955ac90fabeSBarry Smith 29569371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat) { 2957354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX) 2958354c94deSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2959354c94deSBarry Smith PetscInt i, nz; 2960354c94deSBarry Smith PetscScalar *a; 2961354c94deSBarry Smith 2962354c94deSBarry Smith PetscFunctionBegin; 2963354c94deSBarry Smith nz = aij->nz; 29649566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(mat, &a)); 29652205254eSKarl Rupp for (i = 0; i < nz; i++) a[i] = PetscConj(a[i]); 29669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(mat, &a)); 2967354c94deSBarry Smith #else 2968354c94deSBarry Smith PetscFunctionBegin; 2969354c94deSBarry Smith #endif 2970354c94deSBarry Smith PetscFunctionReturn(0); 2971354c94deSBarry Smith } 2972354c94deSBarry Smith 29739371c9d4SSatish Balay PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 2974e34fafa9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 2975d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 2976e34fafa9SBarry Smith PetscReal atmp; 2977985db425SBarry Smith PetscScalar *x; 2978ce496241SStefano Zampini const MatScalar *aa, *av; 2979e34fafa9SBarry Smith 2980e34fafa9SBarry Smith PetscFunctionBegin; 298128b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 29829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 2983ce496241SStefano Zampini aa = av; 2984e34fafa9SBarry Smith ai = a->i; 2985e34fafa9SBarry Smith aj = a->j; 2986e34fafa9SBarry Smith 29879566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 29889566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 29899566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 299008401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 2991e34fafa9SBarry Smith for (i = 0; i < m; i++) { 29929371c9d4SSatish Balay ncols = ai[1] - ai[0]; 29939371c9d4SSatish Balay ai++; 2994e34fafa9SBarry Smith for (j = 0; j < ncols; j++) { 2995985db425SBarry Smith atmp = PetscAbsScalar(*aa); 29969371c9d4SSatish Balay if (PetscAbsScalar(x[i]) < atmp) { 29979371c9d4SSatish Balay x[i] = atmp; 29989371c9d4SSatish Balay if (idx) idx[i] = *aj; 29999371c9d4SSatish Balay } 30009371c9d4SSatish Balay aa++; 30019371c9d4SSatish Balay aj++; 3002985db425SBarry Smith } 3003985db425SBarry Smith } 30049566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 30059566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3006985db425SBarry Smith PetscFunctionReturn(0); 3007985db425SBarry Smith } 3008985db425SBarry Smith 30099371c9d4SSatish Balay PetscErrorCode MatGetRowMax_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 3010985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3011d0f46423SBarry Smith PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 3012985db425SBarry Smith PetscScalar *x; 3013ce496241SStefano Zampini const MatScalar *aa, *av; 3014985db425SBarry Smith 3015985db425SBarry Smith PetscFunctionBegin; 301628b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 30179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3018ce496241SStefano Zampini aa = av; 3019985db425SBarry Smith ai = a->i; 3020985db425SBarry Smith aj = a->j; 3021985db425SBarry Smith 30229566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 30239566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 30249566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 302508401ef6SPierre Jolivet PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3026985db425SBarry Smith for (i = 0; i < m; i++) { 30279371c9d4SSatish Balay ncols = ai[1] - ai[0]; 30289371c9d4SSatish Balay ai++; 3029d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 30309371c9d4SSatish Balay x[i] = *aa; 30319371c9d4SSatish Balay if (idx) idx[i] = 0; 3032985db425SBarry Smith } else { /* row is sparse so already KNOW maximum is 0.0 or higher */ 3033985db425SBarry Smith x[i] = 0.0; 3034985db425SBarry Smith if (idx) { 3035985db425SBarry Smith for (j = 0; j < ncols; j++) { /* find first implicit 0.0 in the row */ 3036985db425SBarry Smith if (aj[j] > j) { 3037985db425SBarry Smith idx[i] = j; 3038985db425SBarry Smith break; 3039985db425SBarry Smith } 3040985db425SBarry Smith } 30411a254869SHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 30421a254869SHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3043985db425SBarry Smith } 3044985db425SBarry Smith } 3045985db425SBarry Smith for (j = 0; j < ncols; j++) { 30469371c9d4SSatish Balay if (PetscRealPart(x[i]) < PetscRealPart(*aa)) { 30479371c9d4SSatish Balay x[i] = *aa; 30489371c9d4SSatish Balay if (idx) idx[i] = *aj; 30499371c9d4SSatish Balay } 30509371c9d4SSatish Balay aa++; 30519371c9d4SSatish Balay aj++; 3052985db425SBarry Smith } 3053985db425SBarry Smith } 30549566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 30559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3056985db425SBarry Smith PetscFunctionReturn(0); 3057985db425SBarry Smith } 3058985db425SBarry Smith 30599371c9d4SSatish Balay PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 3060c87e5d42SMatthew Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3061c87e5d42SMatthew Knepley PetscInt i, j, m = A->rmap->n, *ai, *aj, ncols, n; 3062ce496241SStefano Zampini PetscScalar *x; 3063ce496241SStefano Zampini const MatScalar *aa, *av; 3064c87e5d42SMatthew Knepley 3065c87e5d42SMatthew Knepley PetscFunctionBegin; 30669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3067ce496241SStefano Zampini aa = av; 3068c87e5d42SMatthew Knepley ai = a->i; 3069c87e5d42SMatthew Knepley aj = a->j; 3070c87e5d42SMatthew Knepley 30719566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 30729566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 30739566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 307408401ef6SPierre Jolivet PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n); 3075c87e5d42SMatthew Knepley for (i = 0; i < m; i++) { 30769371c9d4SSatish Balay ncols = ai[1] - ai[0]; 30779371c9d4SSatish Balay ai++; 3078f07e67edSHong Zhang if (ncols == A->cmap->n) { /* row is dense */ 30799371c9d4SSatish Balay x[i] = *aa; 30809371c9d4SSatish Balay if (idx) idx[i] = 0; 3081f07e67edSHong Zhang } else { /* row is sparse so already KNOW minimum is 0.0 or higher */ 3082f07e67edSHong Zhang x[i] = 0.0; 3083f07e67edSHong Zhang if (idx) { /* find first implicit 0.0 in the row */ 3084289a08f5SMatthew Knepley for (j = 0; j < ncols; j++) { 3085f07e67edSHong Zhang if (aj[j] > j) { 3086f07e67edSHong Zhang idx[i] = j; 30872205254eSKarl Rupp break; 30882205254eSKarl Rupp } 3089289a08f5SMatthew Knepley } 3090f07e67edSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3091f07e67edSHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3092f07e67edSHong Zhang } 3093289a08f5SMatthew Knepley } 3094c87e5d42SMatthew Knepley for (j = 0; j < ncols; j++) { 30959371c9d4SSatish Balay if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) { 30969371c9d4SSatish Balay x[i] = *aa; 30979371c9d4SSatish Balay if (idx) idx[i] = *aj; 30989371c9d4SSatish Balay } 30999371c9d4SSatish Balay aa++; 31009371c9d4SSatish Balay aj++; 3101c87e5d42SMatthew Knepley } 3102c87e5d42SMatthew Knepley } 31039566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 31049566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3105c87e5d42SMatthew Knepley PetscFunctionReturn(0); 3106c87e5d42SMatthew Knepley } 3107c87e5d42SMatthew Knepley 31089371c9d4SSatish Balay PetscErrorCode MatGetRowMin_SeqAIJ(Mat A, Vec v, PetscInt idx[]) { 3109985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 3110d9ca1df4SBarry Smith PetscInt i, j, m = A->rmap->n, ncols, n; 3111d9ca1df4SBarry Smith const PetscInt *ai, *aj; 3112985db425SBarry Smith PetscScalar *x; 3113ce496241SStefano Zampini const MatScalar *aa, *av; 3114985db425SBarry Smith 3115985db425SBarry Smith PetscFunctionBegin; 311628b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 31179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &av)); 3118ce496241SStefano Zampini aa = av; 3119985db425SBarry Smith ai = a->i; 3120985db425SBarry Smith aj = a->j; 3121985db425SBarry Smith 31229566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0.0)); 31239566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v, &x)); 31249566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 312508401ef6SPierre Jolivet PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector"); 3126985db425SBarry Smith for (i = 0; i < m; i++) { 31279371c9d4SSatish Balay ncols = ai[1] - ai[0]; 31289371c9d4SSatish Balay ai++; 3129d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 31309371c9d4SSatish Balay x[i] = *aa; 31319371c9d4SSatish Balay if (idx) idx[i] = 0; 3132985db425SBarry Smith } else { /* row is sparse so already KNOW minimum is 0.0 or lower */ 3133985db425SBarry Smith x[i] = 0.0; 3134985db425SBarry Smith if (idx) { /* find first implicit 0.0 in the row */ 3135985db425SBarry Smith for (j = 0; j < ncols; j++) { 3136985db425SBarry Smith if (aj[j] > j) { 3137985db425SBarry Smith idx[i] = j; 3138985db425SBarry Smith break; 3139985db425SBarry Smith } 3140985db425SBarry Smith } 3141fa213d2fSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3142fa213d2fSHong Zhang if (j == ncols && j < A->cmap->n) idx[i] = j; 3143985db425SBarry Smith } 3144985db425SBarry Smith } 3145985db425SBarry Smith for (j = 0; j < ncols; j++) { 31469371c9d4SSatish Balay if (PetscRealPart(x[i]) > PetscRealPart(*aa)) { 31479371c9d4SSatish Balay x[i] = *aa; 31489371c9d4SSatish Balay if (idx) idx[i] = *aj; 31499371c9d4SSatish Balay } 31509371c9d4SSatish Balay aa++; 31519371c9d4SSatish Balay aj++; 3152e34fafa9SBarry Smith } 3153e34fafa9SBarry Smith } 31549566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v, &x)); 31559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &av)); 3156e34fafa9SBarry Smith PetscFunctionReturn(0); 3157e34fafa9SBarry Smith } 3158bbead8a2SBarry Smith 31599371c9d4SSatish Balay PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A, const PetscScalar **values) { 3160bbead8a2SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 316133d57670SJed Brown PetscInt i, bs = PetscAbs(A->rmap->bs), mbs = A->rmap->n / bs, ipvt[5], bs2 = bs * bs, *v_pivots, ij[7], *IJ, j; 3162bbead8a2SBarry Smith MatScalar *diag, work[25], *v_work; 31630da83c2eSBarry Smith const PetscReal shift = 0.0; 31641a9391e3SHong Zhang PetscBool allowzeropivot, zeropivotdetected = PETSC_FALSE; 3165bbead8a2SBarry Smith 3166bbead8a2SBarry Smith PetscFunctionBegin; 3167a455e926SHong Zhang allowzeropivot = PetscNot(A->erroriffailure); 31684a0d0026SBarry Smith if (a->ibdiagvalid) { 31694a0d0026SBarry Smith if (values) *values = a->ibdiag; 31704a0d0026SBarry Smith PetscFunctionReturn(0); 31714a0d0026SBarry Smith } 31729566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 3173bbead8a2SBarry Smith if (!a->ibdiag) { 31749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bs2 * mbs, &a->ibdiag)); 31759566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A, bs2 * mbs * sizeof(PetscScalar))); 3176bbead8a2SBarry Smith } 3177bbead8a2SBarry Smith diag = a->ibdiag; 3178bbead8a2SBarry Smith if (values) *values = a->ibdiag; 3179bbead8a2SBarry Smith /* factor and invert each block */ 3180bbead8a2SBarry Smith switch (bs) { 3181bbead8a2SBarry Smith case 1: 3182bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 31839566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 1, &i, 1, &i, diag + i)); 3184ec1892c8SHong Zhang if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) { 3185ec1892c8SHong Zhang if (allowzeropivot) { 31867b6c816cSBarry Smith A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 31877b6c816cSBarry Smith A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]); 31887b6c816cSBarry Smith A->factorerror_zeropivot_row = i; 31899566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n", i, (double)PetscAbsScalar(diag[i]), (double)PETSC_MACHINE_EPSILON)); 319098921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g", i, (double)PetscAbsScalar(diag[i]), (double)PETSC_MACHINE_EPSILON); 3191ec1892c8SHong Zhang } 3192bbead8a2SBarry Smith diag[i] = (PetscScalar)1.0 / (diag[i] + shift); 3193bbead8a2SBarry Smith } 3194bbead8a2SBarry Smith break; 3195bbead8a2SBarry Smith case 2: 3196bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 31979371c9d4SSatish Balay ij[0] = 2 * i; 31989371c9d4SSatish Balay ij[1] = 2 * i + 1; 31999566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 2, ij, 2, ij, diag)); 32009566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected)); 32017b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32029566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_2(diag)); 3203bbead8a2SBarry Smith diag += 4; 3204bbead8a2SBarry Smith } 3205bbead8a2SBarry Smith break; 3206bbead8a2SBarry Smith case 3: 3207bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32089371c9d4SSatish Balay ij[0] = 3 * i; 32099371c9d4SSatish Balay ij[1] = 3 * i + 1; 32109371c9d4SSatish Balay ij[2] = 3 * i + 2; 32119566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 3, ij, 3, ij, diag)); 32129566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected)); 32137b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32149566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_3(diag)); 3215bbead8a2SBarry Smith diag += 9; 3216bbead8a2SBarry Smith } 3217bbead8a2SBarry Smith break; 3218bbead8a2SBarry Smith case 4: 3219bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32209371c9d4SSatish Balay ij[0] = 4 * i; 32219371c9d4SSatish Balay ij[1] = 4 * i + 1; 32229371c9d4SSatish Balay ij[2] = 4 * i + 2; 32239371c9d4SSatish Balay ij[3] = 4 * i + 3; 32249566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 4, ij, 4, ij, diag)); 32259566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected)); 32267b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32279566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_4(diag)); 3228bbead8a2SBarry Smith diag += 16; 3229bbead8a2SBarry Smith } 3230bbead8a2SBarry Smith break; 3231bbead8a2SBarry Smith case 5: 3232bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32339371c9d4SSatish Balay ij[0] = 5 * i; 32349371c9d4SSatish Balay ij[1] = 5 * i + 1; 32359371c9d4SSatish Balay ij[2] = 5 * i + 2; 32369371c9d4SSatish Balay ij[3] = 5 * i + 3; 32379371c9d4SSatish Balay ij[4] = 5 * i + 4; 32389566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 5, ij, 5, ij, diag)); 32399566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected)); 32407b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32419566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_5(diag)); 3242bbead8a2SBarry Smith diag += 25; 3243bbead8a2SBarry Smith } 3244bbead8a2SBarry Smith break; 3245bbead8a2SBarry Smith case 6: 3246bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32479371c9d4SSatish Balay ij[0] = 6 * i; 32489371c9d4SSatish Balay ij[1] = 6 * i + 1; 32499371c9d4SSatish Balay ij[2] = 6 * i + 2; 32509371c9d4SSatish Balay ij[3] = 6 * i + 3; 32519371c9d4SSatish Balay ij[4] = 6 * i + 4; 32529371c9d4SSatish Balay ij[5] = 6 * i + 5; 32539566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 6, ij, 6, ij, diag)); 32549566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected)); 32557b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32569566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_6(diag)); 3257bbead8a2SBarry Smith diag += 36; 3258bbead8a2SBarry Smith } 3259bbead8a2SBarry Smith break; 3260bbead8a2SBarry Smith case 7: 3261bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32629371c9d4SSatish Balay ij[0] = 7 * i; 32639371c9d4SSatish Balay ij[1] = 7 * i + 1; 32649371c9d4SSatish Balay ij[2] = 7 * i + 2; 32659371c9d4SSatish Balay ij[3] = 7 * i + 3; 32669371c9d4SSatish Balay ij[4] = 7 * i + 4; 32679371c9d4SSatish Balay ij[5] = 7 * i + 5; 32689371c9d4SSatish Balay ij[5] = 7 * i + 6; 32699566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, 7, ij, 7, ij, diag)); 32709566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected)); 32717b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32729566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_7(diag)); 3273bbead8a2SBarry Smith diag += 49; 3274bbead8a2SBarry Smith } 3275bbead8a2SBarry Smith break; 3276bbead8a2SBarry Smith default: 32779566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(bs, &v_work, bs, &v_pivots, bs, &IJ)); 3278bbead8a2SBarry Smith for (i = 0; i < mbs; i++) { 32799371c9d4SSatish Balay for (j = 0; j < bs; j++) { IJ[j] = bs * i + j; } 32809566063dSJacob Faibussowitsch PetscCall(MatGetValues(A, bs, IJ, bs, IJ, diag)); 32819566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A(bs, diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected)); 32827b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 32839566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_N(diag, bs)); 3284bbead8a2SBarry Smith diag += bs2; 3285bbead8a2SBarry Smith } 32869566063dSJacob Faibussowitsch PetscCall(PetscFree3(v_work, v_pivots, IJ)); 3287bbead8a2SBarry Smith } 3288bbead8a2SBarry Smith a->ibdiagvalid = PETSC_TRUE; 3289bbead8a2SBarry Smith PetscFunctionReturn(0); 3290bbead8a2SBarry Smith } 3291bbead8a2SBarry Smith 32929371c9d4SSatish Balay static PetscErrorCode MatSetRandom_SeqAIJ(Mat x, PetscRandom rctx) { 329373a71a0fSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data; 3294fff043a9SJunchao Zhang PetscScalar a, *aa; 329573a71a0fSBarry Smith PetscInt m, n, i, j, col; 329673a71a0fSBarry Smith 329773a71a0fSBarry Smith PetscFunctionBegin; 329873a71a0fSBarry Smith if (!x->assembled) { 32999566063dSJacob Faibussowitsch PetscCall(MatGetSize(x, &m, &n)); 330073a71a0fSBarry Smith for (i = 0; i < m; i++) { 330173a71a0fSBarry Smith for (j = 0; j < aij->imax[i]; j++) { 33029566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx, &a)); 330373a71a0fSBarry Smith col = (PetscInt)(n * PetscRealPart(a)); 33049566063dSJacob Faibussowitsch PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES)); 330573a71a0fSBarry Smith } 330673a71a0fSBarry Smith } 3307e2ce353bSJunchao Zhang } else { 33089566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayWrite(x, &aa)); 33099566063dSJacob Faibussowitsch for (i = 0; i < aij->nz; i++) PetscCall(PetscRandomGetValue(rctx, aa + i)); 33109566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayWrite(x, &aa)); 3311e2ce353bSJunchao Zhang } 33129566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 33139566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 331473a71a0fSBarry Smith PetscFunctionReturn(0); 331573a71a0fSBarry Smith } 331673a71a0fSBarry Smith 3317679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */ 33189371c9d4SSatish Balay PetscErrorCode MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x, PetscInt low, PetscInt high, PetscRandom rctx) { 3319679944adSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data; 3320679944adSJunchao Zhang PetscScalar a; 3321679944adSJunchao Zhang PetscInt m, n, i, j, col, nskip; 3322679944adSJunchao Zhang 3323679944adSJunchao Zhang PetscFunctionBegin; 3324679944adSJunchao Zhang nskip = high - low; 33259566063dSJacob Faibussowitsch PetscCall(MatGetSize(x, &m, &n)); 3326679944adSJunchao Zhang n -= nskip; /* shrink number of columns where nonzeros can be set */ 3327679944adSJunchao Zhang for (i = 0; i < m; i++) { 3328679944adSJunchao Zhang for (j = 0; j < aij->imax[i]; j++) { 33299566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx, &a)); 3330679944adSJunchao Zhang col = (PetscInt)(n * PetscRealPart(a)); 3331679944adSJunchao Zhang if (col >= low) col += nskip; /* shift col rightward to skip the hole */ 33329566063dSJacob Faibussowitsch PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES)); 3333679944adSJunchao Zhang } 3334e2ce353bSJunchao Zhang } 33359566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 33369566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 3337679944adSJunchao Zhang PetscFunctionReturn(0); 3338679944adSJunchao Zhang } 3339679944adSJunchao Zhang 3340682d7d0cSBarry Smith /* -------------------------------------------------------------------*/ 33410a6ffc59SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ, 3342cb5b572fSBarry Smith MatGetRow_SeqAIJ, 3343cb5b572fSBarry Smith MatRestoreRow_SeqAIJ, 3344cb5b572fSBarry Smith MatMult_SeqAIJ, 334597304618SKris Buschelman /* 4*/ MatMultAdd_SeqAIJ, 33467c922b88SBarry Smith MatMultTranspose_SeqAIJ, 33477c922b88SBarry Smith MatMultTransposeAdd_SeqAIJ, 3348f4259b30SLisandro Dalcin NULL, 3349f4259b30SLisandro Dalcin NULL, 3350f4259b30SLisandro Dalcin NULL, 3351f4259b30SLisandro Dalcin /* 10*/ NULL, 3352cb5b572fSBarry Smith MatLUFactor_SeqAIJ, 3353f4259b30SLisandro Dalcin NULL, 335441f059aeSBarry Smith MatSOR_SeqAIJ, 335591e9d3e2SHong Zhang MatTranspose_SeqAIJ, 335697304618SKris Buschelman /*1 5*/ MatGetInfo_SeqAIJ, 3357cb5b572fSBarry Smith MatEqual_SeqAIJ, 3358cb5b572fSBarry Smith MatGetDiagonal_SeqAIJ, 3359cb5b572fSBarry Smith MatDiagonalScale_SeqAIJ, 3360cb5b572fSBarry Smith MatNorm_SeqAIJ, 3361f4259b30SLisandro Dalcin /* 20*/ NULL, 3362cb5b572fSBarry Smith MatAssemblyEnd_SeqAIJ, 3363cb5b572fSBarry Smith MatSetOption_SeqAIJ, 3364cb5b572fSBarry Smith MatZeroEntries_SeqAIJ, 3365d519adbfSMatthew Knepley /* 24*/ MatZeroRows_SeqAIJ, 3366f4259b30SLisandro Dalcin NULL, 3367f4259b30SLisandro Dalcin NULL, 3368f4259b30SLisandro Dalcin NULL, 3369f4259b30SLisandro Dalcin NULL, 33704994cf47SJed Brown /* 29*/ MatSetUp_SeqAIJ, 3371f4259b30SLisandro Dalcin NULL, 3372f4259b30SLisandro Dalcin NULL, 3373f4259b30SLisandro Dalcin NULL, 3374f4259b30SLisandro Dalcin NULL, 3375d519adbfSMatthew Knepley /* 34*/ MatDuplicate_SeqAIJ, 3376f4259b30SLisandro Dalcin NULL, 3377f4259b30SLisandro Dalcin NULL, 3378cb5b572fSBarry Smith MatILUFactor_SeqAIJ, 3379f4259b30SLisandro Dalcin NULL, 3380d519adbfSMatthew Knepley /* 39*/ MatAXPY_SeqAIJ, 33817dae84e0SHong Zhang MatCreateSubMatrices_SeqAIJ, 3382cb5b572fSBarry Smith MatIncreaseOverlap_SeqAIJ, 3383cb5b572fSBarry Smith MatGetValues_SeqAIJ, 3384cb5b572fSBarry Smith MatCopy_SeqAIJ, 3385d519adbfSMatthew Knepley /* 44*/ MatGetRowMax_SeqAIJ, 3386cb5b572fSBarry Smith MatScale_SeqAIJ, 33877d68702bSBarry Smith MatShift_SeqAIJ, 338879299369SBarry Smith MatDiagonalSet_SeqAIJ, 33896e169961SBarry Smith MatZeroRowsColumns_SeqAIJ, 339073a71a0fSBarry Smith /* 49*/ MatSetRandom_SeqAIJ, 33913b2fbd54SBarry Smith MatGetRowIJ_SeqAIJ, 33923b2fbd54SBarry Smith MatRestoreRowIJ_SeqAIJ, 33933b2fbd54SBarry Smith MatGetColumnIJ_SeqAIJ, 3394a93ec695SBarry Smith MatRestoreColumnIJ_SeqAIJ, 339593dfae19SHong Zhang /* 54*/ MatFDColoringCreate_SeqXAIJ, 3396f4259b30SLisandro Dalcin NULL, 3397f4259b30SLisandro Dalcin NULL, 3398cda55fadSBarry Smith MatPermute_SeqAIJ, 3399f4259b30SLisandro Dalcin NULL, 3400f4259b30SLisandro Dalcin /* 59*/ NULL, 3401b9b97703SBarry Smith MatDestroy_SeqAIJ, 3402b9b97703SBarry Smith MatView_SeqAIJ, 3403f4259b30SLisandro Dalcin NULL, 3404f4259b30SLisandro Dalcin NULL, 3405f4259b30SLisandro Dalcin /* 64*/ NULL, 3406321b30b9SSatish Balay MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ, 3407f4259b30SLisandro Dalcin NULL, 3408f4259b30SLisandro Dalcin NULL, 3409f4259b30SLisandro Dalcin NULL, 3410d519adbfSMatthew Knepley /* 69*/ MatGetRowMaxAbs_SeqAIJ, 3411c87e5d42SMatthew Knepley MatGetRowMinAbs_SeqAIJ, 3412f4259b30SLisandro Dalcin NULL, 3413f4259b30SLisandro Dalcin NULL, 3414f4259b30SLisandro Dalcin NULL, 3415f4259b30SLisandro Dalcin /* 74*/ NULL, 34163acb8795SBarry Smith MatFDColoringApply_AIJ, 3417f4259b30SLisandro Dalcin NULL, 3418f4259b30SLisandro Dalcin NULL, 3419f4259b30SLisandro Dalcin NULL, 34206ce1633cSBarry Smith /* 79*/ MatFindZeroDiagonals_SeqAIJ, 3421f4259b30SLisandro Dalcin NULL, 3422f4259b30SLisandro Dalcin NULL, 3423f4259b30SLisandro Dalcin NULL, 3424bc011b1eSHong Zhang MatLoad_SeqAIJ, 3425d519adbfSMatthew Knepley /* 84*/ MatIsSymmetric_SeqAIJ, 34261cbb95d3SBarry Smith MatIsHermitian_SeqAIJ, 3427f4259b30SLisandro Dalcin NULL, 3428f4259b30SLisandro Dalcin NULL, 3429f4259b30SLisandro Dalcin NULL, 3430f4259b30SLisandro Dalcin /* 89*/ NULL, 3431f4259b30SLisandro Dalcin NULL, 343226be0446SHong Zhang MatMatMultNumeric_SeqAIJ_SeqAIJ, 3433f4259b30SLisandro Dalcin NULL, 3434f4259b30SLisandro Dalcin NULL, 34358fa4b5a6SHong Zhang /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy, 3436f4259b30SLisandro Dalcin NULL, 3437f4259b30SLisandro Dalcin NULL, 34386fc122caSHong Zhang MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ, 3439f4259b30SLisandro Dalcin NULL, 34404222ddf1SHong Zhang /* 99*/ MatProductSetFromOptions_SeqAIJ, 3441f4259b30SLisandro Dalcin NULL, 3442f4259b30SLisandro Dalcin NULL, 344387d4246cSBarry Smith MatConjugate_SeqAIJ, 3444f4259b30SLisandro Dalcin NULL, 3445d519adbfSMatthew Knepley /*104*/ MatSetValuesRow_SeqAIJ, 344699cafbc1SBarry Smith MatRealPart_SeqAIJ, 3447f5edf698SHong Zhang MatImaginaryPart_SeqAIJ, 3448f4259b30SLisandro Dalcin NULL, 3449f4259b30SLisandro Dalcin NULL, 3450cbd44569SHong Zhang /*109*/ MatMatSolve_SeqAIJ, 3451f4259b30SLisandro Dalcin NULL, 34522af78befSBarry Smith MatGetRowMin_SeqAIJ, 3453f4259b30SLisandro Dalcin NULL, 3454599ef60dSHong Zhang MatMissingDiagonal_SeqAIJ, 3455f4259b30SLisandro Dalcin /*114*/ NULL, 3456f4259b30SLisandro Dalcin NULL, 3457f4259b30SLisandro Dalcin NULL, 3458f4259b30SLisandro Dalcin NULL, 3459f4259b30SLisandro Dalcin NULL, 3460f4259b30SLisandro Dalcin /*119*/ NULL, 3461f4259b30SLisandro Dalcin NULL, 3462f4259b30SLisandro Dalcin NULL, 3463f4259b30SLisandro Dalcin NULL, 3464b3a44c85SBarry Smith MatGetMultiProcBlock_SeqAIJ, 34650716a85fSBarry Smith /*124*/ MatFindNonzeroRows_SeqAIJ, 3466a873a8cdSSam Reynolds MatGetColumnReductions_SeqAIJ, 346737868618SMatthew G Knepley MatInvertBlockDiagonal_SeqAIJ, 34680da83c2eSBarry Smith MatInvertVariableBlockDiagonal_SeqAIJ, 3469f4259b30SLisandro Dalcin NULL, 3470f4259b30SLisandro Dalcin /*129*/ NULL, 3471f4259b30SLisandro Dalcin NULL, 3472f4259b30SLisandro Dalcin NULL, 347375648e8dSHong Zhang MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ, 3474b9af6bddSHong Zhang MatTransposeColoringCreate_SeqAIJ, 3475b9af6bddSHong Zhang /*134*/ MatTransColoringApplySpToDen_SeqAIJ, 34762b8ad9a3SHong Zhang MatTransColoringApplyDenToSp_SeqAIJ, 3477f4259b30SLisandro Dalcin NULL, 3478f4259b30SLisandro Dalcin NULL, 34793964eb88SJed Brown MatRARtNumeric_SeqAIJ_SeqAIJ, 3480f4259b30SLisandro Dalcin /*139*/ NULL, 3481f4259b30SLisandro Dalcin NULL, 3482f4259b30SLisandro Dalcin NULL, 34833a062f41SBarry Smith MatFDColoringSetUp_SeqXAIJ, 34849c8f2541SHong Zhang MatFindOffBlockDiagonalEntries_SeqAIJ, 34854222ddf1SHong Zhang MatCreateMPIMatConcatenateSeqMat_SeqAIJ, 34864222ddf1SHong Zhang /*145*/ MatDestroySubMatrices_SeqAIJ, 3487f4259b30SLisandro Dalcin NULL, 348872833a62Smarkadams4 NULL, 348972833a62Smarkadams4 MatCreateGraph_Simple_AIJ, 34907fb60732SBarry Smith MatFilter_AIJ, 34919371c9d4SSatish Balay /*150*/ MatTransposeSymbolic_SeqAIJ}; 349217ab2063SBarry Smith 34939371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat, PetscInt *indices) { 3494bef8e0ddSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 349597f1f81fSBarry Smith PetscInt i, nz, n; 3496bef8e0ddSBarry Smith 3497bef8e0ddSBarry Smith PetscFunctionBegin; 3498bef8e0ddSBarry Smith nz = aij->maxnz; 3499d0f46423SBarry Smith n = mat->rmap->n; 35009371c9d4SSatish Balay for (i = 0; i < nz; i++) { aij->j[i] = indices[i]; } 3501bef8e0ddSBarry Smith aij->nz = nz; 35029371c9d4SSatish Balay for (i = 0; i < n; i++) { aij->ilen[i] = aij->imax[i]; } 3503bef8e0ddSBarry Smith PetscFunctionReturn(0); 3504bef8e0ddSBarry Smith } 3505bef8e0ddSBarry Smith 3506a3bb6f32SFande Kong /* 3507ddea5d60SJunchao Zhang * Given a sparse matrix with global column indices, compact it by using a local column space. 3508ddea5d60SJunchao Zhang * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable() 3509ddea5d60SJunchao Zhang */ 35109371c9d4SSatish Balay PetscErrorCode MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping) { 3511a3bb6f32SFande Kong Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3512a3bb6f32SFande Kong PetscTable gid1_lid1; 3513a3bb6f32SFande Kong PetscTablePosition tpos; 351425b670f0SStefano Zampini PetscInt gid, lid, i, ec, nz = aij->nz; 351525b670f0SStefano Zampini PetscInt *garray, *jj = aij->j; 3516a3bb6f32SFande Kong 3517a3bb6f32SFande Kong PetscFunctionBegin; 3518a3bb6f32SFande Kong PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3519a3bb6f32SFande Kong PetscValidPointer(mapping, 2); 3520a3bb6f32SFande Kong /* use a table */ 35219566063dSJacob Faibussowitsch PetscCall(PetscTableCreate(mat->rmap->n, mat->cmap->N + 1, &gid1_lid1)); 3522a3bb6f32SFande Kong ec = 0; 352325b670f0SStefano Zampini for (i = 0; i < nz; i++) { 352425b670f0SStefano Zampini PetscInt data, gid1 = jj[i] + 1; 35259566063dSJacob Faibussowitsch PetscCall(PetscTableFind(gid1_lid1, gid1, &data)); 3526a3bb6f32SFande Kong if (!data) { 3527a3bb6f32SFande Kong /* one based table */ 35289566063dSJacob Faibussowitsch PetscCall(PetscTableAdd(gid1_lid1, gid1, ++ec, INSERT_VALUES)); 3529a3bb6f32SFande Kong } 3530a3bb6f32SFande Kong } 3531a3bb6f32SFande Kong /* form array of columns we need */ 35329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ec, &garray)); 35339566063dSJacob Faibussowitsch PetscCall(PetscTableGetHeadPosition(gid1_lid1, &tpos)); 3534a3bb6f32SFande Kong while (tpos) { 35359566063dSJacob Faibussowitsch PetscCall(PetscTableGetNext(gid1_lid1, &tpos, &gid, &lid)); 3536a3bb6f32SFande Kong gid--; 3537a3bb6f32SFande Kong lid--; 3538a3bb6f32SFande Kong garray[lid] = gid; 3539a3bb6f32SFande Kong } 35409566063dSJacob Faibussowitsch PetscCall(PetscSortInt(ec, garray)); /* sort, and rebuild */ 35419566063dSJacob Faibussowitsch PetscCall(PetscTableRemoveAll(gid1_lid1)); 3542*48a46eb9SPierre Jolivet for (i = 0; i < ec; i++) PetscCall(PetscTableAdd(gid1_lid1, garray[i] + 1, i + 1, INSERT_VALUES)); 3543a3bb6f32SFande Kong /* compact out the extra columns in B */ 354425b670f0SStefano Zampini for (i = 0; i < nz; i++) { 354525b670f0SStefano Zampini PetscInt gid1 = jj[i] + 1; 35469566063dSJacob Faibussowitsch PetscCall(PetscTableFind(gid1_lid1, gid1, &lid)); 3547a3bb6f32SFande Kong lid--; 354825b670f0SStefano Zampini jj[i] = lid; 3549a3bb6f32SFande Kong } 35509566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&mat->cmap)); 35519566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy(&gid1_lid1)); 35529566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat), ec, ec, 1, &mat->cmap)); 35539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, mat->cmap->bs, mat->cmap->n, garray, PETSC_OWN_POINTER, mapping)); 35549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*mapping, ISLOCALTOGLOBALMAPPINGHASH)); 3555a3bb6f32SFande Kong PetscFunctionReturn(0); 3556a3bb6f32SFande Kong } 3557a3bb6f32SFande Kong 3558bef8e0ddSBarry Smith /*@ 3559bef8e0ddSBarry Smith MatSeqAIJSetColumnIndices - Set the column indices for all the rows 3560bef8e0ddSBarry Smith in the matrix. 3561bef8e0ddSBarry Smith 3562bef8e0ddSBarry Smith Input Parameters: 3563bef8e0ddSBarry Smith + mat - the SeqAIJ matrix 3564bef8e0ddSBarry Smith - indices - the column indices 3565bef8e0ddSBarry Smith 356615091d37SBarry Smith Level: advanced 356715091d37SBarry Smith 3568bef8e0ddSBarry Smith Notes: 3569bef8e0ddSBarry Smith This can be called if you have precomputed the nonzero structure of the 3570bef8e0ddSBarry Smith matrix and want to provide it to the matrix object to improve the performance 3571bef8e0ddSBarry Smith of the MatSetValues() operation. 3572bef8e0ddSBarry Smith 3573bef8e0ddSBarry Smith You MUST have set the correct numbers of nonzeros per row in the call to 3574d1be2dadSMatthew Knepley MatCreateSeqAIJ(), and the columns indices MUST be sorted. 3575bef8e0ddSBarry Smith 3576bef8e0ddSBarry Smith MUST be called before any calls to MatSetValues(); 3577bef8e0ddSBarry Smith 3578b9617806SBarry Smith The indices should start with zero, not one. 3579b9617806SBarry Smith 3580bef8e0ddSBarry Smith @*/ 35819371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat, PetscInt *indices) { 3582bef8e0ddSBarry Smith PetscFunctionBegin; 35830700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3584dadcf809SJacob Faibussowitsch PetscValidIntPointer(indices, 2); 3585cac4c232SBarry Smith PetscUseMethod(mat, "MatSeqAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices)); 3586bef8e0ddSBarry Smith PetscFunctionReturn(0); 3587bef8e0ddSBarry Smith } 3588bef8e0ddSBarry Smith 3589be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/ 3590be6bf707SBarry Smith 35919371c9d4SSatish Balay PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) { 3592be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3593d0f46423SBarry Smith size_t nz = aij->i[mat->rmap->n]; 3594be6bf707SBarry Smith 3595be6bf707SBarry Smith PetscFunctionBegin; 359628b400f6SJacob Faibussowitsch PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3597be6bf707SBarry Smith 3598be6bf707SBarry Smith /* allocate space for values if not already there */ 3599be6bf707SBarry Smith if (!aij->saved_values) { 36009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz + 1, &aij->saved_values)); 36019566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)mat, (nz + 1) * sizeof(PetscScalar))); 3602be6bf707SBarry Smith } 3603be6bf707SBarry Smith 3604be6bf707SBarry Smith /* copy values over */ 36059566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz)); 3606be6bf707SBarry Smith PetscFunctionReturn(0); 3607be6bf707SBarry Smith } 3608be6bf707SBarry Smith 3609be6bf707SBarry Smith /*@ 3610be6bf707SBarry Smith MatStoreValues - Stashes a copy of the matrix values; this allows, for 3611be6bf707SBarry Smith example, reuse of the linear part of a Jacobian, while recomputing the 3612be6bf707SBarry Smith nonlinear portion. 3613be6bf707SBarry Smith 3614be6bf707SBarry Smith Collect on Mat 3615be6bf707SBarry Smith 3616be6bf707SBarry Smith Input Parameters: 36170e609b76SBarry Smith . mat - the matrix (currently only AIJ matrices support this option) 3618be6bf707SBarry Smith 361915091d37SBarry Smith Level: advanced 362015091d37SBarry Smith 3621be6bf707SBarry Smith Common Usage, with SNESSolve(): 3622be6bf707SBarry Smith $ Create Jacobian matrix 3623be6bf707SBarry Smith $ Set linear terms into matrix 3624be6bf707SBarry Smith $ Apply boundary conditions to matrix, at this time matrix must have 3625be6bf707SBarry Smith $ final nonzero structure (i.e. setting the nonlinear terms and applying 3626be6bf707SBarry Smith $ boundary conditions again will not change the nonzero structure 3627512a5fc5SBarry Smith $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3628be6bf707SBarry Smith $ ierr = MatStoreValues(mat); 3629be6bf707SBarry Smith $ Call SNESSetJacobian() with matrix 3630be6bf707SBarry Smith $ In your Jacobian routine 3631be6bf707SBarry Smith $ ierr = MatRetrieveValues(mat); 3632be6bf707SBarry Smith $ Set nonlinear terms in matrix 3633be6bf707SBarry Smith 3634be6bf707SBarry Smith Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself: 3635be6bf707SBarry Smith $ // build linear portion of Jacobian 3636512a5fc5SBarry Smith $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3637be6bf707SBarry Smith $ ierr = MatStoreValues(mat); 3638be6bf707SBarry Smith $ loop over nonlinear iterations 3639be6bf707SBarry Smith $ ierr = MatRetrieveValues(mat); 3640be6bf707SBarry Smith $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian 3641be6bf707SBarry Smith $ // call MatAssemblyBegin/End() on matrix 3642be6bf707SBarry Smith $ Solve linear system with Jacobian 3643be6bf707SBarry Smith $ endloop 3644be6bf707SBarry Smith 3645be6bf707SBarry Smith Notes: 3646be6bf707SBarry Smith Matrix must already be assemblied before calling this routine 3647512a5fc5SBarry Smith Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before 3648be6bf707SBarry Smith calling this routine. 3649be6bf707SBarry Smith 36500c468ba9SBarry Smith When this is called multiple times it overwrites the previous set of stored values 36510c468ba9SBarry Smith and does not allocated additional space. 36520c468ba9SBarry Smith 3653db781477SPatrick Sanan .seealso: `MatRetrieveValues()` 3654be6bf707SBarry Smith 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 3682be6bf707SBarry Smith Collect on Mat 3683be6bf707SBarry Smith 3684be6bf707SBarry Smith Input Parameters: 3685386f7cf9SBarry Smith . mat - the matrix (currently only AIJ matrices support this option) 3686be6bf707SBarry Smith 368715091d37SBarry Smith Level: advanced 368815091d37SBarry Smith 3689db781477SPatrick Sanan .seealso: `MatStoreValues()` 3690be6bf707SBarry Smith 3691be6bf707SBarry Smith @*/ 36929371c9d4SSatish Balay PetscErrorCode MatRetrieveValues(Mat mat) { 3693be6bf707SBarry Smith PetscFunctionBegin; 36940700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 369528b400f6SJacob Faibussowitsch PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 369628b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3697cac4c232SBarry Smith PetscUseMethod(mat, "MatRetrieveValues_C", (Mat), (mat)); 3698be6bf707SBarry Smith PetscFunctionReturn(0); 3699be6bf707SBarry Smith } 3700be6bf707SBarry Smith 3701be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/ 370217ab2063SBarry Smith /*@C 3703682d7d0cSBarry Smith MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format 37040d15e28bSLois Curfman McInnes (the default parallel PETSc format). For good matrix assembly performance 37056e62573dSLois Curfman McInnes the user should preallocate the matrix storage by setting the parameter nz 370651c19458SBarry Smith (or the array nnz). By setting these parameters accurately, performance 37072bd5e0b2SLois Curfman McInnes during matrix assembly can be increased by more than a factor of 50. 370817ab2063SBarry Smith 3709d083f849SBarry Smith Collective 3710db81eaa0SLois Curfman McInnes 371117ab2063SBarry Smith Input Parameters: 3712db81eaa0SLois Curfman McInnes + comm - MPI communicator, set to PETSC_COMM_SELF 371317ab2063SBarry Smith . m - number of rows 371417ab2063SBarry Smith . n - number of columns 371517ab2063SBarry Smith . nz - number of nonzeros per row (same for all rows) 371651c19458SBarry Smith - nnz - array containing the number of nonzeros in the various rows 37170298fd71SBarry Smith (possibly different for each row) or NULL 371817ab2063SBarry Smith 371917ab2063SBarry Smith Output Parameter: 3720416022c9SBarry Smith . A - the matrix 372117ab2063SBarry Smith 3722175b88e8SBarry Smith It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 3723f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly. 3724175b88e8SBarry Smith [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 3725175b88e8SBarry Smith 3726b259b22eSLois Curfman McInnes Notes: 372749a6f317SBarry Smith If nnz is given then nz is ignored 372849a6f317SBarry Smith 372917ab2063SBarry Smith The AIJ format (also called the Yale sparse matrix format or 373017ab2063SBarry Smith compressed row storage), is fully compatible with standard Fortran 77 37310002213bSLois Curfman McInnes storage. That is, the stored row and column indices can begin at 373244cd7ae7SLois Curfman McInnes either one (as in Fortran) or zero. See the users' manual for details. 373317ab2063SBarry Smith 373417ab2063SBarry Smith Specify the preallocated storage with either nz or nnz (not both). 37350298fd71SBarry Smith Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 37363d323bbdSBarry Smith allocation. For large problems you MUST preallocate memory or you 37376da5968aSLois Curfman McInnes will get TERRIBLE performance, see the users' manual chapter on matrices. 373817ab2063SBarry Smith 3739682d7d0cSBarry Smith By default, this format uses inodes (identical nodes) when possible, to 37404fca80b9SLois Curfman McInnes improve numerical efficiency of matrix-vector products and solves. We 3741682d7d0cSBarry Smith search for consecutive rows with the same nonzero structure, thereby 37426c7ebb05SLois Curfman McInnes reusing matrix information to achieve increased efficiency. 37436c7ebb05SLois Curfman McInnes 37446c7ebb05SLois Curfman McInnes Options Database Keys: 3745698d4c6aSKris Buschelman + -mat_no_inode - Do not use inodes 37469db58ca8SBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 374717ab2063SBarry Smith 3748027ccd11SLois Curfman McInnes Level: intermediate 3749027ccd11SLois Curfman McInnes 3750db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()` 375136db0b34SBarry Smith 375217ab2063SBarry Smith @*/ 37539371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A) { 37543a40ed3dSBarry Smith PetscFunctionBegin; 37559566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 37569566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, m, n)); 37579566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATSEQAIJ)); 37589566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*A, nz, nnz)); 3759273d9f13SBarry Smith PetscFunctionReturn(0); 3760273d9f13SBarry Smith } 3761273d9f13SBarry Smith 3762273d9f13SBarry Smith /*@C 3763273d9f13SBarry Smith MatSeqAIJSetPreallocation - For good matrix assembly performance 3764273d9f13SBarry Smith the user should preallocate the matrix storage by setting the parameter nz 3765273d9f13SBarry Smith (or the array nnz). By setting these parameters accurately, performance 3766273d9f13SBarry Smith during matrix assembly can be increased by more than a factor of 50. 3767273d9f13SBarry Smith 3768d083f849SBarry Smith Collective 3769273d9f13SBarry Smith 3770273d9f13SBarry Smith Input Parameters: 37711c4f3114SJed Brown + B - The matrix 3772273d9f13SBarry Smith . nz - number of nonzeros per row (same for all rows) 3773273d9f13SBarry Smith - nnz - array containing the number of nonzeros in the various rows 37740298fd71SBarry Smith (possibly different for each row) or NULL 3775273d9f13SBarry Smith 3776273d9f13SBarry Smith Notes: 377749a6f317SBarry Smith If nnz is given then nz is ignored 377849a6f317SBarry Smith 3779273d9f13SBarry Smith The AIJ format (also called the Yale sparse matrix format or 3780273d9f13SBarry Smith compressed row storage), is fully compatible with standard Fortran 77 3781273d9f13SBarry Smith storage. That is, the stored row and column indices can begin at 3782273d9f13SBarry Smith either one (as in Fortran) or zero. See the users' manual for details. 3783273d9f13SBarry Smith 3784273d9f13SBarry Smith Specify the preallocated storage with either nz or nnz (not both). 37850298fd71SBarry Smith Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 3786273d9f13SBarry Smith allocation. For large problems you MUST preallocate memory or you 3787273d9f13SBarry Smith will get TERRIBLE performance, see the users' manual chapter on matrices. 3788273d9f13SBarry Smith 3789aa95bbe8SBarry Smith You can call MatGetInfo() to get information on how effective the preallocation was; 3790aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 3791aa95bbe8SBarry Smith You can also run with the option -info and look for messages with the string 3792aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 3793aa95bbe8SBarry Smith 3794a96a251dSBarry Smith Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix 3795a96a251dSBarry Smith entries or columns indices 3796a96a251dSBarry Smith 3797273d9f13SBarry Smith By default, this format uses inodes (identical nodes) when possible, to 3798273d9f13SBarry Smith improve numerical efficiency of matrix-vector products and solves. We 3799273d9f13SBarry Smith search for consecutive rows with the same nonzero structure, thereby 3800273d9f13SBarry Smith reusing matrix information to achieve increased efficiency. 3801273d9f13SBarry Smith 3802273d9f13SBarry Smith Options Database Keys: 3803698d4c6aSKris Buschelman + -mat_no_inode - Do not use inodes 380447b2e64bSBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3805273d9f13SBarry Smith 3806273d9f13SBarry Smith Level: intermediate 3807273d9f13SBarry Smith 3808db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()`, `MatGetInfo()`, 3809db781477SPatrick Sanan `MatSeqAIJSetTotalPreallocation()` 3810273d9f13SBarry Smith 3811273d9f13SBarry Smith @*/ 38129371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocation(Mat B, PetscInt nz, const PetscInt nnz[]) { 3813a23d5eceSKris Buschelman PetscFunctionBegin; 38146ba663aaSJed Brown PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 38156ba663aaSJed Brown PetscValidType(B, 1); 3816cac4c232SBarry Smith PetscTryMethod(B, "MatSeqAIJSetPreallocation_C", (Mat, PetscInt, const PetscInt[]), (B, nz, nnz)); 3817a23d5eceSKris Buschelman PetscFunctionReturn(0); 3818a23d5eceSKris Buschelman } 3819a23d5eceSKris Buschelman 38209371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B, PetscInt nz, const PetscInt *nnz) { 3821273d9f13SBarry Smith Mat_SeqAIJ *b; 38222576faa2SJed Brown PetscBool skipallocation = PETSC_FALSE, realalloc = PETSC_FALSE; 382397f1f81fSBarry Smith PetscInt i; 3824273d9f13SBarry Smith 3825273d9f13SBarry Smith PetscFunctionBegin; 38262576faa2SJed Brown if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 3827a96a251dSBarry Smith if (nz == MAT_SKIP_ALLOCATION) { 3828c461c341SBarry Smith skipallocation = PETSC_TRUE; 3829c461c341SBarry Smith nz = 0; 3830c461c341SBarry Smith } 38319566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 38329566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 3833899cda47SBarry Smith 3834435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 383508401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz); 3836cf9c20a2SJed Brown if (PetscUnlikelyDebug(nnz)) { 3837d0f46423SBarry Smith for (i = 0; i < B->rmap->n; i++) { 383808401ef6SPierre 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]); 383908401ef6SPierre 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); 3840b73539f3SBarry Smith } 3841b73539f3SBarry Smith } 3842b73539f3SBarry Smith 3843273d9f13SBarry Smith B->preallocated = PETSC_TRUE; 38442205254eSKarl Rupp 3845273d9f13SBarry Smith b = (Mat_SeqAIJ *)B->data; 3846273d9f13SBarry Smith 3847ab93d7beSBarry Smith if (!skipallocation) { 38482ee49352SLisandro Dalcin if (!b->imax) { 38499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n, &b->imax)); 38509566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, B->rmap->n * sizeof(PetscInt))); 3851071fcb05SBarry Smith } 3852071fcb05SBarry Smith if (!b->ilen) { 3853071fcb05SBarry Smith /* b->ilen will count nonzeros in each row so far. */ 38549566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(B->rmap->n, &b->ilen)); 38559566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, B->rmap->n * sizeof(PetscInt))); 3856071fcb05SBarry Smith } else { 38579566063dSJacob Faibussowitsch PetscCall(PetscMemzero(b->ilen, B->rmap->n * sizeof(PetscInt))); 38582ee49352SLisandro Dalcin } 3859846b4da1SFande Kong if (!b->ipre) { 38609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n, &b->ipre)); 38619566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, B->rmap->n * sizeof(PetscInt))); 3862846b4da1SFande Kong } 3863273d9f13SBarry Smith if (!nnz) { 3864435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 3865c62bd62aSJed Brown else if (nz < 0) nz = 1; 38665d2a9ed1SStefano Zampini nz = PetscMin(nz, B->cmap->n); 3867d0f46423SBarry Smith for (i = 0; i < B->rmap->n; i++) b->imax[i] = nz; 3868d0f46423SBarry Smith nz = nz * B->rmap->n; 3869273d9f13SBarry Smith } else { 3870c73702f5SBarry Smith PetscInt64 nz64 = 0; 38719371c9d4SSatish Balay for (i = 0; i < B->rmap->n; i++) { 38729371c9d4SSatish Balay b->imax[i] = nnz[i]; 38739371c9d4SSatish Balay nz64 += nnz[i]; 38749371c9d4SSatish Balay } 38759566063dSJacob Faibussowitsch PetscCall(PetscIntCast(nz64, &nz)); 3876273d9f13SBarry Smith } 3877ab93d7beSBarry Smith 3878273d9f13SBarry Smith /* allocate the matrix space */ 387953dd7562SDmitry Karpeev /* FIXME: should B's old memory be unlogged? */ 38809566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i)); 3881396832f4SHong Zhang if (B->structure_only) { 38829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &b->j)); 38839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n + 1, &b->i)); 38849566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, (B->rmap->n + 1) * sizeof(PetscInt) + nz * sizeof(PetscInt))); 3885396832f4SHong Zhang } else { 38869566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(nz, &b->a, nz, &b->j, B->rmap->n + 1, &b->i)); 38879566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B, (B->rmap->n + 1) * sizeof(PetscInt) + nz * (sizeof(PetscScalar) + sizeof(PetscInt)))); 3888396832f4SHong Zhang } 3889bfeeae90SHong Zhang b->i[0] = 0; 38909371c9d4SSatish Balay for (i = 1; i < B->rmap->n + 1; i++) { b->i[i] = b->i[i - 1] + b->imax[i - 1]; } 3891396832f4SHong Zhang if (B->structure_only) { 3892396832f4SHong Zhang b->singlemalloc = PETSC_FALSE; 3893396832f4SHong Zhang b->free_a = PETSC_FALSE; 3894396832f4SHong Zhang } else { 3895273d9f13SBarry Smith b->singlemalloc = PETSC_TRUE; 3896e6b907acSBarry Smith b->free_a = PETSC_TRUE; 3897396832f4SHong Zhang } 3898e6b907acSBarry Smith b->free_ij = PETSC_TRUE; 3899c461c341SBarry Smith } else { 3900e6b907acSBarry Smith b->free_a = PETSC_FALSE; 3901e6b907acSBarry Smith b->free_ij = PETSC_FALSE; 3902c461c341SBarry Smith } 3903273d9f13SBarry Smith 3904846b4da1SFande Kong if (b->ipre && nnz != b->ipre && b->imax) { 3905846b4da1SFande Kong /* reserve user-requested sparsity */ 39069566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->ipre, b->imax, B->rmap->n)); 3907846b4da1SFande Kong } 3908846b4da1SFande Kong 3909273d9f13SBarry Smith b->nz = 0; 3910273d9f13SBarry Smith b->maxnz = nz; 3911273d9f13SBarry Smith B->info.nz_unneeded = (double)b->maxnz; 39121baa6e33SBarry Smith if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 3913cb7b82ddSBarry Smith B->was_assembled = PETSC_FALSE; 3914cb7b82ddSBarry Smith B->assembled = PETSC_FALSE; 39155519a089SJose E. Roman /* We simply deem preallocation has changed nonzero state. Updating the state 39165519a089SJose E. Roman will give clients (like AIJKokkos) a chance to know something has happened. 39175519a089SJose E. Roman */ 39185519a089SJose E. Roman B->nonzerostate++; 3919273d9f13SBarry Smith PetscFunctionReturn(0); 3920273d9f13SBarry Smith } 3921273d9f13SBarry Smith 39229371c9d4SSatish Balay PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A) { 3923846b4da1SFande Kong Mat_SeqAIJ *a; 3924a5bbaf83SFande Kong PetscInt i; 3925846b4da1SFande Kong 3926846b4da1SFande Kong PetscFunctionBegin; 3927846b4da1SFande Kong PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 392814d0e64fSAlex Lindsay 392914d0e64fSAlex Lindsay /* Check local size. If zero, then return */ 393014d0e64fSAlex Lindsay if (!A->rmap->n) PetscFunctionReturn(0); 393114d0e64fSAlex Lindsay 3932846b4da1SFande Kong a = (Mat_SeqAIJ *)A->data; 39332c814fdeSFande Kong /* if no saved info, we error out */ 393428b400f6SJacob Faibussowitsch PetscCheck(a->ipre, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "No saved preallocation info "); 39352c814fdeSFande Kong 3936aed4548fSBarry 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 "); 39372c814fdeSFande Kong 39389566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->imax, a->ipre, A->rmap->n)); 39399566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(a->ilen, A->rmap->n)); 3940846b4da1SFande Kong a->i[0] = 0; 39419371c9d4SSatish Balay for (i = 1; i < A->rmap->n + 1; i++) { a->i[i] = a->i[i - 1] + a->imax[i - 1]; } 3942846b4da1SFande Kong A->preallocated = PETSC_TRUE; 3943846b4da1SFande Kong a->nz = 0; 3944846b4da1SFande Kong a->maxnz = a->i[A->rmap->n]; 3945846b4da1SFande Kong A->info.nz_unneeded = (double)a->maxnz; 3946846b4da1SFande Kong A->was_assembled = PETSC_FALSE; 3947846b4da1SFande Kong A->assembled = PETSC_FALSE; 3948846b4da1SFande Kong PetscFunctionReturn(0); 3949846b4da1SFande Kong } 3950846b4da1SFande Kong 395158d36128SBarry Smith /*@ 3952a1661176SMatthew Knepley MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format. 3953a1661176SMatthew Knepley 3954a1661176SMatthew Knepley Input Parameters: 3955a1661176SMatthew Knepley + B - the matrix 3956a1661176SMatthew Knepley . i - the indices into j for the start of each row (starts with zero) 3957a1661176SMatthew Knepley . j - the column indices for each row (starts with zero) these must be sorted for each row 3958a1661176SMatthew Knepley - v - optional values in the matrix 3959a1661176SMatthew Knepley 3960a1661176SMatthew Knepley Level: developer 3961a1661176SMatthew Knepley 39626a9b8d82SBarry Smith Notes: 396358d36128SBarry Smith The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays() 396458d36128SBarry Smith 39656a9b8d82SBarry Smith This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero 39666a9b8d82SBarry Smith structure will be the union of all the previous nonzero structures. 39676a9b8d82SBarry Smith 39686a9b8d82SBarry Smith Developer Notes: 39696a9b8d82SBarry 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 39706a9b8d82SBarry Smith then just copies the v values directly with PetscMemcpy(). 39716a9b8d82SBarry Smith 39726a9b8d82SBarry Smith This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them. 39736a9b8d82SBarry Smith 3974db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatSeqAIJSetPreallocation()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MatResetPreallocation()` 3975a1661176SMatthew Knepley @*/ 39769371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B, const PetscInt i[], const PetscInt j[], const PetscScalar v[]) { 3977a1661176SMatthew Knepley PetscFunctionBegin; 39780700a824SBarry Smith PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 39796ba663aaSJed Brown PetscValidType(B, 1); 3980cac4c232SBarry Smith PetscTryMethod(B, "MatSeqAIJSetPreallocationCSR_C", (Mat, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, i, j, v)); 3981a1661176SMatthew Knepley PetscFunctionReturn(0); 3982a1661176SMatthew Knepley } 3983a1661176SMatthew Knepley 39849371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B, const PetscInt Ii[], const PetscInt J[], const PetscScalar v[]) { 3985a1661176SMatthew Knepley PetscInt i; 3986a1661176SMatthew Knepley PetscInt m, n; 3987a1661176SMatthew Knepley PetscInt nz; 39886a9b8d82SBarry Smith PetscInt *nnz; 3989a1661176SMatthew Knepley 3990a1661176SMatthew Knepley PetscFunctionBegin; 3991aed4548fSBarry Smith PetscCheck(Ii[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]); 3992779a8d59SSatish Balay 39939566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 39949566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 3995779a8d59SSatish Balay 39969566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &m, &n)); 39979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &nnz)); 3998a1661176SMatthew Knepley for (i = 0; i < m; i++) { 3999b7940d39SSatish Balay nz = Ii[i + 1] - Ii[i]; 400008401ef6SPierre 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); 4001a1661176SMatthew Knepley nnz[i] = nz; 4002a1661176SMatthew Knepley } 40039566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz)); 40049566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 4005a1661176SMatthew Knepley 4006*48a46eb9SPierre 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)); 4007a1661176SMatthew Knepley 40089566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 40099566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4010a1661176SMatthew Knepley 40119566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 4012a1661176SMatthew Knepley PetscFunctionReturn(0); 4013a1661176SMatthew Knepley } 4014a1661176SMatthew Knepley 4015ad7e164aSPierre Jolivet /*@ 4016ad7e164aSPierre Jolivet MatSeqAIJKron - Computes C, the Kronecker product of A and B. 4017ad7e164aSPierre Jolivet 4018ad7e164aSPierre Jolivet Input Parameters: 4019ad7e164aSPierre Jolivet + A - left-hand side matrix 4020ad7e164aSPierre Jolivet . B - right-hand side matrix 4021ad7e164aSPierre Jolivet - reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 4022ad7e164aSPierre Jolivet 4023ad7e164aSPierre Jolivet Output Parameter: 4024ad7e164aSPierre Jolivet . C - Kronecker product of A and B 4025ad7e164aSPierre Jolivet 4026ad7e164aSPierre Jolivet Level: intermediate 4027ad7e164aSPierre Jolivet 4028ad7e164aSPierre Jolivet Notes: 4029ad7e164aSPierre Jolivet MAT_REUSE_MATRIX can only be used when the nonzero structure of the product matrix has not changed from that last call to MatSeqAIJKron(). 4030ad7e164aSPierre Jolivet 4031db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATKAIJ`, `MatReuse` 4032ad7e164aSPierre Jolivet @*/ 40339371c9d4SSatish Balay PetscErrorCode MatSeqAIJKron(Mat A, Mat B, MatReuse reuse, Mat *C) { 4034ad7e164aSPierre Jolivet PetscFunctionBegin; 4035ad7e164aSPierre Jolivet PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4036ad7e164aSPierre Jolivet PetscValidType(A, 1); 4037ad7e164aSPierre Jolivet PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4038ad7e164aSPierre Jolivet PetscValidType(B, 2); 4039ad7e164aSPierre Jolivet PetscValidPointer(C, 4); 4040ad7e164aSPierre Jolivet if (reuse == MAT_REUSE_MATRIX) { 4041ad7e164aSPierre Jolivet PetscValidHeaderSpecific(*C, MAT_CLASSID, 4); 4042ad7e164aSPierre Jolivet PetscValidType(*C, 4); 4043ad7e164aSPierre Jolivet } 4044cac4c232SBarry Smith PetscTryMethod(A, "MatSeqAIJKron_C", (Mat, Mat, MatReuse, Mat *), (A, B, reuse, C)); 4045ad7e164aSPierre Jolivet PetscFunctionReturn(0); 4046ad7e164aSPierre Jolivet } 4047ad7e164aSPierre Jolivet 40489371c9d4SSatish Balay PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A, Mat B, MatReuse reuse, Mat *C) { 4049ad7e164aSPierre Jolivet Mat newmat; 4050ad7e164aSPierre Jolivet Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 4051ad7e164aSPierre Jolivet Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 4052ad7e164aSPierre Jolivet PetscScalar *v; 4053fff043a9SJunchao Zhang const PetscScalar *aa, *ba; 4054ad7e164aSPierre 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; 4055ad7e164aSPierre Jolivet PetscBool flg; 4056ad7e164aSPierre Jolivet 4057ad7e164aSPierre Jolivet PetscFunctionBegin; 405828b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 405928b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 406028b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 406128b400f6SJacob Faibussowitsch PetscCheck(B->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 40629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATSEQAIJ, &flg)); 406328b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatType %s", ((PetscObject)B)->type_name); 4064aed4548fSBarry Smith PetscCheck(reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatReuse %d", (int)reuse); 4065ad7e164aSPierre Jolivet if (reuse == MAT_INITIAL_MATRIX) { 40669566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(am * bm + 1, &i, a->i[am] * b->i[bm], &j)); 40679566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &newmat)); 40689566063dSJacob Faibussowitsch PetscCall(MatSetSizes(newmat, am * bm, an * bn, am * bm, an * bn)); 40699566063dSJacob Faibussowitsch PetscCall(MatSetType(newmat, MATAIJ)); 4070ad7e164aSPierre Jolivet i[0] = 0; 4071ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4072ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4073ad7e164aSPierre Jolivet i[m * bm + p + 1] = i[m * bm + p] + (a->i[m + 1] - a->i[m]) * (b->i[p + 1] - b->i[p]); 4074ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m + 1]; ++n) { 40759371c9d4SSatish Balay for (q = b->i[p]; q < b->i[p + 1]; ++q) { j[nnz++] = a->j[n] * bn + b->j[q]; } 4076ad7e164aSPierre Jolivet } 4077ad7e164aSPierre Jolivet } 4078ad7e164aSPierre Jolivet } 40799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(newmat, i, j, NULL)); 4080ad7e164aSPierre Jolivet *C = newmat; 40819566063dSJacob Faibussowitsch PetscCall(PetscFree2(i, j)); 4082ad7e164aSPierre Jolivet nnz = 0; 4083ad7e164aSPierre Jolivet } 40849566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(*C, &v)); 40859566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 40869566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &ba)); 4087ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4088ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4089ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m + 1]; ++n) { 40909371c9d4SSatish Balay for (q = b->i[p]; q < b->i[p + 1]; ++q) { v[nnz++] = aa[n] * ba[q]; } 4091ad7e164aSPierre Jolivet } 4092ad7e164aSPierre Jolivet } 4093ad7e164aSPierre Jolivet } 40949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(*C, &v)); 40959566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 40969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &ba)); 4097ad7e164aSPierre Jolivet PetscFunctionReturn(0); 4098ad7e164aSPierre Jolivet } 4099ad7e164aSPierre Jolivet 4100c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h> 4101af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h> 4102170fe5c8SBarry Smith 4103170fe5c8SBarry Smith /* 4104170fe5c8SBarry Smith Computes (B'*A')' since computing B*A directly is untenable 4105170fe5c8SBarry Smith 4106170fe5c8SBarry Smith n p p 41072da392ccSBarry Smith [ ] [ ] [ ] 41082da392ccSBarry Smith m [ A ] * n [ B ] = m [ C ] 41092da392ccSBarry Smith [ ] [ ] [ ] 4110170fe5c8SBarry Smith 4111170fe5c8SBarry Smith */ 41129371c9d4SSatish Balay PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A, Mat B, Mat C) { 4113170fe5c8SBarry Smith Mat_SeqDense *sub_a = (Mat_SeqDense *)A->data; 4114170fe5c8SBarry Smith Mat_SeqAIJ *sub_b = (Mat_SeqAIJ *)B->data; 4115170fe5c8SBarry Smith Mat_SeqDense *sub_c = (Mat_SeqDense *)C->data; 411686214ceeSStefano Zampini PetscInt i, j, n, m, q, p; 4117170fe5c8SBarry Smith const PetscInt *ii, *idx; 4118170fe5c8SBarry Smith const PetscScalar *b, *a, *a_q; 4119170fe5c8SBarry Smith PetscScalar *c, *c_q; 412086214ceeSStefano Zampini PetscInt clda = sub_c->lda; 412186214ceeSStefano Zampini PetscInt alda = sub_a->lda; 4122170fe5c8SBarry Smith 4123170fe5c8SBarry Smith PetscFunctionBegin; 4124d0f46423SBarry Smith m = A->rmap->n; 4125d0f46423SBarry Smith n = A->cmap->n; 4126d0f46423SBarry Smith p = B->cmap->n; 4127170fe5c8SBarry Smith a = sub_a->v; 4128170fe5c8SBarry Smith b = sub_b->a; 4129170fe5c8SBarry Smith c = sub_c->v; 413086214ceeSStefano Zampini if (clda == m) { 41319566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c, m * p)); 413286214ceeSStefano Zampini } else { 413386214ceeSStefano Zampini for (j = 0; j < p; j++) 41349371c9d4SSatish Balay for (i = 0; i < m; i++) c[j * clda + i] = 0.0; 413586214ceeSStefano Zampini } 4136170fe5c8SBarry Smith ii = sub_b->i; 4137170fe5c8SBarry Smith idx = sub_b->j; 4138170fe5c8SBarry Smith for (i = 0; i < n; i++) { 4139170fe5c8SBarry Smith q = ii[i + 1] - ii[i]; 4140170fe5c8SBarry Smith while (q-- > 0) { 414186214ceeSStefano Zampini c_q = c + clda * (*idx); 414286214ceeSStefano Zampini a_q = a + alda * i; 4143854c7f52SBarry Smith PetscKernelAXPY(c_q, *b, a_q, m); 4144170fe5c8SBarry Smith idx++; 4145170fe5c8SBarry Smith b++; 4146170fe5c8SBarry Smith } 4147170fe5c8SBarry Smith } 4148170fe5c8SBarry Smith PetscFunctionReturn(0); 4149170fe5c8SBarry Smith } 4150170fe5c8SBarry Smith 41519371c9d4SSatish Balay PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A, Mat B, PetscReal fill, Mat C) { 4152d0f46423SBarry Smith PetscInt m = A->rmap->n, n = B->cmap->n; 415386214ceeSStefano Zampini PetscBool cisdense; 4154170fe5c8SBarry Smith 4155170fe5c8SBarry Smith PetscFunctionBegin; 415608401ef6SPierre 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); 41579566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, m, n)); 41589566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, B)); 41599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, "")); 4160*48a46eb9SPierre Jolivet if (!cisdense) PetscCall(MatSetType(C, MATDENSE)); 41619566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 4162d73949e8SHong Zhang 41634222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ; 4164170fe5c8SBarry Smith PetscFunctionReturn(0); 4165170fe5c8SBarry Smith } 4166170fe5c8SBarry Smith 4167170fe5c8SBarry Smith /* ----------------------------------------------------------------*/ 41680bad9183SKris Buschelman /*MC 4169fafad747SKris Buschelman MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 41700bad9183SKris Buschelman based on compressed sparse row format. 41710bad9183SKris Buschelman 41720bad9183SKris Buschelman Options Database Keys: 41730bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 41740bad9183SKris Buschelman 41750bad9183SKris Buschelman Level: beginner 41760bad9183SKris Buschelman 41770cd7f59aSBarry Smith Notes: 41780cd7f59aSBarry Smith MatSetValues() may be called for this matrix type with a NULL argument for the numerical values, 41790cd7f59aSBarry Smith in this case the values associated with the rows and columns one passes in are set to zero 41800cd7f59aSBarry Smith in the matrix 41810cd7f59aSBarry Smith 41820cd7f59aSBarry Smith MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no 41830cd7f59aSBarry Smith space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored 41840cd7f59aSBarry Smith 41850cd7f59aSBarry Smith Developer Notes: 41860cd7f59aSBarry Smith It would be nice if all matrix formats supported passing NULL in for the numerical values 41870cd7f59aSBarry Smith 4188db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MatSetFromOptions()`, `MatSetType()`, `MatCreate()`, `MatType`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 41890bad9183SKris Buschelman M*/ 41900bad9183SKris Buschelman 4191ccd284c7SBarry Smith /*MC 4192ccd284c7SBarry Smith MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 4193ccd284c7SBarry Smith 4194ccd284c7SBarry Smith This matrix type is identical to MATSEQAIJ when constructed with a single process communicator, 4195ccd284c7SBarry Smith and MATMPIAIJ otherwise. As a result, for single process communicators, 4196ed73aabaSBarry Smith MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 4197ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4198ccd284c7SBarry Smith the above preallocation routines for simplicity. 4199ccd284c7SBarry Smith 4200ccd284c7SBarry Smith Options Database Keys: 4201ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions() 4202ccd284c7SBarry Smith 420395452b02SPatrick Sanan Developer Notes: 4204ca9cdca7SRichard Tran Mills Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when 4205ccd284c7SBarry Smith enough exist. 4206ccd284c7SBarry Smith 4207ccd284c7SBarry Smith Level: beginner 4208ccd284c7SBarry Smith 4209db781477SPatrick Sanan .seealso: `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATMPIAIJ`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 4210ccd284c7SBarry Smith M*/ 4211ccd284c7SBarry Smith 4212ccd284c7SBarry Smith /*MC 4213ccd284c7SBarry Smith MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 4214ccd284c7SBarry Smith 4215ccd284c7SBarry Smith This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator, 4216ccd284c7SBarry Smith and MATMPIAIJCRL otherwise. As a result, for single process communicators, 4217ccd284c7SBarry Smith MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 4218ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4219ccd284c7SBarry Smith the above preallocation routines for simplicity. 4220ccd284c7SBarry Smith 4221ccd284c7SBarry Smith Options Database Keys: 4222ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions() 4223ccd284c7SBarry Smith 4224ccd284c7SBarry Smith Level: beginner 4225ccd284c7SBarry Smith 4226c2e3fba1SPatrick Sanan .seealso: `MatCreateMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL` 4227ccd284c7SBarry Smith M*/ 4228ccd284c7SBarry Smith 42297906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat, MatType, MatReuse, Mat *); 42307906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 42317906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat, MatType, MatReuse, Mat *); 42327906f579SHong Zhang #endif 4233d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 4234d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat, MatType, MatReuse, Mat *); 4235d24d4204SJose E. Roman #endif 42367906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE) 42377906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType, MatReuse, Mat *); 42387906f579SHong Zhang #endif 42397906f579SHong Zhang 4240d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat, MatType, MatReuse, Mat *); 4241c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat, MatType, MatReuse, Mat *); 42424222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat); 42437906f579SHong Zhang 42448c778c55SBarry Smith /*@C 42458f1ea47aSStefano Zampini MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored 42468c778c55SBarry Smith 42478c778c55SBarry Smith Not Collective 42488c778c55SBarry Smith 42498c778c55SBarry Smith Input Parameter: 4250579dbff0SBarry Smith . mat - a MATSEQAIJ matrix 42518c778c55SBarry Smith 42528c778c55SBarry Smith Output Parameter: 42538c778c55SBarry Smith . array - pointer to the data 42548c778c55SBarry Smith 42558c778c55SBarry Smith Level: intermediate 42568c778c55SBarry Smith 4257db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()` 42588c778c55SBarry Smith @*/ 42599371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArray(Mat A, PetscScalar **array) { 4260d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 42618c778c55SBarry Smith 42628c778c55SBarry Smith PetscFunctionBegin; 4263d67d9f35SJunchao Zhang if (aij->ops->getarray) { 42649566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarray)(A, array)); 4265d67d9f35SJunchao Zhang } else { 4266d67d9f35SJunchao Zhang *array = aij->a; 4267d67d9f35SJunchao Zhang } 4268d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4269d67d9f35SJunchao Zhang } 4270d67d9f35SJunchao Zhang 4271d67d9f35SJunchao Zhang /*@C 4272d67d9f35SJunchao Zhang MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray() 4273d67d9f35SJunchao Zhang 4274d67d9f35SJunchao Zhang Not Collective 4275d67d9f35SJunchao Zhang 4276d67d9f35SJunchao Zhang Input Parameters: 4277d67d9f35SJunchao Zhang + mat - a MATSEQAIJ matrix 4278d67d9f35SJunchao Zhang - array - pointer to the data 4279d67d9f35SJunchao Zhang 4280d67d9f35SJunchao Zhang Level: intermediate 4281d67d9f35SJunchao Zhang 4282db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayF90()` 4283d67d9f35SJunchao Zhang @*/ 42849371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArray(Mat A, PetscScalar **array) { 4285d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4286d67d9f35SJunchao Zhang 4287d67d9f35SJunchao Zhang PetscFunctionBegin; 4288d67d9f35SJunchao Zhang if (aij->ops->restorearray) { 42899566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearray)(A, array)); 4290d67d9f35SJunchao Zhang } else { 4291d67d9f35SJunchao Zhang *array = NULL; 4292d67d9f35SJunchao Zhang } 42939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 42949566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 42958c778c55SBarry Smith PetscFunctionReturn(0); 42968c778c55SBarry Smith } 42978c778c55SBarry Smith 429821e72a00SBarry Smith /*@C 42998f1ea47aSStefano Zampini MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored 43008f1ea47aSStefano Zampini 43018f1ea47aSStefano Zampini Not Collective 43028f1ea47aSStefano Zampini 43038f1ea47aSStefano Zampini Input Parameter: 43048f1ea47aSStefano Zampini . mat - a MATSEQAIJ matrix 43058f1ea47aSStefano Zampini 43068f1ea47aSStefano Zampini Output Parameter: 43078f1ea47aSStefano Zampini . array - pointer to the data 43088f1ea47aSStefano Zampini 43098f1ea47aSStefano Zampini Level: intermediate 43108f1ea47aSStefano Zampini 4311db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 43128f1ea47aSStefano Zampini @*/ 43139371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArrayRead(Mat A, const PetscScalar **array) { 4314d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 43158f1ea47aSStefano Zampini 43168f1ea47aSStefano Zampini PetscFunctionBegin; 4317d67d9f35SJunchao Zhang if (aij->ops->getarrayread) { 43189566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarrayread)(A, array)); 4319d67d9f35SJunchao Zhang } else { 4320d67d9f35SJunchao Zhang *array = aij->a; 4321d67d9f35SJunchao Zhang } 43228f1ea47aSStefano Zampini PetscFunctionReturn(0); 43238f1ea47aSStefano Zampini } 43248f1ea47aSStefano Zampini 43258f1ea47aSStefano Zampini /*@C 43268f1ea47aSStefano Zampini MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead 43278f1ea47aSStefano Zampini 43288f1ea47aSStefano Zampini Not Collective 43298f1ea47aSStefano Zampini 43308f1ea47aSStefano Zampini Input Parameter: 43318f1ea47aSStefano Zampini . mat - a MATSEQAIJ matrix 43328f1ea47aSStefano Zampini 43338f1ea47aSStefano Zampini Output Parameter: 43348f1ea47aSStefano Zampini . array - pointer to the data 43358f1ea47aSStefano Zampini 43368f1ea47aSStefano Zampini Level: intermediate 43378f1ea47aSStefano Zampini 4338db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 43398f1ea47aSStefano Zampini @*/ 43409371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArrayRead(Mat A, const PetscScalar **array) { 4341d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 43428f1ea47aSStefano Zampini 43438f1ea47aSStefano Zampini PetscFunctionBegin; 4344d67d9f35SJunchao Zhang if (aij->ops->restorearrayread) { 43459566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearrayread)(A, array)); 4346d67d9f35SJunchao Zhang } else { 4347d67d9f35SJunchao Zhang *array = NULL; 4348d67d9f35SJunchao Zhang } 4349d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4350d67d9f35SJunchao Zhang } 4351d67d9f35SJunchao Zhang 4352d67d9f35SJunchao Zhang /*@C 4353d67d9f35SJunchao Zhang MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a MATSEQAIJ matrix is stored 4354d67d9f35SJunchao Zhang 4355d67d9f35SJunchao Zhang Not Collective 4356d67d9f35SJunchao Zhang 4357d67d9f35SJunchao Zhang Input Parameter: 4358d67d9f35SJunchao Zhang . mat - a MATSEQAIJ matrix 4359d67d9f35SJunchao Zhang 4360d67d9f35SJunchao Zhang Output Parameter: 4361d67d9f35SJunchao Zhang . array - pointer to the data 4362d67d9f35SJunchao Zhang 4363d67d9f35SJunchao Zhang Level: intermediate 4364d67d9f35SJunchao Zhang 4365db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 4366d67d9f35SJunchao Zhang @*/ 43679371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArrayWrite(Mat A, PetscScalar **array) { 4368d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4369d67d9f35SJunchao Zhang 4370d67d9f35SJunchao Zhang PetscFunctionBegin; 4371d67d9f35SJunchao Zhang if (aij->ops->getarraywrite) { 43729566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarraywrite)(A, array)); 4373d67d9f35SJunchao Zhang } else { 4374d67d9f35SJunchao Zhang *array = aij->a; 4375d67d9f35SJunchao Zhang } 43769566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 43779566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 4378d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4379d67d9f35SJunchao Zhang } 4380d67d9f35SJunchao Zhang 4381d67d9f35SJunchao Zhang /*@C 4382d67d9f35SJunchao Zhang MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead 4383d67d9f35SJunchao Zhang 4384d67d9f35SJunchao Zhang Not Collective 4385d67d9f35SJunchao Zhang 4386d67d9f35SJunchao Zhang Input Parameter: 4387d67d9f35SJunchao Zhang . mat - a MATSEQAIJ matrix 4388d67d9f35SJunchao Zhang 4389d67d9f35SJunchao Zhang Output Parameter: 4390d67d9f35SJunchao Zhang . array - pointer to the data 4391d67d9f35SJunchao Zhang 4392d67d9f35SJunchao Zhang Level: intermediate 4393d67d9f35SJunchao Zhang 4394db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 4395d67d9f35SJunchao Zhang @*/ 43969371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArrayWrite(Mat A, PetscScalar **array) { 4397d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 4398d67d9f35SJunchao Zhang 4399d67d9f35SJunchao Zhang PetscFunctionBegin; 4400d67d9f35SJunchao Zhang if (aij->ops->restorearraywrite) { 44019566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearraywrite)(A, array)); 4402d67d9f35SJunchao Zhang } else { 4403d67d9f35SJunchao Zhang *array = NULL; 4404d67d9f35SJunchao Zhang } 44058f1ea47aSStefano Zampini PetscFunctionReturn(0); 44068f1ea47aSStefano Zampini } 44078f1ea47aSStefano Zampini 44088f1ea47aSStefano Zampini /*@C 44097ee59b9bSJunchao Zhang MatSeqAIJGetCSRAndMemType - Get the CSR arrays and the memory type of the SEQAIJ matrix 44107ee59b9bSJunchao Zhang 44117ee59b9bSJunchao Zhang Not Collective 44127ee59b9bSJunchao Zhang 44137ee59b9bSJunchao Zhang Input Parameter: 44147ee59b9bSJunchao Zhang . mat - a matrix of type MATSEQAIJ or its subclasses 44157ee59b9bSJunchao Zhang 44167ee59b9bSJunchao Zhang Output Parameters: 44177ee59b9bSJunchao Zhang + i - row map array of the matrix 44187ee59b9bSJunchao Zhang . j - column index array of the matrix 44197ee59b9bSJunchao Zhang . a - data array of the matrix 44207ee59b9bSJunchao Zhang - memtype - memory type of the arrays 44217ee59b9bSJunchao Zhang 44227ee59b9bSJunchao Zhang Notes: 44237ee59b9bSJunchao Zhang Any of the output parameters can be NULL, in which case the corresponding value is not returned. 44247ee59b9bSJunchao Zhang If mat is a device matrix, the arrays are on the device. Otherwise, they are on the host. 44257ee59b9bSJunchao Zhang 44267ee59b9bSJunchao Zhang One can call this routine on a preallocated but not assembled matrix to just get the memory of the CSR underneath the matrix. 44277ee59b9bSJunchao Zhang If the matrix is assembled, the data array 'a' is guaranteed to have the latest values of the matrix. 44287ee59b9bSJunchao Zhang 44297ee59b9bSJunchao Zhang Level: Developer 44307ee59b9bSJunchao Zhang 4431db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 44327ee59b9bSJunchao Zhang @*/ 44339371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetCSRAndMemType(Mat mat, const PetscInt **i, const PetscInt **j, PetscScalar **a, PetscMemType *mtype) { 44347ee59b9bSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 44357ee59b9bSJunchao Zhang 44367ee59b9bSJunchao Zhang PetscFunctionBegin; 44377ee59b9bSJunchao Zhang PetscCheck(mat->preallocated, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "matrix is not preallocated"); 44387ee59b9bSJunchao Zhang if (aij->ops->getcsrandmemtype) { 44397ee59b9bSJunchao Zhang PetscCall((*aij->ops->getcsrandmemtype)(mat, i, j, a, mtype)); 44407ee59b9bSJunchao Zhang } else { 44417ee59b9bSJunchao Zhang if (i) *i = aij->i; 44427ee59b9bSJunchao Zhang if (j) *j = aij->j; 44437ee59b9bSJunchao Zhang if (a) *a = aij->a; 44447ee59b9bSJunchao Zhang if (mtype) *mtype = PETSC_MEMTYPE_HOST; 44457ee59b9bSJunchao Zhang } 44467ee59b9bSJunchao Zhang PetscFunctionReturn(0); 44477ee59b9bSJunchao Zhang } 44487ee59b9bSJunchao Zhang 44497ee59b9bSJunchao Zhang /*@C 445021e72a00SBarry Smith MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row 445121e72a00SBarry Smith 445221e72a00SBarry Smith Not Collective 445321e72a00SBarry Smith 445421e72a00SBarry Smith Input Parameter: 4455579dbff0SBarry Smith . mat - a MATSEQAIJ matrix 445621e72a00SBarry Smith 445721e72a00SBarry Smith Output Parameter: 445821e72a00SBarry Smith . nz - the maximum number of nonzeros in any row 445921e72a00SBarry Smith 446021e72a00SBarry Smith Level: intermediate 446121e72a00SBarry Smith 4462db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()` 446321e72a00SBarry Smith @*/ 44649371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetMaxRowNonzeros(Mat A, PetscInt *nz) { 446521e72a00SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 446621e72a00SBarry Smith 446721e72a00SBarry Smith PetscFunctionBegin; 446821e72a00SBarry Smith *nz = aij->rmax; 446921e72a00SBarry Smith PetscFunctionReturn(0); 447021e72a00SBarry Smith } 447121e72a00SBarry Smith 44729371c9d4SSatish Balay PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[]) { 4473394ed5ebSJunchao Zhang MPI_Comm comm; 4474394ed5ebSJunchao Zhang PetscInt *i, *j; 4475394ed5ebSJunchao Zhang PetscInt M, N, row; 4476394ed5ebSJunchao Zhang PetscCount k, p, q, nneg, nnz, start, end; /* Index the coo array, so use PetscCount as their type */ 4477394ed5ebSJunchao Zhang PetscInt *Ai; /* Change to PetscCount once we use it for row pointers */ 4478394ed5ebSJunchao Zhang PetscInt *Aj; 4479394ed5ebSJunchao Zhang PetscScalar *Aa; 4480cbc6b225SStefano Zampini Mat_SeqAIJ *seqaij = (Mat_SeqAIJ *)(mat->data); 4481cbc6b225SStefano Zampini MatType rtype; 4482394ed5ebSJunchao Zhang PetscCount *perm, *jmap; 4483394ed5ebSJunchao Zhang 4484394ed5ebSJunchao Zhang PetscFunctionBegin; 44859566063dSJacob Faibussowitsch PetscCall(MatResetPreallocationCOO_SeqAIJ(mat)); 44869566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 44879566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &M, &N)); 4488e8729f6fSJunchao Zhang i = coo_i; 4489e8729f6fSJunchao Zhang j = coo_j; 44909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n, &perm)); 4491394ed5ebSJunchao Zhang for (k = 0; k < coo_n; k++) { /* Ignore entries with negative row or col indices */ 4492394ed5ebSJunchao Zhang if (j[k] < 0) i[k] = -1; 4493394ed5ebSJunchao Zhang perm[k] = k; 4494394ed5ebSJunchao Zhang } 4495394ed5ebSJunchao Zhang 4496394ed5ebSJunchao Zhang /* Sort by row */ 44979566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithIntCountArrayPair(coo_n, i, j, perm)); 44989371c9d4SSatish Balay for (k = 0; k < coo_n; k++) { 44999371c9d4SSatish Balay if (i[k] >= 0) break; 45009371c9d4SSatish Balay } /* Advance k to the first row with a non-negative index */ 4501394ed5ebSJunchao Zhang nneg = k; 45029566063dSJacob 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 */ 4503394ed5ebSJunchao Zhang nnz = 0; /* Total number of unique nonzeros to be counted */ 4504394ed5ebSJunchao Zhang jmap++; /* Inc jmap by 1 for convinience */ 4505394ed5ebSJunchao Zhang 45069566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(M + 1, &Ai)); /* CSR of A */ 45079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n - nneg, &Aj)); /* We have at most coo_n-nneg unique nonzeros */ 4508394ed5ebSJunchao Zhang 4509394ed5ebSJunchao Zhang /* In each row, sort by column, then unique column indices to get row length */ 4510394ed5ebSJunchao Zhang Ai++; /* Inc by 1 for convinience */ 4511394ed5ebSJunchao Zhang q = 0; /* q-th unique nonzero, with q starting from 0 */ 4512394ed5ebSJunchao Zhang while (k < coo_n) { 4513394ed5ebSJunchao Zhang row = i[k]; 4514394ed5ebSJunchao Zhang start = k; /* [start,end) indices for this row */ 4515394ed5ebSJunchao Zhang while (k < coo_n && i[k] == row) k++; 4516394ed5ebSJunchao Zhang end = k; 45179566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithCountArray(end - start, j + start, perm + start)); 4518394ed5ebSJunchao Zhang /* Find number of unique col entries in this row */ 4519394ed5ebSJunchao Zhang Aj[q] = j[start]; /* Log the first nonzero in this row */ 4520394ed5ebSJunchao Zhang jmap[q] = 1; /* Number of repeats of this nozero entry */ 4521394ed5ebSJunchao Zhang Ai[row] = 1; 4522394ed5ebSJunchao Zhang nnz++; 4523394ed5ebSJunchao Zhang 4524394ed5ebSJunchao Zhang for (p = start + 1; p < end; p++) { /* Scan remaining nonzero in this row */ 4525394ed5ebSJunchao Zhang if (j[p] != j[p - 1]) { /* Meet a new nonzero */ 4526394ed5ebSJunchao Zhang q++; 4527394ed5ebSJunchao Zhang jmap[q] = 1; 4528394ed5ebSJunchao Zhang Aj[q] = j[p]; 4529394ed5ebSJunchao Zhang Ai[row]++; 4530394ed5ebSJunchao Zhang nnz++; 4531394ed5ebSJunchao Zhang } else { 4532394ed5ebSJunchao Zhang jmap[q]++; 4533394ed5ebSJunchao Zhang } 4534394ed5ebSJunchao Zhang } 4535394ed5ebSJunchao Zhang q++; /* Move to next row and thus next unique nonzero */ 4536394ed5ebSJunchao Zhang } 4537394ed5ebSJunchao Zhang 4538394ed5ebSJunchao Zhang Ai--; /* Back to the beginning of Ai[] */ 4539394ed5ebSJunchao Zhang for (k = 0; k < M; k++) Ai[k + 1] += Ai[k]; 4540394ed5ebSJunchao Zhang jmap--; /* Back to the beginning of jmap[] */ 4541394ed5ebSJunchao Zhang jmap[0] = 0; 4542394ed5ebSJunchao Zhang for (k = 0; k < nnz; k++) jmap[k + 1] += jmap[k]; 4543394ed5ebSJunchao Zhang if (nnz < coo_n - nneg) { /* Realloc with actual number of unique nonzeros */ 4544394ed5ebSJunchao Zhang PetscCount *jmap_new; 4545394ed5ebSJunchao Zhang PetscInt *Aj_new; 4546394ed5ebSJunchao Zhang 45479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz + 1, &jmap_new)); 45489566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(jmap_new, jmap, nnz + 1)); 45499566063dSJacob Faibussowitsch PetscCall(PetscFree(jmap)); 4550394ed5ebSJunchao Zhang jmap = jmap_new; 4551394ed5ebSJunchao Zhang 45529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &Aj_new)); 45539566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(Aj_new, Aj, nnz)); 45549566063dSJacob Faibussowitsch PetscCall(PetscFree(Aj)); 4555394ed5ebSJunchao Zhang Aj = Aj_new; 4556394ed5ebSJunchao Zhang } 4557394ed5ebSJunchao Zhang 4558394ed5ebSJunchao Zhang if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */ 4559394ed5ebSJunchao Zhang PetscCount *perm_new; 4560cbc6b225SStefano Zampini 45619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n - nneg, &perm_new)); 45629566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(perm_new, perm + nneg, coo_n - nneg)); 45639566063dSJacob Faibussowitsch PetscCall(PetscFree(perm)); 4564394ed5ebSJunchao Zhang perm = perm_new; 4565394ed5ebSJunchao Zhang } 4566394ed5ebSJunchao Zhang 45679566063dSJacob Faibussowitsch PetscCall(MatGetRootType_Private(mat, &rtype)); 45689566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nnz, &Aa)); /* Zero the matrix */ 45699566063dSJacob Faibussowitsch PetscCall(MatSetSeqAIJWithArrays_private(PETSC_COMM_SELF, M, N, Ai, Aj, Aa, rtype, mat)); 4570394ed5ebSJunchao Zhang 4571394ed5ebSJunchao Zhang seqaij->singlemalloc = PETSC_FALSE; /* Ai, Aj and Aa are not allocated in one big malloc */ 4572394ed5ebSJunchao Zhang seqaij->free_a = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */ 4573394ed5ebSJunchao Zhang /* Record COO fields */ 4574394ed5ebSJunchao Zhang seqaij->coo_n = coo_n; 4575394ed5ebSJunchao Zhang seqaij->Atot = coo_n - nneg; /* Annz is seqaij->nz, so no need to record that again */ 4576394ed5ebSJunchao Zhang seqaij->jmap = jmap; /* of length nnz+1 */ 4577394ed5ebSJunchao Zhang seqaij->perm = perm; 4578394ed5ebSJunchao Zhang PetscFunctionReturn(0); 4579394ed5ebSJunchao Zhang } 4580394ed5ebSJunchao Zhang 45819371c9d4SSatish Balay static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A, const PetscScalar v[], InsertMode imode) { 4582394ed5ebSJunchao Zhang Mat_SeqAIJ *aseq = (Mat_SeqAIJ *)A->data; 4583394ed5ebSJunchao Zhang PetscCount i, j, Annz = aseq->nz; 4584394ed5ebSJunchao Zhang PetscCount *perm = aseq->perm, *jmap = aseq->jmap; 4585394ed5ebSJunchao Zhang PetscScalar *Aa; 4586394ed5ebSJunchao Zhang 4587394ed5ebSJunchao Zhang PetscFunctionBegin; 45889566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &Aa)); 4589394ed5ebSJunchao Zhang for (i = 0; i < Annz; i++) { 4590b6c38306SJunchao Zhang PetscScalar sum = 0.0; 4591b6c38306SJunchao Zhang for (j = jmap[i]; j < jmap[i + 1]; j++) sum += v[perm[j]]; 4592b6c38306SJunchao Zhang Aa[i] = (imode == INSERT_VALUES ? 0.0 : Aa[i]) + sum; 4593394ed5ebSJunchao Zhang } 45949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &Aa)); 4595394ed5ebSJunchao Zhang PetscFunctionReturn(0); 4596394ed5ebSJunchao Zhang } 4597394ed5ebSJunchao Zhang 459834b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 45995063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat, MatType, MatReuse, Mat *); 460002fe1965SBarry Smith #endif 46013d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 46025063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat, MatType, MatReuse, Mat *); 46033d0639e7SStefano Zampini #endif 460402fe1965SBarry Smith 46059371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B) { 4606273d9f13SBarry Smith Mat_SeqAIJ *b; 460738baddfdSBarry Smith PetscMPIInt size; 4608273d9f13SBarry Smith 4609273d9f13SBarry Smith PetscFunctionBegin; 46109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size)); 461108401ef6SPierre Jolivet PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Comm must be of size 1"); 4612273d9f13SBarry Smith 46139566063dSJacob Faibussowitsch PetscCall(PetscNewLog(B, &b)); 46142205254eSKarl Rupp 4615b0a32e0cSBarry Smith B->data = (void *)b; 46162205254eSKarl Rupp 46179566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(B->ops, &MatOps_Values, sizeof(struct _MatOps))); 4618071fcb05SBarry Smith if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 46192205254eSKarl Rupp 4620f4259b30SLisandro Dalcin b->row = NULL; 4621f4259b30SLisandro Dalcin b->col = NULL; 4622f4259b30SLisandro Dalcin b->icol = NULL; 4623b810aeb4SBarry Smith b->reallocs = 0; 462436db0b34SBarry Smith b->ignorezeroentries = PETSC_FALSE; 4625f1e2ffcdSBarry Smith b->roworiented = PETSC_TRUE; 4626416022c9SBarry Smith b->nonew = 0; 4627f4259b30SLisandro Dalcin b->diag = NULL; 4628f4259b30SLisandro Dalcin b->solve_work = NULL; 4629f4259b30SLisandro Dalcin B->spptr = NULL; 4630f4259b30SLisandro Dalcin b->saved_values = NULL; 4631f4259b30SLisandro Dalcin b->idiag = NULL; 4632f4259b30SLisandro Dalcin b->mdiag = NULL; 4633f4259b30SLisandro Dalcin b->ssor_work = NULL; 463471f1c65dSBarry Smith b->omega = 1.0; 463571f1c65dSBarry Smith b->fshift = 0.0; 463671f1c65dSBarry Smith b->idiagvalid = PETSC_FALSE; 4637bbead8a2SBarry Smith b->ibdiagvalid = PETSC_FALSE; 4638a9817697SBarry Smith b->keepnonzeropattern = PETSC_FALSE; 463917ab2063SBarry Smith 46409566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ)); 4641b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE) 46429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEnginePut_C", MatlabEnginePut_SeqAIJ)); 46439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEngineGet_C", MatlabEngineGet_SeqAIJ)); 4644b3866ffcSBarry Smith #endif 46459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetColumnIndices_C", MatSeqAIJSetColumnIndices_SeqAIJ)); 46469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqAIJ)); 46479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqAIJ)); 46489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsbaij_C", MatConvert_SeqAIJ_SeqSBAIJ)); 46499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqbaij_C", MatConvert_SeqAIJ_SeqBAIJ)); 46509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijperm_C", MatConvert_SeqAIJ_SeqAIJPERM)); 46519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijsell_C", MatConvert_SeqAIJ_SeqAIJSELL)); 46529779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 46539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijmkl_C", MatConvert_SeqAIJ_SeqAIJMKL)); 4654191b95cbSRichard Tran Mills #endif 465534b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 46569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcusparse_C", MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 46579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_seqaij_C", MatProductSetFromOptions_SeqAIJ)); 46589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaijcusparse_C", MatProductSetFromOptions_SeqAIJ)); 465902fe1965SBarry Smith #endif 46603d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 46619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijkokkos_C", MatConvert_SeqAIJ_SeqAIJKokkos)); 46623d0639e7SStefano Zampini #endif 46639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcrl_C", MatConvert_SeqAIJ_SeqAIJCRL)); 4664af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 46659566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_elemental_C", MatConvert_SeqAIJ_Elemental)); 4666af8000cdSHong Zhang #endif 4667d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 46689566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_scalapack_C", MatConvert_AIJ_ScaLAPACK)); 4669d24d4204SJose E. Roman #endif 467063c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 46719566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_hypre_C", MatConvert_AIJ_HYPRE)); 46729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_transpose_seqaij_seqaij_C", MatProductSetFromOptions_Transpose_AIJ_AIJ)); 467363c07aadSStefano Zampini #endif 46749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqdense_C", MatConvert_SeqAIJ_SeqDense)); 46759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsell_C", MatConvert_SeqAIJ_SeqSELL)); 46769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_is_C", MatConvert_XAIJ_IS)); 46779566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsTranspose_C", MatIsTranspose_SeqAIJ)); 46789566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsHermitianTranspose_C", MatIsTranspose_SeqAIJ)); 46799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocation_C", MatSeqAIJSetPreallocation_SeqAIJ)); 46809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatResetPreallocation_C", MatResetPreallocation_SeqAIJ)); 46819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocationCSR_C", MatSeqAIJSetPreallocationCSR_SeqAIJ)); 46829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatReorderForNonzeroDiagonal_C", MatReorderForNonzeroDiagonal_SeqAIJ)); 46839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_is_seqaij_C", MatProductSetFromOptions_IS_XAIJ)); 46849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqaij_C", MatProductSetFromOptions_SeqDense_SeqAIJ)); 46859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaij_C", MatProductSetFromOptions_SeqAIJ)); 46869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJKron_C", MatSeqAIJKron_SeqAIJ)); 46879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_SeqAIJ)); 46889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_SeqAIJ)); 46899566063dSJacob Faibussowitsch PetscCall(MatCreate_SeqAIJ_Inode(B)); 46909566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ)); 46919566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetTypeFromOptions(B)); /* this allows changing the matrix subtype to say MATSEQAIJPERM */ 46923a40ed3dSBarry Smith PetscFunctionReturn(0); 469317ab2063SBarry Smith } 469417ab2063SBarry Smith 4695b24902e0SBarry Smith /* 46963893b582SJunchao Zhang Given a matrix generated with MatGetFactor() duplicates all the information in A into C 4697b24902e0SBarry Smith */ 46989371c9d4SSatish Balay PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C, Mat A, MatDuplicateOption cpvalues, PetscBool mallocmatspace) { 46992a350339SBarry Smith Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data, *a = (Mat_SeqAIJ *)A->data; 4700071fcb05SBarry Smith PetscInt m = A->rmap->n, i; 470117ab2063SBarry Smith 47023a40ed3dSBarry Smith PetscFunctionBegin; 4703aed4548fSBarry Smith PetscCheck(A->assembled || cpvalues == MAT_DO_NOT_COPY_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix"); 4704273d9f13SBarry Smith 4705d5f3da31SBarry Smith C->factortype = A->factortype; 4706f4259b30SLisandro Dalcin c->row = NULL; 4707f4259b30SLisandro Dalcin c->col = NULL; 4708f4259b30SLisandro Dalcin c->icol = NULL; 47096ad4291fSHong Zhang c->reallocs = 0; 471017ab2063SBarry Smith 471169272f91SPierre Jolivet C->assembled = A->assembled; 471269272f91SPierre Jolivet C->preallocated = A->preallocated; 471317ab2063SBarry Smith 471469272f91SPierre Jolivet if (A->preallocated) { 47159566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->rmap, &C->rmap)); 47169566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->cmap, &C->cmap)); 4717eec197d1SBarry Smith 47189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &c->imax)); 47199566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->imax, a->imax, m * sizeof(PetscInt))); 47209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &c->ilen)); 47219566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->ilen, a->ilen, m * sizeof(PetscInt))); 47229566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, 2 * m * sizeof(PetscInt))); 472317ab2063SBarry Smith 472417ab2063SBarry Smith /* allocate the matrix space */ 4725f77e22a1SHong Zhang if (mallocmatspace) { 47269566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(a->i[m], &c->a, a->i[m], &c->j, m + 1, &c->i)); 47279566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, a->i[m] * (sizeof(PetscScalar) + sizeof(PetscInt)) + (m + 1) * sizeof(PetscInt))); 47282205254eSKarl Rupp 4729f1e2ffcdSBarry Smith c->singlemalloc = PETSC_TRUE; 47302205254eSKarl Rupp 47319566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->i, a->i, m + 1)); 473217ab2063SBarry Smith if (m > 0) { 47339566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->j, a->j, a->i[m])); 4734be6bf707SBarry Smith if (cpvalues == MAT_COPY_VALUES) { 47352e5835c6SStefano Zampini const PetscScalar *aa; 47362e5835c6SStefano Zampini 47379566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 47389566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->a, aa, a->i[m])); 47399566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 4740be6bf707SBarry Smith } else { 47419566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->a, a->i[m])); 474217ab2063SBarry Smith } 474308480c60SBarry Smith } 4744f77e22a1SHong Zhang } 474517ab2063SBarry Smith 47466ad4291fSHong Zhang c->ignorezeroentries = a->ignorezeroentries; 4747416022c9SBarry Smith c->roworiented = a->roworiented; 4748416022c9SBarry Smith c->nonew = a->nonew; 4749416022c9SBarry Smith if (a->diag) { 47509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &c->diag)); 47519566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->diag, a->diag, m * sizeof(PetscInt))); 47529566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, (m + 1) * sizeof(PetscInt))); 4753071fcb05SBarry Smith } else c->diag = NULL; 47542205254eSKarl Rupp 4755f4259b30SLisandro Dalcin c->solve_work = NULL; 4756f4259b30SLisandro Dalcin c->saved_values = NULL; 4757f4259b30SLisandro Dalcin c->idiag = NULL; 4758f4259b30SLisandro Dalcin c->ssor_work = NULL; 4759a9817697SBarry Smith c->keepnonzeropattern = a->keepnonzeropattern; 4760e6b907acSBarry Smith c->free_a = PETSC_TRUE; 4761e6b907acSBarry Smith c->free_ij = PETSC_TRUE; 47626ad4291fSHong Zhang 4763893ad86cSHong Zhang c->rmax = a->rmax; 4764416022c9SBarry Smith c->nz = a->nz; 47658ed568f8SMatthew G Knepley c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 4766754ec7b1SSatish Balay 47676ad4291fSHong Zhang c->compressedrow.use = a->compressedrow.use; 47686ad4291fSHong Zhang c->compressedrow.nrows = a->compressedrow.nrows; 4769cd6b891eSBarry Smith if (a->compressedrow.use) { 47706ad4291fSHong Zhang i = a->compressedrow.nrows; 47719566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i + 1, &c->compressedrow.i, i, &c->compressedrow.rindex)); 47729566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.i, a->compressedrow.i, i + 1)); 47739566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.rindex, a->compressedrow.rindex, i)); 477427ea64f8SHong Zhang } else { 477527ea64f8SHong Zhang c->compressedrow.use = PETSC_FALSE; 47760298fd71SBarry Smith c->compressedrow.i = NULL; 47770298fd71SBarry Smith c->compressedrow.rindex = NULL; 47786ad4291fSHong Zhang } 4779ea632784SBarry Smith c->nonzerorowcnt = a->nonzerorowcnt; 4780e56f5c9eSBarry Smith C->nonzerostate = A->nonzerostate; 47814846f1f5SKris Buschelman 47829566063dSJacob Faibussowitsch PetscCall(MatDuplicate_SeqAIJ_Inode(A, cpvalues, &C)); 478369272f91SPierre Jolivet } 47849566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist)); 47853a40ed3dSBarry Smith PetscFunctionReturn(0); 478617ab2063SBarry Smith } 478717ab2063SBarry Smith 47889371c9d4SSatish Balay PetscErrorCode MatDuplicate_SeqAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B) { 4789b24902e0SBarry Smith PetscFunctionBegin; 47909566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 47919566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n)); 4792*48a46eb9SPierre Jolivet if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) PetscCall(MatSetBlockSizesFromMats(*B, A, A)); 47939566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, ((PetscObject)A)->type_name)); 47949566063dSJacob Faibussowitsch PetscCall(MatDuplicateNoCreate_SeqAIJ(*B, A, cpvalues, PETSC_TRUE)); 4795b24902e0SBarry Smith PetscFunctionReturn(0); 4796b24902e0SBarry Smith } 4797b24902e0SBarry Smith 47989371c9d4SSatish Balay PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer) { 479952f91c60SVaclav Hapla PetscBool isbinary, ishdf5; 480052f91c60SVaclav Hapla 480152f91c60SVaclav Hapla PetscFunctionBegin; 480252f91c60SVaclav Hapla PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1); 480352f91c60SVaclav Hapla PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 4804c27b3999SVaclav Hapla /* force binary viewer to load .info file if it has not yet done so */ 48059566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 48069566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 48079566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 480852f91c60SVaclav Hapla if (isbinary) { 48099566063dSJacob Faibussowitsch PetscCall(MatLoad_SeqAIJ_Binary(newMat, viewer)); 481052f91c60SVaclav Hapla } else if (ishdf5) { 481152f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5) 48129566063dSJacob Faibussowitsch PetscCall(MatLoad_AIJ_HDF5(newMat, viewer)); 481352f91c60SVaclav Hapla #else 481452f91c60SVaclav Hapla SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 481552f91c60SVaclav Hapla #endif 481652f91c60SVaclav Hapla } else { 481798921bdaSJacob 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); 481852f91c60SVaclav Hapla } 481952f91c60SVaclav Hapla PetscFunctionReturn(0); 482052f91c60SVaclav Hapla } 482152f91c60SVaclav Hapla 48229371c9d4SSatish Balay PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer) { 48233ea6fe3dSLisandro Dalcin Mat_SeqAIJ *a = (Mat_SeqAIJ *)mat->data; 48243ea6fe3dSLisandro Dalcin PetscInt header[4], *rowlens, M, N, nz, sum, rows, cols, i; 4825fbdbba38SShri Abhyankar 4826fbdbba38SShri Abhyankar PetscFunctionBegin; 48279566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 4828bbead8a2SBarry Smith 48293ea6fe3dSLisandro Dalcin /* read in matrix header */ 48309566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT)); 483108401ef6SPierre Jolivet PetscCheck(header[0] == MAT_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file"); 48329371c9d4SSatish Balay M = header[1]; 48339371c9d4SSatish Balay N = header[2]; 48349371c9d4SSatish Balay nz = header[3]; 483508401ef6SPierre Jolivet PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M); 483608401ef6SPierre Jolivet PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N); 483708401ef6SPierre Jolivet PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Matrix stored in special format on disk, cannot load as SeqAIJ"); 4838fbdbba38SShri Abhyankar 48393ea6fe3dSLisandro Dalcin /* set block sizes from the viewer's .info file */ 48409566063dSJacob Faibussowitsch PetscCall(MatLoad_Binary_BlockSizes(mat, viewer)); 48413ea6fe3dSLisandro Dalcin /* set local and global sizes if not set already */ 48423ea6fe3dSLisandro Dalcin if (mat->rmap->n < 0) mat->rmap->n = M; 48433ea6fe3dSLisandro Dalcin if (mat->cmap->n < 0) mat->cmap->n = N; 48443ea6fe3dSLisandro Dalcin if (mat->rmap->N < 0) mat->rmap->N = M; 48453ea6fe3dSLisandro Dalcin if (mat->cmap->N < 0) mat->cmap->N = N; 48469566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->rmap)); 48479566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->cmap)); 48483ea6fe3dSLisandro Dalcin 48493ea6fe3dSLisandro Dalcin /* check if the matrix sizes are correct */ 48509566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 4851aed4548fSBarry 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); 48523ea6fe3dSLisandro Dalcin 4853fbdbba38SShri Abhyankar /* read in row lengths */ 48549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(M, &rowlens)); 48559566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, rowlens, M, NULL, PETSC_INT)); 48563ea6fe3dSLisandro Dalcin /* check if sum(rowlens) is same as nz */ 48579371c9d4SSatish Balay sum = 0; 48589371c9d4SSatish Balay for (i = 0; i < M; i++) sum += rowlens[i]; 485908401ef6SPierre 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); 48603ea6fe3dSLisandro Dalcin /* preallocate and check sizes */ 48619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(mat, 0, rowlens)); 48629566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 4863aed4548fSBarry 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); 48643ea6fe3dSLisandro Dalcin /* store row lengths */ 48659566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->ilen, rowlens, M)); 48669566063dSJacob Faibussowitsch PetscCall(PetscFree(rowlens)); 4867fbdbba38SShri Abhyankar 48683ea6fe3dSLisandro Dalcin /* fill in "i" row pointers */ 48699371c9d4SSatish Balay a->i[0] = 0; 48709371c9d4SSatish Balay for (i = 0; i < M; i++) a->i[i + 1] = a->i[i] + a->ilen[i]; 48713ea6fe3dSLisandro Dalcin /* read in "j" column indices */ 48729566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, a->j, nz, NULL, PETSC_INT)); 48733ea6fe3dSLisandro Dalcin /* read in "a" nonzero values */ 48749566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, a->a, nz, NULL, PETSC_SCALAR)); 4875fbdbba38SShri Abhyankar 48769566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 48779566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 4878fbdbba38SShri Abhyankar PetscFunctionReturn(0); 4879fbdbba38SShri Abhyankar } 4880fbdbba38SShri Abhyankar 48819371c9d4SSatish Balay PetscErrorCode MatEqual_SeqAIJ(Mat A, Mat B, PetscBool *flg) { 48827264ac53SSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data, *b = (Mat_SeqAIJ *)B->data; 4883fff043a9SJunchao Zhang const PetscScalar *aa, *ba; 4884eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 4885eeffb40dSHong Zhang PetscInt k; 4886eeffb40dSHong Zhang #endif 48877264ac53SSatish Balay 48883a40ed3dSBarry Smith PetscFunctionBegin; 4889bfeeae90SHong Zhang /* If the matrix dimensions are not equal,or no of nonzeros */ 4890d0f46423SBarry Smith if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) || (a->nz != b->nz)) { 4891ca44d042SBarry Smith *flg = PETSC_FALSE; 4892ca44d042SBarry Smith PetscFunctionReturn(0); 4893bcd2baecSBarry Smith } 48947264ac53SSatish Balay 48957264ac53SSatish Balay /* if the a->i are the same */ 48969566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->i, b->i, A->rmap->n + 1, flg)); 4897abc0a331SBarry Smith if (!*flg) PetscFunctionReturn(0); 48987264ac53SSatish Balay 48997264ac53SSatish Balay /* if a->j are the same */ 49009566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->j, b->j, a->nz, flg)); 4901abc0a331SBarry Smith if (!*flg) PetscFunctionReturn(0); 4902bcd2baecSBarry Smith 49039566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &aa)); 49049566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B, &ba)); 4905bcd2baecSBarry Smith /* if a->a are the same */ 4906eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 4907eeffb40dSHong Zhang for (k = 0; k < a->nz; k++) { 4908fff043a9SJunchao Zhang if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) { 4909eeffb40dSHong Zhang *flg = PETSC_FALSE; 49103a40ed3dSBarry Smith PetscFunctionReturn(0); 4911eeffb40dSHong Zhang } 4912eeffb40dSHong Zhang } 4913eeffb40dSHong Zhang #else 49149566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(aa, ba, a->nz, flg)); 4915eeffb40dSHong Zhang #endif 49169566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &aa)); 49179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B, &ba)); 4918eeffb40dSHong Zhang PetscFunctionReturn(0); 49197264ac53SSatish Balay } 492036db0b34SBarry Smith 492105869f15SSatish Balay /*@ 492236db0b34SBarry Smith MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format) 492336db0b34SBarry Smith provided by the user. 492436db0b34SBarry Smith 4925d083f849SBarry Smith Collective 492636db0b34SBarry Smith 492736db0b34SBarry Smith Input Parameters: 492836db0b34SBarry Smith + comm - must be an MPI communicator of size 1 492936db0b34SBarry Smith . m - number of rows 493036db0b34SBarry Smith . n - number of columns 4931483a2f95SBarry Smith . i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 493236db0b34SBarry Smith . j - column indices 493336db0b34SBarry Smith - a - matrix values 493436db0b34SBarry Smith 493536db0b34SBarry Smith Output Parameter: 493636db0b34SBarry Smith . mat - the matrix 493736db0b34SBarry Smith 493836db0b34SBarry Smith Level: intermediate 493936db0b34SBarry Smith 494036db0b34SBarry Smith Notes: 49410551d7c0SBarry Smith The i, j, and a arrays are not copied by this routine, the user must free these arrays 4942292fb18eSBarry Smith once the matrix is destroyed and not before 494336db0b34SBarry Smith 494436db0b34SBarry Smith You cannot set new nonzero locations into this matrix, that will generate an error. 494536db0b34SBarry Smith 4946bfeeae90SHong Zhang The i and j indices are 0 based 494736db0b34SBarry Smith 4948a4552177SSatish Balay The format which is used for the sparse matrix input, is equivalent to a 4949a4552177SSatish Balay row-major ordering.. i.e for the following matrix, the input data expected is 49508eef79e4SBarry Smith as shown 4951a4552177SSatish Balay 49528eef79e4SBarry Smith $ 1 0 0 49538eef79e4SBarry Smith $ 2 0 3 49548eef79e4SBarry Smith $ 4 5 6 49558eef79e4SBarry Smith $ 49568eef79e4SBarry Smith $ i = {0,1,3,6} [size = nrow+1 = 3+1] 49578eef79e4SBarry Smith $ j = {0,0,2,0,1,2} [size = 6]; values must be sorted for each row 49588eef79e4SBarry Smith $ v = {1,2,3,4,5,6} [size = 6] 4959a4552177SSatish Balay 4960db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateMPIAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()` 496136db0b34SBarry Smith 496236db0b34SBarry Smith @*/ 49639371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat) { 4964cbcfb4deSHong Zhang PetscInt ii; 496536db0b34SBarry Smith Mat_SeqAIJ *aij; 4966cbcfb4deSHong Zhang PetscInt jj; 496736db0b34SBarry Smith 496836db0b34SBarry Smith PetscFunctionBegin; 4969aed4548fSBarry Smith PetscCheck(m <= 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0"); 49709566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 49719566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 49729566063dSJacob Faibussowitsch /* PetscCall(MatSetBlockSizes(*mat,,)); */ 49739566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQAIJ)); 49749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, MAT_SKIP_ALLOCATION, NULL)); 4975ab93d7beSBarry Smith aij = (Mat_SeqAIJ *)(*mat)->data; 49769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &aij->imax)); 49779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &aij->ilen)); 4978ab93d7beSBarry Smith 497936db0b34SBarry Smith aij->i = i; 498036db0b34SBarry Smith aij->j = j; 498136db0b34SBarry Smith aij->a = a; 498236db0b34SBarry Smith aij->singlemalloc = PETSC_FALSE; 498336db0b34SBarry Smith aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 4984e6b907acSBarry Smith aij->free_a = PETSC_FALSE; 4985e6b907acSBarry Smith aij->free_ij = PETSC_FALSE; 498636db0b34SBarry Smith 4987cbc6b225SStefano Zampini for (ii = 0, aij->nonzerorowcnt = 0, aij->rmax = 0; ii < m; ii++) { 498836db0b34SBarry Smith aij->ilen[ii] = aij->imax[ii] = i[ii + 1] - i[ii]; 498976bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4990aed4548fSBarry 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]); 49919985e31cSBarry Smith for (jj = i[ii] + 1; jj < i[ii + 1]; jj++) { 499208401ef6SPierre 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); 499308401ef6SPierre 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); 49949985e31cSBarry Smith } 499536db0b34SBarry Smith } 499676bd3646SJed Brown } 499776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 499836db0b34SBarry Smith for (ii = 0; ii < aij->i[m]; ii++) { 499908401ef6SPierre 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]); 5000aed4548fSBarry 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]); 500136db0b34SBarry Smith } 500276bd3646SJed Brown } 500336db0b34SBarry Smith 50049566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 50059566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 500636db0b34SBarry Smith PetscFunctionReturn(0); 500736db0b34SBarry Smith } 5008cbc6b225SStefano Zampini 5009f62e3866SBarry Smith /*@ 5010d021a1c5SVictor Minden MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format) 50118a0b0e6bSVictor Minden provided by the user. 50128a0b0e6bSVictor Minden 5013d083f849SBarry Smith Collective 50148a0b0e6bSVictor Minden 50158a0b0e6bSVictor Minden Input Parameters: 50168a0b0e6bSVictor Minden + comm - must be an MPI communicator of size 1 50178a0b0e6bSVictor Minden . m - number of rows 50188a0b0e6bSVictor Minden . n - number of columns 50198a0b0e6bSVictor Minden . i - row indices 50208a0b0e6bSVictor Minden . j - column indices 50211230e6d1SVictor Minden . a - matrix values 50221230e6d1SVictor Minden . nz - number of nonzeros 5023f62e3866SBarry Smith - idx - if the i and j indices start with 1 use PETSC_TRUE otherwise use PETSC_FALSE 50248a0b0e6bSVictor Minden 50258a0b0e6bSVictor Minden Output Parameter: 50268a0b0e6bSVictor Minden . mat - the matrix 50278a0b0e6bSVictor Minden 50288a0b0e6bSVictor Minden Level: intermediate 50298a0b0e6bSVictor Minden 5030f62e3866SBarry Smith Example: 5031f62e3866SBarry Smith For the following matrix, the input data expected is as shown (using 0 based indexing) 50329e99939fSJunchao Zhang .vb 50338a0b0e6bSVictor Minden 1 0 0 50348a0b0e6bSVictor Minden 2 0 3 50358a0b0e6bSVictor Minden 4 5 6 50368a0b0e6bSVictor Minden 50378a0b0e6bSVictor Minden i = {0,1,1,2,2,2} 50388a0b0e6bSVictor Minden j = {0,0,2,0,1,2} 50398a0b0e6bSVictor Minden v = {1,2,3,4,5,6} 50409e99939fSJunchao Zhang .ve 50418a0b0e6bSVictor Minden 5042db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateSeqAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()`, `MatSetValuesCOO()` 50438a0b0e6bSVictor Minden 50448a0b0e6bSVictor Minden @*/ 50459371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat, PetscInt nz, PetscBool idx) { 5046d021a1c5SVictor Minden PetscInt ii, *nnz, one = 1, row, col; 50478a0b0e6bSVictor Minden 50488a0b0e6bSVictor Minden PetscFunctionBegin; 50499566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m, &nnz)); 50509371c9d4SSatish Balay for (ii = 0; ii < nz; ii++) { nnz[i[ii] - !!idx] += 1; } 50519566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 50529566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, m, n)); 50539566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATSEQAIJ)); 50549566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, 0, nnz)); 50551230e6d1SVictor Minden for (ii = 0; ii < nz; ii++) { 50561230e6d1SVictor Minden if (idx) { 50571230e6d1SVictor Minden row = i[ii] - 1; 50581230e6d1SVictor Minden col = j[ii] - 1; 50591230e6d1SVictor Minden } else { 50601230e6d1SVictor Minden row = i[ii]; 50611230e6d1SVictor Minden col = j[ii]; 50628a0b0e6bSVictor Minden } 50639566063dSJacob Faibussowitsch PetscCall(MatSetValues(*mat, one, &row, one, &col, &a[ii], ADD_VALUES)); 50648a0b0e6bSVictor Minden } 50659566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 50669566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 50679566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 50688a0b0e6bSVictor Minden PetscFunctionReturn(0); 50698a0b0e6bSVictor Minden } 507036db0b34SBarry Smith 50719371c9d4SSatish Balay PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A) { 5072acf2f550SJed Brown Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 5073acf2f550SJed Brown 5074acf2f550SJed Brown PetscFunctionBegin; 5075acf2f550SJed Brown a->idiagvalid = PETSC_FALSE; 5076acf2f550SJed Brown a->ibdiagvalid = PETSC_FALSE; 50772205254eSKarl Rupp 50789566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal_Inode(A)); 5079acf2f550SJed Brown PetscFunctionReturn(0); 5080acf2f550SJed Brown } 5081acf2f550SJed Brown 50829371c9d4SSatish Balay PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat) { 50839c8f2541SHong Zhang PetscFunctionBegin; 50849566063dSJacob Faibussowitsch PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm, inmat, n, scall, outmat)); 50859c8f2541SHong Zhang PetscFunctionReturn(0); 50869c8f2541SHong Zhang } 50879c8f2541SHong Zhang 508881824310SBarry Smith /* 508953dd7562SDmitry Karpeev Permute A into C's *local* index space using rowemb,colemb. 509053dd7562SDmitry Karpeev The embedding are supposed to be injections and the above implies that the range of rowemb is a subset 509153dd7562SDmitry Karpeev of [0,m), colemb is in [0,n). 509253dd7562SDmitry Karpeev If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A. 509353dd7562SDmitry Karpeev */ 50949371c9d4SSatish Balay PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C, IS rowemb, IS colemb, MatStructure pattern, Mat B) { 509553dd7562SDmitry Karpeev /* If making this function public, change the error returned in this function away from _PLIB. */ 509653dd7562SDmitry Karpeev Mat_SeqAIJ *Baij; 509753dd7562SDmitry Karpeev PetscBool seqaij; 509853dd7562SDmitry Karpeev PetscInt m, n, *nz, i, j, count; 509953dd7562SDmitry Karpeev PetscScalar v; 510053dd7562SDmitry Karpeev const PetscInt *rowindices, *colindices; 510153dd7562SDmitry Karpeev 510253dd7562SDmitry Karpeev PetscFunctionBegin; 510353dd7562SDmitry Karpeev if (!B) PetscFunctionReturn(0); 510453dd7562SDmitry Karpeev /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */ 51059566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)B, MATSEQAIJ, &seqaij)); 510628b400f6SJacob Faibussowitsch PetscCheck(seqaij, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is of wrong type"); 510753dd7562SDmitry Karpeev if (rowemb) { 51089566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rowemb, &m)); 510908401ef6SPierre 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); 511053dd7562SDmitry Karpeev } else { 511108401ef6SPierre Jolivet PetscCheck(C->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is row-incompatible with the target matrix"); 511253dd7562SDmitry Karpeev } 511353dd7562SDmitry Karpeev if (colemb) { 51149566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(colemb, &n)); 511508401ef6SPierre 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); 511653dd7562SDmitry Karpeev } else { 511708401ef6SPierre Jolivet PetscCheck(C->cmap->n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is col-incompatible with the target matrix"); 511853dd7562SDmitry Karpeev } 511953dd7562SDmitry Karpeev 512053dd7562SDmitry Karpeev Baij = (Mat_SeqAIJ *)(B->data); 512153dd7562SDmitry Karpeev if (pattern == DIFFERENT_NONZERO_PATTERN) { 51229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n, &nz)); 51239371c9d4SSatish Balay for (i = 0; i < B->rmap->n; i++) { nz[i] = Baij->i[i + 1] - Baij->i[i]; } 51249566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(C, 0, nz)); 51259566063dSJacob Faibussowitsch PetscCall(PetscFree(nz)); 512653dd7562SDmitry Karpeev } 5127*48a46eb9SPierre Jolivet if (pattern == SUBSET_NONZERO_PATTERN) PetscCall(MatZeroEntries(C)); 512853dd7562SDmitry Karpeev count = 0; 512953dd7562SDmitry Karpeev rowindices = NULL; 513053dd7562SDmitry Karpeev colindices = NULL; 5131*48a46eb9SPierre Jolivet if (rowemb) PetscCall(ISGetIndices(rowemb, &rowindices)); 5132*48a46eb9SPierre Jolivet if (colemb) PetscCall(ISGetIndices(colemb, &colindices)); 513353dd7562SDmitry Karpeev for (i = 0; i < B->rmap->n; i++) { 513453dd7562SDmitry Karpeev PetscInt row; 513553dd7562SDmitry Karpeev row = i; 513653dd7562SDmitry Karpeev if (rowindices) row = rowindices[i]; 513753dd7562SDmitry Karpeev for (j = Baij->i[i]; j < Baij->i[i + 1]; j++) { 513853dd7562SDmitry Karpeev PetscInt col; 513953dd7562SDmitry Karpeev col = Baij->j[count]; 514053dd7562SDmitry Karpeev if (colindices) col = colindices[col]; 514153dd7562SDmitry Karpeev v = Baij->a[count]; 51429566063dSJacob Faibussowitsch PetscCall(MatSetValues(C, 1, &row, 1, &col, &v, INSERT_VALUES)); 514353dd7562SDmitry Karpeev ++count; 514453dd7562SDmitry Karpeev } 514553dd7562SDmitry Karpeev } 514653dd7562SDmitry Karpeev /* FIXME: set C's nonzerostate correctly. */ 514753dd7562SDmitry Karpeev /* Assembly for C is necessary. */ 514853dd7562SDmitry Karpeev C->preallocated = PETSC_TRUE; 514953dd7562SDmitry Karpeev C->assembled = PETSC_TRUE; 515053dd7562SDmitry Karpeev C->was_assembled = PETSC_FALSE; 515153dd7562SDmitry Karpeev PetscFunctionReturn(0); 515253dd7562SDmitry Karpeev } 515353dd7562SDmitry Karpeev 51544099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL; 51554099cc6bSBarry Smith 51564099cc6bSBarry Smith /*@C 51574099cc6bSBarry Smith MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype 51584099cc6bSBarry Smith 51594099cc6bSBarry Smith Collective on Mat 51604099cc6bSBarry Smith 51614099cc6bSBarry Smith Input Parameters: 51624099cc6bSBarry Smith + mat - the matrix object 51634099cc6bSBarry Smith - matype - matrix type 51644099cc6bSBarry Smith 51654099cc6bSBarry Smith Options Database Key: 51664099cc6bSBarry Smith . -mat_seqai_type <method> - for example seqaijcrl 51674099cc6bSBarry Smith 51684099cc6bSBarry Smith Level: intermediate 51694099cc6bSBarry Smith 5170db781477SPatrick Sanan .seealso: `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat` 51714099cc6bSBarry Smith @*/ 51729371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetType(Mat mat, MatType matype) { 51734099cc6bSBarry Smith PetscBool sametype; 51745f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(Mat, MatType, MatReuse, Mat *); 51754099cc6bSBarry Smith 51764099cc6bSBarry Smith PetscFunctionBegin; 51774099cc6bSBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 51789566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, matype, &sametype)); 51794099cc6bSBarry Smith if (sametype) PetscFunctionReturn(0); 51804099cc6bSBarry Smith 51819566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(MatSeqAIJList, matype, &r)); 51825f80ce2aSJacob Faibussowitsch PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Mat type given: %s", matype); 51839566063dSJacob Faibussowitsch PetscCall((*r)(mat, matype, MAT_INPLACE_MATRIX, &mat)); 51844099cc6bSBarry Smith PetscFunctionReturn(0); 51854099cc6bSBarry Smith } 51864099cc6bSBarry Smith 51874099cc6bSBarry Smith /*@C 51884099cc6bSBarry Smith MatSeqAIJRegister - - Adds a new sub-matrix type for sequential AIJ matrices 51894099cc6bSBarry Smith 51904099cc6bSBarry Smith Not Collective 51914099cc6bSBarry Smith 51924099cc6bSBarry Smith Input Parameters: 51934099cc6bSBarry Smith + name - name of a new user-defined matrix type, for example MATSEQAIJCRL 51944099cc6bSBarry Smith - function - routine to convert to subtype 51954099cc6bSBarry Smith 51964099cc6bSBarry Smith Notes: 51974099cc6bSBarry Smith MatSeqAIJRegister() may be called multiple times to add several user-defined solvers. 51984099cc6bSBarry Smith 51994099cc6bSBarry Smith Then, your matrix can be chosen with the procedural interface at runtime via the option 52004099cc6bSBarry Smith $ -mat_seqaij_type my_mat 52014099cc6bSBarry Smith 52024099cc6bSBarry Smith Level: advanced 52034099cc6bSBarry Smith 5204db781477SPatrick Sanan .seealso: `MatSeqAIJRegisterAll()` 52054099cc6bSBarry Smith 52064099cc6bSBarry Smith Level: advanced 52074099cc6bSBarry Smith @*/ 52089371c9d4SSatish Balay PetscErrorCode MatSeqAIJRegister(const char sname[], PetscErrorCode (*function)(Mat, MatType, MatReuse, Mat *)) { 52094099cc6bSBarry Smith PetscFunctionBegin; 52109566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 52119566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&MatSeqAIJList, sname, function)); 52124099cc6bSBarry Smith PetscFunctionReturn(0); 52134099cc6bSBarry Smith } 52144099cc6bSBarry Smith 52154099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE; 52164099cc6bSBarry Smith 52174099cc6bSBarry Smith /*@C 52184099cc6bSBarry Smith MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ 52194099cc6bSBarry Smith 52204099cc6bSBarry Smith Not Collective 52214099cc6bSBarry Smith 52224099cc6bSBarry Smith Level: advanced 52234099cc6bSBarry Smith 5224db781477SPatrick Sanan .seealso: `MatRegisterAll()`, `MatSeqAIJRegister()` 52254099cc6bSBarry Smith @*/ 52269371c9d4SSatish Balay PetscErrorCode MatSeqAIJRegisterAll(void) { 52274099cc6bSBarry Smith PetscFunctionBegin; 52284099cc6bSBarry Smith if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0); 52294099cc6bSBarry Smith MatSeqAIJRegisterAllCalled = PETSC_TRUE; 52304099cc6bSBarry Smith 52319566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCRL, MatConvert_SeqAIJ_SeqAIJCRL)); 52329566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJPERM, MatConvert_SeqAIJ_SeqAIJPERM)); 52339566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJSELL, MatConvert_SeqAIJ_SeqAIJSELL)); 52349779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 52359566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJMKL, MatConvert_SeqAIJ_SeqAIJMKL)); 5236485f9817SRichard Tran Mills #endif 52375063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA) 52389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 52395063d097SStefano Zampini #endif 52405063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 52419566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJKOKKOS, MatConvert_SeqAIJ_SeqAIJKokkos)); 52425063d097SStefano Zampini #endif 52434099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA) 52449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL)); 52454099cc6bSBarry Smith #endif 52464099cc6bSBarry Smith PetscFunctionReturn(0); 52474099cc6bSBarry Smith } 524853dd7562SDmitry Karpeev 524953dd7562SDmitry Karpeev /* 525081824310SBarry Smith Special version for direct calls from Fortran 525181824310SBarry Smith */ 5252af0996ceSBarry Smith #include <petsc/private/fortranimpl.h> 525381824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS) 525481824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ 525581824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 525681824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij 525781824310SBarry Smith #endif 525881824310SBarry Smith 525981824310SBarry Smith /* Change these macros so can be used in void function */ 526098921bdaSJacob Faibussowitsch 526198921bdaSJacob Faibussowitsch /* Change these macros so can be used in void function */ 52629566063dSJacob Faibussowitsch /* Identical to PetscCallVoid, except it assigns to *_ierr */ 52639566063dSJacob Faibussowitsch #undef PetscCall 52649371c9d4SSatish Balay #define PetscCall(...) \ 52659371c9d4SSatish Balay do { \ 52665f80ce2aSJacob Faibussowitsch PetscErrorCode ierr_msv_mpiaij = __VA_ARGS__; \ 526798921bdaSJacob Faibussowitsch if (PetscUnlikely(ierr_msv_mpiaij)) { \ 526898921bdaSJacob Faibussowitsch *_ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr_msv_mpiaij, PETSC_ERROR_REPEAT, " "); \ 526998921bdaSJacob Faibussowitsch return; \ 527098921bdaSJacob Faibussowitsch } \ 527198921bdaSJacob Faibussowitsch } while (0) 527298921bdaSJacob Faibussowitsch 527398921bdaSJacob Faibussowitsch #undef SETERRQ 52749371c9d4SSatish Balay #define SETERRQ(comm, ierr, ...) \ 52759371c9d4SSatish Balay do { \ 527698921bdaSJacob Faibussowitsch *_ierr = PetscError(comm, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr, PETSC_ERROR_INITIAL, __VA_ARGS__); \ 527798921bdaSJacob Faibussowitsch return; \ 527898921bdaSJacob Faibussowitsch } while (0) 527981824310SBarry Smith 52809371c9d4SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA, PetscInt *mm, const PetscInt im[], PetscInt *nn, const PetscInt in[], const PetscScalar v[], InsertMode *isis, PetscErrorCode *_ierr) { 528181824310SBarry Smith Mat A = *AA; 528281824310SBarry Smith PetscInt m = *mm, n = *nn; 528381824310SBarry Smith InsertMode is = *isis; 528481824310SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 528581824310SBarry Smith PetscInt *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N; 528681824310SBarry Smith PetscInt *imax, *ai, *ailen; 528781824310SBarry Smith PetscInt *aj, nonew = a->nonew, lastcol = -1; 528854f21887SBarry Smith MatScalar *ap, value, *aa; 5289ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 5290ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 529181824310SBarry Smith 529281824310SBarry Smith PetscFunctionBegin; 52934994cf47SJed Brown MatCheckPreallocated(A, 1); 529481824310SBarry Smith imax = a->imax; 529581824310SBarry Smith ai = a->i; 529681824310SBarry Smith ailen = a->ilen; 529781824310SBarry Smith aj = a->j; 529881824310SBarry Smith aa = a->a; 529981824310SBarry Smith 530081824310SBarry Smith for (k = 0; k < m; k++) { /* loop over added rows */ 530181824310SBarry Smith row = im[k]; 530281824310SBarry Smith if (row < 0) continue; 53035f80ce2aSJacob Faibussowitsch PetscCheck(row < A->rmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Row too large"); 53049371c9d4SSatish Balay rp = aj + ai[row]; 53059371c9d4SSatish Balay ap = aa + ai[row]; 53069371c9d4SSatish Balay rmax = imax[row]; 53079371c9d4SSatish Balay nrow = ailen[row]; 530881824310SBarry Smith low = 0; 530981824310SBarry Smith high = nrow; 531081824310SBarry Smith for (l = 0; l < n; l++) { /* loop over added columns */ 531181824310SBarry Smith if (in[l] < 0) continue; 53125f80ce2aSJacob Faibussowitsch PetscCheck(in[l] < A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Column too large"); 531381824310SBarry Smith col = in[l]; 53142205254eSKarl Rupp if (roworiented) value = v[l + k * n]; 53152205254eSKarl Rupp else value = v[k + l * m]; 53162205254eSKarl Rupp 531781824310SBarry Smith if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 531881824310SBarry Smith 53192205254eSKarl Rupp if (col <= lastcol) low = 0; 53202205254eSKarl Rupp else high = nrow; 532181824310SBarry Smith lastcol = col; 532281824310SBarry Smith while (high - low > 5) { 532381824310SBarry Smith t = (low + high) / 2; 532481824310SBarry Smith if (rp[t] > col) high = t; 532581824310SBarry Smith else low = t; 532681824310SBarry Smith } 532781824310SBarry Smith for (i = low; i < high; i++) { 532881824310SBarry Smith if (rp[i] > col) break; 532981824310SBarry Smith if (rp[i] == col) { 533081824310SBarry Smith if (is == ADD_VALUES) ap[i] += value; 533181824310SBarry Smith else ap[i] = value; 533281824310SBarry Smith goto noinsert; 533381824310SBarry Smith } 533481824310SBarry Smith } 533581824310SBarry Smith if (value == 0.0 && ignorezeroentries) goto noinsert; 533681824310SBarry Smith if (nonew == 1) goto noinsert; 53375f80ce2aSJacob Faibussowitsch PetscCheck(nonew != -1, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero in the matrix"); 5338fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A, A->rmap->n, 1, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar); 53399371c9d4SSatish Balay N = nrow++ - 1; 53409371c9d4SSatish Balay a->nz++; 53419371c9d4SSatish Balay high++; 534281824310SBarry Smith /* shift up all the later entries in this row */ 534381824310SBarry Smith for (ii = N; ii >= i; ii--) { 534481824310SBarry Smith rp[ii + 1] = rp[ii]; 534581824310SBarry Smith ap[ii + 1] = ap[ii]; 534681824310SBarry Smith } 534781824310SBarry Smith rp[i] = col; 534881824310SBarry Smith ap[i] = value; 5349e56f5c9eSBarry Smith A->nonzerostate++; 535081824310SBarry Smith noinsert:; 535181824310SBarry Smith low = i + 1; 535281824310SBarry Smith } 535381824310SBarry Smith ailen[row] = nrow; 535481824310SBarry Smith } 535581824310SBarry Smith PetscFunctionReturnVoid(); 535681824310SBarry Smith } 535798921bdaSJacob Faibussowitsch /* Undefining these here since they were redefined from their original definition above! No 535898921bdaSJacob Faibussowitsch * other PETSc functions should be defined past this point, as it is impossible to recover the 535998921bdaSJacob Faibussowitsch * original definitions */ 53609566063dSJacob Faibussowitsch #undef PetscCall 536198921bdaSJacob Faibussowitsch #undef SETERRQ 5362