xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 421480d92be24cdb9933c60510b8e175c0a8d034)
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 
1126cec326SBarry Smith /* defines MatSetValues_Seq_Hash(), MatAssemblyEnd_Seq_Hash(), MatSetUp_Seq_Hash() */
1226cec326SBarry Smith #define TYPE AIJ
1326cec326SBarry Smith #define TYPE_BS
1426cec326SBarry Smith #include "../src/mat/impls/aij/seq/seqhashmatsetvalues.h"
1526cec326SBarry Smith #include "../src/mat/impls/aij/seq/seqhashmat.h"
1626cec326SBarry Smith #undef TYPE
1726cec326SBarry Smith #undef TYPE_BS
1826cec326SBarry Smith 
19*421480d9SBarry Smith MatGetDiagonalMarkers(SeqAIJ, 1)
20*421480d9SBarry Smith 
21ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A)
22d71ae5a4SJacob Faibussowitsch {
234099cc6bSBarry Smith   PetscBool flg;
244099cc6bSBarry Smith   char      type[256];
254099cc6bSBarry Smith 
264099cc6bSBarry Smith   PetscFunctionBegin;
27d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)A);
289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-mat_seqaij_type", "Matrix SeqAIJ type", "MatSeqAIJSetType", MatSeqAIJList, "seqaij", type, 256, &flg));
299566063dSJacob Faibussowitsch   if (flg) PetscCall(MatSeqAIJSetType(A, type));
30d0609cedSBarry Smith   PetscOptionsEnd();
313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
324099cc6bSBarry Smith }
334099cc6bSBarry Smith 
34ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetColumnReductions_SeqAIJ(Mat A, PetscInt type, PetscReal *reductions)
35d71ae5a4SJacob Faibussowitsch {
360716a85fSBarry Smith   PetscInt    i, m, n;
370716a85fSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
380716a85fSBarry Smith 
390716a85fSBarry Smith   PetscFunctionBegin;
409566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
419566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(reductions, n));
420716a85fSBarry Smith   if (type == NORM_2) {
43ad540459SPierre Jolivet     for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscAbsScalar(aij->a[i] * aij->a[i]);
440716a85fSBarry Smith   } else if (type == NORM_1) {
45ad540459SPierre Jolivet     for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]);
460716a85fSBarry Smith   } else if (type == NORM_INFINITY) {
47ad540459SPierre Jolivet     for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]), reductions[aij->j[i]]);
48857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
49ad540459SPierre Jolivet     for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscRealPart(aij->a[i]);
50857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
51ad540459SPierre Jolivet     for (i = 0; i < aij->i[m]; i++) reductions[aij->j[i]] += PetscImaginaryPart(aij->a[i]);
526adde796SStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type");
530716a85fSBarry Smith 
540716a85fSBarry Smith   if (type == NORM_2) {
55a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
56857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
57a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] /= m;
580716a85fSBarry Smith   }
593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
600716a85fSBarry Smith }
610716a85fSBarry Smith 
62ba38deedSJacob Faibussowitsch static PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A, IS *is)
63d71ae5a4SJacob Faibussowitsch {
643a062f41SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data;
653a062f41SBarry Smith   PetscInt        i, m = A->rmap->n, cnt = 0, bs = A->rmap->bs;
663a062f41SBarry Smith   const PetscInt *jj = a->j, *ii = a->i;
673a062f41SBarry Smith   PetscInt       *rows;
683a062f41SBarry Smith 
693a062f41SBarry Smith   PetscFunctionBegin;
703a062f41SBarry Smith   for (i = 0; i < m; i++) {
71ad540459SPierre Jolivet     if ((ii[i] != ii[i + 1]) && ((jj[ii[i]] < bs * (i / bs)) || (jj[ii[i + 1] - 1] > bs * ((i + bs) / bs) - 1))) cnt++;
723a062f41SBarry Smith   }
739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(cnt, &rows));
743a062f41SBarry Smith   cnt = 0;
753a062f41SBarry Smith   for (i = 0; i < m; i++) {
763a062f41SBarry Smith     if ((ii[i] != ii[i + 1]) && ((jj[ii[i]] < bs * (i / bs)) || (jj[ii[i + 1] - 1] > bs * ((i + bs) / bs) - 1))) {
773a062f41SBarry Smith       rows[cnt] = i;
783a062f41SBarry Smith       cnt++;
793a062f41SBarry Smith     }
803a062f41SBarry Smith   }
819566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cnt, rows, PETSC_OWN_POINTER, is));
823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
833a062f41SBarry Smith }
843a062f41SBarry Smith 
85d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A, PetscInt *nrows, PetscInt **zrows)
86d71ae5a4SJacob Faibussowitsch {
876ce1633cSBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
88fff043a9SJunchao Zhang   const MatScalar *aa;
896ce1633cSBarry Smith   PetscInt         i, m = A->rmap->n, cnt = 0;
90b2db7409Sstefano_zampini   const PetscInt  *ii = a->i, *jj = a->j, *diag;
916ce1633cSBarry Smith   PetscInt        *rows;
926ce1633cSBarry Smith 
936ce1633cSBarry Smith   PetscFunctionBegin;
949566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
95*421480d9SBarry Smith   PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, NULL));
966ce1633cSBarry Smith   for (i = 0; i < m; i++) {
97ad540459SPierre Jolivet     if ((diag[i] >= ii[i + 1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) cnt++;
986ce1633cSBarry Smith   }
999566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(cnt, &rows));
1006ce1633cSBarry Smith   cnt = 0;
1016ce1633cSBarry Smith   for (i = 0; i < m; i++) {
102ad540459SPierre Jolivet     if ((diag[i] >= ii[i + 1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) rows[cnt++] = i;
1036ce1633cSBarry Smith   }
104f1f41ecbSJed Brown   *nrows = cnt;
105f1f41ecbSJed Brown   *zrows = rows;
1069566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
1073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
108f1f41ecbSJed Brown }
109f1f41ecbSJed Brown 
110ba38deedSJacob Faibussowitsch static PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A, IS *zrows)
111d71ae5a4SJacob Faibussowitsch {
112f1f41ecbSJed Brown   PetscInt nrows, *rows;
113f1f41ecbSJed Brown 
114f1f41ecbSJed Brown   PetscFunctionBegin;
1150298fd71SBarry Smith   *zrows = NULL;
1169566063dSJacob Faibussowitsch   PetscCall(MatFindZeroDiagonals_SeqAIJ_Private(A, &nrows, &rows));
1179566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), nrows, rows, PETSC_OWN_POINTER, zrows));
1183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1196ce1633cSBarry Smith }
1206ce1633cSBarry Smith 
121ba38deedSJacob Faibussowitsch static PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A, IS *keptrows)
122d71ae5a4SJacob Faibussowitsch {
123b3a44c85SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
124b3a44c85SBarry Smith   const MatScalar *aa;
125b3a44c85SBarry Smith   PetscInt         m = A->rmap->n, cnt = 0;
126b3a44c85SBarry Smith   const PetscInt  *ii;
127b3a44c85SBarry Smith   PetscInt         n, i, j, *rows;
128b3a44c85SBarry Smith 
129b3a44c85SBarry Smith   PetscFunctionBegin;
1309566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
131f4259b30SLisandro Dalcin   *keptrows = NULL;
132b3a44c85SBarry Smith   ii        = a->i;
133b3a44c85SBarry Smith   for (i = 0; i < m; i++) {
134b3a44c85SBarry Smith     n = ii[i + 1] - ii[i];
135b3a44c85SBarry Smith     if (!n) {
136b3a44c85SBarry Smith       cnt++;
137b3a44c85SBarry Smith       goto ok1;
138b3a44c85SBarry Smith     }
1392e5835c6SStefano Zampini     for (j = ii[i]; j < ii[i + 1]; j++) {
140b3a44c85SBarry Smith       if (aa[j] != 0.0) goto ok1;
141b3a44c85SBarry Smith     }
142b3a44c85SBarry Smith     cnt++;
143b3a44c85SBarry Smith   ok1:;
144b3a44c85SBarry Smith   }
1452e5835c6SStefano Zampini   if (!cnt) {
1469566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
1473ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1482e5835c6SStefano Zampini   }
1499566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(A->rmap->n - cnt, &rows));
150b3a44c85SBarry Smith   cnt = 0;
151b3a44c85SBarry Smith   for (i = 0; i < m; i++) {
152b3a44c85SBarry Smith     n = ii[i + 1] - ii[i];
153b3a44c85SBarry Smith     if (!n) continue;
1542e5835c6SStefano Zampini     for (j = ii[i]; j < ii[i + 1]; j++) {
155b3a44c85SBarry Smith       if (aa[j] != 0.0) {
156b3a44c85SBarry Smith         rows[cnt++] = i;
157b3a44c85SBarry Smith         break;
158b3a44c85SBarry Smith       }
159b3a44c85SBarry Smith     }
160b3a44c85SBarry Smith   }
1619566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
1629566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cnt, rows, PETSC_OWN_POINTER, keptrows));
1633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
164b3a44c85SBarry Smith }
165b3a44c85SBarry Smith 
166d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDiagonalSet_SeqAIJ(Mat Y, Vec D, InsertMode is)
167d71ae5a4SJacob Faibussowitsch {
16899e65526SBarry Smith   PetscInt           i, m = Y->rmap->n;
16999e65526SBarry Smith   const PetscInt    *diag;
1702e5835c6SStefano Zampini   MatScalar         *aa;
17199e65526SBarry Smith   const PetscScalar *v;
172*421480d9SBarry Smith   PetscBool          diagDense;
17379299369SBarry Smith 
17479299369SBarry Smith   PetscFunctionBegin;
17509f38230SBarry Smith   if (Y->assembled) {
176*421480d9SBarry Smith     PetscCall(MatGetDiagonalMarkers_SeqAIJ(Y, &diag, &diagDense));
177*421480d9SBarry Smith     if (diagDense) {
1789566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(D, &v));
1799566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(Y, &aa));
18079299369SBarry Smith       if (is == INSERT_VALUES) {
181ad540459SPierre Jolivet         for (i = 0; i < m; i++) aa[diag[i]] = v[i];
18279299369SBarry Smith       } else {
183ad540459SPierre Jolivet         for (i = 0; i < m; i++) aa[diag[i]] += v[i];
18479299369SBarry Smith       }
1859566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJRestoreArray(Y, &aa));
1869566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(D, &v));
1873ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
18879299369SBarry Smith     }
18909f38230SBarry Smith   }
1909566063dSJacob Faibussowitsch   PetscCall(MatDiagonalSet_Default(Y, D, is));
1913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19209f38230SBarry Smith }
19379299369SBarry Smith 
194d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *m, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
195d71ae5a4SJacob Faibussowitsch {
196416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
19797f1f81fSBarry Smith   PetscInt    i, ishift;
19817ab2063SBarry Smith 
1993a40ed3dSBarry Smith   PetscFunctionBegin;
200f1f2ae84SBarry Smith   if (m) *m = A->rmap->n;
2013ba16761SJacob Faibussowitsch   if (!ia) PetscFunctionReturn(PETSC_SUCCESS);
202bfeeae90SHong Zhang   ishift = 0;
203b94d7dedSBarry Smith   if (symmetric && A->structurally_symmetric != PETSC_BOOL3_TRUE) {
2049566063dSJacob Faibussowitsch     PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n, a->i, a->j, PETSC_TRUE, ishift, oshift, (PetscInt **)ia, (PetscInt **)ja));
205bfeeae90SHong Zhang   } else if (oshift == 1) {
2061a83f524SJed Brown     PetscInt *tia;
207d0f46423SBarry Smith     PetscInt  nz = a->i[A->rmap->n];
2083b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
2099566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n + 1, &tia));
2101a83f524SJed Brown     for (i = 0; i < A->rmap->n + 1; i++) tia[i] = a->i[i] + 1;
2111a83f524SJed Brown     *ia = tia;
212ecc77c7aSBarry Smith     if (ja) {
2131a83f524SJed Brown       PetscInt *tja;
2149566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz + 1, &tja));
2151a83f524SJed Brown       for (i = 0; i < nz; i++) tja[i] = a->j[i] + 1;
2161a83f524SJed Brown       *ja = tja;
217ecc77c7aSBarry Smith     }
2186945ee14SBarry Smith   } else {
219ecc77c7aSBarry Smith     *ia = a->i;
220ecc77c7aSBarry Smith     if (ja) *ja = a->j;
221a2ce50c7SBarry Smith   }
2223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
223a2744918SBarry Smith }
224a2744918SBarry Smith 
225d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
226d71ae5a4SJacob Faibussowitsch {
2273a40ed3dSBarry Smith   PetscFunctionBegin;
2283ba16761SJacob Faibussowitsch   if (!ia) PetscFunctionReturn(PETSC_SUCCESS);
229b94d7dedSBarry Smith   if ((symmetric && A->structurally_symmetric != PETSC_BOOL3_TRUE) || oshift == 1) {
2309566063dSJacob Faibussowitsch     PetscCall(PetscFree(*ia));
2319566063dSJacob Faibussowitsch     if (ja) PetscCall(PetscFree(*ja));
232bcd2baecSBarry Smith   }
2333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23417ab2063SBarry Smith }
23517ab2063SBarry Smith 
236d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
237d71ae5a4SJacob Faibussowitsch {
2383b2fbd54SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
239d0f46423SBarry Smith   PetscInt    i, *collengths, *cia, *cja, n = A->cmap->n, m = A->rmap->n;
24097f1f81fSBarry Smith   PetscInt    nz = a->i[m], row, *jj, mr, col;
2413b2fbd54SBarry Smith 
2423a40ed3dSBarry Smith   PetscFunctionBegin;
243899cda47SBarry Smith   *nn = n;
2443ba16761SJacob Faibussowitsch   if (!ia) PetscFunctionReturn(PETSC_SUCCESS);
2453b2fbd54SBarry Smith   if (symmetric) {
2469566063dSJacob Faibussowitsch     PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n, a->i, a->j, PETSC_TRUE, 0, oshift, (PetscInt **)ia, (PetscInt **)ja));
2473b2fbd54SBarry Smith   } else {
2489566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(n, &collengths));
2499566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n + 1, &cia));
2509566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nz, &cja));
2513b2fbd54SBarry Smith     jj = a->j;
252ad540459SPierre Jolivet     for (i = 0; i < nz; i++) collengths[jj[i]]++;
2533b2fbd54SBarry Smith     cia[0] = oshift;
254ad540459SPierre Jolivet     for (i = 0; i < n; i++) cia[i + 1] = cia[i] + collengths[i];
2559566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(collengths, n));
2563b2fbd54SBarry Smith     jj = a->j;
257a93ec695SBarry Smith     for (row = 0; row < m; row++) {
258a93ec695SBarry Smith       mr = a->i[row + 1] - a->i[row];
259a93ec695SBarry Smith       for (i = 0; i < mr; i++) {
260bfeeae90SHong Zhang         col = *jj++;
2612205254eSKarl Rupp 
2623b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
2633b2fbd54SBarry Smith       }
2643b2fbd54SBarry Smith     }
2659566063dSJacob Faibussowitsch     PetscCall(PetscFree(collengths));
2669371c9d4SSatish Balay     *ia = cia;
2679371c9d4SSatish Balay     *ja = cja;
2683b2fbd54SBarry Smith   }
2693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2703b2fbd54SBarry Smith }
2713b2fbd54SBarry Smith 
272d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
273d71ae5a4SJacob Faibussowitsch {
2743a40ed3dSBarry Smith   PetscFunctionBegin;
2753ba16761SJacob Faibussowitsch   if (!ia) PetscFunctionReturn(PETSC_SUCCESS);
2763b2fbd54SBarry Smith 
2779566063dSJacob Faibussowitsch   PetscCall(PetscFree(*ia));
2789566063dSJacob Faibussowitsch   PetscCall(PetscFree(*ja));
2793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2803b2fbd54SBarry Smith }
2813b2fbd54SBarry Smith 
2827cee066cSHong Zhang /*
2837cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
2847cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
285040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
2867cee066cSHong Zhang */
287d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnIJ_SeqAIJ_Color(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *nn, const PetscInt *ia[], const PetscInt *ja[], PetscInt *spidx[], PetscBool *done)
288d71ae5a4SJacob Faibussowitsch {
2897cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data;
2907cee066cSHong Zhang   PetscInt        i, *collengths, *cia, *cja, n = A->cmap->n, m = A->rmap->n;
291071fcb05SBarry Smith   PetscInt        nz = a->i[m], row, mr, col, tmp;
2927cee066cSHong Zhang   PetscInt       *cspidx;
293071fcb05SBarry Smith   const PetscInt *jj;
2947cee066cSHong Zhang 
2957cee066cSHong Zhang   PetscFunctionBegin;
2967cee066cSHong Zhang   *nn = n;
2973ba16761SJacob Faibussowitsch   if (!ia) PetscFunctionReturn(PETSC_SUCCESS);
298625f6d37SHong Zhang 
2999566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(n, &collengths));
3009566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n + 1, &cia));
3019566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nz, &cja));
3029566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nz, &cspidx));
3037cee066cSHong Zhang   jj = a->j;
304ad540459SPierre Jolivet   for (i = 0; i < nz; i++) collengths[jj[i]]++;
3057cee066cSHong Zhang   cia[0] = oshift;
306ad540459SPierre Jolivet   for (i = 0; i < n; i++) cia[i + 1] = cia[i] + collengths[i];
3079566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(collengths, n));
3087cee066cSHong Zhang   jj = a->j;
3097cee066cSHong Zhang   for (row = 0; row < m; row++) {
3107cee066cSHong Zhang     mr = a->i[row + 1] - a->i[row];
3117cee066cSHong Zhang     for (i = 0; i < mr; i++) {
3127cee066cSHong Zhang       col         = *jj++;
313071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
314071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
315071fcb05SBarry Smith       cja[tmp]    = row + oshift;
3167cee066cSHong Zhang     }
3177cee066cSHong Zhang   }
3189566063dSJacob Faibussowitsch   PetscCall(PetscFree(collengths));
319071fcb05SBarry Smith   *ia    = cia;
320071fcb05SBarry Smith   *ja    = cja;
3217cee066cSHong Zhang   *spidx = cspidx;
3223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3237cee066cSHong Zhang }
3247cee066cSHong Zhang 
325d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreColumnIJ_SeqAIJ_Color(Mat A, PetscInt oshift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscInt *spidx[], PetscBool *done)
326d71ae5a4SJacob Faibussowitsch {
3277cee066cSHong Zhang   PetscFunctionBegin;
3289566063dSJacob Faibussowitsch   PetscCall(MatRestoreColumnIJ_SeqAIJ(A, oshift, symmetric, inodecompressed, n, ia, ja, done));
3299566063dSJacob Faibussowitsch   PetscCall(PetscFree(*spidx));
3303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3317cee066cSHong Zhang }
3327cee066cSHong Zhang 
333ba38deedSJacob Faibussowitsch static PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A, PetscInt row, const PetscScalar v[])
334d71ae5a4SJacob Faibussowitsch {
33587d4246cSBarry Smith   Mat_SeqAIJ  *a  = (Mat_SeqAIJ *)A->data;
33687d4246cSBarry Smith   PetscInt    *ai = a->i;
337fff043a9SJunchao Zhang   PetscScalar *aa;
33887d4246cSBarry Smith 
33987d4246cSBarry Smith   PetscFunctionBegin;
3409566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
3419566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aa + ai[row], v, ai[row + 1] - ai[row]));
3429566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
3433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34487d4246cSBarry Smith }
34587d4246cSBarry Smith 
346bd04181cSBarry Smith /*
347bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
348bd04181cSBarry Smith 
349bd04181cSBarry Smith       -   a single row of values is set with each call
350bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
351bd04181cSBarry Smith       -   the values are always added to the matrix, not set
352bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
353bd04181cSBarry Smith 
3541f763a69SBarry Smith      This does NOT assume the global column indices are sorted
355bd04181cSBarry Smith 
3561f763a69SBarry Smith */
357bd04181cSBarry Smith 
358af0996ceSBarry Smith #include <petsc/private/isimpl.h>
359d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is)
360d71ae5a4SJacob Faibussowitsch {
361189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data;
3621f763a69SBarry Smith   PetscInt        low, high, t, row, nrow, i, col, l;
3631f763a69SBarry Smith   const PetscInt *rp, *ai = a->i, *ailen = a->ilen, *aj = a->j;
3641f763a69SBarry Smith   PetscInt        lastcol = -1;
365fff043a9SJunchao Zhang   MatScalar      *ap, value, *aa;
366189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices, *cidx = A->cmap->mapping->indices;
367189e4007SBarry Smith 
368fff043a9SJunchao Zhang   PetscFunctionBegin;
3699566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
370f38dd0b8SBarry Smith   row  = ridx[im[0]];
3711f763a69SBarry Smith   rp   = aj + ai[row];
3721f763a69SBarry Smith   ap   = aa + ai[row];
3731f763a69SBarry Smith   nrow = ailen[row];
374189e4007SBarry Smith   low  = 0;
375189e4007SBarry Smith   high = nrow;
376189e4007SBarry Smith   for (l = 0; l < n; l++) { /* loop over added columns */
377189e4007SBarry Smith     col   = cidx[in[l]];
378f38dd0b8SBarry Smith     value = v[l];
379189e4007SBarry Smith 
380189e4007SBarry Smith     if (col <= lastcol) low = 0;
381189e4007SBarry Smith     else high = nrow;
382189e4007SBarry Smith     lastcol = col;
383189e4007SBarry Smith     while (high - low > 5) {
384189e4007SBarry Smith       t = (low + high) / 2;
385189e4007SBarry Smith       if (rp[t] > col) high = t;
386189e4007SBarry Smith       else low = t;
387189e4007SBarry Smith     }
388189e4007SBarry Smith     for (i = low; i < high; i++) {
389189e4007SBarry Smith       if (rp[i] == col) {
3901f763a69SBarry Smith         ap[i] += value;
391189e4007SBarry Smith         low = i + 1;
3921f763a69SBarry Smith         break;
393189e4007SBarry Smith       }
394189e4007SBarry Smith     }
395189e4007SBarry Smith   }
3969566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
3973ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
398189e4007SBarry Smith }
399189e4007SBarry Smith 
400d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValues_SeqAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is)
401d71ae5a4SJacob Faibussowitsch {
402416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
403e2ee6c50SBarry Smith   PetscInt   *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N;
40497f1f81fSBarry Smith   PetscInt   *imax = a->imax, *ai = a->i, *ailen = a->ilen;
405e2ee6c50SBarry Smith   PetscInt   *aj = a->j, nonew = a->nonew, lastcol = -1;
406ce496241SStefano Zampini   MatScalar  *ap = NULL, value = 0.0, *aa;
407ace3abfcSBarry Smith   PetscBool   ignorezeroentries = a->ignorezeroentries;
408ace3abfcSBarry Smith   PetscBool   roworiented       = a->roworiented;
40917ab2063SBarry Smith 
4103a40ed3dSBarry Smith   PetscFunctionBegin;
4119566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
41217ab2063SBarry Smith   for (k = 0; k < m; k++) { /* loop over added rows */
413416022c9SBarry Smith     row = im[k];
4145ef9f2a5SBarry Smith     if (row < 0) continue;
4156bdcaf15SBarry 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);
4168e3a54c0SPierre Jolivet     rp = PetscSafePointerPlusOffset(aj, ai[row]);
4178e3a54c0SPierre Jolivet     if (!A->structure_only) ap = PetscSafePointerPlusOffset(aa, ai[row]);
4189371c9d4SSatish Balay     rmax = imax[row];
4199371c9d4SSatish Balay     nrow = ailen[row];
420416022c9SBarry Smith     low  = 0;
421c71e6ed7SBarry Smith     high = nrow;
42217ab2063SBarry Smith     for (l = 0; l < n; l++) { /* loop over added columns */
4235ef9f2a5SBarry Smith       if (in[l] < 0) continue;
4246bdcaf15SBarry 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);
425bfeeae90SHong Zhang       col = in[l];
426071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k * n] : v[k + l * m];
427071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
42836db0b34SBarry Smith 
4292205254eSKarl Rupp       if (col <= lastcol) low = 0;
4302205254eSKarl Rupp       else high = nrow;
431e2ee6c50SBarry Smith       lastcol = col;
432416022c9SBarry Smith       while (high - low > 5) {
433416022c9SBarry Smith         t = (low + high) / 2;
434416022c9SBarry Smith         if (rp[t] > col) high = t;
435416022c9SBarry Smith         else low = t;
43617ab2063SBarry Smith       }
437416022c9SBarry Smith       for (i = low; i < high; i++) {
43817ab2063SBarry Smith         if (rp[i] > col) break;
43917ab2063SBarry Smith         if (rp[i] == col) {
440876c6284SHong Zhang           if (!A->structure_only) {
4410c0d7e18SFande Kong             if (is == ADD_VALUES) {
4420c0d7e18SFande Kong               ap[i] += value;
4430c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
4449371c9d4SSatish Balay             } else ap[i] = value;
445720833daSHong Zhang           }
446e44c0bd4SBarry Smith           low = i + 1;
44717ab2063SBarry Smith           goto noinsert;
44817ab2063SBarry Smith         }
44917ab2063SBarry Smith       }
450dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
451c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
45208401ef6SPierre 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);
453720833daSHong Zhang       if (A->structure_only) {
454876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A, A->rmap->n, 1, nrow, row, col, rmax, ai, aj, rp, imax, nonew, MatScalar);
455720833daSHong Zhang       } else {
456fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A, A->rmap->n, 1, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
457720833daSHong Zhang       }
4589371c9d4SSatish Balay       N = nrow++ - 1;
4599371c9d4SSatish Balay       a->nz++;
4609371c9d4SSatish Balay       high++;
461416022c9SBarry Smith       /* shift up all the later entries in this row */
4629566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(rp + i + 1, rp + i, N - i + 1));
46317ab2063SBarry Smith       rp[i] = col;
464580bdb30SBarry Smith       if (!A->structure_only) {
4659566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(ap + i + 1, ap + i, N - i + 1));
466580bdb30SBarry Smith         ap[i] = value;
467580bdb30SBarry Smith       }
468416022c9SBarry Smith       low = i + 1;
469e44c0bd4SBarry Smith     noinsert:;
47017ab2063SBarry Smith     }
47117ab2063SBarry Smith     ailen[row] = nrow;
47217ab2063SBarry Smith   }
4739566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
4743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47517ab2063SBarry Smith }
47617ab2063SBarry Smith 
477ba38deedSJacob Faibussowitsch static PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is)
478d71ae5a4SJacob Faibussowitsch {
47919b08ed1SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
48019b08ed1SBarry Smith   PetscInt   *rp, k, row;
48119b08ed1SBarry Smith   PetscInt   *ai = a->i;
48219b08ed1SBarry Smith   PetscInt   *aj = a->j;
483fff043a9SJunchao Zhang   MatScalar  *aa, *ap;
48419b08ed1SBarry Smith 
48519b08ed1SBarry Smith   PetscFunctionBegin;
48628b400f6SJacob Faibussowitsch   PetscCheck(!A->was_assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call on assembled matrix.");
48708401ef6SPierre 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);
488fff043a9SJunchao Zhang 
4899566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
49019b08ed1SBarry Smith   for (k = 0; k < m; k++) { /* loop over added rows */
49119b08ed1SBarry Smith     row = im[k];
49219b08ed1SBarry Smith     rp  = aj + ai[row];
4938e3a54c0SPierre Jolivet     ap  = PetscSafePointerPlusOffset(aa, ai[row]);
49419b08ed1SBarry Smith 
4959566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(rp, in, n * sizeof(PetscInt)));
49619b08ed1SBarry Smith     if (!A->structure_only) {
49719b08ed1SBarry Smith       if (v) {
4989566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(ap, v, n * sizeof(PetscScalar)));
49919b08ed1SBarry Smith         v += n;
50019b08ed1SBarry Smith       } else {
5019566063dSJacob Faibussowitsch         PetscCall(PetscMemzero(ap, n * sizeof(PetscScalar)));
50219b08ed1SBarry Smith       }
50319b08ed1SBarry Smith     }
50419b08ed1SBarry Smith     a->ilen[row]  = n;
50519b08ed1SBarry Smith     a->imax[row]  = n;
50619b08ed1SBarry Smith     a->i[row + 1] = a->i[row] + n;
50719b08ed1SBarry Smith     a->nz += n;
50819b08ed1SBarry Smith   }
5099566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
5103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51119b08ed1SBarry Smith }
51219b08ed1SBarry Smith 
51319b08ed1SBarry Smith /*@
51419b08ed1SBarry Smith   MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix.
51519b08ed1SBarry Smith 
51619b08ed1SBarry Smith   Input Parameters:
51711a5261eSBarry Smith + A       - the `MATSEQAIJ` matrix
51819b08ed1SBarry Smith - nztotal - bound on the number of nonzeros
51919b08ed1SBarry Smith 
52019b08ed1SBarry Smith   Level: advanced
52119b08ed1SBarry Smith 
52219b08ed1SBarry Smith   Notes:
52319b08ed1SBarry 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.
52411a5261eSBarry Smith   Simply call `MatSetValues()` after this call to provide the matrix entries in the usual manner. This matrix may be used
52519b08ed1SBarry Smith   as always with multiple matrix assemblies.
52619b08ed1SBarry Smith 
5271cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MAT_SORTED_FULL`, `MatSetValues()`, `MatSeqAIJSetPreallocation()`
52819b08ed1SBarry Smith @*/
529d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A, PetscInt nztotal)
530d71ae5a4SJacob Faibussowitsch {
53119b08ed1SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
53219b08ed1SBarry Smith 
53319b08ed1SBarry Smith   PetscFunctionBegin;
5349566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
5359566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
53619b08ed1SBarry Smith   a->maxnz = nztotal;
5373a7d0413SPierre Jolivet   if (!a->imax) PetscCall(PetscMalloc1(A->rmap->n, &a->imax));
53819b08ed1SBarry Smith   if (!a->ilen) {
5399566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n, &a->ilen));
54019b08ed1SBarry Smith   } else {
5419566063dSJacob Faibussowitsch     PetscCall(PetscMemzero(a->ilen, A->rmap->n * sizeof(PetscInt)));
54219b08ed1SBarry Smith   }
54319b08ed1SBarry Smith 
54419b08ed1SBarry Smith   /* allocate the matrix space */
5459f0612e4SBarry Smith   PetscCall(PetscShmgetAllocateArray(A->rmap->n + 1, sizeof(PetscInt), (void **)&a->i));
5469f0612e4SBarry Smith   PetscCall(PetscShmgetAllocateArray(nztotal, sizeof(PetscInt), (void **)&a->j));
5479f0612e4SBarry Smith   a->free_ij = PETSC_TRUE;
54819b08ed1SBarry Smith   if (A->structure_only) {
54919b08ed1SBarry Smith     a->free_a = PETSC_FALSE;
55019b08ed1SBarry Smith   } else {
5519f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(nztotal, sizeof(PetscScalar), (void **)&a->a));
55219b08ed1SBarry Smith     a->free_a = PETSC_TRUE;
55319b08ed1SBarry Smith   }
5549f0612e4SBarry Smith   a->i[0]           = 0;
55519b08ed1SBarry Smith   A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation;
55619b08ed1SBarry Smith   A->preallocated   = PETSC_TRUE;
5573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55819b08ed1SBarry Smith }
55919b08ed1SBarry Smith 
560ba38deedSJacob Faibussowitsch static PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode is)
561d71ae5a4SJacob Faibussowitsch {
562071fcb05SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
563071fcb05SBarry Smith   PetscInt   *rp, k, row;
564071fcb05SBarry Smith   PetscInt   *ai = a->i, *ailen = a->ilen;
565071fcb05SBarry Smith   PetscInt   *aj = a->j;
566fff043a9SJunchao Zhang   MatScalar  *aa, *ap;
567071fcb05SBarry Smith 
568071fcb05SBarry Smith   PetscFunctionBegin;
5699566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
570071fcb05SBarry Smith   for (k = 0; k < m; k++) { /* loop over added rows */
571071fcb05SBarry Smith     row = im[k];
5726bdcaf15SBarry 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);
573071fcb05SBarry Smith     rp = aj + ai[row];
574071fcb05SBarry Smith     ap = aa + ai[row];
57548a46eb9SPierre Jolivet     if (!A->was_assembled) PetscCall(PetscMemcpy(rp, in, n * sizeof(PetscInt)));
576071fcb05SBarry Smith     if (!A->structure_only) {
577071fcb05SBarry Smith       if (v) {
5789566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(ap, v, n * sizeof(PetscScalar)));
579071fcb05SBarry Smith         v += n;
580071fcb05SBarry Smith       } else {
5819566063dSJacob Faibussowitsch         PetscCall(PetscMemzero(ap, n * sizeof(PetscScalar)));
582071fcb05SBarry Smith       }
583071fcb05SBarry Smith     }
584071fcb05SBarry Smith     ailen[row] = n;
585071fcb05SBarry Smith     a->nz += n;
586071fcb05SBarry Smith   }
5879566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
5883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
589071fcb05SBarry Smith }
590071fcb05SBarry Smith 
591ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetValues_SeqAIJ(Mat A, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], PetscScalar v[])
592d71ae5a4SJacob Faibussowitsch {
5937eb43aa7SLois Curfman McInnes   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
59497f1f81fSBarry Smith   PetscInt        *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j;
59597f1f81fSBarry Smith   PetscInt        *ai = a->i, *ailen = a->ilen;
5964e208921SJed Brown   const MatScalar *ap, *aa;
5977eb43aa7SLois Curfman McInnes 
5983a40ed3dSBarry Smith   PetscFunctionBegin;
5994e208921SJed Brown   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
6007eb43aa7SLois Curfman McInnes   for (k = 0; k < m; k++) { /* loop over rows */
6017eb43aa7SLois Curfman McInnes     row = im[k];
6029371c9d4SSatish Balay     if (row < 0) {
6039371c9d4SSatish Balay       v += n;
6049371c9d4SSatish Balay       continue;
6059371c9d4SSatish Balay     } /* negative row */
60654c59aa7SJacob 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);
6078e3a54c0SPierre Jolivet     rp   = PetscSafePointerPlusOffset(aj, ai[row]);
6088e3a54c0SPierre Jolivet     ap   = PetscSafePointerPlusOffset(aa, ai[row]);
6097eb43aa7SLois Curfman McInnes     nrow = ailen[row];
6107eb43aa7SLois Curfman McInnes     for (l = 0; l < n; l++) { /* loop over columns */
6119371c9d4SSatish Balay       if (in[l] < 0) {
6129371c9d4SSatish Balay         v++;
6139371c9d4SSatish Balay         continue;
6149371c9d4SSatish Balay       } /* negative column */
61554c59aa7SJacob 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);
616bfeeae90SHong Zhang       col  = in[l];
6179371c9d4SSatish Balay       high = nrow;
6189371c9d4SSatish Balay       low  = 0; /* assume unsorted */
6197eb43aa7SLois Curfman McInnes       while (high - low > 5) {
6207eb43aa7SLois Curfman McInnes         t = (low + high) / 2;
6217eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
6227eb43aa7SLois Curfman McInnes         else low = t;
6237eb43aa7SLois Curfman McInnes       }
6247eb43aa7SLois Curfman McInnes       for (i = low; i < high; i++) {
6257eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
6267eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
627b49de8d1SLois Curfman McInnes           *v++ = ap[i];
6287eb43aa7SLois Curfman McInnes           goto finished;
6297eb43aa7SLois Curfman McInnes         }
6307eb43aa7SLois Curfman McInnes       }
63197e567efSBarry Smith       *v++ = 0.0;
6327eb43aa7SLois Curfman McInnes     finished:;
6337eb43aa7SLois Curfman McInnes     }
6347eb43aa7SLois Curfman McInnes   }
6354e208921SJed Brown   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
6363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6377eb43aa7SLois Curfman McInnes }
6387eb43aa7SLois Curfman McInnes 
639ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
640d71ae5a4SJacob Faibussowitsch {
6413ea6fe3dSLisandro Dalcin   Mat_SeqAIJ        *A = (Mat_SeqAIJ *)mat->data;
642c898d852SStefano Zampini   const PetscScalar *av;
6433ea6fe3dSLisandro Dalcin   PetscInt           header[4], M, N, m, nz, i;
6443ea6fe3dSLisandro Dalcin   PetscInt          *rowlens;
64517ab2063SBarry Smith 
6463a40ed3dSBarry Smith   PetscFunctionBegin;
6479566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
6482205254eSKarl Rupp 
6493ea6fe3dSLisandro Dalcin   M  = mat->rmap->N;
6503ea6fe3dSLisandro Dalcin   N  = mat->cmap->N;
6513ea6fe3dSLisandro Dalcin   m  = mat->rmap->n;
6523ea6fe3dSLisandro Dalcin   nz = A->nz;
653416022c9SBarry Smith 
6543ea6fe3dSLisandro Dalcin   /* write matrix header */
6553ea6fe3dSLisandro Dalcin   header[0] = MAT_FILE_CLASSID;
6569371c9d4SSatish Balay   header[1] = M;
6579371c9d4SSatish Balay   header[2] = N;
6589371c9d4SSatish Balay   header[3] = nz;
6599566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT));
660416022c9SBarry Smith 
6613ea6fe3dSLisandro Dalcin   /* fill in and store row lengths */
6629566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m, &rowlens));
6633ea6fe3dSLisandro Dalcin   for (i = 0; i < m; i++) rowlens[i] = A->i[i + 1] - A->i[i];
664e457bb90SBarry Smith   if (PetscDefined(USE_DEBUG)) {
665e457bb90SBarry Smith     PetscInt mnz = 0;
666e457bb90SBarry Smith 
667e457bb90SBarry Smith     for (i = 0; i < m; i++) mnz += rowlens[i];
668e457bb90SBarry Smith     PetscCheck(nz == mnz, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Row lens %" PetscInt_FMT " do not sum to nz %" PetscInt_FMT, mnz, nz);
669e457bb90SBarry Smith   }
6709566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWrite(viewer, rowlens, m, PETSC_INT));
6719566063dSJacob Faibussowitsch   PetscCall(PetscFree(rowlens));
6723ea6fe3dSLisandro Dalcin   /* store column indices */
6739566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWrite(viewer, A->j, nz, PETSC_INT));
674416022c9SBarry Smith   /* store nonzero values */
6759566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(mat, &av));
6769566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWrite(viewer, av, nz, PETSC_SCALAR));
6779566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(mat, &av));
678b37d52dbSMark F. Adams 
6793ea6fe3dSLisandro Dalcin   /* write block size option to the viewer's .info file */
6809566063dSJacob Faibussowitsch   PetscCall(MatView_Binary_BlockSizes(mat, viewer));
6813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68217ab2063SBarry Smith }
683416022c9SBarry Smith 
684d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A, PetscViewer viewer)
685d71ae5a4SJacob Faibussowitsch {
6867dc0baabSHong Zhang   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
6877dc0baabSHong Zhang   PetscInt    i, k, m = A->rmap->N;
6887dc0baabSHong Zhang 
6897dc0baabSHong Zhang   PetscFunctionBegin;
6909566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
6917dc0baabSHong Zhang   for (i = 0; i < m; i++) {
6929566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
69348a46eb9SPierre Jolivet     for (k = a->i[i]; k < a->i[i + 1]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ") ", a->j[k]));
6949566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
6957dc0baabSHong Zhang   }
6969566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
6973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6987dc0baabSHong Zhang }
6997dc0baabSHong Zhang 
700ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_SeqAIJ_ASCII(Mat A, PetscViewer viewer)
701d71ae5a4SJacob Faibussowitsch {
702416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
703c898d852SStefano Zampini   const PetscScalar *av;
70460e0710aSBarry Smith   PetscInt           i, j, m = A->rmap->n;
705e060cb09SBarry Smith   const char        *name;
706f3ef73ceSBarry Smith   PetscViewerFormat  format;
70717ab2063SBarry Smith 
7083a40ed3dSBarry Smith   PetscFunctionBegin;
7097dc0baabSHong Zhang   if (A->structure_only) {
7109566063dSJacob Faibussowitsch     PetscCall(MatView_SeqAIJ_ASCII_structonly(A, viewer));
7113ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
7127dc0baabSHong Zhang   }
71343e49210SHong Zhang 
7149566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
715bd6a2ce3SJunchao Zhang   // By petsc's rule, even PETSC_VIEWER_ASCII_INFO_DETAIL doesn't print matrix entries
7163ba16761SJacob Faibussowitsch   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS);
7172e5835c6SStefano Zampini 
718c898d852SStefano Zampini   /* trigger copy to CPU if needed */
7199566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
7209566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
72171c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
72297f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
72360e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m - 1]) || (a->j[a->nz - 1] != A->cmap->n - 1))) {
724c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
725d00d2cf4SBarry Smith       nofinalvalue = 1;
726d00d2cf4SBarry Smith     }
7279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
7289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", m, A->cmap->n));
7299566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "%% Nonzeros = %" PetscInt_FMT " \n", a->nz));
730fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
7319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = zeros(%" PetscInt_FMT ",4);\n", a->nz + nofinalvalue));
732fbfe6fa7SJed Brown #else
7339566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = zeros(%" PetscInt_FMT ",3);\n", a->nz + nofinalvalue));
734fbfe6fa7SJed Brown #endif
7359566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "zzz = [\n"));
73617ab2063SBarry Smith 
73717ab2063SBarry Smith     for (i = 0; i < m; i++) {
73860e0710aSBarry Smith       for (j = a->i[i]; j < a->i[i + 1]; j++) {
739aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
7409566063dSJacob 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])));
74117ab2063SBarry Smith #else
7429566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e\n", i + 1, a->j[j] + 1, (double)a->a[j]));
74317ab2063SBarry Smith #endif
74417ab2063SBarry Smith       }
74517ab2063SBarry Smith     }
746d00d2cf4SBarry Smith     if (nofinalvalue) {
747c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
7489566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e %18.16e\n", m, A->cmap->n, 0., 0.));
749c337ccceSJed Brown #else
7509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e\n", m, A->cmap->n, 0.0));
751c337ccceSJed Brown #endif
752d00d2cf4SBarry Smith     }
7539566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)A, &name));
7549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "];\n %s = spconvert(zzz);\n", name));
7559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
756fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
7579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
75844cd7ae7SLois Curfman McInnes     for (i = 0; i < m; i++) {
7599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
76060e0710aSBarry Smith       for (j = a->i[i]; j < a->i[i + 1]; j++) {
761aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
76236db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
7639566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j])));
76436db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
7659566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)-PetscImaginaryPart(a->a[j])));
76636db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
7679566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j])));
7686831982aSBarry Smith         }
76944cd7ae7SLois Curfman McInnes #else
7709566063dSJacob Faibussowitsch         if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j]));
77144cd7ae7SLois Curfman McInnes #endif
77244cd7ae7SLois Curfman McInnes       }
7739566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
77444cd7ae7SLois Curfman McInnes     }
7759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
776fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
77797f1f81fSBarry Smith     PetscInt nzd = 0, fshift = 1, *sptr;
7789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
7799566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m + 1, &sptr));
780496be53dSLois Curfman McInnes     for (i = 0; i < m; i++) {
781496be53dSLois Curfman McInnes       sptr[i] = nzd + 1;
78260e0710aSBarry Smith       for (j = a->i[i]; j < a->i[i + 1]; j++) {
783496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
784aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
78536db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
786496be53dSLois Curfman McInnes #else
787496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
788496be53dSLois Curfman McInnes #endif
789496be53dSLois Curfman McInnes         }
790496be53dSLois Curfman McInnes       }
791496be53dSLois Curfman McInnes     }
7922e44a96cSLois Curfman McInnes     sptr[m] = nzd + 1;
7939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT "\n\n", m, nzd));
7942e44a96cSLois Curfman McInnes     for (i = 0; i < m + 1; i += 6) {
7952205254eSKarl Rupp       if (i + 4 < m) {
7969566063dSJacob 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]));
7972205254eSKarl Rupp       } else if (i + 3 < m) {
7989566063dSJacob 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]));
7992205254eSKarl Rupp       } else if (i + 2 < m) {
8009566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2], sptr[i + 3]));
8012205254eSKarl Rupp       } else if (i + 1 < m) {
8029566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1], sptr[i + 2]));
8032205254eSKarl Rupp       } else if (i < m) {
8049566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT "\n", sptr[i], sptr[i + 1]));
8052205254eSKarl Rupp       } else {
8069566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "\n", sptr[i]));
8072205254eSKarl Rupp       }
808496be53dSLois Curfman McInnes     }
8099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
8109566063dSJacob Faibussowitsch     PetscCall(PetscFree(sptr));
811496be53dSLois Curfman McInnes     for (i = 0; i < m; i++) {
81260e0710aSBarry Smith       for (j = a->i[i]; j < a->i[i + 1]; j++) {
8139566063dSJacob Faibussowitsch         if (a->j[j] >= i) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " ", a->j[j] + fshift));
814496be53dSLois Curfman McInnes       }
8159566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
816496be53dSLois Curfman McInnes     }
8179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
818496be53dSLois Curfman McInnes     for (i = 0; i < m; i++) {
81960e0710aSBarry Smith       for (j = a->i[i]; j < a->i[i + 1]; j++) {
820496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
821aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
82248a46eb9SPierre 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])));
823496be53dSLois Curfman McInnes #else
8249566063dSJacob Faibussowitsch           if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer, " %18.16e ", (double)a->a[j]));
825496be53dSLois Curfman McInnes #endif
826496be53dSLois Curfman McInnes         }
827496be53dSLois Curfman McInnes       }
8289566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
829496be53dSLois Curfman McInnes     }
8309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
831fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
83297f1f81fSBarry Smith     PetscInt    cnt = 0, jcnt;
83387828ca2SBarry Smith     PetscScalar value;
83468f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
83568f1ed48SBarry Smith     PetscBool realonly = PETSC_TRUE;
83668f1ed48SBarry Smith 
83768f1ed48SBarry Smith     for (i = 0; i < a->i[m]; i++) {
83868f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
83968f1ed48SBarry Smith         realonly = PETSC_FALSE;
84068f1ed48SBarry Smith         break;
84168f1ed48SBarry Smith       }
84268f1ed48SBarry Smith     }
84368f1ed48SBarry Smith #endif
84402594712SBarry Smith 
8459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
84602594712SBarry Smith     for (i = 0; i < m; i++) {
84702594712SBarry Smith       jcnt = 0;
848d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
849e24b481bSBarry Smith         if (jcnt < a->i[i + 1] - a->i[i] && j == a->j[cnt]) {
85002594712SBarry Smith           value = a->a[cnt++];
851e24b481bSBarry Smith           jcnt++;
85202594712SBarry Smith         } else {
85302594712SBarry Smith           value = 0.0;
85402594712SBarry Smith         }
855aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
85668f1ed48SBarry Smith         if (realonly) {
8579566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e ", (double)PetscRealPart(value)));
85868f1ed48SBarry Smith         } else {
8599566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e+%7.5e i ", (double)PetscRealPart(value), (double)PetscImaginaryPart(value)));
86068f1ed48SBarry Smith         }
86102594712SBarry Smith #else
8629566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %7.5e ", (double)value));
86302594712SBarry Smith #endif
86402594712SBarry Smith       }
8659566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
86602594712SBarry Smith     }
8679566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
8683c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
869150b93efSMatthew G. Knepley     PetscInt fshift = 1;
8709566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
8713c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
8729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "%%%%MatrixMarket matrix coordinate complex general\n"));
8733c215bfdSMatthew Knepley #else
8749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "%%%%MatrixMarket matrix coordinate real general\n"));
8753c215bfdSMatthew Knepley #endif
8769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", m, A->cmap->n, a->nz));
8773c215bfdSMatthew Knepley     for (i = 0; i < m; i++) {
87860e0710aSBarry Smith       for (j = a->i[i]; j < a->i[i + 1]; j++) {
8793c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
8809566063dSJacob 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])));
8813c215bfdSMatthew Knepley #else
8829566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %g\n", i + fshift, a->j[j] + fshift, (double)a->a[j]));
8833c215bfdSMatthew Knepley #endif
8843c215bfdSMatthew Knepley       }
8853c215bfdSMatthew Knepley     }
8869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
8873a40ed3dSBarry Smith   } else {
8889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
889d5f3da31SBarry Smith     if (A->factortype) {
890*421480d9SBarry Smith       const PetscInt *adiag;
891*421480d9SBarry Smith 
892*421480d9SBarry Smith       PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &adiag, NULL));
89316cd7e1dSShri Abhyankar       for (i = 0; i < m; i++) {
8949566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
89516cd7e1dSShri Abhyankar         /* L part */
89660e0710aSBarry Smith         for (j = a->i[i]; j < a->i[i + 1]; j++) {
89716cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
89816cd7e1dSShri Abhyankar           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 if (PetscImaginaryPart(a->a[j]) < 0.0) {
9019566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)(-PetscImaginaryPart(a->a[j]))));
90216cd7e1dSShri Abhyankar           } else {
9039566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j])));
90416cd7e1dSShri Abhyankar           }
90516cd7e1dSShri Abhyankar #else
9069566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j]));
90716cd7e1dSShri Abhyankar #endif
90816cd7e1dSShri Abhyankar         }
90916cd7e1dSShri Abhyankar         /* diagonal */
910*421480d9SBarry Smith         j = adiag[i];
91116cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
91216cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
913835f2295SStefano Zampini           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(1 / a->a[j]), (double)PetscImaginaryPart(1 / a->a[j])));
91416cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
915835f2295SStefano Zampini           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(1 / a->a[j]), (double)(-PetscImaginaryPart(1 / a->a[j]))));
91616cd7e1dSShri Abhyankar         } else {
917835f2295SStefano Zampini           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(1 / a->a[j])));
91816cd7e1dSShri Abhyankar         }
91916cd7e1dSShri Abhyankar #else
920835f2295SStefano Zampini         PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)(1 / a->a[j])));
92116cd7e1dSShri Abhyankar #endif
92216cd7e1dSShri Abhyankar 
92316cd7e1dSShri Abhyankar         /* U part */
924*421480d9SBarry Smith         for (j = adiag[i + 1] + 1; j < adiag[i]; j++) {
92516cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
92616cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
9279566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j])));
92816cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9299566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)(-PetscImaginaryPart(a->a[j]))));
93016cd7e1dSShri Abhyankar           } else {
9319566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j])));
93216cd7e1dSShri Abhyankar           }
93316cd7e1dSShri Abhyankar #else
9349566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j]));
93516cd7e1dSShri Abhyankar #endif
93616cd7e1dSShri Abhyankar         }
9379566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
93816cd7e1dSShri Abhyankar       }
93916cd7e1dSShri Abhyankar     } else {
94017ab2063SBarry Smith       for (i = 0; i < m; i++) {
9419566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
94260e0710aSBarry Smith         for (j = a->i[i]; j < a->i[i + 1]; j++) {
943aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
94436db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
9459566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)PetscImaginaryPart(a->a[j])));
94636db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9479566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g - %g i)", a->j[j], (double)PetscRealPart(a->a[j]), (double)-PetscImaginaryPart(a->a[j])));
9483a40ed3dSBarry Smith           } else {
9499566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)PetscRealPart(a->a[j])));
95017ab2063SBarry Smith           }
95117ab2063SBarry Smith #else
9529566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", a->j[j], (double)a->a[j]));
95317ab2063SBarry Smith #endif
95417ab2063SBarry Smith         }
9559566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
95617ab2063SBarry Smith       }
95716cd7e1dSShri Abhyankar     }
9589566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
95917ab2063SBarry Smith   }
9609566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
9613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
962416022c9SBarry Smith }
963416022c9SBarry Smith 
9649804daf3SBarry Smith #include <petscdraw.h>
965ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw, void *Aa)
966d71ae5a4SJacob Faibussowitsch {
967480ef9eaSBarry Smith   Mat                A = (Mat)Aa;
968416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
969383922c3SLisandro Dalcin   PetscInt           i, j, m = A->rmap->n;
970383922c3SLisandro Dalcin   int                color;
971b05fc000SLisandro Dalcin   PetscReal          xl, yl, xr, yr, x_l, x_r, y_l, y_r;
972b0a32e0cSBarry Smith   PetscViewer        viewer;
973f3ef73ceSBarry Smith   PetscViewerFormat  format;
974fff043a9SJunchao Zhang   const PetscScalar *aa;
975cddf8d76SBarry Smith 
9763a40ed3dSBarry Smith   PetscFunctionBegin;
9779566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
9789566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
9799566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
980383922c3SLisandro Dalcin 
981416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
9829566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
983fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
984d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
9850513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
986b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
987416022c9SBarry Smith     for (i = 0; i < m; i++) {
9889371c9d4SSatish Balay       y_l = m - i - 1.0;
9899371c9d4SSatish Balay       y_r = y_l + 1.0;
990bfeeae90SHong Zhang       for (j = a->i[i]; j < a->i[i + 1]; j++) {
9919371c9d4SSatish Balay         x_l = a->j[j];
9929371c9d4SSatish Balay         x_r = x_l + 1.0;
993fff043a9SJunchao Zhang         if (PetscRealPart(aa[j]) >= 0.) continue;
9949566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
995cddf8d76SBarry Smith       }
996cddf8d76SBarry Smith     }
997b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
998cddf8d76SBarry Smith     for (i = 0; i < m; i++) {
9999371c9d4SSatish Balay       y_l = m - i - 1.0;
10009371c9d4SSatish Balay       y_r = y_l + 1.0;
1001bfeeae90SHong Zhang       for (j = a->i[i]; j < a->i[i + 1]; j++) {
10029371c9d4SSatish Balay         x_l = a->j[j];
10039371c9d4SSatish Balay         x_r = x_l + 1.0;
1004fff043a9SJunchao Zhang         if (aa[j] != 0.) continue;
10059566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1006cddf8d76SBarry Smith       }
1007cddf8d76SBarry Smith     }
1008b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
1009cddf8d76SBarry Smith     for (i = 0; i < m; i++) {
10109371c9d4SSatish Balay       y_l = m - i - 1.0;
10119371c9d4SSatish Balay       y_r = y_l + 1.0;
1012bfeeae90SHong Zhang       for (j = a->i[i]; j < a->i[i + 1]; j++) {
10139371c9d4SSatish Balay         x_l = a->j[j];
10149371c9d4SSatish Balay         x_r = x_l + 1.0;
1015fff043a9SJunchao Zhang         if (PetscRealPart(aa[j]) <= 0.) continue;
10169566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1017416022c9SBarry Smith       }
1018416022c9SBarry Smith     }
1019d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
10200513a670SBarry Smith   } else {
10210513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
10220513a670SBarry Smith     /* first determine max of all nonzero values */
1023b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1024383922c3SLisandro Dalcin     PetscInt  nz = a->nz, count = 0;
1025b0a32e0cSBarry Smith     PetscDraw popup;
10260513a670SBarry Smith 
10270513a670SBarry Smith     for (i = 0; i < nz; i++) {
1028fff043a9SJunchao Zhang       if (PetscAbsScalar(aa[i]) > maxv) maxv = PetscAbsScalar(aa[i]);
10290513a670SBarry Smith     }
1030383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
10319566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetPopup(draw, &popup));
10329566063dSJacob Faibussowitsch     PetscCall(PetscDrawScalePopup(popup, minv, maxv));
1033383922c3SLisandro Dalcin 
1034d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
10350513a670SBarry Smith     for (i = 0; i < m; i++) {
1036383922c3SLisandro Dalcin       y_l = m - i - 1.0;
1037383922c3SLisandro Dalcin       y_r = y_l + 1.0;
1038bfeeae90SHong Zhang       for (j = a->i[i]; j < a->i[i + 1]; j++) {
1039383922c3SLisandro Dalcin         x_l   = a->j[j];
1040383922c3SLisandro Dalcin         x_r   = x_l + 1.0;
1041fff043a9SJunchao Zhang         color = PetscDrawRealToColor(PetscAbsScalar(aa[count]), minv, maxv);
10429566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
10430513a670SBarry Smith         count++;
10440513a670SBarry Smith       }
10450513a670SBarry Smith     }
1046d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
10470513a670SBarry Smith   }
10489566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
10493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1050480ef9eaSBarry Smith }
1051cddf8d76SBarry Smith 
10529804daf3SBarry Smith #include <petscdraw.h>
1053ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_SeqAIJ_Draw(Mat A, PetscViewer viewer)
1054d71ae5a4SJacob Faibussowitsch {
1055b0a32e0cSBarry Smith   PetscDraw draw;
105636db0b34SBarry Smith   PetscReal xr, yr, xl, yl, h, w;
1057ace3abfcSBarry Smith   PetscBool isnull;
1058480ef9eaSBarry Smith 
1059480ef9eaSBarry Smith   PetscFunctionBegin;
10609566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
10619566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
10623ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
1063480ef9eaSBarry Smith 
10649371c9d4SSatish Balay   xr = A->cmap->n;
10659371c9d4SSatish Balay   yr = A->rmap->n;
10669371c9d4SSatish Balay   h  = yr / 10.0;
10679371c9d4SSatish Balay   w  = xr / 10.0;
10689371c9d4SSatish Balay   xr += w;
10699371c9d4SSatish Balay   yr += h;
10709371c9d4SSatish Balay   xl = -w;
10719371c9d4SSatish Balay   yl = -h;
10729566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
10739566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
10749566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqAIJ_Draw_Zoom, A));
10759566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
10769566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
10773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1078416022c9SBarry Smith }
1079416022c9SBarry Smith 
1080d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqAIJ(Mat A, PetscViewer viewer)
1081d71ae5a4SJacob Faibussowitsch {
10829f196a02SMartin Diehl   PetscBool isascii, isbinary, isdraw;
1083416022c9SBarry Smith 
10843a40ed3dSBarry Smith   PetscFunctionBegin;
10859f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
10869566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
10879566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
10889f196a02SMartin Diehl   if (isascii) PetscCall(MatView_SeqAIJ_ASCII(A, viewer));
10891baa6e33SBarry Smith   else if (isbinary) PetscCall(MatView_SeqAIJ_Binary(A, viewer));
10901baa6e33SBarry Smith   else if (isdraw) PetscCall(MatView_SeqAIJ_Draw(A, viewer));
10919566063dSJacob Faibussowitsch   PetscCall(MatView_SeqAIJ_Inode(A, viewer));
10923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
109317ab2063SBarry Smith }
109419bcc07fSBarry Smith 
1095d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A, MatAssemblyType mode)
1096d71ae5a4SJacob Faibussowitsch {
1097416022c9SBarry Smith   Mat_SeqAIJ *a      = (Mat_SeqAIJ *)A->data;
1098580bdb30SBarry Smith   PetscInt    fshift = 0, i, *ai = a->i, *aj = a->j, *imax = a->imax;
109907425a8dSBarry Smith   PetscInt    m = A->rmap->n, *ip, N, *ailen = a->ilen, rmax = 0;
110054f21887SBarry Smith   MatScalar  *aa    = a->a, *ap;
11013447b6efSHong Zhang   PetscReal   ratio = 0.6;
110217ab2063SBarry Smith 
11033a40ed3dSBarry Smith   PetscFunctionBegin;
11043ba16761SJacob Faibussowitsch   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(PETSC_SUCCESS);
1105b215bc84SStefano Zampini   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) {
110655a7f34eSJunchao Zhang     /* we need to respect users asking to use or not the inodes routine in between matrix assemblies, e.g., via MatSetOption(A, MAT_USE_INODES, val) */
110755a7f34eSJunchao Zhang     PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A, mode)); /* read the sparsity pattern */
11083ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1109b215bc84SStefano Zampini   }
111017ab2063SBarry Smith 
111143ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
111217ab2063SBarry Smith   for (i = 1; i < m; i++) {
1113416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
111417ab2063SBarry Smith     fshift += imax[i - 1] - ailen[i - 1];
111594a9d846SBarry Smith     rmax = PetscMax(rmax, ailen[i]);
111617ab2063SBarry Smith     if (fshift) {
1117bfeeae90SHong Zhang       ip = aj + ai[i];
1118bfeeae90SHong Zhang       ap = aa + ai[i];
111917ab2063SBarry Smith       N  = ailen[i];
11209566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ip - fshift, ip, N));
112148a46eb9SPierre Jolivet       if (!A->structure_only) PetscCall(PetscArraymove(ap - fshift, ap, N));
112217ab2063SBarry Smith     }
112317ab2063SBarry Smith     ai[i] = ai[i - 1] + ailen[i - 1];
112417ab2063SBarry Smith   }
112517ab2063SBarry Smith   if (m) {
112617ab2063SBarry Smith     fshift += imax[m - 1] - ailen[m - 1];
112717ab2063SBarry Smith     ai[m] = ai[m - 1] + ailen[m - 1];
112817ab2063SBarry Smith   }
112917ab2063SBarry Smith   /* reset ilen and imax for each row */
11307b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1131396832f4SHong Zhang   if (A->structure_only) {
11329566063dSJacob Faibussowitsch     PetscCall(PetscFree(a->imax));
11339566063dSJacob Faibussowitsch     PetscCall(PetscFree(a->ilen));
1134396832f4SHong Zhang   } else { /* !A->structure_only */
113517ab2063SBarry Smith     for (i = 0; i < m; i++) {
113617ab2063SBarry Smith       ailen[i] = imax[i] = ai[i + 1] - ai[i];
11377b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i + 1] - ai[i]) > 0);
113817ab2063SBarry Smith     }
1139396832f4SHong Zhang   }
1140bfeeae90SHong Zhang   a->nz = ai[m];
1141aed4548fSBarry 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);
11429566063dSJacob 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));
11439566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Number of mallocs during MatSetValues() is %" PetscInt_FMT "\n", a->reallocs));
11449566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Maximum nonzeros in any row is %" PetscInt_FMT "\n", rmax));
11452205254eSKarl Rupp 
11468e58a170SBarry Smith   A->info.mallocs += a->reallocs;
1147dd5f02e7SSatish Balay   a->reallocs         = 0;
11486712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
114936db0b34SBarry Smith   a->rmax             = rmax;
11504e220ebcSLois Curfman McInnes 
115148a46eb9SPierre Jolivet   if (!A->structure_only) PetscCall(MatCheckCompressedRow(A, a->nonzerorowcnt, &a->compressedrow, a->i, m, ratio));
11529566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A, mode));
11533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
115417ab2063SBarry Smith }
115517ab2063SBarry Smith 
1156ba38deedSJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqAIJ(Mat A)
1157d71ae5a4SJacob Faibussowitsch {
115899cafbc1SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
115999cafbc1SBarry Smith   PetscInt    i, nz = a->nz;
11602e5835c6SStefano Zampini   MatScalar  *aa;
116199cafbc1SBarry Smith 
116299cafbc1SBarry Smith   PetscFunctionBegin;
11639566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
116499cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscRealPart(aa[i]);
11659566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
11663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
116799cafbc1SBarry Smith }
116899cafbc1SBarry Smith 
1169ba38deedSJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
1170d71ae5a4SJacob Faibussowitsch {
117199cafbc1SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
117299cafbc1SBarry Smith   PetscInt    i, nz = a->nz;
11732e5835c6SStefano Zampini   MatScalar  *aa;
117499cafbc1SBarry Smith 
117599cafbc1SBarry Smith   PetscFunctionBegin;
11769566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
117799cafbc1SBarry Smith   for (i = 0; i < nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
11789566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
11793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
118099cafbc1SBarry Smith }
118199cafbc1SBarry Smith 
1182d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
1183d71ae5a4SJacob Faibussowitsch {
1184fff043a9SJunchao Zhang   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
1185fff043a9SJunchao Zhang   MatScalar  *aa;
11863a40ed3dSBarry Smith 
11873a40ed3dSBarry Smith   PetscFunctionBegin;
11889566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayWrite(A, &aa));
11899566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(aa, a->i[A->rmap->n]));
11909566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayWrite(A, &aa));
11913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
119217ab2063SBarry Smith }
1193416022c9SBarry Smith 
1194674b392bSAlexander static PetscErrorCode MatReset_SeqAIJ(Mat A)
1195d71ae5a4SJacob Faibussowitsch {
1196416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
1197d5d45c9bSBarry Smith 
11983a40ed3dSBarry Smith   PetscFunctionBegin;
1199b4e2f619SBarry Smith   if (A->hash_active) {
1200e3c72094SPierre Jolivet     A->ops[0] = a->cops;
1201b4e2f619SBarry Smith     PetscCall(PetscHMapIJVDestroy(&a->ht));
1202b4e2f619SBarry Smith     PetscCall(PetscFree(a->dnz));
1203b4e2f619SBarry Smith     A->hash_active = PETSC_FALSE;
1204b4e2f619SBarry Smith   }
1205b4e2f619SBarry Smith 
12063ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)A, "Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT, A->rmap->n, A->cmap->n, a->nz));
12079566063dSJacob Faibussowitsch   PetscCall(MatSeqXAIJFreeAIJ(A, &a->a, &a->j, &a->i));
12089566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
12099566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
12109566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->diag));
12119566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->ibdiag));
12129566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->imax));
12139566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->ilen));
12149566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->ipre));
12159566063dSJacob Faibussowitsch   PetscCall(PetscFree3(a->idiag, a->mdiag, a->ssor_work));
12169566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->solve_work));
12179566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->icol));
12189566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->saved_values));
1219820d003aSStefano Zampini   a->compressedrow.use = PETSC_FALSE;
12209566063dSJacob Faibussowitsch   PetscCall(PetscFree2(a->compressedrow.i, a->compressedrow.rindex));
12219566063dSJacob Faibussowitsch   PetscCall(MatDestroy_SeqAIJ_Inode(A));
1222674b392bSAlexander   PetscFunctionReturn(PETSC_SUCCESS);
1223674b392bSAlexander }
1224674b392bSAlexander 
1225674b392bSAlexander static PetscErrorCode MatResetHash_SeqAIJ(Mat A)
1226674b392bSAlexander {
1227674b392bSAlexander   PetscFunctionBegin;
1228674b392bSAlexander   PetscCall(MatReset_SeqAIJ(A));
1229674b392bSAlexander   PetscCall(MatCreate_SeqAIJ_Inode(A));
1230674b392bSAlexander   PetscCall(MatSetUp_Seq_Hash(A));
1231674b392bSAlexander   A->nonzerostate++;
1232674b392bSAlexander   PetscFunctionReturn(PETSC_SUCCESS);
1233674b392bSAlexander }
1234674b392bSAlexander 
1235674b392bSAlexander PetscErrorCode MatDestroy_SeqAIJ(Mat A)
1236674b392bSAlexander {
1237674b392bSAlexander   PetscFunctionBegin;
1238674b392bSAlexander   PetscCall(MatReset_SeqAIJ(A));
12399566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
1240901853e0SKris Buschelman 
12416718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
12426718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
12436718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
12446718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
12456718818eSStefano Zampini      due to different matrix sizes */
12469566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc__ab_dense", NULL));
12476718818eSStefano Zampini 
12489566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL));
12492e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "PetscMatlabEnginePut_C", NULL));
12502e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "PetscMatlabEngineGet_C", NULL));
12519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetColumnIndices_C", NULL));
12529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatStoreValues_C", NULL));
12539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatRetrieveValues_C", NULL));
12549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqsbaij_C", NULL));
12559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqbaij_C", NULL));
12569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijperm_C", NULL));
12572e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijsell_C", NULL));
12582e956fe4SStefano Zampini #if defined(PETSC_HAVE_MKL_SPARSE)
12592e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijmkl_C", NULL));
12602e956fe4SStefano Zampini #endif
12614222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
12629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijcusparse_C", NULL));
12639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_seqaij_C", NULL));
12649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaijcusparse_C", NULL));
12654222ddf1SHong Zhang #endif
1266d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_HIP)
1267d5e393b6SSuyash Tandon   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijhipsparse_C", NULL));
1268d5e393b6SSuyash Tandon   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijhipsparse_seqaij_C", NULL));
1269d5e393b6SSuyash Tandon   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaijhipsparse_C", NULL));
1270d5e393b6SSuyash Tandon #endif
12713d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
12729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijkokkos_C", NULL));
12733d0639e7SStefano Zampini #endif
12749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijcrl_C", NULL));
1275af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
12769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_elemental_C", NULL));
1277af8000cdSHong Zhang #endif
1278d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE))
12799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_scalapack_C", NULL));
1280d24d4204SJose E. Roman #endif
128163c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
12829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_hypre_C", NULL));
12839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_transpose_seqaij_seqaij_C", NULL));
128463c07aadSStefano Zampini #endif
12859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqdense_C", NULL));
12869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqsell_C", NULL));
12879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_is_C", NULL));
12889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatIsTranspose_C", NULL));
12892e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatIsHermitianTranspose_C", NULL));
12909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", NULL));
12919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatResetPreallocation_C", NULL));
1292674b392bSAlexander   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatResetHash_C", NULL));
12939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJSetPreallocationCSR_C", NULL));
12949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatReorderForNonzeroDiagonal_C", NULL));
12959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_is_seqaij_C", NULL));
12969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqdense_seqaij_C", NULL));
12979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_seqaij_C", NULL));
12989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSeqAIJKron_C", NULL));
12999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL));
13009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL));
13012e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL));
13022e956fe4SStefano Zampini   /* these calls do not belong here: the subclasses Duplicate/Destroy are wrong */
13032e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaijsell_seqaij_C", NULL));
13042e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaijperm_seqaij_C", NULL));
13052e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqaij_seqaijviennacl_C", NULL));
13062e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijviennacl_seqdense_C", NULL));
13072e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijviennacl_seqaij_C", NULL));
13083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
130917ab2063SBarry Smith }
131017ab2063SBarry Smith 
1311d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetOption_SeqAIJ(Mat A, MatOption op, PetscBool flg)
1312d71ae5a4SJacob Faibussowitsch {
1313416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
13143a40ed3dSBarry Smith 
13153a40ed3dSBarry Smith   PetscFunctionBegin;
1316a65d3064SKris Buschelman   switch (op) {
1317d71ae5a4SJacob Faibussowitsch   case MAT_ROW_ORIENTED:
1318d71ae5a4SJacob Faibussowitsch     a->roworiented = flg;
1319d71ae5a4SJacob Faibussowitsch     break;
1320d71ae5a4SJacob Faibussowitsch   case MAT_KEEP_NONZERO_PATTERN:
1321d71ae5a4SJacob Faibussowitsch     a->keepnonzeropattern = flg;
1322d71ae5a4SJacob Faibussowitsch     break;
1323d71ae5a4SJacob Faibussowitsch   case MAT_NEW_NONZERO_LOCATIONS:
1324d71ae5a4SJacob Faibussowitsch     a->nonew = (flg ? 0 : 1);
1325d71ae5a4SJacob Faibussowitsch     break;
1326d71ae5a4SJacob Faibussowitsch   case MAT_NEW_NONZERO_LOCATION_ERR:
1327d71ae5a4SJacob Faibussowitsch     a->nonew = (flg ? -1 : 0);
1328d71ae5a4SJacob Faibussowitsch     break;
1329d71ae5a4SJacob Faibussowitsch   case MAT_NEW_NONZERO_ALLOCATION_ERR:
1330d71ae5a4SJacob Faibussowitsch     a->nonew = (flg ? -2 : 0);
1331d71ae5a4SJacob Faibussowitsch     break;
1332d71ae5a4SJacob Faibussowitsch   case MAT_UNUSED_NONZERO_LOCATION_ERR:
1333d71ae5a4SJacob Faibussowitsch     a->nounused = (flg ? -1 : 0);
1334d71ae5a4SJacob Faibussowitsch     break;
1335d71ae5a4SJacob Faibussowitsch   case MAT_IGNORE_ZERO_ENTRIES:
1336d71ae5a4SJacob Faibussowitsch     a->ignorezeroentries = flg;
1337d71ae5a4SJacob Faibussowitsch     break;
1338d71ae5a4SJacob Faibussowitsch   case MAT_USE_INODES:
1339d71ae5a4SJacob Faibussowitsch     PetscCall(MatSetOption_SeqAIJ_Inode(A, MAT_USE_INODES, flg));
1340d71ae5a4SJacob Faibussowitsch     break;
1341d71ae5a4SJacob Faibussowitsch   case MAT_SUBMAT_SINGLEIS:
1342d71ae5a4SJacob Faibussowitsch     A->submat_singleis = flg;
1343d71ae5a4SJacob Faibussowitsch     break;
1344071fcb05SBarry Smith   case MAT_SORTED_FULL:
1345071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1346071fcb05SBarry Smith     else A->ops->setvalues = MatSetValues_SeqAIJ;
1347071fcb05SBarry Smith     break;
1348d71ae5a4SJacob Faibussowitsch   case MAT_FORM_EXPLICIT_TRANSPOSE:
1349d71ae5a4SJacob Faibussowitsch     A->form_explicit_transpose = flg;
1350d71ae5a4SJacob Faibussowitsch     break;
1351d71ae5a4SJacob Faibussowitsch   default:
1352888c827cSStefano Zampini     break;
1353a65d3064SKris Buschelman   }
13543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
135517ab2063SBarry Smith }
135617ab2063SBarry Smith 
13579ee18893SBarry Smith PETSC_INTERN PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A, Vec v)
1358d71ae5a4SJacob Faibussowitsch {
1359416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
1360*421480d9SBarry Smith   PetscInt           n, *ai = a->i;
1361c898d852SStefano Zampini   PetscScalar       *x;
1362c898d852SStefano Zampini   const PetscScalar *aa;
1363*421480d9SBarry Smith   const PetscInt    *diag;
1364*421480d9SBarry Smith   PetscBool          diagDense;
136517ab2063SBarry Smith 
13663a40ed3dSBarry Smith   PetscFunctionBegin;
13679566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &n));
136808401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
13699566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
1370d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1371*421480d9SBarry Smith     PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, NULL));
13729566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(v, &x));
1373*421480d9SBarry Smith     for (PetscInt i = 0; i < n; i++) x[i] = 1.0 / aa[diag[i]];
13749566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(v, &x));
13759566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
13763ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
137735e7444dSHong Zhang   }
137835e7444dSHong Zhang 
1379*421480d9SBarry Smith   PetscCheck(A->factortype == MAT_FACTOR_NONE, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for factor matrices that are not ILU or LU");
1380*421480d9SBarry Smith   PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, &diagDense));
13819566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v, &x));
1382*421480d9SBarry Smith   if (diagDense) {
1383*421480d9SBarry Smith     for (PetscInt i = 0; i < n; i++) x[i] = aa[diag[i]];
1384*421480d9SBarry Smith   } else {
1385*421480d9SBarry Smith     for (PetscInt i = 0; i < n; i++) x[i] = (diag[i] == ai[i + 1]) ? 0.0 : aa[diag[i]];
138617ab2063SBarry Smith   }
13879566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v, &x));
13889566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
13893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
139017ab2063SBarry Smith }
139117ab2063SBarry Smith 
1392c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1393d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A, Vec xx, Vec zz, Vec yy)
1394d71ae5a4SJacob Faibussowitsch {
1395416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
13965f22a7b3SSebastian Grimberg   const MatScalar   *aa;
1397d9ca1df4SBarry Smith   PetscScalar       *y;
1398d9ca1df4SBarry Smith   const PetscScalar *x;
1399d0f46423SBarry Smith   PetscInt           m = A->rmap->n;
14005c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
14015f22a7b3SSebastian Grimberg   const MatScalar  *v;
1402a77337e4SBarry Smith   PetscScalar       alpha;
1403d9ca1df4SBarry Smith   PetscInt          n, i, j;
1404d9ca1df4SBarry Smith   const PetscInt   *idx, *ii, *ridx = NULL;
14053447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1406ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
14075c897100SBarry Smith #endif
140817ab2063SBarry Smith 
14093a40ed3dSBarry Smith   PetscFunctionBegin;
14109566063dSJacob Faibussowitsch   if (zz != yy) PetscCall(VecCopy(zz, yy));
14119566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
14129566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
14139566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
14145c897100SBarry Smith 
14155c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1416fff043a9SJunchao Zhang   fortranmulttransposeaddaij_(&m, x, a->i, a->j, aa, y);
14175c897100SBarry Smith #else
14183447b6efSHong Zhang   if (usecprow) {
14193447b6efSHong Zhang     m    = cprow.nrows;
14203447b6efSHong Zhang     ii   = cprow.i;
14217b2bb3b9SHong Zhang     ridx = cprow.rindex;
14223447b6efSHong Zhang   } else {
14233447b6efSHong Zhang     ii = a->i;
14243447b6efSHong Zhang   }
142517ab2063SBarry Smith   for (i = 0; i < m; i++) {
14263447b6efSHong Zhang     idx = a->j + ii[i];
1427fff043a9SJunchao Zhang     v   = aa + ii[i];
14283447b6efSHong Zhang     n   = ii[i + 1] - ii[i];
14293447b6efSHong Zhang     if (usecprow) {
14307b2bb3b9SHong Zhang       alpha = x[ridx[i]];
14313447b6efSHong Zhang     } else {
143217ab2063SBarry Smith       alpha = x[i];
14333447b6efSHong Zhang     }
143404fbf559SBarry Smith     for (j = 0; j < n; j++) y[idx[j]] += alpha * v[j];
143517ab2063SBarry Smith   }
14365c897100SBarry Smith #endif
14379566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * a->nz));
14389566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
14399566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
14409566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
14413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
144217ab2063SBarry Smith }
144317ab2063SBarry Smith 
1444d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTranspose_SeqAIJ(Mat A, Vec xx, Vec yy)
1445d71ae5a4SJacob Faibussowitsch {
14465c897100SBarry Smith   PetscFunctionBegin;
14479566063dSJacob Faibussowitsch   PetscCall(VecSet(yy, 0.0));
14489566063dSJacob Faibussowitsch   PetscCall(MatMultTransposeAdd_SeqAIJ(A, xx, yy, yy));
14493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14505c897100SBarry Smith }
14515c897100SBarry Smith 
1452c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
145378b84d54SShri Abhyankar 
1454d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMult_SeqAIJ(Mat A, Vec xx, Vec yy)
1455d71ae5a4SJacob Faibussowitsch {
1456416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
1457d9fead3dSBarry Smith   PetscScalar       *y;
145854f21887SBarry Smith   const PetscScalar *x;
14595914357eSBarry Smith   const MatScalar   *a_a;
1460003131ecSBarry Smith   PetscInt           m = A->rmap->n;
14615914357eSBarry Smith   const PetscInt    *ii, *ridx = NULL;
1462ace3abfcSBarry Smith   PetscBool          usecprow = a->compressedrow.use;
146317ab2063SBarry Smith 
1464b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
146597952fefSHong Zhang   #pragma disjoint(*x, *y, *aa)
1466fee21e36SBarry Smith #endif
1467fee21e36SBarry Smith 
14683a40ed3dSBarry Smith   PetscFunctionBegin;
1469b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
14709566063dSJacob Faibussowitsch     PetscCall(MatMult_SeqAIJ_Inode(A, xx, yy));
14713ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1472b215bc84SStefano Zampini   }
14739566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &a_a));
14749566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
14759566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1476416022c9SBarry Smith   ii = a->i;
14774eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
14789566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(y, m));
147997952fefSHong Zhang     m    = a->compressedrow.nrows;
148097952fefSHong Zhang     ii   = a->compressedrow.i;
148197952fefSHong Zhang     ridx = a->compressedrow.rindex;
14825914357eSBarry Smith     PetscPragmaUseOMPKernels(parallel for)
14835914357eSBarry Smith     for (PetscInt i = 0; i < m; i++) {
14845914357eSBarry Smith       PetscInt           n   = ii[i + 1] - ii[i];
14855914357eSBarry Smith       const PetscInt    *aj  = a->j + ii[i];
14865914357eSBarry Smith       const PetscScalar *aa  = a_a + ii[i];
14875914357eSBarry Smith       PetscScalar        sum = 0.0;
1488003131ecSBarry Smith       PetscSparseDensePlusDot(sum, x, aa, aj, n);
1489003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1490c9a1b032SJunchao Zhang       y[ridx[i]] = sum;
149197952fefSHong Zhang     }
149297952fefSHong Zhang   } else { /* do not use compressed row format */
1493b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
14945914357eSBarry Smith     fortranmultaij_(&m, x, ii, a->j, a_a, y);
1495b05257ddSBarry Smith #else
14965914357eSBarry Smith     PetscPragmaUseOMPKernels(parallel for)
14975914357eSBarry Smith     for (PetscInt i = 0; i < m; i++) {
14985914357eSBarry Smith       PetscInt           n   = ii[i + 1] - ii[i];
14995914357eSBarry Smith       const PetscInt    *aj  = a->j + ii[i];
15005914357eSBarry Smith       const PetscScalar *aa  = a_a + ii[i];
15015914357eSBarry Smith       PetscScalar        sum = 0.0;
1502003131ecSBarry Smith       PetscSparseDensePlusDot(sum, x, aa, aj, n);
150317ab2063SBarry Smith       y[i] = sum;
150417ab2063SBarry Smith     }
15058d195f9aSBarry Smith #endif
1506b05257ddSBarry Smith   }
15079566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * a->nz - a->nonzerorowcnt));
15089566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
15099566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
15109566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a));
15113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
151217ab2063SBarry Smith }
151317ab2063SBarry Smith 
1514ba38deedSJacob Faibussowitsch // HACK!!!!! Used by src/mat/tests/ex170.c
1515ba38deedSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatMultMax_SeqAIJ(Mat A, Vec xx, Vec yy)
1516d71ae5a4SJacob Faibussowitsch {
1517b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
1518b434eb95SMatthew G. Knepley   PetscScalar       *y;
1519b434eb95SMatthew G. Knepley   const PetscScalar *x;
1520fff043a9SJunchao Zhang   const MatScalar   *aa, *a_a;
1521b434eb95SMatthew G. Knepley   PetscInt           m = A->rmap->n;
1522b434eb95SMatthew G. Knepley   const PetscInt    *aj, *ii, *ridx   = NULL;
1523b434eb95SMatthew G. Knepley   PetscInt           n, i, nonzerorow = 0;
1524b434eb95SMatthew G. Knepley   PetscScalar        sum;
1525b434eb95SMatthew G. Knepley   PetscBool          usecprow = a->compressedrow.use;
1526b434eb95SMatthew G. Knepley 
1527b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1528b434eb95SMatthew G. Knepley   #pragma disjoint(*x, *y, *aa)
1529b434eb95SMatthew G. Knepley #endif
1530b434eb95SMatthew G. Knepley 
1531b434eb95SMatthew G. Knepley   PetscFunctionBegin;
15329566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &a_a));
15339566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
15349566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1535b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1536b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1537b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1538b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1539b434eb95SMatthew G. Knepley     for (i = 0; i < m; i++) {
1540b434eb95SMatthew G. Knepley       n   = ii[i + 1] - ii[i];
1541b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1542fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1543b434eb95SMatthew G. Knepley       sum = 0.0;
1544b434eb95SMatthew G. Knepley       nonzerorow += (n > 0);
1545b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum, x, aa, aj, n);
1546b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1547b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1548b434eb95SMatthew G. Knepley     }
1549b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
15503d3eaba7SBarry Smith     ii = a->i;
1551b434eb95SMatthew G. Knepley     for (i = 0; i < m; i++) {
1552b434eb95SMatthew G. Knepley       n   = ii[i + 1] - ii[i];
1553b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1554fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1555b434eb95SMatthew G. Knepley       sum = 0.0;
1556b434eb95SMatthew G. Knepley       nonzerorow += (n > 0);
1557b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum, x, aa, aj, n);
1558b434eb95SMatthew G. Knepley       y[i] = sum;
1559b434eb95SMatthew G. Knepley     }
1560b434eb95SMatthew G. Knepley   }
15619566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * a->nz - nonzerorow));
15629566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
15639566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
15649566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a));
15653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1566b434eb95SMatthew G. Knepley }
1567b434eb95SMatthew G. Knepley 
1568ba38deedSJacob Faibussowitsch // HACK!!!!! Used by src/mat/tests/ex170.c
1569ba38deedSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatMultAddMax_SeqAIJ(Mat A, Vec xx, Vec yy, Vec zz)
1570d71ae5a4SJacob Faibussowitsch {
1571b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
1572b434eb95SMatthew G. Knepley   PetscScalar       *y, *z;
1573b434eb95SMatthew G. Knepley   const PetscScalar *x;
1574fff043a9SJunchao Zhang   const MatScalar   *aa, *a_a;
1575b434eb95SMatthew G. Knepley   PetscInt           m = A->rmap->n, *aj, *ii;
1576b434eb95SMatthew G. Knepley   PetscInt           n, i, *ridx = NULL;
1577b434eb95SMatthew G. Knepley   PetscScalar        sum;
1578b434eb95SMatthew G. Knepley   PetscBool          usecprow = a->compressedrow.use;
1579b434eb95SMatthew G. Knepley 
1580b434eb95SMatthew G. Knepley   PetscFunctionBegin;
15819566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &a_a));
15829566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
15839566063dSJacob Faibussowitsch   PetscCall(VecGetArrayPair(yy, zz, &y, &z));
1584b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
158548a46eb9SPierre Jolivet     if (zz != yy) PetscCall(PetscArraycpy(z, y, m));
1586b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1587b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1588b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1589b434eb95SMatthew G. Knepley     for (i = 0; i < m; i++) {
1590b434eb95SMatthew G. Knepley       n   = ii[i + 1] - ii[i];
1591b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1592fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1593b434eb95SMatthew G. Knepley       sum = y[*ridx];
1594b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum, x, aa, aj, n);
1595b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1596b434eb95SMatthew G. Knepley     }
1597b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
15983d3eaba7SBarry Smith     ii = a->i;
1599b434eb95SMatthew G. Knepley     for (i = 0; i < m; i++) {
1600b434eb95SMatthew G. Knepley       n   = ii[i + 1] - ii[i];
1601b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1602fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1603b434eb95SMatthew G. Knepley       sum = y[i];
1604b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum, x, aa, aj, n);
1605b434eb95SMatthew G. Knepley       z[i] = sum;
1606b434eb95SMatthew G. Knepley     }
1607b434eb95SMatthew G. Knepley   }
16089566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * a->nz));
16099566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
16109566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayPair(yy, zz, &y, &z));
16119566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a));
16123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1613b434eb95SMatthew G. Knepley }
1614b434eb95SMatthew G. Knepley 
1615c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1616d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultAdd_SeqAIJ(Mat A, Vec xx, Vec yy, Vec zz)
1617d71ae5a4SJacob Faibussowitsch {
1618416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
1619f15663dcSBarry Smith   PetscScalar       *y, *z;
1620f15663dcSBarry Smith   const PetscScalar *x;
16215914357eSBarry Smith   const MatScalar   *a_a;
16225914357eSBarry Smith   const PetscInt    *ii, *ridx = NULL;
16235914357eSBarry Smith   PetscInt           m        = A->rmap->n;
1624ace3abfcSBarry Smith   PetscBool          usecprow = a->compressedrow.use;
16259ea0dfa2SSatish Balay 
16263a40ed3dSBarry Smith   PetscFunctionBegin;
1627b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
16289566063dSJacob Faibussowitsch     PetscCall(MatMultAdd_SeqAIJ_Inode(A, xx, yy, zz));
16293ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1630b215bc84SStefano Zampini   }
16319566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &a_a));
16329566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
16339566063dSJacob Faibussowitsch   PetscCall(VecGetArrayPair(yy, zz, &y, &z));
16344eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
163548a46eb9SPierre Jolivet     if (zz != yy) PetscCall(PetscArraycpy(z, y, m));
163697952fefSHong Zhang     m    = a->compressedrow.nrows;
163797952fefSHong Zhang     ii   = a->compressedrow.i;
163897952fefSHong Zhang     ridx = a->compressedrow.rindex;
16395914357eSBarry Smith     for (PetscInt i = 0; i < m; i++) {
16405914357eSBarry Smith       PetscInt           n   = ii[i + 1] - ii[i];
16415914357eSBarry Smith       const PetscInt    *aj  = a->j + ii[i];
16425914357eSBarry Smith       const PetscScalar *aa  = a_a + ii[i];
16435914357eSBarry Smith       PetscScalar        sum = y[*ridx];
1644f15663dcSBarry Smith       PetscSparseDensePlusDot(sum, x, aa, aj, n);
164597952fefSHong Zhang       z[*ridx++] = sum;
164697952fefSHong Zhang     }
164797952fefSHong Zhang   } else { /* do not use compressed row format */
16483d3eaba7SBarry Smith     ii = a->i;
1649f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
16505914357eSBarry Smith     fortranmultaddaij_(&m, x, ii, a->j, a_a, y, z);
1651f15663dcSBarry Smith #else
16525914357eSBarry Smith     PetscPragmaUseOMPKernels(parallel for)
16535914357eSBarry Smith     for (PetscInt i = 0; i < m; i++) {
16545914357eSBarry Smith       PetscInt           n   = ii[i + 1] - ii[i];
16555914357eSBarry Smith       const PetscInt    *aj  = a->j + ii[i];
16565914357eSBarry Smith       const PetscScalar *aa  = a_a + ii[i];
16575914357eSBarry Smith       PetscScalar        sum = y[i];
1658f15663dcSBarry Smith       PetscSparseDensePlusDot(sum, x, aa, aj, n);
165917ab2063SBarry Smith       z[i] = sum;
166017ab2063SBarry Smith     }
166102ab625aSSatish Balay #endif
1662f15663dcSBarry Smith   }
16639566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * a->nz));
16649566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
16659566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayPair(yy, zz, &y, &z));
16669566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &a_a));
16673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
166817ab2063SBarry Smith }
166917ab2063SBarry Smith 
1670ba38deedSJacob Faibussowitsch static PetscErrorCode MatShift_SeqAIJ(Mat A, PetscScalar v)
1671d71ae5a4SJacob Faibussowitsch {
167261ecd0c6SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data;
1673*421480d9SBarry Smith   const PetscInt *diag;
167461ecd0c6SBarry Smith   const PetscInt *ii = (const PetscInt *)a->i;
1675*421480d9SBarry Smith   PetscBool       diagDense;
167661ecd0c6SBarry Smith 
167761ecd0c6SBarry Smith   PetscFunctionBegin;
167861ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
16799566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(A, 1, NULL));
16809566063dSJacob Faibussowitsch     PetscCall(MatShift_Basic(A, v));
16813ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
168261ecd0c6SBarry Smith   }
168361ecd0c6SBarry Smith 
1684*421480d9SBarry Smith   PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, &diagDense));
1685*421480d9SBarry Smith   if (diagDense) {
16869566063dSJacob Faibussowitsch     PetscCall(MatShift_Basic(A, v));
168761ecd0c6SBarry Smith   } else {
1688b6f2aa54SBarry Smith     PetscScalar       *olda = a->a; /* preserve pointers to current matrix nonzeros structure and values */
1689b6f2aa54SBarry Smith     PetscInt          *oldj = a->j, *oldi = a->i;
16909f0612e4SBarry Smith     PetscBool          free_a = a->free_a, free_ij = a->free_ij;
16916ea2a7edSJunchao Zhang     const PetscScalar *Aa;
169207425a8dSBarry Smith     PetscInt          *mdiag = NULL;
16936ea2a7edSJunchao Zhang 
169407425a8dSBarry Smith     PetscCall(PetscCalloc1(A->rmap->n, &mdiag));
169507425a8dSBarry Smith     for (PetscInt i = 0; i < A->rmap->n; i++) {
169607425a8dSBarry Smith       if (i < A->cmap->n && diag[i] >= ii[i + 1]) { /* 'out of range' rows never have diagonals */
169707425a8dSBarry Smith         mdiag[i] = 1;
169807425a8dSBarry Smith       }
169907425a8dSBarry Smith     }
17006ea2a7edSJunchao Zhang     PetscCall(MatSeqAIJGetArrayRead(A, &Aa)); // sync the host
17016ea2a7edSJunchao Zhang     PetscCall(MatSeqAIJRestoreArrayRead(A, &Aa));
170261ecd0c6SBarry Smith 
170361ecd0c6SBarry Smith     a->a = NULL;
170461ecd0c6SBarry Smith     a->j = NULL;
170561ecd0c6SBarry Smith     a->i = NULL;
170661ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
170707425a8dSBarry Smith     for (PetscInt i = 0; i < PetscMin(A->rmap->n, A->cmap->n); i++) a->imax[i] += mdiag[i];
17089566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A, 0, a->imax));
170961ecd0c6SBarry Smith 
171061ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
171107425a8dSBarry Smith     for (PetscInt i = 0; i < A->rmap->n; i++) {
17129566063dSJacob Faibussowitsch       PetscCall(MatSetValues(A, 1, &i, a->imax[i] - mdiag[i], &oldj[oldi[i]], &olda[oldi[i]], ADD_VALUES));
171348a46eb9SPierre Jolivet       if (i < A->cmap->n) PetscCall(MatSetValue(A, i, i, v, ADD_VALUES));
1714447d62f5SStefano Zampini     }
17159566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
17169566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
17179f0612e4SBarry Smith     if (free_a) PetscCall(PetscShmgetDeallocateArray((void **)&olda));
17189f0612e4SBarry Smith     if (free_ij) PetscCall(PetscShmgetDeallocateArray((void **)&oldj));
17199f0612e4SBarry Smith     if (free_ij) PetscCall(PetscShmgetDeallocateArray((void **)&oldi));
17209566063dSJacob Faibussowitsch     PetscCall(PetscFree(mdiag));
1721be5855fcSBarry Smith   }
17223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 */
1731ba38deedSJacob Faibussowitsch static PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *diag)
1732d71ae5a4SJacob Faibussowitsch {
17330da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx, j, bsizemax = 0, *v_pivots;
17340da83c2eSBarry Smith   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
17350da83c2eSBarry Smith   const PetscReal shift = 0.0;
17360da83c2eSBarry Smith   PetscInt        ipvt[5];
17374e208921SJed Brown   PetscCount      flops = 0;
17380da83c2eSBarry Smith   PetscScalar     work[25], *v_work;
17390da83c2eSBarry Smith 
17400da83c2eSBarry Smith   PetscFunctionBegin;
17410da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
17420da83c2eSBarry Smith   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
174308401ef6SPierre 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);
1744ad540459SPierre Jolivet   for (i = 0; i < nblocks; i++) bsizemax = PetscMax(bsizemax, bsizes[i]);
17459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(bsizemax, &indx));
174648a46eb9SPierre Jolivet   if (bsizemax > 7) PetscCall(PetscMalloc2(bsizemax, &v_work, bsizemax, &v_pivots));
17470da83c2eSBarry Smith   ncnt = 0;
17480da83c2eSBarry Smith   for (i = 0; i < nblocks; i++) {
17490da83c2eSBarry Smith     for (j = 0; j < bsizes[i]; j++) indx[j] = ncnt + j;
17509566063dSJacob Faibussowitsch     PetscCall(MatGetValues(A, bsizes[i], indx, bsizes[i], indx, diag));
17510da83c2eSBarry Smith     switch (bsizes[i]) {
1752d71ae5a4SJacob Faibussowitsch     case 1:
1753d71ae5a4SJacob Faibussowitsch       *diag = 1.0 / (*diag);
1754d71ae5a4SJacob Faibussowitsch       break;
17550da83c2eSBarry Smith     case 2:
17569566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected));
17570da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17589566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_2(diag));
17590da83c2eSBarry Smith       break;
17600da83c2eSBarry Smith     case 3:
17619566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected));
17620da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17639566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_3(diag));
17640da83c2eSBarry Smith       break;
17650da83c2eSBarry Smith     case 4:
17669566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected));
17670da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17689566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_4(diag));
17690da83c2eSBarry Smith       break;
17700da83c2eSBarry Smith     case 5:
17719566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
17720da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17739566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_5(diag));
17740da83c2eSBarry Smith       break;
17750da83c2eSBarry Smith     case 6:
17769566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected));
17770da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17789566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_6(diag));
17790da83c2eSBarry Smith       break;
17800da83c2eSBarry Smith     case 7:
17819566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected));
17820da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17839566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_7(diag));
17840da83c2eSBarry Smith       break;
17850da83c2eSBarry Smith     default:
17869566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A(bsizes[i], diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
17870da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17889566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_N(diag, bsizes[i]));
17890da83c2eSBarry Smith     }
17900da83c2eSBarry Smith     ncnt += bsizes[i];
17910da83c2eSBarry Smith     diag += bsizes[i] * bsizes[i];
1792baa50dc0SBrad Aagaard     flops += 2 * PetscPowInt64(bsizes[i], 3) / 3;
17930da83c2eSBarry Smith   }
17943ba16761SJacob Faibussowitsch   PetscCall(PetscLogFlops(flops));
179548a46eb9SPierre Jolivet   if (bsizemax > 7) PetscCall(PetscFree2(v_work, v_pivots));
17969566063dSJacob Faibussowitsch   PetscCall(PetscFree(indx));
17973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17980da83c2eSBarry Smith }
17990da83c2eSBarry Smith 
1800422a814eSBarry Smith /*
1801422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1802422a814eSBarry Smith */
180307425a8dSBarry Smith static PetscErrorCode MatInvertDiagonalForSOR_SeqAIJ(Mat A, PetscScalar omega, PetscScalar fshift)
1804d71ae5a4SJacob Faibussowitsch {
180571f1c65dSBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
1806*421480d9SBarry Smith   PetscInt         i, m = A->rmap->n;
18072e5835c6SStefano Zampini   const MatScalar *v;
180854f21887SBarry Smith   PetscScalar     *idiag, *mdiag;
1809*421480d9SBarry Smith   PetscBool        diagDense;
1810*421480d9SBarry Smith   const PetscInt  *diag;
181171f1c65dSBarry Smith 
181271f1c65dSBarry Smith   PetscFunctionBegin;
181307425a8dSBarry Smith   if (a->idiagState == ((PetscObject)A)->state && a->omega == omega && a->fshift == fshift) PetscFunctionReturn(PETSC_SUCCESS);
1814*421480d9SBarry Smith   PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, &diagDense));
1815*421480d9SBarry Smith   PetscCheck(diagDense, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix must have all diagonal locations to invert them");
18163a7d0413SPierre Jolivet   if (!a->idiag) PetscCall(PetscMalloc3(m, &a->idiag, m, &a->mdiag, m, &a->ssor_work));
18172e5835c6SStefano Zampini 
181871f1c65dSBarry Smith   mdiag = a->mdiag;
181971f1c65dSBarry Smith   idiag = a->idiag;
18209566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &v));
1821422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
182271f1c65dSBarry Smith     for (i = 0; i < m; i++) {
182371f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1824899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1825966bd95aSPierre Jolivet         PetscCheck(PetscRealPart(fshift), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Zero diagonal on row %" PetscInt_FMT, i);
18269566063dSJacob Faibussowitsch         PetscCall(PetscInfo(A, "Zero diagonal on row %" PetscInt_FMT "\n", i));
18277b6c816cSBarry Smith         A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18287b6c816cSBarry Smith         A->factorerror_zeropivot_value = 0.0;
18297b6c816cSBarry Smith         A->factorerror_zeropivot_row   = i;
1830899639b0SHong Zhang       }
183171f1c65dSBarry Smith       idiag[i] = 1.0 / v[diag[i]];
183271f1c65dSBarry Smith     }
18339566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(m));
183471f1c65dSBarry Smith   } else {
183571f1c65dSBarry Smith     for (i = 0; i < m; i++) {
183671f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
183771f1c65dSBarry Smith       idiag[i] = omega / (fshift + v[diag[i]]);
183871f1c65dSBarry Smith     }
18399566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * m));
184071f1c65dSBarry Smith   }
18419566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &v));
184207425a8dSBarry Smith   a->idiagState = ((PetscObject)A)->state;
184307425a8dSBarry Smith   a->omega      = omega;
184407425a8dSBarry Smith   a->fshift     = fshift;
18453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
184671f1c65dSBarry Smith }
184771f1c65dSBarry Smith 
1848d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSOR_SeqAIJ(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal fshift, PetscInt its, PetscInt lits, Vec xx)
1849d71ae5a4SJacob Faibussowitsch {
1850416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
1851e6d1f457SBarry Smith   PetscScalar       *x, d, sum, *t, scale;
18522e5835c6SStefano Zampini   const MatScalar   *v, *idiag = NULL, *mdiag, *aa;
185354f21887SBarry Smith   const PetscScalar *b, *bs, *xb, *ts;
18543d3eaba7SBarry Smith   PetscInt           n, m = A->rmap->n, i;
185597f1f81fSBarry Smith   const PetscInt    *idx, *diag;
185617ab2063SBarry Smith 
18573a40ed3dSBarry Smith   PetscFunctionBegin;
1858b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) {
18599566063dSJacob Faibussowitsch     PetscCall(MatSOR_SeqAIJ_Inode(A, bb, omega, flag, fshift, its, lits, xx));
18603ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1861b215bc84SStefano Zampini   }
1862b965ef7fSBarry Smith   its = its * lits;
186307425a8dSBarry Smith   PetscCall(MatInvertDiagonalForSOR_SeqAIJ(A, omega, fshift));
1864*421480d9SBarry Smith   PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, NULL));
186571f1c65dSBarry Smith   t     = a->ssor_work;
1866ed480e8bSBarry Smith   idiag = a->idiag;
186771f1c65dSBarry Smith   mdiag = a->mdiag;
1868ed480e8bSBarry Smith 
18699566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
18709566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx, &x));
18719566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
1872ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
187317ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
187417ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
1875ed480e8bSBarry Smith     bs = b;
187617ab2063SBarry Smith     for (i = 0; i < m; i++) {
187771f1c65dSBarry Smith       d   = fshift + mdiag[i];
1878416022c9SBarry Smith       n   = a->i[i + 1] - diag[i] - 1;
1879ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
18802e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
188117ab2063SBarry Smith       sum = b[i] * d / omega;
1882003131ecSBarry Smith       PetscSparseDensePlusDot(sum, bs, v, idx, n);
188317ab2063SBarry Smith       x[i] = sum;
188417ab2063SBarry Smith     }
18859566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(xx, &x));
18869566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(bb, &b));
18879566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
18889566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(a->nz));
18893ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
189017ab2063SBarry Smith   }
1891c783ea89SBarry Smith 
189208401ef6SPierre Jolivet   PetscCheck(flag != SOR_APPLY_LOWER, PETSC_COMM_SELF, PETSC_ERR_SUP, "SOR_APPLY_LOWER is not implemented");
1893f7d195e4SLawrence Mitchell   if (flag & SOR_EISENSTAT) {
18944c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
1895887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
189617ab2063SBarry Smith 
189717ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
189817ab2063SBarry Smith 
1899887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
190017ab2063SBarry Smith     */
190117ab2063SBarry Smith     scale = (2.0 / omega) - 1.0;
190217ab2063SBarry Smith 
190317ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
190417ab2063SBarry Smith     for (i = m - 1; i >= 0; i--) {
1905416022c9SBarry Smith       n   = a->i[i + 1] - diag[i] - 1;
1906ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
19072e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
190817ab2063SBarry Smith       sum = b[i];
1909e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum, x, v, idx, n);
1910ed480e8bSBarry Smith       x[i] = sum * idiag[i];
191117ab2063SBarry Smith     }
191217ab2063SBarry Smith 
191317ab2063SBarry Smith     /*  t = b - (2*E - D)x */
19142e5835c6SStefano Zampini     v = aa;
19152205254eSKarl Rupp     for (i = 0; i < m; i++) t[i] = b[i] - scale * (v[*diag++]) * x[i];
191617ab2063SBarry Smith 
191717ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
1918ed480e8bSBarry Smith     ts   = t;
1919416022c9SBarry Smith     diag = a->diag;
192017ab2063SBarry Smith     for (i = 0; i < m; i++) {
1921416022c9SBarry Smith       n   = diag[i] - a->i[i];
1922ed480e8bSBarry Smith       idx = a->j + a->i[i];
19232e5835c6SStefano Zampini       v   = aa + a->i[i];
192417ab2063SBarry Smith       sum = t[i];
1925003131ecSBarry Smith       PetscSparseDenseMinusDot(sum, ts, v, idx, n);
1926ed480e8bSBarry Smith       t[i] = sum * idiag[i];
1927733d66baSBarry Smith       /*  x = x + t */
1928733d66baSBarry Smith       x[i] += t[i];
192917ab2063SBarry Smith     }
193017ab2063SBarry Smith 
19319566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(6.0 * m - 1 + 2.0 * a->nz));
19329566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(xx, &x));
19339566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(bb, &b));
19343ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
193517ab2063SBarry Smith   }
193617ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
193717ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
193817ab2063SBarry Smith       for (i = 0; i < m; i++) {
1939416022c9SBarry Smith         n   = diag[i] - a->i[i];
1940ed480e8bSBarry Smith         idx = a->j + a->i[i];
19412e5835c6SStefano Zampini         v   = aa + a->i[i];
194217ab2063SBarry Smith         sum = b[i];
1943e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum, x, v, idx, n);
19445c99c7daSBarry Smith         t[i] = sum;
1945ed480e8bSBarry Smith         x[i] = sum * idiag[i];
194617ab2063SBarry Smith       }
19475c99c7daSBarry Smith       xb = t;
19489566063dSJacob Faibussowitsch       PetscCall(PetscLogFlops(a->nz));
19493a40ed3dSBarry Smith     } else xb = b;
195017ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
195117ab2063SBarry Smith       for (i = m - 1; i >= 0; i--) {
1952416022c9SBarry Smith         n   = a->i[i + 1] - diag[i] - 1;
1953ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
19542e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
195517ab2063SBarry Smith         sum = xb[i];
1956e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum, x, v, idx, n);
19575c99c7daSBarry Smith         if (xb == b) {
1958ed480e8bSBarry Smith           x[i] = sum * idiag[i];
19595c99c7daSBarry Smith         } else {
1960b19a5dc2SMark Adams           x[i] = (1 - omega) * x[i] + sum * idiag[i]; /* omega in idiag */
196117ab2063SBarry Smith         }
19625c99c7daSBarry Smith       }
19639566063dSJacob Faibussowitsch       PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */
196417ab2063SBarry Smith     }
196517ab2063SBarry Smith     its--;
196617ab2063SBarry Smith   }
196717ab2063SBarry Smith   while (its--) {
196817ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
196917ab2063SBarry Smith       for (i = 0; i < m; i++) {
1970b19a5dc2SMark Adams         /* lower */
1971b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
1972ed480e8bSBarry Smith         idx = a->j + a->i[i];
19732e5835c6SStefano Zampini         v   = aa + a->i[i];
197417ab2063SBarry Smith         sum = b[i];
1975e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum, x, v, idx, n);
1976b19a5dc2SMark Adams         t[i] = sum; /* save application of the lower-triangular part */
1977b19a5dc2SMark Adams         /* upper */
1978b19a5dc2SMark Adams         n   = a->i[i + 1] - diag[i] - 1;
1979b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
19802e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
1981b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum, x, v, idx, n);
1982b19a5dc2SMark Adams         x[i] = (1. - omega) * x[i] + sum * idiag[i]; /* omega in idiag */
198317ab2063SBarry Smith       }
1984b19a5dc2SMark Adams       xb = t;
19859566063dSJacob Faibussowitsch       PetscCall(PetscLogFlops(2.0 * a->nz));
1986b19a5dc2SMark Adams     } else xb = b;
198717ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
198817ab2063SBarry Smith       for (i = m - 1; i >= 0; i--) {
1989b19a5dc2SMark Adams         sum = xb[i];
1990b19a5dc2SMark Adams         if (xb == b) {
1991b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
1992416022c9SBarry Smith           n   = a->i[i + 1] - a->i[i];
1993ed480e8bSBarry Smith           idx = a->j + a->i[i];
19942e5835c6SStefano Zampini           v   = aa + a->i[i];
1995e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum, x, v, idx, n);
1996ed480e8bSBarry Smith           x[i] = (1. - omega) * x[i] + (sum + mdiag[i] * x[i]) * idiag[i];
1997b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
1998b19a5dc2SMark Adams           n   = a->i[i + 1] - diag[i] - 1;
1999b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
20002e5835c6SStefano Zampini           v   = aa + diag[i] + 1;
2001b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum, x, v, idx, n);
2002b19a5dc2SMark Adams           x[i] = (1. - omega) * x[i] + sum * idiag[i]; /* omega in idiag */
200317ab2063SBarry Smith         }
2004b19a5dc2SMark Adams       }
2005b19a5dc2SMark Adams       if (xb == b) {
20069566063dSJacob Faibussowitsch         PetscCall(PetscLogFlops(2.0 * a->nz));
2007b19a5dc2SMark Adams       } else {
20089566063dSJacob Faibussowitsch         PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */
2009b19a5dc2SMark Adams       }
201017ab2063SBarry Smith     }
201117ab2063SBarry Smith   }
20129566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
20139566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx, &x));
20149566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
20153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
201617ab2063SBarry Smith }
201717ab2063SBarry Smith 
2018ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetInfo_SeqAIJ(Mat A, MatInfoType flag, MatInfo *info)
2019d71ae5a4SJacob Faibussowitsch {
2020416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
20214e220ebcSLois Curfman McInnes 
20223a40ed3dSBarry Smith   PetscFunctionBegin;
20234e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
20243966268fSBarry Smith   info->nz_allocated = a->maxnz;
20253966268fSBarry Smith   info->nz_used      = a->nz;
20263966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
20273966268fSBarry Smith   info->assemblies   = A->num_ass;
20283966268fSBarry Smith   info->mallocs      = A->info.mallocs;
20294dfa11a4SJacob Faibussowitsch   info->memory       = 0; /* REVIEW ME */
2030d5f3da31SBarry Smith   if (A->factortype) {
20314e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
20324e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
20334e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
20344e220ebcSLois Curfman McInnes   } else {
20354e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
20364e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
20374e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
20384e220ebcSLois Curfman McInnes   }
20393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
204017ab2063SBarry Smith }
204117ab2063SBarry Smith 
2042*421480d9SBarry Smith static PetscErrorCode MatZeroRows_SeqAIJ(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diagv, Vec x, Vec b)
2043d71ae5a4SJacob Faibussowitsch {
2044416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
2045c7da8527SEric Chamberland   PetscInt           i, m = A->rmap->n - 1;
204697b48c8fSBarry Smith   const PetscScalar *xx;
20472e5835c6SStefano Zampini   PetscScalar       *bb, *aa;
2048c7da8527SEric Chamberland   PetscInt           d = 0;
2049*421480d9SBarry Smith   const PetscInt    *diag;
205017ab2063SBarry Smith 
20513a40ed3dSBarry Smith   PetscFunctionBegin;
205297b48c8fSBarry Smith   if (x && b) {
20539566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
20549566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
205597b48c8fSBarry Smith     for (i = 0; i < N; i++) {
2056aed4548fSBarry Smith       PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]);
2057447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
2058*421480d9SBarry Smith       bb[rows[i]] = diagv * xx[rows[i]];
205997b48c8fSBarry Smith     }
20609566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
20619566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
206297b48c8fSBarry Smith   }
206397b48c8fSBarry Smith 
2064*421480d9SBarry Smith   PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, NULL));
20659566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
2066a9817697SBarry Smith   if (a->keepnonzeropattern) {
2067f1e2ffcdSBarry Smith     for (i = 0; i < N; i++) {
2068aed4548fSBarry Smith       PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]);
20699566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(&aa[a->i[rows[i]]], a->ilen[rows[i]]));
2070f1e2ffcdSBarry Smith     }
2071*421480d9SBarry Smith     if (diagv != 0.0) {
2072c7da8527SEric Chamberland       for (i = 0; i < N; i++) {
2073c7da8527SEric Chamberland         d = rows[i];
2074*421480d9SBarry Smith         if (d >= A->cmap->n) continue;
2075*421480d9SBarry Smith         PetscCheck(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);
2076c7da8527SEric Chamberland       }
2077f1e2ffcdSBarry Smith       for (i = 0; i < N; i++) {
2078447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2079*421480d9SBarry Smith         aa[diag[rows[i]]] = diagv;
2080f1e2ffcdSBarry Smith       }
2081f1e2ffcdSBarry Smith     }
2082f1e2ffcdSBarry Smith   } else {
2083*421480d9SBarry Smith     if (diagv != 0.0) {
208417ab2063SBarry Smith       for (i = 0; i < N; i++) {
2085aed4548fSBarry Smith         PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]);
20867ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2087447d62f5SStefano Zampini           if (rows[i] >= A->cmap->n) {
2088447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2089447d62f5SStefano Zampini           } else {
2090416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
2091*421480d9SBarry Smith             aa[a->i[rows[i]]]   = diagv;
2092bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2093447d62f5SStefano Zampini           }
2094447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
2095*421480d9SBarry Smith           PetscCall(MatSetValues_SeqAIJ(A, 1, &rows[i], 1, &rows[i], &diagv, INSERT_VALUES));
209617ab2063SBarry Smith         }
209717ab2063SBarry Smith       }
20983a40ed3dSBarry Smith     } else {
209917ab2063SBarry Smith       for (i = 0; i < N; i++) {
2100aed4548fSBarry Smith         PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]);
2101416022c9SBarry Smith         a->ilen[rows[i]] = 0;
210217ab2063SBarry Smith       }
210317ab2063SBarry Smith     }
2104e56f5c9eSBarry Smith     A->nonzerostate++;
2105f1e2ffcdSBarry Smith   }
21069566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
2107dbbe0bcdSBarry Smith   PetscUseTypeMethod(A, assemblyend, MAT_FINAL_ASSEMBLY);
21083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
210917ab2063SBarry Smith }
211017ab2063SBarry Smith 
2111*421480d9SBarry Smith static PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diagv, Vec x, Vec b)
2112d71ae5a4SJacob Faibussowitsch {
21136e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
21146e169961SBarry Smith   PetscInt           i, j, m = A->rmap->n - 1, d = 0;
2115*421480d9SBarry Smith   PetscBool         *zeroed, vecs = PETSC_FALSE;
21166e169961SBarry Smith   const PetscScalar *xx;
21172e5835c6SStefano Zampini   PetscScalar       *bb, *aa;
2118*421480d9SBarry Smith   const PetscInt    *diag;
2119*421480d9SBarry Smith   PetscBool          diagDense;
21206e169961SBarry Smith 
21216e169961SBarry Smith   PetscFunctionBegin;
21223ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
2123*421480d9SBarry Smith   PetscCall(MatGetDiagonalMarkers_SeqAIJ(A, &diag, &diagDense));
21249566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &aa));
21256e169961SBarry Smith   if (x && b) {
21269566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
21279566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
21282b40b63fSBarry Smith     vecs = PETSC_TRUE;
21296e169961SBarry Smith   }
21309566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(A->rmap->n, &zeroed));
21316e169961SBarry Smith   for (i = 0; i < N; i++) {
2132aed4548fSBarry Smith     PetscCheck(rows[i] >= 0 && rows[i] <= m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "row %" PetscInt_FMT " out of range", rows[i]);
21338e3a54c0SPierre Jolivet     PetscCall(PetscArrayzero(PetscSafePointerPlusOffset(aa, a->i[rows[i]]), a->ilen[rows[i]]));
21342205254eSKarl Rupp 
21356e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
21366e169961SBarry Smith   }
21376e169961SBarry Smith   for (i = 0; i < A->rmap->n; i++) {
21386e169961SBarry Smith     if (!zeroed[i]) {
21396e169961SBarry Smith       for (j = a->i[i]; j < a->i[i + 1]; j++) {
21404cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
21412e5835c6SStefano Zampini           if (vecs) bb[i] -= aa[j] * xx[a->j[j]];
21422e5835c6SStefano Zampini           aa[j] = 0.0;
21436e169961SBarry Smith         }
21446e169961SBarry Smith       }
2145*421480d9SBarry Smith     } else if (vecs && i < A->cmap->N) bb[i] = diagv * xx[i];
21466e169961SBarry Smith   }
21476e169961SBarry Smith   if (x && b) {
21489566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
21499566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
21506e169961SBarry Smith   }
21519566063dSJacob Faibussowitsch   PetscCall(PetscFree(zeroed));
2152*421480d9SBarry Smith   if (diagv != 0.0) {
2153*421480d9SBarry Smith     if (!diagDense) {
21541d5a398dSstefano_zampini       for (i = 0; i < N; i++) {
21554cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
2156aed4548fSBarry 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]);
2157*421480d9SBarry Smith         PetscCall(MatSetValues_SeqAIJ(A, 1, &rows[i], 1, &rows[i], &diagv, INSERT_VALUES));
21581d5a398dSstefano_zampini       }
21591d5a398dSstefano_zampini     } else {
2160*421480d9SBarry Smith       for (i = 0; i < N; i++) aa[diag[rows[i]]] = diagv;
21616e169961SBarry Smith     }
21621d5a398dSstefano_zampini   }
21639566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &aa));
2164dbbe0bcdSBarry Smith   PetscUseTypeMethod(A, assemblyend, MAT_FINAL_ASSEMBLY);
21653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21666e169961SBarry Smith }
21676e169961SBarry Smith 
2168d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRow_SeqAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2169d71ae5a4SJacob Faibussowitsch {
2170fff043a9SJunchao Zhang   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
2171fff043a9SJunchao Zhang   const PetscScalar *aa;
217217ab2063SBarry Smith 
21733a40ed3dSBarry Smith   PetscFunctionBegin;
21749566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
2175416022c9SBarry Smith   *nz = a->i[row + 1] - a->i[row];
21768e3a54c0SPierre Jolivet   if (v) *v = PetscSafePointerPlusOffset((PetscScalar *)aa, a->i[row]);
217717ab2063SBarry Smith   if (idx) {
21785c0db29aSPierre Jolivet     if (*nz && a->j) *idx = a->j + a->i[row];
2179f4259b30SLisandro Dalcin     else *idx = NULL;
218017ab2063SBarry Smith   }
21819566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
21823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
218317ab2063SBarry Smith }
218417ab2063SBarry Smith 
2185d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRestoreRow_SeqAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2186d71ae5a4SJacob Faibussowitsch {
21873a40ed3dSBarry Smith   PetscFunctionBegin;
21883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
218917ab2063SBarry Smith }
219017ab2063SBarry Smith 
2191ba38deedSJacob Faibussowitsch static PetscErrorCode MatNorm_SeqAIJ(Mat A, NormType type, PetscReal *nrm)
2192d71ae5a4SJacob Faibussowitsch {
2193416022c9SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
21942e5835c6SStefano Zampini   const MatScalar *v;
219536db0b34SBarry Smith   PetscReal        sum = 0.0;
219697f1f81fSBarry Smith   PetscInt         i, j;
219717ab2063SBarry Smith 
21983a40ed3dSBarry Smith   PetscFunctionBegin;
21999566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &v));
220017ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2201570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2202570b7f6dSBarry Smith     PetscBLASInt one = 1, nz = a->nz;
2203792fecdfSBarry Smith     PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&nz, v, &one));
2204570b7f6dSBarry Smith #else
2205416022c9SBarry Smith     for (i = 0; i < a->nz; i++) {
22069371c9d4SSatish Balay       sum += PetscRealPart(PetscConj(*v) * (*v));
22079371c9d4SSatish Balay       v++;
220817ab2063SBarry Smith     }
22098f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2210570b7f6dSBarry Smith #endif
22119566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * a->nz));
22123a40ed3dSBarry Smith   } else if (type == NORM_1) {
221336db0b34SBarry Smith     PetscReal *tmp;
221497f1f81fSBarry Smith     PetscInt  *jj = a->j;
22159566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(A->cmap->n + 1, &tmp));
2216064f8208SBarry Smith     *nrm = 0.0;
2217416022c9SBarry Smith     for (j = 0; j < a->nz; j++) {
22189371c9d4SSatish Balay       tmp[*jj++] += PetscAbsScalar(*v);
22199371c9d4SSatish Balay       v++;
222017ab2063SBarry Smith     }
2221d0f46423SBarry Smith     for (j = 0; j < A->cmap->n; j++) {
2222064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
222317ab2063SBarry Smith     }
22249566063dSJacob Faibussowitsch     PetscCall(PetscFree(tmp));
22259566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(PetscMax(a->nz - 1, 0)));
22263a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2227064f8208SBarry Smith     *nrm = 0.0;
2228d0f46423SBarry Smith     for (j = 0; j < A->rmap->n; j++) {
22298e3a54c0SPierre Jolivet       const PetscScalar *v2 = PetscSafePointerPlusOffset(v, a->i[j]);
223017ab2063SBarry Smith       sum                   = 0.0;
2231416022c9SBarry Smith       for (i = 0; i < a->i[j + 1] - a->i[j]; i++) {
22329371c9d4SSatish Balay         sum += PetscAbsScalar(*v2);
22339371c9d4SSatish Balay         v2++;
223417ab2063SBarry Smith       }
2235064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
223617ab2063SBarry Smith     }
22379566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(PetscMax(a->nz - 1, 0)));
2238f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for two norm");
22399566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &v));
22403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
224117ab2063SBarry Smith }
224217ab2063SBarry Smith 
2243ba38deedSJacob Faibussowitsch static PetscErrorCode MatIsTranspose_SeqAIJ(Mat A, Mat B, PetscReal tol, PetscBool *f)
2244d71ae5a4SJacob Faibussowitsch {
22453d3eaba7SBarry Smith   Mat_SeqAIJ      *aij = (Mat_SeqAIJ *)A->data, *bij = (Mat_SeqAIJ *)B->data;
224654f21887SBarry Smith   PetscInt        *adx, *bdx, *aii, *bii, *aptr, *bptr;
22472e5835c6SStefano Zampini   const MatScalar *va, *vb;
224897f1f81fSBarry Smith   PetscInt         ma, na, mb, nb, i;
2249cd0d46ebSvictorle 
2250cd0d46ebSvictorle   PetscFunctionBegin;
22519566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &ma, &na));
22529566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, &mb, &nb));
22535485867bSBarry Smith   if (ma != nb || na != mb) {
22545485867bSBarry Smith     *f = PETSC_FALSE;
22553ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
22565485867bSBarry Smith   }
22579566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &va));
22589566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(B, &vb));
22599371c9d4SSatish Balay   aii = aij->i;
22609371c9d4SSatish Balay   bii = bij->i;
22619371c9d4SSatish Balay   adx = aij->j;
22629371c9d4SSatish Balay   bdx = bij->j;
22639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ma, &aptr));
22649566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(mb, &bptr));
2265cd0d46ebSvictorle   for (i = 0; i < ma; i++) aptr[i] = aii[i];
2266cd0d46ebSvictorle   for (i = 0; i < mb; i++) bptr[i] = bii[i];
2267cd0d46ebSvictorle 
2268cd0d46ebSvictorle   *f = PETSC_TRUE;
2269cd0d46ebSvictorle   for (i = 0; i < ma; i++) {
2270cd0d46ebSvictorle     while (aptr[i] < aii[i + 1]) {
227197f1f81fSBarry Smith       PetscInt    idc, idr;
22725485867bSBarry Smith       PetscScalar vc, vr;
2273cd0d46ebSvictorle       /* column/row index/value */
22745485867bSBarry Smith       idc = adx[aptr[i]];
22755485867bSBarry Smith       idr = bdx[bptr[idc]];
22765485867bSBarry Smith       vc  = va[aptr[i]];
22775485867bSBarry Smith       vr  = vb[bptr[idc]];
22785485867bSBarry Smith       if (i != idr || PetscAbsScalar(vc - vr) > tol) {
22795485867bSBarry Smith         *f = PETSC_FALSE;
22805485867bSBarry Smith         goto done;
2281cd0d46ebSvictorle       } else {
22825485867bSBarry Smith         aptr[i]++;
22835485867bSBarry Smith         if (B || i != idc) bptr[idc]++;
2284cd0d46ebSvictorle       }
2285cd0d46ebSvictorle     }
2286cd0d46ebSvictorle   }
2287cd0d46ebSvictorle done:
22889566063dSJacob Faibussowitsch   PetscCall(PetscFree(aptr));
22899566063dSJacob Faibussowitsch   PetscCall(PetscFree(bptr));
22909566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &va));
22919566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(B, &vb));
22923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2293cd0d46ebSvictorle }
2294cd0d46ebSvictorle 
2295ba38deedSJacob Faibussowitsch static PetscErrorCode MatIsHermitianTranspose_SeqAIJ(Mat A, Mat B, PetscReal tol, PetscBool *f)
2296d71ae5a4SJacob Faibussowitsch {
22973d3eaba7SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data, *bij = (Mat_SeqAIJ *)B->data;
229854f21887SBarry Smith   PetscInt   *adx, *bdx, *aii, *bii, *aptr, *bptr;
229954f21887SBarry Smith   MatScalar  *va, *vb;
23001cbb95d3SBarry Smith   PetscInt    ma, na, mb, nb, i;
23011cbb95d3SBarry Smith 
23021cbb95d3SBarry Smith   PetscFunctionBegin;
23039566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &ma, &na));
23049566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, &mb, &nb));
23051cbb95d3SBarry Smith   if (ma != nb || na != mb) {
23061cbb95d3SBarry Smith     *f = PETSC_FALSE;
23073ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
23081cbb95d3SBarry Smith   }
23099371c9d4SSatish Balay   aii = aij->i;
23109371c9d4SSatish Balay   bii = bij->i;
23119371c9d4SSatish Balay   adx = aij->j;
23129371c9d4SSatish Balay   bdx = bij->j;
23139371c9d4SSatish Balay   va  = aij->a;
23149371c9d4SSatish Balay   vb  = bij->a;
23159566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ma, &aptr));
23169566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(mb, &bptr));
23171cbb95d3SBarry Smith   for (i = 0; i < ma; i++) aptr[i] = aii[i];
23181cbb95d3SBarry Smith   for (i = 0; i < mb; i++) bptr[i] = bii[i];
23191cbb95d3SBarry Smith 
23201cbb95d3SBarry Smith   *f = PETSC_TRUE;
23211cbb95d3SBarry Smith   for (i = 0; i < ma; i++) {
23221cbb95d3SBarry Smith     while (aptr[i] < aii[i + 1]) {
23231cbb95d3SBarry Smith       PetscInt    idc, idr;
23241cbb95d3SBarry Smith       PetscScalar vc, vr;
23251cbb95d3SBarry Smith       /* column/row index/value */
23261cbb95d3SBarry Smith       idc = adx[aptr[i]];
23271cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
23281cbb95d3SBarry Smith       vc  = va[aptr[i]];
23291cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
23301cbb95d3SBarry Smith       if (i != idr || PetscAbsScalar(vc - PetscConj(vr)) > tol) {
23311cbb95d3SBarry Smith         *f = PETSC_FALSE;
23321cbb95d3SBarry Smith         goto done;
23331cbb95d3SBarry Smith       } else {
23341cbb95d3SBarry Smith         aptr[i]++;
23351cbb95d3SBarry Smith         if (B || i != idc) bptr[idc]++;
23361cbb95d3SBarry Smith       }
23371cbb95d3SBarry Smith     }
23381cbb95d3SBarry Smith   }
23391cbb95d3SBarry Smith done:
23409566063dSJacob Faibussowitsch   PetscCall(PetscFree(aptr));
23419566063dSJacob Faibussowitsch   PetscCall(PetscFree(bptr));
23423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23431cbb95d3SBarry Smith }
23441cbb95d3SBarry Smith 
2345d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A, Vec ll, Vec rr)
2346d71ae5a4SJacob Faibussowitsch {
2347416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
2348fff8e43fSBarry Smith   const PetscScalar *l, *r;
2349fff8e43fSBarry Smith   PetscScalar        x;
235054f21887SBarry Smith   MatScalar         *v;
2351fff8e43fSBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, M, nz = a->nz;
2352fff8e43fSBarry Smith   const PetscInt    *jj;
235317ab2063SBarry Smith 
23543a40ed3dSBarry Smith   PetscFunctionBegin;
235517ab2063SBarry Smith   if (ll) {
23563ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
23573ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
23589566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(ll, &m));
235908401ef6SPierre Jolivet     PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vector wrong length");
23609566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ll, &l));
23619566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(A, &v));
236217ab2063SBarry Smith     for (i = 0; i < m; i++) {
236317ab2063SBarry Smith       x = l[i];
2364416022c9SBarry Smith       M = a->i[i + 1] - a->i[i];
23652205254eSKarl Rupp       for (j = 0; j < M; j++) (*v++) *= x;
236617ab2063SBarry Smith     }
23679566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ll, &l));
23689566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(nz));
23699566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArray(A, &v));
237017ab2063SBarry Smith   }
237117ab2063SBarry Smith   if (rr) {
23729566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(rr, &n));
237308401ef6SPierre Jolivet     PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vector wrong length");
23749566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rr, &r));
23759566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(A, &v));
23762e5835c6SStefano Zampini     jj = a->j;
23772205254eSKarl Rupp     for (i = 0; i < nz; i++) (*v++) *= r[*jj++];
23789566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArray(A, &v));
23799566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rr, &r));
23809566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(nz));
238117ab2063SBarry Smith   }
23823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
238317ab2063SBarry Smith }
238417ab2063SBarry Smith 
2385d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A, IS isrow, IS iscol, PetscInt csize, MatReuse scall, Mat *B)
2386d71ae5a4SJacob Faibussowitsch {
2387db02288aSLois Curfman McInnes   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data, *c;
2388d0f46423SBarry Smith   PetscInt          *smap, i, k, kstart, kend, oldcols = A->cmap->n, *lens;
238997f1f81fSBarry Smith   PetscInt           row, mat_i, *mat_j, tcol, first, step, *mat_ilen, sum, lensi;
23905d0c19d7SBarry Smith   const PetscInt    *irow, *icol;
23912e5835c6SStefano Zampini   const PetscScalar *aa;
23925d0c19d7SBarry Smith   PetscInt           nrows, ncols;
239397f1f81fSBarry Smith   PetscInt          *starts, *j_new, *i_new, *aj = a->j, *ai = a->i, ii, *ailen = a->ilen;
2394fb3c7e2dSJunchao Zhang   MatScalar         *a_new, *mat_a, *c_a;
2395416022c9SBarry Smith   Mat                C;
2396cdc6f3adSToby Isaac   PetscBool          stride;
239717ab2063SBarry Smith 
23983a40ed3dSBarry Smith   PetscFunctionBegin;
23999566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(isrow, &irow));
24009566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow, &nrows));
24019566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol, &ncols));
240217ab2063SBarry Smith 
24039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)iscol, ISSTRIDE, &stride));
2404ff718158SBarry Smith   if (stride) {
24059566063dSJacob Faibussowitsch     PetscCall(ISStrideGetInfo(iscol, &first, &step));
2406ff718158SBarry Smith   } else {
2407ff718158SBarry Smith     first = 0;
2408ff718158SBarry Smith     step  = 0;
2409ff718158SBarry Smith   }
2410fee21e36SBarry Smith   if (stride && step == 1) {
241102834360SBarry Smith     /* special case of contiguous rows */
24129566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nrows, &lens, nrows, &starts));
241302834360SBarry Smith     /* loop over new rows determining lens and starting points */
241402834360SBarry Smith     for (i = 0; i < nrows; i++) {
2415bfeeae90SHong Zhang       kstart    = ai[irow[i]];
2416a2744918SBarry Smith       kend      = kstart + ailen[irow[i]];
2417a91a9bebSLisandro Dalcin       starts[i] = kstart;
241802834360SBarry Smith       for (k = kstart; k < kend; k++) {
2419bfeeae90SHong Zhang         if (aj[k] >= first) {
242002834360SBarry Smith           starts[i] = k;
242102834360SBarry Smith           break;
242202834360SBarry Smith         }
242302834360SBarry Smith       }
2424a2744918SBarry Smith       sum = 0;
242502834360SBarry Smith       while (k < kend) {
2426bfeeae90SHong Zhang         if (aj[k++] >= first + ncols) break;
2427a2744918SBarry Smith         sum++;
242802834360SBarry Smith       }
2429a2744918SBarry Smith       lens[i] = sum;
243002834360SBarry Smith     }
243102834360SBarry Smith     /* create submatrix */
2432cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
243397f1f81fSBarry Smith       PetscInt n_cols, n_rows;
24349566063dSJacob Faibussowitsch       PetscCall(MatGetSize(*B, &n_rows, &n_cols));
2435aed4548fSBarry Smith       PetscCheck(n_rows == nrows && n_cols == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Reused submatrix wrong size");
24369566063dSJacob Faibussowitsch       PetscCall(MatZeroEntries(*B));
243708480c60SBarry Smith       C = *B;
24383a40ed3dSBarry Smith     } else {
24393bef6203SJed Brown       PetscInt rbs, cbs;
24409566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
24419566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, nrows, ncols, PETSC_DETERMINE, PETSC_DETERMINE));
24429566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(isrow, &rbs));
24439566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(iscol, &cbs));
24449566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizes(C, rbs, cbs));
24459566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, ((PetscObject)A)->type_name));
24469566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C, 0, lens));
244708480c60SBarry Smith     }
2448db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ *)C->data;
2449db02288aSLois Curfman McInnes 
245002834360SBarry Smith     /* loop over rows inserting into submatrix */
2451fb3c7e2dSJunchao Zhang     PetscCall(MatSeqAIJGetArrayWrite(C, &a_new)); // Not 'a_new = c->a-new', since that raw usage ignores offload state of C
2452db02288aSLois Curfman McInnes     j_new = c->j;
2453db02288aSLois Curfman McInnes     i_new = c->i;
24549566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(A, &aa));
245502834360SBarry Smith     for (i = 0; i < nrows; i++) {
2456a2744918SBarry Smith       ii    = starts[i];
2457a2744918SBarry Smith       lensi = lens[i];
2458810441c8SPierre Jolivet       if (lensi) {
2459ad540459SPierre Jolivet         for (k = 0; k < lensi; k++) *j_new++ = aj[ii + k] - first;
24609566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(a_new, aa + starts[i], lensi));
2461a2744918SBarry Smith         a_new += lensi;
2462810441c8SPierre Jolivet       }
2463a2744918SBarry Smith       i_new[i + 1] = i_new[i] + lensi;
2464a2744918SBarry Smith       c->ilen[i]   = lensi;
246502834360SBarry Smith     }
2466fb3c7e2dSJunchao Zhang     PetscCall(MatSeqAIJRestoreArrayWrite(C, &a_new)); // Set C's offload state properly
24679566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
24689566063dSJacob Faibussowitsch     PetscCall(PetscFree2(lens, starts));
24693a40ed3dSBarry Smith   } else {
24709566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(iscol, &icol));
24719566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(oldcols, &smap));
24729566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(1 + nrows, &lens));
24734dcab191SBarry Smith     for (i = 0; i < ncols; i++) {
24746bdcaf15SBarry 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);
24754dcab191SBarry Smith       smap[icol[i]] = i + 1;
24764dcab191SBarry Smith     }
24774dcab191SBarry Smith 
247802834360SBarry Smith     /* determine lens of each row */
247902834360SBarry Smith     for (i = 0; i < nrows; i++) {
2480bfeeae90SHong Zhang       kstart  = ai[irow[i]];
248102834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
248202834360SBarry Smith       lens[i] = 0;
248302834360SBarry Smith       for (k = kstart; k < kend; k++) {
2484ad540459SPierre Jolivet         if (smap[aj[k]]) lens[i]++;
248502834360SBarry Smith       }
248602834360SBarry Smith     }
248717ab2063SBarry Smith     /* Create and fill new matrix */
2488a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2489ace3abfcSBarry Smith       PetscBool equal;
24900f5bd95cSBarry Smith 
249199141d43SSatish Balay       c = (Mat_SeqAIJ *)((*B)->data);
2492aed4548fSBarry Smith       PetscCheck((*B)->rmap->n == nrows && (*B)->cmap->n == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot reuse matrix. wrong size");
24939566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(c->ilen, lens, (*B)->rmap->n, &equal));
2494fdfbdca6SPierre Jolivet       PetscCheck(equal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot reuse matrix. wrong number of nonzeros");
24959566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(c->ilen, (*B)->rmap->n));
249608480c60SBarry Smith       C = *B;
24973a40ed3dSBarry Smith     } else {
24983bef6203SJed Brown       PetscInt rbs, cbs;
24999566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
25009566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, nrows, ncols, PETSC_DETERMINE, PETSC_DETERMINE));
25019566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(isrow, &rbs));
25029566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(iscol, &cbs));
250337a5e0faSPierre Jolivet       if (rbs > 1 || cbs > 1) PetscCall(MatSetBlockSizes(C, rbs, cbs));
25049566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, ((PetscObject)A)->type_name));
25059566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C, 0, lens));
250608480c60SBarry Smith     }
25079566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(A, &aa));
2508fb3c7e2dSJunchao Zhang 
2509f4f49eeaSPierre Jolivet     c = (Mat_SeqAIJ *)C->data;
2510fb3c7e2dSJunchao Zhang     PetscCall(MatSeqAIJGetArrayWrite(C, &c_a)); // Not 'c->a', since that raw usage ignores offload state of C
251117ab2063SBarry Smith     for (i = 0; i < nrows; i++) {
251299141d43SSatish Balay       row      = irow[i];
2513bfeeae90SHong Zhang       kstart   = ai[row];
251499141d43SSatish Balay       kend     = kstart + a->ilen[row];
2515bfeeae90SHong Zhang       mat_i    = c->i[i];
25168e3a54c0SPierre Jolivet       mat_j    = PetscSafePointerPlusOffset(c->j, mat_i);
25178e3a54c0SPierre Jolivet       mat_a    = PetscSafePointerPlusOffset(c_a, mat_i);
251899141d43SSatish Balay       mat_ilen = c->ilen + i;
251917ab2063SBarry Smith       for (k = kstart; k < kend; k++) {
2520bfeeae90SHong Zhang         if ((tcol = smap[a->j[k]])) {
2521ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
25222e5835c6SStefano Zampini           *mat_a++ = aa[k];
252399141d43SSatish Balay           (*mat_ilen)++;
252417ab2063SBarry Smith         }
252517ab2063SBarry Smith       }
252617ab2063SBarry Smith     }
25279566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
252802834360SBarry Smith     /* Free work space */
25299566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(iscol, &icol));
25309566063dSJacob Faibussowitsch     PetscCall(PetscFree(smap));
25319566063dSJacob Faibussowitsch     PetscCall(PetscFree(lens));
2532cdc6f3adSToby Isaac     /* sort */
2533cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2534cdc6f3adSToby Isaac       PetscInt ilen;
2535cdc6f3adSToby Isaac 
2536cdc6f3adSToby Isaac       mat_i = c->i[i];
25378e3a54c0SPierre Jolivet       mat_j = PetscSafePointerPlusOffset(c->j, mat_i);
25388e3a54c0SPierre Jolivet       mat_a = PetscSafePointerPlusOffset(c_a, mat_i);
2539cdc6f3adSToby Isaac       ilen  = c->ilen[i];
25409566063dSJacob Faibussowitsch       PetscCall(PetscSortIntWithScalarArray(ilen, mat_j, mat_a));
2541cdc6f3adSToby Isaac     }
2542fb3c7e2dSJunchao Zhang     PetscCall(MatSeqAIJRestoreArrayWrite(C, &c_a));
254302834360SBarry Smith   }
25448c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
25459566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU(C, A->boundtocpu));
2546305c6ccfSStefano Zampini #endif
25479566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
25489566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
254917ab2063SBarry Smith 
25509566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(isrow, &irow));
2551416022c9SBarry Smith   *B = C;
25523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
255317ab2063SBarry Smith }
255417ab2063SBarry Smith 
2555ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetMultiProcBlock_SeqAIJ(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
2556d71ae5a4SJacob Faibussowitsch {
255782d44351SHong Zhang   Mat B;
255882d44351SHong Zhang 
255982d44351SHong Zhang   PetscFunctionBegin;
2560c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
25619566063dSJacob Faibussowitsch     PetscCall(MatCreate(subComm, &B));
25629566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->n, mat->cmap->n));
25639566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, mat, mat));
25649566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQAIJ));
25659566063dSJacob Faibussowitsch     PetscCall(MatDuplicateNoCreate_SeqAIJ(B, mat, MAT_COPY_VALUES, PETSC_TRUE));
256682d44351SHong Zhang     *subMat = B;
2567c2d650bdSHong Zhang   } else {
25689566063dSJacob Faibussowitsch     PetscCall(MatCopy_SeqAIJ(mat, *subMat, SAME_NONZERO_PATTERN));
2569c2d650bdSHong Zhang   }
25703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
257182d44351SHong Zhang }
257282d44351SHong Zhang 
2573ba38deedSJacob Faibussowitsch static PetscErrorCode MatILUFactor_SeqAIJ(Mat inA, IS row, IS col, const MatFactorInfo *info)
2574d71ae5a4SJacob Faibussowitsch {
257563b91edcSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)inA->data;
257663b91edcSBarry Smith   Mat         outA;
2577ace3abfcSBarry Smith   PetscBool   row_identity, col_identity;
257863b91edcSBarry Smith 
25793a40ed3dSBarry Smith   PetscFunctionBegin;
258008401ef6SPierre Jolivet   PetscCheck(info->levels == 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only levels=0 supported for in-place ilu");
25811df811f5SHong Zhang 
25829566063dSJacob Faibussowitsch   PetscCall(ISIdentity(row, &row_identity));
25839566063dSJacob Faibussowitsch   PetscCall(ISIdentity(col, &col_identity));
2584a871dcd8SBarry Smith 
258563b91edcSBarry Smith   outA = inA;
25869566063dSJacob Faibussowitsch   PetscCall(PetscFree(inA->solvertype));
25879566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &inA->solvertype));
25882205254eSKarl Rupp 
25899566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
25909566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
25912205254eSKarl Rupp 
2592c3122656SLisandro Dalcin   a->row = row;
25932205254eSKarl Rupp 
25949566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)col));
25959566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
25962205254eSKarl Rupp 
2597c3122656SLisandro Dalcin   a->col = col;
259863b91edcSBarry Smith 
259936db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
26009566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->icol));
26019566063dSJacob Faibussowitsch   PetscCall(ISInvertPermutation(col, PETSC_DECIDE, &a->icol));
2602f0ec6fceSSatish Balay 
260394a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
260484648c2dSPierre Jolivet     PetscCall(PetscMalloc1(inA->rmap->n, &a->solve_work));
260594a9d846SBarry Smith   }
260663b91edcSBarry Smith 
2607137fb511SHong Zhang   if (row_identity && col_identity) {
26089566063dSJacob Faibussowitsch     PetscCall(MatLUFactorNumeric_SeqAIJ_inplace(outA, inA, info));
2609137fb511SHong Zhang   } else {
26109566063dSJacob Faibussowitsch     PetscCall(MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA, inA, info));
2611137fb511SHong Zhang   }
2612*421480d9SBarry Smith   outA->factortype = MAT_FACTOR_LU;
26133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2614a871dcd8SBarry Smith }
2615a871dcd8SBarry Smith 
2616d71ae5a4SJacob Faibussowitsch PetscErrorCode MatScale_SeqAIJ(Mat inA, PetscScalar alpha)
2617d71ae5a4SJacob Faibussowitsch {
2618f0b747eeSBarry Smith   Mat_SeqAIJ  *a = (Mat_SeqAIJ *)inA->data;
2619dfa0f9e5SStefano Zampini   PetscScalar *v;
2620c5df96a5SBarry Smith   PetscBLASInt one = 1, bnz;
26213a40ed3dSBarry Smith 
26223a40ed3dSBarry Smith   PetscFunctionBegin;
26239566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(inA, &v));
26249566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(a->nz, &bnz));
2625792fecdfSBarry Smith   PetscCallBLAS("BLASscal", BLASscal_(&bnz, &alpha, v, &one));
26269566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(a->nz));
26279566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(inA, &v));
26283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2629f0b747eeSBarry Smith }
2630f0b747eeSBarry Smith 
2631d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
2632d71ae5a4SJacob Faibussowitsch {
263316b64355SHong Zhang   PetscInt i;
263416b64355SHong Zhang 
263516b64355SHong Zhang   PetscFunctionBegin;
263616b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
26379566063dSJacob Faibussowitsch     PetscCall(PetscFree4(submatj->sbuf1, submatj->ptr, submatj->tmp, submatj->ctr));
263816b64355SHong Zhang 
263948a46eb9SPierre Jolivet     for (i = 0; i < submatj->nrqr; ++i) PetscCall(PetscFree(submatj->sbuf2[i]));
26409566063dSJacob Faibussowitsch     PetscCall(PetscFree3(submatj->sbuf2, submatj->req_size, submatj->req_source1));
264116b64355SHong Zhang 
264216b64355SHong Zhang     if (submatj->rbuf1) {
26439566063dSJacob Faibussowitsch       PetscCall(PetscFree(submatj->rbuf1[0]));
26449566063dSJacob Faibussowitsch       PetscCall(PetscFree(submatj->rbuf1));
264516b64355SHong Zhang     }
264616b64355SHong Zhang 
264748a46eb9SPierre Jolivet     for (i = 0; i < submatj->nrqs; ++i) PetscCall(PetscFree(submatj->rbuf3[i]));
26489566063dSJacob Faibussowitsch     PetscCall(PetscFree3(submatj->req_source2, submatj->rbuf2, submatj->rbuf3));
26499566063dSJacob Faibussowitsch     PetscCall(PetscFree(submatj->pa));
265016b64355SHong Zhang   }
265116b64355SHong Zhang 
265216b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
2653eec179cfSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&submatj->rmap));
26549566063dSJacob Faibussowitsch   if (submatj->cmap_loc) PetscCall(PetscFree(submatj->cmap_loc));
26559566063dSJacob Faibussowitsch   PetscCall(PetscFree(submatj->rmap_loc));
265616b64355SHong Zhang #else
26579566063dSJacob Faibussowitsch   PetscCall(PetscFree(submatj->rmap));
265816b64355SHong Zhang #endif
265916b64355SHong Zhang 
266016b64355SHong Zhang   if (!submatj->allcolumns) {
266116b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
2662835f2295SStefano Zampini     PetscCall(PetscHMapIDestroy(&submatj->cmap));
266316b64355SHong Zhang #else
26649566063dSJacob Faibussowitsch     PetscCall(PetscFree(submatj->cmap));
266516b64355SHong Zhang #endif
266616b64355SHong Zhang   }
26679566063dSJacob Faibussowitsch   PetscCall(PetscFree(submatj->row2proc));
266816b64355SHong Zhang 
26699566063dSJacob Faibussowitsch   PetscCall(PetscFree(submatj));
26703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
267116b64355SHong Zhang }
267216b64355SHong Zhang 
2673d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
2674d71ae5a4SJacob Faibussowitsch {
267516b64355SHong Zhang   Mat_SeqAIJ  *c       = (Mat_SeqAIJ *)C->data;
26765c39f6d9SHong Zhang   Mat_SubSppt *submatj = c->submatis1;
267716b64355SHong Zhang 
267816b64355SHong Zhang   PetscFunctionBegin;
26799566063dSJacob Faibussowitsch   PetscCall((*submatj->destroy)(C));
26809566063dSJacob Faibussowitsch   PetscCall(MatDestroySubMatrix_Private(submatj));
26813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
268216b64355SHong Zhang }
268316b64355SHong Zhang 
268489a1a59bSHong Zhang /* Note this has code duplication with MatDestroySubMatrices_SeqBAIJ() */
2685ba38deedSJacob Faibussowitsch static PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n, Mat *mat[])
2686d71ae5a4SJacob Faibussowitsch {
26872d033e1fSHong Zhang   PetscInt     i;
26880fb991dcSHong Zhang   Mat          C;
26890fb991dcSHong Zhang   Mat_SeqAIJ  *c;
26900fb991dcSHong Zhang   Mat_SubSppt *submatj;
26912d033e1fSHong Zhang 
26922d033e1fSHong Zhang   PetscFunctionBegin;
26932d033e1fSHong Zhang   for (i = 0; i < n; i++) {
26940fb991dcSHong Zhang     C       = (*mat)[i];
26950fb991dcSHong Zhang     c       = (Mat_SeqAIJ *)C->data;
26960fb991dcSHong Zhang     submatj = c->submatis1;
26972d033e1fSHong Zhang     if (submatj) {
2698682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
269926cc229bSBarry Smith         PetscCall(PetscFree(C->factorprefix));
27009566063dSJacob Faibussowitsch         PetscCall((*submatj->destroy)(C));
27019566063dSJacob Faibussowitsch         PetscCall(MatDestroySubMatrix_Private(submatj));
27029566063dSJacob Faibussowitsch         PetscCall(PetscFree(C->defaultvectype));
27033faff063SStefano Zampini         PetscCall(PetscFree(C->defaultrandtype));
27049566063dSJacob Faibussowitsch         PetscCall(PetscLayoutDestroy(&C->rmap));
27059566063dSJacob Faibussowitsch         PetscCall(PetscLayoutDestroy(&C->cmap));
27069566063dSJacob Faibussowitsch         PetscCall(PetscHeaderDestroy(&C));
2707682e4c99SStefano Zampini       }
27082d033e1fSHong Zhang     } else {
27099566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
27102d033e1fSHong Zhang     }
27112d033e1fSHong Zhang   }
271286e85357SHong Zhang 
271363a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
27149566063dSJacob Faibussowitsch   PetscCall(MatDestroySubMatrices_Dummy(n, mat));
271563a75b2aSHong Zhang 
27169566063dSJacob Faibussowitsch   PetscCall(PetscFree(*mat));
27173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27182d033e1fSHong Zhang }
27192d033e1fSHong Zhang 
2720ba38deedSJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[])
2721d71ae5a4SJacob Faibussowitsch {
272297f1f81fSBarry Smith   PetscInt i;
2723cddf8d76SBarry Smith 
27243a40ed3dSBarry Smith   PetscFunctionBegin;
272548a46eb9SPierre Jolivet   if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n + 1, B));
2726cddf8d76SBarry Smith 
272748a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqAIJ(A, irow[i], icol[i], PETSC_DECIDE, scall, &(*B)[i]));
27283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2729cddf8d76SBarry Smith }
2730cddf8d76SBarry Smith 
2731ba38deedSJacob Faibussowitsch static PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A, PetscInt is_max, IS is[], PetscInt ov)
2732d71ae5a4SJacob Faibussowitsch {
2733e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data;
27349a88ca10SBarry Smith   PetscInt        row, i, j, k, l, ll, m, n, *nidx, isz, val;
27355d0c19d7SBarry Smith   const PetscInt *idx;
273658b7e2c1SStefano Zampini   PetscInt        start, end, *ai, *aj, bs = A->rmap->bs == A->cmap->bs ? A->rmap->bs : 1;
2737f1af5d2fSBarry Smith   PetscBT         table;
2738bbd702dbSSatish Balay 
27393a40ed3dSBarry Smith   PetscFunctionBegin;
27409a88ca10SBarry Smith   m  = A->rmap->n / bs;
2741e4d965acSSatish Balay   ai = a->i;
2742bfeeae90SHong Zhang   aj = a->j;
27438a047759SSatish Balay 
274408401ef6SPierre Jolivet   PetscCheck(ov >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "illegal negative overlap value used");
274506763907SSatish Balay 
27469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &nidx));
27479566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(m, &table));
274806763907SSatish Balay 
2749e4d965acSSatish Balay   for (i = 0; i < is_max; i++) {
2750b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2751e4d965acSSatish Balay     isz = 0;
27529566063dSJacob Faibussowitsch     PetscCall(PetscBTMemzero(m, table));
2753e4d965acSSatish Balay 
2754e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
27559566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is[i], &idx));
27569566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(is[i], &n));
2757e4d965acSSatish Balay 
27589a88ca10SBarry Smith     if (bs > 1) {
27599a88ca10SBarry Smith       /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
27609a88ca10SBarry Smith       for (j = 0; j < n; ++j) {
27619a88ca10SBarry Smith         if (!PetscBTLookupSet(table, idx[j] / bs)) nidx[isz++] = idx[j] / bs;
27629a88ca10SBarry Smith       }
27639a88ca10SBarry Smith       PetscCall(ISRestoreIndices(is[i], &idx));
27649a88ca10SBarry Smith       PetscCall(ISDestroy(&is[i]));
27659a88ca10SBarry Smith 
27669a88ca10SBarry Smith       k = 0;
27679a88ca10SBarry Smith       for (j = 0; j < ov; j++) { /* for each overlap */
27689a88ca10SBarry Smith         n = isz;
27699a88ca10SBarry Smith         for (; k < n; k++) { /* do only those rows in nidx[k], which are not done yet */
27709a88ca10SBarry Smith           for (ll = 0; ll < bs; ll++) {
27719a88ca10SBarry Smith             row   = bs * nidx[k] + ll;
27729a88ca10SBarry Smith             start = ai[row];
27739a88ca10SBarry Smith             end   = ai[row + 1];
27749a88ca10SBarry Smith             for (l = start; l < end; l++) {
27759a88ca10SBarry Smith               val = aj[l] / bs;
27769a88ca10SBarry Smith               if (!PetscBTLookupSet(table, val)) nidx[isz++] = val;
27779a88ca10SBarry Smith             }
27789a88ca10SBarry Smith           }
27799a88ca10SBarry Smith         }
27809a88ca10SBarry Smith       }
278157508eceSPierre Jolivet       PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, isz, nidx, PETSC_COPY_VALUES, is + i));
27829a88ca10SBarry Smith     } else {
2783dd097bc3SLois Curfman McInnes       /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2784e4d965acSSatish Balay       for (j = 0; j < n; ++j) {
27852205254eSKarl Rupp         if (!PetscBTLookupSet(table, idx[j])) nidx[isz++] = idx[j];
27864dcbc457SBarry Smith       }
27879566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(is[i], &idx));
27889566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is[i]));
2789e4d965acSSatish Balay 
279004a348a9SBarry Smith       k = 0;
279104a348a9SBarry Smith       for (j = 0; j < ov; j++) { /* for each overlap */
279204a348a9SBarry Smith         n = isz;
279306763907SSatish Balay         for (; k < n; k++) { /* do only those rows in nidx[k], which are not done yet */
2794e4d965acSSatish Balay           row   = nidx[k];
2795e4d965acSSatish Balay           start = ai[row];
2796e4d965acSSatish Balay           end   = ai[row + 1];
279704a348a9SBarry Smith           for (l = start; l < end; l++) {
2798efb16452SHong Zhang             val = aj[l];
27992205254eSKarl Rupp             if (!PetscBTLookupSet(table, val)) nidx[isz++] = val;
2800e4d965acSSatish Balay           }
2801e4d965acSSatish Balay         }
2802e4d965acSSatish Balay       }
280357508eceSPierre Jolivet       PetscCall(ISCreateGeneral(PETSC_COMM_SELF, isz, nidx, PETSC_COPY_VALUES, is + i));
2804e4d965acSSatish Balay     }
28059a88ca10SBarry Smith   }
28069566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&table));
28079566063dSJacob Faibussowitsch   PetscCall(PetscFree(nidx));
28083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28094dcbc457SBarry Smith }
281017ab2063SBarry Smith 
2811ba38deedSJacob Faibussowitsch static PetscErrorCode MatPermute_SeqAIJ(Mat A, IS rowp, IS colp, Mat *B)
2812d71ae5a4SJacob Faibussowitsch {
28130513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data;
28143b98c0a2SBarry Smith   PetscInt        i, nz = 0, m = A->rmap->n, n = A->cmap->n;
28155d0c19d7SBarry Smith   const PetscInt *row, *col;
28165d0c19d7SBarry Smith   PetscInt       *cnew, j, *lens;
281756cd22aeSBarry Smith   IS              icolp, irowp;
28180298fd71SBarry Smith   PetscInt       *cwork = NULL;
28190298fd71SBarry Smith   PetscScalar    *vwork = NULL;
28200513a670SBarry Smith 
28213a40ed3dSBarry Smith   PetscFunctionBegin;
28229566063dSJacob Faibussowitsch   PetscCall(ISInvertPermutation(rowp, PETSC_DECIDE, &irowp));
28239566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(irowp, &row));
28249566063dSJacob Faibussowitsch   PetscCall(ISInvertPermutation(colp, PETSC_DECIDE, &icolp));
28259566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(icolp, &col));
28260513a670SBarry Smith 
28270513a670SBarry Smith   /* determine lengths of permuted rows */
28289566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &lens));
28292205254eSKarl Rupp   for (i = 0; i < m; i++) lens[row[i]] = a->i[i + 1] - a->i[i];
28309566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B));
28319566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*B, m, n, m, n));
28329566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(*B, A, A));
28339566063dSJacob Faibussowitsch   PetscCall(MatSetType(*B, ((PetscObject)A)->type_name));
28349566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*B, 0, lens));
28359566063dSJacob Faibussowitsch   PetscCall(PetscFree(lens));
28360513a670SBarry Smith 
28379566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, &cnew));
28380513a670SBarry Smith   for (i = 0; i < m; i++) {
28399566063dSJacob Faibussowitsch     PetscCall(MatGetRow_SeqAIJ(A, i, &nz, &cwork, &vwork));
28402205254eSKarl Rupp     for (j = 0; j < nz; j++) cnew[j] = col[cwork[j]];
28419566063dSJacob Faibussowitsch     PetscCall(MatSetValues_SeqAIJ(*B, 1, &row[i], nz, cnew, vwork, INSERT_VALUES));
28429566063dSJacob Faibussowitsch     PetscCall(MatRestoreRow_SeqAIJ(A, i, &nz, &cwork, &vwork));
28430513a670SBarry Smith   }
28449566063dSJacob Faibussowitsch   PetscCall(PetscFree(cnew));
28452205254eSKarl Rupp 
28463c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
28472205254eSKarl Rupp 
28488c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
28499566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU(*B, A->boundtocpu));
28509fe5e383SStefano Zampini #endif
28519566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY));
28529566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY));
28539566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(irowp, &row));
28549566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(icolp, &col));
28559566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&irowp));
28569566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&icolp));
285748a46eb9SPierre Jolivet   if (rowp == colp) PetscCall(MatPropagateSymmetryOptions(A, *B));
28583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28590513a670SBarry Smith }
28600513a670SBarry Smith 
2861d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_SeqAIJ(Mat A, Mat B, MatStructure str)
2862d71ae5a4SJacob Faibussowitsch {
2863cb5b572fSBarry Smith   PetscFunctionBegin;
286433f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
286533f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
2866be6bf707SBarry Smith     Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
2867be6bf707SBarry Smith     Mat_SeqAIJ        *b = (Mat_SeqAIJ *)B->data;
28682e5835c6SStefano Zampini     const PetscScalar *aa;
28693ac85a22SJunchao Zhang     PetscScalar       *bb;
2870be6bf707SBarry Smith 
28719566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(A, &aa));
28723ac85a22SJunchao Zhang     PetscCall(MatSeqAIJGetArrayWrite(B, &bb));
28733ac85a22SJunchao Zhang 
287408401ef6SPierre 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]);
28753ac85a22SJunchao Zhang     PetscCall(PetscArraycpy(bb, aa, a->i[A->rmap->n]));
28769566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)B));
28779566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
28783ac85a22SJunchao Zhang     PetscCall(MatSeqAIJRestoreArrayWrite(B, &bb));
2879cb5b572fSBarry Smith   } else {
28809566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
2881cb5b572fSBarry Smith   }
28823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2883cb5b572fSBarry Smith }
2884cb5b572fSBarry Smith 
2885d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A, PetscScalar *array[])
2886d71ae5a4SJacob Faibussowitsch {
28876c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
28886e111a19SKarl Rupp 
28896c0721eeSBarry Smith   PetscFunctionBegin;
28906c0721eeSBarry Smith   *array = a->a;
28913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28926c0721eeSBarry Smith }
28936c0721eeSBarry Smith 
2894d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A, PetscScalar *array[])
2895d71ae5a4SJacob Faibussowitsch {
28966c0721eeSBarry Smith   PetscFunctionBegin;
2897f38c1e66SStefano Zampini   *array = NULL;
28983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28996c0721eeSBarry Smith }
2900273d9f13SBarry Smith 
29018229c054SShri Abhyankar /*
29028229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
29038229c054SShri Abhyankar    have different nonzero structure.
29048229c054SShri Abhyankar */
2905d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m, const PetscInt *xi, const PetscInt *xj, const PetscInt *yi, const PetscInt *yj, PetscInt *nnz)
2906d71ae5a4SJacob Faibussowitsch {
2907b264fe52SHong Zhang   PetscInt i, j, k, nzx, nzy;
2908ec7775f6SShri Abhyankar 
2909ec7775f6SShri Abhyankar   PetscFunctionBegin;
2910ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
2911ec7775f6SShri Abhyankar   for (i = 0; i < m; i++) {
29128e3a54c0SPierre Jolivet     const PetscInt *xjj = PetscSafePointerPlusOffset(xj, xi[i]), *yjj = PetscSafePointerPlusOffset(yj, yi[i]);
2913b264fe52SHong Zhang     nzx    = xi[i + 1] - xi[i];
2914b264fe52SHong Zhang     nzy    = yi[i + 1] - yi[i];
29158af7cee1SJed Brown     nnz[i] = 0;
29168af7cee1SJed Brown     for (j = 0, k = 0; j < nzx; j++) {                  /* Point in X */
2917b264fe52SHong Zhang       for (; k < nzy && yjj[k] < xjj[j]; k++) nnz[i]++; /* Catch up to X */
2918b264fe52SHong Zhang       if (k < nzy && yjj[k] == xjj[j]) k++;             /* Skip duplicate */
29198af7cee1SJed Brown       nnz[i]++;
29208af7cee1SJed Brown     }
29218af7cee1SJed Brown     for (; k < nzy; k++) nnz[i]++;
2922ec7775f6SShri Abhyankar   }
29233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2924ec7775f6SShri Abhyankar }
2925ec7775f6SShri Abhyankar 
2926d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y, Mat X, PetscInt *nnz)
2927d71ae5a4SJacob Faibussowitsch {
2928b264fe52SHong Zhang   PetscInt    m = Y->rmap->N;
2929b264fe52SHong Zhang   Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data;
2930b264fe52SHong Zhang   Mat_SeqAIJ *y = (Mat_SeqAIJ *)Y->data;
2931b264fe52SHong Zhang 
2932b264fe52SHong Zhang   PetscFunctionBegin;
2933b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
29349566063dSJacob Faibussowitsch   PetscCall(MatAXPYGetPreallocation_SeqX_private(m, x->i, x->j, y->i, y->j, nnz));
29353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2936b264fe52SHong Zhang }
2937b264fe52SHong Zhang 
2938d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_SeqAIJ(Mat Y, PetscScalar a, Mat X, MatStructure str)
2939d71ae5a4SJacob Faibussowitsch {
2940ac90fabeSBarry Smith   Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data, *y = (Mat_SeqAIJ *)Y->data;
2941ac90fabeSBarry Smith 
2942ac90fabeSBarry Smith   PetscFunctionBegin;
2943134adf20SPierre Jolivet   if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) {
2944134adf20SPierre Jolivet     PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE;
2945134adf20SPierre Jolivet     if (e) {
29469566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(x->i, y->i, Y->rmap->n + 1, &e));
294781fa06acSBarry Smith       if (e) {
29489566063dSJacob Faibussowitsch         PetscCall(PetscArraycmp(x->j, y->j, y->nz, &e));
2949134adf20SPierre Jolivet         if (e) str = SAME_NONZERO_PATTERN;
295081fa06acSBarry Smith       }
295181fa06acSBarry Smith     }
295254c59aa7SJacob Faibussowitsch     if (!e) PetscCheck(str != SAME_NONZERO_PATTERN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatStructure is not SAME_NONZERO_PATTERN");
295381fa06acSBarry Smith   }
2954ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
29552e5835c6SStefano Zampini     const PetscScalar *xa;
29562e5835c6SStefano Zampini     PetscScalar       *ya, alpha = a;
295781fa06acSBarry Smith     PetscBLASInt       one = 1, bnz;
295881fa06acSBarry Smith 
29599566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(x->nz, &bnz));
29609566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(Y, &ya));
29619566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(X, &xa));
2962792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &alpha, xa, &one, ya, &one));
29639566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(X, &xa));
29649566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArray(Y, &ya));
29659566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * bnz));
29669566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)Y));
2967ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
29689566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
2969ac90fabeSBarry Smith   } else {
29708229c054SShri Abhyankar     Mat       B;
29718229c054SShri Abhyankar     PetscInt *nnz;
29729566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Y->rmap->N, &nnz));
29739566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &B));
29749566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)B, ((PetscObject)Y)->name));
29759566063dSJacob Faibussowitsch     PetscCall(MatSetLayouts(B, Y->rmap, Y->cmap));
29769566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, ((PetscObject)Y)->type_name));
29779566063dSJacob Faibussowitsch     PetscCall(MatAXPYGetPreallocation_SeqAIJ(Y, X, nnz));
29789566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz));
29799566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
29809566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
29819bb234a9SBarry Smith     PetscCall(MatSeqAIJCheckInode(Y));
29829566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz));
2983ac90fabeSBarry Smith   }
29843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2985ac90fabeSBarry Smith }
2986ac90fabeSBarry Smith 
2987d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat)
2988d71ae5a4SJacob Faibussowitsch {
2989354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
2990354c94deSBarry Smith   Mat_SeqAIJ  *aij = (Mat_SeqAIJ *)mat->data;
2991354c94deSBarry Smith   PetscInt     i, nz;
2992354c94deSBarry Smith   PetscScalar *a;
2993354c94deSBarry Smith 
2994354c94deSBarry Smith   PetscFunctionBegin;
2995354c94deSBarry Smith   nz = aij->nz;
29969566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(mat, &a));
29972205254eSKarl Rupp   for (i = 0; i < nz; i++) a[i] = PetscConj(a[i]);
29989566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(mat, &a));
2999354c94deSBarry Smith #else
3000354c94deSBarry Smith   PetscFunctionBegin;
3001354c94deSBarry Smith #endif
30023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3003354c94deSBarry Smith }
3004354c94deSBarry Smith 
3005ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[])
3006d71ae5a4SJacob Faibussowitsch {
3007e34fafa9SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
3008d0f46423SBarry Smith   PetscInt         i, j, m = A->rmap->n, *ai, *aj, ncols, n;
3009e34fafa9SBarry Smith   PetscReal        atmp;
3010985db425SBarry Smith   PetscScalar     *x;
3011ce496241SStefano Zampini   const MatScalar *aa, *av;
3012e34fafa9SBarry Smith 
3013e34fafa9SBarry Smith   PetscFunctionBegin;
301428b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
30159566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
3016ce496241SStefano Zampini   aa = av;
3017e34fafa9SBarry Smith   ai = a->i;
3018e34fafa9SBarry Smith   aj = a->j;
3019e34fafa9SBarry Smith 
30209566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v, &x));
30219566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &n));
302208401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
3023e34fafa9SBarry Smith   for (i = 0; i < m; i++) {
30249371c9d4SSatish Balay     ncols = ai[1] - ai[0];
30259371c9d4SSatish Balay     ai++;
302662e5df07SMark Adams     x[i] = 0;
3027e34fafa9SBarry Smith     for (j = 0; j < ncols; j++) {
3028985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
30299371c9d4SSatish Balay       if (PetscAbsScalar(x[i]) < atmp) {
30309371c9d4SSatish Balay         x[i] = atmp;
30319371c9d4SSatish Balay         if (idx) idx[i] = *aj;
30329371c9d4SSatish Balay       }
30339371c9d4SSatish Balay       aa++;
30349371c9d4SSatish Balay       aj++;
3035985db425SBarry Smith     }
3036985db425SBarry Smith   }
30379566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v, &x));
30389566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
30393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3040985db425SBarry Smith }
3041985db425SBarry Smith 
3042eede4a3fSMark Adams static PetscErrorCode MatGetRowSumAbs_SeqAIJ(Mat A, Vec v)
3043eede4a3fSMark Adams {
3044eede4a3fSMark Adams   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
3045eede4a3fSMark Adams   PetscInt         i, j, m = A->rmap->n, *ai, ncols, n;
3046eede4a3fSMark Adams   PetscScalar     *x;
3047eede4a3fSMark Adams   const MatScalar *aa, *av;
3048eede4a3fSMark Adams 
3049eede4a3fSMark Adams   PetscFunctionBegin;
3050eede4a3fSMark Adams   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3051eede4a3fSMark Adams   PetscCall(MatSeqAIJGetArrayRead(A, &av));
3052eede4a3fSMark Adams   aa = av;
3053eede4a3fSMark Adams   ai = a->i;
3054eede4a3fSMark Adams 
3055eede4a3fSMark Adams   PetscCall(VecGetArrayWrite(v, &x));
3056eede4a3fSMark Adams   PetscCall(VecGetLocalSize(v, &n));
3057eede4a3fSMark Adams   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
3058eede4a3fSMark Adams   for (i = 0; i < m; i++) {
3059eede4a3fSMark Adams     ncols = ai[1] - ai[0];
3060eede4a3fSMark Adams     ai++;
306162e5df07SMark Adams     x[i] = 0;
3062eede4a3fSMark Adams     for (j = 0; j < ncols; j++) {
3063eede4a3fSMark Adams       x[i] += PetscAbsScalar(*aa);
3064eede4a3fSMark Adams       aa++;
3065eede4a3fSMark Adams     }
3066eede4a3fSMark Adams   }
3067eede4a3fSMark Adams   PetscCall(VecRestoreArrayWrite(v, &x));
3068eede4a3fSMark Adams   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
3069eede4a3fSMark Adams   PetscFunctionReturn(PETSC_SUCCESS);
3070eede4a3fSMark Adams }
3071eede4a3fSMark Adams 
3072ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetRowMax_SeqAIJ(Mat A, Vec v, PetscInt idx[])
3073d71ae5a4SJacob Faibussowitsch {
3074985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
3075d0f46423SBarry Smith   PetscInt         i, j, m = A->rmap->n, *ai, *aj, ncols, n;
3076985db425SBarry Smith   PetscScalar     *x;
3077ce496241SStefano Zampini   const MatScalar *aa, *av;
3078985db425SBarry Smith 
3079985db425SBarry Smith   PetscFunctionBegin;
308028b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
30819566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
3082ce496241SStefano Zampini   aa = av;
3083985db425SBarry Smith   ai = a->i;
3084985db425SBarry Smith   aj = a->j;
3085985db425SBarry Smith 
30869566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v, &x));
30879566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &n));
308808401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
3089985db425SBarry Smith   for (i = 0; i < m; i++) {
30909371c9d4SSatish Balay     ncols = ai[1] - ai[0];
30919371c9d4SSatish Balay     ai++;
3092d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
30939371c9d4SSatish Balay       x[i] = *aa;
30949371c9d4SSatish Balay       if (idx) idx[i] = 0;
3095985db425SBarry Smith     } else { /* row is sparse so already KNOW maximum is 0.0 or higher */
3096985db425SBarry Smith       x[i] = 0.0;
3097985db425SBarry Smith       if (idx) {
3098985db425SBarry Smith         for (j = 0; j < ncols; j++) { /* find first implicit 0.0 in the row */
3099985db425SBarry Smith           if (aj[j] > j) {
3100985db425SBarry Smith             idx[i] = j;
3101985db425SBarry Smith             break;
3102985db425SBarry Smith           }
3103985db425SBarry Smith         }
31041a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
31051a254869SHong Zhang         if (j == ncols && j < A->cmap->n) idx[i] = j;
3106985db425SBarry Smith       }
3107985db425SBarry Smith     }
3108985db425SBarry Smith     for (j = 0; j < ncols; j++) {
31099371c9d4SSatish Balay       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {
31109371c9d4SSatish Balay         x[i] = *aa;
31119371c9d4SSatish Balay         if (idx) idx[i] = *aj;
31129371c9d4SSatish Balay       }
31139371c9d4SSatish Balay       aa++;
31149371c9d4SSatish Balay       aj++;
3115985db425SBarry Smith     }
3116985db425SBarry Smith   }
31179566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v, &x));
31189566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
31193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3120985db425SBarry Smith }
3121985db425SBarry Smith 
3122ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A, Vec v, PetscInt idx[])
3123d71ae5a4SJacob Faibussowitsch {
3124c87e5d42SMatthew Knepley   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
3125c87e5d42SMatthew Knepley   PetscInt         i, j, m = A->rmap->n, *ai, *aj, ncols, n;
3126ce496241SStefano Zampini   PetscScalar     *x;
3127ce496241SStefano Zampini   const MatScalar *aa, *av;
3128c87e5d42SMatthew Knepley 
3129c87e5d42SMatthew Knepley   PetscFunctionBegin;
31309566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
3131ce496241SStefano Zampini   aa = av;
3132c87e5d42SMatthew Knepley   ai = a->i;
3133c87e5d42SMatthew Knepley   aj = a->j;
3134c87e5d42SMatthew Knepley 
31359566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v, &x));
31369566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &n));
313708401ef6SPierre Jolivet   PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n);
3138c87e5d42SMatthew Knepley   for (i = 0; i < m; i++) {
31399371c9d4SSatish Balay     ncols = ai[1] - ai[0];
31409371c9d4SSatish Balay     ai++;
3141f07e67edSHong Zhang     if (ncols == A->cmap->n) { /* row is dense */
31429371c9d4SSatish Balay       x[i] = *aa;
31439371c9d4SSatish Balay       if (idx) idx[i] = 0;
3144f07e67edSHong Zhang     } else { /* row is sparse so already KNOW minimum is 0.0 or higher */
3145f07e67edSHong Zhang       x[i] = 0.0;
3146f07e67edSHong Zhang       if (idx) { /* find first implicit 0.0 in the row */
3147289a08f5SMatthew Knepley         for (j = 0; j < ncols; j++) {
3148f07e67edSHong Zhang           if (aj[j] > j) {
3149f07e67edSHong Zhang             idx[i] = j;
31502205254eSKarl Rupp             break;
31512205254eSKarl Rupp           }
3152289a08f5SMatthew Knepley         }
3153f07e67edSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3154f07e67edSHong Zhang         if (j == ncols && j < A->cmap->n) idx[i] = j;
3155f07e67edSHong Zhang       }
3156289a08f5SMatthew Knepley     }
3157c87e5d42SMatthew Knepley     for (j = 0; j < ncols; j++) {
31589371c9d4SSatish Balay       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {
31599371c9d4SSatish Balay         x[i] = *aa;
31609371c9d4SSatish Balay         if (idx) idx[i] = *aj;
31619371c9d4SSatish Balay       }
31629371c9d4SSatish Balay       aa++;
31639371c9d4SSatish Balay       aj++;
3164c87e5d42SMatthew Knepley     }
3165c87e5d42SMatthew Knepley   }
31669566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v, &x));
31679566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
31683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3169c87e5d42SMatthew Knepley }
3170c87e5d42SMatthew Knepley 
3171ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetRowMin_SeqAIJ(Mat A, Vec v, PetscInt idx[])
3172d71ae5a4SJacob Faibussowitsch {
3173985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
3174d9ca1df4SBarry Smith   PetscInt         i, j, m = A->rmap->n, ncols, n;
3175d9ca1df4SBarry Smith   const PetscInt  *ai, *aj;
3176985db425SBarry Smith   PetscScalar     *x;
3177ce496241SStefano Zampini   const MatScalar *aa, *av;
3178985db425SBarry Smith 
3179985db425SBarry Smith   PetscFunctionBegin;
318028b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
31819566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
3182ce496241SStefano Zampini   aa = av;
3183985db425SBarry Smith   ai = a->i;
3184985db425SBarry Smith   aj = a->j;
3185985db425SBarry Smith 
31869566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v, &x));
31879566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &n));
318808401ef6SPierre Jolivet   PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
3189985db425SBarry Smith   for (i = 0; i < m; i++) {
31909371c9d4SSatish Balay     ncols = ai[1] - ai[0];
31919371c9d4SSatish Balay     ai++;
3192d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
31939371c9d4SSatish Balay       x[i] = *aa;
31949371c9d4SSatish Balay       if (idx) idx[i] = 0;
3195985db425SBarry Smith     } else { /* row is sparse so already KNOW minimum is 0.0 or lower */
3196985db425SBarry Smith       x[i] = 0.0;
3197985db425SBarry Smith       if (idx) { /* find first implicit 0.0 in the row */
3198985db425SBarry Smith         for (j = 0; j < ncols; j++) {
3199985db425SBarry Smith           if (aj[j] > j) {
3200985db425SBarry Smith             idx[i] = j;
3201985db425SBarry Smith             break;
3202985db425SBarry Smith           }
3203985db425SBarry Smith         }
3204fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3205fa213d2fSHong Zhang         if (j == ncols && j < A->cmap->n) idx[i] = j;
3206985db425SBarry Smith       }
3207985db425SBarry Smith     }
3208985db425SBarry Smith     for (j = 0; j < ncols; j++) {
32099371c9d4SSatish Balay       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {
32109371c9d4SSatish Balay         x[i] = *aa;
32119371c9d4SSatish Balay         if (idx) idx[i] = *aj;
32129371c9d4SSatish Balay       }
32139371c9d4SSatish Balay       aa++;
32149371c9d4SSatish Balay       aj++;
3215e34fafa9SBarry Smith     }
3216e34fafa9SBarry Smith   }
32179566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v, &x));
32189566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
32193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3220e34fafa9SBarry Smith }
3221bbead8a2SBarry Smith 
3222ba38deedSJacob Faibussowitsch static PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A, const PetscScalar **values)
3223d71ae5a4SJacob Faibussowitsch {
3224bbead8a2SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data;
322558b7e2c1SStefano Zampini   PetscInt        i, bs = A->rmap->bs, mbs = A->rmap->n / bs, ipvt[5], bs2 = bs * bs, *v_pivots, ij[7], *IJ, j;
3226bbead8a2SBarry Smith   MatScalar      *diag, work[25], *v_work;
32270da83c2eSBarry Smith   const PetscReal shift = 0.0;
32281a9391e3SHong Zhang   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
3229bbead8a2SBarry Smith 
3230bbead8a2SBarry Smith   PetscFunctionBegin;
3231a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
32324a0d0026SBarry Smith   if (a->ibdiagvalid) {
32334a0d0026SBarry Smith     if (values) *values = a->ibdiag;
32343ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
32354a0d0026SBarry Smith   }
32363a7d0413SPierre Jolivet   if (!a->ibdiag) PetscCall(PetscMalloc1(bs2 * mbs, &a->ibdiag));
3237bbead8a2SBarry Smith   diag = a->ibdiag;
3238bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3239bbead8a2SBarry Smith   /* factor and invert each block */
3240bbead8a2SBarry Smith   switch (bs) {
3241bbead8a2SBarry Smith   case 1:
3242bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
32439566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, 1, &i, 1, &i, diag + i));
3244ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3245966bd95aSPierre Jolivet         PetscCheck(allowzeropivot, 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);
32467b6c816cSBarry Smith         A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
32477b6c816cSBarry Smith         A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
32487b6c816cSBarry Smith         A->factorerror_zeropivot_row   = i;
32499566063dSJacob Faibussowitsch         PetscCall(PetscInfo(A, "Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n", i, (double)PetscAbsScalar(diag[i]), (double)PETSC_MACHINE_EPSILON));
3250ec1892c8SHong Zhang       }
3251bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3252bbead8a2SBarry Smith     }
3253bbead8a2SBarry Smith     break;
3254bbead8a2SBarry Smith   case 2:
3255bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
32569371c9d4SSatish Balay       ij[0] = 2 * i;
32579371c9d4SSatish Balay       ij[1] = 2 * i + 1;
32589566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, 2, ij, 2, ij, diag));
32599566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected));
32607b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
32619566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_2(diag));
3262bbead8a2SBarry Smith       diag += 4;
3263bbead8a2SBarry Smith     }
3264bbead8a2SBarry Smith     break;
3265bbead8a2SBarry Smith   case 3:
3266bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
32679371c9d4SSatish Balay       ij[0] = 3 * i;
32689371c9d4SSatish Balay       ij[1] = 3 * i + 1;
32699371c9d4SSatish Balay       ij[2] = 3 * i + 2;
32709566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, 3, ij, 3, ij, diag));
32719566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected));
32727b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
32739566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_3(diag));
3274bbead8a2SBarry Smith       diag += 9;
3275bbead8a2SBarry Smith     }
3276bbead8a2SBarry Smith     break;
3277bbead8a2SBarry Smith   case 4:
3278bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
32799371c9d4SSatish Balay       ij[0] = 4 * i;
32809371c9d4SSatish Balay       ij[1] = 4 * i + 1;
32819371c9d4SSatish Balay       ij[2] = 4 * i + 2;
32829371c9d4SSatish Balay       ij[3] = 4 * i + 3;
32839566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, 4, ij, 4, ij, diag));
32849566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected));
32857b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
32869566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_4(diag));
3287bbead8a2SBarry Smith       diag += 16;
3288bbead8a2SBarry Smith     }
3289bbead8a2SBarry Smith     break;
3290bbead8a2SBarry Smith   case 5:
3291bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
32929371c9d4SSatish Balay       ij[0] = 5 * i;
32939371c9d4SSatish Balay       ij[1] = 5 * i + 1;
32949371c9d4SSatish Balay       ij[2] = 5 * i + 2;
32959371c9d4SSatish Balay       ij[3] = 5 * i + 3;
32969371c9d4SSatish Balay       ij[4] = 5 * i + 4;
32979566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, 5, ij, 5, ij, diag));
32989566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
32997b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33009566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_5(diag));
3301bbead8a2SBarry Smith       diag += 25;
3302bbead8a2SBarry Smith     }
3303bbead8a2SBarry Smith     break;
3304bbead8a2SBarry Smith   case 6:
3305bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
33069371c9d4SSatish Balay       ij[0] = 6 * i;
33079371c9d4SSatish Balay       ij[1] = 6 * i + 1;
33089371c9d4SSatish Balay       ij[2] = 6 * i + 2;
33099371c9d4SSatish Balay       ij[3] = 6 * i + 3;
33109371c9d4SSatish Balay       ij[4] = 6 * i + 4;
33119371c9d4SSatish Balay       ij[5] = 6 * i + 5;
33129566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, 6, ij, 6, ij, diag));
33139566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected));
33147b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33159566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_6(diag));
3316bbead8a2SBarry Smith       diag += 36;
3317bbead8a2SBarry Smith     }
3318bbead8a2SBarry Smith     break;
3319bbead8a2SBarry Smith   case 7:
3320bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
33219371c9d4SSatish Balay       ij[0] = 7 * i;
33229371c9d4SSatish Balay       ij[1] = 7 * i + 1;
33239371c9d4SSatish Balay       ij[2] = 7 * i + 2;
33249371c9d4SSatish Balay       ij[3] = 7 * i + 3;
33259371c9d4SSatish Balay       ij[4] = 7 * i + 4;
33269371c9d4SSatish Balay       ij[5] = 7 * i + 5;
3327cdd8bf47SJunchao Zhang       ij[6] = 7 * i + 6;
33289566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, 7, ij, 7, ij, diag));
33299566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected));
33307b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33319566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_7(diag));
3332bbead8a2SBarry Smith       diag += 49;
3333bbead8a2SBarry Smith     }
3334bbead8a2SBarry Smith     break;
3335bbead8a2SBarry Smith   default:
33369566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(bs, &v_work, bs, &v_pivots, bs, &IJ));
3337bbead8a2SBarry Smith     for (i = 0; i < mbs; i++) {
3338ad540459SPierre Jolivet       for (j = 0; j < bs; j++) IJ[j] = bs * i + j;
33399566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A, bs, IJ, bs, IJ, diag));
33409566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A(bs, diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
33417b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33429566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_N(diag, bs));
3343bbead8a2SBarry Smith       diag += bs2;
3344bbead8a2SBarry Smith     }
33459566063dSJacob Faibussowitsch     PetscCall(PetscFree3(v_work, v_pivots, IJ));
3346bbead8a2SBarry Smith   }
3347bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
33483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3349bbead8a2SBarry Smith }
3350bbead8a2SBarry Smith 
3351d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetRandom_SeqAIJ(Mat x, PetscRandom rctx)
3352d71ae5a4SJacob Faibussowitsch {
335373a71a0fSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data;
3354fff043a9SJunchao Zhang   PetscScalar a, *aa;
335573a71a0fSBarry Smith   PetscInt    m, n, i, j, col;
335673a71a0fSBarry Smith 
335773a71a0fSBarry Smith   PetscFunctionBegin;
335873a71a0fSBarry Smith   if (!x->assembled) {
33599566063dSJacob Faibussowitsch     PetscCall(MatGetSize(x, &m, &n));
336073a71a0fSBarry Smith     for (i = 0; i < m; i++) {
336173a71a0fSBarry Smith       for (j = 0; j < aij->imax[i]; j++) {
33629566063dSJacob Faibussowitsch         PetscCall(PetscRandomGetValue(rctx, &a));
336373a71a0fSBarry Smith         col = (PetscInt)(n * PetscRealPart(a));
33649566063dSJacob Faibussowitsch         PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES));
336573a71a0fSBarry Smith       }
336673a71a0fSBarry Smith     }
3367e2ce353bSJunchao Zhang   } else {
33689566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayWrite(x, &aa));
33699566063dSJacob Faibussowitsch     for (i = 0; i < aij->nz; i++) PetscCall(PetscRandomGetValue(rctx, aa + i));
33709566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayWrite(x, &aa));
3371e2ce353bSJunchao Zhang   }
33729566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
33739566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
33743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
337573a71a0fSBarry Smith }
337673a71a0fSBarry Smith 
3377679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3378d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x, PetscInt low, PetscInt high, PetscRandom rctx)
3379d71ae5a4SJacob Faibussowitsch {
3380679944adSJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)x->data;
3381679944adSJunchao Zhang   PetscScalar a;
3382679944adSJunchao Zhang   PetscInt    m, n, i, j, col, nskip;
3383679944adSJunchao Zhang 
3384679944adSJunchao Zhang   PetscFunctionBegin;
3385679944adSJunchao Zhang   nskip = high - low;
33869566063dSJacob Faibussowitsch   PetscCall(MatGetSize(x, &m, &n));
3387679944adSJunchao Zhang   n -= nskip; /* shrink number of columns where nonzeros can be set */
3388679944adSJunchao Zhang   for (i = 0; i < m; i++) {
3389679944adSJunchao Zhang     for (j = 0; j < aij->imax[i]; j++) {
33909566063dSJacob Faibussowitsch       PetscCall(PetscRandomGetValue(rctx, &a));
3391679944adSJunchao Zhang       col = (PetscInt)(n * PetscRealPart(a));
3392679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
33939566063dSJacob Faibussowitsch       PetscCall(MatSetValues(x, 1, &i, 1, &col, &a, ADD_VALUES));
3394679944adSJunchao Zhang     }
3395e2ce353bSJunchao Zhang   }
33969566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
33979566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
33983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3399679944adSJunchao Zhang }
3400679944adSJunchao Zhang 
34010a6ffc59SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ,
3402cb5b572fSBarry Smith                                        MatGetRow_SeqAIJ,
3403cb5b572fSBarry Smith                                        MatRestoreRow_SeqAIJ,
3404cb5b572fSBarry Smith                                        MatMult_SeqAIJ,
340597304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqAIJ,
34067c922b88SBarry Smith                                        MatMultTranspose_SeqAIJ,
34077c922b88SBarry Smith                                        MatMultTransposeAdd_SeqAIJ,
3408f4259b30SLisandro Dalcin                                        NULL,
3409f4259b30SLisandro Dalcin                                        NULL,
3410f4259b30SLisandro Dalcin                                        NULL,
3411f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
3412cb5b572fSBarry Smith                                        MatLUFactor_SeqAIJ,
3413f4259b30SLisandro Dalcin                                        NULL,
341441f059aeSBarry Smith                                        MatSOR_SeqAIJ,
341591e9d3e2SHong Zhang                                        MatTranspose_SeqAIJ,
341697304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqAIJ,
3417cb5b572fSBarry Smith                                        MatEqual_SeqAIJ,
3418cb5b572fSBarry Smith                                        MatGetDiagonal_SeqAIJ,
3419cb5b572fSBarry Smith                                        MatDiagonalScale_SeqAIJ,
3420cb5b572fSBarry Smith                                        MatNorm_SeqAIJ,
3421f4259b30SLisandro Dalcin                                        /* 20*/ NULL,
3422cb5b572fSBarry Smith                                        MatAssemblyEnd_SeqAIJ,
3423cb5b572fSBarry Smith                                        MatSetOption_SeqAIJ,
3424cb5b572fSBarry Smith                                        MatZeroEntries_SeqAIJ,
3425d519adbfSMatthew Knepley                                        /* 24*/ MatZeroRows_SeqAIJ,
3426f4259b30SLisandro Dalcin                                        NULL,
3427f4259b30SLisandro Dalcin                                        NULL,
3428f4259b30SLisandro Dalcin                                        NULL,
3429f4259b30SLisandro Dalcin                                        NULL,
343026cec326SBarry Smith                                        /* 29*/ MatSetUp_Seq_Hash,
3431f4259b30SLisandro Dalcin                                        NULL,
3432f4259b30SLisandro Dalcin                                        NULL,
3433f4259b30SLisandro Dalcin                                        NULL,
3434f4259b30SLisandro Dalcin                                        NULL,
3435d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqAIJ,
3436f4259b30SLisandro Dalcin                                        NULL,
3437f4259b30SLisandro Dalcin                                        NULL,
3438cb5b572fSBarry Smith                                        MatILUFactor_SeqAIJ,
3439f4259b30SLisandro Dalcin                                        NULL,
3440d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqAIJ,
34417dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqAIJ,
3442cb5b572fSBarry Smith                                        MatIncreaseOverlap_SeqAIJ,
3443cb5b572fSBarry Smith                                        MatGetValues_SeqAIJ,
3444cb5b572fSBarry Smith                                        MatCopy_SeqAIJ,
3445d519adbfSMatthew Knepley                                        /* 44*/ MatGetRowMax_SeqAIJ,
3446cb5b572fSBarry Smith                                        MatScale_SeqAIJ,
34477d68702bSBarry Smith                                        MatShift_SeqAIJ,
344879299369SBarry Smith                                        MatDiagonalSet_SeqAIJ,
34496e169961SBarry Smith                                        MatZeroRowsColumns_SeqAIJ,
345073a71a0fSBarry Smith                                        /* 49*/ MatSetRandom_SeqAIJ,
34513b2fbd54SBarry Smith                                        MatGetRowIJ_SeqAIJ,
34523b2fbd54SBarry Smith                                        MatRestoreRowIJ_SeqAIJ,
34533b2fbd54SBarry Smith                                        MatGetColumnIJ_SeqAIJ,
3454a93ec695SBarry Smith                                        MatRestoreColumnIJ_SeqAIJ,
345593dfae19SHong Zhang                                        /* 54*/ MatFDColoringCreate_SeqXAIJ,
3456f4259b30SLisandro Dalcin                                        NULL,
3457f4259b30SLisandro Dalcin                                        NULL,
3458cda55fadSBarry Smith                                        MatPermute_SeqAIJ,
3459f4259b30SLisandro Dalcin                                        NULL,
3460f4259b30SLisandro Dalcin                                        /* 59*/ NULL,
3461b9b97703SBarry Smith                                        MatDestroy_SeqAIJ,
3462b9b97703SBarry Smith                                        MatView_SeqAIJ,
3463f4259b30SLisandro Dalcin                                        NULL,
3464f4259b30SLisandro Dalcin                                        NULL,
34658bb0f5c6SPierre Jolivet                                        /* 64*/ MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3466f4259b30SLisandro Dalcin                                        NULL,
3467f4259b30SLisandro Dalcin                                        NULL,
3468f4259b30SLisandro Dalcin                                        NULL,
34698bb0f5c6SPierre Jolivet                                        MatGetRowMaxAbs_SeqAIJ,
34708bb0f5c6SPierre Jolivet                                        /* 69*/ MatGetRowMinAbs_SeqAIJ,
3471f4259b30SLisandro Dalcin                                        NULL,
3472f4259b30SLisandro Dalcin                                        NULL,
34733acb8795SBarry Smith                                        MatFDColoringApply_AIJ,
3474f4259b30SLisandro Dalcin                                        NULL,
34758bb0f5c6SPierre Jolivet                                        /* 74*/ MatFindZeroDiagonals_SeqAIJ,
3476f4259b30SLisandro Dalcin                                        NULL,
3477f4259b30SLisandro Dalcin                                        NULL,
3478f4259b30SLisandro Dalcin                                        NULL,
3479bc011b1eSHong Zhang                                        MatLoad_SeqAIJ,
34808bb0f5c6SPierre Jolivet                                        /* 79*/ NULL,
34818bb0f5c6SPierre Jolivet                                        NULL,
34828bb0f5c6SPierre Jolivet                                        NULL,
34838bb0f5c6SPierre Jolivet                                        NULL,
34848bb0f5c6SPierre Jolivet                                        NULL,
34856cff0a6bSPierre Jolivet                                        /* 84*/ NULL,
348626be0446SHong Zhang                                        MatMatMultNumeric_SeqAIJ_SeqAIJ,
34878bb0f5c6SPierre Jolivet                                        MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3488f4259b30SLisandro Dalcin                                        NULL,
34896fc122caSHong Zhang                                        MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
34908bb0f5c6SPierre Jolivet                                        /* 90*/ NULL,
34918bb0f5c6SPierre Jolivet                                        MatProductSetFromOptions_SeqAIJ,
3492f4259b30SLisandro Dalcin                                        NULL,
3493f4259b30SLisandro Dalcin                                        NULL,
349487d4246cSBarry Smith                                        MatConjugate_SeqAIJ,
34958bb0f5c6SPierre Jolivet                                        /* 94*/ NULL,
34968bb0f5c6SPierre Jolivet                                        MatSetValuesRow_SeqAIJ,
349799cafbc1SBarry Smith                                        MatRealPart_SeqAIJ,
3498f5edf698SHong Zhang                                        MatImaginaryPart_SeqAIJ,
3499f4259b30SLisandro Dalcin                                        NULL,
35008bb0f5c6SPierre Jolivet                                        /* 99*/ NULL,
35018bb0f5c6SPierre Jolivet                                        MatMatSolve_SeqAIJ,
3502f4259b30SLisandro Dalcin                                        NULL,
35032af78befSBarry Smith                                        MatGetRowMin_SeqAIJ,
3504f4259b30SLisandro Dalcin                                        NULL,
3505*421480d9SBarry Smith                                        /*104*/ NULL,
3506f4259b30SLisandro Dalcin                                        NULL,
3507f4259b30SLisandro Dalcin                                        NULL,
3508f4259b30SLisandro Dalcin                                        NULL,
3509f4259b30SLisandro Dalcin                                        NULL,
35108bb0f5c6SPierre Jolivet                                        /*109*/ NULL,
3511f4259b30SLisandro Dalcin                                        NULL,
3512f4259b30SLisandro Dalcin                                        NULL,
3513f4259b30SLisandro Dalcin                                        NULL,
3514*421480d9SBarry Smith                                        MatGetMultiProcBlock_SeqAIJ,
3515*421480d9SBarry Smith                                        /*114*/ MatFindNonzeroRows_SeqAIJ,
3516a873a8cdSSam Reynolds                                        MatGetColumnReductions_SeqAIJ,
351737868618SMatthew G Knepley                                        MatInvertBlockDiagonal_SeqAIJ,
35180da83c2eSBarry Smith                                        MatInvertVariableBlockDiagonal_SeqAIJ,
3519f4259b30SLisandro Dalcin                                        NULL,
3520*421480d9SBarry Smith                                        /*119*/ NULL,
3521f4259b30SLisandro Dalcin                                        NULL,
352275648e8dSHong Zhang                                        MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3523b9af6bddSHong Zhang                                        MatTransposeColoringCreate_SeqAIJ,
3524*421480d9SBarry Smith                                        MatTransColoringApplySpToDen_SeqAIJ,
3525*421480d9SBarry Smith                                        /*124*/ MatTransColoringApplyDenToSp_SeqAIJ,
35263964eb88SJed Brown                                        MatRARtNumeric_SeqAIJ_SeqAIJ,
35278bb0f5c6SPierre Jolivet                                        NULL,
35288bb0f5c6SPierre Jolivet                                        NULL,
3529*421480d9SBarry Smith                                        MatFDColoringSetUp_SeqXAIJ,
3530*421480d9SBarry Smith                                        /*129*/ MatFindOffBlockDiagonalEntries_SeqAIJ,
35318bb0f5c6SPierre Jolivet                                        MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
35328bb0f5c6SPierre Jolivet                                        MatDestroySubMatrices_SeqAIJ,
35338bb0f5c6SPierre Jolivet                                        NULL,
3534*421480d9SBarry Smith                                        NULL,
3535*421480d9SBarry Smith                                        /*134*/ MatCreateGraph_Simple_AIJ,
35368bb0f5c6SPierre Jolivet                                        MatTransposeSymbolic_SeqAIJ,
35378bb0f5c6SPierre Jolivet                                        MatEliminateZeros_SeqAIJ,
35388bb0f5c6SPierre Jolivet                                        MatGetRowSumAbs_SeqAIJ,
3539f4259b30SLisandro Dalcin                                        NULL,
3540*421480d9SBarry Smith                                        /*139*/ NULL,
3541f4259b30SLisandro Dalcin                                        NULL,
354203db1824SAlex Lindsay                                        MatCopyHashToXAIJ_Seq_Hash,
3543c2be7ffeSStefano Zampini                                        NULL,
354403db1824SAlex Lindsay                                        NULL};
354517ab2063SBarry Smith 
3546ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat, PetscInt *indices)
3547d71ae5a4SJacob Faibussowitsch {
3548bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
354997f1f81fSBarry Smith   PetscInt    i, nz, n;
3550bef8e0ddSBarry Smith 
3551bef8e0ddSBarry Smith   PetscFunctionBegin;
3552bef8e0ddSBarry Smith   nz = aij->maxnz;
3553d0f46423SBarry Smith   n  = mat->rmap->n;
3554ad540459SPierre Jolivet   for (i = 0; i < nz; i++) aij->j[i] = indices[i];
3555bef8e0ddSBarry Smith   aij->nz = nz;
3556ad540459SPierre Jolivet   for (i = 0; i < n; i++) aij->ilen[i] = aij->imax[i];
35573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3558bef8e0ddSBarry Smith }
3559bef8e0ddSBarry Smith 
3560a3bb6f32SFande Kong /*
3561ddea5d60SJunchao Zhang  * Given a sparse matrix with global column indices, compact it by using a local column space.
3562ddea5d60SJunchao Zhang  * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3563ddea5d60SJunchao Zhang  */
3564d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3565d71ae5a4SJacob Faibussowitsch {
3566a3bb6f32SFande Kong   Mat_SeqAIJ   *aij = (Mat_SeqAIJ *)mat->data;
3567eec179cfSJacob Faibussowitsch   PetscHMapI    gid1_lid1;
3568eec179cfSJacob Faibussowitsch   PetscHashIter tpos;
356925b670f0SStefano Zampini   PetscInt      gid, lid, i, ec, nz = aij->nz;
357025b670f0SStefano Zampini   PetscInt     *garray, *jj = aij->j;
3571a3bb6f32SFande Kong 
3572a3bb6f32SFande Kong   PetscFunctionBegin;
3573a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
35744f572ea9SToby Isaac   PetscAssertPointer(mapping, 2);
3575a3bb6f32SFande Kong   /* use a table */
3576eec179cfSJacob Faibussowitsch   PetscCall(PetscHMapICreateWithSize(mat->rmap->n, &gid1_lid1));
3577a3bb6f32SFande Kong   ec = 0;
357825b670f0SStefano Zampini   for (i = 0; i < nz; i++) {
357925b670f0SStefano Zampini     PetscInt data, gid1 = jj[i] + 1;
3580eec179cfSJacob Faibussowitsch     PetscCall(PetscHMapIGetWithDefault(gid1_lid1, gid1, 0, &data));
3581a3bb6f32SFande Kong     if (!data) {
3582a3bb6f32SFande Kong       /* one based table */
3583c76ffc5fSJacob Faibussowitsch       PetscCall(PetscHMapISet(gid1_lid1, gid1, ++ec));
3584a3bb6f32SFande Kong     }
3585a3bb6f32SFande Kong   }
3586a3bb6f32SFande Kong   /* form array of columns we need */
35879566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ec, &garray));
3588eec179cfSJacob Faibussowitsch   PetscHashIterBegin(gid1_lid1, tpos);
3589eec179cfSJacob Faibussowitsch   while (!PetscHashIterAtEnd(gid1_lid1, tpos)) {
3590eec179cfSJacob Faibussowitsch     PetscHashIterGetKey(gid1_lid1, tpos, gid);
3591eec179cfSJacob Faibussowitsch     PetscHashIterGetVal(gid1_lid1, tpos, lid);
3592eec179cfSJacob Faibussowitsch     PetscHashIterNext(gid1_lid1, tpos);
3593a3bb6f32SFande Kong     gid--;
3594a3bb6f32SFande Kong     lid--;
3595a3bb6f32SFande Kong     garray[lid] = gid;
3596a3bb6f32SFande Kong   }
35979566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(ec, garray)); /* sort, and rebuild */
3598eec179cfSJacob Faibussowitsch   PetscCall(PetscHMapIClear(gid1_lid1));
3599c76ffc5fSJacob Faibussowitsch   for (i = 0; i < ec; i++) PetscCall(PetscHMapISet(gid1_lid1, garray[i] + 1, i + 1));
3600a3bb6f32SFande Kong   /* compact out the extra columns in B */
360125b670f0SStefano Zampini   for (i = 0; i < nz; i++) {
360225b670f0SStefano Zampini     PetscInt gid1 = jj[i] + 1;
3603eec179cfSJacob Faibussowitsch     PetscCall(PetscHMapIGetWithDefault(gid1_lid1, gid1, 0, &lid));
3604a3bb6f32SFande Kong     lid--;
360525b670f0SStefano Zampini     jj[i] = lid;
3606a3bb6f32SFande Kong   }
36079566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&mat->cmap));
3608eec179cfSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&gid1_lid1));
36099566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat), ec, ec, 1, &mat->cmap));
36109566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, mat->cmap->bs, mat->cmap->n, garray, PETSC_OWN_POINTER, mapping));
36119566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(*mapping, ISLOCALTOGLOBALMAPPINGHASH));
36123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3613a3bb6f32SFande Kong }
3614a3bb6f32SFande Kong 
3615bef8e0ddSBarry Smith /*@
3616bef8e0ddSBarry Smith   MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3617bef8e0ddSBarry Smith   in the matrix.
3618bef8e0ddSBarry Smith 
3619bef8e0ddSBarry Smith   Input Parameters:
362011a5261eSBarry Smith + mat     - the `MATSEQAIJ` matrix
3621bef8e0ddSBarry Smith - indices - the column indices
3622bef8e0ddSBarry Smith 
362315091d37SBarry Smith   Level: advanced
362415091d37SBarry Smith 
3625bef8e0ddSBarry Smith   Notes:
3626bef8e0ddSBarry Smith   This can be called if you have precomputed the nonzero structure of the
3627bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
362811a5261eSBarry Smith   of the `MatSetValues()` operation.
3629bef8e0ddSBarry Smith 
3630bef8e0ddSBarry Smith   You MUST have set the correct numbers of nonzeros per row in the call to
363111a5261eSBarry Smith   `MatCreateSeqAIJ()`, and the columns indices MUST be sorted.
3632bef8e0ddSBarry Smith 
363311a5261eSBarry Smith   MUST be called before any calls to `MatSetValues()`
3634bef8e0ddSBarry Smith 
3635b9617806SBarry Smith   The indices should start with zero, not one.
3636b9617806SBarry Smith 
36371cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQAIJ`
3638bef8e0ddSBarry Smith @*/
3639d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat, PetscInt *indices)
3640d71ae5a4SJacob Faibussowitsch {
3641bef8e0ddSBarry Smith   PetscFunctionBegin;
36420700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
36434f572ea9SToby Isaac   PetscAssertPointer(indices, 2);
3644cac4c232SBarry Smith   PetscUseMethod(mat, "MatSeqAIJSetColumnIndices_C", (Mat, PetscInt *), (mat, indices));
36453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3646bef8e0ddSBarry Smith }
3647bef8e0ddSBarry Smith 
3648ba38deedSJacob Faibussowitsch static PetscErrorCode MatStoreValues_SeqAIJ(Mat mat)
3649d71ae5a4SJacob Faibussowitsch {
3650be6bf707SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
3651d0f46423SBarry Smith   size_t      nz  = aij->i[mat->rmap->n];
3652be6bf707SBarry Smith 
3653be6bf707SBarry Smith   PetscFunctionBegin;
365428b400f6SJacob Faibussowitsch   PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3655be6bf707SBarry Smith 
3656be6bf707SBarry Smith   /* allocate space for values if not already there */
36573a7d0413SPierre Jolivet   if (!aij->saved_values) PetscCall(PetscMalloc1(nz + 1, &aij->saved_values));
3658be6bf707SBarry Smith 
3659be6bf707SBarry Smith   /* copy values over */
36609566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->saved_values, aij->a, nz));
36613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3662be6bf707SBarry Smith }
3663be6bf707SBarry Smith 
3664be6bf707SBarry Smith /*@
366520f4b53cSBarry Smith   MatStoreValues - Stashes a copy of the matrix values; this allows reusing of the linear part of a Jacobian, while recomputing only the
3666be6bf707SBarry Smith   nonlinear portion.
3667be6bf707SBarry Smith 
3668c3339decSBarry Smith   Logically Collect
3669be6bf707SBarry Smith 
367027430b45SBarry Smith   Input Parameter:
367111a5261eSBarry Smith . mat - the matrix (currently only `MATAIJ` matrices support this option)
3672be6bf707SBarry Smith 
367315091d37SBarry Smith   Level: advanced
367415091d37SBarry Smith 
36752920cce0SJacob Faibussowitsch   Example Usage:
367627430b45SBarry Smith .vb
36772ef1f0ffSBarry Smith     Using SNES
367827430b45SBarry Smith     Create Jacobian matrix
367927430b45SBarry Smith     Set linear terms into matrix
368027430b45SBarry Smith     Apply boundary conditions to matrix, at this time matrix must have
368127430b45SBarry Smith       final nonzero structure (i.e. setting the nonlinear terms and applying
368227430b45SBarry Smith       boundary conditions again will not change the nonzero structure
368327430b45SBarry Smith     MatSetOption(mat, MAT_NEW_NONZERO_LOCATIONS, PETSC_FALSE);
368427430b45SBarry Smith     MatStoreValues(mat);
368527430b45SBarry Smith     Call SNESSetJacobian() with matrix
368627430b45SBarry Smith     In your Jacobian routine
368727430b45SBarry Smith       MatRetrieveValues(mat);
368827430b45SBarry Smith       Set nonlinear terms in matrix
3689be6bf707SBarry Smith 
369027430b45SBarry Smith     Without `SNESSolve()`, i.e. when you handle nonlinear solve yourself:
369127430b45SBarry Smith     // build linear portion of Jacobian
369227430b45SBarry Smith     MatSetOption(mat, MAT_NEW_NONZERO_LOCATIONS, PETSC_FALSE);
369327430b45SBarry Smith     MatStoreValues(mat);
369427430b45SBarry Smith     loop over nonlinear iterations
369527430b45SBarry Smith        MatRetrieveValues(mat);
369627430b45SBarry Smith        // call MatSetValues(mat,...) to set nonliner portion of Jacobian
369727430b45SBarry Smith        // call MatAssemblyBegin/End() on matrix
369827430b45SBarry Smith        Solve linear system with Jacobian
369927430b45SBarry Smith     endloop
370027430b45SBarry Smith .ve
3701be6bf707SBarry Smith 
3702be6bf707SBarry Smith   Notes:
3703da81f932SPierre Jolivet   Matrix must already be assembled before calling this routine
370411a5261eSBarry Smith   Must set the matrix option `MatSetOption`(mat,`MAT_NEW_NONZERO_LOCATIONS`,`PETSC_FALSE`); before
3705be6bf707SBarry Smith   calling this routine.
3706be6bf707SBarry Smith 
37070c468ba9SBarry Smith   When this is called multiple times it overwrites the previous set of stored values
37080c468ba9SBarry Smith   and does not allocated additional space.
37090c468ba9SBarry Smith 
3710fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `MatRetrieveValues()`
3711be6bf707SBarry Smith @*/
3712d71ae5a4SJacob Faibussowitsch PetscErrorCode MatStoreValues(Mat mat)
3713d71ae5a4SJacob Faibussowitsch {
3714be6bf707SBarry Smith   PetscFunctionBegin;
37150700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
371628b400f6SJacob Faibussowitsch   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
371728b400f6SJacob Faibussowitsch   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3718cac4c232SBarry Smith   PetscUseMethod(mat, "MatStoreValues_C", (Mat), (mat));
37193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3720be6bf707SBarry Smith }
3721be6bf707SBarry Smith 
3722ba38deedSJacob Faibussowitsch static PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat)
3723d71ae5a4SJacob Faibussowitsch {
3724be6bf707SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
3725d0f46423SBarry Smith   PetscInt    nz  = aij->i[mat->rmap->n];
3726be6bf707SBarry Smith 
3727be6bf707SBarry Smith   PetscFunctionBegin;
372828b400f6SJacob Faibussowitsch   PetscCheck(aij->nonew, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
372928b400f6SJacob Faibussowitsch   PetscCheck(aij->saved_values, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call MatStoreValues(A);first");
3730be6bf707SBarry Smith   /* copy values over */
37319566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->a, aij->saved_values, nz));
37323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3733be6bf707SBarry Smith }
3734be6bf707SBarry Smith 
3735be6bf707SBarry Smith /*@
373620f4b53cSBarry Smith   MatRetrieveValues - Retrieves the copy of the matrix values that was stored with `MatStoreValues()`
3737be6bf707SBarry Smith 
3738c3339decSBarry Smith   Logically Collect
3739be6bf707SBarry Smith 
37402fe279fdSBarry Smith   Input Parameter:
374111a5261eSBarry Smith . mat - the matrix (currently only `MATAIJ` matrices support this option)
3742be6bf707SBarry Smith 
374315091d37SBarry Smith   Level: advanced
374415091d37SBarry Smith 
37451cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatStoreValues()`
3746be6bf707SBarry Smith @*/
3747d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRetrieveValues(Mat mat)
3748d71ae5a4SJacob Faibussowitsch {
3749be6bf707SBarry Smith   PetscFunctionBegin;
37500700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
375128b400f6SJacob Faibussowitsch   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
375228b400f6SJacob Faibussowitsch   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3753cac4c232SBarry Smith   PetscUseMethod(mat, "MatRetrieveValues_C", (Mat), (mat));
37543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3755be6bf707SBarry Smith }
3756be6bf707SBarry Smith 
37575d83a8b1SBarry Smith /*@
375811a5261eSBarry Smith   MatCreateSeqAIJ - Creates a sparse matrix in `MATSEQAIJ` (compressed row) format
37590d15e28bSLois Curfman McInnes   (the default parallel PETSc format).  For good matrix assembly performance
376020f4b53cSBarry Smith   the user should preallocate the matrix storage by setting the parameter `nz`
376120f4b53cSBarry Smith   (or the array `nnz`).
376217ab2063SBarry Smith 
3763d083f849SBarry Smith   Collective
3764db81eaa0SLois Curfman McInnes 
376517ab2063SBarry Smith   Input Parameters:
376611a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
376717ab2063SBarry Smith . m    - number of rows
376817ab2063SBarry Smith . n    - number of columns
376917ab2063SBarry Smith . nz   - number of nonzeros per row (same for all rows)
377051c19458SBarry Smith - nnz  - array containing the number of nonzeros in the various rows
37710298fd71SBarry Smith          (possibly different for each row) or NULL
377217ab2063SBarry Smith 
377317ab2063SBarry Smith   Output Parameter:
3774416022c9SBarry Smith . A - the matrix
377517ab2063SBarry Smith 
37762ef1f0ffSBarry Smith   Options Database Keys:
37772ef1f0ffSBarry Smith + -mat_no_inode            - Do not use inodes
37782ef1f0ffSBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5)
37792ef1f0ffSBarry Smith 
37802ef1f0ffSBarry Smith   Level: intermediate
3781175b88e8SBarry Smith 
3782b259b22eSLois Curfman McInnes   Notes:
378377433607SBarry Smith   It is recommend to use `MatCreateFromOptions()` instead of this routine
378477433607SBarry Smith 
37852ef1f0ffSBarry Smith   If `nnz` is given then `nz` is ignored
378649a6f317SBarry Smith 
37872ef1f0ffSBarry Smith   The `MATSEQAIJ` format, also called
37882ef1f0ffSBarry Smith   compressed row storage, is fully compatible with standard Fortran
37890002213bSLois Curfman McInnes   storage.  That is, the stored row and column indices can begin at
37902ef1f0ffSBarry Smith   either one (as in Fortran) or zero.
379117ab2063SBarry Smith 
379220f4b53cSBarry Smith   Specify the preallocated storage with either `nz` or `nnz` (not both).
37932ef1f0ffSBarry Smith   Set `nz` = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory
379420f4b53cSBarry Smith   allocation.
379517ab2063SBarry Smith 
3796682d7d0cSBarry Smith   By default, this format uses inodes (identical nodes) when possible, to
37974fca80b9SLois Curfman McInnes   improve numerical efficiency of matrix-vector products and solves. We
3798682d7d0cSBarry Smith   search for consecutive rows with the same nonzero structure, thereby
37996c7ebb05SLois Curfman McInnes   reusing matrix information to achieve increased efficiency.
38006c7ebb05SLois Curfman McInnes 
38011cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrix Creation](sec_matsparse), `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()`
380217ab2063SBarry Smith @*/
3803d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat *A)
3804d71ae5a4SJacob Faibussowitsch {
38053a40ed3dSBarry Smith   PetscFunctionBegin;
38069566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
38079566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
38089566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQAIJ));
38099566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*A, nz, nnz));
38103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3811273d9f13SBarry Smith }
3812273d9f13SBarry Smith 
38135d83a8b1SBarry Smith /*@
3814273d9f13SBarry Smith   MatSeqAIJSetPreallocation - For good matrix assembly performance
3815273d9f13SBarry Smith   the user should preallocate the matrix storage by setting the parameter nz
3816273d9f13SBarry Smith   (or the array nnz).  By setting these parameters accurately, performance
3817273d9f13SBarry Smith   during matrix assembly can be increased by more than a factor of 50.
3818273d9f13SBarry Smith 
3819d083f849SBarry Smith   Collective
3820273d9f13SBarry Smith 
3821273d9f13SBarry Smith   Input Parameters:
38221c4f3114SJed Brown + B   - The matrix
3823273d9f13SBarry Smith . nz  - number of nonzeros per row (same for all rows)
3824273d9f13SBarry Smith - nnz - array containing the number of nonzeros in the various rows
38250298fd71SBarry Smith          (possibly different for each row) or NULL
3826273d9f13SBarry Smith 
38272ef1f0ffSBarry Smith   Options Database Keys:
38282ef1f0ffSBarry Smith + -mat_no_inode            - Do not use inodes
38292ef1f0ffSBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5)
38302ef1f0ffSBarry Smith 
38312ef1f0ffSBarry Smith   Level: intermediate
38322ef1f0ffSBarry Smith 
3833273d9f13SBarry Smith   Notes:
38342ef1f0ffSBarry Smith   If `nnz` is given then `nz` is ignored
383549a6f317SBarry Smith 
383611a5261eSBarry Smith   The `MATSEQAIJ` format also called
38372ef1f0ffSBarry Smith   compressed row storage, is fully compatible with standard Fortran
3838273d9f13SBarry Smith   storage.  That is, the stored row and column indices can begin at
3839273d9f13SBarry Smith   either one (as in Fortran) or zero.  See the users' manual for details.
3840273d9f13SBarry Smith 
38412ef1f0ffSBarry Smith   Specify the preallocated storage with either `nz` or `nnz` (not both).
38422ef1f0ffSBarry Smith   Set nz = `PETSC_DEFAULT` and `nnz` = `NULL` for PETSc to control dynamic memory
38432ef1f0ffSBarry Smith   allocation.
3844273d9f13SBarry Smith 
384511a5261eSBarry Smith   You can call `MatGetInfo()` to get information on how effective the preallocation was;
3846aa95bbe8SBarry Smith   for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3847aa95bbe8SBarry Smith   You can also run with the option -info and look for messages with the string
3848aa95bbe8SBarry Smith   malloc in them to see if additional memory allocation was needed.
3849aa95bbe8SBarry Smith 
385011a5261eSBarry Smith   Developer Notes:
385111a5261eSBarry Smith   Use nz of `MAT_SKIP_ALLOCATION` to not allocate any space for the matrix
3852a96a251dSBarry Smith   entries or columns indices
3853a96a251dSBarry Smith 
3854273d9f13SBarry Smith   By default, this format uses inodes (identical nodes) when possible, to
3855273d9f13SBarry Smith   improve numerical efficiency of matrix-vector products and solves. We
3856273d9f13SBarry Smith   search for consecutive rows with the same nonzero structure, thereby
3857273d9f13SBarry Smith   reusing matrix information to achieve increased efficiency.
3858273d9f13SBarry Smith 
38591cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()`, `MatGetInfo()`,
3860db781477SPatrick Sanan           `MatSeqAIJSetTotalPreallocation()`
3861273d9f13SBarry Smith @*/
3862d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetPreallocation(Mat B, PetscInt nz, const PetscInt nnz[])
3863d71ae5a4SJacob Faibussowitsch {
3864a23d5eceSKris Buschelman   PetscFunctionBegin;
38656ba663aaSJed Brown   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
38666ba663aaSJed Brown   PetscValidType(B, 1);
3867cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqAIJSetPreallocation_C", (Mat, PetscInt, const PetscInt[]), (B, nz, nnz));
38683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3869a23d5eceSKris Buschelman }
3870a23d5eceSKris Buschelman 
3871d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B, PetscInt nz, const PetscInt *nnz)
3872d71ae5a4SJacob Faibussowitsch {
3873ad79cf63SBarry Smith   Mat_SeqAIJ *b              = (Mat_SeqAIJ *)B->data;
38742576faa2SJed Brown   PetscBool   skipallocation = PETSC_FALSE, realalloc = PETSC_FALSE;
387597f1f81fSBarry Smith   PetscInt    i;
3876273d9f13SBarry Smith 
3877273d9f13SBarry Smith   PetscFunctionBegin;
3878ad79cf63SBarry Smith   if (B->hash_active) {
3879aea10558SJacob Faibussowitsch     B->ops[0] = b->cops;
3880ad79cf63SBarry Smith     PetscCall(PetscHMapIJVDestroy(&b->ht));
3881ad79cf63SBarry Smith     PetscCall(PetscFree(b->dnz));
3882ad79cf63SBarry Smith     B->hash_active = PETSC_FALSE;
3883ad79cf63SBarry Smith   }
38842576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
3885a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
3886c461c341SBarry Smith     skipallocation = PETSC_TRUE;
3887c461c341SBarry Smith     nz             = 0;
3888c461c341SBarry Smith   }
38899566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
38909566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
3891899cda47SBarry Smith 
3892435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
389308401ef6SPierre Jolivet   PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "nz cannot be less than 0: value %" PetscInt_FMT, nz);
38949f0612e4SBarry Smith   if (nnz) {
3895d0f46423SBarry Smith     for (i = 0; i < B->rmap->n; i++) {
389608401ef6SPierre 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]);
389708401ef6SPierre 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);
3898b73539f3SBarry Smith     }
3899b73539f3SBarry Smith   }
3900b73539f3SBarry Smith 
3901273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
3902ab93d7beSBarry Smith   if (!skipallocation) {
39033a7d0413SPierre Jolivet     if (!b->imax) PetscCall(PetscMalloc1(B->rmap->n, &b->imax));
3904071fcb05SBarry Smith     if (!b->ilen) {
3905071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
39069566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(B->rmap->n, &b->ilen));
3907071fcb05SBarry Smith     } else {
39089566063dSJacob Faibussowitsch       PetscCall(PetscMemzero(b->ilen, B->rmap->n * sizeof(PetscInt)));
39092ee49352SLisandro Dalcin     }
3910aa624791SPierre Jolivet     if (!b->ipre) PetscCall(PetscMalloc1(B->rmap->n, &b->ipre));
3911273d9f13SBarry Smith     if (!nnz) {
3912435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
3913c62bd62aSJed Brown       else if (nz < 0) nz = 1;
39145d2a9ed1SStefano Zampini       nz = PetscMin(nz, B->cmap->n);
3915d0f46423SBarry Smith       for (i = 0; i < B->rmap->n; i++) b->imax[i] = nz;
3916c43c4a61SBarry Smith       PetscCall(PetscIntMultError(nz, B->rmap->n, &nz));
3917273d9f13SBarry Smith     } else {
3918c73702f5SBarry Smith       PetscInt64 nz64 = 0;
39199371c9d4SSatish Balay       for (i = 0; i < B->rmap->n; i++) {
39209371c9d4SSatish Balay         b->imax[i] = nnz[i];
39219371c9d4SSatish Balay         nz64 += nnz[i];
39229371c9d4SSatish Balay       }
39239566063dSJacob Faibussowitsch       PetscCall(PetscIntCast(nz64, &nz));
3924273d9f13SBarry Smith     }
3925ab93d7beSBarry Smith 
3926273d9f13SBarry Smith     /* allocate the matrix space */
39279566063dSJacob Faibussowitsch     PetscCall(MatSeqXAIJFreeAIJ(B, &b->a, &b->j, &b->i));
39289f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscInt), (void **)&b->j));
39299f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(B->rmap->n + 1, sizeof(PetscInt), (void **)&b->i));
39309f0612e4SBarry Smith     b->free_ij = PETSC_TRUE;
3931396832f4SHong Zhang     if (B->structure_only) {
39329f0612e4SBarry Smith       b->free_a = PETSC_FALSE;
3933396832f4SHong Zhang     } else {
39349f0612e4SBarry Smith       PetscCall(PetscShmgetAllocateArray(nz, sizeof(PetscScalar), (void **)&b->a));
39359f0612e4SBarry Smith       b->free_a = PETSC_TRUE;
3936396832f4SHong Zhang     }
3937bfeeae90SHong Zhang     b->i[0] = 0;
3938ad540459SPierre Jolivet     for (i = 1; i < B->rmap->n + 1; i++) b->i[i] = b->i[i - 1] + b->imax[i - 1];
3939c461c341SBarry Smith   } else {
3940e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
3941e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
3942c461c341SBarry Smith   }
3943273d9f13SBarry Smith 
3944846b4da1SFande Kong   if (b->ipre && nnz != b->ipre && b->imax) {
3945846b4da1SFande Kong     /* reserve user-requested sparsity */
39469566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(b->ipre, b->imax, B->rmap->n));
3947846b4da1SFande Kong   }
3948846b4da1SFande Kong 
3949273d9f13SBarry Smith   b->nz               = 0;
3950273d9f13SBarry Smith   b->maxnz            = nz;
3951273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
39521baa6e33SBarry Smith   if (realalloc) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
3953cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
3954cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
39555519a089SJose E. Roman   /* We simply deem preallocation has changed nonzero state. Updating the state
39565519a089SJose E. Roman      will give clients (like AIJKokkos) a chance to know something has happened.
39575519a089SJose E. Roman   */
39585519a089SJose E. Roman   B->nonzerostate++;
39593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3960273d9f13SBarry Smith }
3961273d9f13SBarry Smith 
39624c51d546SAlexander PetscErrorCode MatResetPreallocation_SeqAIJ_Private(Mat A, PetscBool *memoryreset)
3963d71ae5a4SJacob Faibussowitsch {
3964846b4da1SFande Kong   Mat_SeqAIJ *a;
3965a5bbaf83SFande Kong   PetscInt    i;
39661f14be2bSBarry Smith   PetscBool   skipreset;
3967846b4da1SFande Kong 
3968846b4da1SFande Kong   PetscFunctionBegin;
3969846b4da1SFande Kong   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
397014d0e64fSAlex Lindsay 
39714c51d546SAlexander   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()");
39724c51d546SAlexander   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
39734c51d546SAlexander 
397414d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
39753ba16761SJacob Faibussowitsch   if (!A->rmap->n) PetscFunctionReturn(PETSC_SUCCESS);
397614d0e64fSAlex Lindsay 
3977846b4da1SFande Kong   a = (Mat_SeqAIJ *)A->data;
39782c814fdeSFande Kong   /* if no saved info, we error out */
397928b400f6SJacob Faibussowitsch   PetscCheck(a->ipre, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "No saved preallocation info ");
39802c814fdeSFande Kong 
39811f14be2bSBarry Smith   PetscCheck(a->i && a->imax && a->ilen, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Memory info is incomplete, and cannot reset preallocation ");
39822c814fdeSFande Kong 
39831f14be2bSBarry Smith   PetscCall(PetscArraycmp(a->ipre, a->ilen, A->rmap->n, &skipreset));
39844c51d546SAlexander   if (skipreset) PetscCall(MatZeroEntries(A));
39854c51d546SAlexander   else {
39869566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(a->imax, a->ipre, A->rmap->n));
39879566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(a->ilen, A->rmap->n));
3988846b4da1SFande Kong     a->i[0] = 0;
3989ad540459SPierre Jolivet     for (i = 1; i < A->rmap->n + 1; i++) a->i[i] = a->i[i - 1] + a->imax[i - 1];
3990846b4da1SFande Kong     A->preallocated     = PETSC_TRUE;
3991846b4da1SFande Kong     a->nz               = 0;
3992846b4da1SFande Kong     a->maxnz            = a->i[A->rmap->n];
3993846b4da1SFande Kong     A->info.nz_unneeded = (double)a->maxnz;
3994846b4da1SFande Kong     A->was_assembled    = PETSC_FALSE;
3995846b4da1SFande Kong     A->assembled        = PETSC_FALSE;
3996b3a35320SAlex Lindsay     A->nonzerostate++;
3997b3a35320SAlex Lindsay     /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */
3998b3a35320SAlex Lindsay     PetscCall(PetscObjectStateIncrease((PetscObject)A));
39991f14be2bSBarry Smith   }
40004c51d546SAlexander   if (memoryreset) *memoryreset = (PetscBool)!skipreset;
40014c51d546SAlexander   PetscFunctionReturn(PETSC_SUCCESS);
40024c51d546SAlexander }
40034c51d546SAlexander 
40044c51d546SAlexander static PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
40054c51d546SAlexander {
40064c51d546SAlexander   PetscFunctionBegin;
40074c51d546SAlexander   PetscCall(MatResetPreallocation_SeqAIJ_Private(A, NULL));
40083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4009846b4da1SFande Kong }
4010846b4da1SFande Kong 
401158d36128SBarry Smith /*@
401211a5261eSBarry Smith   MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in `MATSEQAIJ` format.
4013a1661176SMatthew Knepley 
4014a1661176SMatthew Knepley   Input Parameters:
4015a1661176SMatthew Knepley + B - the matrix
4016d8a51d2aSBarry Smith . i - the indices into `j` for the start of each row (indices start with zero)
4017d8a51d2aSBarry Smith . j - the column indices for each row (indices start with zero) these must be sorted for each row
4018d8a51d2aSBarry Smith - v - optional values in the matrix, use `NULL` if not provided
4019a1661176SMatthew Knepley 
4020a1661176SMatthew Knepley   Level: developer
4021a1661176SMatthew Knepley 
40226a9b8d82SBarry Smith   Notes:
40232ef1f0ffSBarry Smith   The `i`,`j`,`v` values are COPIED with this routine; to avoid the copy use `MatCreateSeqAIJWithArrays()`
402458d36128SBarry Smith 
40256a9b8d82SBarry Smith   This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
40266a9b8d82SBarry Smith   structure will be the union of all the previous nonzero structures.
40276a9b8d82SBarry Smith 
40286a9b8d82SBarry Smith   Developer Notes:
40292ef1f0ffSBarry 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
40302ef1f0ffSBarry Smith   then just copies the `v` values directly with `PetscMemcpy()`.
40316a9b8d82SBarry Smith 
403211a5261eSBarry Smith   This routine could also take a `PetscCopyMode` argument to allow sharing the values instead of always copying them.
40336a9b8d82SBarry Smith 
4034fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatSeqAIJSetPreallocation()`, `MATSEQAIJ`, `MatResetPreallocation()`
4035a1661176SMatthew Knepley @*/
4036d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B, const PetscInt i[], const PetscInt j[], const PetscScalar v[])
4037d71ae5a4SJacob Faibussowitsch {
4038a1661176SMatthew Knepley   PetscFunctionBegin;
40390700a824SBarry Smith   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
40406ba663aaSJed Brown   PetscValidType(B, 1);
4041cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqAIJSetPreallocationCSR_C", (Mat, const PetscInt[], const PetscInt[], const PetscScalar[]), (B, i, j, v));
40423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4043a1661176SMatthew Knepley }
4044a1661176SMatthew Knepley 
4045ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B, const PetscInt Ii[], const PetscInt J[], const PetscScalar v[])
4046d71ae5a4SJacob Faibussowitsch {
4047a1661176SMatthew Knepley   PetscInt  i;
4048a1661176SMatthew Knepley   PetscInt  m, n;
4049a1661176SMatthew Knepley   PetscInt  nz;
40506a9b8d82SBarry Smith   PetscInt *nnz;
4051a1661176SMatthew Knepley 
4052a1661176SMatthew Knepley   PetscFunctionBegin;
4053aed4548fSBarry Smith   PetscCheck(Ii[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]);
4054779a8d59SSatish Balay 
40559566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
40569566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
4057779a8d59SSatish Balay 
40589566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, &m, &n));
40599566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &nnz));
4060a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4061b7940d39SSatish Balay     nz = Ii[i + 1] - Ii[i];
406208401ef6SPierre 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);
4063a1661176SMatthew Knepley     nnz[i] = nz;
4064a1661176SMatthew Knepley   }
40659566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz));
40669566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
4067a1661176SMatthew Knepley 
40688e3a54c0SPierre Jolivet   for (i = 0; i < m; i++) PetscCall(MatSetValues_SeqAIJ(B, 1, &i, Ii[i + 1] - Ii[i], J + Ii[i], PetscSafePointerPlusOffset(v, Ii[i]), INSERT_VALUES));
4069a1661176SMatthew Knepley 
40709566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
40719566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4072a1661176SMatthew Knepley 
40739566063dSJacob Faibussowitsch   PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
40743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4075a1661176SMatthew Knepley }
4076a1661176SMatthew Knepley 
4077ad7e164aSPierre Jolivet /*@
40782ef1f0ffSBarry Smith   MatSeqAIJKron - Computes `C`, the Kronecker product of `A` and `B`.
4079ad7e164aSPierre Jolivet 
4080ad7e164aSPierre Jolivet   Input Parameters:
4081ad7e164aSPierre Jolivet + A     - left-hand side matrix
4082ad7e164aSPierre Jolivet . B     - right-hand side matrix
408311a5261eSBarry Smith - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
4084ad7e164aSPierre Jolivet 
4085ad7e164aSPierre Jolivet   Output Parameter:
40862ef1f0ffSBarry Smith . C - Kronecker product of `A` and `B`
4087ad7e164aSPierre Jolivet 
4088ad7e164aSPierre Jolivet   Level: intermediate
4089ad7e164aSPierre Jolivet 
409011a5261eSBarry Smith   Note:
409111a5261eSBarry 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()`.
4092ad7e164aSPierre Jolivet 
40931cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATKAIJ`, `MatReuse`
4094ad7e164aSPierre Jolivet @*/
4095d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJKron(Mat A, Mat B, MatReuse reuse, Mat *C)
4096d71ae5a4SJacob Faibussowitsch {
4097ad7e164aSPierre Jolivet   PetscFunctionBegin;
4098ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4099ad7e164aSPierre Jolivet   PetscValidType(A, 1);
4100ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4101ad7e164aSPierre Jolivet   PetscValidType(B, 2);
41024f572ea9SToby Isaac   PetscAssertPointer(C, 4);
4103ad7e164aSPierre Jolivet   if (reuse == MAT_REUSE_MATRIX) {
4104ad7e164aSPierre Jolivet     PetscValidHeaderSpecific(*C, MAT_CLASSID, 4);
4105ad7e164aSPierre Jolivet     PetscValidType(*C, 4);
4106ad7e164aSPierre Jolivet   }
4107cac4c232SBarry Smith   PetscTryMethod(A, "MatSeqAIJKron_C", (Mat, Mat, MatReuse, Mat *), (A, B, reuse, C));
41083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4109ad7e164aSPierre Jolivet }
4110ad7e164aSPierre Jolivet 
4111ba38deedSJacob Faibussowitsch static PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A, Mat B, MatReuse reuse, Mat *C)
4112d71ae5a4SJacob Faibussowitsch {
4113ad7e164aSPierre Jolivet   Mat                newmat;
4114ad7e164aSPierre Jolivet   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data;
4115ad7e164aSPierre Jolivet   Mat_SeqAIJ        *b = (Mat_SeqAIJ *)B->data;
4116ad7e164aSPierre Jolivet   PetscScalar       *v;
4117fff043a9SJunchao Zhang   const PetscScalar *aa, *ba;
4118ad7e164aSPierre 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;
4119ad7e164aSPierre Jolivet   PetscBool          flg;
4120ad7e164aSPierre Jolivet 
4121ad7e164aSPierre Jolivet   PetscFunctionBegin;
412228b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
412328b400f6SJacob Faibussowitsch   PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
412428b400f6SJacob Faibussowitsch   PetscCheck(!B->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
412528b400f6SJacob Faibussowitsch   PetscCheck(B->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
41269566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATSEQAIJ, &flg));
412728b400f6SJacob Faibussowitsch   PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatType %s", ((PetscObject)B)->type_name);
4128aed4548fSBarry Smith   PetscCheck(reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatReuse %d", (int)reuse);
4129ad7e164aSPierre Jolivet   if (reuse == MAT_INITIAL_MATRIX) {
41309566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(am * bm + 1, &i, a->i[am] * b->i[bm], &j));
41319566063dSJacob Faibussowitsch     PetscCall(MatCreate(PETSC_COMM_SELF, &newmat));
41329566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(newmat, am * bm, an * bn, am * bm, an * bn));
41339566063dSJacob Faibussowitsch     PetscCall(MatSetType(newmat, MATAIJ));
4134ad7e164aSPierre Jolivet     i[0] = 0;
4135ad7e164aSPierre Jolivet     for (m = 0; m < am; ++m) {
4136ad7e164aSPierre Jolivet       for (p = 0; p < bm; ++p) {
4137ad7e164aSPierre Jolivet         i[m * bm + p + 1] = i[m * bm + p] + (a->i[m + 1] - a->i[m]) * (b->i[p + 1] - b->i[p]);
4138ad7e164aSPierre Jolivet         for (n = a->i[m]; n < a->i[m + 1]; ++n) {
4139ad540459SPierre Jolivet           for (q = b->i[p]; q < b->i[p + 1]; ++q) j[nnz++] = a->j[n] * bn + b->j[q];
4140ad7e164aSPierre Jolivet         }
4141ad7e164aSPierre Jolivet       }
4142ad7e164aSPierre Jolivet     }
41439566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocationCSR(newmat, i, j, NULL));
4144ad7e164aSPierre Jolivet     *C = newmat;
41459566063dSJacob Faibussowitsch     PetscCall(PetscFree2(i, j));
4146ad7e164aSPierre Jolivet     nnz = 0;
4147ad7e164aSPierre Jolivet   }
41489566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(*C, &v));
41499566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
41509566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(B, &ba));
4151ad7e164aSPierre Jolivet   for (m = 0; m < am; ++m) {
4152ad7e164aSPierre Jolivet     for (p = 0; p < bm; ++p) {
4153ad7e164aSPierre Jolivet       for (n = a->i[m]; n < a->i[m + 1]; ++n) {
4154ad540459SPierre Jolivet         for (q = b->i[p]; q < b->i[p + 1]; ++q) v[nnz++] = aa[n] * ba[q];
4155ad7e164aSPierre Jolivet       }
4156ad7e164aSPierre Jolivet     }
4157ad7e164aSPierre Jolivet   }
41589566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(*C, &v));
41599566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
41609566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(B, &ba));
41613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4162ad7e164aSPierre Jolivet }
4163ad7e164aSPierre Jolivet 
4164c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4165af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4166170fe5c8SBarry Smith 
4167170fe5c8SBarry Smith /*
4168170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4169170fe5c8SBarry Smith 
4170170fe5c8SBarry Smith                n                       p                          p
41712da392ccSBarry Smith         [             ]       [             ]         [                 ]
41722da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
41732da392ccSBarry Smith         [             ]       [             ]         [                 ]
4174170fe5c8SBarry Smith 
4175170fe5c8SBarry Smith */
4176d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A, Mat B, Mat C)
4177d71ae5a4SJacob Faibussowitsch {
4178170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense *)A->data;
4179170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ *)B->data;
4180170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense *)C->data;
418186214ceeSStefano Zampini   PetscInt           i, j, n, m, q, p;
4182170fe5c8SBarry Smith   const PetscInt    *ii, *idx;
4183170fe5c8SBarry Smith   const PetscScalar *b, *a, *a_q;
4184170fe5c8SBarry Smith   PetscScalar       *c, *c_q;
418586214ceeSStefano Zampini   PetscInt           clda = sub_c->lda;
418686214ceeSStefano Zampini   PetscInt           alda = sub_a->lda;
4187170fe5c8SBarry Smith 
4188170fe5c8SBarry Smith   PetscFunctionBegin;
4189d0f46423SBarry Smith   m = A->rmap->n;
4190d0f46423SBarry Smith   n = A->cmap->n;
4191d0f46423SBarry Smith   p = B->cmap->n;
4192170fe5c8SBarry Smith   a = sub_a->v;
4193170fe5c8SBarry Smith   b = sub_b->a;
4194170fe5c8SBarry Smith   c = sub_c->v;
419586214ceeSStefano Zampini   if (clda == m) {
41969566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(c, m * p));
419786214ceeSStefano Zampini   } else {
419886214ceeSStefano Zampini     for (j = 0; j < p; j++)
41999371c9d4SSatish Balay       for (i = 0; i < m; i++) c[j * clda + i] = 0.0;
420086214ceeSStefano Zampini   }
4201170fe5c8SBarry Smith   ii  = sub_b->i;
4202170fe5c8SBarry Smith   idx = sub_b->j;
4203170fe5c8SBarry Smith   for (i = 0; i < n; i++) {
4204170fe5c8SBarry Smith     q = ii[i + 1] - ii[i];
4205170fe5c8SBarry Smith     while (q-- > 0) {
420686214ceeSStefano Zampini       c_q = c + clda * (*idx);
420786214ceeSStefano Zampini       a_q = a + alda * i;
4208854c7f52SBarry Smith       PetscKernelAXPY(c_q, *b, a_q, m);
4209170fe5c8SBarry Smith       idx++;
4210170fe5c8SBarry Smith       b++;
4211170fe5c8SBarry Smith     }
4212170fe5c8SBarry Smith   }
42133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4214170fe5c8SBarry Smith }
4215170fe5c8SBarry Smith 
4216d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A, Mat B, PetscReal fill, Mat C)
4217d71ae5a4SJacob Faibussowitsch {
4218d0f46423SBarry Smith   PetscInt  m = A->rmap->n, n = B->cmap->n;
421986214ceeSStefano Zampini   PetscBool cisdense;
4220170fe5c8SBarry Smith 
4221170fe5c8SBarry Smith   PetscFunctionBegin;
422208401ef6SPierre 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);
42239566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
42249566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(C, A, B));
4225d5e393b6SSuyash Tandon   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, MATSEQDENSEHIP, ""));
422648a46eb9SPierre Jolivet   if (!cisdense) PetscCall(MatSetType(C, MATDENSE));
42279566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
4228d73949e8SHong Zhang 
42294222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
42303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4231170fe5c8SBarry Smith }
4232170fe5c8SBarry Smith 
42330bad9183SKris Buschelman /*MC
4234fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
42350bad9183SKris Buschelman    based on compressed sparse row format.
42360bad9183SKris Buschelman 
42372ef1f0ffSBarry Smith    Options Database Key:
42380bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
42390bad9183SKris Buschelman 
42400bad9183SKris Buschelman    Level: beginner
42410bad9183SKris Buschelman 
42420cd7f59aSBarry Smith    Notes:
42432ef1f0ffSBarry Smith     `MatSetValues()` may be called for this matrix type with a `NULL` argument for the numerical values,
42440cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
42450cd7f59aSBarry Smith     in the matrix
42460cd7f59aSBarry Smith 
424711a5261eSBarry Smith     `MatSetOptions`(,`MAT_STRUCTURE_ONLY`,`PETSC_TRUE`) may be called for this matrix type. In this no
424811a5261eSBarry Smith     space is allocated for the nonzero entries and any entries passed with `MatSetValues()` are ignored
42490cd7f59aSBarry Smith 
425011a5261eSBarry Smith   Developer Note:
42512ef1f0ffSBarry Smith     It would be nice if all matrix formats supported passing `NULL` in for the numerical values
42520cd7f59aSBarry Smith 
42531cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatSetFromOptions()`, `MatSetType()`, `MatCreate()`, `MatType`, `MATSELL`, `MATSEQSELL`, `MATMPISELL`
42540bad9183SKris Buschelman M*/
42550bad9183SKris Buschelman 
4256ccd284c7SBarry Smith /*MC
4257ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4258ccd284c7SBarry Smith 
425911a5261eSBarry Smith    This matrix type is identical to `MATSEQAIJ` when constructed with a single process communicator,
426011a5261eSBarry Smith    and `MATMPIAIJ` otherwise.  As a result, for single process communicators,
426111a5261eSBarry Smith    `MatSeqAIJSetPreallocation()` is supported, and similarly `MatMPIAIJSetPreallocation()` is supported
4262ccd284c7SBarry Smith    for communicators controlling multiple processes.  It is recommended that you call both of
4263ccd284c7SBarry Smith    the above preallocation routines for simplicity.
4264ccd284c7SBarry Smith 
42652ef1f0ffSBarry Smith    Options Database Key:
426611a5261eSBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to `MatSetFromOptions()`
4267ccd284c7SBarry Smith 
42682ef1f0ffSBarry Smith   Level: beginner
42692ef1f0ffSBarry Smith 
427011a5261eSBarry Smith    Note:
427111a5261eSBarry Smith    Subclasses include `MATAIJCUSPARSE`, `MATAIJPERM`, `MATAIJSELL`, `MATAIJMKL`, `MATAIJCRL`, and also automatically switches over to use inodes when
4272ccd284c7SBarry Smith    enough exist.
4273ccd284c7SBarry Smith 
42741cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATMPIAIJ`, `MATSELL`, `MATSEQSELL`, `MATMPISELL`
4275ccd284c7SBarry Smith M*/
4276ccd284c7SBarry Smith 
4277ccd284c7SBarry Smith /*MC
4278ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4279ccd284c7SBarry Smith 
42802ef1f0ffSBarry Smith    Options Database Key:
42812ef1f0ffSBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to `MatSetFromOptions()`
42822ef1f0ffSBarry Smith 
42832ef1f0ffSBarry Smith   Level: beginner
42842ef1f0ffSBarry Smith 
42852ef1f0ffSBarry Smith    Note:
428611a5261eSBarry Smith    This matrix type is identical to `MATSEQAIJCRL` when constructed with a single process communicator,
428711a5261eSBarry Smith    and `MATMPIAIJCRL` otherwise.  As a result, for single process communicators,
428811a5261eSBarry Smith    `MatSeqAIJSetPreallocation()` is supported, and similarly `MatMPIAIJSetPreallocation()` is supported
4289ccd284c7SBarry Smith    for communicators controlling multiple processes.  It is recommended that you call both of
4290ccd284c7SBarry Smith    the above preallocation routines for simplicity.
4291ccd284c7SBarry Smith 
42921cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL`
4293ccd284c7SBarry Smith M*/
4294ccd284c7SBarry Smith 
42957906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat, MatType, MatReuse, Mat *);
42967906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
42977906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat, MatType, MatReuse, Mat *);
42987906f579SHong Zhang #endif
4299d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE))
4300d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat, MatType, MatReuse, Mat *);
4301d24d4204SJose E. Roman #endif
43027906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
43037906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType, MatReuse, Mat *);
43047906f579SHong Zhang #endif
43057906f579SHong Zhang 
4306d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat, MatType, MatReuse, Mat *);
4307c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat, MatType, MatReuse, Mat *);
43084222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
43097906f579SHong Zhang 
43108c778c55SBarry Smith /*@C
431111a5261eSBarry Smith   MatSeqAIJGetArray - gives read/write access to the array where the data for a `MATSEQAIJ` matrix is stored
43128c778c55SBarry Smith 
43138c778c55SBarry Smith   Not Collective
43148c778c55SBarry Smith 
43158c778c55SBarry Smith   Input Parameter:
4316fe59aa6dSJacob Faibussowitsch . A - a `MATSEQAIJ` matrix
43178c778c55SBarry Smith 
43188c778c55SBarry Smith   Output Parameter:
43198c778c55SBarry Smith . array - pointer to the data
43208c778c55SBarry Smith 
43218c778c55SBarry Smith   Level: intermediate
43228c778c55SBarry Smith 
4323ce78bad3SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArray()`
43248c778c55SBarry Smith @*/
43255d83a8b1SBarry Smith PetscErrorCode MatSeqAIJGetArray(Mat A, PetscScalar *array[])
4326d71ae5a4SJacob Faibussowitsch {
4327d67d9f35SJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
43288c778c55SBarry Smith 
43298c778c55SBarry Smith   PetscFunctionBegin;
4330d67d9f35SJunchao Zhang   if (aij->ops->getarray) {
43319566063dSJacob Faibussowitsch     PetscCall((*aij->ops->getarray)(A, array));
4332d67d9f35SJunchao Zhang   } else {
4333d67d9f35SJunchao Zhang     *array = aij->a;
4334d67d9f35SJunchao Zhang   }
43353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4336d67d9f35SJunchao Zhang }
4337d67d9f35SJunchao Zhang 
4338d67d9f35SJunchao Zhang /*@C
433911a5261eSBarry Smith   MatSeqAIJRestoreArray - returns access to the array where the data for a `MATSEQAIJ` matrix is stored obtained by `MatSeqAIJGetArray()`
4340d67d9f35SJunchao Zhang 
4341d67d9f35SJunchao Zhang   Not Collective
4342d67d9f35SJunchao Zhang 
4343d67d9f35SJunchao Zhang   Input Parameters:
4344fe59aa6dSJacob Faibussowitsch + A     - a `MATSEQAIJ` matrix
4345d67d9f35SJunchao Zhang - array - pointer to the data
4346d67d9f35SJunchao Zhang 
4347d67d9f35SJunchao Zhang   Level: intermediate
4348d67d9f35SJunchao Zhang 
4349ce78bad3SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArray()`
4350d67d9f35SJunchao Zhang @*/
43515d83a8b1SBarry Smith PetscErrorCode MatSeqAIJRestoreArray(Mat A, PetscScalar *array[])
4352d71ae5a4SJacob Faibussowitsch {
4353d67d9f35SJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
4354d67d9f35SJunchao Zhang 
4355d67d9f35SJunchao Zhang   PetscFunctionBegin;
4356d67d9f35SJunchao Zhang   if (aij->ops->restorearray) {
43579566063dSJacob Faibussowitsch     PetscCall((*aij->ops->restorearray)(A, array));
4358d67d9f35SJunchao Zhang   } else {
4359d67d9f35SJunchao Zhang     *array = NULL;
4360d67d9f35SJunchao Zhang   }
43619566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
43623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43638c778c55SBarry Smith }
43648c778c55SBarry Smith 
436521e72a00SBarry Smith /*@C
436611a5261eSBarry Smith   MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a `MATSEQAIJ` matrix is stored
43678f1ea47aSStefano Zampini 
43680ab4885dSBarry Smith   Not Collective; No Fortran Support
43698f1ea47aSStefano Zampini 
43708f1ea47aSStefano Zampini   Input Parameter:
4371fe59aa6dSJacob Faibussowitsch . A - a `MATSEQAIJ` matrix
43728f1ea47aSStefano Zampini 
43738f1ea47aSStefano Zampini   Output Parameter:
43748f1ea47aSStefano Zampini . array - pointer to the data
43758f1ea47aSStefano Zampini 
43768f1ea47aSStefano Zampini   Level: intermediate
43778f1ea47aSStefano Zampini 
43781cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()`
43798f1ea47aSStefano Zampini @*/
43805d83a8b1SBarry Smith PetscErrorCode MatSeqAIJGetArrayRead(Mat A, const PetscScalar *array[])
4381d71ae5a4SJacob Faibussowitsch {
4382d67d9f35SJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
43838f1ea47aSStefano Zampini 
43848f1ea47aSStefano Zampini   PetscFunctionBegin;
4385d67d9f35SJunchao Zhang   if (aij->ops->getarrayread) {
43869566063dSJacob Faibussowitsch     PetscCall((*aij->ops->getarrayread)(A, array));
4387d67d9f35SJunchao Zhang   } else {
4388d67d9f35SJunchao Zhang     *array = aij->a;
4389d67d9f35SJunchao Zhang   }
43903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43918f1ea47aSStefano Zampini }
43928f1ea47aSStefano Zampini 
43938f1ea47aSStefano Zampini /*@C
439411a5261eSBarry Smith   MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from `MatSeqAIJGetArrayRead()`
43958f1ea47aSStefano Zampini 
43960ab4885dSBarry Smith   Not Collective; No Fortran Support
43978f1ea47aSStefano Zampini 
43988f1ea47aSStefano Zampini   Input Parameter:
4399fe59aa6dSJacob Faibussowitsch . A - a `MATSEQAIJ` matrix
44008f1ea47aSStefano Zampini 
44018f1ea47aSStefano Zampini   Output Parameter:
44028f1ea47aSStefano Zampini . array - pointer to the data
44038f1ea47aSStefano Zampini 
44048f1ea47aSStefano Zampini   Level: intermediate
44058f1ea47aSStefano Zampini 
44061cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()`
44078f1ea47aSStefano Zampini @*/
44085d83a8b1SBarry Smith PetscErrorCode MatSeqAIJRestoreArrayRead(Mat A, const PetscScalar *array[])
4409d71ae5a4SJacob Faibussowitsch {
4410d67d9f35SJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
44118f1ea47aSStefano Zampini 
44128f1ea47aSStefano Zampini   PetscFunctionBegin;
4413d67d9f35SJunchao Zhang   if (aij->ops->restorearrayread) {
44149566063dSJacob Faibussowitsch     PetscCall((*aij->ops->restorearrayread)(A, array));
4415d67d9f35SJunchao Zhang   } else {
4416d67d9f35SJunchao Zhang     *array = NULL;
4417d67d9f35SJunchao Zhang   }
44183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4419d67d9f35SJunchao Zhang }
4420d67d9f35SJunchao Zhang 
4421d67d9f35SJunchao Zhang /*@C
442211a5261eSBarry Smith   MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a `MATSEQAIJ` matrix is stored
4423d67d9f35SJunchao Zhang 
44240ab4885dSBarry Smith   Not Collective; No Fortran Support
4425d67d9f35SJunchao Zhang 
4426d67d9f35SJunchao Zhang   Input Parameter:
4427fe59aa6dSJacob Faibussowitsch . A - a `MATSEQAIJ` matrix
4428d67d9f35SJunchao Zhang 
4429d67d9f35SJunchao Zhang   Output Parameter:
4430d67d9f35SJunchao Zhang . array - pointer to the data
4431d67d9f35SJunchao Zhang 
4432d67d9f35SJunchao Zhang   Level: intermediate
4433d67d9f35SJunchao Zhang 
44341cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()`
4435d67d9f35SJunchao Zhang @*/
44365d83a8b1SBarry Smith PetscErrorCode MatSeqAIJGetArrayWrite(Mat A, PetscScalar *array[])
4437d71ae5a4SJacob Faibussowitsch {
4438d67d9f35SJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
4439d67d9f35SJunchao Zhang 
4440d67d9f35SJunchao Zhang   PetscFunctionBegin;
4441d67d9f35SJunchao Zhang   if (aij->ops->getarraywrite) {
44429566063dSJacob Faibussowitsch     PetscCall((*aij->ops->getarraywrite)(A, array));
4443d67d9f35SJunchao Zhang   } else {
4444d67d9f35SJunchao Zhang     *array = aij->a;
4445d67d9f35SJunchao Zhang   }
44469566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
44473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4448d67d9f35SJunchao Zhang }
4449d67d9f35SJunchao Zhang 
4450d67d9f35SJunchao Zhang /*@C
4451d67d9f35SJunchao Zhang   MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead
4452d67d9f35SJunchao Zhang 
44530ab4885dSBarry Smith   Not Collective; No Fortran Support
4454d67d9f35SJunchao Zhang 
4455d67d9f35SJunchao Zhang   Input Parameter:
4456fe59aa6dSJacob Faibussowitsch . A - a MATSEQAIJ matrix
4457d67d9f35SJunchao Zhang 
4458d67d9f35SJunchao Zhang   Output Parameter:
4459d67d9f35SJunchao Zhang . array - pointer to the data
4460d67d9f35SJunchao Zhang 
4461d67d9f35SJunchao Zhang   Level: intermediate
4462d67d9f35SJunchao Zhang 
44631cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()`
4464d67d9f35SJunchao Zhang @*/
44655d83a8b1SBarry Smith PetscErrorCode MatSeqAIJRestoreArrayWrite(Mat A, PetscScalar *array[])
4466d71ae5a4SJacob Faibussowitsch {
4467d67d9f35SJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
4468d67d9f35SJunchao Zhang 
4469d67d9f35SJunchao Zhang   PetscFunctionBegin;
4470d67d9f35SJunchao Zhang   if (aij->ops->restorearraywrite) {
44719566063dSJacob Faibussowitsch     PetscCall((*aij->ops->restorearraywrite)(A, array));
4472d67d9f35SJunchao Zhang   } else {
4473d67d9f35SJunchao Zhang     *array = NULL;
4474d67d9f35SJunchao Zhang   }
44753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44768f1ea47aSStefano Zampini }
44778f1ea47aSStefano Zampini 
44788f1ea47aSStefano Zampini /*@C
447911a5261eSBarry Smith   MatSeqAIJGetCSRAndMemType - Get the CSR arrays and the memory type of the `MATSEQAIJ` matrix
44807ee59b9bSJunchao Zhang 
44810ab4885dSBarry Smith   Not Collective; No Fortran Support
44827ee59b9bSJunchao Zhang 
44837ee59b9bSJunchao Zhang   Input Parameter:
448411a5261eSBarry Smith . mat - a matrix of type `MATSEQAIJ` or its subclasses
44857ee59b9bSJunchao Zhang 
44867ee59b9bSJunchao Zhang   Output Parameters:
44877ee59b9bSJunchao Zhang + i     - row map array of the matrix
44887ee59b9bSJunchao Zhang . j     - column index array of the matrix
44897ee59b9bSJunchao Zhang . a     - data array of the matrix
4490fe59aa6dSJacob Faibussowitsch - mtype - memory type of the arrays
44917ee59b9bSJunchao Zhang 
4492fe59aa6dSJacob Faibussowitsch   Level: developer
44932ef1f0ffSBarry Smith 
44947ee59b9bSJunchao Zhang   Notes:
44952ef1f0ffSBarry Smith   Any of the output parameters can be `NULL`, in which case the corresponding value is not returned.
44967ee59b9bSJunchao Zhang   If mat is a device matrix, the arrays are on the device. Otherwise, they are on the host.
44977ee59b9bSJunchao Zhang 
44987ee59b9bSJunchao Zhang   One can call this routine on a preallocated but not assembled matrix to just get the memory of the CSR underneath the matrix.
44992ef1f0ffSBarry Smith   If the matrix is assembled, the data array `a` is guaranteed to have the latest values of the matrix.
45007ee59b9bSJunchao Zhang 
45011cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()`
45027ee59b9bSJunchao Zhang @*/
45035d83a8b1SBarry Smith PetscErrorCode MatSeqAIJGetCSRAndMemType(Mat mat, const PetscInt *i[], const PetscInt *j[], PetscScalar *a[], PetscMemType *mtype)
4504d71ae5a4SJacob Faibussowitsch {
45057ee59b9bSJunchao Zhang   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
45067ee59b9bSJunchao Zhang 
45077ee59b9bSJunchao Zhang   PetscFunctionBegin;
45087ee59b9bSJunchao Zhang   PetscCheck(mat->preallocated, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "matrix is not preallocated");
45097ee59b9bSJunchao Zhang   if (aij->ops->getcsrandmemtype) {
45107ee59b9bSJunchao Zhang     PetscCall((*aij->ops->getcsrandmemtype)(mat, i, j, a, mtype));
45117ee59b9bSJunchao Zhang   } else {
45127ee59b9bSJunchao Zhang     if (i) *i = aij->i;
45137ee59b9bSJunchao Zhang     if (j) *j = aij->j;
45147ee59b9bSJunchao Zhang     if (a) *a = aij->a;
45157ee59b9bSJunchao Zhang     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
45167ee59b9bSJunchao Zhang   }
45173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45187ee59b9bSJunchao Zhang }
45197ee59b9bSJunchao Zhang 
4520cc4c1da9SBarry Smith /*@
452121e72a00SBarry Smith   MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
452221e72a00SBarry Smith 
452321e72a00SBarry Smith   Not Collective
452421e72a00SBarry Smith 
452521e72a00SBarry Smith   Input Parameter:
4526fe59aa6dSJacob Faibussowitsch . A - a `MATSEQAIJ` matrix
452721e72a00SBarry Smith 
452821e72a00SBarry Smith   Output Parameter:
452921e72a00SBarry Smith . nz - the maximum number of nonzeros in any row
453021e72a00SBarry Smith 
453121e72a00SBarry Smith   Level: intermediate
453221e72a00SBarry Smith 
4533ce78bad3SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArray()`
453421e72a00SBarry Smith @*/
4535d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJGetMaxRowNonzeros(Mat A, PetscInt *nz)
4536d71ae5a4SJacob Faibussowitsch {
453721e72a00SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data;
453821e72a00SBarry Smith 
453921e72a00SBarry Smith   PetscFunctionBegin;
454021e72a00SBarry Smith   *nz = aij->rmax;
45413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
454221e72a00SBarry Smith }
454321e72a00SBarry Smith 
454449abdd8aSBarry Smith static PetscErrorCode MatCOOStructDestroy_SeqAIJ(void **data)
45452c4ab24aSJunchao Zhang {
454649abdd8aSBarry Smith   MatCOOStruct_SeqAIJ *coo = (MatCOOStruct_SeqAIJ *)*data;
45474d86920dSPierre Jolivet 
45482c4ab24aSJunchao Zhang   PetscFunctionBegin;
45492c4ab24aSJunchao Zhang   PetscCall(PetscFree(coo->perm));
45502c4ab24aSJunchao Zhang   PetscCall(PetscFree(coo->jmap));
45512c4ab24aSJunchao Zhang   PetscCall(PetscFree(coo));
45522c4ab24aSJunchao Zhang   PetscFunctionReturn(PETSC_SUCCESS);
45532c4ab24aSJunchao Zhang }
45542c4ab24aSJunchao Zhang 
4555d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[])
4556d71ae5a4SJacob Faibussowitsch {
4557394ed5ebSJunchao Zhang   MPI_Comm             comm;
4558394ed5ebSJunchao Zhang   PetscInt            *i, *j;
45590d88f7f4SJunchao Zhang   PetscInt             M, N, row, iprev;
4560394ed5ebSJunchao Zhang   PetscCount           k, p, q, nneg, nnz, start, end; /* Index the coo array, so use PetscCount as their type */
4561394ed5ebSJunchao Zhang   PetscInt            *Ai;                             /* Change to PetscCount once we use it for row pointers */
4562394ed5ebSJunchao Zhang   PetscInt            *Aj;
4563394ed5ebSJunchao Zhang   PetscScalar         *Aa;
4564f4f49eeaSPierre Jolivet   Mat_SeqAIJ          *seqaij = (Mat_SeqAIJ *)mat->data;
4565cbc6b225SStefano Zampini   MatType              rtype;
4566394ed5ebSJunchao Zhang   PetscCount          *perm, *jmap;
45672c4ab24aSJunchao Zhang   MatCOOStruct_SeqAIJ *coo;
45680d88f7f4SJunchao Zhang   PetscBool            isorted;
45699f0612e4SBarry Smith   PetscBool            hypre;
4570394ed5ebSJunchao Zhang 
4571394ed5ebSJunchao Zhang   PetscFunctionBegin;
45729566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
45739566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &M, &N));
4574e8729f6fSJunchao Zhang   i = coo_i;
4575e8729f6fSJunchao Zhang   j = coo_j;
45769566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(coo_n, &perm));
45770d88f7f4SJunchao Zhang 
45780d88f7f4SJunchao Zhang   /* Ignore entries with negative row or col indices; at the same time, check if i[] is already sorted (e.g., MatConvert_AlJ_HYPRE results in this case) */
45790d88f7f4SJunchao Zhang   isorted = PETSC_TRUE;
45800d88f7f4SJunchao Zhang   iprev   = PETSC_INT_MIN;
45810d88f7f4SJunchao Zhang   for (k = 0; k < coo_n; k++) {
4582394ed5ebSJunchao Zhang     if (j[k] < 0) i[k] = -1;
45830d88f7f4SJunchao Zhang     if (isorted) {
45840d88f7f4SJunchao Zhang       if (i[k] < iprev) isorted = PETSC_FALSE;
45850d88f7f4SJunchao Zhang       else iprev = i[k];
45860d88f7f4SJunchao Zhang     }
4587394ed5ebSJunchao Zhang     perm[k] = k;
4588394ed5ebSJunchao Zhang   }
4589394ed5ebSJunchao Zhang 
45900d88f7f4SJunchao Zhang   /* Sort by row if not already */
45910d88f7f4SJunchao Zhang   if (!isorted) PetscCall(PetscSortIntWithIntCountArrayPair(coo_n, i, j, perm));
45922b35a777SBarry Smith   PetscCheck(coo_n == 0 || i[coo_n - 1] < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "COO row index %" PetscInt_FMT " is >= the matrix row size %" PetscInt_FMT, i[coo_n - 1], M);
4593651b1cf9SStefano Zampini 
4594651b1cf9SStefano Zampini   /* Advance k to the first row with a non-negative index */
4595651b1cf9SStefano Zampini   for (k = 0; k < coo_n; k++)
45969371c9d4SSatish Balay     if (i[k] >= 0) break;
4597394ed5ebSJunchao Zhang   nneg = k;
45989566063dSJacob 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 */
4599394ed5ebSJunchao Zhang   nnz = 0;                                          /* Total number of unique nonzeros to be counted */
460035cb6cd3SPierre Jolivet   jmap++;                                           /* Inc jmap by 1 for convenience */
4601394ed5ebSJunchao Zhang 
46029f0612e4SBarry Smith   PetscCall(PetscShmgetAllocateArray(M + 1, sizeof(PetscInt), (void **)&Ai)); /* CSR of A */
46039f0612e4SBarry Smith   PetscCall(PetscArrayzero(Ai, M + 1));
46049f0612e4SBarry Smith   PetscCall(PetscShmgetAllocateArray(coo_n - nneg, sizeof(PetscInt), (void **)&Aj)); /* We have at most coo_n-nneg unique nonzeros */
4605394ed5ebSJunchao Zhang 
460621fb621cSStefano Zampini   PetscCall(PetscStrcmp("_internal_COO_mat_for_hypre", ((PetscObject)mat)->name, &hypre));
4607651b1cf9SStefano Zampini 
4608394ed5ebSJunchao Zhang   /* In each row, sort by column, then unique column indices to get row length */
460935cb6cd3SPierre Jolivet   Ai++;  /* Inc by 1 for convenience */
4610394ed5ebSJunchao Zhang   q = 0; /* q-th unique nonzero, with q starting from 0 */
4611394ed5ebSJunchao Zhang   while (k < coo_n) {
46120d88f7f4SJunchao Zhang     PetscBool strictly_sorted; // this row is strictly sorted?
46130d88f7f4SJunchao Zhang     PetscInt  jprev;
46140d88f7f4SJunchao Zhang 
46150d88f7f4SJunchao Zhang     /* get [start,end) indices for this row; also check if cols in this row are strictly sorted */
4616394ed5ebSJunchao Zhang     row             = i[k];
46170d88f7f4SJunchao Zhang     start           = k;
46180d88f7f4SJunchao Zhang     jprev           = PETSC_INT_MIN;
46190d88f7f4SJunchao Zhang     strictly_sorted = PETSC_TRUE;
46200d88f7f4SJunchao Zhang     while (k < coo_n && i[k] == row) {
46210d88f7f4SJunchao Zhang       if (strictly_sorted) {
46220d88f7f4SJunchao Zhang         if (j[k] <= jprev) strictly_sorted = PETSC_FALSE;
46230d88f7f4SJunchao Zhang         else jprev = j[k];
46240d88f7f4SJunchao Zhang       }
46250d88f7f4SJunchao Zhang       k++;
46260d88f7f4SJunchao Zhang     }
4627394ed5ebSJunchao Zhang     end = k;
46280d88f7f4SJunchao Zhang 
4629651b1cf9SStefano Zampini     /* hack for HYPRE: swap min column to diag so that diagonal values will go first */
4630651b1cf9SStefano Zampini     if (hypre) {
46311690c2aeSBarry Smith       PetscInt  minj    = PETSC_INT_MAX;
4632651b1cf9SStefano Zampini       PetscBool hasdiag = PETSC_FALSE;
46330d88f7f4SJunchao Zhang 
46340d88f7f4SJunchao Zhang       if (strictly_sorted) { // fast path to swap the first and the diag
46350d88f7f4SJunchao Zhang         PetscCount tmp;
46360d88f7f4SJunchao Zhang         for (p = start; p < end; p++) {
46370d88f7f4SJunchao Zhang           if (j[p] == row && p != start) {
46381c265611SJunchao Zhang             j[p]        = j[start]; // swap j[], so that the diagonal value will go first (manipulated by perm[])
46390d88f7f4SJunchao Zhang             j[start]    = row;
46400d88f7f4SJunchao Zhang             tmp         = perm[start];
46411c265611SJunchao Zhang             perm[start] = perm[p]; // also swap perm[] so we can save the call to PetscSortIntWithCountArray() below
46420d88f7f4SJunchao Zhang             perm[p]     = tmp;
46430d88f7f4SJunchao Zhang             break;
46440d88f7f4SJunchao Zhang           }
46450d88f7f4SJunchao Zhang         }
46460d88f7f4SJunchao Zhang       } else {
4647651b1cf9SStefano Zampini         for (p = start; p < end; p++) {
4648651b1cf9SStefano Zampini           hasdiag = (PetscBool)(hasdiag || (j[p] == row));
4649651b1cf9SStefano Zampini           minj    = PetscMin(minj, j[p]);
4650651b1cf9SStefano Zampini         }
46510d88f7f4SJunchao Zhang 
4652651b1cf9SStefano Zampini         if (hasdiag) {
4653651b1cf9SStefano Zampini           for (p = start; p < end; p++) {
4654651b1cf9SStefano Zampini             if (j[p] == minj) j[p] = row;
4655651b1cf9SStefano Zampini             else if (j[p] == row) j[p] = minj;
4656651b1cf9SStefano Zampini           }
4657651b1cf9SStefano Zampini         }
4658651b1cf9SStefano Zampini       }
46590d88f7f4SJunchao Zhang     }
46601c265611SJunchao Zhang     // sort by columns in a row. perm[] indicates their original order
46610d88f7f4SJunchao Zhang     if (!strictly_sorted) PetscCall(PetscSortIntWithCountArray(end - start, j + start, perm + start));
46628551dd9cSJunchao Zhang     PetscCheck(end == start || j[end - 1] < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "COO column index %" PetscInt_FMT " is >= the matrix column size %" PetscInt_FMT, j[end - 1], N);
4663651b1cf9SStefano Zampini 
46640d88f7f4SJunchao Zhang     if (strictly_sorted) { // fast path to set Aj[], jmap[], Ai[], nnz, q
46650d88f7f4SJunchao Zhang       for (p = start; p < end; p++, q++) {
46660d88f7f4SJunchao Zhang         Aj[q]   = j[p];
46670d88f7f4SJunchao Zhang         jmap[q] = 1;
46680d88f7f4SJunchao Zhang       }
46696497c311SBarry Smith       PetscCall(PetscIntCast(end - start, Ai + row));
46700d88f7f4SJunchao Zhang       nnz += Ai[row]; // q is already advanced
46710d88f7f4SJunchao Zhang     } else {
4672394ed5ebSJunchao Zhang       /* Find number of unique col entries in this row */
4673394ed5ebSJunchao Zhang       Aj[q]   = j[start]; /* Log the first nonzero in this row */
4674651b1cf9SStefano Zampini       jmap[q] = 1;        /* Number of repeats of this nonzero entry */
4675394ed5ebSJunchao Zhang       Ai[row] = 1;
4676394ed5ebSJunchao Zhang       nnz++;
4677394ed5ebSJunchao Zhang 
4678394ed5ebSJunchao Zhang       for (p = start + 1; p < end; p++) { /* Scan remaining nonzero in this row */
4679394ed5ebSJunchao Zhang         if (j[p] != j[p - 1]) {           /* Meet a new nonzero */
4680394ed5ebSJunchao Zhang           q++;
4681394ed5ebSJunchao Zhang           jmap[q] = 1;
4682394ed5ebSJunchao Zhang           Aj[q]   = j[p];
4683394ed5ebSJunchao Zhang           Ai[row]++;
4684394ed5ebSJunchao Zhang           nnz++;
4685394ed5ebSJunchao Zhang         } else {
4686394ed5ebSJunchao Zhang           jmap[q]++;
4687394ed5ebSJunchao Zhang         }
4688394ed5ebSJunchao Zhang       }
4689394ed5ebSJunchao Zhang       q++; /* Move to next row and thus next unique nonzero */
4690394ed5ebSJunchao Zhang     }
46910d88f7f4SJunchao Zhang   }
46920d88f7f4SJunchao Zhang 
4693394ed5ebSJunchao Zhang   Ai--; /* Back to the beginning of Ai[] */
4694394ed5ebSJunchao Zhang   for (k = 0; k < M; k++) Ai[k + 1] += Ai[k];
46950d88f7f4SJunchao Zhang   jmap--; // Back to the beginning of jmap[]
4696394ed5ebSJunchao Zhang   jmap[0] = 0;
4697394ed5ebSJunchao Zhang   for (k = 0; k < nnz; k++) jmap[k + 1] += jmap[k];
46980d88f7f4SJunchao Zhang 
46999f0612e4SBarry Smith   if (nnz < coo_n - nneg) { /* Reallocate with actual number of unique nonzeros */
4700394ed5ebSJunchao Zhang     PetscCount *jmap_new;
4701394ed5ebSJunchao Zhang     PetscInt   *Aj_new;
4702394ed5ebSJunchao Zhang 
47039566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz + 1, &jmap_new));
47049566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(jmap_new, jmap, nnz + 1));
47059566063dSJacob Faibussowitsch     PetscCall(PetscFree(jmap));
4706394ed5ebSJunchao Zhang     jmap = jmap_new;
4707394ed5ebSJunchao Zhang 
47089f0612e4SBarry Smith     PetscCall(PetscShmgetAllocateArray(nnz, sizeof(PetscInt), (void **)&Aj_new));
47099566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(Aj_new, Aj, nnz));
47109f0612e4SBarry Smith     PetscCall(PetscShmgetDeallocateArray((void **)&Aj));
4711394ed5ebSJunchao Zhang     Aj = Aj_new;
4712394ed5ebSJunchao Zhang   }
4713394ed5ebSJunchao Zhang 
4714394ed5ebSJunchao Zhang   if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */
4715394ed5ebSJunchao Zhang     PetscCount *perm_new;
4716cbc6b225SStefano Zampini 
47179566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coo_n - nneg, &perm_new));
47189566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(perm_new, perm + nneg, coo_n - nneg));
47199566063dSJacob Faibussowitsch     PetscCall(PetscFree(perm));
4720394ed5ebSJunchao Zhang     perm = perm_new;
4721394ed5ebSJunchao Zhang   }
4722394ed5ebSJunchao Zhang 
47239566063dSJacob Faibussowitsch   PetscCall(MatGetRootType_Private(mat, &rtype));
47249f0612e4SBarry Smith   PetscCall(PetscShmgetAllocateArray(nnz, sizeof(PetscScalar), (void **)&Aa));
47259f0612e4SBarry Smith   PetscCall(PetscArrayzero(Aa, nnz));
47269566063dSJacob Faibussowitsch   PetscCall(MatSetSeqAIJWithArrays_private(PETSC_COMM_SELF, M, N, Ai, Aj, Aa, rtype, mat));
4727394ed5ebSJunchao Zhang 
4728394ed5ebSJunchao Zhang   seqaij->free_a = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */
47292c4ab24aSJunchao Zhang 
47302c4ab24aSJunchao Zhang   // Put the COO struct in a container and then attach that to the matrix
47312c4ab24aSJunchao Zhang   PetscCall(PetscMalloc1(1, &coo));
47326497c311SBarry Smith   PetscCall(PetscIntCast(nnz, &coo->nz));
47332c4ab24aSJunchao Zhang   coo->n    = coo_n;
47342c4ab24aSJunchao Zhang   coo->Atot = coo_n - nneg; // Annz is seqaij->nz, so no need to record that again
47352c4ab24aSJunchao Zhang   coo->jmap = jmap;         // of length nnz+1
47362c4ab24aSJunchao Zhang   coo->perm = perm;
473703e76207SPierre Jolivet   PetscCall(PetscObjectContainerCompose((PetscObject)mat, "__PETSc_MatCOOStruct_Host", coo, MatCOOStructDestroy_SeqAIJ));
47383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4739394ed5ebSJunchao Zhang }
4740394ed5ebSJunchao Zhang 
4741d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A, const PetscScalar v[], InsertMode imode)
4742d71ae5a4SJacob Faibussowitsch {
4743394ed5ebSJunchao Zhang   Mat_SeqAIJ          *aseq = (Mat_SeqAIJ *)A->data;
4744394ed5ebSJunchao Zhang   PetscCount           i, j, Annz = aseq->nz;
47452c4ab24aSJunchao Zhang   PetscCount          *perm, *jmap;
4746394ed5ebSJunchao Zhang   PetscScalar         *Aa;
47472c4ab24aSJunchao Zhang   PetscContainer       container;
47482c4ab24aSJunchao Zhang   MatCOOStruct_SeqAIJ *coo;
4749394ed5ebSJunchao Zhang 
4750394ed5ebSJunchao Zhang   PetscFunctionBegin;
47512c4ab24aSJunchao Zhang   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_MatCOOStruct_Host", (PetscObject *)&container));
47522c4ab24aSJunchao Zhang   PetscCheck(container, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not found MatCOOStruct on this matrix");
47532c4ab24aSJunchao Zhang   PetscCall(PetscContainerGetPointer(container, (void **)&coo));
47542c4ab24aSJunchao Zhang   perm = coo->perm;
47552c4ab24aSJunchao Zhang   jmap = coo->jmap;
47569566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A, &Aa));
4757394ed5ebSJunchao Zhang   for (i = 0; i < Annz; i++) {
4758b6c38306SJunchao Zhang     PetscScalar sum = 0.0;
4759b6c38306SJunchao Zhang     for (j = jmap[i]; j < jmap[i + 1]; j++) sum += v[perm[j]];
4760b6c38306SJunchao Zhang     Aa[i] = (imode == INSERT_VALUES ? 0.0 : Aa[i]) + sum;
4761394ed5ebSJunchao Zhang   }
47629566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A, &Aa));
47633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4764394ed5ebSJunchao Zhang }
4765394ed5ebSJunchao Zhang 
476634b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
47675063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat, MatType, MatReuse, Mat *);
476802fe1965SBarry Smith #endif
4769d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_HIP)
4770d5e393b6SSuyash Tandon PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJHIPSPARSE(Mat, MatType, MatReuse, Mat *);
4771d5e393b6SSuyash Tandon #endif
47723d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
47735063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat, MatType, MatReuse, Mat *);
47743d0639e7SStefano Zampini #endif
477502fe1965SBarry Smith 
4776d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4777d71ae5a4SJacob Faibussowitsch {
4778273d9f13SBarry Smith   Mat_SeqAIJ *b;
477938baddfdSBarry Smith   PetscMPIInt size;
4780273d9f13SBarry Smith 
4781273d9f13SBarry Smith   PetscFunctionBegin;
47829566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
478308401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Comm must be of size 1");
4784273d9f13SBarry Smith 
47854dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
47862205254eSKarl Rupp 
4787b0a32e0cSBarry Smith   B->data   = (void *)b;
4788aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
4789071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
47902205254eSKarl Rupp 
4791f4259b30SLisandro Dalcin   b->row                = NULL;
4792f4259b30SLisandro Dalcin   b->col                = NULL;
4793f4259b30SLisandro Dalcin   b->icol               = NULL;
4794b810aeb4SBarry Smith   b->reallocs           = 0;
479536db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4796f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4797416022c9SBarry Smith   b->nonew              = 0;
4798f4259b30SLisandro Dalcin   b->diag               = NULL;
4799f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4800f4259b30SLisandro Dalcin   B->spptr              = NULL;
4801f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4802f4259b30SLisandro Dalcin   b->idiag              = NULL;
4803f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4804f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
480571f1c65dSBarry Smith   b->omega              = 1.0;
480671f1c65dSBarry Smith   b->fshift             = 0.0;
4807bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4808a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
480917ab2063SBarry Smith 
48109566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ));
4811d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
48129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEnginePut_C", MatlabEnginePut_SeqAIJ));
48139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "PetscMatlabEngineGet_C", MatlabEngineGet_SeqAIJ));
4814b3866ffcSBarry Smith #endif
48159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetColumnIndices_C", MatSeqAIJSetColumnIndices_SeqAIJ));
48169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_SeqAIJ));
48179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_SeqAIJ));
48189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsbaij_C", MatConvert_SeqAIJ_SeqSBAIJ));
48199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqbaij_C", MatConvert_SeqAIJ_SeqBAIJ));
48209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijperm_C", MatConvert_SeqAIJ_SeqAIJPERM));
48219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijsell_C", MatConvert_SeqAIJ_SeqAIJSELL));
48229779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
48239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijmkl_C", MatConvert_SeqAIJ_SeqAIJMKL));
4824191b95cbSRichard Tran Mills #endif
482534b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
48269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcusparse_C", MatConvert_SeqAIJ_SeqAIJCUSPARSE));
48279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_seqaij_C", MatProductSetFromOptions_SeqAIJ));
48289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaijcusparse_C", MatProductSetFromOptions_SeqAIJ));
482902fe1965SBarry Smith #endif
4830d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_HIP)
4831d5e393b6SSuyash Tandon   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijhipsparse_C", MatConvert_SeqAIJ_SeqAIJHIPSPARSE));
4832d5e393b6SSuyash Tandon   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijhipsparse_seqaij_C", MatProductSetFromOptions_SeqAIJ));
4833d5e393b6SSuyash Tandon   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaijhipsparse_C", MatProductSetFromOptions_SeqAIJ));
4834d5e393b6SSuyash Tandon #endif
48353d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
48369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijkokkos_C", MatConvert_SeqAIJ_SeqAIJKokkos));
48373d0639e7SStefano Zampini #endif
48389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqaijcrl_C", MatConvert_SeqAIJ_SeqAIJCRL));
4839af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
48409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_elemental_C", MatConvert_SeqAIJ_Elemental));
4841af8000cdSHong Zhang #endif
4842d1a032dbSPierre Jolivet #if defined(PETSC_HAVE_SCALAPACK) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE))
48439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_scalapack_C", MatConvert_AIJ_ScaLAPACK));
4844d24d4204SJose E. Roman #endif
484563c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
48469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_hypre_C", MatConvert_AIJ_HYPRE));
48479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_transpose_seqaij_seqaij_C", MatProductSetFromOptions_Transpose_AIJ_AIJ));
484863c07aadSStefano Zampini #endif
48499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqdense_C", MatConvert_SeqAIJ_SeqDense));
48509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_seqsell_C", MatConvert_SeqAIJ_SeqSELL));
48519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqaij_is_C", MatConvert_XAIJ_IS));
48529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsTranspose_C", MatIsTranspose_SeqAIJ));
485314e4dea2SJose E. Roman   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsHermitianTranspose_C", MatIsHermitianTranspose_SeqAIJ));
48549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocation_C", MatSeqAIJSetPreallocation_SeqAIJ));
48559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatResetPreallocation_C", MatResetPreallocation_SeqAIJ));
4856674b392bSAlexander   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatResetHash_C", MatResetHash_SeqAIJ));
48579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJSetPreallocationCSR_C", MatSeqAIJSetPreallocationCSR_SeqAIJ));
48589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatReorderForNonzeroDiagonal_C", MatReorderForNonzeroDiagonal_SeqAIJ));
48599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_is_seqaij_C", MatProductSetFromOptions_IS_XAIJ));
48609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqaij_C", MatProductSetFromOptions_SeqDense_SeqAIJ));
48619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqaij_C", MatProductSetFromOptions_SeqAIJ));
48629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqAIJKron_C", MatSeqAIJKron_SeqAIJ));
48639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_SeqAIJ));
48649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_SeqAIJ));
48659566063dSJacob Faibussowitsch   PetscCall(MatCreate_SeqAIJ_Inode(B));
48669566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ));
48679566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetTypeFromOptions(B)); /* this allows changing the matrix subtype to say MATSEQAIJPERM */
48683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
486917ab2063SBarry Smith }
487017ab2063SBarry Smith 
4871b24902e0SBarry Smith /*
48723893b582SJunchao Zhang     Given a matrix generated with MatGetFactor() duplicates all the information in A into C
4873b24902e0SBarry Smith */
4874d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C, Mat A, MatDuplicateOption cpvalues, PetscBool mallocmatspace)
4875d71ae5a4SJacob Faibussowitsch {
48762a350339SBarry Smith   Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data, *a = (Mat_SeqAIJ *)A->data;
4877071fcb05SBarry Smith   PetscInt    m = A->rmap->n, i;
487817ab2063SBarry Smith 
48793a40ed3dSBarry Smith   PetscFunctionBegin;
4880aed4548fSBarry Smith   PetscCheck(A->assembled || cpvalues == MAT_DO_NOT_COPY_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot duplicate unassembled matrix");
4881273d9f13SBarry Smith 
4882d5f3da31SBarry Smith   C->factortype = A->factortype;
4883f4259b30SLisandro Dalcin   c->row        = NULL;
4884f4259b30SLisandro Dalcin   c->col        = NULL;
4885f4259b30SLisandro Dalcin   c->icol       = NULL;
48866ad4291fSHong Zhang   c->reallocs   = 0;
488769272f91SPierre Jolivet   C->assembled  = A->assembled;
488817ab2063SBarry Smith 
488969272f91SPierre Jolivet   if (A->preallocated) {
48909566063dSJacob Faibussowitsch     PetscCall(PetscLayoutReference(A->rmap, &C->rmap));
48919566063dSJacob Faibussowitsch     PetscCall(PetscLayoutReference(A->cmap, &C->cmap));
4892eec197d1SBarry Smith 
489331fe6a7dSBarry Smith     if (!A->hash_active) {
48949566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(m, &c->imax));
48959566063dSJacob Faibussowitsch       PetscCall(PetscMemcpy(c->imax, a->imax, m * sizeof(PetscInt)));
48969566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(m, &c->ilen));
48979566063dSJacob Faibussowitsch       PetscCall(PetscMemcpy(c->ilen, a->ilen, m * sizeof(PetscInt)));
489817ab2063SBarry Smith 
489917ab2063SBarry Smith       /* allocate the matrix space */
4900f77e22a1SHong Zhang       if (mallocmatspace) {
49019f0612e4SBarry Smith         PetscCall(PetscShmgetAllocateArray(a->i[m], sizeof(PetscScalar), (void **)&c->a));
49029f0612e4SBarry Smith         PetscCall(PetscShmgetAllocateArray(a->i[m], sizeof(PetscInt), (void **)&c->j));
49039f0612e4SBarry Smith         PetscCall(PetscShmgetAllocateArray(m + 1, sizeof(PetscInt), (void **)&c->i));
49049566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(c->i, a->i, m + 1));
49059f0612e4SBarry Smith         c->free_a  = PETSC_TRUE;
49069f0612e4SBarry Smith         c->free_ij = PETSC_TRUE;
490717ab2063SBarry Smith         if (m > 0) {
49089566063dSJacob Faibussowitsch           PetscCall(PetscArraycpy(c->j, a->j, a->i[m]));
4909be6bf707SBarry Smith           if (cpvalues == MAT_COPY_VALUES) {
49102e5835c6SStefano Zampini             const PetscScalar *aa;
49112e5835c6SStefano Zampini 
49129566063dSJacob Faibussowitsch             PetscCall(MatSeqAIJGetArrayRead(A, &aa));
49139566063dSJacob Faibussowitsch             PetscCall(PetscArraycpy(c->a, aa, a->i[m]));
49149566063dSJacob Faibussowitsch             PetscCall(MatSeqAIJGetArrayRead(A, &aa));
4915be6bf707SBarry Smith           } else {
49169566063dSJacob Faibussowitsch             PetscCall(PetscArrayzero(c->a, a->i[m]));
491717ab2063SBarry Smith           }
491808480c60SBarry Smith         }
4919f77e22a1SHong Zhang       }
492031fe6a7dSBarry Smith       C->preallocated = PETSC_TRUE;
492131fe6a7dSBarry Smith     } else {
492231fe6a7dSBarry Smith       PetscCheck(mallocmatspace, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Cannot malloc matrix memory from a non-preallocated matrix");
492331fe6a7dSBarry Smith       PetscCall(MatSetUp(C));
492431fe6a7dSBarry Smith     }
492517ab2063SBarry Smith 
49266ad4291fSHong Zhang     c->ignorezeroentries  = a->ignorezeroentries;
4927416022c9SBarry Smith     c->roworiented        = a->roworiented;
4928416022c9SBarry Smith     c->nonew              = a->nonew;
4929f4259b30SLisandro Dalcin     c->solve_work         = NULL;
4930f4259b30SLisandro Dalcin     c->saved_values       = NULL;
4931f4259b30SLisandro Dalcin     c->idiag              = NULL;
4932f4259b30SLisandro Dalcin     c->ssor_work          = NULL;
4933a9817697SBarry Smith     c->keepnonzeropattern = a->keepnonzeropattern;
49346ad4291fSHong Zhang 
4935893ad86cSHong Zhang     c->rmax  = a->rmax;
4936416022c9SBarry Smith     c->nz    = a->nz;
49378ed568f8SMatthew G Knepley     c->maxnz = a->nz; /* Since we allocate exactly the right amount */
4938754ec7b1SSatish Balay 
49396ad4291fSHong Zhang     c->compressedrow.use   = a->compressedrow.use;
49406ad4291fSHong Zhang     c->compressedrow.nrows = a->compressedrow.nrows;
4941cd6b891eSBarry Smith     if (a->compressedrow.use) {
49426ad4291fSHong Zhang       i = a->compressedrow.nrows;
49439566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(i + 1, &c->compressedrow.i, i, &c->compressedrow.rindex));
49449566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->compressedrow.i, a->compressedrow.i, i + 1));
49459566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->compressedrow.rindex, a->compressedrow.rindex, i));
494627ea64f8SHong Zhang     } else {
494727ea64f8SHong Zhang       c->compressedrow.use    = PETSC_FALSE;
49480298fd71SBarry Smith       c->compressedrow.i      = NULL;
49490298fd71SBarry Smith       c->compressedrow.rindex = NULL;
49506ad4291fSHong Zhang     }
4951ea632784SBarry Smith     c->nonzerorowcnt = a->nonzerorowcnt;
4952e56f5c9eSBarry Smith     C->nonzerostate  = A->nonzerostate;
49534846f1f5SKris Buschelman 
49549566063dSJacob Faibussowitsch     PetscCall(MatDuplicate_SeqAIJ_Inode(A, cpvalues, &C));
495569272f91SPierre Jolivet   }
49569566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist, &((PetscObject)C)->qlist));
49573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
495817ab2063SBarry Smith }
495917ab2063SBarry Smith 
4960d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqAIJ(Mat A, MatDuplicateOption cpvalues, Mat *B)
4961d71ae5a4SJacob Faibussowitsch {
4962b24902e0SBarry Smith   PetscFunctionBegin;
49639566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B));
49649566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*B, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
496548a46eb9SPierre Jolivet   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) PetscCall(MatSetBlockSizesFromMats(*B, A, A));
49669566063dSJacob Faibussowitsch   PetscCall(MatSetType(*B, ((PetscObject)A)->type_name));
49679566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqAIJ(*B, A, cpvalues, PETSC_TRUE));
49683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4969b24902e0SBarry Smith }
4970b24902e0SBarry Smith 
4971d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4972d71ae5a4SJacob Faibussowitsch {
497352f91c60SVaclav Hapla   PetscBool isbinary, ishdf5;
497452f91c60SVaclav Hapla 
497552f91c60SVaclav Hapla   PetscFunctionBegin;
497652f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1);
497752f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
4978c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
49799566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
49809566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
49819566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
498252f91c60SVaclav Hapla   if (isbinary) {
49839566063dSJacob Faibussowitsch     PetscCall(MatLoad_SeqAIJ_Binary(newMat, viewer));
498452f91c60SVaclav Hapla   } else if (ishdf5) {
498552f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
49869566063dSJacob Faibussowitsch     PetscCall(MatLoad_AIJ_HDF5(newMat, viewer));
498752f91c60SVaclav Hapla #else
498852f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
498952f91c60SVaclav Hapla #endif
499052f91c60SVaclav Hapla   } else {
499198921bdaSJacob 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);
499252f91c60SVaclav Hapla   }
49933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
499452f91c60SVaclav Hapla }
499552f91c60SVaclav Hapla 
4996d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
4997d71ae5a4SJacob Faibussowitsch {
49983ea6fe3dSLisandro Dalcin   Mat_SeqAIJ *a = (Mat_SeqAIJ *)mat->data;
49993ea6fe3dSLisandro Dalcin   PetscInt    header[4], *rowlens, M, N, nz, sum, rows, cols, i;
5000fbdbba38SShri Abhyankar 
5001fbdbba38SShri Abhyankar   PetscFunctionBegin;
50029566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
5003bbead8a2SBarry Smith 
50043ea6fe3dSLisandro Dalcin   /* read in matrix header */
50059566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT));
500608401ef6SPierre Jolivet   PetscCheck(header[0] == MAT_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file");
50079371c9d4SSatish Balay   M  = header[1];
50089371c9d4SSatish Balay   N  = header[2];
50099371c9d4SSatish Balay   nz = header[3];
501008401ef6SPierre Jolivet   PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M);
501108401ef6SPierre Jolivet   PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N);
501208401ef6SPierre Jolivet   PetscCheck(nz >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Matrix stored in special format on disk, cannot load as SeqAIJ");
5013fbdbba38SShri Abhyankar 
50143ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
50159566063dSJacob Faibussowitsch   PetscCall(MatLoad_Binary_BlockSizes(mat, viewer));
50163ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
50173ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
50183ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
50193ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
50203ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
50219566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
50229566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
50233ea6fe3dSLisandro Dalcin 
50243ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
50259566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &rows, &cols));
5026aed4548fSBarry 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);
50273ea6fe3dSLisandro Dalcin 
5028fbdbba38SShri Abhyankar   /* read in row lengths */
50299566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(M, &rowlens));
50309566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, rowlens, M, NULL, PETSC_INT));
50313ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
50329371c9d4SSatish Balay   sum = 0;
50339371c9d4SSatish Balay   for (i = 0; i < M; i++) sum += rowlens[i];
503408401ef6SPierre 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);
50353ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
50369566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(mat, 0, rowlens));
50379566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &rows, &cols));
5038aed4548fSBarry 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);
50393ea6fe3dSLisandro Dalcin   /* store row lengths */
50409566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(a->ilen, rowlens, M));
50419566063dSJacob Faibussowitsch   PetscCall(PetscFree(rowlens));
5042fbdbba38SShri Abhyankar 
50433ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
50449371c9d4SSatish Balay   a->i[0] = 0;
50459371c9d4SSatish Balay   for (i = 0; i < M; i++) a->i[i + 1] = a->i[i] + a->ilen[i];
50463ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
50479566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, a->j, nz, NULL, PETSC_INT));
50483ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
50499566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, a->a, nz, NULL, PETSC_SCALAR));
5050fbdbba38SShri Abhyankar 
50519566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
50529566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
50533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5054fbdbba38SShri Abhyankar }
5055fbdbba38SShri Abhyankar 
5056d71ae5a4SJacob Faibussowitsch PetscErrorCode MatEqual_SeqAIJ(Mat A, Mat B, PetscBool *flg)
5057d71ae5a4SJacob Faibussowitsch {
50587264ac53SSatish Balay   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)A->data, *b = (Mat_SeqAIJ *)B->data;
5059fff043a9SJunchao Zhang   const PetscScalar *aa, *ba;
5060eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
5061eeffb40dSHong Zhang   PetscInt k;
5062eeffb40dSHong Zhang #endif
50637264ac53SSatish Balay 
50643a40ed3dSBarry Smith   PetscFunctionBegin;
5065bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
5066d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) || (a->nz != b->nz)) {
5067ca44d042SBarry Smith     *flg = PETSC_FALSE;
50683ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5069bcd2baecSBarry Smith   }
50707264ac53SSatish Balay 
50717264ac53SSatish Balay   /* if the a->i are the same */
50729566063dSJacob Faibussowitsch   PetscCall(PetscArraycmp(a->i, b->i, A->rmap->n + 1, flg));
50733ba16761SJacob Faibussowitsch   if (!*flg) PetscFunctionReturn(PETSC_SUCCESS);
50747264ac53SSatish Balay 
50757264ac53SSatish Balay   /* if a->j are the same */
50769566063dSJacob Faibussowitsch   PetscCall(PetscArraycmp(a->j, b->j, a->nz, flg));
50773ba16761SJacob Faibussowitsch   if (!*flg) PetscFunctionReturn(PETSC_SUCCESS);
5078bcd2baecSBarry Smith 
50799566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &aa));
50809566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(B, &ba));
5081bcd2baecSBarry Smith   /* if a->a are the same */
5082eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
5083eeffb40dSHong Zhang   for (k = 0; k < a->nz; k++) {
5084fff043a9SJunchao Zhang     if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) {
5085eeffb40dSHong Zhang       *flg = PETSC_FALSE;
50863ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
5087eeffb40dSHong Zhang     }
5088eeffb40dSHong Zhang   }
5089eeffb40dSHong Zhang #else
50909566063dSJacob Faibussowitsch   PetscCall(PetscArraycmp(aa, ba, a->nz, flg));
5091eeffb40dSHong Zhang #endif
50929566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &aa));
50939566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(B, &ba));
50943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50957264ac53SSatish Balay }
509636db0b34SBarry Smith 
509705869f15SSatish Balay /*@
509811a5261eSBarry Smith   MatCreateSeqAIJWithArrays - Creates an sequential `MATSEQAIJ` matrix using matrix elements (in CSR format)
509936db0b34SBarry Smith   provided by the user.
510036db0b34SBarry Smith 
5101d083f849SBarry Smith   Collective
510236db0b34SBarry Smith 
510336db0b34SBarry Smith   Input Parameters:
510436db0b34SBarry Smith + comm - must be an MPI communicator of size 1
510536db0b34SBarry Smith . m    - number of rows
510636db0b34SBarry Smith . n    - number of columns
5107483a2f95SBarry Smith . i    - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
510836db0b34SBarry Smith . j    - column indices
510936db0b34SBarry Smith - a    - matrix values
511036db0b34SBarry Smith 
511136db0b34SBarry Smith   Output Parameter:
511236db0b34SBarry Smith . mat - the matrix
511336db0b34SBarry Smith 
511436db0b34SBarry Smith   Level: intermediate
511536db0b34SBarry Smith 
511636db0b34SBarry Smith   Notes:
51172ef1f0ffSBarry Smith   The `i`, `j`, and `a` arrays are not copied by this routine, the user must free these arrays
5118292fb18eSBarry Smith   once the matrix is destroyed and not before
511936db0b34SBarry Smith 
512036db0b34SBarry Smith   You cannot set new nonzero locations into this matrix, that will generate an error.
512136db0b34SBarry Smith 
51222ef1f0ffSBarry Smith   The `i` and `j` indices are 0 based
512336db0b34SBarry Smith 
5124a4552177SSatish Balay   The format which is used for the sparse matrix input, is equivalent to a
5125a4552177SSatish Balay   row-major ordering.. i.e for the following matrix, the input data expected is
51268eef79e4SBarry Smith   as shown
51272ef1f0ffSBarry Smith .vb
51282ef1f0ffSBarry Smith         1 0 0
51292ef1f0ffSBarry Smith         2 0 3
51302ef1f0ffSBarry Smith         4 5 6
5131a4552177SSatish Balay 
51322ef1f0ffSBarry Smith         i =  {0,1,3,6}  [size = nrow+1  = 3+1]
51332ef1f0ffSBarry Smith         j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
51342ef1f0ffSBarry Smith         v =  {1,2,3,4,5,6}  [size = 6]
51352ef1f0ffSBarry Smith .ve
5136a4552177SSatish Balay 
51371cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateMPIAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()`
513836db0b34SBarry Smith @*/
5139d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat)
5140d71ae5a4SJacob Faibussowitsch {
5141cbcfb4deSHong Zhang   PetscInt    ii;
514236db0b34SBarry Smith   Mat_SeqAIJ *aij;
5143cbcfb4deSHong Zhang   PetscInt    jj;
514436db0b34SBarry Smith 
514536db0b34SBarry Smith   PetscFunctionBegin;
5146aed4548fSBarry Smith   PetscCheck(m <= 0 || i[0] == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "i (row indices) must start with 0");
51479566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, mat));
51489566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mat, m, n, m, n));
51499566063dSJacob Faibussowitsch   /* PetscCall(MatSetBlockSizes(*mat,,)); */
51509566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mat, MATSEQAIJ));
51519566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, MAT_SKIP_ALLOCATION, NULL));
5152ab93d7beSBarry Smith   aij = (Mat_SeqAIJ *)(*mat)->data;
51539566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m, &aij->imax));
51549566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m, &aij->ilen));
5155ab93d7beSBarry Smith 
515636db0b34SBarry Smith   aij->i       = i;
515736db0b34SBarry Smith   aij->j       = j;
515836db0b34SBarry Smith   aij->a       = a;
515936db0b34SBarry Smith   aij->nonew   = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
5160e6b907acSBarry Smith   aij->free_a  = PETSC_FALSE;
5161e6b907acSBarry Smith   aij->free_ij = PETSC_FALSE;
516236db0b34SBarry Smith 
5163cbc6b225SStefano Zampini   for (ii = 0, aij->nonzerorowcnt = 0, aij->rmax = 0; ii < m; ii++) {
516436db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii + 1] - i[ii];
516576bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
5166aed4548fSBarry 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]);
51679985e31cSBarry Smith       for (jj = i[ii] + 1; jj < i[ii + 1]; jj++) {
516808401ef6SPierre 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);
516908401ef6SPierre 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);
51709985e31cSBarry Smith       }
517136db0b34SBarry Smith     }
517276bd3646SJed Brown   }
517376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
517436db0b34SBarry Smith     for (ii = 0; ii < aij->i[m]; ii++) {
517508401ef6SPierre 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]);
5176da0802e2SStefano Zampini       PetscCheck(j[ii] <= n - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column index to large at location = %" PetscInt_FMT " index = %" PetscInt_FMT " last column = %" PetscInt_FMT, ii, j[ii], n - 1);
517736db0b34SBarry Smith     }
517876bd3646SJed Brown   }
517936db0b34SBarry Smith 
51809566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY));
51819566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY));
51823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
518336db0b34SBarry Smith }
5184cbc6b225SStefano Zampini 
5185f62e3866SBarry Smith /*@
518611a5261eSBarry Smith   MatCreateSeqAIJFromTriple - Creates an sequential `MATSEQAIJ` matrix using matrix elements (in COO format)
51878a0b0e6bSVictor Minden   provided by the user.
51888a0b0e6bSVictor Minden 
5189d083f849SBarry Smith   Collective
51908a0b0e6bSVictor Minden 
51918a0b0e6bSVictor Minden   Input Parameters:
51928a0b0e6bSVictor Minden + comm - must be an MPI communicator of size 1
51938a0b0e6bSVictor Minden . m    - number of rows
51948a0b0e6bSVictor Minden . n    - number of columns
51958a0b0e6bSVictor Minden . i    - row indices
51968a0b0e6bSVictor Minden . j    - column indices
51971230e6d1SVictor Minden . a    - matrix values
51981230e6d1SVictor Minden . nz   - number of nonzeros
51992ef1f0ffSBarry Smith - idx  - if the `i` and `j` indices start with 1 use `PETSC_TRUE` otherwise use `PETSC_FALSE`
52008a0b0e6bSVictor Minden 
52018a0b0e6bSVictor Minden   Output Parameter:
52028a0b0e6bSVictor Minden . mat - the matrix
52038a0b0e6bSVictor Minden 
52048a0b0e6bSVictor Minden   Level: intermediate
52058a0b0e6bSVictor Minden 
5206f62e3866SBarry Smith   Example:
5207f62e3866SBarry Smith   For the following matrix, the input data expected is as shown (using 0 based indexing)
52089e99939fSJunchao Zhang .vb
52098a0b0e6bSVictor Minden         1 0 0
52108a0b0e6bSVictor Minden         2 0 3
52118a0b0e6bSVictor Minden         4 5 6
52128a0b0e6bSVictor Minden 
52138a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
52148a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
52158a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
52169e99939fSJunchao Zhang .ve
5217fe59aa6dSJacob Faibussowitsch 
52182ef1f0ffSBarry Smith   Note:
5219d7547e51SJunchao Zhang   Instead of using this function, users should also consider `MatSetPreallocationCOO()` and `MatSetValuesCOO()`, which allow repeated or remote entries,
5220d7547e51SJunchao Zhang   and are particularly useful in iterative applications.
52218a0b0e6bSVictor Minden 
52221cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateSeqAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()`, `MatSetValuesCOO()`, `MatSetPreallocationCOO()`
52238a0b0e6bSVictor Minden @*/
5224ce78bad3SBarry Smith PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt i[], PetscInt j[], PetscScalar a[], Mat *mat, PetscCount nz, PetscBool idx)
5225d71ae5a4SJacob Faibussowitsch {
5226d021a1c5SVictor Minden   PetscInt ii, *nnz, one = 1, row, col;
52278a0b0e6bSVictor Minden 
52288a0b0e6bSVictor Minden   PetscFunctionBegin;
52299566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(m, &nnz));
5230ad540459SPierre Jolivet   for (ii = 0; ii < nz; ii++) nnz[i[ii] - !!idx] += 1;
52319566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, mat));
52329566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mat, m, n, m, n));
52339566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mat, MATSEQAIJ));
52349566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat, 0, nnz));
52351230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
52361230e6d1SVictor Minden     if (idx) {
52371230e6d1SVictor Minden       row = i[ii] - 1;
52381230e6d1SVictor Minden       col = j[ii] - 1;
52391230e6d1SVictor Minden     } else {
52401230e6d1SVictor Minden       row = i[ii];
52411230e6d1SVictor Minden       col = j[ii];
52428a0b0e6bSVictor Minden     }
52439566063dSJacob Faibussowitsch     PetscCall(MatSetValues(*mat, one, &row, one, &col, &a[ii], ADD_VALUES));
52448a0b0e6bSVictor Minden   }
52459566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY));
52469566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY));
52479566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
52483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52498a0b0e6bSVictor Minden }
525036db0b34SBarry Smith 
5251d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
5252d71ae5a4SJacob Faibussowitsch {
52539c8f2541SHong Zhang   PetscFunctionBegin;
52549566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm, inmat, n, scall, outmat));
52553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52569c8f2541SHong Zhang }
52579c8f2541SHong Zhang 
525881824310SBarry Smith /*
525953dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
526053dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
526153dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
526253dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
526353dd7562SDmitry Karpeev  */
5264d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C, IS rowemb, IS colemb, MatStructure pattern, Mat B)
5265d71ae5a4SJacob Faibussowitsch {
526653dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
526753dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
526853dd7562SDmitry Karpeev   PetscBool       seqaij;
526953dd7562SDmitry Karpeev   PetscInt        m, n, *nz, i, j, count;
527053dd7562SDmitry Karpeev   PetscScalar     v;
527153dd7562SDmitry Karpeev   const PetscInt *rowindices, *colindices;
527253dd7562SDmitry Karpeev 
527353dd7562SDmitry Karpeev   PetscFunctionBegin;
52743ba16761SJacob Faibussowitsch   if (!B) PetscFunctionReturn(PETSC_SUCCESS);
527553dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
52769566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)B, MATSEQAIJ, &seqaij));
527728b400f6SJacob Faibussowitsch   PetscCheck(seqaij, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is of wrong type");
527853dd7562SDmitry Karpeev   if (rowemb) {
52799566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(rowemb, &m));
528008401ef6SPierre 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);
528153dd7562SDmitry Karpeev   } else {
528208401ef6SPierre Jolivet     PetscCheck(C->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is row-incompatible with the target matrix");
528353dd7562SDmitry Karpeev   }
528453dd7562SDmitry Karpeev   if (colemb) {
52859566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(colemb, &n));
528608401ef6SPierre 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);
528753dd7562SDmitry Karpeev   } else {
528808401ef6SPierre Jolivet     PetscCheck(C->cmap->n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Input matrix is col-incompatible with the target matrix");
528953dd7562SDmitry Karpeev   }
529053dd7562SDmitry Karpeev 
5291f4f49eeaSPierre Jolivet   Baij = (Mat_SeqAIJ *)B->data;
529253dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
52939566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(B->rmap->n, &nz));
5294ad540459SPierre Jolivet     for (i = 0; i < B->rmap->n; i++) nz[i] = Baij->i[i + 1] - Baij->i[i];
52959566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(C, 0, nz));
52969566063dSJacob Faibussowitsch     PetscCall(PetscFree(nz));
529753dd7562SDmitry Karpeev   }
529848a46eb9SPierre Jolivet   if (pattern == SUBSET_NONZERO_PATTERN) PetscCall(MatZeroEntries(C));
529953dd7562SDmitry Karpeev   count      = 0;
530053dd7562SDmitry Karpeev   rowindices = NULL;
530153dd7562SDmitry Karpeev   colindices = NULL;
530248a46eb9SPierre Jolivet   if (rowemb) PetscCall(ISGetIndices(rowemb, &rowindices));
530348a46eb9SPierre Jolivet   if (colemb) PetscCall(ISGetIndices(colemb, &colindices));
530453dd7562SDmitry Karpeev   for (i = 0; i < B->rmap->n; i++) {
530553dd7562SDmitry Karpeev     PetscInt row;
530653dd7562SDmitry Karpeev     row = i;
530753dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
530853dd7562SDmitry Karpeev     for (j = Baij->i[i]; j < Baij->i[i + 1]; j++) {
530953dd7562SDmitry Karpeev       PetscInt col;
531053dd7562SDmitry Karpeev       col = Baij->j[count];
531153dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
531253dd7562SDmitry Karpeev       v = Baij->a[count];
53139566063dSJacob Faibussowitsch       PetscCall(MatSetValues(C, 1, &row, 1, &col, &v, INSERT_VALUES));
531453dd7562SDmitry Karpeev       ++count;
531553dd7562SDmitry Karpeev     }
531653dd7562SDmitry Karpeev   }
531753dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
531853dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
531953dd7562SDmitry Karpeev   C->preallocated  = PETSC_TRUE;
532053dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
532153dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
53223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
532353dd7562SDmitry Karpeev }
532453dd7562SDmitry Karpeev 
532558c11ad4SPierre Jolivet PetscErrorCode MatEliminateZeros_SeqAIJ(Mat A, PetscBool keep)
5326dec0b466SHong Zhang {
5327dec0b466SHong Zhang   Mat_SeqAIJ *a  = (Mat_SeqAIJ *)A->data;
5328dec0b466SHong Zhang   MatScalar  *aa = a->a;
5329dec0b466SHong Zhang   PetscInt    m = A->rmap->n, fshift = 0, fshift_prev = 0, i, k;
5330dec0b466SHong Zhang   PetscInt   *ailen = a->ilen, *imax = a->imax, *ai = a->i, *aj = a->j, rmax = 0;
5331dec0b466SHong Zhang 
5332dec0b466SHong Zhang   PetscFunctionBegin;
5333dec0b466SHong Zhang   PetscCheck(A->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot eliminate zeros for unassembled matrix");
5334dec0b466SHong Zhang   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
5335dec0b466SHong Zhang   for (i = 1; i <= m; i++) {
5336dec0b466SHong Zhang     /* move each nonzero entry back by the amount of zero slots (fshift) before it*/
5337dec0b466SHong Zhang     for (k = ai[i - 1]; k < ai[i]; k++) {
533858c11ad4SPierre Jolivet       if (aa[k] == 0 && (aj[k] != i - 1 || !keep)) fshift++;
5339dec0b466SHong Zhang       else {
5340dec0b466SHong Zhang         if (aa[k] == 0 && aj[k] == i - 1) PetscCall(PetscInfo(A, "Keep the diagonal zero at row %" PetscInt_FMT "\n", i - 1));
5341dec0b466SHong Zhang         aa[k - fshift] = aa[k];
5342dec0b466SHong Zhang         aj[k - fshift] = aj[k];
5343dec0b466SHong Zhang       }
5344dec0b466SHong Zhang     }
5345dec0b466SHong Zhang     ai[i - 1] -= fshift_prev; // safe to update ai[i-1] now since it will not be used in the next iteration
5346dec0b466SHong Zhang     fshift_prev = fshift;
5347dec0b466SHong Zhang     /* reset ilen and imax for each row */
5348dec0b466SHong Zhang     ailen[i - 1] = imax[i - 1] = ai[i] - fshift - ai[i - 1];
5349dec0b466SHong Zhang     a->nonzerorowcnt += ((ai[i] - fshift - ai[i - 1]) > 0);
5350dec0b466SHong Zhang     rmax = PetscMax(rmax, ailen[i - 1]);
5351dec0b466SHong Zhang   }
5352312eded4SPierre Jolivet   if (fshift) {
5353dec0b466SHong Zhang     if (m) {
5354dec0b466SHong Zhang       ai[m] -= fshift;
5355dec0b466SHong Zhang       a->nz = ai[m];
5356dec0b466SHong Zhang     }
5357dec0b466SHong Zhang     PetscCall(PetscInfo(A, "Matrix size: %" PetscInt_FMT " X %" PetscInt_FMT "; zeros eliminated: %" PetscInt_FMT "; nonzeros left: %" PetscInt_FMT "\n", m, A->cmap->n, fshift, a->nz));
5358312eded4SPierre Jolivet     A->nonzerostate++;
5359dec0b466SHong Zhang     A->info.nz_unneeded += (PetscReal)fshift;
5360dec0b466SHong Zhang     a->rmax = rmax;
5361dec0b466SHong Zhang     if (a->inode.use && a->inode.checked) PetscCall(MatSeqAIJCheckInode(A));
5362dec0b466SHong Zhang     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
5363dec0b466SHong Zhang     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
5364312eded4SPierre Jolivet   }
53653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5366dec0b466SHong Zhang }
5367dec0b466SHong Zhang 
53684099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
53694099cc6bSBarry Smith 
5370cc4c1da9SBarry Smith /*@
537111a5261eSBarry Smith   MatSeqAIJSetType - Converts a `MATSEQAIJ` matrix to a subtype
53724099cc6bSBarry Smith 
5373c3339decSBarry Smith   Collective
53744099cc6bSBarry Smith 
53754099cc6bSBarry Smith   Input Parameters:
53764099cc6bSBarry Smith + mat    - the matrix object
53774099cc6bSBarry Smith - matype - matrix type
53784099cc6bSBarry Smith 
53794099cc6bSBarry Smith   Options Database Key:
53804e187271SRichard Tran Mills . -mat_seqaij_type  <method> - for example seqaijcrl
53814099cc6bSBarry Smith 
53824099cc6bSBarry Smith   Level: intermediate
53834099cc6bSBarry Smith 
5384fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`
53854099cc6bSBarry Smith @*/
5386d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJSetType(Mat mat, MatType matype)
5387d71ae5a4SJacob Faibussowitsch {
53884099cc6bSBarry Smith   PetscBool sametype;
53895f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(Mat, MatType, MatReuse, Mat *);
53904099cc6bSBarry Smith 
53914099cc6bSBarry Smith   PetscFunctionBegin;
53924099cc6bSBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
53939566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)mat, matype, &sametype));
53943ba16761SJacob Faibussowitsch   if (sametype) PetscFunctionReturn(PETSC_SUCCESS);
53954099cc6bSBarry Smith 
53969566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(MatSeqAIJList, matype, &r));
53976adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Mat type given: %s", matype);
53989566063dSJacob Faibussowitsch   PetscCall((*r)(mat, matype, MAT_INPLACE_MATRIX, &mat));
53993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54004099cc6bSBarry Smith }
54014099cc6bSBarry Smith 
54024099cc6bSBarry Smith /*@C
540311a5261eSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential `MATSEQAIJ` matrices
54044099cc6bSBarry Smith 
5405cc4c1da9SBarry Smith   Not Collective, No Fortran Support
54064099cc6bSBarry Smith 
54074099cc6bSBarry Smith   Input Parameters:
5408fe59aa6dSJacob Faibussowitsch + sname    - name of a new user-defined matrix type, for example `MATSEQAIJCRL`
54094099cc6bSBarry Smith - function - routine to convert to subtype
54104099cc6bSBarry Smith 
54112ef1f0ffSBarry Smith   Level: advanced
54122ef1f0ffSBarry Smith 
54134099cc6bSBarry Smith   Notes:
541411a5261eSBarry Smith   `MatSeqAIJRegister()` may be called multiple times to add several user-defined solvers.
54154099cc6bSBarry Smith 
54164099cc6bSBarry Smith   Then, your matrix can be chosen with the procedural interface at runtime via the option
5417b44f4de4SBarry Smith .vb
5418b44f4de4SBarry Smith   -mat_seqaij_type my_mat
5419b44f4de4SBarry Smith .ve
54204099cc6bSBarry Smith 
54211cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRegisterAll()`
54224099cc6bSBarry Smith @*/
5423d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJRegister(const char sname[], PetscErrorCode (*function)(Mat, MatType, MatReuse, Mat *))
5424d71ae5a4SJacob Faibussowitsch {
54254099cc6bSBarry Smith   PetscFunctionBegin;
54269566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
54279566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&MatSeqAIJList, sname, function));
54283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54294099cc6bSBarry Smith }
54304099cc6bSBarry Smith 
54314099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
54324099cc6bSBarry Smith 
54334099cc6bSBarry Smith /*@C
543411a5261eSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of `MATSSEQAIJ`
54354099cc6bSBarry Smith 
54364099cc6bSBarry Smith   Not Collective
54374099cc6bSBarry Smith 
54384099cc6bSBarry Smith   Level: advanced
54394099cc6bSBarry Smith 
54402ef1f0ffSBarry Smith   Note:
54412ef1f0ffSBarry Smith   This registers the versions of `MATSEQAIJ` for GPUs
54422ef1f0ffSBarry Smith 
54431cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatRegisterAll()`, `MatSeqAIJRegister()`
54444099cc6bSBarry Smith @*/
5445d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJRegisterAll(void)
5446d71ae5a4SJacob Faibussowitsch {
54474099cc6bSBarry Smith   PetscFunctionBegin;
54483ba16761SJacob Faibussowitsch   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
54494099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
54504099cc6bSBarry Smith 
54519566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJCRL, MatConvert_SeqAIJ_SeqAIJCRL));
54529566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJPERM, MatConvert_SeqAIJ_SeqAIJPERM));
54539566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJSELL, MatConvert_SeqAIJ_SeqAIJSELL));
54549779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
54559566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJMKL, MatConvert_SeqAIJ_SeqAIJMKL));
5456485f9817SRichard Tran Mills #endif
54575063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA)
54589566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE));
54595063d097SStefano Zampini #endif
5460d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_HIP)
5461d5e393b6SSuyash Tandon   PetscCall(MatSeqAIJRegister(MATSEQAIJHIPSPARSE, MatConvert_SeqAIJ_SeqAIJHIPSPARSE));
5462d5e393b6SSuyash Tandon #endif
54635063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
54649566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJKOKKOS, MatConvert_SeqAIJ_SeqAIJKokkos));
54655063d097SStefano Zampini #endif
54664099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
54679566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL));
54684099cc6bSBarry Smith #endif
54693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54704099cc6bSBarry Smith }
547153dd7562SDmitry Karpeev 
547253dd7562SDmitry Karpeev /*
547381824310SBarry Smith     Special version for direct calls from Fortran
547481824310SBarry Smith */
547581824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
547681824310SBarry Smith   #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
547781824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
547881824310SBarry Smith   #define matsetvaluesseqaij_ matsetvaluesseqaij
547981824310SBarry Smith #endif
548081824310SBarry Smith 
548181824310SBarry Smith /* Change these macros so can be used in void function */
548298921bdaSJacob Faibussowitsch 
548398921bdaSJacob Faibussowitsch /* Change these macros so can be used in void function */
54849566063dSJacob Faibussowitsch /* Identical to PetscCallVoid, except it assigns to *_ierr */
54859566063dSJacob Faibussowitsch #undef PetscCall
54869371c9d4SSatish Balay #define PetscCall(...) \
54879371c9d4SSatish Balay   do { \
54885f80ce2aSJacob Faibussowitsch     PetscErrorCode ierr_msv_mpiaij = __VA_ARGS__; \
548998921bdaSJacob Faibussowitsch     if (PetscUnlikely(ierr_msv_mpiaij)) { \
549098921bdaSJacob Faibussowitsch       *_ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr_msv_mpiaij, PETSC_ERROR_REPEAT, " "); \
549198921bdaSJacob Faibussowitsch       return; \
549298921bdaSJacob Faibussowitsch     } \
549398921bdaSJacob Faibussowitsch   } while (0)
549498921bdaSJacob Faibussowitsch 
549598921bdaSJacob Faibussowitsch #undef SETERRQ
54969371c9d4SSatish Balay #define SETERRQ(comm, ierr, ...) \
54979371c9d4SSatish Balay   do { \
549898921bdaSJacob Faibussowitsch     *_ierr = PetscError(comm, __LINE__, PETSC_FUNCTION_NAME, __FILE__, ierr, PETSC_ERROR_INITIAL, __VA_ARGS__); \
549998921bdaSJacob Faibussowitsch     return; \
550098921bdaSJacob Faibussowitsch   } while (0)
550181824310SBarry Smith 
5502d71ae5a4SJacob Faibussowitsch PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA, PetscInt *mm, const PetscInt im[], PetscInt *nn, const PetscInt in[], const PetscScalar v[], InsertMode *isis, PetscErrorCode *_ierr)
5503d71ae5a4SJacob Faibussowitsch {
550481824310SBarry Smith   Mat         A = *AA;
550581824310SBarry Smith   PetscInt    m = *mm, n = *nn;
550681824310SBarry Smith   InsertMode  is = *isis;
550781824310SBarry Smith   Mat_SeqAIJ *a  = (Mat_SeqAIJ *)A->data;
550881824310SBarry Smith   PetscInt   *rp, k, low, high, t, ii, row, nrow, i, col, l, rmax, N;
550981824310SBarry Smith   PetscInt   *imax, *ai, *ailen;
551081824310SBarry Smith   PetscInt   *aj, nonew = a->nonew, lastcol = -1;
551154f21887SBarry Smith   MatScalar  *ap, value, *aa;
5512ace3abfcSBarry Smith   PetscBool   ignorezeroentries = a->ignorezeroentries;
5513ace3abfcSBarry Smith   PetscBool   roworiented       = a->roworiented;
551481824310SBarry Smith 
551581824310SBarry Smith   PetscFunctionBegin;
55164994cf47SJed Brown   MatCheckPreallocated(A, 1);
551781824310SBarry Smith   imax  = a->imax;
551881824310SBarry Smith   ai    = a->i;
551981824310SBarry Smith   ailen = a->ilen;
552081824310SBarry Smith   aj    = a->j;
552181824310SBarry Smith   aa    = a->a;
552281824310SBarry Smith 
552381824310SBarry Smith   for (k = 0; k < m; k++) { /* loop over added rows */
552481824310SBarry Smith     row = im[k];
552581824310SBarry Smith     if (row < 0) continue;
55265f80ce2aSJacob Faibussowitsch     PetscCheck(row < A->rmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Row too large");
55279371c9d4SSatish Balay     rp   = aj + ai[row];
55289371c9d4SSatish Balay     ap   = aa + ai[row];
55299371c9d4SSatish Balay     rmax = imax[row];
55309371c9d4SSatish Balay     nrow = ailen[row];
553181824310SBarry Smith     low  = 0;
553281824310SBarry Smith     high = nrow;
553381824310SBarry Smith     for (l = 0; l < n; l++) { /* loop over added columns */
553481824310SBarry Smith       if (in[l] < 0) continue;
55355f80ce2aSJacob Faibussowitsch       PetscCheck(in[l] < A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Column too large");
553681824310SBarry Smith       col = in[l];
55372205254eSKarl Rupp       if (roworiented) value = v[l + k * n];
55382205254eSKarl Rupp       else value = v[k + l * m];
55392205254eSKarl Rupp 
554081824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
554181824310SBarry Smith 
55422205254eSKarl Rupp       if (col <= lastcol) low = 0;
55432205254eSKarl Rupp       else high = nrow;
554481824310SBarry Smith       lastcol = col;
554581824310SBarry Smith       while (high - low > 5) {
554681824310SBarry Smith         t = (low + high) / 2;
554781824310SBarry Smith         if (rp[t] > col) high = t;
554881824310SBarry Smith         else low = t;
554981824310SBarry Smith       }
555081824310SBarry Smith       for (i = low; i < high; i++) {
555181824310SBarry Smith         if (rp[i] > col) break;
555281824310SBarry Smith         if (rp[i] == col) {
555381824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
555481824310SBarry Smith           else ap[i] = value;
555581824310SBarry Smith           goto noinsert;
555681824310SBarry Smith         }
555781824310SBarry Smith       }
555881824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
555981824310SBarry Smith       if (nonew == 1) goto noinsert;
55605f80ce2aSJacob Faibussowitsch       PetscCheck(nonew != -1, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero in the matrix");
5561fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A, A->rmap->n, 1, nrow, row, col, rmax, aa, ai, aj, rp, ap, imax, nonew, MatScalar);
55629371c9d4SSatish Balay       N = nrow++ - 1;
55639371c9d4SSatish Balay       a->nz++;
55649371c9d4SSatish Balay       high++;
556581824310SBarry Smith       /* shift up all the later entries in this row */
556681824310SBarry Smith       for (ii = N; ii >= i; ii--) {
556781824310SBarry Smith         rp[ii + 1] = rp[ii];
556881824310SBarry Smith         ap[ii + 1] = ap[ii];
556981824310SBarry Smith       }
557081824310SBarry Smith       rp[i] = col;
557181824310SBarry Smith       ap[i] = value;
557281824310SBarry Smith     noinsert:;
557381824310SBarry Smith       low = i + 1;
557481824310SBarry Smith     }
557581824310SBarry Smith     ailen[row] = nrow;
557681824310SBarry Smith   }
557781824310SBarry Smith   PetscFunctionReturnVoid();
557881824310SBarry Smith }
557998921bdaSJacob Faibussowitsch /* Undefining these here since they were redefined from their original definition above! No
558098921bdaSJacob Faibussowitsch  * other PETSc functions should be defined past this point, as it is impossible to recover the
558198921bdaSJacob Faibussowitsch  * original definitions */
55829566063dSJacob Faibussowitsch #undef PetscCall
558398921bdaSJacob Faibussowitsch #undef SETERRQ
5584