xref: /petsc/src/mat/impls/aij/seq/aij.c (revision d67d9f35029c46d2b17dfe35a469d0777d0ecdc9)
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   PetscErrorCode       ierr;
144099cc6bSBarry Smith   PetscBool            flg;
154099cc6bSBarry Smith   char                 type[256];
164099cc6bSBarry Smith 
174099cc6bSBarry Smith   PetscFunctionBegin;
181e1ea65dSPierre Jolivet   ierr = PetscObjectOptionsBegin((PetscObject)A);CHKERRQ(ierr);
194099cc6bSBarry Smith   ierr = PetscOptionsFList("-mat_seqaij_type","Matrix SeqAIJ type","MatSeqAIJSetType",MatSeqAIJList,"seqaij",type,256,&flg);CHKERRQ(ierr);
204099cc6bSBarry Smith   if (flg) {
214099cc6bSBarry Smith     ierr = MatSeqAIJSetType(A,type);CHKERRQ(ierr);
224099cc6bSBarry Smith   }
234099cc6bSBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
244099cc6bSBarry Smith   PetscFunctionReturn(0);
254099cc6bSBarry Smith }
264099cc6bSBarry Smith 
27857cbf51SRichard Tran Mills PetscErrorCode MatGetColumnReductions_SeqAIJ(Mat A,PetscInt type,PetscReal *reductions)
280716a85fSBarry Smith {
290716a85fSBarry Smith   PetscErrorCode ierr;
300716a85fSBarry Smith   PetscInt       i,m,n;
310716a85fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
320716a85fSBarry Smith 
330716a85fSBarry Smith   PetscFunctionBegin;
340716a85fSBarry Smith   ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr);
35a873a8cdSSam Reynolds   ierr = PetscArrayzero(reductions,n);CHKERRQ(ierr);
360716a85fSBarry Smith   if (type == NORM_2) {
370716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
38a873a8cdSSam Reynolds       reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]);
390716a85fSBarry Smith     }
400716a85fSBarry Smith   } else if (type == NORM_1) {
410716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
42a873a8cdSSam Reynolds       reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]);
430716a85fSBarry Smith     }
440716a85fSBarry Smith   } else if (type == NORM_INFINITY) {
450716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
46a873a8cdSSam Reynolds       reductions[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),reductions[aij->j[i]]);
470716a85fSBarry Smith     }
48857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
49a873a8cdSSam Reynolds     for (i=0; i<aij->i[m]; i++) {
50857cbf51SRichard Tran Mills       reductions[aij->j[i]] += PetscRealPart(aij->a[i]);
51a873a8cdSSam Reynolds     }
52857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
53857cbf51SRichard Tran Mills     for (i=0; i<aij->i[m]; i++) {
54857cbf51SRichard Tran Mills       reductions[aij->j[i]] += PetscImaginaryPart(aij->a[i]);
55857cbf51SRichard Tran Mills     }
56857cbf51SRichard Tran Mills   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown reduction type");
570716a85fSBarry Smith 
580716a85fSBarry Smith   if (type == NORM_2) {
59a873a8cdSSam Reynolds     for (i=0; i<n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
60857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
61a873a8cdSSam Reynolds     for (i=0; i<n; i++) reductions[i] /= m;
620716a85fSBarry Smith   }
630716a85fSBarry Smith   PetscFunctionReturn(0);
640716a85fSBarry Smith }
650716a85fSBarry Smith 
663a062f41SBarry Smith PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A,IS *is)
673a062f41SBarry Smith {
683a062f41SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
693a062f41SBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0, bs = A->rmap->bs;
703a062f41SBarry Smith   const PetscInt  *jj = a->j,*ii = a->i;
713a062f41SBarry Smith   PetscInt        *rows;
723a062f41SBarry Smith   PetscErrorCode  ierr;
733a062f41SBarry Smith 
743a062f41SBarry Smith   PetscFunctionBegin;
753a062f41SBarry Smith   for (i=0; i<m; i++) {
763a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
773a062f41SBarry Smith       cnt++;
783a062f41SBarry Smith     }
793a062f41SBarry Smith   }
803a062f41SBarry Smith   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
813a062f41SBarry Smith   cnt  = 0;
823a062f41SBarry Smith   for (i=0; i<m; i++) {
833a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
843a062f41SBarry Smith       rows[cnt] = i;
853a062f41SBarry Smith       cnt++;
863a062f41SBarry Smith     }
873a062f41SBarry Smith   }
883a062f41SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,is);CHKERRQ(ierr);
893a062f41SBarry Smith   PetscFunctionReturn(0);
903a062f41SBarry Smith }
913a062f41SBarry Smith 
92f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A,PetscInt *nrows,PetscInt **zrows)
936ce1633cSBarry Smith {
946ce1633cSBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
956ce1633cSBarry Smith   const MatScalar *aa = a->a;
966ce1633cSBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0;
97b2db7409Sstefano_zampini   const PetscInt  *ii = a->i,*jj = a->j,*diag;
986ce1633cSBarry Smith   PetscInt        *rows;
996ce1633cSBarry Smith   PetscErrorCode  ierr;
1006ce1633cSBarry Smith 
1016ce1633cSBarry Smith   PetscFunctionBegin;
1026ce1633cSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1036ce1633cSBarry Smith   diag = a->diag;
1046ce1633cSBarry Smith   for (i=0; i<m; i++) {
105b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1066ce1633cSBarry Smith       cnt++;
1076ce1633cSBarry Smith     }
1086ce1633cSBarry Smith   }
109785e854fSJed Brown   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
1106ce1633cSBarry Smith   cnt  = 0;
1116ce1633cSBarry Smith   for (i=0; i<m; i++) {
112b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1136ce1633cSBarry Smith       rows[cnt++] = i;
1146ce1633cSBarry Smith     }
1156ce1633cSBarry Smith   }
116f1f41ecbSJed Brown   *nrows = cnt;
117f1f41ecbSJed Brown   *zrows = rows;
118f1f41ecbSJed Brown   PetscFunctionReturn(0);
119f1f41ecbSJed Brown }
120f1f41ecbSJed Brown 
121f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
122f1f41ecbSJed Brown {
123f1f41ecbSJed Brown   PetscInt       nrows,*rows;
124f1f41ecbSJed Brown   PetscErrorCode ierr;
125f1f41ecbSJed Brown 
126f1f41ecbSJed Brown   PetscFunctionBegin;
1270298fd71SBarry Smith   *zrows = NULL;
128f1f41ecbSJed Brown   ierr   = MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows);CHKERRQ(ierr);
129ce94432eSBarry Smith   ierr   = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr);
1306ce1633cSBarry Smith   PetscFunctionReturn(0);
1316ce1633cSBarry Smith }
1326ce1633cSBarry Smith 
133b3a44c85SBarry Smith PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows)
134b3a44c85SBarry Smith {
135b3a44c85SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
136b3a44c85SBarry Smith   const MatScalar *aa;
137b3a44c85SBarry Smith   PetscInt        m=A->rmap->n,cnt = 0;
138b3a44c85SBarry Smith   const PetscInt  *ii;
139b3a44c85SBarry Smith   PetscInt        n,i,j,*rows;
140b3a44c85SBarry Smith   PetscErrorCode  ierr;
141b3a44c85SBarry Smith 
142b3a44c85SBarry Smith   PetscFunctionBegin;
1432e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
144f4259b30SLisandro Dalcin   *keptrows = NULL;
145b3a44c85SBarry Smith   ii        = a->i;
146b3a44c85SBarry Smith   for (i=0; i<m; i++) {
147b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
148b3a44c85SBarry Smith     if (!n) {
149b3a44c85SBarry Smith       cnt++;
150b3a44c85SBarry Smith       goto ok1;
151b3a44c85SBarry Smith     }
1522e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
153b3a44c85SBarry Smith       if (aa[j] != 0.0) goto ok1;
154b3a44c85SBarry Smith     }
155b3a44c85SBarry Smith     cnt++;
156b3a44c85SBarry Smith ok1:;
157b3a44c85SBarry Smith   }
1582e5835c6SStefano Zampini   if (!cnt) {
1592e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
1602e5835c6SStefano Zampini     PetscFunctionReturn(0);
1612e5835c6SStefano Zampini   }
162854ce69bSBarry Smith   ierr = PetscMalloc1(A->rmap->n-cnt,&rows);CHKERRQ(ierr);
163b3a44c85SBarry Smith   cnt  = 0;
164b3a44c85SBarry Smith   for (i=0; i<m; i++) {
165b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
166b3a44c85SBarry Smith     if (!n) continue;
1672e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
168b3a44c85SBarry Smith       if (aa[j] != 0.0) {
169b3a44c85SBarry Smith         rows[cnt++] = i;
170b3a44c85SBarry Smith         break;
171b3a44c85SBarry Smith       }
172b3a44c85SBarry Smith     }
173b3a44c85SBarry Smith   }
1742e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
175b3a44c85SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr);
176b3a44c85SBarry Smith   PetscFunctionReturn(0);
177b3a44c85SBarry Smith }
178b3a44c85SBarry Smith 
1797087cfbeSBarry Smith PetscErrorCode  MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
18079299369SBarry Smith {
18179299369SBarry Smith   PetscErrorCode    ierr;
18279299369SBarry Smith   Mat_SeqAIJ        *aij = (Mat_SeqAIJ*) Y->data;
18399e65526SBarry Smith   PetscInt          i,m = Y->rmap->n;
18499e65526SBarry Smith   const PetscInt    *diag;
1852e5835c6SStefano Zampini   MatScalar         *aa;
18699e65526SBarry Smith   const PetscScalar *v;
187ace3abfcSBarry Smith   PetscBool         missing;
1888c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
189837a59e1SRichard Tran Mills   PetscBool         inserted = PETSC_FALSE;
190837a59e1SRichard Tran Mills #endif
19179299369SBarry Smith 
19279299369SBarry Smith   PetscFunctionBegin;
19309f38230SBarry Smith   if (Y->assembled) {
1940298fd71SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,NULL);CHKERRQ(ierr);
19509f38230SBarry Smith     if (!missing) {
19679299369SBarry Smith       diag = aij->diag;
19799e65526SBarry Smith       ierr = VecGetArrayRead(D,&v);CHKERRQ(ierr);
1982e5835c6SStefano Zampini       ierr = MatSeqAIJGetArray(Y,&aa);CHKERRQ(ierr);
19979299369SBarry Smith       if (is == INSERT_VALUES) {
2008c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
201837a59e1SRichard Tran Mills         inserted = PETSC_TRUE;
202837a59e1SRichard Tran Mills #endif
20379299369SBarry Smith         for (i=0; i<m; i++) {
20479299369SBarry Smith           aa[diag[i]] = v[i];
20579299369SBarry Smith         }
20679299369SBarry Smith       } else {
20779299369SBarry Smith         for (i=0; i<m; i++) {
2088c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
209837a59e1SRichard Tran Mills           if (v[i] != 0.0) inserted = PETSC_TRUE;
210837a59e1SRichard Tran Mills #endif
21179299369SBarry Smith           aa[diag[i]] += v[i];
21279299369SBarry Smith         }
21379299369SBarry Smith       }
2142e5835c6SStefano Zampini       ierr = MatSeqAIJRestoreArray(Y,&aa);CHKERRQ(ierr);
2158c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
216837a59e1SRichard Tran Mills       if (inserted) Y->offloadmask = PETSC_OFFLOAD_CPU;
217837a59e1SRichard Tran Mills #endif
21899e65526SBarry Smith       ierr = VecRestoreArrayRead(D,&v);CHKERRQ(ierr);
21979299369SBarry Smith       PetscFunctionReturn(0);
22079299369SBarry Smith     }
221acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
22209f38230SBarry Smith   }
22309f38230SBarry Smith   ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
22409f38230SBarry Smith   PetscFunctionReturn(0);
22509f38230SBarry Smith }
22679299369SBarry Smith 
2271a83f524SJed Brown PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
22817ab2063SBarry Smith {
229416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
230dfbe8321SBarry Smith   PetscErrorCode ierr;
23197f1f81fSBarry Smith   PetscInt       i,ishift;
23217ab2063SBarry Smith 
2333a40ed3dSBarry Smith   PetscFunctionBegin;
234d0f46423SBarry Smith   *m = A->rmap->n;
2353a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
236bfeeae90SHong Zhang   ishift = 0;
23753e63a63SBarry Smith   if (symmetric && !A->structurally_symmetric) {
2382462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
239bfeeae90SHong Zhang   } else if (oshift == 1) {
2401a83f524SJed Brown     PetscInt *tia;
241d0f46423SBarry Smith     PetscInt nz = a->i[A->rmap->n];
2423b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
243854ce69bSBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&tia);CHKERRQ(ierr);
2441a83f524SJed Brown     for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1;
2451a83f524SJed Brown     *ia = tia;
246ecc77c7aSBarry Smith     if (ja) {
2471a83f524SJed Brown       PetscInt *tja;
248854ce69bSBarry Smith       ierr = PetscMalloc1(nz+1,&tja);CHKERRQ(ierr);
2491a83f524SJed Brown       for (i=0; i<nz; i++) tja[i] = a->j[i] + 1;
2501a83f524SJed Brown       *ja = tja;
251ecc77c7aSBarry Smith     }
2526945ee14SBarry Smith   } else {
253ecc77c7aSBarry Smith     *ia = a->i;
254ecc77c7aSBarry Smith     if (ja) *ja = a->j;
255a2ce50c7SBarry Smith   }
2563a40ed3dSBarry Smith   PetscFunctionReturn(0);
257a2744918SBarry Smith }
258a2744918SBarry Smith 
2591a83f524SJed Brown PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2606945ee14SBarry Smith {
261dfbe8321SBarry Smith   PetscErrorCode ierr;
2626945ee14SBarry Smith 
2633a40ed3dSBarry Smith   PetscFunctionBegin;
2643a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
265bfeeae90SHong Zhang   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
266606d414cSSatish Balay     ierr = PetscFree(*ia);CHKERRQ(ierr);
267ecc77c7aSBarry Smith     if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);}
268bcd2baecSBarry Smith   }
2693a40ed3dSBarry Smith   PetscFunctionReturn(0);
27017ab2063SBarry Smith }
27117ab2063SBarry Smith 
2721a83f524SJed Brown PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2733b2fbd54SBarry Smith {
2743b2fbd54SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
275dfbe8321SBarry Smith   PetscErrorCode ierr;
276d0f46423SBarry Smith   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
27797f1f81fSBarry Smith   PetscInt       nz = a->i[m],row,*jj,mr,col;
2783b2fbd54SBarry Smith 
2793a40ed3dSBarry Smith   PetscFunctionBegin;
280899cda47SBarry Smith   *nn = n;
2813a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2823b2fbd54SBarry Smith   if (symmetric) {
2832462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
2843b2fbd54SBarry Smith   } else {
285b9e7e5c1SBarry Smith     ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
286854ce69bSBarry Smith     ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
287b9e7e5c1SBarry Smith     ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
2883b2fbd54SBarry Smith     jj   = a->j;
2893b2fbd54SBarry Smith     for (i=0; i<nz; i++) {
290bfeeae90SHong Zhang       collengths[jj[i]]++;
2913b2fbd54SBarry Smith     }
2923b2fbd54SBarry Smith     cia[0] = oshift;
2933b2fbd54SBarry Smith     for (i=0; i<n; i++) {
2943b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
2953b2fbd54SBarry Smith     }
296580bdb30SBarry Smith     ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
2973b2fbd54SBarry Smith     jj   = a->j;
298a93ec695SBarry Smith     for (row=0; row<m; row++) {
299a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
300a93ec695SBarry Smith       for (i=0; i<mr; i++) {
301bfeeae90SHong Zhang         col = *jj++;
3022205254eSKarl Rupp 
3033b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
3043b2fbd54SBarry Smith       }
3053b2fbd54SBarry Smith     }
306606d414cSSatish Balay     ierr = PetscFree(collengths);CHKERRQ(ierr);
3073b2fbd54SBarry Smith     *ia  = cia; *ja = cja;
3083b2fbd54SBarry Smith   }
3093a40ed3dSBarry Smith   PetscFunctionReturn(0);
3103b2fbd54SBarry Smith }
3113b2fbd54SBarry Smith 
3121a83f524SJed Brown PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
3133b2fbd54SBarry Smith {
314dfbe8321SBarry Smith   PetscErrorCode ierr;
315606d414cSSatish Balay 
3163a40ed3dSBarry Smith   PetscFunctionBegin;
3173a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
3183b2fbd54SBarry Smith 
319606d414cSSatish Balay   ierr = PetscFree(*ia);CHKERRQ(ierr);
320606d414cSSatish Balay   ierr = PetscFree(*ja);CHKERRQ(ierr);
3213a40ed3dSBarry Smith   PetscFunctionReturn(0);
3223b2fbd54SBarry Smith }
3233b2fbd54SBarry Smith 
3247cee066cSHong Zhang /*
3257cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
3267cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
327040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
3287cee066cSHong Zhang */
3297cee066cSHong 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)
3307cee066cSHong Zhang {
3317cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3327cee066cSHong Zhang   PetscErrorCode ierr;
3337cee066cSHong Zhang   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
334071fcb05SBarry Smith   PetscInt       nz = a->i[m],row,mr,col,tmp;
3357cee066cSHong Zhang   PetscInt       *cspidx;
336071fcb05SBarry Smith   const PetscInt *jj;
3377cee066cSHong Zhang 
3387cee066cSHong Zhang   PetscFunctionBegin;
3397cee066cSHong Zhang   *nn = n;
3407cee066cSHong Zhang   if (!ia) PetscFunctionReturn(0);
341625f6d37SHong Zhang 
342b9e7e5c1SBarry Smith   ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
343854ce69bSBarry Smith   ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
344b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
345b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cspidx);CHKERRQ(ierr);
3467cee066cSHong Zhang   jj   = a->j;
3477cee066cSHong Zhang   for (i=0; i<nz; i++) {
3487cee066cSHong Zhang     collengths[jj[i]]++;
3497cee066cSHong Zhang   }
3507cee066cSHong Zhang   cia[0] = oshift;
3517cee066cSHong Zhang   for (i=0; i<n; i++) {
3527cee066cSHong Zhang     cia[i+1] = cia[i] + collengths[i];
3537cee066cSHong Zhang   }
354580bdb30SBarry Smith   ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
3557cee066cSHong Zhang   jj   = a->j;
3567cee066cSHong Zhang   for (row=0; row<m; row++) {
3577cee066cSHong Zhang     mr = a->i[row+1] - a->i[row];
3587cee066cSHong Zhang     for (i=0; i<mr; i++) {
3597cee066cSHong Zhang       col         = *jj++;
360071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
361071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
362071fcb05SBarry Smith       cja[tmp]    = row + oshift;
3637cee066cSHong Zhang     }
3647cee066cSHong Zhang   }
3657cee066cSHong Zhang   ierr   = PetscFree(collengths);CHKERRQ(ierr);
366071fcb05SBarry Smith   *ia    = cia;
367071fcb05SBarry Smith   *ja    = cja;
3687cee066cSHong Zhang   *spidx = cspidx;
3697cee066cSHong Zhang   PetscFunctionReturn(0);
3707cee066cSHong Zhang }
3717cee066cSHong Zhang 
3727cee066cSHong 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)
3737cee066cSHong Zhang {
3747cee066cSHong Zhang   PetscErrorCode ierr;
3757cee066cSHong Zhang 
3767cee066cSHong Zhang   PetscFunctionBegin;
3775243ef75SHong Zhang   ierr = MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
3787cee066cSHong Zhang   ierr = PetscFree(*spidx);CHKERRQ(ierr);
3797cee066cSHong Zhang   PetscFunctionReturn(0);
3807cee066cSHong Zhang }
3817cee066cSHong Zhang 
38287d4246cSBarry Smith PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
38387d4246cSBarry Smith {
38487d4246cSBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
38587d4246cSBarry Smith   PetscInt       *ai = a->i;
38687d4246cSBarry Smith   PetscErrorCode ierr;
38787d4246cSBarry Smith 
38887d4246cSBarry Smith   PetscFunctionBegin;
389580bdb30SBarry Smith   ierr = PetscArraycpy(a->a+ai[row],v,ai[row+1]-ai[row]);CHKERRQ(ierr);
3908c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
391c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && ai[row+1]-ai[row]) A->offloadmask = PETSC_OFFLOAD_CPU;
392e2cf4d64SStefano Zampini #endif
39387d4246cSBarry Smith   PetscFunctionReturn(0);
39487d4246cSBarry Smith }
39587d4246cSBarry Smith 
396bd04181cSBarry Smith /*
397bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
398bd04181cSBarry Smith 
399bd04181cSBarry Smith       -   a single row of values is set with each call
400bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
401bd04181cSBarry Smith       -   the values are always added to the matrix, not set
402bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
403bd04181cSBarry Smith 
4041f763a69SBarry Smith      This does NOT assume the global column indices are sorted
405bd04181cSBarry Smith 
4061f763a69SBarry Smith */
407bd04181cSBarry Smith 
408af0996ceSBarry Smith #include <petsc/private/isimpl.h>
409189e4007SBarry Smith PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
410189e4007SBarry Smith {
411189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
4121f763a69SBarry Smith   PetscInt       low,high,t,row,nrow,i,col,l;
4131f763a69SBarry Smith   const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j;
4141f763a69SBarry Smith   PetscInt       lastcol = -1;
415189e4007SBarry Smith   MatScalar      *ap,value,*aa = a->a;
416189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices;
417189e4007SBarry Smith 
418f38dd0b8SBarry Smith   row  = ridx[im[0]];
4191f763a69SBarry Smith   rp   = aj + ai[row];
4201f763a69SBarry Smith   ap   = aa + ai[row];
4211f763a69SBarry Smith   nrow = ailen[row];
422189e4007SBarry Smith   low  = 0;
423189e4007SBarry Smith   high = nrow;
424189e4007SBarry Smith   for (l=0; l<n; l++) { /* loop over added columns */
425189e4007SBarry Smith     col = cidx[in[l]];
426f38dd0b8SBarry Smith     value = v[l];
427189e4007SBarry Smith 
428189e4007SBarry Smith     if (col <= lastcol) low = 0;
429189e4007SBarry Smith     else high = nrow;
430189e4007SBarry Smith     lastcol = col;
431189e4007SBarry Smith     while (high-low > 5) {
432189e4007SBarry Smith       t = (low+high)/2;
433189e4007SBarry Smith       if (rp[t] > col) high = t;
434189e4007SBarry Smith       else low = t;
435189e4007SBarry Smith     }
436189e4007SBarry Smith     for (i=low; i<high; i++) {
437189e4007SBarry Smith       if (rp[i] == col) {
4381f763a69SBarry Smith         ap[i] += value;
439189e4007SBarry Smith         low = i + 1;
4401f763a69SBarry Smith         break;
441189e4007SBarry Smith       }
442189e4007SBarry Smith     }
443189e4007SBarry Smith   }
4448c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
445c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
446e2cf4d64SStefano Zampini #endif
447f38dd0b8SBarry Smith   return 0;
448189e4007SBarry Smith }
449189e4007SBarry Smith 
45097f1f81fSBarry Smith PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
45117ab2063SBarry Smith {
452416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
453e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
45497f1f81fSBarry Smith   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
4556849ba73SBarry Smith   PetscErrorCode ierr;
456e2ee6c50SBarry Smith   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
457ce496241SStefano Zampini   MatScalar      *ap=NULL,value=0.0,*aa;
458ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
459ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
4608c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
461e2cf4d64SStefano Zampini   PetscBool      inserted          = PETSC_FALSE;
462e2cf4d64SStefano Zampini #endif
46317ab2063SBarry Smith 
4643a40ed3dSBarry Smith   PetscFunctionBegin;
465ce496241SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
466ce496241SStefano Zampini   if (A->offloadmask == PETSC_OFFLOAD_GPU) {
467ce496241SStefano Zampini     const PetscScalar *dummy;
468ce496241SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&dummy);CHKERRQ(ierr);
469ce496241SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&dummy);CHKERRQ(ierr);
470ce496241SStefano Zampini   }
471ce496241SStefano Zampini #endif
472ce496241SStefano Zampini   aa = a->a;
47317ab2063SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
474416022c9SBarry Smith     row = im[k];
4755ef9f2a5SBarry Smith     if (row < 0) continue;
476cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
477720833daSHong Zhang     rp   = aj + ai[row];
478876c6284SHong Zhang     if (!A->structure_only) ap = aa + ai[row];
47917ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
480416022c9SBarry Smith     low  = 0;
481c71e6ed7SBarry Smith     high = nrow;
48217ab2063SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
4835ef9f2a5SBarry Smith       if (in[l] < 0) continue;
484cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
485bfeeae90SHong Zhang       col = in[l];
486071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m];
487071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
48836db0b34SBarry Smith 
4892205254eSKarl Rupp       if (col <= lastcol) low = 0;
4902205254eSKarl Rupp       else high = nrow;
491e2ee6c50SBarry Smith       lastcol = col;
492416022c9SBarry Smith       while (high-low > 5) {
493416022c9SBarry Smith         t = (low+high)/2;
494416022c9SBarry Smith         if (rp[t] > col) high = t;
495416022c9SBarry Smith         else low = t;
49617ab2063SBarry Smith       }
497416022c9SBarry Smith       for (i=low; i<high; i++) {
49817ab2063SBarry Smith         if (rp[i] > col) break;
49917ab2063SBarry Smith         if (rp[i] == col) {
500876c6284SHong Zhang           if (!A->structure_only) {
5010c0d7e18SFande Kong             if (is == ADD_VALUES) {
5020c0d7e18SFande Kong               ap[i] += value;
5030c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
5040c0d7e18SFande Kong             }
50517ab2063SBarry Smith             else ap[i] = value;
5068c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
507e2cf4d64SStefano Zampini             inserted = PETSC_TRUE;
508e2cf4d64SStefano Zampini #endif
509720833daSHong Zhang           }
510e44c0bd4SBarry Smith           low = i + 1;
51117ab2063SBarry Smith           goto noinsert;
51217ab2063SBarry Smith         }
51317ab2063SBarry Smith       }
514dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
515c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
516e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
517720833daSHong Zhang       if (A->structure_only) {
518876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar);
519720833daSHong Zhang       } else {
520fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
521720833daSHong Zhang       }
522c03d1d03SSatish Balay       N = nrow++ - 1; a->nz++; high++;
523416022c9SBarry Smith       /* shift up all the later entries in this row */
524580bdb30SBarry Smith       ierr  = PetscArraymove(rp+i+1,rp+i,N-i+1);CHKERRQ(ierr);
52517ab2063SBarry Smith       rp[i] = col;
526580bdb30SBarry Smith       if (!A->structure_only) {
527580bdb30SBarry Smith         ierr  = PetscArraymove(ap+i+1,ap+i,N-i+1);CHKERRQ(ierr);
528580bdb30SBarry Smith         ap[i] = value;
529580bdb30SBarry Smith       }
530416022c9SBarry Smith       low = i + 1;
531e56f5c9eSBarry Smith       A->nonzerostate++;
5328c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
533e2cf4d64SStefano Zampini       inserted = PETSC_TRUE;
534e2cf4d64SStefano Zampini #endif
535e44c0bd4SBarry Smith noinsert:;
53617ab2063SBarry Smith     }
53717ab2063SBarry Smith     ailen[row] = nrow;
53817ab2063SBarry Smith   }
5398c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
540c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && inserted) A->offloadmask = PETSC_OFFLOAD_CPU;
541e2cf4d64SStefano Zampini #endif
5423a40ed3dSBarry Smith   PetscFunctionReturn(0);
54317ab2063SBarry Smith }
54417ab2063SBarry Smith 
54519b08ed1SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
54619b08ed1SBarry Smith {
54719b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
54819b08ed1SBarry Smith   PetscInt       *rp,k,row;
54919b08ed1SBarry Smith   PetscInt       *ai = a->i;
55019b08ed1SBarry Smith   PetscErrorCode ierr;
55119b08ed1SBarry Smith   PetscInt       *aj = a->j;
55219b08ed1SBarry Smith   MatScalar      *aa = a->a,*ap;
55319b08ed1SBarry Smith 
55419b08ed1SBarry Smith   PetscFunctionBegin;
55519b08ed1SBarry Smith   if (A->was_assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call on assembled matrix.");
55619b08ed1SBarry Smith   if (m*n+a->nz > a->maxnz) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of entries in matrix will be larger than maximum nonzeros allocated for %D in MatSeqAIJSetTotalPreallocation()",a->maxnz);
55719b08ed1SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
55819b08ed1SBarry Smith     row  = im[k];
55919b08ed1SBarry Smith     rp   = aj + ai[row];
56019b08ed1SBarry Smith     ap   = aa + ai[row];
56119b08ed1SBarry Smith 
56219b08ed1SBarry Smith     ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
56319b08ed1SBarry Smith     if (!A->structure_only) {
56419b08ed1SBarry Smith       if (v) {
56519b08ed1SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
56619b08ed1SBarry Smith         v   += n;
56719b08ed1SBarry Smith       } else {
56819b08ed1SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
56919b08ed1SBarry Smith       }
57019b08ed1SBarry Smith     }
57119b08ed1SBarry Smith     a->ilen[row] = n;
57219b08ed1SBarry Smith     a->imax[row] = n;
57319b08ed1SBarry Smith     a->i[row+1]  = a->i[row]+n;
57419b08ed1SBarry Smith     a->nz       += n;
57519b08ed1SBarry Smith   }
5768c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
57719b08ed1SBarry Smith   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
57819b08ed1SBarry Smith #endif
57919b08ed1SBarry Smith   PetscFunctionReturn(0);
58019b08ed1SBarry Smith }
58119b08ed1SBarry Smith 
58219b08ed1SBarry Smith /*@
58319b08ed1SBarry Smith     MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix.
58419b08ed1SBarry Smith 
58519b08ed1SBarry Smith   Input Parameters:
58619b08ed1SBarry Smith +  A - the SeqAIJ matrix
58719b08ed1SBarry Smith -  nztotal - bound on the number of nonzeros
58819b08ed1SBarry Smith 
58919b08ed1SBarry Smith   Level: advanced
59019b08ed1SBarry Smith 
59119b08ed1SBarry Smith   Notes:
59219b08ed1SBarry 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.
59319b08ed1SBarry Smith     Simply call MatSetValues() after this call to provide the matrix entries in the usual manner. This matrix may be used
59419b08ed1SBarry Smith     as always with multiple matrix assemblies.
59519b08ed1SBarry Smith 
59619b08ed1SBarry Smith .seealso: MatSetOption(), MAT_SORTED_FULL, MatSetValues(), MatSeqAIJSetPreallocation()
59719b08ed1SBarry Smith @*/
59819b08ed1SBarry Smith 
59919b08ed1SBarry Smith PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A,PetscInt nztotal)
60019b08ed1SBarry Smith {
60119b08ed1SBarry Smith   PetscErrorCode ierr;
60219b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
60319b08ed1SBarry Smith 
60419b08ed1SBarry Smith   PetscFunctionBegin;
60519b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
60619b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
60719b08ed1SBarry Smith   a->maxnz  = nztotal;
60819b08ed1SBarry Smith   if (!a->imax) {
60919b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->imax);CHKERRQ(ierr);
61019b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
61119b08ed1SBarry Smith   }
61219b08ed1SBarry Smith   if (!a->ilen) {
61319b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->ilen);CHKERRQ(ierr);
61419b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
61519b08ed1SBarry Smith   } else {
61619b08ed1SBarry Smith     ierr = PetscMemzero(a->ilen,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
61719b08ed1SBarry Smith   }
61819b08ed1SBarry Smith 
61919b08ed1SBarry Smith   /* allocate the matrix space */
62019b08ed1SBarry Smith   if (A->structure_only) {
62119b08ed1SBarry Smith     ierr = PetscMalloc1(nztotal,&a->j);CHKERRQ(ierr);
62219b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&a->i);CHKERRQ(ierr);
62319b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*sizeof(PetscInt));CHKERRQ(ierr);
62419b08ed1SBarry Smith   } else {
62519b08ed1SBarry Smith     ierr = PetscMalloc3(nztotal,&a->a,nztotal,&a->j,A->rmap->n+1,&a->i);CHKERRQ(ierr);
62619b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
62719b08ed1SBarry Smith   }
62819b08ed1SBarry Smith   a->i[0] = 0;
62919b08ed1SBarry Smith   if (A->structure_only) {
63019b08ed1SBarry Smith     a->singlemalloc = PETSC_FALSE;
63119b08ed1SBarry Smith     a->free_a       = PETSC_FALSE;
63219b08ed1SBarry Smith   } else {
63319b08ed1SBarry Smith     a->singlemalloc = PETSC_TRUE;
63419b08ed1SBarry Smith     a->free_a       = PETSC_TRUE;
63519b08ed1SBarry Smith   }
63619b08ed1SBarry Smith   a->free_ij         = PETSC_TRUE;
63719b08ed1SBarry Smith   A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation;
63819b08ed1SBarry Smith   A->preallocated   = PETSC_TRUE;
63919b08ed1SBarry Smith   PetscFunctionReturn(0);
64019b08ed1SBarry Smith }
64119b08ed1SBarry Smith 
642071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
643071fcb05SBarry Smith {
644071fcb05SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
645071fcb05SBarry Smith   PetscInt       *rp,k,row;
646071fcb05SBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
647071fcb05SBarry Smith   PetscErrorCode ierr;
648071fcb05SBarry Smith   PetscInt       *aj = a->j;
649071fcb05SBarry Smith   MatScalar      *aa = a->a,*ap;
650071fcb05SBarry Smith 
651071fcb05SBarry Smith   PetscFunctionBegin;
652071fcb05SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
653071fcb05SBarry Smith     row  = im[k];
65419b08ed1SBarry Smith     if (PetscUnlikelyDebug(n > a->imax[row])) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Preallocation for row %D does not match number of columns provided",n);
655071fcb05SBarry Smith     rp   = aj + ai[row];
656071fcb05SBarry Smith     ap   = aa + ai[row];
657071fcb05SBarry Smith     if (!A->was_assembled) {
658071fcb05SBarry Smith       ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
659071fcb05SBarry Smith     }
660071fcb05SBarry Smith     if (!A->structure_only) {
661071fcb05SBarry Smith       if (v) {
662071fcb05SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
663071fcb05SBarry Smith         v   += n;
664071fcb05SBarry Smith       } else {
665071fcb05SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
666071fcb05SBarry Smith       }
667071fcb05SBarry Smith     }
668071fcb05SBarry Smith     ailen[row] = n;
669071fcb05SBarry Smith     a->nz      += n;
670071fcb05SBarry Smith   }
6718c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
672c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
673e2cf4d64SStefano Zampini #endif
674071fcb05SBarry Smith   PetscFunctionReturn(0);
675071fcb05SBarry Smith }
676071fcb05SBarry Smith 
677a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
6787eb43aa7SLois Curfman McInnes {
6797eb43aa7SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
68097f1f81fSBarry Smith   PetscInt   *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
68197f1f81fSBarry Smith   PetscInt   *ai = a->i,*ailen = a->ilen;
68254f21887SBarry Smith   MatScalar  *ap,*aa = a->a;
6837eb43aa7SLois Curfman McInnes 
6843a40ed3dSBarry Smith   PetscFunctionBegin;
6857eb43aa7SLois Curfman McInnes   for (k=0; k<m; k++) { /* loop over rows */
6867eb43aa7SLois Curfman McInnes     row = im[k];
687e32f2f54SBarry Smith     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
688e32f2f54SBarry Smith     if (row >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
689bfeeae90SHong Zhang     rp   = aj + ai[row]; ap = aa + ai[row];
6907eb43aa7SLois Curfman McInnes     nrow = ailen[row];
6917eb43aa7SLois Curfman McInnes     for (l=0; l<n; l++) { /* loop over columns */
692e32f2f54SBarry Smith       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
693e32f2f54SBarry Smith       if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
694bfeeae90SHong Zhang       col  = in[l];
6957eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
6967eb43aa7SLois Curfman McInnes       while (high-low > 5) {
6977eb43aa7SLois Curfman McInnes         t = (low+high)/2;
6987eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
6997eb43aa7SLois Curfman McInnes         else low = t;
7007eb43aa7SLois Curfman McInnes       }
7017eb43aa7SLois Curfman McInnes       for (i=low; i<high; i++) {
7027eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
7037eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
704b49de8d1SLois Curfman McInnes           *v++ = ap[i];
7057eb43aa7SLois Curfman McInnes           goto finished;
7067eb43aa7SLois Curfman McInnes         }
7077eb43aa7SLois Curfman McInnes       }
70897e567efSBarry Smith       *v++ = 0.0;
7097eb43aa7SLois Curfman McInnes finished:;
7107eb43aa7SLois Curfman McInnes     }
7117eb43aa7SLois Curfman McInnes   }
7123a40ed3dSBarry Smith   PetscFunctionReturn(0);
7137eb43aa7SLois Curfman McInnes }
7147eb43aa7SLois Curfman McInnes 
7153ea6fe3dSLisandro Dalcin PetscErrorCode MatView_SeqAIJ_Binary(Mat mat,PetscViewer viewer)
71617ab2063SBarry Smith {
7173ea6fe3dSLisandro Dalcin   Mat_SeqAIJ        *A = (Mat_SeqAIJ*)mat->data;
718c898d852SStefano Zampini   const PetscScalar *av;
7193ea6fe3dSLisandro Dalcin   PetscInt          header[4],M,N,m,nz,i;
7203ea6fe3dSLisandro Dalcin   PetscInt          *rowlens;
7216849ba73SBarry Smith   PetscErrorCode    ierr;
72217ab2063SBarry Smith 
7233a40ed3dSBarry Smith   PetscFunctionBegin;
7243ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
7252205254eSKarl Rupp 
7263ea6fe3dSLisandro Dalcin   M  = mat->rmap->N;
7273ea6fe3dSLisandro Dalcin   N  = mat->cmap->N;
7283ea6fe3dSLisandro Dalcin   m  = mat->rmap->n;
7293ea6fe3dSLisandro Dalcin   nz = A->nz;
730416022c9SBarry Smith 
7313ea6fe3dSLisandro Dalcin   /* write matrix header */
7323ea6fe3dSLisandro Dalcin   header[0] = MAT_FILE_CLASSID;
7333ea6fe3dSLisandro Dalcin   header[1] = M; header[2] = N; header[3] = nz;
7343ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,header,4,PETSC_INT);CHKERRQ(ierr);
735416022c9SBarry Smith 
7363ea6fe3dSLisandro Dalcin   /* fill in and store row lengths */
7373ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(m,&rowlens);CHKERRQ(ierr);
7383ea6fe3dSLisandro Dalcin   for (i=0; i<m; i++) rowlens[i] = A->i[i+1] - A->i[i];
7393ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,rowlens,m,PETSC_INT);CHKERRQ(ierr);
7403ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
7413ea6fe3dSLisandro Dalcin   /* store column indices */
7423ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,A->j,nz,PETSC_INT);CHKERRQ(ierr);
743416022c9SBarry Smith   /* store nonzero values */
744c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(mat,&av);CHKERRQ(ierr);
745c898d852SStefano Zampini   ierr = PetscViewerBinaryWrite(viewer,av,nz,PETSC_SCALAR);CHKERRQ(ierr);
746c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(mat,&av);CHKERRQ(ierr);
747b37d52dbSMark F. Adams 
7483ea6fe3dSLisandro Dalcin   /* write block size option to the viewer's .info file */
7493ea6fe3dSLisandro Dalcin   ierr = MatView_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
7503a40ed3dSBarry Smith   PetscFunctionReturn(0);
75117ab2063SBarry Smith }
752416022c9SBarry Smith 
7537dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer)
7547dc0baabSHong Zhang {
7557dc0baabSHong Zhang   PetscErrorCode ierr;
7567dc0baabSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
7577dc0baabSHong Zhang   PetscInt       i,k,m=A->rmap->N;
7587dc0baabSHong Zhang 
7597dc0baabSHong Zhang   PetscFunctionBegin;
7607dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
7617dc0baabSHong Zhang   for (i=0; i<m; i++) {
7627dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
7637dc0baabSHong Zhang     for (k=a->i[i]; k<a->i[i+1]; k++) {
7647dc0baabSHong Zhang       ierr = PetscViewerASCIIPrintf(viewer," (%D) ",a->j[k]);CHKERRQ(ierr);
7657dc0baabSHong Zhang     }
7667dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
7677dc0baabSHong Zhang   }
7687dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
7697dc0baabSHong Zhang   PetscFunctionReturn(0);
7707dc0baabSHong Zhang }
7717dc0baabSHong Zhang 
77209573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
773cd155464SBarry Smith 
774dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
775416022c9SBarry Smith {
776416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
777c898d852SStefano Zampini   const PetscScalar *av;
778dfbe8321SBarry Smith   PetscErrorCode    ierr;
77960e0710aSBarry Smith   PetscInt          i,j,m = A->rmap->n;
780e060cb09SBarry Smith   const char        *name;
781f3ef73ceSBarry Smith   PetscViewerFormat format;
78217ab2063SBarry Smith 
7833a40ed3dSBarry Smith   PetscFunctionBegin;
7847dc0baabSHong Zhang   if (A->structure_only) {
7857dc0baabSHong Zhang     ierr = MatView_SeqAIJ_ASCII_structonly(A,viewer);CHKERRQ(ierr);
7867dc0baabSHong Zhang     PetscFunctionReturn(0);
7877dc0baabSHong Zhang   }
78843e49210SHong Zhang 
789b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
7902e5835c6SStefano Zampini   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
7912e5835c6SStefano Zampini 
792c898d852SStefano Zampini   /* trigger copy to CPU if needed */
793c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
794c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
79571c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
79697f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
79760e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) {
798c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
799d00d2cf4SBarry Smith       nofinalvalue = 1;
800d00d2cf4SBarry Smith     }
801d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
802d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr);
80377431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr);
804fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
805fbfe6fa7SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,4);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
806fbfe6fa7SJed Brown #else
80777431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
808fbfe6fa7SJed Brown #endif
809b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
81017ab2063SBarry Smith 
81117ab2063SBarry Smith     for (i=0; i<m; i++) {
81260e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
813aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
814a9bf72d8SJed Brown         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e %18.16e\n",i+1,a->j[j]+1,(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
81517ab2063SBarry Smith #else
81660e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]);CHKERRQ(ierr);
81717ab2063SBarry Smith #endif
81817ab2063SBarry Smith       }
81917ab2063SBarry Smith     }
820d00d2cf4SBarry Smith     if (nofinalvalue) {
821c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
822c337ccceSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e %18.16e\n",m,A->cmap->n,0.,0.);CHKERRQ(ierr);
823c337ccceSJed Brown #else
824d0f46423SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr);
825c337ccceSJed Brown #endif
826d00d2cf4SBarry Smith     }
827317d6ea6SBarry Smith     ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
828fb9695e5SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
829d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
830fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
831d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
83244cd7ae7SLois Curfman McInnes     for (i=0; i<m; i++) {
83377431f27SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
83460e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
835aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
83636db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
83760e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
83836db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
83960e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
84036db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
84160e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
8426831982aSBarry Smith         }
84344cd7ae7SLois Curfman McInnes #else
84460e0710aSBarry Smith         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);}
84544cd7ae7SLois Curfman McInnes #endif
84644cd7ae7SLois Curfman McInnes       }
847b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
84844cd7ae7SLois Curfman McInnes     }
849d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
850fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
85197f1f81fSBarry Smith     PetscInt nzd=0,fshift=1,*sptr;
852d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
853854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&sptr);CHKERRQ(ierr);
854496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
855496be53dSLois Curfman McInnes       sptr[i] = nzd+1;
85660e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
857496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
858aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
85936db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
860496be53dSLois Curfman McInnes #else
861496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
862496be53dSLois Curfman McInnes #endif
863496be53dSLois Curfman McInnes         }
864496be53dSLois Curfman McInnes       }
865496be53dSLois Curfman McInnes     }
8662e44a96cSLois Curfman McInnes     sptr[m] = nzd+1;
86777431f27SBarry Smith     ierr    = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr);
8682e44a96cSLois Curfman McInnes     for (i=0; i<m+1; i+=6) {
8692205254eSKarl Rupp       if (i+4<m) {
8702205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4],sptr[i+5]);CHKERRQ(ierr);
8712205254eSKarl Rupp       } else if (i+3<m) {
8722205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4]);CHKERRQ(ierr);
8732205254eSKarl Rupp       } else if (i+2<m) {
8742205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);
8752205254eSKarl Rupp       } else if (i+1<m) {
8762205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);
8772205254eSKarl Rupp       } else if (i<m) {
8782205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);
8792205254eSKarl Rupp       } else {
8802205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);
8812205254eSKarl Rupp       }
882496be53dSLois Curfman McInnes     }
883b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
884606d414cSSatish Balay     ierr = PetscFree(sptr);CHKERRQ(ierr);
885496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
88660e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
88777431f27SBarry Smith         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);}
888496be53dSLois Curfman McInnes       }
889b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
890496be53dSLois Curfman McInnes     }
891b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
892496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
89360e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
894496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
895aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
89636db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
89760e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
8986831982aSBarry Smith           }
899496be53dSLois Curfman McInnes #else
90060e0710aSBarry Smith           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]);CHKERRQ(ierr);}
901496be53dSLois Curfman McInnes #endif
902496be53dSLois Curfman McInnes         }
903496be53dSLois Curfman McInnes       }
904b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
905496be53dSLois Curfman McInnes     }
906d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
907fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
90897f1f81fSBarry Smith     PetscInt    cnt = 0,jcnt;
90987828ca2SBarry Smith     PetscScalar value;
91068f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
91168f1ed48SBarry Smith     PetscBool   realonly = PETSC_TRUE;
91268f1ed48SBarry Smith 
91368f1ed48SBarry Smith     for (i=0; i<a->i[m]; i++) {
91468f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
91568f1ed48SBarry Smith         realonly = PETSC_FALSE;
91668f1ed48SBarry Smith         break;
91768f1ed48SBarry Smith       }
91868f1ed48SBarry Smith     }
91968f1ed48SBarry Smith #endif
92002594712SBarry Smith 
921d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
92202594712SBarry Smith     for (i=0; i<m; i++) {
92302594712SBarry Smith       jcnt = 0;
924d0f46423SBarry Smith       for (j=0; j<A->cmap->n; j++) {
925e24b481bSBarry Smith         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
92602594712SBarry Smith           value = a->a[cnt++];
927e24b481bSBarry Smith           jcnt++;
92802594712SBarry Smith         } else {
92902594712SBarry Smith           value = 0.0;
93002594712SBarry Smith         }
931aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
93268f1ed48SBarry Smith         if (realonly) {
93360e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value));CHKERRQ(ierr);
93468f1ed48SBarry Smith         } else {
93560e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value));CHKERRQ(ierr);
93668f1ed48SBarry Smith         }
93702594712SBarry Smith #else
93860e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value);CHKERRQ(ierr);
93902594712SBarry Smith #endif
94002594712SBarry Smith       }
941b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
94202594712SBarry Smith     }
943d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9443c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
945150b93efSMatthew G. Knepley     PetscInt fshift=1;
946d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
9473c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
94819303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n");CHKERRQ(ierr);
9493c215bfdSMatthew Knepley #else
95019303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n");CHKERRQ(ierr);
9513c215bfdSMatthew Knepley #endif
952d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr);
9533c215bfdSMatthew Knepley     for (i=0; i<m; i++) {
95460e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
9553c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
956a9a0e077SKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g %g\n", i+fshift,a->j[j]+fshift,(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
9573c215bfdSMatthew Knepley #else
958150b93efSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]);CHKERRQ(ierr);
9593c215bfdSMatthew Knepley #endif
9603c215bfdSMatthew Knepley       }
9613c215bfdSMatthew Knepley     }
962d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9633a40ed3dSBarry Smith   } else {
964d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
965d5f3da31SBarry Smith     if (A->factortype) {
96616cd7e1dSShri Abhyankar       for (i=0; i<m; i++) {
96716cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
96816cd7e1dSShri Abhyankar         /* L part */
96960e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
97016cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
97116cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
97260e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
97316cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9746712e2f1SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
97516cd7e1dSShri Abhyankar           } else {
97660e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
97716cd7e1dSShri Abhyankar           }
97816cd7e1dSShri Abhyankar #else
97960e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
98016cd7e1dSShri Abhyankar #endif
98116cd7e1dSShri Abhyankar         }
98216cd7e1dSShri Abhyankar         /* diagonal */
98316cd7e1dSShri Abhyankar         j = a->diag[i];
98416cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
98516cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
98660e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)PetscImaginaryPart(1.0/a->a[j]));CHKERRQ(ierr);
98716cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9886712e2f1SBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)(-PetscImaginaryPart(1.0/a->a[j])));CHKERRQ(ierr);
98916cd7e1dSShri Abhyankar         } else {
99060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j]));CHKERRQ(ierr);
99116cd7e1dSShri Abhyankar         }
99216cd7e1dSShri Abhyankar #else
99360e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)(1.0/a->a[j]));CHKERRQ(ierr);
99416cd7e1dSShri Abhyankar #endif
99516cd7e1dSShri Abhyankar 
99616cd7e1dSShri Abhyankar         /* U part */
99760e0710aSBarry Smith         for (j=a->diag[i+1]+1; j<a->diag[i]; j++) {
99816cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
99916cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
100060e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
100116cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
100222ab088eSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
100316cd7e1dSShri Abhyankar           } else {
100460e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
100516cd7e1dSShri Abhyankar           }
100616cd7e1dSShri Abhyankar #else
100760e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
100816cd7e1dSShri Abhyankar #endif
100916cd7e1dSShri Abhyankar         }
101016cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
101116cd7e1dSShri Abhyankar       }
101216cd7e1dSShri Abhyankar     } else {
101317ab2063SBarry Smith       for (i=0; i<m; i++) {
101477431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
101560e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
1016aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
101736db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
101860e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
101936db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
102060e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
10213a40ed3dSBarry Smith           } else {
102260e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
102317ab2063SBarry Smith           }
102417ab2063SBarry Smith #else
102560e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
102617ab2063SBarry Smith #endif
102717ab2063SBarry Smith         }
1028b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
102917ab2063SBarry Smith       }
103016cd7e1dSShri Abhyankar     }
1031d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
103217ab2063SBarry Smith   }
1033b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
10343a40ed3dSBarry Smith   PetscFunctionReturn(0);
1035416022c9SBarry Smith }
1036416022c9SBarry Smith 
10379804daf3SBarry Smith #include <petscdraw.h>
1038dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
1039416022c9SBarry Smith {
1040480ef9eaSBarry Smith   Mat               A  = (Mat) Aa;
1041416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1042dfbe8321SBarry Smith   PetscErrorCode    ierr;
1043383922c3SLisandro Dalcin   PetscInt          i,j,m = A->rmap->n;
1044383922c3SLisandro Dalcin   int               color;
1045b05fc000SLisandro Dalcin   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
1046b0a32e0cSBarry Smith   PetscViewer       viewer;
1047f3ef73ceSBarry Smith   PetscViewerFormat format;
1048cddf8d76SBarry Smith 
10493a40ed3dSBarry Smith   PetscFunctionBegin;
1050480ef9eaSBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
1051b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1052b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
1053383922c3SLisandro Dalcin 
1054416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
10550513a670SBarry Smith 
1056fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1057383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10580513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
1059b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
1060416022c9SBarry Smith     for (i=0; i<m; i++) {
1061cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1062bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1063bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
106436db0b34SBarry Smith         if (PetscRealPart(a->a[j]) >=  0.) continue;
1065b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1066cddf8d76SBarry Smith       }
1067cddf8d76SBarry Smith     }
1068b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
1069cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1070cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1071bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1072bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1073cddf8d76SBarry Smith         if (a->a[j] !=  0.) continue;
1074b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1075cddf8d76SBarry Smith       }
1076cddf8d76SBarry Smith     }
1077b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
1078cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1079cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1080bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1081bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
108236db0b34SBarry Smith         if (PetscRealPart(a->a[j]) <=  0.) continue;
1083b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1084416022c9SBarry Smith       }
1085416022c9SBarry Smith     }
1086383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10870513a670SBarry Smith   } else {
10880513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
10890513a670SBarry Smith     /* first determine max of all nonzero values */
1090b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1091383922c3SLisandro Dalcin     PetscInt  nz = a->nz, count = 0;
1092b0a32e0cSBarry Smith     PetscDraw popup;
10930513a670SBarry Smith 
10940513a670SBarry Smith     for (i=0; i<nz; i++) {
10950513a670SBarry Smith       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
10960513a670SBarry Smith     }
1097383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
1098b0a32e0cSBarry Smith     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
109945f3bb6eSLisandro Dalcin     ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr);
1100383922c3SLisandro Dalcin 
1101383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
11020513a670SBarry Smith     for (i=0; i<m; i++) {
1103383922c3SLisandro Dalcin       y_l = m - i - 1.0;
1104383922c3SLisandro Dalcin       y_r = y_l + 1.0;
1105bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1106383922c3SLisandro Dalcin         x_l = a->j[j];
1107383922c3SLisandro Dalcin         x_r = x_l + 1.0;
1108b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(a->a[count]),minv,maxv);
1109b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
11100513a670SBarry Smith         count++;
11110513a670SBarry Smith       }
11120513a670SBarry Smith     }
1113383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
11140513a670SBarry Smith   }
1115480ef9eaSBarry Smith   PetscFunctionReturn(0);
1116480ef9eaSBarry Smith }
1117cddf8d76SBarry Smith 
11189804daf3SBarry Smith #include <petscdraw.h>
1119dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
1120480ef9eaSBarry Smith {
1121dfbe8321SBarry Smith   PetscErrorCode ierr;
1122b0a32e0cSBarry Smith   PetscDraw      draw;
112336db0b34SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
1124ace3abfcSBarry Smith   PetscBool      isnull;
1125480ef9eaSBarry Smith 
1126480ef9eaSBarry Smith   PetscFunctionBegin;
1127b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1128b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
1129480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
1130480ef9eaSBarry Smith 
1131d0f46423SBarry Smith   xr   = A->cmap->n; yr  = A->rmap->n; h = yr/10.0; w = xr/10.0;
1132480ef9eaSBarry Smith   xr  += w;          yr += h;         xl = -w;     yl = -h;
1133b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
1134832b7cebSLisandro Dalcin   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
1135b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
11360298fd71SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr);
1137832b7cebSLisandro Dalcin   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
11383a40ed3dSBarry Smith   PetscFunctionReturn(0);
1139416022c9SBarry Smith }
1140416022c9SBarry Smith 
1141dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
1142416022c9SBarry Smith {
1143dfbe8321SBarry Smith   PetscErrorCode ierr;
1144ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw;
1145416022c9SBarry Smith 
11463a40ed3dSBarry Smith   PetscFunctionBegin;
1147251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1148251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1149251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1150c45a1595SBarry Smith   if (iascii) {
11513a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
11520f5bd95cSBarry Smith   } else if (isbinary) {
11533a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
11540f5bd95cSBarry Smith   } else if (isdraw) {
11553a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
115611aeaf0aSBarry Smith   }
11574108e4d5SBarry Smith   ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr);
11583a40ed3dSBarry Smith   PetscFunctionReturn(0);
115917ab2063SBarry Smith }
116019bcc07fSBarry Smith 
1161dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
116217ab2063SBarry Smith {
1163416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
11646849ba73SBarry Smith   PetscErrorCode ierr;
1165580bdb30SBarry Smith   PetscInt       fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax;
1166d0f46423SBarry Smith   PetscInt       m      = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
116754f21887SBarry Smith   MatScalar      *aa    = a->a,*ap;
11683447b6efSHong Zhang   PetscReal      ratio  = 0.6;
116917ab2063SBarry Smith 
11703a40ed3dSBarry Smith   PetscFunctionBegin;
11713a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1172071fcb05SBarry Smith   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1173b215bc84SStefano Zampini   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) {
1174b215bc84SStefano Zampini     /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */
1175b215bc84SStefano Zampini     ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
1176b215bc84SStefano Zampini     PetscFunctionReturn(0);
1177b215bc84SStefano Zampini   }
117817ab2063SBarry Smith 
117943ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
118017ab2063SBarry Smith   for (i=1; i<m; i++) {
1181416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
118217ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
118394a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
118417ab2063SBarry Smith     if (fshift) {
1185bfeeae90SHong Zhang       ip = aj + ai[i];
1186bfeeae90SHong Zhang       ap = aa + ai[i];
118717ab2063SBarry Smith       N  = ailen[i];
1188580bdb30SBarry Smith       ierr = PetscArraymove(ip-fshift,ip,N);CHKERRQ(ierr);
1189580bdb30SBarry Smith       if (!A->structure_only) {
1190580bdb30SBarry Smith         ierr = PetscArraymove(ap-fshift,ap,N);CHKERRQ(ierr);
119117ab2063SBarry Smith       }
119217ab2063SBarry Smith     }
119317ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
119417ab2063SBarry Smith   }
119517ab2063SBarry Smith   if (m) {
119617ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
119717ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
119817ab2063SBarry Smith   }
11997b083b7cSBarry Smith 
120017ab2063SBarry Smith   /* reset ilen and imax for each row */
12017b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1202396832f4SHong Zhang   if (A->structure_only) {
1203071fcb05SBarry Smith     ierr = PetscFree(a->imax);CHKERRQ(ierr);
1204071fcb05SBarry Smith     ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1205396832f4SHong Zhang   } else { /* !A->structure_only */
120617ab2063SBarry Smith     for (i=0; i<m; i++) {
120717ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
12087b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
120917ab2063SBarry Smith     }
1210396832f4SHong Zhang   }
1211bfeeae90SHong Zhang   a->nz = ai[m];
121265e19b50SBarry Smith   if (fshift && a->nounused == -1) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Unused space detected in matrix: %D X %D, %D unneeded", m, A->cmap->n, fshift);
121317ab2063SBarry Smith 
121409f38230SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1215d0f46423SBarry Smith   ierr = PetscInfo4(A,"Matrix size: %D X %D; storage space: %D unneeded,%D used\n",m,A->cmap->n,fshift,a->nz);CHKERRQ(ierr);
1216ae15b995SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
1217ae15b995SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
12182205254eSKarl Rupp 
12198e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1220dd5f02e7SSatish Balay   a->reallocs         = 0;
12216712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
122236db0b34SBarry Smith   a->rmax             = rmax;
12234e220ebcSLois Curfman McInnes 
1224396832f4SHong Zhang   if (!A->structure_only) {
122511e456e1SBarry Smith     ierr = MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
1226396832f4SHong Zhang   }
12274108e4d5SBarry Smith   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
12283a40ed3dSBarry Smith   PetscFunctionReturn(0);
122917ab2063SBarry Smith }
123017ab2063SBarry Smith 
123199cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
123299cafbc1SBarry Smith {
123399cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
123499cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
12352e5835c6SStefano Zampini   MatScalar      *aa;
1236acf2f550SJed Brown   PetscErrorCode ierr;
123799cafbc1SBarry Smith 
123899cafbc1SBarry Smith   PetscFunctionBegin;
12392e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
124099cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
12412e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
1242acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12438c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1244c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1245e2cf4d64SStefano Zampini #endif
124699cafbc1SBarry Smith   PetscFunctionReturn(0);
124799cafbc1SBarry Smith }
124899cafbc1SBarry Smith 
124999cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
125099cafbc1SBarry Smith {
125199cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
125299cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
12532e5835c6SStefano Zampini   MatScalar      *aa;
1254acf2f550SJed Brown   PetscErrorCode ierr;
125599cafbc1SBarry Smith 
125699cafbc1SBarry Smith   PetscFunctionBegin;
12572e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
125899cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
12592e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
1260acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12618c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1262c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1263e2cf4d64SStefano Zampini #endif
126499cafbc1SBarry Smith   PetscFunctionReturn(0);
126599cafbc1SBarry Smith }
126699cafbc1SBarry Smith 
1267dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
126817ab2063SBarry Smith {
1269416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1270dfbe8321SBarry Smith   PetscErrorCode ierr;
12713a40ed3dSBarry Smith 
12723a40ed3dSBarry Smith   PetscFunctionBegin;
1273580bdb30SBarry Smith   ierr = PetscArrayzero(a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
1274acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12758c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1276c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1277e2cf4d64SStefano Zampini #endif
12783a40ed3dSBarry Smith   PetscFunctionReturn(0);
127917ab2063SBarry Smith }
1280416022c9SBarry Smith 
1281dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
128217ab2063SBarry Smith {
1283416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1284dfbe8321SBarry Smith   PetscErrorCode ierr;
1285d5d45c9bSBarry Smith 
12863a40ed3dSBarry Smith   PetscFunctionBegin;
1287aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1288d0f46423SBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
128917ab2063SBarry Smith #endif
1290e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
12916bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
12926bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
129305b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
1294d48dcb14SBarry Smith   ierr = PetscFree(a->ibdiag);CHKERRQ(ierr);
1295071fcb05SBarry Smith   ierr = PetscFree(a->imax);CHKERRQ(ierr);
1296071fcb05SBarry Smith   ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1297846b4da1SFande Kong   ierr = PetscFree(a->ipre);CHKERRQ(ierr);
129871f1c65dSBarry Smith   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
129905b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
13006bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
130105b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
1302cd6b891eSBarry Smith   ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr);
1303a30b2313SHong Zhang 
13044108e4d5SBarry Smith   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
1305bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1306901853e0SKris Buschelman 
13076718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
13086718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
13096718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
13106718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
13116718818eSStefano Zampini      due to different matrix sizes */
13126718818eSStefano Zampini   ierr = PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL);CHKERRQ(ierr);
13136718818eSStefano Zampini 
1314f4259b30SLisandro Dalcin   ierr = PetscObjectChangeTypeName((PetscObject)A,NULL);CHKERRQ(ierr);
1315bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr);
1316bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr);
1317bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
1318bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr);
1319bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr);
1320bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr);
13214222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
13224222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
1323e6e9a74fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL);CHKERRQ(ierr);
1324fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
13254222ddf1SHong Zhang #endif
13263d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
13273d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijkokkos_C",NULL);CHKERRQ(ierr);
13283d0639e7SStefano Zampini #endif
13294222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL);CHKERRQ(ierr);
1330af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1331af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr);
1332af8000cdSHong Zhang #endif
1333d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
1334d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL);CHKERRQ(ierr);
1335d24d4204SJose E. Roman #endif
133663c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
133763c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr);
13384222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
133963c07aadSStefano Zampini #endif
1340b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1341c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr);
1342c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr);
1343bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
1344bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr);
1345846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr);
1346bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr);
1347bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr);
13484222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL);CHKERRQ(ierr);
13494222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL);CHKERRQ(ierr);
13504222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
1351ad7e164aSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJKron_C",NULL);CHKERRQ(ierr);
13523a40ed3dSBarry Smith   PetscFunctionReturn(0);
135317ab2063SBarry Smith }
135417ab2063SBarry Smith 
1355ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
135617ab2063SBarry Smith {
1357416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13584846f1f5SKris Buschelman   PetscErrorCode ierr;
13593a40ed3dSBarry Smith 
13603a40ed3dSBarry Smith   PetscFunctionBegin;
1361a65d3064SKris Buschelman   switch (op) {
1362a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
13634e0d8c25SBarry Smith     a->roworiented = flg;
1364a65d3064SKris Buschelman     break;
1365a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1366a9817697SBarry Smith     a->keepnonzeropattern = flg;
1367a65d3064SKris Buschelman     break;
1368512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1369512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1370a65d3064SKris Buschelman     break;
1371a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
13724e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1373a65d3064SKris Buschelman     break;
1374a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
13754e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1376a65d3064SKris Buschelman     break;
137728b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
137828b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
137928b2fa4aSMatthew Knepley     break;
1380a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
13814e0d8c25SBarry Smith     a->ignorezeroentries = flg;
13820df259c2SBarry Smith     break;
13833d472b54SHong Zhang   case MAT_SPD:
1384b1646e73SJed Brown   case MAT_SYMMETRIC:
1385b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1386b1646e73SJed Brown   case MAT_HERMITIAN:
1387b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1388957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
13895021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
13905021d80fSJed Brown     break;
13918c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
1392a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1393a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
1394290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1395a65d3064SKris Buschelman     break;
1396b87ac2d8SJed Brown   case MAT_USE_INODES:
1397b215bc84SStefano Zampini     ierr = MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg);CHKERRQ(ierr);
1398b87ac2d8SJed Brown     break;
1399c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1400c10200c1SHong Zhang     A->submat_singleis = flg;
1401c10200c1SHong Zhang     break;
1402071fcb05SBarry Smith   case MAT_SORTED_FULL:
1403071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1404071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1405071fcb05SBarry Smith     break;
14061a2c6b5cSJunchao Zhang   case MAT_FORM_EXPLICIT_TRANSPOSE:
14071a2c6b5cSJunchao Zhang     A->form_explicit_transpose = flg;
14081a2c6b5cSJunchao Zhang     break;
1409a65d3064SKris Buschelman   default:
1410e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1411a65d3064SKris Buschelman   }
14123a40ed3dSBarry Smith   PetscFunctionReturn(0);
141317ab2063SBarry Smith }
141417ab2063SBarry Smith 
1415dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
141617ab2063SBarry Smith {
1417416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
14186849ba73SBarry Smith   PetscErrorCode    ierr;
1419fdc842d1SBarry Smith   PetscInt          i,j,n,*ai=a->i,*aj=a->j;
1420c898d852SStefano Zampini   PetscScalar       *x;
1421c898d852SStefano Zampini   const PetscScalar *aa;
142217ab2063SBarry Smith 
14233a40ed3dSBarry Smith   PetscFunctionBegin;
1424d3e70bfaSHong Zhang   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1425e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1426c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
1427d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1428d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
1429fdc842d1SBarry Smith     ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
14302c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1431fdc842d1SBarry Smith     ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1432c898d852SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
143335e7444dSHong Zhang     PetscFunctionReturn(0);
143435e7444dSHong Zhang   }
143535e7444dSHong Zhang 
1436fdc842d1SBarry Smith   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
143735e7444dSHong Zhang   for (i=0; i<n; i++) {
1438fdc842d1SBarry Smith     x[i] = 0.0;
143935e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
144035e7444dSHong Zhang       if (aj[j] == i) {
144135e7444dSHong Zhang         x[i] = aa[j];
144217ab2063SBarry Smith         break;
144317ab2063SBarry Smith       }
144417ab2063SBarry Smith     }
144517ab2063SBarry Smith   }
1446fdc842d1SBarry Smith   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1447c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
14483a40ed3dSBarry Smith   PetscFunctionReturn(0);
144917ab2063SBarry Smith }
145017ab2063SBarry Smith 
1451c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1452dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
145317ab2063SBarry Smith {
1454416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1455d9ca1df4SBarry Smith   PetscScalar       *y;
1456d9ca1df4SBarry Smith   const PetscScalar *x;
1457dfbe8321SBarry Smith   PetscErrorCode    ierr;
1458d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
14595c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1460d9ca1df4SBarry Smith   const MatScalar   *v;
1461a77337e4SBarry Smith   PetscScalar       alpha;
1462d9ca1df4SBarry Smith   PetscInt          n,i,j;
1463d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
14643447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1465ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
14665c897100SBarry Smith #endif
146717ab2063SBarry Smith 
14683a40ed3dSBarry Smith   PetscFunctionBegin;
14692e8a6d31SBarry Smith   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
1470d9ca1df4SBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
14711ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
14725c897100SBarry Smith 
14735c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1474bfeeae90SHong Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
14755c897100SBarry Smith #else
14763447b6efSHong Zhang   if (usecprow) {
14773447b6efSHong Zhang     m    = cprow.nrows;
14783447b6efSHong Zhang     ii   = cprow.i;
14797b2bb3b9SHong Zhang     ridx = cprow.rindex;
14803447b6efSHong Zhang   } else {
14813447b6efSHong Zhang     ii = a->i;
14823447b6efSHong Zhang   }
148317ab2063SBarry Smith   for (i=0; i<m; i++) {
14843447b6efSHong Zhang     idx = a->j + ii[i];
14853447b6efSHong Zhang     v   = a->a + ii[i];
14863447b6efSHong Zhang     n   = ii[i+1] - ii[i];
14873447b6efSHong Zhang     if (usecprow) {
14887b2bb3b9SHong Zhang       alpha = x[ridx[i]];
14893447b6efSHong Zhang     } else {
149017ab2063SBarry Smith       alpha = x[i];
14913447b6efSHong Zhang     }
149204fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
149317ab2063SBarry Smith   }
14945c897100SBarry Smith #endif
1495dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1496d9ca1df4SBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
14971ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
14983a40ed3dSBarry Smith   PetscFunctionReturn(0);
149917ab2063SBarry Smith }
150017ab2063SBarry Smith 
1501dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
15025c897100SBarry Smith {
1503dfbe8321SBarry Smith   PetscErrorCode ierr;
15045c897100SBarry Smith 
15055c897100SBarry Smith   PetscFunctionBegin;
1506170fe5c8SBarry Smith   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
15075c897100SBarry Smith   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
15085c897100SBarry Smith   PetscFunctionReturn(0);
15095c897100SBarry Smith }
15105c897100SBarry Smith 
1511c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
151278b84d54SShri Abhyankar 
1513dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
151417ab2063SBarry Smith {
1515416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1516d9fead3dSBarry Smith   PetscScalar       *y;
151754f21887SBarry Smith   const PetscScalar *x;
151854f21887SBarry Smith   const MatScalar   *aa;
1519dfbe8321SBarry Smith   PetscErrorCode    ierr;
1520003131ecSBarry Smith   PetscInt          m=A->rmap->n;
15210298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
15227b083b7cSBarry Smith   PetscInt          n,i;
1523362ced78SSatish Balay   PetscScalar       sum;
1524ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
152517ab2063SBarry Smith 
1526b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
152797952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1528fee21e36SBarry Smith #endif
1529fee21e36SBarry Smith 
15303a40ed3dSBarry Smith   PetscFunctionBegin;
1531b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1532b215bc84SStefano Zampini     ierr = MatMult_SeqAIJ_Inode(A,xx,yy);CHKERRQ(ierr);
1533b215bc84SStefano Zampini     PetscFunctionReturn(0);
1534b215bc84SStefano Zampini   }
15353649974fSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
15361ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1537416022c9SBarry Smith   ii   = a->i;
15384eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
1539580bdb30SBarry Smith     ierr = PetscArrayzero(y,m);CHKERRQ(ierr);
154097952fefSHong Zhang     m    = a->compressedrow.nrows;
154197952fefSHong Zhang     ii   = a->compressedrow.i;
154297952fefSHong Zhang     ridx = a->compressedrow.rindex;
154397952fefSHong Zhang     for (i=0; i<m; i++) {
154497952fefSHong Zhang       n           = ii[i+1] - ii[i];
154597952fefSHong Zhang       aj          = a->j + ii[i];
154697952fefSHong Zhang       aa          = a->a + ii[i];
154797952fefSHong Zhang       sum         = 0.0;
1548003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1549003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
155097952fefSHong Zhang       y[*ridx++] = sum;
155197952fefSHong Zhang     }
155297952fefSHong Zhang   } else { /* do not use compressed row format */
1553b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
15543d3eaba7SBarry Smith     aj   = a->j;
15553d3eaba7SBarry Smith     aa   = a->a;
1556b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1557b05257ddSBarry Smith #else
155817ab2063SBarry Smith     for (i=0; i<m; i++) {
1559003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1560003131ecSBarry Smith       aj          = a->j + ii[i];
1561003131ecSBarry Smith       aa          = a->a + ii[i];
156217ab2063SBarry Smith       sum         = 0.0;
1563003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
156417ab2063SBarry Smith       y[i] = sum;
156517ab2063SBarry Smith     }
15668d195f9aSBarry Smith #endif
1567b05257ddSBarry Smith   }
15687b083b7cSBarry Smith   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
15693649974fSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
15701ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
15713a40ed3dSBarry Smith   PetscFunctionReturn(0);
157217ab2063SBarry Smith }
157317ab2063SBarry Smith 
1574b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1575b434eb95SMatthew G. Knepley {
1576b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1577b434eb95SMatthew G. Knepley   PetscScalar       *y;
1578b434eb95SMatthew G. Knepley   const PetscScalar *x;
1579b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1580b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1581b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1582b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1583b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1584b434eb95SMatthew G. Knepley   PetscScalar       sum;
1585b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1586b434eb95SMatthew G. Knepley 
1587b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1588b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1589b434eb95SMatthew G. Knepley #endif
1590b434eb95SMatthew G. Knepley 
1591b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1592b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1593b434eb95SMatthew G. Knepley   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1594b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1595b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1596b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1597b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1598b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1599b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1600b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1601b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1602b434eb95SMatthew G. Knepley       sum         = 0.0;
1603b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1604b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1605b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1606b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1607b434eb95SMatthew G. Knepley     }
1608b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16093d3eaba7SBarry Smith     ii = a->i;
1610b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1611b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1612b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1613b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1614b434eb95SMatthew G. Knepley       sum         = 0.0;
1615b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1616b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1617b434eb95SMatthew G. Knepley       y[i] = sum;
1618b434eb95SMatthew G. Knepley     }
1619b434eb95SMatthew G. Knepley   }
1620b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1621b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1622b434eb95SMatthew G. Knepley   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1623b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1624b434eb95SMatthew G. Knepley }
1625b434eb95SMatthew G. Knepley 
1626b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1627b434eb95SMatthew G. Knepley {
1628b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1629b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1630b434eb95SMatthew G. Knepley   const PetscScalar *x;
1631b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1632b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1633b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1634b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1635b434eb95SMatthew G. Knepley   PetscScalar       sum;
1636b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1637b434eb95SMatthew G. Knepley 
1638b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1639b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1640d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1641b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1642b434eb95SMatthew G. Knepley     if (zz != yy) {
1643580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
1644b434eb95SMatthew G. Knepley     }
1645b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1646b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1647b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1648b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1649b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1650b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1651b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1652b434eb95SMatthew G. Knepley       sum = y[*ridx];
1653b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1654b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1655b434eb95SMatthew G. Knepley     }
1656b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16573d3eaba7SBarry Smith     ii = a->i;
1658b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1659b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1660b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1661b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1662b434eb95SMatthew G. Knepley       sum = y[i];
1663b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1664b434eb95SMatthew G. Knepley       z[i] = sum;
1665b434eb95SMatthew G. Knepley     }
1666b434eb95SMatthew G. Knepley   }
1667b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1668b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1669d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1670b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1671b434eb95SMatthew G. Knepley }
1672b434eb95SMatthew G. Knepley 
1673c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1674dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
167517ab2063SBarry Smith {
1676416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1677f15663dcSBarry Smith   PetscScalar       *y,*z;
1678f15663dcSBarry Smith   const PetscScalar *x;
167954f21887SBarry Smith   const MatScalar   *aa;
1680dfbe8321SBarry Smith   PetscErrorCode    ierr;
1681d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1682d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1683362ced78SSatish Balay   PetscScalar       sum;
1684ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
16859ea0dfa2SSatish Balay 
16863a40ed3dSBarry Smith   PetscFunctionBegin;
1687b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1688b215bc84SStefano Zampini     ierr = MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz);CHKERRQ(ierr);
1689b215bc84SStefano Zampini     PetscFunctionReturn(0);
1690b215bc84SStefano Zampini   }
1691f15663dcSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1692d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
16934eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
16944eb6d288SHong Zhang     if (zz != yy) {
1695580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
16964eb6d288SHong Zhang     }
169797952fefSHong Zhang     m    = a->compressedrow.nrows;
169897952fefSHong Zhang     ii   = a->compressedrow.i;
169997952fefSHong Zhang     ridx = a->compressedrow.rindex;
170097952fefSHong Zhang     for (i=0; i<m; i++) {
170197952fefSHong Zhang       n   = ii[i+1] - ii[i];
170297952fefSHong Zhang       aj  = a->j + ii[i];
170397952fefSHong Zhang       aa  = a->a + ii[i];
170497952fefSHong Zhang       sum = y[*ridx];
1705f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
170697952fefSHong Zhang       z[*ridx++] = sum;
170797952fefSHong Zhang     }
170897952fefSHong Zhang   } else { /* do not use compressed row format */
17093d3eaba7SBarry Smith     ii = a->i;
1710f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
17113d3eaba7SBarry Smith     aj = a->j;
17123d3eaba7SBarry Smith     aa = a->a;
1713f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1714f15663dcSBarry Smith #else
171517ab2063SBarry Smith     for (i=0; i<m; i++) {
1716f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1717f15663dcSBarry Smith       aj  = a->j + ii[i];
1718f15663dcSBarry Smith       aa  = a->a + ii[i];
171917ab2063SBarry Smith       sum = y[i];
1720f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
172117ab2063SBarry Smith       z[i] = sum;
172217ab2063SBarry Smith     }
172302ab625aSSatish Balay #endif
1724f15663dcSBarry Smith   }
1725dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1726f15663dcSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1727d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
17283a40ed3dSBarry Smith   PetscFunctionReturn(0);
172917ab2063SBarry Smith }
173017ab2063SBarry Smith 
173117ab2063SBarry Smith /*
173217ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
173317ab2063SBarry Smith */
1734dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
173517ab2063SBarry Smith {
1736416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
17376849ba73SBarry Smith   PetscErrorCode ierr;
1738d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
173917ab2063SBarry Smith 
17403a40ed3dSBarry Smith   PetscFunctionBegin;
174109f38230SBarry Smith   if (!a->diag) {
1742785e854fSJed Brown     ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr);
17433bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr);
174409f38230SBarry Smith   }
1745d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
174609f38230SBarry Smith     a->diag[i] = a->i[i+1];
1747bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1748bfeeae90SHong Zhang       if (a->j[j] == i) {
174909f38230SBarry Smith         a->diag[i] = j;
175017ab2063SBarry Smith         break;
175117ab2063SBarry Smith       }
175217ab2063SBarry Smith     }
175317ab2063SBarry Smith   }
17543a40ed3dSBarry Smith   PetscFunctionReturn(0);
175517ab2063SBarry Smith }
175617ab2063SBarry Smith 
175761ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
175861ecd0c6SBarry Smith {
175961ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
176061ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
176161ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
176261ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
176361ecd0c6SBarry Smith   PetscErrorCode    ierr;
176461ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
176561ecd0c6SBarry Smith 
176661ecd0c6SBarry Smith   PetscFunctionBegin;
176761ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
176861ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
176961ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
177061ecd0c6SBarry Smith     PetscFunctionReturn(0);
177161ecd0c6SBarry Smith   }
177261ecd0c6SBarry Smith 
177361ecd0c6SBarry Smith   if (a->diagonaldense) {
177461ecd0c6SBarry Smith     cnt = 0;
177561ecd0c6SBarry Smith   } else {
177661ecd0c6SBarry Smith     ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr);
177761ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
177861ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
177961ecd0c6SBarry Smith         cnt++;
178061ecd0c6SBarry Smith         mdiag[i] = 1;
178161ecd0c6SBarry Smith       }
178261ecd0c6SBarry Smith     }
178361ecd0c6SBarry Smith   }
178461ecd0c6SBarry Smith   if (!cnt) {
178561ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
178661ecd0c6SBarry Smith   } else {
1787b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1788b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
178961ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
179061ecd0c6SBarry Smith 
179161ecd0c6SBarry Smith     a->a = NULL;
179261ecd0c6SBarry Smith     a->j = NULL;
179361ecd0c6SBarry Smith     a->i = NULL;
179461ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
179561ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
179661ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1797447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
179861ecd0c6SBarry Smith     }
179961ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr);
180061ecd0c6SBarry Smith 
180161ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
180261ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
180361ecd0c6SBarry Smith       ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr);
1804447d62f5SStefano Zampini       if (i < A->cmap->n) {
180561ecd0c6SBarry Smith         ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr);
180661ecd0c6SBarry Smith       }
1807447d62f5SStefano Zampini     }
180861ecd0c6SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
180961ecd0c6SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
181061ecd0c6SBarry Smith     if (singlemalloc) {
181161ecd0c6SBarry Smith       ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr);
181261ecd0c6SBarry Smith     } else {
181361ecd0c6SBarry Smith       if (free_a)  {ierr = PetscFree(olda);CHKERRQ(ierr);}
181461ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);}
181561ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);}
181661ecd0c6SBarry Smith     }
181761ecd0c6SBarry Smith   }
181861ecd0c6SBarry Smith   ierr = PetscFree(mdiag);CHKERRQ(ierr);
181961ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
182061ecd0c6SBarry Smith   PetscFunctionReturn(0);
182161ecd0c6SBarry Smith }
182261ecd0c6SBarry Smith 
1823be5855fcSBarry Smith /*
1824be5855fcSBarry Smith      Checks for missing diagonals
1825be5855fcSBarry Smith */
1826ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1827be5855fcSBarry Smith {
1828be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
18297734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1830994fe344SLisandro Dalcin   PetscErrorCode ierr;
1831be5855fcSBarry Smith 
1832be5855fcSBarry Smith   PetscFunctionBegin;
183309f38230SBarry Smith   *missing = PETSC_FALSE;
18347734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
183509f38230SBarry Smith     *missing = PETSC_TRUE;
183609f38230SBarry Smith     if (d) *d = 0;
1837994fe344SLisandro Dalcin     ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr);
183809f38230SBarry Smith   } else {
183901445905SHong Zhang     PetscInt n;
184001445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1841f1e2ffcdSBarry Smith     diag = a->diag;
184201445905SHong Zhang     for (i=0; i<n; i++) {
18437734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
184409f38230SBarry Smith         *missing = PETSC_TRUE;
184509f38230SBarry Smith         if (d) *d = i;
1846994fe344SLisandro Dalcin         ierr = PetscInfo1(A,"Matrix is missing diagonal number %D\n",i);CHKERRQ(ierr);
1847358d2f5dSShri Abhyankar         break;
184809f38230SBarry Smith       }
1849be5855fcSBarry Smith     }
1850be5855fcSBarry Smith   }
1851be5855fcSBarry Smith   PetscFunctionReturn(0);
1852be5855fcSBarry Smith }
1853be5855fcSBarry Smith 
18540da83c2eSBarry Smith #include <petscblaslapack.h>
18550da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
18560da83c2eSBarry Smith 
18570da83c2eSBarry Smith /*
18580da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
18590da83c2eSBarry Smith */
18600da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
18610da83c2eSBarry Smith {
18620da83c2eSBarry Smith   PetscErrorCode  ierr;
18630da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
18640da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
18650da83c2eSBarry Smith   const PetscReal shift = 0.0;
18660da83c2eSBarry Smith   PetscInt        ipvt[5];
18670da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
18680da83c2eSBarry Smith 
18690da83c2eSBarry Smith   PetscFunctionBegin;
18700da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
18710da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
18720da83c2eSBarry Smith   if (ncnt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %D doesn't match number matrix rows %D",ncnt,n);
18730da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18740da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
18750da83c2eSBarry Smith   }
18760da83c2eSBarry Smith   ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr);
18770da83c2eSBarry Smith   if (bsizemax > 7) {
18780da83c2eSBarry Smith     ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr);
18790da83c2eSBarry Smith   }
18800da83c2eSBarry Smith   ncnt = 0;
18810da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18820da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
18830da83c2eSBarry Smith     ierr    = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr);
18840da83c2eSBarry Smith     switch (bsizes[i]) {
18850da83c2eSBarry Smith     case 1:
18860da83c2eSBarry Smith       *diag = 1.0/(*diag);
18870da83c2eSBarry Smith       break;
18880da83c2eSBarry Smith     case 2:
18890da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18900da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18910da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
18920da83c2eSBarry Smith       break;
18930da83c2eSBarry Smith     case 3:
18940da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18950da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18960da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
18970da83c2eSBarry Smith       break;
18980da83c2eSBarry Smith     case 4:
18990da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19000da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19010da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
19020da83c2eSBarry Smith       break;
19030da83c2eSBarry Smith     case 5:
19040da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19050da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19060da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
19070da83c2eSBarry Smith       break;
19080da83c2eSBarry Smith     case 6:
19090da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19100da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19110da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
19120da83c2eSBarry Smith       break;
19130da83c2eSBarry Smith     case 7:
19140da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19150da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19160da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
19170da83c2eSBarry Smith       break;
19180da83c2eSBarry Smith     default:
19190da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19200da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19210da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr);
19220da83c2eSBarry Smith     }
19230da83c2eSBarry Smith     ncnt   += bsizes[i];
19240da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
19250da83c2eSBarry Smith   }
19260da83c2eSBarry Smith   if (bsizemax > 7) {
19270da83c2eSBarry Smith     ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr);
19280da83c2eSBarry Smith   }
19290da83c2eSBarry Smith   ierr = PetscFree(indx);CHKERRQ(ierr);
19300da83c2eSBarry Smith   PetscFunctionReturn(0);
19310da83c2eSBarry Smith }
19320da83c2eSBarry Smith 
1933422a814eSBarry Smith /*
1934422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1935422a814eSBarry Smith */
19367087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
193771f1c65dSBarry Smith {
193871f1c65dSBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
193971f1c65dSBarry Smith   PetscErrorCode  ierr;
1940d0f46423SBarry Smith   PetscInt        i,*diag,m = A->rmap->n;
19412e5835c6SStefano Zampini   const MatScalar *v;
194254f21887SBarry Smith   PetscScalar     *idiag,*mdiag;
194371f1c65dSBarry Smith 
194471f1c65dSBarry Smith   PetscFunctionBegin;
194571f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
194671f1c65dSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
194771f1c65dSBarry Smith   diag = a->diag;
194871f1c65dSBarry Smith   if (!a->idiag) {
1949dcca6d9dSJed Brown     ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr);
19503bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,3*m*sizeof(PetscScalar));CHKERRQ(ierr);
195171f1c65dSBarry Smith   }
19522e5835c6SStefano Zampini 
195371f1c65dSBarry Smith   mdiag = a->mdiag;
195471f1c65dSBarry Smith   idiag = a->idiag;
19552e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
1956422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
195771f1c65dSBarry Smith     for (i=0; i<m; i++) {
195871f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1959899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1960899639b0SHong Zhang         if (PetscRealPart(fshift)) {
1961899639b0SHong Zhang           ierr = PetscInfo1(A,"Zero diagonal on row %D\n",i);CHKERRQ(ierr);
19627b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19637b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
19647b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
1965a6fa060aSHong Zhang         } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1966899639b0SHong Zhang       }
196771f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
196871f1c65dSBarry Smith     }
196971f1c65dSBarry Smith     ierr = PetscLogFlops(m);CHKERRQ(ierr);
197071f1c65dSBarry Smith   } else {
197171f1c65dSBarry Smith     for (i=0; i<m; i++) {
197271f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
197371f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
197471f1c65dSBarry Smith     }
1975dc0b31edSSatish Balay     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
197671f1c65dSBarry Smith   }
197771f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
19782e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
197971f1c65dSBarry Smith   PetscFunctionReturn(0);
198071f1c65dSBarry Smith }
198171f1c65dSBarry Smith 
1982c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
198341f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
198417ab2063SBarry Smith {
1985416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1986e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
19872e5835c6SStefano Zampini   const MatScalar   *v,*idiag=NULL,*mdiag,*aa;
198854f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
1989dfbe8321SBarry Smith   PetscErrorCode    ierr;
19903d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
199197f1f81fSBarry Smith   const PetscInt    *idx,*diag;
199217ab2063SBarry Smith 
19933a40ed3dSBarry Smith   PetscFunctionBegin;
1994b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) {
1995b215bc84SStefano Zampini     ierr = MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx);CHKERRQ(ierr);
1996b215bc84SStefano Zampini     PetscFunctionReturn(0);
1997b215bc84SStefano Zampini   }
1998b965ef7fSBarry Smith   its = its*lits;
199991723122SBarry Smith 
200071f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
200171f1c65dSBarry Smith   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
200271f1c65dSBarry Smith   a->fshift = fshift;
200371f1c65dSBarry Smith   a->omega  = omega;
2004ed480e8bSBarry Smith 
200571f1c65dSBarry Smith   diag  = a->diag;
200671f1c65dSBarry Smith   t     = a->ssor_work;
2007ed480e8bSBarry Smith   idiag = a->idiag;
200871f1c65dSBarry Smith   mdiag = a->mdiag;
2009ed480e8bSBarry Smith 
20102e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
20111ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
20123649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
2013ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
201417ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
201517ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
2016ed480e8bSBarry Smith     bs = b;
201717ab2063SBarry Smith     for (i=0; i<m; i++) {
201871f1c65dSBarry Smith       d   = fshift + mdiag[i];
2019416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2020ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20212e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
202217ab2063SBarry Smith       sum = b[i]*d/omega;
2023003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
202417ab2063SBarry Smith       x[i] = sum;
202517ab2063SBarry Smith     }
20261ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20273649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20282e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
2029efee365bSSatish Balay     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20303a40ed3dSBarry Smith     PetscFunctionReturn(0);
203117ab2063SBarry Smith   }
2032c783ea89SBarry Smith 
20332205254eSKarl Rupp   if (flag == SOR_APPLY_LOWER) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
20342205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
20354c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
2036887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
203717ab2063SBarry Smith 
203817ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
203917ab2063SBarry Smith 
2040887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
204117ab2063SBarry Smith     */
204217ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
204317ab2063SBarry Smith 
204417ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
204517ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
2046416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2047ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20482e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
204917ab2063SBarry Smith       sum = b[i];
2050e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
2051ed480e8bSBarry Smith       x[i] = sum*idiag[i];
205217ab2063SBarry Smith     }
205317ab2063SBarry Smith 
205417ab2063SBarry Smith     /*  t = b - (2*E - D)x */
20552e5835c6SStefano Zampini     v = aa;
20562205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
205717ab2063SBarry Smith 
205817ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
2059ed480e8bSBarry Smith     ts   = t;
2060416022c9SBarry Smith     diag = a->diag;
206117ab2063SBarry Smith     for (i=0; i<m; i++) {
2062416022c9SBarry Smith       n   = diag[i] - a->i[i];
2063ed480e8bSBarry Smith       idx = a->j + a->i[i];
20642e5835c6SStefano Zampini       v   = aa + a->i[i];
206517ab2063SBarry Smith       sum = t[i];
2066003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
2067ed480e8bSBarry Smith       t[i] = sum*idiag[i];
2068733d66baSBarry Smith       /*  x = x + t */
2069733d66baSBarry Smith       x[i] += t[i];
207017ab2063SBarry Smith     }
207117ab2063SBarry Smith 
2072dc0b31edSSatish Balay     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
20731ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20743649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20753a40ed3dSBarry Smith     PetscFunctionReturn(0);
207617ab2063SBarry Smith   }
207717ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
207817ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
207917ab2063SBarry Smith       for (i=0; i<m; i++) {
2080416022c9SBarry Smith         n   = diag[i] - a->i[i];
2081ed480e8bSBarry Smith         idx = a->j + a->i[i];
20822e5835c6SStefano Zampini         v   = aa + a->i[i];
208317ab2063SBarry Smith         sum = b[i];
2084e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20855c99c7daSBarry Smith         t[i] = sum;
2086ed480e8bSBarry Smith         x[i] = sum*idiag[i];
208717ab2063SBarry Smith       }
20885c99c7daSBarry Smith       xb   = t;
2089efee365bSSatish Balay       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20903a40ed3dSBarry Smith     } else xb = b;
209117ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
209217ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2093416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
2094ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
20952e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
209617ab2063SBarry Smith         sum = xb[i];
2097e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20985c99c7daSBarry Smith         if (xb == b) {
2099ed480e8bSBarry Smith           x[i] = sum*idiag[i];
21005c99c7daSBarry Smith         } else {
2101b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
210217ab2063SBarry Smith         }
21035c99c7daSBarry Smith       }
2104b19a5dc2SMark Adams       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
210517ab2063SBarry Smith     }
210617ab2063SBarry Smith     its--;
210717ab2063SBarry Smith   }
210817ab2063SBarry Smith   while (its--) {
210917ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
211017ab2063SBarry Smith       for (i=0; i<m; i++) {
2111b19a5dc2SMark Adams         /* lower */
2112b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
2113ed480e8bSBarry Smith         idx = a->j + a->i[i];
21142e5835c6SStefano Zampini         v   = aa + a->i[i];
211517ab2063SBarry Smith         sum = b[i];
2116e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2117b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
2118b19a5dc2SMark Adams         /* upper */
2119b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
2120b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
21212e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
2122b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2123b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
212417ab2063SBarry Smith       }
2125b19a5dc2SMark Adams       xb   = t;
21269f863219SBarry Smith       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2127b19a5dc2SMark Adams     } else xb = b;
212817ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
212917ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2130b19a5dc2SMark Adams         sum = xb[i];
2131b19a5dc2SMark Adams         if (xb == b) {
2132b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
2133416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
2134ed480e8bSBarry Smith           idx = a->j + a->i[i];
21352e5835c6SStefano Zampini           v   = aa + a->i[i];
2136e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2137ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
2138b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
2139b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
2140b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
21412e5835c6SStefano Zampini           v   = aa + diag[i] + 1;
2142b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2143b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
214417ab2063SBarry Smith         }
2145b19a5dc2SMark Adams       }
2146b19a5dc2SMark Adams       if (xb == b) {
21479f863219SBarry Smith         ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2148b19a5dc2SMark Adams       } else {
2149b19a5dc2SMark Adams         ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
2150b19a5dc2SMark Adams       }
215117ab2063SBarry Smith     }
215217ab2063SBarry Smith   }
21532e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
21541ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
21553649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
2156365a8a9eSBarry Smith   PetscFunctionReturn(0);
215717ab2063SBarry Smith }
215817ab2063SBarry Smith 
2159dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
216017ab2063SBarry Smith {
2161416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
21624e220ebcSLois Curfman McInnes 
21633a40ed3dSBarry Smith   PetscFunctionBegin;
21644e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
21653966268fSBarry Smith   info->nz_allocated = a->maxnz;
21663966268fSBarry Smith   info->nz_used      = a->nz;
21673966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
21683966268fSBarry Smith   info->assemblies   = A->num_ass;
21693966268fSBarry Smith   info->mallocs      = A->info.mallocs;
21707adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
2171d5f3da31SBarry Smith   if (A->factortype) {
21724e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
21734e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
21744e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
21754e220ebcSLois Curfman McInnes   } else {
21764e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
21774e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
21784e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
21794e220ebcSLois Curfman McInnes   }
21803a40ed3dSBarry Smith   PetscFunctionReturn(0);
218117ab2063SBarry Smith }
218217ab2063SBarry Smith 
21832b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
218417ab2063SBarry Smith {
2185416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2186c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
21876849ba73SBarry Smith   PetscErrorCode    ierr;
218897b48c8fSBarry Smith   const PetscScalar *xx;
21892e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
2190c7da8527SEric Chamberland   PetscInt          d = 0;
219117ab2063SBarry Smith 
21923a40ed3dSBarry Smith   PetscFunctionBegin;
219397b48c8fSBarry Smith   if (x && b) {
219497b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
219597b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
219697b48c8fSBarry Smith     for (i=0; i<N; i++) {
219797b48c8fSBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2198447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
219997b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
220097b48c8fSBarry Smith     }
220197b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
220297b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
220397b48c8fSBarry Smith   }
220497b48c8fSBarry Smith 
22052e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
2206a9817697SBarry Smith   if (a->keepnonzeropattern) {
2207f1e2ffcdSBarry Smith     for (i=0; i<N; i++) {
2208e32f2f54SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
22092e5835c6SStefano Zampini       ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
2210f1e2ffcdSBarry Smith     }
2211f4df32b1SMatthew Knepley     if (diag != 0.0) {
2212c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2213c7da8527SEric Chamberland         d = rows[i];
2214447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2215c7da8527SEric Chamberland         if (a->diag[d] >= a->i[d+1]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in the zeroed row %D",d);
2216c7da8527SEric Chamberland       }
2217f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2218447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
22192e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
2220f1e2ffcdSBarry Smith       }
2221f1e2ffcdSBarry Smith     }
2222f1e2ffcdSBarry Smith   } else {
2223f4df32b1SMatthew Knepley     if (diag != 0.0) {
222417ab2063SBarry Smith       for (i=0; i<N; i++) {
2225e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
22267ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2227447d62f5SStefano Zampini           if (rows[i] >= A->cmap->n) {
2228447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2229447d62f5SStefano Zampini           } else {
2230416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
22312e5835c6SStefano Zampini             aa[a->i[rows[i]]]   = diag;
2232bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2233447d62f5SStefano Zampini           }
2234447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
2235f4df32b1SMatthew Knepley           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
223617ab2063SBarry Smith         }
223717ab2063SBarry Smith       }
22383a40ed3dSBarry Smith     } else {
223917ab2063SBarry Smith       for (i=0; i<N; i++) {
2240e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2241416022c9SBarry Smith         a->ilen[rows[i]] = 0;
224217ab2063SBarry Smith       }
224317ab2063SBarry Smith     }
2244e56f5c9eSBarry Smith     A->nonzerostate++;
2245f1e2ffcdSBarry Smith   }
22462e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
22478c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2248c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2249e2cf4d64SStefano Zampini #endif
22504099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22513a40ed3dSBarry Smith   PetscFunctionReturn(0);
225217ab2063SBarry Smith }
225317ab2063SBarry Smith 
22546e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
22556e169961SBarry Smith {
22566e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
22576e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
22586e169961SBarry Smith   PetscErrorCode    ierr;
22592b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
22606e169961SBarry Smith   const PetscScalar *xx;
22612e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
22626e169961SBarry Smith 
22636e169961SBarry Smith   PetscFunctionBegin;
22642e5835c6SStefano Zampini   if (!N) PetscFunctionReturn(0);
22652e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
22666e169961SBarry Smith   if (x && b) {
22676e169961SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
22686e169961SBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
22692b40b63fSBarry Smith     vecs = PETSC_TRUE;
22706e169961SBarry Smith   }
22711795a4d1SJed Brown   ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr);
22726e169961SBarry Smith   for (i=0; i<N; i++) {
22736e169961SBarry Smith     if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
22742e5835c6SStefano Zampini     ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
22752205254eSKarl Rupp 
22766e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
22776e169961SBarry Smith   }
22786e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
22796e169961SBarry Smith     if (!zeroed[i]) {
22806e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
22814cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
22822e5835c6SStefano Zampini           if (vecs) bb[i] -= aa[j]*xx[a->j[j]];
22832e5835c6SStefano Zampini           aa[j] = 0.0;
22846e169961SBarry Smith         }
22856e169961SBarry Smith       }
22864cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
22876e169961SBarry Smith   }
22886e169961SBarry Smith   if (x && b) {
22896e169961SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
22906e169961SBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
22916e169961SBarry Smith   }
22926e169961SBarry Smith   ierr = PetscFree(zeroed);CHKERRQ(ierr);
22936e169961SBarry Smith   if (diag != 0.0) {
22946e169961SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
22951d5a398dSstefano_zampini     if (missing) {
22961d5a398dSstefano_zampini       for (i=0; i<N; i++) {
22974cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
22984cf107fdSStefano Zampini         if (a->nonew && rows[i] >= d) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D (%D)",d,rows[i]);
22991d5a398dSstefano_zampini         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
23001d5a398dSstefano_zampini       }
23011d5a398dSstefano_zampini     } else {
23026e169961SBarry Smith       for (i=0; i<N; i++) {
23032e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
23046e169961SBarry Smith       }
23056e169961SBarry Smith     }
23061d5a398dSstefano_zampini   }
23072e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
23088c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2309c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2310e2cf4d64SStefano Zampini #endif
23114099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
23126e169961SBarry Smith   PetscFunctionReturn(0);
23136e169961SBarry Smith }
23146e169961SBarry Smith 
2315a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
231617ab2063SBarry Smith {
2317416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
23182e5835c6SStefano Zampini   const PetscScalar *aa = a->a;
231997f1f81fSBarry Smith   PetscInt          *itmp;
23202e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
23212e5835c6SStefano Zampini   PetscErrorCode    ierr;
23222e5835c6SStefano Zampini   PetscBool         rest = PETSC_FALSE;
23232e5835c6SStefano Zampini #endif
232417ab2063SBarry Smith 
23253a40ed3dSBarry Smith   PetscFunctionBegin;
23262e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
23272e5835c6SStefano Zampini   if (v && A->offloadmask == PETSC_OFFLOAD_GPU) {
23282e5835c6SStefano Zampini     /* triggers copy to CPU */
23292e5835c6SStefano Zampini     rest = PETSC_TRUE;
23302e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
23312e5835c6SStefano Zampini   } else aa = a->a;
23322e5835c6SStefano Zampini #endif
2333416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
23342e5835c6SStefano Zampini   if (v) *v = (PetscScalar*)(aa + a->i[row]);
233517ab2063SBarry Smith   if (idx) {
2336bfeeae90SHong Zhang     itmp = a->j + a->i[row];
233726fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
2338f4259b30SLisandro Dalcin     else *idx = NULL;
233917ab2063SBarry Smith   }
23402e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
23412e5835c6SStefano Zampini   if (rest) {
23422e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
23432e5835c6SStefano Zampini   }
23442e5835c6SStefano Zampini #endif
23453a40ed3dSBarry Smith   PetscFunctionReturn(0);
234617ab2063SBarry Smith }
234717ab2063SBarry Smith 
2348a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
234917ab2063SBarry Smith {
23503a40ed3dSBarry Smith   PetscFunctionBegin;
2351cb4a9cd9SHong Zhang   if (nz)  *nz = 0;
23522e5835c6SStefano Zampini   if (idx) *idx = NULL;
23532e5835c6SStefano Zampini   if (v)   *v = NULL;
23543a40ed3dSBarry Smith   PetscFunctionReturn(0);
235517ab2063SBarry Smith }
235617ab2063SBarry Smith 
2357dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
235817ab2063SBarry Smith {
2359416022c9SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
23602e5835c6SStefano Zampini   const MatScalar *v;
236136db0b34SBarry Smith   PetscReal       sum = 0.0;
23626849ba73SBarry Smith   PetscErrorCode  ierr;
236397f1f81fSBarry Smith   PetscInt        i,j;
236417ab2063SBarry Smith 
23653a40ed3dSBarry Smith   PetscFunctionBegin;
23662e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
236717ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2368570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2369570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
237073cf7048SBarry Smith     PetscStackCallBLAS("BLASnrm2",*nrm = BLASnrm2_(&nz,v,&one));
2371570b7f6dSBarry Smith #else
2372416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
237336db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
237417ab2063SBarry Smith     }
23758f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2376570b7f6dSBarry Smith #endif
2377ca0c957dSBarry Smith     ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
23783a40ed3dSBarry Smith   } else if (type == NORM_1) {
237936db0b34SBarry Smith     PetscReal *tmp;
238097f1f81fSBarry Smith     PetscInt  *jj = a->j;
23811795a4d1SJed Brown     ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr);
2382064f8208SBarry Smith     *nrm = 0.0;
2383416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2384bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
238517ab2063SBarry Smith     }
2386d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2387064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
238817ab2063SBarry Smith     }
2389606d414cSSatish Balay     ierr = PetscFree(tmp);CHKERRQ(ierr);
239051f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
23913a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2392064f8208SBarry Smith     *nrm = 0.0;
2393d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
23942e5835c6SStefano Zampini       const PetscScalar *v2 = v + a->i[j];
239517ab2063SBarry Smith       sum = 0.0;
2396416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
23972e5835c6SStefano Zampini         sum += PetscAbsScalar(*v2); v2++;
239817ab2063SBarry Smith       }
2399064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
240017ab2063SBarry Smith     }
240151f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
2402f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
24032e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
24043a40ed3dSBarry Smith   PetscFunctionReturn(0);
240517ab2063SBarry Smith }
240617ab2063SBarry Smith 
24074e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
24084e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
24094e938277SHong Zhang {
24104e938277SHong Zhang   PetscErrorCode ierr;
24114e938277SHong Zhang   PetscInt       i,j,anzj;
24124e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
24134e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
24144e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
24154e938277SHong Zhang 
24164e938277SHong Zhang   PetscFunctionBegin;
24174e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
2418854ce69bSBarry Smith   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
2419785e854fSJed Brown   ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
2420785e854fSJed Brown   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
24214e938277SHong Zhang 
24224e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
24234e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
242426fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
24254e938277SHong Zhang   /* Form ati for csr format of A^T. */
242626fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
24274e938277SHong Zhang 
24284e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
2429580bdb30SBarry Smith   ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr);
24304e938277SHong Zhang 
24314e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
24324e938277SHong Zhang   for (i=0;i<am;i++) {
24334e938277SHong Zhang     anzj = ai[i+1] - ai[i];
24344e938277SHong Zhang     for (j=0;j<anzj;j++) {
24354e938277SHong Zhang       atj[atfill[*aj]] = i;
24364e938277SHong Zhang       atfill[*aj++]   += 1;
24374e938277SHong Zhang     }
24384e938277SHong Zhang   }
24394e938277SHong Zhang 
24404e938277SHong Zhang   /* Clean up temporary space and complete requests. */
24414e938277SHong Zhang   ierr = PetscFree(atfill);CHKERRQ(ierr);
2442ce94432eSBarry Smith   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr);
244333d57670SJed Brown   ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
2444b5bb3eecSMark Adams   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2445a2f3521dSMark F. Adams 
24464e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
24474e938277SHong Zhang   b->free_a  = PETSC_FALSE;
24484e938277SHong Zhang   b->free_ij = PETSC_TRUE;
24494e938277SHong Zhang   b->nonew   = 0;
24504e938277SHong Zhang   PetscFunctionReturn(0);
24514e938277SHong Zhang }
24524e938277SHong Zhang 
24537087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2454cd0d46ebSvictorle {
24553d3eaba7SBarry Smith   Mat_SeqAIJ      *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
245654f21887SBarry Smith   PetscInt        *adx,*bdx,*aii,*bii,*aptr,*bptr;
24572e5835c6SStefano Zampini   const MatScalar *va,*vb;
24586849ba73SBarry Smith   PetscErrorCode  ierr;
245997f1f81fSBarry Smith   PetscInt        ma,na,mb,nb, i;
2460cd0d46ebSvictorle 
2461cd0d46ebSvictorle   PetscFunctionBegin;
2462cd0d46ebSvictorle   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
2463cd0d46ebSvictorle   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24645485867bSBarry Smith   if (ma!=nb || na!=mb) {
24655485867bSBarry Smith     *f = PETSC_FALSE;
24665485867bSBarry Smith     PetscFunctionReturn(0);
24675485867bSBarry Smith   }
24682e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&va);CHKERRQ(ierr);
24692e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(B,&vb);CHKERRQ(ierr);
2470cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2471cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
2472785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2473785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
2474cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2475cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2476cd0d46ebSvictorle 
2477cd0d46ebSvictorle   *f = PETSC_TRUE;
2478cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2479cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
248097f1f81fSBarry Smith       PetscInt    idc,idr;
24815485867bSBarry Smith       PetscScalar vc,vr;
2482cd0d46ebSvictorle       /* column/row index/value */
24835485867bSBarry Smith       idc = adx[aptr[i]];
24845485867bSBarry Smith       idr = bdx[bptr[idc]];
24855485867bSBarry Smith       vc  = va[aptr[i]];
24865485867bSBarry Smith       vr  = vb[bptr[idc]];
24875485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
24885485867bSBarry Smith         *f = PETSC_FALSE;
24895485867bSBarry Smith         goto done;
2490cd0d46ebSvictorle       } else {
24915485867bSBarry Smith         aptr[i]++;
24925485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2493cd0d46ebSvictorle       }
2494cd0d46ebSvictorle     }
2495cd0d46ebSvictorle   }
2496cd0d46ebSvictorle done:
2497cd0d46ebSvictorle   ierr = PetscFree(aptr);CHKERRQ(ierr);
24983aeef889SHong Zhang   ierr = PetscFree(bptr);CHKERRQ(ierr);
24992e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&va);CHKERRQ(ierr);
25002e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(B,&vb);CHKERRQ(ierr);
2501cd0d46ebSvictorle   PetscFunctionReturn(0);
2502cd0d46ebSvictorle }
2503cd0d46ebSvictorle 
25047087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
25051cbb95d3SBarry Smith {
25063d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
250754f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
250854f21887SBarry Smith   MatScalar      *va,*vb;
25091cbb95d3SBarry Smith   PetscErrorCode ierr;
25101cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
25111cbb95d3SBarry Smith 
25121cbb95d3SBarry Smith   PetscFunctionBegin;
25131cbb95d3SBarry Smith   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
25141cbb95d3SBarry Smith   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
25151cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
25161cbb95d3SBarry Smith     *f = PETSC_FALSE;
25171cbb95d3SBarry Smith     PetscFunctionReturn(0);
25181cbb95d3SBarry Smith   }
25191cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
25201cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
25211cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
2522785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2523785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
25241cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
25251cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
25261cbb95d3SBarry Smith 
25271cbb95d3SBarry Smith   *f = PETSC_TRUE;
25281cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
25291cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
25301cbb95d3SBarry Smith       PetscInt    idc,idr;
25311cbb95d3SBarry Smith       PetscScalar vc,vr;
25321cbb95d3SBarry Smith       /* column/row index/value */
25331cbb95d3SBarry Smith       idc = adx[aptr[i]];
25341cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
25351cbb95d3SBarry Smith       vc  = va[aptr[i]];
25361cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
25371cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
25381cbb95d3SBarry Smith         *f = PETSC_FALSE;
25391cbb95d3SBarry Smith         goto done;
25401cbb95d3SBarry Smith       } else {
25411cbb95d3SBarry Smith         aptr[i]++;
25421cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
25431cbb95d3SBarry Smith       }
25441cbb95d3SBarry Smith     }
25451cbb95d3SBarry Smith   }
25461cbb95d3SBarry Smith done:
25471cbb95d3SBarry Smith   ierr = PetscFree(aptr);CHKERRQ(ierr);
25481cbb95d3SBarry Smith   ierr = PetscFree(bptr);CHKERRQ(ierr);
25491cbb95d3SBarry Smith   PetscFunctionReturn(0);
25501cbb95d3SBarry Smith }
25511cbb95d3SBarry Smith 
2552ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25539e29f15eSvictorle {
2554dfbe8321SBarry Smith   PetscErrorCode ierr;
25556e111a19SKarl Rupp 
25569e29f15eSvictorle   PetscFunctionBegin;
25575485867bSBarry Smith   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25589e29f15eSvictorle   PetscFunctionReturn(0);
25599e29f15eSvictorle }
25609e29f15eSvictorle 
2561ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25621cbb95d3SBarry Smith {
25631cbb95d3SBarry Smith   PetscErrorCode ierr;
25646e111a19SKarl Rupp 
25651cbb95d3SBarry Smith   PetscFunctionBegin;
25661cbb95d3SBarry Smith   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25671cbb95d3SBarry Smith   PetscFunctionReturn(0);
25681cbb95d3SBarry Smith }
25691cbb95d3SBarry Smith 
2570dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
257117ab2063SBarry Smith {
2572416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2573fff8e43fSBarry Smith   const PetscScalar *l,*r;
2574fff8e43fSBarry Smith   PetscScalar       x;
257554f21887SBarry Smith   MatScalar         *v;
2576dfbe8321SBarry Smith   PetscErrorCode    ierr;
2577fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2578fff8e43fSBarry Smith   const PetscInt    *jj;
257917ab2063SBarry Smith 
25803a40ed3dSBarry Smith   PetscFunctionBegin;
258117ab2063SBarry Smith   if (ll) {
25823ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
25833ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
2584e1311b90SBarry Smith     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
2585e32f2f54SBarry Smith     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
2586fff8e43fSBarry Smith     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
25872e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr);
258817ab2063SBarry Smith     for (i=0; i<m; i++) {
258917ab2063SBarry Smith       x = l[i];
2590416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
25912205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
259217ab2063SBarry Smith     }
2593fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
2594efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
25952e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr);
259617ab2063SBarry Smith   }
259717ab2063SBarry Smith   if (rr) {
2598e1311b90SBarry Smith     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
2599e32f2f54SBarry Smith     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
2600fff8e43fSBarry Smith     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
26012e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr);
26022e5835c6SStefano Zampini     jj = a->j;
26032205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
26042e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr);
2605fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
2606efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
260717ab2063SBarry Smith   }
2608acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
26098c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2610c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2611e2cf4d64SStefano Zampini #endif
26123a40ed3dSBarry Smith   PetscFunctionReturn(0);
261317ab2063SBarry Smith }
261417ab2063SBarry Smith 
26157dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
261617ab2063SBarry Smith {
2617db02288aSLois Curfman McInnes   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*c;
26186849ba73SBarry Smith   PetscErrorCode    ierr;
2619d0f46423SBarry Smith   PetscInt          *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
262097f1f81fSBarry Smith   PetscInt          row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
26215d0c19d7SBarry Smith   const PetscInt    *irow,*icol;
26222e5835c6SStefano Zampini   const PetscScalar *aa;
26235d0c19d7SBarry Smith   PetscInt          nrows,ncols;
262497f1f81fSBarry Smith   PetscInt          *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
262554f21887SBarry Smith   MatScalar         *a_new,*mat_a;
2626416022c9SBarry Smith   Mat               C;
2627cdc6f3adSToby Isaac   PetscBool         stride;
262817ab2063SBarry Smith 
26293a40ed3dSBarry Smith   PetscFunctionBegin;
263017ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2631b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
2632b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
263317ab2063SBarry Smith 
2634251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
2635ff718158SBarry Smith   if (stride) {
2636ff718158SBarry Smith     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
2637ff718158SBarry Smith   } else {
2638ff718158SBarry Smith     first = 0;
2639ff718158SBarry Smith     step  = 0;
2640ff718158SBarry Smith   }
2641fee21e36SBarry Smith   if (stride && step == 1) {
264202834360SBarry Smith     /* special case of contiguous rows */
2643dcca6d9dSJed Brown     ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr);
264402834360SBarry Smith     /* loop over new rows determining lens and starting points */
264502834360SBarry Smith     for (i=0; i<nrows; i++) {
2646bfeeae90SHong Zhang       kstart = ai[irow[i]];
2647a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2648a91a9bebSLisandro Dalcin       starts[i] = kstart;
264902834360SBarry Smith       for (k=kstart; k<kend; k++) {
2650bfeeae90SHong Zhang         if (aj[k] >= first) {
265102834360SBarry Smith           starts[i] = k;
265202834360SBarry Smith           break;
265302834360SBarry Smith         }
265402834360SBarry Smith       }
2655a2744918SBarry Smith       sum = 0;
265602834360SBarry Smith       while (k < kend) {
2657bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2658a2744918SBarry Smith         sum++;
265902834360SBarry Smith       }
2660a2744918SBarry Smith       lens[i] = sum;
266102834360SBarry Smith     }
266202834360SBarry Smith     /* create submatrix */
2663cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
266497f1f81fSBarry Smith       PetscInt n_cols,n_rows;
266508480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
2666e32f2f54SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2667d8ced48eSBarry Smith       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
266808480c60SBarry Smith       C    = *B;
26693a40ed3dSBarry Smith     } else {
26703bef6203SJed Brown       PetscInt rbs,cbs;
2671ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2672f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
26733bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
26743bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
26753bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
26767adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2677ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
267808480c60SBarry Smith     }
2679db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2680db02288aSLois Curfman McInnes 
268102834360SBarry Smith     /* loop over rows inserting into submatrix */
2682db02288aSLois Curfman McInnes     a_new = c->a;
2683db02288aSLois Curfman McInnes     j_new = c->j;
2684db02288aSLois Curfman McInnes     i_new = c->i;
26852e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
268602834360SBarry Smith     for (i=0; i<nrows; i++) {
2687a2744918SBarry Smith       ii    = starts[i];
2688a2744918SBarry Smith       lensi = lens[i];
2689a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2690a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
269102834360SBarry Smith       }
26922e5835c6SStefano Zampini       ierr       = PetscArraycpy(a_new,aa + starts[i],lensi);CHKERRQ(ierr);
2693a2744918SBarry Smith       a_new     += lensi;
2694a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2695a2744918SBarry Smith       c->ilen[i] = lensi;
269602834360SBarry Smith     }
26972e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
26980e83c824SBarry Smith     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
26993a40ed3dSBarry Smith   } else {
270002834360SBarry Smith     ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
27011795a4d1SJed Brown     ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr);
2702854ce69bSBarry Smith     ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr);
27034dcab191SBarry Smith     for (i=0; i<ncols; i++) {
2704d9ef940eSSatish Balay       if (PetscUnlikelyDebug(icol[i] >= oldcols)) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Requesting column beyond largest column icol[%D] %D >= A->cmap->n %D",i,icol[i],oldcols);
27054dcab191SBarry Smith       smap[icol[i]] = i+1;
27064dcab191SBarry Smith     }
27074dcab191SBarry Smith 
270802834360SBarry Smith     /* determine lens of each row */
270902834360SBarry Smith     for (i=0; i<nrows; i++) {
2710bfeeae90SHong Zhang       kstart  = ai[irow[i]];
271102834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
271202834360SBarry Smith       lens[i] = 0;
271302834360SBarry Smith       for (k=kstart; k<kend; k++) {
2714bfeeae90SHong Zhang         if (smap[aj[k]]) {
271502834360SBarry Smith           lens[i]++;
271602834360SBarry Smith         }
271702834360SBarry Smith       }
271802834360SBarry Smith     }
271917ab2063SBarry Smith     /* Create and fill new matrix */
2720a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2721ace3abfcSBarry Smith       PetscBool equal;
27220f5bd95cSBarry Smith 
272399141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
2724e32f2f54SBarry Smith       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2725580bdb30SBarry Smith       ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr);
2726f23aa3ddSBarry Smith       if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2727580bdb30SBarry Smith       ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr);
272808480c60SBarry Smith       C    = *B;
27293a40ed3dSBarry Smith     } else {
27303bef6203SJed Brown       PetscInt rbs,cbs;
2731ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2732f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
27333bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
27343bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
27353bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
27367adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2737ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
273808480c60SBarry Smith     }
27392e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
274099141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
274117ab2063SBarry Smith     for (i=0; i<nrows; i++) {
274299141d43SSatish Balay       row      = irow[i];
2743bfeeae90SHong Zhang       kstart   = ai[row];
274499141d43SSatish Balay       kend     = kstart + a->ilen[row];
2745bfeeae90SHong Zhang       mat_i    = c->i[i];
274699141d43SSatish Balay       mat_j    = c->j + mat_i;
274799141d43SSatish Balay       mat_a    = c->a + mat_i;
274899141d43SSatish Balay       mat_ilen = c->ilen + i;
274917ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2750bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2751ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
27522e5835c6SStefano Zampini           *mat_a++ = aa[k];
275399141d43SSatish Balay           (*mat_ilen)++;
275499141d43SSatish Balay 
275517ab2063SBarry Smith         }
275617ab2063SBarry Smith       }
275717ab2063SBarry Smith     }
27582e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
275902834360SBarry Smith     /* Free work space */
276002834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
2761606d414cSSatish Balay     ierr = PetscFree(smap);CHKERRQ(ierr);
2762606d414cSSatish Balay     ierr = PetscFree(lens);CHKERRQ(ierr);
2763cdc6f3adSToby Isaac     /* sort */
2764cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2765cdc6f3adSToby Isaac       PetscInt ilen;
2766cdc6f3adSToby Isaac 
2767cdc6f3adSToby Isaac       mat_i = c->i[i];
2768cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2769cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2770cdc6f3adSToby Isaac       ilen  = c->ilen[i];
2771390e1bf2SBarry Smith       ierr  = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr);
2772cdc6f3adSToby Isaac     }
277302834360SBarry Smith   }
27748c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2775b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(C,A->boundtocpu);CHKERRQ(ierr);
2776305c6ccfSStefano Zampini #endif
27776d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27786d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
277917ab2063SBarry Smith 
278017ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2781416022c9SBarry Smith   *B   = C;
27823a40ed3dSBarry Smith   PetscFunctionReturn(0);
278317ab2063SBarry Smith }
278417ab2063SBarry Smith 
2785fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
278682d44351SHong Zhang {
278782d44351SHong Zhang   PetscErrorCode ierr;
278882d44351SHong Zhang   Mat            B;
278982d44351SHong Zhang 
279082d44351SHong Zhang   PetscFunctionBegin;
2791c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
279282d44351SHong Zhang     ierr    = MatCreate(subComm,&B);CHKERRQ(ierr);
279382d44351SHong Zhang     ierr    = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr);
279433d57670SJed Brown     ierr    = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr);
279582d44351SHong Zhang     ierr    = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
279682d44351SHong Zhang     ierr    = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr);
279782d44351SHong Zhang     *subMat = B;
2798c2d650bdSHong Zhang   } else {
2799c2d650bdSHong Zhang     ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2800c2d650bdSHong Zhang   }
280182d44351SHong Zhang   PetscFunctionReturn(0);
280282d44351SHong Zhang }
280382d44351SHong Zhang 
28049a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2805a871dcd8SBarry Smith {
280663b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2807dfbe8321SBarry Smith   PetscErrorCode ierr;
280863b91edcSBarry Smith   Mat            outA;
2809ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
281063b91edcSBarry Smith 
28113a40ed3dSBarry Smith   PetscFunctionBegin;
2812e32f2f54SBarry Smith   if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
28131df811f5SHong Zhang 
2814b8a78c4aSBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
2815b8a78c4aSBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
2816a871dcd8SBarry Smith 
281763b91edcSBarry Smith   outA             = inA;
2818d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
2819f6224b95SHong Zhang   ierr = PetscFree(inA->solvertype);CHKERRQ(ierr);
2820f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr);
28212205254eSKarl Rupp 
2822c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
28236bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
28242205254eSKarl Rupp 
2825c3122656SLisandro Dalcin   a->row = row;
28262205254eSKarl Rupp 
2827c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
28286bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
28292205254eSKarl Rupp 
2830c3122656SLisandro Dalcin   a->col = col;
283163b91edcSBarry Smith 
283236db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
28336bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
28344c49b128SBarry Smith   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
28353bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr);
2836f0ec6fceSSatish Balay 
283794a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
2838854ce69bSBarry Smith     ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr);
28393bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
284094a9d846SBarry Smith   }
284163b91edcSBarry Smith 
2842f1e2ffcdSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
2843137fb511SHong Zhang   if (row_identity && col_identity) {
2844ad04f41aSHong Zhang     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
2845137fb511SHong Zhang   } else {
2846719d5645SBarry Smith     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
2847137fb511SHong Zhang   }
28483a40ed3dSBarry Smith   PetscFunctionReturn(0);
2849a871dcd8SBarry Smith }
2850a871dcd8SBarry Smith 
2851f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2852f0b747eeSBarry Smith {
2853f0b747eeSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2854dfa0f9e5SStefano Zampini   PetscScalar    *v;
2855efee365bSSatish Balay   PetscErrorCode ierr;
2856c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
28573a40ed3dSBarry Smith 
28583a40ed3dSBarry Smith   PetscFunctionBegin;
2859dfa0f9e5SStefano Zampini   ierr = MatSeqAIJGetArray(inA,&v);CHKERRQ(ierr);
2860c5df96a5SBarry Smith   ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr);
2861dfa0f9e5SStefano Zampini   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&alpha,v,&one));
2862efee365bSSatish Balay   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
2863dfa0f9e5SStefano Zampini   ierr = MatSeqAIJRestoreArray(inA,&v);CHKERRQ(ierr);
2864acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr);
28653a40ed3dSBarry Smith   PetscFunctionReturn(0);
2866f0b747eeSBarry Smith }
2867f0b747eeSBarry Smith 
2868f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
286916b64355SHong Zhang {
287016b64355SHong Zhang   PetscErrorCode ierr;
287116b64355SHong Zhang   PetscInt       i;
287216b64355SHong Zhang 
287316b64355SHong Zhang   PetscFunctionBegin;
287416b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
287516b64355SHong Zhang     ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr);
287616b64355SHong Zhang 
287716b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
287816b64355SHong Zhang       ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr);
287916b64355SHong Zhang     }
288016b64355SHong Zhang     ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr);
288116b64355SHong Zhang 
288216b64355SHong Zhang     if (submatj->rbuf1) {
288316b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr);
288416b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr);
288516b64355SHong Zhang     }
288616b64355SHong Zhang 
288716b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
288816b64355SHong Zhang       ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr);
288916b64355SHong Zhang     }
289016b64355SHong Zhang     ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr);
289116b64355SHong Zhang     ierr = PetscFree(submatj->pa);CHKERRQ(ierr);
289216b64355SHong Zhang   }
289316b64355SHong Zhang 
289416b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
289516b64355SHong Zhang   ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr);
289616b64355SHong Zhang   if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);}
289716b64355SHong Zhang   ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr);
289816b64355SHong Zhang #else
289916b64355SHong Zhang   ierr = PetscFree(submatj->rmap);CHKERRQ(ierr);
290016b64355SHong Zhang #endif
290116b64355SHong Zhang 
290216b64355SHong Zhang   if (!submatj->allcolumns) {
290316b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
290416b64355SHong Zhang     ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr);
290516b64355SHong Zhang #else
290616b64355SHong Zhang     ierr = PetscFree(submatj->cmap);CHKERRQ(ierr);
290716b64355SHong Zhang #endif
290816b64355SHong Zhang   }
290916b64355SHong Zhang   ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr);
291016b64355SHong Zhang 
291116b64355SHong Zhang   ierr = PetscFree(submatj);CHKERRQ(ierr);
291216b64355SHong Zhang   PetscFunctionReturn(0);
291316b64355SHong Zhang }
291416b64355SHong Zhang 
29150fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
291616b64355SHong Zhang {
291716b64355SHong Zhang   PetscErrorCode ierr;
291816b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
29195c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
292016b64355SHong Zhang 
292116b64355SHong Zhang   PetscFunctionBegin;
292234136279SStefano Zampini   ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2923f68bb481SHong Zhang   ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
292416b64355SHong Zhang   PetscFunctionReturn(0);
292516b64355SHong Zhang }
292616b64355SHong Zhang 
29272d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
29282d033e1fSHong Zhang {
29292d033e1fSHong Zhang   PetscErrorCode ierr;
29302d033e1fSHong Zhang   PetscInt       i;
29310fb991dcSHong Zhang   Mat            C;
29320fb991dcSHong Zhang   Mat_SeqAIJ     *c;
29330fb991dcSHong Zhang   Mat_SubSppt    *submatj;
29342d033e1fSHong Zhang 
29352d033e1fSHong Zhang   PetscFunctionBegin;
29362d033e1fSHong Zhang   for (i=0; i<n; i++) {
29370fb991dcSHong Zhang     C       = (*mat)[i];
29380fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
29390fb991dcSHong Zhang     submatj = c->submatis1;
29402d033e1fSHong Zhang     if (submatj) {
2941682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
294234136279SStefano Zampini         ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2943f68bb481SHong Zhang         ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
294434136279SStefano Zampini         ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr);
29452d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr);
29462d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr);
29472d033e1fSHong Zhang         ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
2948682e4c99SStefano Zampini       }
29492d033e1fSHong Zhang     } else {
29502d033e1fSHong Zhang       ierr = MatDestroy(&C);CHKERRQ(ierr);
29512d033e1fSHong Zhang     }
29522d033e1fSHong Zhang   }
295386e85357SHong Zhang 
295463a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
295563a75b2aSHong Zhang   ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr);
295663a75b2aSHong Zhang 
29572d033e1fSHong Zhang   ierr = PetscFree(*mat);CHKERRQ(ierr);
29582d033e1fSHong Zhang   PetscFunctionReturn(0);
29592d033e1fSHong Zhang }
29602d033e1fSHong Zhang 
29617dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2962cddf8d76SBarry Smith {
2963dfbe8321SBarry Smith   PetscErrorCode ierr;
296497f1f81fSBarry Smith   PetscInt       i;
2965cddf8d76SBarry Smith 
29663a40ed3dSBarry Smith   PetscFunctionBegin;
2967cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
2968df750dc8SHong Zhang     ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr);
2969cddf8d76SBarry Smith   }
2970cddf8d76SBarry Smith 
2971cddf8d76SBarry Smith   for (i=0; i<n; i++) {
29727dae84e0SHong Zhang     ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
2973cddf8d76SBarry Smith   }
29743a40ed3dSBarry Smith   PetscFunctionReturn(0);
2975cddf8d76SBarry Smith }
2976cddf8d76SBarry Smith 
297797f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
29784dcbc457SBarry Smith {
2979e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29806849ba73SBarry Smith   PetscErrorCode ierr;
29815d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
29825d0c19d7SBarry Smith   const PetscInt *idx;
298397f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2984f1af5d2fSBarry Smith   PetscBT        table;
2985bbd702dbSSatish Balay 
29863a40ed3dSBarry Smith   PetscFunctionBegin;
2987d0f46423SBarry Smith   m  = A->rmap->n;
2988e4d965acSSatish Balay   ai = a->i;
2989bfeeae90SHong Zhang   aj = a->j;
29908a047759SSatish Balay 
2991e32f2f54SBarry Smith   if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
299206763907SSatish Balay 
2993854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr);
299453b8de81SBarry Smith   ierr = PetscBTCreate(m,&table);CHKERRQ(ierr);
299506763907SSatish Balay 
2996e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2997b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2998e4d965acSSatish Balay     isz  = 0;
29996831982aSBarry Smith     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
3000e4d965acSSatish Balay 
3001e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
30024dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
3003b9b97703SBarry Smith     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
3004e4d965acSSatish Balay 
3005dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
3006e4d965acSSatish Balay     for (j=0; j<n; ++j) {
30072205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
30084dcbc457SBarry Smith     }
300906763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
30106bf464f9SBarry Smith     ierr = ISDestroy(&is[i]);CHKERRQ(ierr);
3011e4d965acSSatish Balay 
301204a348a9SBarry Smith     k = 0;
301304a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
301404a348a9SBarry Smith       n = isz;
301506763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
3016e4d965acSSatish Balay         row   = nidx[k];
3017e4d965acSSatish Balay         start = ai[row];
3018e4d965acSSatish Balay         end   = ai[row+1];
301904a348a9SBarry Smith         for (l = start; l<end; l++) {
3020efb16452SHong Zhang           val = aj[l];
30212205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
3022e4d965acSSatish Balay         }
3023e4d965acSSatish Balay       }
3024e4d965acSSatish Balay     }
302570b3c8c7SBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr);
3026e4d965acSSatish Balay   }
302794bacf5dSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
3028606d414cSSatish Balay   ierr = PetscFree(nidx);CHKERRQ(ierr);
30293a40ed3dSBarry Smith   PetscFunctionReturn(0);
30304dcbc457SBarry Smith }
303117ab2063SBarry Smith 
30320513a670SBarry Smith /* -------------------------------------------------------------- */
3033dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
30340513a670SBarry Smith {
30350513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
30366849ba73SBarry Smith   PetscErrorCode ierr;
30373b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
30385d0c19d7SBarry Smith   const PetscInt *row,*col;
30395d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
304056cd22aeSBarry Smith   IS             icolp,irowp;
30410298fd71SBarry Smith   PetscInt       *cwork = NULL;
30420298fd71SBarry Smith   PetscScalar    *vwork = NULL;
30430513a670SBarry Smith 
30443a40ed3dSBarry Smith   PetscFunctionBegin;
30454c49b128SBarry Smith   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
304656cd22aeSBarry Smith   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
30474c49b128SBarry Smith   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
304856cd22aeSBarry Smith   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
30490513a670SBarry Smith 
30500513a670SBarry Smith   /* determine lengths of permuted rows */
3051854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr);
30522205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
3053ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
3054f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
305533d57670SJed Brown   ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
30567adad957SLisandro Dalcin   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
3057ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
3058606d414cSSatish Balay   ierr = PetscFree(lens);CHKERRQ(ierr);
30590513a670SBarry Smith 
3060785e854fSJed Brown   ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr);
30610513a670SBarry Smith   for (i=0; i<m; i++) {
306232ec9ce4SBarry Smith     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30632205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
3064cdc0ba36SBarry Smith     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
306532ec9ce4SBarry Smith     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30660513a670SBarry Smith   }
3067606d414cSSatish Balay   ierr = PetscFree(cnew);CHKERRQ(ierr);
30682205254eSKarl Rupp 
30693c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
30702205254eSKarl Rupp 
30718c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
3072b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(*B,A->boundtocpu);CHKERRQ(ierr);
30739fe5e383SStefano Zampini #endif
30740513a670SBarry Smith   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
30750513a670SBarry Smith   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
307656cd22aeSBarry Smith   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
307756cd22aeSBarry Smith   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
30786bf464f9SBarry Smith   ierr = ISDestroy(&irowp);CHKERRQ(ierr);
30796bf464f9SBarry Smith   ierr = ISDestroy(&icolp);CHKERRQ(ierr);
30806768869dSprj-   if (rowp == colp) {
3081dc29a518SPierre Jolivet     ierr = MatPropagateSymmetryOptions(A,*B);CHKERRQ(ierr);
30826768869dSprj-   }
30833a40ed3dSBarry Smith   PetscFunctionReturn(0);
30840513a670SBarry Smith }
30850513a670SBarry Smith 
3086dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
3087cb5b572fSBarry Smith {
3088dfbe8321SBarry Smith   PetscErrorCode ierr;
3089cb5b572fSBarry Smith 
3090cb5b572fSBarry Smith   PetscFunctionBegin;
309133f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
309233f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
3093be6bf707SBarry Smith     Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
3094be6bf707SBarry Smith     Mat_SeqAIJ        *b = (Mat_SeqAIJ*)B->data;
30952e5835c6SStefano Zampini     const PetscScalar *aa;
3096be6bf707SBarry Smith 
30972e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
30984d805d7cSStefano Zampini     if (a->i[A->rmap->n] != b->i[B->rmap->n]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different %D != %D",a->i[A->rmap->n],b->i[B->rmap->n]);
30992e5835c6SStefano Zampini     ierr = PetscArraycpy(b->a,aa,a->i[A->rmap->n]);CHKERRQ(ierr);
3100cdc753b6SBarry Smith     ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
31012e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
3102cb5b572fSBarry Smith   } else {
3103cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
3104cb5b572fSBarry Smith   }
3105cb5b572fSBarry Smith   PetscFunctionReturn(0);
3106cb5b572fSBarry Smith }
3107cb5b572fSBarry Smith 
31084994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
3109273d9f13SBarry Smith {
3110dfbe8321SBarry Smith   PetscErrorCode ierr;
3111273d9f13SBarry Smith 
3112273d9f13SBarry Smith   PetscFunctionBegin;
3113f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
3114273d9f13SBarry Smith   PetscFunctionReturn(0);
3115273d9f13SBarry Smith }
3116273d9f13SBarry Smith 
3117f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
31186c0721eeSBarry Smith {
31196c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
31206e111a19SKarl Rupp 
31216c0721eeSBarry Smith   PetscFunctionBegin;
31226c0721eeSBarry Smith   *array = a->a;
31236c0721eeSBarry Smith   PetscFunctionReturn(0);
31246c0721eeSBarry Smith }
31256c0721eeSBarry Smith 
3126f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
31276c0721eeSBarry Smith {
31286c0721eeSBarry Smith   PetscFunctionBegin;
3129f38c1e66SStefano Zampini   *array = NULL;
31306c0721eeSBarry Smith   PetscFunctionReturn(0);
31316c0721eeSBarry Smith }
3132273d9f13SBarry Smith 
31338229c054SShri Abhyankar /*
31348229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
31358229c054SShri Abhyankar    have different nonzero structure.
31368229c054SShri Abhyankar */
3137b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
3138ec7775f6SShri Abhyankar {
3139b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
3140ec7775f6SShri Abhyankar 
3141ec7775f6SShri Abhyankar   PetscFunctionBegin;
3142ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
3143ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
3144b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
3145b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
3146b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
31478af7cee1SJed Brown     nnz[i] = 0;
31488af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
3149b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
3150b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
31518af7cee1SJed Brown       nnz[i]++;
31528af7cee1SJed Brown     }
31538af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
3154ec7775f6SShri Abhyankar   }
3155ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
3156ec7775f6SShri Abhyankar }
3157ec7775f6SShri Abhyankar 
3158b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
3159b264fe52SHong Zhang {
3160b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
3161b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
3162b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
3163b264fe52SHong Zhang   PetscErrorCode ierr;
3164b264fe52SHong Zhang 
3165b264fe52SHong Zhang   PetscFunctionBegin;
3166b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
3167b264fe52SHong Zhang   ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr);
3168b264fe52SHong Zhang   PetscFunctionReturn(0);
3169b264fe52SHong Zhang }
3170b264fe52SHong Zhang 
3171f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
3172ac90fabeSBarry Smith {
3173dfbe8321SBarry Smith   PetscErrorCode ierr;
3174ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
3175ac90fabeSBarry Smith 
3176ac90fabeSBarry Smith   PetscFunctionBegin;
317741f5e1b1SStefano Zampini   if (str == UNKNOWN_NONZERO_PATTERN && x->nz == y->nz) {
317881fa06acSBarry Smith     PetscBool e;
317981fa06acSBarry Smith     ierr = PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e);CHKERRQ(ierr);
318081fa06acSBarry Smith     if (e) {
318181fa06acSBarry Smith       ierr = PetscArraycmp(x->j,y->j,y->nz,&e);CHKERRQ(ierr);
318281fa06acSBarry Smith       if (e) {
318381fa06acSBarry Smith         str = SAME_NONZERO_PATTERN;
318481fa06acSBarry Smith       }
318581fa06acSBarry Smith     }
318681fa06acSBarry Smith   }
3187ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
31882e5835c6SStefano Zampini     const PetscScalar *xa;
31892e5835c6SStefano Zampini     PetscScalar       *ya,alpha = a;
319081fa06acSBarry Smith     PetscBLASInt      one = 1,bnz;
319181fa06acSBarry Smith 
319281fa06acSBarry Smith     ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
31932e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(Y,&ya);CHKERRQ(ierr);
31942e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(X,&xa);CHKERRQ(ierr);
31952e5835c6SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,xa,&one,ya,&one));
31962e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(X,&xa);CHKERRQ(ierr);
31972e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(Y,&ya);CHKERRQ(ierr);
319841f5e1b1SStefano Zampini     ierr = PetscLogFlops(2.0*bnz);CHKERRQ(ierr);
3199acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
3200a3fa217bSJose E. Roman     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
3201ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
3202ab784542SHong Zhang     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
3203ac90fabeSBarry Smith   } else {
32048229c054SShri Abhyankar     Mat      B;
32058229c054SShri Abhyankar     PetscInt *nnz;
3206785e854fSJed Brown     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
3207ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
3208bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
320981fa06acSBarry Smith     ierr = MatSetLayouts(B,Y->rmap,Y->cmap);CHKERRQ(ierr);
32102e5835c6SStefano Zampini     ierr = MatSetType(B,((PetscObject)Y)->type_name);CHKERRQ(ierr);
32118229c054SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
3212ecd8bba6SJed Brown     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
3213ec7775f6SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
321428be2f97SBarry Smith     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
32158229c054SShri Abhyankar     ierr = PetscFree(nnz);CHKERRQ(ierr);
3216ac90fabeSBarry Smith   }
3217ac90fabeSBarry Smith   PetscFunctionReturn(0);
3218ac90fabeSBarry Smith }
3219ac90fabeSBarry Smith 
32202726fb6dSPierre Jolivet PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat)
3221354c94deSBarry Smith {
3222354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3223354c94deSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
3224354c94deSBarry Smith   PetscInt       i,nz;
3225354c94deSBarry Smith   PetscScalar    *a;
3226ce496241SStefano Zampini   PetscErrorCode ierr;
3227354c94deSBarry Smith 
3228354c94deSBarry Smith   PetscFunctionBegin;
3229354c94deSBarry Smith   nz = aij->nz;
3230ce496241SStefano Zampini   ierr = MatSeqAIJGetArray(mat,&a);CHKERRQ(ierr);
32312205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
3232ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArray(mat,&a);CHKERRQ(ierr);
3233354c94deSBarry Smith #else
3234354c94deSBarry Smith   PetscFunctionBegin;
3235354c94deSBarry Smith #endif
3236354c94deSBarry Smith   PetscFunctionReturn(0);
3237354c94deSBarry Smith }
3238354c94deSBarry Smith 
3239985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3240e34fafa9SBarry Smith {
3241e34fafa9SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3242e34fafa9SBarry Smith   PetscErrorCode  ierr;
3243d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3244e34fafa9SBarry Smith   PetscReal       atmp;
3245985db425SBarry Smith   PetscScalar     *x;
3246ce496241SStefano Zampini   const MatScalar *aa,*av;
3247e34fafa9SBarry Smith 
3248e34fafa9SBarry Smith   PetscFunctionBegin;
3249e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3250ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3251ce496241SStefano Zampini   aa = av;
3252e34fafa9SBarry Smith   ai = a->i;
3253e34fafa9SBarry Smith   aj = a->j;
3254e34fafa9SBarry Smith 
3255985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3256475b8b61SHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3257e34fafa9SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3258e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3259e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3260e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3261e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3262985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3263985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3264985db425SBarry Smith       aa++; aj++;
3265985db425SBarry Smith     }
3266985db425SBarry Smith   }
3267475b8b61SHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3268ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3269985db425SBarry Smith   PetscFunctionReturn(0);
3270985db425SBarry Smith }
3271985db425SBarry Smith 
3272985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3273985db425SBarry Smith {
3274985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3275985db425SBarry Smith   PetscErrorCode  ierr;
3276d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3277985db425SBarry Smith   PetscScalar     *x;
3278ce496241SStefano Zampini   const MatScalar *aa,*av;
3279985db425SBarry Smith 
3280985db425SBarry Smith   PetscFunctionBegin;
3281e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3282ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3283ce496241SStefano Zampini   aa = av;
3284985db425SBarry Smith   ai = a->i;
3285985db425SBarry Smith   aj = a->j;
3286985db425SBarry Smith 
3287985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3288fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3289985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3290e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3291985db425SBarry Smith   for (i=0; i<m; i++) {
3292985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3293d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3294985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3295985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3296985db425SBarry Smith       x[i] = 0.0;
3297985db425SBarry Smith       if (idx) {
3298985db425SBarry Smith         for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */
3299985db425SBarry Smith           if (aj[j] > j) {
3300985db425SBarry Smith             idx[i] = j;
3301985db425SBarry Smith             break;
3302985db425SBarry Smith           }
3303985db425SBarry Smith         }
33041a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
33051a254869SHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3306985db425SBarry Smith       }
3307985db425SBarry Smith     }
3308985db425SBarry Smith     for (j=0; j<ncols; j++) {
3309985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3310985db425SBarry Smith       aa++; aj++;
3311985db425SBarry Smith     }
3312985db425SBarry Smith   }
3313fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3314ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3315985db425SBarry Smith   PetscFunctionReturn(0);
3316985db425SBarry Smith }
3317985db425SBarry Smith 
3318c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3319c87e5d42SMatthew Knepley {
3320c87e5d42SMatthew Knepley   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3321c87e5d42SMatthew Knepley   PetscErrorCode  ierr;
3322c87e5d42SMatthew Knepley   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3323ce496241SStefano Zampini   PetscScalar     *x;
3324ce496241SStefano Zampini   const MatScalar *aa,*av;
3325c87e5d42SMatthew Knepley 
3326c87e5d42SMatthew Knepley   PetscFunctionBegin;
3327ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3328ce496241SStefano Zampini   aa = av;
3329c87e5d42SMatthew Knepley   ai = a->i;
3330c87e5d42SMatthew Knepley   aj = a->j;
3331c87e5d42SMatthew Knepley 
3332c87e5d42SMatthew Knepley   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3333f07e67edSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3334c87e5d42SMatthew Knepley   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3335f07e67edSHong Zhang   if (n != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %D vs. %D rows", m, n);
3336c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3337c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3338f07e67edSHong Zhang     if (ncols == A->cmap->n) { /* row is dense */
3339f07e67edSHong Zhang       x[i] = *aa; if (idx) idx[i] = 0;
3340f07e67edSHong Zhang     } else {  /* row is sparse so already KNOW minimum is 0.0 or higher */
3341f07e67edSHong Zhang       x[i] = 0.0;
3342f07e67edSHong Zhang       if (idx) {   /* find first implicit 0.0 in the row */
3343289a08f5SMatthew Knepley         for (j=0; j<ncols; j++) {
3344f07e67edSHong Zhang           if (aj[j] > j) {
3345f07e67edSHong Zhang             idx[i] = j;
33462205254eSKarl Rupp             break;
33472205254eSKarl Rupp           }
3348289a08f5SMatthew Knepley         }
3349f07e67edSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3350f07e67edSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3351f07e67edSHong Zhang       }
3352289a08f5SMatthew Knepley     }
3353c87e5d42SMatthew Knepley     for (j=0; j<ncols; j++) {
3354f07e67edSHong Zhang       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3355c87e5d42SMatthew Knepley       aa++; aj++;
3356c87e5d42SMatthew Knepley     }
3357c87e5d42SMatthew Knepley   }
3358f07e67edSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3359ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3360c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3361c87e5d42SMatthew Knepley }
3362c87e5d42SMatthew Knepley 
3363985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3364985db425SBarry Smith {
3365985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3366985db425SBarry Smith   PetscErrorCode  ierr;
3367d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3368d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3369985db425SBarry Smith   PetscScalar     *x;
3370ce496241SStefano Zampini   const MatScalar *aa,*av;
3371985db425SBarry Smith 
3372985db425SBarry Smith   PetscFunctionBegin;
3373e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3374ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3375ce496241SStefano Zampini   aa = av;
3376985db425SBarry Smith   ai = a->i;
3377985db425SBarry Smith   aj = a->j;
3378985db425SBarry Smith 
3379985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3380fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3381985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3382f07e67edSHong Zhang   if (n != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3383985db425SBarry Smith   for (i=0; i<m; i++) {
3384985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3385d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3386985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3387985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3388985db425SBarry Smith       x[i] = 0.0;
3389985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3390985db425SBarry Smith         for (j=0; j<ncols; j++) {
3391985db425SBarry Smith           if (aj[j] > j) {
3392985db425SBarry Smith             idx[i] = j;
3393985db425SBarry Smith             break;
3394985db425SBarry Smith           }
3395985db425SBarry Smith         }
3396fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3397fa213d2fSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3398985db425SBarry Smith       }
3399985db425SBarry Smith     }
3400985db425SBarry Smith     for (j=0; j<ncols; j++) {
3401985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3402985db425SBarry Smith       aa++; aj++;
3403e34fafa9SBarry Smith     }
3404e34fafa9SBarry Smith   }
3405fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3406ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3407e34fafa9SBarry Smith   PetscFunctionReturn(0);
3408e34fafa9SBarry Smith }
3409bbead8a2SBarry Smith 
3410713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3411bbead8a2SBarry Smith {
3412bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3413bbead8a2SBarry Smith   PetscErrorCode  ierr;
341433d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3415bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
34160da83c2eSBarry Smith   const PetscReal shift = 0.0;
34171a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3418bbead8a2SBarry Smith 
3419bbead8a2SBarry Smith   PetscFunctionBegin;
3420a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
34214a0d0026SBarry Smith   if (a->ibdiagvalid) {
34224a0d0026SBarry Smith     if (values) *values = a->ibdiag;
34234a0d0026SBarry Smith     PetscFunctionReturn(0);
34244a0d0026SBarry Smith   }
3425bbead8a2SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3426bbead8a2SBarry Smith   if (!a->ibdiag) {
3427785e854fSJed Brown     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
34283bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3429bbead8a2SBarry Smith   }
3430bbead8a2SBarry Smith   diag = a->ibdiag;
3431bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3432bbead8a2SBarry Smith   /* factor and invert each block */
3433bbead8a2SBarry Smith   switch (bs) {
3434bbead8a2SBarry Smith   case 1:
3435bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3436bbead8a2SBarry Smith       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3437ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3438ec1892c8SHong Zhang         if (allowzeropivot) {
34397b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
34407b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
34417b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
34427b6c816cSBarry Smith           ierr = PetscInfo3(A,"Zero pivot, row %D pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
34437b6c816cSBarry Smith         } else SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_MAT_LU_ZRPVT,"Zero pivot, row %D pivot %g tolerance %g",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);
3444ec1892c8SHong Zhang       }
3445bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3446bbead8a2SBarry Smith     }
3447bbead8a2SBarry Smith     break;
3448bbead8a2SBarry Smith   case 2:
3449bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3450bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
3451bbead8a2SBarry Smith       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3452a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34537b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
345496b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3455bbead8a2SBarry Smith       diag += 4;
3456bbead8a2SBarry Smith     }
3457bbead8a2SBarry Smith     break;
3458bbead8a2SBarry Smith   case 3:
3459bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3460bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3461bbead8a2SBarry Smith       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3462a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34637b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
346496b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3465bbead8a2SBarry Smith       diag += 9;
3466bbead8a2SBarry Smith     }
3467bbead8a2SBarry Smith     break;
3468bbead8a2SBarry Smith   case 4:
3469bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3470bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3471bbead8a2SBarry Smith       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3472a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34737b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
347496b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3475bbead8a2SBarry Smith       diag += 16;
3476bbead8a2SBarry Smith     }
3477bbead8a2SBarry Smith     break;
3478bbead8a2SBarry Smith   case 5:
3479bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3480bbead8a2SBarry 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;
3481bbead8a2SBarry Smith       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3482a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34837b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
348496b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3485bbead8a2SBarry Smith       diag += 25;
3486bbead8a2SBarry Smith     }
3487bbead8a2SBarry Smith     break;
3488bbead8a2SBarry Smith   case 6:
3489bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3490bbead8a2SBarry 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;
3491bbead8a2SBarry Smith       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3492a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34937b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
349496b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3495bbead8a2SBarry Smith       diag += 36;
3496bbead8a2SBarry Smith     }
3497bbead8a2SBarry Smith     break;
3498bbead8a2SBarry Smith   case 7:
3499bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3500bbead8a2SBarry 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;
3501bbead8a2SBarry Smith       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3502a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
35037b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
350496b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3505bbead8a2SBarry Smith       diag += 49;
3506bbead8a2SBarry Smith     }
3507bbead8a2SBarry Smith     break;
3508bbead8a2SBarry Smith   default:
3509dcca6d9dSJed Brown     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3510bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3511bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3512bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3513bbead8a2SBarry Smith       }
3514bbead8a2SBarry Smith       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
35155f8bbccaSHong Zhang       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
35167b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
351796b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3518bbead8a2SBarry Smith       diag += bs2;
3519bbead8a2SBarry Smith     }
3520bbead8a2SBarry Smith     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3521bbead8a2SBarry Smith   }
3522bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3523bbead8a2SBarry Smith   PetscFunctionReturn(0);
3524bbead8a2SBarry Smith }
3525bbead8a2SBarry Smith 
352673a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
352773a71a0fSBarry Smith {
352873a71a0fSBarry Smith   PetscErrorCode ierr;
352973a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
353073a71a0fSBarry Smith   PetscScalar    a;
353173a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
353273a71a0fSBarry Smith 
353373a71a0fSBarry Smith   PetscFunctionBegin;
353473a71a0fSBarry Smith   if (!x->assembled) {
353573a71a0fSBarry Smith     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
353673a71a0fSBarry Smith     for (i=0; i<m; i++) {
353773a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
353873a71a0fSBarry Smith         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
353973a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
354073a71a0fSBarry Smith         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
354173a71a0fSBarry Smith       }
354273a71a0fSBarry Smith     }
3543e2ce353bSJunchao Zhang   } else {
3544e2ce353bSJunchao Zhang     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aij->a+i);CHKERRQ(ierr);}
3545e2ce353bSJunchao Zhang   }
3546ce496241SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
3547ce496241SStefano Zampini   if (x->offloadmask != PETSC_OFFLOAD_UNALLOCATED) x->offloadmask = PETSC_OFFLOAD_CPU;
3548ce496241SStefano Zampini #endif
354973a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
355073a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
355173a71a0fSBarry Smith   PetscFunctionReturn(0);
355273a71a0fSBarry Smith }
355373a71a0fSBarry Smith 
3554679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3555679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3556679944adSJunchao Zhang {
3557679944adSJunchao Zhang   PetscErrorCode ierr;
3558679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3559679944adSJunchao Zhang   PetscScalar    a;
3560679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3561679944adSJunchao Zhang 
3562679944adSJunchao Zhang   PetscFunctionBegin;
3563679944adSJunchao Zhang   nskip = high - low;
3564679944adSJunchao Zhang   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3565679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3566679944adSJunchao Zhang   for (i=0; i<m; i++) {
3567679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
3568679944adSJunchao Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3569679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3570679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3571679944adSJunchao Zhang       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3572679944adSJunchao Zhang     }
3573e2ce353bSJunchao Zhang   }
3574679944adSJunchao Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3575679944adSJunchao Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3576679944adSJunchao Zhang   PetscFunctionReturn(0);
3577679944adSJunchao Zhang }
3578679944adSJunchao Zhang 
3579682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
35800a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3581cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3582cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3583cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
358497304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
35857c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
35867c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3587f4259b30SLisandro Dalcin                                         NULL,
3588f4259b30SLisandro Dalcin                                         NULL,
3589f4259b30SLisandro Dalcin                                         NULL,
3590f4259b30SLisandro Dalcin                                 /* 10*/ NULL,
3591cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3592f4259b30SLisandro Dalcin                                         NULL,
359341f059aeSBarry Smith                                         MatSOR_SeqAIJ,
359491e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
359597304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3596cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3597cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3598cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3599cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
3600f4259b30SLisandro Dalcin                                 /* 20*/ NULL,
3601cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3602cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3603cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3604d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3605f4259b30SLisandro Dalcin                                         NULL,
3606f4259b30SLisandro Dalcin                                         NULL,
3607f4259b30SLisandro Dalcin                                         NULL,
3608f4259b30SLisandro Dalcin                                         NULL,
36094994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3610f4259b30SLisandro Dalcin                                         NULL,
3611f4259b30SLisandro Dalcin                                         NULL,
3612f4259b30SLisandro Dalcin                                         NULL,
3613f4259b30SLisandro Dalcin                                         NULL,
3614d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3615f4259b30SLisandro Dalcin                                         NULL,
3616f4259b30SLisandro Dalcin                                         NULL,
3617cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3618f4259b30SLisandro Dalcin                                         NULL,
3619d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
36207dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3621cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3622cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3623cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3624d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3625cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
36267d68702bSBarry Smith                                         MatShift_SeqAIJ,
362779299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
36286e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
362973a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
36303b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
36313b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
36323b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3633a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
363493dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3635f4259b30SLisandro Dalcin                                         NULL,
3636f4259b30SLisandro Dalcin                                         NULL,
3637cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3638f4259b30SLisandro Dalcin                                         NULL,
3639f4259b30SLisandro Dalcin                                 /* 59*/ NULL,
3640b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3641b9b97703SBarry Smith                                         MatView_SeqAIJ,
3642f4259b30SLisandro Dalcin                                         NULL,
3643f4259b30SLisandro Dalcin                                         NULL,
3644f4259b30SLisandro Dalcin                                 /* 64*/ NULL,
3645321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3646f4259b30SLisandro Dalcin                                         NULL,
3647f4259b30SLisandro Dalcin                                         NULL,
3648f4259b30SLisandro Dalcin                                         NULL,
3649d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3650c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3651f4259b30SLisandro Dalcin                                         NULL,
3652f4259b30SLisandro Dalcin                                         NULL,
3653f4259b30SLisandro Dalcin                                         NULL,
3654f4259b30SLisandro Dalcin                                 /* 74*/ NULL,
36553acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
3656f4259b30SLisandro Dalcin                                         NULL,
3657f4259b30SLisandro Dalcin                                         NULL,
3658f4259b30SLisandro Dalcin                                         NULL,
36596ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3660f4259b30SLisandro Dalcin                                         NULL,
3661f4259b30SLisandro Dalcin                                         NULL,
3662f4259b30SLisandro Dalcin                                         NULL,
3663bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3664d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
36651cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
3666f4259b30SLisandro Dalcin                                         NULL,
3667f4259b30SLisandro Dalcin                                         NULL,
3668f4259b30SLisandro Dalcin                                         NULL,
3669f4259b30SLisandro Dalcin                                 /* 89*/ NULL,
3670f4259b30SLisandro Dalcin                                         NULL,
367126be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
3672f4259b30SLisandro Dalcin                                         NULL,
3673f4259b30SLisandro Dalcin                                         NULL,
36748fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3675f4259b30SLisandro Dalcin                                         NULL,
3676f4259b30SLisandro Dalcin                                         NULL,
36776fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3678f4259b30SLisandro Dalcin                                         NULL,
36794222ddf1SHong Zhang                                 /* 99*/ MatProductSetFromOptions_SeqAIJ,
3680f4259b30SLisandro Dalcin                                         NULL,
3681f4259b30SLisandro Dalcin                                         NULL,
368287d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
3683f4259b30SLisandro Dalcin                                         NULL,
3684d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
368599cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3686f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3687f4259b30SLisandro Dalcin                                         NULL,
3688f4259b30SLisandro Dalcin                                         NULL,
3689cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3690f4259b30SLisandro Dalcin                                         NULL,
36912af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
3692f4259b30SLisandro Dalcin                                         NULL,
3693599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3694f4259b30SLisandro Dalcin                                 /*114*/ NULL,
3695f4259b30SLisandro Dalcin                                         NULL,
3696f4259b30SLisandro Dalcin                                         NULL,
3697f4259b30SLisandro Dalcin                                         NULL,
3698f4259b30SLisandro Dalcin                                         NULL,
3699f4259b30SLisandro Dalcin                                 /*119*/ NULL,
3700f4259b30SLisandro Dalcin                                         NULL,
3701f4259b30SLisandro Dalcin                                         NULL,
3702f4259b30SLisandro Dalcin                                         NULL,
3703b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
37040716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3705a873a8cdSSam Reynolds                                         MatGetColumnReductions_SeqAIJ,
370637868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
37070da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
3708f4259b30SLisandro Dalcin                                         NULL,
3709f4259b30SLisandro Dalcin                                 /*129*/ NULL,
3710f4259b30SLisandro Dalcin                                         NULL,
3711f4259b30SLisandro Dalcin                                         NULL,
371275648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3713b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3714b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
37152b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
3716f4259b30SLisandro Dalcin                                         NULL,
3717f4259b30SLisandro Dalcin                                         NULL,
37183964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
3719f4259b30SLisandro Dalcin                                  /*139*/NULL,
3720f4259b30SLisandro Dalcin                                         NULL,
3721f4259b30SLisandro Dalcin                                         NULL,
37223a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
37239c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
37244222ddf1SHong Zhang                                         MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
37254222ddf1SHong Zhang                                  /*145*/MatDestroySubMatrices_SeqAIJ,
3726f4259b30SLisandro Dalcin                                         NULL,
3727f4259b30SLisandro Dalcin                                         NULL
37289e29f15eSvictorle };
372917ab2063SBarry Smith 
37307087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3731bef8e0ddSBarry Smith {
3732bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
373397f1f81fSBarry Smith   PetscInt   i,nz,n;
3734bef8e0ddSBarry Smith 
3735bef8e0ddSBarry Smith   PetscFunctionBegin;
3736bef8e0ddSBarry Smith   nz = aij->maxnz;
3737d0f46423SBarry Smith   n  = mat->rmap->n;
3738bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3739bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3740bef8e0ddSBarry Smith   }
3741bef8e0ddSBarry Smith   aij->nz = nz;
3742bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3743bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3744bef8e0ddSBarry Smith   }
3745bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3746bef8e0ddSBarry Smith }
3747bef8e0ddSBarry Smith 
3748a3bb6f32SFande Kong /*
3749ddea5d60SJunchao Zhang  * Given a sparse matrix with global column indices, compact it by using a local column space.
3750ddea5d60SJunchao Zhang  * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3751ddea5d60SJunchao Zhang  */
3752a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3753a3bb6f32SFande Kong {
3754a3bb6f32SFande Kong   Mat_SeqAIJ         *aij = (Mat_SeqAIJ*)mat->data;
3755a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3756a3bb6f32SFande Kong   PetscTablePosition tpos;
375725b670f0SStefano Zampini   PetscInt           gid,lid,i,ec,nz = aij->nz;
375825b670f0SStefano Zampini   PetscInt           *garray,*jj = aij->j;
3759a3bb6f32SFande Kong   PetscErrorCode     ierr;
3760a3bb6f32SFande Kong 
3761a3bb6f32SFande Kong   PetscFunctionBegin;
3762a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3763a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3764a3bb6f32SFande Kong   /* use a table */
3765a3bb6f32SFande Kong   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3766a3bb6f32SFande Kong   ec = 0;
376725b670f0SStefano Zampini   for (i=0; i<nz; i++) {
376825b670f0SStefano Zampini     PetscInt data,gid1 = jj[i] + 1;
3769a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3770a3bb6f32SFande Kong     if (!data) {
3771a3bb6f32SFande Kong       /* one based table */
3772a3bb6f32SFande Kong       ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3773a3bb6f32SFande Kong     }
3774a3bb6f32SFande Kong   }
3775a3bb6f32SFande Kong   /* form array of columns we need */
3776b3c64f9dSJunchao Zhang   ierr = PetscMalloc1(ec,&garray);CHKERRQ(ierr);
3777a3bb6f32SFande Kong   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3778a3bb6f32SFande Kong   while (tpos) {
3779a3bb6f32SFande Kong     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3780a3bb6f32SFande Kong     gid--;
3781a3bb6f32SFande Kong     lid--;
3782a3bb6f32SFande Kong     garray[lid] = gid;
3783a3bb6f32SFande Kong   }
3784a3bb6f32SFande Kong   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3785a3bb6f32SFande Kong   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3786a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
3787a3bb6f32SFande Kong     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3788a3bb6f32SFande Kong   }
3789a3bb6f32SFande Kong   /* compact out the extra columns in B */
379025b670f0SStefano Zampini   for (i=0; i<nz; i++) {
379125b670f0SStefano Zampini     PetscInt gid1 = jj[i] + 1;
3792a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3793a3bb6f32SFande Kong     lid--;
379425b670f0SStefano Zampini     jj[i] = lid;
3795a3bb6f32SFande Kong   }
3796ca5434daSLawrence Mitchell   ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
3797a3bb6f32SFande Kong   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
379825b670f0SStefano Zampini   ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr);
3799a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3800a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3801a3bb6f32SFande Kong   PetscFunctionReturn(0);
3802a3bb6f32SFande Kong }
3803a3bb6f32SFande Kong 
3804bef8e0ddSBarry Smith /*@
3805bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3806bef8e0ddSBarry Smith        in the matrix.
3807bef8e0ddSBarry Smith 
3808bef8e0ddSBarry Smith   Input Parameters:
3809bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3810bef8e0ddSBarry Smith -  indices - the column indices
3811bef8e0ddSBarry Smith 
381215091d37SBarry Smith   Level: advanced
381315091d37SBarry Smith 
3814bef8e0ddSBarry Smith   Notes:
3815bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3816bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3817bef8e0ddSBarry Smith   of the MatSetValues() operation.
3818bef8e0ddSBarry Smith 
3819bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3820d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3821bef8e0ddSBarry Smith 
3822bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3823bef8e0ddSBarry Smith 
3824b9617806SBarry Smith     The indices should start with zero, not one.
3825b9617806SBarry Smith 
3826bef8e0ddSBarry Smith @*/
38277087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3828bef8e0ddSBarry Smith {
38294ac538c5SBarry Smith   PetscErrorCode ierr;
3830bef8e0ddSBarry Smith 
3831bef8e0ddSBarry Smith   PetscFunctionBegin;
38320700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
38334482741eSBarry Smith   PetscValidPointer(indices,2);
38344ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3835bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3836bef8e0ddSBarry Smith }
3837bef8e0ddSBarry Smith 
3838be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3839be6bf707SBarry Smith 
38407087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3841be6bf707SBarry Smith {
3842be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
38436849ba73SBarry Smith   PetscErrorCode ierr;
3844d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3845be6bf707SBarry Smith 
3846be6bf707SBarry Smith   PetscFunctionBegin;
3847169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3848be6bf707SBarry Smith 
3849be6bf707SBarry Smith   /* allocate space for values if not already there */
3850be6bf707SBarry Smith   if (!aij->saved_values) {
3851854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
38523bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3853be6bf707SBarry Smith   }
3854be6bf707SBarry Smith 
3855be6bf707SBarry Smith   /* copy values over */
3856580bdb30SBarry Smith   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3857be6bf707SBarry Smith   PetscFunctionReturn(0);
3858be6bf707SBarry Smith }
3859be6bf707SBarry Smith 
3860be6bf707SBarry Smith /*@
3861be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3862be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3863be6bf707SBarry Smith        nonlinear portion.
3864be6bf707SBarry Smith 
3865be6bf707SBarry Smith    Collect on Mat
3866be6bf707SBarry Smith 
3867be6bf707SBarry Smith   Input Parameters:
38680e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3869be6bf707SBarry Smith 
387015091d37SBarry Smith   Level: advanced
387115091d37SBarry Smith 
3872be6bf707SBarry Smith   Common Usage, with SNESSolve():
3873be6bf707SBarry Smith $    Create Jacobian matrix
3874be6bf707SBarry Smith $    Set linear terms into matrix
3875be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3876be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3877be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3878512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3879be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3880be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3881be6bf707SBarry Smith $    In your Jacobian routine
3882be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3883be6bf707SBarry Smith $      Set nonlinear terms in matrix
3884be6bf707SBarry Smith 
3885be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3886be6bf707SBarry Smith $    // build linear portion of Jacobian
3887512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3888be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3889be6bf707SBarry Smith $    loop over nonlinear iterations
3890be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3891be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3892be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3893be6bf707SBarry Smith $       Solve linear system with Jacobian
3894be6bf707SBarry Smith $    endloop
3895be6bf707SBarry Smith 
3896be6bf707SBarry Smith   Notes:
3897be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3898512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3899be6bf707SBarry Smith     calling this routine.
3900be6bf707SBarry Smith 
39010c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
39020c468ba9SBarry Smith     and does not allocated additional space.
39030c468ba9SBarry Smith 
3904be6bf707SBarry Smith .seealso: MatRetrieveValues()
3905be6bf707SBarry Smith 
3906be6bf707SBarry Smith @*/
39077087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3908be6bf707SBarry Smith {
39094ac538c5SBarry Smith   PetscErrorCode ierr;
3910be6bf707SBarry Smith 
3911be6bf707SBarry Smith   PetscFunctionBegin;
39120700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3913e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3914e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
39154ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3916be6bf707SBarry Smith   PetscFunctionReturn(0);
3917be6bf707SBarry Smith }
3918be6bf707SBarry Smith 
39197087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3920be6bf707SBarry Smith {
3921be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
39226849ba73SBarry Smith   PetscErrorCode ierr;
3923d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3924be6bf707SBarry Smith 
3925be6bf707SBarry Smith   PetscFunctionBegin;
3926169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3927f23aa3ddSBarry Smith   if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3928be6bf707SBarry Smith   /* copy values over */
3929580bdb30SBarry Smith   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3930be6bf707SBarry Smith   PetscFunctionReturn(0);
3931be6bf707SBarry Smith }
3932be6bf707SBarry Smith 
3933be6bf707SBarry Smith /*@
3934be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3935be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3936be6bf707SBarry Smith        nonlinear portion.
3937be6bf707SBarry Smith 
3938be6bf707SBarry Smith    Collect on Mat
3939be6bf707SBarry Smith 
3940be6bf707SBarry Smith   Input Parameters:
3941386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3942be6bf707SBarry Smith 
394315091d37SBarry Smith   Level: advanced
394415091d37SBarry Smith 
3945be6bf707SBarry Smith .seealso: MatStoreValues()
3946be6bf707SBarry Smith 
3947be6bf707SBarry Smith @*/
39487087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3949be6bf707SBarry Smith {
39504ac538c5SBarry Smith   PetscErrorCode ierr;
3951be6bf707SBarry Smith 
3952be6bf707SBarry Smith   PetscFunctionBegin;
39530700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3954e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3955e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
39564ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3957be6bf707SBarry Smith   PetscFunctionReturn(0);
3958be6bf707SBarry Smith }
3959be6bf707SBarry Smith 
3960be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
396117ab2063SBarry Smith /*@C
3962682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
39630d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
39646e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
396551c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
39662bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
396717ab2063SBarry Smith 
3968d083f849SBarry Smith    Collective
3969db81eaa0SLois Curfman McInnes 
397017ab2063SBarry Smith    Input Parameters:
3971db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
397217ab2063SBarry Smith .  m - number of rows
397317ab2063SBarry Smith .  n - number of columns
397417ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
397551c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39760298fd71SBarry Smith          (possibly different for each row) or NULL
397717ab2063SBarry Smith 
397817ab2063SBarry Smith    Output Parameter:
3979416022c9SBarry Smith .  A - the matrix
398017ab2063SBarry Smith 
3981175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3982f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3983175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3984175b88e8SBarry Smith 
3985b259b22eSLois Curfman McInnes    Notes:
398649a6f317SBarry Smith    If nnz is given then nz is ignored
398749a6f317SBarry Smith 
398817ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
398917ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
39900002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
399144cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
399217ab2063SBarry Smith 
399317ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39940298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
39953d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
39966da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
399717ab2063SBarry Smith 
3998682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
39994fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
4000682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
40016c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
40026c7ebb05SLois Curfman McInnes 
40036c7ebb05SLois Curfman McInnes    Options Database Keys:
4004698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
40059db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
400617ab2063SBarry Smith 
4007027ccd11SLois Curfman McInnes    Level: intermediate
4008027ccd11SLois Curfman McInnes 
400969b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
401036db0b34SBarry Smith 
401117ab2063SBarry Smith @*/
40127087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
401317ab2063SBarry Smith {
4014dfbe8321SBarry Smith   PetscErrorCode ierr;
40156945ee14SBarry Smith 
40163a40ed3dSBarry Smith   PetscFunctionBegin;
4017f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
4018117016b1SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
4019c4752a88SBarry Smith   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
4020d28bb7d2SJed Brown   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
4021273d9f13SBarry Smith   PetscFunctionReturn(0);
4022273d9f13SBarry Smith }
4023273d9f13SBarry Smith 
4024273d9f13SBarry Smith /*@C
4025273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
4026273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
4027273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
4028273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
4029273d9f13SBarry Smith 
4030d083f849SBarry Smith    Collective
4031273d9f13SBarry Smith 
4032273d9f13SBarry Smith    Input Parameters:
40331c4f3114SJed Brown +  B - The matrix
4034273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
4035273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
40360298fd71SBarry Smith          (possibly different for each row) or NULL
4037273d9f13SBarry Smith 
4038273d9f13SBarry Smith    Notes:
403949a6f317SBarry Smith      If nnz is given then nz is ignored
404049a6f317SBarry Smith 
4041273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
4042273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
4043273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
4044273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
4045273d9f13SBarry Smith 
4046273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
40470298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
4048273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
4049273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
4050273d9f13SBarry Smith 
4051aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
4052aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
4053aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
4054aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
4055aa95bbe8SBarry Smith 
4056a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
4057a96a251dSBarry Smith    entries or columns indices
4058a96a251dSBarry Smith 
4059273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
4060273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
4061273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
4062273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
4063273d9f13SBarry Smith 
4064273d9f13SBarry Smith    Options Database Keys:
4065698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
406647b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
4067273d9f13SBarry Smith 
4068273d9f13SBarry Smith    Level: intermediate
4069273d9f13SBarry Smith 
407019b08ed1SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo(),
407119b08ed1SBarry Smith           MatSeqAIJSetTotalPreallocation()
4072273d9f13SBarry Smith 
4073273d9f13SBarry Smith @*/
40747087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
4075273d9f13SBarry Smith {
40764ac538c5SBarry Smith   PetscErrorCode ierr;
4077a23d5eceSKris Buschelman 
4078a23d5eceSKris Buschelman   PetscFunctionBegin;
40796ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
40806ba663aaSJed Brown   PetscValidType(B,1);
40814ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
4082a23d5eceSKris Buschelman   PetscFunctionReturn(0);
4083a23d5eceSKris Buschelman }
4084a23d5eceSKris Buschelman 
40857087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
4086a23d5eceSKris Buschelman {
4087273d9f13SBarry Smith   Mat_SeqAIJ     *b;
40882576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
40896849ba73SBarry Smith   PetscErrorCode ierr;
409097f1f81fSBarry Smith   PetscInt       i;
4091273d9f13SBarry Smith 
4092273d9f13SBarry Smith   PetscFunctionBegin;
40932576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
4094a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
4095c461c341SBarry Smith     skipallocation = PETSC_TRUE;
4096c461c341SBarry Smith     nz             = 0;
4097c461c341SBarry Smith   }
409826283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
409926283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4100899cda47SBarry Smith 
4101435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
410260e0710aSBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
4103cf9c20a2SJed Brown   if (PetscUnlikelyDebug(nnz)) {
4104d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
410560e0710aSBarry Smith       if (nnz[i] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %D value %D",i,nnz[i]);
410660e0710aSBarry Smith       if (nnz[i] > B->cmap->n) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %D value %d rowlength %D",i,nnz[i],B->cmap->n);
4107b73539f3SBarry Smith     }
4108b73539f3SBarry Smith   }
4109b73539f3SBarry Smith 
4110273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
41112205254eSKarl Rupp 
4112273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
4113273d9f13SBarry Smith 
4114ab93d7beSBarry Smith   if (!skipallocation) {
41152ee49352SLisandro Dalcin     if (!b->imax) {
4116071fcb05SBarry Smith       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
4117071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4118071fcb05SBarry Smith     }
4119071fcb05SBarry Smith     if (!b->ilen) {
4120071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
4121071fcb05SBarry Smith       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
4122071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4123071fcb05SBarry Smith     } else {
4124071fcb05SBarry Smith       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
41252ee49352SLisandro Dalcin     }
4126846b4da1SFande Kong     if (!b->ipre) {
4127846b4da1SFande Kong       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
4128846b4da1SFande Kong       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4129846b4da1SFande Kong     }
4130273d9f13SBarry Smith     if (!nnz) {
4131435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
4132c62bd62aSJed Brown       else if (nz < 0) nz = 1;
41335d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
4134d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
4135d0f46423SBarry Smith       nz = nz*B->rmap->n;
4136273d9f13SBarry Smith     } else {
4137c73702f5SBarry Smith       PetscInt64 nz64 = 0;
4138c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
4139c73702f5SBarry Smith       ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr);
4140273d9f13SBarry Smith     }
4141ab93d7beSBarry Smith 
4142273d9f13SBarry Smith     /* allocate the matrix space */
414353dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
41442ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
4145396832f4SHong Zhang     if (B->structure_only) {
41465848002fSHong Zhang       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
41475848002fSHong Zhang       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
4148396832f4SHong Zhang       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
4149396832f4SHong Zhang     } else {
4150dcca6d9dSJed Brown       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
41513bb1ff40SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
4152396832f4SHong Zhang     }
4153bfeeae90SHong Zhang     b->i[0] = 0;
4154d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
41555da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
41565da197adSKris Buschelman     }
4157396832f4SHong Zhang     if (B->structure_only) {
4158396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
4159396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
4160396832f4SHong Zhang     } else {
4161273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
4162e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
4163396832f4SHong Zhang     }
4164e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
4165c461c341SBarry Smith   } else {
4166e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
4167e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
4168c461c341SBarry Smith   }
4169273d9f13SBarry Smith 
4170846b4da1SFande Kong   if (b->ipre && nnz != b->ipre  && b->imax) {
4171846b4da1SFande Kong     /* reserve user-requested sparsity */
4172580bdb30SBarry Smith     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
4173846b4da1SFande Kong   }
4174846b4da1SFande Kong 
4175273d9f13SBarry Smith   b->nz               = 0;
4176273d9f13SBarry Smith   b->maxnz            = nz;
4177273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
41782205254eSKarl Rupp   if (realalloc) {
41792205254eSKarl Rupp     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
41802205254eSKarl Rupp   }
4181cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
4182cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
4183273d9f13SBarry Smith   PetscFunctionReturn(0);
4184273d9f13SBarry Smith }
4185273d9f13SBarry Smith 
4186846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
4187846b4da1SFande Kong {
4188846b4da1SFande Kong   Mat_SeqAIJ     *a;
4189a5bbaf83SFande Kong   PetscInt       i;
4190846b4da1SFande Kong   PetscErrorCode ierr;
4191846b4da1SFande Kong 
4192846b4da1SFande Kong   PetscFunctionBegin;
4193846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
419414d0e64fSAlex Lindsay 
419514d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
419614d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
419714d0e64fSAlex Lindsay 
4198846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
41992c814fdeSFande Kong   /* if no saved info, we error out */
4200fb4dc15dSAlex Lindsay   if (!a->ipre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info \n");
42012c814fdeSFande Kong 
4202fb4dc15dSAlex Lindsay   if (!a->i || !a->j || !a->a || !a->imax || !a->ilen) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Memory info is incomplete, and can not reset preallocation \n");
42032c814fdeSFande Kong 
4204580bdb30SBarry Smith   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
4205580bdb30SBarry Smith   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
4206846b4da1SFande Kong   a->i[0] = 0;
4207846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
4208846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
4209846b4da1SFande Kong   }
4210846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
4211846b4da1SFande Kong   a->nz               = 0;
4212846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
4213846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
4214846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4215846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4216846b4da1SFande Kong   PetscFunctionReturn(0);
4217846b4da1SFande Kong }
4218846b4da1SFande Kong 
421958d36128SBarry Smith /*@
4220a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4221a1661176SMatthew Knepley 
4222a1661176SMatthew Knepley    Input Parameters:
4223a1661176SMatthew Knepley +  B - the matrix
4224a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4225a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4226a1661176SMatthew Knepley -  v - optional values in the matrix
4227a1661176SMatthew Knepley 
4228a1661176SMatthew Knepley    Level: developer
4229a1661176SMatthew Knepley 
42306a9b8d82SBarry Smith    Notes:
423158d36128SBarry Smith       The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
423258d36128SBarry Smith 
42336a9b8d82SBarry Smith       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
42346a9b8d82SBarry Smith       structure will be the union of all the previous nonzero structures.
42356a9b8d82SBarry Smith 
42366a9b8d82SBarry Smith     Developer Notes:
42376a9b8d82SBarry 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
42386a9b8d82SBarry Smith       then just copies the v values directly with PetscMemcpy().
42396a9b8d82SBarry Smith 
42406a9b8d82SBarry Smith       This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them.
42416a9b8d82SBarry Smith 
42426a9b8d82SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ, MatResetPreallocation()
4243a1661176SMatthew Knepley @*/
4244a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4245a1661176SMatthew Knepley {
4246a1661176SMatthew Knepley   PetscErrorCode ierr;
4247a1661176SMatthew Knepley 
4248a1661176SMatthew Knepley   PetscFunctionBegin;
42490700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
42506ba663aaSJed Brown   PetscValidType(B,1);
42514ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
4252a1661176SMatthew Knepley   PetscFunctionReturn(0);
4253a1661176SMatthew Knepley }
4254a1661176SMatthew Knepley 
42557087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4256a1661176SMatthew Knepley {
4257a1661176SMatthew Knepley   PetscInt       i;
4258a1661176SMatthew Knepley   PetscInt       m,n;
4259a1661176SMatthew Knepley   PetscInt       nz;
42606a9b8d82SBarry Smith   PetscInt       *nnz;
4261a1661176SMatthew Knepley   PetscErrorCode ierr;
4262a1661176SMatthew Knepley 
4263a1661176SMatthew Knepley   PetscFunctionBegin;
426465e19b50SBarry Smith   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
4265779a8d59SSatish Balay 
4266779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4267779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4268779a8d59SSatish Balay 
4269779a8d59SSatish Balay   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
4270854ce69bSBarry Smith   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
4271a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4272b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
427365e19b50SBarry Smith     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
4274a1661176SMatthew Knepley     nnz[i] = nz;
4275a1661176SMatthew Knepley   }
4276a1661176SMatthew Knepley   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
4277a1661176SMatthew Knepley   ierr = PetscFree(nnz);CHKERRQ(ierr);
4278a1661176SMatthew Knepley 
4279a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4280071fcb05SBarry Smith     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
4281a1661176SMatthew Knepley   }
4282a1661176SMatthew Knepley 
4283a1661176SMatthew Knepley   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4284a1661176SMatthew Knepley   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4285a1661176SMatthew Knepley 
42867827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4287a1661176SMatthew Knepley   PetscFunctionReturn(0);
4288a1661176SMatthew Knepley }
4289a1661176SMatthew Knepley 
4290ad7e164aSPierre Jolivet /*@
4291ad7e164aSPierre Jolivet    MatSeqAIJKron - Computes C, the Kronecker product of A and B.
4292ad7e164aSPierre Jolivet 
4293ad7e164aSPierre Jolivet    Input Parameters:
4294ad7e164aSPierre Jolivet +  A - left-hand side matrix
4295ad7e164aSPierre Jolivet .  B - right-hand side matrix
4296ad7e164aSPierre Jolivet -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
4297ad7e164aSPierre Jolivet 
4298ad7e164aSPierre Jolivet    Output Parameter:
4299ad7e164aSPierre Jolivet .  C - Kronecker product of A and B
4300ad7e164aSPierre Jolivet 
4301ad7e164aSPierre Jolivet    Level: intermediate
4302ad7e164aSPierre Jolivet 
4303ad7e164aSPierre Jolivet    Notes:
4304ad7e164aSPierre 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().
4305ad7e164aSPierre Jolivet 
4306ad7e164aSPierre Jolivet .seealso: MatCreateSeqAIJ(), MATSEQAIJ, MATKAIJ, MatReuse
4307ad7e164aSPierre Jolivet @*/
4308ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron(Mat A,Mat B,MatReuse reuse,Mat *C)
4309ad7e164aSPierre Jolivet {
4310ad7e164aSPierre Jolivet   PetscErrorCode ierr;
4311ad7e164aSPierre Jolivet 
4312ad7e164aSPierre Jolivet   PetscFunctionBegin;
4313ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4314ad7e164aSPierre Jolivet   PetscValidType(A,1);
4315ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4316ad7e164aSPierre Jolivet   PetscValidType(B,2);
4317ad7e164aSPierre Jolivet   PetscValidPointer(C,4);
4318ad7e164aSPierre Jolivet   if (reuse == MAT_REUSE_MATRIX) {
4319ad7e164aSPierre Jolivet     PetscValidHeaderSpecific(*C,MAT_CLASSID,4);
4320ad7e164aSPierre Jolivet     PetscValidType(*C,4);
4321ad7e164aSPierre Jolivet   }
4322ad7e164aSPierre Jolivet   ierr = PetscTryMethod(A,"MatSeqAIJKron_C",(Mat,Mat,MatReuse,Mat*),(A,B,reuse,C));CHKERRQ(ierr);
4323ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4324ad7e164aSPierre Jolivet }
4325ad7e164aSPierre Jolivet 
4326ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A,Mat B,MatReuse reuse,Mat *C)
4327ad7e164aSPierre Jolivet {
4328ad7e164aSPierre Jolivet   Mat            newmat;
4329ad7e164aSPierre Jolivet   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
4330ad7e164aSPierre Jolivet   Mat_SeqAIJ     *b = (Mat_SeqAIJ*)B->data;
4331ad7e164aSPierre Jolivet   PetscScalar    *v;
4332ad7e164aSPierre 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;
4333ad7e164aSPierre Jolivet   PetscBool      flg;
4334ad7e164aSPierre Jolivet   PetscErrorCode ierr;
4335ad7e164aSPierre Jolivet 
4336ad7e164aSPierre Jolivet   PetscFunctionBegin;
4337ad7e164aSPierre Jolivet   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4338ad7e164aSPierre Jolivet   if (!A->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4339ad7e164aSPierre Jolivet   if (B->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4340ad7e164aSPierre Jolivet   if (!B->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4341ad7e164aSPierre Jolivet   ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&flg);CHKERRQ(ierr);
4342ad7e164aSPierre Jolivet   if (!flg) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatType %s",((PetscObject)B)->type_name);
4343ad7e164aSPierre Jolivet   if (reuse != MAT_INITIAL_MATRIX && reuse != MAT_REUSE_MATRIX) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatReuse %d",(int)reuse);
4344ad7e164aSPierre Jolivet   if (reuse == MAT_INITIAL_MATRIX) {
4345ad7e164aSPierre Jolivet     ierr = PetscMalloc2(am*bm+1,&i,a->i[am]*b->i[bm],&j);CHKERRQ(ierr);
4346ad7e164aSPierre Jolivet     ierr = MatCreate(PETSC_COMM_SELF,&newmat);CHKERRQ(ierr);
4347ad7e164aSPierre Jolivet     ierr = MatSetSizes(newmat,am*bm,an*bn,am*bm,an*bn);CHKERRQ(ierr);
4348ad7e164aSPierre Jolivet     ierr = MatSetType(newmat,MATAIJ);CHKERRQ(ierr);
4349ad7e164aSPierre Jolivet     i[0] = 0;
4350ad7e164aSPierre Jolivet     for (m = 0; m < am; ++m) {
4351ad7e164aSPierre Jolivet       for (p = 0; p < bm; ++p) {
4352ad7e164aSPierre Jolivet         i[m*bm + p + 1] = i[m*bm + p] + (a->i[m+1] - a->i[m]) * (b->i[p+1] - b->i[p]);
4353ad7e164aSPierre Jolivet         for (n = a->i[m]; n < a->i[m+1]; ++n) {
4354ad7e164aSPierre Jolivet           for (q = b->i[p]; q < b->i[p+1]; ++q) {
4355ad7e164aSPierre Jolivet             j[nnz++] = a->j[n]*bn + b->j[q];
4356ad7e164aSPierre Jolivet           }
4357ad7e164aSPierre Jolivet         }
4358ad7e164aSPierre Jolivet       }
4359ad7e164aSPierre Jolivet     }
4360ad7e164aSPierre Jolivet     ierr = MatSeqAIJSetPreallocationCSR(newmat,i,j,NULL);CHKERRQ(ierr);
4361ad7e164aSPierre Jolivet     *C = newmat;
4362ad7e164aSPierre Jolivet     ierr = PetscFree2(i,j);CHKERRQ(ierr);
4363ad7e164aSPierre Jolivet     nnz = 0;
4364ad7e164aSPierre Jolivet   }
4365ad7e164aSPierre Jolivet   ierr = MatSeqAIJGetArray(*C,&v);CHKERRQ(ierr);
4366ad7e164aSPierre Jolivet   for (m = 0; m < am; ++m) {
4367ad7e164aSPierre Jolivet     for (p = 0; p < bm; ++p) {
4368ad7e164aSPierre Jolivet       for (n = a->i[m]; n < a->i[m+1]; ++n) {
4369ad7e164aSPierre Jolivet         for (q = b->i[p]; q < b->i[p+1]; ++q) {
4370ad7e164aSPierre Jolivet           v[nnz++] = a->a[n] * b->a[q];
4371ad7e164aSPierre Jolivet         }
4372ad7e164aSPierre Jolivet       }
4373ad7e164aSPierre Jolivet     }
4374ad7e164aSPierre Jolivet   }
4375ad7e164aSPierre Jolivet   ierr = MatSeqAIJRestoreArray(*C,&v);CHKERRQ(ierr);
4376ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4377ad7e164aSPierre Jolivet }
4378ad7e164aSPierre Jolivet 
4379c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4380af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4381170fe5c8SBarry Smith 
4382170fe5c8SBarry Smith /*
4383170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4384170fe5c8SBarry Smith 
4385170fe5c8SBarry Smith                n                       p                          p
43862da392ccSBarry Smith         [             ]       [             ]         [                 ]
43872da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
43882da392ccSBarry Smith         [             ]       [             ]         [                 ]
4389170fe5c8SBarry Smith 
4390170fe5c8SBarry Smith */
4391170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4392170fe5c8SBarry Smith {
4393170fe5c8SBarry Smith   PetscErrorCode    ierr;
4394170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4395170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4396170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
439786214ceeSStefano Zampini   PetscInt          i,j,n,m,q,p;
4398170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4399170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4400170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
440186214ceeSStefano Zampini   PetscInt          clda = sub_c->lda;
440286214ceeSStefano Zampini   PetscInt          alda = sub_a->lda;
4403170fe5c8SBarry Smith 
4404170fe5c8SBarry Smith   PetscFunctionBegin;
4405d0f46423SBarry Smith   m    = A->rmap->n;
4406d0f46423SBarry Smith   n    = A->cmap->n;
4407d0f46423SBarry Smith   p    = B->cmap->n;
4408170fe5c8SBarry Smith   a    = sub_a->v;
4409170fe5c8SBarry Smith   b    = sub_b->a;
4410170fe5c8SBarry Smith   c    = sub_c->v;
441186214ceeSStefano Zampini   if (clda == m) {
4412580bdb30SBarry Smith     ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
441386214ceeSStefano Zampini   } else {
441486214ceeSStefano Zampini     for (j=0;j<p;j++)
441586214ceeSStefano Zampini       for (i=0;i<m;i++)
441686214ceeSStefano Zampini         c[j*clda + i] = 0.0;
441786214ceeSStefano Zampini   }
4418170fe5c8SBarry Smith   ii  = sub_b->i;
4419170fe5c8SBarry Smith   idx = sub_b->j;
4420170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4421170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4422170fe5c8SBarry Smith     while (q-->0) {
442386214ceeSStefano Zampini       c_q = c + clda*(*idx);
442486214ceeSStefano Zampini       a_q = a + alda*i;
4425854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4426170fe5c8SBarry Smith       idx++;
4427170fe5c8SBarry Smith       b++;
4428170fe5c8SBarry Smith     }
4429170fe5c8SBarry Smith   }
4430170fe5c8SBarry Smith   PetscFunctionReturn(0);
4431170fe5c8SBarry Smith }
4432170fe5c8SBarry Smith 
44334222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C)
4434170fe5c8SBarry Smith {
4435170fe5c8SBarry Smith   PetscErrorCode ierr;
4436d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
443786214ceeSStefano Zampini   PetscBool      cisdense;
4438170fe5c8SBarry Smith 
4439170fe5c8SBarry Smith   PetscFunctionBegin;
444060e0710aSBarry Smith   if (A->cmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %D != B->rmap->n %D\n",A->cmap->n,B->rmap->n);
44414222ddf1SHong Zhang   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
44424222ddf1SHong Zhang   ierr = MatSetBlockSizesFromMats(C,A,B);CHKERRQ(ierr);
444386214ceeSStefano Zampini   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
444486214ceeSStefano Zampini   if (!cisdense) {
444586214ceeSStefano Zampini     ierr = MatSetType(C,MATDENSE);CHKERRQ(ierr);
444686214ceeSStefano Zampini   }
444786214ceeSStefano Zampini   ierr = MatSetUp(C);CHKERRQ(ierr);
4448d73949e8SHong Zhang 
44494222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4450170fe5c8SBarry Smith   PetscFunctionReturn(0);
4451170fe5c8SBarry Smith }
4452170fe5c8SBarry Smith 
4453170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
44540bad9183SKris Buschelman /*MC
4455fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
44560bad9183SKris Buschelman    based on compressed sparse row format.
44570bad9183SKris Buschelman 
44580bad9183SKris Buschelman    Options Database Keys:
44590bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
44600bad9183SKris Buschelman 
44610bad9183SKris Buschelman    Level: beginner
44620bad9183SKris Buschelman 
44630cd7f59aSBarry Smith    Notes:
44640cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
44650cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
44660cd7f59aSBarry Smith     in the matrix
44670cd7f59aSBarry Smith 
44680cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
44690cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
44700cd7f59aSBarry Smith 
44710cd7f59aSBarry Smith   Developer Notes:
44720cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
44730cd7f59aSBarry Smith 
4474f587520bSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
44750bad9183SKris Buschelman M*/
44760bad9183SKris Buschelman 
4477ccd284c7SBarry Smith /*MC
4478ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4479ccd284c7SBarry Smith 
4480ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4481ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
44820cd7f59aSBarry Smith   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation() is supported
4483ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4484ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4485ccd284c7SBarry Smith 
4486ccd284c7SBarry Smith    Options Database Keys:
4487ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4488ccd284c7SBarry Smith 
448995452b02SPatrick Sanan   Developer Notes:
4490ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4491ccd284c7SBarry Smith    enough exist.
4492ccd284c7SBarry Smith 
4493ccd284c7SBarry Smith   Level: beginner
4494ccd284c7SBarry Smith 
4495ccd284c7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ
4496ccd284c7SBarry Smith M*/
4497ccd284c7SBarry Smith 
4498ccd284c7SBarry Smith /*MC
4499ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4500ccd284c7SBarry Smith 
4501ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4502ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4503ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4504ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4505ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4506ccd284c7SBarry Smith 
4507ccd284c7SBarry Smith    Options Database Keys:
4508ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4509ccd284c7SBarry Smith 
4510ccd284c7SBarry Smith   Level: beginner
4511ccd284c7SBarry Smith 
4512ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4513ccd284c7SBarry Smith M*/
4514ccd284c7SBarry Smith 
45157906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
45167906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
45177906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
45187906f579SHong Zhang #endif
4519d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4520d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*);
4521d24d4204SJose E. Roman #endif
45227906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
45237906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
45247906f579SHong Zhang #endif
45257906f579SHong Zhang 
4526d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4527c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
45284222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
45297906f579SHong Zhang 
45308c778c55SBarry Smith /*@C
45318f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
45328c778c55SBarry Smith 
45338c778c55SBarry Smith    Not Collective
45348c778c55SBarry Smith 
45358c778c55SBarry Smith    Input Parameter:
4536579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
45378c778c55SBarry Smith 
45388c778c55SBarry Smith    Output Parameter:
45398c778c55SBarry Smith .   array - pointer to the data
45408c778c55SBarry Smith 
45418c778c55SBarry Smith    Level: intermediate
45428c778c55SBarry Smith 
4543774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
45448c778c55SBarry Smith @*/
45458c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
45468c778c55SBarry Smith {
45478c778c55SBarry Smith   PetscErrorCode ierr;
4548*d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
45498c778c55SBarry Smith 
45508c778c55SBarry Smith   PetscFunctionBegin;
4551*d67d9f35SJunchao Zhang   if (aij->ops->getarray) {
4552*d67d9f35SJunchao Zhang     ierr = (*aij->ops->getarray)(A,array);CHKERRQ(ierr);
4553*d67d9f35SJunchao Zhang   } else {
4554*d67d9f35SJunchao Zhang     *array = aij->a;
4555*d67d9f35SJunchao Zhang   }
4556*d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4557*d67d9f35SJunchao Zhang }
4558*d67d9f35SJunchao Zhang 
4559*d67d9f35SJunchao Zhang /*@C
4560*d67d9f35SJunchao Zhang    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
4561*d67d9f35SJunchao Zhang 
4562*d67d9f35SJunchao Zhang    Not Collective
4563*d67d9f35SJunchao Zhang 
4564*d67d9f35SJunchao Zhang    Input Parameters:
4565*d67d9f35SJunchao Zhang +  mat - a MATSEQAIJ matrix
4566*d67d9f35SJunchao Zhang -  array - pointer to the data
4567*d67d9f35SJunchao Zhang 
4568*d67d9f35SJunchao Zhang    Level: intermediate
4569*d67d9f35SJunchao Zhang 
4570*d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
4571*d67d9f35SJunchao Zhang @*/
4572*d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
4573*d67d9f35SJunchao Zhang {
4574*d67d9f35SJunchao Zhang   PetscErrorCode ierr;
4575*d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4576*d67d9f35SJunchao Zhang 
4577*d67d9f35SJunchao Zhang   PetscFunctionBegin;
4578*d67d9f35SJunchao Zhang   if (aij->ops->restorearray) {
4579*d67d9f35SJunchao Zhang     ierr = (*aij->ops->restorearray)(A,array);CHKERRQ(ierr);
4580*d67d9f35SJunchao Zhang   } else {
4581*d67d9f35SJunchao Zhang     *array = NULL;
4582*d67d9f35SJunchao Zhang   }
45838c778c55SBarry Smith   PetscFunctionReturn(0);
45848c778c55SBarry Smith }
45858c778c55SBarry Smith 
458621e72a00SBarry Smith /*@C
45878f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
45888f1ea47aSStefano Zampini 
45898f1ea47aSStefano Zampini    Not Collective
45908f1ea47aSStefano Zampini 
45918f1ea47aSStefano Zampini    Input Parameter:
45928f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
45938f1ea47aSStefano Zampini 
45948f1ea47aSStefano Zampini    Output Parameter:
45958f1ea47aSStefano Zampini .   array - pointer to the data
45968f1ea47aSStefano Zampini 
45978f1ea47aSStefano Zampini    Level: intermediate
45988f1ea47aSStefano Zampini 
45998f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
46008f1ea47aSStefano Zampini @*/
46018f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
46028f1ea47aSStefano Zampini {
46038f1ea47aSStefano Zampini   PetscErrorCode ierr;
4604*d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
46058f1ea47aSStefano Zampini 
46068f1ea47aSStefano Zampini   PetscFunctionBegin;
4607*d67d9f35SJunchao Zhang   if (aij->ops->getarrayread) {
4608*d67d9f35SJunchao Zhang     ierr = (*aij->ops->getarrayread)(A,array);CHKERRQ(ierr);
4609*d67d9f35SJunchao Zhang   } else {
4610*d67d9f35SJunchao Zhang     *array = aij->a;
4611*d67d9f35SJunchao Zhang   }
46128f1ea47aSStefano Zampini   PetscFunctionReturn(0);
46138f1ea47aSStefano Zampini }
46148f1ea47aSStefano Zampini 
46158f1ea47aSStefano Zampini /*@C
46168f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
46178f1ea47aSStefano Zampini 
46188f1ea47aSStefano Zampini    Not Collective
46198f1ea47aSStefano Zampini 
46208f1ea47aSStefano Zampini    Input Parameter:
46218f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
46228f1ea47aSStefano Zampini 
46238f1ea47aSStefano Zampini    Output Parameter:
46248f1ea47aSStefano Zampini .   array - pointer to the data
46258f1ea47aSStefano Zampini 
46268f1ea47aSStefano Zampini    Level: intermediate
46278f1ea47aSStefano Zampini 
46288f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
46298f1ea47aSStefano Zampini @*/
46308f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
46318f1ea47aSStefano Zampini {
46328f1ea47aSStefano Zampini   PetscErrorCode ierr;
4633*d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
46348f1ea47aSStefano Zampini 
46358f1ea47aSStefano Zampini   PetscFunctionBegin;
4636*d67d9f35SJunchao Zhang   if (aij->ops->restorearrayread) {
4637*d67d9f35SJunchao Zhang     ierr = (*aij->ops->restorearrayread)(A,array);CHKERRQ(ierr);
4638*d67d9f35SJunchao Zhang   } else {
4639*d67d9f35SJunchao Zhang     *array = NULL;
4640*d67d9f35SJunchao Zhang   }
4641*d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4642*d67d9f35SJunchao Zhang }
4643*d67d9f35SJunchao Zhang 
4644*d67d9f35SJunchao Zhang /*@C
4645*d67d9f35SJunchao Zhang    MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a MATSEQAIJ matrix is stored
4646*d67d9f35SJunchao Zhang 
4647*d67d9f35SJunchao Zhang    Not Collective
4648*d67d9f35SJunchao Zhang 
4649*d67d9f35SJunchao Zhang    Input Parameter:
4650*d67d9f35SJunchao Zhang .  mat - a MATSEQAIJ matrix
4651*d67d9f35SJunchao Zhang 
4652*d67d9f35SJunchao Zhang    Output Parameter:
4653*d67d9f35SJunchao Zhang .   array - pointer to the data
4654*d67d9f35SJunchao Zhang 
4655*d67d9f35SJunchao Zhang    Level: intermediate
4656*d67d9f35SJunchao Zhang 
4657*d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
4658*d67d9f35SJunchao Zhang @*/
4659*d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJGetArrayWrite(Mat A,PetscScalar **array)
4660*d67d9f35SJunchao Zhang {
4661*d67d9f35SJunchao Zhang   PetscErrorCode ierr;
4662*d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4663*d67d9f35SJunchao Zhang 
4664*d67d9f35SJunchao Zhang   PetscFunctionBegin;
4665*d67d9f35SJunchao Zhang   if (aij->ops->getarraywrite) {
4666*d67d9f35SJunchao Zhang     ierr = (*aij->ops->getarraywrite)(A,array);CHKERRQ(ierr);
4667*d67d9f35SJunchao Zhang   } else {
4668*d67d9f35SJunchao Zhang     *array = aij->a;
4669*d67d9f35SJunchao Zhang   }
4670*d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4671*d67d9f35SJunchao Zhang }
4672*d67d9f35SJunchao Zhang 
4673*d67d9f35SJunchao Zhang /*@C
4674*d67d9f35SJunchao Zhang    MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead
4675*d67d9f35SJunchao Zhang 
4676*d67d9f35SJunchao Zhang    Not Collective
4677*d67d9f35SJunchao Zhang 
4678*d67d9f35SJunchao Zhang    Input Parameter:
4679*d67d9f35SJunchao Zhang .  mat - a MATSEQAIJ matrix
4680*d67d9f35SJunchao Zhang 
4681*d67d9f35SJunchao Zhang    Output Parameter:
4682*d67d9f35SJunchao Zhang .   array - pointer to the data
4683*d67d9f35SJunchao Zhang 
4684*d67d9f35SJunchao Zhang    Level: intermediate
4685*d67d9f35SJunchao Zhang 
4686*d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
4687*d67d9f35SJunchao Zhang @*/
4688*d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJRestoreArrayWrite(Mat A,PetscScalar **array)
4689*d67d9f35SJunchao Zhang {
4690*d67d9f35SJunchao Zhang   PetscErrorCode ierr;
4691*d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4692*d67d9f35SJunchao Zhang 
4693*d67d9f35SJunchao Zhang   PetscFunctionBegin;
4694*d67d9f35SJunchao Zhang   if (aij->ops->restorearraywrite) {
4695*d67d9f35SJunchao Zhang     ierr = (*aij->ops->restorearraywrite)(A,array);CHKERRQ(ierr);
4696*d67d9f35SJunchao Zhang   } else {
4697*d67d9f35SJunchao Zhang     *array = NULL;
4698*d67d9f35SJunchao Zhang   }
46998f1ea47aSStefano Zampini   PetscFunctionReturn(0);
47008f1ea47aSStefano Zampini }
47018f1ea47aSStefano Zampini 
47028f1ea47aSStefano Zampini /*@C
470321e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
470421e72a00SBarry Smith 
470521e72a00SBarry Smith    Not Collective
470621e72a00SBarry Smith 
470721e72a00SBarry Smith    Input Parameter:
4708579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
470921e72a00SBarry Smith 
471021e72a00SBarry Smith    Output Parameter:
471121e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
471221e72a00SBarry Smith 
471321e72a00SBarry Smith    Level: intermediate
471421e72a00SBarry Smith 
471521e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
471621e72a00SBarry Smith @*/
471721e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
471821e72a00SBarry Smith {
471921e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
472021e72a00SBarry Smith 
472121e72a00SBarry Smith   PetscFunctionBegin;
472221e72a00SBarry Smith   *nz = aij->rmax;
472321e72a00SBarry Smith   PetscFunctionReturn(0);
472421e72a00SBarry Smith }
472521e72a00SBarry Smith 
472634b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
47275063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat,MatType,MatReuse,Mat*);
472802fe1965SBarry Smith #endif
47293d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
47305063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat,MatType,MatReuse,Mat*);
47313d0639e7SStefano Zampini #endif
473202fe1965SBarry Smith 
47338cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4734273d9f13SBarry Smith {
4735273d9f13SBarry Smith   Mat_SeqAIJ     *b;
4736dfbe8321SBarry Smith   PetscErrorCode ierr;
473738baddfdSBarry Smith   PetscMPIInt    size;
4738273d9f13SBarry Smith 
4739273d9f13SBarry Smith   PetscFunctionBegin;
4740ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRMPI(ierr);
4741e32f2f54SBarry Smith   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4742273d9f13SBarry Smith 
4743b00a9115SJed Brown   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
47442205254eSKarl Rupp 
4745b0a32e0cSBarry Smith   B->data = (void*)b;
47462205254eSKarl Rupp 
4747549d3d68SSatish Balay   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4748071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
47492205254eSKarl Rupp 
4750f4259b30SLisandro Dalcin   b->row                = NULL;
4751f4259b30SLisandro Dalcin   b->col                = NULL;
4752f4259b30SLisandro Dalcin   b->icol               = NULL;
4753b810aeb4SBarry Smith   b->reallocs           = 0;
475436db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4755f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4756416022c9SBarry Smith   b->nonew              = 0;
4757f4259b30SLisandro Dalcin   b->diag               = NULL;
4758f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4759f4259b30SLisandro Dalcin   B->spptr              = NULL;
4760f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4761f4259b30SLisandro Dalcin   b->idiag              = NULL;
4762f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4763f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
476471f1c65dSBarry Smith   b->omega              = 1.0;
476571f1c65dSBarry Smith   b->fshift             = 0.0;
476671f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4767bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4768a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
476917ab2063SBarry Smith 
477035d8aa7fSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
47718c778c55SBarry Smith 
4772b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
4773bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4774bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4775b3866ffcSBarry Smith #endif
477617f1a0eaSHong Zhang 
4777bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4778bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4779bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4780bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4781bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4782bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
47834dfdc2d9SRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
47849779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
47854a2a386eSRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4786191b95cbSRichard Tran Mills #endif
478734b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
478802fe1965SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
47894222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4790fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
479102fe1965SBarry Smith #endif
47923d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
47933d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
47943d0639e7SStefano Zampini #endif
4795bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4796af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
4797af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4798af8000cdSHong Zhang #endif
4799d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4800d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK);CHKERRQ(ierr);
4801d24d4204SJose E. Roman #endif
480263c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
480363c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
48044222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ);CHKERRQ(ierr);
480563c07aadSStefano Zampini #endif
4806b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4807d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4808c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4809bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4810bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4811bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4812846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4813bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4814bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
48154222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ);CHKERRQ(ierr);
48164222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ);CHKERRQ(ierr);
48174222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4818ad7e164aSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJKron_C",MatSeqAIJKron_SeqAIJ);CHKERRQ(ierr);
48194108e4d5SBarry Smith   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
482017667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
48214099cc6bSBarry Smith   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
48223a40ed3dSBarry Smith   PetscFunctionReturn(0);
482317ab2063SBarry Smith }
482417ab2063SBarry Smith 
4825b24902e0SBarry Smith /*
4826b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4827b24902e0SBarry Smith */
4828ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
482917ab2063SBarry Smith {
48302a350339SBarry Smith   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data;
48316849ba73SBarry Smith   PetscErrorCode ierr;
4832071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
483317ab2063SBarry Smith 
48343a40ed3dSBarry Smith   PetscFunctionBegin;
4835ca133879SJose E. Roman   if (!A->assembled && cpvalues!=MAT_DO_NOT_COPY_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix");
4836273d9f13SBarry Smith 
4837d5f3da31SBarry Smith   C->factortype = A->factortype;
4838f4259b30SLisandro Dalcin   c->row        = NULL;
4839f4259b30SLisandro Dalcin   c->col        = NULL;
4840f4259b30SLisandro Dalcin   c->icol       = NULL;
48416ad4291fSHong Zhang   c->reallocs   = 0;
484217ab2063SBarry Smith 
48436ad4291fSHong Zhang   C->assembled = PETSC_TRUE;
484417ab2063SBarry Smith 
4845aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4846aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4847eec197d1SBarry Smith 
4848071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4849071fcb05SBarry Smith   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4850071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4851071fcb05SBarry Smith   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
48523bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
485317ab2063SBarry Smith 
485417ab2063SBarry Smith   /* allocate the matrix space */
4855f77e22a1SHong Zhang   if (mallocmatspace) {
4856dcca6d9dSJed Brown     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
48573bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
48582205254eSKarl Rupp 
4859f1e2ffcdSBarry Smith     c->singlemalloc = PETSC_TRUE;
48602205254eSKarl Rupp 
4861580bdb30SBarry Smith     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
486217ab2063SBarry Smith     if (m > 0) {
4863580bdb30SBarry Smith       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4864be6bf707SBarry Smith       if (cpvalues == MAT_COPY_VALUES) {
48652e5835c6SStefano Zampini         const PetscScalar *aa;
48662e5835c6SStefano Zampini 
48672e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
48682e5835c6SStefano Zampini         ierr = PetscArraycpy(c->a,aa,a->i[m]);CHKERRQ(ierr);
48692e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
4870be6bf707SBarry Smith       } else {
4871580bdb30SBarry Smith         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
487217ab2063SBarry Smith       }
487308480c60SBarry Smith     }
4874f77e22a1SHong Zhang   }
487517ab2063SBarry Smith 
48766ad4291fSHong Zhang   c->ignorezeroentries = a->ignorezeroentries;
4877416022c9SBarry Smith   c->roworiented       = a->roworiented;
4878416022c9SBarry Smith   c->nonew             = a->nonew;
4879416022c9SBarry Smith   if (a->diag) {
4880854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4881071fcb05SBarry Smith     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
48823bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4883071fcb05SBarry Smith   } else c->diag = NULL;
48842205254eSKarl Rupp 
4885f4259b30SLisandro Dalcin   c->solve_work         = NULL;
4886f4259b30SLisandro Dalcin   c->saved_values       = NULL;
4887f4259b30SLisandro Dalcin   c->idiag              = NULL;
4888f4259b30SLisandro Dalcin   c->ssor_work          = NULL;
4889a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
4890e6b907acSBarry Smith   c->free_a             = PETSC_TRUE;
4891e6b907acSBarry Smith   c->free_ij            = PETSC_TRUE;
48926ad4291fSHong Zhang 
4893893ad86cSHong Zhang   c->rmax         = a->rmax;
4894416022c9SBarry Smith   c->nz           = a->nz;
48958ed568f8SMatthew G Knepley   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4896273d9f13SBarry Smith   C->preallocated = PETSC_TRUE;
4897754ec7b1SSatish Balay 
48986ad4291fSHong Zhang   c->compressedrow.use   = a->compressedrow.use;
48996ad4291fSHong Zhang   c->compressedrow.nrows = a->compressedrow.nrows;
4900cd6b891eSBarry Smith   if (a->compressedrow.use) {
49016ad4291fSHong Zhang     i    = a->compressedrow.nrows;
4902dcca6d9dSJed Brown     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
4903580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
4904580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
490527ea64f8SHong Zhang   } else {
490627ea64f8SHong Zhang     c->compressedrow.use    = PETSC_FALSE;
49070298fd71SBarry Smith     c->compressedrow.i      = NULL;
49080298fd71SBarry Smith     c->compressedrow.rindex = NULL;
49096ad4291fSHong Zhang   }
4910ea632784SBarry Smith   c->nonzerorowcnt = a->nonzerorowcnt;
4911e56f5c9eSBarry Smith   C->nonzerostate  = A->nonzerostate;
49124846f1f5SKris Buschelman 
49132205254eSKarl Rupp   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
4914140e18c1SBarry Smith   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
49153a40ed3dSBarry Smith   PetscFunctionReturn(0);
491617ab2063SBarry Smith }
491717ab2063SBarry Smith 
4918b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4919b24902e0SBarry Smith {
4920b24902e0SBarry Smith   PetscErrorCode ierr;
4921b24902e0SBarry Smith 
4922b24902e0SBarry Smith   PetscFunctionBegin;
4923ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
49244b6263acSBarry Smith   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
4925cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
492633d57670SJed Brown     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
4927cfd3f464SBarry Smith   }
4928a54f2f98SBarry Smith   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
4929f77e22a1SHong Zhang   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
4930b24902e0SBarry Smith   PetscFunctionReturn(0);
4931b24902e0SBarry Smith }
4932b24902e0SBarry Smith 
4933112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4934fbdbba38SShri Abhyankar {
493552f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
493652f91c60SVaclav Hapla   PetscErrorCode ierr;
493752f91c60SVaclav Hapla 
493852f91c60SVaclav Hapla   PetscFunctionBegin;
493952f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
494052f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4941c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
4942c27b3999SVaclav Hapla   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
494352f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
494452f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
494552f91c60SVaclav Hapla   if (isbinary) {
494652f91c60SVaclav Hapla     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
494752f91c60SVaclav Hapla   } else if (ishdf5) {
494852f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
494952f91c60SVaclav Hapla     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
495052f91c60SVaclav Hapla #else
495152f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
495252f91c60SVaclav Hapla #endif
495352f91c60SVaclav Hapla   } else {
495452f91c60SVaclav Hapla     SETERRQ2(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"Viewer type %s not yet supported for reading %s matrices",((PetscObject)viewer)->type_name,((PetscObject)newMat)->type_name);
495552f91c60SVaclav Hapla   }
495652f91c60SVaclav Hapla   PetscFunctionReturn(0);
495752f91c60SVaclav Hapla }
495852f91c60SVaclav Hapla 
49593ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
496052f91c60SVaclav Hapla {
49613ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
4962fbdbba38SShri Abhyankar   PetscErrorCode ierr;
49633ea6fe3dSLisandro Dalcin   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
4964fbdbba38SShri Abhyankar 
4965fbdbba38SShri Abhyankar   PetscFunctionBegin;
49663ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
4967bbead8a2SBarry Smith 
49683ea6fe3dSLisandro Dalcin   /* read in matrix header */
49693ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
49703ea6fe3dSLisandro Dalcin   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
4971fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
49723ea6fe3dSLisandro Dalcin   if (M < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%D) in file is negative",M);
49733ea6fe3dSLisandro Dalcin   if (N < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%D) in file is negative",N);
4974bbead8a2SBarry Smith   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
4975fbdbba38SShri Abhyankar 
49763ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
49773ea6fe3dSLisandro Dalcin   ierr = MatLoad_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
49783ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
49793ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
49803ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
49813ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
49823ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
49833ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
49843ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
49853ea6fe3dSLisandro Dalcin 
49863ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
49873ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
49883ea6fe3dSLisandro Dalcin   if (M != rows || N != cols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different sizes (%D, %D) than the input matrix (%D, %D)",M,N,rows,cols);
49893ea6fe3dSLisandro Dalcin 
4990fbdbba38SShri Abhyankar   /* read in row lengths */
49913ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(M,&rowlens);CHKERRQ(ierr);
49923ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT);CHKERRQ(ierr);
49933ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
49943ea6fe3dSLisandro Dalcin   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
49953ea6fe3dSLisandro Dalcin   if (sum != nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Inconsistent matrix data in file: nonzeros = %D, sum-row-lengths = %D\n",nz,sum);
49963ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
49973ea6fe3dSLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens);CHKERRQ(ierr);
49983ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
499960e0710aSBarry Smith   if (M != rows || N != cols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%D, %D) than the input matrix (%D, %D)",M,N,rows,cols);
50003ea6fe3dSLisandro Dalcin   /* store row lengths */
50013ea6fe3dSLisandro Dalcin   ierr = PetscArraycpy(a->ilen,rowlens,M);CHKERRQ(ierr);
50023ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
5003fbdbba38SShri Abhyankar 
50043ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
50053ea6fe3dSLisandro Dalcin   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
50063ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
50073ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
50083ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
50093ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
5010fbdbba38SShri Abhyankar 
50113ea6fe3dSLisandro Dalcin   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
50123ea6fe3dSLisandro Dalcin   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5013fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
5014fbdbba38SShri Abhyankar }
5015fbdbba38SShri Abhyankar 
5016ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
50177264ac53SSatish Balay {
50187264ac53SSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
5019dfbe8321SBarry Smith   PetscErrorCode ierr;
5020eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
5021eeffb40dSHong Zhang   PetscInt k;
5022eeffb40dSHong Zhang #endif
50237264ac53SSatish Balay 
50243a40ed3dSBarry Smith   PetscFunctionBegin;
5025bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
5026d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
5027ca44d042SBarry Smith     *flg = PETSC_FALSE;
5028ca44d042SBarry Smith     PetscFunctionReturn(0);
5029bcd2baecSBarry Smith   }
50307264ac53SSatish Balay 
50317264ac53SSatish Balay   /* if the a->i are the same */
5032580bdb30SBarry Smith   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
5033abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
50347264ac53SSatish Balay 
50357264ac53SSatish Balay   /* if a->j are the same */
5036580bdb30SBarry Smith   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
5037abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
5038bcd2baecSBarry Smith 
5039bcd2baecSBarry Smith   /* if a->a are the same */
5040eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
5041eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
5042eeffb40dSHong Zhang     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])) {
5043eeffb40dSHong Zhang       *flg = PETSC_FALSE;
50443a40ed3dSBarry Smith       PetscFunctionReturn(0);
5045eeffb40dSHong Zhang     }
5046eeffb40dSHong Zhang   }
5047eeffb40dSHong Zhang #else
5048580bdb30SBarry Smith   ierr = PetscArraycmp(a->a,b->a,a->nz,flg);CHKERRQ(ierr);
5049eeffb40dSHong Zhang #endif
5050eeffb40dSHong Zhang   PetscFunctionReturn(0);
50517264ac53SSatish Balay }
505236db0b34SBarry Smith 
505305869f15SSatish Balay /*@
505436db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
505536db0b34SBarry Smith               provided by the user.
505636db0b34SBarry Smith 
5057d083f849SBarry Smith       Collective
505836db0b34SBarry Smith 
505936db0b34SBarry Smith    Input Parameters:
506036db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
506136db0b34SBarry Smith .   m - number of rows
506236db0b34SBarry Smith .   n - number of columns
5063483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
506436db0b34SBarry Smith .   j - column indices
506536db0b34SBarry Smith -   a - matrix values
506636db0b34SBarry Smith 
506736db0b34SBarry Smith    Output Parameter:
506836db0b34SBarry Smith .   mat - the matrix
506936db0b34SBarry Smith 
507036db0b34SBarry Smith    Level: intermediate
507136db0b34SBarry Smith 
507236db0b34SBarry Smith    Notes:
50730551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
5074292fb18eSBarry Smith     once the matrix is destroyed and not before
507536db0b34SBarry Smith 
507636db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
507736db0b34SBarry Smith 
5078bfeeae90SHong Zhang        The i and j indices are 0 based
507936db0b34SBarry Smith 
5080a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
5081a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
50828eef79e4SBarry Smith     as shown
5083a4552177SSatish Balay 
50848eef79e4SBarry Smith $        1 0 0
50858eef79e4SBarry Smith $        2 0 3
50868eef79e4SBarry Smith $        4 5 6
50878eef79e4SBarry Smith $
50888eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
50898eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
50908eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
5091a4552177SSatish Balay 
509269b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
509336db0b34SBarry Smith 
509436db0b34SBarry Smith @*/
5095c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
509636db0b34SBarry Smith {
5097dfbe8321SBarry Smith   PetscErrorCode ierr;
5098cbcfb4deSHong Zhang   PetscInt       ii;
509936db0b34SBarry Smith   Mat_SeqAIJ     *aij;
5100cbcfb4deSHong Zhang   PetscInt jj;
510136db0b34SBarry Smith 
510236db0b34SBarry Smith   PetscFunctionBegin;
510341096f02SStefano Zampini   if (m > 0 && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
5104f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
5105f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
5106a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
5107ab93d7beSBarry Smith   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
5108f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL);CHKERRQ(ierr);
5109ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
5110071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
5111071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
5112ab93d7beSBarry Smith 
511336db0b34SBarry Smith   aij->i            = i;
511436db0b34SBarry Smith   aij->j            = j;
511536db0b34SBarry Smith   aij->a            = a;
511636db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
511736db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
5118e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
5119e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
512036db0b34SBarry Smith 
512136db0b34SBarry Smith   for (ii=0; ii<m; ii++) {
512236db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
512376bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
512460e0710aSBarry Smith       if (i[ii+1] - i[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %D length = %D",ii,i[ii+1] - i[ii]);
51259985e31cSBarry Smith       for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
5126a061629eSStefano Zampini         if (j[jj] < j[jj-1]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual column %D) in row %D is not sorted",jj-i[ii],j[jj],ii);
5127a061629eSStefano Zampini         if (j[jj] == j[jj-1]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual column %D) in row %D is identical to previous entry",jj-i[ii],j[jj],ii);
51289985e31cSBarry Smith       }
512936db0b34SBarry Smith     }
513076bd3646SJed Brown   }
513176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
513236db0b34SBarry Smith     for (ii=0; ii<aij->i[m]; ii++) {
513360e0710aSBarry Smith       if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]);
513460e0710aSBarry Smith       if (j[ii] > n - 1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %D index = %D",ii,j[ii]);
513536db0b34SBarry Smith     }
513676bd3646SJed Brown   }
513736db0b34SBarry Smith 
5138b65db4caSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5139b65db4caSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
514036db0b34SBarry Smith   PetscFunctionReturn(0);
514136db0b34SBarry Smith }
514280ef6e79SMatthew G Knepley /*@C
5143d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
51448a0b0e6bSVictor Minden               provided by the user.
51458a0b0e6bSVictor Minden 
5146d083f849SBarry Smith       Collective
51478a0b0e6bSVictor Minden 
51488a0b0e6bSVictor Minden    Input Parameters:
51498a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
51508a0b0e6bSVictor Minden .   m   - number of rows
51518a0b0e6bSVictor Minden .   n   - number of columns
51528a0b0e6bSVictor Minden .   i   - row indices
51538a0b0e6bSVictor Minden .   j   - column indices
51541230e6d1SVictor Minden .   a   - matrix values
51551230e6d1SVictor Minden .   nz  - number of nonzeros
51561230e6d1SVictor Minden -   idx - 0 or 1 based
51578a0b0e6bSVictor Minden 
51588a0b0e6bSVictor Minden    Output Parameter:
51598a0b0e6bSVictor Minden .   mat - the matrix
51608a0b0e6bSVictor Minden 
51618a0b0e6bSVictor Minden    Level: intermediate
51628a0b0e6bSVictor Minden 
51638a0b0e6bSVictor Minden    Notes:
51649e99939fSJunchao Zhang        The i and j indices are 0 based. The format which is used for the sparse matrix input, is equivalent to a row-major ordering. i.e for the following matrix,
51659e99939fSJunchao Zhang        the input data expected is as shown
51669e99939fSJunchao Zhang .vb
51678a0b0e6bSVictor Minden         1 0 0
51688a0b0e6bSVictor Minden         2 0 3
51698a0b0e6bSVictor Minden         4 5 6
51708a0b0e6bSVictor Minden 
51718a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
51728a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
51738a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
51749e99939fSJunchao Zhang .ve
51758a0b0e6bSVictor Minden 
517669b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
51778a0b0e6bSVictor Minden 
51788a0b0e6bSVictor Minden @*/
5179c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
51808a0b0e6bSVictor Minden {
51818a0b0e6bSVictor Minden   PetscErrorCode ierr;
5182d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
51838a0b0e6bSVictor Minden 
51848a0b0e6bSVictor Minden   PetscFunctionBegin;
51851795a4d1SJed Brown   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
51861230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
5187c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
51881230e6d1SVictor Minden   }
51898a0b0e6bSVictor Minden   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
51908a0b0e6bSVictor Minden   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
51918a0b0e6bSVictor Minden   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
51921230e6d1SVictor Minden   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
51931230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
51941230e6d1SVictor Minden     if (idx) {
51951230e6d1SVictor Minden       row = i[ii] - 1;
51961230e6d1SVictor Minden       col = j[ii] - 1;
51971230e6d1SVictor Minden     } else {
51981230e6d1SVictor Minden       row = i[ii];
51991230e6d1SVictor Minden       col = j[ii];
52008a0b0e6bSVictor Minden     }
52011230e6d1SVictor Minden     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
52028a0b0e6bSVictor Minden   }
52038a0b0e6bSVictor Minden   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
52048a0b0e6bSVictor Minden   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5205d021a1c5SVictor Minden   ierr = PetscFree(nnz);CHKERRQ(ierr);
52068a0b0e6bSVictor Minden   PetscFunctionReturn(0);
52078a0b0e6bSVictor Minden }
520836db0b34SBarry Smith 
5209acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
5210acf2f550SJed Brown {
5211acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
5212acf2f550SJed Brown   PetscErrorCode ierr;
5213acf2f550SJed Brown 
5214acf2f550SJed Brown   PetscFunctionBegin;
5215acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
5216acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
52172205254eSKarl Rupp 
5218acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
5219acf2f550SJed Brown   PetscFunctionReturn(0);
5220acf2f550SJed Brown }
5221acf2f550SJed Brown 
52229c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
52239c8f2541SHong Zhang {
52249c8f2541SHong Zhang   PetscErrorCode ierr;
52258761c3d6SHong Zhang   PetscMPIInt    size;
52269c8f2541SHong Zhang 
52279c8f2541SHong Zhang   PetscFunctionBegin;
5228ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
52297bbdc51dSHong Zhang   if (size == 1) {
52307bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
52317bbdc51dSHong Zhang       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
52327bbdc51dSHong Zhang     } else {
52338761c3d6SHong Zhang       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
52347bbdc51dSHong Zhang     }
52358761c3d6SHong Zhang   } else {
52369c8f2541SHong Zhang     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
52378761c3d6SHong Zhang   }
52389c8f2541SHong Zhang   PetscFunctionReturn(0);
52399c8f2541SHong Zhang }
52409c8f2541SHong Zhang 
524181824310SBarry Smith /*
524253dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
524353dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
524453dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
524553dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
524653dd7562SDmitry Karpeev  */
524753dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
524853dd7562SDmitry Karpeev {
524953dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
525053dd7562SDmitry Karpeev   PetscErrorCode ierr;
525153dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
525253dd7562SDmitry Karpeev   PetscBool      seqaij;
525353dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
525453dd7562SDmitry Karpeev   PetscScalar    v;
525553dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
525653dd7562SDmitry Karpeev 
525753dd7562SDmitry Karpeev   PetscFunctionBegin;
525853dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
525953dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
52604099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
526153dd7562SDmitry Karpeev   if (!seqaij) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
526253dd7562SDmitry Karpeev   if (rowemb) {
526353dd7562SDmitry Karpeev     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
526453dd7562SDmitry Karpeev     if (m != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Row IS of size %D is incompatible with matrix row size %D",m,B->rmap->n);
526553dd7562SDmitry Karpeev   } else {
52666c4ed002SBarry Smith     if (C->rmap->n != B->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
526753dd7562SDmitry Karpeev   }
526853dd7562SDmitry Karpeev   if (colemb) {
526953dd7562SDmitry Karpeev     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
527053dd7562SDmitry Karpeev     if (n != B->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Diag col IS of size %D is incompatible with input matrix col size %D",n,B->cmap->n);
527153dd7562SDmitry Karpeev   } else {
527253dd7562SDmitry Karpeev     if (C->cmap->n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
527353dd7562SDmitry Karpeev   }
527453dd7562SDmitry Karpeev 
527553dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
527653dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
527753dd7562SDmitry Karpeev     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
527853dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
527953dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
528053dd7562SDmitry Karpeev     }
528153dd7562SDmitry Karpeev     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
528253dd7562SDmitry Karpeev     ierr = PetscFree(nz);CHKERRQ(ierr);
528353dd7562SDmitry Karpeev   }
528453dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
528553dd7562SDmitry Karpeev     ierr = MatZeroEntries(C);CHKERRQ(ierr);
528653dd7562SDmitry Karpeev   }
528753dd7562SDmitry Karpeev   count = 0;
528853dd7562SDmitry Karpeev   rowindices = NULL;
528953dd7562SDmitry Karpeev   colindices = NULL;
529053dd7562SDmitry Karpeev   if (rowemb) {
529153dd7562SDmitry Karpeev     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
529253dd7562SDmitry Karpeev   }
529353dd7562SDmitry Karpeev   if (colemb) {
529453dd7562SDmitry Karpeev     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
529553dd7562SDmitry Karpeev   }
529653dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
529753dd7562SDmitry Karpeev     PetscInt row;
529853dd7562SDmitry Karpeev     row = i;
529953dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
530053dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
530153dd7562SDmitry Karpeev       PetscInt col;
530253dd7562SDmitry Karpeev       col  = Baij->j[count];
530353dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
530453dd7562SDmitry Karpeev       v    = Baij->a[count];
530553dd7562SDmitry Karpeev       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
530653dd7562SDmitry Karpeev       ++count;
530753dd7562SDmitry Karpeev     }
530853dd7562SDmitry Karpeev   }
530953dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
531053dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
531153dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
531253dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
531353dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
531453dd7562SDmitry Karpeev   PetscFunctionReturn(0);
531553dd7562SDmitry Karpeev }
531653dd7562SDmitry Karpeev 
53174099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
53184099cc6bSBarry Smith 
53194099cc6bSBarry Smith /*@C
53204099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
53214099cc6bSBarry Smith 
53224099cc6bSBarry Smith    Collective on Mat
53234099cc6bSBarry Smith 
53244099cc6bSBarry Smith    Input Parameters:
53254099cc6bSBarry Smith +  mat      - the matrix object
53264099cc6bSBarry Smith -  matype   - matrix type
53274099cc6bSBarry Smith 
53284099cc6bSBarry Smith    Options Database Key:
53294099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
53304099cc6bSBarry Smith 
53314099cc6bSBarry Smith   Level: intermediate
53324099cc6bSBarry Smith 
53334099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
53344099cc6bSBarry Smith @*/
53354099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
53364099cc6bSBarry Smith {
5337fd9d3c67SJed Brown   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
53384099cc6bSBarry Smith   PetscBool      sametype;
53394099cc6bSBarry Smith 
53404099cc6bSBarry Smith   PetscFunctionBegin;
53414099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
53424099cc6bSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
53434099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
53444099cc6bSBarry Smith 
53454099cc6bSBarry Smith   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
53464099cc6bSBarry Smith   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
53474099cc6bSBarry Smith   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
53484099cc6bSBarry Smith   PetscFunctionReturn(0);
53494099cc6bSBarry Smith }
53504099cc6bSBarry Smith 
53514099cc6bSBarry Smith /*@C
53524099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
53534099cc6bSBarry Smith 
53544099cc6bSBarry Smith    Not Collective
53554099cc6bSBarry Smith 
53564099cc6bSBarry Smith    Input Parameters:
53574099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
53584099cc6bSBarry Smith -  function - routine to convert to subtype
53594099cc6bSBarry Smith 
53604099cc6bSBarry Smith    Notes:
53614099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
53624099cc6bSBarry Smith 
53634099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
53644099cc6bSBarry Smith $     -mat_seqaij_type my_mat
53654099cc6bSBarry Smith 
53664099cc6bSBarry Smith    Level: advanced
53674099cc6bSBarry Smith 
53684099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
53694099cc6bSBarry Smith 
53704099cc6bSBarry Smith   Level: advanced
53714099cc6bSBarry Smith @*/
5372388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
53734099cc6bSBarry Smith {
53744099cc6bSBarry Smith   PetscErrorCode ierr;
53754099cc6bSBarry Smith 
53764099cc6bSBarry Smith   PetscFunctionBegin;
53779cc31a68SJed Brown   ierr = MatInitializePackage();CHKERRQ(ierr);
53784099cc6bSBarry Smith   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
53794099cc6bSBarry Smith   PetscFunctionReturn(0);
53804099cc6bSBarry Smith }
53814099cc6bSBarry Smith 
53824099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
53834099cc6bSBarry Smith 
53844099cc6bSBarry Smith /*@C
53854099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
53864099cc6bSBarry Smith 
53874099cc6bSBarry Smith   Not Collective
53884099cc6bSBarry Smith 
53894099cc6bSBarry Smith   Level: advanced
53904099cc6bSBarry Smith 
53914099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
53924099cc6bSBarry Smith @*/
53934099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
53944099cc6bSBarry Smith {
53954099cc6bSBarry Smith   PetscErrorCode ierr;
53964099cc6bSBarry Smith 
53974099cc6bSBarry Smith   PetscFunctionBegin;
53984099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
53994099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
54004099cc6bSBarry Smith 
54014099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
54024099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
54034dfdc2d9SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
54049779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
54056b62b571SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
5406485f9817SRichard Tran Mills #endif
54075063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA)
54085063d097SStefano Zampini   ierr = MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
54095063d097SStefano Zampini #endif
54105063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
54115063d097SStefano Zampini   ierr = MatSeqAIJRegister(MATSEQAIJKOKKOS,   MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
54125063d097SStefano Zampini #endif
54134099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
54144099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
54154099cc6bSBarry Smith #endif
54164099cc6bSBarry Smith   PetscFunctionReturn(0);
54174099cc6bSBarry Smith }
541853dd7562SDmitry Karpeev 
541953dd7562SDmitry Karpeev /*
542081824310SBarry Smith     Special version for direct calls from Fortran
542181824310SBarry Smith */
5422af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
542381824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
542481824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
542581824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
542681824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
542781824310SBarry Smith #endif
542881824310SBarry Smith 
542981824310SBarry Smith /* Change these macros so can be used in void function */
543081824310SBarry Smith #undef CHKERRQ
54312e58f0efSBarry Smith #define CHKERRQ(err) CHKERRABORT(PetscObjectComm((PetscObject)A),err)
543281824310SBarry Smith #undef SETERRQ2
54332e58f0efSBarry Smith #define SETERRQ2(comm,err,b,c,d) CHKERRABORT(comm,err)
54344994cf47SJed Brown #undef SETERRQ3
54352e58f0efSBarry Smith #define SETERRQ3(comm,err,b,c,d,e) CHKERRABORT(comm,err)
543681824310SBarry Smith 
543719caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
543881824310SBarry Smith {
543981824310SBarry Smith   Mat            A  = *AA;
544081824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
544181824310SBarry Smith   InsertMode     is = *isis;
544281824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
544381824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
544481824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
544581824310SBarry Smith   PetscErrorCode ierr;
544681824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
544754f21887SBarry Smith   MatScalar      *ap,value,*aa;
5448ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5449ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
545081824310SBarry Smith 
545181824310SBarry Smith   PetscFunctionBegin;
54524994cf47SJed Brown   MatCheckPreallocated(A,1);
545381824310SBarry Smith   imax  = a->imax;
545481824310SBarry Smith   ai    = a->i;
545581824310SBarry Smith   ailen = a->ilen;
545681824310SBarry Smith   aj    = a->j;
545781824310SBarry Smith   aa    = a->a;
545881824310SBarry Smith 
545981824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
546081824310SBarry Smith     row = im[k];
546181824310SBarry Smith     if (row < 0) continue;
5462cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
546381824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
546481824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
546581824310SBarry Smith     low  = 0;
546681824310SBarry Smith     high = nrow;
546781824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
546881824310SBarry Smith       if (in[l] < 0) continue;
5469cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
547081824310SBarry Smith       col = in[l];
54712205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
54722205254eSKarl Rupp       else value = v[k + l*m];
54732205254eSKarl Rupp 
547481824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
547581824310SBarry Smith 
54762205254eSKarl Rupp       if (col <= lastcol) low = 0;
54772205254eSKarl Rupp       else high = nrow;
547881824310SBarry Smith       lastcol = col;
547981824310SBarry Smith       while (high-low > 5) {
548081824310SBarry Smith         t = (low+high)/2;
548181824310SBarry Smith         if (rp[t] > col) high = t;
548281824310SBarry Smith         else             low  = t;
548381824310SBarry Smith       }
548481824310SBarry Smith       for (i=low; i<high; i++) {
548581824310SBarry Smith         if (rp[i] > col) break;
548681824310SBarry Smith         if (rp[i] == col) {
548781824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
548881824310SBarry Smith           else                  ap[i] = value;
548981824310SBarry Smith           goto noinsert;
549081824310SBarry Smith         }
549181824310SBarry Smith       }
549281824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
549381824310SBarry Smith       if (nonew == 1) goto noinsert;
5494ce94432eSBarry Smith       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5495fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
549681824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
549781824310SBarry Smith       /* shift up all the later entries in this row */
549881824310SBarry Smith       for (ii=N; ii>=i; ii--) {
549981824310SBarry Smith         rp[ii+1] = rp[ii];
550081824310SBarry Smith         ap[ii+1] = ap[ii];
550181824310SBarry Smith       }
550281824310SBarry Smith       rp[i] = col;
550381824310SBarry Smith       ap[i] = value;
5504e56f5c9eSBarry Smith       A->nonzerostate++;
550581824310SBarry Smith noinsert:;
550681824310SBarry Smith       low = i + 1;
550781824310SBarry Smith     }
550881824310SBarry Smith     ailen[row] = nrow;
550981824310SBarry Smith   }
551081824310SBarry Smith   PetscFunctionReturnVoid();
551181824310SBarry Smith }
5512