xref: /petsc/src/mat/impls/aij/seq/aij.c (revision c2e3fba1fe1cda7e6350bbca19c4ed35ce95940a)
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 
114099cc6bSBarry Smith PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A)
124099cc6bSBarry Smith {
134099cc6bSBarry Smith   PetscBool            flg;
144099cc6bSBarry Smith   char                 type[256];
154099cc6bSBarry Smith 
164099cc6bSBarry Smith   PetscFunctionBegin;
17d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)A);
189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-mat_seqaij_type","Matrix SeqAIJ type","MatSeqAIJSetType",MatSeqAIJList,"seqaij",type,256,&flg));
199566063dSJacob Faibussowitsch   if (flg) PetscCall(MatSeqAIJSetType(A,type));
20d0609cedSBarry Smith   PetscOptionsEnd();
214099cc6bSBarry Smith   PetscFunctionReturn(0);
224099cc6bSBarry Smith }
234099cc6bSBarry Smith 
24857cbf51SRichard Tran Mills PetscErrorCode MatGetColumnReductions_SeqAIJ(Mat A,PetscInt type,PetscReal *reductions)
250716a85fSBarry Smith {
260716a85fSBarry Smith   PetscInt       i,m,n;
270716a85fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
280716a85fSBarry Smith 
290716a85fSBarry Smith   PetscFunctionBegin;
309566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,&m,&n));
319566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(reductions,n));
320716a85fSBarry Smith   if (type == NORM_2) {
330716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
34a873a8cdSSam Reynolds       reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]);
350716a85fSBarry Smith     }
360716a85fSBarry Smith   } else if (type == NORM_1) {
370716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
38a873a8cdSSam Reynolds       reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]);
390716a85fSBarry Smith     }
400716a85fSBarry Smith   } else if (type == NORM_INFINITY) {
410716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
42a873a8cdSSam Reynolds       reductions[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),reductions[aij->j[i]]);
430716a85fSBarry Smith     }
44857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
45a873a8cdSSam Reynolds     for (i=0; i<aij->i[m]; i++) {
46857cbf51SRichard Tran Mills       reductions[aij->j[i]] += PetscRealPart(aij->a[i]);
47a873a8cdSSam Reynolds     }
48857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
49857cbf51SRichard Tran Mills     for (i=0; i<aij->i[m]; i++) {
50857cbf51SRichard Tran Mills       reductions[aij->j[i]] += PetscImaginaryPart(aij->a[i]);
51857cbf51SRichard Tran Mills     }
52857cbf51SRichard Tran Mills   } else SETERRQ(PETSC_COMM_SELF,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   }
590716a85fSBarry Smith   PetscFunctionReturn(0);
600716a85fSBarry Smith }
610716a85fSBarry Smith 
623a062f41SBarry Smith PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A,IS *is)
633a062f41SBarry Smith {
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++) {
713a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
723a062f41SBarry Smith       cnt++;
733a062f41SBarry Smith     }
743a062f41SBarry Smith   }
759566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(cnt,&rows));
763a062f41SBarry Smith   cnt  = 0;
773a062f41SBarry Smith   for (i=0; i<m; i++) {
783a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
793a062f41SBarry Smith       rows[cnt] = i;
803a062f41SBarry Smith       cnt++;
813a062f41SBarry Smith     }
823a062f41SBarry Smith   }
839566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,is));
843a062f41SBarry Smith   PetscFunctionReturn(0);
853a062f41SBarry Smith }
863a062f41SBarry Smith 
87f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A,PetscInt *nrows,PetscInt **zrows)
886ce1633cSBarry Smith {
896ce1633cSBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
90fff043a9SJunchao Zhang   const MatScalar *aa;
916ce1633cSBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0;
92b2db7409Sstefano_zampini   const PetscInt  *ii = a->i,*jj = a->j,*diag;
936ce1633cSBarry Smith   PetscInt        *rows;
946ce1633cSBarry Smith 
956ce1633cSBarry Smith   PetscFunctionBegin;
969566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&aa));
979566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqAIJ(A));
986ce1633cSBarry Smith   diag = a->diag;
996ce1633cSBarry Smith   for (i=0; i<m; i++) {
100b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1016ce1633cSBarry Smith       cnt++;
1026ce1633cSBarry Smith     }
1036ce1633cSBarry Smith   }
1049566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(cnt,&rows));
1056ce1633cSBarry Smith   cnt  = 0;
1066ce1633cSBarry Smith   for (i=0; i<m; i++) {
107b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1086ce1633cSBarry Smith       rows[cnt++] = i;
1096ce1633cSBarry Smith     }
1106ce1633cSBarry Smith   }
111f1f41ecbSJed Brown   *nrows = cnt;
112f1f41ecbSJed Brown   *zrows = rows;
1139566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
114f1f41ecbSJed Brown   PetscFunctionReturn(0);
115f1f41ecbSJed Brown }
116f1f41ecbSJed Brown 
117f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
118f1f41ecbSJed Brown {
119f1f41ecbSJed Brown   PetscInt       nrows,*rows;
120f1f41ecbSJed Brown 
121f1f41ecbSJed Brown   PetscFunctionBegin;
1220298fd71SBarry Smith   *zrows = NULL;
1239566063dSJacob Faibussowitsch   PetscCall(MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows));
1249566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A),nrows,rows,PETSC_OWN_POINTER,zrows));
1256ce1633cSBarry Smith   PetscFunctionReturn(0);
1266ce1633cSBarry Smith }
1276ce1633cSBarry Smith 
128b3a44c85SBarry Smith PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows)
129b3a44c85SBarry Smith {
130b3a44c85SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
131b3a44c85SBarry Smith   const MatScalar *aa;
132b3a44c85SBarry Smith   PetscInt        m=A->rmap->n,cnt = 0;
133b3a44c85SBarry Smith   const PetscInt  *ii;
134b3a44c85SBarry Smith   PetscInt        n,i,j,*rows;
135b3a44c85SBarry Smith 
136b3a44c85SBarry Smith   PetscFunctionBegin;
1379566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&aa));
138f4259b30SLisandro Dalcin   *keptrows = NULL;
139b3a44c85SBarry Smith   ii        = a->i;
140b3a44c85SBarry Smith   for (i=0; i<m; i++) {
141b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
142b3a44c85SBarry Smith     if (!n) {
143b3a44c85SBarry Smith       cnt++;
144b3a44c85SBarry Smith       goto ok1;
145b3a44c85SBarry Smith     }
1462e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
147b3a44c85SBarry Smith       if (aa[j] != 0.0) goto ok1;
148b3a44c85SBarry Smith     }
149b3a44c85SBarry Smith     cnt++;
150b3a44c85SBarry Smith ok1:;
151b3a44c85SBarry Smith   }
1522e5835c6SStefano Zampini   if (!cnt) {
1539566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
1542e5835c6SStefano Zampini     PetscFunctionReturn(0);
1552e5835c6SStefano Zampini   }
1569566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(A->rmap->n-cnt,&rows));
157b3a44c85SBarry Smith   cnt  = 0;
158b3a44c85SBarry Smith   for (i=0; i<m; i++) {
159b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
160b3a44c85SBarry Smith     if (!n) continue;
1612e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
162b3a44c85SBarry Smith       if (aa[j] != 0.0) {
163b3a44c85SBarry Smith         rows[cnt++] = i;
164b3a44c85SBarry Smith         break;
165b3a44c85SBarry Smith       }
166b3a44c85SBarry Smith     }
167b3a44c85SBarry Smith   }
1689566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
1699566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows));
170b3a44c85SBarry Smith   PetscFunctionReturn(0);
171b3a44c85SBarry Smith }
172b3a44c85SBarry Smith 
1737087cfbeSBarry Smith PetscErrorCode  MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
17479299369SBarry Smith {
17579299369SBarry Smith   Mat_SeqAIJ        *aij = (Mat_SeqAIJ*) Y->data;
17699e65526SBarry Smith   PetscInt          i,m = Y->rmap->n;
17799e65526SBarry Smith   const PetscInt    *diag;
1782e5835c6SStefano Zampini   MatScalar         *aa;
17999e65526SBarry Smith   const PetscScalar *v;
180ace3abfcSBarry Smith   PetscBool         missing;
18179299369SBarry Smith 
18279299369SBarry Smith   PetscFunctionBegin;
18309f38230SBarry Smith   if (Y->assembled) {
1849566063dSJacob Faibussowitsch     PetscCall(MatMissingDiagonal_SeqAIJ(Y,&missing,NULL));
18509f38230SBarry Smith     if (!missing) {
18679299369SBarry Smith       diag = aij->diag;
1879566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(D,&v));
1889566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(Y,&aa));
18979299369SBarry Smith       if (is == INSERT_VALUES) {
19079299369SBarry Smith         for (i=0; i<m; i++) {
19179299369SBarry Smith           aa[diag[i]] = v[i];
19279299369SBarry Smith         }
19379299369SBarry Smith       } else {
19479299369SBarry Smith         for (i=0; i<m; i++) {
19579299369SBarry Smith           aa[diag[i]] += v[i];
19679299369SBarry Smith         }
19779299369SBarry Smith       }
1989566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJRestoreArray(Y,&aa));
1999566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(D,&v));
20079299369SBarry Smith       PetscFunctionReturn(0);
20179299369SBarry Smith     }
2029566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJInvalidateDiagonal(Y));
20309f38230SBarry Smith   }
2049566063dSJacob Faibussowitsch   PetscCall(MatDiagonalSet_Default(Y,D,is));
20509f38230SBarry Smith   PetscFunctionReturn(0);
20609f38230SBarry Smith }
20779299369SBarry Smith 
2081a83f524SJed Brown PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
20917ab2063SBarry Smith {
210416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
21197f1f81fSBarry Smith   PetscInt       i,ishift;
21217ab2063SBarry Smith 
2133a40ed3dSBarry Smith   PetscFunctionBegin;
214d0f46423SBarry Smith   *m = A->rmap->n;
2153a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
216bfeeae90SHong Zhang   ishift = 0;
21753e63a63SBarry Smith   if (symmetric && !A->structurally_symmetric) {
2189566063dSJacob Faibussowitsch     PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja));
219bfeeae90SHong Zhang   } else if (oshift == 1) {
2201a83f524SJed Brown     PetscInt *tia;
221d0f46423SBarry Smith     PetscInt nz = a->i[A->rmap->n];
2223b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
2239566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n+1,&tia));
2241a83f524SJed Brown     for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1;
2251a83f524SJed Brown     *ia = tia;
226ecc77c7aSBarry Smith     if (ja) {
2271a83f524SJed Brown       PetscInt *tja;
2289566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz+1,&tja));
2291a83f524SJed Brown       for (i=0; i<nz; i++) tja[i] = a->j[i] + 1;
2301a83f524SJed Brown       *ja = tja;
231ecc77c7aSBarry Smith     }
2326945ee14SBarry Smith   } else {
233ecc77c7aSBarry Smith     *ia = a->i;
234ecc77c7aSBarry Smith     if (ja) *ja = a->j;
235a2ce50c7SBarry Smith   }
2363a40ed3dSBarry Smith   PetscFunctionReturn(0);
237a2744918SBarry Smith }
238a2744918SBarry Smith 
2391a83f524SJed Brown PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2406945ee14SBarry Smith {
2413a40ed3dSBarry Smith   PetscFunctionBegin;
2423a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
243bfeeae90SHong Zhang   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
2449566063dSJacob Faibussowitsch     PetscCall(PetscFree(*ia));
2459566063dSJacob Faibussowitsch     if (ja) PetscCall(PetscFree(*ja));
246bcd2baecSBarry Smith   }
2473a40ed3dSBarry Smith   PetscFunctionReturn(0);
24817ab2063SBarry Smith }
24917ab2063SBarry Smith 
2501a83f524SJed Brown PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2513b2fbd54SBarry Smith {
2523b2fbd54SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
253d0f46423SBarry Smith   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
25497f1f81fSBarry Smith   PetscInt       nz = a->i[m],row,*jj,mr,col;
2553b2fbd54SBarry Smith 
2563a40ed3dSBarry Smith   PetscFunctionBegin;
257899cda47SBarry Smith   *nn = n;
2583a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2593b2fbd54SBarry Smith   if (symmetric) {
2609566063dSJacob Faibussowitsch     PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja));
2613b2fbd54SBarry Smith   } else {
2629566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(n,&collengths));
2639566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n+1,&cia));
2649566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nz,&cja));
2653b2fbd54SBarry Smith     jj   = a->j;
2663b2fbd54SBarry Smith     for (i=0; i<nz; i++) {
267bfeeae90SHong Zhang       collengths[jj[i]]++;
2683b2fbd54SBarry Smith     }
2693b2fbd54SBarry Smith     cia[0] = oshift;
2703b2fbd54SBarry Smith     for (i=0; i<n; i++) {
2713b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
2723b2fbd54SBarry Smith     }
2739566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(collengths,n));
2743b2fbd54SBarry Smith     jj   = a->j;
275a93ec695SBarry Smith     for (row=0; row<m; row++) {
276a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
277a93ec695SBarry Smith       for (i=0; i<mr; i++) {
278bfeeae90SHong Zhang         col = *jj++;
2792205254eSKarl Rupp 
2803b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
2813b2fbd54SBarry Smith       }
2823b2fbd54SBarry Smith     }
2839566063dSJacob Faibussowitsch     PetscCall(PetscFree(collengths));
2843b2fbd54SBarry Smith     *ia  = cia; *ja = cja;
2853b2fbd54SBarry Smith   }
2863a40ed3dSBarry Smith   PetscFunctionReturn(0);
2873b2fbd54SBarry Smith }
2883b2fbd54SBarry Smith 
2891a83f524SJed Brown PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2903b2fbd54SBarry Smith {
2913a40ed3dSBarry Smith   PetscFunctionBegin;
2923a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2933b2fbd54SBarry Smith 
2949566063dSJacob Faibussowitsch   PetscCall(PetscFree(*ia));
2959566063dSJacob Faibussowitsch   PetscCall(PetscFree(*ja));
2963a40ed3dSBarry Smith   PetscFunctionReturn(0);
2973b2fbd54SBarry Smith }
2983b2fbd54SBarry Smith 
2997cee066cSHong Zhang /*
3007cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
3017cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
302040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
3037cee066cSHong Zhang */
3047cee066cSHong Zhang PetscErrorCode MatGetColumnIJ_SeqAIJ_Color(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool  *done)
3057cee066cSHong Zhang {
3067cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3077cee066cSHong Zhang   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
308071fcb05SBarry Smith   PetscInt       nz = a->i[m],row,mr,col,tmp;
3097cee066cSHong Zhang   PetscInt       *cspidx;
310071fcb05SBarry Smith   const PetscInt *jj;
3117cee066cSHong Zhang 
3127cee066cSHong Zhang   PetscFunctionBegin;
3137cee066cSHong Zhang   *nn = n;
3147cee066cSHong Zhang   if (!ia) PetscFunctionReturn(0);
315625f6d37SHong Zhang 
3169566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(n,&collengths));
3179566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n+1,&cia));
3189566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nz,&cja));
3199566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nz,&cspidx));
3207cee066cSHong Zhang   jj   = a->j;
3217cee066cSHong Zhang   for (i=0; i<nz; i++) {
3227cee066cSHong Zhang     collengths[jj[i]]++;
3237cee066cSHong Zhang   }
3247cee066cSHong Zhang   cia[0] = oshift;
3257cee066cSHong Zhang   for (i=0; i<n; i++) {
3267cee066cSHong Zhang     cia[i+1] = cia[i] + collengths[i];
3277cee066cSHong Zhang   }
3289566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(collengths,n));
3297cee066cSHong Zhang   jj   = a->j;
3307cee066cSHong Zhang   for (row=0; row<m; row++) {
3317cee066cSHong Zhang     mr = a->i[row+1] - a->i[row];
3327cee066cSHong Zhang     for (i=0; i<mr; i++) {
3337cee066cSHong Zhang       col         = *jj++;
334071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
335071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
336071fcb05SBarry Smith       cja[tmp]    = row + oshift;
3377cee066cSHong Zhang     }
3387cee066cSHong Zhang   }
3399566063dSJacob Faibussowitsch   PetscCall(PetscFree(collengths));
340071fcb05SBarry Smith   *ia    = cia;
341071fcb05SBarry Smith   *ja    = cja;
3427cee066cSHong Zhang   *spidx = cspidx;
3437cee066cSHong Zhang   PetscFunctionReturn(0);
3447cee066cSHong Zhang }
3457cee066cSHong Zhang 
3467cee066cSHong Zhang PetscErrorCode MatRestoreColumnIJ_SeqAIJ_Color(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool  *done)
3477cee066cSHong Zhang {
3487cee066cSHong Zhang   PetscFunctionBegin;
3499566063dSJacob Faibussowitsch   PetscCall(MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done));
3509566063dSJacob Faibussowitsch   PetscCall(PetscFree(*spidx));
3517cee066cSHong Zhang   PetscFunctionReturn(0);
3527cee066cSHong Zhang }
3537cee066cSHong Zhang 
35487d4246cSBarry Smith PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
35587d4246cSBarry Smith {
35687d4246cSBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
35787d4246cSBarry Smith   PetscInt       *ai = a->i;
358fff043a9SJunchao Zhang   PetscScalar    *aa;
35987d4246cSBarry Smith 
36087d4246cSBarry Smith   PetscFunctionBegin;
3619566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A,&aa));
3629566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aa+ai[row],v,ai[row+1]-ai[row]));
3639566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A,&aa));
36487d4246cSBarry Smith   PetscFunctionReturn(0);
36587d4246cSBarry Smith }
36687d4246cSBarry Smith 
367bd04181cSBarry Smith /*
368bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
369bd04181cSBarry Smith 
370bd04181cSBarry Smith       -   a single row of values is set with each call
371bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
372bd04181cSBarry Smith       -   the values are always added to the matrix, not set
373bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
374bd04181cSBarry Smith 
3751f763a69SBarry Smith      This does NOT assume the global column indices are sorted
376bd04181cSBarry Smith 
3771f763a69SBarry Smith */
378bd04181cSBarry Smith 
379af0996ceSBarry Smith #include <petsc/private/isimpl.h>
380189e4007SBarry Smith PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
381189e4007SBarry Smith {
382189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3831f763a69SBarry Smith   PetscInt       low,high,t,row,nrow,i,col,l;
3841f763a69SBarry Smith   const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j;
3851f763a69SBarry Smith   PetscInt       lastcol = -1;
386fff043a9SJunchao Zhang   MatScalar      *ap,value,*aa;
387189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices;
388189e4007SBarry Smith 
389fff043a9SJunchao Zhang   PetscFunctionBegin;
3909566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A,&aa));
391f38dd0b8SBarry Smith   row  = ridx[im[0]];
3921f763a69SBarry Smith   rp   = aj + ai[row];
3931f763a69SBarry Smith   ap   = aa + ai[row];
3941f763a69SBarry Smith   nrow = ailen[row];
395189e4007SBarry Smith   low  = 0;
396189e4007SBarry Smith   high = nrow;
397189e4007SBarry Smith   for (l=0; l<n; l++) { /* loop over added columns */
398189e4007SBarry Smith     col = cidx[in[l]];
399f38dd0b8SBarry Smith     value = v[l];
400189e4007SBarry Smith 
401189e4007SBarry Smith     if (col <= lastcol) low = 0;
402189e4007SBarry Smith     else high = nrow;
403189e4007SBarry Smith     lastcol = col;
404189e4007SBarry Smith     while (high-low > 5) {
405189e4007SBarry Smith       t = (low+high)/2;
406189e4007SBarry Smith       if (rp[t] > col) high = t;
407189e4007SBarry Smith       else low = t;
408189e4007SBarry Smith     }
409189e4007SBarry Smith     for (i=low; i<high; i++) {
410189e4007SBarry Smith       if (rp[i] == col) {
4111f763a69SBarry Smith         ap[i] += value;
412189e4007SBarry Smith         low = i + 1;
4131f763a69SBarry Smith         break;
414189e4007SBarry Smith       }
415189e4007SBarry Smith     }
416189e4007SBarry Smith   }
4179566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A,&aa));
418f38dd0b8SBarry Smith   return 0;
419189e4007SBarry Smith }
420189e4007SBarry Smith 
42197f1f81fSBarry Smith PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
42217ab2063SBarry Smith {
423416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
424e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
42597f1f81fSBarry Smith   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
426e2ee6c50SBarry Smith   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
427ce496241SStefano Zampini   MatScalar      *ap=NULL,value=0.0,*aa;
428ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
429ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
43017ab2063SBarry Smith 
4313a40ed3dSBarry Smith   PetscFunctionBegin;
4329566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A,&aa));
43317ab2063SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
434416022c9SBarry Smith     row = im[k];
4355ef9f2a5SBarry Smith     if (row < 0) continue;
4366bdcaf15SBarry 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);
437720833daSHong Zhang     rp   = aj + ai[row];
438876c6284SHong Zhang     if (!A->structure_only) ap = aa + ai[row];
43917ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
440416022c9SBarry Smith     low  = 0;
441c71e6ed7SBarry Smith     high = nrow;
44217ab2063SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
4435ef9f2a5SBarry Smith       if (in[l] < 0) continue;
4446bdcaf15SBarry 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);
445bfeeae90SHong Zhang       col = in[l];
446071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m];
447071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
44836db0b34SBarry Smith 
4492205254eSKarl Rupp       if (col <= lastcol) low = 0;
4502205254eSKarl Rupp       else high = nrow;
451e2ee6c50SBarry Smith       lastcol = col;
452416022c9SBarry Smith       while (high-low > 5) {
453416022c9SBarry Smith         t = (low+high)/2;
454416022c9SBarry Smith         if (rp[t] > col) high = t;
455416022c9SBarry Smith         else low = t;
45617ab2063SBarry Smith       }
457416022c9SBarry Smith       for (i=low; i<high; i++) {
45817ab2063SBarry Smith         if (rp[i] > col) break;
45917ab2063SBarry Smith         if (rp[i] == col) {
460876c6284SHong Zhang           if (!A->structure_only) {
4610c0d7e18SFande Kong             if (is == ADD_VALUES) {
4620c0d7e18SFande Kong               ap[i] += value;
4630c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
4640c0d7e18SFande Kong             }
46517ab2063SBarry Smith             else ap[i] = value;
466720833daSHong Zhang           }
467e44c0bd4SBarry Smith           low = i + 1;
46817ab2063SBarry Smith           goto noinsert;
46917ab2063SBarry Smith         }
47017ab2063SBarry Smith       }
471dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
472c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
47308401ef6SPierre 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);
474720833daSHong Zhang       if (A->structure_only) {
475876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar);
476720833daSHong Zhang       } else {
477fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
478720833daSHong Zhang       }
479c03d1d03SSatish Balay       N = nrow++ - 1; a->nz++; high++;
480416022c9SBarry Smith       /* shift up all the later entries in this row */
4819566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(rp+i+1,rp+i,N-i+1));
48217ab2063SBarry Smith       rp[i] = col;
483580bdb30SBarry Smith       if (!A->structure_only) {
4849566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(ap+i+1,ap+i,N-i+1));
485580bdb30SBarry Smith         ap[i] = value;
486580bdb30SBarry Smith       }
487416022c9SBarry Smith       low = i + 1;
488e56f5c9eSBarry Smith       A->nonzerostate++;
489e44c0bd4SBarry Smith noinsert:;
49017ab2063SBarry Smith     }
49117ab2063SBarry Smith     ailen[row] = nrow;
49217ab2063SBarry Smith   }
4939566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A,&aa));
4943a40ed3dSBarry Smith   PetscFunctionReturn(0);
49517ab2063SBarry Smith }
49617ab2063SBarry Smith 
49719b08ed1SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
49819b08ed1SBarry Smith {
49919b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
50019b08ed1SBarry Smith   PetscInt       *rp,k,row;
50119b08ed1SBarry Smith   PetscInt       *ai = a->i;
50219b08ed1SBarry Smith   PetscInt       *aj = a->j;
503fff043a9SJunchao Zhang   MatScalar      *aa,*ap;
50419b08ed1SBarry Smith 
50519b08ed1SBarry Smith   PetscFunctionBegin;
50628b400f6SJacob Faibussowitsch   PetscCheck(!A->was_assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call on assembled matrix.");
50708401ef6SPierre 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);
508fff043a9SJunchao Zhang 
5099566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A,&aa));
51019b08ed1SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
51119b08ed1SBarry Smith     row  = im[k];
51219b08ed1SBarry Smith     rp   = aj + ai[row];
51319b08ed1SBarry Smith     ap   = aa + ai[row];
51419b08ed1SBarry Smith 
5159566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(rp,in,n*sizeof(PetscInt)));
51619b08ed1SBarry Smith     if (!A->structure_only) {
51719b08ed1SBarry Smith       if (v) {
5189566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(ap,v,n*sizeof(PetscScalar)));
51919b08ed1SBarry Smith         v   += n;
52019b08ed1SBarry Smith       } else {
5219566063dSJacob Faibussowitsch         PetscCall(PetscMemzero(ap,n*sizeof(PetscScalar)));
52219b08ed1SBarry Smith       }
52319b08ed1SBarry Smith     }
52419b08ed1SBarry Smith     a->ilen[row] = n;
52519b08ed1SBarry Smith     a->imax[row] = n;
52619b08ed1SBarry Smith     a->i[row+1]  = a->i[row]+n;
52719b08ed1SBarry Smith     a->nz       += n;
52819b08ed1SBarry Smith   }
5299566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A,&aa));
53019b08ed1SBarry Smith   PetscFunctionReturn(0);
53119b08ed1SBarry Smith }
53219b08ed1SBarry Smith 
53319b08ed1SBarry Smith /*@
53419b08ed1SBarry Smith     MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix.
53519b08ed1SBarry Smith 
53619b08ed1SBarry Smith   Input Parameters:
53719b08ed1SBarry Smith +  A - the SeqAIJ matrix
53819b08ed1SBarry Smith -  nztotal - bound on the number of nonzeros
53919b08ed1SBarry Smith 
54019b08ed1SBarry Smith   Level: advanced
54119b08ed1SBarry Smith 
54219b08ed1SBarry Smith   Notes:
54319b08ed1SBarry 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.
54419b08ed1SBarry Smith     Simply call MatSetValues() after this call to provide the matrix entries in the usual manner. This matrix may be used
54519b08ed1SBarry Smith     as always with multiple matrix assemblies.
54619b08ed1SBarry Smith 
547db781477SPatrick Sanan .seealso: `MatSetOption()`, `MAT_SORTED_FULL`, `MatSetValues()`, `MatSeqAIJSetPreallocation()`
54819b08ed1SBarry Smith @*/
54919b08ed1SBarry Smith 
55019b08ed1SBarry Smith PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A,PetscInt nztotal)
55119b08ed1SBarry Smith {
55219b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
55319b08ed1SBarry Smith 
55419b08ed1SBarry Smith   PetscFunctionBegin;
5559566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
5569566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
55719b08ed1SBarry Smith   a->maxnz  = nztotal;
55819b08ed1SBarry Smith   if (!a->imax) {
5599566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n,&a->imax));
5609566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt)));
56119b08ed1SBarry Smith   }
56219b08ed1SBarry Smith   if (!a->ilen) {
5639566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n,&a->ilen));
5649566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt)));
56519b08ed1SBarry Smith   } else {
5669566063dSJacob Faibussowitsch     PetscCall(PetscMemzero(a->ilen,A->rmap->n*sizeof(PetscInt)));
56719b08ed1SBarry Smith   }
56819b08ed1SBarry Smith 
56919b08ed1SBarry Smith   /* allocate the matrix space */
57019b08ed1SBarry Smith   if (A->structure_only) {
5719566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nztotal,&a->j));
5729566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n+1,&a->i));
5739566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*sizeof(PetscInt)));
57419b08ed1SBarry Smith   } else {
5759566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(nztotal,&a->a,nztotal,&a->j,A->rmap->n+1,&a->i));
5769566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*(sizeof(PetscScalar)+sizeof(PetscInt))));
57719b08ed1SBarry Smith   }
57819b08ed1SBarry Smith   a->i[0] = 0;
57919b08ed1SBarry Smith   if (A->structure_only) {
58019b08ed1SBarry Smith     a->singlemalloc = PETSC_FALSE;
58119b08ed1SBarry Smith     a->free_a       = PETSC_FALSE;
58219b08ed1SBarry Smith   } else {
58319b08ed1SBarry Smith     a->singlemalloc = PETSC_TRUE;
58419b08ed1SBarry Smith     a->free_a       = PETSC_TRUE;
58519b08ed1SBarry Smith   }
58619b08ed1SBarry Smith   a->free_ij        = PETSC_TRUE;
58719b08ed1SBarry Smith   A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation;
58819b08ed1SBarry Smith   A->preallocated   = PETSC_TRUE;
58919b08ed1SBarry Smith   PetscFunctionReturn(0);
59019b08ed1SBarry Smith }
59119b08ed1SBarry Smith 
592071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
593071fcb05SBarry Smith {
594071fcb05SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
595071fcb05SBarry Smith   PetscInt       *rp,k,row;
596071fcb05SBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
597071fcb05SBarry Smith   PetscInt       *aj = a->j;
598fff043a9SJunchao Zhang   MatScalar      *aa,*ap;
599071fcb05SBarry Smith 
600071fcb05SBarry Smith   PetscFunctionBegin;
6019566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A,&aa));
602071fcb05SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
603071fcb05SBarry Smith     row  = im[k];
6046bdcaf15SBarry 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);
605071fcb05SBarry Smith     rp   = aj + ai[row];
606071fcb05SBarry Smith     ap   = aa + ai[row];
607071fcb05SBarry Smith     if (!A->was_assembled) {
6089566063dSJacob Faibussowitsch       PetscCall(PetscMemcpy(rp,in,n*sizeof(PetscInt)));
609071fcb05SBarry Smith     }
610071fcb05SBarry Smith     if (!A->structure_only) {
611071fcb05SBarry Smith       if (v) {
6129566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(ap,v,n*sizeof(PetscScalar)));
613071fcb05SBarry Smith         v   += n;
614071fcb05SBarry Smith       } else {
6159566063dSJacob Faibussowitsch         PetscCall(PetscMemzero(ap,n*sizeof(PetscScalar)));
616071fcb05SBarry Smith       }
617071fcb05SBarry Smith     }
618071fcb05SBarry Smith     ailen[row] = n;
619071fcb05SBarry Smith     a->nz      += n;
620071fcb05SBarry Smith   }
6219566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A,&aa));
622071fcb05SBarry Smith   PetscFunctionReturn(0);
623071fcb05SBarry Smith }
624071fcb05SBarry Smith 
625a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
6267eb43aa7SLois Curfman McInnes {
6277eb43aa7SLois Curfman McInnes   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
62897f1f81fSBarry Smith   PetscInt       *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
62997f1f81fSBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
630fff043a9SJunchao Zhang   MatScalar      *ap,*aa;
6317eb43aa7SLois Curfman McInnes 
6323a40ed3dSBarry Smith   PetscFunctionBegin;
6339566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A,&aa));
6347eb43aa7SLois Curfman McInnes   for (k=0; k<m; k++) { /* loop over rows */
6357eb43aa7SLois Curfman McInnes     row = im[k];
63654c59aa7SJacob Faibussowitsch     if (row < 0) {v += n; continue;} /* negative row */
63754c59aa7SJacob 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);
638bfeeae90SHong Zhang     rp   = aj + ai[row]; ap = aa + ai[row];
6397eb43aa7SLois Curfman McInnes     nrow = ailen[row];
6407eb43aa7SLois Curfman McInnes     for (l=0; l<n; l++) { /* loop over columns */
64154c59aa7SJacob Faibussowitsch       if (in[l] < 0) {v++; continue;} /* negative column */
64254c59aa7SJacob 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);
643bfeeae90SHong Zhang       col  = in[l];
6447eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
6457eb43aa7SLois Curfman McInnes       while (high-low > 5) {
6467eb43aa7SLois Curfman McInnes         t = (low+high)/2;
6477eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
6487eb43aa7SLois Curfman McInnes         else low = t;
6497eb43aa7SLois Curfman McInnes       }
6507eb43aa7SLois Curfman McInnes       for (i=low; i<high; i++) {
6517eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
6527eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
653b49de8d1SLois Curfman McInnes           *v++ = ap[i];
6547eb43aa7SLois Curfman McInnes           goto finished;
6557eb43aa7SLois Curfman McInnes         }
6567eb43aa7SLois Curfman McInnes       }
65797e567efSBarry Smith       *v++ = 0.0;
6587eb43aa7SLois Curfman McInnes finished:;
6597eb43aa7SLois Curfman McInnes     }
6607eb43aa7SLois Curfman McInnes   }
6619566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A,&aa));
6623a40ed3dSBarry Smith   PetscFunctionReturn(0);
6637eb43aa7SLois Curfman McInnes }
6647eb43aa7SLois Curfman McInnes 
6653ea6fe3dSLisandro Dalcin PetscErrorCode MatView_SeqAIJ_Binary(Mat mat,PetscViewer viewer)
66617ab2063SBarry Smith {
6673ea6fe3dSLisandro Dalcin   Mat_SeqAIJ        *A = (Mat_SeqAIJ*)mat->data;
668c898d852SStefano Zampini   const PetscScalar *av;
6693ea6fe3dSLisandro Dalcin   PetscInt          header[4],M,N,m,nz,i;
6703ea6fe3dSLisandro Dalcin   PetscInt          *rowlens;
67117ab2063SBarry Smith 
6723a40ed3dSBarry Smith   PetscFunctionBegin;
6739566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
6742205254eSKarl Rupp 
6753ea6fe3dSLisandro Dalcin   M  = mat->rmap->N;
6763ea6fe3dSLisandro Dalcin   N  = mat->cmap->N;
6773ea6fe3dSLisandro Dalcin   m  = mat->rmap->n;
6783ea6fe3dSLisandro Dalcin   nz = A->nz;
679416022c9SBarry Smith 
6803ea6fe3dSLisandro Dalcin   /* write matrix header */
6813ea6fe3dSLisandro Dalcin   header[0] = MAT_FILE_CLASSID;
6823ea6fe3dSLisandro Dalcin   header[1] = M; header[2] = N; header[3] = nz;
6839566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWrite(viewer,header,4,PETSC_INT));
684416022c9SBarry Smith 
6853ea6fe3dSLisandro Dalcin   /* fill in and store row lengths */
6869566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m,&rowlens));
6873ea6fe3dSLisandro Dalcin   for (i=0; i<m; i++) rowlens[i] = A->i[i+1] - A->i[i];
6889566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWrite(viewer,rowlens,m,PETSC_INT));
6899566063dSJacob Faibussowitsch   PetscCall(PetscFree(rowlens));
6903ea6fe3dSLisandro Dalcin   /* store column indices */
6919566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWrite(viewer,A->j,nz,PETSC_INT));
692416022c9SBarry Smith   /* store nonzero values */
6939566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(mat,&av));
6949566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWrite(viewer,av,nz,PETSC_SCALAR));
6959566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(mat,&av));
696b37d52dbSMark F. Adams 
6973ea6fe3dSLisandro Dalcin   /* write block size option to the viewer's .info file */
6989566063dSJacob Faibussowitsch   PetscCall(MatView_Binary_BlockSizes(mat,viewer));
6993a40ed3dSBarry Smith   PetscFunctionReturn(0);
70017ab2063SBarry Smith }
701416022c9SBarry Smith 
7027dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer)
7037dc0baabSHong Zhang {
7047dc0baabSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
7057dc0baabSHong Zhang   PetscInt       i,k,m=A->rmap->N;
7067dc0baabSHong Zhang 
7077dc0baabSHong Zhang   PetscFunctionBegin;
7089566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
7097dc0baabSHong Zhang   for (i=0; i<m; i++) {
7109566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i));
7117dc0baabSHong Zhang     for (k=a->i[i]; k<a->i[i+1]; k++) {
7129566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ") ",a->j[k]));
7137dc0baabSHong Zhang     }
7149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
7157dc0baabSHong Zhang   }
7169566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
7177dc0baabSHong Zhang   PetscFunctionReturn(0);
7187dc0baabSHong Zhang }
7197dc0baabSHong Zhang 
72009573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
721cd155464SBarry Smith 
722dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
723416022c9SBarry Smith {
724416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
725c898d852SStefano Zampini   const PetscScalar *av;
72660e0710aSBarry Smith   PetscInt          i,j,m = A->rmap->n;
727e060cb09SBarry Smith   const char        *name;
728f3ef73ceSBarry Smith   PetscViewerFormat format;
72917ab2063SBarry Smith 
7303a40ed3dSBarry Smith   PetscFunctionBegin;
7317dc0baabSHong Zhang   if (A->structure_only) {
7329566063dSJacob Faibussowitsch     PetscCall(MatView_SeqAIJ_ASCII_structonly(A,viewer));
7337dc0baabSHong Zhang     PetscFunctionReturn(0);
7347dc0baabSHong Zhang   }
73543e49210SHong Zhang 
7369566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer,&format));
7372e5835c6SStefano Zampini   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
7382e5835c6SStefano Zampini 
739c898d852SStefano Zampini   /* trigger copy to CPU if needed */
7409566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&av));
7419566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&av));
74271c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
74397f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
74460e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) {
745c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
746d00d2cf4SBarry Smith       nofinalvalue = 1;
747d00d2cf4SBarry Smith     }
7489566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
7499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n",m,A->cmap->n));
7509566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %" PetscInt_FMT " \n",a->nz));
751fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
7529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"zzz = zeros(%" PetscInt_FMT ",4);\n",a->nz+nofinalvalue));
753fbfe6fa7SJed Brown #else
7549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"zzz = zeros(%" PetscInt_FMT ",3);\n",a->nz+nofinalvalue));
755fbfe6fa7SJed Brown #endif
7569566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"zzz = [\n"));
75717ab2063SBarry Smith 
75817ab2063SBarry Smith     for (i=0; i<m; i++) {
75960e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
760aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
7619566063dSJacob 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])));
76217ab2063SBarry Smith #else
7639566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]));
76417ab2063SBarry Smith #endif
76517ab2063SBarry Smith       }
76617ab2063SBarry Smith     }
767d00d2cf4SBarry Smith     if (nofinalvalue) {
768c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
7699566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e %18.16e\n",m,A->cmap->n,0.,0.));
770c337ccceSJed Brown #else
7719566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e\n",m,A->cmap->n,0.0));
772c337ccceSJed Brown #endif
773d00d2cf4SBarry Smith     }
7749566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)A,&name));
7759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name));
7769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
777fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
7789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
77944cd7ae7SLois Curfman McInnes     for (i=0; i<m; i++) {
7809566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i));
78160e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
782aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
78336db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
7849566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j])));
78536db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
7869566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j])));
78736db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
7889566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j])));
7896831982aSBarry Smith         }
79044cd7ae7SLois Curfman McInnes #else
7919566063dSJacob Faibussowitsch         if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j]));
79244cd7ae7SLois Curfman McInnes #endif
79344cd7ae7SLois Curfman McInnes       }
7949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
79544cd7ae7SLois Curfman McInnes     }
7969566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
797fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
79897f1f81fSBarry Smith     PetscInt nzd=0,fshift=1,*sptr;
7999566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
8009566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m+1,&sptr));
801496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
802496be53dSLois Curfman McInnes       sptr[i] = nzd+1;
80360e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
804496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
805aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
80636db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
807496be53dSLois Curfman McInnes #else
808496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
809496be53dSLois Curfman McInnes #endif
810496be53dSLois Curfman McInnes         }
811496be53dSLois Curfman McInnes       }
812496be53dSLois Curfman McInnes     }
8132e44a96cSLois Curfman McInnes     sptr[m] = nzd+1;
8149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT "\n\n",m,nzd));
8152e44a96cSLois Curfman McInnes     for (i=0; i<m+1; i+=6) {
8162205254eSKarl Rupp       if (i+4<m) {
8179566063dSJacob 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]));
8182205254eSKarl Rupp       } else if (i+3<m) {
8199566063dSJacob 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]));
8202205254eSKarl Rupp       } else if (i+2<m) {
8219566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]));
8222205254eSKarl Rupp       } else if (i+1<m) {
8239566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1],sptr[i+2]));
8242205254eSKarl Rupp       } else if (i<m) {
8259566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1]));
8262205254eSKarl Rupp       } else {
8279566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT "\n",sptr[i]));
8282205254eSKarl Rupp       }
829496be53dSLois Curfman McInnes     }
8309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
8319566063dSJacob Faibussowitsch     PetscCall(PetscFree(sptr));
832496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
83360e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
8349566063dSJacob Faibussowitsch         if (a->j[j] >= i) PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " ",a->j[j]+fshift));
835496be53dSLois Curfman McInnes       }
8369566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
837496be53dSLois Curfman McInnes     }
8389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
839496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
84060e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
841496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
842aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
84336db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
8449566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j])));
8456831982aSBarry Smith           }
846496be53dSLois Curfman McInnes #else
8479566063dSJacob Faibussowitsch           if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]));
848496be53dSLois Curfman McInnes #endif
849496be53dSLois Curfman McInnes         }
850496be53dSLois Curfman McInnes       }
8519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
852496be53dSLois Curfman McInnes     }
8539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
854fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
85597f1f81fSBarry Smith     PetscInt    cnt = 0,jcnt;
85687828ca2SBarry Smith     PetscScalar value;
85768f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
85868f1ed48SBarry Smith     PetscBool   realonly = PETSC_TRUE;
85968f1ed48SBarry Smith 
86068f1ed48SBarry Smith     for (i=0; i<a->i[m]; i++) {
86168f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
86268f1ed48SBarry Smith         realonly = PETSC_FALSE;
86368f1ed48SBarry Smith         break;
86468f1ed48SBarry Smith       }
86568f1ed48SBarry Smith     }
86668f1ed48SBarry Smith #endif
86702594712SBarry Smith 
8689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
86902594712SBarry Smith     for (i=0; i<m; i++) {
87002594712SBarry Smith       jcnt = 0;
871d0f46423SBarry Smith       for (j=0; j<A->cmap->n; j++) {
872e24b481bSBarry Smith         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
87302594712SBarry Smith           value = a->a[cnt++];
874e24b481bSBarry Smith           jcnt++;
87502594712SBarry Smith         } else {
87602594712SBarry Smith           value = 0.0;
87702594712SBarry Smith         }
878aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
87968f1ed48SBarry Smith         if (realonly) {
8809566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value)));
88168f1ed48SBarry Smith         } else {
8829566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value)));
88368f1ed48SBarry Smith         }
88402594712SBarry Smith #else
8859566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value));
88602594712SBarry Smith #endif
88702594712SBarry Smith       }
8889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
88902594712SBarry Smith     }
8909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
8913c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
892150b93efSMatthew G. Knepley     PetscInt fshift=1;
8939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
8943c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
8959566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n"));
8963c215bfdSMatthew Knepley #else
8979566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n"));
8983c215bfdSMatthew Knepley #endif
8999566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", m, A->cmap->n, a->nz));
9003c215bfdSMatthew Knepley     for (i=0; i<m; i++) {
90160e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
9023c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
9039566063dSJacob 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])));
9043c215bfdSMatthew Knepley #else
9059566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT " %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]));
9063c215bfdSMatthew Knepley #endif
9073c215bfdSMatthew Knepley       }
9083c215bfdSMatthew Knepley     }
9099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
9103a40ed3dSBarry Smith   } else {
9119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
912d5f3da31SBarry Smith     if (A->factortype) {
91316cd7e1dSShri Abhyankar       for (i=0; i<m; i++) {
9149566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i));
91516cd7e1dSShri Abhyankar         /* L part */
91660e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
91716cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
91816cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
9199566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j])));
92016cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9219566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j]))));
92216cd7e1dSShri Abhyankar           } else {
9239566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j])));
92416cd7e1dSShri Abhyankar           }
92516cd7e1dSShri Abhyankar #else
9269566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j]));
92716cd7e1dSShri Abhyankar #endif
92816cd7e1dSShri Abhyankar         }
92916cd7e1dSShri Abhyankar         /* diagonal */
93016cd7e1dSShri Abhyankar         j = a->diag[i];
93116cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
93216cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
9339566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)PetscImaginaryPart(1.0/a->a[j])));
93416cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9359566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)(-PetscImaginaryPart(1.0/a->a[j]))));
93616cd7e1dSShri Abhyankar         } else {
9379566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j])));
93816cd7e1dSShri Abhyankar         }
93916cd7e1dSShri Abhyankar #else
9409566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)(1.0/a->a[j])));
94116cd7e1dSShri Abhyankar #endif
94216cd7e1dSShri Abhyankar 
94316cd7e1dSShri Abhyankar         /* U part */
94460e0710aSBarry Smith         for (j=a->diag[i+1]+1; j<a->diag[i]; j++) {
94516cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
94616cd7e1dSShri Abhyankar           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])));
94816cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9499566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j]))));
95016cd7e1dSShri Abhyankar           } else {
9519566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j])));
95216cd7e1dSShri Abhyankar           }
95316cd7e1dSShri Abhyankar #else
9549566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j]));
95516cd7e1dSShri Abhyankar #endif
95616cd7e1dSShri Abhyankar         }
9579566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
95816cd7e1dSShri Abhyankar       }
95916cd7e1dSShri Abhyankar     } else {
96017ab2063SBarry Smith       for (i=0; i<m; i++) {
9619566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i));
96260e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
963aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
96436db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
9659566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j])));
96636db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9679566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j])));
9683a40ed3dSBarry Smith           } else {
9699566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j])));
97017ab2063SBarry Smith           }
97117ab2063SBarry Smith #else
9729566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j]));
97317ab2063SBarry Smith #endif
97417ab2063SBarry Smith         }
9759566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
97617ab2063SBarry Smith       }
97716cd7e1dSShri Abhyankar     }
9789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
97917ab2063SBarry Smith   }
9809566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
9813a40ed3dSBarry Smith   PetscFunctionReturn(0);
982416022c9SBarry Smith }
983416022c9SBarry Smith 
9849804daf3SBarry Smith #include <petscdraw.h>
985dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
986416022c9SBarry Smith {
987480ef9eaSBarry Smith   Mat               A  = (Mat) Aa;
988416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
989383922c3SLisandro Dalcin   PetscInt          i,j,m = A->rmap->n;
990383922c3SLisandro Dalcin   int               color;
991b05fc000SLisandro Dalcin   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
992b0a32e0cSBarry Smith   PetscViewer       viewer;
993f3ef73ceSBarry Smith   PetscViewerFormat format;
994fff043a9SJunchao Zhang   const PetscScalar *aa;
995cddf8d76SBarry Smith 
9963a40ed3dSBarry Smith   PetscFunctionBegin;
9979566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer));
9989566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer,&format));
9999566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr));
1000383922c3SLisandro Dalcin 
1001416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
10029566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&aa));
1003fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1004d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
10050513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
1006b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
1007416022c9SBarry Smith     for (i=0; i<m; i++) {
1008cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1009bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1010bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1011fff043a9SJunchao Zhang         if (PetscRealPart(aa[j]) >=  0.) continue;
10129566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color));
1013cddf8d76SBarry Smith       }
1014cddf8d76SBarry Smith     }
1015b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
1016cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1017cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1018bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1019bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1020fff043a9SJunchao Zhang         if (aa[j] !=  0.) continue;
10219566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color));
1022cddf8d76SBarry Smith       }
1023cddf8d76SBarry Smith     }
1024b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
1025cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1026cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1027bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1028bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1029fff043a9SJunchao Zhang         if (PetscRealPart(aa[j]) <=  0.) continue;
10309566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color));
1031416022c9SBarry Smith       }
1032416022c9SBarry Smith     }
1033d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
10340513a670SBarry Smith   } else {
10350513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
10360513a670SBarry Smith     /* first determine max of all nonzero values */
1037b05fc000SLisandro Dalcin     PetscReal      minv = 0.0, maxv = 0.0;
1038383922c3SLisandro Dalcin     PetscInt       nz   = a->nz, count = 0;
1039b0a32e0cSBarry Smith     PetscDraw      popup;
10400513a670SBarry Smith 
10410513a670SBarry Smith     for (i=0; i<nz; i++) {
1042fff043a9SJunchao Zhang       if (PetscAbsScalar(aa[i]) > maxv) maxv = PetscAbsScalar(aa[i]);
10430513a670SBarry Smith     }
1044383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
10459566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetPopup(draw,&popup));
10469566063dSJacob Faibussowitsch     PetscCall(PetscDrawScalePopup(popup,minv,maxv));
1047383922c3SLisandro Dalcin 
1048d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
10490513a670SBarry Smith     for (i=0; i<m; i++) {
1050383922c3SLisandro Dalcin       y_l = m - i - 1.0;
1051383922c3SLisandro Dalcin       y_r = y_l + 1.0;
1052bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1053383922c3SLisandro Dalcin         x_l = a->j[j];
1054383922c3SLisandro Dalcin         x_r = x_l + 1.0;
1055fff043a9SJunchao Zhang         color = PetscDrawRealToColor(PetscAbsScalar(aa[count]),minv,maxv);
10569566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color));
10570513a670SBarry Smith         count++;
10580513a670SBarry Smith       }
10590513a670SBarry Smith     }
1060d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
10610513a670SBarry Smith   }
10629566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
1063480ef9eaSBarry Smith   PetscFunctionReturn(0);
1064480ef9eaSBarry Smith }
1065cddf8d76SBarry Smith 
10669804daf3SBarry Smith #include <petscdraw.h>
1067dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
1068480ef9eaSBarry Smith {
1069b0a32e0cSBarry Smith   PetscDraw      draw;
107036db0b34SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
1071ace3abfcSBarry Smith   PetscBool      isnull;
1072480ef9eaSBarry Smith 
1073480ef9eaSBarry Smith   PetscFunctionBegin;
10749566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer,0,&draw));
10759566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw,&isnull));
1076480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
1077480ef9eaSBarry Smith 
1078d0f46423SBarry Smith   xr   = A->cmap->n; yr  = A->rmap->n; h = yr/10.0; w = xr/10.0;
1079480ef9eaSBarry Smith   xr  += w;          yr += h;         xl = -w;     yl = -h;
10809566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw,xl,yl,xr,yr));
10819566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer));
10829566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A));
10839566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL));
10849566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
10853a40ed3dSBarry Smith   PetscFunctionReturn(0);
1086416022c9SBarry Smith }
1087416022c9SBarry Smith 
1088dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
1089416022c9SBarry Smith {
1090ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw;
1091416022c9SBarry Smith 
10923a40ed3dSBarry Smith   PetscFunctionBegin;
10939566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
10949566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary));
10959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw));
1096c45a1595SBarry Smith   if (iascii) {
10979566063dSJacob Faibussowitsch     PetscCall(MatView_SeqAIJ_ASCII(A,viewer));
10980f5bd95cSBarry Smith   } else if (isbinary) {
10999566063dSJacob Faibussowitsch     PetscCall(MatView_SeqAIJ_Binary(A,viewer));
11000f5bd95cSBarry Smith   } else if (isdraw) {
11019566063dSJacob Faibussowitsch     PetscCall(MatView_SeqAIJ_Draw(A,viewer));
110211aeaf0aSBarry Smith   }
11039566063dSJacob Faibussowitsch   PetscCall(MatView_SeqAIJ_Inode(A,viewer));
11043a40ed3dSBarry Smith   PetscFunctionReturn(0);
110517ab2063SBarry Smith }
110619bcc07fSBarry Smith 
1107dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
110817ab2063SBarry Smith {
1109416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1110580bdb30SBarry Smith   PetscInt       fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax;
1111d0f46423SBarry Smith   PetscInt       m      = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
111254f21887SBarry Smith   MatScalar      *aa    = a->a,*ap;
11133447b6efSHong Zhang   PetscReal      ratio  = 0.6;
111417ab2063SBarry Smith 
11153a40ed3dSBarry Smith   PetscFunctionBegin;
11163a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
11179566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(A));
1118b215bc84SStefano Zampini   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) {
1119b215bc84SStefano Zampini     /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */
11209566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A,mode));
1121b215bc84SStefano Zampini     PetscFunctionReturn(0);
1122b215bc84SStefano Zampini   }
112317ab2063SBarry Smith 
112443ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
112517ab2063SBarry Smith   for (i=1; i<m; i++) {
1126416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
112717ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
112894a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
112917ab2063SBarry Smith     if (fshift) {
1130bfeeae90SHong Zhang       ip = aj + ai[i];
1131bfeeae90SHong Zhang       ap = aa + ai[i];
113217ab2063SBarry Smith       N  = ailen[i];
11339566063dSJacob Faibussowitsch       PetscCall(PetscArraymove(ip-fshift,ip,N));
1134580bdb30SBarry Smith       if (!A->structure_only) {
11359566063dSJacob Faibussowitsch         PetscCall(PetscArraymove(ap-fshift,ap,N));
113617ab2063SBarry Smith       }
113717ab2063SBarry Smith     }
113817ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
113917ab2063SBarry Smith   }
114017ab2063SBarry Smith   if (m) {
114117ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
114217ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
114317ab2063SBarry Smith   }
11447b083b7cSBarry Smith 
114517ab2063SBarry Smith   /* reset ilen and imax for each row */
11467b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1147396832f4SHong Zhang   if (A->structure_only) {
11489566063dSJacob Faibussowitsch     PetscCall(PetscFree(a->imax));
11499566063dSJacob Faibussowitsch     PetscCall(PetscFree(a->ilen));
1150396832f4SHong Zhang   } else { /* !A->structure_only */
115117ab2063SBarry Smith     for (i=0; i<m; i++) {
115217ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
11537b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
115417ab2063SBarry Smith     }
1155396832f4SHong Zhang   }
1156bfeeae90SHong Zhang   a->nz = ai[m];
1157aed4548fSBarry 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);
115817ab2063SBarry Smith 
11599566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqAIJ(A));
11609566063dSJacob 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));
11619566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A,"Number of mallocs during MatSetValues() is %" PetscInt_FMT "\n",a->reallocs));
11629566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A,"Maximum nonzeros in any row is %" PetscInt_FMT "\n",rmax));
11632205254eSKarl Rupp 
11648e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1165dd5f02e7SSatish Balay   a->reallocs         = 0;
11666712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
116736db0b34SBarry Smith   a->rmax             = rmax;
11684e220ebcSLois Curfman McInnes 
1169396832f4SHong Zhang   if (!A->structure_only) {
11709566063dSJacob Faibussowitsch     PetscCall(MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio));
1171396832f4SHong Zhang   }
11729566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A,mode));
11733a40ed3dSBarry Smith   PetscFunctionReturn(0);
117417ab2063SBarry Smith }
117517ab2063SBarry Smith 
117699cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
117799cafbc1SBarry Smith {
117899cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
117999cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
11802e5835c6SStefano Zampini   MatScalar      *aa;
118199cafbc1SBarry Smith 
118299cafbc1SBarry Smith   PetscFunctionBegin;
11839566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A,&aa));
118499cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
11859566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A,&aa));
11869566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(A));
118799cafbc1SBarry Smith   PetscFunctionReturn(0);
118899cafbc1SBarry Smith }
118999cafbc1SBarry Smith 
119099cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
119199cafbc1SBarry Smith {
119299cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
119399cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
11942e5835c6SStefano Zampini   MatScalar      *aa;
119599cafbc1SBarry Smith 
119699cafbc1SBarry Smith   PetscFunctionBegin;
11979566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A,&aa));
119899cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
11999566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A,&aa));
12009566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(A));
120199cafbc1SBarry Smith   PetscFunctionReturn(0);
120299cafbc1SBarry Smith }
120399cafbc1SBarry Smith 
1204dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
120517ab2063SBarry Smith {
1206fff043a9SJunchao Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1207fff043a9SJunchao Zhang   MatScalar      *aa;
12083a40ed3dSBarry Smith 
12093a40ed3dSBarry Smith   PetscFunctionBegin;
12109566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayWrite(A,&aa));
12119566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(aa,a->i[A->rmap->n]));
12129566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayWrite(A,&aa));
12139566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(A));
12143a40ed3dSBarry Smith   PetscFunctionReturn(0);
121517ab2063SBarry Smith }
1216416022c9SBarry Smith 
1217cbc6b225SStefano Zampini PETSC_INTERN PetscErrorCode MatResetPreallocationCOO_SeqAIJ(Mat A)
1218cbc6b225SStefano Zampini {
1219cbc6b225SStefano Zampini   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1220cbc6b225SStefano Zampini 
1221cbc6b225SStefano Zampini   PetscFunctionBegin;
12229566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->perm));
12239566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->jmap));
1224cbc6b225SStefano Zampini   PetscFunctionReturn(0);
1225cbc6b225SStefano Zampini }
1226cbc6b225SStefano Zampini 
1227dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
122817ab2063SBarry Smith {
1229416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1230d5d45c9bSBarry Smith 
12313a40ed3dSBarry Smith   PetscFunctionBegin;
1232aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1233c0aa6a63SJacob Faibussowitsch   PetscLogObjectState((PetscObject)A,"Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT,A->rmap->n,A->cmap->n,a->nz);
123417ab2063SBarry Smith #endif
12359566063dSJacob Faibussowitsch   PetscCall(MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i));
12369566063dSJacob Faibussowitsch   PetscCall(MatResetPreallocationCOO_SeqAIJ(A));
12379566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
12389566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
12399566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->diag));
12409566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->ibdiag));
12419566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->imax));
12429566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->ilen));
12439566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->ipre));
12449566063dSJacob Faibussowitsch   PetscCall(PetscFree3(a->idiag,a->mdiag,a->ssor_work));
12459566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->solve_work));
12469566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->icol));
12479566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->saved_values));
12489566063dSJacob Faibussowitsch   PetscCall(PetscFree2(a->compressedrow.i,a->compressedrow.rindex));
12499566063dSJacob Faibussowitsch   PetscCall(MatDestroy_SeqAIJ_Inode(A));
12509566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
1251901853e0SKris Buschelman 
12526718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
12536718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
12546718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
12556718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
12566718818eSStefano Zampini      due to different matrix sizes */
12579566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL));
12586718818eSStefano Zampini 
12599566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A,NULL));
12609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL));
12619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL));
12629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL));
12639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL));
12649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL));
12659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL));
12664222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
12679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL));
12689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL));
12699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",NULL));
12704222ddf1SHong Zhang #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
1278d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
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));
12899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL));
12909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL));
12919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL));
12929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL));
12939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL));
12949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL));
12959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL));
12969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJKron_C",NULL));
12979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",NULL));
12989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",NULL));
12993a40ed3dSBarry Smith   PetscFunctionReturn(0);
130017ab2063SBarry Smith }
130117ab2063SBarry Smith 
1302ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
130317ab2063SBarry Smith {
1304416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13053a40ed3dSBarry Smith 
13063a40ed3dSBarry Smith   PetscFunctionBegin;
1307a65d3064SKris Buschelman   switch (op) {
1308a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
13094e0d8c25SBarry Smith     a->roworiented = flg;
1310a65d3064SKris Buschelman     break;
1311a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1312a9817697SBarry Smith     a->keepnonzeropattern = flg;
1313a65d3064SKris Buschelman     break;
1314512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1315512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1316a65d3064SKris Buschelman     break;
1317a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
13184e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1319a65d3064SKris Buschelman     break;
1320a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
13214e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1322a65d3064SKris Buschelman     break;
132328b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
132428b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
132528b2fa4aSMatthew Knepley     break;
1326a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
13274e0d8c25SBarry Smith     a->ignorezeroentries = flg;
13280df259c2SBarry Smith     break;
13293d472b54SHong Zhang   case MAT_SPD:
1330b1646e73SJed Brown   case MAT_SYMMETRIC:
1331b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1332b1646e73SJed Brown   case MAT_HERMITIAN:
1333b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1334957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
13355021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
13365021d80fSJed Brown     break;
13378c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
1338a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1339a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
13409566063dSJacob Faibussowitsch     PetscCall(PetscInfo(A,"Option %s ignored\n",MatOptions[op]));
1341a65d3064SKris Buschelman     break;
1342b87ac2d8SJed Brown   case MAT_USE_INODES:
13439566063dSJacob Faibussowitsch     PetscCall(MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg));
1344b87ac2d8SJed Brown     break;
1345c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1346c10200c1SHong Zhang     A->submat_singleis = flg;
1347c10200c1SHong Zhang     break;
1348071fcb05SBarry Smith   case MAT_SORTED_FULL:
1349071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1350071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1351071fcb05SBarry Smith     break;
13521a2c6b5cSJunchao Zhang   case MAT_FORM_EXPLICIT_TRANSPOSE:
13531a2c6b5cSJunchao Zhang     A->form_explicit_transpose = flg;
13541a2c6b5cSJunchao Zhang     break;
1355a65d3064SKris Buschelman   default:
135698921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1357a65d3064SKris Buschelman   }
13583a40ed3dSBarry Smith   PetscFunctionReturn(0);
135917ab2063SBarry Smith }
136017ab2063SBarry Smith 
1361dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
136217ab2063SBarry Smith {
1363416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1364fdc842d1SBarry Smith   PetscInt          i,j,n,*ai=a->i,*aj=a->j;
1365c898d852SStefano Zampini   PetscScalar       *x;
1366c898d852SStefano Zampini   const PetscScalar *aa;
136717ab2063SBarry Smith 
13683a40ed3dSBarry Smith   PetscFunctionBegin;
13699566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v,&n));
137008401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
13719566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&aa));
1372d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1373d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
13749566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(v,&x));
13752c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
13769566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(v,&x));
13779566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
137835e7444dSHong Zhang     PetscFunctionReturn(0);
137935e7444dSHong Zhang   }
138035e7444dSHong Zhang 
13819566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v,&x));
138235e7444dSHong Zhang   for (i=0; i<n; i++) {
1383fdc842d1SBarry Smith     x[i] = 0.0;
138435e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
138535e7444dSHong Zhang       if (aj[j] == i) {
138635e7444dSHong Zhang         x[i] = aa[j];
138717ab2063SBarry Smith         break;
138817ab2063SBarry Smith       }
138917ab2063SBarry Smith     }
139017ab2063SBarry Smith   }
13919566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v,&x));
13929566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
13933a40ed3dSBarry Smith   PetscFunctionReturn(0);
139417ab2063SBarry Smith }
139517ab2063SBarry Smith 
1396c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1397dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
139817ab2063SBarry Smith {
1399416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
14005f22a7b3SSebastian Grimberg   const MatScalar   *aa;
1401d9ca1df4SBarry Smith   PetscScalar       *y;
1402d9ca1df4SBarry Smith   const PetscScalar *x;
1403d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
14045c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
14055f22a7b3SSebastian Grimberg   const MatScalar   *v;
1406a77337e4SBarry Smith   PetscScalar       alpha;
1407d9ca1df4SBarry Smith   PetscInt          n,i,j;
1408d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
14093447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1410ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
14115c897100SBarry Smith #endif
141217ab2063SBarry Smith 
14133a40ed3dSBarry Smith   PetscFunctionBegin;
14149566063dSJacob Faibussowitsch   if (zz != yy) PetscCall(VecCopy(zz,yy));
14159566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx,&x));
14169566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy,&y));
14179566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&aa));
14185c897100SBarry Smith 
14195c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1420fff043a9SJunchao Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,aa,y);
14215c897100SBarry Smith #else
14223447b6efSHong Zhang   if (usecprow) {
14233447b6efSHong Zhang     m    = cprow.nrows;
14243447b6efSHong Zhang     ii   = cprow.i;
14257b2bb3b9SHong Zhang     ridx = cprow.rindex;
14263447b6efSHong Zhang   } else {
14273447b6efSHong Zhang     ii = a->i;
14283447b6efSHong Zhang   }
142917ab2063SBarry Smith   for (i=0; i<m; i++) {
14303447b6efSHong Zhang     idx = a->j + ii[i];
1431fff043a9SJunchao Zhang     v   = aa + ii[i];
14323447b6efSHong Zhang     n   = ii[i+1] - ii[i];
14333447b6efSHong Zhang     if (usecprow) {
14347b2bb3b9SHong Zhang       alpha = x[ridx[i]];
14353447b6efSHong Zhang     } else {
143617ab2063SBarry Smith       alpha = x[i];
14373447b6efSHong Zhang     }
143804fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
143917ab2063SBarry Smith   }
14405c897100SBarry Smith #endif
14419566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0*a->nz));
14429566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx,&x));
14439566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy,&y));
14449566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
14453a40ed3dSBarry Smith   PetscFunctionReturn(0);
144617ab2063SBarry Smith }
144717ab2063SBarry Smith 
1448dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
14495c897100SBarry Smith {
14505c897100SBarry Smith   PetscFunctionBegin;
14519566063dSJacob Faibussowitsch   PetscCall(VecSet(yy,0.0));
14529566063dSJacob Faibussowitsch   PetscCall(MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy));
14535c897100SBarry Smith   PetscFunctionReturn(0);
14545c897100SBarry Smith }
14555c897100SBarry Smith 
1456c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
145778b84d54SShri Abhyankar 
1458dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
145917ab2063SBarry Smith {
1460416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1461d9fead3dSBarry Smith   PetscScalar       *y;
146254f21887SBarry Smith   const PetscScalar *x;
1463fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1464003131ecSBarry Smith   PetscInt          m=A->rmap->n;
14650298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
14667b083b7cSBarry Smith   PetscInt          n,i;
1467362ced78SSatish Balay   PetscScalar       sum;
1468ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
146917ab2063SBarry Smith 
1470b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
147197952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1472fee21e36SBarry Smith #endif
1473fee21e36SBarry Smith 
14743a40ed3dSBarry Smith   PetscFunctionBegin;
1475b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
14769566063dSJacob Faibussowitsch     PetscCall(MatMult_SeqAIJ_Inode(A,xx,yy));
1477b215bc84SStefano Zampini     PetscFunctionReturn(0);
1478b215bc84SStefano Zampini   }
14799566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&a_a));
14809566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx,&x));
14819566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy,&y));
1482416022c9SBarry Smith   ii   = a->i;
14834eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
14849566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(y,m));
148597952fefSHong Zhang     m    = a->compressedrow.nrows;
148697952fefSHong Zhang     ii   = a->compressedrow.i;
148797952fefSHong Zhang     ridx = a->compressedrow.rindex;
148897952fefSHong Zhang     for (i=0; i<m; i++) {
148997952fefSHong Zhang       n           = ii[i+1] - ii[i];
149097952fefSHong Zhang       aj          = a->j + ii[i];
1491fff043a9SJunchao Zhang       aa          = a_a + ii[i];
149297952fefSHong Zhang       sum         = 0.0;
1493003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1494003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
149597952fefSHong Zhang       y[*ridx++] = sum;
149697952fefSHong Zhang     }
149797952fefSHong Zhang   } else { /* do not use compressed row format */
1498b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
14993d3eaba7SBarry Smith     aj   = a->j;
1500fff043a9SJunchao Zhang     aa   = a_a;
1501b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1502b05257ddSBarry Smith #else
150317ab2063SBarry Smith     for (i=0; i<m; i++) {
1504003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1505003131ecSBarry Smith       aj          = a->j + ii[i];
1506fff043a9SJunchao Zhang       aa          = a_a + ii[i];
150717ab2063SBarry Smith       sum         = 0.0;
1508003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
150917ab2063SBarry Smith       y[i] = sum;
151017ab2063SBarry Smith     }
15118d195f9aSBarry Smith #endif
1512b05257ddSBarry Smith   }
15139566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0*a->nz - a->nonzerorowcnt));
15149566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx,&x));
15159566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy,&y));
15169566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&a_a));
15173a40ed3dSBarry Smith   PetscFunctionReturn(0);
151817ab2063SBarry Smith }
151917ab2063SBarry Smith 
1520b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1521b434eb95SMatthew G. Knepley {
1522b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1523b434eb95SMatthew G. Knepley   PetscScalar       *y;
1524b434eb95SMatthew G. Knepley   const PetscScalar *x;
1525fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1526b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1527b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1528b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1529b434eb95SMatthew G. Knepley   PetscScalar       sum;
1530b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1531b434eb95SMatthew G. Knepley 
1532b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1533b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1534b434eb95SMatthew G. Knepley #endif
1535b434eb95SMatthew G. Knepley 
1536b434eb95SMatthew G. Knepley   PetscFunctionBegin;
15379566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&a_a));
15389566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx,&x));
15399566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy,&y));
1540b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1541b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1542b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1543b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1544b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1545b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1546b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1547fff043a9SJunchao Zhang       aa          = a_a + ii[i];
1548b434eb95SMatthew G. Knepley       sum         = 0.0;
1549b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1550b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1551b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1552b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1553b434eb95SMatthew G. Knepley     }
1554b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
15553d3eaba7SBarry Smith     ii = a->i;
1556b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1557b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1558b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1559fff043a9SJunchao Zhang       aa          = a_a + ii[i];
1560b434eb95SMatthew G. Knepley       sum         = 0.0;
1561b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1562b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1563b434eb95SMatthew G. Knepley       y[i] = sum;
1564b434eb95SMatthew G. Knepley     }
1565b434eb95SMatthew G. Knepley   }
15669566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0*a->nz - nonzerorow));
15679566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx,&x));
15689566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy,&y));
15699566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&a_a));
1570b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1571b434eb95SMatthew G. Knepley }
1572b434eb95SMatthew G. Knepley 
1573b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1574b434eb95SMatthew G. Knepley {
1575b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1576b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1577b434eb95SMatthew G. Knepley   const PetscScalar *x;
1578fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1579b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1580b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1581b434eb95SMatthew G. Knepley   PetscScalar       sum;
1582b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1583b434eb95SMatthew G. Knepley 
1584b434eb95SMatthew G. Knepley   PetscFunctionBegin;
15859566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&a_a));
15869566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx,&x));
15879566063dSJacob Faibussowitsch   PetscCall(VecGetArrayPair(yy,zz,&y,&z));
1588b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1589b434eb95SMatthew G. Knepley     if (zz != yy) {
15909566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(z,y,m));
1591b434eb95SMatthew G. Knepley     }
1592b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1593b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1594b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1595b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1596b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1597b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1598fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1599b434eb95SMatthew G. Knepley       sum = y[*ridx];
1600b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1601b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1602b434eb95SMatthew G. Knepley     }
1603b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16043d3eaba7SBarry Smith     ii = a->i;
1605b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1606b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1607b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1608fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1609b434eb95SMatthew G. Knepley       sum = y[i];
1610b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1611b434eb95SMatthew G. Knepley       z[i] = sum;
1612b434eb95SMatthew G. Knepley     }
1613b434eb95SMatthew G. Knepley   }
16149566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0*a->nz));
16159566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx,&x));
16169566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayPair(yy,zz,&y,&z));
16179566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&a_a));
1618b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1619b434eb95SMatthew G. Knepley }
1620b434eb95SMatthew G. Knepley 
1621c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1622dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
162317ab2063SBarry Smith {
1624416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1625f15663dcSBarry Smith   PetscScalar       *y,*z;
1626f15663dcSBarry Smith   const PetscScalar *x;
1627fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1628d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1629d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1630362ced78SSatish Balay   PetscScalar       sum;
1631ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
16329ea0dfa2SSatish Balay 
16333a40ed3dSBarry Smith   PetscFunctionBegin;
1634b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
16359566063dSJacob Faibussowitsch     PetscCall(MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz));
1636b215bc84SStefano Zampini     PetscFunctionReturn(0);
1637b215bc84SStefano Zampini   }
16389566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&a_a));
16399566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx,&x));
16409566063dSJacob Faibussowitsch   PetscCall(VecGetArrayPair(yy,zz,&y,&z));
16414eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
16424eb6d288SHong Zhang     if (zz != yy) {
16439566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(z,y,m));
16444eb6d288SHong Zhang     }
164597952fefSHong Zhang     m    = a->compressedrow.nrows;
164697952fefSHong Zhang     ii   = a->compressedrow.i;
164797952fefSHong Zhang     ridx = a->compressedrow.rindex;
164897952fefSHong Zhang     for (i=0; i<m; i++) {
164997952fefSHong Zhang       n   = ii[i+1] - ii[i];
165097952fefSHong Zhang       aj  = a->j + ii[i];
1651fff043a9SJunchao Zhang       aa  = a_a + ii[i];
165297952fefSHong Zhang       sum = y[*ridx];
1653f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
165497952fefSHong Zhang       z[*ridx++] = sum;
165597952fefSHong Zhang     }
165697952fefSHong Zhang   } else { /* do not use compressed row format */
16573d3eaba7SBarry Smith     ii = a->i;
1658f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
16593d3eaba7SBarry Smith     aj = a->j;
1660fff043a9SJunchao Zhang     aa = a_a;
1661f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1662f15663dcSBarry Smith #else
166317ab2063SBarry Smith     for (i=0; i<m; i++) {
1664f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1665f15663dcSBarry Smith       aj  = a->j + ii[i];
1666fff043a9SJunchao Zhang       aa  = a_a + ii[i];
166717ab2063SBarry Smith       sum = y[i];
1668f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
166917ab2063SBarry Smith       z[i] = sum;
167017ab2063SBarry Smith     }
167102ab625aSSatish Balay #endif
1672f15663dcSBarry Smith   }
16739566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0*a->nz));
16749566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx,&x));
16759566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayPair(yy,zz,&y,&z));
16769566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&a_a));
16773a40ed3dSBarry Smith   PetscFunctionReturn(0);
167817ab2063SBarry Smith }
167917ab2063SBarry Smith 
168017ab2063SBarry Smith /*
168117ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
168217ab2063SBarry Smith */
1683dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
168417ab2063SBarry Smith {
1685416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1686d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
1687c0c07093SJunchao Zhang   PetscBool      alreadySet = PETSC_TRUE;
168817ab2063SBarry Smith 
16893a40ed3dSBarry Smith   PetscFunctionBegin;
169009f38230SBarry Smith   if (!a->diag) {
16919566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m,&a->diag));
16929566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt)));
1693c0c07093SJunchao Zhang     alreadySet = PETSC_FALSE;
169409f38230SBarry Smith   }
1695d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
1696c0c07093SJunchao Zhang     /* If A's diagonal is already correctly set, this fast track enables cheap and repeated MatMarkDiagonal_SeqAIJ() calls */
1697c0c07093SJunchao Zhang     if (alreadySet) {
1698c0c07093SJunchao Zhang       PetscInt pos = a->diag[i];
1699c0c07093SJunchao Zhang       if (pos >= a->i[i] && pos < a->i[i+1] && a->j[pos] == i) continue;
1700c0c07093SJunchao Zhang     }
1701c0c07093SJunchao Zhang 
170209f38230SBarry Smith     a->diag[i] = a->i[i+1];
1703bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1704bfeeae90SHong Zhang       if (a->j[j] == i) {
170509f38230SBarry Smith         a->diag[i] = j;
170617ab2063SBarry Smith         break;
170717ab2063SBarry Smith       }
170817ab2063SBarry Smith     }
170917ab2063SBarry Smith   }
17103a40ed3dSBarry Smith   PetscFunctionReturn(0);
171117ab2063SBarry Smith }
171217ab2063SBarry Smith 
171361ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
171461ecd0c6SBarry Smith {
171561ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
171661ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
171761ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
171861ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
171961ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
172061ecd0c6SBarry Smith 
172161ecd0c6SBarry Smith   PetscFunctionBegin;
172261ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
17239566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(A,1,NULL));
17249566063dSJacob Faibussowitsch     PetscCall(MatShift_Basic(A,v));
172561ecd0c6SBarry Smith     PetscFunctionReturn(0);
172661ecd0c6SBarry Smith   }
172761ecd0c6SBarry Smith 
172861ecd0c6SBarry Smith   if (a->diagonaldense) {
172961ecd0c6SBarry Smith     cnt = 0;
173061ecd0c6SBarry Smith   } else {
17319566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(A->rmap->n,&mdiag));
173261ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
173361ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
173461ecd0c6SBarry Smith         cnt++;
173561ecd0c6SBarry Smith         mdiag[i] = 1;
173661ecd0c6SBarry Smith       }
173761ecd0c6SBarry Smith     }
173861ecd0c6SBarry Smith   }
173961ecd0c6SBarry Smith   if (!cnt) {
17409566063dSJacob Faibussowitsch     PetscCall(MatShift_Basic(A,v));
174161ecd0c6SBarry Smith   } else {
1742b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1743b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
174461ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
174561ecd0c6SBarry Smith 
174661ecd0c6SBarry Smith     a->a = NULL;
174761ecd0c6SBarry Smith     a->j = NULL;
174861ecd0c6SBarry Smith     a->i = NULL;
174961ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
175061ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
175161ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1752447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
175361ecd0c6SBarry Smith     }
17549566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax));
175561ecd0c6SBarry Smith 
175661ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
175761ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
17589566063dSJacob Faibussowitsch       PetscCall(MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES));
1759447d62f5SStefano Zampini       if (i < A->cmap->n) {
17609566063dSJacob Faibussowitsch         PetscCall(MatSetValue(A,i,i,v,ADD_VALUES));
176161ecd0c6SBarry Smith       }
1762447d62f5SStefano Zampini     }
17639566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
17649566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
176561ecd0c6SBarry Smith     if (singlemalloc) {
17669566063dSJacob Faibussowitsch       PetscCall(PetscFree3(olda,oldj,oldi));
176761ecd0c6SBarry Smith     } else {
17689566063dSJacob Faibussowitsch       if (free_a)  PetscCall(PetscFree(olda));
17699566063dSJacob Faibussowitsch       if (free_ij) PetscCall(PetscFree(oldj));
17709566063dSJacob Faibussowitsch       if (free_ij) PetscCall(PetscFree(oldi));
177161ecd0c6SBarry Smith     }
177261ecd0c6SBarry Smith   }
17739566063dSJacob Faibussowitsch   PetscCall(PetscFree(mdiag));
177461ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
177561ecd0c6SBarry Smith   PetscFunctionReturn(0);
177661ecd0c6SBarry Smith }
177761ecd0c6SBarry Smith 
1778be5855fcSBarry Smith /*
1779be5855fcSBarry Smith      Checks for missing diagonals
1780be5855fcSBarry Smith */
1781ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1782be5855fcSBarry Smith {
1783be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
17847734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1785be5855fcSBarry Smith 
1786be5855fcSBarry Smith   PetscFunctionBegin;
178709f38230SBarry Smith   *missing = PETSC_FALSE;
17887734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
178909f38230SBarry Smith     *missing = PETSC_TRUE;
179009f38230SBarry Smith     if (d) *d = 0;
17919566063dSJacob Faibussowitsch     PetscCall(PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n"));
179209f38230SBarry Smith   } else {
179301445905SHong Zhang     PetscInt n;
179401445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1795f1e2ffcdSBarry Smith     diag = a->diag;
179601445905SHong Zhang     for (i=0; i<n; i++) {
17977734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
179809f38230SBarry Smith         *missing = PETSC_TRUE;
179909f38230SBarry Smith         if (d) *d = i;
18009566063dSJacob Faibussowitsch         PetscCall(PetscInfo(A,"Matrix is missing diagonal number %" PetscInt_FMT "\n",i));
1801358d2f5dSShri Abhyankar         break;
180209f38230SBarry Smith       }
1803be5855fcSBarry Smith     }
1804be5855fcSBarry Smith   }
1805be5855fcSBarry Smith   PetscFunctionReturn(0);
1806be5855fcSBarry Smith }
1807be5855fcSBarry Smith 
18080da83c2eSBarry Smith #include <petscblaslapack.h>
18090da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
18100da83c2eSBarry Smith 
18110da83c2eSBarry Smith /*
18120da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
18130da83c2eSBarry Smith */
18140da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
18150da83c2eSBarry Smith {
18160da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
18170da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
18180da83c2eSBarry Smith   const PetscReal shift = 0.0;
18190da83c2eSBarry Smith   PetscInt        ipvt[5];
18200da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
18210da83c2eSBarry Smith 
18220da83c2eSBarry Smith   PetscFunctionBegin;
18230da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
18240da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
182508401ef6SPierre 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);
18260da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18270da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
18280da83c2eSBarry Smith   }
18299566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(bsizemax,&indx));
18300da83c2eSBarry Smith   if (bsizemax > 7) {
18319566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots));
18320da83c2eSBarry Smith   }
18330da83c2eSBarry Smith   ncnt = 0;
18340da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18350da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
18369566063dSJacob Faibussowitsch     PetscCall(MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag));
18370da83c2eSBarry Smith     switch (bsizes[i]) {
18380da83c2eSBarry Smith     case 1:
18390da83c2eSBarry Smith       *diag = 1.0/(*diag);
18400da83c2eSBarry Smith       break;
18410da83c2eSBarry Smith     case 2:
18429566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected));
18430da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18449566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_2(diag));
18450da83c2eSBarry Smith       break;
18460da83c2eSBarry Smith     case 3:
18479566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected));
18480da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18499566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_3(diag));
18500da83c2eSBarry Smith       break;
18510da83c2eSBarry Smith     case 4:
18529566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected));
18530da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18549566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_4(diag));
18550da83c2eSBarry Smith       break;
18560da83c2eSBarry Smith     case 5:
18579566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected));
18580da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18599566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_5(diag));
18600da83c2eSBarry Smith       break;
18610da83c2eSBarry Smith     case 6:
18629566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected));
18630da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18649566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_6(diag));
18650da83c2eSBarry Smith       break;
18660da83c2eSBarry Smith     case 7:
18679566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected));
18680da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18699566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_7(diag));
18700da83c2eSBarry Smith       break;
18710da83c2eSBarry Smith     default:
18729566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected));
18730da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18749566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]));
18750da83c2eSBarry Smith     }
18760da83c2eSBarry Smith     ncnt   += bsizes[i];
18770da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
18780da83c2eSBarry Smith   }
18790da83c2eSBarry Smith   if (bsizemax > 7) {
18809566063dSJacob Faibussowitsch     PetscCall(PetscFree2(v_work,v_pivots));
18810da83c2eSBarry Smith   }
18829566063dSJacob Faibussowitsch   PetscCall(PetscFree(indx));
18830da83c2eSBarry Smith   PetscFunctionReturn(0);
18840da83c2eSBarry Smith }
18850da83c2eSBarry Smith 
1886422a814eSBarry Smith /*
1887422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1888422a814eSBarry Smith */
18897087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
189071f1c65dSBarry Smith {
189171f1c65dSBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
1892d0f46423SBarry Smith   PetscInt        i,*diag,m = A->rmap->n;
18932e5835c6SStefano Zampini   const MatScalar *v;
189454f21887SBarry Smith   PetscScalar     *idiag,*mdiag;
189571f1c65dSBarry Smith 
189671f1c65dSBarry Smith   PetscFunctionBegin;
189771f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
18989566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqAIJ(A));
189971f1c65dSBarry Smith   diag = a->diag;
190071f1c65dSBarry Smith   if (!a->idiag) {
19019566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work));
19029566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A,3*m*sizeof(PetscScalar)));
190371f1c65dSBarry Smith   }
19042e5835c6SStefano Zampini 
190571f1c65dSBarry Smith   mdiag = a->mdiag;
190671f1c65dSBarry Smith   idiag = a->idiag;
19079566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&v));
1908422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
190971f1c65dSBarry Smith     for (i=0; i<m; i++) {
191071f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1911899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1912899639b0SHong Zhang         if (PetscRealPart(fshift)) {
19139566063dSJacob Faibussowitsch           PetscCall(PetscInfo(A,"Zero diagonal on row %" PetscInt_FMT "\n",i));
19147b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19157b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
19167b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
191798921bdaSJacob Faibussowitsch         } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %" PetscInt_FMT,i);
1918899639b0SHong Zhang       }
191971f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
192071f1c65dSBarry Smith     }
19219566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(m));
192271f1c65dSBarry Smith   } else {
192371f1c65dSBarry Smith     for (i=0; i<m; i++) {
192471f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
192571f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
192671f1c65dSBarry Smith     }
19279566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0*m));
192871f1c65dSBarry Smith   }
192971f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
19309566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&v));
193171f1c65dSBarry Smith   PetscFunctionReturn(0);
193271f1c65dSBarry Smith }
193371f1c65dSBarry Smith 
1934c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
193541f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
193617ab2063SBarry Smith {
1937416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1938e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
19392e5835c6SStefano Zampini   const MatScalar   *v,*idiag=NULL,*mdiag,*aa;
194054f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
19413d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
194297f1f81fSBarry Smith   const PetscInt    *idx,*diag;
194317ab2063SBarry Smith 
19443a40ed3dSBarry Smith   PetscFunctionBegin;
1945b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) {
19469566063dSJacob Faibussowitsch     PetscCall(MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx));
1947b215bc84SStefano Zampini     PetscFunctionReturn(0);
1948b215bc84SStefano Zampini   }
1949b965ef7fSBarry Smith   its = its*lits;
195091723122SBarry Smith 
195171f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
19529566063dSJacob Faibussowitsch   if (!a->idiagvalid) PetscCall(MatInvertDiagonal_SeqAIJ(A,omega,fshift));
195371f1c65dSBarry Smith   a->fshift = fshift;
195471f1c65dSBarry Smith   a->omega  = omega;
1955ed480e8bSBarry Smith 
195671f1c65dSBarry Smith   diag  = a->diag;
195771f1c65dSBarry Smith   t     = a->ssor_work;
1958ed480e8bSBarry Smith   idiag = a->idiag;
195971f1c65dSBarry Smith   mdiag = a->mdiag;
1960ed480e8bSBarry Smith 
19619566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&aa));
19629566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx,&x));
19639566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb,&b));
1964ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
196517ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
196617ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
1967ed480e8bSBarry Smith     bs = b;
196817ab2063SBarry Smith     for (i=0; i<m; i++) {
196971f1c65dSBarry Smith       d   = fshift + mdiag[i];
1970416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
1971ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
19722e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
197317ab2063SBarry Smith       sum = b[i]*d/omega;
1974003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
197517ab2063SBarry Smith       x[i] = sum;
197617ab2063SBarry Smith     }
19779566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(xx,&x));
19789566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(bb,&b));
19799566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
19809566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(a->nz));
19813a40ed3dSBarry Smith     PetscFunctionReturn(0);
198217ab2063SBarry Smith   }
1983c783ea89SBarry Smith 
198408401ef6SPierre Jolivet   PetscCheck(flag != SOR_APPLY_LOWER,PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
19852205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
19864c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
1987887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
198817ab2063SBarry Smith 
198917ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
199017ab2063SBarry Smith 
1991887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
199217ab2063SBarry Smith     */
199317ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
199417ab2063SBarry Smith 
199517ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
199617ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
1997416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
1998ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
19992e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
200017ab2063SBarry Smith       sum = b[i];
2001e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
2002ed480e8bSBarry Smith       x[i] = sum*idiag[i];
200317ab2063SBarry Smith     }
200417ab2063SBarry Smith 
200517ab2063SBarry Smith     /*  t = b - (2*E - D)x */
20062e5835c6SStefano Zampini     v = aa;
20072205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
200817ab2063SBarry Smith 
200917ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
2010ed480e8bSBarry Smith     ts   = t;
2011416022c9SBarry Smith     diag = a->diag;
201217ab2063SBarry Smith     for (i=0; i<m; i++) {
2013416022c9SBarry Smith       n   = diag[i] - a->i[i];
2014ed480e8bSBarry Smith       idx = a->j + a->i[i];
20152e5835c6SStefano Zampini       v   = aa + a->i[i];
201617ab2063SBarry Smith       sum = t[i];
2017003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
2018ed480e8bSBarry Smith       t[i] = sum*idiag[i];
2019733d66baSBarry Smith       /*  x = x + t */
2020733d66baSBarry Smith       x[i] += t[i];
202117ab2063SBarry Smith     }
202217ab2063SBarry Smith 
20239566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(6.0*m-1 + 2.0*a->nz));
20249566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(xx,&x));
20259566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(bb,&b));
20263a40ed3dSBarry Smith     PetscFunctionReturn(0);
202717ab2063SBarry Smith   }
202817ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
202917ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
203017ab2063SBarry Smith       for (i=0; i<m; i++) {
2031416022c9SBarry Smith         n   = diag[i] - a->i[i];
2032ed480e8bSBarry Smith         idx = a->j + a->i[i];
20332e5835c6SStefano Zampini         v   = aa + a->i[i];
203417ab2063SBarry Smith         sum = b[i];
2035e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20365c99c7daSBarry Smith         t[i] = sum;
2037ed480e8bSBarry Smith         x[i] = sum*idiag[i];
203817ab2063SBarry Smith       }
20395c99c7daSBarry Smith       xb   = t;
20409566063dSJacob Faibussowitsch       PetscCall(PetscLogFlops(a->nz));
20413a40ed3dSBarry Smith     } else xb = b;
204217ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
204317ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2044416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
2045ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
20462e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
204717ab2063SBarry Smith         sum = xb[i];
2048e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20495c99c7daSBarry Smith         if (xb == b) {
2050ed480e8bSBarry Smith           x[i] = sum*idiag[i];
20515c99c7daSBarry Smith         } else {
2052b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
205317ab2063SBarry Smith         }
20545c99c7daSBarry Smith       }
20559566063dSJacob Faibussowitsch       PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */
205617ab2063SBarry Smith     }
205717ab2063SBarry Smith     its--;
205817ab2063SBarry Smith   }
205917ab2063SBarry Smith   while (its--) {
206017ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
206117ab2063SBarry Smith       for (i=0; i<m; i++) {
2062b19a5dc2SMark Adams         /* lower */
2063b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
2064ed480e8bSBarry Smith         idx = a->j + a->i[i];
20652e5835c6SStefano Zampini         v   = aa + a->i[i];
206617ab2063SBarry Smith         sum = b[i];
2067e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2068b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
2069b19a5dc2SMark Adams         /* upper */
2070b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
2071b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
20722e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
2073b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2074b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
207517ab2063SBarry Smith       }
2076b19a5dc2SMark Adams       xb   = t;
20779566063dSJacob Faibussowitsch       PetscCall(PetscLogFlops(2.0*a->nz));
2078b19a5dc2SMark Adams     } else xb = b;
207917ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
208017ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2081b19a5dc2SMark Adams         sum = xb[i];
2082b19a5dc2SMark Adams         if (xb == b) {
2083b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
2084416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
2085ed480e8bSBarry Smith           idx = a->j + a->i[i];
20862e5835c6SStefano Zampini           v   = aa + a->i[i];
2087e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2088ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
2089b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
2090b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
2091b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
20922e5835c6SStefano Zampini           v   = aa + diag[i] + 1;
2093b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2094b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
209517ab2063SBarry Smith         }
2096b19a5dc2SMark Adams       }
2097b19a5dc2SMark Adams       if (xb == b) {
20989566063dSJacob Faibussowitsch         PetscCall(PetscLogFlops(2.0*a->nz));
2099b19a5dc2SMark Adams       } else {
21009566063dSJacob Faibussowitsch         PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */
2101b19a5dc2SMark Adams       }
210217ab2063SBarry Smith     }
210317ab2063SBarry Smith   }
21049566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
21059566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx,&x));
21069566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb,&b));
2107365a8a9eSBarry Smith   PetscFunctionReturn(0);
210817ab2063SBarry Smith }
210917ab2063SBarry Smith 
2110dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
211117ab2063SBarry Smith {
2112416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
21134e220ebcSLois Curfman McInnes 
21143a40ed3dSBarry Smith   PetscFunctionBegin;
21154e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
21163966268fSBarry Smith   info->nz_allocated = a->maxnz;
21173966268fSBarry Smith   info->nz_used      = a->nz;
21183966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
21193966268fSBarry Smith   info->assemblies   = A->num_ass;
21203966268fSBarry Smith   info->mallocs      = A->info.mallocs;
21217adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
2122d5f3da31SBarry Smith   if (A->factortype) {
21234e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
21244e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
21254e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
21264e220ebcSLois Curfman McInnes   } else {
21274e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
21284e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
21294e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
21304e220ebcSLois Curfman McInnes   }
21313a40ed3dSBarry Smith   PetscFunctionReturn(0);
213217ab2063SBarry Smith }
213317ab2063SBarry Smith 
21342b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
213517ab2063SBarry Smith {
2136416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2137c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
213897b48c8fSBarry Smith   const PetscScalar *xx;
21392e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
2140c7da8527SEric Chamberland   PetscInt          d = 0;
214117ab2063SBarry Smith 
21423a40ed3dSBarry Smith   PetscFunctionBegin;
214397b48c8fSBarry Smith   if (x && b) {
21449566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x,&xx));
21459566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b,&bb));
214697b48c8fSBarry Smith     for (i=0; i<N; i++) {
2147aed4548fSBarry Smith       PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
2148447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
214997b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
215097b48c8fSBarry Smith     }
21519566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x,&xx));
21529566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b,&bb));
215397b48c8fSBarry Smith   }
215497b48c8fSBarry Smith 
21559566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A,&aa));
2156a9817697SBarry Smith   if (a->keepnonzeropattern) {
2157f1e2ffcdSBarry Smith     for (i=0; i<N; i++) {
2158aed4548fSBarry Smith       PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
21599566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]));
2160f1e2ffcdSBarry Smith     }
2161f4df32b1SMatthew Knepley     if (diag != 0.0) {
2162c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2163c7da8527SEric Chamberland         d = rows[i];
2164447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
216508401ef6SPierre Jolivet         PetscCheck(a->diag[d] < a->i[d+1],PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in the zeroed row %" PetscInt_FMT,d);
2166c7da8527SEric Chamberland       }
2167f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2168447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
21692e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
2170f1e2ffcdSBarry Smith       }
2171f1e2ffcdSBarry Smith     }
2172f1e2ffcdSBarry Smith   } else {
2173f4df32b1SMatthew Knepley     if (diag != 0.0) {
217417ab2063SBarry Smith       for (i=0; i<N; i++) {
2175aed4548fSBarry Smith         PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
21767ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2177447d62f5SStefano Zampini           if (rows[i] >= A->cmap->n) {
2178447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2179447d62f5SStefano Zampini           } else {
2180416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
21812e5835c6SStefano Zampini             aa[a->i[rows[i]]]   = diag;
2182bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2183447d62f5SStefano Zampini           }
2184447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
21859566063dSJacob Faibussowitsch           PetscCall(MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES));
218617ab2063SBarry Smith         }
218717ab2063SBarry Smith       }
21883a40ed3dSBarry Smith     } else {
218917ab2063SBarry Smith       for (i=0; i<N; i++) {
2190aed4548fSBarry Smith         PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
2191416022c9SBarry Smith         a->ilen[rows[i]] = 0;
219217ab2063SBarry Smith       }
219317ab2063SBarry Smith     }
2194e56f5c9eSBarry Smith     A->nonzerostate++;
2195f1e2ffcdSBarry Smith   }
21969566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A,&aa));
21979566063dSJacob Faibussowitsch   PetscCall((*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY));
21983a40ed3dSBarry Smith   PetscFunctionReturn(0);
219917ab2063SBarry Smith }
220017ab2063SBarry Smith 
22016e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
22026e169961SBarry Smith {
22036e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
22046e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
22052b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
22066e169961SBarry Smith   const PetscScalar *xx;
22072e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
22086e169961SBarry Smith 
22096e169961SBarry Smith   PetscFunctionBegin;
22102e5835c6SStefano Zampini   if (!N) PetscFunctionReturn(0);
22119566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A,&aa));
22126e169961SBarry Smith   if (x && b) {
22139566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x,&xx));
22149566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b,&bb));
22152b40b63fSBarry Smith     vecs = PETSC_TRUE;
22166e169961SBarry Smith   }
22179566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(A->rmap->n,&zeroed));
22186e169961SBarry Smith   for (i=0; i<N; i++) {
2219aed4548fSBarry Smith     PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
22209566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]));
22212205254eSKarl Rupp 
22226e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
22236e169961SBarry Smith   }
22246e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
22256e169961SBarry Smith     if (!zeroed[i]) {
22266e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
22274cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
22282e5835c6SStefano Zampini           if (vecs) bb[i] -= aa[j]*xx[a->j[j]];
22292e5835c6SStefano Zampini           aa[j] = 0.0;
22306e169961SBarry Smith         }
22316e169961SBarry Smith       }
22324cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
22336e169961SBarry Smith   }
22346e169961SBarry Smith   if (x && b) {
22359566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x,&xx));
22369566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b,&bb));
22376e169961SBarry Smith   }
22389566063dSJacob Faibussowitsch   PetscCall(PetscFree(zeroed));
22396e169961SBarry Smith   if (diag != 0.0) {
22409566063dSJacob Faibussowitsch     PetscCall(MatMissingDiagonal_SeqAIJ(A,&missing,&d));
22411d5a398dSstefano_zampini     if (missing) {
22421d5a398dSstefano_zampini       for (i=0; i<N; i++) {
22434cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
2244aed4548fSBarry 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]);
22459566063dSJacob Faibussowitsch         PetscCall(MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES));
22461d5a398dSstefano_zampini       }
22471d5a398dSstefano_zampini     } else {
22486e169961SBarry Smith       for (i=0; i<N; i++) {
22492e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
22506e169961SBarry Smith       }
22516e169961SBarry Smith     }
22521d5a398dSstefano_zampini   }
22539566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A,&aa));
22549566063dSJacob Faibussowitsch   PetscCall((*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY));
22556e169961SBarry Smith   PetscFunctionReturn(0);
22566e169961SBarry Smith }
22576e169961SBarry Smith 
2258a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
225917ab2063SBarry Smith {
2260fff043a9SJunchao Zhang   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2261fff043a9SJunchao Zhang   const PetscScalar *aa;
2262fff043a9SJunchao Zhang   PetscInt          *itmp;
226317ab2063SBarry Smith 
22643a40ed3dSBarry Smith   PetscFunctionBegin;
22659566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&aa));
2266416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
22672e5835c6SStefano Zampini   if (v) *v = (PetscScalar*)(aa + a->i[row]);
226817ab2063SBarry Smith   if (idx) {
2269bfeeae90SHong Zhang     itmp = a->j + a->i[row];
227026fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
2271f4259b30SLisandro Dalcin     else *idx = NULL;
227217ab2063SBarry Smith   }
22739566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
22743a40ed3dSBarry Smith   PetscFunctionReturn(0);
227517ab2063SBarry Smith }
227617ab2063SBarry Smith 
2277a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
227817ab2063SBarry Smith {
22793a40ed3dSBarry Smith   PetscFunctionBegin;
2280cb4a9cd9SHong Zhang   if (nz)  *nz = 0;
22812e5835c6SStefano Zampini   if (idx) *idx = NULL;
22822e5835c6SStefano Zampini   if (v)   *v = NULL;
22833a40ed3dSBarry Smith   PetscFunctionReturn(0);
228417ab2063SBarry Smith }
228517ab2063SBarry Smith 
2286dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
228717ab2063SBarry Smith {
2288416022c9SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
22892e5835c6SStefano Zampini   const MatScalar *v;
229036db0b34SBarry Smith   PetscReal       sum = 0.0;
229197f1f81fSBarry Smith   PetscInt        i,j;
229217ab2063SBarry Smith 
22933a40ed3dSBarry Smith   PetscFunctionBegin;
22949566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&v));
229517ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2296570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2297570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
229873cf7048SBarry Smith     PetscStackCallBLAS("BLASnrm2",*nrm = BLASnrm2_(&nz,v,&one));
2299570b7f6dSBarry Smith #else
2300416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
230136db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
230217ab2063SBarry Smith     }
23038f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2304570b7f6dSBarry Smith #endif
23059566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0*a->nz));
23063a40ed3dSBarry Smith   } else if (type == NORM_1) {
230736db0b34SBarry Smith     PetscReal *tmp;
230897f1f81fSBarry Smith     PetscInt  *jj = a->j;
23099566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(A->cmap->n+1,&tmp));
2310064f8208SBarry Smith     *nrm = 0.0;
2311416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2312bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
231317ab2063SBarry Smith     }
2314d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2315064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
231617ab2063SBarry Smith     }
23179566063dSJacob Faibussowitsch     PetscCall(PetscFree(tmp));
23189566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(PetscMax(a->nz-1,0)));
23193a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2320064f8208SBarry Smith     *nrm = 0.0;
2321d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
23222e5835c6SStefano Zampini       const PetscScalar *v2 = v + a->i[j];
232317ab2063SBarry Smith       sum = 0.0;
2324416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
23252e5835c6SStefano Zampini         sum += PetscAbsScalar(*v2); v2++;
232617ab2063SBarry Smith       }
2327064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
232817ab2063SBarry Smith     }
23299566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(PetscMax(a->nz-1,0)));
2330f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
23319566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&v));
23323a40ed3dSBarry Smith   PetscFunctionReturn(0);
233317ab2063SBarry Smith }
233417ab2063SBarry Smith 
23354e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
23364e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
23374e938277SHong Zhang {
23384e938277SHong Zhang   PetscInt       i,j,anzj;
23394e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
23404e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
23414e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
23424e938277SHong Zhang 
23434e938277SHong Zhang   PetscFunctionBegin;
23444e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
23459566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(an+1,&ati));
23469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ai[am],&atj));
23479566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(an,&atfill));
23484e938277SHong Zhang 
23494e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
23504e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
235126fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
23524e938277SHong Zhang   /* Form ati for csr format of A^T. */
235326fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
23544e938277SHong Zhang 
23554e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
23569566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(atfill,ati,an));
23574e938277SHong Zhang 
23584e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
23594e938277SHong Zhang   for (i=0;i<am;i++) {
23604e938277SHong Zhang     anzj = ai[i+1] - ai[i];
23614e938277SHong Zhang     for (j=0;j<anzj;j++) {
23624e938277SHong Zhang       atj[atfill[*aj]] = i;
23634e938277SHong Zhang       atfill[*aj++]   += 1;
23644e938277SHong Zhang     }
23654e938277SHong Zhang   }
23664e938277SHong Zhang 
23674e938277SHong Zhang   /* Clean up temporary space and complete requests. */
23689566063dSJacob Faibussowitsch   PetscCall(PetscFree(atfill));
23699566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B));
23709566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs)));
23719566063dSJacob Faibussowitsch   PetscCall(MatSetType(*B,((PetscObject)A)->type_name));
2372a2f3521dSMark F. Adams 
23734e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
23744e938277SHong Zhang   b->free_a  = PETSC_FALSE;
23754e938277SHong Zhang   b->free_ij = PETSC_TRUE;
23764e938277SHong Zhang   b->nonew   = 0;
23774e938277SHong Zhang   PetscFunctionReturn(0);
23784e938277SHong Zhang }
23794e938277SHong Zhang 
23807087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2381cd0d46ebSvictorle {
23823d3eaba7SBarry Smith   Mat_SeqAIJ      *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
238354f21887SBarry Smith   PetscInt        *adx,*bdx,*aii,*bii,*aptr,*bptr;
23842e5835c6SStefano Zampini   const MatScalar *va,*vb;
238597f1f81fSBarry Smith   PetscInt        ma,na,mb,nb, i;
2386cd0d46ebSvictorle 
2387cd0d46ebSvictorle   PetscFunctionBegin;
23889566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,&ma,&na));
23899566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B,&mb,&nb));
23905485867bSBarry Smith   if (ma!=nb || na!=mb) {
23915485867bSBarry Smith     *f = PETSC_FALSE;
23925485867bSBarry Smith     PetscFunctionReturn(0);
23935485867bSBarry Smith   }
23949566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&va));
23959566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(B,&vb));
2396cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2397cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
23989566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ma,&aptr));
23999566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(mb,&bptr));
2400cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2401cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2402cd0d46ebSvictorle 
2403cd0d46ebSvictorle   *f = PETSC_TRUE;
2404cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2405cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
240697f1f81fSBarry Smith       PetscInt    idc,idr;
24075485867bSBarry Smith       PetscScalar vc,vr;
2408cd0d46ebSvictorle       /* column/row index/value */
24095485867bSBarry Smith       idc = adx[aptr[i]];
24105485867bSBarry Smith       idr = bdx[bptr[idc]];
24115485867bSBarry Smith       vc  = va[aptr[i]];
24125485867bSBarry Smith       vr  = vb[bptr[idc]];
24135485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
24145485867bSBarry Smith         *f = PETSC_FALSE;
24155485867bSBarry Smith         goto done;
2416cd0d46ebSvictorle       } else {
24175485867bSBarry Smith         aptr[i]++;
24185485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2419cd0d46ebSvictorle       }
2420cd0d46ebSvictorle     }
2421cd0d46ebSvictorle   }
2422cd0d46ebSvictorle done:
24239566063dSJacob Faibussowitsch   PetscCall(PetscFree(aptr));
24249566063dSJacob Faibussowitsch   PetscCall(PetscFree(bptr));
24259566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&va));
24269566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(B,&vb));
2427cd0d46ebSvictorle   PetscFunctionReturn(0);
2428cd0d46ebSvictorle }
2429cd0d46ebSvictorle 
24307087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
24311cbb95d3SBarry Smith {
24323d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
243354f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
243454f21887SBarry Smith   MatScalar      *va,*vb;
24351cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
24361cbb95d3SBarry Smith 
24371cbb95d3SBarry Smith   PetscFunctionBegin;
24389566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,&ma,&na));
24399566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B,&mb,&nb));
24401cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
24411cbb95d3SBarry Smith     *f = PETSC_FALSE;
24421cbb95d3SBarry Smith     PetscFunctionReturn(0);
24431cbb95d3SBarry Smith   }
24441cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
24451cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
24461cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
24479566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ma,&aptr));
24489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(mb,&bptr));
24491cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
24501cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
24511cbb95d3SBarry Smith 
24521cbb95d3SBarry Smith   *f = PETSC_TRUE;
24531cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
24541cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
24551cbb95d3SBarry Smith       PetscInt    idc,idr;
24561cbb95d3SBarry Smith       PetscScalar vc,vr;
24571cbb95d3SBarry Smith       /* column/row index/value */
24581cbb95d3SBarry Smith       idc = adx[aptr[i]];
24591cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
24601cbb95d3SBarry Smith       vc  = va[aptr[i]];
24611cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
24621cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
24631cbb95d3SBarry Smith         *f = PETSC_FALSE;
24641cbb95d3SBarry Smith         goto done;
24651cbb95d3SBarry Smith       } else {
24661cbb95d3SBarry Smith         aptr[i]++;
24671cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
24681cbb95d3SBarry Smith       }
24691cbb95d3SBarry Smith     }
24701cbb95d3SBarry Smith   }
24711cbb95d3SBarry Smith done:
24729566063dSJacob Faibussowitsch   PetscCall(PetscFree(aptr));
24739566063dSJacob Faibussowitsch   PetscCall(PetscFree(bptr));
24741cbb95d3SBarry Smith   PetscFunctionReturn(0);
24751cbb95d3SBarry Smith }
24761cbb95d3SBarry Smith 
2477ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
24789e29f15eSvictorle {
24799e29f15eSvictorle   PetscFunctionBegin;
24809566063dSJacob Faibussowitsch   PetscCall(MatIsTranspose_SeqAIJ(A,A,tol,f));
24819e29f15eSvictorle   PetscFunctionReturn(0);
24829e29f15eSvictorle }
24839e29f15eSvictorle 
2484ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
24851cbb95d3SBarry Smith {
24861cbb95d3SBarry Smith   PetscFunctionBegin;
24879566063dSJacob Faibussowitsch   PetscCall(MatIsHermitianTranspose_SeqAIJ(A,A,tol,f));
24881cbb95d3SBarry Smith   PetscFunctionReturn(0);
24891cbb95d3SBarry Smith }
24901cbb95d3SBarry Smith 
2491dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
249217ab2063SBarry Smith {
2493416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2494fff8e43fSBarry Smith   const PetscScalar *l,*r;
2495fff8e43fSBarry Smith   PetscScalar       x;
249654f21887SBarry Smith   MatScalar         *v;
2497fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2498fff8e43fSBarry Smith   const PetscInt    *jj;
249917ab2063SBarry Smith 
25003a40ed3dSBarry Smith   PetscFunctionBegin;
250117ab2063SBarry Smith   if (ll) {
25023ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
25033ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
25049566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(ll,&m));
250508401ef6SPierre Jolivet     PetscCheck(m == A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
25069566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ll,&l));
25079566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(A,&v));
250817ab2063SBarry Smith     for (i=0; i<m; i++) {
250917ab2063SBarry Smith       x = l[i];
2510416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
25112205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
251217ab2063SBarry Smith     }
25139566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ll,&l));
25149566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(nz));
25159566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArray(A,&v));
251617ab2063SBarry Smith   }
251717ab2063SBarry Smith   if (rr) {
25189566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(rr,&n));
251908401ef6SPierre Jolivet     PetscCheck(n == A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
25209566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rr,&r));
25219566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(A,&v));
25222e5835c6SStefano Zampini     jj = a->j;
25232205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
25249566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArray(A,&v));
25259566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rr,&r));
25269566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(nz));
252717ab2063SBarry Smith   }
25289566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(A));
25293a40ed3dSBarry Smith   PetscFunctionReturn(0);
253017ab2063SBarry Smith }
253117ab2063SBarry Smith 
25327dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
253317ab2063SBarry Smith {
2534db02288aSLois Curfman McInnes   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*c;
2535d0f46423SBarry Smith   PetscInt          *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
253697f1f81fSBarry Smith   PetscInt          row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
25375d0c19d7SBarry Smith   const PetscInt    *irow,*icol;
25382e5835c6SStefano Zampini   const PetscScalar *aa;
25395d0c19d7SBarry Smith   PetscInt          nrows,ncols;
254097f1f81fSBarry Smith   PetscInt          *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
254154f21887SBarry Smith   MatScalar         *a_new,*mat_a;
2542416022c9SBarry Smith   Mat               C;
2543cdc6f3adSToby Isaac   PetscBool         stride;
254417ab2063SBarry Smith 
25453a40ed3dSBarry Smith   PetscFunctionBegin;
25469566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(isrow,&irow));
25479566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow,&nrows));
25489566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol,&ncols));
254917ab2063SBarry Smith 
25509566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride));
2551ff718158SBarry Smith   if (stride) {
25529566063dSJacob Faibussowitsch     PetscCall(ISStrideGetInfo(iscol,&first,&step));
2553ff718158SBarry Smith   } else {
2554ff718158SBarry Smith     first = 0;
2555ff718158SBarry Smith     step  = 0;
2556ff718158SBarry Smith   }
2557fee21e36SBarry Smith   if (stride && step == 1) {
255802834360SBarry Smith     /* special case of contiguous rows */
25599566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nrows,&lens,nrows,&starts));
256002834360SBarry Smith     /* loop over new rows determining lens and starting points */
256102834360SBarry Smith     for (i=0; i<nrows; i++) {
2562bfeeae90SHong Zhang       kstart = ai[irow[i]];
2563a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2564a91a9bebSLisandro Dalcin       starts[i] = kstart;
256502834360SBarry Smith       for (k=kstart; k<kend; k++) {
2566bfeeae90SHong Zhang         if (aj[k] >= first) {
256702834360SBarry Smith           starts[i] = k;
256802834360SBarry Smith           break;
256902834360SBarry Smith         }
257002834360SBarry Smith       }
2571a2744918SBarry Smith       sum = 0;
257202834360SBarry Smith       while (k < kend) {
2573bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2574a2744918SBarry Smith         sum++;
257502834360SBarry Smith       }
2576a2744918SBarry Smith       lens[i] = sum;
257702834360SBarry Smith     }
257802834360SBarry Smith     /* create submatrix */
2579cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
258097f1f81fSBarry Smith       PetscInt n_cols,n_rows;
25819566063dSJacob Faibussowitsch       PetscCall(MatGetSize(*B,&n_rows,&n_cols));
2582aed4548fSBarry Smith       PetscCheck(n_rows == nrows && n_cols == ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
25839566063dSJacob Faibussowitsch       PetscCall(MatZeroEntries(*B));
258408480c60SBarry Smith       C    = *B;
25853a40ed3dSBarry Smith     } else {
25863bef6203SJed Brown       PetscInt rbs,cbs;
25879566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&C));
25889566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE));
25899566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(isrow,&rbs));
25909566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(iscol,&cbs));
25919566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizes(C,rbs,cbs));
25929566063dSJacob Faibussowitsch       PetscCall(MatSetType(C,((PetscObject)A)->type_name));
25939566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens));
259408480c60SBarry Smith     }
2595db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2596db02288aSLois Curfman McInnes 
259702834360SBarry Smith     /* loop over rows inserting into submatrix */
2598db02288aSLois Curfman McInnes     a_new = c->a;
2599db02288aSLois Curfman McInnes     j_new = c->j;
2600db02288aSLois Curfman McInnes     i_new = c->i;
26019566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(A,&aa));
260202834360SBarry Smith     for (i=0; i<nrows; i++) {
2603a2744918SBarry Smith       ii    = starts[i];
2604a2744918SBarry Smith       lensi = lens[i];
2605a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2606a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
260702834360SBarry Smith       }
26089566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(a_new,aa + starts[i],lensi));
2609a2744918SBarry Smith       a_new     += lensi;
2610a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2611a2744918SBarry Smith       c->ilen[i] = lensi;
261202834360SBarry Smith     }
26139566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
26149566063dSJacob Faibussowitsch     PetscCall(PetscFree2(lens,starts));
26153a40ed3dSBarry Smith   } else {
26169566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(iscol,&icol));
26179566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(oldcols,&smap));
26189566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(1+nrows,&lens));
26194dcab191SBarry Smith     for (i=0; i<ncols; i++) {
26206bdcaf15SBarry 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);
26214dcab191SBarry Smith       smap[icol[i]] = i+1;
26224dcab191SBarry Smith     }
26234dcab191SBarry Smith 
262402834360SBarry Smith     /* determine lens of each row */
262502834360SBarry Smith     for (i=0; i<nrows; i++) {
2626bfeeae90SHong Zhang       kstart  = ai[irow[i]];
262702834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
262802834360SBarry Smith       lens[i] = 0;
262902834360SBarry Smith       for (k=kstart; k<kend; k++) {
2630bfeeae90SHong Zhang         if (smap[aj[k]]) {
263102834360SBarry Smith           lens[i]++;
263202834360SBarry Smith         }
263302834360SBarry Smith       }
263402834360SBarry Smith     }
263517ab2063SBarry Smith     /* Create and fill new matrix */
2636a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2637ace3abfcSBarry Smith       PetscBool equal;
26380f5bd95cSBarry Smith 
263999141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
2640aed4548fSBarry Smith       PetscCheck((*B)->rmap->n  == nrows && (*B)->cmap->n == ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
26419566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal));
264228b400f6SJacob Faibussowitsch       PetscCheck(equal,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
26439566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(c->ilen,(*B)->rmap->n));
264408480c60SBarry Smith       C    = *B;
26453a40ed3dSBarry Smith     } else {
26463bef6203SJed Brown       PetscInt rbs,cbs;
26479566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&C));
26489566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE));
26499566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(isrow,&rbs));
26509566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(iscol,&cbs));
26519566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizes(C,rbs,cbs));
26529566063dSJacob Faibussowitsch       PetscCall(MatSetType(C,((PetscObject)A)->type_name));
26539566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens));
265408480c60SBarry Smith     }
26559566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(A,&aa));
265699141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
265717ab2063SBarry Smith     for (i=0; i<nrows; i++) {
265899141d43SSatish Balay       row      = irow[i];
2659bfeeae90SHong Zhang       kstart   = ai[row];
266099141d43SSatish Balay       kend     = kstart + a->ilen[row];
2661bfeeae90SHong Zhang       mat_i    = c->i[i];
266299141d43SSatish Balay       mat_j    = c->j + mat_i;
266399141d43SSatish Balay       mat_a    = c->a + mat_i;
266499141d43SSatish Balay       mat_ilen = c->ilen + i;
266517ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2666bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2667ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
26682e5835c6SStefano Zampini           *mat_a++ = aa[k];
266999141d43SSatish Balay           (*mat_ilen)++;
267099141d43SSatish Balay 
267117ab2063SBarry Smith         }
267217ab2063SBarry Smith       }
267317ab2063SBarry Smith     }
26749566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
267502834360SBarry Smith     /* Free work space */
26769566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(iscol,&icol));
26779566063dSJacob Faibussowitsch     PetscCall(PetscFree(smap));
26789566063dSJacob Faibussowitsch     PetscCall(PetscFree(lens));
2679cdc6f3adSToby Isaac     /* sort */
2680cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2681cdc6f3adSToby Isaac       PetscInt ilen;
2682cdc6f3adSToby Isaac 
2683cdc6f3adSToby Isaac       mat_i = c->i[i];
2684cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2685cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2686cdc6f3adSToby Isaac       ilen  = c->ilen[i];
26879566063dSJacob Faibussowitsch       PetscCall(PetscSortIntWithScalarArray(ilen,mat_j,mat_a));
2688cdc6f3adSToby Isaac     }
268902834360SBarry Smith   }
26908c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
26919566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU(C,A->boundtocpu));
2692305c6ccfSStefano Zampini #endif
26939566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
26949566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
269517ab2063SBarry Smith 
26969566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(isrow,&irow));
2697416022c9SBarry Smith   *B   = C;
26983a40ed3dSBarry Smith   PetscFunctionReturn(0);
269917ab2063SBarry Smith }
270017ab2063SBarry Smith 
2701fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
270282d44351SHong Zhang {
270382d44351SHong Zhang   Mat            B;
270482d44351SHong Zhang 
270582d44351SHong Zhang   PetscFunctionBegin;
2706c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
27079566063dSJacob Faibussowitsch     PetscCall(MatCreate(subComm,&B));
27089566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n));
27099566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B,mat,mat));
27109566063dSJacob Faibussowitsch     PetscCall(MatSetType(B,MATSEQAIJ));
27119566063dSJacob Faibussowitsch     PetscCall(MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE));
271282d44351SHong Zhang     *subMat = B;
2713c2d650bdSHong Zhang   } else {
27149566063dSJacob Faibussowitsch     PetscCall(MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN));
2715c2d650bdSHong Zhang   }
271682d44351SHong Zhang   PetscFunctionReturn(0);
271782d44351SHong Zhang }
271882d44351SHong Zhang 
27199a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2720a871dcd8SBarry Smith {
272163b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
272263b91edcSBarry Smith   Mat            outA;
2723ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
272463b91edcSBarry Smith 
27253a40ed3dSBarry Smith   PetscFunctionBegin;
272608401ef6SPierre Jolivet   PetscCheck(info->levels == 0,PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
27271df811f5SHong Zhang 
27289566063dSJacob Faibussowitsch   PetscCall(ISIdentity(row,&row_identity));
27299566063dSJacob Faibussowitsch   PetscCall(ISIdentity(col,&col_identity));
2730a871dcd8SBarry Smith 
273163b91edcSBarry Smith   outA             = inA;
2732d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
27339566063dSJacob Faibussowitsch   PetscCall(PetscFree(inA->solvertype));
27349566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype));
27352205254eSKarl Rupp 
27369566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)row));
27379566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->row));
27382205254eSKarl Rupp 
2739c3122656SLisandro Dalcin   a->row = row;
27402205254eSKarl Rupp 
27419566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)col));
27429566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->col));
27432205254eSKarl Rupp 
2744c3122656SLisandro Dalcin   a->col = col;
274563b91edcSBarry Smith 
274636db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
27479566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&a->icol));
27489566063dSJacob Faibussowitsch   PetscCall(ISInvertPermutation(col,PETSC_DECIDE,&a->icol));
27499566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol));
2750f0ec6fceSSatish Balay 
275194a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
27529566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(inA->rmap->n+1,&a->solve_work));
27539566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar)));
275494a9d846SBarry Smith   }
275563b91edcSBarry Smith 
27569566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqAIJ(inA));
2757137fb511SHong Zhang   if (row_identity && col_identity) {
27589566063dSJacob Faibussowitsch     PetscCall(MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info));
2759137fb511SHong Zhang   } else {
27609566063dSJacob Faibussowitsch     PetscCall(MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info));
2761137fb511SHong Zhang   }
27623a40ed3dSBarry Smith   PetscFunctionReturn(0);
2763a871dcd8SBarry Smith }
2764a871dcd8SBarry Smith 
2765f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2766f0b747eeSBarry Smith {
2767f0b747eeSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2768dfa0f9e5SStefano Zampini   PetscScalar    *v;
2769c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
27703a40ed3dSBarry Smith 
27713a40ed3dSBarry Smith   PetscFunctionBegin;
27729566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(inA,&v));
27739566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(a->nz,&bnz));
2774dfa0f9e5SStefano Zampini   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&alpha,v,&one));
27759566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(a->nz));
27769566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(inA,&v));
27779566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(inA));
27783a40ed3dSBarry Smith   PetscFunctionReturn(0);
2779f0b747eeSBarry Smith }
2780f0b747eeSBarry Smith 
2781f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
278216b64355SHong Zhang {
278316b64355SHong Zhang   PetscInt       i;
278416b64355SHong Zhang 
278516b64355SHong Zhang   PetscFunctionBegin;
278616b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
27879566063dSJacob Faibussowitsch     PetscCall(PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr));
278816b64355SHong Zhang 
278916b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
27909566063dSJacob Faibussowitsch       PetscCall(PetscFree(submatj->sbuf2[i]));
279116b64355SHong Zhang     }
27929566063dSJacob Faibussowitsch     PetscCall(PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1));
279316b64355SHong Zhang 
279416b64355SHong Zhang     if (submatj->rbuf1) {
27959566063dSJacob Faibussowitsch       PetscCall(PetscFree(submatj->rbuf1[0]));
27969566063dSJacob Faibussowitsch       PetscCall(PetscFree(submatj->rbuf1));
279716b64355SHong Zhang     }
279816b64355SHong Zhang 
279916b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
28009566063dSJacob Faibussowitsch       PetscCall(PetscFree(submatj->rbuf3[i]));
280116b64355SHong Zhang     }
28029566063dSJacob Faibussowitsch     PetscCall(PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3));
28039566063dSJacob Faibussowitsch     PetscCall(PetscFree(submatj->pa));
280416b64355SHong Zhang   }
280516b64355SHong Zhang 
280616b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
28079566063dSJacob Faibussowitsch   PetscCall(PetscTableDestroy((PetscTable*)&submatj->rmap));
28089566063dSJacob Faibussowitsch   if (submatj->cmap_loc) PetscCall(PetscFree(submatj->cmap_loc));
28099566063dSJacob Faibussowitsch   PetscCall(PetscFree(submatj->rmap_loc));
281016b64355SHong Zhang #else
28119566063dSJacob Faibussowitsch   PetscCall(PetscFree(submatj->rmap));
281216b64355SHong Zhang #endif
281316b64355SHong Zhang 
281416b64355SHong Zhang   if (!submatj->allcolumns) {
281516b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
28169566063dSJacob Faibussowitsch     PetscCall(PetscTableDestroy((PetscTable*)&submatj->cmap));
281716b64355SHong Zhang #else
28189566063dSJacob Faibussowitsch     PetscCall(PetscFree(submatj->cmap));
281916b64355SHong Zhang #endif
282016b64355SHong Zhang   }
28219566063dSJacob Faibussowitsch   PetscCall(PetscFree(submatj->row2proc));
282216b64355SHong Zhang 
28239566063dSJacob Faibussowitsch   PetscCall(PetscFree(submatj));
282416b64355SHong Zhang   PetscFunctionReturn(0);
282516b64355SHong Zhang }
282616b64355SHong Zhang 
28270fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
282816b64355SHong Zhang {
282916b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
28305c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
283116b64355SHong Zhang 
283216b64355SHong Zhang   PetscFunctionBegin;
28339566063dSJacob Faibussowitsch   PetscCall((*submatj->destroy)(C));
28349566063dSJacob Faibussowitsch   PetscCall(MatDestroySubMatrix_Private(submatj));
283516b64355SHong Zhang   PetscFunctionReturn(0);
283616b64355SHong Zhang }
283716b64355SHong Zhang 
28382d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
28392d033e1fSHong Zhang {
28402d033e1fSHong Zhang   PetscInt       i;
28410fb991dcSHong Zhang   Mat            C;
28420fb991dcSHong Zhang   Mat_SeqAIJ     *c;
28430fb991dcSHong Zhang   Mat_SubSppt    *submatj;
28442d033e1fSHong Zhang 
28452d033e1fSHong Zhang   PetscFunctionBegin;
28462d033e1fSHong Zhang   for (i=0; i<n; i++) {
28470fb991dcSHong Zhang     C       = (*mat)[i];
28480fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
28490fb991dcSHong Zhang     submatj = c->submatis1;
28502d033e1fSHong Zhang     if (submatj) {
2851682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
28529566063dSJacob Faibussowitsch         PetscCall((*submatj->destroy)(C));
28539566063dSJacob Faibussowitsch         PetscCall(MatDestroySubMatrix_Private(submatj));
28549566063dSJacob Faibussowitsch         PetscCall(PetscFree(C->defaultvectype));
28559566063dSJacob Faibussowitsch         PetscCall(PetscLayoutDestroy(&C->rmap));
28569566063dSJacob Faibussowitsch         PetscCall(PetscLayoutDestroy(&C->cmap));
28579566063dSJacob Faibussowitsch         PetscCall(PetscHeaderDestroy(&C));
2858682e4c99SStefano Zampini       }
28592d033e1fSHong Zhang     } else {
28609566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
28612d033e1fSHong Zhang     }
28622d033e1fSHong Zhang   }
286386e85357SHong Zhang 
286463a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
28659566063dSJacob Faibussowitsch   PetscCall(MatDestroySubMatrices_Dummy(n,mat));
286663a75b2aSHong Zhang 
28679566063dSJacob Faibussowitsch   PetscCall(PetscFree(*mat));
28682d033e1fSHong Zhang   PetscFunctionReturn(0);
28692d033e1fSHong Zhang }
28702d033e1fSHong Zhang 
28717dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2872cddf8d76SBarry Smith {
287397f1f81fSBarry Smith   PetscInt       i;
2874cddf8d76SBarry Smith 
28753a40ed3dSBarry Smith   PetscFunctionBegin;
2876cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
28779566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(n+1,B));
2878cddf8d76SBarry Smith   }
2879cddf8d76SBarry Smith 
2880cddf8d76SBarry Smith   for (i=0; i<n; i++) {
28819566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]));
2882cddf8d76SBarry Smith   }
28833a40ed3dSBarry Smith   PetscFunctionReturn(0);
2884cddf8d76SBarry Smith }
2885cddf8d76SBarry Smith 
288697f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
28874dcbc457SBarry Smith {
2888e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
28895d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
28905d0c19d7SBarry Smith   const PetscInt *idx;
289197f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2892f1af5d2fSBarry Smith   PetscBT        table;
2893bbd702dbSSatish Balay 
28943a40ed3dSBarry Smith   PetscFunctionBegin;
2895d0f46423SBarry Smith   m  = A->rmap->n;
2896e4d965acSSatish Balay   ai = a->i;
2897bfeeae90SHong Zhang   aj = a->j;
28988a047759SSatish Balay 
289908401ef6SPierre Jolivet   PetscCheck(ov >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
290006763907SSatish Balay 
29019566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m+1,&nidx));
29029566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(m,&table));
290306763907SSatish Balay 
2904e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2905b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2906e4d965acSSatish Balay     isz  = 0;
29079566063dSJacob Faibussowitsch     PetscCall(PetscBTMemzero(m,table));
2908e4d965acSSatish Balay 
2909e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
29109566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is[i],&idx));
29119566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(is[i],&n));
2912e4d965acSSatish Balay 
2913dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2914e4d965acSSatish Balay     for (j=0; j<n; ++j) {
29152205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
29164dcbc457SBarry Smith     }
29179566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is[i],&idx));
29189566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is[i]));
2919e4d965acSSatish Balay 
292004a348a9SBarry Smith     k = 0;
292104a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
292204a348a9SBarry Smith       n = isz;
292306763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
2924e4d965acSSatish Balay         row   = nidx[k];
2925e4d965acSSatish Balay         start = ai[row];
2926e4d965acSSatish Balay         end   = ai[row+1];
292704a348a9SBarry Smith         for (l = start; l<end; l++) {
2928efb16452SHong Zhang           val = aj[l];
29292205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
2930e4d965acSSatish Balay         }
2931e4d965acSSatish Balay       }
2932e4d965acSSatish Balay     }
29339566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i)));
2934e4d965acSSatish Balay   }
29359566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&table));
29369566063dSJacob Faibussowitsch   PetscCall(PetscFree(nidx));
29373a40ed3dSBarry Smith   PetscFunctionReturn(0);
29384dcbc457SBarry Smith }
293917ab2063SBarry Smith 
29400513a670SBarry Smith /* -------------------------------------------------------------- */
2941dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
29420513a670SBarry Smith {
29430513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29443b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
29455d0c19d7SBarry Smith   const PetscInt *row,*col;
29465d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
294756cd22aeSBarry Smith   IS             icolp,irowp;
29480298fd71SBarry Smith   PetscInt       *cwork = NULL;
29490298fd71SBarry Smith   PetscScalar    *vwork = NULL;
29500513a670SBarry Smith 
29513a40ed3dSBarry Smith   PetscFunctionBegin;
29529566063dSJacob Faibussowitsch   PetscCall(ISInvertPermutation(rowp,PETSC_DECIDE,&irowp));
29539566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(irowp,&row));
29549566063dSJacob Faibussowitsch   PetscCall(ISInvertPermutation(colp,PETSC_DECIDE,&icolp));
29559566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(icolp,&col));
29560513a670SBarry Smith 
29570513a670SBarry Smith   /* determine lengths of permuted rows */
29589566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m+1,&lens));
29592205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
29609566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A),B));
29619566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*B,m,n,m,n));
29629566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(*B,A,A));
29639566063dSJacob Faibussowitsch   PetscCall(MatSetType(*B,((PetscObject)A)->type_name));
29649566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens));
29659566063dSJacob Faibussowitsch   PetscCall(PetscFree(lens));
29660513a670SBarry Smith 
29679566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n,&cnew));
29680513a670SBarry Smith   for (i=0; i<m; i++) {
29699566063dSJacob Faibussowitsch     PetscCall(MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork));
29702205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
29719566063dSJacob Faibussowitsch     PetscCall(MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES));
29729566063dSJacob Faibussowitsch     PetscCall(MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork));
29730513a670SBarry Smith   }
29749566063dSJacob Faibussowitsch   PetscCall(PetscFree(cnew));
29752205254eSKarl Rupp 
29763c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
29772205254eSKarl Rupp 
29788c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
29799566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU(*B,A->boundtocpu));
29809fe5e383SStefano Zampini #endif
29819566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY));
29829566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY));
29839566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(irowp,&row));
29849566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(icolp,&col));
29859566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&irowp));
29869566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&icolp));
29876768869dSprj-   if (rowp == colp) {
29889566063dSJacob Faibussowitsch     PetscCall(MatPropagateSymmetryOptions(A,*B));
29896768869dSprj-   }
29903a40ed3dSBarry Smith   PetscFunctionReturn(0);
29910513a670SBarry Smith }
29920513a670SBarry Smith 
2993dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
2994cb5b572fSBarry Smith {
2995cb5b572fSBarry Smith   PetscFunctionBegin;
299633f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
299733f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
2998be6bf707SBarry Smith     Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2999be6bf707SBarry Smith     Mat_SeqAIJ        *b = (Mat_SeqAIJ*)B->data;
30002e5835c6SStefano Zampini     const PetscScalar *aa;
3001be6bf707SBarry Smith 
30029566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(A,&aa));
300308401ef6SPierre 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]);
30049566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(b->a,aa,a->i[A->rmap->n]));
30059566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)B));
30069566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
3007cb5b572fSBarry Smith   } else {
30089566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A,B,str));
3009cb5b572fSBarry Smith   }
3010cb5b572fSBarry Smith   PetscFunctionReturn(0);
3011cb5b572fSBarry Smith }
3012cb5b572fSBarry Smith 
30134994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
3014273d9f13SBarry Smith {
3015273d9f13SBarry Smith   PetscFunctionBegin;
30169566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL));
3017273d9f13SBarry Smith   PetscFunctionReturn(0);
3018273d9f13SBarry Smith }
3019273d9f13SBarry Smith 
3020f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
30216c0721eeSBarry Smith {
30226c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
30236e111a19SKarl Rupp 
30246c0721eeSBarry Smith   PetscFunctionBegin;
30256c0721eeSBarry Smith   *array = a->a;
30266c0721eeSBarry Smith   PetscFunctionReturn(0);
30276c0721eeSBarry Smith }
30286c0721eeSBarry Smith 
3029f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
30306c0721eeSBarry Smith {
30316c0721eeSBarry Smith   PetscFunctionBegin;
3032f38c1e66SStefano Zampini   *array = NULL;
30336c0721eeSBarry Smith   PetscFunctionReturn(0);
30346c0721eeSBarry Smith }
3035273d9f13SBarry Smith 
30368229c054SShri Abhyankar /*
30378229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
30388229c054SShri Abhyankar    have different nonzero structure.
30398229c054SShri Abhyankar */
3040b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
3041ec7775f6SShri Abhyankar {
3042b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
3043ec7775f6SShri Abhyankar 
3044ec7775f6SShri Abhyankar   PetscFunctionBegin;
3045ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
3046ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
3047b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
3048b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
3049b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
30508af7cee1SJed Brown     nnz[i] = 0;
30518af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
3052b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
3053b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
30548af7cee1SJed Brown       nnz[i]++;
30558af7cee1SJed Brown     }
30568af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
3057ec7775f6SShri Abhyankar   }
3058ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
3059ec7775f6SShri Abhyankar }
3060ec7775f6SShri Abhyankar 
3061b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
3062b264fe52SHong Zhang {
3063b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
3064b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
3065b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
3066b264fe52SHong Zhang 
3067b264fe52SHong Zhang   PetscFunctionBegin;
3068b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
30699566063dSJacob Faibussowitsch   PetscCall(MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz));
3070b264fe52SHong Zhang   PetscFunctionReturn(0);
3071b264fe52SHong Zhang }
3072b264fe52SHong Zhang 
3073f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
3074ac90fabeSBarry Smith {
3075ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
3076ac90fabeSBarry Smith 
3077ac90fabeSBarry Smith   PetscFunctionBegin;
3078134adf20SPierre Jolivet   if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) {
3079134adf20SPierre Jolivet     PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE;
3080134adf20SPierre Jolivet     if (e) {
30819566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e));
308281fa06acSBarry Smith       if (e) {
30839566063dSJacob Faibussowitsch         PetscCall(PetscArraycmp(x->j,y->j,y->nz,&e));
3084134adf20SPierre Jolivet         if (e) str = SAME_NONZERO_PATTERN;
308581fa06acSBarry Smith       }
308681fa06acSBarry Smith     }
308754c59aa7SJacob Faibussowitsch     if (!e) PetscCheck(str != SAME_NONZERO_PATTERN,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MatStructure is not SAME_NONZERO_PATTERN");
308881fa06acSBarry Smith   }
3089ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
30902e5835c6SStefano Zampini     const PetscScalar *xa;
30912e5835c6SStefano Zampini     PetscScalar       *ya,alpha = a;
309281fa06acSBarry Smith     PetscBLASInt      one = 1,bnz;
309381fa06acSBarry Smith 
30949566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(x->nz,&bnz));
30959566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(Y,&ya));
30969566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(X,&xa));
30972e5835c6SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,xa,&one,ya,&one));
30989566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(X,&xa));
30999566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArray(Y,&ya));
31009566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0*bnz));
31019566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJInvalidateDiagonal(Y));
31029566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)Y));
3103ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
31049566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y,a,X,str));
3105ac90fabeSBarry Smith   } else {
31068229c054SShri Abhyankar     Mat      B;
31078229c054SShri Abhyankar     PetscInt *nnz;
31089566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Y->rmap->N,&nnz));
31099566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)Y),&B));
31109566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name));
31119566063dSJacob Faibussowitsch     PetscCall(MatSetLayouts(B,Y->rmap,Y->cmap));
31129566063dSJacob Faibussowitsch     PetscCall(MatSetType(B,((PetscObject)Y)->type_name));
31139566063dSJacob Faibussowitsch     PetscCall(MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz));
31149566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(B,0,nnz));
31159566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B,Y,a,X,str));
31169566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y,&B));
31179566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz));
3118ac90fabeSBarry Smith   }
3119ac90fabeSBarry Smith   PetscFunctionReturn(0);
3120ac90fabeSBarry Smith }
3121ac90fabeSBarry Smith 
31222726fb6dSPierre Jolivet PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat)
3123354c94deSBarry Smith {
3124354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3125354c94deSBarry Smith   Mat_SeqAIJ  *aij = (Mat_SeqAIJ*)mat->data;
3126354c94deSBarry Smith   PetscInt     i,nz;
3127354c94deSBarry Smith   PetscScalar *a;
3128354c94deSBarry Smith 
3129354c94deSBarry Smith   PetscFunctionBegin;
3130354c94deSBarry Smith   nz = aij->nz;
31319566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(mat,&a));
31322205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
31339566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(mat,&a));
3134354c94deSBarry Smith #else
3135354c94deSBarry Smith   PetscFunctionBegin;
3136354c94deSBarry Smith #endif
3137354c94deSBarry Smith   PetscFunctionReturn(0);
3138354c94deSBarry Smith }
3139354c94deSBarry Smith 
3140985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3141e34fafa9SBarry Smith {
3142e34fafa9SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3143d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3144e34fafa9SBarry Smith   PetscReal       atmp;
3145985db425SBarry Smith   PetscScalar     *x;
3146ce496241SStefano Zampini   const MatScalar *aa,*av;
3147e34fafa9SBarry Smith 
3148e34fafa9SBarry Smith   PetscFunctionBegin;
314928b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
31509566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&av));
3151ce496241SStefano Zampini   aa = av;
3152e34fafa9SBarry Smith   ai = a->i;
3153e34fafa9SBarry Smith   aj = a->j;
3154e34fafa9SBarry Smith 
31559566063dSJacob Faibussowitsch   PetscCall(VecSet(v,0.0));
31569566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v,&x));
31579566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v,&n));
315808401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3159e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3160e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3161e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3162985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3163985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3164985db425SBarry Smith       aa++; aj++;
3165985db425SBarry Smith     }
3166985db425SBarry Smith   }
31679566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v,&x));
31689566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&av));
3169985db425SBarry Smith   PetscFunctionReturn(0);
3170985db425SBarry Smith }
3171985db425SBarry Smith 
3172985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3173985db425SBarry Smith {
3174985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3175d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
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(VecSet(v,0.0));
31879566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v,&x));
31889566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v,&n));
318908401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3190985db425SBarry Smith   for (i=0; i<m; i++) {
3191985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3192d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3193985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3194985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3195985db425SBarry Smith       x[i] = 0.0;
3196985db425SBarry Smith       if (idx) {
3197985db425SBarry Smith         for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */
3198985db425SBarry Smith           if (aj[j] > j) {
3199985db425SBarry Smith             idx[i] = j;
3200985db425SBarry Smith             break;
3201985db425SBarry Smith           }
3202985db425SBarry Smith         }
32031a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
32041a254869SHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3205985db425SBarry Smith       }
3206985db425SBarry Smith     }
3207985db425SBarry Smith     for (j=0; j<ncols; j++) {
3208985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3209985db425SBarry Smith       aa++; aj++;
3210985db425SBarry Smith     }
3211985db425SBarry Smith   }
32129566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v,&x));
32139566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&av));
3214985db425SBarry Smith   PetscFunctionReturn(0);
3215985db425SBarry Smith }
3216985db425SBarry Smith 
3217c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3218c87e5d42SMatthew Knepley {
3219c87e5d42SMatthew Knepley   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3220c87e5d42SMatthew Knepley   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3221ce496241SStefano Zampini   PetscScalar     *x;
3222ce496241SStefano Zampini   const MatScalar *aa,*av;
3223c87e5d42SMatthew Knepley 
3224c87e5d42SMatthew Knepley   PetscFunctionBegin;
32259566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&av));
3226ce496241SStefano Zampini   aa = av;
3227c87e5d42SMatthew Knepley   ai = a->i;
3228c87e5d42SMatthew Knepley   aj = a->j;
3229c87e5d42SMatthew Knepley 
32309566063dSJacob Faibussowitsch   PetscCall(VecSet(v,0.0));
32319566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v,&x));
32329566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v,&n));
323308401ef6SPierre Jolivet   PetscCheck(n == m,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n);
3234c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3235c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3236f07e67edSHong Zhang     if (ncols == A->cmap->n) { /* row is dense */
3237f07e67edSHong Zhang       x[i] = *aa; if (idx) idx[i] = 0;
3238f07e67edSHong Zhang     } else {  /* row is sparse so already KNOW minimum is 0.0 or higher */
3239f07e67edSHong Zhang       x[i] = 0.0;
3240f07e67edSHong Zhang       if (idx) {   /* find first implicit 0.0 in the row */
3241289a08f5SMatthew Knepley         for (j=0; j<ncols; j++) {
3242f07e67edSHong Zhang           if (aj[j] > j) {
3243f07e67edSHong Zhang             idx[i] = j;
32442205254eSKarl Rupp             break;
32452205254eSKarl Rupp           }
3246289a08f5SMatthew Knepley         }
3247f07e67edSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3248f07e67edSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3249f07e67edSHong Zhang       }
3250289a08f5SMatthew Knepley     }
3251c87e5d42SMatthew Knepley     for (j=0; j<ncols; j++) {
3252f07e67edSHong Zhang       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3253c87e5d42SMatthew Knepley       aa++; aj++;
3254c87e5d42SMatthew Knepley     }
3255c87e5d42SMatthew Knepley   }
32569566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v,&x));
32579566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&av));
3258c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3259c87e5d42SMatthew Knepley }
3260c87e5d42SMatthew Knepley 
3261985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3262985db425SBarry Smith {
3263985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3264d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3265d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3266985db425SBarry Smith   PetscScalar     *x;
3267ce496241SStefano Zampini   const MatScalar *aa,*av;
3268985db425SBarry Smith 
3269985db425SBarry Smith   PetscFunctionBegin;
327028b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
32719566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&av));
3272ce496241SStefano Zampini   aa = av;
3273985db425SBarry Smith   ai = a->i;
3274985db425SBarry Smith   aj = a->j;
3275985db425SBarry Smith 
32769566063dSJacob Faibussowitsch   PetscCall(VecSet(v,0.0));
32779566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(v,&x));
32789566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v,&n));
327908401ef6SPierre Jolivet   PetscCheck(n == m,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3280985db425SBarry Smith   for (i=0; i<m; i++) {
3281985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3282d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3283985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3284985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3285985db425SBarry Smith       x[i] = 0.0;
3286985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3287985db425SBarry Smith         for (j=0; j<ncols; j++) {
3288985db425SBarry Smith           if (aj[j] > j) {
3289985db425SBarry Smith             idx[i] = j;
3290985db425SBarry Smith             break;
3291985db425SBarry Smith           }
3292985db425SBarry Smith         }
3293fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3294fa213d2fSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3295985db425SBarry Smith       }
3296985db425SBarry Smith     }
3297985db425SBarry Smith     for (j=0; j<ncols; j++) {
3298985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3299985db425SBarry Smith       aa++; aj++;
3300e34fafa9SBarry Smith     }
3301e34fafa9SBarry Smith   }
33029566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(v,&x));
33039566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&av));
3304e34fafa9SBarry Smith   PetscFunctionReturn(0);
3305e34fafa9SBarry Smith }
3306bbead8a2SBarry Smith 
3307713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3308bbead8a2SBarry Smith {
3309bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
331033d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3311bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
33120da83c2eSBarry Smith   const PetscReal shift = 0.0;
33131a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3314bbead8a2SBarry Smith 
3315bbead8a2SBarry Smith   PetscFunctionBegin;
3316a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
33174a0d0026SBarry Smith   if (a->ibdiagvalid) {
33184a0d0026SBarry Smith     if (values) *values = a->ibdiag;
33194a0d0026SBarry Smith     PetscFunctionReturn(0);
33204a0d0026SBarry Smith   }
33219566063dSJacob Faibussowitsch   PetscCall(MatMarkDiagonal_SeqAIJ(A));
3322bbead8a2SBarry Smith   if (!a->ibdiag) {
33239566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(bs2*mbs,&a->ibdiag));
33249566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar)));
3325bbead8a2SBarry Smith   }
3326bbead8a2SBarry Smith   diag = a->ibdiag;
3327bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3328bbead8a2SBarry Smith   /* factor and invert each block */
3329bbead8a2SBarry Smith   switch (bs) {
3330bbead8a2SBarry Smith   case 1:
3331bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
33329566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A,1,&i,1,&i,diag+i));
3333ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3334ec1892c8SHong Zhang         if (allowzeropivot) {
33357b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33367b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
33377b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
33389566063dSJacob Faibussowitsch           PetscCall(PetscInfo(A,"Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON));
333998921bdaSJacob Faibussowitsch         } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MAT_LU_ZRPVT,"Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);
3340ec1892c8SHong Zhang       }
3341bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3342bbead8a2SBarry Smith     }
3343bbead8a2SBarry Smith     break;
3344bbead8a2SBarry Smith   case 2:
3345bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3346bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
33479566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A,2,ij,2,ij,diag));
33489566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected));
33497b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33509566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_2(diag));
3351bbead8a2SBarry Smith       diag += 4;
3352bbead8a2SBarry Smith     }
3353bbead8a2SBarry Smith     break;
3354bbead8a2SBarry Smith   case 3:
3355bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3356bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
33579566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A,3,ij,3,ij,diag));
33589566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected));
33597b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33609566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_3(diag));
3361bbead8a2SBarry Smith       diag += 9;
3362bbead8a2SBarry Smith     }
3363bbead8a2SBarry Smith     break;
3364bbead8a2SBarry Smith   case 4:
3365bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3366bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
33679566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A,4,ij,4,ij,diag));
33689566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected));
33697b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33709566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_4(diag));
3371bbead8a2SBarry Smith       diag += 16;
3372bbead8a2SBarry Smith     }
3373bbead8a2SBarry Smith     break;
3374bbead8a2SBarry Smith   case 5:
3375bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3376bbead8a2SBarry Smith       ij[0] = 5*i; ij[1] = 5*i + 1; ij[2] = 5*i + 2; ij[3] = 5*i + 3; ij[4] = 5*i + 4;
33779566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A,5,ij,5,ij,diag));
33789566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected));
33797b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33809566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_5(diag));
3381bbead8a2SBarry Smith       diag += 25;
3382bbead8a2SBarry Smith     }
3383bbead8a2SBarry Smith     break;
3384bbead8a2SBarry Smith   case 6:
3385bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3386bbead8a2SBarry Smith       ij[0] = 6*i; ij[1] = 6*i + 1; ij[2] = 6*i + 2; ij[3] = 6*i + 3; ij[4] = 6*i + 4; ij[5] = 6*i + 5;
33879566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A,6,ij,6,ij,diag));
33889566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected));
33897b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33909566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_6(diag));
3391bbead8a2SBarry Smith       diag += 36;
3392bbead8a2SBarry Smith     }
3393bbead8a2SBarry Smith     break;
3394bbead8a2SBarry Smith   case 7:
3395bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3396bbead8a2SBarry Smith       ij[0] = 7*i; ij[1] = 7*i + 1; ij[2] = 7*i + 2; ij[3] = 7*i + 3; ij[4] = 7*i + 4; ij[5] = 7*i + 5; ij[5] = 7*i + 6;
33979566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A,7,ij,7,ij,diag));
33989566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected));
33997b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
34009566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_7(diag));
3401bbead8a2SBarry Smith       diag += 49;
3402bbead8a2SBarry Smith     }
3403bbead8a2SBarry Smith     break;
3404bbead8a2SBarry Smith   default:
34059566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ));
3406bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3407bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3408bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3409bbead8a2SBarry Smith       }
34109566063dSJacob Faibussowitsch       PetscCall(MatGetValues(A,bs,IJ,bs,IJ,diag));
34119566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected));
34127b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
34139566063dSJacob Faibussowitsch       PetscCall(PetscKernel_A_gets_transpose_A_N(diag,bs));
3414bbead8a2SBarry Smith       diag += bs2;
3415bbead8a2SBarry Smith     }
34169566063dSJacob Faibussowitsch     PetscCall(PetscFree3(v_work,v_pivots,IJ));
3417bbead8a2SBarry Smith   }
3418bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3419bbead8a2SBarry Smith   PetscFunctionReturn(0);
3420bbead8a2SBarry Smith }
3421bbead8a2SBarry Smith 
342273a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
342373a71a0fSBarry Smith {
342473a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3425fff043a9SJunchao Zhang   PetscScalar    a,*aa;
342673a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
342773a71a0fSBarry Smith 
342873a71a0fSBarry Smith   PetscFunctionBegin;
342973a71a0fSBarry Smith   if (!x->assembled) {
34309566063dSJacob Faibussowitsch     PetscCall(MatGetSize(x,&m,&n));
343173a71a0fSBarry Smith     for (i=0; i<m; i++) {
343273a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
34339566063dSJacob Faibussowitsch         PetscCall(PetscRandomGetValue(rctx,&a));
343473a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
34359566063dSJacob Faibussowitsch         PetscCall(MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES));
343673a71a0fSBarry Smith       }
343773a71a0fSBarry Smith     }
3438e2ce353bSJunchao Zhang   } else {
34399566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayWrite(x,&aa));
34409566063dSJacob Faibussowitsch     for (i=0; i<aij->nz; i++) PetscCall(PetscRandomGetValue(rctx,aa+i));
34419566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayWrite(x,&aa));
3442e2ce353bSJunchao Zhang   }
34439566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY));
34449566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY));
344573a71a0fSBarry Smith   PetscFunctionReturn(0);
344673a71a0fSBarry Smith }
344773a71a0fSBarry Smith 
3448679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3449679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3450679944adSJunchao Zhang {
3451679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3452679944adSJunchao Zhang   PetscScalar    a;
3453679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3454679944adSJunchao Zhang 
3455679944adSJunchao Zhang   PetscFunctionBegin;
3456679944adSJunchao Zhang   nskip = high - low;
34579566063dSJacob Faibussowitsch   PetscCall(MatGetSize(x,&m,&n));
3458679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3459679944adSJunchao Zhang   for (i=0; i<m; i++) {
3460679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
34619566063dSJacob Faibussowitsch       PetscCall(PetscRandomGetValue(rctx,&a));
3462679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3463679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
34649566063dSJacob Faibussowitsch       PetscCall(MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES));
3465679944adSJunchao Zhang     }
3466e2ce353bSJunchao Zhang   }
34679566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY));
34689566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY));
3469679944adSJunchao Zhang   PetscFunctionReturn(0);
3470679944adSJunchao Zhang }
3471679944adSJunchao Zhang 
3472682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
34730a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3474cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3475cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3476cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
347797304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
34787c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
34797c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3480f4259b30SLisandro Dalcin                                         NULL,
3481f4259b30SLisandro Dalcin                                         NULL,
3482f4259b30SLisandro Dalcin                                         NULL,
3483f4259b30SLisandro Dalcin                                 /* 10*/ NULL,
3484cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3485f4259b30SLisandro Dalcin                                         NULL,
348641f059aeSBarry Smith                                         MatSOR_SeqAIJ,
348791e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
348897304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3489cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3490cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3491cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3492cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
3493f4259b30SLisandro Dalcin                                 /* 20*/ NULL,
3494cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3495cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3496cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3497d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3498f4259b30SLisandro Dalcin                                         NULL,
3499f4259b30SLisandro Dalcin                                         NULL,
3500f4259b30SLisandro Dalcin                                         NULL,
3501f4259b30SLisandro Dalcin                                         NULL,
35024994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3503f4259b30SLisandro Dalcin                                         NULL,
3504f4259b30SLisandro Dalcin                                         NULL,
3505f4259b30SLisandro Dalcin                                         NULL,
3506f4259b30SLisandro Dalcin                                         NULL,
3507d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3508f4259b30SLisandro Dalcin                                         NULL,
3509f4259b30SLisandro Dalcin                                         NULL,
3510cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3511f4259b30SLisandro Dalcin                                         NULL,
3512d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
35137dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3514cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3515cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3516cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3517d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3518cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
35197d68702bSBarry Smith                                         MatShift_SeqAIJ,
352079299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
35216e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
352273a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
35233b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
35243b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
35253b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3526a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
352793dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3528f4259b30SLisandro Dalcin                                         NULL,
3529f4259b30SLisandro Dalcin                                         NULL,
3530cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3531f4259b30SLisandro Dalcin                                         NULL,
3532f4259b30SLisandro Dalcin                                 /* 59*/ NULL,
3533b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3534b9b97703SBarry Smith                                         MatView_SeqAIJ,
3535f4259b30SLisandro Dalcin                                         NULL,
3536f4259b30SLisandro Dalcin                                         NULL,
3537f4259b30SLisandro Dalcin                                 /* 64*/ NULL,
3538321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3539f4259b30SLisandro Dalcin                                         NULL,
3540f4259b30SLisandro Dalcin                                         NULL,
3541f4259b30SLisandro Dalcin                                         NULL,
3542d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3543c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3544f4259b30SLisandro Dalcin                                         NULL,
3545f4259b30SLisandro Dalcin                                         NULL,
3546f4259b30SLisandro Dalcin                                         NULL,
3547f4259b30SLisandro Dalcin                                 /* 74*/ NULL,
35483acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
3549f4259b30SLisandro Dalcin                                         NULL,
3550f4259b30SLisandro Dalcin                                         NULL,
3551f4259b30SLisandro Dalcin                                         NULL,
35526ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3553f4259b30SLisandro Dalcin                                         NULL,
3554f4259b30SLisandro Dalcin                                         NULL,
3555f4259b30SLisandro Dalcin                                         NULL,
3556bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3557d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
35581cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
3559f4259b30SLisandro Dalcin                                         NULL,
3560f4259b30SLisandro Dalcin                                         NULL,
3561f4259b30SLisandro Dalcin                                         NULL,
3562f4259b30SLisandro Dalcin                                 /* 89*/ NULL,
3563f4259b30SLisandro Dalcin                                         NULL,
356426be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
3565f4259b30SLisandro Dalcin                                         NULL,
3566f4259b30SLisandro Dalcin                                         NULL,
35678fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3568f4259b30SLisandro Dalcin                                         NULL,
3569f4259b30SLisandro Dalcin                                         NULL,
35706fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3571f4259b30SLisandro Dalcin                                         NULL,
35724222ddf1SHong Zhang                                 /* 99*/ MatProductSetFromOptions_SeqAIJ,
3573f4259b30SLisandro Dalcin                                         NULL,
3574f4259b30SLisandro Dalcin                                         NULL,
357587d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
3576f4259b30SLisandro Dalcin                                         NULL,
3577d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
357899cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3579f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3580f4259b30SLisandro Dalcin                                         NULL,
3581f4259b30SLisandro Dalcin                                         NULL,
3582cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3583f4259b30SLisandro Dalcin                                         NULL,
35842af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
3585f4259b30SLisandro Dalcin                                         NULL,
3586599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3587f4259b30SLisandro Dalcin                                 /*114*/ NULL,
3588f4259b30SLisandro Dalcin                                         NULL,
3589f4259b30SLisandro Dalcin                                         NULL,
3590f4259b30SLisandro Dalcin                                         NULL,
3591f4259b30SLisandro Dalcin                                         NULL,
3592f4259b30SLisandro Dalcin                                 /*119*/ NULL,
3593f4259b30SLisandro Dalcin                                         NULL,
3594f4259b30SLisandro Dalcin                                         NULL,
3595f4259b30SLisandro Dalcin                                         NULL,
3596b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
35970716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3598a873a8cdSSam Reynolds                                         MatGetColumnReductions_SeqAIJ,
359937868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
36000da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
3601f4259b30SLisandro Dalcin                                         NULL,
3602f4259b30SLisandro Dalcin                                 /*129*/ NULL,
3603f4259b30SLisandro Dalcin                                         NULL,
3604f4259b30SLisandro Dalcin                                         NULL,
360575648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3606b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3607b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
36082b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
3609f4259b30SLisandro Dalcin                                         NULL,
3610f4259b30SLisandro Dalcin                                         NULL,
36113964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
3612f4259b30SLisandro Dalcin                                  /*139*/NULL,
3613f4259b30SLisandro Dalcin                                         NULL,
3614f4259b30SLisandro Dalcin                                         NULL,
36153a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
36169c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
36174222ddf1SHong Zhang                                         MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
36184222ddf1SHong Zhang                                  /*145*/MatDestroySubMatrices_SeqAIJ,
3619f4259b30SLisandro Dalcin                                         NULL,
3620f4259b30SLisandro Dalcin                                         NULL
36219e29f15eSvictorle };
362217ab2063SBarry Smith 
36237087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3624bef8e0ddSBarry Smith {
3625bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
362697f1f81fSBarry Smith   PetscInt   i,nz,n;
3627bef8e0ddSBarry Smith 
3628bef8e0ddSBarry Smith   PetscFunctionBegin;
3629bef8e0ddSBarry Smith   nz = aij->maxnz;
3630d0f46423SBarry Smith   n  = mat->rmap->n;
3631bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3632bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3633bef8e0ddSBarry Smith   }
3634bef8e0ddSBarry Smith   aij->nz = nz;
3635bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3636bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3637bef8e0ddSBarry Smith   }
3638bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3639bef8e0ddSBarry Smith }
3640bef8e0ddSBarry Smith 
3641a3bb6f32SFande Kong /*
3642ddea5d60SJunchao Zhang  * Given a sparse matrix with global column indices, compact it by using a local column space.
3643ddea5d60SJunchao Zhang  * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3644ddea5d60SJunchao Zhang  */
3645a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3646a3bb6f32SFande Kong {
3647a3bb6f32SFande Kong   Mat_SeqAIJ         *aij = (Mat_SeqAIJ*)mat->data;
3648a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3649a3bb6f32SFande Kong   PetscTablePosition tpos;
365025b670f0SStefano Zampini   PetscInt           gid,lid,i,ec,nz = aij->nz;
365125b670f0SStefano Zampini   PetscInt           *garray,*jj = aij->j;
3652a3bb6f32SFande Kong 
3653a3bb6f32SFande Kong   PetscFunctionBegin;
3654a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3655a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3656a3bb6f32SFande Kong   /* use a table */
36579566063dSJacob Faibussowitsch   PetscCall(PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1));
3658a3bb6f32SFande Kong   ec = 0;
365925b670f0SStefano Zampini   for (i=0; i<nz; i++) {
366025b670f0SStefano Zampini     PetscInt data,gid1 = jj[i] + 1;
36619566063dSJacob Faibussowitsch     PetscCall(PetscTableFind(gid1_lid1,gid1,&data));
3662a3bb6f32SFande Kong     if (!data) {
3663a3bb6f32SFande Kong       /* one based table */
36649566063dSJacob Faibussowitsch       PetscCall(PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES));
3665a3bb6f32SFande Kong     }
3666a3bb6f32SFande Kong   }
3667a3bb6f32SFande Kong   /* form array of columns we need */
36689566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ec,&garray));
36699566063dSJacob Faibussowitsch   PetscCall(PetscTableGetHeadPosition(gid1_lid1,&tpos));
3670a3bb6f32SFande Kong   while (tpos) {
36719566063dSJacob Faibussowitsch     PetscCall(PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid));
3672a3bb6f32SFande Kong     gid--;
3673a3bb6f32SFande Kong     lid--;
3674a3bb6f32SFande Kong     garray[lid] = gid;
3675a3bb6f32SFande Kong   }
36769566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(ec,garray)); /* sort, and rebuild */
36779566063dSJacob Faibussowitsch   PetscCall(PetscTableRemoveAll(gid1_lid1));
3678a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
36799566063dSJacob Faibussowitsch     PetscCall(PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES));
3680a3bb6f32SFande Kong   }
3681a3bb6f32SFande Kong   /* compact out the extra columns in B */
368225b670f0SStefano Zampini   for (i=0; i<nz; i++) {
368325b670f0SStefano Zampini     PetscInt gid1 = jj[i] + 1;
36849566063dSJacob Faibussowitsch     PetscCall(PetscTableFind(gid1_lid1,gid1,&lid));
3685a3bb6f32SFande Kong     lid--;
368625b670f0SStefano Zampini     jj[i] = lid;
3687a3bb6f32SFande Kong   }
36889566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&mat->cmap));
36899566063dSJacob Faibussowitsch   PetscCall(PetscTableDestroy(&gid1_lid1));
36909566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap));
36919566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping));
36929566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH));
3693a3bb6f32SFande Kong   PetscFunctionReturn(0);
3694a3bb6f32SFande Kong }
3695a3bb6f32SFande Kong 
3696bef8e0ddSBarry Smith /*@
3697bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3698bef8e0ddSBarry Smith        in the matrix.
3699bef8e0ddSBarry Smith 
3700bef8e0ddSBarry Smith   Input Parameters:
3701bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3702bef8e0ddSBarry Smith -  indices - the column indices
3703bef8e0ddSBarry Smith 
370415091d37SBarry Smith   Level: advanced
370515091d37SBarry Smith 
3706bef8e0ddSBarry Smith   Notes:
3707bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3708bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3709bef8e0ddSBarry Smith   of the MatSetValues() operation.
3710bef8e0ddSBarry Smith 
3711bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3712d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3713bef8e0ddSBarry Smith 
3714bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3715bef8e0ddSBarry Smith 
3716b9617806SBarry Smith     The indices should start with zero, not one.
3717b9617806SBarry Smith 
3718bef8e0ddSBarry Smith @*/
37197087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3720bef8e0ddSBarry Smith {
3721bef8e0ddSBarry Smith   PetscFunctionBegin;
37220700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3723dadcf809SJacob Faibussowitsch   PetscValidIntPointer(indices,2);
3724cac4c232SBarry Smith   PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));
3725bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3726bef8e0ddSBarry Smith }
3727bef8e0ddSBarry Smith 
3728be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3729be6bf707SBarry Smith 
37307087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3731be6bf707SBarry Smith {
3732be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
3733d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3734be6bf707SBarry Smith 
3735be6bf707SBarry Smith   PetscFunctionBegin;
373628b400f6SJacob Faibussowitsch   PetscCheck(aij->nonew,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3737be6bf707SBarry Smith 
3738be6bf707SBarry Smith   /* allocate space for values if not already there */
3739be6bf707SBarry Smith   if (!aij->saved_values) {
37409566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nz+1,&aij->saved_values));
37419566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar)));
3742be6bf707SBarry Smith   }
3743be6bf707SBarry Smith 
3744be6bf707SBarry Smith   /* copy values over */
37459566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->saved_values,aij->a,nz));
3746be6bf707SBarry Smith   PetscFunctionReturn(0);
3747be6bf707SBarry Smith }
3748be6bf707SBarry Smith 
3749be6bf707SBarry Smith /*@
3750be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3751be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3752be6bf707SBarry Smith        nonlinear portion.
3753be6bf707SBarry Smith 
3754be6bf707SBarry Smith    Collect on Mat
3755be6bf707SBarry Smith 
3756be6bf707SBarry Smith   Input Parameters:
37570e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3758be6bf707SBarry Smith 
375915091d37SBarry Smith   Level: advanced
376015091d37SBarry Smith 
3761be6bf707SBarry Smith   Common Usage, with SNESSolve():
3762be6bf707SBarry Smith $    Create Jacobian matrix
3763be6bf707SBarry Smith $    Set linear terms into matrix
3764be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3765be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3766be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3767512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3768be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3769be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3770be6bf707SBarry Smith $    In your Jacobian routine
3771be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3772be6bf707SBarry Smith $      Set nonlinear terms in matrix
3773be6bf707SBarry Smith 
3774be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3775be6bf707SBarry Smith $    // build linear portion of Jacobian
3776512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3777be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3778be6bf707SBarry Smith $    loop over nonlinear iterations
3779be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3780be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3781be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3782be6bf707SBarry Smith $       Solve linear system with Jacobian
3783be6bf707SBarry Smith $    endloop
3784be6bf707SBarry Smith 
3785be6bf707SBarry Smith   Notes:
3786be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3787512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3788be6bf707SBarry Smith     calling this routine.
3789be6bf707SBarry Smith 
37900c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
37910c468ba9SBarry Smith     and does not allocated additional space.
37920c468ba9SBarry Smith 
3793db781477SPatrick Sanan .seealso: `MatRetrieveValues()`
3794be6bf707SBarry Smith 
3795be6bf707SBarry Smith @*/
37967087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3797be6bf707SBarry Smith {
3798be6bf707SBarry Smith   PetscFunctionBegin;
37990700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
380028b400f6SJacob Faibussowitsch   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
380128b400f6SJacob Faibussowitsch   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3802cac4c232SBarry Smith   PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));
3803be6bf707SBarry Smith   PetscFunctionReturn(0);
3804be6bf707SBarry Smith }
3805be6bf707SBarry Smith 
38067087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3807be6bf707SBarry Smith {
3808be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
3809d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3810be6bf707SBarry Smith 
3811be6bf707SBarry Smith   PetscFunctionBegin;
381228b400f6SJacob Faibussowitsch   PetscCheck(aij->nonew,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
381328b400f6SJacob Faibussowitsch   PetscCheck(aij->saved_values,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3814be6bf707SBarry Smith   /* copy values over */
38159566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aij->a,aij->saved_values,nz));
3816be6bf707SBarry Smith   PetscFunctionReturn(0);
3817be6bf707SBarry Smith }
3818be6bf707SBarry Smith 
3819be6bf707SBarry Smith /*@
3820be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3821be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3822be6bf707SBarry Smith        nonlinear portion.
3823be6bf707SBarry Smith 
3824be6bf707SBarry Smith    Collect on Mat
3825be6bf707SBarry Smith 
3826be6bf707SBarry Smith   Input Parameters:
3827386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3828be6bf707SBarry Smith 
382915091d37SBarry Smith   Level: advanced
383015091d37SBarry Smith 
3831db781477SPatrick Sanan .seealso: `MatStoreValues()`
3832be6bf707SBarry Smith 
3833be6bf707SBarry Smith @*/
38347087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3835be6bf707SBarry Smith {
3836be6bf707SBarry Smith   PetscFunctionBegin;
38370700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
383828b400f6SJacob Faibussowitsch   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
383928b400f6SJacob Faibussowitsch   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3840cac4c232SBarry Smith   PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));
3841be6bf707SBarry Smith   PetscFunctionReturn(0);
3842be6bf707SBarry Smith }
3843be6bf707SBarry Smith 
3844be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
384517ab2063SBarry Smith /*@C
3846682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
38470d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
38486e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
384951c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
38502bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
385117ab2063SBarry Smith 
3852d083f849SBarry Smith    Collective
3853db81eaa0SLois Curfman McInnes 
385417ab2063SBarry Smith    Input Parameters:
3855db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
385617ab2063SBarry Smith .  m - number of rows
385717ab2063SBarry Smith .  n - number of columns
385817ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
385951c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
38600298fd71SBarry Smith          (possibly different for each row) or NULL
386117ab2063SBarry Smith 
386217ab2063SBarry Smith    Output Parameter:
3863416022c9SBarry Smith .  A - the matrix
386417ab2063SBarry Smith 
3865175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3866f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3867175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3868175b88e8SBarry Smith 
3869b259b22eSLois Curfman McInnes    Notes:
387049a6f317SBarry Smith    If nnz is given then nz is ignored
387149a6f317SBarry Smith 
387217ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
387317ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
38740002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
387544cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
387617ab2063SBarry Smith 
387717ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
38780298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
38793d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
38806da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
388117ab2063SBarry Smith 
3882682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
38834fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3884682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
38856c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
38866c7ebb05SLois Curfman McInnes 
38876c7ebb05SLois Curfman McInnes    Options Database Keys:
3888698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
38899db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
389017ab2063SBarry Smith 
3891027ccd11SLois Curfman McInnes    Level: intermediate
3892027ccd11SLois Curfman McInnes 
3893db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()`
389436db0b34SBarry Smith 
389517ab2063SBarry Smith @*/
38967087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
389717ab2063SBarry Smith {
38983a40ed3dSBarry Smith   PetscFunctionBegin;
38999566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,A));
39009566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A,m,n,m,n));
39019566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A,MATSEQAIJ));
39029566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz));
3903273d9f13SBarry Smith   PetscFunctionReturn(0);
3904273d9f13SBarry Smith }
3905273d9f13SBarry Smith 
3906273d9f13SBarry Smith /*@C
3907273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
3908273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
3909273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
3910273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
3911273d9f13SBarry Smith 
3912d083f849SBarry Smith    Collective
3913273d9f13SBarry Smith 
3914273d9f13SBarry Smith    Input Parameters:
39151c4f3114SJed Brown +  B - The matrix
3916273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
3917273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39180298fd71SBarry Smith          (possibly different for each row) or NULL
3919273d9f13SBarry Smith 
3920273d9f13SBarry Smith    Notes:
392149a6f317SBarry Smith      If nnz is given then nz is ignored
392249a6f317SBarry Smith 
3923273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
3924273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
3925273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
3926273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
3927273d9f13SBarry Smith 
3928273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39290298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
3930273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
3931273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
3932273d9f13SBarry Smith 
3933aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
3934aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3935aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
3936aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
3937aa95bbe8SBarry Smith 
3938a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
3939a96a251dSBarry Smith    entries or columns indices
3940a96a251dSBarry Smith 
3941273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
3942273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
3943273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
3944273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
3945273d9f13SBarry Smith 
3946273d9f13SBarry Smith    Options Database Keys:
3947698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
394847b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3949273d9f13SBarry Smith 
3950273d9f13SBarry Smith    Level: intermediate
3951273d9f13SBarry Smith 
3952db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()`, `MatGetInfo()`,
3953db781477SPatrick Sanan           `MatSeqAIJSetTotalPreallocation()`
3954273d9f13SBarry Smith 
3955273d9f13SBarry Smith @*/
39567087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
3957273d9f13SBarry Smith {
3958a23d5eceSKris Buschelman   PetscFunctionBegin;
39596ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
39606ba663aaSJed Brown   PetscValidType(B,1);
3961cac4c232SBarry Smith   PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));
3962a23d5eceSKris Buschelman   PetscFunctionReturn(0);
3963a23d5eceSKris Buschelman }
3964a23d5eceSKris Buschelman 
39657087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
3966a23d5eceSKris Buschelman {
3967273d9f13SBarry Smith   Mat_SeqAIJ     *b;
39682576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
396997f1f81fSBarry Smith   PetscInt       i;
3970273d9f13SBarry Smith 
3971273d9f13SBarry Smith   PetscFunctionBegin;
39722576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
3973a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
3974c461c341SBarry Smith     skipallocation = PETSC_TRUE;
3975c461c341SBarry Smith     nz             = 0;
3976c461c341SBarry Smith   }
39779566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
39789566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
3979899cda47SBarry Smith 
3980435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
398108401ef6SPierre Jolivet   PetscCheck(nz >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %" PetscInt_FMT,nz);
3982cf9c20a2SJed Brown   if (PetscUnlikelyDebug(nnz)) {
3983d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
398408401ef6SPierre 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]);
398508401ef6SPierre 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);
3986b73539f3SBarry Smith     }
3987b73539f3SBarry Smith   }
3988b73539f3SBarry Smith 
3989273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
39902205254eSKarl Rupp 
3991273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
3992273d9f13SBarry Smith 
3993ab93d7beSBarry Smith   if (!skipallocation) {
39942ee49352SLisandro Dalcin     if (!b->imax) {
39959566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(B->rmap->n,&b->imax));
39969566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt)));
3997071fcb05SBarry Smith     }
3998071fcb05SBarry Smith     if (!b->ilen) {
3999071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
40009566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(B->rmap->n,&b->ilen));
40019566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt)));
4002071fcb05SBarry Smith     } else {
40039566063dSJacob Faibussowitsch       PetscCall(PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt)));
40042ee49352SLisandro Dalcin     }
4005846b4da1SFande Kong     if (!b->ipre) {
40069566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(B->rmap->n,&b->ipre));
40079566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt)));
4008846b4da1SFande Kong     }
4009273d9f13SBarry Smith     if (!nnz) {
4010435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
4011c62bd62aSJed Brown       else if (nz < 0) nz = 1;
40125d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
4013d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
4014d0f46423SBarry Smith       nz = nz*B->rmap->n;
4015273d9f13SBarry Smith     } else {
4016c73702f5SBarry Smith       PetscInt64 nz64 = 0;
4017c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
40189566063dSJacob Faibussowitsch       PetscCall(PetscIntCast(nz64,&nz));
4019273d9f13SBarry Smith     }
4020ab93d7beSBarry Smith 
4021273d9f13SBarry Smith     /* allocate the matrix space */
402253dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
40239566063dSJacob Faibussowitsch     PetscCall(MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i));
4024396832f4SHong Zhang     if (B->structure_only) {
40259566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nz,&b->j));
40269566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(B->rmap->n+1,&b->i));
40279566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt)));
4028396832f4SHong Zhang     } else {
40299566063dSJacob Faibussowitsch       PetscCall(PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i));
40309566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt))));
4031396832f4SHong Zhang     }
4032bfeeae90SHong Zhang     b->i[0] = 0;
4033d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
40345da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
40355da197adSKris Buschelman     }
4036396832f4SHong Zhang     if (B->structure_only) {
4037396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
4038396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
4039396832f4SHong Zhang     } else {
4040273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
4041e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
4042396832f4SHong Zhang     }
4043e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
4044c461c341SBarry Smith   } else {
4045e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
4046e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
4047c461c341SBarry Smith   }
4048273d9f13SBarry Smith 
4049846b4da1SFande Kong   if (b->ipre && nnz != b->ipre && b->imax) {
4050846b4da1SFande Kong     /* reserve user-requested sparsity */
40519566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(b->ipre,b->imax,B->rmap->n));
4052846b4da1SFande Kong   }
4053846b4da1SFande Kong 
4054273d9f13SBarry Smith   b->nz               = 0;
4055273d9f13SBarry Smith   b->maxnz            = nz;
4056273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
40572205254eSKarl Rupp   if (realalloc) {
40589566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
40592205254eSKarl Rupp   }
4060cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
4061cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
4062273d9f13SBarry Smith   PetscFunctionReturn(0);
4063273d9f13SBarry Smith }
4064273d9f13SBarry Smith 
4065846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
4066846b4da1SFande Kong {
4067846b4da1SFande Kong   Mat_SeqAIJ     *a;
4068a5bbaf83SFande Kong   PetscInt       i;
4069846b4da1SFande Kong 
4070846b4da1SFande Kong   PetscFunctionBegin;
4071846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
407214d0e64fSAlex Lindsay 
407314d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
407414d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
407514d0e64fSAlex Lindsay 
4076846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
40772c814fdeSFande Kong   /* if no saved info, we error out */
407828b400f6SJacob Faibussowitsch   PetscCheck(a->ipre,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info ");
40792c814fdeSFande Kong 
4080aed4548fSBarry Smith   PetscCheck(a->i && a->j && a->a && a->imax && a->ilen,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Memory info is incomplete, and can not reset preallocation ");
40812c814fdeSFande Kong 
40829566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(a->imax,a->ipre,A->rmap->n));
40839566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(a->ilen,A->rmap->n));
4084846b4da1SFande Kong   a->i[0] = 0;
4085846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
4086846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
4087846b4da1SFande Kong   }
4088846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
4089846b4da1SFande Kong   a->nz               = 0;
4090846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
4091846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
4092846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4093846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4094846b4da1SFande Kong   PetscFunctionReturn(0);
4095846b4da1SFande Kong }
4096846b4da1SFande Kong 
409758d36128SBarry Smith /*@
4098a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4099a1661176SMatthew Knepley 
4100a1661176SMatthew Knepley    Input Parameters:
4101a1661176SMatthew Knepley +  B - the matrix
4102a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4103a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4104a1661176SMatthew Knepley -  v - optional values in the matrix
4105a1661176SMatthew Knepley 
4106a1661176SMatthew Knepley    Level: developer
4107a1661176SMatthew Knepley 
41086a9b8d82SBarry Smith    Notes:
410958d36128SBarry Smith       The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
411058d36128SBarry Smith 
41116a9b8d82SBarry Smith       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
41126a9b8d82SBarry Smith       structure will be the union of all the previous nonzero structures.
41136a9b8d82SBarry Smith 
41146a9b8d82SBarry Smith     Developer Notes:
41156a9b8d82SBarry 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
41166a9b8d82SBarry Smith       then just copies the v values directly with PetscMemcpy().
41176a9b8d82SBarry Smith 
41186a9b8d82SBarry Smith       This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them.
41196a9b8d82SBarry Smith 
4120db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatSeqAIJSetPreallocation()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MatResetPreallocation()`
4121a1661176SMatthew Knepley @*/
4122a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4123a1661176SMatthew Knepley {
4124a1661176SMatthew Knepley   PetscFunctionBegin;
41250700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
41266ba663aaSJed Brown   PetscValidType(B,1);
4127cac4c232SBarry Smith   PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));
4128a1661176SMatthew Knepley   PetscFunctionReturn(0);
4129a1661176SMatthew Knepley }
4130a1661176SMatthew Knepley 
41317087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4132a1661176SMatthew Knepley {
4133a1661176SMatthew Knepley   PetscInt       i;
4134a1661176SMatthew Knepley   PetscInt       m,n;
4135a1661176SMatthew Knepley   PetscInt       nz;
41366a9b8d82SBarry Smith   PetscInt       *nnz;
4137a1661176SMatthew Knepley 
4138a1661176SMatthew Knepley   PetscFunctionBegin;
4139aed4548fSBarry Smith   PetscCheck(Ii[0] == 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]);
4140779a8d59SSatish Balay 
41419566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
41429566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
4143779a8d59SSatish Balay 
41449566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, &m, &n));
41459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m+1, &nnz));
4146a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4147b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
414808401ef6SPierre 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);
4149a1661176SMatthew Knepley     nnz[i] = nz;
4150a1661176SMatthew Knepley   }
41519566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz));
41529566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
4153a1661176SMatthew Knepley 
4154a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
41559566063dSJacob Faibussowitsch     PetscCall(MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES));
4156a1661176SMatthew Knepley   }
4157a1661176SMatthew Knepley 
41589566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
41599566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
4160a1661176SMatthew Knepley 
41619566063dSJacob Faibussowitsch   PetscCall(MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE));
4162a1661176SMatthew Knepley   PetscFunctionReturn(0);
4163a1661176SMatthew Knepley }
4164a1661176SMatthew Knepley 
4165ad7e164aSPierre Jolivet /*@
4166ad7e164aSPierre Jolivet    MatSeqAIJKron - Computes C, the Kronecker product of A and B.
4167ad7e164aSPierre Jolivet 
4168ad7e164aSPierre Jolivet    Input Parameters:
4169ad7e164aSPierre Jolivet +  A - left-hand side matrix
4170ad7e164aSPierre Jolivet .  B - right-hand side matrix
4171ad7e164aSPierre Jolivet -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
4172ad7e164aSPierre Jolivet 
4173ad7e164aSPierre Jolivet    Output Parameter:
4174ad7e164aSPierre Jolivet .  C - Kronecker product of A and B
4175ad7e164aSPierre Jolivet 
4176ad7e164aSPierre Jolivet    Level: intermediate
4177ad7e164aSPierre Jolivet 
4178ad7e164aSPierre Jolivet    Notes:
4179ad7e164aSPierre Jolivet       MAT_REUSE_MATRIX can only be used when the nonzero structure of the product matrix has not changed from that last call to MatSeqAIJKron().
4180ad7e164aSPierre Jolivet 
4181db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATKAIJ`, `MatReuse`
4182ad7e164aSPierre Jolivet @*/
4183ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron(Mat A,Mat B,MatReuse reuse,Mat *C)
4184ad7e164aSPierre Jolivet {
4185ad7e164aSPierre Jolivet   PetscFunctionBegin;
4186ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4187ad7e164aSPierre Jolivet   PetscValidType(A,1);
4188ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4189ad7e164aSPierre Jolivet   PetscValidType(B,2);
4190ad7e164aSPierre Jolivet   PetscValidPointer(C,4);
4191ad7e164aSPierre Jolivet   if (reuse == MAT_REUSE_MATRIX) {
4192ad7e164aSPierre Jolivet     PetscValidHeaderSpecific(*C,MAT_CLASSID,4);
4193ad7e164aSPierre Jolivet     PetscValidType(*C,4);
4194ad7e164aSPierre Jolivet   }
4195cac4c232SBarry Smith   PetscTryMethod(A,"MatSeqAIJKron_C",(Mat,Mat,MatReuse,Mat*),(A,B,reuse,C));
4196ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4197ad7e164aSPierre Jolivet }
4198ad7e164aSPierre Jolivet 
4199ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A,Mat B,MatReuse reuse,Mat *C)
4200ad7e164aSPierre Jolivet {
4201ad7e164aSPierre Jolivet   Mat                newmat;
4202ad7e164aSPierre Jolivet   Mat_SeqAIJ         *a = (Mat_SeqAIJ*)A->data;
4203ad7e164aSPierre Jolivet   Mat_SeqAIJ         *b = (Mat_SeqAIJ*)B->data;
4204ad7e164aSPierre Jolivet   PetscScalar        *v;
4205fff043a9SJunchao Zhang   const PetscScalar  *aa,*ba;
4206ad7e164aSPierre 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;
4207ad7e164aSPierre Jolivet   PetscBool          flg;
4208ad7e164aSPierre Jolivet 
4209ad7e164aSPierre Jolivet   PetscFunctionBegin;
421028b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
421128b400f6SJacob Faibussowitsch   PetscCheck(A->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
421228b400f6SJacob Faibussowitsch   PetscCheck(!B->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
421328b400f6SJacob Faibussowitsch   PetscCheck(B->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
42149566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&flg));
421528b400f6SJacob Faibussowitsch   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatType %s",((PetscObject)B)->type_name);
4216aed4548fSBarry Smith   PetscCheck(reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatReuse %d",(int)reuse);
4217ad7e164aSPierre Jolivet   if (reuse == MAT_INITIAL_MATRIX) {
42189566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(am*bm+1,&i,a->i[am]*b->i[bm],&j));
42199566063dSJacob Faibussowitsch     PetscCall(MatCreate(PETSC_COMM_SELF,&newmat));
42209566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(newmat,am*bm,an*bn,am*bm,an*bn));
42219566063dSJacob Faibussowitsch     PetscCall(MatSetType(newmat,MATAIJ));
4222ad7e164aSPierre Jolivet     i[0] = 0;
4223ad7e164aSPierre Jolivet     for (m = 0; m < am; ++m) {
4224ad7e164aSPierre Jolivet       for (p = 0; p < bm; ++p) {
4225ad7e164aSPierre Jolivet         i[m*bm + p + 1] = i[m*bm + p] + (a->i[m+1] - a->i[m]) * (b->i[p+1] - b->i[p]);
4226ad7e164aSPierre Jolivet         for (n = a->i[m]; n < a->i[m+1]; ++n) {
4227ad7e164aSPierre Jolivet           for (q = b->i[p]; q < b->i[p+1]; ++q) {
4228ad7e164aSPierre Jolivet             j[nnz++] = a->j[n]*bn + b->j[q];
4229ad7e164aSPierre Jolivet           }
4230ad7e164aSPierre Jolivet         }
4231ad7e164aSPierre Jolivet       }
4232ad7e164aSPierre Jolivet     }
42339566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocationCSR(newmat,i,j,NULL));
4234ad7e164aSPierre Jolivet     *C = newmat;
42359566063dSJacob Faibussowitsch     PetscCall(PetscFree2(i,j));
4236ad7e164aSPierre Jolivet     nnz = 0;
4237ad7e164aSPierre Jolivet   }
42389566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(*C,&v));
42399566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&aa));
42409566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(B,&ba));
4241ad7e164aSPierre Jolivet   for (m = 0; m < am; ++m) {
4242ad7e164aSPierre Jolivet     for (p = 0; p < bm; ++p) {
4243ad7e164aSPierre Jolivet       for (n = a->i[m]; n < a->i[m+1]; ++n) {
4244ad7e164aSPierre Jolivet         for (q = b->i[p]; q < b->i[p+1]; ++q) {
4245fff043a9SJunchao Zhang           v[nnz++] = aa[n] * ba[q];
4246ad7e164aSPierre Jolivet         }
4247ad7e164aSPierre Jolivet       }
4248ad7e164aSPierre Jolivet     }
4249ad7e164aSPierre Jolivet   }
42509566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(*C,&v));
42519566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
42529566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(B,&ba));
4253ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4254ad7e164aSPierre Jolivet }
4255ad7e164aSPierre Jolivet 
4256c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4257af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4258170fe5c8SBarry Smith 
4259170fe5c8SBarry Smith /*
4260170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4261170fe5c8SBarry Smith 
4262170fe5c8SBarry Smith                n                       p                          p
42632da392ccSBarry Smith         [             ]       [             ]         [                 ]
42642da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
42652da392ccSBarry Smith         [             ]       [             ]         [                 ]
4266170fe5c8SBarry Smith 
4267170fe5c8SBarry Smith */
4268170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4269170fe5c8SBarry Smith {
4270170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4271170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4272170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
427386214ceeSStefano Zampini   PetscInt          i,j,n,m,q,p;
4274170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4275170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4276170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
427786214ceeSStefano Zampini   PetscInt          clda = sub_c->lda;
427886214ceeSStefano Zampini   PetscInt          alda = sub_a->lda;
4279170fe5c8SBarry Smith 
4280170fe5c8SBarry Smith   PetscFunctionBegin;
4281d0f46423SBarry Smith   m    = A->rmap->n;
4282d0f46423SBarry Smith   n    = A->cmap->n;
4283d0f46423SBarry Smith   p    = B->cmap->n;
4284170fe5c8SBarry Smith   a    = sub_a->v;
4285170fe5c8SBarry Smith   b    = sub_b->a;
4286170fe5c8SBarry Smith   c    = sub_c->v;
428786214ceeSStefano Zampini   if (clda == m) {
42889566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(c,m*p));
428986214ceeSStefano Zampini   } else {
429086214ceeSStefano Zampini     for (j=0;j<p;j++)
429186214ceeSStefano Zampini       for (i=0;i<m;i++)
429286214ceeSStefano Zampini         c[j*clda + i] = 0.0;
429386214ceeSStefano Zampini   }
4294170fe5c8SBarry Smith   ii  = sub_b->i;
4295170fe5c8SBarry Smith   idx = sub_b->j;
4296170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4297170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4298170fe5c8SBarry Smith     while (q-->0) {
429986214ceeSStefano Zampini       c_q = c + clda*(*idx);
430086214ceeSStefano Zampini       a_q = a + alda*i;
4301854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4302170fe5c8SBarry Smith       idx++;
4303170fe5c8SBarry Smith       b++;
4304170fe5c8SBarry Smith     }
4305170fe5c8SBarry Smith   }
4306170fe5c8SBarry Smith   PetscFunctionReturn(0);
4307170fe5c8SBarry Smith }
4308170fe5c8SBarry Smith 
43094222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C)
4310170fe5c8SBarry Smith {
4311d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
431286214ceeSStefano Zampini   PetscBool      cisdense;
4313170fe5c8SBarry Smith 
4314170fe5c8SBarry Smith   PetscFunctionBegin;
431508401ef6SPierre 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);
43169566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C,m,n,m,n));
43179566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(C,A,B));
43189566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,""));
431986214ceeSStefano Zampini   if (!cisdense) {
43209566063dSJacob Faibussowitsch     PetscCall(MatSetType(C,MATDENSE));
432186214ceeSStefano Zampini   }
43229566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
4323d73949e8SHong Zhang 
43244222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4325170fe5c8SBarry Smith   PetscFunctionReturn(0);
4326170fe5c8SBarry Smith }
4327170fe5c8SBarry Smith 
4328170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
43290bad9183SKris Buschelman /*MC
4330fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
43310bad9183SKris Buschelman    based on compressed sparse row format.
43320bad9183SKris Buschelman 
43330bad9183SKris Buschelman    Options Database Keys:
43340bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
43350bad9183SKris Buschelman 
43360bad9183SKris Buschelman    Level: beginner
43370bad9183SKris Buschelman 
43380cd7f59aSBarry Smith    Notes:
43390cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
43400cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
43410cd7f59aSBarry Smith     in the matrix
43420cd7f59aSBarry Smith 
43430cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
43440cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
43450cd7f59aSBarry Smith 
43460cd7f59aSBarry Smith   Developer Notes:
43470cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
43480cd7f59aSBarry Smith 
4349db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MatSetFromOptions()`, `MatSetType()`, `MatCreate()`, `MatType`, `MATSELL`, `MATSEQSELL`, `MATMPISELL`
43500bad9183SKris Buschelman M*/
43510bad9183SKris Buschelman 
4352ccd284c7SBarry Smith /*MC
4353ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4354ccd284c7SBarry Smith 
4355ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4356ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
4357ed73aabaSBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4358ccd284c7SBarry Smith    for communicators controlling multiple processes.  It is recommended that you call both of
4359ccd284c7SBarry Smith    the above preallocation routines for simplicity.
4360ccd284c7SBarry Smith 
4361ccd284c7SBarry Smith    Options Database Keys:
4362ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4363ccd284c7SBarry Smith 
436495452b02SPatrick Sanan   Developer Notes:
4365ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4366ccd284c7SBarry Smith    enough exist.
4367ccd284c7SBarry Smith 
4368ccd284c7SBarry Smith   Level: beginner
4369ccd284c7SBarry Smith 
4370db781477SPatrick Sanan .seealso: `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATMPIAIJ`, `MATSELL`, `MATSEQSELL`, `MATMPISELL`
4371ccd284c7SBarry Smith M*/
4372ccd284c7SBarry Smith 
4373ccd284c7SBarry Smith /*MC
4374ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4375ccd284c7SBarry Smith 
4376ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4377ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4378ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4379ccd284c7SBarry Smith    for communicators controlling multiple processes.  It is recommended that you call both of
4380ccd284c7SBarry Smith    the above preallocation routines for simplicity.
4381ccd284c7SBarry Smith 
4382ccd284c7SBarry Smith    Options Database Keys:
4383ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4384ccd284c7SBarry Smith 
4385ccd284c7SBarry Smith   Level: beginner
4386ccd284c7SBarry Smith 
4387*c2e3fba1SPatrick Sanan .seealso: `MatCreateMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL`
4388ccd284c7SBarry Smith M*/
4389ccd284c7SBarry Smith 
43907906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
43917906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
43927906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
43937906f579SHong Zhang #endif
4394d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4395d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*);
4396d24d4204SJose E. Roman #endif
43977906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
43987906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
43997906f579SHong Zhang #endif
44007906f579SHong Zhang 
4401d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4402c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
44034222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
44047906f579SHong Zhang 
44058c778c55SBarry Smith /*@C
44068f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
44078c778c55SBarry Smith 
44088c778c55SBarry Smith    Not Collective
44098c778c55SBarry Smith 
44108c778c55SBarry Smith    Input Parameter:
4411579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
44128c778c55SBarry Smith 
44138c778c55SBarry Smith    Output Parameter:
44148c778c55SBarry Smith .   array - pointer to the data
44158c778c55SBarry Smith 
44168c778c55SBarry Smith    Level: intermediate
44178c778c55SBarry Smith 
4418db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()`
44198c778c55SBarry Smith @*/
44208c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
44218c778c55SBarry Smith {
4422d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
44238c778c55SBarry Smith 
44248c778c55SBarry Smith   PetscFunctionBegin;
4425d67d9f35SJunchao Zhang   if (aij->ops->getarray) {
44269566063dSJacob Faibussowitsch     PetscCall((*aij->ops->getarray)(A,array));
4427d67d9f35SJunchao Zhang   } else {
4428d67d9f35SJunchao Zhang     *array = aij->a;
4429d67d9f35SJunchao Zhang   }
4430d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4431d67d9f35SJunchao Zhang }
4432d67d9f35SJunchao Zhang 
4433d67d9f35SJunchao Zhang /*@C
4434d67d9f35SJunchao Zhang    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
4435d67d9f35SJunchao Zhang 
4436d67d9f35SJunchao Zhang    Not Collective
4437d67d9f35SJunchao Zhang 
4438d67d9f35SJunchao Zhang    Input Parameters:
4439d67d9f35SJunchao Zhang +  mat - a MATSEQAIJ matrix
4440d67d9f35SJunchao Zhang -  array - pointer to the data
4441d67d9f35SJunchao Zhang 
4442d67d9f35SJunchao Zhang    Level: intermediate
4443d67d9f35SJunchao Zhang 
4444db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayF90()`
4445d67d9f35SJunchao Zhang @*/
4446d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
4447d67d9f35SJunchao Zhang {
4448d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4449d67d9f35SJunchao Zhang 
4450d67d9f35SJunchao Zhang   PetscFunctionBegin;
4451d67d9f35SJunchao Zhang   if (aij->ops->restorearray) {
44529566063dSJacob Faibussowitsch     PetscCall((*aij->ops->restorearray)(A,array));
4453d67d9f35SJunchao Zhang   } else {
4454d67d9f35SJunchao Zhang     *array = NULL;
4455d67d9f35SJunchao Zhang   }
44569566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(A));
44579566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
44588c778c55SBarry Smith   PetscFunctionReturn(0);
44598c778c55SBarry Smith }
44608c778c55SBarry Smith 
446121e72a00SBarry Smith /*@C
44628f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
44638f1ea47aSStefano Zampini 
44648f1ea47aSStefano Zampini    Not Collective
44658f1ea47aSStefano Zampini 
44668f1ea47aSStefano Zampini    Input Parameter:
44678f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
44688f1ea47aSStefano Zampini 
44698f1ea47aSStefano Zampini    Output Parameter:
44708f1ea47aSStefano Zampini .   array - pointer to the data
44718f1ea47aSStefano Zampini 
44728f1ea47aSStefano Zampini    Level: intermediate
44738f1ea47aSStefano Zampini 
4474db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()`
44758f1ea47aSStefano Zampini @*/
44768f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
44778f1ea47aSStefano Zampini {
4478d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
44798f1ea47aSStefano Zampini 
44808f1ea47aSStefano Zampini   PetscFunctionBegin;
4481d67d9f35SJunchao Zhang   if (aij->ops->getarrayread) {
44829566063dSJacob Faibussowitsch     PetscCall((*aij->ops->getarrayread)(A,array));
4483d67d9f35SJunchao Zhang   } else {
4484d67d9f35SJunchao Zhang     *array = aij->a;
4485d67d9f35SJunchao Zhang   }
44868f1ea47aSStefano Zampini   PetscFunctionReturn(0);
44878f1ea47aSStefano Zampini }
44888f1ea47aSStefano Zampini 
44898f1ea47aSStefano Zampini /*@C
44908f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
44918f1ea47aSStefano Zampini 
44928f1ea47aSStefano Zampini    Not Collective
44938f1ea47aSStefano Zampini 
44948f1ea47aSStefano Zampini    Input Parameter:
44958f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
44968f1ea47aSStefano Zampini 
44978f1ea47aSStefano Zampini    Output Parameter:
44988f1ea47aSStefano Zampini .   array - pointer to the data
44998f1ea47aSStefano Zampini 
45008f1ea47aSStefano Zampini    Level: intermediate
45018f1ea47aSStefano Zampini 
4502db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()`
45038f1ea47aSStefano Zampini @*/
45048f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
45058f1ea47aSStefano Zampini {
4506d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
45078f1ea47aSStefano Zampini 
45088f1ea47aSStefano Zampini   PetscFunctionBegin;
4509d67d9f35SJunchao Zhang   if (aij->ops->restorearrayread) {
45109566063dSJacob Faibussowitsch     PetscCall((*aij->ops->restorearrayread)(A,array));
4511d67d9f35SJunchao Zhang   } else {
4512d67d9f35SJunchao Zhang     *array = NULL;
4513d67d9f35SJunchao Zhang   }
4514d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4515d67d9f35SJunchao Zhang }
4516d67d9f35SJunchao Zhang 
4517d67d9f35SJunchao Zhang /*@C
4518d67d9f35SJunchao Zhang    MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a MATSEQAIJ matrix is stored
4519d67d9f35SJunchao Zhang 
4520d67d9f35SJunchao Zhang    Not Collective
4521d67d9f35SJunchao Zhang 
4522d67d9f35SJunchao Zhang    Input Parameter:
4523d67d9f35SJunchao Zhang .  mat - a MATSEQAIJ matrix
4524d67d9f35SJunchao Zhang 
4525d67d9f35SJunchao Zhang    Output Parameter:
4526d67d9f35SJunchao Zhang .   array - pointer to the data
4527d67d9f35SJunchao Zhang 
4528d67d9f35SJunchao Zhang    Level: intermediate
4529d67d9f35SJunchao Zhang 
4530db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()`
4531d67d9f35SJunchao Zhang @*/
4532d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJGetArrayWrite(Mat A,PetscScalar **array)
4533d67d9f35SJunchao Zhang {
4534d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4535d67d9f35SJunchao Zhang 
4536d67d9f35SJunchao Zhang   PetscFunctionBegin;
4537d67d9f35SJunchao Zhang   if (aij->ops->getarraywrite) {
45389566063dSJacob Faibussowitsch     PetscCall((*aij->ops->getarraywrite)(A,array));
4539d67d9f35SJunchao Zhang   } else {
4540d67d9f35SJunchao Zhang     *array = aij->a;
4541d67d9f35SJunchao Zhang   }
45429566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal(A));
45439566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
4544d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4545d67d9f35SJunchao Zhang }
4546d67d9f35SJunchao Zhang 
4547d67d9f35SJunchao Zhang /*@C
4548d67d9f35SJunchao Zhang    MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead
4549d67d9f35SJunchao Zhang 
4550d67d9f35SJunchao Zhang    Not Collective
4551d67d9f35SJunchao Zhang 
4552d67d9f35SJunchao Zhang    Input Parameter:
4553d67d9f35SJunchao Zhang .  mat - a MATSEQAIJ matrix
4554d67d9f35SJunchao Zhang 
4555d67d9f35SJunchao Zhang    Output Parameter:
4556d67d9f35SJunchao Zhang .   array - pointer to the data
4557d67d9f35SJunchao Zhang 
4558d67d9f35SJunchao Zhang    Level: intermediate
4559d67d9f35SJunchao Zhang 
4560db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()`
4561d67d9f35SJunchao Zhang @*/
4562d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJRestoreArrayWrite(Mat A,PetscScalar **array)
4563d67d9f35SJunchao Zhang {
4564d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4565d67d9f35SJunchao Zhang 
4566d67d9f35SJunchao Zhang   PetscFunctionBegin;
4567d67d9f35SJunchao Zhang   if (aij->ops->restorearraywrite) {
45689566063dSJacob Faibussowitsch     PetscCall((*aij->ops->restorearraywrite)(A,array));
4569d67d9f35SJunchao Zhang   } else {
4570d67d9f35SJunchao Zhang     *array = NULL;
4571d67d9f35SJunchao Zhang   }
45728f1ea47aSStefano Zampini   PetscFunctionReturn(0);
45738f1ea47aSStefano Zampini }
45748f1ea47aSStefano Zampini 
45758f1ea47aSStefano Zampini /*@C
45767ee59b9bSJunchao Zhang    MatSeqAIJGetCSRAndMemType - Get the CSR arrays and the memory type of the SEQAIJ matrix
45777ee59b9bSJunchao Zhang 
45787ee59b9bSJunchao Zhang    Not Collective
45797ee59b9bSJunchao Zhang 
45807ee59b9bSJunchao Zhang    Input Parameter:
45817ee59b9bSJunchao Zhang .  mat - a matrix of type MATSEQAIJ or its subclasses
45827ee59b9bSJunchao Zhang 
45837ee59b9bSJunchao Zhang    Output Parameters:
45847ee59b9bSJunchao Zhang +  i - row map array of the matrix
45857ee59b9bSJunchao Zhang .  j - column index array of the matrix
45867ee59b9bSJunchao Zhang .  a - data array of the matrix
45877ee59b9bSJunchao Zhang -  memtype - memory type of the arrays
45887ee59b9bSJunchao Zhang 
45897ee59b9bSJunchao Zhang   Notes:
45907ee59b9bSJunchao Zhang    Any of the output parameters can be NULL, in which case the corresponding value is not returned.
45917ee59b9bSJunchao Zhang    If mat is a device matrix, the arrays are on the device. Otherwise, they are on the host.
45927ee59b9bSJunchao Zhang 
45937ee59b9bSJunchao Zhang    One can call this routine on a preallocated but not assembled matrix to just get the memory of the CSR underneath the matrix.
45947ee59b9bSJunchao Zhang    If the matrix is assembled, the data array 'a' is guaranteed to have the latest values of the matrix.
45957ee59b9bSJunchao Zhang 
45967ee59b9bSJunchao Zhang    Level: Developer
45977ee59b9bSJunchao Zhang 
4598db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()`
45997ee59b9bSJunchao Zhang @*/
46007ee59b9bSJunchao Zhang PetscErrorCode MatSeqAIJGetCSRAndMemType(Mat mat,const PetscInt **i,const PetscInt **j,PetscScalar **a,PetscMemType *mtype)
46017ee59b9bSJunchao Zhang {
46027ee59b9bSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
46037ee59b9bSJunchao Zhang 
46047ee59b9bSJunchao Zhang   PetscFunctionBegin;
46057ee59b9bSJunchao Zhang   PetscCheck(mat->preallocated,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"matrix is not preallocated");
46067ee59b9bSJunchao Zhang   if (aij->ops->getcsrandmemtype) {
46077ee59b9bSJunchao Zhang     PetscCall((*aij->ops->getcsrandmemtype)(mat,i,j,a,mtype));
46087ee59b9bSJunchao Zhang   } else {
46097ee59b9bSJunchao Zhang     if (i) *i = aij->i;
46107ee59b9bSJunchao Zhang     if (j) *j = aij->j;
46117ee59b9bSJunchao Zhang     if (a) *a = aij->a;
46127ee59b9bSJunchao Zhang     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
46137ee59b9bSJunchao Zhang   }
46147ee59b9bSJunchao Zhang   PetscFunctionReturn(0);
46157ee59b9bSJunchao Zhang }
46167ee59b9bSJunchao Zhang 
46177ee59b9bSJunchao Zhang /*@C
461821e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
461921e72a00SBarry Smith 
462021e72a00SBarry Smith    Not Collective
462121e72a00SBarry Smith 
462221e72a00SBarry Smith    Input Parameter:
4623579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
462421e72a00SBarry Smith 
462521e72a00SBarry Smith    Output Parameter:
462621e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
462721e72a00SBarry Smith 
462821e72a00SBarry Smith    Level: intermediate
462921e72a00SBarry Smith 
4630db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()`
463121e72a00SBarry Smith @*/
463221e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
463321e72a00SBarry Smith {
463421e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
463521e72a00SBarry Smith 
463621e72a00SBarry Smith   PetscFunctionBegin;
463721e72a00SBarry Smith   *nz = aij->rmax;
463821e72a00SBarry Smith   PetscFunctionReturn(0);
463921e72a00SBarry Smith }
464021e72a00SBarry Smith 
4641394ed5ebSJunchao Zhang PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, const PetscInt coo_i[], const PetscInt coo_j[])
4642394ed5ebSJunchao Zhang {
4643394ed5ebSJunchao Zhang   MPI_Comm                  comm;
4644394ed5ebSJunchao Zhang   PetscInt                  *i,*j;
4645394ed5ebSJunchao Zhang   PetscInt                  M,N,row;
4646394ed5ebSJunchao Zhang   PetscCount                k,p,q,nneg,nnz,start,end; /* Index the coo array, so use PetscCount as their type */
4647394ed5ebSJunchao Zhang   PetscInt                  *Ai; /* Change to PetscCount once we use it for row pointers */
4648394ed5ebSJunchao Zhang   PetscInt                  *Aj;
4649394ed5ebSJunchao Zhang   PetscScalar               *Aa;
4650cbc6b225SStefano Zampini   Mat_SeqAIJ                *seqaij = (Mat_SeqAIJ*)(mat->data);
4651cbc6b225SStefano Zampini   MatType                   rtype;
4652394ed5ebSJunchao Zhang   PetscCount                *perm,*jmap;
4653394ed5ebSJunchao Zhang 
4654394ed5ebSJunchao Zhang   PetscFunctionBegin;
46559566063dSJacob Faibussowitsch   PetscCall(MatResetPreallocationCOO_SeqAIJ(mat));
46569566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
46579566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat,&M,&N));
46589566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(coo_n,&i,coo_n,&j));
46599566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(i,coo_i,coo_n)); /* Make a copy since we'll modify it */
46609566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(j,coo_j,coo_n));
46619566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(coo_n,&perm));
4662394ed5ebSJunchao Zhang   for (k=0; k<coo_n; k++) { /* Ignore entries with negative row or col indices */
4663394ed5ebSJunchao Zhang     if (j[k] < 0) i[k] = -1;
4664394ed5ebSJunchao Zhang     perm[k] = k;
4665394ed5ebSJunchao Zhang   }
4666394ed5ebSJunchao Zhang 
4667394ed5ebSJunchao Zhang   /* Sort by row */
46689566063dSJacob Faibussowitsch   PetscCall(PetscSortIntWithIntCountArrayPair(coo_n,i,j,perm));
4669394ed5ebSJunchao Zhang   for (k=0; k<coo_n; k++) {if (i[k] >= 0) break;} /* Advance k to the first row with a non-negative index */
4670394ed5ebSJunchao Zhang   nneg = k;
46719566063dSJacob 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 */
4672394ed5ebSJunchao Zhang   nnz  = 0; /* Total number of unique nonzeros to be counted */
4673394ed5ebSJunchao Zhang   jmap++; /* Inc jmap by 1 for convinience */
4674394ed5ebSJunchao Zhang 
46759566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(M+1,&Ai)); /* CSR of A */
46769566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(coo_n-nneg,&Aj)); /* We have at most coo_n-nneg unique nonzeros */
4677394ed5ebSJunchao Zhang 
4678394ed5ebSJunchao Zhang   /* In each row, sort by column, then unique column indices to get row length */
4679394ed5ebSJunchao Zhang   Ai++; /* Inc by 1 for convinience */
4680394ed5ebSJunchao Zhang   q = 0; /* q-th unique nonzero, with q starting from 0 */
4681394ed5ebSJunchao Zhang   while (k<coo_n) {
4682394ed5ebSJunchao Zhang     row   = i[k];
4683394ed5ebSJunchao Zhang     start = k; /* [start,end) indices for this row */
4684394ed5ebSJunchao Zhang     while (k<coo_n && i[k] == row) k++;
4685394ed5ebSJunchao Zhang     end   = k;
46869566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithCountArray(end-start,j+start,perm+start));
4687394ed5ebSJunchao Zhang     /* Find number of unique col entries in this row */
4688394ed5ebSJunchao Zhang     Aj[q]   = j[start]; /* Log the first nonzero in this row */
4689394ed5ebSJunchao Zhang     jmap[q] = 1; /* Number of repeats of this nozero entry */
4690394ed5ebSJunchao Zhang     Ai[row] = 1;
4691394ed5ebSJunchao Zhang     nnz++;
4692394ed5ebSJunchao Zhang 
4693394ed5ebSJunchao Zhang     for (p=start+1; p<end; p++) { /* Scan remaining nonzero in this row */
4694394ed5ebSJunchao Zhang       if (j[p] != j[p-1]) { /* Meet a new nonzero */
4695394ed5ebSJunchao Zhang         q++;
4696394ed5ebSJunchao Zhang         jmap[q] = 1;
4697394ed5ebSJunchao Zhang         Aj[q]   = j[p];
4698394ed5ebSJunchao Zhang         Ai[row]++;
4699394ed5ebSJunchao Zhang         nnz++;
4700394ed5ebSJunchao Zhang       } else {
4701394ed5ebSJunchao Zhang         jmap[q]++;
4702394ed5ebSJunchao Zhang       }
4703394ed5ebSJunchao Zhang     }
4704394ed5ebSJunchao Zhang     q++; /* Move to next row and thus next unique nonzero */
4705394ed5ebSJunchao Zhang   }
47069566063dSJacob Faibussowitsch   PetscCall(PetscFree2(i,j));
4707394ed5ebSJunchao Zhang 
4708394ed5ebSJunchao Zhang   Ai--; /* Back to the beginning of Ai[] */
4709394ed5ebSJunchao Zhang   for (k=0; k<M; k++) Ai[k+1] += Ai[k];
4710394ed5ebSJunchao Zhang   jmap--; /* Back to the beginning of jmap[] */
4711394ed5ebSJunchao Zhang   jmap[0] = 0;
4712394ed5ebSJunchao Zhang   for (k=0; k<nnz; k++) jmap[k+1] += jmap[k];
4713394ed5ebSJunchao Zhang   if (nnz < coo_n-nneg) { /* Realloc with actual number of unique nonzeros */
4714394ed5ebSJunchao Zhang     PetscCount *jmap_new;
4715394ed5ebSJunchao Zhang     PetscInt   *Aj_new;
4716394ed5ebSJunchao Zhang 
47179566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz+1,&jmap_new));
47189566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(jmap_new,jmap,nnz+1));
47199566063dSJacob Faibussowitsch     PetscCall(PetscFree(jmap));
4720394ed5ebSJunchao Zhang     jmap = jmap_new;
4721394ed5ebSJunchao Zhang 
47229566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz,&Aj_new));
47239566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(Aj_new,Aj,nnz));
47249566063dSJacob Faibussowitsch     PetscCall(PetscFree(Aj));
4725394ed5ebSJunchao Zhang     Aj   = Aj_new;
4726394ed5ebSJunchao Zhang   }
4727394ed5ebSJunchao Zhang 
4728394ed5ebSJunchao Zhang   if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */
4729394ed5ebSJunchao Zhang     PetscCount *perm_new;
4730cbc6b225SStefano Zampini 
47319566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coo_n-nneg,&perm_new));
47329566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(perm_new,perm+nneg,coo_n-nneg));
47339566063dSJacob Faibussowitsch     PetscCall(PetscFree(perm));
4734394ed5ebSJunchao Zhang     perm = perm_new;
4735394ed5ebSJunchao Zhang   }
4736394ed5ebSJunchao Zhang 
47379566063dSJacob Faibussowitsch   PetscCall(MatGetRootType_Private(mat,&rtype));
47389566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nnz,&Aa)); /* Zero the matrix */
47399566063dSJacob Faibussowitsch   PetscCall(MatSetSeqAIJWithArrays_private(PETSC_COMM_SELF,M,N,Ai,Aj,Aa,rtype,mat));
4740394ed5ebSJunchao Zhang 
4741394ed5ebSJunchao Zhang   seqaij->singlemalloc = PETSC_FALSE; /* Ai, Aj and Aa are not allocated in one big malloc */
4742394ed5ebSJunchao Zhang   seqaij->free_a       = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */
4743394ed5ebSJunchao Zhang   /* Record COO fields */
4744394ed5ebSJunchao Zhang   seqaij->coo_n        = coo_n;
4745394ed5ebSJunchao Zhang   seqaij->Atot         = coo_n-nneg; /* Annz is seqaij->nz, so no need to record that again */
4746394ed5ebSJunchao Zhang   seqaij->jmap         = jmap; /* of length nnz+1 */
4747394ed5ebSJunchao Zhang   seqaij->perm         = perm;
4748394ed5ebSJunchao Zhang   PetscFunctionReturn(0);
4749394ed5ebSJunchao Zhang }
4750394ed5ebSJunchao Zhang 
4751394ed5ebSJunchao Zhang static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A,const PetscScalar v[],InsertMode imode)
4752394ed5ebSJunchao Zhang {
4753394ed5ebSJunchao Zhang   Mat_SeqAIJ                  *aseq = (Mat_SeqAIJ*)A->data;
4754394ed5ebSJunchao Zhang   PetscCount                  i,j,Annz = aseq->nz;
4755394ed5ebSJunchao Zhang   PetscCount                  *perm = aseq->perm,*jmap = aseq->jmap;
4756394ed5ebSJunchao Zhang   PetscScalar                 *Aa;
4757394ed5ebSJunchao Zhang 
4758394ed5ebSJunchao Zhang   PetscFunctionBegin;
47599566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A,&Aa));
4760394ed5ebSJunchao Zhang   for (i=0; i<Annz; i++) {
4761b6c38306SJunchao Zhang     PetscScalar sum = 0.0;
4762b6c38306SJunchao Zhang     for (j=jmap[i]; j<jmap[i+1]; j++) sum += v[perm[j]];
4763b6c38306SJunchao Zhang     Aa[i] = (imode == INSERT_VALUES? 0.0 : Aa[i]) + sum;
4764394ed5ebSJunchao Zhang   }
47659566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A,&Aa));
4766394ed5ebSJunchao Zhang   PetscFunctionReturn(0);
4767394ed5ebSJunchao Zhang }
4768394ed5ebSJunchao Zhang 
476934b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
47705063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat,MatType,MatReuse,Mat*);
477102fe1965SBarry Smith #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 
47768cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4777273d9f13SBarry Smith {
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 
47859566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(B,&b));
47862205254eSKarl Rupp 
4787b0a32e0cSBarry Smith   B->data = (void*)b;
47882205254eSKarl Rupp 
47899566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps)));
4790071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
47912205254eSKarl Rupp 
4792f4259b30SLisandro Dalcin   b->row                = NULL;
4793f4259b30SLisandro Dalcin   b->col                = NULL;
4794f4259b30SLisandro Dalcin   b->icol               = NULL;
4795b810aeb4SBarry Smith   b->reallocs           = 0;
479636db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4797f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4798416022c9SBarry Smith   b->nonew              = 0;
4799f4259b30SLisandro Dalcin   b->diag               = NULL;
4800f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4801f4259b30SLisandro Dalcin   B->spptr              = NULL;
4802f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4803f4259b30SLisandro Dalcin   b->idiag              = NULL;
4804f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4805f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
480671f1c65dSBarry Smith   b->omega              = 1.0;
480771f1c65dSBarry Smith   b->fshift             = 0.0;
480871f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4809bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4810a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
481117ab2063SBarry Smith 
48129566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ));
48138c778c55SBarry Smith 
4814b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
48159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ));
48169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ));
4817b3866ffcSBarry Smith #endif
481817f1a0eaSHong Zhang 
48199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ));
48209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ));
48219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ));
48229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ));
48239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ));
48249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM));
48259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL));
48269779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
48279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL));
4828191b95cbSRichard Tran Mills #endif
482934b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
48309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE));
48319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ));
48329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",MatProductSetFromOptions_SeqAIJ));
483302fe1965SBarry Smith #endif
48343d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
48359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos));
48363d0639e7SStefano Zampini #endif
48379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL));
4838af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
48399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental));
4840af8000cdSHong Zhang #endif
4841d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
48429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK));
4843d24d4204SJose E. Roman #endif
484463c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
48459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE));
48469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ));
484763c07aadSStefano Zampini #endif
48489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense));
48499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL));
48509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS));
48519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ));
48529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ));
48539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ));
48549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ));
48559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ));
48569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ));
48579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ));
48589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ));
48599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ));
48609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJKron_C",MatSeqAIJKron_SeqAIJ));
48619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSetPreallocationCOO_C",MatSetPreallocationCOO_SeqAIJ));
48629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSetValuesCOO_C",MatSetValuesCOO_SeqAIJ));
48639566063dSJacob Faibussowitsch   PetscCall(MatCreate_SeqAIJ_Inode(B));
48649566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ));
48659566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetTypeFromOptions(B));  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
48663a40ed3dSBarry Smith   PetscFunctionReturn(0);
486717ab2063SBarry Smith }
486817ab2063SBarry Smith 
4869b24902e0SBarry Smith /*
4870b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4871b24902e0SBarry Smith */
4872ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
487317ab2063SBarry Smith {
48742a350339SBarry Smith   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data;
4875071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
487617ab2063SBarry Smith 
48773a40ed3dSBarry Smith   PetscFunctionBegin;
4878aed4548fSBarry Smith   PetscCheck(A->assembled || cpvalues == MAT_DO_NOT_COPY_VALUES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix");
4879273d9f13SBarry Smith 
4880d5f3da31SBarry Smith   C->factortype = A->factortype;
4881f4259b30SLisandro Dalcin   c->row        = NULL;
4882f4259b30SLisandro Dalcin   c->col        = NULL;
4883f4259b30SLisandro Dalcin   c->icol       = NULL;
48846ad4291fSHong Zhang   c->reallocs   = 0;
488517ab2063SBarry Smith 
488669272f91SPierre Jolivet   C->assembled    = A->assembled;
488769272f91SPierre Jolivet   C->preallocated = A->preallocated;
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 
48939566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m,&c->imax));
48949566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt)));
48959566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m,&c->ilen));
48969566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt)));
48979566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt)));
489817ab2063SBarry Smith 
489917ab2063SBarry Smith     /* allocate the matrix space */
4900f77e22a1SHong Zhang     if (mallocmatspace) {
49019566063dSJacob Faibussowitsch       PetscCall(PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i));
49029566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt)));
49032205254eSKarl Rupp 
4904f1e2ffcdSBarry Smith       c->singlemalloc = PETSC_TRUE;
49052205254eSKarl Rupp 
49069566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->i,a->i,m+1));
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     }
492017ab2063SBarry Smith 
49216ad4291fSHong Zhang     c->ignorezeroentries = a->ignorezeroentries;
4922416022c9SBarry Smith     c->roworiented       = a->roworiented;
4923416022c9SBarry Smith     c->nonew             = a->nonew;
4924416022c9SBarry Smith     if (a->diag) {
49259566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(m+1,&c->diag));
49269566063dSJacob Faibussowitsch       PetscCall(PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt)));
49279566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt)));
4928071fcb05SBarry Smith     } else c->diag = NULL;
49292205254eSKarl Rupp 
4930f4259b30SLisandro Dalcin     c->solve_work         = NULL;
4931f4259b30SLisandro Dalcin     c->saved_values       = NULL;
4932f4259b30SLisandro Dalcin     c->idiag              = NULL;
4933f4259b30SLisandro Dalcin     c->ssor_work          = NULL;
4934a9817697SBarry Smith     c->keepnonzeropattern = a->keepnonzeropattern;
4935e6b907acSBarry Smith     c->free_a             = PETSC_TRUE;
4936e6b907acSBarry Smith     c->free_ij            = PETSC_TRUE;
49376ad4291fSHong Zhang 
4938893ad86cSHong Zhang     c->rmax         = a->rmax;
4939416022c9SBarry Smith     c->nz           = a->nz;
49408ed568f8SMatthew G Knepley     c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4941754ec7b1SSatish Balay 
49426ad4291fSHong Zhang     c->compressedrow.use   = a->compressedrow.use;
49436ad4291fSHong Zhang     c->compressedrow.nrows = a->compressedrow.nrows;
4944cd6b891eSBarry Smith     if (a->compressedrow.use) {
49456ad4291fSHong Zhang       i    = a->compressedrow.nrows;
49469566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex));
49479566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1));
49489566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i));
494927ea64f8SHong Zhang     } else {
495027ea64f8SHong Zhang       c->compressedrow.use    = PETSC_FALSE;
49510298fd71SBarry Smith       c->compressedrow.i      = NULL;
49520298fd71SBarry Smith       c->compressedrow.rindex = NULL;
49536ad4291fSHong Zhang     }
4954ea632784SBarry Smith     c->nonzerorowcnt = a->nonzerorowcnt;
4955e56f5c9eSBarry Smith     C->nonzerostate  = A->nonzerostate;
49564846f1f5SKris Buschelman 
49579566063dSJacob Faibussowitsch     PetscCall(MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C));
495869272f91SPierre Jolivet   }
49599566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist));
49603a40ed3dSBarry Smith   PetscFunctionReturn(0);
496117ab2063SBarry Smith }
496217ab2063SBarry Smith 
4963b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4964b24902e0SBarry Smith {
4965b24902e0SBarry Smith   PetscFunctionBegin;
49669566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A),B));
49679566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n));
4968cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
49699566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(*B,A,A));
4970cfd3f464SBarry Smith   }
49719566063dSJacob Faibussowitsch   PetscCall(MatSetType(*B,((PetscObject)A)->type_name));
49729566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE));
4973b24902e0SBarry Smith   PetscFunctionReturn(0);
4974b24902e0SBarry Smith }
4975b24902e0SBarry Smith 
4976112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4977fbdbba38SShri Abhyankar {
497852f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
497952f91c60SVaclav Hapla 
498052f91c60SVaclav Hapla   PetscFunctionBegin;
498152f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
498252f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4983c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
49849566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
49859566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary));
49869566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5));
498752f91c60SVaclav Hapla   if (isbinary) {
49889566063dSJacob Faibussowitsch     PetscCall(MatLoad_SeqAIJ_Binary(newMat,viewer));
498952f91c60SVaclav Hapla   } else if (ishdf5) {
499052f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
49919566063dSJacob Faibussowitsch     PetscCall(MatLoad_AIJ_HDF5(newMat,viewer));
499252f91c60SVaclav Hapla #else
499352f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
499452f91c60SVaclav Hapla #endif
499552f91c60SVaclav Hapla   } else {
499698921bdaSJacob 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);
499752f91c60SVaclav Hapla   }
499852f91c60SVaclav Hapla   PetscFunctionReturn(0);
499952f91c60SVaclav Hapla }
500052f91c60SVaclav Hapla 
50013ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
500252f91c60SVaclav Hapla {
50033ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
50043ea6fe3dSLisandro Dalcin   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
5005fbdbba38SShri Abhyankar 
5006fbdbba38SShri Abhyankar   PetscFunctionBegin;
50079566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
5008bbead8a2SBarry Smith 
50093ea6fe3dSLisandro Dalcin   /* read in matrix header */
50109566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT));
501108401ef6SPierre Jolivet   PetscCheck(header[0] == MAT_FILE_CLASSID,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
5012fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
501308401ef6SPierre Jolivet   PetscCheck(M >= 0,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%" PetscInt_FMT ") in file is negative",M);
501408401ef6SPierre Jolivet   PetscCheck(N >= 0,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%" PetscInt_FMT ") in file is negative",N);
501508401ef6SPierre Jolivet   PetscCheck(nz >= 0,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
5016fbdbba38SShri Abhyankar 
50173ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
50189566063dSJacob Faibussowitsch   PetscCall(MatLoad_Binary_BlockSizes(mat,viewer));
50193ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
50203ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
50213ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
50223ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
50233ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
50249566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
50259566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
50263ea6fe3dSLisandro Dalcin 
50273ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
50289566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat,&rows,&cols));
5029aed4548fSBarry 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);
50303ea6fe3dSLisandro Dalcin 
5031fbdbba38SShri Abhyankar   /* read in row lengths */
50329566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(M,&rowlens));
50339566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT));
50343ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
50353ea6fe3dSLisandro Dalcin   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
503608401ef6SPierre 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);
50373ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
50389566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens));
50399566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat,&rows,&cols));
5040aed4548fSBarry 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);
50413ea6fe3dSLisandro Dalcin   /* store row lengths */
50429566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(a->ilen,rowlens,M));
50439566063dSJacob Faibussowitsch   PetscCall(PetscFree(rowlens));
5044fbdbba38SShri Abhyankar 
50453ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
50463ea6fe3dSLisandro Dalcin   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
50473ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
50489566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT));
50493ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
50509566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR));
5051fbdbba38SShri Abhyankar 
50529566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY));
50539566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY));
5054fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
5055fbdbba38SShri Abhyankar }
5056fbdbba38SShri Abhyankar 
5057ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
50587264ac53SSatish Balay {
50597264ac53SSatish Balay   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
5060fff043a9SJunchao Zhang   const PetscScalar *aa,*ba;
5061eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
5062eeffb40dSHong Zhang   PetscInt k;
5063eeffb40dSHong Zhang #endif
50647264ac53SSatish Balay 
50653a40ed3dSBarry Smith   PetscFunctionBegin;
5066bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
5067d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
5068ca44d042SBarry Smith     *flg = PETSC_FALSE;
5069ca44d042SBarry Smith     PetscFunctionReturn(0);
5070bcd2baecSBarry Smith   }
50717264ac53SSatish Balay 
50727264ac53SSatish Balay   /* if the a->i are the same */
50739566063dSJacob Faibussowitsch   PetscCall(PetscArraycmp(a->i,b->i,A->rmap->n+1,flg));
5074abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
50757264ac53SSatish Balay 
50767264ac53SSatish Balay   /* if a->j are the same */
50779566063dSJacob Faibussowitsch   PetscCall(PetscArraycmp(a->j,b->j,a->nz,flg));
5078abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
5079bcd2baecSBarry Smith 
50809566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A,&aa));
50819566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(B,&ba));
5082bcd2baecSBarry Smith   /* if a->a are the same */
5083eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
5084eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
5085fff043a9SJunchao Zhang     if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) {
5086eeffb40dSHong Zhang       *flg = PETSC_FALSE;
50873a40ed3dSBarry Smith       PetscFunctionReturn(0);
5088eeffb40dSHong Zhang     }
5089eeffb40dSHong Zhang   }
5090eeffb40dSHong Zhang #else
50919566063dSJacob Faibussowitsch   PetscCall(PetscArraycmp(aa,ba,a->nz,flg));
5092eeffb40dSHong Zhang #endif
50939566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A,&aa));
50949566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(B,&ba));
5095eeffb40dSHong Zhang   PetscFunctionReturn(0);
50967264ac53SSatish Balay }
509736db0b34SBarry Smith 
509805869f15SSatish Balay /*@
509936db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
510036db0b34SBarry Smith               provided by the user.
510136db0b34SBarry Smith 
5102d083f849SBarry Smith       Collective
510336db0b34SBarry Smith 
510436db0b34SBarry Smith    Input Parameters:
510536db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
510636db0b34SBarry Smith .   m - number of rows
510736db0b34SBarry Smith .   n - number of columns
5108483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
510936db0b34SBarry Smith .   j - column indices
511036db0b34SBarry Smith -   a - matrix values
511136db0b34SBarry Smith 
511236db0b34SBarry Smith    Output Parameter:
511336db0b34SBarry Smith .   mat - the matrix
511436db0b34SBarry Smith 
511536db0b34SBarry Smith    Level: intermediate
511636db0b34SBarry Smith 
511736db0b34SBarry Smith    Notes:
51180551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
5119292fb18eSBarry Smith     once the matrix is destroyed and not before
512036db0b34SBarry Smith 
512136db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
512236db0b34SBarry Smith 
5123bfeeae90SHong Zhang        The i and j indices are 0 based
512436db0b34SBarry Smith 
5125a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
5126a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
51278eef79e4SBarry Smith     as shown
5128a4552177SSatish Balay 
51298eef79e4SBarry Smith $        1 0 0
51308eef79e4SBarry Smith $        2 0 3
51318eef79e4SBarry Smith $        4 5 6
51328eef79e4SBarry Smith $
51338eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
51348eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
51358eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
5136a4552177SSatish Balay 
5137db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateMPIAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()`
513836db0b34SBarry Smith 
513936db0b34SBarry Smith @*/
5140c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
514136db0b34SBarry Smith {
5142cbcfb4deSHong Zhang   PetscInt       ii;
514336db0b34SBarry Smith   Mat_SeqAIJ     *aij;
5144cbcfb4deSHong Zhang   PetscInt jj;
514536db0b34SBarry Smith 
514636db0b34SBarry Smith   PetscFunctionBegin;
5147aed4548fSBarry Smith   PetscCheck(m <= 0 || i[0] == 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
51489566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,mat));
51499566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mat,m,n,m,n));
51509566063dSJacob Faibussowitsch   /* PetscCall(MatSetBlockSizes(*mat,,)); */
51519566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mat,MATSEQAIJ));
51529566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL));
5153ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
51549566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m,&aij->imax));
51559566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m,&aij->ilen));
5156ab93d7beSBarry Smith 
515736db0b34SBarry Smith   aij->i            = i;
515836db0b34SBarry Smith   aij->j            = j;
515936db0b34SBarry Smith   aij->a            = a;
516036db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
516136db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
5162e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
5163e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
516436db0b34SBarry Smith 
5165cbc6b225SStefano Zampini   for (ii=0,aij->nonzerorowcnt=0,aij->rmax=0; ii<m; ii++) {
516636db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
516776bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
5168aed4548fSBarry 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]);
51699985e31cSBarry Smith       for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
517008401ef6SPierre 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);
517108401ef6SPierre 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);
51729985e31cSBarry Smith       }
517336db0b34SBarry Smith     }
517476bd3646SJed Brown   }
517576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
517636db0b34SBarry Smith     for (ii=0; ii<aij->i[m]; ii++) {
517708401ef6SPierre 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]);
5178aed4548fSBarry Smith       PetscCheck(j[ii] <= n - 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %" PetscInt_FMT " index = %" PetscInt_FMT,ii,j[ii]);
517936db0b34SBarry Smith     }
518076bd3646SJed Brown   }
518136db0b34SBarry Smith 
51829566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY));
51839566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY));
518436db0b34SBarry Smith   PetscFunctionReturn(0);
518536db0b34SBarry Smith }
5186cbc6b225SStefano Zampini 
5187f62e3866SBarry Smith /*@
5188d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
51898a0b0e6bSVictor Minden               provided by the user.
51908a0b0e6bSVictor Minden 
5191d083f849SBarry Smith       Collective
51928a0b0e6bSVictor Minden 
51938a0b0e6bSVictor Minden    Input Parameters:
51948a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
51958a0b0e6bSVictor Minden .   m   - number of rows
51968a0b0e6bSVictor Minden .   n   - number of columns
51978a0b0e6bSVictor Minden .   i   - row indices
51988a0b0e6bSVictor Minden .   j   - column indices
51991230e6d1SVictor Minden .   a   - matrix values
52001230e6d1SVictor Minden .   nz  - number of nonzeros
5201f62e3866SBarry Smith -   idx - if the i and j indices start with 1 use PETSC_TRUE otherwise use PETSC_FALSE
52028a0b0e6bSVictor Minden 
52038a0b0e6bSVictor Minden    Output Parameter:
52048a0b0e6bSVictor Minden .   mat - the matrix
52058a0b0e6bSVictor Minden 
52068a0b0e6bSVictor Minden    Level: intermediate
52078a0b0e6bSVictor Minden 
5208f62e3866SBarry Smith    Example:
5209f62e3866SBarry Smith        For the following matrix, the input data expected is as shown (using 0 based indexing)
52109e99939fSJunchao Zhang .vb
52118a0b0e6bSVictor Minden         1 0 0
52128a0b0e6bSVictor Minden         2 0 3
52138a0b0e6bSVictor Minden         4 5 6
52148a0b0e6bSVictor Minden 
52158a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
52168a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
52178a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
52189e99939fSJunchao Zhang .ve
52198a0b0e6bSVictor Minden 
5220db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateSeqAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()`, `MatSetValuesCOO()`
52218a0b0e6bSVictor Minden 
52228a0b0e6bSVictor Minden @*/
5223c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
52248a0b0e6bSVictor Minden {
5225d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
52268a0b0e6bSVictor Minden 
52278a0b0e6bSVictor Minden   PetscFunctionBegin;
52289566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(m,&nnz));
52291230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
5230c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
52311230e6d1SVictor Minden   }
52329566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,mat));
52339566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mat,m,n,m,n));
52349566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mat,MATSEQAIJ));
52359566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz));
52361230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
52371230e6d1SVictor Minden     if (idx) {
52381230e6d1SVictor Minden       row = i[ii] - 1;
52391230e6d1SVictor Minden       col = j[ii] - 1;
52401230e6d1SVictor Minden     } else {
52411230e6d1SVictor Minden       row = i[ii];
52421230e6d1SVictor Minden       col = j[ii];
52438a0b0e6bSVictor Minden     }
52449566063dSJacob Faibussowitsch     PetscCall(MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES));
52458a0b0e6bSVictor Minden   }
52469566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY));
52479566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY));
52489566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
52498a0b0e6bSVictor Minden   PetscFunctionReturn(0);
52508a0b0e6bSVictor Minden }
525136db0b34SBarry Smith 
5252acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
5253acf2f550SJed Brown {
5254acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
5255acf2f550SJed Brown 
5256acf2f550SJed Brown   PetscFunctionBegin;
5257acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
5258acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
52592205254eSKarl Rupp 
52609566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJInvalidateDiagonal_Inode(A));
5261acf2f550SJed Brown   PetscFunctionReturn(0);
5262acf2f550SJed Brown }
5263acf2f550SJed Brown 
52649c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
52659c8f2541SHong Zhang {
52668761c3d6SHong Zhang   PetscMPIInt    size;
52679c8f2541SHong Zhang 
52689c8f2541SHong Zhang   PetscFunctionBegin;
52699566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm,&size));
52707bbdc51dSHong Zhang   if (size == 1) {
52717bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
52729566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(inmat,MAT_COPY_VALUES,outmat));
52737bbdc51dSHong Zhang     } else {
52749566063dSJacob Faibussowitsch       PetscCall(MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN));
52757bbdc51dSHong Zhang     }
52768761c3d6SHong Zhang   } else {
52779566063dSJacob Faibussowitsch     PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat));
52788761c3d6SHong Zhang   }
52799c8f2541SHong Zhang   PetscFunctionReturn(0);
52809c8f2541SHong Zhang }
52819c8f2541SHong Zhang 
528281824310SBarry Smith /*
528353dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
528453dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
528553dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
528653dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
528753dd7562SDmitry Karpeev  */
528853dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
528953dd7562SDmitry Karpeev {
529053dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
529153dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
529253dd7562SDmitry Karpeev   PetscBool      seqaij;
529353dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
529453dd7562SDmitry Karpeev   PetscScalar    v;
529553dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
529653dd7562SDmitry Karpeev 
529753dd7562SDmitry Karpeev   PetscFunctionBegin;
529853dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
529953dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
53009566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij));
530128b400f6SJacob Faibussowitsch   PetscCheck(seqaij,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
530253dd7562SDmitry Karpeev   if (rowemb) {
53039566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(rowemb,&m));
530408401ef6SPierre 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);
530553dd7562SDmitry Karpeev   } else {
530608401ef6SPierre Jolivet     PetscCheck(C->rmap->n == B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
530753dd7562SDmitry Karpeev   }
530853dd7562SDmitry Karpeev   if (colemb) {
53099566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(colemb,&n));
531008401ef6SPierre 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);
531153dd7562SDmitry Karpeev   } else {
531208401ef6SPierre Jolivet     PetscCheck(C->cmap->n == B->cmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
531353dd7562SDmitry Karpeev   }
531453dd7562SDmitry Karpeev 
531553dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
531653dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
53179566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(B->rmap->n,&nz));
531853dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
531953dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
532053dd7562SDmitry Karpeev     }
53219566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(C,0,nz));
53229566063dSJacob Faibussowitsch     PetscCall(PetscFree(nz));
532353dd7562SDmitry Karpeev   }
532453dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
53259566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(C));
532653dd7562SDmitry Karpeev   }
532753dd7562SDmitry Karpeev   count = 0;
532853dd7562SDmitry Karpeev   rowindices = NULL;
532953dd7562SDmitry Karpeev   colindices = NULL;
533053dd7562SDmitry Karpeev   if (rowemb) {
53319566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(rowemb,&rowindices));
533253dd7562SDmitry Karpeev   }
533353dd7562SDmitry Karpeev   if (colemb) {
53349566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(colemb,&colindices));
533553dd7562SDmitry Karpeev   }
533653dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
533753dd7562SDmitry Karpeev     PetscInt row;
533853dd7562SDmitry Karpeev     row = i;
533953dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
534053dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
534153dd7562SDmitry Karpeev       PetscInt col;
534253dd7562SDmitry Karpeev       col  = Baij->j[count];
534353dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
534453dd7562SDmitry Karpeev       v    = Baij->a[count];
53459566063dSJacob Faibussowitsch       PetscCall(MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES));
534653dd7562SDmitry Karpeev       ++count;
534753dd7562SDmitry Karpeev     }
534853dd7562SDmitry Karpeev   }
534953dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
535053dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
535153dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
535253dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
535353dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
535453dd7562SDmitry Karpeev   PetscFunctionReturn(0);
535553dd7562SDmitry Karpeev }
535653dd7562SDmitry Karpeev 
53574099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
53584099cc6bSBarry Smith 
53594099cc6bSBarry Smith /*@C
53604099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
53614099cc6bSBarry Smith 
53624099cc6bSBarry Smith    Collective on Mat
53634099cc6bSBarry Smith 
53644099cc6bSBarry Smith    Input Parameters:
53654099cc6bSBarry Smith +  mat      - the matrix object
53664099cc6bSBarry Smith -  matype   - matrix type
53674099cc6bSBarry Smith 
53684099cc6bSBarry Smith    Options Database Key:
53694099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
53704099cc6bSBarry Smith 
53714099cc6bSBarry Smith   Level: intermediate
53724099cc6bSBarry Smith 
5373db781477SPatrick Sanan .seealso: `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat`
53744099cc6bSBarry Smith @*/
53754099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
53764099cc6bSBarry Smith {
53774099cc6bSBarry Smith   PetscBool      sametype;
53785f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(Mat,MatType,MatReuse,Mat*);
53794099cc6bSBarry Smith 
53804099cc6bSBarry Smith   PetscFunctionBegin;
53814099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
53829566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)mat,matype,&sametype));
53834099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
53844099cc6bSBarry Smith 
53859566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(MatSeqAIJList,matype,&r));
53865f80ce2aSJacob Faibussowitsch   PetscCheck(r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
53879566063dSJacob Faibussowitsch   PetscCall((*r)(mat,matype,MAT_INPLACE_MATRIX,&mat));
53884099cc6bSBarry Smith   PetscFunctionReturn(0);
53894099cc6bSBarry Smith }
53904099cc6bSBarry Smith 
53914099cc6bSBarry Smith /*@C
53924099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
53934099cc6bSBarry Smith 
53944099cc6bSBarry Smith    Not Collective
53954099cc6bSBarry Smith 
53964099cc6bSBarry Smith    Input Parameters:
53974099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
53984099cc6bSBarry Smith -  function - routine to convert to subtype
53994099cc6bSBarry Smith 
54004099cc6bSBarry Smith    Notes:
54014099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
54024099cc6bSBarry Smith 
54034099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
54044099cc6bSBarry Smith $     -mat_seqaij_type my_mat
54054099cc6bSBarry Smith 
54064099cc6bSBarry Smith    Level: advanced
54074099cc6bSBarry Smith 
5408db781477SPatrick Sanan .seealso: `MatSeqAIJRegisterAll()`
54094099cc6bSBarry Smith 
54104099cc6bSBarry Smith   Level: advanced
54114099cc6bSBarry Smith @*/
5412388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
54134099cc6bSBarry Smith {
54144099cc6bSBarry Smith   PetscFunctionBegin;
54159566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
54169566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&MatSeqAIJList,sname,function));
54174099cc6bSBarry Smith   PetscFunctionReturn(0);
54184099cc6bSBarry Smith }
54194099cc6bSBarry Smith 
54204099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
54214099cc6bSBarry Smith 
54224099cc6bSBarry Smith /*@C
54234099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
54244099cc6bSBarry Smith 
54254099cc6bSBarry Smith   Not Collective
54264099cc6bSBarry Smith 
54274099cc6bSBarry Smith   Level: advanced
54284099cc6bSBarry Smith 
5429db781477SPatrick Sanan .seealso: `MatRegisterAll()`, `MatSeqAIJRegister()`
54304099cc6bSBarry Smith @*/
54314099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
54324099cc6bSBarry Smith {
54334099cc6bSBarry Smith   PetscFunctionBegin;
54344099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
54354099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
54364099cc6bSBarry Smith 
54379566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL));
54389566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM));
54399566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL));
54409779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
54419566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL));
5442485f9817SRichard Tran Mills #endif
54435063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA)
54449566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE));
54455063d097SStefano Zampini #endif
54465063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
54479566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATSEQAIJKOKKOS,   MatConvert_SeqAIJ_SeqAIJKokkos));
54485063d097SStefano Zampini #endif
54494099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
54509566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL));
54514099cc6bSBarry Smith #endif
54524099cc6bSBarry Smith   PetscFunctionReturn(0);
54534099cc6bSBarry Smith }
545453dd7562SDmitry Karpeev 
545553dd7562SDmitry Karpeev /*
545681824310SBarry Smith     Special version for direct calls from Fortran
545781824310SBarry Smith */
5458af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
545981824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
546081824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
546181824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
546281824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
546381824310SBarry Smith #endif
546481824310SBarry Smith 
546581824310SBarry Smith /* Change these macros so can be used in void function */
546698921bdaSJacob Faibussowitsch 
546798921bdaSJacob Faibussowitsch /* Change these macros so can be used in void function */
54689566063dSJacob Faibussowitsch /* Identical to PetscCallVoid, except it assigns to *_ierr */
54699566063dSJacob Faibussowitsch #undef  PetscCall
54709566063dSJacob Faibussowitsch #define PetscCall(...) do {                                                                    \
54715f80ce2aSJacob Faibussowitsch     PetscErrorCode ierr_msv_mpiaij = __VA_ARGS__;                                              \
547298921bdaSJacob Faibussowitsch     if (PetscUnlikely(ierr_msv_mpiaij)) {                                                      \
547398921bdaSJacob Faibussowitsch       *_ierr = PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,ierr_msv_mpiaij,PETSC_ERROR_REPEAT," "); \
547498921bdaSJacob Faibussowitsch       return;                                                                                  \
547598921bdaSJacob Faibussowitsch     }                                                                                          \
547698921bdaSJacob Faibussowitsch   } while (0)
547798921bdaSJacob Faibussowitsch 
547898921bdaSJacob Faibussowitsch #undef SETERRQ
547998921bdaSJacob Faibussowitsch #define SETERRQ(comm,ierr,...) do {                                                            \
548098921bdaSJacob Faibussowitsch     *_ierr = PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,ierr,PETSC_ERROR_INITIAL,__VA_ARGS__); \
548198921bdaSJacob Faibussowitsch     return;                                                                                    \
548298921bdaSJacob Faibussowitsch   } while (0)
548381824310SBarry Smith 
548419caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
548581824310SBarry Smith {
548681824310SBarry Smith   Mat            A  = *AA;
548781824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
548881824310SBarry Smith   InsertMode     is = *isis;
548981824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
549081824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
549181824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
549281824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
549354f21887SBarry Smith   MatScalar      *ap,value,*aa;
5494ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5495ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
549681824310SBarry Smith 
549781824310SBarry Smith   PetscFunctionBegin;
54984994cf47SJed Brown   MatCheckPreallocated(A,1);
549981824310SBarry Smith   imax  = a->imax;
550081824310SBarry Smith   ai    = a->i;
550181824310SBarry Smith   ailen = a->ilen;
550281824310SBarry Smith   aj    = a->j;
550381824310SBarry Smith   aa    = a->a;
550481824310SBarry Smith 
550581824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
550681824310SBarry Smith     row = im[k];
550781824310SBarry Smith     if (row < 0) continue;
55085f80ce2aSJacob Faibussowitsch     PetscCheck(row < A->rmap->n,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
550981824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
551081824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
551181824310SBarry Smith     low  = 0;
551281824310SBarry Smith     high = nrow;
551381824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
551481824310SBarry Smith       if (in[l] < 0) continue;
55155f80ce2aSJacob Faibussowitsch       PetscCheck(in[l] < A->cmap->n,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
551681824310SBarry Smith       col = in[l];
55172205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
55182205254eSKarl Rupp       else value = v[k + l*m];
55192205254eSKarl Rupp 
552081824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
552181824310SBarry Smith 
55222205254eSKarl Rupp       if (col <= lastcol) low = 0;
55232205254eSKarl Rupp       else high = nrow;
552481824310SBarry Smith       lastcol = col;
552581824310SBarry Smith       while (high-low > 5) {
552681824310SBarry Smith         t = (low+high)/2;
552781824310SBarry Smith         if (rp[t] > col) high = t;
552881824310SBarry Smith         else             low  = t;
552981824310SBarry Smith       }
553081824310SBarry Smith       for (i=low; i<high; i++) {
553181824310SBarry Smith         if (rp[i] > col) break;
553281824310SBarry Smith         if (rp[i] == col) {
553381824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
553481824310SBarry Smith           else                  ap[i] = value;
553581824310SBarry Smith           goto noinsert;
553681824310SBarry Smith         }
553781824310SBarry Smith       }
553881824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
553981824310SBarry Smith       if (nonew == 1) goto noinsert;
55405f80ce2aSJacob Faibussowitsch       PetscCheck(nonew != -1,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5541fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
554281824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
554381824310SBarry Smith       /* shift up all the later entries in this row */
554481824310SBarry Smith       for (ii=N; ii>=i; ii--) {
554581824310SBarry Smith         rp[ii+1] = rp[ii];
554681824310SBarry Smith         ap[ii+1] = ap[ii];
554781824310SBarry Smith       }
554881824310SBarry Smith       rp[i] = col;
554981824310SBarry Smith       ap[i] = value;
5550e56f5c9eSBarry Smith       A->nonzerostate++;
555181824310SBarry Smith noinsert:;
555281824310SBarry Smith       low = i + 1;
555381824310SBarry Smith     }
555481824310SBarry Smith     ailen[row] = nrow;
555581824310SBarry Smith   }
555681824310SBarry Smith   PetscFunctionReturnVoid();
555781824310SBarry Smith }
555898921bdaSJacob Faibussowitsch /* Undefining these here since they were redefined from their original definition above! No
555998921bdaSJacob Faibussowitsch  * other PETSc functions should be defined past this point, as it is impossible to recover the
556098921bdaSJacob Faibussowitsch  * original definitions */
55619566063dSJacob Faibussowitsch #undef PetscCall
556298921bdaSJacob Faibussowitsch #undef SETERRQ
5563