xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 3faff0630ddb0e5c928de8ab5c63f2cda2d2edd1)
1d5d45c9bSBarry Smith /*
23369ce9aSBarry Smith     Defines the basic matrix operations for the AIJ (compressed row)
3d5d45c9bSBarry Smith   matrix storage format.
4d5d45c9bSBarry Smith */
53369ce9aSBarry Smith 
6c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h> /*I "petscmat.h" I*/
7c6db04a5SJed Brown #include <petscblaslapack.h>
8c6db04a5SJed Brown #include <petscbt.h>
9af0996ceSBarry Smith #include <petsc/private/kernels/blocktranspose.h>
100716a85fSBarry Smith 
119371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A) {
124099cc6bSBarry Smith   PetscBool flg;
134099cc6bSBarry Smith   char      type[256];
144099cc6bSBarry Smith 
154099cc6bSBarry Smith   PetscFunctionBegin;
16d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)A);
179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-mat_seqaij_type", "Matrix SeqAIJ type", "MatSeqAIJSetType", MatSeqAIJList, "seqaij", type, 256, &flg));
189566063dSJacob Faibussowitsch   if (flg) PetscCall(MatSeqAIJSetType(A, type));
19d0609cedSBarry Smith   PetscOptionsEnd();
204099cc6bSBarry Smith   PetscFunctionReturn(0);
214099cc6bSBarry Smith }
224099cc6bSBarry Smith 
239371c9d4SSatish Balay PetscErrorCode MatGetColumnReductions_SeqAIJ(Mat A, PetscInt type, PetscReal *reductions) {
240716a85fSBarry Smith   PetscInt    i, m, n;
250716a85fSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
260716a85fSBarry Smith 
270716a85fSBarry Smith   PetscFunctionBegin;
289566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
299566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(reductions, n));
300716a85fSBarry Smith   if (type == NORM_2) {
31ad540459SPierre Jolivet     for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscAbsScalar(aij->a[i] * aij->a[i]);
320716a85fSBarry Smith   } else if (type == NORM_1) {
33ad540459SPierre Jolivet     for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]);
340716a85fSBarry Smith   } else if (type == NORM_INFINITY) {
35ad540459SPierre Jolivet     for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]), reductions[aij->j[i]]);
36857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
37ad540459SPierre Jolivet     for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscRealPart(aij->a[i]);
38857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
39ad540459SPierre Jolivet     for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscImaginaryPart(aij->a[i]);
40857cbf51SRichard Tran Mills   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown reduction type");
410716a85fSBarry Smith 
420716a85fSBarry Smith   if (type == NORM_2) {
43a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
44857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
45a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] /= m;
460716a85fSBarry Smith   }
470716a85fSBarry Smith   PetscFunctionReturn(0);
480716a85fSBarry Smith }
490716a85fSBarry Smith 
509371c9d4SSatish Balay PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A, IS *is) {
513a062f41SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data;
523a062f41SBarry Smith   PetscInt        i, m = A->rmap->n, cnt = 0, bs = A->rmap->bs;
533a062f41SBarry Smith   const PetscInt *jj = a->j, *ii = a->i;
543a062f41SBarry Smith   PetscInt       *rows;
553a062f41SBarry Smith 
563a062f41SBarry Smith   PetscFunctionBegin;
573a062f41SBarry Smith   for (i = 0; i < m; i++) {
58ad540459SPierre Jolivet     if ((ii[i] != ii[i + 1]) && ((jj[ii[i]] < bs * (i / bs)) || (jj[ii[i + 1] - 1] > bs * ((i + bs) / bs) - 1))) cnt++;
593a062f41SBarry Smith   }
609566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(cnt, &rows));
613a062f41SBarry Smith   cnt = 0;
623a062f41SBarry Smith   for (i = 0; i < m; i++) {
633a062f41SBarry Smith     if ((ii[i] != ii[i + 1]) && ((jj[ii[i]] < bs * (i / bs)) || (jj[ii[i + 1] - 1] > bs * ((i + bs) / bs) - 1))) {
643a062f41SBarry Smith       rows[cnt] = i;
653a062f41SBarry Smith       cnt++;
663a062f41SBarry Smith     }
673a062f41SBarry Smith   }
689566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cnt, rows, PETSC_OWN_POINTER, is));
693a062f41SBarry Smith   PetscFunctionReturn(0);
703a062f41SBarry Smith }
713a062f41SBarry Smith 
729371c9d4SSatish Balay PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A, PetscInt *nrows, PetscInt **zrows) {
736ce1633cSBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
74fff043a9SJunchao Zhang   const MatScalar *aa;
756ce1633cSBarry Smith   PetscInt         i, m = A->rmap->n, cnt = 0;
76b2db7409Sstefano_zampini   const PetscInt  *ii = a->i, *jj = a->j, *diag;
776ce1633cSBarry Smith   PetscInt        *rows;
786ce1633cSBarry Smith 
796ce1633cSBarry Smith   PetscFunctionBegin;
809566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
819566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqAIJ(A));
826ce1633cSBarry Smith   diag = a->diag;
836ce1633cSBarry Smith   for (i = 0; i < m; i++) {
84ad540459SPierre Jolivet     if ((diag[i] >= ii[i + 1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) cnt++;
856ce1633cSBarry Smith   }
869566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(cnt, &rows));
876ce1633cSBarry Smith   cnt = 0;
886ce1633cSBarry Smith   for (i = 0; i < m; i++) {
89ad540459SPierre Jolivet     if ((diag[i] >= ii[i + 1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) rows[cnt++] = i;
906ce1633cSBarry Smith   }
91f1f41ecbSJed Brown   *nrows = cnt;
92f1f41ecbSJed Brown   *zrows = rows;
939566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
94f1f41ecbSJed Brown   PetscFunctionReturn(0);
95f1f41ecbSJed Brown }
96f1f41ecbSJed Brown 
979371c9d4SSatish Balay PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A, IS *zrows) {
98f1f41ecbSJed Brown   PetscInt nrows, *rows;
99f1f41ecbSJed Brown 
100f1f41ecbSJed Brown   PetscFunctionBegin;
1010298fd71SBarry Smith   *zrows = NULL;
1029566063dSJacob Faibussowitsch   PetscCall(MatFindZeroDiagonals_SeqAIJ_Private(A, &nrows, &rows));
1039566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), nrows, rows, PETSC_OWN_POINTER, zrows));
1046ce1633cSBarry Smith   PetscFunctionReturn(0);
1056ce1633cSBarry Smith }
1066ce1633cSBarry Smith 
1079371c9d4SSatish Balay PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A, IS *keptrows) {
108b3a44c85SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
109b3a44c85SBarry Smith   const MatScalar *aa;
110b3a44c85SBarry Smith   PetscInt         m = A->rmap->n, cnt = 0;
111b3a44c85SBarry Smith   const PetscInt  *ii;
112b3a44c85SBarry Smith   PetscInt         n, i, j, *rows;
113b3a44c85SBarry Smith 
114b3a44c85SBarry Smith   PetscFunctionBegin;
1159566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
116f4259b30SLisandro Dalcin   *keptrows = NULL;
117b3a44c85SBarry Smith   ii        = a->i;
118b3a44c85SBarry Smith   for (i = 0; i < m; i++) {
119b3a44c85SBarry Smith     n = ii[i + 1] - ii[i];
120b3a44c85SBarry Smith     if (!n) {
121b3a44c85SBarry Smith       cnt++;
122b3a44c85SBarry Smith       goto ok1;
123b3a44c85SBarry Smith     }
1242e5835c6SStefano Zampini     for (j = ii[i]; j < ii[i + 1]; j++) {
125b3a44c85SBarry Smith       if (aa[j] != 0.0) goto ok1;
126b3a44c85SBarry Smith     }
127b3a44c85SBarry Smith     cnt++;
128b3a44c85SBarry Smith   ok1:;
129b3a44c85SBarry Smith   }
1302e5835c6SStefano Zampini   if (!cnt) {
1319566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
1322e5835c6SStefano Zampini     PetscFunctionReturn(0);
1332e5835c6SStefano Zampini   }
1349566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(A->rmap->n - cnt, &rows));
135b3a44c85SBarry Smith   cnt = 0;
136b3a44c85SBarry Smith   for (i = 0; i < m; i++) {
137b3a44c85SBarry Smith     n = ii[i + 1] - ii[i];
138b3a44c85SBarry Smith     if (!n) continue;
1392e5835c6SStefano Zampini     for (j = ii[i]; j < ii[i + 1]; j++) {
140b3a44c85SBarry Smith       if (aa[j] != 0.0) {
141b3a44c85SBarry Smith         rows[cnt++] = i;
142b3a44c85SBarry Smith         break;
143b3a44c85SBarry Smith       }
144b3a44c85SBarry Smith     }
145b3a44c85SBarry Smith   }
1469566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
1479566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cnt, rows, PETSC_OWN_POINTER, keptrows));
148b3a44c85SBarry Smith   PetscFunctionReturn(0);
149b3a44c85SBarry Smith }
150b3a44c85SBarry Smith 
1519371c9d4SSatish Balay PetscErrorCode MatDiagonalSet_SeqAIJ(Mat Y, Vec D, InsertMode is) {
15279299369SBarry Smith   Mat_SeqAIJ        *aij = (Mat_SeqAIJ *)Y->data;
15399e65526SBarry Smith   PetscInt           i, m = Y->rmap->n;
15499e65526SBarry Smith   const PetscInt    *diag;
1552e5835c6SStefano Zampini   MatScalar         *aa;
15699e65526SBarry Smith   const PetscScalar *v;
157ace3abfcSBarry Smith   PetscBool          missing;
15879299369SBarry Smith 
15979299369SBarry Smith   PetscFunctionBegin;
16009f38230SBarry Smith   if (Y->assembled) {
1619566063dSJacob Faibussowitsch     PetscCall(MatMissingDiagonal_SeqAIJ(Y, &missing, NULL));
16209f38230SBarry Smith     if (!missing) {
16379299369SBarry Smith       diag = aij->diag;
1649566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(D, &v));
1659566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(Y, &aa));
16679299369SBarry Smith       if (is == INSERT_VALUES) {
167ad540459SPierre Jolivet         for (i = 0; i < m; i++) aa[diag[i]] = v[i];
16879299369SBarry Smith       } else {
169ad540459SPierre Jolivet         for (i = 0; i < m; i++) aa[diag[i]] += v[i];
17079299369SBarry Smith       }
1719566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJRestoreArray(Y, &aa));
1729566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(D, &v));
17379299369SBarry Smith       PetscFunctionReturn(0);
17479299369SBarry Smith     }
1759566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJInvalidateDiagonal(Y));
17609f38230SBarry Smith   }
1779566063dSJacob Faibussowitsch   PetscCall(MatDiagonalSet_Default(Y, D, is));
17809f38230SBarry Smith   PetscFunctionReturn(0);
17909f38230SBarry Smith }
18079299369SBarry Smith 
1819371c9d4SSatish Balay PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *m, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
182416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
18397f1f81fSBarry Smith   PetscInt    i, ishift;
18417ab2063SBarry Smith 
1853a40ed3dSBarry Smith   PetscFunctionBegin;
186f1f2ae84SBarry Smith   if (m) *m = A->rmap->n;
1873a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
188bfeeae90SHong Zhang   ishift = 0;
189b94d7dedSBarry Smith   if (symmetric && A->structurally_symmetric != PETSC_BOOL3_TRUE) {
1909566063dSJacob Faibussowitsch     PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n, a->i, a->j, PETSC_TRUE, ishift, oshift, (PetscInt **)ia, (PetscInt **)ja));
191bfeeae90SHong Zhang   } else if (oshift == 1) {
1921a83f524SJed Brown     PetscInt *tia;
193d0f46423SBarry Smith     PetscInt  nz = a->i[A->rmap->n];
1943b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
1959566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n + 1, &tia));
1961a83f524SJed Brown     for (i = 0; i < A->rmap->n + 1; i++) tia[i] = a->i[i] + 1;
1971a83f524SJed Brown     *ia = tia;
198ecc77c7aSBarry Smith     if (ja) {
1991a83f524SJed Brown       PetscInt *tja;
2009566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz + 1, &tja));
2011a83f524SJed Brown       for (i = 0; i < nz; i++) tja[i] = a->j[i] + 1;
2021a83f524SJed Brown       *ja = tja;
203ecc77c7aSBarry Smith     }
2046945ee14SBarry Smith   } else {
205ecc77c7aSBarry Smith     *ia = a->i;
206ecc77c7aSBarry Smith     if (ja) *ja = a->j;
207a2ce50c7SBarry Smith   }
2083a40ed3dSBarry Smith   PetscFunctionReturn(0);
209a2744918SBarry Smith }
210a2744918SBarry Smith 
2119371c9d4SSatish Balay PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
2123a40ed3dSBarry Smith   PetscFunctionBegin;
2133a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
214b94d7dedSBarry Smith   if ((symmetric && A->structurally_symmetric != PETSC_BOOL3_TRUE) || oshift == 1) {
2159566063dSJacob Faibussowitsch     PetscCall(PetscFree(*ia));
2169566063dSJacob Faibussowitsch     if (ja) PetscCall(PetscFree(*ja));
217bcd2baecSBarry Smith   }
2183a40ed3dSBarry Smith   PetscFunctionReturn(0);
21917ab2063SBarry Smith }
22017ab2063SBarry Smith 
2219371c9d4SSatish Balay PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
2223b2fbd54SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
223d0f46423SBarry Smith   PetscInt    i, *collengths, *cia, *cja, n = A->cmap->n, m = A->rmap->n;
22497f1f81fSBarry Smith   PetscInt    nz = a->i[m], row, *jj, mr, col;
2253b2fbd54SBarry Smith 
2263a40ed3dSBarry Smith   PetscFunctionBegin;
227899cda47SBarry Smith   *nn = n;
2283a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2293b2fbd54SBarry Smith   if (symmetric) {
2309566063dSJacob Faibussowitsch     PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n, a->i, a->j, PETSC_TRUE, 0, oshift, (PetscInt **)ia, (PetscInt **)ja));
2313b2fbd54SBarry Smith   } else {
2329566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(n, &collengths));
2339566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n + 1, &cia));
2349566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nz, &cja));
2353b2fbd54SBarry Smith     jj = a->j;
236ad540459SPierre Jolivet     for (i = 0; i < nz; i++) collengths[jj[i]]++;
2373b2fbd54SBarry Smith     cia[0] = oshift;
238ad540459SPierre Jolivet     for (i = 0; i < n; i++) cia[i + 1] = cia[i] + collengths[i];
2399566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(collengths, n));
2403b2fbd54SBarry Smith     jj = a->j;
241a93ec695SBarry Smith     for (row = 0; row < m; row++) {
242a93ec695SBarry Smith       mr = a->i[row + 1] - a->i[row];
243a93ec695SBarry Smith       for (i = 0; i < mr; i++) {
244bfeeae90SHong Zhang         col = *jj++;
2452205254eSKarl Rupp 
2463b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
2473b2fbd54SBarry Smith       }
2483b2fbd54SBarry Smith     }
2499566063dSJacob Faibussowitsch     PetscCall(PetscFree(collengths));
2509371c9d4SSatish Balay     *ia = cia;
2519371c9d4SSatish Balay     *ja = cja;
2523b2fbd54SBarry Smith   }
2533a40ed3dSBarry Smith   PetscFunctionReturn(0);
2543b2fbd54SBarry Smith }
2553b2fbd54SBarry Smith 
2569371c9d4SSatish Balay PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
2573a40ed3dSBarry Smith   PetscFunctionBegin;
2583a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2593b2fbd54SBarry Smith 
2609566063dSJacob Faibussowitsch   PetscCall(PetscFree(*ia));
2619566063dSJacob Faibussowitsch   PetscCall(PetscFree(*ja));
2623a40ed3dSBarry Smith   PetscFunctionReturn(0);
2633b2fbd54SBarry Smith }
2643b2fbd54SBarry Smith 
2657cee066cSHong Zhang /*
2667cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
2677cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
268040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
2697cee066cSHong Zhang */
2709371c9d4SSatish Balay PetscErrorCode MatGetColumnIJ_SeqAIJ_Color(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscInt *spidx[], PetscBool *done) {
2717cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data;
2727cee066cSHong Zhang   PetscInt        i, *collengths, *cia, *cja, n = A->cmap->n, m = A->rmap->n;
273071fcb05SBarry Smith   PetscInt        nz = a->i[m], row, mr, col, tmp;
2747cee066cSHong Zhang   PetscInt       *cspidx;
275071fcb05SBarry Smith   const PetscInt *jj;
2767cee066cSHong Zhang 
2777cee066cSHong Zhang   PetscFunctionBegin;
2787cee066cSHong Zhang   *nn = n;
2797cee066cSHong Zhang   if (!ia) PetscFunctionReturn(0);
280625f6d37SHong Zhang 
2819566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(n, &collengths));
2829566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n + 1, &cia));
2839566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nz, &cja));
2849566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nz, &cspidx));
2857cee066cSHong Zhang   jj = a->j;
286ad540459SPierre Jolivet   for (i = 0; i < nz; i++) collengths[jj[i]]++;
2877cee066cSHong Zhang   cia[0] = oshift;
288ad540459SPierre Jolivet   for (i = 0; i < n; i++) cia[i + 1] = cia[i] + collengths[i];
2899566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(collengths, n));
2907cee066cSHong Zhang   jj = a->j;
2917cee066cSHong Zhang   for (row = 0; row < m; row++) {
2927cee066cSHong Zhang     mr = a->i[row + 1] - a->i[row];
2937cee066cSHong Zhang     for (i = 0; i < mr; i++) {
2947cee066cSHong Zhang       col         = *jj++;
295071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
296071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
297071fcb05SBarry Smith       cja[tmp]    = row + oshift;
2987cee066cSHong Zhang     }
2997cee066cSHong Zhang   }
3009566063dSJacob Faibussowitsch   PetscCall(PetscFree(collengths));
301071fcb05SBarry Smith   *ia    = cia;
302071fcb05SBarry Smith   *ja    = cja;
3037cee066cSHong Zhang   *spidx = cspidx;
3047cee066cSHong Zhang   PetscFunctionReturn(0);
3057cee066cSHong Zhang }
3067cee066cSHong Zhang 
3079371c9d4SSatish Balay PetscErrorCode MatRestoreColumnIJ_SeqAIJ_Color(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscInt *spidx[], PetscBool *done) {
3087cee066cSHong Zhang   PetscFunctionBegin;
3099566063dSJacob Faibussowitsch   PetscCall(MatRestoreColumnIJ_SeqAIJ(A, oshift, symmetric, inodecompressed, n, ia, ja, done));
3109566063dSJacob Faibussowitsch   PetscCall(PetscFree(*spidx));
3117cee066cSHong Zhang   PetscFunctionReturn(0);
3127cee066cSHong Zhang }
3137cee066cSHong Zhang 
3149371c9d4SSatish Balay PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A, PetscInt row, const PetscScalar v[]) {
31587d4246cSBarry Smith   Mat_SeqAIJ  *a  = (Mat_SeqAIJ *)A->data;
31687d4246cSBarry Smith   PetscInt    *ai = a->i;
317fff043a9SJunchao Zhang   PetscScalar *aa;
31887d4246cSBarry Smith 
31987d4246cSBarry Smith   PetscFunctionBegin;
3209566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
3219566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aa + ai[row], v, ai[row + 1] - ai[row]));
3229566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
32387d4246cSBarry Smith   PetscFunctionReturn(0);
32487d4246cSBarry Smith }
32587d4246cSBarry Smith 
326bd04181cSBarry Smith /*
327bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
328bd04181cSBarry Smith 
329bd04181cSBarry Smith       -   a single row of values is set with each call
330bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
331bd04181cSBarry Smith       -   the values are always added to the matrix, not set
332bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
333bd04181cSBarry Smith 
3341f763a69SBarry Smith      This does NOT assume the global column indices are sorted
335bd04181cSBarry Smith 
3361f763a69SBarry Smith */
337bd04181cSBarry Smith 
338af0996ceSBarry Smith #include <petsc/private/isimpl.h>
3399371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) {
340189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data;
3411f763a69SBarry Smith   PetscInt        low, high, t, row, nrow, i, col, l;
3421f763a69SBarry Smith   const PetscInt *rp, *ai = a->i, *ailen = a->ilen, *aj = a->j;
3431f763a69SBarry Smith   PetscInt        lastcol = -1;
344fff043a9SJunchao Zhang   MatScalar      *ap, value, *aa;
345189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices, *cidx = A->cmap->mapping->indices;
346189e4007SBarry Smith 
347fff043a9SJunchao Zhang   PetscFunctionBegin;
3489566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
349f38dd0b8SBarry Smith   row  = ridx[im[0]];
3501f763a69SBarry Smith   rp   = aj + ai[row];
3511f763a69SBarry Smith   ap   = aa + ai[row];
3521f763a69SBarry Smith   nrow = ailen[row];
353189e4007SBarry Smith   low  = 0;
354189e4007SBarry Smith   high = nrow;
355189e4007SBarry Smith   for (l = 0; l < n; l++) { /* loop over added columns */
356189e4007SBarry Smith     col   = cidx[in[l]];
357f38dd0b8SBarry Smith     value = v[l];
358189e4007SBarry Smith 
359189e4007SBarry Smith     if (col <= lastcol) low = 0;
360189e4007SBarry Smith     else high = nrow;
361189e4007SBarry Smith     lastcol = col;
362189e4007SBarry Smith     while (high - low > 5) {
363189e4007SBarry Smith       t = (low + high) / 2;
364189e4007SBarry Smith       if (rp[t] > col) high = t;
365189e4007SBarry Smith       else low = t;
366189e4007SBarry Smith     }
367189e4007SBarry Smith     for (i = low; i < high; i++) {
368189e4007SBarry Smith       if (rp[i] == col) {
3691f763a69SBarry Smith         ap[i] += value;
370189e4007SBarry Smith         low = i + 1;
3711f763a69SBarry Smith         break;
372189e4007SBarry Smith       }
373189e4007SBarry Smith     }
374189e4007SBarry Smith   }
3759566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
376f38dd0b8SBarry Smith   return 0;
377189e4007SBarry Smith }
378189e4007SBarry Smith 
3799371c9d4SSatish Balay PetscErrorCode MatSetValues_SeqAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) {
380416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
381e2ee6c50SBarry Smith   PetscInt   *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N;
38297f1f81fSBarry Smith   PetscInt   *imax = a->imax, *ai = a->i, *ailen = a->ilen;
383e2ee6c50SBarry Smith   PetscInt   *aj = a->j, nonew = a->nonew, lastcol = -1;
384ce496241SStefano Zampini   MatScalar  *ap = NULL, value = 0.0, *aa;
385ace3abfcSBarry Smith   PetscBool   ignorezeroentries = a->ignorezeroentries;
386ace3abfcSBarry Smith   PetscBool   roworiented       = a->roworiented;
38717ab2063SBarry Smith 
3883a40ed3dSBarry Smith   PetscFunctionBegin;
3899566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
39017ab2063SBarry Smith   for (k = 0; k < m; k++) { /* loop over added rows */
391416022c9SBarry Smith     row = im[k];
3925ef9f2a5SBarry Smith     if (row < 0) continue;
3936bdcaf15SBarry Smith     PetscCheck(row < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, row, A->rmap->n - 1);
394720833daSHong Zhang     rp = aj + ai[row];
395876c6284SHong Zhang     if (!A->structure_only) ap = aa + ai[row];
3969371c9d4SSatish Balay     rmax = imax[row];
3979371c9d4SSatish Balay     nrow = ailen[row];
398416022c9SBarry Smith     low  = 0;
399c71e6ed7SBarry Smith     high = nrow;
40017ab2063SBarry Smith     for (l = 0; l < n; l++) { /* loop over added columns */
4015ef9f2a5SBarry Smith       if (in[l] < 0) continue;
4026bdcaf15SBarry Smith       PetscCheck(in[l] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, in[l], A->cmap->n - 1);
403bfeeae90SHong Zhang       col = in[l];
404071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k * n] : v[k + l * m];
405071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
40636db0b34SBarry Smith 
4072205254eSKarl Rupp       if (col <= lastcol) low = 0;
4082205254eSKarl Rupp       else high = nrow;
409e2ee6c50SBarry Smith       lastcol = col;
410416022c9SBarry Smith       while (high - low > 5) {
411416022c9SBarry Smith         t = (low + high) / 2;
412416022c9SBarry Smith         if (rp[t] > col) high = t;
413416022c9SBarry Smith         else low = t;
41417ab2063SBarry Smith       }
415416022c9SBarry Smith       for (i = low; i < high; i++) {
41617ab2063SBarry Smith         if (rp[i] > col) break;
41717ab2063SBarry Smith         if (rp[i] == col) {
418876c6284SHong Zhang           if (!A->structure_only) {
4190c0d7e18SFande Kong             if (is == ADD_VALUES) {
4200c0d7e18SFande Kong               ap[i] += value;
4210c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
4229371c9d4SSatish Balay             } else ap[i] = value;
423720833daSHong Zhang           }
424e44c0bd4SBarry Smith           low = i + 1;
42517ab2063SBarry Smith           goto noinsert;
42617ab2063SBarry Smith         }
42717ab2063SBarry Smith       }
428dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
429c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
43008401ef6SPierre Jolivet       PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero at (%" PetscInt_FMT ",%" PetscInt_FMT ") in the matrix", row, col);
431720833daSHong Zhang       if (A->structure_only) {
432876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A, A->rmap->n, 1, nrow, row, col, rmax, ai, aj, rp, imax, nonew, MatScalar);
433720833daSHong Zhang       } else {
434fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A, A->rmap->n, 1, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
435720833daSHong Zhang       }
4369371c9d4SSatish Balay       N = nrow++ - 1;
4379371c9d4SSatish Balay       a->nz++;
4389371c9d4SSatish Balay       high++;
439416022c9SBarry Smith       /* shift up all the later entries in this row */
4409566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1));
44117ab2063SBarry Smith       rp[i] = col;
442580bdb30SBarry Smith       if (!A->structure_only) {
4439566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(ap + i + 1, ap + i, N - i + 1));
444580bdb30SBarry Smith         ap[i] = value;
445580bdb30SBarry Smith       }
446416022c9SBarry Smith       low = i + 1;
447e56f5c9eSBarry Smith       A->nonzerostate++;
448e44c0bd4SBarry Smith     noinsert:;
44917ab2063SBarry Smith     }
45017ab2063SBarry Smith     ailen[row] = nrow;
45117ab2063SBarry Smith   }
4529566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
4533a40ed3dSBarry Smith   PetscFunctionReturn(0);
45417ab2063SBarry Smith }
45517ab2063SBarry Smith 
4569371c9d4SSatish Balay PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) {
45719b08ed1SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
45819b08ed1SBarry Smith   PetscInt   *rp, k, row;
45919b08ed1SBarry Smith   PetscInt   *ai = a->i;
46019b08ed1SBarry Smith   PetscInt   *aj = a->j;
461fff043a9SJunchao Zhang   MatScalar  *aa, *ap;
46219b08ed1SBarry Smith 
46319b08ed1SBarry Smith   PetscFunctionBegin;
46428b400f6SJacob Faibussowitsch   PetscCheck(!A->was_assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call on assembled matrix.");
46508401ef6SPierre Jolivet   PetscCheck(m * n + a->nz <= a->maxnz, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of entries in matrix will be larger than maximum nonzeros allocated for %" PetscInt_FMT " in MatSeqAIJSetTotalPreallocation()", a->maxnz);
466fff043a9SJunchao Zhang 
4679566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
46819b08ed1SBarry Smith   for (k = 0; k < m; k++) { /* loop over added rows */
46919b08ed1SBarry Smith     row = im[k];
47019b08ed1SBarry Smith     rp  = aj + ai[row];
47119b08ed1SBarry Smith     ap  = aa + ai[row];
47219b08ed1SBarry Smith 
4739566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(rp, in, n * sizeof(PetscInt)));
47419b08ed1SBarry Smith     if (!A->structure_only) {
47519b08ed1SBarry Smith       if (v) {
4769566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(ap, v, n * sizeof(PetscScalar)));
47719b08ed1SBarry Smith         v += n;
47819b08ed1SBarry Smith       } else {
4799566063dSJacob Faibussowitsch         PetscCall(PetscMemzero(ap, n * sizeof(PetscScalar)));
48019b08ed1SBarry Smith       }
48119b08ed1SBarry Smith     }
48219b08ed1SBarry Smith     a->ilen[row]  = n;
48319b08ed1SBarry Smith     a->imax[row]  = n;
48419b08ed1SBarry Smith     a->i[row + 1] = a->i[row] + n;
48519b08ed1SBarry Smith     a->nz += n;
48619b08ed1SBarry Smith   }
4879566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
48819b08ed1SBarry Smith   PetscFunctionReturn(0);
48919b08ed1SBarry Smith }
49019b08ed1SBarry Smith 
49119b08ed1SBarry Smith /*@
49219b08ed1SBarry Smith     MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix.
49319b08ed1SBarry Smith 
49419b08ed1SBarry Smith   Input Parameters:
49511a5261eSBarry Smith +  A - the `MATSEQAIJ` matrix
49619b08ed1SBarry Smith -  nztotal - bound on the number of nonzeros
49719b08ed1SBarry Smith 
49819b08ed1SBarry Smith   Level: advanced
49919b08ed1SBarry Smith 
50019b08ed1SBarry Smith   Notes:
50119b08ed1SBarry Smith     This can be called if you will be provided the matrix row by row (from row zero) with sorted column indices for each row.
50211a5261eSBarry Smith     Simply call `MatSetValues()` after this call to provide the matrix entries in the usual manner. This matrix may be used
50319b08ed1SBarry Smith     as always with multiple matrix assemblies.
50419b08ed1SBarry Smith 
505db781477SPatrick Sanan .seealso: `MatSetOption()`, `MAT_SORTED_FULL`, `MatSetValues()`, `MatSeqAIJSetPreallocation()`
50619b08ed1SBarry Smith @*/
50719b08ed1SBarry Smith 
5089371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A, PetscInt nztotal) {
50919b08ed1SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
51019b08ed1SBarry Smith 
51119b08ed1SBarry Smith   PetscFunctionBegin;
5129566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
5139566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
51419b08ed1SBarry Smith   a->maxnz = nztotal;
51519b08ed1SBarry Smith   if (!a->imax) {
5169566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n, &a->imax));
5179566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A, A->rmap->n * sizeof(PetscInt)));
51819b08ed1SBarry Smith   }
51919b08ed1SBarry Smith   if (!a->ilen) {
5209566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n, &a->ilen));
5219566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A, A->rmap->n * sizeof(PetscInt)));
52219b08ed1SBarry Smith   } else {
5239566063dSJacob Faibussowitsch     PetscCall(PetscMemzero(a->ilen, A->rmap->n * sizeof(PetscInt)));
52419b08ed1SBarry Smith   }
52519b08ed1SBarry Smith 
52619b08ed1SBarry Smith   /* allocate the matrix space */
52719b08ed1SBarry Smith   if (A->structure_only) {
5289566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nztotal, &a->j));
5299566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n + 1, &a->i));
5309566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A, (A->rmap->n + 1) * sizeof(PetscInt) + nztotal * sizeof(PetscInt)));
53119b08ed1SBarry Smith   } else {
5329566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(nztotal, &a->a, nztotal, &a->j, A->rmap->n + 1, &a->i));
5339566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A, (A->rmap->n + 1) * sizeof(PetscInt) + nztotal * (sizeof(PetscScalar) + sizeof(PetscInt))));
53419b08ed1SBarry Smith   }
53519b08ed1SBarry Smith   a->i[0] = 0;
53619b08ed1SBarry Smith   if (A->structure_only) {
53719b08ed1SBarry Smith     a->singlemalloc = PETSC_FALSE;
53819b08ed1SBarry Smith     a->free_a       = PETSC_FALSE;
53919b08ed1SBarry Smith   } else {
54019b08ed1SBarry Smith     a->singlemalloc = PETSC_TRUE;
54119b08ed1SBarry Smith     a->free_a       = PETSC_TRUE;
54219b08ed1SBarry Smith   }
54319b08ed1SBarry Smith   a->free_ij        = PETSC_TRUE;
54419b08ed1SBarry Smith   A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation;
54519b08ed1SBarry Smith   A->preallocated   = PETSC_TRUE;
54619b08ed1SBarry Smith   PetscFunctionReturn(0);
54719b08ed1SBarry Smith }
54819b08ed1SBarry Smith 
5499371c9d4SSatish Balay PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is) {
550071fcb05SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
551071fcb05SBarry Smith   PetscInt   *rp, k, row;
552071fcb05SBarry Smith   PetscInt   *ai = a->i, *ailen = a->ilen;
553071fcb05SBarry Smith   PetscInt   *aj = a->j;
554fff043a9SJunchao Zhang   MatScalar  *aa, *ap;
555071fcb05SBarry Smith 
556071fcb05SBarry Smith   PetscFunctionBegin;
5579566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
558071fcb05SBarry Smith   for (k = 0; k < m; k++) { /* loop over added rows */
559071fcb05SBarry Smith     row = im[k];
5606bdcaf15SBarry Smith     PetscCheck(n <= a->imax[row], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Preallocation for row %" PetscInt_FMT " does not match number of columns provided", n);
561071fcb05SBarry Smith     rp = aj + ai[row];
562071fcb05SBarry Smith     ap = aa + ai[row];
56348a46eb9SPierre Jolivet     if (!A->was_assembled) PetscCall(PetscMemcpy(rp, in, n * sizeof(PetscInt)));
564071fcb05SBarry Smith     if (!A->structure_only) {
565071fcb05SBarry Smith       if (v) {
5669566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(ap, v, n * sizeof(PetscScalar)));
567071fcb05SBarry Smith         v += n;
568071fcb05SBarry Smith       } else {
5699566063dSJacob Faibussowitsch         PetscCall(PetscMemzero(ap, n * sizeof(PetscScalar)));
570071fcb05SBarry Smith       }
571071fcb05SBarry Smith     }
572071fcb05SBarry Smith     ailen[row] = n;
573071fcb05SBarry Smith     a->nz += n;
574071fcb05SBarry Smith   }
5759566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
576071fcb05SBarry Smith   PetscFunctionReturn(0);
577071fcb05SBarry Smith }
578071fcb05SBarry Smith 
5799371c9d4SSatish Balay PetscErrorCode MatGetValues_SeqAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[]) {
5807eb43aa7SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
58197f1f81fSBarry Smith   PetscInt   *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j;
58297f1f81fSBarry Smith   PetscInt   *ai = a->i, *ailen = a->ilen;
583fff043a9SJunchao Zhang   MatScalar  *ap, *aa;
5847eb43aa7SLois Curfman McInnes 
5853a40ed3dSBarry Smith   PetscFunctionBegin;
5869566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
5877eb43aa7SLois Curfman McInnes   for (k = 0; k < m; k++) { /* loop over rows */
5887eb43aa7SLois Curfman McInnes     row = im[k];
5899371c9d4SSatish Balay     if (row < 0) {
5909371c9d4SSatish Balay       v += n;
5919371c9d4SSatish Balay       continue;
5929371c9d4SSatish Balay     } /* negative row */
59354c59aa7SJacob Faibussowitsch     PetscCheck(row < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, row, A->rmap->n - 1);
5949371c9d4SSatish Balay     rp   = aj + ai[row];
5959371c9d4SSatish Balay     ap   = aa + ai[row];
5967eb43aa7SLois Curfman McInnes     nrow = ailen[row];
5977eb43aa7SLois Curfman McInnes     for (l = 0; l < n; l++) { /* loop over columns */
5989371c9d4SSatish Balay       if (in[l] < 0) {
5999371c9d4SSatish Balay         v++;
6009371c9d4SSatish Balay         continue;
6019371c9d4SSatish Balay       } /* negative column */
60254c59aa7SJacob Faibussowitsch       PetscCheck(in[l] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, in[l], A->cmap->n - 1);
603bfeeae90SHong Zhang       col  = in[l];
6049371c9d4SSatish Balay       high = nrow;
6059371c9d4SSatish Balay       low  = 0; /* assume unsorted */
6067eb43aa7SLois Curfman McInnes       while (high - low > 5) {
6077eb43aa7SLois Curfman McInnes         t = (low + high) / 2;
6087eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
6097eb43aa7SLois Curfman McInnes         else low = t;
6107eb43aa7SLois Curfman McInnes       }
6117eb43aa7SLois Curfman McInnes       for (i = low; i < high; i++) {
6127eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
6137eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
614b49de8d1SLois Curfman McInnes           *v++ = ap[i];
6157eb43aa7SLois Curfman McInnes           goto finished;
6167eb43aa7SLois Curfman McInnes         }
6177eb43aa7SLois Curfman McInnes       }
61897e567efSBarry Smith       *v++ = 0.0;
6197eb43aa7SLois Curfman McInnes     finished:;
6207eb43aa7SLois Curfman McInnes     }
6217eb43aa7SLois Curfman McInnes   }
6229566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
6233a40ed3dSBarry Smith   PetscFunctionReturn(0);
6247eb43aa7SLois Curfman McInnes }
6257eb43aa7SLois Curfman McInnes 
6269371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ_Binary(Mat mat, PetscViewer viewer) {
6273ea6fe3dSLisandro Dalcin   Mat_SeqAIJ        *A = (Mat_SeqAIJ *)mat->data;
628c898d852SStefano Zampini   const PetscScalar *av;
6293ea6fe3dSLisandro Dalcin   PetscInt           header[4], M, N, m, nz, i;
6303ea6fe3dSLisandro Dalcin   PetscInt          *rowlens;
63117ab2063SBarry Smith 
6323a40ed3dSBarry Smith   PetscFunctionBegin;
6339566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
6342205254eSKarl Rupp 
6353ea6fe3dSLisandro Dalcin   M  = mat->rmap->N;
6363ea6fe3dSLisandro Dalcin   N  = mat->cmap->N;
6373ea6fe3dSLisandro Dalcin   m  = mat->rmap->n;
6383ea6fe3dSLisandro Dalcin   nz = A->nz;
639416022c9SBarry Smith 
6403ea6fe3dSLisandro Dalcin   /* write matrix header */
6413ea6fe3dSLisandro Dalcin   header[0] = MAT_FILE_CLASSID;
6429371c9d4SSatish Balay   header[1] = M;
6439371c9d4SSatish Balay   header[2] = N;
6449371c9d4SSatish Balay   header[3] = nz;
6459566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT));
646416022c9SBarry Smith 
6473ea6fe3dSLisandro Dalcin   /* fill in and store row lengths */
6489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m, &rowlens));
6493ea6fe3dSLisandro Dalcin   for (i = 0; i < m; i++) rowlens[i] = A->i[i + 1] - A->i[i];
6509566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWrite(viewer, rowlens, m, PETSC_INT));
6519566063dSJacob Faibussowitsch   PetscCall(PetscFree(rowlens));
6523ea6fe3dSLisandro Dalcin   /* store column indices */
6539566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWrite(viewer, A->j, nz, PETSC_INT));
654416022c9SBarry Smith   /* store nonzero values */
6559566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(mat, &av));
6569566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWrite(viewer, av, nz, PETSC_SCALAR));
6579566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(mat, &av));
658b37d52dbSMark F. Adams 
6593ea6fe3dSLisandro Dalcin   /* write block size option to the viewer's .info file */
6609566063dSJacob Faibussowitsch   PetscCall(MatView_Binary_BlockSizes(mat, viewer));
6613a40ed3dSBarry Smith   PetscFunctionReturn(0);
66217ab2063SBarry Smith }
663416022c9SBarry Smith 
6649371c9d4SSatish Balay static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A, PetscViewer viewer) {
6657dc0baabSHong Zhang   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
6667dc0baabSHong Zhang   PetscInt    i, k, m = A->rmap->N;
6677dc0baabSHong Zhang 
6687dc0baabSHong Zhang   PetscFunctionBegin;
6699566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
6707dc0baabSHong Zhang   for (i = 0; i < m; i++) {
6719566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
67248a46eb9SPierre Jolivet     for (k = a->i[i]; k < a->i[i + 1]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ") ", a->j[k]));
6739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
6747dc0baabSHong Zhang   }
6759566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
6767dc0baabSHong Zhang   PetscFunctionReturn(0);
6777dc0baabSHong Zhang }
6787dc0baabSHong Zhang 
67909573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat, PetscViewer);
680cd155464SBarry Smith 
6819371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ_ASCII(Mat A, PetscViewer viewer) {
682416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
683c898d852SStefano Zampini   const PetscScalar *av;
68460e0710aSBarry Smith   PetscInt           i, j, m = A->rmap->n;
685e060cb09SBarry Smith   const char        *name;
686f3ef73ceSBarry Smith   PetscViewerFormat  format;
68717ab2063SBarry Smith 
6883a40ed3dSBarry Smith   PetscFunctionBegin;
6897dc0baabSHong Zhang   if (A->structure_only) {
6909566063dSJacob Faibussowitsch     PetscCall(MatView_SeqAIJ_ASCII_structonly(A, viewer));
6917dc0baabSHong Zhang     PetscFunctionReturn(0);
6927dc0baabSHong Zhang   }
69343e49210SHong Zhang 
6949566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6952e5835c6SStefano Zampini   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
6962e5835c6SStefano Zampini 
697c898d852SStefano Zampini   /* trigger copy to CPU if needed */
6989566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
6999566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
70071c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
70197f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
70260e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m - 1]) || (a->j[a->nz - 1] != A->cmap->n - 1))) {
703c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
704d00d2cf4SBarry Smith       nofinalvalue = 1;
705d00d2cf4SBarry Smith     }
7069566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
7079566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", m, A->cmap->n));
7089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "%% Nonzeros = %" PetscInt_FMT " \n", a->nz));
709fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
7109566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = zeros(%" PetscInt_FMT ",4);\n", a->nz + nofinalvalue));
711fbfe6fa7SJed Brown #else
7129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = zeros(%" PetscInt_FMT ",3);\n", a->nz + nofinalvalue));
713fbfe6fa7SJed Brown #endif
7149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = [\n"));
71517ab2063SBarry Smith 
71617ab2063SBarry Smith     for (i = 0; i < m; i++) {
71760e0710aSBarry Smith       for (j = a->i[i]; j < a->i[i + 1]; j++) {
718aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
7199566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e %18.16e\n", i + 1, a->j[j] + 1, (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j])));
72017ab2063SBarry Smith #else
7219566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e\n", i + 1, a->j[j] + 1, (double)a->a[j]));
72217ab2063SBarry Smith #endif
72317ab2063SBarry Smith       }
72417ab2063SBarry Smith     }
725d00d2cf4SBarry Smith     if (nofinalvalue) {
726c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
7279566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e %18.16e\n", m, A->cmap->n, 0., 0.));
728c337ccceSJed Brown #else
7299566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e\n", m, A->cmap->n, 0.0));
730c337ccceSJed Brown #endif
731d00d2cf4SBarry Smith     }
7329566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)A, &name));
7339566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "];\n %s = spconvert(zzz);\n", name));
7349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
735fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
7369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
73744cd7ae7SLois Curfman McInnes     for (i = 0; i < m; i++) {
7389566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
73960e0710aSBarry Smith       for (j = a->i[i]; j < a->i[i + 1]; j++) {
740aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
74136db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
7429566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j])));
74336db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
7449566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)-PetscImaginaryPart(a->a[j])));
74536db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
7469566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j])));
7476831982aSBarry Smith         }
74844cd7ae7SLois Curfman McInnes #else
7499566063dSJacob Faibussowitsch         if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j]));
75044cd7ae7SLois Curfman McInnes #endif
75144cd7ae7SLois Curfman McInnes       }
7529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
75344cd7ae7SLois Curfman McInnes     }
7549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
755fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
75697f1f81fSBarry Smith     PetscInt nzd = 0, fshift = 1, *sptr;
7579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
7589566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m + 1, &sptr));
759496be53dSLois Curfman McInnes     for (i = 0; i < m; i++) {
760496be53dSLois Curfman McInnes       sptr[i] = nzd + 1;
76160e0710aSBarry Smith       for (j = a->i[i]; j < a->i[i + 1]; j++) {
762496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
763aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
76436db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
765496be53dSLois Curfman McInnes #else
766496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
767496be53dSLois Curfman McInnes #endif
768496be53dSLois Curfman McInnes         }
769496be53dSLois Curfman McInnes       }
770496be53dSLois Curfman McInnes     }
7712e44a96cSLois Curfman McInnes     sptr[m] = nzd + 1;
7729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT "\n\n", m, nzd));
7732e44a96cSLois Curfman McInnes     for (i = 0; i < m + 1; i += 6) {
7742205254eSKarl Rupp       if (i + 4 < m) {
7759566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2], sptr[i + 3], sptr[i + 4], sptr[i + 5]));
7762205254eSKarl Rupp       } else if (i + 3 < m) {
7779566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2], sptr[i + 3], sptr[i + 4]));
7782205254eSKarl Rupp       } else if (i + 2 < m) {
7799566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2], sptr[i + 3]));
7802205254eSKarl Rupp       } else if (i + 1 < m) {
7819566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2]));
7822205254eSKarl Rupp       } else if (i < m) {
7839566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1]));
7842205254eSKarl Rupp       } else {
7859566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "\n", sptr[i]));
7862205254eSKarl Rupp       }
787496be53dSLois Curfman McInnes     }
7889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
7899566063dSJacob Faibussowitsch     PetscCall(PetscFree(sptr));
790496be53dSLois Curfman McInnes     for (i = 0; i < m; i++) {
79160e0710aSBarry Smith       for (j = a->i[i]; j < a->i[i + 1]; j++) {
7929566063dSJacob Faibussowitsch         if (a->j[j] >= i) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " ", a->j[j] + fshift));
793496be53dSLois Curfman McInnes       }
7949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
795496be53dSLois Curfman McInnes     }
7969566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
797496be53dSLois Curfman McInnes     for (i = 0; i < m; i++) {
79860e0710aSBarry Smith       for (j = a->i[i]; j < a->i[i + 1]; j++) {
799496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
800aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
80148a46eb9SPierre Jolivet           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " %18.16e %18.16e ", (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j])));
802496be53dSLois Curfman McInnes #else
8039566063dSJacob Faibussowitsch           if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " %18.16e ", (double)a->a[j]));
804496be53dSLois Curfman McInnes #endif
805496be53dSLois Curfman McInnes         }
806496be53dSLois Curfman McInnes       }
8079566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
808496be53dSLois Curfman McInnes     }
8099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
810fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
81197f1f81fSBarry Smith     PetscInt    cnt = 0, jcnt;
81287828ca2SBarry Smith     PetscScalar value;
81368f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
81468f1ed48SBarry Smith     PetscBool realonly = PETSC_TRUE;
81568f1ed48SBarry Smith 
81668f1ed48SBarry Smith     for (i = 0; i < a->i[m]; i++) {
81768f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
81868f1ed48SBarry Smith         realonly = PETSC_FALSE;
81968f1ed48SBarry Smith         break;
82068f1ed48SBarry Smith       }
82168f1ed48SBarry Smith     }
82268f1ed48SBarry Smith #endif
82302594712SBarry Smith 
8249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
82502594712SBarry Smith     for (i = 0; i < m; i++) {
82602594712SBarry Smith       jcnt = 0;
827d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
828e24b481bSBarry Smith         if (jcnt < a->i[i + 1] - a->i[i] && j == a->j[cnt]) {
82902594712SBarry Smith           value = a->a[cnt++];
830e24b481bSBarry Smith           jcnt++;
83102594712SBarry Smith         } else {
83202594712SBarry Smith           value = 0.0;
83302594712SBarry Smith         }
834aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
83568f1ed48SBarry Smith         if (realonly) {
8369566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e ", (double)PetscRealPart(value)));
83768f1ed48SBarry Smith         } else {
8389566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e+%7.5e i ", (double)PetscRealPart(value), (double)PetscImaginaryPart(value)));
83968f1ed48SBarry Smith         }
84002594712SBarry Smith #else
8419566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e ", (double)value));
84202594712SBarry Smith #endif
84302594712SBarry Smith       }
8449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
84502594712SBarry Smith     }
8469566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
8473c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
848150b93efSMatthew G. Knepley     PetscInt fshift = 1;
8499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
8503c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
8519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "%%%%MatrixMarket matrix coordinate complex general\n"));
8523c215bfdSMatthew Knepley #else
8539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "%%%%MatrixMarket matrix coordinate real general\n"));
8543c215bfdSMatthew Knepley #endif
8559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", m, A->cmap->n, a->nz));
8563c215bfdSMatthew Knepley     for (i = 0; i < m; i++) {
85760e0710aSBarry Smith       for (j = a->i[i]; j < a->i[i + 1]; j++) {
8583c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
8599566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %g %g\n", i + fshift, a->j[j] + fshift, (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j])));
8603c215bfdSMatthew Knepley #else
8619566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %g\n", i + fshift, a->j[j] + fshift, (double)a->a[j]));
8623c215bfdSMatthew Knepley #endif
8633c215bfdSMatthew Knepley       }
8643c215bfdSMatthew Knepley     }
8659566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
8663a40ed3dSBarry Smith   } else {
8679566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
868d5f3da31SBarry Smith     if (A->factortype) {
86916cd7e1dSShri Abhyankar       for (i = 0; i < m; i++) {
8709566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
87116cd7e1dSShri Abhyankar         /* L part */
87260e0710aSBarry Smith         for (j = a->i[i]; j < a->i[i + 1]; j++) {
87316cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
87416cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
8759566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j])));
87616cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
8779566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)(-PetscImaginaryPart(a->a[j]))));
87816cd7e1dSShri Abhyankar           } else {
8799566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j])));
88016cd7e1dSShri Abhyankar           }
88116cd7e1dSShri Abhyankar #else
8829566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j]));
88316cd7e1dSShri Abhyankar #endif
88416cd7e1dSShri Abhyankar         }
88516cd7e1dSShri Abhyankar         /* diagonal */
88616cd7e1dSShri Abhyankar         j = a->diag[i];
88716cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
88816cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
8899566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(1.0 / a->a[j]), (double)PetscImaginaryPart(1.0 / a->a[j])));
89016cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
8919566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(1.0 / a->a[j]), (double)(-PetscImaginaryPart(1.0 / a->a[j]))));
89216cd7e1dSShri Abhyankar         } else {
8939566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(1.0 / a->a[j])));
89416cd7e1dSShri Abhyankar         }
89516cd7e1dSShri Abhyankar #else
8969566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)(1.0 / a->a[j])));
89716cd7e1dSShri Abhyankar #endif
89816cd7e1dSShri Abhyankar 
89916cd7e1dSShri Abhyankar         /* U part */
90060e0710aSBarry Smith         for (j = a->diag[i + 1] + 1; j < a->diag[i]; j++) {
90116cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
90216cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
9039566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j])));
90416cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9059566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)(-PetscImaginaryPart(a->a[j]))));
90616cd7e1dSShri Abhyankar           } else {
9079566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j])));
90816cd7e1dSShri Abhyankar           }
90916cd7e1dSShri Abhyankar #else
9109566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j]));
91116cd7e1dSShri Abhyankar #endif
91216cd7e1dSShri Abhyankar         }
9139566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
91416cd7e1dSShri Abhyankar       }
91516cd7e1dSShri Abhyankar     } else {
91617ab2063SBarry Smith       for (i = 0; i < m; i++) {
9179566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
91860e0710aSBarry Smith         for (j = a->i[i]; j < a->i[i + 1]; j++) {
919aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
92036db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
9219566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j])));
92236db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9239566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)-PetscImaginaryPart(a->a[j])));
9243a40ed3dSBarry Smith           } else {
9259566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j])));
92617ab2063SBarry Smith           }
92717ab2063SBarry Smith #else
9289566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j]));
92917ab2063SBarry Smith #endif
93017ab2063SBarry Smith         }
9319566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
93217ab2063SBarry Smith       }
93316cd7e1dSShri Abhyankar     }
9349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
93517ab2063SBarry Smith   }
9369566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
9373a40ed3dSBarry Smith   PetscFunctionReturn(0);
938416022c9SBarry Smith }
939416022c9SBarry Smith 
9409804daf3SBarry Smith #include <petscdraw.h>
9419371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw, void *Aa) {
942480ef9eaSBarry Smith   Mat                A = (Mat)Aa;
943416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
944383922c3SLisandro Dalcin   PetscInt           i, j, m = A->rmap->n;
945383922c3SLisandro Dalcin   int                color;
946b05fc000SLisandro Dalcin   PetscReal          xl, yl, xr, yr, x_l, x_r, y_l, y_r;
947b0a32e0cSBarry Smith   PetscViewer        viewer;
948f3ef73ceSBarry Smith   PetscViewerFormat  format;
949fff043a9SJunchao Zhang   const PetscScalar *aa;
950cddf8d76SBarry Smith 
9513a40ed3dSBarry Smith   PetscFunctionBegin;
9529566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
9539566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
9549566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
955383922c3SLisandro Dalcin 
956416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
9579566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
958fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
959d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
9600513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
961b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
962416022c9SBarry Smith     for (i = 0; i < m; i++) {
9639371c9d4SSatish Balay       y_l = m - i - 1.0;
9649371c9d4SSatish Balay       y_r = y_l + 1.0;
965bfeeae90SHong Zhang       for (j = a->i[i]; j < a->i[i + 1]; j++) {
9669371c9d4SSatish Balay         x_l = a->j[j];
9679371c9d4SSatish Balay         x_r = x_l + 1.0;
968fff043a9SJunchao Zhang         if (PetscRealPart(aa[j]) >= 0.) continue;
9699566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
970cddf8d76SBarry Smith       }
971cddf8d76SBarry Smith     }
972b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
973cddf8d76SBarry Smith     for (i = 0; i < m; i++) {
9749371c9d4SSatish Balay       y_l = m - i - 1.0;
9759371c9d4SSatish Balay       y_r = y_l + 1.0;
976bfeeae90SHong Zhang       for (j = a->i[i]; j < a->i[i + 1]; j++) {
9779371c9d4SSatish Balay         x_l = a->j[j];
9789371c9d4SSatish Balay         x_r = x_l + 1.0;
979fff043a9SJunchao Zhang         if (aa[j] != 0.) continue;
9809566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
981cddf8d76SBarry Smith       }
982cddf8d76SBarry Smith     }
983b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
984cddf8d76SBarry Smith     for (i = 0; i < m; i++) {
9859371c9d4SSatish Balay       y_l = m - i - 1.0;
9869371c9d4SSatish Balay       y_r = y_l + 1.0;
987bfeeae90SHong Zhang       for (j = a->i[i]; j < a->i[i + 1]; j++) {
9889371c9d4SSatish Balay         x_l = a->j[j];
9899371c9d4SSatish Balay         x_r = x_l + 1.0;
990fff043a9SJunchao Zhang         if (PetscRealPart(aa[j]) <= 0.) continue;
9919566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
992416022c9SBarry Smith       }
993416022c9SBarry Smith     }
994d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
9950513a670SBarry Smith   } else {
9960513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
9970513a670SBarry Smith     /* first determine max of all nonzero values */
998b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
999383922c3SLisandro Dalcin     PetscInt  nz = a->nz, count = 0;
1000b0a32e0cSBarry Smith     PetscDraw popup;
10010513a670SBarry Smith 
10020513a670SBarry Smith     for (i = 0; i < nz; i++) {
1003fff043a9SJunchao Zhang       if (PetscAbsScalar(aa[i]) > maxv) maxv = PetscAbsScalar(aa[i]);
10040513a670SBarry Smith     }
1005383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
10069566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetPopup(draw, &popup));
10079566063dSJacob Faibussowitsch     PetscCall(PetscDrawScalePopup(popup, minv, maxv));
1008383922c3SLisandro Dalcin 
1009d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
10100513a670SBarry Smith     for (i = 0; i < m; i++) {
1011383922c3SLisandro Dalcin       y_l = m - i - 1.0;
1012383922c3SLisandro Dalcin       y_r = y_l + 1.0;
1013bfeeae90SHong Zhang       for (j = a->i[i]; j < a->i[i + 1]; j++) {
1014383922c3SLisandro Dalcin         x_l   = a->j[j];
1015383922c3SLisandro Dalcin         x_r   = x_l + 1.0;
1016fff043a9SJunchao Zhang         color = PetscDrawRealToColor(PetscAbsScalar(aa[count]), minv, maxv);
10179566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
10180513a670SBarry Smith         count++;
10190513a670SBarry Smith       }
10200513a670SBarry Smith     }
1021d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
10220513a670SBarry Smith   }
10239566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
1024480ef9eaSBarry Smith   PetscFunctionReturn(0);
1025480ef9eaSBarry Smith }
1026cddf8d76SBarry Smith 
10279804daf3SBarry Smith #include <petscdraw.h>
10289371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ_Draw(Mat A, PetscViewer viewer) {
1029b0a32e0cSBarry Smith   PetscDraw draw;
103036db0b34SBarry Smith   PetscReal xr, yr, xl, yl, h, w;
1031ace3abfcSBarry Smith   PetscBool isnull;
1032480ef9eaSBarry Smith 
1033480ef9eaSBarry Smith   PetscFunctionBegin;
10349566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
10359566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
1036480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
1037480ef9eaSBarry Smith 
10389371c9d4SSatish Balay   xr = A->cmap->n;
10399371c9d4SSatish Balay   yr = A->rmap->n;
10409371c9d4SSatish Balay   h  = yr / 10.0;
10419371c9d4SSatish Balay   w  = xr / 10.0;
10429371c9d4SSatish Balay   xr += w;
10439371c9d4SSatish Balay   yr += h;
10449371c9d4SSatish Balay   xl = -w;
10459371c9d4SSatish Balay   yl = -h;
10469566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
10479566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
10489566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqAIJ_Draw_Zoom, A));
10499566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
10509566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
10513a40ed3dSBarry Smith   PetscFunctionReturn(0);
1052416022c9SBarry Smith }
1053416022c9SBarry Smith 
10549371c9d4SSatish Balay PetscErrorCode MatView_SeqAIJ(Mat A, PetscViewer viewer) {
1055ace3abfcSBarry Smith   PetscBool iascii, isbinary, isdraw;
1056416022c9SBarry Smith 
10573a40ed3dSBarry Smith   PetscFunctionBegin;
10589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
10599566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
10609566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
10611baa6e33SBarry Smith   if (iascii) PetscCall(MatView_SeqAIJ_ASCII(A, viewer));
10621baa6e33SBarry Smith   else if (isbinary) PetscCall(MatView_SeqAIJ_Binary(A, viewer));
10631baa6e33SBarry Smith   else if (isdraw) PetscCall(MatView_SeqAIJ_Draw(A, viewer));
10649566063dSJacob Faibussowitsch   PetscCall(MatView_SeqAIJ_Inode(A, viewer));
10653a40ed3dSBarry Smith   PetscFunctionReturn(0);
106617ab2063SBarry Smith }
106719bcc07fSBarry Smith 
10689371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A, MatAssemblyType mode) {
1069416022c9SBarry Smith   Mat_SeqAIJ *a      = (Mat_SeqAIJ *)A->data;
1070580bdb30SBarry Smith   PetscInt    fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax;
1071d0f46423SBarry Smith   PetscInt    m = A->rmap->n, *ip, N, *ailen = a->ilen, rmax = 0;
107254f21887SBarry Smith   MatScalar  *aa    = a->a, *ap;
10733447b6efSHong Zhang   PetscReal   ratio = 0.6;
107417ab2063SBarry Smith 
10753a40ed3dSBarry Smith   PetscFunctionBegin;
10763a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
10779566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(A));
1078b215bc84SStefano Zampini   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) {
1079b215bc84SStefano Zampini     /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */
10809566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A, mode));
1081b215bc84SStefano Zampini     PetscFunctionReturn(0);
1082b215bc84SStefano Zampini   }
108317ab2063SBarry Smith 
108443ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
108517ab2063SBarry Smith   for (i = 1; i < m; i++) {
1086416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
108717ab2063SBarry Smith     fshift += imax[i - 1] - ailen[i - 1];
108894a9d846SBarry Smith     rmax = PetscMax(rmax, ailen[i]);
108917ab2063SBarry Smith     if (fshift) {
1090bfeeae90SHong Zhang       ip = aj + ai[i];
1091bfeeae90SHong Zhang       ap = aa + ai[i];
109217ab2063SBarry Smith       N  = ailen[i];
10939566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ip - fshift, ip, N));
109448a46eb9SPierre Jolivet       if (!A->structure_only) PetscCall(PetscArraymove(ap - fshift, ap, N));
109517ab2063SBarry Smith     }
109617ab2063SBarry Smith     ai[i] = ai[i - 1] + ailen[i - 1];
109717ab2063SBarry Smith   }
109817ab2063SBarry Smith   if (m) {
109917ab2063SBarry Smith     fshift += imax[m - 1] - ailen[m - 1];
110017ab2063SBarry Smith     ai[m] = ai[m - 1] + ailen[m - 1];
110117ab2063SBarry Smith   }
11027b083b7cSBarry Smith 
110317ab2063SBarry Smith   /* reset ilen and imax for each row */
11047b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1105396832f4SHong Zhang   if (A->structure_only) {
11069566063dSJacob Faibussowitsch     PetscCall(PetscFree(a->imax));
11079566063dSJacob Faibussowitsch     PetscCall(PetscFree(a->ilen));
1108396832f4SHong Zhang   } else { /* !A->structure_only */
110917ab2063SBarry Smith     for (i = 0; i < m; i++) {
111017ab2063SBarry Smith       ailen[i] = imax[i] = ai[i + 1] - ai[i];
11117b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i + 1] - ai[i]) > 0);
111217ab2063SBarry Smith     }
1113396832f4SHong Zhang   }
1114bfeeae90SHong Zhang   a->nz = ai[m];
1115aed4548fSBarry Smith   PetscCheck(!fshift || a->nounused != -1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unused space detected in matrix: %" PetscInt_FMT " X %" PetscInt_FMT ", %" PetscInt_FMT " unneeded", m, A->cmap->n, fshift);
111617ab2063SBarry Smith 
11179566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqAIJ(A));
11189566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Matrix size: %" PetscInt_FMT " X %" PetscInt_FMT "; storage space: %" PetscInt_FMT " unneeded,%" PetscInt_FMT " used\n", m, A->cmap->n, fshift, a->nz));
11199566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues() is %" PetscInt_FMT "\n", a->reallocs));
11209566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Maximum nonzeros in any row is %" PetscInt_FMT "\n", rmax));
11212205254eSKarl Rupp 
11228e58a170SBarry Smith   A->info.mallocs += a->reallocs;
1123dd5f02e7SSatish Balay   a->reallocs         = 0;
11246712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
112536db0b34SBarry Smith   a->rmax             = rmax;
11264e220ebcSLois Curfman McInnes 
112748a46eb9SPierre Jolivet   if (!A->structure_only) PetscCall(MatCheckCompressedRow(A, a->nonzerorowcnt, &a->compressedrow, a->i, m, ratio));
11289566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A, mode));
11293a40ed3dSBarry Smith   PetscFunctionReturn(0);
113017ab2063SBarry Smith }
113117ab2063SBarry Smith 
11329371c9d4SSatish Balay PetscErrorCode MatRealPart_SeqAIJ(Mat A) {
113399cafbc1SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
113499cafbc1SBarry Smith   PetscInt    i, nz = a->nz;
11352e5835c6SStefano Zampini   MatScalar  *aa;
113699cafbc1SBarry Smith 
113799cafbc1SBarry Smith   PetscFunctionBegin;
11389566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
113999cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]);
11409566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
11419566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(A));
114299cafbc1SBarry Smith   PetscFunctionReturn(0);
114399cafbc1SBarry Smith }
114499cafbc1SBarry Smith 
11459371c9d4SSatish Balay PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A) {
114699cafbc1SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
114799cafbc1SBarry Smith   PetscInt    i, nz = a->nz;
11482e5835c6SStefano Zampini   MatScalar  *aa;
114999cafbc1SBarry Smith 
115099cafbc1SBarry Smith   PetscFunctionBegin;
11519566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
115299cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
11539566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
11549566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(A));
115599cafbc1SBarry Smith   PetscFunctionReturn(0);
115699cafbc1SBarry Smith }
115799cafbc1SBarry Smith 
11589371c9d4SSatish Balay PetscErrorCode MatZeroEntries_SeqAIJ(Mat A) {
1159fff043a9SJunchao Zhang   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
1160fff043a9SJunchao Zhang   MatScalar  *aa;
11613a40ed3dSBarry Smith 
11623a40ed3dSBarry Smith   PetscFunctionBegin;
11639566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayWrite(A, &aa));
11649566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(aa, a->i[A->rmap->n]));
11659566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayWrite(A, &aa));
11669566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(A));
11673a40ed3dSBarry Smith   PetscFunctionReturn(0);
116817ab2063SBarry Smith }
1169416022c9SBarry Smith 
11709371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatResetPreallocationCOO_SeqAIJ(Mat A) {
1171cbc6b225SStefano Zampini   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
1172cbc6b225SStefano Zampini 
1173cbc6b225SStefano Zampini   PetscFunctionBegin;
11749566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->perm));
11759566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->jmap));
1176cbc6b225SStefano Zampini   PetscFunctionReturn(0);
1177cbc6b225SStefano Zampini }
1178cbc6b225SStefano Zampini 
11799371c9d4SSatish Balay PetscErrorCode MatDestroy_SeqAIJ(Mat A) {
1180416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
1181d5d45c9bSBarry Smith 
11823a40ed3dSBarry Smith   PetscFunctionBegin;
1183aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1184c0aa6a63SJacob Faibussowitsch   PetscLogObjectState((PetscObject)A, "Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT, A->rmap->n, A->cmap->n, a->nz);
118517ab2063SBarry Smith #endif
11869566063dSJacob Faibussowitsch   PetscCall(MatSeqXAIJFreeAIJ(A, &a->a, &a->j, &a->i));
11879566063dSJacob Faibussowitsch   PetscCall(MatResetPreallocationCOO_SeqAIJ(A));
11889566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
11899566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
11909566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->diag));
11919566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->ibdiag));
11929566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->imax));
11939566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->ilen));
11949566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->ipre));
11959566063dSJacob Faibussowitsch   PetscCall(PetscFree3(a->idiag, a->mdiag, a->ssor_work));
11969566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->solve_work));
11979566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->icol));
11989566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->saved_values));
11999566063dSJacob Faibussowitsch   PetscCall(PetscFree2(a->compressedrow.i, a->compressedrow.rindex));
12009566063dSJacob Faibussowitsch   PetscCall(MatDestroy_SeqAIJ_Inode(A));
12019566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
1202901853e0SKris Buschelman 
12036718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
12046718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
12056718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
12066718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
12076718818eSStefano Zampini      due to different matrix sizes */
12089566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc__ab_dense", NULL));
12096718818eSStefano Zampini 
12109566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL));
12112e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "PetscMatlabEnginePut_C", NULL));
12122e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "PetscMatlabEngineGet_C", NULL));
12139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetColumnIndices_C", NULL));
12149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatStoreValues_C", NULL));
12159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatRetrieveValues_C", NULL));
12169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqsbaij_C", NULL));
12179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqbaij_C", NULL));
12189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijperm_C", NULL));
12192e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijsell_C", NULL));
12202e956fe4SStefano Zampini #if defined(PETSC_HAVE_MKL_SPARSE)
12212e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijmkl_C", NULL));
12222e956fe4SStefano Zampini #endif
12234222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
12249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijcusparse_C", NULL));
12259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_seqaij_C", NULL));
12269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaijcusparse_C", NULL));
12274222ddf1SHong Zhang #endif
12283d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
12299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijkokkos_C", NULL));
12303d0639e7SStefano Zampini #endif
12319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijcrl_C", NULL));
1232af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
12339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_elemental_C", NULL));
1234af8000cdSHong Zhang #endif
1235d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
12369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_scalapack_C", NULL));
1237d24d4204SJose E. Roman #endif
123863c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
12399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_hypre_C", NULL));
12409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_transpose_seqaij_seqaij_C", NULL));
124163c07aadSStefano Zampini #endif
12429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqdense_C", NULL));
12439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqsell_C", NULL));
12449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_is_C", NULL));
12459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatIsTranspose_C", NULL));
12462e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatIsHermitianTranspose_C", NULL));
12479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", NULL));
12489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatResetPreallocation_C", NULL));
12499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetPreallocationCSR_C", NULL));
12509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatReorderForNonzeroDiagonal_C", NULL));
12519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_is_seqaij_C", NULL));
12529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqdense_seqaij_C", NULL));
12539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaij_C", NULL));
12549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJKron_C", NULL));
12559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL));
12569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL));
12572e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL));
12582e956fe4SStefano Zampini   /* these calls do not belong here: the subclasses Duplicate/Destroy are wrong */
12592e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaijsell_seqaij_C", NULL));
12602e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaijperm_seqaij_C", NULL));
12612e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijviennacl_C", NULL));
12622e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijviennacl_seqdense_C", NULL));
12632e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijviennacl_seqaij_C", NULL));
12643a40ed3dSBarry Smith   PetscFunctionReturn(0);
126517ab2063SBarry Smith }
126617ab2063SBarry Smith 
12679371c9d4SSatish Balay PetscErrorCode MatSetOption_SeqAIJ(Mat A, MatOption op, PetscBool flg) {
1268416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
12693a40ed3dSBarry Smith 
12703a40ed3dSBarry Smith   PetscFunctionBegin;
1271a65d3064SKris Buschelman   switch (op) {
12729371c9d4SSatish Balay   case MAT_ROW_ORIENTED: a->roworiented = flg; break;
12739371c9d4SSatish Balay   case MAT_KEEP_NONZERO_PATTERN: a->keepnonzeropattern = flg; break;
12749371c9d4SSatish Balay   case MAT_NEW_NONZERO_LOCATIONS: a->nonew = (flg ? 0 : 1); break;
12759371c9d4SSatish Balay   case MAT_NEW_NONZERO_LOCATION_ERR: a->nonew = (flg ? -1 : 0); break;
12769371c9d4SSatish Balay   case MAT_NEW_NONZERO_ALLOCATION_ERR: a->nonew = (flg ? -2 : 0); break;
12779371c9d4SSatish Balay   case MAT_UNUSED_NONZERO_LOCATION_ERR: a->nounused = (flg ? -1 : 0); break;
12789371c9d4SSatish Balay   case MAT_IGNORE_ZERO_ENTRIES: a->ignorezeroentries = flg; break;
12793d472b54SHong Zhang   case MAT_SPD:
1280b1646e73SJed Brown   case MAT_SYMMETRIC:
1281b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1282b1646e73SJed Brown   case MAT_HERMITIAN:
1283b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1284957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
1285b94d7dedSBarry Smith   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
1286b94d7dedSBarry Smith   case MAT_SPD_ETERNAL:
1287b94d7dedSBarry Smith     /* if the diagonal matrix is square it inherits some of the properties above */
12885021d80fSJed Brown     break;
12898c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
1290a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
12919371c9d4SSatish Balay   case MAT_USE_HASH_TABLE: PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op])); break;
12929371c9d4SSatish Balay   case MAT_USE_INODES: PetscCall(MatSetOption_SeqAIJ_Inode(A, MAT_USE_INODES, flg)); break;
12939371c9d4SSatish Balay   case MAT_SUBMAT_SINGLEIS: A->submat_singleis = flg; break;
1294071fcb05SBarry Smith   case MAT_SORTED_FULL:
1295071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1296071fcb05SBarry Smith     else A->ops->setvalues = MatSetValues_SeqAIJ;
1297071fcb05SBarry Smith     break;
12989371c9d4SSatish Balay   case MAT_FORM_EXPLICIT_TRANSPOSE: A->form_explicit_transpose = flg; break;
12999371c9d4SSatish Balay   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %d", op);
1300a65d3064SKris Buschelman   }
13013a40ed3dSBarry Smith   PetscFunctionReturn(0);
130217ab2063SBarry Smith }
130317ab2063SBarry Smith 
13049371c9d4SSatish Balay PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A, Vec v) {
1305416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
1306fdc842d1SBarry Smith   PetscInt           i, j, n, *ai = a->i, *aj = a->j;
1307c898d852SStefano Zampini   PetscScalar       *x;
1308c898d852SStefano Zampini   const PetscScalar *aa;
130917ab2063SBarry Smith 
13103a40ed3dSBarry Smith   PetscFunctionBegin;
13119566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &n));
131208401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
13139566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
1314d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1315d3e70bfaSHong Zhang     PetscInt *diag = a->diag;
13169566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(v, &x));
13172c990fa1SHong Zhang     for (i = 0; i < n; i++) x[i] = 1.0 / aa[diag[i]];
13189566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(v, &x));
13199566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
132035e7444dSHong Zhang     PetscFunctionReturn(0);
132135e7444dSHong Zhang   }
132235e7444dSHong Zhang 
13239566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v, &x));
132435e7444dSHong Zhang   for (i = 0; i < n; i++) {
1325fdc842d1SBarry Smith     x[i] = 0.0;
132635e7444dSHong Zhang     for (j = ai[i]; j < ai[i + 1]; j++) {
132735e7444dSHong Zhang       if (aj[j] == i) {
132835e7444dSHong Zhang         x[i] = aa[j];
132917ab2063SBarry Smith         break;
133017ab2063SBarry Smith       }
133117ab2063SBarry Smith     }
133217ab2063SBarry Smith   }
13339566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v, &x));
13349566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
13353a40ed3dSBarry Smith   PetscFunctionReturn(0);
133617ab2063SBarry Smith }
133717ab2063SBarry Smith 
1338c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
13399371c9d4SSatish Balay PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A, Vec xx, Vec zz, Vec yy) {
1340416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
13415f22a7b3SSebastian Grimberg   const MatScalar   *aa;
1342d9ca1df4SBarry Smith   PetscScalar       *y;
1343d9ca1df4SBarry Smith   const PetscScalar *x;
1344d0f46423SBarry Smith   PetscInt           m = A->rmap->n;
13455c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
13465f22a7b3SSebastian Grimberg   const MatScalar  *v;
1347a77337e4SBarry Smith   PetscScalar       alpha;
1348d9ca1df4SBarry Smith   PetscInt          n, i, j;
1349d9ca1df4SBarry Smith   const PetscInt   *idx, *ii, *ridx = NULL;
13503447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1351ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
13525c897100SBarry Smith #endif
135317ab2063SBarry Smith 
13543a40ed3dSBarry Smith   PetscFunctionBegin;
13559566063dSJacob Faibussowitsch   if (zz != yy) PetscCall(VecCopy(zz, yy));
13569566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
13579566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
13589566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
13595c897100SBarry Smith 
13605c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1361fff043a9SJunchao Zhang   fortranmulttransposeaddaij_(&m, x, a->i, a->j, aa, y);
13625c897100SBarry Smith #else
13633447b6efSHong Zhang   if (usecprow) {
13643447b6efSHong Zhang     m = cprow.nrows;
13653447b6efSHong Zhang     ii = cprow.i;
13667b2bb3b9SHong Zhang     ridx = cprow.rindex;
13673447b6efSHong Zhang   } else {
13683447b6efSHong Zhang     ii = a->i;
13693447b6efSHong Zhang   }
137017ab2063SBarry Smith   for (i = 0; i < m; i++) {
13713447b6efSHong Zhang     idx = a->j + ii[i];
1372fff043a9SJunchao Zhang     v = aa + ii[i];
13733447b6efSHong Zhang     n = ii[i + 1] - ii[i];
13743447b6efSHong Zhang     if (usecprow) {
13757b2bb3b9SHong Zhang       alpha = x[ridx[i]];
13763447b6efSHong Zhang     } else {
137717ab2063SBarry Smith       alpha = x[i];
13783447b6efSHong Zhang     }
137904fbf559SBarry Smith     for (j = 0; j < n; j++) y[idx[j]] += alpha * v[j];
138017ab2063SBarry Smith   }
13815c897100SBarry Smith #endif
13829566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * a->nz));
13839566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
13849566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
13859566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
13863a40ed3dSBarry Smith   PetscFunctionReturn(0);
138717ab2063SBarry Smith }
138817ab2063SBarry Smith 
13899371c9d4SSatish Balay PetscErrorCode MatMultTranspose_SeqAIJ(Mat A, Vec xx, Vec yy) {
13905c897100SBarry Smith   PetscFunctionBegin;
13919566063dSJacob Faibussowitsch   PetscCall(VecSet(yy, 0.0));
13929566063dSJacob Faibussowitsch   PetscCall(MatMultTransposeAdd_SeqAIJ(A, xx, yy, yy));
13935c897100SBarry Smith   PetscFunctionReturn(0);
13945c897100SBarry Smith }
13955c897100SBarry Smith 
1396c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
139778b84d54SShri Abhyankar 
13989371c9d4SSatish Balay PetscErrorCode MatMult_SeqAIJ(Mat A, Vec xx, Vec yy) {
1399416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
1400d9fead3dSBarry Smith   PetscScalar       *y;
140154f21887SBarry Smith   const PetscScalar *x;
1402fff043a9SJunchao Zhang   const MatScalar   *aa, *a_a;
1403003131ecSBarry Smith   PetscInt           m = A->rmap->n;
14040298fd71SBarry Smith   const PetscInt    *aj, *ii, *ridx = NULL;
14057b083b7cSBarry Smith   PetscInt           n, i;
1406362ced78SSatish Balay   PetscScalar        sum;
1407ace3abfcSBarry Smith   PetscBool          usecprow = a->compressedrow.use;
140817ab2063SBarry Smith 
1409b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
141097952fefSHong Zhang #pragma disjoint(*x, *y, *aa)
1411fee21e36SBarry Smith #endif
1412fee21e36SBarry Smith 
14133a40ed3dSBarry Smith   PetscFunctionBegin;
1414b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
14159566063dSJacob Faibussowitsch     PetscCall(MatMult_SeqAIJ_Inode(A, xx, yy));
1416b215bc84SStefano Zampini     PetscFunctionReturn(0);
1417b215bc84SStefano Zampini   }
14189566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &a_a));
14199566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
14209566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1421416022c9SBarry Smith   ii = a->i;
14224eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
14239566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(y, m));
142497952fefSHong Zhang     m    = a->compressedrow.nrows;
142597952fefSHong Zhang     ii   = a->compressedrow.i;
142697952fefSHong Zhang     ridx = a->compressedrow.rindex;
142797952fefSHong Zhang     for (i = 0; i < m; i++) {
142897952fefSHong Zhang       n   = ii[i + 1] - ii[i];
142997952fefSHong Zhang       aj  = a->j + ii[i];
1430fff043a9SJunchao Zhang       aa  = a_a + ii[i];
143197952fefSHong Zhang       sum = 0.0;
1432003131ecSBarry Smith       PetscSparseDensePlusDot(sum, x, aa, aj, n);
1433003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
143497952fefSHong Zhang       y[*ridx++] = sum;
143597952fefSHong Zhang     }
143697952fefSHong Zhang   } else { /* do not use compressed row format */
1437b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
14383d3eaba7SBarry Smith     aj = a->j;
1439fff043a9SJunchao Zhang     aa = a_a;
1440b05257ddSBarry Smith     fortranmultaij_(&m, x, ii, aj, aa, y);
1441b05257ddSBarry Smith #else
144217ab2063SBarry Smith     for (i = 0; i < m; i++) {
1443003131ecSBarry Smith       n = ii[i + 1] - ii[i];
1444003131ecSBarry Smith       aj = a->j + ii[i];
1445fff043a9SJunchao Zhang       aa = a_a + ii[i];
144617ab2063SBarry Smith       sum = 0.0;
1447003131ecSBarry Smith       PetscSparseDensePlusDot(sum, x, aa, aj, n);
144817ab2063SBarry Smith       y[i] = sum;
144917ab2063SBarry Smith     }
14508d195f9aSBarry Smith #endif
1451b05257ddSBarry Smith   }
14529566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * a->nz - a->nonzerorowcnt));
14539566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
14549566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
14559566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a));
14563a40ed3dSBarry Smith   PetscFunctionReturn(0);
145717ab2063SBarry Smith }
145817ab2063SBarry Smith 
14599371c9d4SSatish Balay PetscErrorCode MatMultMax_SeqAIJ(Mat A, Vec xx, Vec yy) {
1460b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
1461b434eb95SMatthew G. Knepley   PetscScalar       *y;
1462b434eb95SMatthew G. Knepley   const PetscScalar *x;
1463fff043a9SJunchao Zhang   const MatScalar   *aa, *a_a;
1464b434eb95SMatthew G. Knepley   PetscInt           m = A->rmap->n;
1465b434eb95SMatthew G. Knepley   const PetscInt    *aj, *ii, *ridx   = NULL;
1466b434eb95SMatthew G. Knepley   PetscInt           n, i, nonzerorow = 0;
1467b434eb95SMatthew G. Knepley   PetscScalar        sum;
1468b434eb95SMatthew G. Knepley   PetscBool          usecprow = a->compressedrow.use;
1469b434eb95SMatthew G. Knepley 
1470b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1471b434eb95SMatthew G. Knepley #pragma disjoint(*x, *y, *aa)
1472b434eb95SMatthew G. Knepley #endif
1473b434eb95SMatthew G. Knepley 
1474b434eb95SMatthew G. Knepley   PetscFunctionBegin;
14759566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &a_a));
14769566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
14779566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1478b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1479b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1480b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1481b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1482b434eb95SMatthew G. Knepley     for (i = 0; i < m; i++) {
1483b434eb95SMatthew G. Knepley       n   = ii[i + 1] - ii[i];
1484b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1485fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1486b434eb95SMatthew G. Knepley       sum = 0.0;
1487b434eb95SMatthew G. Knepley       nonzerorow += (n > 0);
1488b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum, x, aa, aj, n);
1489b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1490b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1491b434eb95SMatthew G. Knepley     }
1492b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
14933d3eaba7SBarry Smith     ii = a->i;
1494b434eb95SMatthew G. Knepley     for (i = 0; i < m; i++) {
1495b434eb95SMatthew G. Knepley       n   = ii[i + 1] - ii[i];
1496b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1497fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1498b434eb95SMatthew G. Knepley       sum = 0.0;
1499b434eb95SMatthew G. Knepley       nonzerorow += (n > 0);
1500b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum, x, aa, aj, n);
1501b434eb95SMatthew G. Knepley       y[i] = sum;
1502b434eb95SMatthew G. Knepley     }
1503b434eb95SMatthew G. Knepley   }
15049566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * a->nz - nonzerorow));
15059566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
15069566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
15079566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a));
1508b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1509b434eb95SMatthew G. Knepley }
1510b434eb95SMatthew G. Knepley 
15119371c9d4SSatish Balay PetscErrorCode MatMultAddMax_SeqAIJ(Mat A, Vec xx, Vec yy, Vec zz) {
1512b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
1513b434eb95SMatthew G. Knepley   PetscScalar       *y, *z;
1514b434eb95SMatthew G. Knepley   const PetscScalar *x;
1515fff043a9SJunchao Zhang   const MatScalar   *aa, *a_a;
1516b434eb95SMatthew G. Knepley   PetscInt           m = A->rmap->n, *aj, *ii;
1517b434eb95SMatthew G. Knepley   PetscInt           n, i, *ridx = NULL;
1518b434eb95SMatthew G. Knepley   PetscScalar        sum;
1519b434eb95SMatthew G. Knepley   PetscBool          usecprow = a->compressedrow.use;
1520b434eb95SMatthew G. Knepley 
1521b434eb95SMatthew G. Knepley   PetscFunctionBegin;
15229566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &a_a));
15239566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
15249566063dSJacob Faibussowitsch   PetscCall(VecGetArrayPair(yy, zz, &y, &z));
1525b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
152648a46eb9SPierre Jolivet     if (zz != yy) PetscCall(PetscArraycpy(z, y, m));
1527b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1528b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1529b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1530b434eb95SMatthew G. Knepley     for (i = 0; i < m; i++) {
1531b434eb95SMatthew G. Knepley       n   = ii[i + 1] - ii[i];
1532b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1533fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1534b434eb95SMatthew G. Knepley       sum = y[*ridx];
1535b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum, x, aa, aj, n);
1536b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1537b434eb95SMatthew G. Knepley     }
1538b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
15393d3eaba7SBarry Smith     ii = a->i;
1540b434eb95SMatthew G. Knepley     for (i = 0; i < m; i++) {
1541b434eb95SMatthew G. Knepley       n   = ii[i + 1] - ii[i];
1542b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1543fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1544b434eb95SMatthew G. Knepley       sum = y[i];
1545b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum, x, aa, aj, n);
1546b434eb95SMatthew G. Knepley       z[i] = sum;
1547b434eb95SMatthew G. Knepley     }
1548b434eb95SMatthew G. Knepley   }
15499566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * a->nz));
15509566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
15519566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayPair(yy, zz, &y, &z));
15529566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a));
1553b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1554b434eb95SMatthew G. Knepley }
1555b434eb95SMatthew G. Knepley 
1556c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
15579371c9d4SSatish Balay PetscErrorCode MatMultAdd_SeqAIJ(Mat A, Vec xx, Vec yy, Vec zz) {
1558416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
1559f15663dcSBarry Smith   PetscScalar       *y, *z;
1560f15663dcSBarry Smith   const PetscScalar *x;
1561fff043a9SJunchao Zhang   const MatScalar   *aa, *a_a;
1562d9ca1df4SBarry Smith   const PetscInt    *aj, *ii, *ridx = NULL;
1563d9ca1df4SBarry Smith   PetscInt           m = A->rmap->n, n, i;
1564362ced78SSatish Balay   PetscScalar        sum;
1565ace3abfcSBarry Smith   PetscBool          usecprow = a->compressedrow.use;
15669ea0dfa2SSatish Balay 
15673a40ed3dSBarry Smith   PetscFunctionBegin;
1568b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
15699566063dSJacob Faibussowitsch     PetscCall(MatMultAdd_SeqAIJ_Inode(A, xx, yy, zz));
1570b215bc84SStefano Zampini     PetscFunctionReturn(0);
1571b215bc84SStefano Zampini   }
15729566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &a_a));
15739566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
15749566063dSJacob Faibussowitsch   PetscCall(VecGetArrayPair(yy, zz, &y, &z));
15754eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
157648a46eb9SPierre Jolivet     if (zz != yy) PetscCall(PetscArraycpy(z, y, m));
157797952fefSHong Zhang     m    = a->compressedrow.nrows;
157897952fefSHong Zhang     ii   = a->compressedrow.i;
157997952fefSHong Zhang     ridx = a->compressedrow.rindex;
158097952fefSHong Zhang     for (i = 0; i < m; i++) {
158197952fefSHong Zhang       n   = ii[i + 1] - ii[i];
158297952fefSHong Zhang       aj  = a->j + ii[i];
1583fff043a9SJunchao Zhang       aa  = a_a + ii[i];
158497952fefSHong Zhang       sum = y[*ridx];
1585f15663dcSBarry Smith       PetscSparseDensePlusDot(sum, x, aa, aj, n);
158697952fefSHong Zhang       z[*ridx++] = sum;
158797952fefSHong Zhang     }
158897952fefSHong Zhang   } else { /* do not use compressed row format */
15893d3eaba7SBarry Smith     ii = a->i;
1590f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
15913d3eaba7SBarry Smith     aj = a->j;
1592fff043a9SJunchao Zhang     aa = a_a;
1593f15663dcSBarry Smith     fortranmultaddaij_(&m, x, ii, aj, aa, y, z);
1594f15663dcSBarry Smith #else
159517ab2063SBarry Smith     for (i = 0; i < m; i++) {
1596f15663dcSBarry Smith       n = ii[i + 1] - ii[i];
1597f15663dcSBarry Smith       aj = a->j + ii[i];
1598fff043a9SJunchao Zhang       aa = a_a + ii[i];
159917ab2063SBarry Smith       sum = y[i];
1600f15663dcSBarry Smith       PetscSparseDensePlusDot(sum, x, aa, aj, n);
160117ab2063SBarry Smith       z[i] = sum;
160217ab2063SBarry Smith     }
160302ab625aSSatish Balay #endif
1604f15663dcSBarry Smith   }
16059566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * a->nz));
16069566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
16079566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayPair(yy, zz, &y, &z));
16089566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a));
16093a40ed3dSBarry Smith   PetscFunctionReturn(0);
161017ab2063SBarry Smith }
161117ab2063SBarry Smith 
161217ab2063SBarry Smith /*
161317ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
161417ab2063SBarry Smith */
16159371c9d4SSatish Balay PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A) {
1616416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
1617d0f46423SBarry Smith   PetscInt    i, j, m = A->rmap->n;
1618c0c07093SJunchao Zhang   PetscBool   alreadySet = PETSC_TRUE;
161917ab2063SBarry Smith 
16203a40ed3dSBarry Smith   PetscFunctionBegin;
162109f38230SBarry Smith   if (!a->diag) {
16229566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &a->diag));
16239566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A, m * sizeof(PetscInt)));
1624c0c07093SJunchao Zhang     alreadySet = PETSC_FALSE;
162509f38230SBarry Smith   }
1626d0f46423SBarry Smith   for (i = 0; i < A->rmap->n; i++) {
1627c0c07093SJunchao Zhang     /* If A's diagonal is already correctly set, this fast track enables cheap and repeated MatMarkDiagonal_SeqAIJ() calls */
1628c0c07093SJunchao Zhang     if (alreadySet) {
1629c0c07093SJunchao Zhang       PetscInt pos = a->diag[i];
1630c0c07093SJunchao Zhang       if (pos >= a->i[i] && pos < a->i[i + 1] && a->j[pos] == i) continue;
1631c0c07093SJunchao Zhang     }
1632c0c07093SJunchao Zhang 
163309f38230SBarry Smith     a->diag[i] = a->i[i + 1];
1634bfeeae90SHong Zhang     for (j = a->i[i]; j < a->i[i + 1]; j++) {
1635bfeeae90SHong Zhang       if (a->j[j] == i) {
163609f38230SBarry Smith         a->diag[i] = j;
163717ab2063SBarry Smith         break;
163817ab2063SBarry Smith       }
163917ab2063SBarry Smith     }
164017ab2063SBarry Smith   }
16413a40ed3dSBarry Smith   PetscFunctionReturn(0);
164217ab2063SBarry Smith }
164317ab2063SBarry Smith 
16449371c9d4SSatish Balay PetscErrorCode MatShift_SeqAIJ(Mat A, PetscScalar v) {
164561ecd0c6SBarry Smith   Mat_SeqAIJ     *a    = (Mat_SeqAIJ *)A->data;
164661ecd0c6SBarry Smith   const PetscInt *diag = (const PetscInt *)a->diag;
164761ecd0c6SBarry Smith   const PetscInt *ii   = (const PetscInt *)a->i;
164861ecd0c6SBarry Smith   PetscInt        i, *mdiag = NULL;
164961ecd0c6SBarry Smith   PetscInt        cnt = 0; /* how many diagonals are missing */
165061ecd0c6SBarry Smith 
165161ecd0c6SBarry Smith   PetscFunctionBegin;
165261ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
16539566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(A, 1, NULL));
16549566063dSJacob Faibussowitsch     PetscCall(MatShift_Basic(A, v));
165561ecd0c6SBarry Smith     PetscFunctionReturn(0);
165661ecd0c6SBarry Smith   }
165761ecd0c6SBarry Smith 
165861ecd0c6SBarry Smith   if (a->diagonaldense) {
165961ecd0c6SBarry Smith     cnt = 0;
166061ecd0c6SBarry Smith   } else {
16619566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(A->rmap->n, &mdiag));
166261ecd0c6SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1663349d3b71SJunchao Zhang       if (i < A->cmap->n && diag[i] >= ii[i + 1]) { /* 'out of range' rows never have diagonals */
166461ecd0c6SBarry Smith         cnt++;
166561ecd0c6SBarry Smith         mdiag[i] = 1;
166661ecd0c6SBarry Smith       }
166761ecd0c6SBarry Smith     }
166861ecd0c6SBarry Smith   }
166961ecd0c6SBarry Smith   if (!cnt) {
16709566063dSJacob Faibussowitsch     PetscCall(MatShift_Basic(A, v));
167161ecd0c6SBarry Smith   } else {
1672b6f2aa54SBarry Smith     PetscScalar *olda = a->a; /* preserve pointers to current matrix nonzeros structure and values */
1673b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
167461ecd0c6SBarry Smith     PetscBool    singlemalloc = a->singlemalloc, free_a = a->free_a, free_ij = a->free_ij;
167561ecd0c6SBarry Smith 
167661ecd0c6SBarry Smith     a->a = NULL;
167761ecd0c6SBarry Smith     a->j = NULL;
167861ecd0c6SBarry Smith     a->i = NULL;
167961ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
1680ad540459SPierre Jolivet     for (i = 0; i < PetscMin(A->rmap->n, A->cmap->n); i++) a->imax[i] += mdiag[i];
16819566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A, 0, a->imax));
168261ecd0c6SBarry Smith 
168361ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
168461ecd0c6SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
16859566063dSJacob Faibussowitsch       PetscCall(MatSetValues(A, 1, &i, a->imax[i] - mdiag[i], &oldj[oldi[i]], &olda[oldi[i]], ADD_VALUES));
168648a46eb9SPierre Jolivet       if (i < A->cmap->n) PetscCall(MatSetValue(A, i, i, v, ADD_VALUES));
1687447d62f5SStefano Zampini     }
16889566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
16899566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
169061ecd0c6SBarry Smith     if (singlemalloc) {
16919566063dSJacob Faibussowitsch       PetscCall(PetscFree3(olda, oldj, oldi));
169261ecd0c6SBarry Smith     } else {
16939566063dSJacob Faibussowitsch       if (free_a) PetscCall(PetscFree(olda));
16949566063dSJacob Faibussowitsch       if (free_ij) PetscCall(PetscFree(oldj));
16959566063dSJacob Faibussowitsch       if (free_ij) PetscCall(PetscFree(oldi));
169661ecd0c6SBarry Smith     }
169761ecd0c6SBarry Smith   }
16989566063dSJacob Faibussowitsch   PetscCall(PetscFree(mdiag));
169961ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
170061ecd0c6SBarry Smith   PetscFunctionReturn(0);
170161ecd0c6SBarry Smith }
170261ecd0c6SBarry Smith 
1703be5855fcSBarry Smith /*
1704be5855fcSBarry Smith      Checks for missing diagonals
1705be5855fcSBarry Smith */
17069371c9d4SSatish Balay PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A, PetscBool *missing, PetscInt *d) {
1707be5855fcSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
17087734d3b5SMatthew G. Knepley   PetscInt   *diag, *ii = a->i, i;
1709be5855fcSBarry Smith 
1710be5855fcSBarry Smith   PetscFunctionBegin;
171109f38230SBarry Smith   *missing = PETSC_FALSE;
17127734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
171309f38230SBarry Smith     *missing = PETSC_TRUE;
171409f38230SBarry Smith     if (d) *d = 0;
17159566063dSJacob Faibussowitsch     PetscCall(PetscInfo(A, "Matrix has no entries therefore is missing diagonal\n"));
171609f38230SBarry Smith   } else {
171701445905SHong Zhang     PetscInt n;
171801445905SHong Zhang     n    = PetscMin(A->rmap->n, A->cmap->n);
1719f1e2ffcdSBarry Smith     diag = a->diag;
172001445905SHong Zhang     for (i = 0; i < n; i++) {
17217734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i + 1]) {
172209f38230SBarry Smith         *missing = PETSC_TRUE;
172309f38230SBarry Smith         if (d) *d = i;
17249566063dSJacob Faibussowitsch         PetscCall(PetscInfo(A, "Matrix is missing diagonal number %" PetscInt_FMT "\n", i));
1725358d2f5dSShri Abhyankar         break;
172609f38230SBarry Smith       }
1727be5855fcSBarry Smith     }
1728be5855fcSBarry Smith   }
1729be5855fcSBarry Smith   PetscFunctionReturn(0);
1730be5855fcSBarry Smith }
1731be5855fcSBarry Smith 
17320da83c2eSBarry Smith #include <petscblaslapack.h>
17330da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
17340da83c2eSBarry Smith 
17350da83c2eSBarry Smith /*
17360da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
17370da83c2eSBarry Smith */
17389371c9d4SSatish Balay PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *diag) {
17390da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx, j, bsizemax = 0, *v_pivots;
17400da83c2eSBarry Smith   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
17410da83c2eSBarry Smith   const PetscReal shift = 0.0;
17420da83c2eSBarry Smith   PetscInt        ipvt[5];
17430da83c2eSBarry Smith   PetscScalar     work[25], *v_work;
17440da83c2eSBarry Smith 
17450da83c2eSBarry Smith   PetscFunctionBegin;
17460da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
17470da83c2eSBarry Smith   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
174808401ef6SPierre Jolivet   PetscCheck(ncnt == n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total blocksizes %" PetscInt_FMT " doesn't match number matrix rows %" PetscInt_FMT, ncnt, n);
1749ad540459SPierre Jolivet   for (i = 0; i < nblocks; i++) bsizemax = PetscMax(bsizemax, bsizes[i]);
17509566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(bsizemax, &indx));
175148a46eb9SPierre Jolivet   if (bsizemax > 7) PetscCall(PetscMalloc2(bsizemax, &v_work, bsizemax, &v_pivots));
17520da83c2eSBarry Smith   ncnt = 0;
17530da83c2eSBarry Smith   for (i = 0; i < nblocks; i++) {
17540da83c2eSBarry Smith     for (j = 0; j < bsizes[i]; j++) indx[j] = ncnt + j;
17559566063dSJacob Faibussowitsch     PetscCall(MatGetValues(A, bsizes[i], indx, bsizes[i], indx, diag));
17560da83c2eSBarry Smith     switch (bsizes[i]) {
17579371c9d4SSatish Balay     case 1: *diag = 1.0 / (*diag); break;
17580da83c2eSBarry Smith     case 2:
17599566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected));
17600da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17619566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_2(diag));
17620da83c2eSBarry Smith       break;
17630da83c2eSBarry Smith     case 3:
17649566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected));
17650da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17669566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_3(diag));
17670da83c2eSBarry Smith       break;
17680da83c2eSBarry Smith     case 4:
17699566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected));
17700da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17719566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_4(diag));
17720da83c2eSBarry Smith       break;
17730da83c2eSBarry Smith     case 5:
17749566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
17750da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17769566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_5(diag));
17770da83c2eSBarry Smith       break;
17780da83c2eSBarry Smith     case 6:
17799566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected));
17800da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17819566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_6(diag));
17820da83c2eSBarry Smith       break;
17830da83c2eSBarry Smith     case 7:
17849566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected));
17850da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17869566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_7(diag));
17870da83c2eSBarry Smith       break;
17880da83c2eSBarry Smith     default:
17899566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A(bsizes[i], diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
17900da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17919566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_N(diag, bsizes[i]));
17920da83c2eSBarry Smith     }
17930da83c2eSBarry Smith     ncnt += bsizes[i];
17940da83c2eSBarry Smith     diag += bsizes[i] * bsizes[i];
17950da83c2eSBarry Smith   }
179648a46eb9SPierre Jolivet   if (bsizemax > 7) PetscCall(PetscFree2(v_work, v_pivots));
17979566063dSJacob Faibussowitsch   PetscCall(PetscFree(indx));
17980da83c2eSBarry Smith   PetscFunctionReturn(0);
17990da83c2eSBarry Smith }
18000da83c2eSBarry Smith 
1801422a814eSBarry Smith /*
1802422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1803422a814eSBarry Smith */
18049371c9d4SSatish Balay PetscErrorCode MatInvertDiagonal_SeqAIJ(Mat A, PetscScalar omega, PetscScalar fshift) {
180571f1c65dSBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
1806d0f46423SBarry Smith   PetscInt         i, *diag, m = A->rmap->n;
18072e5835c6SStefano Zampini   const MatScalar *v;
180854f21887SBarry Smith   PetscScalar     *idiag, *mdiag;
180971f1c65dSBarry Smith 
181071f1c65dSBarry Smith   PetscFunctionBegin;
181171f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
18129566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqAIJ(A));
181371f1c65dSBarry Smith   diag = a->diag;
181471f1c65dSBarry Smith   if (!a->idiag) {
18159566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(m, &a->idiag, m, &a->mdiag, m, &a->ssor_work));
18169566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A, 3 * m * sizeof(PetscScalar)));
181771f1c65dSBarry Smith   }
18182e5835c6SStefano Zampini 
181971f1c65dSBarry Smith   mdiag = a->mdiag;
182071f1c65dSBarry Smith   idiag = a->idiag;
18219566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &v));
1822422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
182371f1c65dSBarry Smith     for (i = 0; i < m; i++) {
182471f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1825899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1826899639b0SHong Zhang         if (PetscRealPart(fshift)) {
18279566063dSJacob Faibussowitsch           PetscCall(PetscInfo(A, "Zero diagonal on row %" PetscInt_FMT "\n", i));
18287b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18297b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
18307b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
183198921bdaSJacob Faibussowitsch         } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Zero diagonal on row %" PetscInt_FMT, i);
1832899639b0SHong Zhang       }
183371f1c65dSBarry Smith       idiag[i] = 1.0 / v[diag[i]];
183471f1c65dSBarry Smith     }
18359566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(m));
183671f1c65dSBarry Smith   } else {
183771f1c65dSBarry Smith     for (i = 0; i < m; i++) {
183871f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
183971f1c65dSBarry Smith       idiag[i] = omega / (fshift + v[diag[i]]);
184071f1c65dSBarry Smith     }
18419566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * m));
184271f1c65dSBarry Smith   }
184371f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
18449566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &v));
184571f1c65dSBarry Smith   PetscFunctionReturn(0);
184671f1c65dSBarry Smith }
184771f1c65dSBarry Smith 
1848c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
18499371c9d4SSatish Balay PetscErrorCode MatSOR_SeqAIJ(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal fshift, PetscInt its, PetscInt lits, Vec xx) {
1850416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
1851e6d1f457SBarry Smith   PetscScalar       *x, d, sum, *t, scale;
18522e5835c6SStefano Zampini   const MatScalar   *v, *idiag = NULL, *mdiag, *aa;
185354f21887SBarry Smith   const PetscScalar *b, *bs, *xb, *ts;
18543d3eaba7SBarry Smith   PetscInt           n, m = A->rmap->n, i;
185597f1f81fSBarry Smith   const PetscInt    *idx, *diag;
185617ab2063SBarry Smith 
18573a40ed3dSBarry Smith   PetscFunctionBegin;
1858b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) {
18599566063dSJacob Faibussowitsch     PetscCall(MatSOR_SeqAIJ_Inode(A, bb, omega, flag, fshift, its, lits, xx));
1860b215bc84SStefano Zampini     PetscFunctionReturn(0);
1861b215bc84SStefano Zampini   }
1862b965ef7fSBarry Smith   its = its * lits;
186391723122SBarry Smith 
186471f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
18659566063dSJacob Faibussowitsch   if (!a->idiagvalid) PetscCall(MatInvertDiagonal_SeqAIJ(A, omega, fshift));
186671f1c65dSBarry Smith   a->fshift = fshift;
186771f1c65dSBarry Smith   a->omega  = omega;
1868ed480e8bSBarry Smith 
186971f1c65dSBarry Smith   diag  = a->diag;
187071f1c65dSBarry Smith   t     = a->ssor_work;
1871ed480e8bSBarry Smith   idiag = a->idiag;
187271f1c65dSBarry Smith   mdiag = a->mdiag;
1873ed480e8bSBarry Smith 
18749566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
18759566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx, &x));
18769566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
1877ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
187817ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
187917ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
1880ed480e8bSBarry Smith     bs = b;
188117ab2063SBarry Smith     for (i = 0; i < m; i++) {
188271f1c65dSBarry Smith       d   = fshift + mdiag[i];
1883416022c9SBarry Smith       n   = a->i[i + 1] - diag[i] - 1;
1884ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
18852e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
188617ab2063SBarry Smith       sum = b[i] * d / omega;
1887003131ecSBarry Smith       PetscSparseDensePlusDot(sum, bs, v, idx, n);
188817ab2063SBarry Smith       x[i] = sum;
188917ab2063SBarry Smith     }
18909566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(xx, &x));
18919566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(bb, &b));
18929566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
18939566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(a->nz));
18943a40ed3dSBarry Smith     PetscFunctionReturn(0);
189517ab2063SBarry Smith   }
1896c783ea89SBarry Smith 
189708401ef6SPierre Jolivet   PetscCheck(flag != SOR_APPLY_LOWER, PETSC_COMM_SELF, PETSC_ERR_SUP, "SOR_APPLY_LOWER is not implemented");
1898f7d195e4SLawrence Mitchell   if (flag & SOR_EISENSTAT) {
18994c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
1900887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
190117ab2063SBarry Smith 
190217ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
190317ab2063SBarry Smith 
1904887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
190517ab2063SBarry Smith     */
190617ab2063SBarry Smith     scale = (2.0 / omega) - 1.0;
190717ab2063SBarry Smith 
190817ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
190917ab2063SBarry Smith     for (i = m - 1; i >= 0; i--) {
1910416022c9SBarry Smith       n   = a->i[i + 1] - diag[i] - 1;
1911ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
19122e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
191317ab2063SBarry Smith       sum = b[i];
1914e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum, x, v, idx, n);
1915ed480e8bSBarry Smith       x[i] = sum * idiag[i];
191617ab2063SBarry Smith     }
191717ab2063SBarry Smith 
191817ab2063SBarry Smith     /*  t = b - (2*E - D)x */
19192e5835c6SStefano Zampini     v = aa;
19202205254eSKarl Rupp     for (i = 0; i < m; i++) t[i] = b[i] - scale * (v[*diag++]) * x[i];
192117ab2063SBarry Smith 
192217ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
1923ed480e8bSBarry Smith     ts   = t;
1924416022c9SBarry Smith     diag = a->diag;
192517ab2063SBarry Smith     for (i = 0; i < m; i++) {
1926416022c9SBarry Smith       n   = diag[i] - a->i[i];
1927ed480e8bSBarry Smith       idx = a->j + a->i[i];
19282e5835c6SStefano Zampini       v   = aa + a->i[i];
192917ab2063SBarry Smith       sum = t[i];
1930003131ecSBarry Smith       PetscSparseDenseMinusDot(sum, ts, v, idx, n);
1931ed480e8bSBarry Smith       t[i] = sum * idiag[i];
1932733d66baSBarry Smith       /*  x = x + t */
1933733d66baSBarry Smith       x[i] += t[i];
193417ab2063SBarry Smith     }
193517ab2063SBarry Smith 
19369566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(6.0 * m - 1 + 2.0 * a->nz));
19379566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(xx, &x));
19389566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(bb, &b));
19393a40ed3dSBarry Smith     PetscFunctionReturn(0);
194017ab2063SBarry Smith   }
194117ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
194217ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
194317ab2063SBarry Smith       for (i = 0; i < m; i++) {
1944416022c9SBarry Smith         n   = diag[i] - a->i[i];
1945ed480e8bSBarry Smith         idx = a->j + a->i[i];
19462e5835c6SStefano Zampini         v   = aa + a->i[i];
194717ab2063SBarry Smith         sum = b[i];
1948e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum, x, v, idx, n);
19495c99c7daSBarry Smith         t[i] = sum;
1950ed480e8bSBarry Smith         x[i] = sum * idiag[i];
195117ab2063SBarry Smith       }
19525c99c7daSBarry Smith       xb = t;
19539566063dSJacob Faibussowitsch       PetscCall(PetscLogFlops(a->nz));
19543a40ed3dSBarry Smith     } else xb = b;
195517ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
195617ab2063SBarry Smith       for (i = m - 1; i >= 0; i--) {
1957416022c9SBarry Smith         n   = a->i[i + 1] - diag[i] - 1;
1958ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
19592e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
196017ab2063SBarry Smith         sum = xb[i];
1961e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum, x, v, idx, n);
19625c99c7daSBarry Smith         if (xb == b) {
1963ed480e8bSBarry Smith           x[i] = sum * idiag[i];
19645c99c7daSBarry Smith         } else {
1965b19a5dc2SMark Adams           x[i] = (1 - omega) * x[i] + sum * idiag[i]; /* omega in idiag */
196617ab2063SBarry Smith         }
19675c99c7daSBarry Smith       }
19689566063dSJacob Faibussowitsch       PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */
196917ab2063SBarry Smith     }
197017ab2063SBarry Smith     its--;
197117ab2063SBarry Smith   }
197217ab2063SBarry Smith   while (its--) {
197317ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
197417ab2063SBarry Smith       for (i = 0; i < m; i++) {
1975b19a5dc2SMark Adams         /* lower */
1976b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
1977ed480e8bSBarry Smith         idx = a->j + a->i[i];
19782e5835c6SStefano Zampini         v   = aa + a->i[i];
197917ab2063SBarry Smith         sum = b[i];
1980e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum, x, v, idx, n);
1981b19a5dc2SMark Adams         t[i] = sum; /* save application of the lower-triangular part */
1982b19a5dc2SMark Adams         /* upper */
1983b19a5dc2SMark Adams         n    = a->i[i + 1] - diag[i] - 1;
1984b19a5dc2SMark Adams         idx  = a->j + diag[i] + 1;
19852e5835c6SStefano Zampini         v    = aa + diag[i] + 1;
1986b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum, x, v, idx, n);
1987b19a5dc2SMark Adams         x[i] = (1. - omega) * x[i] + sum * idiag[i]; /* omega in idiag */
198817ab2063SBarry Smith       }
1989b19a5dc2SMark Adams       xb = t;
19909566063dSJacob Faibussowitsch       PetscCall(PetscLogFlops(2.0 * a->nz));
1991b19a5dc2SMark Adams     } else xb = b;
199217ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
199317ab2063SBarry Smith       for (i = m - 1; i >= 0; i--) {
1994b19a5dc2SMark Adams         sum = xb[i];
1995b19a5dc2SMark Adams         if (xb == b) {
1996b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
1997416022c9SBarry Smith           n   = a->i[i + 1] - a->i[i];
1998ed480e8bSBarry Smith           idx = a->j + a->i[i];
19992e5835c6SStefano Zampini           v   = aa + a->i[i];
2000e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum, x, v, idx, n);
2001ed480e8bSBarry Smith           x[i] = (1. - omega) * x[i] + (sum + mdiag[i] * x[i]) * idiag[i];
2002b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
2003b19a5dc2SMark Adams           n   = a->i[i + 1] - diag[i] - 1;
2004b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
20052e5835c6SStefano Zampini           v   = aa + diag[i] + 1;
2006b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum, x, v, idx, n);
2007b19a5dc2SMark Adams           x[i] = (1. - omega) * x[i] + sum * idiag[i]; /* omega in idiag */
200817ab2063SBarry Smith         }
2009b19a5dc2SMark Adams       }
2010b19a5dc2SMark Adams       if (xb == b) {
20119566063dSJacob Faibussowitsch         PetscCall(PetscLogFlops(2.0 * a->nz));
2012b19a5dc2SMark Adams       } else {
20139566063dSJacob Faibussowitsch         PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */
2014b19a5dc2SMark Adams       }
201517ab2063SBarry Smith     }
201617ab2063SBarry Smith   }
20179566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
20189566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx, &x));
20199566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
2020365a8a9eSBarry Smith   PetscFunctionReturn(0);
202117ab2063SBarry Smith }
202217ab2063SBarry Smith 
20239371c9d4SSatish Balay PetscErrorCode MatGetInfo_SeqAIJ(Mat A, MatInfoType flag, MatInfo *info) {
2024416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
20254e220ebcSLois Curfman McInnes 
20263a40ed3dSBarry Smith   PetscFunctionBegin;
20274e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
20283966268fSBarry Smith   info->nz_allocated = a->maxnz;
20293966268fSBarry Smith   info->nz_used      = a->nz;
20303966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
20313966268fSBarry Smith   info->assemblies   = A->num_ass;
20323966268fSBarry Smith   info->mallocs      = A->info.mallocs;
20337adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
2034d5f3da31SBarry Smith   if (A->factortype) {
20354e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
20364e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
20374e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
20384e220ebcSLois Curfman McInnes   } else {
20394e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
20404e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
20414e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
20424e220ebcSLois Curfman McInnes   }
20433a40ed3dSBarry Smith   PetscFunctionReturn(0);
204417ab2063SBarry Smith }
204517ab2063SBarry Smith 
20469371c9d4SSatish Balay PetscErrorCode MatZeroRows_SeqAIJ(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
2047416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
2048c7da8527SEric Chamberland   PetscInt           i, m = A->rmap->n - 1;
204997b48c8fSBarry Smith   const PetscScalar *xx;
20502e5835c6SStefano Zampini   PetscScalar       *bb, *aa;
2051c7da8527SEric Chamberland   PetscInt           d = 0;
205217ab2063SBarry Smith 
20533a40ed3dSBarry Smith   PetscFunctionBegin;
205497b48c8fSBarry Smith   if (x && b) {
20559566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
20569566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
205797b48c8fSBarry Smith     for (i = 0; i < N; i++) {
2058aed4548fSBarry Smith       PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]);
2059447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
206097b48c8fSBarry Smith       bb[rows[i]] = diag * xx[rows[i]];
206197b48c8fSBarry Smith     }
20629566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
20639566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
206497b48c8fSBarry Smith   }
206597b48c8fSBarry Smith 
20669566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
2067a9817697SBarry Smith   if (a->keepnonzeropattern) {
2068f1e2ffcdSBarry Smith     for (i = 0; i < N; i++) {
2069aed4548fSBarry Smith       PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]);
20709566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(&aa[a->i[rows[i]]], a->ilen[rows[i]]));
2071f1e2ffcdSBarry Smith     }
2072f4df32b1SMatthew Knepley     if (diag != 0.0) {
2073c7da8527SEric Chamberland       for (i = 0; i < N; i++) {
2074c7da8527SEric Chamberland         d = rows[i];
2075447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
207608401ef6SPierre Jolivet         PetscCheck(a->diag[d] < a->i[d + 1], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix is missing diagonal entry in the zeroed row %" PetscInt_FMT, d);
2077c7da8527SEric Chamberland       }
2078f1e2ffcdSBarry Smith       for (i = 0; i < N; i++) {
2079447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
20802e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
2081f1e2ffcdSBarry Smith       }
2082f1e2ffcdSBarry Smith     }
2083f1e2ffcdSBarry Smith   } else {
2084f4df32b1SMatthew Knepley     if (diag != 0.0) {
208517ab2063SBarry Smith       for (i = 0; i < N; i++) {
2086aed4548fSBarry Smith         PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]);
20877ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2088447d62f5SStefano Zampini           if (rows[i] >= A->cmap->n) {
2089447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2090447d62f5SStefano Zampini           } else {
2091416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
20922e5835c6SStefano Zampini             aa[a->i[rows[i]]]   = diag;
2093bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2094447d62f5SStefano Zampini           }
2095447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
20969566063dSJacob Faibussowitsch           PetscCall(MatSetValues_SeqAIJ(A, 1, &rows[i], 1, &rows[i], &diag, INSERT_VALUES));
209717ab2063SBarry Smith         }
209817ab2063SBarry Smith       }
20993a40ed3dSBarry Smith     } else {
210017ab2063SBarry Smith       for (i = 0; i < N; i++) {
2101aed4548fSBarry Smith         PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]);
2102416022c9SBarry Smith         a->ilen[rows[i]] = 0;
210317ab2063SBarry Smith       }
210417ab2063SBarry Smith     }
2105e56f5c9eSBarry Smith     A->nonzerostate++;
2106f1e2ffcdSBarry Smith   }
21079566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
2108dbbe0bcdSBarry Smith   PetscUseTypeMethod(A, assemblyend, MAT_FINAL_ASSEMBLY);
21093a40ed3dSBarry Smith   PetscFunctionReturn(0);
211017ab2063SBarry Smith }
211117ab2063SBarry Smith 
21129371c9d4SSatish Balay PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
21136e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
21146e169961SBarry Smith   PetscInt           i, j, m = A->rmap->n - 1, d = 0;
21152b40b63fSBarry Smith   PetscBool          missing, *zeroed, vecs = PETSC_FALSE;
21166e169961SBarry Smith   const PetscScalar *xx;
21172e5835c6SStefano Zampini   PetscScalar       *bb, *aa;
21186e169961SBarry Smith 
21196e169961SBarry Smith   PetscFunctionBegin;
21202e5835c6SStefano Zampini   if (!N) PetscFunctionReturn(0);
21219566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
21226e169961SBarry Smith   if (x && b) {
21239566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
21249566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
21252b40b63fSBarry Smith     vecs = PETSC_TRUE;
21266e169961SBarry Smith   }
21279566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(A->rmap->n, &zeroed));
21286e169961SBarry Smith   for (i = 0; i < N; i++) {
2129aed4548fSBarry Smith     PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]);
21309566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(&aa[a->i[rows[i]]], a->ilen[rows[i]]));
21312205254eSKarl Rupp 
21326e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
21336e169961SBarry Smith   }
21346e169961SBarry Smith   for (i = 0; i < A->rmap->n; i++) {
21356e169961SBarry Smith     if (!zeroed[i]) {
21366e169961SBarry Smith       for (j = a->i[i]; j < a->i[i + 1]; j++) {
21374cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
21382e5835c6SStefano Zampini           if (vecs) bb[i] -= aa[j] * xx[a->j[j]];
21392e5835c6SStefano Zampini           aa[j] = 0.0;
21406e169961SBarry Smith         }
21416e169961SBarry Smith       }
21424cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag * xx[i];
21436e169961SBarry Smith   }
21446e169961SBarry Smith   if (x && b) {
21459566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
21469566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
21476e169961SBarry Smith   }
21489566063dSJacob Faibussowitsch   PetscCall(PetscFree(zeroed));
21496e169961SBarry Smith   if (diag != 0.0) {
21509566063dSJacob Faibussowitsch     PetscCall(MatMissingDiagonal_SeqAIJ(A, &missing, &d));
21511d5a398dSstefano_zampini     if (missing) {
21521d5a398dSstefano_zampini       for (i = 0; i < N; i++) {
21534cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
2154aed4548fSBarry Smith         PetscCheck(!a->nonew || rows[i] < d, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix is missing diagonal entry in row %" PetscInt_FMT " (%" PetscInt_FMT ")", d, rows[i]);
21559566063dSJacob Faibussowitsch         PetscCall(MatSetValues_SeqAIJ(A, 1, &rows[i], 1, &rows[i], &diag, INSERT_VALUES));
21561d5a398dSstefano_zampini       }
21571d5a398dSstefano_zampini     } else {
2158ad540459SPierre Jolivet       for (i = 0; i < N; i++) aa[a->diag[rows[i]]] = diag;
21596e169961SBarry Smith     }
21601d5a398dSstefano_zampini   }
21619566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
2162dbbe0bcdSBarry Smith   PetscUseTypeMethod(A, assemblyend, MAT_FINAL_ASSEMBLY);
21636e169961SBarry Smith   PetscFunctionReturn(0);
21646e169961SBarry Smith }
21656e169961SBarry Smith 
21669371c9d4SSatish Balay PetscErrorCode MatGetRow_SeqAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) {
2167fff043a9SJunchao Zhang   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
2168fff043a9SJunchao Zhang   const PetscScalar *aa;
2169fff043a9SJunchao Zhang   PetscInt          *itmp;
217017ab2063SBarry Smith 
21713a40ed3dSBarry Smith   PetscFunctionBegin;
21729566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
2173416022c9SBarry Smith   *nz = a->i[row + 1] - a->i[row];
21742e5835c6SStefano Zampini   if (v) *v = (PetscScalar *)(aa + a->i[row]);
217517ab2063SBarry Smith   if (idx) {
2176bfeeae90SHong Zhang     itmp = a->j + a->i[row];
217726fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
2178f4259b30SLisandro Dalcin     else *idx = NULL;
217917ab2063SBarry Smith   }
21809566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
21813a40ed3dSBarry Smith   PetscFunctionReturn(0);
218217ab2063SBarry Smith }
218317ab2063SBarry Smith 
21849371c9d4SSatish Balay PetscErrorCode MatRestoreRow_SeqAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) {
21853a40ed3dSBarry Smith   PetscFunctionBegin;
2186cb4a9cd9SHong Zhang   if (nz) *nz = 0;
21872e5835c6SStefano Zampini   if (idx) *idx = NULL;
21882e5835c6SStefano Zampini   if (v) *v = NULL;
21893a40ed3dSBarry Smith   PetscFunctionReturn(0);
219017ab2063SBarry Smith }
219117ab2063SBarry Smith 
21929371c9d4SSatish Balay PetscErrorCode MatNorm_SeqAIJ(Mat A, NormType type, PetscReal *nrm) {
2193416022c9SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
21942e5835c6SStefano Zampini   const MatScalar *v;
219536db0b34SBarry Smith   PetscReal        sum = 0.0;
219697f1f81fSBarry Smith   PetscInt         i, j;
219717ab2063SBarry Smith 
21983a40ed3dSBarry Smith   PetscFunctionBegin;
21999566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &v));
220017ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2201570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2202570b7f6dSBarry Smith     PetscBLASInt one = 1, nz = a->nz;
2203792fecdfSBarry Smith     PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&nz, v, &one));
2204570b7f6dSBarry Smith #else
2205416022c9SBarry Smith     for (i = 0; i < a->nz; i++) {
22069371c9d4SSatish Balay       sum += PetscRealPart(PetscConj(*v) * (*v));
22079371c9d4SSatish Balay       v++;
220817ab2063SBarry Smith     }
22098f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2210570b7f6dSBarry Smith #endif
22119566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * a->nz));
22123a40ed3dSBarry Smith   } else if (type == NORM_1) {
221336db0b34SBarry Smith     PetscReal *tmp;
221497f1f81fSBarry Smith     PetscInt  *jj = a->j;
22159566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(A->cmap->n + 1, &tmp));
2216064f8208SBarry Smith     *nrm = 0.0;
2217416022c9SBarry Smith     for (j = 0; j < a->nz; j++) {
22189371c9d4SSatish Balay       tmp[*jj++] += PetscAbsScalar(*v);
22199371c9d4SSatish Balay       v++;
222017ab2063SBarry Smith     }
2221d0f46423SBarry Smith     for (j = 0; j < A->cmap->n; j++) {
2222064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
222317ab2063SBarry Smith     }
22249566063dSJacob Faibussowitsch     PetscCall(PetscFree(tmp));
22259566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(PetscMax(a->nz - 1, 0)));
22263a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2227064f8208SBarry Smith     *nrm = 0.0;
2228d0f46423SBarry Smith     for (j = 0; j < A->rmap->n; j++) {
22292e5835c6SStefano Zampini       const PetscScalar *v2 = v + a->i[j];
223017ab2063SBarry Smith       sum                   = 0.0;
2231416022c9SBarry Smith       for (i = 0; i < a->i[j + 1] - a->i[j]; i++) {
22329371c9d4SSatish Balay         sum += PetscAbsScalar(*v2);
22339371c9d4SSatish Balay         v2++;
223417ab2063SBarry Smith       }
2235064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
223617ab2063SBarry Smith     }
22379566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(PetscMax(a->nz - 1, 0)));
2238f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for two norm");
22399566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &v));
22403a40ed3dSBarry Smith   PetscFunctionReturn(0);
224117ab2063SBarry Smith }
224217ab2063SBarry Smith 
22439371c9d4SSatish Balay PetscErrorCode MatIsTranspose_SeqAIJ(Mat A, Mat B, PetscReal tol, PetscBool *f) {
22443d3eaba7SBarry Smith   Mat_SeqAIJ      *aij = (Mat_SeqAIJ *)A->data, *bij = (Mat_SeqAIJ *)B->data;
224554f21887SBarry Smith   PetscInt        *adx, *bdx, *aii, *bii, *aptr, *bptr;
22462e5835c6SStefano Zampini   const MatScalar *va, *vb;
224797f1f81fSBarry Smith   PetscInt         ma, na, mb, nb, i;
2248cd0d46ebSvictorle 
2249cd0d46ebSvictorle   PetscFunctionBegin;
22509566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &ma, &na));
22519566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, &mb, &nb));
22525485867bSBarry Smith   if (ma != nb || na != mb) {
22535485867bSBarry Smith     *f = PETSC_FALSE;
22545485867bSBarry Smith     PetscFunctionReturn(0);
22555485867bSBarry Smith   }
22569566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &va));
22579566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(B, &vb));
22589371c9d4SSatish Balay   aii = aij->i;
22599371c9d4SSatish Balay   bii = bij->i;
22609371c9d4SSatish Balay   adx = aij->j;
22619371c9d4SSatish Balay   bdx = bij->j;
22629566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ma, &aptr));
22639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(mb, &bptr));
2264cd0d46ebSvictorle   for (i = 0; i < ma; i++) aptr[i] = aii[i];
2265cd0d46ebSvictorle   for (i = 0; i < mb; i++) bptr[i] = bii[i];
2266cd0d46ebSvictorle 
2267cd0d46ebSvictorle   *f = PETSC_TRUE;
2268cd0d46ebSvictorle   for (i = 0; i < ma; i++) {
2269cd0d46ebSvictorle     while (aptr[i] < aii[i + 1]) {
227097f1f81fSBarry Smith       PetscInt    idc, idr;
22715485867bSBarry Smith       PetscScalar vc, vr;
2272cd0d46ebSvictorle       /* column/row index/value */
22735485867bSBarry Smith       idc = adx[aptr[i]];
22745485867bSBarry Smith       idr = bdx[bptr[idc]];
22755485867bSBarry Smith       vc  = va[aptr[i]];
22765485867bSBarry Smith       vr  = vb[bptr[idc]];
22775485867bSBarry Smith       if (i != idr || PetscAbsScalar(vc - vr) > tol) {
22785485867bSBarry Smith         *f = PETSC_FALSE;
22795485867bSBarry Smith         goto done;
2280cd0d46ebSvictorle       } else {
22815485867bSBarry Smith         aptr[i]++;
22825485867bSBarry Smith         if (B || i != idc) bptr[idc]++;
2283cd0d46ebSvictorle       }
2284cd0d46ebSvictorle     }
2285cd0d46ebSvictorle   }
2286cd0d46ebSvictorle done:
22879566063dSJacob Faibussowitsch   PetscCall(PetscFree(aptr));
22889566063dSJacob Faibussowitsch   PetscCall(PetscFree(bptr));
22899566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &va));
22909566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(B, &vb));
2291cd0d46ebSvictorle   PetscFunctionReturn(0);
2292cd0d46ebSvictorle }
2293cd0d46ebSvictorle 
22949371c9d4SSatish Balay PetscErrorCode MatIsHermitianTranspose_SeqAIJ(Mat A, Mat B, PetscReal tol, PetscBool *f) {
22953d3eaba7SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data, *bij = (Mat_SeqAIJ *)B->data;
229654f21887SBarry Smith   PetscInt   *adx, *bdx, *aii, *bii, *aptr, *bptr;
229754f21887SBarry Smith   MatScalar  *va, *vb;
22981cbb95d3SBarry Smith   PetscInt    ma, na, mb, nb, i;
22991cbb95d3SBarry Smith 
23001cbb95d3SBarry Smith   PetscFunctionBegin;
23019566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &ma, &na));
23029566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, &mb, &nb));
23031cbb95d3SBarry Smith   if (ma != nb || na != mb) {
23041cbb95d3SBarry Smith     *f = PETSC_FALSE;
23051cbb95d3SBarry Smith     PetscFunctionReturn(0);
23061cbb95d3SBarry Smith   }
23079371c9d4SSatish Balay   aii = aij->i;
23089371c9d4SSatish Balay   bii = bij->i;
23099371c9d4SSatish Balay   adx = aij->j;
23109371c9d4SSatish Balay   bdx = bij->j;
23119371c9d4SSatish Balay   va  = aij->a;
23129371c9d4SSatish Balay   vb  = bij->a;
23139566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ma, &aptr));
23149566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(mb, &bptr));
23151cbb95d3SBarry Smith   for (i = 0; i < ma; i++) aptr[i] = aii[i];
23161cbb95d3SBarry Smith   for (i = 0; i < mb; i++) bptr[i] = bii[i];
23171cbb95d3SBarry Smith 
23181cbb95d3SBarry Smith   *f = PETSC_TRUE;
23191cbb95d3SBarry Smith   for (i = 0; i < ma; i++) {
23201cbb95d3SBarry Smith     while (aptr[i] < aii[i + 1]) {
23211cbb95d3SBarry Smith       PetscInt    idc, idr;
23221cbb95d3SBarry Smith       PetscScalar vc, vr;
23231cbb95d3SBarry Smith       /* column/row index/value */
23241cbb95d3SBarry Smith       idc = adx[aptr[i]];
23251cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
23261cbb95d3SBarry Smith       vc  = va[aptr[i]];
23271cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
23281cbb95d3SBarry Smith       if (i != idr || PetscAbsScalar(vc - PetscConj(vr)) > tol) {
23291cbb95d3SBarry Smith         *f = PETSC_FALSE;
23301cbb95d3SBarry Smith         goto done;
23311cbb95d3SBarry Smith       } else {
23321cbb95d3SBarry Smith         aptr[i]++;
23331cbb95d3SBarry Smith         if (B || i != idc) bptr[idc]++;
23341cbb95d3SBarry Smith       }
23351cbb95d3SBarry Smith     }
23361cbb95d3SBarry Smith   }
23371cbb95d3SBarry Smith done:
23389566063dSJacob Faibussowitsch   PetscCall(PetscFree(aptr));
23399566063dSJacob Faibussowitsch   PetscCall(PetscFree(bptr));
23401cbb95d3SBarry Smith   PetscFunctionReturn(0);
23411cbb95d3SBarry Smith }
23421cbb95d3SBarry Smith 
23439371c9d4SSatish Balay PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A, PetscReal tol, PetscBool *f) {
23449e29f15eSvictorle   PetscFunctionBegin;
23459566063dSJacob Faibussowitsch   PetscCall(MatIsTranspose_SeqAIJ(A, A, tol, f));
23469e29f15eSvictorle   PetscFunctionReturn(0);
23479e29f15eSvictorle }
23489e29f15eSvictorle 
23499371c9d4SSatish Balay PetscErrorCode MatIsHermitian_SeqAIJ(Mat A, PetscReal tol, PetscBool *f) {
23501cbb95d3SBarry Smith   PetscFunctionBegin;
23519566063dSJacob Faibussowitsch   PetscCall(MatIsHermitianTranspose_SeqAIJ(A, A, tol, f));
23521cbb95d3SBarry Smith   PetscFunctionReturn(0);
23531cbb95d3SBarry Smith }
23541cbb95d3SBarry Smith 
23559371c9d4SSatish Balay PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A, Vec ll, Vec rr) {
2356416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
2357fff8e43fSBarry Smith   const PetscScalar *l, *r;
2358fff8e43fSBarry Smith   PetscScalar        x;
235954f21887SBarry Smith   MatScalar         *v;
2360fff8e43fSBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, M, nz = a->nz;
2361fff8e43fSBarry Smith   const PetscInt    *jj;
236217ab2063SBarry Smith 
23633a40ed3dSBarry Smith   PetscFunctionBegin;
236417ab2063SBarry Smith   if (ll) {
23653ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
23663ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
23679566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(ll, &m));
236808401ef6SPierre Jolivet     PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vector wrong length");
23699566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ll, &l));
23709566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(A, &v));
237117ab2063SBarry Smith     for (i = 0; i < m; i++) {
237217ab2063SBarry Smith       x = l[i];
2373416022c9SBarry Smith       M = a->i[i + 1] - a->i[i];
23742205254eSKarl Rupp       for (j = 0; j < M; j++) (*v++) *= x;
237517ab2063SBarry Smith     }
23769566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ll, &l));
23779566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(nz));
23789566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArray(A, &v));
237917ab2063SBarry Smith   }
238017ab2063SBarry Smith   if (rr) {
23819566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(rr, &n));
238208401ef6SPierre Jolivet     PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vector wrong length");
23839566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rr, &r));
23849566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(A, &v));
23852e5835c6SStefano Zampini     jj = a->j;
23862205254eSKarl Rupp     for (i = 0; i < nz; i++) (*v++) *= r[*jj++];
23879566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArray(A, &v));
23889566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rr, &r));
23899566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(nz));
239017ab2063SBarry Smith   }
23919566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(A));
23923a40ed3dSBarry Smith   PetscFunctionReturn(0);
239317ab2063SBarry Smith }
239417ab2063SBarry Smith 
23959371c9d4SSatish Balay PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A, IS isrow, IS iscol, PetscInt csize, MatReuse scall, Mat *B) {
2396db02288aSLois Curfman McInnes   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data, *c;
2397d0f46423SBarry Smith   PetscInt          *smap, i, k, kstart, kend, oldcols = A->cmap->n, *lens;
239897f1f81fSBarry Smith   PetscInt           row, mat_i, *mat_j, tcol, first, step, *mat_ilen, sum, lensi;
23995d0c19d7SBarry Smith   const PetscInt    *irow, *icol;
24002e5835c6SStefano Zampini   const PetscScalar *aa;
24015d0c19d7SBarry Smith   PetscInt           nrows, ncols;
240297f1f81fSBarry Smith   PetscInt          *starts, *j_new, *i_new, *aj = a->j, *ai = a->i, ii, *ailen = a->ilen;
240354f21887SBarry Smith   MatScalar         *a_new, *mat_a;
2404416022c9SBarry Smith   Mat                C;
2405cdc6f3adSToby Isaac   PetscBool          stride;
240617ab2063SBarry Smith 
24073a40ed3dSBarry Smith   PetscFunctionBegin;
24089566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(isrow, &irow));
24099566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow, &nrows));
24109566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol, &ncols));
241117ab2063SBarry Smith 
24129566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)iscol, ISSTRIDE, &stride));
2413ff718158SBarry Smith   if (stride) {
24149566063dSJacob Faibussowitsch     PetscCall(ISStrideGetInfo(iscol, &first, &step));
2415ff718158SBarry Smith   } else {
2416ff718158SBarry Smith     first = 0;
2417ff718158SBarry Smith     step  = 0;
2418ff718158SBarry Smith   }
2419fee21e36SBarry Smith   if (stride && step == 1) {
242002834360SBarry Smith     /* special case of contiguous rows */
24219566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nrows, &lens, nrows, &starts));
242202834360SBarry Smith     /* loop over new rows determining lens and starting points */
242302834360SBarry Smith     for (i = 0; i < nrows; i++) {
2424bfeeae90SHong Zhang       kstart    = ai[irow[i]];
2425a2744918SBarry Smith       kend      = kstart + ailen[irow[i]];
2426a91a9bebSLisandro Dalcin       starts[i] = kstart;
242702834360SBarry Smith       for (k = kstart; k < kend; k++) {
2428bfeeae90SHong Zhang         if (aj[k] >= first) {
242902834360SBarry Smith           starts[i] = k;
243002834360SBarry Smith           break;
243102834360SBarry Smith         }
243202834360SBarry Smith       }
2433a2744918SBarry Smith       sum = 0;
243402834360SBarry Smith       while (k < kend) {
2435bfeeae90SHong Zhang         if (aj[k++] >= first + ncols) break;
2436a2744918SBarry Smith         sum++;
243702834360SBarry Smith       }
2438a2744918SBarry Smith       lens[i] = sum;
243902834360SBarry Smith     }
244002834360SBarry Smith     /* create submatrix */
2441cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
244297f1f81fSBarry Smith       PetscInt n_cols, n_rows;
24439566063dSJacob Faibussowitsch       PetscCall(MatGetSize(*B, &n_rows, &n_cols));
2444aed4548fSBarry Smith       PetscCheck(n_rows == nrows && n_cols == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Reused submatrix wrong size");
24459566063dSJacob Faibussowitsch       PetscCall(MatZeroEntries(*B));
244608480c60SBarry Smith       C = *B;
24473a40ed3dSBarry Smith     } else {
24483bef6203SJed Brown       PetscInt rbs, cbs;
24499566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
24509566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, nrows, ncols, PETSC_DETERMINE, PETSC_DETERMINE));
24519566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(isrow, &rbs));
24529566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(iscol, &cbs));
24539566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizes(C, rbs, cbs));
24549566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, ((PetscObject)A)->type_name));
24559566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C, 0, lens));
245608480c60SBarry Smith     }
2457db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ *)C->data;
2458db02288aSLois Curfman McInnes 
245902834360SBarry Smith     /* loop over rows inserting into submatrix */
2460db02288aSLois Curfman McInnes     a_new = c->a;
2461db02288aSLois Curfman McInnes     j_new = c->j;
2462db02288aSLois Curfman McInnes     i_new = c->i;
24639566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(A, &aa));
246402834360SBarry Smith     for (i = 0; i < nrows; i++) {
2465a2744918SBarry Smith       ii    = starts[i];
2466a2744918SBarry Smith       lensi = lens[i];
2467ad540459SPierre Jolivet       for (k = 0; k < lensi; k++) *j_new++ = aj[ii + k] - first;
24689566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(a_new, aa + starts[i], lensi));
2469a2744918SBarry Smith       a_new += lensi;
2470a2744918SBarry Smith       i_new[i + 1] = i_new[i] + lensi;
2471a2744918SBarry Smith       c->ilen[i]   = lensi;
247202834360SBarry Smith     }
24739566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
24749566063dSJacob Faibussowitsch     PetscCall(PetscFree2(lens, starts));
24753a40ed3dSBarry Smith   } else {
24769566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(iscol, &icol));
24779566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(oldcols, &smap));
24789566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(1 + nrows, &lens));
24794dcab191SBarry Smith     for (i = 0; i < ncols; i++) {
24806bdcaf15SBarry Smith       PetscCheck(icol[i] < oldcols, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Requesting column beyond largest column icol[%" PetscInt_FMT "] %" PetscInt_FMT " >= A->cmap->n %" PetscInt_FMT, i, icol[i], oldcols);
24814dcab191SBarry Smith       smap[icol[i]] = i + 1;
24824dcab191SBarry Smith     }
24834dcab191SBarry Smith 
248402834360SBarry Smith     /* determine lens of each row */
248502834360SBarry Smith     for (i = 0; i < nrows; i++) {
2486bfeeae90SHong Zhang       kstart  = ai[irow[i]];
248702834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
248802834360SBarry Smith       lens[i] = 0;
248902834360SBarry Smith       for (k = kstart; k < kend; k++) {
2490ad540459SPierre Jolivet         if (smap[aj[k]]) lens[i]++;
249102834360SBarry Smith       }
249202834360SBarry Smith     }
249317ab2063SBarry Smith     /* Create and fill new matrix */
2494a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2495ace3abfcSBarry Smith       PetscBool equal;
24960f5bd95cSBarry Smith 
249799141d43SSatish Balay       c = (Mat_SeqAIJ *)((*B)->data);
2498aed4548fSBarry Smith       PetscCheck((*B)->rmap->n == nrows && (*B)->cmap->n == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot reuse matrix. wrong size");
24999566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(c->ilen, lens, (*B)->rmap->n, &equal));
250028b400f6SJacob Faibussowitsch       PetscCheck(equal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot reuse matrix. wrong no of nonzeros");
25019566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(c->ilen, (*B)->rmap->n));
250208480c60SBarry Smith       C = *B;
25033a40ed3dSBarry Smith     } else {
25043bef6203SJed Brown       PetscInt rbs, cbs;
25059566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
25069566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, nrows, ncols, PETSC_DETERMINE, PETSC_DETERMINE));
25079566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(isrow, &rbs));
25089566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(iscol, &cbs));
25099566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizes(C, rbs, cbs));
25109566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, ((PetscObject)A)->type_name));
25119566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C, 0, lens));
251208480c60SBarry Smith     }
25139566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(A, &aa));
251499141d43SSatish Balay     c = (Mat_SeqAIJ *)(C->data);
251517ab2063SBarry Smith     for (i = 0; i < nrows; i++) {
251699141d43SSatish Balay       row      = irow[i];
2517bfeeae90SHong Zhang       kstart   = ai[row];
251899141d43SSatish Balay       kend     = kstart + a->ilen[row];
2519bfeeae90SHong Zhang       mat_i    = c->i[i];
252099141d43SSatish Balay       mat_j    = c->j + mat_i;
252199141d43SSatish Balay       mat_a    = c->a + mat_i;
252299141d43SSatish Balay       mat_ilen = c->ilen + i;
252317ab2063SBarry Smith       for (k = kstart; k < kend; k++) {
2524bfeeae90SHong Zhang         if ((tcol = smap[a->j[k]])) {
2525ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
25262e5835c6SStefano Zampini           *mat_a++ = aa[k];
252799141d43SSatish Balay           (*mat_ilen)++;
252817ab2063SBarry Smith         }
252917ab2063SBarry Smith       }
253017ab2063SBarry Smith     }
25319566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
253202834360SBarry Smith     /* Free work space */
25339566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(iscol, &icol));
25349566063dSJacob Faibussowitsch     PetscCall(PetscFree(smap));
25359566063dSJacob Faibussowitsch     PetscCall(PetscFree(lens));
2536cdc6f3adSToby Isaac     /* sort */
2537cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2538cdc6f3adSToby Isaac       PetscInt ilen;
2539cdc6f3adSToby Isaac 
2540cdc6f3adSToby Isaac       mat_i = c->i[i];
2541cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2542cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2543cdc6f3adSToby Isaac       ilen  = c->ilen[i];
25449566063dSJacob Faibussowitsch       PetscCall(PetscSortIntWithScalarArray(ilen, mat_j, mat_a));
2545cdc6f3adSToby Isaac     }
254602834360SBarry Smith   }
25478c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
25489566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU(C, A->boundtocpu));
2549305c6ccfSStefano Zampini #endif
25509566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
25519566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
255217ab2063SBarry Smith 
25539566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(isrow, &irow));
2554416022c9SBarry Smith   *B = C;
25553a40ed3dSBarry Smith   PetscFunctionReturn(0);
255617ab2063SBarry Smith }
255717ab2063SBarry Smith 
25589371c9d4SSatish Balay PetscErrorCode MatGetMultiProcBlock_SeqAIJ(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) {
255982d44351SHong Zhang   Mat B;
256082d44351SHong Zhang 
256182d44351SHong Zhang   PetscFunctionBegin;
2562c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
25639566063dSJacob Faibussowitsch     PetscCall(MatCreate(subComm, &B));
25649566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->n, mat->cmap->n));
25659566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, mat, mat));
25669566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQAIJ));
25679566063dSJacob Faibussowitsch     PetscCall(MatDuplicateNoCreate_SeqAIJ(B, mat, MAT_COPY_VALUES, PETSC_TRUE));
256882d44351SHong Zhang     *subMat = B;
2569c2d650bdSHong Zhang   } else {
25709566063dSJacob Faibussowitsch     PetscCall(MatCopy_SeqAIJ(mat, *subMat, SAME_NONZERO_PATTERN));
2571c2d650bdSHong Zhang   }
257282d44351SHong Zhang   PetscFunctionReturn(0);
257382d44351SHong Zhang }
257482d44351SHong Zhang 
25759371c9d4SSatish Balay PetscErrorCode MatILUFactor_SeqAIJ(Mat inA, IS row, IS col, const MatFactorInfo *info) {
257663b91edcSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)inA->data;
257763b91edcSBarry Smith   Mat         outA;
2578ace3abfcSBarry Smith   PetscBool   row_identity, col_identity;
257963b91edcSBarry Smith 
25803a40ed3dSBarry Smith   PetscFunctionBegin;
258108401ef6SPierre Jolivet   PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 supported for in-place ilu");
25821df811f5SHong Zhang 
25839566063dSJacob Faibussowitsch   PetscCall(ISIdentity(row, &row_identity));
25849566063dSJacob Faibussowitsch   PetscCall(ISIdentity(col, &col_identity));
2585a871dcd8SBarry Smith 
258663b91edcSBarry Smith   outA             = inA;
2587d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
25889566063dSJacob Faibussowitsch   PetscCall(PetscFree(inA->solvertype));
25899566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype));
25902205254eSKarl Rupp 
25919566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
25929566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
25932205254eSKarl Rupp 
2594c3122656SLisandro Dalcin   a->row = row;
25952205254eSKarl Rupp 
25969566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)col));
25979566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
25982205254eSKarl Rupp 
2599c3122656SLisandro Dalcin   a->col = col;
260063b91edcSBarry Smith 
260136db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
26029566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->icol));
26039566063dSJacob Faibussowitsch   PetscCall(ISInvertPermutation(col, PETSC_DECIDE, &a->icol));
26049566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)inA, (PetscObject)a->icol));
2605f0ec6fceSSatish Balay 
260694a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
26079566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(inA->rmap->n + 1, &a->solve_work));
26089566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n + 1) * sizeof(PetscScalar)));
260994a9d846SBarry Smith   }
261063b91edcSBarry Smith 
26119566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqAIJ(inA));
2612137fb511SHong Zhang   if (row_identity && col_identity) {
26139566063dSJacob Faibussowitsch     PetscCall(MatLUFactorNumeric_SeqAIJ_inplace(outA, inA, info));
2614137fb511SHong Zhang   } else {
26159566063dSJacob Faibussowitsch     PetscCall(MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA, inA, info));
2616137fb511SHong Zhang   }
26173a40ed3dSBarry Smith   PetscFunctionReturn(0);
2618a871dcd8SBarry Smith }
2619a871dcd8SBarry Smith 
26209371c9d4SSatish Balay PetscErrorCode MatScale_SeqAIJ(Mat inA, PetscScalar alpha) {
2621f0b747eeSBarry Smith   Mat_SeqAIJ  *a = (Mat_SeqAIJ *)inA->data;
2622dfa0f9e5SStefano Zampini   PetscScalar *v;
2623c5df96a5SBarry Smith   PetscBLASInt one = 1, bnz;
26243a40ed3dSBarry Smith 
26253a40ed3dSBarry Smith   PetscFunctionBegin;
26269566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(inA, &v));
26279566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(a->nz, &bnz));
2628792fecdfSBarry Smith   PetscCallBLAS("BLASscal", BLASscal_(&bnz, &alpha, v, &one));
26299566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(a->nz));
26309566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(inA, &v));
26319566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(inA));
26323a40ed3dSBarry Smith   PetscFunctionReturn(0);
2633f0b747eeSBarry Smith }
2634f0b747eeSBarry Smith 
26359371c9d4SSatish Balay PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj) {
263616b64355SHong Zhang   PetscInt i;
263716b64355SHong Zhang 
263816b64355SHong Zhang   PetscFunctionBegin;
263916b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
26409566063dSJacob Faibussowitsch     PetscCall(PetscFree4(submatj->sbuf1, submatj->ptr, submatj->tmp, submatj->ctr));
264116b64355SHong Zhang 
264248a46eb9SPierre Jolivet     for (i = 0; i < submatj->nrqr; ++i) PetscCall(PetscFree(submatj->sbuf2[i]));
26439566063dSJacob Faibussowitsch     PetscCall(PetscFree3(submatj->sbuf2, submatj->req_size, submatj->req_source1));
264416b64355SHong Zhang 
264516b64355SHong Zhang     if (submatj->rbuf1) {
26469566063dSJacob Faibussowitsch       PetscCall(PetscFree(submatj->rbuf1[0]));
26479566063dSJacob Faibussowitsch       PetscCall(PetscFree(submatj->rbuf1));
264816b64355SHong Zhang     }
264916b64355SHong Zhang 
265048a46eb9SPierre Jolivet     for (i = 0; i < submatj->nrqs; ++i) PetscCall(PetscFree(submatj->rbuf3[i]));
26519566063dSJacob Faibussowitsch     PetscCall(PetscFree3(submatj->req_source2, submatj->rbuf2, submatj->rbuf3));
26529566063dSJacob Faibussowitsch     PetscCall(PetscFree(submatj->pa));
265316b64355SHong Zhang   }
265416b64355SHong Zhang 
265516b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
26569566063dSJacob Faibussowitsch   PetscCall(PetscTableDestroy((PetscTable *)&submatj->rmap));
26579566063dSJacob Faibussowitsch   if (submatj->cmap_loc) PetscCall(PetscFree(submatj->cmap_loc));
26589566063dSJacob Faibussowitsch   PetscCall(PetscFree(submatj->rmap_loc));
265916b64355SHong Zhang #else
26609566063dSJacob Faibussowitsch   PetscCall(PetscFree(submatj->rmap));
266116b64355SHong Zhang #endif
266216b64355SHong Zhang 
266316b64355SHong Zhang   if (!submatj->allcolumns) {
266416b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
26659566063dSJacob Faibussowitsch     PetscCall(PetscTableDestroy((PetscTable *)&submatj->cmap));
266616b64355SHong Zhang #else
26679566063dSJacob Faibussowitsch     PetscCall(PetscFree(submatj->cmap));
266816b64355SHong Zhang #endif
266916b64355SHong Zhang   }
26709566063dSJacob Faibussowitsch   PetscCall(PetscFree(submatj->row2proc));
267116b64355SHong Zhang 
26729566063dSJacob Faibussowitsch   PetscCall(PetscFree(submatj));
267316b64355SHong Zhang   PetscFunctionReturn(0);
267416b64355SHong Zhang }
267516b64355SHong Zhang 
26769371c9d4SSatish Balay PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C) {
267716b64355SHong Zhang   Mat_SeqAIJ  *c       = (Mat_SeqAIJ *)C->data;
26785c39f6d9SHong Zhang   Mat_SubSppt *submatj = c->submatis1;
267916b64355SHong Zhang 
268016b64355SHong Zhang   PetscFunctionBegin;
26819566063dSJacob Faibussowitsch   PetscCall((*submatj->destroy)(C));
26829566063dSJacob Faibussowitsch   PetscCall(MatDestroySubMatrix_Private(submatj));
268316b64355SHong Zhang   PetscFunctionReturn(0);
268416b64355SHong Zhang }
268516b64355SHong Zhang 
268689a1a59bSHong Zhang /* Note this has code duplication with MatDestroySubMatrices_SeqBAIJ() */
26879371c9d4SSatish Balay PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n, Mat *mat[]) {
26882d033e1fSHong Zhang   PetscInt     i;
26890fb991dcSHong Zhang   Mat          C;
26900fb991dcSHong Zhang   Mat_SeqAIJ  *c;
26910fb991dcSHong Zhang   Mat_SubSppt *submatj;
26922d033e1fSHong Zhang 
26932d033e1fSHong Zhang   PetscFunctionBegin;
26942d033e1fSHong Zhang   for (i = 0; i < n; i++) {
26950fb991dcSHong Zhang     C       = (*mat)[i];
26960fb991dcSHong Zhang     c       = (Mat_SeqAIJ *)C->data;
26970fb991dcSHong Zhang     submatj = c->submatis1;
26982d033e1fSHong Zhang     if (submatj) {
2699682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
270026cc229bSBarry Smith         PetscCall(PetscFree(C->factorprefix));
27019566063dSJacob Faibussowitsch         PetscCall((*submatj->destroy)(C));
27029566063dSJacob Faibussowitsch         PetscCall(MatDestroySubMatrix_Private(submatj));
27039566063dSJacob Faibussowitsch         PetscCall(PetscFree(C->defaultvectype));
2704*3faff063SStefano Zampini         PetscCall(PetscFree(C->defaultrandtype));
27059566063dSJacob Faibussowitsch         PetscCall(PetscLayoutDestroy(&C->rmap));
27069566063dSJacob Faibussowitsch         PetscCall(PetscLayoutDestroy(&C->cmap));
27079566063dSJacob Faibussowitsch         PetscCall(PetscHeaderDestroy(&C));
2708682e4c99SStefano Zampini       }
27092d033e1fSHong Zhang     } else {
27109566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
27112d033e1fSHong Zhang     }
27122d033e1fSHong Zhang   }
271386e85357SHong Zhang 
271463a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
27159566063dSJacob Faibussowitsch   PetscCall(MatDestroySubMatrices_Dummy(n, mat));
271663a75b2aSHong Zhang 
27179566063dSJacob Faibussowitsch   PetscCall(PetscFree(*mat));
27182d033e1fSHong Zhang   PetscFunctionReturn(0);
27192d033e1fSHong Zhang }
27202d033e1fSHong Zhang 
27219371c9d4SSatish Balay PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[]) {
272297f1f81fSBarry Smith   PetscInt i;
2723cddf8d76SBarry Smith 
27243a40ed3dSBarry Smith   PetscFunctionBegin;
272548a46eb9SPierre Jolivet   if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n + 1, B));
2726cddf8d76SBarry Smith 
272748a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqAIJ(A, irow[i], icol[i], PETSC_DECIDE, scall, &(*B)[i]));
27283a40ed3dSBarry Smith   PetscFunctionReturn(0);
2729cddf8d76SBarry Smith }
2730cddf8d76SBarry Smith 
27319371c9d4SSatish Balay PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A, PetscInt is_max, IS is[], PetscInt ov) {
2732e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data;
27335d0c19d7SBarry Smith   PetscInt        row, i, j, k, l, m, n, *nidx, isz, val;
27345d0c19d7SBarry Smith   const PetscInt *idx;
273597f1f81fSBarry Smith   PetscInt        start, end, *ai, *aj;
2736f1af5d2fSBarry Smith   PetscBT         table;
2737bbd702dbSSatish Balay 
27383a40ed3dSBarry Smith   PetscFunctionBegin;
2739d0f46423SBarry Smith   m  = A->rmap->n;
2740e4d965acSSatish Balay   ai = a->i;
2741bfeeae90SHong Zhang   aj = a->j;
27428a047759SSatish Balay 
274308401ef6SPierre Jolivet   PetscCheck(ov >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "illegal negative overlap value used");
274406763907SSatish Balay 
27459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &nidx));
27469566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(m, &table));
274706763907SSatish Balay 
2748e4d965acSSatish Balay   for (i = 0; i < is_max; i++) {
2749b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2750e4d965acSSatish Balay     isz = 0;
27519566063dSJacob Faibussowitsch     PetscCall(PetscBTMemzero(m, table));
2752e4d965acSSatish Balay 
2753e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
27549566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is[i], &idx));
27559566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(is[i], &n));
2756e4d965acSSatish Balay 
2757dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2758e4d965acSSatish Balay     for (j = 0; j < n; ++j) {
27592205254eSKarl Rupp       if (!PetscBTLookupSet(table, idx[j])) nidx[isz++] = idx[j];
27604dcbc457SBarry Smith     }
27619566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is[i], &idx));
27629566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is[i]));
2763e4d965acSSatish Balay 
276404a348a9SBarry Smith     k = 0;
276504a348a9SBarry Smith     for (j = 0; j < ov; j++) { /* for each overlap */
276604a348a9SBarry Smith       n = isz;
276706763907SSatish Balay       for (; k < n; k++) { /* do only those rows in nidx[k], which are not done yet */
2768e4d965acSSatish Balay         row   = nidx[k];
2769e4d965acSSatish Balay         start = ai[row];
2770e4d965acSSatish Balay         end   = ai[row + 1];
277104a348a9SBarry Smith         for (l = start; l < end; l++) {
2772efb16452SHong Zhang           val = aj[l];
27732205254eSKarl Rupp           if (!PetscBTLookupSet(table, val)) nidx[isz++] = val;
2774e4d965acSSatish Balay         }
2775e4d965acSSatish Balay       }
2776e4d965acSSatish Balay     }
27779566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, isz, nidx, PETSC_COPY_VALUES, (is + i)));
2778e4d965acSSatish Balay   }
27799566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&table));
27809566063dSJacob Faibussowitsch   PetscCall(PetscFree(nidx));
27813a40ed3dSBarry Smith   PetscFunctionReturn(0);
27824dcbc457SBarry Smith }
278317ab2063SBarry Smith 
27840513a670SBarry Smith /* -------------------------------------------------------------- */
27859371c9d4SSatish Balay PetscErrorCode MatPermute_SeqAIJ(Mat A, IS rowp, IS colp, Mat *B) {
27860513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data;
27873b98c0a2SBarry Smith   PetscInt        i, nz = 0, m = A->rmap->n, n = A->cmap->n;
27885d0c19d7SBarry Smith   const PetscInt *row, *col;
27895d0c19d7SBarry Smith   PetscInt       *cnew, j, *lens;
279056cd22aeSBarry Smith   IS              icolp, irowp;
27910298fd71SBarry Smith   PetscInt       *cwork = NULL;
27920298fd71SBarry Smith   PetscScalar    *vwork = NULL;
27930513a670SBarry Smith 
27943a40ed3dSBarry Smith   PetscFunctionBegin;
27959566063dSJacob Faibussowitsch   PetscCall(ISInvertPermutation(rowp, PETSC_DECIDE, &irowp));
27969566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(irowp, &row));
27979566063dSJacob Faibussowitsch   PetscCall(ISInvertPermutation(colp, PETSC_DECIDE, &icolp));
27989566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(icolp, &col));
27990513a670SBarry Smith 
28000513a670SBarry Smith   /* determine lengths of permuted rows */
28019566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &lens));
28022205254eSKarl Rupp   for (i = 0; i < m; i++) lens[row[i]] = a->i[i + 1] - a->i[i];
28039566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B));
28049566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*B, m, n, m, n));
28059566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(*B, A, A));
28069566063dSJacob Faibussowitsch   PetscCall(MatSetType(*B, ((PetscObject)A)->type_name));
28079566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*B, 0, lens));
28089566063dSJacob Faibussowitsch   PetscCall(PetscFree(lens));
28090513a670SBarry Smith 
28109566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, &cnew));
28110513a670SBarry Smith   for (i = 0; i < m; i++) {
28129566063dSJacob Faibussowitsch     PetscCall(MatGetRow_SeqAIJ(A, i, &nz, &cwork, &vwork));
28132205254eSKarl Rupp     for (j = 0; j < nz; j++) cnew[j] = col[cwork[j]];
28149566063dSJacob Faibussowitsch     PetscCall(MatSetValues_SeqAIJ(*B, 1, &row[i], nz, cnew, vwork, INSERT_VALUES));
28159566063dSJacob Faibussowitsch     PetscCall(MatRestoreRow_SeqAIJ(A, i, &nz, &cwork, &vwork));
28160513a670SBarry Smith   }
28179566063dSJacob Faibussowitsch   PetscCall(PetscFree(cnew));
28182205254eSKarl Rupp 
28193c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
28202205254eSKarl Rupp 
28218c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
28229566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU(*B, A->boundtocpu));
28239fe5e383SStefano Zampini #endif
28249566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY));
28259566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY));
28269566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(irowp, &row));
28279566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(icolp, &col));
28289566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&irowp));
28299566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&icolp));
283048a46eb9SPierre Jolivet   if (rowp == colp) PetscCall(MatPropagateSymmetryOptions(A, *B));
28313a40ed3dSBarry Smith   PetscFunctionReturn(0);
28320513a670SBarry Smith }
28330513a670SBarry Smith 
28349371c9d4SSatish Balay PetscErrorCode MatCopy_SeqAIJ(Mat A, Mat B, MatStructure str) {
2835cb5b572fSBarry Smith   PetscFunctionBegin;
283633f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
283733f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
2838be6bf707SBarry Smith     Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
2839be6bf707SBarry Smith     Mat_SeqAIJ        *b = (Mat_SeqAIJ *)B->data;
28402e5835c6SStefano Zampini     const PetscScalar *aa;
2841be6bf707SBarry Smith 
28429566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(A, &aa));
284308401ef6SPierre Jolivet     PetscCheck(a->i[A->rmap->n] == b->i[B->rmap->n], PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of nonzeros in two matrices are different %" PetscInt_FMT " != %" PetscInt_FMT, a->i[A->rmap->n], b->i[B->rmap->n]);
28449566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(b->a, aa, a->i[A->rmap->n]));
28459566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)B));
28469566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
2847cb5b572fSBarry Smith   } else {
28489566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
2849cb5b572fSBarry Smith   }
2850cb5b572fSBarry Smith   PetscFunctionReturn(0);
2851cb5b572fSBarry Smith }
2852cb5b572fSBarry Smith 
28539371c9d4SSatish Balay PetscErrorCode MatSetUp_SeqAIJ(Mat A) {
2854273d9f13SBarry Smith   PetscFunctionBegin;
28559566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A, PETSC_DEFAULT, NULL));
2856273d9f13SBarry Smith   PetscFunctionReturn(0);
2857273d9f13SBarry Smith }
2858273d9f13SBarry Smith 
28599371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A, PetscScalar *array[]) {
28606c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
28616e111a19SKarl Rupp 
28626c0721eeSBarry Smith   PetscFunctionBegin;
28636c0721eeSBarry Smith   *array = a->a;
28646c0721eeSBarry Smith   PetscFunctionReturn(0);
28656c0721eeSBarry Smith }
28666c0721eeSBarry Smith 
28679371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A, PetscScalar *array[]) {
28686c0721eeSBarry Smith   PetscFunctionBegin;
2869f38c1e66SStefano Zampini   *array = NULL;
28706c0721eeSBarry Smith   PetscFunctionReturn(0);
28716c0721eeSBarry Smith }
2872273d9f13SBarry Smith 
28738229c054SShri Abhyankar /*
28748229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
28758229c054SShri Abhyankar    have different nonzero structure.
28768229c054SShri Abhyankar */
28779371c9d4SSatish Balay PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m, const PetscInt *xi, const PetscInt *xj, const PetscInt *yi, const PetscInt *yj, PetscInt *nnz) {
2878b264fe52SHong Zhang   PetscInt i, j, k, nzx, nzy;
2879ec7775f6SShri Abhyankar 
2880ec7775f6SShri Abhyankar   PetscFunctionBegin;
2881ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
2882ec7775f6SShri Abhyankar   for (i = 0; i < m; i++) {
2883b264fe52SHong Zhang     const PetscInt *xjj = xj + xi[i], *yjj = yj + yi[i];
2884b264fe52SHong Zhang     nzx    = xi[i + 1] - xi[i];
2885b264fe52SHong Zhang     nzy    = yi[i + 1] - yi[i];
28868af7cee1SJed Brown     nnz[i] = 0;
28878af7cee1SJed Brown     for (j = 0, k = 0; j < nzx; j++) {                  /* Point in X */
2888b264fe52SHong Zhang       for (; k < nzy && yjj[k] < xjj[j]; k++) nnz[i]++; /* Catch up to X */
2889b264fe52SHong Zhang       if (k < nzy && yjj[k] == xjj[j]) k++;             /* Skip duplicate */
28908af7cee1SJed Brown       nnz[i]++;
28918af7cee1SJed Brown     }
28928af7cee1SJed Brown     for (; k < nzy; k++) nnz[i]++;
2893ec7775f6SShri Abhyankar   }
2894ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
2895ec7775f6SShri Abhyankar }
2896ec7775f6SShri Abhyankar 
28979371c9d4SSatish Balay PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y, Mat X, PetscInt *nnz) {
2898b264fe52SHong Zhang   PetscInt    m = Y->rmap->N;
2899b264fe52SHong Zhang   Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data;
2900b264fe52SHong Zhang   Mat_SeqAIJ *y = (Mat_SeqAIJ *)Y->data;
2901b264fe52SHong Zhang 
2902b264fe52SHong Zhang   PetscFunctionBegin;
2903b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
29049566063dSJacob Faibussowitsch   PetscCall(MatAXPYGetPreallocation_SeqX_private(m, x->i, x->j, y->i, y->j, nnz));
2905b264fe52SHong Zhang   PetscFunctionReturn(0);
2906b264fe52SHong Zhang }
2907b264fe52SHong Zhang 
29089371c9d4SSatish Balay PetscErrorCode MatAXPY_SeqAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str) {
2909ac90fabeSBarry Smith   Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data, *y = (Mat_SeqAIJ *)Y->data;
2910ac90fabeSBarry Smith 
2911ac90fabeSBarry Smith   PetscFunctionBegin;
2912134adf20SPierre Jolivet   if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) {
2913134adf20SPierre Jolivet     PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE;
2914134adf20SPierre Jolivet     if (e) {
29159566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(x->i, y->i, Y->rmap->n + 1, &e));
291681fa06acSBarry Smith       if (e) {
29179566063dSJacob Faibussowitsch         PetscCall(PetscArraycmp(x->j, y->j, y->nz, &e));
2918134adf20SPierre Jolivet         if (e) str = SAME_NONZERO_PATTERN;
291981fa06acSBarry Smith       }
292081fa06acSBarry Smith     }
292154c59aa7SJacob Faibussowitsch     if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN");
292281fa06acSBarry Smith   }
2923ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
29242e5835c6SStefano Zampini     const PetscScalar *xa;
29252e5835c6SStefano Zampini     PetscScalar       *ya, alpha = a;
292681fa06acSBarry Smith     PetscBLASInt       one = 1, bnz;
292781fa06acSBarry Smith 
29289566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(x->nz, &bnz));
29299566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(Y, &ya));
29309566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(X, &xa));
2931792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, xa, &one, ya, &one));
29329566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(X, &xa));
29339566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArray(Y, &ya));
29349566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * bnz));
29359566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJInvalidateDiagonal(Y));
29369566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)Y));
2937ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
29389566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
2939ac90fabeSBarry Smith   } else {
29408229c054SShri Abhyankar     Mat       B;
29418229c054SShri Abhyankar     PetscInt *nnz;
29429566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Y->rmap->N, &nnz));
29439566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B));
29449566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name));
29459566063dSJacob Faibussowitsch     PetscCall(MatSetLayouts(B, Y->rmap, Y->cmap));
29469566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, ((PetscObject)Y)->type_name));
29479566063dSJacob Faibussowitsch     PetscCall(MatAXPYGetPreallocation_SeqAIJ(Y, X, nnz));
29489566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz));
29499566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
29509566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
29519bb234a9SBarry Smith     PetscCall(MatSeqAIJCheckInode(Y));
29529566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz));
2953ac90fabeSBarry Smith   }
2954ac90fabeSBarry Smith   PetscFunctionReturn(0);
2955ac90fabeSBarry Smith }
2956ac90fabeSBarry Smith 
29579371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat) {
2958354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
2959354c94deSBarry Smith   Mat_SeqAIJ  *aij = (Mat_SeqAIJ *)mat->data;
2960354c94deSBarry Smith   PetscInt     i, nz;
2961354c94deSBarry Smith   PetscScalar *a;
2962354c94deSBarry Smith 
2963354c94deSBarry Smith   PetscFunctionBegin;
2964354c94deSBarry Smith   nz = aij->nz;
29659566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(mat, &a));
29662205254eSKarl Rupp   for (i = 0; i < nz; i++) a[i] = PetscConj(a[i]);
29679566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(mat, &a));
2968354c94deSBarry Smith #else
2969354c94deSBarry Smith   PetscFunctionBegin;
2970354c94deSBarry Smith #endif
2971354c94deSBarry Smith   PetscFunctionReturn(0);
2972354c94deSBarry Smith }
2973354c94deSBarry Smith 
29749371c9d4SSatish Balay PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[]) {
2975e34fafa9SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
2976d0f46423SBarry Smith   PetscInt         i, j, m = A->rmap->n, *ai, *aj, ncols, n;
2977e34fafa9SBarry Smith   PetscReal        atmp;
2978985db425SBarry Smith   PetscScalar     *x;
2979ce496241SStefano Zampini   const MatScalar *aa, *av;
2980e34fafa9SBarry Smith 
2981e34fafa9SBarry Smith   PetscFunctionBegin;
298228b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29839566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
2984ce496241SStefano Zampini   aa = av;
2985e34fafa9SBarry Smith   ai = a->i;
2986e34fafa9SBarry Smith   aj = a->j;
2987e34fafa9SBarry Smith 
29889566063dSJacob Faibussowitsch   PetscCall(VecSet(v, 0.0));
29899566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v, &x));
29909566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &n));
299108401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2992e34fafa9SBarry Smith   for (i = 0; i < m; i++) {
29939371c9d4SSatish Balay     ncols = ai[1] - ai[0];
29949371c9d4SSatish Balay     ai++;
2995e34fafa9SBarry Smith     for (j = 0; j < ncols; j++) {
2996985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
29979371c9d4SSatish Balay       if (PetscAbsScalar(x[i]) < atmp) {
29989371c9d4SSatish Balay         x[i] = atmp;
29999371c9d4SSatish Balay         if (idx) idx[i] = *aj;
30009371c9d4SSatish Balay       }
30019371c9d4SSatish Balay       aa++;
30029371c9d4SSatish Balay       aj++;
3003985db425SBarry Smith     }
3004985db425SBarry Smith   }
30059566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v, &x));
30069566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
3007985db425SBarry Smith   PetscFunctionReturn(0);
3008985db425SBarry Smith }
3009985db425SBarry Smith 
30109371c9d4SSatish Balay PetscErrorCode MatGetRowMax_SeqAIJ(Mat A, Vec v, PetscInt idx[]) {
3011985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
3012d0f46423SBarry Smith   PetscInt         i, j, m = A->rmap->n, *ai, *aj, ncols, n;
3013985db425SBarry Smith   PetscScalar     *x;
3014ce496241SStefano Zampini   const MatScalar *aa, *av;
3015985db425SBarry Smith 
3016985db425SBarry Smith   PetscFunctionBegin;
301728b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
30189566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
3019ce496241SStefano Zampini   aa = av;
3020985db425SBarry Smith   ai = a->i;
3021985db425SBarry Smith   aj = a->j;
3022985db425SBarry Smith 
30239566063dSJacob Faibussowitsch   PetscCall(VecSet(v, 0.0));
30249566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v, &x));
30259566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &n));
302608401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
3027985db425SBarry Smith   for (i = 0; i < m; i++) {
30289371c9d4SSatish Balay     ncols = ai[1] - ai[0];
30299371c9d4SSatish Balay     ai++;
3030d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
30319371c9d4SSatish Balay       x[i] = *aa;
30329371c9d4SSatish Balay       if (idx) idx[i] = 0;
3033985db425SBarry Smith     } else { /* row is sparse so already KNOW maximum is 0.0 or higher */
3034985db425SBarry Smith       x[i] = 0.0;
3035985db425SBarry Smith       if (idx) {
3036985db425SBarry Smith         for (j = 0; j < ncols; j++) { /* find first implicit 0.0 in the row */
3037985db425SBarry Smith           if (aj[j] > j) {
3038985db425SBarry Smith             idx[i] = j;
3039985db425SBarry Smith             break;
3040985db425SBarry Smith           }
3041985db425SBarry Smith         }
30421a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
30431a254869SHong Zhang         if (j == ncols && j < A->cmap->n) idx[i] = j;
3044985db425SBarry Smith       }
3045985db425SBarry Smith     }
3046985db425SBarry Smith     for (j = 0; j < ncols; j++) {
30479371c9d4SSatish Balay       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {
30489371c9d4SSatish Balay         x[i] = *aa;
30499371c9d4SSatish Balay         if (idx) idx[i] = *aj;
30509371c9d4SSatish Balay       }
30519371c9d4SSatish Balay       aa++;
30529371c9d4SSatish Balay       aj++;
3053985db425SBarry Smith     }
3054985db425SBarry Smith   }
30559566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v, &x));
30569566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
3057985db425SBarry Smith   PetscFunctionReturn(0);
3058985db425SBarry Smith }
3059985db425SBarry Smith 
30609371c9d4SSatish Balay PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[]) {
3061c87e5d42SMatthew Knepley   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
3062c87e5d42SMatthew Knepley   PetscInt         i, j, m = A->rmap->n, *ai, *aj, ncols, n;
3063ce496241SStefano Zampini   PetscScalar     *x;
3064ce496241SStefano Zampini   const MatScalar *aa, *av;
3065c87e5d42SMatthew Knepley 
3066c87e5d42SMatthew Knepley   PetscFunctionBegin;
30679566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
3068ce496241SStefano Zampini   aa = av;
3069c87e5d42SMatthew Knepley   ai = a->i;
3070c87e5d42SMatthew Knepley   aj = a->j;
3071c87e5d42SMatthew Knepley 
30729566063dSJacob Faibussowitsch   PetscCall(VecSet(v, 0.0));
30739566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v, &x));
30749566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &n));
307508401ef6SPierre Jolivet   PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n);
3076c87e5d42SMatthew Knepley   for (i = 0; i < m; i++) {
30779371c9d4SSatish Balay     ncols = ai[1] - ai[0];
30789371c9d4SSatish Balay     ai++;
3079f07e67edSHong Zhang     if (ncols == A->cmap->n) { /* row is dense */
30809371c9d4SSatish Balay       x[i] = *aa;
30819371c9d4SSatish Balay       if (idx) idx[i] = 0;
3082f07e67edSHong Zhang     } else { /* row is sparse so already KNOW minimum is 0.0 or higher */
3083f07e67edSHong Zhang       x[i] = 0.0;
3084f07e67edSHong Zhang       if (idx) { /* find first implicit 0.0 in the row */
3085289a08f5SMatthew Knepley         for (j = 0; j < ncols; j++) {
3086f07e67edSHong Zhang           if (aj[j] > j) {
3087f07e67edSHong Zhang             idx[i] = j;
30882205254eSKarl Rupp             break;
30892205254eSKarl Rupp           }
3090289a08f5SMatthew Knepley         }
3091f07e67edSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3092f07e67edSHong Zhang         if (j == ncols && j < A->cmap->n) idx[i] = j;
3093f07e67edSHong Zhang       }
3094289a08f5SMatthew Knepley     }
3095c87e5d42SMatthew Knepley     for (j = 0; j < ncols; j++) {
30969371c9d4SSatish Balay       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {
30979371c9d4SSatish Balay         x[i] = *aa;
30989371c9d4SSatish Balay         if (idx) idx[i] = *aj;
30999371c9d4SSatish Balay       }
31009371c9d4SSatish Balay       aa++;
31019371c9d4SSatish Balay       aj++;
3102c87e5d42SMatthew Knepley     }
3103c87e5d42SMatthew Knepley   }
31049566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v, &x));
31059566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
3106c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3107c87e5d42SMatthew Knepley }
3108c87e5d42SMatthew Knepley 
31099371c9d4SSatish Balay PetscErrorCode MatGetRowMin_SeqAIJ(Mat A, Vec v, PetscInt idx[]) {
3110985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
3111d9ca1df4SBarry Smith   PetscInt         i, j, m = A->rmap->n, ncols, n;
3112d9ca1df4SBarry Smith   const PetscInt  *ai, *aj;
3113985db425SBarry Smith   PetscScalar     *x;
3114ce496241SStefano Zampini   const MatScalar *aa, *av;
3115985db425SBarry Smith 
3116985db425SBarry Smith   PetscFunctionBegin;
311728b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
31189566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
3119ce496241SStefano Zampini   aa = av;
3120985db425SBarry Smith   ai = a->i;
3121985db425SBarry Smith   aj = a->j;
3122985db425SBarry Smith 
31239566063dSJacob Faibussowitsch   PetscCall(VecSet(v, 0.0));
31249566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v, &x));
31259566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &n));
312608401ef6SPierre Jolivet   PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
3127985db425SBarry Smith   for (i = 0; i < m; i++) {
31289371c9d4SSatish Balay     ncols = ai[1] - ai[0];
31299371c9d4SSatish Balay     ai++;
3130d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
31319371c9d4SSatish Balay       x[i] = *aa;
31329371c9d4SSatish Balay       if (idx) idx[i] = 0;
3133985db425SBarry Smith     } else { /* row is sparse so already KNOW minimum is 0.0 or lower */
3134985db425SBarry Smith       x[i] = 0.0;
3135985db425SBarry Smith       if (idx) { /* find first implicit 0.0 in the row */
3136985db425SBarry Smith         for (j = 0; j < ncols; j++) {
3137985db425SBarry Smith           if (aj[j] > j) {
3138985db425SBarry Smith             idx[i] = j;
3139985db425SBarry Smith             break;
3140985db425SBarry Smith           }
3141985db425SBarry Smith         }
3142fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3143fa213d2fSHong Zhang         if (j == ncols && j < A->cmap->n) idx[i] = j;
3144985db425SBarry Smith       }
3145985db425SBarry Smith     }
3146985db425SBarry Smith     for (j = 0; j < ncols; j++) {
31479371c9d4SSatish Balay       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {
31489371c9d4SSatish Balay         x[i] = *aa;
31499371c9d4SSatish Balay         if (idx) idx[i] = *aj;
31509371c9d4SSatish Balay       }
31519371c9d4SSatish Balay       aa++;
31529371c9d4SSatish Balay       aj++;
3153e34fafa9SBarry Smith     }
3154e34fafa9SBarry Smith   }
31559566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v, &x));
31569566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
3157e34fafa9SBarry Smith   PetscFunctionReturn(0);
3158e34fafa9SBarry Smith }
3159bbead8a2SBarry Smith 
31609371c9d4SSatish Balay PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A, const PetscScalar **values) {
3161bbead8a2SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data;
316233d57670SJed Brown   PetscInt        i, bs = PetscAbs(A->rmap->bs), mbs = A->rmap->n / bs, ipvt[5], bs2 = bs * bs, *v_pivots, ij[7], *IJ, j;
3163bbead8a2SBarry Smith   MatScalar      *diag, work[25], *v_work;
31640da83c2eSBarry Smith   const PetscReal shift = 0.0;
31651a9391e3SHong Zhang   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
3166bbead8a2SBarry Smith 
3167bbead8a2SBarry Smith   PetscFunctionBegin;
3168a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
31694a0d0026SBarry Smith   if (a->ibdiagvalid) {
31704a0d0026SBarry Smith     if (values) *values = a->ibdiag;
31714a0d0026SBarry Smith     PetscFunctionReturn(0);
31724a0d0026SBarry Smith   }
31739566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqAIJ(A));
3174bbead8a2SBarry Smith   if (!a->ibdiag) {
31759566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(bs2 * mbs, &a->ibdiag));
31769566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A, bs2 * mbs * sizeof(PetscScalar)));
3177bbead8a2SBarry Smith   }
3178bbead8a2SBarry Smith   diag = a->ibdiag;
3179bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3180bbead8a2SBarry Smith   /* factor and invert each block */
3181bbead8a2SBarry Smith   switch (bs) {
3182bbead8a2SBarry Smith   case 1:
3183bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
31849566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, 1, &i, 1, &i, diag + i));
3185ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3186ec1892c8SHong Zhang         if (allowzeropivot) {
31877b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
31887b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
31897b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
31909566063dSJacob Faibussowitsch           PetscCall(PetscInfo(A, "Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n", i, (double)PetscAbsScalar(diag[i]), (double)PETSC_MACHINE_EPSILON));
319198921bdaSJacob Faibussowitsch         } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g", i, (double)PetscAbsScalar(diag[i]), (double)PETSC_MACHINE_EPSILON);
3192ec1892c8SHong Zhang       }
3193bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3194bbead8a2SBarry Smith     }
3195bbead8a2SBarry Smith     break;
3196bbead8a2SBarry Smith   case 2:
3197bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
31989371c9d4SSatish Balay       ij[0] = 2 * i;
31999371c9d4SSatish Balay       ij[1] = 2 * i + 1;
32009566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, 2, ij, 2, ij, diag));
32019566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected));
32027b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
32039566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_2(diag));
3204bbead8a2SBarry Smith       diag += 4;
3205bbead8a2SBarry Smith     }
3206bbead8a2SBarry Smith     break;
3207bbead8a2SBarry Smith   case 3:
3208bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
32099371c9d4SSatish Balay       ij[0] = 3 * i;
32109371c9d4SSatish Balay       ij[1] = 3 * i + 1;
32119371c9d4SSatish Balay       ij[2] = 3 * i + 2;
32129566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, 3, ij, 3, ij, diag));
32139566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected));
32147b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
32159566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_3(diag));
3216bbead8a2SBarry Smith       diag += 9;
3217bbead8a2SBarry Smith     }
3218bbead8a2SBarry Smith     break;
3219bbead8a2SBarry Smith   case 4:
3220bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
32219371c9d4SSatish Balay       ij[0] = 4 * i;
32229371c9d4SSatish Balay       ij[1] = 4 * i + 1;
32239371c9d4SSatish Balay       ij[2] = 4 * i + 2;
32249371c9d4SSatish Balay       ij[3] = 4 * i + 3;
32259566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, 4, ij, 4, ij, diag));
32269566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected));
32277b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
32289566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_4(diag));
3229bbead8a2SBarry Smith       diag += 16;
3230bbead8a2SBarry Smith     }
3231bbead8a2SBarry Smith     break;
3232bbead8a2SBarry Smith   case 5:
3233bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
32349371c9d4SSatish Balay       ij[0] = 5 * i;
32359371c9d4SSatish Balay       ij[1] = 5 * i + 1;
32369371c9d4SSatish Balay       ij[2] = 5 * i + 2;
32379371c9d4SSatish Balay       ij[3] = 5 * i + 3;
32389371c9d4SSatish Balay       ij[4] = 5 * i + 4;
32399566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, 5, ij, 5, ij, diag));
32409566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
32417b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
32429566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_5(diag));
3243bbead8a2SBarry Smith       diag += 25;
3244bbead8a2SBarry Smith     }
3245bbead8a2SBarry Smith     break;
3246bbead8a2SBarry Smith   case 6:
3247bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
32489371c9d4SSatish Balay       ij[0] = 6 * i;
32499371c9d4SSatish Balay       ij[1] = 6 * i + 1;
32509371c9d4SSatish Balay       ij[2] = 6 * i + 2;
32519371c9d4SSatish Balay       ij[3] = 6 * i + 3;
32529371c9d4SSatish Balay       ij[4] = 6 * i + 4;
32539371c9d4SSatish Balay       ij[5] = 6 * i + 5;
32549566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, 6, ij, 6, ij, diag));
32559566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected));
32567b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
32579566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_6(diag));
3258bbead8a2SBarry Smith       diag += 36;
3259bbead8a2SBarry Smith     }
3260bbead8a2SBarry Smith     break;
3261bbead8a2SBarry Smith   case 7:
3262bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
32639371c9d4SSatish Balay       ij[0] = 7 * i;
32649371c9d4SSatish Balay       ij[1] = 7 * i + 1;
32659371c9d4SSatish Balay       ij[2] = 7 * i + 2;
32669371c9d4SSatish Balay       ij[3] = 7 * i + 3;
32679371c9d4SSatish Balay       ij[4] = 7 * i + 4;
32689371c9d4SSatish Balay       ij[5] = 7 * i + 5;
32699371c9d4SSatish Balay       ij[5] = 7 * i + 6;
32709566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, 7, ij, 7, ij, diag));
32719566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected));
32727b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
32739566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_7(diag));
3274bbead8a2SBarry Smith       diag += 49;
3275bbead8a2SBarry Smith     }
3276bbead8a2SBarry Smith     break;
3277bbead8a2SBarry Smith   default:
32789566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(bs, &v_work, bs, &v_pivots, bs, &IJ));
3279bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
3280ad540459SPierre Jolivet       for (j = 0; j < bs; j++) IJ[j] = bs * i + j;
32819566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, bs, IJ, bs, IJ, diag));
32829566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A(bs, diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
32837b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
32849566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_N(diag, bs));
3285bbead8a2SBarry Smith       diag += bs2;
3286bbead8a2SBarry Smith     }
32879566063dSJacob Faibussowitsch     PetscCall(PetscFree3(v_work, v_pivots, IJ));
3288bbead8a2SBarry Smith   }
3289bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3290bbead8a2SBarry Smith   PetscFunctionReturn(0);
3291bbead8a2SBarry Smith }
3292bbead8a2SBarry Smith 
32939371c9d4SSatish Balay static PetscErrorCode MatSetRandom_SeqAIJ(Mat x, PetscRandom rctx) {
329473a71a0fSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data;
3295fff043a9SJunchao Zhang   PetscScalar a, *aa;
329673a71a0fSBarry Smith   PetscInt    m, n, i, j, col;
329773a71a0fSBarry Smith 
329873a71a0fSBarry Smith   PetscFunctionBegin;
329973a71a0fSBarry Smith   if (!x->assembled) {
33009566063dSJacob Faibussowitsch     PetscCall(MatGetSize(x, &m, &n));
330173a71a0fSBarry Smith     for (i = 0; i < m; i++) {
330273a71a0fSBarry Smith       for (j = 0; j < aij->imax[i]; j++) {
33039566063dSJacob Faibussowitsch         PetscCall(PetscRandomGetValue(rctx, &a));
330473a71a0fSBarry Smith         col = (PetscInt)(n * PetscRealPart(a));
33059566063dSJacob Faibussowitsch         PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES));
330673a71a0fSBarry Smith       }
330773a71a0fSBarry Smith     }
3308e2ce353bSJunchao Zhang   } else {
33099566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayWrite(x, &aa));
33109566063dSJacob Faibussowitsch     for (i = 0; i < aij->nz; i++) PetscCall(PetscRandomGetValue(rctx, aa + i));
33119566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayWrite(x, &aa));
3312e2ce353bSJunchao Zhang   }
33139566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
33149566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
331573a71a0fSBarry Smith   PetscFunctionReturn(0);
331673a71a0fSBarry Smith }
331773a71a0fSBarry Smith 
3318679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
33199371c9d4SSatish Balay PetscErrorCode MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x, PetscInt low, PetscInt high, PetscRandom rctx) {
3320679944adSJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data;
3321679944adSJunchao Zhang   PetscScalar a;
3322679944adSJunchao Zhang   PetscInt    m, n, i, j, col, nskip;
3323679944adSJunchao Zhang 
3324679944adSJunchao Zhang   PetscFunctionBegin;
3325679944adSJunchao Zhang   nskip = high - low;
33269566063dSJacob Faibussowitsch   PetscCall(MatGetSize(x, &m, &n));
3327679944adSJunchao Zhang   n -= nskip; /* shrink number of columns where nonzeros can be set */
3328679944adSJunchao Zhang   for (i = 0; i < m; i++) {
3329679944adSJunchao Zhang     for (j = 0; j < aij->imax[i]; j++) {
33309566063dSJacob Faibussowitsch       PetscCall(PetscRandomGetValue(rctx, &a));
3331679944adSJunchao Zhang       col = (PetscInt)(n * PetscRealPart(a));
3332679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
33339566063dSJacob Faibussowitsch       PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES));
3334679944adSJunchao Zhang     }
3335e2ce353bSJunchao Zhang   }
33369566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
33379566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
3338679944adSJunchao Zhang   PetscFunctionReturn(0);
3339679944adSJunchao Zhang }
3340679944adSJunchao Zhang 
3341682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
33420a6ffc59SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ,
3343cb5b572fSBarry Smith                                        MatGetRow_SeqAIJ,
3344cb5b572fSBarry Smith                                        MatRestoreRow_SeqAIJ,
3345cb5b572fSBarry Smith                                        MatMult_SeqAIJ,
334697304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqAIJ,
33477c922b88SBarry Smith                                        MatMultTranspose_SeqAIJ,
33487c922b88SBarry Smith                                        MatMultTransposeAdd_SeqAIJ,
3349f4259b30SLisandro Dalcin                                        NULL,
3350f4259b30SLisandro Dalcin                                        NULL,
3351f4259b30SLisandro Dalcin                                        NULL,
3352f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
3353cb5b572fSBarry Smith                                        MatLUFactor_SeqAIJ,
3354f4259b30SLisandro Dalcin                                        NULL,
335541f059aeSBarry Smith                                        MatSOR_SeqAIJ,
335691e9d3e2SHong Zhang                                        MatTranspose_SeqAIJ,
335797304618SKris Buschelman                                        /*1 5*/ MatGetInfo_SeqAIJ,
3358cb5b572fSBarry Smith                                        MatEqual_SeqAIJ,
3359cb5b572fSBarry Smith                                        MatGetDiagonal_SeqAIJ,
3360cb5b572fSBarry Smith                                        MatDiagonalScale_SeqAIJ,
3361cb5b572fSBarry Smith                                        MatNorm_SeqAIJ,
3362f4259b30SLisandro Dalcin                                        /* 20*/ NULL,
3363cb5b572fSBarry Smith                                        MatAssemblyEnd_SeqAIJ,
3364cb5b572fSBarry Smith                                        MatSetOption_SeqAIJ,
3365cb5b572fSBarry Smith                                        MatZeroEntries_SeqAIJ,
3366d519adbfSMatthew Knepley                                        /* 24*/ MatZeroRows_SeqAIJ,
3367f4259b30SLisandro Dalcin                                        NULL,
3368f4259b30SLisandro Dalcin                                        NULL,
3369f4259b30SLisandro Dalcin                                        NULL,
3370f4259b30SLisandro Dalcin                                        NULL,
33714994cf47SJed Brown                                        /* 29*/ MatSetUp_SeqAIJ,
3372f4259b30SLisandro Dalcin                                        NULL,
3373f4259b30SLisandro Dalcin                                        NULL,
3374f4259b30SLisandro Dalcin                                        NULL,
3375f4259b30SLisandro Dalcin                                        NULL,
3376d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqAIJ,
3377f4259b30SLisandro Dalcin                                        NULL,
3378f4259b30SLisandro Dalcin                                        NULL,
3379cb5b572fSBarry Smith                                        MatILUFactor_SeqAIJ,
3380f4259b30SLisandro Dalcin                                        NULL,
3381d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqAIJ,
33827dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqAIJ,
3383cb5b572fSBarry Smith                                        MatIncreaseOverlap_SeqAIJ,
3384cb5b572fSBarry Smith                                        MatGetValues_SeqAIJ,
3385cb5b572fSBarry Smith                                        MatCopy_SeqAIJ,
3386d519adbfSMatthew Knepley                                        /* 44*/ MatGetRowMax_SeqAIJ,
3387cb5b572fSBarry Smith                                        MatScale_SeqAIJ,
33887d68702bSBarry Smith                                        MatShift_SeqAIJ,
338979299369SBarry Smith                                        MatDiagonalSet_SeqAIJ,
33906e169961SBarry Smith                                        MatZeroRowsColumns_SeqAIJ,
339173a71a0fSBarry Smith                                        /* 49*/ MatSetRandom_SeqAIJ,
33923b2fbd54SBarry Smith                                        MatGetRowIJ_SeqAIJ,
33933b2fbd54SBarry Smith                                        MatRestoreRowIJ_SeqAIJ,
33943b2fbd54SBarry Smith                                        MatGetColumnIJ_SeqAIJ,
3395a93ec695SBarry Smith                                        MatRestoreColumnIJ_SeqAIJ,
339693dfae19SHong Zhang                                        /* 54*/ MatFDColoringCreate_SeqXAIJ,
3397f4259b30SLisandro Dalcin                                        NULL,
3398f4259b30SLisandro Dalcin                                        NULL,
3399cda55fadSBarry Smith                                        MatPermute_SeqAIJ,
3400f4259b30SLisandro Dalcin                                        NULL,
3401f4259b30SLisandro Dalcin                                        /* 59*/ NULL,
3402b9b97703SBarry Smith                                        MatDestroy_SeqAIJ,
3403b9b97703SBarry Smith                                        MatView_SeqAIJ,
3404f4259b30SLisandro Dalcin                                        NULL,
3405f4259b30SLisandro Dalcin                                        NULL,
3406f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
3407321b30b9SSatish Balay                                        MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3408f4259b30SLisandro Dalcin                                        NULL,
3409f4259b30SLisandro Dalcin                                        NULL,
3410f4259b30SLisandro Dalcin                                        NULL,
3411d519adbfSMatthew Knepley                                        /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3412c87e5d42SMatthew Knepley                                        MatGetRowMinAbs_SeqAIJ,
3413f4259b30SLisandro Dalcin                                        NULL,
3414f4259b30SLisandro Dalcin                                        NULL,
3415f4259b30SLisandro Dalcin                                        NULL,
3416f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
34173acb8795SBarry Smith                                        MatFDColoringApply_AIJ,
3418f4259b30SLisandro Dalcin                                        NULL,
3419f4259b30SLisandro Dalcin                                        NULL,
3420f4259b30SLisandro Dalcin                                        NULL,
34216ce1633cSBarry Smith                                        /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3422f4259b30SLisandro Dalcin                                        NULL,
3423f4259b30SLisandro Dalcin                                        NULL,
3424f4259b30SLisandro Dalcin                                        NULL,
3425bc011b1eSHong Zhang                                        MatLoad_SeqAIJ,
3426d519adbfSMatthew Knepley                                        /* 84*/ MatIsSymmetric_SeqAIJ,
34271cbb95d3SBarry Smith                                        MatIsHermitian_SeqAIJ,
3428f4259b30SLisandro Dalcin                                        NULL,
3429f4259b30SLisandro Dalcin                                        NULL,
3430f4259b30SLisandro Dalcin                                        NULL,
3431f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
3432f4259b30SLisandro Dalcin                                        NULL,
343326be0446SHong Zhang                                        MatMatMultNumeric_SeqAIJ_SeqAIJ,
3434f4259b30SLisandro Dalcin                                        NULL,
3435f4259b30SLisandro Dalcin                                        NULL,
34368fa4b5a6SHong Zhang                                        /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3437f4259b30SLisandro Dalcin                                        NULL,
3438f4259b30SLisandro Dalcin                                        NULL,
34396fc122caSHong Zhang                                        MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3440f4259b30SLisandro Dalcin                                        NULL,
34414222ddf1SHong Zhang                                        /* 99*/ MatProductSetFromOptions_SeqAIJ,
3442f4259b30SLisandro Dalcin                                        NULL,
3443f4259b30SLisandro Dalcin                                        NULL,
344487d4246cSBarry Smith                                        MatConjugate_SeqAIJ,
3445f4259b30SLisandro Dalcin                                        NULL,
3446d519adbfSMatthew Knepley                                        /*104*/ MatSetValuesRow_SeqAIJ,
344799cafbc1SBarry Smith                                        MatRealPart_SeqAIJ,
3448f5edf698SHong Zhang                                        MatImaginaryPart_SeqAIJ,
3449f4259b30SLisandro Dalcin                                        NULL,
3450f4259b30SLisandro Dalcin                                        NULL,
3451cbd44569SHong Zhang                                        /*109*/ MatMatSolve_SeqAIJ,
3452f4259b30SLisandro Dalcin                                        NULL,
34532af78befSBarry Smith                                        MatGetRowMin_SeqAIJ,
3454f4259b30SLisandro Dalcin                                        NULL,
3455599ef60dSHong Zhang                                        MatMissingDiagonal_SeqAIJ,
3456f4259b30SLisandro Dalcin                                        /*114*/ NULL,
3457f4259b30SLisandro Dalcin                                        NULL,
3458f4259b30SLisandro Dalcin                                        NULL,
3459f4259b30SLisandro Dalcin                                        NULL,
3460f4259b30SLisandro Dalcin                                        NULL,
3461f4259b30SLisandro Dalcin                                        /*119*/ NULL,
3462f4259b30SLisandro Dalcin                                        NULL,
3463f4259b30SLisandro Dalcin                                        NULL,
3464f4259b30SLisandro Dalcin                                        NULL,
3465b3a44c85SBarry Smith                                        MatGetMultiProcBlock_SeqAIJ,
34660716a85fSBarry Smith                                        /*124*/ MatFindNonzeroRows_SeqAIJ,
3467a873a8cdSSam Reynolds                                        MatGetColumnReductions_SeqAIJ,
346837868618SMatthew G Knepley                                        MatInvertBlockDiagonal_SeqAIJ,
34690da83c2eSBarry Smith                                        MatInvertVariableBlockDiagonal_SeqAIJ,
3470f4259b30SLisandro Dalcin                                        NULL,
3471f4259b30SLisandro Dalcin                                        /*129*/ NULL,
3472f4259b30SLisandro Dalcin                                        NULL,
3473f4259b30SLisandro Dalcin                                        NULL,
347475648e8dSHong Zhang                                        MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3475b9af6bddSHong Zhang                                        MatTransposeColoringCreate_SeqAIJ,
3476b9af6bddSHong Zhang                                        /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
34772b8ad9a3SHong Zhang                                        MatTransColoringApplyDenToSp_SeqAIJ,
3478f4259b30SLisandro Dalcin                                        NULL,
3479f4259b30SLisandro Dalcin                                        NULL,
34803964eb88SJed Brown                                        MatRARtNumeric_SeqAIJ_SeqAIJ,
3481f4259b30SLisandro Dalcin                                        /*139*/ NULL,
3482f4259b30SLisandro Dalcin                                        NULL,
3483f4259b30SLisandro Dalcin                                        NULL,
34843a062f41SBarry Smith                                        MatFDColoringSetUp_SeqXAIJ,
34859c8f2541SHong Zhang                                        MatFindOffBlockDiagonalEntries_SeqAIJ,
34864222ddf1SHong Zhang                                        MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
34874222ddf1SHong Zhang                                        /*145*/ MatDestroySubMatrices_SeqAIJ,
3488f4259b30SLisandro Dalcin                                        NULL,
348972833a62Smarkadams4                                        NULL,
349072833a62Smarkadams4                                        MatCreateGraph_Simple_AIJ,
34917fb60732SBarry Smith                                        MatFilter_AIJ,
34929371c9d4SSatish Balay                                        /*150*/ MatTransposeSymbolic_SeqAIJ};
349317ab2063SBarry Smith 
34949371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat, PetscInt *indices) {
3495bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
349697f1f81fSBarry Smith   PetscInt    i, nz, n;
3497bef8e0ddSBarry Smith 
3498bef8e0ddSBarry Smith   PetscFunctionBegin;
3499bef8e0ddSBarry Smith   nz = aij->maxnz;
3500d0f46423SBarry Smith   n  = mat->rmap->n;
3501ad540459SPierre Jolivet   for (i = 0; i < nz; i++) aij->j[i] = indices[i];
3502bef8e0ddSBarry Smith   aij->nz = nz;
3503ad540459SPierre Jolivet   for (i = 0; i < n; i++) aij->ilen[i] = aij->imax[i];
3504bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3505bef8e0ddSBarry Smith }
3506bef8e0ddSBarry Smith 
3507a3bb6f32SFande Kong /*
3508ddea5d60SJunchao Zhang  * Given a sparse matrix with global column indices, compact it by using a local column space.
3509ddea5d60SJunchao Zhang  * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3510ddea5d60SJunchao Zhang  */
35119371c9d4SSatish Balay PetscErrorCode MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping) {
3512a3bb6f32SFande Kong   Mat_SeqAIJ        *aij = (Mat_SeqAIJ *)mat->data;
3513a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3514a3bb6f32SFande Kong   PetscTablePosition tpos;
351525b670f0SStefano Zampini   PetscInt           gid, lid, i, ec, nz = aij->nz;
351625b670f0SStefano Zampini   PetscInt          *garray, *jj = aij->j;
3517a3bb6f32SFande Kong 
3518a3bb6f32SFande Kong   PetscFunctionBegin;
3519a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3520a3bb6f32SFande Kong   PetscValidPointer(mapping, 2);
3521a3bb6f32SFande Kong   /* use a table */
35229566063dSJacob Faibussowitsch   PetscCall(PetscTableCreate(mat->rmap->n, mat->cmap->N + 1, &gid1_lid1));
3523a3bb6f32SFande Kong   ec = 0;
352425b670f0SStefano Zampini   for (i = 0; i < nz; i++) {
352525b670f0SStefano Zampini     PetscInt data, gid1 = jj[i] + 1;
35269566063dSJacob Faibussowitsch     PetscCall(PetscTableFind(gid1_lid1, gid1, &data));
3527a3bb6f32SFande Kong     if (!data) {
3528a3bb6f32SFande Kong       /* one based table */
35299566063dSJacob Faibussowitsch       PetscCall(PetscTableAdd(gid1_lid1, gid1, ++ec, INSERT_VALUES));
3530a3bb6f32SFande Kong     }
3531a3bb6f32SFande Kong   }
3532a3bb6f32SFande Kong   /* form array of columns we need */
35339566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ec, &garray));
35349566063dSJacob Faibussowitsch   PetscCall(PetscTableGetHeadPosition(gid1_lid1, &tpos));
3535a3bb6f32SFande Kong   while (tpos) {
35369566063dSJacob Faibussowitsch     PetscCall(PetscTableGetNext(gid1_lid1, &tpos, &gid, &lid));
3537a3bb6f32SFande Kong     gid--;
3538a3bb6f32SFande Kong     lid--;
3539a3bb6f32SFande Kong     garray[lid] = gid;
3540a3bb6f32SFande Kong   }
35419566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(ec, garray)); /* sort, and rebuild */
35429566063dSJacob Faibussowitsch   PetscCall(PetscTableRemoveAll(gid1_lid1));
354348a46eb9SPierre Jolivet   for (i = 0; i < ec; i++) PetscCall(PetscTableAdd(gid1_lid1, garray[i] + 1, i + 1, INSERT_VALUES));
3544a3bb6f32SFande Kong   /* compact out the extra columns in B */
354525b670f0SStefano Zampini   for (i = 0; i < nz; i++) {
354625b670f0SStefano Zampini     PetscInt gid1 = jj[i] + 1;
35479566063dSJacob Faibussowitsch     PetscCall(PetscTableFind(gid1_lid1, gid1, &lid));
3548a3bb6f32SFande Kong     lid--;
354925b670f0SStefano Zampini     jj[i] = lid;
3550a3bb6f32SFande Kong   }
35519566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&mat->cmap));
35529566063dSJacob Faibussowitsch   PetscCall(PetscTableDestroy(&gid1_lid1));
35539566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat), ec, ec, 1, &mat->cmap));
35549566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, mat->cmap->bs, mat->cmap->n, garray, PETSC_OWN_POINTER, mapping));
35559566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(*mapping, ISLOCALTOGLOBALMAPPINGHASH));
3556a3bb6f32SFande Kong   PetscFunctionReturn(0);
3557a3bb6f32SFande Kong }
3558a3bb6f32SFande Kong 
3559bef8e0ddSBarry Smith /*@
3560bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3561bef8e0ddSBarry Smith        in the matrix.
3562bef8e0ddSBarry Smith 
3563bef8e0ddSBarry Smith   Input Parameters:
356411a5261eSBarry Smith +  mat - the `MATSEQAIJ` matrix
3565bef8e0ddSBarry Smith -  indices - the column indices
3566bef8e0ddSBarry Smith 
356715091d37SBarry Smith   Level: advanced
356815091d37SBarry Smith 
3569bef8e0ddSBarry Smith   Notes:
3570bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3571bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
357211a5261eSBarry Smith   of the `MatSetValues()` operation.
3573bef8e0ddSBarry Smith 
3574bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
357511a5261eSBarry Smith   `MatCreateSeqAIJ()`, and the columns indices MUST be sorted.
3576bef8e0ddSBarry Smith 
357711a5261eSBarry Smith     MUST be called before any calls to `MatSetValues()`
3578bef8e0ddSBarry Smith 
3579b9617806SBarry Smith     The indices should start with zero, not one.
3580b9617806SBarry Smith 
3581bef8e0ddSBarry Smith @*/
35829371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat, PetscInt *indices) {
3583bef8e0ddSBarry Smith   PetscFunctionBegin;
35840700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3585dadcf809SJacob Faibussowitsch   PetscValidIntPointer(indices, 2);
3586cac4c232SBarry Smith   PetscUseMethod(mat, "MatSeqAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices));
3587bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3588bef8e0ddSBarry Smith }
3589bef8e0ddSBarry Smith 
3590be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3591be6bf707SBarry Smith 
35929371c9d4SSatish Balay PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) {
3593be6bf707SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
3594d0f46423SBarry Smith   size_t      nz  = aij->i[mat->rmap->n];
3595be6bf707SBarry Smith 
3596be6bf707SBarry Smith   PetscFunctionBegin;
359728b400f6SJacob Faibussowitsch   PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3598be6bf707SBarry Smith 
3599be6bf707SBarry Smith   /* allocate space for values if not already there */
3600be6bf707SBarry Smith   if (!aij->saved_values) {
36019566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nz + 1, &aij->saved_values));
36029566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)mat, (nz + 1) * sizeof(PetscScalar)));
3603be6bf707SBarry Smith   }
3604be6bf707SBarry Smith 
3605be6bf707SBarry Smith   /* copy values over */
36069566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz));
3607be6bf707SBarry Smith   PetscFunctionReturn(0);
3608be6bf707SBarry Smith }
3609be6bf707SBarry Smith 
3610be6bf707SBarry Smith /*@
3611be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3612be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3613be6bf707SBarry Smith        nonlinear portion.
3614be6bf707SBarry Smith 
361511a5261eSBarry Smith    Collect on mat
3616be6bf707SBarry Smith 
3617be6bf707SBarry Smith   Input Parameters:
361811a5261eSBarry Smith .  mat - the matrix (currently only `MATAIJ` matrices support this option)
3619be6bf707SBarry Smith 
362015091d37SBarry Smith   Level: advanced
362115091d37SBarry Smith 
362211a5261eSBarry Smith   Common Usage, with `SNESSolve()`:
3623be6bf707SBarry Smith $    Create Jacobian matrix
3624be6bf707SBarry Smith $    Set linear terms into matrix
3625be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3626be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3627be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3628512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3629be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3630be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3631be6bf707SBarry Smith $    In your Jacobian routine
3632be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3633be6bf707SBarry Smith $      Set nonlinear terms in matrix
3634be6bf707SBarry Smith 
3635be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3636be6bf707SBarry Smith $    // build linear portion of Jacobian
3637512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3638be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3639be6bf707SBarry Smith $    loop over nonlinear iterations
3640be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3641be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3642be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3643be6bf707SBarry Smith $       Solve linear system with Jacobian
3644be6bf707SBarry Smith $    endloop
3645be6bf707SBarry Smith 
3646be6bf707SBarry Smith   Notes:
3647be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
364811a5261eSBarry Smith     Must set the matrix option `MatSetOption`(mat,`MAT_NEW_NONZERO_LOCATIONS`,`PETSC_FALSE`); before
3649be6bf707SBarry Smith     calling this routine.
3650be6bf707SBarry Smith 
36510c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
36520c468ba9SBarry Smith     and does not allocated additional space.
36530c468ba9SBarry Smith 
3654db781477SPatrick Sanan .seealso: `MatRetrieveValues()`
3655be6bf707SBarry Smith @*/
36569371c9d4SSatish Balay PetscErrorCode MatStoreValues(Mat mat) {
3657be6bf707SBarry Smith   PetscFunctionBegin;
36580700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
365928b400f6SJacob Faibussowitsch   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
366028b400f6SJacob Faibussowitsch   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3661cac4c232SBarry Smith   PetscUseMethod(mat, "MatStoreValues_C", (Mat), (mat));
3662be6bf707SBarry Smith   PetscFunctionReturn(0);
3663be6bf707SBarry Smith }
3664be6bf707SBarry Smith 
36659371c9d4SSatish Balay PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat) {
3666be6bf707SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
3667d0f46423SBarry Smith   PetscInt    nz  = aij->i[mat->rmap->n];
3668be6bf707SBarry Smith 
3669be6bf707SBarry Smith   PetscFunctionBegin;
367028b400f6SJacob Faibussowitsch   PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
367128b400f6SJacob Faibussowitsch   PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first");
3672be6bf707SBarry Smith   /* copy values over */
36739566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz));
3674be6bf707SBarry Smith   PetscFunctionReturn(0);
3675be6bf707SBarry Smith }
3676be6bf707SBarry Smith 
3677be6bf707SBarry Smith /*@
3678be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3679be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3680be6bf707SBarry Smith        nonlinear portion.
3681be6bf707SBarry Smith 
368211a5261eSBarry Smith    Collect on mat
3683be6bf707SBarry Smith 
3684be6bf707SBarry Smith   Input Parameters:
368511a5261eSBarry Smith .  mat - the matrix (currently only `MATAIJ` matrices support this option)
3686be6bf707SBarry Smith 
368715091d37SBarry Smith   Level: advanced
368815091d37SBarry Smith 
3689db781477SPatrick Sanan .seealso: `MatStoreValues()`
3690be6bf707SBarry Smith @*/
36919371c9d4SSatish Balay PetscErrorCode MatRetrieveValues(Mat mat) {
3692be6bf707SBarry Smith   PetscFunctionBegin;
36930700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
369428b400f6SJacob Faibussowitsch   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
369528b400f6SJacob Faibussowitsch   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3696cac4c232SBarry Smith   PetscUseMethod(mat, "MatRetrieveValues_C", (Mat), (mat));
3697be6bf707SBarry Smith   PetscFunctionReturn(0);
3698be6bf707SBarry Smith }
3699be6bf707SBarry Smith 
3700be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
370117ab2063SBarry Smith /*@C
370211a5261eSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in `MATSEQAIJ` (compressed row) format
37030d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
37046e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
370551c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
37062bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
370717ab2063SBarry Smith 
3708d083f849SBarry Smith    Collective
3709db81eaa0SLois Curfman McInnes 
371017ab2063SBarry Smith    Input Parameters:
371111a5261eSBarry Smith +  comm - MPI communicator, set to `PETSC_COMM_SELF`
371217ab2063SBarry Smith .  m - number of rows
371317ab2063SBarry Smith .  n - number of columns
371417ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
371551c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
37160298fd71SBarry Smith          (possibly different for each row) or NULL
371717ab2063SBarry Smith 
371817ab2063SBarry Smith    Output Parameter:
3719416022c9SBarry Smith .  A - the matrix
372017ab2063SBarry Smith 
372111a5261eSBarry Smith    It is recommended that one use the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`,
3722f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
372311a5261eSBarry Smith    [MatXXXXSetPreallocation() is, for example, `MatSeqAIJSetPreallocation()`]
3724175b88e8SBarry Smith 
3725b259b22eSLois Curfman McInnes    Notes:
372649a6f317SBarry Smith    If nnz is given then nz is ignored
372749a6f317SBarry Smith 
372811a5261eSBarry Smith    The AIJ format, also called
372911a5261eSBarry Smith    compressed row storage, is fully compatible with standard Fortran 77
37300002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
373144cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
373217ab2063SBarry Smith 
373317ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
373411a5261eSBarry Smith    Set nz = `PETSC_DEFAULT` and nnz = NULL for PETSc to control dynamic memory
37353d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
37366da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
373717ab2063SBarry Smith 
3738682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
37394fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3740682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
37416c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
37426c7ebb05SLois Curfman McInnes 
37436c7ebb05SLois Curfman McInnes    Options Database Keys:
3744698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
37459db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
374617ab2063SBarry Smith 
3747027ccd11SLois Curfman McInnes    Level: intermediate
3748027ccd11SLois Curfman McInnes 
3749db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()`
375017ab2063SBarry Smith @*/
37519371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A) {
37523a40ed3dSBarry Smith   PetscFunctionBegin;
37539566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
37549566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
37559566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQAIJ));
37569566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*A, nz, nnz));
3757273d9f13SBarry Smith   PetscFunctionReturn(0);
3758273d9f13SBarry Smith }
3759273d9f13SBarry Smith 
3760273d9f13SBarry Smith /*@C
3761273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
3762273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
3763273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
3764273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
3765273d9f13SBarry Smith 
3766d083f849SBarry Smith    Collective
3767273d9f13SBarry Smith 
3768273d9f13SBarry Smith    Input Parameters:
37691c4f3114SJed Brown +  B - The matrix
3770273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
3771273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
37720298fd71SBarry Smith          (possibly different for each row) or NULL
3773273d9f13SBarry Smith 
3774273d9f13SBarry Smith    Notes:
377549a6f317SBarry Smith      If nnz is given then nz is ignored
377649a6f317SBarry Smith 
377711a5261eSBarry Smith     The `MATSEQAIJ` format also called
377811a5261eSBarry Smith    compressed row storage, is fully compatible with standard Fortran 77
3779273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
3780273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
3781273d9f13SBarry Smith 
3782273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
378311a5261eSBarry Smith    Set nz = `PETSC_DEFAULT` and nnz = NULL for PETSc to control dynamic memory
3784273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
3785273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
3786273d9f13SBarry Smith 
378711a5261eSBarry Smith    You can call `MatGetInfo()` to get information on how effective the preallocation was;
3788aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3789aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
3790aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
3791aa95bbe8SBarry Smith 
379211a5261eSBarry Smith    Developer Notes:
379311a5261eSBarry Smith    Use nz of `MAT_SKIP_ALLOCATION` to not allocate any space for the matrix
3794a96a251dSBarry Smith    entries or columns indices
3795a96a251dSBarry Smith 
3796273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
3797273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
3798273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
3799273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
3800273d9f13SBarry Smith 
3801273d9f13SBarry Smith    Options Database Keys:
3802698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
380347b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3804273d9f13SBarry Smith 
3805273d9f13SBarry Smith    Level: intermediate
3806273d9f13SBarry Smith 
3807db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()`, `MatGetInfo()`,
3808db781477SPatrick Sanan           `MatSeqAIJSetTotalPreallocation()`
3809273d9f13SBarry Smith @*/
38109371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocation(Mat B, PetscInt nz, const PetscInt nnz[]) {
3811a23d5eceSKris Buschelman   PetscFunctionBegin;
38126ba663aaSJed Brown   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
38136ba663aaSJed Brown   PetscValidType(B, 1);
3814cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqAIJSetPreallocation_C", (Mat, PetscInt, const PetscInt[]), (B, nz, nnz));
3815a23d5eceSKris Buschelman   PetscFunctionReturn(0);
3816a23d5eceSKris Buschelman }
3817a23d5eceSKris Buschelman 
38189371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B, PetscInt nz, const PetscInt *nnz) {
3819273d9f13SBarry Smith   Mat_SeqAIJ *b;
38202576faa2SJed Brown   PetscBool   skipallocation = PETSC_FALSE, realalloc = PETSC_FALSE;
382197f1f81fSBarry Smith   PetscInt    i;
3822273d9f13SBarry Smith 
3823273d9f13SBarry Smith   PetscFunctionBegin;
38242576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
3825a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
3826c461c341SBarry Smith     skipallocation = PETSC_TRUE;
3827c461c341SBarry Smith     nz             = 0;
3828c461c341SBarry Smith   }
38299566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
38309566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
3831899cda47SBarry Smith 
3832435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
383308401ef6SPierre Jolivet   PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz);
3834cf9c20a2SJed Brown   if (PetscUnlikelyDebug(nnz)) {
3835d0f46423SBarry Smith     for (i = 0; i < B->rmap->n; i++) {
383608401ef6SPierre Jolivet       PetscCheck(nnz[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nnz cannot be less than 0: local row %" PetscInt_FMT " value %" PetscInt_FMT, i, nnz[i]);
383708401ef6SPierre Jolivet       PetscCheck(nnz[i] <= B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nnz cannot be greater than row length: local row %" PetscInt_FMT " value %" PetscInt_FMT " rowlength %" PetscInt_FMT, i, nnz[i], B->cmap->n);
3838b73539f3SBarry Smith     }
3839b73539f3SBarry Smith   }
3840b73539f3SBarry Smith 
3841273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
38422205254eSKarl Rupp 
3843273d9f13SBarry Smith   b = (Mat_SeqAIJ *)B->data;
3844273d9f13SBarry Smith 
3845ab93d7beSBarry Smith   if (!skipallocation) {
38462ee49352SLisandro Dalcin     if (!b->imax) {
38479566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(B->rmap->n, &b->imax));
38489566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)B, B->rmap->n * sizeof(PetscInt)));
3849071fcb05SBarry Smith     }
3850071fcb05SBarry Smith     if (!b->ilen) {
3851071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
38529566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(B->rmap->n, &b->ilen));
38539566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)B, B->rmap->n * sizeof(PetscInt)));
3854071fcb05SBarry Smith     } else {
38559566063dSJacob Faibussowitsch       PetscCall(PetscMemzero(b->ilen, B->rmap->n * sizeof(PetscInt)));
38562ee49352SLisandro Dalcin     }
3857846b4da1SFande Kong     if (!b->ipre) {
38589566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(B->rmap->n, &b->ipre));
38599566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)B, B->rmap->n * sizeof(PetscInt)));
3860846b4da1SFande Kong     }
3861273d9f13SBarry Smith     if (!nnz) {
3862435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
3863c62bd62aSJed Brown       else if (nz < 0) nz = 1;
38645d2a9ed1SStefano Zampini       nz = PetscMin(nz, B->cmap->n);
3865d0f46423SBarry Smith       for (i = 0; i < B->rmap->n; i++) b->imax[i] = nz;
3866d0f46423SBarry Smith       nz = nz * B->rmap->n;
3867273d9f13SBarry Smith     } else {
3868c73702f5SBarry Smith       PetscInt64 nz64 = 0;
38699371c9d4SSatish Balay       for (i = 0; i < B->rmap->n; i++) {
38709371c9d4SSatish Balay         b->imax[i] = nnz[i];
38719371c9d4SSatish Balay         nz64 += nnz[i];
38729371c9d4SSatish Balay       }
38739566063dSJacob Faibussowitsch       PetscCall(PetscIntCast(nz64, &nz));
3874273d9f13SBarry Smith     }
3875ab93d7beSBarry Smith 
3876273d9f13SBarry Smith     /* allocate the matrix space */
387753dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
38789566063dSJacob Faibussowitsch     PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i));
3879396832f4SHong Zhang     if (B->structure_only) {
38809566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz, &b->j));
38819566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(B->rmap->n + 1, &b->i));
38829566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)B, (B->rmap->n + 1) * sizeof(PetscInt) + nz * sizeof(PetscInt)));
3883396832f4SHong Zhang     } else {
38849566063dSJacob Faibussowitsch       PetscCall(PetscMalloc3(nz, &b->a, nz, &b->j, B->rmap->n + 1, &b->i));
38859566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)B, (B->rmap->n + 1) * sizeof(PetscInt) + nz * (sizeof(PetscScalar) + sizeof(PetscInt))));
3886396832f4SHong Zhang     }
3887bfeeae90SHong Zhang     b->i[0] = 0;
3888ad540459SPierre Jolivet     for (i = 1; i < B->rmap->n + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1];
3889396832f4SHong Zhang     if (B->structure_only) {
3890396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
3891396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
3892396832f4SHong Zhang     } else {
3893273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
3894e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
3895396832f4SHong Zhang     }
3896e6b907acSBarry Smith     b->free_ij = PETSC_TRUE;
3897c461c341SBarry Smith   } else {
3898e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
3899e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
3900c461c341SBarry Smith   }
3901273d9f13SBarry Smith 
3902846b4da1SFande Kong   if (b->ipre && nnz != b->ipre && b->imax) {
3903846b4da1SFande Kong     /* reserve user-requested sparsity */
39049566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(b->ipre, b->imax, B->rmap->n));
3905846b4da1SFande Kong   }
3906846b4da1SFande Kong 
3907273d9f13SBarry Smith   b->nz               = 0;
3908273d9f13SBarry Smith   b->maxnz            = nz;
3909273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
39101baa6e33SBarry Smith   if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
3911cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
3912cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
39135519a089SJose E. Roman   /* We simply deem preallocation has changed nonzero state. Updating the state
39145519a089SJose E. Roman      will give clients (like AIJKokkos) a chance to know something has happened.
39155519a089SJose E. Roman   */
39165519a089SJose E. Roman   B->nonzerostate++;
3917273d9f13SBarry Smith   PetscFunctionReturn(0);
3918273d9f13SBarry Smith }
3919273d9f13SBarry Smith 
39209371c9d4SSatish Balay PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A) {
3921846b4da1SFande Kong   Mat_SeqAIJ *a;
3922a5bbaf83SFande Kong   PetscInt    i;
3923846b4da1SFande Kong 
3924846b4da1SFande Kong   PetscFunctionBegin;
3925846b4da1SFande Kong   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
392614d0e64fSAlex Lindsay 
392714d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
392814d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
392914d0e64fSAlex Lindsay 
3930846b4da1SFande Kong   a = (Mat_SeqAIJ *)A->data;
39312c814fdeSFande Kong   /* if no saved info, we error out */
393228b400f6SJacob Faibussowitsch   PetscCheck(a->ipre, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "No saved preallocation info ");
39332c814fdeSFande Kong 
3934aed4548fSBarry Smith   PetscCheck(a->i && a->j && a->a && a->imax && a->ilen, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Memory info is incomplete, and can not reset preallocation ");
39352c814fdeSFande Kong 
39369566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(a->imax, a->ipre, A->rmap->n));
39379566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(a->ilen, A->rmap->n));
3938846b4da1SFande Kong   a->i[0] = 0;
3939ad540459SPierre Jolivet   for (i = 1; i < A->rmap->n + 1; i++) a->i[i] = a->i[i - 1] + a->imax[i - 1];
3940846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
3941846b4da1SFande Kong   a->nz               = 0;
3942846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
3943846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
3944846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
3945846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
3946846b4da1SFande Kong   PetscFunctionReturn(0);
3947846b4da1SFande Kong }
3948846b4da1SFande Kong 
394958d36128SBarry Smith /*@
395011a5261eSBarry Smith    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in `MATSEQAIJ` format.
3951a1661176SMatthew Knepley 
3952a1661176SMatthew Knepley    Input Parameters:
3953a1661176SMatthew Knepley +  B - the matrix
3954a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
3955a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
3956a1661176SMatthew Knepley -  v - optional values in the matrix
3957a1661176SMatthew Knepley 
3958a1661176SMatthew Knepley    Level: developer
3959a1661176SMatthew Knepley 
39606a9b8d82SBarry Smith    Notes:
396111a5261eSBarry Smith       The i,j,v values are COPIED with this routine; to avoid the copy use `MatCreateSeqAIJWithArrays()`
396258d36128SBarry Smith 
39636a9b8d82SBarry Smith       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
39646a9b8d82SBarry Smith       structure will be the union of all the previous nonzero structures.
39656a9b8d82SBarry Smith 
39666a9b8d82SBarry Smith     Developer Notes:
39676a9b8d82SBarry Smith       An optimization could be added to the implementation where it checks if the i, and j are identical to the current i and j and
396811a5261eSBarry Smith       then just copies the v values directly with `PetscMemcpy()`.
39696a9b8d82SBarry Smith 
397011a5261eSBarry Smith       This routine could also take a `PetscCopyMode` argument to allow sharing the values instead of always copying them.
39716a9b8d82SBarry Smith 
3972db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatSeqAIJSetPreallocation()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MatResetPreallocation()`
3973a1661176SMatthew Knepley @*/
39749371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B, const PetscInt i[], const PetscInt j[], const PetscScalar v[]) {
3975a1661176SMatthew Knepley   PetscFunctionBegin;
39760700a824SBarry Smith   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
39776ba663aaSJed Brown   PetscValidType(B, 1);
3978cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqAIJSetPreallocationCSR_C", (Mat, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, i, j, v));
3979a1661176SMatthew Knepley   PetscFunctionReturn(0);
3980a1661176SMatthew Knepley }
3981a1661176SMatthew Knepley 
39829371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B, const PetscInt Ii[], const PetscInt J[], const PetscScalar v[]) {
3983a1661176SMatthew Knepley   PetscInt  i;
3984a1661176SMatthew Knepley   PetscInt  m, n;
3985a1661176SMatthew Knepley   PetscInt  nz;
39866a9b8d82SBarry Smith   PetscInt *nnz;
3987a1661176SMatthew Knepley 
3988a1661176SMatthew Knepley   PetscFunctionBegin;
3989aed4548fSBarry Smith   PetscCheck(Ii[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]);
3990779a8d59SSatish Balay 
39919566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
39929566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
3993779a8d59SSatish Balay 
39949566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, &m, &n));
39959566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &nnz));
3996a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
3997b7940d39SSatish Balay     nz = Ii[i + 1] - Ii[i];
399808401ef6SPierre Jolivet     PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz);
3999a1661176SMatthew Knepley     nnz[i] = nz;
4000a1661176SMatthew Knepley   }
40019566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz));
40029566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
4003a1661176SMatthew Knepley 
400448a46eb9SPierre Jolivet   for (i = 0; i < m; i++) PetscCall(MatSetValues_SeqAIJ(B, 1, &i, Ii[i + 1] - Ii[i], J + Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES));
4005a1661176SMatthew Knepley 
40069566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
40079566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4008a1661176SMatthew Knepley 
40099566063dSJacob Faibussowitsch   PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
4010a1661176SMatthew Knepley   PetscFunctionReturn(0);
4011a1661176SMatthew Knepley }
4012a1661176SMatthew Knepley 
4013ad7e164aSPierre Jolivet /*@
4014ad7e164aSPierre Jolivet    MatSeqAIJKron - Computes C, the Kronecker product of A and B.
4015ad7e164aSPierre Jolivet 
4016ad7e164aSPierre Jolivet    Input Parameters:
4017ad7e164aSPierre Jolivet +  A - left-hand side matrix
4018ad7e164aSPierre Jolivet .  B - right-hand side matrix
401911a5261eSBarry Smith -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
4020ad7e164aSPierre Jolivet 
4021ad7e164aSPierre Jolivet    Output Parameter:
4022ad7e164aSPierre Jolivet .  C - Kronecker product of A and B
4023ad7e164aSPierre Jolivet 
4024ad7e164aSPierre Jolivet    Level: intermediate
4025ad7e164aSPierre Jolivet 
402611a5261eSBarry Smith    Note:
402711a5261eSBarry Smith       `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the product matrix has not changed from that last call to `MatSeqAIJKron()`.
4028ad7e164aSPierre Jolivet 
4029db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATKAIJ`, `MatReuse`
4030ad7e164aSPierre Jolivet @*/
40319371c9d4SSatish Balay PetscErrorCode MatSeqAIJKron(Mat A, Mat B, MatReuse reuse, Mat *C) {
4032ad7e164aSPierre Jolivet   PetscFunctionBegin;
4033ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4034ad7e164aSPierre Jolivet   PetscValidType(A, 1);
4035ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4036ad7e164aSPierre Jolivet   PetscValidType(B, 2);
4037ad7e164aSPierre Jolivet   PetscValidPointer(C, 4);
4038ad7e164aSPierre Jolivet   if (reuse == MAT_REUSE_MATRIX) {
4039ad7e164aSPierre Jolivet     PetscValidHeaderSpecific(*C, MAT_CLASSID, 4);
4040ad7e164aSPierre Jolivet     PetscValidType(*C, 4);
4041ad7e164aSPierre Jolivet   }
4042cac4c232SBarry Smith   PetscTryMethod(A, "MatSeqAIJKron_C", (Mat, Mat, MatReuse, Mat *), (A, B, reuse, C));
4043ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4044ad7e164aSPierre Jolivet }
4045ad7e164aSPierre Jolivet 
40469371c9d4SSatish Balay PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A, Mat B, MatReuse reuse, Mat *C) {
4047ad7e164aSPierre Jolivet   Mat                newmat;
4048ad7e164aSPierre Jolivet   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
4049ad7e164aSPierre Jolivet   Mat_SeqAIJ        *b = (Mat_SeqAIJ *)B->data;
4050ad7e164aSPierre Jolivet   PetscScalar       *v;
4051fff043a9SJunchao Zhang   const PetscScalar *aa, *ba;
4052ad7e164aSPierre Jolivet   PetscInt          *i, *j, m, n, p, q, nnz = 0, am = A->rmap->n, bm = B->rmap->n, an = A->cmap->n, bn = B->cmap->n;
4053ad7e164aSPierre Jolivet   PetscBool          flg;
4054ad7e164aSPierre Jolivet 
4055ad7e164aSPierre Jolivet   PetscFunctionBegin;
405628b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
405728b400f6SJacob Faibussowitsch   PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
405828b400f6SJacob Faibussowitsch   PetscCheck(!B->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
405928b400f6SJacob Faibussowitsch   PetscCheck(B->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
40609566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATSEQAIJ, &flg));
406128b400f6SJacob Faibussowitsch   PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatType %s", ((PetscObject)B)->type_name);
4062aed4548fSBarry Smith   PetscCheck(reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatReuse %d", (int)reuse);
4063ad7e164aSPierre Jolivet   if (reuse == MAT_INITIAL_MATRIX) {
40649566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(am * bm + 1, &i, a->i[am] * b->i[bm], &j));
40659566063dSJacob Faibussowitsch     PetscCall(MatCreate(PETSC_COMM_SELF, &newmat));
40669566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(newmat, am * bm, an * bn, am * bm, an * bn));
40679566063dSJacob Faibussowitsch     PetscCall(MatSetType(newmat, MATAIJ));
4068ad7e164aSPierre Jolivet     i[0] = 0;
4069ad7e164aSPierre Jolivet     for (m = 0; m < am; ++m) {
4070ad7e164aSPierre Jolivet       for (p = 0; p < bm; ++p) {
4071ad7e164aSPierre Jolivet         i[m * bm + p + 1] = i[m * bm + p] + (a->i[m + 1] - a->i[m]) * (b->i[p + 1] - b->i[p]);
4072ad7e164aSPierre Jolivet         for (n = a->i[m]; n < a->i[m + 1]; ++n) {
4073ad540459SPierre Jolivet           for (q = b->i[p]; q < b->i[p + 1]; ++q) j[nnz++] = a->j[n] * bn + b->j[q];
4074ad7e164aSPierre Jolivet         }
4075ad7e164aSPierre Jolivet       }
4076ad7e164aSPierre Jolivet     }
40779566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocationCSR(newmat, i, j, NULL));
4078ad7e164aSPierre Jolivet     *C = newmat;
40799566063dSJacob Faibussowitsch     PetscCall(PetscFree2(i, j));
4080ad7e164aSPierre Jolivet     nnz = 0;
4081ad7e164aSPierre Jolivet   }
40829566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(*C, &v));
40839566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
40849566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(B, &ba));
4085ad7e164aSPierre Jolivet   for (m = 0; m < am; ++m) {
4086ad7e164aSPierre Jolivet     for (p = 0; p < bm; ++p) {
4087ad7e164aSPierre Jolivet       for (n = a->i[m]; n < a->i[m + 1]; ++n) {
4088ad540459SPierre Jolivet         for (q = b->i[p]; q < b->i[p + 1]; ++q) v[nnz++] = aa[n] * ba[q];
4089ad7e164aSPierre Jolivet       }
4090ad7e164aSPierre Jolivet     }
4091ad7e164aSPierre Jolivet   }
40929566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(*C, &v));
40939566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
40949566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(B, &ba));
4095ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4096ad7e164aSPierre Jolivet }
4097ad7e164aSPierre Jolivet 
4098c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4099af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4100170fe5c8SBarry Smith 
4101170fe5c8SBarry Smith /*
4102170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4103170fe5c8SBarry Smith 
4104170fe5c8SBarry Smith                n                       p                          p
41052da392ccSBarry Smith         [             ]       [             ]         [                 ]
41062da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
41072da392ccSBarry Smith         [             ]       [             ]         [                 ]
4108170fe5c8SBarry Smith 
4109170fe5c8SBarry Smith */
41109371c9d4SSatish Balay PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A, Mat B, Mat C) {
4111170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense *)A->data;
4112170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ *)B->data;
4113170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense *)C->data;
411486214ceeSStefano Zampini   PetscInt           i, j, n, m, q, p;
4115170fe5c8SBarry Smith   const PetscInt    *ii, *idx;
4116170fe5c8SBarry Smith   const PetscScalar *b, *a, *a_q;
4117170fe5c8SBarry Smith   PetscScalar       *c, *c_q;
411886214ceeSStefano Zampini   PetscInt           clda = sub_c->lda;
411986214ceeSStefano Zampini   PetscInt           alda = sub_a->lda;
4120170fe5c8SBarry Smith 
4121170fe5c8SBarry Smith   PetscFunctionBegin;
4122d0f46423SBarry Smith   m = A->rmap->n;
4123d0f46423SBarry Smith   n = A->cmap->n;
4124d0f46423SBarry Smith   p = B->cmap->n;
4125170fe5c8SBarry Smith   a = sub_a->v;
4126170fe5c8SBarry Smith   b = sub_b->a;
4127170fe5c8SBarry Smith   c = sub_c->v;
412886214ceeSStefano Zampini   if (clda == m) {
41299566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(c, m * p));
413086214ceeSStefano Zampini   } else {
413186214ceeSStefano Zampini     for (j = 0; j < p; j++)
41329371c9d4SSatish Balay       for (i = 0; i < m; i++) c[j * clda + i] = 0.0;
413386214ceeSStefano Zampini   }
4134170fe5c8SBarry Smith   ii  = sub_b->i;
4135170fe5c8SBarry Smith   idx = sub_b->j;
4136170fe5c8SBarry Smith   for (i = 0; i < n; i++) {
4137170fe5c8SBarry Smith     q = ii[i + 1] - ii[i];
4138170fe5c8SBarry Smith     while (q-- > 0) {
413986214ceeSStefano Zampini       c_q = c + clda * (*idx);
414086214ceeSStefano Zampini       a_q = a + alda * i;
4141854c7f52SBarry Smith       PetscKernelAXPY(c_q, *b, a_q, m);
4142170fe5c8SBarry Smith       idx++;
4143170fe5c8SBarry Smith       b++;
4144170fe5c8SBarry Smith     }
4145170fe5c8SBarry Smith   }
4146170fe5c8SBarry Smith   PetscFunctionReturn(0);
4147170fe5c8SBarry Smith }
4148170fe5c8SBarry Smith 
41499371c9d4SSatish Balay PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A, Mat B, PetscReal fill, Mat C) {
4150d0f46423SBarry Smith   PetscInt  m = A->rmap->n, n = B->cmap->n;
415186214ceeSStefano Zampini   PetscBool cisdense;
4152170fe5c8SBarry Smith 
4153170fe5c8SBarry Smith   PetscFunctionBegin;
415408401ef6SPierre Jolivet   PetscCheck(A->cmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "A->cmap->n %" PetscInt_FMT " != B->rmap->n %" PetscInt_FMT, A->cmap->n, B->rmap->n);
41559566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
41569566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(C, A, B));
41579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
415848a46eb9SPierre Jolivet   if (!cisdense) PetscCall(MatSetType(C, MATDENSE));
41599566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
4160d73949e8SHong Zhang 
41614222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4162170fe5c8SBarry Smith   PetscFunctionReturn(0);
4163170fe5c8SBarry Smith }
4164170fe5c8SBarry Smith 
4165170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
41660bad9183SKris Buschelman /*MC
4167fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
41680bad9183SKris Buschelman    based on compressed sparse row format.
41690bad9183SKris Buschelman 
41700bad9183SKris Buschelman    Options Database Keys:
41710bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
41720bad9183SKris Buschelman 
41730bad9183SKris Buschelman    Level: beginner
41740bad9183SKris Buschelman 
41750cd7f59aSBarry Smith    Notes:
417611a5261eSBarry Smith     `MatSetValues()` may be called for this matrix type with a NULL argument for the numerical values,
41770cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
41780cd7f59aSBarry Smith     in the matrix
41790cd7f59aSBarry Smith 
418011a5261eSBarry Smith     `MatSetOptions`(,`MAT_STRUCTURE_ONLY`,`PETSC_TRUE`) may be called for this matrix type. In this no
418111a5261eSBarry Smith     space is allocated for the nonzero entries and any entries passed with `MatSetValues()` are ignored
41820cd7f59aSBarry Smith 
418311a5261eSBarry Smith   Developer Note:
41840cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
41850cd7f59aSBarry Smith 
4186db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MatSetFromOptions()`, `MatSetType()`, `MatCreate()`, `MatType`, `MATSELL`, `MATSEQSELL`, `MATMPISELL`
41870bad9183SKris Buschelman M*/
41880bad9183SKris Buschelman 
4189ccd284c7SBarry Smith /*MC
4190ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4191ccd284c7SBarry Smith 
419211a5261eSBarry Smith    This matrix type is identical to `MATSEQAIJ` when constructed with a single process communicator,
419311a5261eSBarry Smith    and `MATMPIAIJ` otherwise.  As a result, for single process communicators,
419411a5261eSBarry Smith    `MatSeqAIJSetPreallocation()` is supported, and similarly `MatMPIAIJSetPreallocation()` is supported
4195ccd284c7SBarry Smith    for communicators controlling multiple processes.  It is recommended that you call both of
4196ccd284c7SBarry Smith    the above preallocation routines for simplicity.
4197ccd284c7SBarry Smith 
4198ccd284c7SBarry Smith    Options Database Keys:
419911a5261eSBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to `MatSetFromOptions()`
4200ccd284c7SBarry Smith 
420111a5261eSBarry Smith    Note:
420211a5261eSBarry Smith    Subclasses include `MATAIJCUSPARSE`, `MATAIJPERM`, `MATAIJSELL`, `MATAIJMKL`, `MATAIJCRL`, and also automatically switches over to use inodes when
4203ccd284c7SBarry Smith    enough exist.
4204ccd284c7SBarry Smith 
4205ccd284c7SBarry Smith   Level: beginner
4206ccd284c7SBarry Smith 
4207db781477SPatrick Sanan .seealso: `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATMPIAIJ`, `MATSELL`, `MATSEQSELL`, `MATMPISELL`
4208ccd284c7SBarry Smith M*/
4209ccd284c7SBarry Smith 
4210ccd284c7SBarry Smith /*MC
4211ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4212ccd284c7SBarry Smith 
421311a5261eSBarry Smith    This matrix type is identical to `MATSEQAIJCRL` when constructed with a single process communicator,
421411a5261eSBarry Smith    and `MATMPIAIJCRL` otherwise.  As a result, for single process communicators,
421511a5261eSBarry Smith    `MatSeqAIJSetPreallocation()` is supported, and similarly `MatMPIAIJSetPreallocation()` is supported
4216ccd284c7SBarry Smith    for communicators controlling multiple processes.  It is recommended that you call both of
4217ccd284c7SBarry Smith    the above preallocation routines for simplicity.
4218ccd284c7SBarry Smith 
4219ccd284c7SBarry Smith    Options Database Keys:
422011a5261eSBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to `MatSetFromOptions()`
4221ccd284c7SBarry Smith 
4222ccd284c7SBarry Smith   Level: beginner
4223ccd284c7SBarry Smith 
4224c2e3fba1SPatrick Sanan .seealso: `MatCreateMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL`
4225ccd284c7SBarry Smith M*/
4226ccd284c7SBarry Smith 
42277906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat, MatType, MatReuse, Mat *);
42287906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
42297906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat, MatType, MatReuse, Mat *);
42307906f579SHong Zhang #endif
4231d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4232d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat, MatType, MatReuse, Mat *);
4233d24d4204SJose E. Roman #endif
42347906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
42357906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType, MatReuse, Mat *);
42367906f579SHong Zhang #endif
42377906f579SHong Zhang 
4238d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat, MatType, MatReuse, Mat *);
4239c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat, MatType, MatReuse, Mat *);
42404222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
42417906f579SHong Zhang 
42428c778c55SBarry Smith /*@C
424311a5261eSBarry Smith    MatSeqAIJGetArray - gives read/write access to the array where the data for a `MATSEQAIJ` matrix is stored
42448c778c55SBarry Smith 
42458c778c55SBarry Smith    Not Collective
42468c778c55SBarry Smith 
42478c778c55SBarry Smith    Input Parameter:
424811a5261eSBarry Smith .  mat - a `MATSEQAIJ` matrix
42498c778c55SBarry Smith 
42508c778c55SBarry Smith    Output Parameter:
42518c778c55SBarry Smith .   array - pointer to the data
42528c778c55SBarry Smith 
42538c778c55SBarry Smith    Level: intermediate
42548c778c55SBarry Smith 
4255db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()`
42568c778c55SBarry Smith @*/
42579371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArray(Mat A, PetscScalar **array) {
4258d67d9f35SJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
42598c778c55SBarry Smith 
42608c778c55SBarry Smith   PetscFunctionBegin;
4261d67d9f35SJunchao Zhang   if (aij->ops->getarray) {
42629566063dSJacob Faibussowitsch     PetscCall((*aij->ops->getarray)(A, array));
4263d67d9f35SJunchao Zhang   } else {
4264d67d9f35SJunchao Zhang     *array = aij->a;
4265d67d9f35SJunchao Zhang   }
4266d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4267d67d9f35SJunchao Zhang }
4268d67d9f35SJunchao Zhang 
4269d67d9f35SJunchao Zhang /*@C
427011a5261eSBarry Smith    MatSeqAIJRestoreArray - returns access to the array where the data for a `MATSEQAIJ` matrix is stored obtained by `MatSeqAIJGetArray()`
4271d67d9f35SJunchao Zhang 
4272d67d9f35SJunchao Zhang    Not Collective
4273d67d9f35SJunchao Zhang 
4274d67d9f35SJunchao Zhang    Input Parameters:
427511a5261eSBarry Smith +  mat - a `MATSEQAIJ` matrix
4276d67d9f35SJunchao Zhang -  array - pointer to the data
4277d67d9f35SJunchao Zhang 
4278d67d9f35SJunchao Zhang    Level: intermediate
4279d67d9f35SJunchao Zhang 
4280db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayF90()`
4281d67d9f35SJunchao Zhang @*/
42829371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArray(Mat A, PetscScalar **array) {
4283d67d9f35SJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
4284d67d9f35SJunchao Zhang 
4285d67d9f35SJunchao Zhang   PetscFunctionBegin;
4286d67d9f35SJunchao Zhang   if (aij->ops->restorearray) {
42879566063dSJacob Faibussowitsch     PetscCall((*aij->ops->restorearray)(A, array));
4288d67d9f35SJunchao Zhang   } else {
4289d67d9f35SJunchao Zhang     *array = NULL;
4290d67d9f35SJunchao Zhang   }
42919566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(A));
42929566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
42938c778c55SBarry Smith   PetscFunctionReturn(0);
42948c778c55SBarry Smith }
42958c778c55SBarry Smith 
429621e72a00SBarry Smith /*@C
429711a5261eSBarry Smith    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a `MATSEQAIJ` matrix is stored
42988f1ea47aSStefano Zampini 
42998f1ea47aSStefano Zampini    Not Collective
43008f1ea47aSStefano Zampini 
43018f1ea47aSStefano Zampini    Input Parameter:
430211a5261eSBarry Smith .  mat - a `MATSEQAIJ` matrix
43038f1ea47aSStefano Zampini 
43048f1ea47aSStefano Zampini    Output Parameter:
43058f1ea47aSStefano Zampini .   array - pointer to the data
43068f1ea47aSStefano Zampini 
43078f1ea47aSStefano Zampini    Level: intermediate
43088f1ea47aSStefano Zampini 
4309db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()`
43108f1ea47aSStefano Zampini @*/
43119371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArrayRead(Mat A, const PetscScalar **array) {
4312d67d9f35SJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
43138f1ea47aSStefano Zampini 
43148f1ea47aSStefano Zampini   PetscFunctionBegin;
4315d67d9f35SJunchao Zhang   if (aij->ops->getarrayread) {
43169566063dSJacob Faibussowitsch     PetscCall((*aij->ops->getarrayread)(A, array));
4317d67d9f35SJunchao Zhang   } else {
4318d67d9f35SJunchao Zhang     *array = aij->a;
4319d67d9f35SJunchao Zhang   }
43208f1ea47aSStefano Zampini   PetscFunctionReturn(0);
43218f1ea47aSStefano Zampini }
43228f1ea47aSStefano Zampini 
43238f1ea47aSStefano Zampini /*@C
432411a5261eSBarry Smith    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from `MatSeqAIJGetArrayRead()`
43258f1ea47aSStefano Zampini 
43268f1ea47aSStefano Zampini    Not Collective
43278f1ea47aSStefano Zampini 
43288f1ea47aSStefano Zampini    Input Parameter:
432911a5261eSBarry Smith .  mat - a `MATSEQAIJ` matrix
43308f1ea47aSStefano Zampini 
43318f1ea47aSStefano Zampini    Output Parameter:
43328f1ea47aSStefano Zampini .   array - pointer to the data
43338f1ea47aSStefano Zampini 
43348f1ea47aSStefano Zampini    Level: intermediate
43358f1ea47aSStefano Zampini 
4336db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()`
43378f1ea47aSStefano Zampini @*/
43389371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArrayRead(Mat A, const PetscScalar **array) {
4339d67d9f35SJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
43408f1ea47aSStefano Zampini 
43418f1ea47aSStefano Zampini   PetscFunctionBegin;
4342d67d9f35SJunchao Zhang   if (aij->ops->restorearrayread) {
43439566063dSJacob Faibussowitsch     PetscCall((*aij->ops->restorearrayread)(A, array));
4344d67d9f35SJunchao Zhang   } else {
4345d67d9f35SJunchao Zhang     *array = NULL;
4346d67d9f35SJunchao Zhang   }
4347d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4348d67d9f35SJunchao Zhang }
4349d67d9f35SJunchao Zhang 
4350d67d9f35SJunchao Zhang /*@C
435111a5261eSBarry Smith    MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a `MATSEQAIJ` matrix is stored
4352d67d9f35SJunchao Zhang 
4353d67d9f35SJunchao Zhang    Not Collective
4354d67d9f35SJunchao Zhang 
4355d67d9f35SJunchao Zhang    Input Parameter:
435611a5261eSBarry Smith .  mat - a `MATSEQAIJ` matrix
4357d67d9f35SJunchao Zhang 
4358d67d9f35SJunchao Zhang    Output Parameter:
4359d67d9f35SJunchao Zhang .   array - pointer to the data
4360d67d9f35SJunchao Zhang 
4361d67d9f35SJunchao Zhang    Level: intermediate
4362d67d9f35SJunchao Zhang 
4363db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()`
4364d67d9f35SJunchao Zhang @*/
43659371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetArrayWrite(Mat A, PetscScalar **array) {
4366d67d9f35SJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
4367d67d9f35SJunchao Zhang 
4368d67d9f35SJunchao Zhang   PetscFunctionBegin;
4369d67d9f35SJunchao Zhang   if (aij->ops->getarraywrite) {
43709566063dSJacob Faibussowitsch     PetscCall((*aij->ops->getarraywrite)(A, array));
4371d67d9f35SJunchao Zhang   } else {
4372d67d9f35SJunchao Zhang     *array = aij->a;
4373d67d9f35SJunchao Zhang   }
43749566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(A));
43759566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
4376d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4377d67d9f35SJunchao Zhang }
4378d67d9f35SJunchao Zhang 
4379d67d9f35SJunchao Zhang /*@C
4380d67d9f35SJunchao Zhang    MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead
4381d67d9f35SJunchao Zhang 
4382d67d9f35SJunchao Zhang    Not Collective
4383d67d9f35SJunchao Zhang 
4384d67d9f35SJunchao Zhang    Input Parameter:
4385d67d9f35SJunchao Zhang .  mat - a MATSEQAIJ matrix
4386d67d9f35SJunchao Zhang 
4387d67d9f35SJunchao Zhang    Output Parameter:
4388d67d9f35SJunchao Zhang .   array - pointer to the data
4389d67d9f35SJunchao Zhang 
4390d67d9f35SJunchao Zhang    Level: intermediate
4391d67d9f35SJunchao Zhang 
4392db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()`
4393d67d9f35SJunchao Zhang @*/
43949371c9d4SSatish Balay PetscErrorCode MatSeqAIJRestoreArrayWrite(Mat A, PetscScalar **array) {
4395d67d9f35SJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
4396d67d9f35SJunchao Zhang 
4397d67d9f35SJunchao Zhang   PetscFunctionBegin;
4398d67d9f35SJunchao Zhang   if (aij->ops->restorearraywrite) {
43999566063dSJacob Faibussowitsch     PetscCall((*aij->ops->restorearraywrite)(A, array));
4400d67d9f35SJunchao Zhang   } else {
4401d67d9f35SJunchao Zhang     *array = NULL;
4402d67d9f35SJunchao Zhang   }
44038f1ea47aSStefano Zampini   PetscFunctionReturn(0);
44048f1ea47aSStefano Zampini }
44058f1ea47aSStefano Zampini 
44068f1ea47aSStefano Zampini /*@C
440711a5261eSBarry Smith    MatSeqAIJGetCSRAndMemType - Get the CSR arrays and the memory type of the `MATSEQAIJ` matrix
44087ee59b9bSJunchao Zhang 
44097ee59b9bSJunchao Zhang    Not Collective
44107ee59b9bSJunchao Zhang 
44117ee59b9bSJunchao Zhang    Input Parameter:
441211a5261eSBarry Smith .  mat - a matrix of type `MATSEQAIJ` or its subclasses
44137ee59b9bSJunchao Zhang 
44147ee59b9bSJunchao Zhang    Output Parameters:
44157ee59b9bSJunchao Zhang +  i - row map array of the matrix
44167ee59b9bSJunchao Zhang .  j - column index array of the matrix
44177ee59b9bSJunchao Zhang .  a - data array of the matrix
44187ee59b9bSJunchao Zhang -  memtype - memory type of the arrays
44197ee59b9bSJunchao Zhang 
44207ee59b9bSJunchao Zhang   Notes:
44217ee59b9bSJunchao Zhang    Any of the output parameters can be NULL, in which case the corresponding value is not returned.
44227ee59b9bSJunchao Zhang    If mat is a device matrix, the arrays are on the device. Otherwise, they are on the host.
44237ee59b9bSJunchao Zhang 
44247ee59b9bSJunchao Zhang    One can call this routine on a preallocated but not assembled matrix to just get the memory of the CSR underneath the matrix.
44257ee59b9bSJunchao Zhang    If the matrix is assembled, the data array 'a' is guaranteed to have the latest values of the matrix.
44267ee59b9bSJunchao Zhang 
44277ee59b9bSJunchao Zhang    Level: Developer
44287ee59b9bSJunchao Zhang 
4429db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()`
44307ee59b9bSJunchao Zhang @*/
44319371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetCSRAndMemType(Mat mat, const PetscInt **i, const PetscInt **j, PetscScalar **a, PetscMemType *mtype) {
44327ee59b9bSJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
44337ee59b9bSJunchao Zhang 
44347ee59b9bSJunchao Zhang   PetscFunctionBegin;
44357ee59b9bSJunchao Zhang   PetscCheck(mat->preallocated, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "matrix is not preallocated");
44367ee59b9bSJunchao Zhang   if (aij->ops->getcsrandmemtype) {
44377ee59b9bSJunchao Zhang     PetscCall((*aij->ops->getcsrandmemtype)(mat, i, j, a, mtype));
44387ee59b9bSJunchao Zhang   } else {
44397ee59b9bSJunchao Zhang     if (i) *i = aij->i;
44407ee59b9bSJunchao Zhang     if (j) *j = aij->j;
44417ee59b9bSJunchao Zhang     if (a) *a = aij->a;
44427ee59b9bSJunchao Zhang     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
44437ee59b9bSJunchao Zhang   }
44447ee59b9bSJunchao Zhang   PetscFunctionReturn(0);
44457ee59b9bSJunchao Zhang }
44467ee59b9bSJunchao Zhang 
44477ee59b9bSJunchao Zhang /*@C
444821e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
444921e72a00SBarry Smith 
445021e72a00SBarry Smith    Not Collective
445121e72a00SBarry Smith 
445221e72a00SBarry Smith    Input Parameter:
445311a5261eSBarry Smith .  mat - a `MATSEQAIJ` matrix
445421e72a00SBarry Smith 
445521e72a00SBarry Smith    Output Parameter:
445621e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
445721e72a00SBarry Smith 
445821e72a00SBarry Smith    Level: intermediate
445921e72a00SBarry Smith 
4460db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()`
446121e72a00SBarry Smith @*/
44629371c9d4SSatish Balay PetscErrorCode MatSeqAIJGetMaxRowNonzeros(Mat A, PetscInt *nz) {
446321e72a00SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
446421e72a00SBarry Smith 
446521e72a00SBarry Smith   PetscFunctionBegin;
446621e72a00SBarry Smith   *nz = aij->rmax;
446721e72a00SBarry Smith   PetscFunctionReturn(0);
446821e72a00SBarry Smith }
446921e72a00SBarry Smith 
44709371c9d4SSatish Balay PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[]) {
4471394ed5ebSJunchao Zhang   MPI_Comm     comm;
4472394ed5ebSJunchao Zhang   PetscInt    *i, *j;
4473394ed5ebSJunchao Zhang   PetscInt     M, N, row;
4474394ed5ebSJunchao Zhang   PetscCount   k, p, q, nneg, nnz, start, end; /* Index the coo array, so use PetscCount as their type */
4475394ed5ebSJunchao Zhang   PetscInt    *Ai;                             /* Change to PetscCount once we use it for row pointers */
4476394ed5ebSJunchao Zhang   PetscInt    *Aj;
4477394ed5ebSJunchao Zhang   PetscScalar *Aa;
4478cbc6b225SStefano Zampini   Mat_SeqAIJ  *seqaij = (Mat_SeqAIJ *)(mat->data);
4479cbc6b225SStefano Zampini   MatType      rtype;
4480394ed5ebSJunchao Zhang   PetscCount  *perm, *jmap;
4481394ed5ebSJunchao Zhang 
4482394ed5ebSJunchao Zhang   PetscFunctionBegin;
44839566063dSJacob Faibussowitsch   PetscCall(MatResetPreallocationCOO_SeqAIJ(mat));
44849566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
44859566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &M, &N));
4486e8729f6fSJunchao Zhang   i = coo_i;
4487e8729f6fSJunchao Zhang   j = coo_j;
44889566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(coo_n, &perm));
4489394ed5ebSJunchao Zhang   for (k = 0; k < coo_n; k++) { /* Ignore entries with negative row or col indices */
4490394ed5ebSJunchao Zhang     if (j[k] < 0) i[k] = -1;
4491394ed5ebSJunchao Zhang     perm[k] = k;
4492394ed5ebSJunchao Zhang   }
4493394ed5ebSJunchao Zhang 
4494394ed5ebSJunchao Zhang   /* Sort by row */
44959566063dSJacob Faibussowitsch   PetscCall(PetscSortIntWithIntCountArrayPair(coo_n, i, j, perm));
44969371c9d4SSatish Balay   for (k = 0; k < coo_n; k++) {
44979371c9d4SSatish Balay     if (i[k] >= 0) break;
44989371c9d4SSatish Balay   } /* Advance k to the first row with a non-negative index */
4499394ed5ebSJunchao Zhang   nneg = k;
45009566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(coo_n - nneg + 1, &jmap)); /* +1 to make a CSR-like data structure. jmap[i] originally is the number of repeats for i-th nonzero */
4501394ed5ebSJunchao Zhang   nnz = 0;                                          /* Total number of unique nonzeros to be counted */
4502394ed5ebSJunchao Zhang   jmap++;                                           /* Inc jmap by 1 for convinience */
4503394ed5ebSJunchao Zhang 
45049566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(M + 1, &Ai));        /* CSR of A */
45059566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(coo_n - nneg, &Aj)); /* We have at most coo_n-nneg unique nonzeros */
4506394ed5ebSJunchao Zhang 
4507394ed5ebSJunchao Zhang   /* In each row, sort by column, then unique column indices to get row length */
4508394ed5ebSJunchao Zhang   Ai++;  /* Inc by 1 for convinience */
4509394ed5ebSJunchao Zhang   q = 0; /* q-th unique nonzero, with q starting from 0 */
4510394ed5ebSJunchao Zhang   while (k < coo_n) {
4511394ed5ebSJunchao Zhang     row   = i[k];
4512394ed5ebSJunchao Zhang     start = k; /* [start,end) indices for this row */
4513394ed5ebSJunchao Zhang     while (k < coo_n && i[k] == row) k++;
4514394ed5ebSJunchao Zhang     end = k;
45159566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithCountArray(end - start, j + start, perm + start));
4516394ed5ebSJunchao Zhang     /* Find number of unique col entries in this row */
4517394ed5ebSJunchao Zhang     Aj[q]   = j[start]; /* Log the first nonzero in this row */
4518394ed5ebSJunchao Zhang     jmap[q] = 1;        /* Number of repeats of this nozero entry */
4519394ed5ebSJunchao Zhang     Ai[row] = 1;
4520394ed5ebSJunchao Zhang     nnz++;
4521394ed5ebSJunchao Zhang 
4522394ed5ebSJunchao Zhang     for (p = start + 1; p < end; p++) { /* Scan remaining nonzero in this row */
4523394ed5ebSJunchao Zhang       if (j[p] != j[p - 1]) {           /* Meet a new nonzero */
4524394ed5ebSJunchao Zhang         q++;
4525394ed5ebSJunchao Zhang         jmap[q] = 1;
4526394ed5ebSJunchao Zhang         Aj[q]   = j[p];
4527394ed5ebSJunchao Zhang         Ai[row]++;
4528394ed5ebSJunchao Zhang         nnz++;
4529394ed5ebSJunchao Zhang       } else {
4530394ed5ebSJunchao Zhang         jmap[q]++;
4531394ed5ebSJunchao Zhang       }
4532394ed5ebSJunchao Zhang     }
4533394ed5ebSJunchao Zhang     q++; /* Move to next row and thus next unique nonzero */
4534394ed5ebSJunchao Zhang   }
4535394ed5ebSJunchao Zhang 
4536394ed5ebSJunchao Zhang   Ai--; /* Back to the beginning of Ai[] */
4537394ed5ebSJunchao Zhang   for (k = 0; k < M; k++) Ai[k + 1] += Ai[k];
4538394ed5ebSJunchao Zhang   jmap--; /* Back to the beginning of jmap[] */
4539394ed5ebSJunchao Zhang   jmap[0] = 0;
4540394ed5ebSJunchao Zhang   for (k = 0; k < nnz; k++) jmap[k + 1] += jmap[k];
4541394ed5ebSJunchao Zhang   if (nnz < coo_n - nneg) { /* Realloc with actual number of unique nonzeros */
4542394ed5ebSJunchao Zhang     PetscCount *jmap_new;
4543394ed5ebSJunchao Zhang     PetscInt   *Aj_new;
4544394ed5ebSJunchao Zhang 
45459566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz + 1, &jmap_new));
45469566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(jmap_new, jmap, nnz + 1));
45479566063dSJacob Faibussowitsch     PetscCall(PetscFree(jmap));
4548394ed5ebSJunchao Zhang     jmap = jmap_new;
4549394ed5ebSJunchao Zhang 
45509566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &Aj_new));
45519566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(Aj_new, Aj, nnz));
45529566063dSJacob Faibussowitsch     PetscCall(PetscFree(Aj));
4553394ed5ebSJunchao Zhang     Aj = Aj_new;
4554394ed5ebSJunchao Zhang   }
4555394ed5ebSJunchao Zhang 
4556394ed5ebSJunchao Zhang   if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */
4557394ed5ebSJunchao Zhang     PetscCount *perm_new;
4558cbc6b225SStefano Zampini 
45599566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coo_n - nneg, &perm_new));
45609566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(perm_new, perm + nneg, coo_n - nneg));
45619566063dSJacob Faibussowitsch     PetscCall(PetscFree(perm));
4562394ed5ebSJunchao Zhang     perm = perm_new;
4563394ed5ebSJunchao Zhang   }
4564394ed5ebSJunchao Zhang 
45659566063dSJacob Faibussowitsch   PetscCall(MatGetRootType_Private(mat, &rtype));
45669566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nnz, &Aa)); /* Zero the matrix */
45679566063dSJacob Faibussowitsch   PetscCall(MatSetSeqAIJWithArrays_private(PETSC_COMM_SELF, M, N, Ai, Aj, Aa, rtype, mat));
4568394ed5ebSJunchao Zhang 
4569394ed5ebSJunchao Zhang   seqaij->singlemalloc = PETSC_FALSE;            /* Ai, Aj and Aa are not allocated in one big malloc */
4570394ed5ebSJunchao Zhang   seqaij->free_a = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */
4571394ed5ebSJunchao Zhang   /* Record COO fields */
4572394ed5ebSJunchao Zhang   seqaij->coo_n                    = coo_n;
4573394ed5ebSJunchao Zhang   seqaij->Atot                     = coo_n - nneg; /* Annz is seqaij->nz, so no need to record that again */
4574394ed5ebSJunchao Zhang   seqaij->jmap                     = jmap;         /* of length nnz+1 */
4575394ed5ebSJunchao Zhang   seqaij->perm                     = perm;
4576394ed5ebSJunchao Zhang   PetscFunctionReturn(0);
4577394ed5ebSJunchao Zhang }
4578394ed5ebSJunchao Zhang 
45799371c9d4SSatish Balay static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A, const PetscScalar v[], InsertMode imode) {
4580394ed5ebSJunchao Zhang   Mat_SeqAIJ  *aseq = (Mat_SeqAIJ *)A->data;
4581394ed5ebSJunchao Zhang   PetscCount   i, j, Annz = aseq->nz;
4582394ed5ebSJunchao Zhang   PetscCount  *perm = aseq->perm, *jmap = aseq->jmap;
4583394ed5ebSJunchao Zhang   PetscScalar *Aa;
4584394ed5ebSJunchao Zhang 
4585394ed5ebSJunchao Zhang   PetscFunctionBegin;
45869566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &Aa));
4587394ed5ebSJunchao Zhang   for (i = 0; i < Annz; i++) {
4588b6c38306SJunchao Zhang     PetscScalar sum = 0.0;
4589b6c38306SJunchao Zhang     for (j = jmap[i]; j < jmap[i + 1]; j++) sum += v[perm[j]];
4590b6c38306SJunchao Zhang     Aa[i] = (imode == INSERT_VALUES ? 0.0 : Aa[i]) + sum;
4591394ed5ebSJunchao Zhang   }
45929566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &Aa));
4593394ed5ebSJunchao Zhang   PetscFunctionReturn(0);
4594394ed5ebSJunchao Zhang }
4595394ed5ebSJunchao Zhang 
459634b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
45975063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat, MatType, MatReuse, Mat *);
459802fe1965SBarry Smith #endif
45993d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
46005063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat, MatType, MatReuse, Mat *);
46013d0639e7SStefano Zampini #endif
460202fe1965SBarry Smith 
46039371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B) {
4604273d9f13SBarry Smith   Mat_SeqAIJ *b;
460538baddfdSBarry Smith   PetscMPIInt size;
4606273d9f13SBarry Smith 
4607273d9f13SBarry Smith   PetscFunctionBegin;
46089566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
460908401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Comm must be of size 1");
4610273d9f13SBarry Smith 
46119566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(B, &b));
46122205254eSKarl Rupp 
4613b0a32e0cSBarry Smith   B->data = (void *)b;
46142205254eSKarl Rupp 
46159566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(B->ops, &MatOps_Values, sizeof(struct _MatOps)));
4616071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
46172205254eSKarl Rupp 
4618f4259b30SLisandro Dalcin   b->row                = NULL;
4619f4259b30SLisandro Dalcin   b->col                = NULL;
4620f4259b30SLisandro Dalcin   b->icol               = NULL;
4621b810aeb4SBarry Smith   b->reallocs           = 0;
462236db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4623f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4624416022c9SBarry Smith   b->nonew              = 0;
4625f4259b30SLisandro Dalcin   b->diag               = NULL;
4626f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4627f4259b30SLisandro Dalcin   B->spptr              = NULL;
4628f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4629f4259b30SLisandro Dalcin   b->idiag              = NULL;
4630f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4631f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
463271f1c65dSBarry Smith   b->omega              = 1.0;
463371f1c65dSBarry Smith   b->fshift             = 0.0;
463471f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4635bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4636a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
463717ab2063SBarry Smith 
46389566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ));
4639b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
46409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEnginePut_C", MatlabEnginePut_SeqAIJ));
46419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEngineGet_C", MatlabEngineGet_SeqAIJ));
4642b3866ffcSBarry Smith #endif
46439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetColumnIndices_C", MatSeqAIJSetColumnIndices_SeqAIJ));
46449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqAIJ));
46459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqAIJ));
46469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsbaij_C", MatConvert_SeqAIJ_SeqSBAIJ));
46479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqbaij_C", MatConvert_SeqAIJ_SeqBAIJ));
46489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijperm_C", MatConvert_SeqAIJ_SeqAIJPERM));
46499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijsell_C", MatConvert_SeqAIJ_SeqAIJSELL));
46509779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
46519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijmkl_C", MatConvert_SeqAIJ_SeqAIJMKL));
4652191b95cbSRichard Tran Mills #endif
465334b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
46549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcusparse_C", MatConvert_SeqAIJ_SeqAIJCUSPARSE));
46559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_seqaij_C", MatProductSetFromOptions_SeqAIJ));
46569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaijcusparse_C", MatProductSetFromOptions_SeqAIJ));
465702fe1965SBarry Smith #endif
46583d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
46599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijkokkos_C", MatConvert_SeqAIJ_SeqAIJKokkos));
46603d0639e7SStefano Zampini #endif
46619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcrl_C", MatConvert_SeqAIJ_SeqAIJCRL));
4662af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
46639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_elemental_C", MatConvert_SeqAIJ_Elemental));
4664af8000cdSHong Zhang #endif
4665d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
46669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_scalapack_C", MatConvert_AIJ_ScaLAPACK));
4667d24d4204SJose E. Roman #endif
466863c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
46699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_hypre_C", MatConvert_AIJ_HYPRE));
46709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_transpose_seqaij_seqaij_C", MatProductSetFromOptions_Transpose_AIJ_AIJ));
467163c07aadSStefano Zampini #endif
46729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqdense_C", MatConvert_SeqAIJ_SeqDense));
46739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsell_C", MatConvert_SeqAIJ_SeqSELL));
46749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_is_C", MatConvert_XAIJ_IS));
46759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsTranspose_C", MatIsTranspose_SeqAIJ));
46769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsHermitianTranspose_C", MatIsTranspose_SeqAIJ));
46779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocation_C", MatSeqAIJSetPreallocation_SeqAIJ));
46789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatResetPreallocation_C", MatResetPreallocation_SeqAIJ));
46799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocationCSR_C", MatSeqAIJSetPreallocationCSR_SeqAIJ));
46809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatReorderForNonzeroDiagonal_C", MatReorderForNonzeroDiagonal_SeqAIJ));
46819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_is_seqaij_C", MatProductSetFromOptions_IS_XAIJ));
46829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqaij_C", MatProductSetFromOptions_SeqDense_SeqAIJ));
46839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaij_C", MatProductSetFromOptions_SeqAIJ));
46849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJKron_C", MatSeqAIJKron_SeqAIJ));
46859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_SeqAIJ));
46869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_SeqAIJ));
46879566063dSJacob Faibussowitsch   PetscCall(MatCreate_SeqAIJ_Inode(B));
46889566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ));
46899566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetTypeFromOptions(B)); /* this allows changing the matrix subtype to say MATSEQAIJPERM */
46903a40ed3dSBarry Smith   PetscFunctionReturn(0);
469117ab2063SBarry Smith }
469217ab2063SBarry Smith 
4693b24902e0SBarry Smith /*
46943893b582SJunchao Zhang     Given a matrix generated with MatGetFactor() duplicates all the information in A into C
4695b24902e0SBarry Smith */
46969371c9d4SSatish Balay PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C, Mat A, MatDuplicateOption cpvalues, PetscBool mallocmatspace) {
46972a350339SBarry Smith   Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data, *a = (Mat_SeqAIJ *)A->data;
4698071fcb05SBarry Smith   PetscInt    m = A->rmap->n, i;
469917ab2063SBarry Smith 
47003a40ed3dSBarry Smith   PetscFunctionBegin;
4701aed4548fSBarry Smith   PetscCheck(A->assembled || cpvalues == MAT_DO_NOT_COPY_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix");
4702273d9f13SBarry Smith 
4703d5f3da31SBarry Smith   C->factortype = A->factortype;
4704f4259b30SLisandro Dalcin   c->row        = NULL;
4705f4259b30SLisandro Dalcin   c->col        = NULL;
4706f4259b30SLisandro Dalcin   c->icol       = NULL;
47076ad4291fSHong Zhang   c->reallocs   = 0;
470817ab2063SBarry Smith 
470969272f91SPierre Jolivet   C->assembled    = A->assembled;
471069272f91SPierre Jolivet   C->preallocated = A->preallocated;
471117ab2063SBarry Smith 
471269272f91SPierre Jolivet   if (A->preallocated) {
47139566063dSJacob Faibussowitsch     PetscCall(PetscLayoutReference(A->rmap, &C->rmap));
47149566063dSJacob Faibussowitsch     PetscCall(PetscLayoutReference(A->cmap, &C->cmap));
4715eec197d1SBarry Smith 
47169566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &c->imax));
47179566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(c->imax, a->imax, m * sizeof(PetscInt)));
47189566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &c->ilen));
47199566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(c->ilen, a->ilen, m * sizeof(PetscInt)));
47209566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)C, 2 * m * sizeof(PetscInt)));
472117ab2063SBarry Smith 
472217ab2063SBarry Smith     /* allocate the matrix space */
4723f77e22a1SHong Zhang     if (mallocmatspace) {
47249566063dSJacob Faibussowitsch       PetscCall(PetscMalloc3(a->i[m], &c->a, a->i[m], &c->j, m + 1, &c->i));
47259566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)C, a->i[m] * (sizeof(PetscScalar) + sizeof(PetscInt)) + (m + 1) * sizeof(PetscInt)));
47262205254eSKarl Rupp 
4727f1e2ffcdSBarry Smith       c->singlemalloc = PETSC_TRUE;
47282205254eSKarl Rupp 
47299566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->i, a->i, m + 1));
473017ab2063SBarry Smith       if (m > 0) {
47319566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(c->j, a->j, a->i[m]));
4732be6bf707SBarry Smith         if (cpvalues == MAT_COPY_VALUES) {
47332e5835c6SStefano Zampini           const PetscScalar *aa;
47342e5835c6SStefano Zampini 
47359566063dSJacob Faibussowitsch           PetscCall(MatSeqAIJGetArrayRead(A, &aa));
47369566063dSJacob Faibussowitsch           PetscCall(PetscArraycpy(c->a, aa, a->i[m]));
47379566063dSJacob Faibussowitsch           PetscCall(MatSeqAIJGetArrayRead(A, &aa));
4738be6bf707SBarry Smith         } else {
47399566063dSJacob Faibussowitsch           PetscCall(PetscArrayzero(c->a, a->i[m]));
474017ab2063SBarry Smith         }
474108480c60SBarry Smith       }
4742f77e22a1SHong Zhang     }
474317ab2063SBarry Smith 
47446ad4291fSHong Zhang     c->ignorezeroentries = a->ignorezeroentries;
4745416022c9SBarry Smith     c->roworiented       = a->roworiented;
4746416022c9SBarry Smith     c->nonew             = a->nonew;
4747416022c9SBarry Smith     if (a->diag) {
47489566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(m + 1, &c->diag));
47499566063dSJacob Faibussowitsch       PetscCall(PetscMemcpy(c->diag, a->diag, m * sizeof(PetscInt)));
47509566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)C, (m + 1) * sizeof(PetscInt)));
4751071fcb05SBarry Smith     } else c->diag = NULL;
47522205254eSKarl Rupp 
4753f4259b30SLisandro Dalcin     c->solve_work         = NULL;
4754f4259b30SLisandro Dalcin     c->saved_values       = NULL;
4755f4259b30SLisandro Dalcin     c->idiag              = NULL;
4756f4259b30SLisandro Dalcin     c->ssor_work          = NULL;
4757a9817697SBarry Smith     c->keepnonzeropattern = a->keepnonzeropattern;
4758e6b907acSBarry Smith     c->free_a             = PETSC_TRUE;
4759e6b907acSBarry Smith     c->free_ij            = PETSC_TRUE;
47606ad4291fSHong Zhang 
4761893ad86cSHong Zhang     c->rmax  = a->rmax;
4762416022c9SBarry Smith     c->nz    = a->nz;
47638ed568f8SMatthew G Knepley     c->maxnz = a->nz; /* Since we allocate exactly the right amount */
4764754ec7b1SSatish Balay 
47656ad4291fSHong Zhang     c->compressedrow.use   = a->compressedrow.use;
47666ad4291fSHong Zhang     c->compressedrow.nrows = a->compressedrow.nrows;
4767cd6b891eSBarry Smith     if (a->compressedrow.use) {
47686ad4291fSHong Zhang       i = a->compressedrow.nrows;
47699566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(i + 1, &c->compressedrow.i, i, &c->compressedrow.rindex));
47709566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->compressedrow.i, a->compressedrow.i, i + 1));
47719566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->compressedrow.rindex, a->compressedrow.rindex, i));
477227ea64f8SHong Zhang     } else {
477327ea64f8SHong Zhang       c->compressedrow.use    = PETSC_FALSE;
47740298fd71SBarry Smith       c->compressedrow.i      = NULL;
47750298fd71SBarry Smith       c->compressedrow.rindex = NULL;
47766ad4291fSHong Zhang     }
4777ea632784SBarry Smith     c->nonzerorowcnt = a->nonzerorowcnt;
4778e56f5c9eSBarry Smith     C->nonzerostate  = A->nonzerostate;
47794846f1f5SKris Buschelman 
47809566063dSJacob Faibussowitsch     PetscCall(MatDuplicate_SeqAIJ_Inode(A, cpvalues, &C));
478169272f91SPierre Jolivet   }
47829566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist));
47833a40ed3dSBarry Smith   PetscFunctionReturn(0);
478417ab2063SBarry Smith }
478517ab2063SBarry Smith 
47869371c9d4SSatish Balay PetscErrorCode MatDuplicate_SeqAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B) {
4787b24902e0SBarry Smith   PetscFunctionBegin;
47889566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B));
47899566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*B, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
479048a46eb9SPierre Jolivet   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) PetscCall(MatSetBlockSizesFromMats(*B, A, A));
47919566063dSJacob Faibussowitsch   PetscCall(MatSetType(*B, ((PetscObject)A)->type_name));
47929566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqAIJ(*B, A, cpvalues, PETSC_TRUE));
4793b24902e0SBarry Smith   PetscFunctionReturn(0);
4794b24902e0SBarry Smith }
4795b24902e0SBarry Smith 
47969371c9d4SSatish Balay PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer) {
479752f91c60SVaclav Hapla   PetscBool isbinary, ishdf5;
479852f91c60SVaclav Hapla 
479952f91c60SVaclav Hapla   PetscFunctionBegin;
480052f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1);
480152f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
4802c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
48039566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
48049566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
48059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
480652f91c60SVaclav Hapla   if (isbinary) {
48079566063dSJacob Faibussowitsch     PetscCall(MatLoad_SeqAIJ_Binary(newMat, viewer));
480852f91c60SVaclav Hapla   } else if (ishdf5) {
480952f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
48109566063dSJacob Faibussowitsch     PetscCall(MatLoad_AIJ_HDF5(newMat, viewer));
481152f91c60SVaclav Hapla #else
481252f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
481352f91c60SVaclav Hapla #endif
481452f91c60SVaclav Hapla   } else {
481598921bdaSJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "Viewer type %s not yet supported for reading %s matrices", ((PetscObject)viewer)->type_name, ((PetscObject)newMat)->type_name);
481652f91c60SVaclav Hapla   }
481752f91c60SVaclav Hapla   PetscFunctionReturn(0);
481852f91c60SVaclav Hapla }
481952f91c60SVaclav Hapla 
48209371c9d4SSatish Balay PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer) {
48213ea6fe3dSLisandro Dalcin   Mat_SeqAIJ *a = (Mat_SeqAIJ *)mat->data;
48223ea6fe3dSLisandro Dalcin   PetscInt    header[4], *rowlens, M, N, nz, sum, rows, cols, i;
4823fbdbba38SShri Abhyankar 
4824fbdbba38SShri Abhyankar   PetscFunctionBegin;
48259566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
4826bbead8a2SBarry Smith 
48273ea6fe3dSLisandro Dalcin   /* read in matrix header */
48289566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT));
482908401ef6SPierre Jolivet   PetscCheck(header[0] == MAT_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file");
48309371c9d4SSatish Balay   M  = header[1];
48319371c9d4SSatish Balay   N  = header[2];
48329371c9d4SSatish Balay   nz = header[3];
483308401ef6SPierre Jolivet   PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M);
483408401ef6SPierre Jolivet   PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N);
483508401ef6SPierre Jolivet   PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Matrix stored in special format on disk, cannot load as SeqAIJ");
4836fbdbba38SShri Abhyankar 
48373ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
48389566063dSJacob Faibussowitsch   PetscCall(MatLoad_Binary_BlockSizes(mat, viewer));
48393ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
48403ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
48413ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
48423ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
48433ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
48449566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
48459566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
48463ea6fe3dSLisandro Dalcin 
48473ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
48489566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &rows, &cols));
4849aed4548fSBarry Smith   PetscCheck(M == rows && N == cols, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different sizes (%" PetscInt_FMT ", %" PetscInt_FMT ") than the input matrix (%" PetscInt_FMT ", %" PetscInt_FMT ")", M, N, rows, cols);
48503ea6fe3dSLisandro Dalcin 
4851fbdbba38SShri Abhyankar   /* read in row lengths */
48529566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(M, &rowlens));
48539566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, rowlens, M, NULL, PETSC_INT));
48543ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
48559371c9d4SSatish Balay   sum = 0;
48569371c9d4SSatish Balay   for (i = 0; i < M; i++) sum += rowlens[i];
485708401ef6SPierre Jolivet   PetscCheck(sum == nz, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Inconsistent matrix data in file: nonzeros = %" PetscInt_FMT ", sum-row-lengths = %" PetscInt_FMT, nz, sum);
48583ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
48599566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(mat, 0, rowlens));
48609566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &rows, &cols));
4861aed4548fSBarry Smith   PetscCheck(M == rows && N == cols, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%" PetscInt_FMT ", %" PetscInt_FMT ") than the input matrix (%" PetscInt_FMT ", %" PetscInt_FMT ")", M, N, rows, cols);
48623ea6fe3dSLisandro Dalcin   /* store row lengths */
48639566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(a->ilen, rowlens, M));
48649566063dSJacob Faibussowitsch   PetscCall(PetscFree(rowlens));
4865fbdbba38SShri Abhyankar 
48663ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
48679371c9d4SSatish Balay   a->i[0] = 0;
48689371c9d4SSatish Balay   for (i = 0; i < M; i++) a->i[i + 1] = a->i[i] + a->ilen[i];
48693ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
48709566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, a->j, nz, NULL, PETSC_INT));
48713ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
48729566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, a->a, nz, NULL, PETSC_SCALAR));
4873fbdbba38SShri Abhyankar 
48749566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
48759566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
4876fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
4877fbdbba38SShri Abhyankar }
4878fbdbba38SShri Abhyankar 
48799371c9d4SSatish Balay PetscErrorCode MatEqual_SeqAIJ(Mat A, Mat B, PetscBool *flg) {
48807264ac53SSatish Balay   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data, *b = (Mat_SeqAIJ *)B->data;
4881fff043a9SJunchao Zhang   const PetscScalar *aa, *ba;
4882eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4883eeffb40dSHong Zhang   PetscInt k;
4884eeffb40dSHong Zhang #endif
48857264ac53SSatish Balay 
48863a40ed3dSBarry Smith   PetscFunctionBegin;
4887bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
4888d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) || (a->nz != b->nz)) {
4889ca44d042SBarry Smith     *flg = PETSC_FALSE;
4890ca44d042SBarry Smith     PetscFunctionReturn(0);
4891bcd2baecSBarry Smith   }
48927264ac53SSatish Balay 
48937264ac53SSatish Balay   /* if the a->i are the same */
48949566063dSJacob Faibussowitsch   PetscCall(PetscArraycmp(a->i, b->i, A->rmap->n + 1, flg));
4895abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
48967264ac53SSatish Balay 
48977264ac53SSatish Balay   /* if a->j are the same */
48989566063dSJacob Faibussowitsch   PetscCall(PetscArraycmp(a->j, b->j, a->nz, flg));
4899abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
4900bcd2baecSBarry Smith 
49019566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
49029566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(B, &ba));
4903bcd2baecSBarry Smith   /* if a->a are the same */
4904eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4905eeffb40dSHong Zhang   for (k = 0; k < a->nz; k++) {
4906fff043a9SJunchao Zhang     if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) {
4907eeffb40dSHong Zhang       *flg = PETSC_FALSE;
49083a40ed3dSBarry Smith       PetscFunctionReturn(0);
4909eeffb40dSHong Zhang     }
4910eeffb40dSHong Zhang   }
4911eeffb40dSHong Zhang #else
49129566063dSJacob Faibussowitsch   PetscCall(PetscArraycmp(aa, ba, a->nz, flg));
4913eeffb40dSHong Zhang #endif
49149566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
49159566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(B, &ba));
4916eeffb40dSHong Zhang   PetscFunctionReturn(0);
49177264ac53SSatish Balay }
491836db0b34SBarry Smith 
491905869f15SSatish Balay /*@
492011a5261eSBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential `MATSEQAIJ` matrix using matrix elements (in CSR format)
492136db0b34SBarry Smith               provided by the user.
492236db0b34SBarry Smith 
4923d083f849SBarry Smith       Collective
492436db0b34SBarry Smith 
492536db0b34SBarry Smith    Input Parameters:
492636db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
492736db0b34SBarry Smith .   m - number of rows
492836db0b34SBarry Smith .   n - number of columns
4929483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
493036db0b34SBarry Smith .   j - column indices
493136db0b34SBarry Smith -   a - matrix values
493236db0b34SBarry Smith 
493336db0b34SBarry Smith    Output Parameter:
493436db0b34SBarry Smith .   mat - the matrix
493536db0b34SBarry Smith 
493636db0b34SBarry Smith    Level: intermediate
493736db0b34SBarry Smith 
493836db0b34SBarry Smith    Notes:
49390551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
4940292fb18eSBarry Smith     once the matrix is destroyed and not before
494136db0b34SBarry Smith 
494236db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
494336db0b34SBarry Smith 
4944bfeeae90SHong Zhang        The i and j indices are 0 based
494536db0b34SBarry Smith 
4946a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
4947a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
49488eef79e4SBarry Smith     as shown
4949a4552177SSatish Balay 
49508eef79e4SBarry Smith $        1 0 0
49518eef79e4SBarry Smith $        2 0 3
49528eef79e4SBarry Smith $        4 5 6
49538eef79e4SBarry Smith $
49548eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
49558eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
49568eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
4957a4552177SSatish Balay 
4958db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateMPIAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()`
495936db0b34SBarry Smith @*/
49609371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat) {
4961cbcfb4deSHong Zhang   PetscInt    ii;
496236db0b34SBarry Smith   Mat_SeqAIJ *aij;
4963cbcfb4deSHong Zhang   PetscInt    jj;
496436db0b34SBarry Smith 
496536db0b34SBarry Smith   PetscFunctionBegin;
4966aed4548fSBarry Smith   PetscCheck(m <= 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0");
49679566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, mat));
49689566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mat, m, n, m, n));
49699566063dSJacob Faibussowitsch   /* PetscCall(MatSetBlockSizes(*mat,,)); */
49709566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mat, MATSEQAIJ));
49719566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, MAT_SKIP_ALLOCATION, NULL));
4972ab93d7beSBarry Smith   aij = (Mat_SeqAIJ *)(*mat)->data;
49739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m, &aij->imax));
49749566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m, &aij->ilen));
4975ab93d7beSBarry Smith 
497636db0b34SBarry Smith   aij->i            = i;
497736db0b34SBarry Smith   aij->j            = j;
497836db0b34SBarry Smith   aij->a            = a;
497936db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
498036db0b34SBarry Smith   aij->nonew        = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
4981e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
4982e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
498336db0b34SBarry Smith 
4984cbc6b225SStefano Zampini   for (ii = 0, aij->nonzerorowcnt = 0, aij->rmax = 0; ii < m; ii++) {
498536db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii + 1] - i[ii];
498676bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
4987aed4548fSBarry Smith       PetscCheck(i[ii + 1] - i[ii] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row length in i (row indices) row = %" PetscInt_FMT " length = %" PetscInt_FMT, ii, i[ii + 1] - i[ii]);
49889985e31cSBarry Smith       for (jj = i[ii] + 1; jj < i[ii + 1]; jj++) {
498908401ef6SPierre Jolivet         PetscCheck(j[jj] >= j[jj - 1], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column entry number %" PetscInt_FMT " (actual column %" PetscInt_FMT ") in row %" PetscInt_FMT " is not sorted", jj - i[ii], j[jj], ii);
499008401ef6SPierre Jolivet         PetscCheck(j[jj] != j[jj - 1], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column entry number %" PetscInt_FMT " (actual column %" PetscInt_FMT ") in row %" PetscInt_FMT " is identical to previous entry", jj - i[ii], j[jj], ii);
49919985e31cSBarry Smith       }
499236db0b34SBarry Smith     }
499376bd3646SJed Brown   }
499476bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
499536db0b34SBarry Smith     for (ii = 0; ii < aij->i[m]; ii++) {
499608401ef6SPierre Jolivet       PetscCheck(j[ii] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative column index at location = %" PetscInt_FMT " index = %" PetscInt_FMT, ii, j[ii]);
4997aed4548fSBarry Smith       PetscCheck(j[ii] <= n - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column index to large at location = %" PetscInt_FMT " index = %" PetscInt_FMT, ii, j[ii]);
499836db0b34SBarry Smith     }
499976bd3646SJed Brown   }
500036db0b34SBarry Smith 
50019566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY));
50029566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY));
500336db0b34SBarry Smith   PetscFunctionReturn(0);
500436db0b34SBarry Smith }
5005cbc6b225SStefano Zampini 
5006f62e3866SBarry Smith /*@
500711a5261eSBarry Smith      MatCreateSeqAIJFromTriple - Creates an sequential `MATSEQAIJ` matrix using matrix elements (in COO format)
50088a0b0e6bSVictor Minden               provided by the user.
50098a0b0e6bSVictor Minden 
5010d083f849SBarry Smith       Collective
50118a0b0e6bSVictor Minden 
50128a0b0e6bSVictor Minden    Input Parameters:
50138a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
50148a0b0e6bSVictor Minden .   m   - number of rows
50158a0b0e6bSVictor Minden .   n   - number of columns
50168a0b0e6bSVictor Minden .   i   - row indices
50178a0b0e6bSVictor Minden .   j   - column indices
50181230e6d1SVictor Minden .   a   - matrix values
50191230e6d1SVictor Minden .   nz  - number of nonzeros
502011a5261eSBarry Smith -   idx - if the i and j indices start with 1 use `PETSC_TRUE` otherwise use `PETSC_FALSE`
50218a0b0e6bSVictor Minden 
50228a0b0e6bSVictor Minden    Output Parameter:
50238a0b0e6bSVictor Minden .   mat - the matrix
50248a0b0e6bSVictor Minden 
50258a0b0e6bSVictor Minden    Level: intermediate
50268a0b0e6bSVictor Minden 
5027f62e3866SBarry Smith    Example:
5028f62e3866SBarry Smith        For the following matrix, the input data expected is as shown (using 0 based indexing)
50299e99939fSJunchao Zhang .vb
50308a0b0e6bSVictor Minden         1 0 0
50318a0b0e6bSVictor Minden         2 0 3
50328a0b0e6bSVictor Minden         4 5 6
50338a0b0e6bSVictor Minden 
50348a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
50358a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
50368a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
50379e99939fSJunchao Zhang .ve
50388a0b0e6bSVictor Minden 
5039db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateSeqAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()`, `MatSetValuesCOO()`
50408a0b0e6bSVictor Minden @*/
50419371c9d4SSatish Balay PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat, PetscInt nz, PetscBool idx) {
5042d021a1c5SVictor Minden   PetscInt ii, *nnz, one = 1, row, col;
50438a0b0e6bSVictor Minden 
50448a0b0e6bSVictor Minden   PetscFunctionBegin;
50459566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(m, &nnz));
5046ad540459SPierre Jolivet   for (ii = 0; ii < nz; ii++) nnz[i[ii] - !!idx] += 1;
50479566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, mat));
50489566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mat, m, n, m, n));
50499566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mat, MATSEQAIJ));
50509566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, 0, nnz));
50511230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
50521230e6d1SVictor Minden     if (idx) {
50531230e6d1SVictor Minden       row = i[ii] - 1;
50541230e6d1SVictor Minden       col = j[ii] - 1;
50551230e6d1SVictor Minden     } else {
50561230e6d1SVictor Minden       row = i[ii];
50571230e6d1SVictor Minden       col = j[ii];
50588a0b0e6bSVictor Minden     }
50599566063dSJacob Faibussowitsch     PetscCall(MatSetValues(*mat, one, &row, one, &col, &a[ii], ADD_VALUES));
50608a0b0e6bSVictor Minden   }
50619566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY));
50629566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY));
50639566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
50648a0b0e6bSVictor Minden   PetscFunctionReturn(0);
50658a0b0e6bSVictor Minden }
506636db0b34SBarry Smith 
50679371c9d4SSatish Balay PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A) {
5068acf2f550SJed Brown   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
5069acf2f550SJed Brown 
5070acf2f550SJed Brown   PetscFunctionBegin;
5071acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
5072acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
50732205254eSKarl Rupp 
50749566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal_Inode(A));
5075acf2f550SJed Brown   PetscFunctionReturn(0);
5076acf2f550SJed Brown }
5077acf2f550SJed Brown 
50789371c9d4SSatish Balay PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat) {
50799c8f2541SHong Zhang   PetscFunctionBegin;
50809566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm, inmat, n, scall, outmat));
50819c8f2541SHong Zhang   PetscFunctionReturn(0);
50829c8f2541SHong Zhang }
50839c8f2541SHong Zhang 
508481824310SBarry Smith /*
508553dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
508653dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
508753dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
508853dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
508953dd7562SDmitry Karpeev  */
50909371c9d4SSatish Balay PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C, IS rowemb, IS colemb, MatStructure pattern, Mat B) {
509153dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
509253dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
509353dd7562SDmitry Karpeev   PetscBool       seqaij;
509453dd7562SDmitry Karpeev   PetscInt        m, n, *nz, i, j, count;
509553dd7562SDmitry Karpeev   PetscScalar     v;
509653dd7562SDmitry Karpeev   const PetscInt *rowindices, *colindices;
509753dd7562SDmitry Karpeev 
509853dd7562SDmitry Karpeev   PetscFunctionBegin;
509953dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
510053dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
51019566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)B, MATSEQAIJ, &seqaij));
510228b400f6SJacob Faibussowitsch   PetscCheck(seqaij, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is of wrong type");
510353dd7562SDmitry Karpeev   if (rowemb) {
51049566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(rowemb, &m));
510508401ef6SPierre Jolivet     PetscCheck(m == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Row IS of size %" PetscInt_FMT " is incompatible with matrix row size %" PetscInt_FMT, m, B->rmap->n);
510653dd7562SDmitry Karpeev   } else {
510708401ef6SPierre Jolivet     PetscCheck(C->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is row-incompatible with the target matrix");
510853dd7562SDmitry Karpeev   }
510953dd7562SDmitry Karpeev   if (colemb) {
51109566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(colemb, &n));
511108401ef6SPierre Jolivet     PetscCheck(n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Diag col IS of size %" PetscInt_FMT " is incompatible with input matrix col size %" PetscInt_FMT, n, B->cmap->n);
511253dd7562SDmitry Karpeev   } else {
511308401ef6SPierre Jolivet     PetscCheck(C->cmap->n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is col-incompatible with the target matrix");
511453dd7562SDmitry Karpeev   }
511553dd7562SDmitry Karpeev 
511653dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ *)(B->data);
511753dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
51189566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(B->rmap->n, &nz));
5119ad540459SPierre Jolivet     for (i = 0; i < B->rmap->n; i++) nz[i] = Baij->i[i + 1] - Baij->i[i];
51209566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(C, 0, nz));
51219566063dSJacob Faibussowitsch     PetscCall(PetscFree(nz));
512253dd7562SDmitry Karpeev   }
512348a46eb9SPierre Jolivet   if (pattern == SUBSET_NONZERO_PATTERN) PetscCall(MatZeroEntries(C));
512453dd7562SDmitry Karpeev   count      = 0;
512553dd7562SDmitry Karpeev   rowindices = NULL;
512653dd7562SDmitry Karpeev   colindices = NULL;
512748a46eb9SPierre Jolivet   if (rowemb) PetscCall(ISGetIndices(rowemb, &rowindices));
512848a46eb9SPierre Jolivet   if (colemb) PetscCall(ISGetIndices(colemb, &colindices));
512953dd7562SDmitry Karpeev   for (i = 0; i < B->rmap->n; i++) {
513053dd7562SDmitry Karpeev     PetscInt row;
513153dd7562SDmitry Karpeev     row = i;
513253dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
513353dd7562SDmitry Karpeev     for (j = Baij->i[i]; j < Baij->i[i + 1]; j++) {
513453dd7562SDmitry Karpeev       PetscInt col;
513553dd7562SDmitry Karpeev       col = Baij->j[count];
513653dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
513753dd7562SDmitry Karpeev       v = Baij->a[count];
51389566063dSJacob Faibussowitsch       PetscCall(MatSetValues(C, 1, &row, 1, &col, &v, INSERT_VALUES));
513953dd7562SDmitry Karpeev       ++count;
514053dd7562SDmitry Karpeev     }
514153dd7562SDmitry Karpeev   }
514253dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
514353dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
514453dd7562SDmitry Karpeev   C->preallocated  = PETSC_TRUE;
514553dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
514653dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
514753dd7562SDmitry Karpeev   PetscFunctionReturn(0);
514853dd7562SDmitry Karpeev }
514953dd7562SDmitry Karpeev 
51504099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
51514099cc6bSBarry Smith 
51524099cc6bSBarry Smith /*@C
515311a5261eSBarry Smith    MatSeqAIJSetType - Converts a `MATSEQAIJ` matrix to a subtype
51544099cc6bSBarry Smith 
515511a5261eSBarry Smith    Collective on mat
51564099cc6bSBarry Smith 
51574099cc6bSBarry Smith    Input Parameters:
51584099cc6bSBarry Smith +  mat      - the matrix object
51594099cc6bSBarry Smith -  matype   - matrix type
51604099cc6bSBarry Smith 
51614099cc6bSBarry Smith    Options Database Key:
51624099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
51634099cc6bSBarry Smith 
51644099cc6bSBarry Smith   Level: intermediate
51654099cc6bSBarry Smith 
5166db781477SPatrick Sanan .seealso: `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat`
51674099cc6bSBarry Smith @*/
51689371c9d4SSatish Balay PetscErrorCode MatSeqAIJSetType(Mat mat, MatType matype) {
51694099cc6bSBarry Smith   PetscBool sametype;
51705f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(Mat, MatType, MatReuse, Mat *);
51714099cc6bSBarry Smith 
51724099cc6bSBarry Smith   PetscFunctionBegin;
51734099cc6bSBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
51749566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)mat, matype, &sametype));
51754099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
51764099cc6bSBarry Smith 
51779566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(MatSeqAIJList, matype, &r));
51785f80ce2aSJacob Faibussowitsch   PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Mat type given: %s", matype);
51799566063dSJacob Faibussowitsch   PetscCall((*r)(mat, matype, MAT_INPLACE_MATRIX, &mat));
51804099cc6bSBarry Smith   PetscFunctionReturn(0);
51814099cc6bSBarry Smith }
51824099cc6bSBarry Smith 
51834099cc6bSBarry Smith /*@C
518411a5261eSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential `MATSEQAIJ` matrices
51854099cc6bSBarry Smith 
51864099cc6bSBarry Smith    Not Collective
51874099cc6bSBarry Smith 
51884099cc6bSBarry Smith    Input Parameters:
518911a5261eSBarry Smith +  name - name of a new user-defined matrix type, for example `MATSEQAIJCRL`
51904099cc6bSBarry Smith -  function - routine to convert to subtype
51914099cc6bSBarry Smith 
51924099cc6bSBarry Smith    Notes:
519311a5261eSBarry Smith    `MatSeqAIJRegister()` may be called multiple times to add several user-defined solvers.
51944099cc6bSBarry Smith 
51954099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
51964099cc6bSBarry Smith $     -mat_seqaij_type my_mat
51974099cc6bSBarry Smith 
51984099cc6bSBarry Smith    Level: advanced
51994099cc6bSBarry Smith 
5200db781477SPatrick Sanan .seealso: `MatSeqAIJRegisterAll()`
52014099cc6bSBarry Smith @*/
52029371c9d4SSatish Balay PetscErrorCode MatSeqAIJRegister(const char sname[], PetscErrorCode (*function)(Mat, MatType, MatReuse, Mat *)) {
52034099cc6bSBarry Smith   PetscFunctionBegin;
52049566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
52059566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&MatSeqAIJList, sname, function));
52064099cc6bSBarry Smith   PetscFunctionReturn(0);
52074099cc6bSBarry Smith }
52084099cc6bSBarry Smith 
52094099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
52104099cc6bSBarry Smith 
52114099cc6bSBarry Smith /*@C
521211a5261eSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of `MATSSEQAIJ`
52134099cc6bSBarry Smith 
52144099cc6bSBarry Smith   Not Collective
52154099cc6bSBarry Smith 
52164099cc6bSBarry Smith   Level: advanced
52174099cc6bSBarry Smith 
5218db781477SPatrick Sanan .seealso: `MatRegisterAll()`, `MatSeqAIJRegister()`
52194099cc6bSBarry Smith @*/
52209371c9d4SSatish Balay PetscErrorCode MatSeqAIJRegisterAll(void) {
52214099cc6bSBarry Smith   PetscFunctionBegin;
52224099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
52234099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
52244099cc6bSBarry Smith 
52259566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJCRL, MatConvert_SeqAIJ_SeqAIJCRL));
52269566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJPERM, MatConvert_SeqAIJ_SeqAIJPERM));
52279566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJSELL, MatConvert_SeqAIJ_SeqAIJSELL));
52289779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
52299566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJMKL, MatConvert_SeqAIJ_SeqAIJMKL));
5230485f9817SRichard Tran Mills #endif
52315063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA)
52329566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE));
52335063d097SStefano Zampini #endif
52345063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
52359566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJKOKKOS, MatConvert_SeqAIJ_SeqAIJKokkos));
52365063d097SStefano Zampini #endif
52374099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
52389566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL));
52394099cc6bSBarry Smith #endif
52404099cc6bSBarry Smith   PetscFunctionReturn(0);
52414099cc6bSBarry Smith }
524253dd7562SDmitry Karpeev 
524353dd7562SDmitry Karpeev /*
524481824310SBarry Smith     Special version for direct calls from Fortran
524581824310SBarry Smith */
5246af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
524781824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
524881824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
524981824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
525081824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
525181824310SBarry Smith #endif
525281824310SBarry Smith 
525381824310SBarry Smith /* Change these macros so can be used in void function */
525498921bdaSJacob Faibussowitsch 
525598921bdaSJacob Faibussowitsch /* Change these macros so can be used in void function */
52569566063dSJacob Faibussowitsch /* Identical to PetscCallVoid, except it assigns to *_ierr */
52579566063dSJacob Faibussowitsch #undef PetscCall
52589371c9d4SSatish Balay #define PetscCall(...) \
52599371c9d4SSatish Balay   do { \
52605f80ce2aSJacob Faibussowitsch     PetscErrorCode ierr_msv_mpiaij = __VA_ARGS__; \
526198921bdaSJacob Faibussowitsch     if (PetscUnlikely(ierr_msv_mpiaij)) { \
526298921bdaSJacob Faibussowitsch       *_ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr_msv_mpiaij, PETSC_ERROR_REPEAT, " "); \
526398921bdaSJacob Faibussowitsch       return; \
526498921bdaSJacob Faibussowitsch     } \
526598921bdaSJacob Faibussowitsch   } while (0)
526698921bdaSJacob Faibussowitsch 
526798921bdaSJacob Faibussowitsch #undef SETERRQ
52689371c9d4SSatish Balay #define SETERRQ(comm, ierr, ...) \
52699371c9d4SSatish Balay   do { \
527098921bdaSJacob Faibussowitsch     *_ierr = PetscError(comm, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr, PETSC_ERROR_INITIAL, __VA_ARGS__); \
527198921bdaSJacob Faibussowitsch     return; \
527298921bdaSJacob Faibussowitsch   } while (0)
527381824310SBarry Smith 
52749371c9d4SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA, PetscInt *mm, const PetscInt im[], PetscInt *nn, const PetscInt in[], const PetscScalar v[], InsertMode *isis, PetscErrorCode *_ierr) {
527581824310SBarry Smith   Mat         A = *AA;
527681824310SBarry Smith   PetscInt    m = *mm, n = *nn;
527781824310SBarry Smith   InsertMode  is = *isis;
527881824310SBarry Smith   Mat_SeqAIJ *a  = (Mat_SeqAIJ *)A->data;
527981824310SBarry Smith   PetscInt   *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N;
528081824310SBarry Smith   PetscInt   *imax, *ai, *ailen;
528181824310SBarry Smith   PetscInt   *aj, nonew = a->nonew, lastcol = -1;
528254f21887SBarry Smith   MatScalar  *ap, value, *aa;
5283ace3abfcSBarry Smith   PetscBool   ignorezeroentries = a->ignorezeroentries;
5284ace3abfcSBarry Smith   PetscBool   roworiented       = a->roworiented;
528581824310SBarry Smith 
528681824310SBarry Smith   PetscFunctionBegin;
52874994cf47SJed Brown   MatCheckPreallocated(A, 1);
528881824310SBarry Smith   imax  = a->imax;
528981824310SBarry Smith   ai    = a->i;
529081824310SBarry Smith   ailen = a->ilen;
529181824310SBarry Smith   aj    = a->j;
529281824310SBarry Smith   aa    = a->a;
529381824310SBarry Smith 
529481824310SBarry Smith   for (k = 0; k < m; k++) { /* loop over added rows */
529581824310SBarry Smith     row = im[k];
529681824310SBarry Smith     if (row < 0) continue;
52975f80ce2aSJacob Faibussowitsch     PetscCheck(row < A->rmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Row too large");
52989371c9d4SSatish Balay     rp   = aj + ai[row];
52999371c9d4SSatish Balay     ap   = aa + ai[row];
53009371c9d4SSatish Balay     rmax = imax[row];
53019371c9d4SSatish Balay     nrow = ailen[row];
530281824310SBarry Smith     low  = 0;
530381824310SBarry Smith     high = nrow;
530481824310SBarry Smith     for (l = 0; l < n; l++) { /* loop over added columns */
530581824310SBarry Smith       if (in[l] < 0) continue;
53065f80ce2aSJacob Faibussowitsch       PetscCheck(in[l] < A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Column too large");
530781824310SBarry Smith       col = in[l];
53082205254eSKarl Rupp       if (roworiented) value = v[l + k * n];
53092205254eSKarl Rupp       else value = v[k + l * m];
53102205254eSKarl Rupp 
531181824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
531281824310SBarry Smith 
53132205254eSKarl Rupp       if (col <= lastcol) low = 0;
53142205254eSKarl Rupp       else high = nrow;
531581824310SBarry Smith       lastcol = col;
531681824310SBarry Smith       while (high - low > 5) {
531781824310SBarry Smith         t = (low + high) / 2;
531881824310SBarry Smith         if (rp[t] > col) high = t;
531981824310SBarry Smith         else low = t;
532081824310SBarry Smith       }
532181824310SBarry Smith       for (i = low; i < high; i++) {
532281824310SBarry Smith         if (rp[i] > col) break;
532381824310SBarry Smith         if (rp[i] == col) {
532481824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
532581824310SBarry Smith           else ap[i] = value;
532681824310SBarry Smith           goto noinsert;
532781824310SBarry Smith         }
532881824310SBarry Smith       }
532981824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
533081824310SBarry Smith       if (nonew == 1) goto noinsert;
53315f80ce2aSJacob Faibussowitsch       PetscCheck(nonew != -1, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero in the matrix");
5332fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A, A->rmap->n, 1, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
53339371c9d4SSatish Balay       N = nrow++ - 1;
53349371c9d4SSatish Balay       a->nz++;
53359371c9d4SSatish Balay       high++;
533681824310SBarry Smith       /* shift up all the later entries in this row */
533781824310SBarry Smith       for (ii = N; ii >= i; ii--) {
533881824310SBarry Smith         rp[ii + 1] = rp[ii];
533981824310SBarry Smith         ap[ii + 1] = ap[ii];
534081824310SBarry Smith       }
534181824310SBarry Smith       rp[i] = col;
534281824310SBarry Smith       ap[i] = value;
5343e56f5c9eSBarry Smith       A->nonzerostate++;
534481824310SBarry Smith     noinsert:;
534581824310SBarry Smith       low = i + 1;
534681824310SBarry Smith     }
534781824310SBarry Smith     ailen[row] = nrow;
534881824310SBarry Smith   }
534981824310SBarry Smith   PetscFunctionReturnVoid();
535081824310SBarry Smith }
535198921bdaSJacob Faibussowitsch /* Undefining these here since they were redefined from their original definition above! No
535298921bdaSJacob Faibussowitsch  * other PETSc functions should be defined past this point, as it is impossible to recover the
535398921bdaSJacob Faibussowitsch  * original definitions */
53549566063dSJacob Faibussowitsch #undef PetscCall
535598921bdaSJacob Faibussowitsch #undef SETERRQ
5356