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